TerrainPatch.cpp 23 KB

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