TerrainPatch.cpp 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670
  1. #include "Base.h"
  2. #include "TerrainPatch.h"
  3. #include "Terrain.h"
  4. #include "MeshPart.h"
  5. #include "Scene.h"
  6. #include "Game.h"
  7. namespace gameplay
  8. {
  9. /**
  10. * @script{ignore}
  11. */
  12. float calculateHeight(float* heights, unsigned int width, unsigned int height, unsigned int x, unsigned int z);
  13. /**
  14. * @script{ignore}
  15. */
  16. template <class T> T clamp(T value, T min, T max) { return value < min ? min : (value > max ? max : value); }
  17. TerrainPatch::TerrainPatch() :
  18. _terrain(NULL), _row(0), _column(0), _materialDirty(true)
  19. {
  20. }
  21. TerrainPatch::~TerrainPatch()
  22. {
  23. for (size_t i = 0, count = _levels.size(); i < count; ++i)
  24. {
  25. Level* level = _levels[i];
  26. SAFE_RELEASE(level->model);
  27. SAFE_DELETE(level);
  28. }
  29. while (_layers.size() > 0)
  30. {
  31. deleteLayer(*_layers.begin());
  32. }
  33. }
  34. TerrainPatch* TerrainPatch::create(Terrain* terrain,
  35. unsigned int row, unsigned int column,
  36. float* heights, unsigned int width, unsigned int height,
  37. unsigned int x1, unsigned int z1, unsigned int x2, unsigned int z2,
  38. float xOffset, float zOffset,
  39. unsigned int maxStep, float verticalSkirtSize)
  40. {
  41. // Create patch
  42. TerrainPatch* patch = new TerrainPatch();
  43. patch->_terrain = terrain;
  44. patch->_row = row;
  45. patch->_column = column;
  46. // Add patch lods
  47. for (unsigned int step = 1; step <= maxStep; step *= 2)
  48. {
  49. patch->addLOD(heights, width, height, x1, z1, x2, z2, xOffset, zOffset, step, verticalSkirtSize);
  50. }
  51. // Set our bounding box using the base LOD mesh
  52. BoundingBox& bounds = patch->_boundingBox;
  53. bounds.set(patch->_levels[0]->model->getMesh()->getBoundingBox());
  54. // Apply the terrain's local scale to our bounds
  55. const Vector3& localScale = terrain->_localScale;
  56. if (!localScale.isOne())
  57. {
  58. bounds.min.set(bounds.min.x * localScale.x, bounds.min.y * localScale.y, bounds.min.z * localScale.z);
  59. bounds.max.set(bounds.max.x * localScale.x, bounds.max.y * localScale.y, bounds.max.z * localScale.z);
  60. }
  61. return patch;
  62. }
  63. void TerrainPatch::addLOD(float* heights, unsigned int width, unsigned int height,
  64. unsigned int x1, unsigned int z1, unsigned int x2, unsigned int z2,
  65. float xOffset, float zOffset,
  66. unsigned int step, float verticalSkirtSize)
  67. {
  68. // Allocate vertex data for this patch
  69. unsigned int patchWidth;
  70. unsigned int patchHeight;
  71. if (step == 1)
  72. {
  73. patchWidth = (x2 - x1) + 1;
  74. patchHeight = (z2 - z1) + 1;
  75. }
  76. else
  77. {
  78. patchWidth = (x2 - x1) / step + ((x2 - x1) %step == 0 ? 0 : 1) + 1;
  79. patchHeight = (z2 - z1) / step + ((z2 - z1) % step == 0 ? 0 : 1) + 1;
  80. }
  81. if (patchWidth < 2 || patchHeight < 2)
  82. return; // ignore this level, not enough geometry
  83. if (verticalSkirtSize > 0.0f)
  84. {
  85. patchWidth += 2;
  86. patchHeight += 2;
  87. }
  88. unsigned int vertexCount = patchHeight * patchWidth;
  89. unsigned int vertexElements = _terrain->_normalMap ? 5 : 8; //<x,y,z>[i,j,k]<u,v>
  90. float* vertices = new float[vertexCount * vertexElements];
  91. unsigned int index = 0;
  92. Vector3 min(FLT_MAX, FLT_MAX, FLT_MAX);
  93. Vector3 max(-FLT_MAX, -FLT_MAX, -FLT_MAX);
  94. bool zskirt = verticalSkirtSize > 0 ? true : false;
  95. for (unsigned int z = z1; ; )
  96. {
  97. bool xskirt = verticalSkirtSize > 0 ? true : false;
  98. for (unsigned int x = x1; ; )
  99. {
  100. GP_ASSERT(index < vertexCount);
  101. float* v = vertices + (index * vertexElements);
  102. index++;
  103. // Compute position
  104. v[0] = x + xOffset;
  105. v[1] = calculateHeight(heights, width, height, x, z);
  106. if (xskirt || zskirt)
  107. v[1] -= verticalSkirtSize;
  108. v[2] = z + zOffset;
  109. // Update bounding box min/max (don't include vertical skirt vertices in bounding box)
  110. if (!(xskirt || zskirt))
  111. {
  112. if (v[0] < min.x)
  113. min.x = v[0];
  114. if (v[1] < min.y)
  115. min.y = v[1];
  116. if (v[2] < min.z)
  117. min.z = v[2];
  118. if (v[0] > max.x)
  119. max.x = v[0];
  120. if (v[1] > max.y)
  121. max.y = v[1];
  122. if (v[2] > max.z)
  123. max.z = v[2];
  124. }
  125. v += 3;
  126. // Compute normal
  127. if (!_terrain->_normalMap)
  128. {
  129. Vector3 p(x, calculateHeight(heights, width, height, x, z), z);
  130. Vector3 w(Vector3(x>=step ? x-step : x, calculateHeight(heights, width, height, x>=step ? x-step : x, z), z), p);
  131. Vector3 e(Vector3(x<width-step ? x+step : x, calculateHeight(heights, width, height, x<width-step ? x+step : x, z), z), p);
  132. Vector3 s(Vector3(x, calculateHeight(heights, width, height, x, z>=step ? z-step : z), z>=step ? z-step : z), p);
  133. Vector3 n(Vector3(x, calculateHeight(heights, width, height, x, z<height-step ? z+step : z), z<height-step ? z+step : z), p);
  134. Vector3 normals[4];
  135. Vector3::cross(n, w, &normals[0]);
  136. Vector3::cross(w, s, &normals[1]);
  137. Vector3::cross(e, n, &normals[2]);
  138. Vector3::cross(s, e, &normals[3]);
  139. Vector3 normal = -(normals[0] + normals[1] + normals[2] + normals[3]);
  140. normal.normalize();
  141. v[0] = normal.x;
  142. v[1] = normal.y;
  143. v[2] = normal.z;
  144. v += 3;
  145. }
  146. // Compute texture coord
  147. v[0] = (float)x / width;
  148. v[1] = 1.0f - (float)z / height;
  149. if (xskirt)
  150. {
  151. float offset = verticalSkirtSize / width;
  152. v[0] = x == x1 ? v[0]-offset : v[0]+offset;
  153. }
  154. else if (zskirt)
  155. {
  156. float offset = verticalSkirtSize / height;
  157. v[1] = z == z1 ? v[1]-offset : v[1]+offset;
  158. }
  159. if (x == x2)
  160. {
  161. if ((verticalSkirtSize == 0) || xskirt)
  162. break;
  163. else
  164. xskirt = true;
  165. }
  166. else if (xskirt)
  167. {
  168. xskirt = false;
  169. }
  170. else
  171. {
  172. x = std::min(x + step, x2);
  173. }
  174. }
  175. if (z == z2)
  176. {
  177. if ((verticalSkirtSize == 0) || zskirt)
  178. break;
  179. else
  180. zskirt = true;
  181. }
  182. else if (zskirt)
  183. {
  184. zskirt = false;
  185. }
  186. else
  187. {
  188. z = std::min(z + step, z2);
  189. }
  190. }
  191. GP_ASSERT(index == vertexCount);
  192. Vector3 center(min + ((max - min) * 0.5f));
  193. // Create mesh
  194. VertexFormat::Element elements[3];
  195. elements[0] = VertexFormat::Element(VertexFormat::POSITION, 3);
  196. if (_terrain->_normalMap)
  197. {
  198. elements[1] = VertexFormat::Element(VertexFormat::TEXCOORD0, 2);
  199. }
  200. else
  201. {
  202. elements[1] = VertexFormat::Element(VertexFormat::NORMAL, 3);
  203. elements[2] = VertexFormat::Element(VertexFormat::TEXCOORD0, 2);
  204. }
  205. VertexFormat format(elements, _terrain->_normalMap ? 2 : 3);
  206. Mesh* mesh = Mesh::createMesh(format, vertexCount);
  207. mesh->setVertexData(vertices);
  208. mesh->setBoundingBox(BoundingBox(min, max));
  209. mesh->setBoundingSphere(BoundingSphere(center, center.distance(max)));
  210. // Add mesh part for indices
  211. unsigned int indexCount =
  212. (patchWidth * 2) * // # indices per row of tris
  213. (patchHeight - 1) + // # rows of tris
  214. (patchHeight-2) * 2; // # degenerate tris
  215. // Support a maximum number of indices of USHRT_MAX. Any more indices we will require breaking up the
  216. // terrain into smaller patches.
  217. if (indexCount > USHRT_MAX)
  218. {
  219. GP_WARN("Index count of %d for terrain patch exceeds the limit of 65535. Please specifiy a smaller patch size.", indexCount);
  220. GP_ASSERT(indexCount <= USHRT_MAX);
  221. }
  222. MeshPart* part = mesh->addPart(Mesh::TRIANGLE_STRIP, Mesh::INDEX16, indexCount);
  223. unsigned short* indices = new unsigned short[indexCount];
  224. index = 0;
  225. for (unsigned int z = 0; z < patchHeight-1; ++z)
  226. {
  227. unsigned int i1 = z * patchWidth;
  228. unsigned int i2 = (z+1) * patchWidth;
  229. // Move left to right for even rows and right to left for odd rows.
  230. // Note that this results in two degenerate triangles between rows
  231. // for stitching purposes, but actually does not require any extra
  232. // indices to achieve this.
  233. if (z % 2 == 0)
  234. {
  235. if (z > 0)
  236. {
  237. // Add degenerate indices to connect strips
  238. indices[index] = indices[index-1];
  239. ++index;
  240. indices[index++] = i1;
  241. }
  242. // Add row strip
  243. for (unsigned int x = 0; x < patchWidth; ++x)
  244. {
  245. indices[index++] = i1 + x;
  246. indices[index++] = i2 + x;
  247. }
  248. }
  249. else
  250. {
  251. // Add degenerate indices to connect strips
  252. if (z > 0)
  253. {
  254. indices[index] = indices[index-1];
  255. ++index;
  256. indices[index++] = i2 + ((int)patchWidth-1);
  257. }
  258. // Add row strip
  259. for (int x = (int)patchWidth-1; x >= 0; --x)
  260. {
  261. indices[index++] = i2 + x;
  262. indices[index++] = i1 + x;
  263. }
  264. }
  265. }
  266. GP_ASSERT(index == indexCount);
  267. part->setIndexData(indices, 0, indexCount);
  268. SAFE_DELETE_ARRAY(vertices);
  269. SAFE_DELETE_ARRAY(indices);
  270. // Create model
  271. Model* model = Model::create(mesh);
  272. mesh->release();
  273. // Add this level
  274. Level* level = new Level();
  275. level->model = model;
  276. _levels.push_back(level);
  277. }
  278. void TerrainPatch::deleteLayer(Layer* layer)
  279. {
  280. // Release layer samplers
  281. if (layer->textureIndex != -1)
  282. {
  283. if (_samplers[layer->textureIndex]->getRefCount() == 1)
  284. {
  285. SAFE_RELEASE(_samplers[layer->textureIndex]);
  286. }
  287. else
  288. {
  289. _samplers[layer->textureIndex]->release();
  290. }
  291. }
  292. if (layer->blendIndex != -1)
  293. {
  294. if (_samplers[layer->blendIndex]->getRefCount() == 1)
  295. {
  296. SAFE_RELEASE(_samplers[layer->blendIndex]);
  297. }
  298. else
  299. {
  300. _samplers[layer->blendIndex]->release();
  301. }
  302. }
  303. _layers.erase(layer);
  304. SAFE_DELETE(layer);
  305. }
  306. int TerrainPatch::addSampler(const char* path)
  307. {
  308. // TODO: Support shared samplers stored in Terrain class for layers that span all patches
  309. // on the terrain (row == col == -1).
  310. // Load the texture. If this texture is already loaded, it will return
  311. // a pointer to the same one, with its ref count incremented.
  312. Texture* texture = Texture::create(path, true);
  313. if (!texture)
  314. return -1;
  315. int firstAvailableIndex = -1;
  316. for (size_t i = 0, count = _samplers.size(); i < count; ++i)
  317. {
  318. Texture::Sampler* sampler = _samplers[i];
  319. if (sampler == NULL && firstAvailableIndex == -1)
  320. {
  321. firstAvailableIndex = (int)i;
  322. }
  323. else if (sampler->getTexture() == texture)
  324. {
  325. // A sampler was already added for this texture.
  326. // Increase the ref count for the sampler to indicate that a new
  327. // layer will be referencing it.
  328. texture->release();
  329. sampler->addRef();
  330. return (int)i;
  331. }
  332. }
  333. // Add a new sampler to the list
  334. Texture::Sampler* sampler = Texture::Sampler::create(texture);
  335. texture->release();
  336. sampler->setWrapMode(Texture::REPEAT, Texture::REPEAT);
  337. sampler->setFilterMode(Texture::LINEAR_MIPMAP_LINEAR, Texture::LINEAR);
  338. if (firstAvailableIndex != -1)
  339. {
  340. _samplers[firstAvailableIndex] = sampler;
  341. return firstAvailableIndex;
  342. }
  343. _samplers.push_back(sampler);
  344. return (int)(_samplers.size()-1);
  345. }
  346. bool TerrainPatch::setLayer(int index, const char* texturePath, const Vector2& textureRepeat, const char* blendPath, int blendChannel)
  347. {
  348. // If there is an existing layer at this index, delete it
  349. for (std::set<Layer*, LayerCompare>::iterator itr = _layers.begin(); itr != _layers.end(); ++itr)
  350. {
  351. Layer* layer = *itr;
  352. if (layer->index == index)
  353. {
  354. deleteLayer(layer);
  355. break;
  356. }
  357. }
  358. // Load texture sampler
  359. int textureIndex = addSampler(texturePath);
  360. if (textureIndex == -1)
  361. return false;
  362. // Load blend sampler
  363. int blendIndex = -1;
  364. if (blendPath)
  365. {
  366. blendIndex = addSampler(blendPath);
  367. }
  368. // Create the layer
  369. Layer* layer = new Layer();
  370. layer->index = index;
  371. layer->textureIndex = textureIndex;
  372. layer->textureRepeat = textureRepeat;
  373. layer->blendIndex = blendIndex;
  374. layer->blendChannel = blendChannel;
  375. _layers.insert(layer);
  376. _materialDirty = true;
  377. return true;
  378. }
  379. bool TerrainPatch::updateMaterial()
  380. {
  381. if (!_materialDirty)
  382. return true;
  383. _materialDirty = false;
  384. for (size_t i = 0, count = _levels.size(); i < count; ++i)
  385. {
  386. // Build preprocessor string to pass to shader.
  387. // NOTE: I make heavy use of preprocessor definitions, rather than passing in arrays and doing
  388. // non-constant array access in the shader. This is due to the fact that non-constant array access
  389. // in GLES is very slow on some GLES 2.x hardware.
  390. std::ostringstream defines;
  391. defines << "LAYER_COUNT " << _layers.size();
  392. defines << ";SAMPLER_COUNT " << _samplers.size();
  393. if (_terrain->isFlagSet(Terrain::DEBUG_PATCHES))
  394. defines << ";DEBUG_PATCHES";
  395. if (_terrain->_normalMap)
  396. defines << ";NORMAL_MAP";
  397. // Append texture and blend index constants to preprocessor definition.
  398. // We need to do this since older versions of GLSL only allow sampler arrays
  399. // to be indexed using constant expressions (otherwise we could simply pass an
  400. // array of indices to use for sampler lookup).
  401. //
  402. // Rebuild layer lists while we're at it.
  403. //
  404. int layerIndex = 0;
  405. for (std::set<Layer*, LayerCompare>::iterator itr = _layers.begin(); itr != _layers.end(); ++itr, ++layerIndex)
  406. {
  407. Layer* layer = *itr;
  408. defines << ";TEXTURE_INDEX_" << layerIndex << " " << layer->textureIndex;
  409. defines << ";TEXTURE_REPEAT_" << layerIndex << " vec2(" << layer->textureRepeat.x << "," << layer->textureRepeat.y << ")";
  410. if (layerIndex > 0)
  411. {
  412. defines << ";BLEND_INDEX_" << layerIndex << " " << layer->blendIndex;
  413. defines << ";BLEND_CHANNEL_" << layerIndex << " " << layer->blendChannel;
  414. }
  415. }
  416. Material* material = Material::create("res/shaders/terrain.vert", "res/shaders/terrain.frag", defines.str().c_str());
  417. if (!material)
  418. return false;
  419. material->getStateBlock()->setCullFace(true);
  420. material->getStateBlock()->setDepthTest(true);
  421. // Set material parameter bindings
  422. material->getParameter("u_worldViewProjectionMatrix")->bindValue(_terrain, &Terrain::getWorldViewProjectionMatrix);
  423. if (!_terrain->_normalMap)
  424. material->getParameter("u_normalMatrix")->bindValue(_terrain, &Terrain::getNormalMatrix);
  425. material->getParameter("u_ambientColor")->bindValue(this, &TerrainPatch::getAmbientColor);
  426. material->getParameter("u_lightColor")->bindValue(this, &TerrainPatch::getLightColor);
  427. material->getParameter("u_lightDirection")->bindValue(this, &TerrainPatch::getLightDirection);
  428. if (_layers.size() > 0)
  429. {
  430. material->getParameter("u_samplers")->setValue((const Texture::Sampler**)&_samplers[0], (unsigned int)_samplers.size());
  431. if (_terrain->_normalMap)
  432. material->getParameter("u_normalMap")->setValue(_terrain->_normalMap);
  433. }
  434. if (_terrain->isFlagSet(Terrain::DEBUG_PATCHES))
  435. {
  436. material->getParameter("u_row")->setValue((float)_row);
  437. material->getParameter("u_column")->setValue((float)_column);
  438. }
  439. // Set material on this lod level
  440. _levels[i]->model->setMaterial(material);
  441. material->release();
  442. }
  443. return true;
  444. }
  445. void TerrainPatch::draw(bool wireframe)
  446. {
  447. Scene* scene = _terrain->_node ? _terrain->_node->getScene() : NULL;
  448. Camera* camera = scene ? scene->getActiveCamera() : NULL;
  449. if (!camera)
  450. return;
  451. // Get our world-space bounding box
  452. BoundingBox bounds = getBoundingBox(true);
  453. // If the box does not intersect the view frustum, cull it
  454. if (_terrain->isFlagSet(Terrain::ENABLE_FRUSTUM_CULLING) && !camera->getFrustum().intersects(bounds))
  455. return;
  456. if (!updateMaterial())
  457. return;
  458. // Compute the LOD level from the camera's perspective
  459. size_t lod = computeLOD(camera, bounds);
  460. // Draw the model for the current LOD
  461. _levels[lod]->model->draw(wireframe);
  462. }
  463. bool TerrainPatch::isVisible() const
  464. {
  465. // If frustum culling is disabled, assume the patch is always visible
  466. if ((_terrain->_flags & Terrain::ENABLE_FRUSTUM_CULLING) == 0)
  467. return true;
  468. Scene* scene = _terrain->_node ? _terrain->_node->getScene() : NULL;
  469. Camera* camera = scene ? scene->getActiveCamera() : NULL;
  470. if (!camera)
  471. return false;
  472. // Does the current camera view frustum intersect our world bounds?
  473. return camera->getFrustum().intersects(getBoundingBox(true));
  474. }
  475. unsigned int TerrainPatch::getTriangleCount() const
  476. {
  477. // Patches are made up of a single mesh part using triangle strips
  478. return _levels[0]->model->getMesh()->getPart(0)->getIndexCount() - 2;
  479. }
  480. unsigned int TerrainPatch::getVisibleTriangleCount() const
  481. {
  482. Scene* scene = _terrain->_node ? _terrain->_node->getScene() : NULL;
  483. Camera* camera = scene ? scene->getActiveCamera() : NULL;
  484. if (!camera)
  485. return 0;
  486. // Does the current camera intersect this patch at all?
  487. BoundingBox bounds = getBoundingBox(true);
  488. if (!camera->getFrustum().intersects(bounds))
  489. return 0;
  490. // Return the triangle count of the LOD level depending on the camera
  491. size_t lod = computeLOD(camera, bounds);
  492. return _levels[lod]->model->getMesh()->getPart(0)->getIndexCount() - 2;
  493. }
  494. BoundingBox TerrainPatch::getBoundingBox(bool worldSpace) const
  495. {
  496. if (!worldSpace)
  497. return _boundingBox;
  498. // Apply a world-space transformation to our bounding box
  499. BoundingBox bounds(_boundingBox);
  500. // Transform the bounding box by the terrain node's world transform.
  501. // We don't use Terrain::getWorldMatrix because that returns a matrix
  502. // that has terrain->_localScale factored in - and our patche's bounding
  503. // box already has local scale factored in.
  504. if (_terrain->_node)
  505. bounds.transform(_terrain->_node->getWorldMatrix());
  506. return bounds;
  507. }
  508. const Vector3& TerrainPatch::getAmbientColor() const
  509. {
  510. Scene* scene = _terrain->_node ? _terrain->_node->getScene() : NULL;
  511. return scene ? scene->getAmbientColor() : Vector3::zero();
  512. }
  513. const Vector3& TerrainPatch::getLightColor() const
  514. {
  515. Scene* scene = _terrain->_node ? _terrain->_node->getScene() : NULL;
  516. return scene ? scene->getLightColor() : Vector3::one();
  517. }
  518. const Vector3& TerrainPatch::getLightDirection() const
  519. {
  520. Scene* scene = _terrain->_node ? _terrain->_node->getScene() : NULL;
  521. if (!scene)
  522. {
  523. static Vector3 down(0, -1, 0);
  524. return down;
  525. }
  526. return scene->getLightDirection();
  527. }
  528. size_t TerrainPatch::computeLOD(Camera* camera, const BoundingBox& worldBounds) const
  529. {
  530. if (!_terrain->isFlagSet(Terrain::ENABLE_LEVEL_OF_DETAIL) || _levels.size() == 0)
  531. return 0; // base level
  532. // Compute LOD to use based on very simple distance metric.
  533. // TODO: Optimize this.
  534. Game* game = Game::getInstance();
  535. Rectangle vp(0, 0, game->getWidth(), game->getHeight());
  536. Vector3 corners[8];
  537. Vector2 min(FLT_MAX, FLT_MAX);
  538. Vector2 max(-FLT_MAX, -FLT_MAX);
  539. worldBounds.getCorners(corners);
  540. for (unsigned int i = 0; i < 8; ++i)
  541. {
  542. const Vector3& corner = corners[i];
  543. float x, y;
  544. camera->project(vp, corners[i], &x, &y);
  545. if (x < min.x)
  546. min.x = x;
  547. if (y < min.y)
  548. min.y = y;
  549. if (x > max.x)
  550. max.x = x;
  551. if (y > max.y)
  552. max.y = y;
  553. }
  554. float area = (max.x - min.x) * (max.y - min.y);
  555. float screenArea = game->getWidth() * game->getHeight() / 10.0f;
  556. float error = screenArea / area;
  557. // Level LOD based on distance from camera
  558. size_t maxLod = _levels.size()-1;
  559. size_t lod = (size_t)error;
  560. lod = std::max(lod, (size_t)0);
  561. lod = std::min(lod, maxLod);
  562. return lod;
  563. }
  564. float calculateHeight(float* heights, unsigned int width, unsigned int height, unsigned int x, unsigned int z)
  565. {
  566. return heights[z * width + x];
  567. }
  568. TerrainPatch::Layer::Layer() :
  569. index(0), row(-1), column(-1), textureIndex(-1), blendIndex(-1)
  570. {
  571. }
  572. TerrainPatch::Layer::~Layer()
  573. {
  574. }
  575. bool TerrainPatch::LayerCompare::operator() (const Layer* lhs, const Layer* rhs) const
  576. {
  577. return (lhs->index < rhs->index);
  578. }
  579. }