Earth3D.cpp
上传用户:lbr_007
上传日期:2019-05-31
资源大小:282k
文件大小:28k
源码类别:

传真(Fax)编程

开发平台:

Visual C++

  1.  // ogl3d.cpp
  2. //
  3. #include "stdafx.h"
  4. #include "earth3d.h"
  5. #include <math.h>
  6. #include <vector>
  7. #include <arraycontainer.h>
  8. #include <geo.h>
  9. namespace E3D {
  10. const INT32 BaseMapList = 111;
  11. const INT32 OverlayList = 112;
  12. const INT32 HeaderList = 113;
  13. const INT32 PickList = 114;
  14. const INT32 AircraftList = 115;
  15. const UINT32 CellSize = 8; // 8x8 rectangles
  16. const UINT32 PickCellSize = 2;
  17. const double hdrSize = 0.2;
  18. const double AircraftLength = 0.000050;
  19. }
  20. class V3D {
  21. public:
  22. double x;
  23. double y;
  24. double z;
  25. V3D(void){ x = y = z = 0.0;}
  26. V3D(const V3D& v){ x = y = z = 0.0; Copy(v);}
  27. V3D(double * p){ x = p[0]; y = p[1]; z = p[2];}
  28. ~V3D(void){}
  29. void Create(double x1, double x2, double x3){ x = x1; y = x2; z = x3;}
  30. void Create(double * p){ x = p[0]; y = p[1]; z = p[2];}
  31. void Copy(const V3D& v)
  32. {
  33. x = v.x;
  34. y = v.y;
  35. z = v.z;
  36. }
  37. V3D& operator = (const V3D& v)
  38. {
  39. Copy(v);
  40. return *this;
  41. }
  42. void Init(void){ x = y = z = 0.0;}
  43. };
  44. //
  45. // arbitrary rotation of the point p theta radians around the axis r to
  46. // produce the point q
  47. //
  48. void ArbitraryRotate(V3D& p, double theta, V3D& r, V3D& q)
  49. {
  50.    double costheta,sintheta;
  51.    costheta = cos(theta);
  52.    sintheta = sin(theta);
  53.    q.x = (costheta + (1 - costheta) * r.x * r.x) * p.x;
  54.    q.x += ((1 - costheta) * r.x * r.y - r.z * sintheta) * p.y;
  55.    q.x += ((1 - costheta) * r.x * r.z + r.y * sintheta) * p.z;
  56.    q.y = ((1 - costheta) * r.x * r.y + r.z * sintheta) * p.x;
  57.    q.y += (costheta + (1 - costheta) * r.y * r.y) * p.y;
  58.    q.y += ((1 - costheta) * r.y * r.z - r.x * sintheta) * p.z;
  59.    q.z = ((1 - costheta) * r.x * r.z - r.y * sintheta) * p.x;
  60.    q.z += ((1 - costheta) * r.y * r.z + r.x * sintheta) * p.y;
  61.    q.z += (costheta + (1 - costheta) * r.z * r.z) * p.z;
  62. }
  63. void GEOTex::CreateTexture(DIBSection& dib, UTMProjection * pj)
  64. {
  65. UINT32 width = dib.Width();
  66. UINT32 height = dib.Height();
  67. UINT32 w, h;
  68. if (width >= 1024) w = 1024;
  69. else if (width >= 512) w = 512;
  70. else if (width >= 256) w = 256;
  71. else if (width >= 128) w = 128;
  72. else if (width >= 64) w = 64;
  73. else if (width >= 32) w = 32;
  74. else w = 16;
  75. if (height >= 1024) h = 1024;
  76. else if (height >= 512) h = 512;
  77. else if (height >= 256) h = 256;
  78. else if (height >= 128) h = 128;
  79. else if (height >= 64) h = 64;
  80. else if (height >= 32) h = 32;
  81. else h = 16;
  82. DIBSection tmpDIB;
  83. dib.ResizeImage(tmpDIB, w, h);
  84. UINT32 totalSize = w * h * 3; // 24-bit
  85. m_imgData.CreateArray(totalSize);
  86. memcpy(m_imgData.GetData(), tmpDIB.GetBits(), totalSize);
  87. m_hScale = (double)width / (double)w;
  88. m_vScale = (double)height / (double)h;
  89. m_gr = dib.GetConstGeoReference();
  90. m_pj = pj;
  91. m_texWidth = w;
  92. m_texHeight = h;
  93. }
  94. void GEOTex::DrawTexture(void)
  95. {
  96. }
  97. Earth3D::Earth3D(void)
  98. {
  99. InitEarth3D();
  100. }
  101. Earth3D::~Earth3D(void)
  102. {
  103. }
  104. void Earth3D::GeoToXYZ(double lat, double lon, double& x, double& y, double& z, double R)
  105. {
  106. //
  107. // its necessary to use the negative of the longitude because the OpenGL
  108. // (x,y,z) coordinate system is essentially backwards from the lat/long coordinate system
  109. // where we assume negative longitudes mean west and positive means eastern hemisphere
  110. //
  111. x = R * cos((-lon*GEO::DE2RA)) * cos((lat*GEO::DE2RA));
  112. y = R * sin((lat*GEO::DE2RA));
  113. z = R * sin((-lon*GEO::DE2RA)) * cos((lat*GEO::DE2RA));
  114. }
  115. void Earth3D::SetGeoImage(DIBSection * dib, UTMProjection * pj)
  116. {
  117. m_gt.CreateTexture(*dib, pj);
  118. double x1, y1;
  119. double EL = m_model_matrix.XRot();
  120. double elev = m_eyeDist * sin(EL * GEO::DE2RA);
  121. double southLat, southLon, eastLat, eastLon, M;
  122. double southPt[3], eastPt[3];
  123. x1 = m_gt.m_gr.m_tieX + (m_gt.m_gr.m_resX * (m_gt.m_gr.m_cols/2.0));
  124. y1 = m_gt.m_gr.m_tieY - (m_gt.m_gr.m_resY * (m_gt.m_gr.m_rows/2.0));
  125. m_gt.m_pj->inverse(x1,y1,m_centerLat,m_centerLon);
  126. m_eyeDist = 1.5 * sqrt((y1 - m_gt.m_gr.m_tieY)*(y1 - m_gt.m_gr.m_tieY)) / 1000.0;
  127. GeoToXYZ(m_centerLat, m_centerLon, m_centerPt[0], m_centerPt[1], m_centerPt[2]);
  128. // setting up the rectangular block at the northern extent of the
  129. // image that says "North"
  130. m_northHdr.Create(64, 32, 24);
  131. CRect r;
  132. m_northHdr.GetDC()->DrawText("North", -1, &r, DT_CALCRECT);
  133. m_northHdr.GetDC()->PatBlt(0,0,64,32,WHITENESS);
  134. m_northHdr.GetDC()->TextOut(32-r.Width()/2, 16, "North", 5);
  135. // calculate south and eastern coordinates
  136. GeoCalc::GCDistanceAzimuth(m_centerLat, m_centerLon, m_eyeDist, 180, southLat, southLon);
  137. GeoCalc::GCDistanceAzimuth(m_centerLat, m_centerLon, m_eyeDist, 90, eastLat, eastLon);
  138. // calculate southern and eastern points in the model coordinate system
  139. GeoToXYZ(southLat,southLon, southPt[0],southPt[1],southPt[2]);
  140. GeoToXYZ(eastLat,eastLon, eastPt[0],eastPt[1],eastPt[2]);
  141. // make unitSouthPt a unit vector in the southern direction (model coord sys)
  142. m_unitSouthPt[0] = southPt[0] - m_centerPt[0];
  143. m_unitSouthPt[1] = southPt[1] - m_centerPt[1];
  144. m_unitSouthPt[2] = southPt[2] - m_centerPt[2];
  145. M = sqrt(m_unitSouthPt[0]*m_unitSouthPt[0] + m_unitSouthPt[1]*m_unitSouthPt[1] +
  146. m_unitSouthPt[2]*m_unitSouthPt[2]);
  147. m_unitSouthPt[0] /= M;
  148. m_unitSouthPt[1] /= M;
  149. m_unitSouthPt[2] /= M;
  150. // make unitEastPt a unit vector in the eastern direction (model coord sys)
  151. m_unitEastPt[0] = eastPt[0] - m_centerPt[0];
  152. m_unitEastPt[1] = eastPt[1] - m_centerPt[1];
  153. m_unitEastPt[2] = eastPt[2] - m_centerPt[2];
  154. M = sqrt(m_unitEastPt[0]*m_unitEastPt[0] + m_unitEastPt[1]*m_unitEastPt[1] +
  155. m_unitEastPt[2]*m_unitEastPt[2]);
  156. m_unitEastPt[0] /= M;
  157. m_unitEastPt[1] /= M;
  158. m_unitEastPt[2] /= M;
  159. // make unitCenterPt a unit vector pointing from the origin to the center point
  160. // (model coord sys)
  161. m_unitCenterPt[0] = m_centerPt[0];
  162. m_unitCenterPt[1] = m_centerPt[1];
  163. m_unitCenterPt[2] = m_centerPt[2];
  164. M = sqrt(m_centerPt[0]*m_centerPt[0] + m_centerPt[1]*m_centerPt[1] +
  165. m_centerPt[2]*m_centerPt[2]);
  166. m_unitCenterPt[0] /= M;
  167. m_unitCenterPt[1] /= M;
  168. m_unitCenterPt[2] /= M;
  169. }
  170. void Earth3D::SetOrientation(void)
  171. {
  172. if (m_flyMode && m_flyFirstPerson)
  173. {
  174. //
  175. // if we're flying then the orientation is simple: our eye point is the
  176. // current fly point and we're looking at the next fly point, our up
  177. // vector is the next fly point
  178. //
  179. gluLookAt(m_flyPt[0], m_flyPt[1], m_flyPt[2],
  180. m_flyTo[0], m_flyTo[1], m_flyTo[2],
  181. m_flyTo[0], m_flyTo[1], m_flyTo[2]);
  182. }
  183. else
  184. {
  185. double upVec[3];
  186. // dividing by the Earth radius essentially scales from a world
  187. // coordinate system to this OpenGL coordinate system where the
  188. // radius of the Earth equals 1.0
  189. double D = (m_eyeDist / m_model_matrix.XScale())/GEO::ERAD;
  190. V3D p(m_unitSouthPt);
  191. V3D u(m_unitCenterPt);
  192. V3D q, v, w, x;
  193. // rotate the south vector around the center vector
  194. ArbitraryRotate(p,(-m_model_matrix.YRot())*GEO::DE2RA,u,q);
  195. v.Create(m_unitEastPt);
  196. // rotate the east vector around the center vector
  197. ArbitraryRotate(v,(-m_model_matrix.YRot())*GEO::DE2RA,u,w);
  198. p = q;
  199. // rotate the (formerly) south vector around the (formerly) east vector
  200. ArbitraryRotate(p,-m_model_matrix.XRot()*GEO::DE2RA,w,q);
  201. // calculate the eye point
  202. m_eyePt[0] = m_centerPt[0] + D * q.x;
  203. m_eyePt[1] = m_centerPt[1] + D * q.y;
  204. m_eyePt[2] = m_centerPt[2] + D * q.z;
  205. p.Create(m_unitCenterPt);
  206. // rotate the center vector around the (formerly) east vector
  207. ArbitraryRotate(p,-m_model_matrix.XRot()*GEO::DE2RA,w,q);
  208. upVec[0] = q.x;
  209. upVec[1] = q.y;
  210. upVec[2] = q.z;
  211. gluLookAt( m_eyePt[0], m_eyePt[1], m_eyePt[2],
  212. m_centerPt[0], m_centerPt[1], m_centerPt[2],
  213. upVec[0], upVec[1], upVec[2]);
  214. }
  215. }
  216. void RenderCylinder(double * startPt, double * endPt, double r = 0.0000075, UINT32 steps = 100)
  217. {
  218. if (steps > 1)
  219. {
  220. int i, j;
  221. double d[3], n[3], c1[3], c2[3], u[3], v[3], w[3];
  222. double dIncr[3], angle1, D, N;
  223. d[0] = endPt[0] - startPt[0];
  224. d[1] = endPt[1] - startPt[1];
  225. d[2] = endPt[2] - startPt[2];
  226. D = sqrt(d[0]*d[0] + d[1]*d[1] + d[2]*d[2]);
  227. dIncr[0] = (endPt[0] - startPt[0]) / (double)(steps - 1);
  228. dIncr[1] = (endPt[1] - startPt[1]) / (double)(steps - 1);
  229. dIncr[2] = (endPt[2] - startPt[2]) / (double)(steps - 1);
  230. n[0] = (endPt[1]*startPt[2] - endPt[2]*startPt[1]);
  231. n[1] = (endPt[2]*startPt[0] - endPt[0]*startPt[2]);
  232. n[2] = (endPt[0]*startPt[1] - endPt[1]*startPt[0]);
  233. // making the n-vector a unit vector
  234. N = sqrt(n[0]*n[0] + n[1]*n[1] + n[2]*n[2]);
  235. n[0] /= N;
  236. n[1] /= N;
  237. n[2] /= N;
  238. n[0] *= r;
  239. n[1] *= r;
  240. n[2] *= r;
  241. const int numAngles = 36;
  242. double perp[numAngles][3];
  243. V3D p, t, q;
  244. p.x = n[0]; p.y = n[1]; p.z = n[2];
  245. t.x = d[0]/D; t.y = d[1]/D; t.z = d[2]/D;
  246. double dTheta = 360.0 / (numAngles - 1);
  247. for (i = 0; i < numAngles; i++){
  248. angle1 = (double)i*dTheta;
  249. ArbitraryRotate(p,angle1*GEO::DE2RA,t,q);
  250. perp[i][0] = q.x;
  251. perp[i][1] = q.y;
  252. perp[i][2] = q.z;
  253. }
  254. glBegin( GL_TRIANGLES );
  255. for (j = 0; j < (steps - 1); j++){
  256. c1[0] = startPt[0] + (double)j * dIncr[0];
  257. c1[1] = startPt[1] + (double)j * dIncr[1];
  258. c1[2] = startPt[2] + (double)j * dIncr[2];
  259. c2[0] = startPt[0] + (double)(j+1) * dIncr[0];
  260. c2[1] = startPt[1] + (double)(j+1) * dIncr[1];
  261. c2[2] = startPt[2] + (double)(j+1) * dIncr[2];
  262. for (i = 0; i < (numAngles-1); i++){
  263. u[0] = c1[0] + perp[i][0];
  264. u[1] = c1[1] + perp[i][1];
  265. u[2] = c1[2] + perp[i][2];
  266. v[0] = c2[0] + perp[i][0];
  267. v[1] = c2[1] + perp[i][1];
  268. v[2] = c2[2] + perp[i][2];
  269. w[0] = c1[0] + perp[i+1][0];
  270. w[1] = c1[1] + perp[i+1][1];
  271. w[2] = c1[2] + perp[i+1][2];
  272. glNormal3dv(perp[i]);
  273. glVertex3dv(u);
  274. glVertex3dv(v);
  275. glVertex3dv(w);
  276. u[0] = c2[0] + perp[i+1][0];
  277. u[1] = c2[1] + perp[i+1][1];
  278. u[2] = c2[2] + perp[i+1][2];
  279. glNormal3dv(perp[i+1]);
  280. glVertex3dv(w);
  281. glVertex3dv(v);
  282. glVertex3dv(u);
  283. }
  284. }
  285. glEnd();
  286. }
  287. }
  288. void Earth3D::SetTexture(DIBSection& dib)
  289. {
  290. if (dib.IsCreated())
  291. {
  292. GenTexture(dib);
  293. }
  294. }
  295. void Earth3D::GenTexture(DIBSection& dib)
  296. {
  297. UINT32 width = dib.Width();
  298. UINT32 height = dib.Height();
  299. int w, h;
  300. UINT32 max_dimension = width > height ? width : height;
  301. if (width >= 512) w = 512;
  302. else if (width >= 256) w = 256;
  303. else if (width >= 128) w = 128;
  304. else if (width >= 64) w = 64;
  305. else if (width >= 32) w = 32;
  306. else w = 16;
  307. if (height >= 512) h = 512;
  308. else if (height >= 256) h = 256;
  309. else if (height >= 128) h = 128;
  310. else if (height >= 64) h = 64;
  311. else if (height >= 32) h = 32;
  312. else h = 16;
  313. dib.ResizeImage(m_texture_dib,w,h);
  314. }
  315. void Earth3D::RenderPrimaryImage(void)
  316. {
  317. glPolygonMode(GL_FRONT_AND_BACK,GL_FILL);
  318. if (m_pickMode)
  319. {
  320. glCallList( E3D::PickList );
  321. m_pickPoint = false;
  322. if (m_dib.IsCreated())
  323. {
  324. COLORREF clr;
  325. m_dib.GetPixel(m_pickX, m_pickY, clr);
  326. INT32 horzCells = (m_gt.m_texWidth - E3D::PickCellSize)/E3D::PickCellSize;
  327. INT32 vertCells = (m_gt.m_texHeight - E3D::PickCellSize)/E3D::PickCellSize;
  328. INT32 row = clr / horzCells;
  329. INT32 col = clr - (row * horzCells);
  330. if ((row >= 0) && (row < vertCells) && (col >= 0) && (col < horzCells))
  331. {
  332. double x = m_gt.m_gr.m_tieX + (double)col * m_gt.m_gr.m_resX * m_gt.m_hScale*E3D::PickCellSize;
  333. x += m_gt.m_gr.m_tieX + (double)(col+E3D::PickCellSize) * m_gt.m_gr.m_resX * m_gt.m_hScale*E3D::PickCellSize;
  334. x /= 2.0;
  335. double y = m_gt.m_gr.m_tieY - (double)row * m_gt.m_gr.m_resY * m_gt.m_vScale*E3D::PickCellSize;
  336. y += m_gt.m_gr.m_tieY - (double)(row+E3D::PickCellSize) * m_gt.m_gr.m_resY * m_gt.m_vScale*E3D::PickCellSize;
  337. y /= 2.0;
  338. m_gt.m_pj->inverse(x,y,m_pickLat,m_pickLon);
  339. m_pickPoint = true;
  340. }
  341. }
  342. }
  343. else
  344. {
  345. if (m_flyMode)
  346. {
  347. RenderDirectionHeaders(m_northHdr, 0);
  348. RenderEarthImage(); // shows the earth underneath image
  349. RenderGEOImage();
  350. if (!m_flyFirstPerson)
  351. {
  352. RenderAircraftImage();
  353. }
  354. }
  355. else
  356. {
  357. RenderPickImage();
  358. RenderDirectionHeaders(m_northHdr, 0);
  359. RenderEarthImage(); // shows the earth underneath image
  360. RenderGEOImage();
  361. }
  362. }
  363. }
  364. void Earth3D::SetFlyPosition(double u[3], double v[3], bool firstPerson)
  365. {
  366. m_flyPt[0] = u[0];
  367. m_flyPt[1] = u[1];
  368. m_flyPt[2] = u[2];
  369. m_flyTo[0] = v[0];
  370. m_flyTo[1] = v[1];
  371. m_flyTo[2] = v[2];
  372. m_flyFirstPerson = firstPerson;
  373. }
  374. void Earth3D::RenderGEOImage(void)
  375. {
  376. if (m_gt.IsCreated() && m_gt.m_pj)
  377. {
  378. if (m_rebuildTexture)
  379. {
  380. glNewList( E3D::OverlayList, GL_COMPILE);
  381. UINT32 row, col;
  382. double x1, x2, y1, y2;
  383. double lat[4], lon[4];
  384. GLdouble u[3], v[3], w[3], n[3], tx1, tx2, ty1, ty2;
  385. GLdouble R = 1.0000;
  386. glColor3ub(32,32,32);
  387. glTexImage2D(GL_TEXTURE_2D,0,3, m_gt.m_texWidth, m_gt.m_texHeight,
  388. 0,GL_BGR_EXT,GL_UNSIGNED_BYTE,(GLvoid *)m_gt.m_imgData.GetData());
  389. glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
  390. glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
  391. glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
  392. glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
  393. glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
  394. glEnable( GL_TEXTURE_2D );
  395. {
  396. glBegin( GL_TRIANGLES );
  397. {
  398. //
  399. // Notes:
  400. // 1. each texture mapping point is like a spot weld so
  401. // most of the time we don't need to texture map every point,
  402. // instead we will break up the image into 2D cells.
  403. // 2. all four points of the cell must be un-projected for
  404. // accuracy...inverting a projection is slow...another reason
  405. // we don't want to texture map every point.
  406. // 3. each cell will be broken into 2 triangles and we have to be
  407. // careful that the normal vector for the 2 triangles are both
  408. // pointing the same direction and that direction must be up.
  409. // 4. one optimization i use below is to re-use the v & w points
  410. // from the first triangle in the second triangle because those
  411. // points are used in both. you may be able to come up with much
  412. // more re-use of points and improve performance of this code, but
  413. // keep in mind we are only building an OpenGL call list here so
  414. // this code does not get executed on each and every re-draw, the
  415. // non-opengl code only gets executed when this model is re-built.
  416. // this fact pushes us more towards using high resolution up to the
  417. // point that we are creating too much opengl code.
  418. // 5. set the texture coordinate before setting the vertex. the
  419. // texture coordinate is handled like a state when the vertex coordinates
  420. // get set.
  421. // 6. upper left texture coordinate is (1.0,1.0) as you go right and down
  422. // the texture coordinate moves towards (0.0, 0.0)
  423. //
  424. for (row = 0; row < (m_gt.m_texHeight - E3D::CellSize); row += E3D::CellSize){
  425. //
  426. // x1, y1, x2, y2 are based off the coordinate system of the 
  427. // original geotiff image
  428. //
  429. y1 = m_gt.m_gr.m_tieY - m_gt.m_gr.m_resY * ((double)row * m_gt.m_vScale);
  430. y2 = m_gt.m_gr.m_tieY - m_gt.m_gr.m_resY * ((double)(row+E3D::CellSize) * m_gt.m_vScale);
  431. //
  432. // tx1, ty1, tx2, ty2 are based off the image data that was re-sized to
  433. // meet OpenGL requirements for image dimensions that are powers of two.
  434. //
  435. ty1 = 1.0 - (double)row/(double)m_gt.m_texHeight;
  436. ty2 = 1.0 - (double)(row + E3D::CellSize)/(double)m_gt.m_texHeight;
  437. for (col = 0; col < (m_gt.m_texWidth - E3D::CellSize); col += E3D::CellSize){
  438. x1 = m_gt.m_gr.m_tieX + m_gt.m_gr.m_resX * ((double)col * m_gt.m_hScale);
  439. x2 = m_gt.m_gr.m_tieX + m_gt.m_gr.m_resX * ((double)(col + E3D::CellSize) * m_gt.m_hScale);
  440. tx1 = (double)col/(double)(m_gt.m_texWidth);
  441. tx2 = (double)(col + E3D::CellSize)/(double)(m_gt.m_texWidth);
  442. //
  443. // going clockwise around this rectangle for inverse projections
  444. //
  445. m_gt.m_pj->inverse( x1, y1, lat[0], lon[0]);
  446. m_gt.m_pj->inverse( x2, y1, lat[1], lon[1]);
  447. m_gt.m_pj->inverse( x1, y2, lat[2], lon[2]);
  448. m_gt.m_pj->inverse( x2, y2, lat[3], lon[3]);
  449. GeoToXYZ(lat[0],lon[0],u[0],u[1],u[2]);
  450. GeoToXYZ(lat[1],lon[1],v[0],v[1],v[2]);
  451. GeoToXYZ(lat[2],lon[2],w[0],w[1],w[2]);
  452. //
  453. // i'm switching the order of the coordinates u,w,v instead of
  454. // u,v,w so that we get counter-clockwise direction. using the right
  455. // hand rule this means that the normal vector will point up. here
  456. // we do upper-left, lower-left, upper-right
  457. //
  458. NormalVector(u,w,v,n);
  459. glNormal3dv(n);
  460. glTexCoord2d(tx1, ty1);
  461. glVertex3dv(u);
  462. glTexCoord2d(tx1, ty2);
  463. glVertex3dv(w);
  464. glTexCoord2d(tx2, ty1);
  465. glVertex3dv(v);
  466. GeoToXYZ(lat[3],lon[3],u[0],u[1],u[2]);
  467. //
  468. // again, we want to go counter clockwise for the second triangle
  469. // (the lower right triangle) to keep our normal vector going up.
  470. // so we want the latitude & longitude of points lower-left then
  471. // lower-right, then upper-right...and this completes our cell.
  472. //
  473. NormalVector(w,u,v,n);
  474. glNormal3dv(n);
  475. glTexCoord2d(tx1, ty2);
  476. glVertex3dv(w);
  477. glTexCoord2d(tx2, ty2);
  478. glVertex3dv(u);
  479. glTexCoord2d(tx2, ty1);
  480. glVertex3dv(v);
  481. }
  482. }
  483. }
  484. glEnd();
  485. }
  486. glDisable( GL_TEXTURE_2D );
  487. glEndList();
  488. m_rebuildTexture = false;
  489. }
  490. glCallList( E3D::OverlayList );
  491. }
  492. }
  493. void Earth3D::RenderAircraftImage(void)
  494. {
  495. glPushMatrix();
  496. {
  497. //
  498. // we're going to draw a simple aircraft made up of
  499. // 3 triangles: a fuselage, wings, and rudder. First
  500. // we have to get unit vectors for the aircraft's orientation
  501. // and direction.
  502. //
  503. GLdouble u[3], v[3], w[3], n1[3], n2[3], n3[3], norm[3], m;
  504. u[0] = m_flyTo[0] - m_flyPt[0];
  505. u[1] = m_flyTo[1] - m_flyPt[1];
  506. u[2] = m_flyTo[2] - m_flyPt[2];
  507. m = sqrt(u[0]*u[0] + u[1]*u[1] + u[2]*u[2]);
  508. // u is the unit vector for the direction of the aircraft
  509. u[0] /= m;
  510. u[1] /= m;
  511. u[2] /= m;
  512. v[0] = m_flyPt[0];
  513. v[1] = m_flyPt[1];
  514. v[2] = m_flyPt[2];
  515. m = sqrt(v[0]*v[0] + v[1]*v[1] + v[2]*v[2]);
  516. // v is the unit vector pointing up
  517. v[0] /= m;
  518. v[1] /= m;
  519. v[2] /= m;
  520. // cross product of the up vector and the forward vector should
  521. // the vector to the left wing.
  522. w[0] = v[1]*u[2] - v[2]*u[1];
  523. w[1] = v[2]*u[0] - v[0]*u[2];
  524. w[2] = v[0]*u[1] - v[1]*u[0];
  525. m = sqrt(w[0]*w[0] + w[1]*w[1] + w[2]*w[2]);
  526. // w is the unit vector from the flight point to the left wing
  527. w[0] /= m;
  528. w[1] /= m;
  529. w[2] /= m;
  530. glTranslated( m_flyTo[0], m_flyTo[1], m_flyTo[2]);
  531. //if (m_buildAircraft)
  532. //{
  533. //glNewList( E3D::AircraftList, GL_COMPILE);
  534. //m_buildAircraft = false;
  535. glBegin( GL_TRIANGLES );
  536. {
  537. glColor3ub(64,64,224); // light blue...i think???
  538. // first six vertices will be the aircraft fuselage
  539. n1[0] = E3D::AircraftLength*u[0];
  540. n1[1] = E3D::AircraftLength*u[1];
  541. n1[2] = E3D::AircraftLength*u[2];
  542. n2[0] = E3D::AircraftLength*w[0]*0.20;
  543. n2[1] = E3D::AircraftLength*w[1]*0.20;
  544. n2[2] = E3D::AircraftLength*w[2]*0.20;
  545. n3[0] = E3D::AircraftLength*u[0]*0.20;
  546. n3[1] = E3D::AircraftLength*u[1]*0.20;
  547. n3[2] = E3D::AircraftLength*u[2]*0.20;
  548. NormalVector(n1,n2,n3,norm);
  549. glNormal3dv(norm);
  550. glVertex3dv(n1);
  551. glVertex3dv(n2);
  552. glVertex3dv(n3);
  553. n1[0] = E3D::AircraftLength*u[0];
  554. n1[1] = E3D::AircraftLength*u[1];
  555. n1[2] = E3D::AircraftLength*u[2];
  556. n2[0] = E3D::AircraftLength*(-w[0])*0.20;
  557. n2[1] = E3D::AircraftLength*(-w[1])*0.20;
  558. n2[2] = E3D::AircraftLength*(-w[2])*0.20;
  559. NormalVector(n1,n3,n2,norm);
  560. glNormal3dv(norm);
  561. glVertex3dv(n1);
  562. glVertex3dv(n3);
  563. glVertex3dv(n2);
  564. // next lets do the wings
  565. glColor3ub(64,64,128);
  566. n1[0] = E3D::AircraftLength*u[0]*0.75;
  567. n1[1] = E3D::AircraftLength*u[1]*0.75;
  568. n1[2] = E3D::AircraftLength*u[2]*0.75;
  569. n2[0] = -E3D::AircraftLength*w[0]*0.50 + E3D::AircraftLength*u[0]*0.20;
  570. n2[1] = -E3D::AircraftLength*w[1]*0.50 + E3D::AircraftLength*u[1]*0.20;
  571. n2[2] = -E3D::AircraftLength*w[2]*0.50 + E3D::AircraftLength*u[2]*0.20;
  572. n3[0] = E3D::AircraftLength*(w[0])*0.50 + E3D::AircraftLength*u[0]*0.20;
  573. n3[1] = E3D::AircraftLength*(w[1])*0.50 + E3D::AircraftLength*u[1]*0.20;
  574. n3[2] = E3D::AircraftLength*(w[2])*0.50 + E3D::AircraftLength*u[2]*0.20;
  575. NormalVector(n1,n2,n3,norm);
  576. glNormal3dv(norm);
  577. glVertex3dv(n1);
  578. glVertex3dv(n2);
  579. glVertex3dv(n3);
  580. // next lets do the rudders
  581. glColor3ub(192,192,192);
  582. n1[0] = E3D::AircraftLength*u[0]*0.50;
  583. n1[1] = E3D::AircraftLength*u[1]*0.50;
  584. n1[2] = E3D::AircraftLength*u[2]*0.50;
  585. n2[0] = 0.0;
  586. n2[1] = 0.0;
  587. n2[2] = 0.0;
  588. n3[0] = E3D::AircraftLength*v[0]*0.15;
  589. n3[1] = E3D::AircraftLength*v[1]*0.15;
  590. n3[2] = E3D::AircraftLength*v[2]*0.15;
  591. NormalVector(n1,n2,n3,norm);
  592. glNormal3dv(norm);
  593. glVertex3dv(n1);
  594. glVertex3dv(n2);
  595. glVertex3dv(n3);
  596. }
  597. glEnd();
  598. //glEndList();
  599. //}
  600. //else
  601. //{
  602. // glCallList( E3D::AircraftList );
  603. //}
  604. }
  605. glPopMatrix();
  606. }
  607. void Earth3D::RenderPickImage(void)
  608. {
  609. if (m_gt.IsCreated() && m_gt.m_pj)
  610. {
  611. if (m_rebuildTexture)
  612. {
  613. glNewList( E3D::PickList, GL_COMPILE);
  614. glShadeModel(GL_FLAT);
  615. glDisable(GL_LIGHT0);
  616. glDisable(GL_LIGHTING);
  617. glDisable( GL_TEXTURE_2D );
  618. UINT32 row, col;
  619. double x1, x2, y1, y2;
  620. double lat[4], lon[4];
  621. GLdouble u[3], v[3], w[3];
  622. COLORREF clr = 0;
  623. glBegin( GL_TRIANGLES );
  624. {
  625. for (row = 0; row < (m_gt.m_texHeight - E3D::PickCellSize); row+=E3D::PickCellSize){
  626. //
  627. // x1, y1, x2, y2 are based off the coordinate system of the 
  628. // original geotiff image
  629. //
  630. y1 = m_gt.m_gr.m_tieY - m_gt.m_gr.m_resY * ((double)row * m_gt.m_vScale);
  631. y2 = m_gt.m_gr.m_tieY - m_gt.m_gr.m_resY * ((double)(row+E3D::PickCellSize) * m_gt.m_vScale);
  632. for (col = 0; col < (m_gt.m_texWidth - E3D::PickCellSize); col+=E3D::PickCellSize){
  633. x1 = m_gt.m_gr.m_tieX + m_gt.m_gr.m_resX * ((double)col * m_gt.m_hScale);
  634. x2 = m_gt.m_gr.m_tieX + m_gt.m_gr.m_resX * ((double)(col + E3D::PickCellSize) * m_gt.m_hScale);
  635. //
  636. // going clockwise around this rectangle for inverse projections
  637. //
  638. m_gt.m_pj->inverse( x1, y1, lat[0], lon[0]);
  639. m_gt.m_pj->inverse( x2, y1, lat[1], lon[1]);
  640. m_gt.m_pj->inverse( x1, y2, lat[2], lon[2]);
  641. m_gt.m_pj->inverse( x2, y2, lat[3], lon[3]);
  642. GeoToXYZ(lat[0],lon[0],u[0],u[1],u[2]);
  643. GeoToXYZ(lat[1],lon[1],v[0],v[1],v[2]);
  644. GeoToXYZ(lat[2],lon[2],w[0],w[1],w[2]);
  645. glColor3ub(GetRValue(clr),GetGValue(clr),GetBValue(clr));
  646. clr++;
  647. glVertex3dv(u);
  648. glVertex3dv(w);
  649. glVertex3dv(v);
  650. GeoToXYZ(lat[3],lon[3],u[0],u[1],u[2]);
  651. glVertex3dv(w);
  652. glVertex3dv(u);
  653. glVertex3dv(v);
  654. }
  655. }
  656. }
  657. glEnd();
  658. glEndList();
  659. }
  660. }
  661. }
  662. void Earth3D::RenderDirectionHeaders(DIBSection& dib, int direction)
  663. {
  664. if (m_gt.IsCreated() && m_gt.m_pj)
  665. {
  666. if (m_rebuildTexture)
  667. {
  668. glNewList( E3D::HeaderList, GL_COMPILE);
  669. double x1, x2, y1, y2;
  670. double lat[4], lon[4];
  671. GLdouble u[3], v[3], w[3], n[3], e1[3], e2[3];
  672. GLdouble R = 1.0;
  673. glTexImage2D(GL_TEXTURE_2D,0,3, dib.Width(), dib.Height(),
  674. 0,GL_BGR_EXT,GL_UNSIGNED_BYTE,(GLvoid *)dib.GetBits());
  675. glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
  676. glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
  677. glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
  678. glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
  679. glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
  680. glEnable( GL_TEXTURE_2D );
  681. {
  682. glBegin( GL_TRIANGLES );
  683. {
  684. x1 = m_gt.m_gr.m_tieX;
  685. x2 = x1 + m_gt.m_gr.m_resX * m_gt.m_gr.m_cols;
  686. y1 = m_gt.m_gr.m_tieY;
  687. y2 = y1 - m_gt.m_gr.m_resY * m_gt.m_gr.m_rows;
  688. m_gt.m_pj->inverse( x1, y1, lat[0], lon[0]);
  689. m_gt.m_pj->inverse( x2, y1, lat[1], lon[1]);
  690. m_gt.m_pj->inverse( x1, y2, lat[2], lon[2]);
  691. m_gt.m_pj->inverse( x2, y2, lat[3], lon[3]);
  692. NormalVector(u,w,v,n);
  693. glNormal3dv(n);
  694. switch (direction){
  695. case 0: // north
  696. {
  697. GeoToXYZ(lat[0], lon[0],u[0],u[1],u[2]);
  698. GeoToXYZ(lat[1], lon[1],v[0],v[1],v[2]);
  699. GeoToXYZ(lat[2], lon[2],w[0],w[1],w[2]);
  700. glTexCoord2d(0.0, 0.0);
  701. glVertex3dv(u);
  702. glTexCoord2d(1.0, 0.0);
  703. glVertex3dv(v);
  704. e1[0] = u[0] + E3D::hdrSize * (u[0] - w[0]);
  705. e1[1] = u[1] + E3D::hdrSize * (u[1] - w[1]);
  706. e1[2] = u[2] + E3D::hdrSize * (u[2] - w[2]);
  707. GeoToXYZ(lat[3], lon[3],w[0],w[1],w[2]);
  708. e2[0] = v[0] + E3D::hdrSize * (v[0] - w[0]);
  709. e2[1] = v[1] + E3D::hdrSize * (v[1] - w[1]);
  710. e2[2] = v[2] + E3D::hdrSize * (v[2] - w[2]);
  711. glTexCoord2d(1.0, 1.0);
  712. glVertex3dv(e2);
  713. glTexCoord2d(0.0, 0.0);
  714. glVertex3dv(u);
  715. glTexCoord2d(1.0, 1.0);
  716. glVertex3dv(e2);
  717. glTexCoord2d(0.0, 1.0);
  718. glVertex3dv(e1);
  719. }
  720. break;
  721. case 1: // south
  722. {
  723. }
  724. break;
  725. case 2: // east
  726. {
  727. }
  728. break;
  729. case 3: // west
  730. {
  731. }
  732. break;
  733. }
  734. }
  735. glEnd();
  736. }
  737. glDisable( GL_TEXTURE_2D );
  738. glEndList();
  739. }
  740. glCallList( E3D::HeaderList );
  741. }
  742. }
  743. void Earth3D::RenderEarthImage(void)
  744. {
  745. if (m_rebuildEarth)
  746. {
  747. glNewList( E3D::BaseMapList, GL_COMPILE);
  748. const int NumLatitudes = 90;
  749. const int NumLongitudes = 180;
  750. double start_lat, start_lon;
  751. double theta1, phi1, theta2, phi2, lat_incr, lon_incr;
  752. GLdouble u[3], v[3], w[3], n[3];
  753. GLdouble R;
  754. glColor3ub(224,224,224);
  755. /*
  756. if (m_texture_dib.IsCreated())
  757. {
  758. glTexImage2D(GL_TEXTURE_2D,0,3,m_texture_dib.Width(),m_texture_dib.Height(),
  759. 0,GL_BGR_EXT,GL_UNSIGNED_BYTE,(GLvoid *)m_texture_dib.GetBits());
  760. glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
  761. glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
  762. glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
  763. glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
  764. glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
  765. glEnable( GL_TEXTURE_2D );
  766. }
  767. else
  768. {
  769. glDisable( GL_TEXTURE_2D );
  770. }
  771. */
  772. start_lat = -90.0;
  773. start_lon = -180.0;
  774. R = 1.0;
  775. lat_incr = 180.0 / (double)NumLatitudes;
  776. lon_incr = 360.0 / (double)NumLongitudes;
  777. int row, col;
  778. //GLdouble tx1, tx2, ty1, ty2;
  779. glBegin( GL_TRIANGLES );
  780. {
  781. for (col = 0; col < NumLongitudes; col++){
  782. phi1 = (start_lon + col * lon_incr);
  783. phi2 = (start_lon + (col + 1) * lon_incr);
  784. //tx1 = (180.0 + phi1)/360.0;
  785. //tx2 = (180.0 + phi2)/360.0;
  786. for (row = 0; row < NumLatitudes; row++){
  787. theta1 = (start_lat + row * lat_incr);
  788. theta2 = (start_lat + (row + 1) * lat_incr);
  789. //ty1 = (90.0 + theta1)/180.0;
  790. //ty2 = (90.0 + theta2)/180.0;
  791. GeoToXYZ(theta1,phi1,u[0],u[1],u[2]);
  792. GeoToXYZ(theta2,phi1,v[0],v[1],v[2]);
  793. GeoToXYZ(theta2,phi2,w[0],w[1],w[2]);
  794. NormalVector(u,v,w,n);
  795. glNormal3dv(n);
  796. //glTexCoord2d(tx1,ty1);
  797. glVertex3dv(u);
  798. //glTexCoord2d(tx1,ty2);
  799. glVertex3dv(v);
  800. //glTexCoord2d(tx2,ty2);
  801. glVertex3dv(w);
  802. GeoToXYZ(theta1,phi2,v[0],v[1],v[2]);
  803. NormalVector(u,w,v,n);
  804. glNormal3dv(n);
  805. //glTexCoord2d(tx1,ty1);
  806. glVertex3dv(u);
  807. //glTexCoord2d(tx2,ty2);
  808. glVertex3dv(w);
  809. //glTexCoord2d(tx2,ty1);
  810. glVertex3dv(v);
  811. }
  812. }
  813. }
  814. glEnd();
  815. //glDisable( GL_TEXTURE_2D );
  816. glEndList();
  817. m_rebuildEarth = false;
  818. }
  819. glCallList( E3D::BaseMapList );
  820. }