TerrainPatch.cpp 22 KB

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