TerrainPatch.cpp 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756
  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. template <class T> T clamp(T value, T min, T max) { return value < min ? min : (value > max ? max : value); }
  13. #define TERRAINPATCH_DIRTY_MATERIAL 1
  14. #define TERRAINPATCH_DIRTY_BOUNDS 2
  15. #define TERRAINPATCH_DIRTY_LEVEL 4
  16. #define TERRAINPATCH_DIRTY_ALL (TERRAINPATCH_DIRTY_MATERIAL | TERRAINPATCH_DIRTY_BOUNDS | TERRAINPATCH_DIRTY_LEVEL)
  17. /**
  18. * Custom material auto-binding resolver for terrain.
  19. * @script{ignore}
  20. */
  21. class TerrainAutoBindingResolver : RenderState::AutoBindingResolver
  22. {
  23. bool resolveAutoBinding(const char* autoBinding, Node* node, MaterialParameter* parameter);
  24. };
  25. static TerrainAutoBindingResolver __autoBindingResolver;
  26. static int __currentPatchIndex = -1;
  27. TerrainPatch::TerrainPatch() :
  28. _terrain(NULL), _row(0), _column(0), _camera(NULL), _level(0), _bits(TERRAINPATCH_DIRTY_ALL)
  29. {
  30. }
  31. TerrainPatch::~TerrainPatch()
  32. {
  33. for (size_t i = 0, count = _levels.size(); i < count; ++i)
  34. {
  35. Level* level = _levels[i];
  36. SAFE_RELEASE(level->model);
  37. SAFE_DELETE(level);
  38. }
  39. while (_layers.size() > 0)
  40. {
  41. deleteLayer(*_layers.begin());
  42. }
  43. SAFE_RELEASE(_camera);
  44. }
  45. TerrainPatch* TerrainPatch::create(Terrain* terrain, unsigned int index,
  46. unsigned int row, unsigned int column,
  47. float* heights, unsigned int width, unsigned int height,
  48. unsigned int x1, unsigned int z1, unsigned int x2, unsigned int z2,
  49. float xOffset, float zOffset,
  50. unsigned int maxStep, float verticalSkirtSize)
  51. {
  52. // Create patch
  53. TerrainPatch* patch = new TerrainPatch();
  54. patch->_terrain = terrain;
  55. patch->_index = index;
  56. patch->_row = row;
  57. patch->_column = column;
  58. // Add patch lods
  59. for (unsigned int step = 1; step <= maxStep; step *= 2)
  60. {
  61. patch->addLOD(heights, width, height, x1, z1, x2, z2, xOffset, zOffset, step, verticalSkirtSize);
  62. }
  63. // Set our bounding box using the base LOD mesh
  64. BoundingBox& bounds = patch->_boundingBox;
  65. bounds.set(patch->_levels[0]->model->getMesh()->getBoundingBox());
  66. return patch;
  67. }
  68. unsigned int TerrainPatch::getMaterialCount() const
  69. {
  70. return _levels.size();
  71. }
  72. Material* TerrainPatch::getMaterial(int index) const
  73. {
  74. if (index == -1)
  75. {
  76. Scene* scene = _terrain->_node ? _terrain->_node->getScene() : NULL;
  77. Camera* camera = scene ? scene->getActiveCamera() : NULL;
  78. if (!camera)
  79. {
  80. _level = const_cast<TerrainPatch*>(this)->computeLOD(camera, getBoundingBox(true));
  81. }
  82. else
  83. {
  84. _level = 0;
  85. }
  86. return _levels[_level]->model->getMaterial();
  87. }
  88. return _levels[index]->model->getMaterial();
  89. }
  90. void TerrainPatch::addLOD(float* heights, unsigned int width, unsigned int height,
  91. unsigned int x1, unsigned int z1, unsigned int x2, unsigned int z2,
  92. float xOffset, float zOffset,
  93. unsigned int step, float verticalSkirtSize)
  94. {
  95. // Allocate vertex data for this patch
  96. unsigned int patchWidth;
  97. unsigned int patchHeight;
  98. if (step == 1)
  99. {
  100. patchWidth = (x2 - x1) + 1;
  101. patchHeight = (z2 - z1) + 1;
  102. }
  103. else
  104. {
  105. patchWidth = (x2 - x1) / step + ((x2 - x1) %step == 0 ? 0 : 1) + 1;
  106. patchHeight = (z2 - z1) / step + ((z2 - z1) % step == 0 ? 0 : 1) + 1;
  107. }
  108. if (patchWidth < 2 || patchHeight < 2)
  109. return; // ignore this level, not enough geometry
  110. if (verticalSkirtSize > 0.0f)
  111. {
  112. patchWidth += 2;
  113. patchHeight += 2;
  114. }
  115. unsigned int vertexCount = patchHeight * patchWidth;
  116. unsigned int vertexElements = _terrain->_normalMap ? 5 : 8; //<x,y,z>[i,j,k]<u,v>
  117. float* vertices = new float[vertexCount * vertexElements];
  118. unsigned int index = 0;
  119. Vector3 min(FLT_MAX, FLT_MAX, FLT_MAX);
  120. Vector3 max(-FLT_MAX, -FLT_MAX, -FLT_MAX);
  121. float stepXScaled = step * _terrain->_localScale.x;
  122. float stepZScaled = step * _terrain->_localScale.z;
  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 - apply the local scale of the terrain into the vertex data
  133. v[0] = (x + xOffset) * _terrain->_localScale.x;
  134. v[1] = computeHeight(heights, width, x, z);
  135. if (xskirt || zskirt)
  136. v[1] -= verticalSkirtSize * _terrain->_localScale.y;
  137. v[2] = (z + zOffset) * _terrain->_localScale.z;
  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. // Compute normal
  155. if (!_terrain->_normalMap)
  156. {
  157. Vector3 p(v[0], computeHeight(heights, width, x, z), v[2]);
  158. Vector3 w(Vector3(x>=step ? v[0]-stepXScaled : v[0], computeHeight(heights, width, x>=step ? x-step : x, z), v[2]), p);
  159. Vector3 e(Vector3(x<width-step ? v[0]+stepXScaled : v[0], computeHeight(heights, width, x<width-step ? x+step : x, z), v[2]), p);
  160. Vector3 s(Vector3(v[0], computeHeight(heights, width, x, z>=step ? z-step : z), z>=step ? v[2]-stepZScaled : v[2]), p);
  161. Vector3 n(Vector3(v[0], computeHeight(heights, width, x, z<height-step ? z+step : z), z<height-step ? v[2]+stepZScaled : v[2]), p);
  162. Vector3 normals[4];
  163. Vector3::cross(n, w, &normals[0]);
  164. Vector3::cross(w, s, &normals[1]);
  165. Vector3::cross(e, n, &normals[2]);
  166. Vector3::cross(s, e, &normals[3]);
  167. Vector3 normal = -(normals[0] + normals[1] + normals[2] + normals[3]);
  168. normal.normalize();
  169. v[3] = normal.x;
  170. v[4] = normal.y;
  171. v[5] = normal.z;
  172. v += 3;
  173. }
  174. v += 3;
  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. // Textures should only be 2D
  345. if (texture->getType() != Texture::TEXTURE_2D)
  346. {
  347. SAFE_RELEASE(texture);
  348. return -1;
  349. }
  350. int firstAvailableIndex = -1;
  351. for (size_t i = 0, count = _samplers.size(); i < count; ++i)
  352. {
  353. Texture::Sampler* sampler = _samplers[i];
  354. if (sampler == NULL && firstAvailableIndex == -1)
  355. {
  356. firstAvailableIndex = (int)i;
  357. }
  358. else if (sampler->getTexture() == texture)
  359. {
  360. // A sampler was already added for this texture.
  361. // Increase the ref count for the sampler to indicate that a new
  362. // layer will be referencing it.
  363. texture->release();
  364. sampler->addRef();
  365. return (int)i;
  366. }
  367. }
  368. // Add a new sampler to the list
  369. Texture::Sampler* sampler = Texture::Sampler::create(texture);
  370. texture->release();
  371. sampler->setWrapMode(Texture::REPEAT, Texture::REPEAT);
  372. sampler->setFilterMode(Texture::LINEAR_MIPMAP_LINEAR, Texture::LINEAR);
  373. if (firstAvailableIndex != -1)
  374. {
  375. _samplers[firstAvailableIndex] = sampler;
  376. return firstAvailableIndex;
  377. }
  378. _samplers.push_back(sampler);
  379. return (int)(_samplers.size()-1);
  380. }
  381. bool TerrainPatch::setLayer(int index, const char* texturePath, const Vector2& textureRepeat, const char* blendPath, int blendChannel)
  382. {
  383. // If there is an existing layer at this index, delete it
  384. for (std::set<Layer*, LayerCompare>::iterator itr = _layers.begin(); itr != _layers.end(); ++itr)
  385. {
  386. Layer* layer = *itr;
  387. if (layer->index == index)
  388. {
  389. deleteLayer(layer);
  390. break;
  391. }
  392. }
  393. // Load texture sampler
  394. int textureIndex = addSampler(texturePath);
  395. if (textureIndex == -1)
  396. return false;
  397. // Load blend sampler
  398. int blendIndex = -1;
  399. if (blendPath)
  400. {
  401. blendIndex = addSampler(blendPath);
  402. }
  403. // Create the layer
  404. Layer* layer = new Layer();
  405. layer->index = index;
  406. layer->textureIndex = textureIndex;
  407. layer->textureRepeat = textureRepeat;
  408. layer->blendIndex = blendIndex;
  409. layer->blendChannel = blendChannel;
  410. _layers.insert(layer);
  411. _bits |= TERRAINPATCH_DIRTY_MATERIAL;
  412. return true;
  413. }
  414. std::string TerrainPatch::passCallback(Pass* pass, void* cookie)
  415. {
  416. TerrainPatch* patch = reinterpret_cast<TerrainPatch*>(cookie);
  417. GP_ASSERT(patch);
  418. return patch->passCreated(pass);
  419. }
  420. std::string TerrainPatch::passCreated(Pass* pass)
  421. {
  422. // Build preprocessor string to be passed to the terrain shader.
  423. // NOTE: I make heavy use of preprocessor definitions, rather than passing in arrays and doing
  424. // non-constant array access in the shader. This is due to the fact that non-constant array access
  425. // in GLES is very slow on some hardware.
  426. std::ostringstream defines;
  427. defines << "LAYER_COUNT " << _layers.size();
  428. defines << ";SAMPLER_COUNT " << _samplers.size();
  429. if (_terrain->isFlagSet(Terrain::DEBUG_PATCHES))
  430. {
  431. defines << ";DEBUG_PATCHES";
  432. pass->getParameter("u_row")->setFloat(_row);
  433. pass->getParameter("u_column")->setFloat(_column);
  434. }
  435. if (_terrain->_normalMap)
  436. defines << ";NORMAL_MAP";
  437. // Append texture and blend index constants to preprocessor definition.
  438. // We need to do this since older versions of GLSL only allow sampler arrays
  439. // to be indexed using constant expressions (otherwise we could simply pass an
  440. // array of indices to use for sampler lookup).
  441. //
  442. // Rebuild layer lists while we're at it.
  443. //
  444. int layerIndex = 0;
  445. for (std::set<Layer*, LayerCompare>::iterator itr = _layers.begin(); itr != _layers.end(); ++itr, ++layerIndex)
  446. {
  447. Layer* layer = *itr;
  448. defines << ";TEXTURE_INDEX_" << layerIndex << " " << layer->textureIndex;
  449. defines << ";TEXTURE_REPEAT_" << layerIndex << " vec2(" << layer->textureRepeat.x << "," << layer->textureRepeat.y << ")";
  450. if (layerIndex > 0)
  451. {
  452. defines << ";BLEND_INDEX_" << layerIndex << " " << layer->blendIndex;
  453. defines << ";BLEND_CHANNEL_" << layerIndex << " " << layer->blendChannel;
  454. }
  455. }
  456. return defines.str();
  457. }
  458. bool TerrainPatch::updateMaterial()
  459. {
  460. if (!(_bits & TERRAINPATCH_DIRTY_MATERIAL))
  461. return true;
  462. _bits &= ~TERRAINPATCH_DIRTY_MATERIAL;
  463. __currentPatchIndex = _index;
  464. for (size_t i = 0, count = _levels.size(); i < count; ++i)
  465. {
  466. Material* material = Material::create(_terrain->_materialPath.c_str(), &passCallback, this);
  467. GP_ASSERT(material);
  468. if (!material)
  469. {
  470. GP_WARN("Failed to load material for terrain patch: %s", _terrain->_materialPath.c_str());
  471. __currentPatchIndex = -1;
  472. return false;
  473. }
  474. material->setNodeBinding(_terrain->_node);
  475. // Set material on this lod level
  476. _levels[i]->model->setMaterial(material);
  477. material->release();
  478. }
  479. __currentPatchIndex = -1;
  480. return true;
  481. }
  482. void TerrainPatch::updateNodeBindings()
  483. {
  484. __currentPatchIndex = _index;
  485. for (size_t i = 0, count = _levels.size(); i < count; ++i)
  486. {
  487. _levels[i]->model->getMaterial()->setNodeBinding(_terrain->_node);
  488. }
  489. __currentPatchIndex = -1;
  490. }
  491. unsigned int TerrainPatch::draw(bool wireframe)
  492. {
  493. Scene* scene = _terrain->_node ? _terrain->_node->getScene() : NULL;
  494. Camera* camera = scene ? scene->getActiveCamera() : NULL;
  495. if (!camera)
  496. return 0;
  497. // Get our world-space bounding box
  498. BoundingBox bounds = getBoundingBox(true);
  499. // If the box does not intersect the view frustum, cull it
  500. if (_terrain->isFlagSet(Terrain::FRUSTUM_CULLING) && !camera->getFrustum().intersects(bounds))
  501. return 0;
  502. if (!updateMaterial())
  503. return 0;
  504. // Compute the LOD level from the camera's perspective
  505. _level = computeLOD(camera, bounds);
  506. // Draw the model for the current LOD
  507. return _levels[_level]->model->draw(wireframe);
  508. }
  509. const BoundingBox& TerrainPatch::getBoundingBox(bool worldSpace) const
  510. {
  511. if (!worldSpace)
  512. return _boundingBox;
  513. if (!(_bits & TERRAINPATCH_DIRTY_BOUNDS))
  514. return _boundingBoxWorld;
  515. _bits &= ~TERRAINPATCH_DIRTY_BOUNDS;
  516. // Apply a world-space transformation to our bounding box
  517. _boundingBoxWorld.set(_boundingBox);
  518. // Transform the bounding box by the terrain node's world transform.
  519. if (_terrain->_node)
  520. _boundingBoxWorld.transform(_terrain->_node->getWorldMatrix());
  521. return _boundingBoxWorld;
  522. }
  523. void TerrainPatch::cameraChanged(Camera* camera)
  524. {
  525. _bits |= TERRAINPATCH_DIRTY_LEVEL;
  526. }
  527. unsigned int TerrainPatch::computeLOD(Camera* camera, const BoundingBox& worldBounds)
  528. {
  529. if (camera != _camera)
  530. {
  531. if (_camera != NULL)
  532. {
  533. _camera->removeListener(this);
  534. _camera->release();
  535. }
  536. _camera = camera;
  537. _camera->addRef();
  538. _camera->addListener(this);
  539. _bits |= TERRAINPATCH_DIRTY_LEVEL;
  540. }
  541. // base level
  542. if (!_terrain->isFlagSet(Terrain::LEVEL_OF_DETAIL) || _levels.size() == 0)
  543. return 0;
  544. if (!(_bits & TERRAINPATCH_DIRTY_LEVEL))
  545. return _level;
  546. _bits &= ~TERRAINPATCH_DIRTY_LEVEL;
  547. // Compute LOD to use based on very simple distance metric. TODO: Optimize me.
  548. Game* game = Game::getInstance();
  549. Rectangle vp(0, 0, game->getWidth(), game->getHeight());
  550. Vector3 corners[8];
  551. Vector2 min(FLT_MAX, FLT_MAX);
  552. Vector2 max(-FLT_MAX, -FLT_MAX);
  553. worldBounds.getCorners(corners);
  554. for (unsigned int i = 0; i < 8; ++i)
  555. {
  556. const Vector3& corner = corners[i];
  557. float x, y;
  558. camera->project(vp, corners[i], &x, &y);
  559. if (x < min.x)
  560. min.x = x;
  561. if (y < min.y)
  562. min.y = y;
  563. if (x > max.x)
  564. max.x = x;
  565. if (y > max.y)
  566. max.y = y;
  567. }
  568. float area = (max.x - min.x) * (max.y - min.y);
  569. float screenArea = game->getWidth() * game->getHeight() / 10.0f;
  570. float error = screenArea / area;
  571. // Level LOD based on distance from camera
  572. size_t maxLod = _levels.size()-1;
  573. size_t lod = (size_t)error;
  574. lod = std::max(lod, (size_t)0);
  575. lod = std::min(lod, maxLod);
  576. _level = lod;
  577. return _level;
  578. }
  579. const Vector3& TerrainPatch::getAmbientColor() const
  580. {
  581. Scene* scene = _terrain->_node ? _terrain->_node->getScene() : NULL;
  582. return scene ? scene->getAmbientColor() : Vector3::zero();
  583. }
  584. void TerrainPatch::setMaterialDirty()
  585. {
  586. _bits |= TERRAINPATCH_DIRTY_MATERIAL;
  587. }
  588. float TerrainPatch::computeHeight(float* heights, unsigned int width, unsigned int x, unsigned int z)
  589. {
  590. return heights[z * width + x] * _terrain->_localScale.y;
  591. }
  592. TerrainPatch::Layer::Layer() :
  593. index(0), row(-1), column(-1), textureIndex(-1), blendIndex(-1)
  594. {
  595. }
  596. TerrainPatch::Layer::~Layer()
  597. {
  598. }
  599. TerrainPatch::Level::Level() : model(NULL)
  600. {
  601. }
  602. bool TerrainPatch::LayerCompare::operator() (const Layer* lhs, const Layer* rhs) const
  603. {
  604. return (lhs->index < rhs->index);
  605. }
  606. bool TerrainAutoBindingResolver::resolveAutoBinding(const char* autoBinding, Node* node, MaterialParameter* parameter)
  607. {
  608. // Local helper functions
  609. struct HelperFunctions
  610. {
  611. static TerrainPatch* getPatch(Node* node)
  612. {
  613. Terrain* terrain = node->getTerrain();
  614. if (terrain)
  615. {
  616. if (__currentPatchIndex >= 0 && __currentPatchIndex < (int)terrain->_patches.size())
  617. return terrain->_patches[__currentPatchIndex];
  618. }
  619. return NULL;
  620. }
  621. };
  622. if (strcmp(autoBinding, "TERRAIN_LAYER_MAPS") == 0)
  623. {
  624. TerrainPatch* patch = HelperFunctions::getPatch(node);
  625. if (patch && patch->_layers.size() > 0)
  626. parameter->setValue((const Texture::Sampler**)&patch->_samplers[0], (unsigned int)patch->_samplers.size());
  627. return true;
  628. }
  629. else if (strcmp(autoBinding, "TERRAIN_NORMAL_MAP") == 0)
  630. {
  631. Terrain* terrain = node->getTerrain();
  632. if (terrain && terrain->_normalMap)
  633. parameter->setValue(terrain->_normalMap);
  634. return true;
  635. }
  636. else if (strcmp(autoBinding, "TERRAIN_ROW") == 0)
  637. {
  638. TerrainPatch* patch = HelperFunctions::getPatch(node);
  639. if (patch)
  640. parameter->setValue((float)patch->_row);
  641. return true;
  642. }
  643. else if (strcmp(autoBinding, "TERRAIN_COLUMN") == 0)
  644. {
  645. TerrainPatch* patch = HelperFunctions::getPatch(node);
  646. if (patch)
  647. parameter->setValue((float)patch->_column);
  648. return true;
  649. }
  650. return false;
  651. }
  652. }