PageRenderTime 60ms CodeModel.GetById 20ms RepoModel.GetById 1ms app.codeStats 0ms

/ecere/src/gfx/Display.ec

https://github.com/thexa4/sdk
C | 1593 lines | 1144 code | 185 blank | 264 comment | 197 complexity | d235e357d547425d4c31e9b725969030 MD5 | raw file
  1. namespace gfx;
  2. #if (defined(ECERE_VANILLA) || defined(ECERE_ONEDRIVER)) && defined(__WIN32__)
  3. #define ECERE_NOTRUETYPE
  4. #endif
  5. import "System"
  6. import "Color"
  7. import "Bitmap"
  8. import "Surface"
  9. import "DisplaySystem"
  10. import "Resource"
  11. import "FontResource"
  12. import "BitmapResource"
  13. import "LFBDisplayDriver"
  14. // TOFIX: Temporary until we pass Display instead of DisplaySystem to FontExtent
  15. #if defined(__WIN32__) && !defined(ECERE_NOTRUETYPE)
  16. import "GDIDisplayDriver"
  17. #endif
  18. #if !defined(ECERE_VANILLA) && !defined(ECERE_NO3D)
  19. import "Camera"
  20. import "Plane"
  21. import "Matrix"
  22. import "Mesh"
  23. import "Object"
  24. import "Quaternion"
  25. import "Vector3D"
  26. #endif
  27. public enum RenderState { fillMode = 1, depthTest, depthWrite, fogDensity, fogColor, blend, ambient, alphaWrite, antiAlias, vSync };
  28. public enum FillModeValue { solid, wireframe };
  29. public class DisplayFlags
  30. {
  31. public bool fullScreen:1, flipping:1, alpha:1, memBackBuffer:1, text:1, scrolling:1, printer:1;
  32. };
  33. public class FontFlags
  34. {
  35. public bool bold:1, italic:1, underline:1;
  36. };
  37. static void DummyFunction()
  38. {
  39. Mutex mutex { };
  40. }
  41. public class DisplayDriver
  42. {
  43. public:
  44. class_data char * name;
  45. class_data bool textMode;
  46. class_data bool printer;
  47. class_data DisplaySystem displaySystem;
  48. class_property DisplaySystem displaySystem
  49. {
  50. set { class_data(displaySystem) = value; }
  51. get { return class_data(displaySystem); }
  52. };
  53. class_property char * name
  54. {
  55. set { class_data(name) = value; }
  56. get { return class_data(name); }
  57. };
  58. class_property bool printer
  59. {
  60. set { class_data(printer) = value; }
  61. get { return class_data(printer); }
  62. };
  63. // Constructor / Destructor
  64. virtual bool ::CreateDisplaySystem(DisplaySystem);
  65. virtual void ::DestroyDisplaySystem(DisplaySystem);
  66. virtual bool ::CreateDisplay(Display);
  67. virtual void ::DestroyDisplay(Display);
  68. // Display Position and Size
  69. virtual bool ::DisplaySize(Display, int, int);
  70. virtual void ::DisplayPosition(Display, int, int);
  71. // Palettes
  72. virtual void ::SetPalette(Display, ColorAlpha *, bool);
  73. virtual void ::RestorePalette(Display);
  74. // Display the back buffer content
  75. virtual void ::StartUpdate(Display);
  76. virtual void ::Scroll(Display, Box, int, int, Extent);
  77. virtual void ::Update(Display, Box);
  78. virtual void ::EndUpdate(Display);
  79. // Allocate/free a bitmap
  80. virtual bool ::AllocateBitmap(DisplaySystem, Bitmap, int, int, int, PixelFormat, bool);
  81. virtual void ::FreeBitmap(DisplaySystem, Bitmap);
  82. // Lock
  83. virtual bool ::LockSystem(DisplaySystem displaySystem);
  84. virtual void ::UnlockSystem(DisplaySystem displaySystem);
  85. virtual bool ::Lock(Display);
  86. virtual void ::Unlock(Display);
  87. // Get/release a surface
  88. virtual bool ::GetSurface(Display, Surface surface, int,int,Box);
  89. virtual bool ::GetBitmapSurface(DisplaySystem displaySystem, Surface surface, Bitmap bitmap, int,int,Box);
  90. virtual void ::ReleaseSurface(Display this, Surface);
  91. // Clip a surface
  92. virtual void ::Clip(Display, Surface, Box);
  93. // Grab from the screen
  94. virtual bool ::GrabScreen(Display, Bitmap, int, int, unsigned int, unsigned int);
  95. // Converts a bitmap format
  96. virtual bool ::ConvertBitmap(DisplaySystem, Bitmap, PixelFormat, ColorAlpha *);
  97. // Converts an LFB bitmap into an offscreen bitmap for this device
  98. virtual bool ::MakeDDBitmap(DisplaySystem, Bitmap, bool);
  99. // Font loading
  100. virtual Font ::LoadFont(DisplaySystem displaySystem, char * faceName, float size, FontFlags flags);
  101. virtual void ::UnloadFont(DisplaySystem, Font);
  102. // 2D Drawing
  103. virtual void ::SetForeground(Display, Surface, ColorAlpha);
  104. virtual void ::SetBackground(Display, Surface, ColorAlpha);
  105. virtual void ::LineStipple(Display, Surface, uint);
  106. virtual ColorAlpha ::GetPixel(Display, Surface, int, int);
  107. virtual void ::PutPixel(Display, Surface, int, int);
  108. virtual void ::DrawLine(Display, Surface, int, int, int, int);
  109. virtual void ::Rectangle(Display, Surface,int,int,int,int);
  110. virtual void ::Area(Display, Surface,int,int,int,int);
  111. virtual void ::Clear(Display, Surface, ClearType);
  112. virtual void ::Blit(Display, Surface, Bitmap, int, int, int, int, int, int);
  113. virtual void ::Stretch(Display, Surface, Bitmap, int, int, int, int, int, int,int,int);
  114. virtual void ::Filter(Display, Surface, Bitmap, int, int, int, int, int, int,int,int);
  115. virtual void ::BlitDI(Display, Surface, Bitmap, int, int, int, int, int, int);
  116. virtual void ::StretchDI(Display, Surface, Bitmap, int, int, int, int, int, int,int,int);
  117. virtual void ::FilterDI(Display, Surface, Bitmap, int, int, int, int, int, int, int,int);
  118. virtual void ::TextFont(Display, Surface, Font);
  119. virtual void ::TextOpacity(Display, Surface, bool);
  120. virtual void ::WriteText(Display, Surface, int, int, char *, int);
  121. virtual void ::TextExtent(Display, Surface, char *, int, int *, int *);
  122. virtual void ::FontExtent(DisplaySystem, Font, char *, int, int *, int *);
  123. virtual void ::DrawingChar(Display, Surface, char);
  124. virtual void ::NextPage(Display);
  125. #if !defined(ECERE_VANILLA) && !defined(ECERE_NO3D)
  126. // 3D Graphics
  127. virtual void ::SetRenderState(Display, RenderState, uint);
  128. virtual void ::SetLight(Display, int, Light);
  129. virtual void ::SetCamera(Display, Surface, Camera);
  130. virtual bool ::AllocateMesh(DisplaySystem, Mesh);
  131. virtual void ::FreeMesh(DisplaySystem, Mesh);
  132. virtual bool ::LockMesh(DisplaySystem, Mesh, MeshFeatures flags);
  133. virtual void ::UnlockMesh(DisplaySystem, Mesh, MeshFeatures flags);
  134. virtual void * ::AllocateIndices(DisplaySystem, int nIndices, bool indices32bit);
  135. virtual void ::FreeIndices(DisplaySystem, void * indices);
  136. virtual uint16 * ::LockIndices(DisplaySystem, void * indices);
  137. virtual void ::UnlockIndices(DisplaySystem, void * indices, bool indices32bit, int nIndices);
  138. virtual void ::SelectMesh(Display, Mesh);
  139. virtual void ::ApplyMaterial(Display, Material, Mesh);
  140. virtual void ::DrawPrimitives(Display, PrimitiveSingle *, Mesh mesh);
  141. virtual void ::PushMatrix(Display);
  142. virtual void ::PopMatrix(Display, bool);
  143. virtual void ::SetTransform(Display, Matrix, bool, bool);
  144. #endif
  145. virtual void ::SetBlitTint(Display, Surface, ColorAlpha);
  146. };
  147. public enum Alignment { left, right, center };
  148. public enum ClearType { colorBuffer, depthBuffer, colorAndDepth };
  149. subclass(DisplayDriver) GetDisplayDriver(char * driverName)
  150. {
  151. if(driverName)
  152. {
  153. OldLink link;
  154. for(link = class(DisplayDriver).derivatives.first; link; link = link.next)
  155. {
  156. subclass(DisplayDriver) displayDriver = link.data;
  157. if(displayDriver && displayDriver.name && !strcmp(displayDriver.name, driverName))
  158. return displayDriver;
  159. }
  160. }
  161. return null;
  162. }
  163. DisplaySystem GetDisplaySystem(char * driverName)
  164. {
  165. subclass(DisplayDriver) displayDriver = GetDisplayDriver(driverName);
  166. return displayDriver ? displayDriver.displaySystem : null;
  167. }
  168. define textCellW = 8;
  169. define textCellH = 16;
  170. public enum PixelFormat // : byte MESSES UP GuiApplication
  171. {
  172. pixelFormat4, pixelFormat8, pixelFormat444, pixelFormat555, pixelFormat565, pixelFormat888, pixelFormatAlpha, pixelFormatText, pixelFormatRGBA
  173. };
  174. public enum Resolution : int
  175. {
  176. resText80x25, res320x200, res320x240, res320x400, res360x480, res400x256, res400x300, res512x256, res512x384,
  177. res640x200, res640x350, res640x400, res640x480, res720x348, res800x600, res856x480, res960x720, res1024x768,
  178. res1152x864, res1280x1024, res1600x1200, res768x480
  179. };
  180. #if !defined(ECERE_VANILLA) && !defined(ECERE_NO3D)
  181. public class LightFlags
  182. {
  183. public bool off:1, spot:1, omni:1, attenuation:1;
  184. };
  185. public struct Light
  186. {
  187. LightFlags flags;
  188. ColorRGB ambient;
  189. ColorRGB diffuse;
  190. ColorRGB specular;
  191. Vector3D direction;
  192. Quaternion orientation;
  193. Object lightObject;
  194. Object target;
  195. Degrees fallOff;
  196. Degrees hotSpot;
  197. float Kc;
  198. float Kl;
  199. float Kq;
  200. Degrees start;
  201. Degrees end;
  202. float multiplier;
  203. };
  204. define NumberOfLights = 8;
  205. // Painter's algorithm
  206. public class HitRecord : struct
  207. {
  208. public:
  209. HitRecord prev, next;
  210. uint pos;
  211. uint numTags;
  212. Vector3D center;
  213. void * tags[1]; // More tags may follow
  214. int Compare(HitRecord recordB, void * unused)
  215. {
  216. if(center.z > recordB.center.z)
  217. return 1;
  218. else if(center.z < recordB.center.z)
  219. return -1;
  220. else if(pos > recordB.pos)
  221. return 1;
  222. else if(pos < recordB.pos)
  223. return -1;
  224. else
  225. return 0;
  226. }
  227. };
  228. #define EPSILON 0.00001
  229. struct SortPrimitive
  230. {
  231. PrimitiveSingle * triangle;
  232. Object object;
  233. Vector3Df middle;
  234. Vector3Df min, max;
  235. Plane plane;
  236. bool marked;
  237. int Compare(SortPrimitive primitive2)
  238. {
  239. double value;
  240. if(ZOverlap(primitive2) && Sgn(plane.d) != Sgn(primitive2.plane.d))
  241. value = plane.d - primitive2.plane.d;
  242. else
  243. value = middle.z - primitive2.middle.z;
  244. if(value > EPSILON)
  245. return 1;
  246. else if(value<-EPSILON)
  247. return -1;
  248. else
  249. return 0;
  250. }
  251. bool ZOverlap(SortPrimitive poly2)
  252. {
  253. if(min.z > poly2.max.z - EPSILON || poly2.min.z > max.z - EPSILON)
  254. return false;
  255. return true;
  256. }
  257. /*
  258. bool XYOverlap(SortPrimitive poly2)
  259. {
  260. if(min.x > poly2.max.x - EPSILON || poly2.min.x > max.x - EPSILON )
  261. return false;
  262. if(min.y > poly2.max.y - EPSILON || poly2.min.y > max.y - EPSILON )
  263. return false;
  264. return true;
  265. }
  266. bool SurfaceOutside(SortPrimitive poly2)
  267. {
  268. bool result = true;
  269. PrimitiveSingle * primitive = triangle;
  270. Mesh mesh = object.mesh;
  271. Matrix * matrix = &object.matrix;
  272. int v;
  273. float a = poly2.plane.a, b = poly2.plane.b, c = poly2.plane.c, d = poly2.plane.d;
  274. if(d < 0)
  275. {
  276. a*=-1;
  277. b*=-1;
  278. c*=-1;
  279. d = - (a * poly2.middle.x + b * poly2.middle.y + c * poly2.middle.z);
  280. }
  281. for(v = 0; v < primitive->nIndices; v++)
  282. {
  283. double surface;
  284. Vector3Df * local = &mesh.vertices[primitive->indices[v]];
  285. Vector3Df vertex;
  286. vertex.MultMatrix(local, matrix);
  287. surface = a * vertex.x + b * vertex.y + c * vertex.z + d;
  288. if(surface < EPSILON)
  289. {
  290. result = false;
  291. break;
  292. }
  293. }
  294. if(result == true)
  295. return true;
  296. else
  297. return result;
  298. }
  299. int SurfaceInside(SortPrimitive poly2)
  300. {
  301. bool result = true;
  302. PrimitiveSingle * primitive = poly2.triangle;
  303. Mesh mesh = poly2.object.mesh;
  304. Matrix * matrix = &poly2.object.matrix;
  305. int v;
  306. float a = plane.a, b = plane.b, c = plane.c, d = plane.d;
  307. if(d < 0)
  308. {
  309. a*=-1;
  310. b*=-1;
  311. c*=-1;
  312. d = - (a * middle.x + b * middle.y + c * middle.z);
  313. }
  314. for(v = 0; v < primitive->nIndices; v++)
  315. {
  316. double surface;
  317. Vector3Df * local = &mesh.vertices[primitive->indices[v]];
  318. Vector3Df vertex;
  319. vertex.Transform(local, matrix);
  320. surface = a * vertex.x + b * vertex.y + c * vertex.z + d;
  321. if(surface > -EPSILON)
  322. {
  323. result = false;
  324. break;
  325. }
  326. }
  327. if(result == true)
  328. return true;
  329. else
  330. return result;
  331. }
  332. bool ShouldBeSwapped(SortPrimitive poly2)
  333. {
  334. if (!XYOverlap(poly2)) return false;
  335. if (SurfaceOutside(poly2)) return false;
  336. if (SurfaceInside(poly2)) return false;
  337. return true;
  338. }
  339. */
  340. };
  341. #endif
  342. #define MAX_CLIP_POINTS 50
  343. public class Display
  344. {
  345. public:
  346. ~Display()
  347. {
  348. if(displaySystem)
  349. {
  350. displaySystem.numDisplays--;
  351. displaySystem.driver.DestroyDisplay(this);
  352. }
  353. #if !defined(ECERE_VANILLA) && !defined(ECERE_NO3D)
  354. delete display3D;
  355. #endif
  356. }
  357. bool Create(DisplaySystem displaySystem, void * window)
  358. {
  359. bool result = false;
  360. if(displaySystem)
  361. {
  362. this.displaySystem = displaySystem;
  363. this.window = window;
  364. displaySystem.numDisplays++;
  365. if(displaySystem.driver.CreateDisplay(this))
  366. result = true;
  367. // if(!result) LogErrorCode(DisplayInitFailed, displaySystem.driver.name);
  368. }
  369. return result;
  370. }
  371. Surface GetSurface(int x, int y, Box clip)
  372. {
  373. Surface result = null;
  374. Surface surface { };
  375. if(surface)
  376. {
  377. Box box { -x, -y, -x + width - 1, -y + height - 1 };
  378. box.Clip(clip);
  379. surface.width = width - x;
  380. surface.height = height - y;
  381. surface.driver = displaySystem.driver;
  382. surface.displaySystem = displaySystem;
  383. surface.display = this;
  384. if(displaySystem.driver.GetSurface(this, surface, x, y, box))
  385. result = surface;
  386. if(!result)
  387. delete surface;
  388. }
  389. return result;
  390. }
  391. bool Resize(int width, int height)
  392. {
  393. return displaySystem.driver.DisplaySize(this, width, height);
  394. }
  395. void Position(int x, int y)
  396. {
  397. displaySystem.driver.DisplayPosition(this, x,y);
  398. }
  399. void StartUpdate(void)
  400. {
  401. displaySystem.driver.StartUpdate(this);
  402. }
  403. void Scroll(Box scroll, int x, int y, Extent dirty)
  404. {
  405. displaySystem.driver.Scroll(this, scroll, x, y, dirty);
  406. }
  407. void Update(Box updateBox)
  408. {
  409. displaySystem.driver.Update(this, updateBox);
  410. }
  411. void EndUpdate(void)
  412. {
  413. displaySystem.driver.EndUpdate(this);
  414. }
  415. void NextPage(void)
  416. {
  417. displaySystem.driver.NextPage(this);
  418. }
  419. bool Grab(Bitmap bitmap, int x, int y, int w, int h)
  420. {
  421. bool result = false;
  422. if(bitmap && w > 0 && h > 0 &&
  423. displaySystem.driver.GrabScreen(this, bitmap, x, y, w, h))
  424. result = true;
  425. else
  426. bitmap.Free();
  427. return result;
  428. }
  429. void FontExtent(Font font, char * text, int len, int * width, int * height)
  430. {
  431. // Fix for OnLoadGraphics time alpha blended window text extent on GDI
  432. #if defined(__WIN32__) && !defined(ECERE_NOTRUETYPE)
  433. if(this && alphaBlend && pixelFormat == pixelFormat888 &&
  434. displaySystem.driver == class(GDIDisplayDriver))
  435. {
  436. Surface s = GetSurface(0,0,null);
  437. if(s)
  438. {
  439. s.font = font;
  440. s.TextExtent(text, len, width, height);
  441. delete s;
  442. }
  443. }
  444. else
  445. #endif
  446. // TODO: Should really pass display here...
  447. DisplaySystem::FontExtent(this ? displaySystem : null, font, text, len, width, height);
  448. }
  449. void SetPalette(ColorAlpha * palette, bool colorMatch)
  450. {
  451. displaySystem.driver.SetPalette(this, palette, colorMatch);
  452. }
  453. void RestorePalette(void)
  454. {
  455. displaySystem.driver.RestorePalette(this);
  456. }
  457. bool Lock(bool render)
  458. {
  459. bool result = false;
  460. /*
  461. int c;
  462. for(c = 0; c<current; c++)
  463. Log(" ");
  464. Logf("Locking (%d)\n", current+1);
  465. */
  466. // TOCHECK: Why is displaySystem null with GISDesigner?
  467. result = displaySystem && displaySystem.Lock();
  468. if(result && render)
  469. {
  470. mutex.Wait();
  471. if(!current)
  472. result = displaySystem.driver.Lock(this);
  473. else
  474. result = true;
  475. current++;
  476. }
  477. return result;
  478. }
  479. void Unlock(void)
  480. {
  481. if(current)
  482. {
  483. current--;
  484. /*{
  485. int c;
  486. for(c = 0; c<current; c++)
  487. Log(" ");
  488. Logf("Unlocking (%d)\n", current);
  489. }
  490. */
  491. if(!current && displaySystem)
  492. displaySystem.driver.Unlock(this);
  493. mutex.Release();
  494. }
  495. if(displaySystem)
  496. displaySystem.Unlock();
  497. }
  498. #if !defined(ECERE_VANILLA) && !defined(ECERE_NO3D)
  499. // *** 3D GRAPHICS ***
  500. void SetCamera(Surface surface, Camera camera)
  501. {
  502. if(!display3D)
  503. {
  504. display3D = Display3D { };
  505. }
  506. if(!display3D.selection)
  507. DrawTranslucency();
  508. if(!camera)
  509. {
  510. if(!display3D.selection)
  511. displaySystem.driver.SelectMesh(this, null);
  512. display3D.material = null;
  513. display3D.mesh = null;
  514. }
  515. if(!display3D.selection)
  516. {
  517. displaySystem.driver.SetCamera(this, surface, camera);
  518. }
  519. this.display3D.camera = camera;
  520. if(camera)
  521. {
  522. if(!camera.focalX)
  523. camera.Setup(width, height, null);
  524. // Always calling Update() here had broken interpolation in OrbitWithMouse!
  525. if(!camera.cAngle.w)
  526. camera.Update();
  527. if(display3D.selection)
  528. {
  529. // Compute Picking Planes
  530. Vector3D normal;
  531. Vector3D point { 0,0,0 };
  532. Quaternion quat;
  533. Angle fovLeft, fovRight, fovTop, fovBottom;
  534. ClippingPlane c;
  535. double l = camera.origin.x - (display3D.pickX - display3D.pickWidth/2.0f);
  536. double r = camera.origin.x - (display3D.pickX + display3D.pickWidth/2.0f);
  537. double t = (display3D.pickY - display3D.pickHeight/2.0f) - camera.origin.y;
  538. double b = (display3D.pickY + display3D.pickHeight/2.0f) - camera.origin.y;
  539. fovLeft = atan(l / camera.focalX);
  540. fovRight = atan(r / camera.focalX);
  541. fovTop = atan(t / camera.focalY);
  542. fovBottom = atan(b / camera.focalY);
  543. // --- Left ---
  544. quat.Yaw(fovLeft - Pi/2);
  545. quat.ToDirection(normal);
  546. display3D.viewPickingPlanes[left].FromPointNormal(normal, point);
  547. // --- Right ---
  548. quat.Yaw(fovRight + Pi/2);
  549. quat.ToDirection(normal);
  550. display3D.viewPickingPlanes[right].FromPointNormal(normal, point);
  551. // --- Top ---
  552. quat.Pitch(fovTop + Pi/2);
  553. quat.ToDirection(normal);
  554. display3D.viewPickingPlanes[top].FromPointNormal(normal, point);
  555. // --- Bottom ---
  556. quat.Pitch(fovBottom - Pi/2);
  557. quat.ToDirection(normal);
  558. display3D.viewPickingPlanes[bottom].FromPointNormal(normal, point);
  559. // --- Near ---
  560. normal.x = 0; normal.y = 0; normal.z = 1;
  561. point.z = camera.zMin;
  562. display3D.viewPickingPlanes[near].FromPointNormal(normal, point);
  563. // --- Far ---
  564. normal.x = 0; normal.y = 0; normal.z = -1;
  565. point.z = camera.zMax;
  566. display3D.viewPickingPlanes[far].FromPointNormal(normal, point);
  567. for(c = 0; c<ClippingPlane::enumSize; c++)
  568. display3D.worldPickingPlanes[c].MultMatrix(display3D.viewPickingPlanes[c], camera.inverseTranspose);
  569. // Compute picking ray
  570. {
  571. Vector3D p;
  572. display3D.rayView.p0 = { 0, 0, 0 };
  573. p.x = display3D.pickX;
  574. p.y = display3D.pickY;
  575. p.z = 0.0f;
  576. camera.Unproject(p, display3D.rayView.delta);
  577. // Convert ray to world space
  578. camera.Untransform(display3D.rayView.p0, display3D.rayWorld.p0);
  579. camera.Untransform(display3D.rayView.delta, p);
  580. display3D.rayWorld.delta.Subtract(p, display3D.rayWorld.p0);
  581. }
  582. }
  583. }
  584. }
  585. // --- Lights ---
  586. void SetLight(int id, Light light)
  587. {
  588. displaySystem.driver.SetLight(this, id, light);
  589. }
  590. void SetLights(Object object)
  591. {
  592. if(object)
  593. display3D._SetLights(this, object, 0);
  594. }
  595. // --- Transformations ---
  596. void SetTransform(Matrix matrix, bool viewSpace)
  597. {
  598. if(display3D.selection)
  599. {
  600. ClippingPlane c;
  601. Matrix transpose;
  602. transpose.Transpose(matrix);
  603. if(viewSpace)
  604. {
  605. for(c = 0; c<ClippingPlane::enumSize; c++)
  606. display3D.localPickingPlanes[c].MultMatrix(display3D.viewPickingPlanes[c], transpose);
  607. }
  608. else
  609. {
  610. for(c = 0; c<ClippingPlane::enumSize; c++)
  611. display3D.localPickingPlanes[c].MultMatrix(display3D.worldPickingPlanes[c], transpose);
  612. }
  613. // Transform ray
  614. if(display3D.intersecting)
  615. {
  616. Vector3D p2, tp2;
  617. if(viewSpace)
  618. p2.Add(display3D.rayView.p0, display3D.rayView.delta);
  619. else
  620. p2.Add(display3D.rayWorld.p0, display3D.rayWorld.delta);
  621. display3D.rayLocal.p0.DivideMatrix(display3D.rayWorld.p0, matrix);
  622. tp2.DivideMatrix(p2, matrix);
  623. display3D.rayLocal.delta.Subtract(tp2, display3D.rayLocal.p0);
  624. }
  625. }
  626. else
  627. displaySystem.driver.SetTransform(this, matrix, viewSpace, viewSpace ? false : true);
  628. }
  629. void PushMatrix(void)
  630. {
  631. displaySystem.driver.PushMatrix(this);
  632. }
  633. void PopMatrix(void)
  634. {
  635. displaySystem.driver.PopMatrix(this, true);
  636. }
  637. // --- Drawing ---
  638. void ApplyMaterial(Material material, Mesh mesh)
  639. {
  640. if(material != display3D.material)
  641. {
  642. display3D.material = material;
  643. displaySystem.driver.ApplyMaterial(this, material, mesh);
  644. }
  645. }
  646. void DrawPrimitives(PrimitiveSingle primitive, Mesh mesh)
  647. {
  648. displaySystem.driver.DrawPrimitives(this, primitive, mesh);
  649. }
  650. void SelectMesh(Mesh mesh)
  651. {
  652. displaySystem.driver.SelectMesh(this, mesh);
  653. display3D.mesh = mesh;
  654. }
  655. bool DrawMesh(Object object)
  656. {
  657. bool result = false;
  658. if(display3D.selection)
  659. result = display3D.PickMesh(object, null);
  660. else
  661. {
  662. Mesh mesh = object.mesh;
  663. Material objectMaterial = object.material;
  664. if(mesh.groups.first)
  665. {
  666. PrimitiveGroup group;
  667. displaySystem.driver.SelectMesh(this, mesh);
  668. display3D.mesh = mesh;
  669. for(group = mesh.groups.first; group; group = group.next)
  670. {
  671. Material material = group.material ? group.material : objectMaterial;
  672. if(!material) material = defaultMaterial;
  673. if(material != display3D.material)
  674. {
  675. display3D.material = material;
  676. displaySystem.driver.ApplyMaterial(this, material, mesh);
  677. }
  678. // *** Render Vertex Arrays ***
  679. displaySystem.driver.DrawPrimitives(this, (PrimitiveSingle *)&group.type, mesh);
  680. }
  681. }
  682. if(object.flags.translucent)
  683. {
  684. Matrix matrix;
  685. Matrix inverse, inverseTranspose;
  686. int c;
  687. if(object.flags.viewSpace)
  688. matrix = object.matrix;
  689. else
  690. {
  691. Camera camera = display3D.camera;
  692. Matrix temp = object.matrix;
  693. temp.m[3][0] -= camera.cPosition.x;
  694. temp.m[3][1] -= camera.cPosition.y;
  695. temp.m[3][2] -= camera.cPosition.z;
  696. matrix.Multiply(temp, camera.viewMatrix);
  697. }
  698. inverse.Inverse(matrix);
  699. inverseTranspose.Transpose(inverse);
  700. for(c = 0; c < mesh.nPrimitives; c++)
  701. {
  702. PrimitiveSingle * triangle = &mesh.primitives[c];
  703. SortPrimitive * sort;
  704. Plane * plane = &triangle->plane;
  705. if(display3D.nTriangles >= display3D.maxTriangles)
  706. {
  707. display3D.maxTriangles = display3D.maxTriangles ? (display3D.maxTriangles * 3 / 2) : 32768;
  708. display3D.triangles = renew display3D.triangles SortPrimitive[display3D.maxTriangles];
  709. }
  710. sort = &display3D.triangles[display3D.nTriangles++];
  711. sort->object = object;
  712. sort->triangle = triangle;
  713. sort->middle.MultMatrix(triangle->middle, matrix);
  714. sort->middle.z *= -1;
  715. // sort->plane.MultMatrix(triangle->plane, inverseTranspose);
  716. sort->plane.d = plane->a * inverseTranspose.m[0][3] +
  717. plane->b * inverseTranspose.m[1][3] +
  718. plane->c * inverseTranspose.m[2][3] +
  719. plane->d * inverseTranspose.m[3][3];
  720. }
  721. }
  722. else
  723. {
  724. int c;
  725. displaySystem.driver.SelectMesh(this, mesh);
  726. display3D.mesh = mesh;
  727. for(c = 0; c<mesh.nPrimitives; c++)
  728. {
  729. PrimitiveSingle * primitive = &mesh.primitives[c];
  730. Material material = primitive->material ? primitive->material : objectMaterial;
  731. if(!material) material = defaultMaterial;
  732. if(material != display3D.material)
  733. {
  734. display3D.material = material;
  735. displaySystem.driver.ApplyMaterial(this, material, mesh);
  736. }
  737. displaySystem.driver.DrawPrimitives(this, primitive, display3D.mesh);
  738. }
  739. }
  740. result = true;
  741. }
  742. return result;
  743. }
  744. bool IsObjectVisible(Object object)
  745. {
  746. Plane * planes;
  747. if(display3D.selection || !display3D.camera)
  748. planes = object.flags.viewSpace ? display3D.viewPickingPlanes : display3D.worldPickingPlanes;
  749. else
  750. planes = object.flags.viewSpace ? display3D.camera.viewClippingPlanes : display3D.camera.worldClippingPlanes;
  751. return object.InsideFrustum(planes) != outside;
  752. }
  753. bool DrawObject(Object object)
  754. {
  755. bool result = false;
  756. if(object && object.volume)
  757. {
  758. Object child;
  759. FrustumPlacement visible;
  760. Plane * planes;
  761. Camera camera = display3D.camera;
  762. if(display3D.selection || !camera)
  763. planes = object.flags.viewSpace ? display3D.viewPickingPlanes : display3D.worldPickingPlanes;
  764. else
  765. planes = object.flags.viewSpace ? camera.viewClippingPlanes : camera.worldClippingPlanes;
  766. visible = object.InsideFrustum(planes);
  767. if(visible || display3D.pickingPlanes)
  768. {
  769. if(display3D.collectingHits && object.tag)
  770. {
  771. /*if(object.flags.root)
  772. this.tags[display3D.tagIndex] = object.tag;
  773. else if(object.tag)
  774. this.tags[++display3D.tagIndex] = object.tag;
  775. */
  776. display3D.tags[display3D.tagIndex++] = object.tag;
  777. }
  778. if(object.flags.mesh && object.mesh)
  779. {
  780. if(!display3D.selection && displaySystem.driver.PushMatrix)
  781. displaySystem.driver.PushMatrix(this);
  782. SetTransform(object.matrix, object.flags.viewSpace);
  783. if(display3D.selection)
  784. {
  785. if(visible == intersecting || display3D.intersecting)
  786. {
  787. Vector3D rayIntersect;
  788. if(display3D.PickMesh(object, rayIntersect))
  789. {
  790. if(display3D.intersecting)
  791. {
  792. Vector3D wresult, vresult;
  793. wresult.MultMatrix(rayIntersect, object.matrix);
  794. if(!object.flags.viewSpace)
  795. camera.TransformPoint(vresult, wresult);
  796. else
  797. vresult = wresult;
  798. if(vresult.z < display3D.rayIntersect.z)
  799. display3D.rayIntersect = vresult;
  800. display3D.intersected = true;
  801. }
  802. result = true;
  803. }
  804. }
  805. else
  806. result = true;
  807. }
  808. else
  809. {
  810. result |= DrawMesh(object);
  811. if(displaySystem.driver.PopMatrix)
  812. displaySystem.driver.PopMatrix(this, true);
  813. }
  814. if(display3D.collectingHits && result /*&& object.tag*/)
  815. {
  816. int c;
  817. HitRecord hit = (HitRecord)new0 byte[sizeof(class HitRecord) + sizeof(void *) * (display3D.tagIndex/*+1*/)];
  818. display3D.hitList.Add(hit);
  819. hit.pos = display3D.hitList.count-1;
  820. hit.numTags = display3D.tagIndex /*+ 1*/;
  821. for(c = 0; c</*=*/display3D.tagIndex; c++)
  822. {
  823. hit.tags[c] = display3D.tags[c];
  824. }
  825. if(!object.flags.viewSpace)
  826. camera.TransformPoint(hit.center, object.wcenter);
  827. else
  828. hit.center = object.wcenter;
  829. }
  830. }
  831. for(child = object.children.first; child; child = child.next)
  832. result |= DrawObject(child);
  833. if(display3D.collectingHits && /*!object.flags.root && */object.tag)
  834. display3D.tagIndex--;
  835. }
  836. }
  837. return result;
  838. }
  839. void DrawTranslucency(void)
  840. {
  841. if(display3D.camera)
  842. {
  843. // *** Render translucent primitives ***
  844. if(display3D.nTriangles)
  845. {
  846. Matrix * matrix = null;
  847. int c;
  848. blend = true;
  849. display3D.SortTriangles();
  850. depthWrite = false;
  851. displaySystem.driver.PushMatrix(this);
  852. for(c=0; c<display3D.nTriangles; c++)
  853. {
  854. SortPrimitive * sort = &display3D.triangles[c];
  855. Mesh mesh = sort->object.mesh;
  856. PrimitiveSingle * primitive = sort->triangle;
  857. Material material;
  858. if(&sort->object.matrix != matrix)
  859. {
  860. matrix = &sort->object.matrix;
  861. displaySystem.driver.PopMatrix(this, false);
  862. displaySystem.driver.PushMatrix(this);
  863. SetTransform(matrix, sort->object.flags.viewSpace);
  864. }
  865. if(mesh != display3D.mesh)
  866. {
  867. displaySystem.driver.SelectMesh(this, mesh);
  868. display3D.mesh = mesh;
  869. }
  870. material = primitive->material ? primitive->material : sort->object.material;
  871. if(!material) material = defaultMaterial;
  872. if(material != display3D.material)
  873. {
  874. displaySystem.driver.ApplyMaterial(this, material, display3D.mesh);
  875. display3D.material = material;
  876. }
  877. /*
  878. {
  879. Material testMaterial { };
  880. float amount;
  881. amount = (display3D.triangles[0].middle.z - display3D.triangles[c].middle.z) /
  882. (display3D.triangles[0].middle.z - display3D.triangles[display3D.nTriangles-1].middle.z);
  883. testMaterial.flags.doubleSided = { doubleSided = true, translucent = true };
  884. testMaterial.diffuse.a = 1;
  885. testMaterial.emissive.r = testMaterial.emissive.g = testMaterial.emissive.b = amount;
  886. testMaterial.baseMap = material->baseMap;
  887. displaySystem.driver.ApplyMaterial(this, testMaterial, display3D.mesh);
  888. }
  889. */
  890. // *** Render primitive ***
  891. // if(sort->plane.d > 0)
  892. displaySystem.driver.DrawPrimitives(this, primitive, display3D.mesh);
  893. }
  894. displaySystem.driver.PopMatrix(this, true);
  895. display3D.nTriangles = 0;
  896. blend = false;
  897. }
  898. }
  899. }
  900. // --- Picking ---
  901. void StartSelection(int pickX, int pickY, int pickW, int pickH)
  902. {
  903. if(!display3D)
  904. {
  905. display3D = Display3D { };
  906. }
  907. display3D.pickX = (float)pickX;
  908. display3D.pickY = (float)pickY;
  909. display3D.pickWidth = (float)pickW;
  910. display3D.pickHeight = (float)pickH;
  911. display3D.selection = true;
  912. }
  913. void CollectHits(void)
  914. {
  915. display3D.collectingHits = true;
  916. }
  917. int GetHits(OldList list)
  918. {
  919. display3D.collectingHits = false;
  920. display3D.hitList.Sort(HitRecord::Compare, null);
  921. list = display3D.hitList;
  922. display3D.hitList.Clear();
  923. return list.count;
  924. }
  925. void IntersectPolygons(void)
  926. {
  927. display3D.rayIntersect = { MAXFLOAT, MAXFLOAT, MAXFLOAT };
  928. display3D.intersected = false;
  929. display3D.intersecting = true;
  930. }
  931. bool GetIntersect(Vector3D intersect)
  932. {
  933. intersect = display3D.rayIntersect;
  934. display3D.intersecting = false;
  935. return display3D.intersected;
  936. }
  937. void StopSelection(void)
  938. {
  939. display3D.selection = false;
  940. }
  941. // --- Rendering States ---
  942. property FillModeValue fillMode { set { displaySystem.driver.SetRenderState(this, fillMode, value); } };
  943. property bool depthTest { set { displaySystem.driver.SetRenderState(this, depthTest, value); } };
  944. property bool depthWrite { set { displaySystem.driver.SetRenderState(this, depthWrite, value); } };
  945. property float fogDensity { set { displaySystem.driver.SetRenderState(this, fogDensity, *(uint *)(void *)&value); } };
  946. property Color fogColor { set { displaySystem.driver.SetRenderState(this, fogColor, value); } };
  947. property bool blend { set { displaySystem.driver.SetRenderState(this, blend, value); } };
  948. property Color ambient { set { displaySystem.driver.SetRenderState(this, ambient, value); } };
  949. property bool alphaWrite { set { displaySystem.driver.SetRenderState(this, alphaWrite, value); } };
  950. property bool antiAlias { set { displaySystem.driver.SetRenderState(this, antiAlias, value); } };
  951. property bool vSync { set { displaySystem.driver.SetRenderState(this, vSync, value); } };
  952. property bool pickingPlanes { set { display3D.pickingPlanes = value; } };
  953. #endif
  954. property DisplayFlags flags { get { return displaySystem.flags; } }
  955. property PixelFormat pixelFormat { get { return /*alphaBlend ? pixelFormat888 : */displaySystem.pixelFormat; } }
  956. property bool alphaBlend { set { alphaBlend = value; } get { return alphaBlend; } };
  957. property bool useSharedMemory { set { useSharedMemory = value; } get { return useSharedMemory; } };
  958. property void * systemWindow { get { return window; } };
  959. property DisplaySystem displaySystem { get { return displaySystem; } };
  960. int width, height;
  961. void * driverData;
  962. private:
  963. DisplaySystem displaySystem;
  964. void * window;
  965. Mutex mutex { };
  966. int current;
  967. #if !defined(ECERE_VANILLA) && !defined(ECERE_NO3D)
  968. Display3D display3D;
  969. #endif
  970. bool alphaBlend;
  971. void * windowDriverData;
  972. bool useSharedMemory;
  973. };
  974. #if !defined(ECERE_VANILLA) && !defined(ECERE_NO3D)
  975. private class Display3D
  976. {
  977. // 3D Display
  978. int nTriangles;
  979. SortPrimitive * triangles;
  980. int maxTriangles;
  981. Vector3D points[MAX_CLIP_POINTS];
  982. Vector3D newPoints[MAX_CLIP_POINTS];
  983. byte goodPoints[MAX_CLIP_POINTS];
  984. Material material;
  985. Mesh mesh;
  986. Camera camera;
  987. Plane viewPickingPlanes[ClippingPlane], worldPickingPlanes[ClippingPlane];
  988. Plane localPickingPlanes[ClippingPlane];
  989. bool collectingHits, selection, intersecting, intersected, pickingPlanes;
  990. float pickX, pickY, pickWidth, pickHeight;
  991. OldList hitList;
  992. void * tags[64];
  993. int tagIndex;
  994. Line rayView, rayWorld, rayLocal;
  995. Vector3D rayIntersect;
  996. ~Display3D()
  997. {
  998. delete triangles;
  999. }
  1000. int _SetLights(Display display, Object object, int id)
  1001. {
  1002. if(id < NumberOfLights)
  1003. {
  1004. Object child;
  1005. if(object.flags.light && !object.light.flags.off)
  1006. display.SetLight(id++, object.light);
  1007. for(child = object.children.first; child; child = child.next)
  1008. {
  1009. id = _SetLights(display, child, id);
  1010. }
  1011. }
  1012. return id;
  1013. }
  1014. //#define TRESHOLD -1
  1015. //#define TRESHOLD -0.25
  1016. #define TRESHOLD -0.0025
  1017. bool PickPrimitives(Mesh mesh, PrimitiveSingle primitive, Vector3D rayDiff, Vector3D rayIntersect)
  1018. {
  1019. Plane * planes = localPickingPlanes;
  1020. int c = 0;
  1021. int nIndex = 1, nPoints = 1;
  1022. int offset = 0;
  1023. bool result = false;
  1024. Vector3D * points = this.points;
  1025. Vector3D * newPoints = this.newPoints;
  1026. byte * goodPoints = this.goodPoints;
  1027. int nVertices = primitive.type.vertexRange ? primitive.nVertices : primitive.nIndices;
  1028. int strip = 1;
  1029. Vector3Df tmp;
  1030. bool i32bit = primitive.type.indices32bit;
  1031. uint32 * indices32 = primitive.indices;
  1032. uint16 * indices16 = primitive.indices;
  1033. switch(primitive.type.primitiveType)
  1034. {
  1035. case triangles: nIndex = 3; nPoints = 3; break;
  1036. case quads: nIndex = 4; nPoints = 4; break;
  1037. case triStrip:
  1038. case triFan:
  1039. nIndex = 1; nPoints = 3;
  1040. offset = 2;
  1041. tmp = primitive.type.vertexRange ? mesh.vertices[primitive.first] : mesh.vertices[(i32bit ? indices32[0] : indices16[0])];
  1042. points[0] = { (double)tmp.x, (double)tmp.y, (double)tmp.z };
  1043. tmp = primitive.type.vertexRange ? mesh.vertices[primitive.first+1] : mesh.vertices[(i32bit ? indices32[1] : indices16[1])];
  1044. points[1] = { (double)tmp.x, (double)tmp.y, (double)tmp.z };
  1045. break;
  1046. }
  1047. for(c = offset; c<nVertices; c += nIndex)
  1048. {
  1049. bool outside = false;
  1050. if(!pickingPlanes)
  1051. {
  1052. int p;
  1053. int n = nPoints;
  1054. int i;
  1055. if(primitive.type.vertexRange)
  1056. {
  1057. if(primitive.type.primitiveType == triStrip)
  1058. {
  1059. tmp = mesh.vertices[primitive.first + (c & 1) ? (c - 1) : (c - 2)];
  1060. points[0] = { (double)tmp.x, (double)tmp.y, (double)tmp.z };
  1061. tmp = mesh.vertices[primitive.first + (c & 1) ? (c - 2) : (c - 1)];
  1062. points[1] = { (double)tmp.x, (double)tmp.y, (double)tmp.z };
  1063. }
  1064. else if(primitive.type.primitiveType == triFan)
  1065. {
  1066. tmp = mesh.vertices[primitive.first + 0];
  1067. points[0] = { (double)tmp.x, (double)tmp.y, (double)tmp.z };
  1068. tmp = mesh.vertices[primitive.first + c - 1];
  1069. points[1] = { (double)tmp.x, (double)tmp.y, (double)tmp.z };
  1070. }
  1071. for(i = 0; i<nIndex; i++)
  1072. {
  1073. tmp = mesh.vertices[primitive.first + c+i];
  1074. points[i + offset] = { (double)tmp.x, (double)tmp.y, (double)tmp.z };
  1075. }
  1076. }
  1077. else
  1078. {
  1079. if(primitive.type.primitiveType == triStrip)
  1080. {
  1081. i = (c & 1) ? (c - 1) : (c - 2);
  1082. tmp = mesh.vertices[(i32bit ? indices32[i] : indices16[i])];
  1083. points[0] = { (double)tmp.x, (double)tmp.y, (double)tmp.z };
  1084. i = (c & 1) ? (c - 2) : (c - 1);
  1085. tmp = mesh.vertices[(i32bit ? indices32[i] : indices16[i])];
  1086. points[1] = { (double)tmp.x, (double)tmp.y, (double)tmp.z };
  1087. }
  1088. else if(primitive.type.primitiveType == triFan)
  1089. {
  1090. tmp = mesh.vertices[(i32bit ? indices32[0] : indices16[0])];
  1091. points[0] = { (double)tmp.x, (double)tmp.y, (double)tmp.z };
  1092. tmp = mesh.vertices[(i32bit ? indices32[c-1] : indices16[c-1])];
  1093. points[1] = { (double)tmp.x, (double)tmp.y, (double)tmp.z };
  1094. }
  1095. for(i = 0; i<nIndex; i++)
  1096. {
  1097. tmp = mesh.vertices[(i32bit ? indices32[c+i] : indices16[c+i])];
  1098. points[i + offset] = { (double)tmp.x, (double)tmp.y, (double)tmp.z };
  1099. }
  1100. }
  1101. for(p = 0; p < 6; p++)
  1102. {
  1103. Plane * plane = &planes[p];
  1104. int i;
  1105. int numGoodPoints = 0;
  1106. memset(goodPoints, 0, n);
  1107. for(i = 0; i < n; i++)
  1108. {
  1109. double dot = plane->normal.DotProduct(points[i]);
  1110. double distance = dot + plane->d;
  1111. if(distance > TRESHOLD)
  1112. {
  1113. numGoodPoints++;
  1114. goodPoints[i] = 1;
  1115. }
  1116. }
  1117. if(!numGoodPoints)
  1118. {
  1119. outside = true;
  1120. break;
  1121. }
  1122. if(numGoodPoints < n)
  1123. {
  1124. // Clip the polygon
  1125. int newN = 0;
  1126. int lastGood = -1;
  1127. int j;
  1128. for(j = 0; j<n; )
  1129. {
  1130. if(goodPoints[j])
  1131. {
  1132. newPoints[newN++] = points[j];
  1133. lastGood = j++;
  1134. }
  1135. else
  1136. {
  1137. Line edge;
  1138. int next;
  1139. if(lastGood == -1)
  1140. for(lastGood = n-1; !goodPoints[lastGood]; lastGood--);
  1141. edge.p0 = points[lastGood];
  1142. edge.delta.Subtract(points[j], edge.p0);
  1143. plane->IntersectLine(edge, newPoints[newN++]);
  1144. for(next = j+1; next != j; next++)
  1145. {
  1146. if(next == n) next = 0;
  1147. if(goodPoints[next])
  1148. {
  1149. int prev = next - 1;
  1150. if(prev < 0) prev = n-1;
  1151. edge.p0 = points[prev];
  1152. edge.delta.Subtract(points[next], edge.p0);
  1153. plane->IntersectLine(edge, newPoints[newN++]);
  1154. break;
  1155. }
  1156. }
  1157. if(next <= j)
  1158. break;
  1159. else
  1160. j = next;
  1161. }
  1162. }
  1163. // Use the new points
  1164. memcpy(points, newPoints, newN * sizeof(Vector3D));
  1165. n = newN;
  1166. }
  1167. }
  1168. }
  1169. if(!outside)
  1170. {
  1171. result = true;
  1172. // TODO: Implement intersection with TriStrip, TriFan...
  1173. if(intersecting)
  1174. {
  1175. // Intersect primitives
  1176. Plane plane;
  1177. Vector3D intersect, diff;
  1178. int i0 = c, i1 = c+1, i2 = c+2;
  1179. if(primitive.type.primitiveType == triStrip)
  1180. {
  1181. i0 = (c & 1) ? (c - 1) : (c - 2);
  1182. i1 = (c & 1) ? (c - 2) : (c - 1);
  1183. i2 = c;
  1184. }
  1185. else if(primitive.type.primitiveType == triFan)
  1186. {
  1187. i0 = 0;
  1188. i1 = c - 1;
  1189. i2 = c;
  1190. }
  1191. if(primitive.type.vertexRange)
  1192. plane.FromPointsf(
  1193. mesh.vertices[primitive.first + i0],
  1194. mesh.vertices[primitive.first + i1],
  1195. mesh.vertices[primitive.first + i2]);
  1196. else
  1197. plane.FromPointsf(
  1198. mesh.vertices[(i32bit ? indices32[i0] : indices16[i0])],
  1199. mesh.vertices[(i32bit ? indices32[i1] : indices16[i1])],
  1200. mesh.vertices[(i32bit ? indices32[i2] : indices16[i2])]);
  1201. plane.IntersectLine(rayLocal, intersect);
  1202. diff.Subtract(intersect, rayLocal.p0);
  1203. diff.x /= rayLocal.delta.x;
  1204. diff.y /= rayLocal.delta.y;
  1205. diff.z /= rayLocal.delta.z;
  1206. if(diff.x < rayDiff.x || diff.y < rayDiff.y || diff.z < rayDiff.z)
  1207. {
  1208. rayDiff = diff;
  1209. rayIntersect = intersect;
  1210. }
  1211. }
  1212. else
  1213. break;
  1214. }
  1215. switch(primitive.type)
  1216. {
  1217. case triStrip:
  1218. points[strip] = points[2];
  1219. strip ^= 1;
  1220. break;
  1221. case triFan:
  1222. points[1] = points[2];
  1223. break;
  1224. }
  1225. }
  1226. return result;
  1227. }
  1228. bool PickMesh(Object object, Vector3D rayIntersect)
  1229. {
  1230. Mesh mesh = object.mesh;
  1231. bool result = false;
  1232. Vector3D rayDiff { MAXFLOAT, MAXFLOAT, MAXFLOAT };
  1233. if(rayIntersect != null)
  1234. rayIntersect = { MAXFLOAT, MAXFLOAT, MAXFLOAT };
  1235. if(mesh.groups.first)
  1236. {
  1237. PrimitiveGroup group;
  1238. for(group = mesh.groups.first; group; group = group.next)
  1239. {
  1240. if(PickPrimitives(mesh, (PrimitiveSingle *)&group.type, rayDiff, rayIntersect))
  1241. {
  1242. result = true;
  1243. if(!intersecting)
  1244. break;
  1245. }
  1246. }
  1247. }
  1248. else
  1249. {
  1250. int c;
  1251. for(c = 0; c < mesh.nPrimitives; c++)
  1252. {
  1253. if(PickPrimitives(mesh, mesh.primitives[c], rayDiff, rayIntersect))
  1254. {
  1255. result = true;
  1256. if(!intersecting)
  1257. break;
  1258. }
  1259. }
  1260. }
  1261. return result;
  1262. }
  1263. void SortTriangles(void)
  1264. {
  1265. Matrix matrix;
  1266. Object object = null;
  1267. int c;
  1268. for(c=0; c<nTriangles; c++)
  1269. {
  1270. SortPrimitive * sort = &triangles[c];
  1271. Mesh mesh = sort->object.mesh;
  1272. PrimitiveSingle * primitive = sort->triangle;
  1273. Vector3Df min { MAXFLOAT, MAXFLOAT, MAXFLOAT };
  1274. Vector3Df max { -MAXFLOAT, -MAXFLOAT, -MAXFLOAT };
  1275. int v;
  1276. if(object != sort->object)
  1277. {
  1278. object = sort->object;
  1279. if(object.flags.viewSpace)
  1280. matrix = object.matrix;
  1281. else
  1282. {
  1283. Camera camera = this.camera;
  1284. Matrix temp = object.matrix;
  1285. temp.m[3][0] -= camera.cPosition.x;
  1286. temp.m[3][1] -= camera.cPosition.y;
  1287. temp.m[3][2] -= camera.cPosition.z;
  1288. matrix.Multiply(temp, camera.viewMatrix);
  1289. }
  1290. }
  1291. for(v = 0; v<primitive->nIndices; v++)
  1292. {
  1293. Vector3Df * local = &mesh.vertices[primitive->indices[v]];
  1294. Vector3Df vertex;
  1295. vertex.MultMatrix(local, &matrix);
  1296. if(vertex.x > max.x) max.x = vertex.x;
  1297. if(vertex.y > max.y) max.y = vertex.y;
  1298. if(vertex.z > max.z) max.z = vertex.z;
  1299. if(vertex.x < min.x) min.x = vertex.x;
  1300. if(vertex.y < min.y) min.y = vertex.y;
  1301. if(vertex.z < min.z) min.z = vertex.z;
  1302. }
  1303. sort->min = min;
  1304. sort->max = max;
  1305. sort->marked = false;
  1306. }
  1307. /*
  1308. Logf("========= Before Sort ==========\n");
  1309. for(c=0; c<nTriangles; c++)
  1310. {
  1311. SortPrimitive * sort = &triangles[c];
  1312. int v;
  1313. Mesh mesh = sort->mesh;
  1314. PrimitiveSingle * primitive = sort->triangle;
  1315. Logf("Triangle %d (%s):\n", c, primitive->material->name);
  1316. for(v = 0; v<primitive->nIndices; v++)
  1317. {
  1318. Vector3Df * local = &mesh.vertices[primitive->indices[v]];
  1319. Vector3Df vertex;
  1320. vertex.<MultMatrix(local, sort->matrix);
  1321. Logf("Vertex %d:", v);
  1322. // Logf(" Local %f, %f, %f:\n", local->x, local->y, local->z);
  1323. Logf(" View %f, %f, %f:\n", vertex.x, vertex.y, vertex.z);
  1324. }
  1325. Logf("Min %f, %f, %f:\n", sort->min.x, sort->min.y, sort->min.z);
  1326. Logf("Max %f, %f, %f:\n", sort->max.x, sort->max.y, sort->max.z);
  1327. Logf("\n", c);
  1328. }*/
  1329. // *** Sort translucent primitives ***
  1330. qsort((void*) triangles, nTriangles, sizeof(SortPrimitive), SortPrimitive::Compare);
  1331. /*
  1332. Logf("\n\n========= After Sort ==========\n");
  1333. for(c=0; c<nTriangles; c++)
  1334. {
  1335. SortPrimitive * sort = &triangles[c];
  1336. int v;
  1337. Mesh mesh = sort->mesh;
  1338. PrimitiveSingle * primitive = sort->triangle;
  1339. Logf("Triangle %d (%s):\n", c, primitive->material->name);
  1340. for(v = 0; v<primitive->nIndices; v++)
  1341. {
  1342. Vector3Df * local = &mesh.vertices[primitive->indices[v]];
  1343. Vector3Df vertex;
  1344. vertex.MultMatrix(local, sort->matrix);
  1345. Logf("Vertex %d:", v);
  1346. // Logf(" Local %f, %f, %f:\n", local->x, local->y, local->z);
  1347. Logf(" View %f, %f, %f:\n", vertex.x, vertex.y, vertex.z);
  1348. }
  1349. Logf("Min %f, %f, %f:\n", sort->min.x, sort->min.y, sort->min.z);
  1350. Logf("Max %f, %f, %f:\n", sort->max.x, sort->max.y, sort->max.z);
  1351. Logf("\n", c);
  1352. }
  1353. */
  1354. //exit(0);
  1355. /*
  1356. If all five tests fail for a particular Q,
  1357. then P might obscure Q. Now Q must be tested.
  1358. First, the algorithm checks if Q has been "marked."
  1359. If Q is marked, then Q was "moved around" in the list
  1360. during a previous iteration of the loop. The algorithm
  1361. only allows a polygon to be moved once, to avoid the possibility
  1362. of infinite loops. If Q is not marked, it is tested to see
  1363. if it might obscure P. If Q cannot obscure P, then Q is possibly
  1364. behind P and so it is good candidate to be drawn next.
  1365. Therefore, the algorithm "abandons" the current P (that is, it
  1366. stops testing Q's against the current P) and moves the current
  1367. Q to the end of the list to become the next P.
  1368. */
  1369. /*
  1370. {
  1371. int p;
  1372. for(p = 0; p<nTriangles; p++)
  1373. {
  1374. SortPrimitive * poly1 =