PageRenderTime 146ms CodeModel.GetById 33ms RepoModel.GetById 1ms app.codeStats 1ms

/source/og-core/geo/VirtualGlobeTerrainBlock.cpp

http://github.com/OpenWebGlobe/Application-SDK
C++ | 1850 lines | 1261 code | 397 blank | 192 comment | 186 complexity | 80b264de54d71235b5e722b4a980c850 MD5 | raw file
Possible License(s): MIT

Large files files are truncated, but you can click here to view the full file

  1. /*******************************************************************************
  2. Project : i3D OpenWebGlobe SDK - Reference Implementation
  3. Version : 1.0
  4. Author : Martin Christen, martin.christen@fhnw.ch
  5. Copyright : (c) 2006-2011 by FHNW/IVGI. All Rights Reserved
  6. $License$
  7. *******************************************************************************/
  8. #include "geo/VirtualGlobeTerrainBlock.h"
  9. #include "renderer/BufferFactory.h"
  10. #include <math/mathutils.h>
  11. #include "geo/MercatorTransformation.h"
  12. #include "math/TextureTransformation.h"
  13. #include "geo/VirtualGlobeCache.h"
  14. //#include "VirtualGlobeRenderer.h"
  15. #include "renderer/gl/BuffersOGL.h"
  16. #include <iostream>
  17. //-----------------------------------------------------------------------------
  18. VirtualGlobeTerrainBlock::VirtualGlobeTerrainBlock(IRenderEngine* pEngine, const std::string& sQuadcode, const boost::shared_ptr<MercatorQuadtree>& qQuadtree)
  19. {
  20. _pEngine = pEngine;
  21. _qTexture = 0;
  22. _sQuadcode = sQuadcode;
  23. _qQuadtree = qQuadtree;
  24. _nLod = (int)_sQuadcode.length();
  25. _bReady = false;
  26. _nElevationBlockSize = 17;
  27. _nTextureSize = 256;
  28. _nImageDataChannels = 4;
  29. _bIsBlock = false;
  30. _bFinishMerge = false;
  31. _dCurtainElevation = 0.0;
  32. _curLayer = 0;
  33. _bBuffersCreated = false;
  34. CalcLocation();
  35. }
  36. //-----------------------------------------------------------------------------
  37. VirtualGlobeTerrainBlock::~VirtualGlobeTerrainBlock()
  38. {
  39. if (_qTexture)
  40. {
  41. _qTexture->Destroy();
  42. }
  43. }
  44. //-----------------------------------------------------------------------------
  45. void VirtualGlobeTerrainBlock::_OnTileReady(const std::string& sQuadcode, ImageTile* pTile)
  46. {
  47. if (!pTile || pTile->GetHeight() != pTile->GetWidth() || pTile->GetWidth() != 256)
  48. {
  49. assert(false);
  50. return;
  51. }
  52. _MergeImageData(pTile->GetRawData(), pTile->GetNumChannels(), pTile->GetWidth());
  53. delete pTile;
  54. if (IsMergeFinished())
  55. {
  56. SetReady();
  57. return;
  58. }
  59. _ContinueDownload();
  60. }
  61. //-----------------------------------------------------------------------------
  62. void VirtualGlobeTerrainBlock::_ContinueDownload()
  63. {
  64. size_t maximg = _lstImg.size();
  65. if (_curLayer>=(int)_lstImg.size()-1)
  66. {
  67. SetReady();
  68. return; //no more layers!
  69. }
  70. _curLayer++;
  71. for (size_t i=_curLayer;i<(int)_lstImg.size();i++)
  72. {
  73. _curLayer = i;
  74. IImageLayer* pLayer = _lstImg[i].get();
  75. // always interpolate last layer. We want to see data!
  76. if (_curLayer == maximg-1 || _nLod <= pLayer->GetMaxLod() /*&& _nLod>3*/)
  77. {
  78. pLayer->RequestTile(_sQuadcode,
  79. boost::bind(&VirtualGlobeTerrainBlock::_OnTileReady, this, _1, _2),
  80. boost::bind(&VirtualGlobeTerrainBlock::_OnTileFailed, this, _1));
  81. return;
  82. }
  83. }
  84. SetReady();
  85. }
  86. //-----------------------------------------------------------------------------
  87. void VirtualGlobeTerrainBlock::_OnTileFailed(const std::string& sQuadcode)
  88. {
  89. _ContinueDownload();
  90. }
  91. //-----------------------------------------------------------------------------
  92. void VirtualGlobeTerrainBlock::Request(std::vector< boost::shared_ptr<IImageLayer> >& lstImg, std::vector< boost::shared_ptr<IElevationLayer> >& lstElv)
  93. {
  94. _lstImg = lstImg;
  95. _lstElv = lstElv;
  96. // Request Elevation Tile
  97. const int tilesize = 9;
  98. boost::shared_array<float> data = boost::shared_array<float>(new float[tilesize*tilesize]);
  99. for (int i=0;i<tilesize*tilesize;i++) data[i] = 0;
  100. SetElevationDataBlock(data, tilesize);
  101. // Request Image Tile
  102. size_t maximg = lstImg.size();
  103. if (lstImg.size()>0)
  104. {
  105. for (size_t i=0;i<maximg;i++)
  106. {
  107. _curLayer = i;
  108. IImageLayer* pLayer = lstImg[i].get();
  109. // always interpolate last layer. We want to see data!
  110. if (_curLayer == maximg-1 || _nLod <= pLayer->GetMaxLod())
  111. {
  112. pLayer->RequestTile(_sQuadcode,
  113. boost::bind(&VirtualGlobeTerrainBlock::_OnTileReady, this, _1, _2),
  114. boost::bind(&VirtualGlobeTerrainBlock::_OnTileFailed, this, _1));
  115. return;
  116. }
  117. }
  118. }
  119. }
  120. //-----------------------------------------------------------------------------
  121. bool VirtualGlobeTerrainBlock::IsAvailable()
  122. {
  123. return _bReady;
  124. }
  125. //-----------------------------------------------------------------------------
  126. void VirtualGlobeTerrainBlock::SetReady()
  127. {
  128. _bReady = true;
  129. _CreateBuffers();
  130. }
  131. //-----------------------------------------------------------------------------
  132. void VirtualGlobeTerrainBlock::SetElevationData(ElevationTile& oElevationTile)
  133. {
  134. _vOffset = oElevationTile.GetOffset();
  135. _lstElevationPointWGS84 = oElevationTile.GetPointsWGS84();
  136. _lstTexCoord = oElevationTile.GetTexCoord();
  137. _lstPosIdx = oElevationTile.GetIndices();
  138. _vCornerPoints = oElevationTile.GetCornerPoints();
  139. _vNorthPoints = oElevationTile.GetNorthPoints();
  140. _vEastPoints = oElevationTile.GetEastPoints();
  141. _vSouthPoints = oElevationTile.GetSouthPoints();
  142. _vWestPoints = oElevationTile.GetWestPoints();
  143. //_vMiddlePoints = oElevationTile.GetMiddlePoints(); // middle points are currently not of interest... at a later time (real time recreation) it will be required...
  144. _bIsBlock = false; // this tile is a TIN!
  145. //}
  146. }
  147. //-----------------------------------------------------------------------------
  148. void VirtualGlobeTerrainBlock::SetElevationDataBlock(boost::shared_array<float>& data, unsigned int nBlocksize)
  149. {
  150. _nElevationBlockSize = nBlocksize;
  151. _qElevationData = data;
  152. _bIsBlock = true;
  153. }
  154. //-----------------------------------------------------------------------------
  155. void VirtualGlobeTerrainBlock::_MergeImageData(boost::shared_array<unsigned char>& data, unsigned int nChannels, unsigned int nTextureSize)
  156. {
  157. _nImageDataChannels = 4;
  158. // Mixing different Texture sizes is currently unsupported and could be added here...
  159. _nTextureSize = nTextureSize;
  160. if (!_qImageData) // no image data yet!
  161. {
  162. _qImageData = boost::shared_array<unsigned char>(new unsigned char[_nTextureSize*_nTextureSize*4]);
  163. memset(_qImageData.get(), 0, _nTextureSize*_nTextureSize*4);
  164. }
  165. // if a RGB image is loaded, convert to RGBA and overwrite everything that is transparent
  166. if (nChannels == 3)
  167. {
  168. // convert to RGBA
  169. unsigned int adr_src, adr_dst;
  170. for (unsigned int y=0;y<_nTextureSize;y++)
  171. {
  172. for (unsigned int x=0;x<_nTextureSize;x++)
  173. {
  174. adr_dst = 4*y*_nTextureSize+4*x; // RGBA
  175. adr_src = 3*y*_nTextureSize+3*x; // RGB
  176. unsigned char curAlpha = _qImageData.get()[adr_dst+3];
  177. //if (curAlpha < 255)
  178. {
  179. unsigned char red, green, blue;
  180. red = data.get()[adr_src+0];
  181. green = data.get()[adr_src+1];
  182. blue = data.get()[adr_src+2];
  183. if (red == 0 && green == 0 && blue == 0)
  184. {
  185. }
  186. else
  187. {
  188. double alpha = double(curAlpha) / 255.0; // 0...1
  189. _qImageData.get()[adr_dst+0] = unsigned char(alpha*(double)_qImageData.get()[adr_dst+0] + (1.0-alpha)*(double)data.get()[adr_src+0]);
  190. _qImageData.get()[adr_dst+1] = unsigned char(alpha*(double)_qImageData.get()[adr_dst+1] + (1.0-alpha)*(double)data.get()[adr_src+1]);
  191. _qImageData.get()[adr_dst+2] = unsigned char(alpha*(double)_qImageData.get()[adr_dst+2] + (1.0-alpha)*(double)data.get()[adr_src+2]);
  192. _qImageData.get()[adr_dst+3] = 255;
  193. }
  194. }
  195. }
  196. }
  197. _bFinishMerge = true;
  198. }
  199. else // channels = 4, _qImageData is set...
  200. {
  201. // Blend new data with old data using alpha value of new data...
  202. unsigned int adr_src, adr_dst;
  203. //unsigned char alpha;
  204. size_t alphacnt = _nTextureSize*_nTextureSize;
  205. for (unsigned int y=0;y<_nTextureSize;y++)
  206. {
  207. for (unsigned int x=0;x<_nTextureSize;x++)
  208. {
  209. adr_dst = 4*y*_nTextureSize+4*x; // RGBA
  210. adr_src = 4*y*_nTextureSize+4*x; // RGBA
  211. unsigned char curAlpha = _qImageData.get()[adr_dst+3];
  212. unsigned char red, green, blue, alpha;
  213. red = data.get()[adr_src+0];
  214. green = data.get()[adr_src+1];
  215. blue = data.get()[adr_src+2];
  216. alpha = data.get()[adr_src+3];
  217. /*if (curAlpha <5)
  218. {
  219. _qImageData.get()[adr_dst+0] = data.get()[adr_src+0];
  220. _qImageData.get()[adr_dst+1] = data.get()[adr_src+1];
  221. _qImageData.get()[adr_dst+2] = data.get()[adr_src+2];
  222. _qImageData.get()[adr_dst+3] = data.get()[adr_src+3];
  223. }*/
  224. //else //if (curAlpha < 255)
  225. {
  226. if (red == 0 && green == 0 && blue == 0)
  227. {
  228. }
  229. else
  230. {
  231. double talpha = _qImageData.get()[adr_src+3] / 255.0; // 0...1
  232. _qImageData.get()[adr_dst+0] = unsigned char(talpha*(double)_qImageData.get()[adr_dst+0] + (1.0-talpha)*(double)data.get()[adr_src+0]);
  233. _qImageData.get()[adr_dst+1] = unsigned char(talpha*(double)_qImageData.get()[adr_dst+1] + (1.0-talpha)*(double)data.get()[adr_src+1]);
  234. _qImageData.get()[adr_dst+2] = unsigned char(talpha*(double)_qImageData.get()[adr_dst+2] + (1.0-talpha)*(double)data.get()[adr_src+2]);
  235. _qImageData.get()[adr_dst+3] = unsigned char(talpha*(double)_qImageData.get()[adr_dst+3] + (1.0-talpha)*(double)data.get()[adr_src+3]);;
  236. }
  237. }
  238. if (curAlpha == 255)
  239. {
  240. alphacnt--;
  241. }
  242. }
  243. }
  244. if (alphacnt == 0)
  245. {
  246. _bFinishMerge = true;
  247. }
  248. }
  249. }
  250. //-----------------------------------------------------------------------------
  251. inline void _ttScale(TextureTransformation<double>& oTexTransSet, double x, double y, double z)
  252. {
  253. oTexTransSet._vScale.x *= x;
  254. oTexTransSet._vScale.y *= y;
  255. oTexTransSet._vScale.z *= z;
  256. }
  257. //-----------------------------------------------------------------------------
  258. inline void _ttTranslate(TextureTransformation<double>& oTexTransSet, double x, double y, double z)
  259. {
  260. oTexTransSet._vTranslation.x += oTexTransSet._vScale.x * x;
  261. oTexTransSet._vTranslation.y += oTexTransSet._vScale.y * y;
  262. oTexTransSet._vTranslation.z += oTexTransSet._vScale.z * z;
  263. }
  264. //-----------------------------------------------------------------------------
  265. void VirtualGlobeTerrainBlock::_QuadKeyMatrixTraversal(std::string& sLowQuadcode, std::string& sHighQuadcode, TextureTransformation<double>& outTexTrans)
  266. {
  267. outTexTrans.SetIdentity();
  268. int nHighDepth = sLowQuadcode.size();
  269. int nLowDepth = sHighQuadcode.size();
  270. std::string sCurQuadcode = sLowQuadcode;
  271. for (int i=nLowDepth; i < nHighDepth; i++)
  272. {
  273. int nLocation = _qQuadtree->GetQuad(sLowQuadcode,i);
  274. switch(nLocation)
  275. {
  276. case 0:
  277. _ttTranslate(outTexTrans, 0, 0.5, 0);
  278. _ttScale(outTexTrans, 0.5, 0.5, 0);
  279. break;
  280. case 1:
  281. _ttTranslate(outTexTrans, 0.5, 0.5f, 0);
  282. _ttScale(outTexTrans, 0.5, 0.5, 0);
  283. break;
  284. case 2:
  285. //_ttTranslate(oTexTransSet, 0, 0, 0);
  286. _ttScale(outTexTrans, 0.5, 0.5, 0);
  287. break;
  288. case 3:
  289. _ttTranslate(outTexTrans, 0.5, 0, 0);
  290. _ttScale(outTexTrans, 0.5, 0.5, 0);
  291. break;
  292. }
  293. }
  294. }
  295. void VirtualGlobeTerrainBlock::_SetTexture(ITexture* qTexture, bool bLinear)
  296. {
  297. qTexture->BindTexture(0);
  298. if (bLinear)
  299. {
  300. glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER, GL_LINEAR); // Linear Filtering
  301. glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER, GL_LINEAR); // Linear Filtering
  302. }
  303. else
  304. {
  305. glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER, GL_NEAREST); // Linear Filtering
  306. glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER, GL_NEAREST); // Linear Filtering
  307. }
  308. //glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 8.0f);
  309. if (GLEW_EXT_texture_edge_clamp)
  310. {
  311. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
  312. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
  313. }
  314. else
  315. {
  316. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
  317. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
  318. }
  319. }
  320. //-----------------------------------------------------------------------------
  321. inline void _DrawBoundingBox(const aabb3<double>& bbox)
  322. {
  323. //bool bAxisAligned = false;
  324. vec3<double> t(0,0,0);
  325. double r,g,b;
  326. vec3<double> minv;
  327. vec3<double> maxv;
  328. r = 1; g = 0; b = 0;
  329. minv = bbox.MinEdge;
  330. maxv = bbox.MaxEdge;
  331. double dx, dy, dz;
  332. dx = fabs(maxv.x-minv.x);
  333. dy = fabs(maxv.y-minv.y);
  334. dz = fabs(maxv.z-minv.z);
  335. vec3<double> A( minv.x, minv.y, minv.z);
  336. vec3<double> B( minv.x+dx, minv.y, minv.z);
  337. vec3<double> C( minv.x+dx, minv.y+dy, minv.z);
  338. vec3<double> D( minv.x, minv.y+dy, minv.z);
  339. vec3<double> E( minv.x, minv.y, minv.z+dz);
  340. vec3<double> F( minv.x+dx, minv.y, minv.z+dz);
  341. vec3<double> G( minv.x+dx, minv.y+dy, minv.z+dz);
  342. vec3<double> H( minv.x, minv.y+dy, minv.z+dz);
  343. glPushAttrib(GL_CURRENT_BIT);
  344. glPushMatrix();
  345. // load view matrix, we don't want to use current model matrix because
  346. // aabb has absolute values!
  347. //glLoadMatrixd(_matView.GetGLMatrix());
  348. glLineWidth(2.5);
  349. // "Boden"
  350. glBegin(GL_LINES);
  351. // Boden: ABCD
  352. glColor3d(r,g,b); glVertex3d(A.x+t.x,A.y+t.y,A.z+t.z);
  353. glColor3d(r,g,b); glVertex3d(B.x+t.x,B.y+t.y,B.z+t.z);
  354. glColor3d(r,g,b); glVertex3d(B.x+t.x,B.y+t.y,B.z+t.z);
  355. glColor3d(r,g,b); glVertex3d(C.x+t.x,C.y+t.y,C.z+t.z);
  356. glColor3d(r,g,b); glVertex3d(C.x+t.x,C.y+t.y,C.z+t.z);
  357. glColor3d(r,g,b); glVertex3d(D.x+t.x,D.y+t.y,D.z+t.z);
  358. glColor3d(r,g,b); glVertex3d(D.x+t.x,D.y+t.y,D.z+t.z);
  359. glColor3d(r,g,b); glVertex3d(A.x+t.x,A.y+t.y,A.z+t.z);
  360. // Deckel
  361. glColor3d(r,g,b); glVertex3d(E.x+t.x,E.y+t.y,E.z+t.z);
  362. glColor3d(r,g,b); glVertex3d(F.x+t.x,F.y+t.y,F.z+t.z);
  363. glColor3d(r,g,b); glVertex3d(F.x+t.x,F.y+t.y,F.z+t.z);
  364. glColor3d(r,g,b); glVertex3d(G.x+t.x,G.y+t.y,G.z+t.z);
  365. glColor3d(r,g,b); glVertex3d(G.x+t.x,G.y+t.y,G.z+t.z);
  366. glColor3d(r,g,b); glVertex3d(H.x+t.x,H.y+t.y,H.z+t.z);
  367. glColor3d(r,g,b); glVertex3d(H.x+t.x,H.y+t.y,H.z+t.z);
  368. glColor3d(r,g,b); glVertex3d(E.x+t.x,E.y+t.y,E.z+t.z);
  369. //AE,BF,CG,DH
  370. glColor3d(r,g,b); glVertex3d(A.x+t.x,A.y+t.y,A.z+t.z);
  371. glColor3d(r,g,b); glVertex3d(E.x+t.x,E.y+t.y,E.z+t.z);
  372. glColor3d(r,g,b); glVertex3d(B.x+t.x,B.y+t.y,B.z+t.z);
  373. glColor3d(r,g,b); glVertex3d(F.x+t.x,F.y+t.y,F.z+t.z);
  374. glColor3d(r,g,b); glVertex3d(C.x+t.x,C.y+t.y,C.z+t.z);
  375. glColor3d(r,g,b); glVertex3d(G.x+t.x,G.y+t.y,G.z+t.z);
  376. glColor3d(r,g,b); glVertex3d(D.x+t.x,D.y+t.y,D.z+t.z);
  377. glColor3d(r,g,b); glVertex3d(H.x+t.x,H.y+t.y,H.z+t.z);
  378. glEnd();
  379. glPopMatrix();
  380. glPopAttrib();
  381. }
  382. //-----------------------------------------------------------------------------
  383. void VirtualGlobeTerrainBlock::_CreateBuffers()
  384. {
  385. if (_bBuffersCreated)
  386. {
  387. assert(false); // already created!
  388. return;
  389. }
  390. _CreateTexture();
  391. _CreateVertexBuffer();
  392. _CreateIndexBuffer();
  393. _bBuffersCreated = true;
  394. }
  395. //-----------------------------------------------------------------------------
  396. void VirtualGlobeTerrainBlock::Render(const mat4<double>& oModelMatrix, const mat4<double>& oViewMatrix, boost::shared_ptr<VirtualGlobeCache>& qCache/*, const VirtualGlobeRenderOptions& oRenderOptions*/)
  397. {
  398. //-------------------------
  399. // some options:
  400. bool bShowCurtain = true;
  401. bool bShowBB = false;
  402. //-------------------------
  403. if (_qVB && _qIB)
  404. {
  405. if (_qTexture)
  406. {
  407. _SetTexture(_qTexture, true);
  408. }
  409. else
  410. {
  411. // Search through qCache and find texture of this area...
  412. std::string sQuadcode = _sQuadcode;
  413. std::string sQuadcodeWithTexture;
  414. ITexture* qParentTexture;
  415. do
  416. {
  417. sQuadcode = _qQuadtree->GetParent(sQuadcode);
  418. boost::shared_ptr<VirtualGlobeTerrainBlock> qBlock = qCache->GetCachedBlock(sQuadcode);
  419. if (qBlock)
  420. {
  421. if (qBlock->IsAvailable())
  422. {
  423. qParentTexture = qBlock->GetTexture();
  424. if (qParentTexture)
  425. {
  426. sQuadcodeWithTexture = sQuadcode;
  427. break;
  428. }
  429. }
  430. }
  431. } while(sQuadcode.size()>2);
  432. if (qParentTexture)
  433. {
  434. TextureTransformation<double> outTexTrans;
  435. mat4<double> oTextureMatrix;
  436. _QuadKeyMatrixTraversal(_sQuadcode, sQuadcodeWithTexture, outTexTrans);
  437. outTexTrans.ToMatrix4x4(oTextureMatrix);
  438. glMatrixMode(GL_TEXTURE);
  439. glLoadMatrixd(oTextureMatrix.GetGLMatrix());
  440. _SetTexture(qParentTexture, true);
  441. glMatrixMode(GL_MODELVIEW);
  442. }
  443. else
  444. {
  445. glBindTexture(GL_TEXTURE_2D, 0);
  446. }
  447. }
  448. if (_bIsBlock)
  449. {
  450. glPushMatrix();
  451. {
  452. mat4<double> model = oModelMatrix;
  453. model._vals[3][0] += _vOffset.x;
  454. model._vals[3][1] += _vOffset.y;
  455. model._vals[3][2] += _vOffset.z;
  456. mat4<double> modelview = oViewMatrix * model;
  457. glLoadMatrixd(modelview.GetGLMatrix());
  458. SetVertexBuffer(_qVB.get());
  459. DrawIndexedPrimitive(GL_TRIANGLE_STRIP, _qIB.get());
  460. //_RenderPointCloud(oRenderOptions.fPointSize);
  461. }
  462. glPopMatrix();
  463. }
  464. else
  465. {
  466. glPushMatrix();
  467. mat4<double> model = oModelMatrix;
  468. model._vals[3][0] += _vOffset.x;
  469. model._vals[3][1] += _vOffset.y;
  470. model._vals[3][2] += _vOffset.z;
  471. mat4<double> modelview = oViewMatrix * model;
  472. glLoadMatrixd(modelview.GetGLMatrix());
  473. //Draw Regular Terrain BUffer:
  474. SetVertexBuffer(_qVB.get());
  475. DrawIndexedPrimitive(GL_TRIANGLES, _qIB.get());
  476. //if (!oRenderOptions.bWireframe)
  477. {
  478. if (bShowCurtain)
  479. {
  480. //Draw Stiching Buffer:
  481. if (_qVBStichN && _qIBStichN)
  482. {
  483. SetVertexBuffer(_qVBStichN.get());
  484. DrawIndexedPrimitive(GL_TRIANGLES, _qIBStichN.get());
  485. }
  486. if (_qVBStichE && _qIBStichE)
  487. {
  488. SetVertexBuffer(_qVBStichE.get());
  489. DrawIndexedPrimitive(GL_TRIANGLES, _qIBStichE.get());
  490. }
  491. if (_qVBStichS && _qIBStichS)
  492. {
  493. SetVertexBuffer(_qVBStichS.get());
  494. DrawIndexedPrimitive(GL_TRIANGLES, _qIBStichS.get());
  495. }
  496. if (_qVBStichW && _qIBStichW)
  497. {
  498. SetVertexBuffer(_qVBStichW.get());
  499. DrawIndexedPrimitive(GL_TRIANGLES, _qIBStichW.get());
  500. }
  501. }
  502. }
  503. //_RenderPointCloud(oRenderOptions.fPointSize);
  504. glPopMatrix();
  505. if (bShowBB)
  506. {
  507. _DrawBoundingBox(_BoundingBox);
  508. }
  509. }
  510. if (!_qTexture)
  511. {
  512. glMatrixMode(GL_TEXTURE);
  513. glLoadIdentity();
  514. glMatrixMode(GL_MODELVIEW);
  515. }
  516. }
  517. }
  518. //-----------------------------------------------------------------------------
  519. // Create Vertex Buffer as Block (if no TIN data is available!)
  520. void VirtualGlobeTerrainBlock::_CreateVertexBufferBlock()
  521. {
  522. if (!_qElevationData || !_qQuadtree)
  523. {
  524. assert(false);
  525. return;
  526. }
  527. boost::shared_ptr<IVertexAttributeBuffer> qAttributePosition;
  528. boost::shared_ptr<IVertexAttributeBuffer> qAttributeTextureCoord;
  529. boost::shared_array<float> qTempVertexBuffer = boost::shared_array<float>(new float[3*_nElevationBlockSize*_nElevationBlockSize]);
  530. boost::shared_array<float> qTempTexcoordBuffer = boost::shared_array<float>(new float[2*_nElevationBlockSize*_nElevationBlockSize]);
  531. _qVB = BufferFactory::CreateVertexBuffer(_nElevationBlockSize*_nElevationBlockSize, true);
  532. qAttributePosition = BufferFactory::CreateVertexAttributeBuffer(_nElevationBlockSize*_nElevationBlockSize, Vertex, float3);
  533. qAttributeTextureCoord = BufferFactory::CreateVertexAttributeBuffer(_nElevationBlockSize*_nElevationBlockSize, TexCoord0, float2);
  534. //-----------------------------------------------------------------------------
  535. // 1. Create Texture Coordinates
  536. //-----------------------------------------------------------------------------
  537. float fdX;
  538. fdX = 1.0f / float(_nElevationBlockSize-1);
  539. if (qTempTexcoordBuffer)
  540. {
  541. for (unsigned int nV = 0; nV<_nElevationBlockSize; nV++)
  542. {
  543. for (unsigned int nU = 0; nU<_nElevationBlockSize; nU++)
  544. {
  545. qTempTexcoordBuffer[2*(nV*_nElevationBlockSize+nU)+0] = nU*fdX;
  546. qTempTexcoordBuffer[2*(nV*_nElevationBlockSize+nU)+1] = /*1.0f-*/nV*fdX;
  547. }
  548. }
  549. }
  550. //-----------------------------------------------------------------------------
  551. // 2. Create Vertex Positions
  552. //-----------------------------------------------------------------------------
  553. double x0,y0,x1,y1;
  554. _qQuadtree->QuadKeyToMercatorCoord(_sQuadcode, x0, y0, x1, y1);
  555. double dH = (y1-y0)/double(_nElevationBlockSize-1);
  556. double dW = (x1-x0)/double(_nElevationBlockSize-1);
  557. double x_coord, y_coord;
  558. double x_cart, y_cart, z_cart;
  559. GeoCoord g;
  560. for (unsigned int y=0;y<_nElevationBlockSize;y++)
  561. {
  562. for (unsigned int x=0;x<_nElevationBlockSize;x++)
  563. {
  564. x_coord = x0 + (double)x*dW;
  565. y_coord = y0 + (double)y*dH;
  566. // Calculate 3D Position:
  567. _qQuadtree->MercatorToWGS84(x_coord, y_coord);
  568. g.SetLongitude(x_coord);
  569. g.SetLatitude(y_coord);
  570. g.SetEllipsoidHeight((double)_qElevationData.get()[y*_nElevationBlockSize+x]);
  571. g.ToCartesian(&x_cart, &y_cart, &z_cart);
  572. if (x==0 && y==0)
  573. {
  574. _vOffset = vec3<double>(x_cart, y_cart, z_cart);
  575. }
  576. if (x==0 && y==0)
  577. {
  578. _vTilePoints[0].x = x_cart; _vTilePoints[0].y = y_cart; _vTilePoints[0].z = z_cart;
  579. }
  580. else if (x==_nElevationBlockSize-1 && y==0)
  581. {
  582. _vTilePoints[1].x = x_cart; _vTilePoints[1].y = y_cart; _vTilePoints[1].z = z_cart;
  583. }
  584. else if (x==_nElevationBlockSize-1 && y==_nElevationBlockSize-1)
  585. {
  586. _vTilePoints[2].x = x_cart; _vTilePoints[2].y = y_cart; _vTilePoints[2].z = z_cart;
  587. }
  588. else if (x==0 && y==_nElevationBlockSize-1)
  589. {
  590. _vTilePoints[3].x = x_cart; _vTilePoints[3].y = y_cart; _vTilePoints[3].z = z_cart;
  591. }
  592. else if (x==_nElevationBlockSize/2 && y==_nElevationBlockSize/2)
  593. {
  594. _vTilePoints[4].x = x_cart; _vTilePoints[4].y = y_cart; _vTilePoints[4].z = z_cart;
  595. }
  596. qTempVertexBuffer.get()[3*y*_nElevationBlockSize+3*x+0] = (float) (x_cart -_vOffset.x);
  597. qTempVertexBuffer.get()[3*y*_nElevationBlockSize+3*x+1] = (float) (y_cart -_vOffset.y);
  598. qTempVertexBuffer.get()[3*y*_nElevationBlockSize+3*x+2] = (float) (z_cart -_vOffset.z);
  599. }
  600. }
  601. // Upload to GPU
  602. memcpy(qAttributePosition->GetDataPtr(), qTempVertexBuffer.get(), 3*_nElevationBlockSize*_nElevationBlockSize*sizeof(float));
  603. memcpy(qAttributeTextureCoord->GetDataPtr(), qTempTexcoordBuffer.get(), 2*_nElevationBlockSize*_nElevationBlockSize*sizeof(float));
  604. _qVB->AddVertexAttributeBuffer(qAttributePosition);
  605. _qVB->AddVertexAttributeBuffer(qAttributeTextureCoord);
  606. _qVB->CreateVRAMObject();
  607. _qVB->CopyToVRAM(true);
  608. // Update Bounding box for this block!
  609. _UpdateBoundingBox();
  610. }
  611. //-----------------------------------------------------------------------------
  612. void VirtualGlobeTerrainBlock::_CreateVertexBufferTIN()
  613. {
  614. if (_lstTexCoord.size() != _lstElevationPointWGS84.size())
  615. {
  616. assert(false);
  617. return;
  618. }
  619. if (_lstElevationPointWGS84.size()<3)
  620. return;
  621. unsigned int nBufferSize = (unsigned int)_lstElevationPointWGS84.size();
  622. _qVB = BufferFactory::CreateVertexBuffer(nBufferSize, true);
  623. if (!_qVB)
  624. {
  625. assert(false);
  626. return;
  627. }
  628. boost::shared_ptr<IVertexAttributeBuffer> qAttributeTextureCoord = BufferFactory::CreateVertexAttributeBuffer(nBufferSize, TexCoord0, float2);
  629. boost::shared_ptr<IVertexAttributeBuffer> qAttrPosition = BufferFactory::CreateVertexAttributeBuffer(nBufferSize, Vertex, float3);
  630. for (size_t i=0; i< _lstElevationPointWGS84.size();i++)
  631. {
  632. qAttributeTextureCoord->SetValue(unsigned int(i), _lstTexCoord[i].x, _lstTexCoord[i].y);
  633. qAttrPosition->SetValue(unsigned int(i), _lstElevationPointWGS84[i].x, _lstElevationPointWGS84[i].y, _lstElevationPointWGS84[i].z);
  634. }
  635. // Add Buffers
  636. _qVB->AddVertexAttributeBuffer(qAttrPosition);
  637. _qVB->AddVertexAttributeBuffer(qAttributeTextureCoord);
  638. //_qVB->AddVertexAttributeBuffer(qAttrNormals);
  639. _qVB->CreateVRAMObject();
  640. _qVB->CopyToVRAM(true);
  641. // Update Bounding box for this block!
  642. _UpdateBoundingBox();
  643. }
  644. //-----------------------------------------------------------------------------
  645. void VirtualGlobeTerrainBlock::_CreateVertexBufferTINCurtainNorth()
  646. {
  647. // Data is TIN
  648. std::vector<ElevationPoint>::iterator it;
  649. if (_lstElevationPointWGS84.size()<3)
  650. return;
  651. unsigned int nBufferSize = 2*(2 + // corner points count double...
  652. + (unsigned int) _vNorthPoints.size());
  653. _qVBStichN = BufferFactory::CreateVertexBuffer(nBufferSize, true);
  654. if (!_qVBStichN)
  655. {
  656. assert(false);
  657. return;
  658. }
  659. boost::shared_ptr<IVertexAttributeBuffer> qAttributeTextureCoord = BufferFactory::CreateVertexAttributeBuffer(nBufferSize, TexCoord0, float2);
  660. boost::shared_ptr<IVertexAttributeBuffer> qAttrPosition = BufferFactory::CreateVertexAttributeBuffer(nBufferSize, Vertex, float3);
  661. std::vector<ElevationPoint> vWall;
  662. ElevationPoint ptTmp;
  663. /* N
  664. ------>
  665. 3 +-----------+ 2
  666. ^ | | ^
  667. | | | |
  668. W | | | | E
  669. | | | |
  670. | |
  671. 0 +-----------+ 1
  672. ------->
  673. S
  674. */
  675. //If one edge point is below zero, draw curtain 200 meters below the value of this edge point.
  676. _dCurtainElevation = 0;
  677. double minElevation = 0.0;
  678. for (size_t i = 0; i < _vNorthPoints.size(); i++)
  679. {
  680. minElevation = MIN(minElevation, _vNorthPoints[i].elevation);
  681. }
  682. for (size_t i = 0; i < _vEastPoints.size(); i++)
  683. {
  684. minElevation = MIN(minElevation, _vEastPoints[i].elevation);
  685. }
  686. for (size_t i = 0; i < _vSouthPoints.size(); i++)
  687. {
  688. minElevation = MIN(minElevation, _vSouthPoints[i].elevation);
  689. }
  690. for (size_t i = 0; i < _vWestPoints.size(); i++)
  691. {
  692. minElevation = MIN(minElevation, _vWestPoints[i].elevation);
  693. }
  694. if (minElevation < 0.0)
  695. {
  696. _dCurtainElevation = minElevation - 1000;
  697. }
  698. //----------------------
  699. // POINTS FOR NORTH WALL
  700. //----------------------
  701. ptTmp = _vCornerPoints[3];
  702. vWall.push_back(ptTmp);
  703. ptTmp.elevation = _dCurtainElevation;
  704. vWall.push_back(ptTmp);
  705. for (size_t p=0;p<_vNorthPoints.size();p++)
  706. {
  707. ptTmp = _vNorthPoints[p];
  708. vWall.push_back(ptTmp);
  709. ptTmp.elevation = _dCurtainElevation;
  710. vWall.push_back(ptTmp);
  711. }
  712. ptTmp = _vCornerPoints[2];
  713. vWall.push_back(ptTmp);
  714. ptTmp.elevation = _dCurtainElevation;
  715. vWall.push_back(ptTmp);
  716. // Make sure everything is calculated correctly!!
  717. assert(nBufferSize == vWall.size());
  718. // Create Buffer
  719. int i=0;
  720. GeoCoord oGeoCoord;
  721. GeoCoord oGeoCoordNorm;
  722. double lng, lat;
  723. double x,y,z;
  724. double TexCoordOffsetX = _vCornerPoints[0].x;
  725. double TexCoordOffsetY = _vCornerPoints[0].y;
  726. double TexCoordDX = fabs(_vCornerPoints[1].x - _vCornerPoints[0].x);
  727. double TexCoordDY = fabs(_vCornerPoints[3].y - _vCornerPoints[0].y);
  728. it = vWall.begin();
  729. while (it!=vWall.end())
  730. {
  731. GeoRef::Mercator::ReverseCustom((*it).x, (*it).y, lng, lat, 0.0);
  732. oGeoCoord.SetLatitude(lat);
  733. oGeoCoord.SetLongitude(lng);
  734. oGeoCoord.SetEllipsoidHeight((*it).elevation);
  735. oGeoCoord.ToCartesian(&x,&y,&z);
  736. double u = ((*it).x - TexCoordOffsetX) / TexCoordDX;
  737. double v = 1.0; // 0.0
  738. qAttributeTextureCoord->SetValue(unsigned int(i), (float)u, (float)v);
  739. // Set Attribute Position with virtual camera offset:
  740. qAttrPosition->SetValue(unsigned int(i),
  741. (float) (x-_vOffset.x),
  742. (float) (y-_vOffset.y),
  743. (float) (z-_vOffset.z));
  744. it++;
  745. //normit++;
  746. i++;
  747. }
  748. // Texture Coordinate: #todo
  749. // Add Buffers
  750. _qVBStichN->AddVertexAttributeBuffer(qAttrPosition);
  751. _qVBStichN->AddVertexAttributeBuffer(qAttributeTextureCoord);
  752. _qVBStichN->CreateVRAMObject();
  753. _qVBStichN->CopyToVRAM(true);
  754. }
  755. //-----------------------------------------------------------------------------
  756. void VirtualGlobeTerrainBlock::_CreateVertexBufferTINCurtainEast()
  757. {
  758. // Data is TIN
  759. std::vector<ElevationPoint>::iterator it;
  760. if (_lstElevationPointWGS84.size()<3)
  761. return;
  762. unsigned int nBufferSize = 2*(2 + // corner points count double...
  763. + (unsigned int) _vEastPoints.size());
  764. _qVBStichE = BufferFactory::CreateVertexBuffer(nBufferSize, true);
  765. if (!_qVBStichE)
  766. {
  767. assert(false);
  768. return;
  769. }
  770. boost::shared_ptr<IVertexAttributeBuffer> qAttributeTextureCoord = BufferFactory::CreateVertexAttributeBuffer(nBufferSize, TexCoord0, float2);
  771. boost::shared_ptr<IVertexAttributeBuffer> qAttrPosition = BufferFactory::CreateVertexAttributeBuffer(nBufferSize, Vertex, float3);
  772. std::vector<ElevationPoint> vWall;
  773. ElevationPoint ptTmp;
  774. //----------------------
  775. // POINTS FOR EAST WALL
  776. //----------------------
  777. ptTmp = _vCornerPoints[1];
  778. vWall.push_back(ptTmp);
  779. ptTmp.elevation = _dCurtainElevation;
  780. vWall.push_back(ptTmp);
  781. for (size_t p=0;p<_vEastPoints.size();p++)
  782. {
  783. ptTmp = _vEastPoints[p];
  784. vWall.push_back(ptTmp);
  785. ptTmp.elevation = _dCurtainElevation;
  786. vWall.push_back(ptTmp);
  787. }
  788. ptTmp = _vCornerPoints[2];
  789. vWall.push_back(ptTmp);
  790. ptTmp.elevation = _dCurtainElevation;
  791. vWall.push_back(ptTmp);
  792. // Make sure everything is calculated correctly!!
  793. assert(nBufferSize == vWall.size());
  794. // Create Buffer
  795. int i=0;
  796. GeoCoord oGeoCoord;
  797. GeoCoord oGeoCoordNorm;
  798. double lng, lat;
  799. double x,y,z;
  800. double TexCoordOffsetX = _vCornerPoints[0].x;
  801. double TexCoordOffsetY = _vCornerPoints[0].y;
  802. double TexCoordDX = fabs(_vCornerPoints[1].x - _vCornerPoints[0].x);
  803. double TexCoordDY = fabs(_vCornerPoints[3].y - _vCornerPoints[0].y);
  804. it = vWall.begin();
  805. while (it!=vWall.end())
  806. {
  807. GeoRef::Mercator::ReverseCustom((*it).x, (*it).y, lng, lat, 0.0);
  808. oGeoCoord.SetLatitude(lat);
  809. oGeoCoord.SetLongitude(lng);
  810. oGeoCoord.SetEllipsoidHeight((*it).elevation);
  811. oGeoCoord.ToCartesian(&x,&y,&z);
  812. double u = 1.0;
  813. double v = ((*it).y - TexCoordOffsetY) / TexCoordDY;
  814. qAttributeTextureCoord->SetValue(unsigned int(i), (float)u, (float)v);
  815. // Set Attribute Position with virtual camera offset:
  816. qAttrPosition->SetValue(unsigned int(i),
  817. (float) (x-_vOffset.x),
  818. (float) (y-_vOffset.y),
  819. (float) (z-_vOffset.z));
  820. it++;
  821. //normit++;
  822. i++;
  823. }
  824. // Texture Coordinate: #todo
  825. // Add Buffers
  826. _qVBStichE->AddVertexAttributeBuffer(qAttrPosition);
  827. _qVBStichE->AddVertexAttributeBuffer(qAttributeTextureCoord);
  828. //_qVB->AddVertexAttributeBuffer(qAttrNormals);
  829. _qVBStichE->CreateVRAMObject();
  830. _qVBStichE->CopyToVRAM(true);
  831. }
  832. //-----------------------------------------------------------------------------
  833. void VirtualGlobeTerrainBlock::_CreateVertexBufferTINCurtainSouth()
  834. {
  835. // Data is TIN
  836. std::vector<ElevationPoint>::iterator it;
  837. if (_lstElevationPointWGS84.size()<3)
  838. return;
  839. unsigned int nBufferSize = 2*(2 + // corner points count double...
  840. + (unsigned int) _vSouthPoints.size());
  841. _qVBStichS = BufferFactory::CreateVertexBuffer(nBufferSize, true);
  842. if (!_qVBStichS)
  843. {
  844. assert(false);
  845. return;
  846. }
  847. boost::shared_ptr<IVertexAttributeBuffer> qAttributeTextureCoord = BufferFactory::CreateVertexAttributeBuffer(nBufferSize, TexCoord0, float2);
  848. boost::shared_ptr<IVertexAttributeBuffer> qAttrPosition = BufferFactory::CreateVertexAttributeBuffer(nBufferSize, Vertex, float3);
  849. std::vector<ElevationPoint> vWall;
  850. ElevationPoint ptTmp;
  851. //----------------------
  852. // POINTS FOR SOUTH WALL
  853. //----------------------
  854. ptTmp = _vCornerPoints[0];
  855. vWall.push_back(ptTmp);
  856. ptTmp.elevation = _dCurtainElevation;
  857. vWall.push_back(ptTmp);
  858. for (size_t p=0;p<_vSouthPoints.size();p++)
  859. {
  860. ptTmp = _vSouthPoints[p];
  861. vWall.push_back(ptTmp);
  862. ptTmp.elevation = _dCurtainElevation;
  863. vWall.push_back(ptTmp);
  864. }
  865. ptTmp = _vCornerPoints[1];
  866. vWall.push_back(ptTmp);
  867. ptTmp.elevation = _dCurtainElevation;
  868. vWall.push_back(ptTmp);
  869. // Make sure everything is calculated correctly!!
  870. assert(nBufferSize == vWall.size());
  871. // Create Buffer
  872. int i=0;
  873. GeoCoord oGeoCoord;
  874. GeoCoord oGeoCoordNorm;
  875. double lng, lat;
  876. double x,y,z;
  877. double TexCoordOffsetX = _vCornerPoints[0].x;
  878. double TexCoordOffsetY = _vCornerPoints[0].y;
  879. double TexCoordDX = fabs(_vCornerPoints[1].x - _vCornerPoints[0].x);
  880. double TexCoordDY = fabs(_vCornerPoints[3].y - _vCornerPoints[0].y);
  881. it = vWall.begin();
  882. while (it!=vWall.end())
  883. {
  884. GeoRef::Mercator::ReverseCustom((*it).x, (*it).y, lng, lat, 0.0);
  885. oGeoCoord.SetLatitude(lat);
  886. oGeoCoord.SetLongitude(lng);
  887. oGeoCoord.SetEllipsoidHeight((*it).elevation);
  888. oGeoCoord.ToCartesian(&x,&y,&z);
  889. double u = ((*it).x - TexCoordOffsetX) / TexCoordDX;
  890. double v = 0.0; // 1.0
  891. qAttributeTextureCoord->SetValue(unsigned int(i), (float)u, (float)v);
  892. // Set Attribute Position with virtual camera offset:
  893. qAttrPosition->SetValue(unsigned int(i),
  894. (float) (x-_vOffset.x),
  895. (float) (y-_vOffset.y),
  896. (float) (z-_vOffset.z));
  897. it++;
  898. //normit++;
  899. i++;
  900. }
  901. // Texture Coordinate: #todo
  902. // Add Buffers
  903. _qVBStichS->AddVertexAttributeBuffer(qAttrPosition);
  904. _qVBStichS->AddVertexAttributeBuffer(qAttributeTextureCoord);
  905. _qVBStichS->CreateVRAMObject();
  906. _qVBStichS->CopyToVRAM(true);
  907. }
  908. //-----------------------------------------------------------------------------
  909. void VirtualGlobeTerrainBlock::_CreateVertexBufferTINCurtainWest()
  910. {
  911. // Data is TIN
  912. std::vector<ElevationPoint>::iterator it;
  913. if (_lstElevationPointWGS84.size()<3)
  914. return;
  915. unsigned int nBufferSize = 2*(2 + // corner points count double...
  916. + (unsigned int) _vWestPoints.size());
  917. _qVBStichW = BufferFactory::CreateVertexBuffer(nBufferSize, true);
  918. if (!_qVBStichW)
  919. {
  920. assert(false);
  921. return;
  922. }
  923. boost::shared_ptr<IVertexAttributeBuffer> qAttributeTextureCoord = BufferFactory::CreateVertexAttributeBuffer(nBufferSize, TexCoord0, float2);
  924. boost::shared_ptr<IVertexAttributeBuffer> qAttrPosition = BufferFactory::CreateVertexAttributeBuffer(nBufferSize, Vertex, float3);
  925. std::vector<ElevationPoint> vWall;
  926. ElevationPoint ptTmp;
  927. //----------------------
  928. // POINTS FOR WEST WALL
  929. //----------------------
  930. ptTmp = _vCornerPoints[0];
  931. vWall.push_back(ptTmp);
  932. ptTmp.elevation = _dCurtainElevation;
  933. vWall.push_back(ptTmp);
  934. for (size_t p=0;p<_vWestPoints.size();p++)
  935. {
  936. ptTmp = _vWestPoints[p];
  937. vWall.push_back(ptTmp);
  938. ptTmp.elevation = _dCurtainElevation;
  939. vWall.push_back(ptTmp);
  940. }
  941. ptTmp = _vCornerPoints[3];
  942. vWall.push_back(ptTmp);
  943. ptTmp.elevation = _dCurtainElevation;
  944. vWall.push_back(ptTmp);
  945. // Make sure everything is calculated correctly!!
  946. assert(nBufferSize == vWall.size());
  947. // Create Buffer
  948. int i=0;
  949. GeoCoord oGeoCoord;
  950. GeoCoord oGeoCoordNorm;
  951. double lng, lat;
  952. double x,y,z;
  953. double TexCoordOffsetX = _vCornerPoints[0].x;
  954. double TexCoordOffsetY = _vCornerPoints[0].y;
  955. double TexCoordDX = fabs(_vCornerPoints[1].x - _vCornerPoints[0].x);
  956. double TexCoordDY = fabs(_vCornerPoints[3].y - _vCornerPoints[0].y);
  957. it = vWall.begin();
  958. while (it!=vWall.end())
  959. {
  960. GeoRef::Mercator::ReverseCustom((*it).x, (*it).y, lng, lat, 0.0);
  961. oGeoCoord.SetLatitude(lat);
  962. oGeoCoord.SetLongitude(lng);
  963. oGeoCoord.SetEllipsoidHeight((*it).elevation);
  964. oGeoCoord.ToCartesian(&x,&y,&z);
  965. double u = 0.0;
  966. double v = ((*it).y - TexCoordOffsetY) / TexCoordDY;
  967. qAttributeTextureCoord->SetValue(unsigned int(i), (float)u, (float)v);
  968. // Set Attribute Position with virtual camera offset:
  969. qAttrPosition->SetValue(unsigned int(i),
  970. (float) (x-_vOffset.x),
  971. (float) (y-_vOffset.y),
  972. (float) (z-_vOffset.z));
  973. it++;
  974. //normit++;
  975. i++;
  976. }
  977. // Texture Coordinate: #todo
  978. // Add Buffers
  979. _qVBStichW->AddVertexAttributeBuffer(qAttrPosition);
  980. _qVBStichW->AddVertexAttributeBuffer(qAttributeTextureCoord);
  981. _qVBStichW->CreateVRAMObject();
  982. _qVBStichW->CopyToVRAM(true);
  983. }
  984. //-----------------------------------------------------------------------------
  985. void VirtualGlobeTerrainBlock::_CreateVertexBuffer()
  986. {
  987. if (_bIsBlock)
  988. {
  989. _CreateVertexBufferBlock();
  990. }
  991. else
  992. {
  993. _CreateVertexBufferTIN();
  994. _CreateVertexBufferTINCurtainNorth(); // TIN with curtain!
  995. _CreateVertexBufferTINCurtainEast(); // TIN with curtain!
  996. _CreateVertexBufferTINCurtainSouth(); // TIN with curtain!
  997. _CreateVertexBufferTINCurtainWest(); // TIN with curtain!
  998. }
  999. }
  1000. //-----------------------------------------------------------------------------
  1001. void VirtualGlobeTerrainBlock::_CreateIndexBufferTIN()
  1002. {
  1003. // is TIN (or Geometry)
  1004. std::vector<int>::iterator idxit;
  1005. if (_lstPosIdx.size() < 1)
  1006. return;
  1007. _qIB = BufferFactory::CreateIndexBuffer((unsigned int)_lstPosIdx.size());
  1008. if (!_qIB)
  1009. return;
  1010. // --- Indices
  1011. idxit = _lstPosIdx.begin();
  1012. int i = 0;
  1013. while (idxit != _lstPosIdx.end())
  1014. {
  1015. _qIB->SetValue((unsigned int)i, *idxit, 0);
  1016. idxit++;
  1017. i++;
  1018. }
  1019. _qIB->CreateVRAMObject();
  1020. _qIB->CopyToVRAM(true);
  1021. }
  1022. //-----------------------------------------------------------------------------
  1023. void VirtualGlobeTerrainBlock::_CreateIndexBufferTINCurtain()
  1024. {
  1025. // NORTH
  1026. if (!_qVBStichN)
  1027. {
  1028. assert(false);
  1029. return;
  1030. }
  1031. unsigned int nBufferSize;
  1032. nBufferSize = 3*(_qVBStichN->GetSize() - 2);
  1033. _qIBStichN = BufferFactory::CreateIndexBuffer(nBufferSize);
  1034. if (!_qIBStichN)
  1035. return;
  1036. // *(s, s+1, s+2) and (s+1, s+3, s+2)
  1037. // (s+2, s+1, s+0) and (s+2, s+3, s+1)
  1038. unsigned int i=0;
  1039. for (unsigned int s=0;s<nBufferSize/6;s++)
  1040. {
  1041. _qIBStichN->SetValue(i, 2*s+2, 0); i++;
  1042. _qIBStichN->SetValue(i, 2*s+1, 0); i++;
  1043. _qIBStichN->SetValue(i, 2*s+0, 0); i++;
  1044. _qIBStichN->SetValue(i, 2*s+2, 0); i++;
  1045. _qIBStichN->SetValue(i, 2*s+3, 0); i++;
  1046. _qIBStichN->SetValue(i, 2*s+1, 0); i++;
  1047. }
  1048. _qIBStichN->CreateVRAMObject();
  1049. _qIBStichN->CopyToVRAM(true);
  1050. // EAST
  1051. if (!_qVBStichE)
  1052. {
  1053. assert(false);
  1054. return;
  1055. }
  1056. nBufferSize = 3*(_qVBStichE->GetSize() - 2);
  1057. _qIBStichE = BufferFactory::CreateIndexBuffer(nBufferSize);
  1058. if (!_qIBStichE)
  1059. return;
  1060. // (s, s+1, s+2) and (s+1, s+3, s+2)
  1061. // *(s+2, s+1, s+0) and (s+2, s+3, s+1)
  1062. i=0;
  1063. for (unsigned int s=0;s<nBufferSize/6;s++)
  1064. {
  1065. _qIBStichE->SetValue(i, 2*s+0, 0); i++;
  1066. _qIBStichE->SetValue(i, 2*s+1, 0); i++;
  1067. _qIBStichE->SetValue(i, 2*s+2, 0); i++;
  1068. _qIBStichE->SetValue(i, 2*s+1, 0); i++;
  1069. _qIBStichE->SetValue(i, 2*s+3, 0); i++;
  1070. _qIBStichE->SetValue(i, 2*s+2, 0); i++;
  1071. }
  1072. _qIBStichE->CreateVRAMObject();
  1073. _qIBStichE->CopyToVRAM(true);
  1074. // SOUTH
  1075. if (!_qVBStichS)
  1076. {
  1077. assert(false);
  1078. return;
  1079. }
  1080. nBufferSize = 3*(_qVBStichS->GetSize() - 2);
  1081. _qIBStichS = BufferFactory::CreateIndexBuffer(nBufferSize);
  1082. if (!_qIBStichS)
  1083. return;
  1084. // (s, s+1, s+2) and (s+1, s+3, s+2)
  1085. // *(s+2, s+1, s+0) and (s+2, s+3, s+1)
  1086. i=0;
  1087. for (unsigned int s=0;s<nBufferSize/6;s++)
  1088. {
  1089. _qIBStichS->SetValue(i, 2*s+0, 0); i++;
  1090. _qIBStichS->SetValue(i, 2*s+1, 0); i++;
  1091. _qIBStichS->SetValue(i, 2*s+2, 0); i++;
  1092. _qIBStichS->SetValue(i, 2*s+1, 0); i++;
  1093. _qIBStichS->SetValue(i, 2*s+3, 0); i++;
  1094. _qIBStichS->SetValue(i, 2*s+2, 0); i++;
  1095. }
  1096. _qIBStichS->CreateVRAMObject();
  1097. _qIBStichS->CopyToVRAM(true);
  1098. //WEST
  1099. if (!_qVBStichW)
  1100. {
  1101. assert(false);
  1102. return;
  1103. }
  1104. nBufferSize = 3*(_qVBStichW->GetSize() - 2);
  1105. _qIBStichW = BufferFactory::CreateIndexBuffer(nBufferSize);
  1106. if (!_qIBStichW)
  1107. return;
  1108. // *(s, s+1, s+2) and (s+1, s+3, s+2)
  1109. // (s+2, s+1, s+0) and (s+2, s+3, s+1)
  1110. i=0;
  1111. for (unsigned int s=0;s<nBufferSize/6;s++)
  1112. {
  1113. _qIBStichW->SetValue(i, 2*s+2, 0); i++;
  1114. _qIBStichW->SetValue(i, 2*s+1, 0); i++;
  1115. _qIBStichW->SetValue(i, 2*s+0, 0); i++;
  1116. _qIBStichW->SetValue(i, 2*s+2, 0); i++;
  1117. _qIBStichW->SetValue(i, 2*s+3, 0); i++;
  1118. _qIBStichW->SetValue(i, 2*s+1, 0); i++;
  1119. }
  1120. _qIBStichW->CreateVRAMObject();
  1121. _qIBStichW->CopyToVRAM(true);
  1122. }
  1123. //-----------------------------------------------------------------------------
  1124. void VirtualGlobeTerrainBlock::_CreateIndexBuffer()
  1125. {
  1126. if (_bIsBlock)
  1127. {
  1128. boost::shared_array<unsigned short> indices;
  1129. int nIndexCount;
  1130. indices = _CreateIndices(nIndexCount, 0,0,0,0, 0,0, _nElevationBlockSize-1, _nElevationBlockSize-1, 0);
  1131. if (nIndexCount>0)
  1132. {
  1133. _qIB = BufferFactory::CreateIndexBuffer(nIndexCount);
  1134. for (int i=0;i<nIndexCount;i++)
  1135. {
  1136. _qIB->SetValue(i, (int)indices[i]);
  1137. assert(indices[i] < _nElevationBlockSize*_nElevationBlockSize);
  1138. }
  1139. _qIB->CreateVRAMObject();
  1140. _qIB->CopyToVRAM(true);
  1141. }
  1142. }
  1143. else
  1144. {
  1145. _CreateIndexBufferTIN();
  1146. _CreateIndexBufferTINCurtain();
  1147. }
  1148. }
  1149. //-----------------------------------------------------------------------------
  1150. void VirtualGlobeTerrainBlock::_CreateTexture()
  1151. {
  1152. if (!_qImageData)
  1153. return;
  1154. // Convert Texture to RGB
  1155. boost::shared_array<unsigned char> qData =
  1156. boost::shared_array<unsigned char>(new unsigned char[3*_nTextureSize*_nTextureSize]);
  1157. for (unsigned int y = 0; y<_nTextureSize; y++)
  1158. {
  1159. for (unsigned int x=0; x<_nTextureSize; x++)
  1160. {
  1161. qData.get()[3*y*_nTextureSize+3*x+0] = _qImageData.get()[_nImageDataChannels*y*_nTextureSize+_nImageDataChannels*x+2];
  1162. qData.get()[3*y*_nTextureSize+3*x+1] = _qImageData.get()[_nImageDataChannels*y*_nTextureSize+_nImageDataChannels*x+1];
  1163. qData.get()[3*y*_nTextureSize+3*x+2] = _qImageData.get()[_nImageDataChannels*y*_nTextureSize+_nImageDataChannels*x+0];
  1164. }
  1165. }
  1166. _qTexture = _pEngine->CreateTexture();
  1167. _qTexture->CreateTexture(Texture::GFX_TEXTURE_2D, _nTextureSize, _nTextureSize, Texture::GFX_BGR, Texture::GFX_UNSIGNED_BYTE, (void*)qData.get());
  1168. //#EXPERIMENT
  1169. //if (_sQuadcode.length()<5)
  1170. //_qTexture = TextureFactory::CreateTextureFromMemory((const char*)qData.get(), _nTextureSize, _nTextureSize, 3, true, i3dNodeRoot::GetMipmapSetting());
  1171. }
  1172. //-----------------------------------------------------------------------------
  1173. #define MACRO_getIndex(x,y,n) ((y)*(n)+(x))
  1174. boost::shared_array<unsigned short> VirtualGlobeTerrainBlock::_CreateIndices(int& nIndexCount, int a, int b, int c, int d, int x_start, int y_start, int x_end, int y_end, int LOD)
  1175. {
  1176. int v3;
  1177. boost::shared_array<unsigned short> _pIndexBuffer = boost::shared_array<unsigned short>(new unsigned short[4*_nElevationBlockSize*_nElevationBlockSize]);
  1178. if (a<=LOD) a=0;
  1179. if (b<=LOD) b=0;
  1180. if (c<=LOD) c=0;
  1181. if (d<=LOD) d=0;
  1182. a = math::Pow2(a);
  1183. b = math::Pow2(b);
  1184. c = math::Pow2(c);
  1185. d = math::Pow2(d);
  1186. int lod = math::Pow2(LOD);
  1187. x_start = (x_start / lod) * lod;
  1188. y_start = (y_start / lod) * lod;
  1189. int cnt = 0; int xcnt = 0;
  1190. int xx1, xx2, yy1, yy2;
  1191. for (int x=x_start;x<=x_end-1;x+=lod)
  1192. {
  1193. for (int y=y_start;y<=y_end;y+=lod)
  1194. {
  1195. xx1 = x;
  1196. xx2 = x+lod;
  1197. if (xcnt%2 == 0) yy1 = yy2 = y_end+y_start-y;
  1198. else yy1 = yy2 = y;
  1199. // Neighbour based selection
  1200. // a
  1201. // +-----+
  1202. // b | | d
  1203. // | |
  1204. // +-----+
  1205. // c
  1206. //--------------------------------------------------------------------
  1207. //c
  1208. if (c>1)
  1209. {
  1210. if (yy1==y_start)
  1211. {
  1212. xx1 = (xx1/int(c))*int(c); // integer division is intentional!!
  1213. xx2 = (xx2/int(c))*int(c); // integer division is intentional!!
  1214. }
  1215. }
  1216. //--------------------------------------------------------------------
  1217. //b
  1218. if (b>1)
  1219. {
  1220. if (xx2==x_end)
  1221. {
  1222. yy2=yy2-yy2%b;
  1223. }
  1224. }
  1225. //--------------------------------------------------------------------
  1226. //d
  1227. if (d>1)
  1228. {
  1229. if (xx1==x_start)
  1230. {
  1231. yy1=yy1-yy1%d;
  1232. }
  1233. }
  1234. //--------------------------------------------------------------------
  1235. //a
  1236. if (a>1)
  1237. {
  1238. if (yy2==y_end)
  1239. {
  1240. if (x<((x_end-x_start+1)/2))
  1241. {
  1242. xx1 = (xx1/int(a))*int(a); // integer division is intentional!!
  1243. xx2 = (xx2/int(a))*int(a); // integer division is intentional!!
  1244. }
  1245. else
  1246. {
  1247. xx1 = ((xx1+1*lod)/int(a))*int(a); // integer division is intentional!!
  1248. xx2 = ((xx2+2*lod)/int(a))*int(a); // integer division is intentional!!
  1249. if (xx2 > x_end)
  1250. xx2 = x_end;
  1251. }
  1252. }
  1253. }
  1254. //--------------------------------------------------------------------
  1255. v3 = MACRO_getIndex(xx2,yy2,_nElevationBlockSize);
  1256. _pIndexBuffer[cnt++] = MACRO_getIndex(xx1,yy1,_nElevationBlockSize);
  1257. _pIndexBuffer[cnt++] = v3;
  1258. }
  1259. _pIndexBuffer[cnt++] = v3;
  1260. xcnt += 1;
  1261. }
  1262. nIndexCount = cnt;
  1263. boost::shared_array<unsigned short> index_buffer_real = boost::shared_array<unsigned short>(new unsigned short[cnt]);
  1264. for (int c = 0;c<cnt;c++)
  1265. {
  1266. assert(_pIndexBuffer[c] < _nElevationBlockSize*_nElevationBlockSize);
  1267. index_buffer_real[c] = _pIndexBuffer[c];
  1268. }
  1269. return index_buffer_real;
  1270. }
  1271. //-----------------------------------------------------------------------------
  1272. double VirtualGlobeTerrainBlock::GetPixelSize(const mat4<double>& mModelViewProjection, const int& nWidth, const int& nHeight)
  1273. {
  1274. vec3<double> v[5];
  1275. double dx = -1e20;
  1276. double dy = -1e20;
  1277. for (int i=0;i<5;i++)
  1278. {
  1279. v[i] = mModelViewProjection.vec3mul(_vTilePoints[i]);
  1280. }
  1281. dx= math::Max(dx, fabs(v[0].x / 2.0 - v[1].x / 2.0) * nWidth);
  1282. dy= math::Max(dy, fabs(v[0].y / 2.0 - v[1].y / 2.0) * nHeight);
  1283. dx= math::Max(dx, fabs(v[1].x / 2.0 - v[2].x / 2.0) * nWidth);
  1284. dy= math::Max(dy, fabs(v[1].y / 2.0 - v[2].y / 2.0) * nHeight);
  1285. dx= math::Max(dx, fabs(v[2].x / 2.0 - v[3].x / 2.0) * nWidth);
  1286. dy= math::Max(dy, fabs(v[2].y / 2.0 - v[3].y / 2.0) * nHeight);
  1287. dx= math::Max(dx, fabs(v[3].x / 2.0 - v[0].x / 2.0) * nWidth);
  1288. dy= math::Max(dy, fabs(v[3].y / 2.0 - v[0].y / 2.0) * nHeight);
  1289. return math::Max<double>(dx,dy) / double(_nTextureSize);
  1290. }
  1291. //------------------------------------------------------------------------------
  1292. double VirtualGlobeTerrainBlock::GetBlockSize()
  1293. {
  1294. return _dBlockSize;
  1295. }
  1296. //-----------------------------------------------------------------------------
  1297. double VirtualGlobeTerrainBlock::CalcDistanceTo(vec3<double>& vWhere, vec3<double>& outHitpoint)
  1298. {
  1299. double len = 1e20;
  1300. vec3<double> vPos;
  1301. vec3<double> vStart = vWhere;
  1302. if (_qVB)
  1303. {
  1304. IVertexAttributeBuffer* pVertexAttribute;
  1305. float* pData;
  1306. int numVertices;
  1307. numVertices = _qVB->GetSize();
  1308. pVertexAttribute = _qVB->GetVertexAttributeBuffer(Vertex);
  1309. if (pVertexAttribute)
  1310. {
  1311. if (pVertexAttribute->GetAttributeDataType() == 1) // FLOAT list
  1312. {
  1313. pData = (float*)pVertexAttribute->GetDataPtr();
  1314. if (!pData)
  1315. {
  1316. assert(false); // no data ???
  1317. return len;
  1318. }
  1319. int components = pVertexAttribute->GetNumComponents();
  1320. if (components>=3) // bounding box requires 3D geometry! (x,y,z)
  1321. {
  1322. for (int j=0;j<numVertices;j++)
  1323. {
  1324. vPos.Set(pData[components*j] + _vOffset.x,

Large files files are truncated, but you can click here to view the full file