blTerrainSystem.cpp 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717
  1. //-----------------------------------------------------------------------------
  2. // Copyright (c) 2012 GarageGames, LLC
  3. //
  4. // Permission is hereby granted, free of charge, to any person obtaining a copy
  5. // of this software and associated documentation files (the "Software"), to
  6. // deal in the Software without restriction, including without limitation the
  7. // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  8. // sell copies of the Software, and to permit persons to whom the Software is
  9. // furnished to do so, subject to the following conditions:
  10. //
  11. // The above copyright notice and this permission notice shall be included in
  12. // all copies or substantial portions of the Software.
  13. //
  14. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  19. // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  20. // IN THE SOFTWARE.
  21. //-----------------------------------------------------------------------------
  22. #include "platform/platform.h"
  23. #include "lighting/basic/blTerrainSystem.h"
  24. #include "core/bitVector.h"
  25. #include "lighting/common/shadowVolumeBSP.h"
  26. #include "lighting/lightingInterfaces.h"
  27. #include "terrain/terrData.h"
  28. #include "lighting/basic/basicLightManager.h"
  29. #include "lighting/common/sceneLighting.h"
  30. #include "gfx/bitmap/gBitmap.h"
  31. #include "collision/collision.h"
  32. extern SceneLighting* gLighting;
  33. struct blTerrainChunk : public PersistInfo::PersistChunk
  34. {
  35. typedef PersistInfo::PersistChunk Parent;
  36. blTerrainChunk();
  37. ~blTerrainChunk();
  38. GBitmap *mLightmap;
  39. bool read(Stream &);
  40. bool write(Stream &);
  41. };
  42. //------------------------------------------------------------------------------
  43. // Class SceneLighting::TerrainChunk
  44. //------------------------------------------------------------------------------
  45. blTerrainChunk::blTerrainChunk()
  46. {
  47. mChunkType = PersistChunk::TerrainChunkType;
  48. mLightmap = NULL;
  49. }
  50. blTerrainChunk::~blTerrainChunk()
  51. {
  52. if(mLightmap)
  53. delete mLightmap;
  54. }
  55. //------------------------------------------------------------------------------
  56. bool blTerrainChunk::read(Stream & stream)
  57. {
  58. if(!Parent::read(stream))
  59. return(false);
  60. mLightmap = new GBitmap();
  61. return mLightmap->readBitmap("png",stream);
  62. }
  63. bool blTerrainChunk::write(Stream & stream)
  64. {
  65. if(!Parent::write(stream))
  66. return(false);
  67. if(!mLightmap)
  68. return(false);
  69. if(!mLightmap->writeBitmap("png",stream))
  70. return(false);
  71. return(true);
  72. }
  73. class blTerrainProxy : public SceneLighting::ObjectProxy
  74. {
  75. protected:
  76. typedef ObjectProxy Parent;
  77. BitVector mShadowMask;
  78. ShadowVolumeBSP * mShadowVolume;
  79. ColorF * mLightmap;
  80. /// The dimension of the lightmap in pixels.
  81. const U32 mLightMapSize;
  82. /// The dimension of the terrain height map sample array.
  83. const U32 mTerrainBlockSize;
  84. ColorF *sgBakedLightmap;
  85. Vector<LightInfo *> sgLights;
  86. bool sgMarkStaticShadow(void *terrainproxy, SceneObject *sceneobject, LightInfo *light);
  87. //void postLight(bool lastLight);
  88. void lightVector(LightInfo *);
  89. struct SquareStackNode
  90. {
  91. U8 mLevel;
  92. U16 mClipFlags;
  93. Point2I mPos;
  94. };
  95. S32 testSquare(const Point3F &, const Point3F &, S32, F32, const Vector<PlaneF> &);
  96. bool markObjectShadow(ObjectProxy *);
  97. bool sgIsCorrectStaticObjectType(SceneObject *obj);
  98. inline ColorF _getValue( S32 row, S32 column );
  99. public:
  100. blTerrainProxy(SceneObject * obj);
  101. ~blTerrainProxy();
  102. TerrainBlock * operator->() {return(static_cast<TerrainBlock*>(static_cast<SceneObject*>(mObj)));}
  103. TerrainBlock * getObject() {return(static_cast<TerrainBlock*>(static_cast<SceneObject*>(mObj)));}
  104. bool getShadowedSquares(const Vector<PlaneF> &, Vector<U16> &);
  105. // lighting
  106. void init();
  107. bool preLight(LightInfo *);
  108. void light(LightInfo *);
  109. // persist
  110. U32 getResourceCRC();
  111. bool setPersistInfo(PersistInfo::PersistChunk *);
  112. bool getPersistInfo(PersistInfo::PersistChunk *);
  113. virtual bool supportsShadowVolume();
  114. virtual void getClipPlanes(Vector<PlaneF>& planes);
  115. virtual void addToShadowVolume(ShadowVolumeBSP * shadowVolume, LightInfo * light, S32 level);
  116. // events
  117. //virtual void processTGELightProcessEvent(U32 curr, U32 max, LightInfo* currlight);
  118. //virtual void processSGObjectProcessEvent(LightInfo* currLight);
  119. };
  120. //-------------------------------------------------------------------------------
  121. // Class SceneLighting::TerrainProxy:
  122. //-------------------------------------------------------------------------------
  123. blTerrainProxy::blTerrainProxy( SceneObject *obj ) :
  124. Parent( obj ),
  125. mLightMapSize( getObject()->getLightMapSize() ),
  126. mTerrainBlockSize( getObject()->getBlockSize() ),
  127. mShadowVolume( NULL ),
  128. mLightmap( NULL ),
  129. sgBakedLightmap( NULL )
  130. {
  131. }
  132. blTerrainProxy::~blTerrainProxy()
  133. {
  134. delete [] mLightmap;
  135. }
  136. //-------------------------------------------------------------------------------
  137. void blTerrainProxy::init()
  138. {
  139. mLightmap = new ColorF[ mLightMapSize * mLightMapSize ];
  140. dMemset(mLightmap, 0, mLightMapSize * mLightMapSize * sizeof(ColorF));
  141. mShadowMask.setSize( mTerrainBlockSize * mTerrainBlockSize );
  142. }
  143. bool blTerrainProxy::preLight(LightInfo * light)
  144. {
  145. if(!bool(mObj))
  146. return(false);
  147. if(light->getType() != LightInfo::Vector)
  148. return(false);
  149. mShadowMask.clear();
  150. return(true);
  151. }
  152. inline ColorF blTerrainProxy::_getValue( S32 row, S32 column )
  153. {
  154. while( row < 0 )
  155. row += mLightMapSize;
  156. row = row % mLightMapSize;
  157. while( column < 0 )
  158. column += mLightMapSize;
  159. column = column % mLightMapSize;
  160. U32 offset = row * mLightMapSize + column;
  161. return mLightmap[offset];
  162. }
  163. bool blTerrainProxy::markObjectShadow(ObjectProxy * proxy)
  164. {
  165. if (!proxy->supportsShadowVolume())
  166. return false;
  167. // setup the clip planes
  168. Vector<PlaneF> clipPlanes;
  169. proxy->getClipPlanes(clipPlanes);
  170. Vector<U16> shadowList;
  171. if(!getShadowedSquares(clipPlanes, shadowList))
  172. return(false);
  173. // set the correct bit
  174. for(U32 i = 0; i < shadowList.size(); i++)
  175. mShadowMask.set(shadowList[i]);
  176. return(true);
  177. }
  178. void blTerrainProxy::light(LightInfo * light)
  179. {
  180. // If we don't have terrain or its not a directional
  181. // light then skip processing.
  182. TerrainBlock * terrain = getObject();
  183. if ( !terrain || light->getType() != LightInfo::Vector )
  184. return;
  185. S32 time = Platform::getRealMilliseconds();
  186. // reset
  187. mShadowVolume = new ShadowVolumeBSP;
  188. // build interior shadow volume
  189. for(ObjectProxy ** itr = gLighting->mLitObjects.begin(); itr != gLighting->mLitObjects.end(); itr++)
  190. {
  191. ObjectProxy* objproxy = *itr;
  192. if (markObjectShadow(objproxy))
  193. objproxy->addToShadowVolume(mShadowVolume, light, SceneLighting::SHADOW_DETAIL);
  194. }
  195. lightVector(light);
  196. // set the lightmap...
  197. terrain->clearLightMap();
  198. // Blur...
  199. F32 kernel[3][3] = { {1, 2, 1},
  200. {2, 3, 2},
  201. {1, 2, 1} };
  202. F32 modifier = 1;
  203. F32 divisor = 0;
  204. for( U32 i=0; i<3; i++ )
  205. {
  206. for( U32 j=0; j<3; j++ )
  207. {
  208. if( i==1 && j==1 )
  209. {
  210. kernel[i][j] = 1 + kernel[i][j] * modifier;
  211. }
  212. else
  213. {
  214. kernel[i][j] = kernel[i][j] * modifier;
  215. }
  216. divisor += kernel[i][j];
  217. }
  218. }
  219. for( U32 i=0; i < mLightMapSize; i++ )
  220. {
  221. for( U32 j=0; j < mLightMapSize; j++ )
  222. {
  223. ColorF val;
  224. val = _getValue( i-1, j-1 ) * kernel[0][0];
  225. val += _getValue( i-1, j ) * kernel[0][1];
  226. val += _getValue( i-1, j+1 ) * kernel[0][2];
  227. val += _getValue( i, j-1 ) * kernel[1][0];
  228. val += _getValue( i, j ) * kernel[1][1];
  229. val += _getValue( i, j+1 ) * kernel[1][2];
  230. val += _getValue( i+1, j-1 ) * kernel[2][0];
  231. val += _getValue( i+1, j ) * kernel[2][1];
  232. val += _getValue( i+1, j+1 ) * kernel[2][2];
  233. U32 edge = 0;
  234. if( j == 0 || j == mLightMapSize - 1 )
  235. edge++;
  236. if( i == 0 || i == mLightMapSize - 1 )
  237. edge++;
  238. if( !edge )
  239. val = val / divisor;
  240. else
  241. val = mLightmap[ i * mLightMapSize + j ];
  242. // clamp values
  243. mLightmap[ i * mLightMapSize + j ]= val;
  244. }
  245. }
  246. // And stuff it into the texture...
  247. GBitmap *terrLightMap = terrain->getLightMap();
  248. for(U32 y = 0; y < mLightMapSize; y++)
  249. {
  250. for(U32 x = 0; x < mLightMapSize; x++)
  251. {
  252. ColorI color(255, 255, 255, 255);
  253. color.red = mLightmap[x + y * mLightMapSize].red * 255;
  254. color.green = mLightmap[x + y * mLightMapSize].green * 255;
  255. color.blue = mLightmap[x + y * mLightMapSize].blue * 255;
  256. terrLightMap->setColor(x, y, color);
  257. }
  258. }
  259. /*
  260. // This handles matching up the outer edges of the terrain
  261. // lightmap when it has neighbors
  262. if (!terrain->isTiling())
  263. {
  264. for (S32 y = 0; y < terrLightMap->getHeight(); y++)
  265. {
  266. ColorI c;
  267. if (terrain->getFile()->mEdgeTerrainFiles[0])
  268. {
  269. terrLightMap->getColor(terrLightMap->getWidth()-1,y,c);
  270. terrLightMap->setColor(0,y,c);
  271. terrLightMap->setColor(1,y,c);
  272. }
  273. else
  274. {
  275. terrLightMap->getColor(0,y,c);
  276. terrLightMap->setColor(terrLightMap->getWidth()-1,y,c);
  277. terrLightMap->setColor(terrLightMap->getWidth()-2,y,c);
  278. }
  279. }
  280. for (S32 x = 0; x < terrLightMap->getHeight(); x++)
  281. {
  282. ColorI c;
  283. if (terrain->getFile()->mEdgeTerrainFiles[1])
  284. {
  285. terrLightMap->getColor(x,terrLightMap->getHeight()-1,c);
  286. terrLightMap->setColor(x,0,c);
  287. terrLightMap->setColor(x,1,c);
  288. }
  289. else
  290. {
  291. terrLightMap->getColor(x,0,c);
  292. terrLightMap->setColor(x,terrLightMap->getHeight()-1,c);
  293. terrLightMap->setColor(x,terrLightMap->getHeight()-2,c);
  294. }
  295. }
  296. }
  297. */
  298. delete mShadowVolume;
  299. Con::printf(" = terrain lit in %3.3f seconds", (Platform::getRealMilliseconds()-time)/1000.f);
  300. }
  301. //------------------------------------------------------------------------------
  302. S32 blTerrainProxy::testSquare(const Point3F & min, const Point3F & max, S32 mask, F32 expand, const Vector<PlaneF> & clipPlanes)
  303. {
  304. expand = 0;
  305. S32 retMask = 0;
  306. Point3F minPoint, maxPoint;
  307. for(S32 i = 0; i < clipPlanes.size(); i++)
  308. {
  309. if(mask & (1 << i))
  310. {
  311. if(clipPlanes[i].x > 0)
  312. {
  313. maxPoint.x = max.x;
  314. minPoint.x = min.x;
  315. }
  316. else
  317. {
  318. maxPoint.x = min.x;
  319. minPoint.x = max.x;
  320. }
  321. if(clipPlanes[i].y > 0)
  322. {
  323. maxPoint.y = max.y;
  324. minPoint.y = min.y;
  325. }
  326. else
  327. {
  328. maxPoint.y = min.y;
  329. minPoint.y = max.y;
  330. }
  331. if(clipPlanes[i].z > 0)
  332. {
  333. maxPoint.z = max.z;
  334. minPoint.z = min.z;
  335. }
  336. else
  337. {
  338. maxPoint.z = min.z;
  339. minPoint.z = max.z;
  340. }
  341. F32 maxDot = mDot(maxPoint, clipPlanes[i]);
  342. F32 minDot = mDot(minPoint, clipPlanes[i]);
  343. F32 planeD = clipPlanes[i].d;
  344. if(maxDot <= -(planeD + expand))
  345. return(U16(-1));
  346. if(minDot <= -planeD)
  347. retMask |= (1 << i);
  348. }
  349. }
  350. return(retMask);
  351. }
  352. bool blTerrainProxy::getShadowedSquares(const Vector<PlaneF> & clipPlanes, Vector<U16> & shadowList)
  353. {
  354. TerrainBlock *terrain = getObject();
  355. if ( !terrain )
  356. return false;
  357. // TODO: Fix me for variable terrain sizes!
  358. return true;
  359. /*
  360. SquareStackNode stack[TerrainBlock::BlockShift * 4];
  361. stack[0].mLevel = TerrainBlock::BlockShift;
  362. stack[0].mClipFlags = 0xff;
  363. stack[0].mPos.set(0,0);
  364. U32 stackSize = 1;
  365. Point3F blockPos;
  366. terrain->getTransform().getColumn(3, &blockPos);
  367. S32 squareSize = terrain->getSquareSize();
  368. F32 floatSquareSize = (F32)squareSize;
  369. bool marked = false;
  370. // push through all the levels of the quadtree
  371. while(stackSize)
  372. {
  373. SquareStackNode * node = &stack[stackSize - 1];
  374. S32 clipFlags = node->mClipFlags;
  375. Point2I pos = node->mPos;
  376. GridSquare * sq = terrain->findSquare(node->mLevel, pos);
  377. Point3F minPoint, maxPoint;
  378. minPoint.set(squareSize * pos.x + blockPos.x,
  379. squareSize * pos.y + blockPos.y,
  380. fixedToFloat(sq->minHeight));
  381. maxPoint.set(minPoint.x + (squareSize << node->mLevel),
  382. minPoint.y + (squareSize << node->mLevel),
  383. fixedToFloat(sq->maxHeight));
  384. // test the square against the current level
  385. if(clipFlags)
  386. {
  387. clipFlags = testSquare(minPoint, maxPoint, clipFlags, floatSquareSize, clipPlanes);
  388. if(clipFlags == U16(-1))
  389. {
  390. stackSize--;
  391. continue;
  392. }
  393. }
  394. // shadowed?
  395. if(node->mLevel == 0)
  396. {
  397. marked = true;
  398. shadowList.push_back(pos.x + (pos.y << TerrainBlock::BlockShift));
  399. stackSize--;
  400. continue;
  401. }
  402. // setup the next level of squares
  403. U8 nextLevel = node->mLevel - 1;
  404. S32 squareHalfSize = 1 << nextLevel;
  405. for(U32 i = 0; i < 4; i++)
  406. {
  407. node[i].mLevel = nextLevel;
  408. node[i].mClipFlags = clipFlags;
  409. }
  410. node[3].mPos = pos;
  411. node[2].mPos.set(pos.x + squareHalfSize, pos.y);
  412. node[1].mPos.set(pos.x, pos.y + squareHalfSize);
  413. node[0].mPos.set(pos.x + squareHalfSize, pos.y + squareHalfSize);
  414. stackSize += 3;
  415. }
  416. return marked;
  417. */
  418. }
  419. void blTerrainProxy::lightVector(LightInfo * light)
  420. {
  421. // Grab our terrain object
  422. TerrainBlock* terrain = getObject();
  423. if (!terrain)
  424. return;
  425. // Get the direction to the light (the inverse of the direction
  426. // the light is pointing)
  427. Point3F lightDir = -light->getDirection();
  428. lightDir.normalize();
  429. // Get the ratio between the light map pixel and world space (used below)
  430. F32 lmTerrRatio = (F32)mTerrainBlockSize / (F32) mLightMapSize;
  431. lmTerrRatio *= terrain->getSquareSize();
  432. // Get the terrain position
  433. Point3F terrPos( terrain->getTransform().getPosition() );
  434. U32 i = 0;
  435. for (U32 y = 0; y < mLightMapSize; y++)
  436. {
  437. for (U32 x = 0; x < mLightMapSize; x++)
  438. {
  439. // Get the relative pixel position and scale it
  440. // by the ratio between lightmap and world space
  441. Point2F pixelPos(x, y);
  442. pixelPos *= lmTerrRatio;
  443. // Start with a default normal of straight up
  444. Point3F normal(0.0f, 0.0f, 1.0f);
  445. // Try to get the actual normal from the terrain.
  446. // Note: this won't change the default normal if
  447. // it can't find a normal.
  448. terrain->getNormal(pixelPos, &normal);
  449. // The terrain lightmap only contains shadows.
  450. F32 shadowed = 0.0f;
  451. // Get the height at the lightmap pixel's position
  452. F32 height = 0.0f;
  453. terrain->getHeight(pixelPos, &height);
  454. // Calculate the 3D position of the pixel
  455. Point3F pixelPos3F(pixelPos.x, pixelPos.y, height);
  456. // Translate that position by the terrain's transform
  457. terrain->getTransform().mulP(pixelPos3F);
  458. // Offset slighting along the normal so that we don't
  459. // raycast into ourself
  460. pixelPos3F += (normal * 0.1f);
  461. // Calculate the light's position.
  462. // If it is a vector light like the sun (no position
  463. // just direction) then translate along that direction
  464. // a reasonable distance to get a point sufficiently
  465. // far away
  466. Point3F lightPos = light->getPosition();
  467. if(light->getType() == LightInfo::Vector)
  468. {
  469. lightPos = 1000.f * lightDir;
  470. lightPos = pixelPos3F + lightPos;
  471. }
  472. // Cast a ray from the world space position of the lightmap pixel to the light source.
  473. // If we hit something then we are in shadow. This allows us to be shadowed by anything
  474. // that supports a castRay operation.
  475. RayInfo info;
  476. if(terrain->getContainer()->castRay(pixelPos3F, lightPos, STATIC_COLLISION_TYPEMASK, &info))
  477. {
  478. // Shadow the pixel.
  479. shadowed = 1.0f;
  480. }
  481. // Set the final lightmap color.
  482. mLightmap[i++] += ColorF::WHITE * mClampF( 1.0f - shadowed, 0.0f, 1.0f );
  483. }
  484. }
  485. }
  486. //--------------------------------------------------------------------------
  487. U32 blTerrainProxy::getResourceCRC()
  488. {
  489. TerrainBlock * terrain = getObject();
  490. if(!terrain)
  491. return(0);
  492. return(terrain->getCRC());
  493. }
  494. //--------------------------------------------------------------------------
  495. bool blTerrainProxy::setPersistInfo(PersistInfo::PersistChunk * info)
  496. {
  497. if(!Parent::setPersistInfo(info))
  498. return(false);
  499. blTerrainChunk * chunk = dynamic_cast<blTerrainChunk*>(info);
  500. AssertFatal(chunk, "blTerrainProxy::setPersistInfo: invalid info chunk!");
  501. TerrainBlock * terrain = getObject();
  502. if(!terrain || !terrain->getLightMap())
  503. return(false);
  504. terrain->setLightMap( new GBitmap( *chunk->mLightmap) );
  505. return(true);
  506. }
  507. bool blTerrainProxy::getPersistInfo(PersistInfo::PersistChunk * info)
  508. {
  509. if(!Parent::getPersistInfo(info))
  510. return(false);
  511. blTerrainChunk * chunk = dynamic_cast<blTerrainChunk*>(info);
  512. AssertFatal(chunk, "blTerrainProxy::getPersistInfo: invalid info chunk!");
  513. TerrainBlock * terrain = getObject();
  514. if(!terrain || !terrain->getLightMap())
  515. return(false);
  516. if(chunk->mLightmap) delete chunk->mLightmap;
  517. chunk->mLightmap = new GBitmap(*terrain->getLightMap());
  518. return(true);
  519. }
  520. bool blTerrainProxy::supportsShadowVolume()
  521. {
  522. return false;
  523. }
  524. void blTerrainProxy::getClipPlanes(Vector<PlaneF>& planes)
  525. {
  526. }
  527. void blTerrainProxy::addToShadowVolume(ShadowVolumeBSP * shadowVolume, LightInfo * light, S32 level)
  528. {
  529. }
  530. void blTerrainSystem::init()
  531. {
  532. }
  533. U32 blTerrainSystem::addObjectType()
  534. {
  535. return TerrainObjectType;
  536. }
  537. SceneLighting::ObjectProxy* blTerrainSystem::createObjectProxy(SceneObject* obj, SceneLighting::ObjectProxyList* sceneObjects)
  538. {
  539. if ((obj->getTypeMask() & TerrainObjectType) != 0)
  540. return new blTerrainProxy(obj);
  541. else
  542. return NULL;
  543. }
  544. PersistInfo::PersistChunk* blTerrainSystem::createPersistChunk(const U32 chunkType)
  545. {
  546. if (chunkType == PersistInfo::PersistChunk::TerrainChunkType)
  547. return new blTerrainChunk();
  548. else
  549. return NULL;
  550. }
  551. bool blTerrainSystem::createPersistChunkFromProxy(SceneLighting::ObjectProxy* objproxy, PersistInfo::PersistChunk **ret)
  552. {
  553. if (dynamic_cast<blTerrainProxy*>(objproxy) != NULL)
  554. {
  555. *ret = new blTerrainChunk();
  556. return true;
  557. } else {
  558. return NULL;
  559. }
  560. }
  561. // Given a ray, this will return the color from the lightmap of this object, return true if handled
  562. bool blTerrainSystem::getColorFromRayInfo(const RayInfo & collision, ColorF& result) const
  563. {
  564. TerrainBlock *terrain = dynamic_cast<TerrainBlock *>(collision.object);
  565. if (!terrain)
  566. return false;
  567. Point2F uv;
  568. F32 terrainlength = (F32)terrain->getBlockSize();
  569. Point3F pos = terrain->getPosition();
  570. uv.x = (collision.point.x - pos.x) / terrainlength;
  571. uv.y = (collision.point.y - pos.y) / terrainlength;
  572. // similar to x = x & width...
  573. uv.x = uv.x - F32(U32(uv.x));
  574. uv.y = uv.y - F32(U32(uv.y));
  575. const GBitmap* lightmap = terrain->getLightMap();
  576. if (!lightmap)
  577. return false;
  578. result = lightmap->sampleTexel(uv.x, uv.y);
  579. // terrain lighting is dim - look into this (same thing done in shaders)...
  580. result *= 2.0f;
  581. return true;
  582. }