TerrainPatch.cpp 22 KB

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