PageRenderTime 30ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 0ms

/ecere/src/gfx/3D/Object.ec

https://github.com/thexa4/sdk
C | 1543 lines | 1291 code | 186 blank | 66 comment | 285 complexity | dd6800341f63b07f6ebc236baa992e00 MD5 | raw file
  1. namespace gfx3D;
  2. import "Display"
  3. public enum FrustumPlacement { outside, inside, intersecting };
  4. public class ObjectFormat
  5. {
  6. class_data char * extension;
  7. class_property char * extension
  8. {
  9. set { class_data(extension) = value; }
  10. get { return class_data(extension); }
  11. }
  12. virtual bool ::Load(Object object, char * fileName, DisplaySystem displaySystem);
  13. };
  14. // TODO: Review these:
  15. public class ObjectFlags
  16. {
  17. public:
  18. bool root:1, viewSpace:1, ownMesh:1, translucent:1, flipWindings:1, keysLoaded:1, transform:1, mesh:1, light:1, camera:1;
  19. int hierarchy:16:16;
  20. };
  21. public struct Transform
  22. {
  23. Vector3D position;
  24. Quaternion orientation;
  25. Vector3Df scaling;
  26. };
  27. /*static float ease(float t, float a, float b)
  28. {
  29. float k;
  30. float s = a + b;
  31. if (s == 0.0f) return t;
  32. if (s > 1.0f)
  33. {
  34. a /= s;
  35. b /= s;
  36. }
  37. k = 1.0f/(2.0f-a-b);
  38. if (t < a) return (k/a)*t*t;
  39. if (t < 1.0f - b) return k*(2.0f * t - a);
  40. t = 1.0f - t;
  41. return 1.0f - (k/b)*t*t;
  42. }*/
  43. public enum FrameTrackType : uint16 { position = 1, rotation, scaling, fov, roll, colorChange, morph, hotSpot, fallOff, hide };
  44. public class FrameTrackBits
  45. {
  46. FrameTrackType type;
  47. bool loop:1;
  48. };
  49. public struct FrameKey
  50. {
  51. unsigned int frame;
  52. float tension, continuity, bias;
  53. float easeFrom, easeTo;
  54. union
  55. {
  56. Vector3Df position;
  57. Quaternion orientation;
  58. Vector3Df scaling;
  59. float roll;
  60. float fov;
  61. ColorRGB color;
  62. float hotSpot;
  63. float fallOff;
  64. };
  65. };
  66. enum SplinePart { splinePoint, splineA, splineB };
  67. public class FrameTrack : struct
  68. {
  69. FrameTrack prev, next;
  70. FrameTrackBits type;
  71. unsigned int numKeys;
  72. FrameKey * keys;
  73. void Free(void)
  74. {
  75. delete keys;
  76. }
  77. ~FrameTrack()
  78. {
  79. Free();
  80. }
  81. float GetFloat(SplinePart what, unsigned int n)
  82. {
  83. float value;
  84. FrameKey *kn_1, *kn, *kn1;
  85. float pn_1, pn, pn1;
  86. int d1, d2;
  87. kn = &keys[n];
  88. pn = kn->roll;
  89. if(what == splinePoint)
  90. value = pn;
  91. else
  92. {
  93. if(n == 0)
  94. {
  95. kn1 = &keys[1];
  96. pn1 = kn1->roll;
  97. if(numKeys == 2)
  98. {
  99. value = pn1 - pn;
  100. value *= 1.0f - kn->tension;
  101. return value;
  102. }
  103. if(type.loop)
  104. {
  105. kn_1 = &keys[numKeys-2];
  106. d1 = keys[numKeys-1].frame - kn_1->frame;
  107. d2 = kn1->frame - kn->frame;
  108. }
  109. else
  110. {
  111. float a1;
  112. value = pn1 - pn;
  113. value *= 1.5f;
  114. a1 = GetFloat(splineA, 1);
  115. a1 *= 0.5f;
  116. value -= a1;
  117. value *= 1.0f - kn->tension;
  118. return value;
  119. }
  120. }
  121. else if(n == numKeys-1)
  122. {
  123. kn_1 = &keys[n-1];
  124. pn_1 = kn_1->roll;
  125. if(numKeys == 2)
  126. {
  127. value = pn - pn_1;
  128. value *= 1.0f - kn->tension;
  129. return value;
  130. }
  131. if(type.loop)
  132. {
  133. kn1 = &keys[1];
  134. d1 = kn->frame - kn_1->frame;
  135. d2 = kn1->frame - keys[0].frame;
  136. }
  137. else
  138. {
  139. float bn_1;
  140. value = pn - pn_1;
  141. value *= 1.5f;
  142. bn_1 = GetFloat(splineB, n-1);
  143. bn_1 *= 0.5f;
  144. value -= bn_1;
  145. value *= 1.0f - kn->tension;
  146. return value;
  147. }
  148. }
  149. else
  150. {
  151. kn_1 = &keys[n-1];
  152. kn1 = &keys[n+1];
  153. d1 = kn->frame - kn_1->frame;
  154. d2 = kn1->frame - kn->frame;
  155. }
  156. {
  157. float C, adjust;
  158. float part1, part2;
  159. pn_1 = kn_1->roll;
  160. pn1 = kn1->roll;
  161. if(what == splineA)
  162. {
  163. C = kn->continuity;
  164. adjust = (float)d1;
  165. }
  166. else
  167. {
  168. C = -kn->continuity;
  169. adjust = (float)d2;
  170. }
  171. adjust /= d1 + d2;
  172. adjust = 0.5f + (1.0f - Abs(C))*(adjust - 0.5f);
  173. part1 = pn - pn_1;
  174. part1 *= (1.0f + kn->bias)*(1.0f - C);
  175. part2 = pn1 - pn;
  176. part2 *= (1.0f - kn->bias)*(1.0f + C);
  177. value = part1 + part2;
  178. value *= (1.0f - kn->tension)*adjust;
  179. }
  180. }
  181. return value;
  182. }
  183. void GetVector(Vector3Df vector, SplinePart what, unsigned int n)
  184. {
  185. FrameKey *kn_1, *kn, *kn1;
  186. Vector3Df *pn_1, *pn, *pn1;
  187. int d1, d2;
  188. kn = &keys[n];
  189. pn = &kn->position;
  190. if(what == splinePoint)
  191. vector = *pn;
  192. else
  193. {
  194. if(n == 0)
  195. {
  196. kn1 = &keys[1];
  197. pn1 = &kn1->position;
  198. if(numKeys == 2)
  199. {
  200. vector.Subtract(pn1, pn);
  201. vector.Scale(vector, 1.0f - kn->tension);
  202. return;
  203. }
  204. if(type.loop)
  205. {
  206. kn_1 = &keys[numKeys-2];
  207. d1 = keys[numKeys-1].frame - kn_1->frame;
  208. d2 = kn1->frame - kn->frame;
  209. }
  210. else
  211. {
  212. Vector3Df a1;
  213. vector.Subtract(pn1, pn);
  214. vector.Scale(vector, 1.5f);
  215. GetVector(a1, splineA, 1);
  216. a1.Scale(a1, 0.5f);
  217. vector.Subtract(vector, a1);
  218. vector.Scale(vector, 1.0f - kn->tension);
  219. return;
  220. }
  221. }
  222. else if(n == numKeys-1)
  223. {
  224. kn_1 = &keys[n-1];
  225. pn_1 = &kn_1->position;
  226. if(numKeys == 2)
  227. {
  228. vector.Subtract(pn, pn_1);
  229. vector.Scale(vector, 1.0f - kn->tension);
  230. return;
  231. }
  232. if(type.loop)
  233. {
  234. kn1 = &keys[1];
  235. d1 = kn->frame - kn_1->frame;
  236. d2 = kn1->frame - keys[0].frame;
  237. }
  238. else
  239. {
  240. Vector3Df bn_1;
  241. vector.Subtract(pn, pn_1);
  242. vector.Scale(vector, 1.5f);
  243. GetVector(&bn_1, splineB, n-1);
  244. bn_1.Scale(bn_1, 0.5f);
  245. vector.Subtract(vector, bn_1);
  246. vector.Scale(vector, 1.0f - kn->tension);
  247. return;
  248. }
  249. }
  250. else
  251. {
  252. kn_1 = &keys[n-1];
  253. kn1 = &keys[n+1];
  254. d1 = kn->frame - kn_1->frame;
  255. d2 = kn1->frame - kn->frame;
  256. }
  257. {
  258. float C, adjust;
  259. Vector3Df part1, part2;
  260. pn_1 = &kn_1->position;
  261. pn1 = &kn1->position;
  262. if(what == splineA)
  263. {
  264. C = kn->continuity;
  265. adjust = (float)d1;
  266. }
  267. else
  268. {
  269. C = -kn->continuity;
  270. adjust = (float)d2;
  271. }
  272. adjust /= d1 + d2;
  273. adjust = 0.5f + (1.0f - Abs(C))*(adjust - 0.5f);
  274. part1.Subtract(pn, pn_1);
  275. part1.Scale(part1, (1.0f + kn->bias)*(1.0f - C));
  276. part2.Subtract(pn1, pn);
  277. part2.Scale(part2, (1.0f - kn->bias)*(1.0f + C));
  278. vector.Add(part1, part2);
  279. vector.Scale(vector, (1.0f - kn->tension)*adjust);
  280. }
  281. }
  282. }
  283. void GetQuaternion(Quaternion quat, SplinePart what, unsigned int n)
  284. {
  285. FrameKey *kn_1, *kn, *kn1;
  286. Quaternion *qn_1, *qn, *qn1;
  287. int d1, d2;
  288. kn = &keys[n];
  289. qn = &kn->orientation;
  290. if (what == splinePoint)
  291. quat = *qn;
  292. else
  293. {
  294. if(n == 0)
  295. {
  296. kn1 = &keys[1];
  297. if (!(type.loop) || numKeys <= 2)
  298. {
  299. qn1 = &kn1->orientation;
  300. quat.Slerp(qn, qn1, (1.0f - kn->tension)*(1.0f + kn->continuity*kn->bias)/3.0f);
  301. return;
  302. }
  303. else
  304. {
  305. kn_1= &keys[numKeys-2];
  306. d1 = keys[numKeys-1].frame - kn_1->frame;
  307. d2 = kn1->frame - kn->frame;
  308. }
  309. }
  310. else if (n == numKeys-1)
  311. {
  312. kn_1 = &keys[n-1];
  313. if (!(type.loop) || numKeys <= 2)
  314. {
  315. qn_1 = &kn_1->orientation;
  316. quat.Slerp(qn, qn_1, (1.0f - kn->tension)*(1.0f - kn->continuity*kn->bias)/3.0f);
  317. return;
  318. }
  319. else
  320. {
  321. kn1 = &keys[1];
  322. d1 = kn->frame - kn_1->frame;
  323. d2 = kn1->frame - keys[0].frame;
  324. }
  325. }
  326. else
  327. {
  328. kn_1 = &keys[n-1];
  329. kn1 = &keys[n+1];
  330. d1 = kn->frame - kn_1->frame;
  331. d2 = kn1->frame - kn->frame;
  332. }
  333. {
  334. float f, adjust;
  335. Quaternion g1, g2, tmp;
  336. qn_1 = &kn_1->orientation;
  337. qn1 = &kn1->orientation;
  338. if (what == splineA)
  339. {
  340. f = 1.0f;
  341. adjust = (float)d1;
  342. }
  343. else
  344. {
  345. f = -1.0f;
  346. adjust = (float)d2;
  347. }
  348. adjust /= d1 + d2;
  349. adjust = 0.5f + (1.0f - Abs(kn->continuity))*(adjust - 0.5f);
  350. g1.Slerp(qn, qn_1,-(1.0f + kn->bias)/3.0f);
  351. g2.Slerp(qn, qn1 , (1.0f - kn->bias)/3.0f);
  352. tmp.Slerp(g1, g2, 0.5f + f*0.5f*kn->continuity);
  353. quat.Slerp(qn, &tmp, f*(kn->tension - 1.0f)*adjust*2.0f);
  354. }
  355. }
  356. }
  357. void Interpolate(Vector3Df vector, Vector3Df prevVector, Vector3Df nextVector, int prev, int next, float t)
  358. {
  359. if(!t)
  360. vector = prevVector;
  361. else
  362. {
  363. Vector3Df p1 = prevVector, p2 = nextVector;
  364. Vector3Df r1, r2;
  365. GetVector(r1, splineB, prev);
  366. GetVector(r2, splineA, next);
  367. p1.Scale(p1, 2*t*t*t - 3*t*t + 1);
  368. p2.Scale(p2,-2*t*t*t + 3*t*t);
  369. r1.Scale(r1, t*t*t - 2*t*t + t);
  370. r2.Scale(r2, t*t*t - t*t);
  371. vector = p1;
  372. vector.Add(vector, r1);
  373. vector.Add(vector, p2);
  374. vector.Add(vector, r2);
  375. }
  376. }
  377. void InterpolateQuat(Quaternion quat, Quaternion prevQuat, Quaternion nextQuat, int prev, int next, float t)
  378. {
  379. if(!t)
  380. quat = prevQuat;
  381. else
  382. {
  383. Quaternion a, b;
  384. Quaternion q0, q1, q2;
  385. GetQuaternion(b, splineB, prev);
  386. GetQuaternion(a, splineA, next);
  387. q0.Slerp(prevQuat, b, t);
  388. q1.Slerp(b, a, t);
  389. q2.Slerp(a, nextQuat, t);
  390. q0.Slerp(q0, q1, t);
  391. q1.Slerp(q1, q2, t);
  392. quat.Slerp(q0, q1, t);
  393. }
  394. }
  395. float InterpolateFloat(float prevValue, float nextValue, int prev, int next, float t)
  396. {
  397. float value;
  398. if(!t)
  399. value = prevValue;
  400. else
  401. {
  402. float p1 = prevValue, p2 = nextValue;
  403. float r1 = GetFloat(splineB, prev);
  404. float r2 = GetFloat(splineA, next);
  405. p1 *= 2*t*t*t - 3*t*t + 1;
  406. p2 *= -2*t*t*t + 3*t*t;
  407. r1 *= t*t*t - 2*t*t + t;
  408. r2 *= t*t*t - t*t;
  409. value = p1 + r1 + p2 + r2;
  410. }
  411. return value;
  412. }
  413. };
  414. static bool FindMaterialAndType(Mesh mesh, Material material, PrimitiveGroupType type)
  415. {
  416. PrimitiveGroup group;
  417. for(group = mesh.groups.first; group; group = group.next)
  418. if(group.material == material && group.type == type)
  419. return true;
  420. return false;
  421. }
  422. public class Object
  423. {
  424. public:
  425. void SetMinMaxRadius(bool processMesh)
  426. {
  427. Object child;
  428. if(flags.mesh && mesh)
  429. {
  430. if(processMesh)
  431. mesh.SetMinMaxRadius();
  432. min = mesh.min;
  433. max = mesh.max;
  434. volume = true;
  435. }
  436. else
  437. {
  438. min = { MAXFLOAT, MAXFLOAT, MAXFLOAT };
  439. max = { -MAXFLOAT, -MAXFLOAT, -MAXFLOAT };
  440. volume = false;
  441. }
  442. for(child = children.first; child; child = child.next)
  443. {
  444. child.SetMinMaxRadius(processMesh);
  445. if(child.volume)
  446. {
  447. // Child Local + Child Object Transform
  448. Vector3Df points[8] =
  449. {
  450. { child.min.x, child.min.y, child.min.z },
  451. { child.min.x, child.min.y, child.max.z },
  452. { child.min.x, child.max.y, child.min.z },
  453. { child.min.x, child.max.y, child.max.z },
  454. { child.max.x, child.min.y, child.min.z },
  455. { child.max.x, child.min.y, child.max.z },
  456. { child.max.x, child.max.y, child.min.z },
  457. { child.max.x, child.max.y, child.max.z }
  458. };
  459. int c;
  460. for(c = 0; c<8; c++)
  461. {
  462. Vector3Df point;
  463. point.MultMatrix(points[c], child.localMatrix);
  464. if(point.x < this.min.x) this.min.x = point.x;
  465. if(point.y < this.min.y) this.min.y = point.y;
  466. if(point.z < this.min.z) this.min.z = point.z;
  467. if(point.x > this.max.x) this.max.x = point.x;
  468. if(point.y > this.max.y) this.max.y = point.y;
  469. if(point.z > this.max.z) this.max.z = point.z;
  470. }
  471. volume = true;
  472. }
  473. }
  474. if(volume)
  475. {
  476. Vector3Df points[8] =
  477. {
  478. { min.x, min.y, min.z },
  479. { min.x, min.y, max.z },
  480. { min.x, max.y, min.z },
  481. { min.x, max.y, max.z },
  482. { max.x, min.y, min.z },
  483. { max.x, min.y, max.z },
  484. { max.x, max.y, min.z },
  485. { max.x, max.y, max.z }
  486. };
  487. Vector3Df halfExtent;
  488. Vector3D halfExtentd;
  489. // Local
  490. center.Add(min, max);
  491. center.Scale(center, 0.5f);
  492. halfExtent.Subtract(max, min);
  493. halfExtent.Scale(halfExtent, 0.5f);
  494. radius = halfExtent.length;
  495. // World
  496. {
  497. Vector3D min { MAXFLOAT, MAXFLOAT, MAXFLOAT };
  498. Vector3D max { -MAXFLOAT, -MAXFLOAT, -MAXFLOAT };
  499. int c;
  500. for(c = 0; c<8; c++)
  501. {
  502. Vector3D point;
  503. point.MultMatrixf(points[c], matrix);
  504. if(point.x < min.x) min.x = point.x;
  505. if(point.y < min.y) min.y = point.y;
  506. if(point.z < min.z) min.z = point.z;
  507. if(point.x > max.x) max.x = point.x;
  508. if(point.y > max.y) max.y = point.y;
  509. if(point.z > max.z) max.z = point.z;
  510. }
  511. wmin = min;
  512. wmax = max;
  513. }
  514. wcenter.Add(wmin, wmax);
  515. wcenter.Scale(wcenter, 0.5f);
  516. halfExtentd.Subtract(wmax, wmin);
  517. halfExtentd.Scale(halfExtentd, 0.5);
  518. wradius = halfExtentd.length;
  519. }
  520. }
  521. void Duplicate(Object model)
  522. {
  523. if(model)
  524. {
  525. Object modelChild;
  526. name = model.name;
  527. flags = model.flags;
  528. flags.ownMesh = false;
  529. mesh = model.mesh;
  530. /*
  531. min = model.min;
  532. max = model.max;
  533. radius = model.radius;
  534. */
  535. transform = model.transform;
  536. for(modelChild = model.children.first; modelChild; modelChild = modelChild.next)
  537. {
  538. Object child { parent = this };
  539. child.Duplicate(modelChild);
  540. children.AddName(child);
  541. }
  542. }
  543. }
  544. void Free(DisplaySystem displaySystem)
  545. {
  546. if(this)
  547. {
  548. Object child;
  549. while((child = children.first))
  550. {
  551. children.Remove(child);
  552. child.Free(displaySystem);
  553. }
  554. if(flags.ownMesh)
  555. {
  556. DisplaySystem meshDisplaySystem = mesh.displaySystem;
  557. mesh.Free(0);
  558. if(meshDisplaySystem)
  559. meshDisplaySystem.RemoveMesh(mesh);
  560. delete mesh;
  561. }
  562. tracks.Free(FrameTrack::Free);
  563. delete name;
  564. }
  565. }
  566. bool Load(char * fileName, char * type, DisplaySystem displaySystem)
  567. {
  568. char ext[MAX_EXTENSION];
  569. subclass(ObjectFormat) format;
  570. OldLink link;
  571. bool result = false;
  572. if(!type && fileName)
  573. {
  574. type = GetExtension(fileName, ext);
  575. strlwr(type);
  576. }
  577. for(link = class(ObjectFormat).derivatives.first; link; link = link.next)
  578. {
  579. format = link.data;
  580. if(format.extension && !strcmp(format.extension, type))
  581. break;
  582. }
  583. if(!link) format = null;
  584. if(format)
  585. {
  586. if((format.Load(this, fileName, displaySystem)))
  587. result = true;
  588. }
  589. /*if(!result)
  590. ErrorLogCode(GERR_LOAD_OBJECT_FAILED, fileName);*/
  591. return result;
  592. }
  593. void FreeMesh(DisplaySystem displaySystem)
  594. {
  595. if(this)
  596. {
  597. Object child;
  598. mesh.Free(0);
  599. for(child = children.first; child; child = child.next)
  600. child.FreeMesh(displaySystem);
  601. }
  602. }
  603. Object Find(char * name)
  604. {
  605. if(this && name)
  606. {
  607. Object child;
  608. if(this.name && !strcmp(this.name, name))
  609. return this;
  610. else
  611. {
  612. for(child = children.first; child; child = child.next)
  613. {
  614. Object result = child.Find(name);
  615. if(result)
  616. return result;
  617. }
  618. }
  619. }
  620. return null;
  621. }
  622. void Initialize(void)
  623. {
  624. if(this)
  625. {
  626. transform.scaling = { 1, 1, 1 };
  627. transform.orientation = { 1,0,0,0 };
  628. flags.root = true;
  629. flags.transform = true;
  630. matrix.Identity();
  631. }
  632. }
  633. Mesh InitializeMesh(DisplaySystem displaySystem)
  634. {
  635. if(this)
  636. {
  637. flags.mesh = true;
  638. if(!mesh)
  639. {
  640. mesh = Mesh { };
  641. flags.ownMesh = true;
  642. }
  643. if(mesh)
  644. {
  645. FillBytes(mesh, 0, sizeof(class Mesh));
  646. displaySystem.AddMesh(mesh);
  647. }
  648. matrix.Identity();
  649. return mesh;
  650. }
  651. return null;
  652. }
  653. bool AddName(Object object, char * name)
  654. {
  655. bool result;
  656. if(this)
  657. {
  658. char * newName = CopyString(name);
  659. object.name = newName;
  660. result = children.AddName(object);
  661. if(result)
  662. object.parent = this;
  663. object.flags.transform = true;
  664. }
  665. return result;
  666. }
  667. // TODO: Add support to Merge Vertex Colors mesh feature
  668. bool Merge(DisplaySystem displaySystem)
  669. {
  670. bool result = false;
  671. if(!children.first)
  672. result = true;
  673. else
  674. {
  675. Object child, nextChild;
  676. int nVertices = 0;
  677. MeshFeatures flags = 0;
  678. Mesh objectMesh = mesh;
  679. bool freeMesh = this.flags.ownMesh;
  680. mesh = Mesh { };
  681. this.flags.ownMesh = true;
  682. this.flags.mesh = true;
  683. displaySystem.AddMesh(mesh);
  684. // Count total number of vertices
  685. if(objectMesh)
  686. {
  687. flags |= objectMesh.flags;
  688. nVertices += objectMesh.nVertices;
  689. }
  690. for(child = children.first; child; child = child.next)
  691. {
  692. child.Merge(displaySystem);
  693. if(child.mesh)
  694. {
  695. nVertices += child.mesh.nVertices;
  696. flags |= child.mesh.flags;
  697. }
  698. }
  699. if(mesh.Allocate(flags, nVertices, displaySystem))
  700. {
  701. int c;
  702. int nTriangles = 0;
  703. int vertexOffset = 0;
  704. PrimitiveGroup group = null;
  705. // Merge vertices
  706. nVertices = 0;
  707. if(objectMesh)
  708. {
  709. for(c = 0; c<objectMesh.nVertices; c++)
  710. {
  711. mesh.vertices[nVertices] = objectMesh.vertices[c];
  712. if(objectMesh.normals)
  713. mesh.normals[nVertices] = objectMesh.normals[c];
  714. if(objectMesh.texCoords)
  715. mesh.texCoords[nVertices] = objectMesh.texCoords[c];
  716. nVertices++;
  717. }
  718. }
  719. for(child = children.first; child; child = child.next)
  720. {
  721. Matrix matrix, normalMatrix;
  722. matrix.Identity();
  723. matrix.Scale(child.transform.scaling.x, child.transform.scaling.y, child.transform.scaling.z);
  724. matrix.Rotate(child.transform.orientation);
  725. normalMatrix = matrix;
  726. matrix.Translate(child.transform.position.x, child.transform.position.y, child.transform.position.z);
  727. if(child.mesh)
  728. {
  729. for(c = 0; c<child.mesh.nVertices; c++)
  730. {
  731. mesh.vertices[nVertices].MultMatrix(child.mesh.vertices[c], matrix);
  732. if(child.mesh.normals)
  733. mesh.normals[nVertices].MultMatrix(child.mesh.normals[c], normalMatrix);
  734. if(child.mesh.texCoords)
  735. mesh.texCoords[nVertices] = child.mesh.texCoords[c];
  736. nVertices++;
  737. }
  738. }
  739. }
  740. // Merge Indexed Primitive Groups
  741. while(true)
  742. {
  743. int nIndices = 0;
  744. PrimitiveGroupType type;
  745. Material material = null;
  746. bool foundGroup = false;
  747. // Find first group type/material to process and determine how many indices are required
  748. if(objectMesh)
  749. {
  750. for(group = objectMesh.groups.first; group; group = group.next)
  751. {
  752. if(!foundGroup && !(group.type.vertexRange))
  753. {
  754. if(!FindMaterialAndType(mesh, group.material, group.type))
  755. {
  756. material = group.material;
  757. type = group.type;
  758. nIndices += group.nIndices;
  759. foundGroup = true;
  760. }
  761. }
  762. else if(material == group.material && type == group.type)
  763. nIndices += group.nIndices;
  764. }
  765. }
  766. for(child = children.first; child; child = child.next)
  767. {
  768. if(child.mesh)
  769. {
  770. for(group = child.mesh.groups.first; group; group = group.next)
  771. {
  772. if(!foundGroup && !(group.type.vertexRange))
  773. {
  774. if(!FindMaterialAndType(mesh, group.material ? group.material : child.material, group.type))
  775. {
  776. material = group.material ? group.material : child.material;
  777. type = group.type;
  778. nIndices += group.nIndices;
  779. foundGroup = true;
  780. }
  781. }
  782. else if(material == (group.material ? group.material : child.material) && type == group.type)
  783. nIndices += group.nIndices;
  784. }
  785. }
  786. }
  787. // Merge with all similar groups
  788. if(foundGroup)
  789. {
  790. PrimitiveGroup newGroup = mesh.AddPrimitiveGroup(type, nIndices);
  791. if(newGroup)
  792. {
  793. newGroup.material = material;
  794. nIndices = 0;
  795. vertexOffset = 0;
  796. if(objectMesh)
  797. {
  798. for(group = objectMesh.groups.first; group; group = group.next)
  799. {
  800. if(newGroup.material == group.material && newGroup.type == group.type)
  801. {
  802. int c;
  803. for(c = 0; c<group.nIndices; c++)
  804. newGroup.indices[nIndices++] = group.indices[c] + (uint16)vertexOffset;
  805. }
  806. }
  807. vertexOffset += objectMesh.nVertices;
  808. }
  809. for(child = children.first; child; child = child.next)
  810. {
  811. if(child.mesh)
  812. {
  813. for(group = child.mesh.groups.first; group; group = group.next)
  814. {
  815. if(newGroup.material == (group.material ? group.material : child.material) &&
  816. newGroup.type == group.type)
  817. {
  818. int c;
  819. for(c = 0; c<group.nIndices; c++)
  820. newGroup.indices[nIndices++] = group.indices[c] + (uint16)vertexOffset;
  821. }
  822. }
  823. vertexOffset += child.mesh.nVertices;
  824. }
  825. }
  826. mesh.UnlockPrimitiveGroup(newGroup);
  827. }
  828. }
  829. else
  830. break;
  831. }
  832. // Merge Non-Indexed Primitive Groups
  833. vertexOffset = 0;
  834. if(objectMesh)
  835. {
  836. for(group = objectMesh.groups.first; group; group = group.next)
  837. {
  838. if(group.type.vertexRange)
  839. {
  840. PrimitiveGroup newGroup = mesh.AddPrimitiveGroup(group.type, 0);
  841. if(newGroup)
  842. {
  843. newGroup.material = group.material;
  844. newGroup.nVertices = group.nVertices;
  845. newGroup.first = group.first + vertexOffset;
  846. }
  847. }
  848. }
  849. vertexOffset += objectMesh.nVertices;
  850. }
  851. for(child = children.first; child; child = child.next)
  852. {
  853. if(child.mesh)
  854. {
  855. for(group = child.mesh.groups.first; group; group = group.next)
  856. {
  857. if(group.type.vertexRange)
  858. {
  859. PrimitiveGroup newGroup = mesh.AddPrimitiveGroup(group.type, 0);
  860. if(newGroup)
  861. {
  862. newGroup.material = group.material ? group.material : child.material;
  863. newGroup.nVertices = group.nVertices;
  864. newGroup.first = group.first + vertexOffset;
  865. }
  866. }
  867. }
  868. vertexOffset += child.mesh.nVertices;
  869. }
  870. }
  871. // Merge Triangles
  872. if(objectMesh)
  873. nTriangles = objectMesh.nPrimitives;
  874. for(child = children.first; child; child = child.next)
  875. {
  876. if(child.mesh)
  877. nTriangles += child.mesh.nPrimitives;
  878. }
  879. mesh.primitives = new PrimitiveSingle[nTriangles];
  880. mesh.nPrimitives = 0;
  881. vertexOffset = 0;
  882. if(objectMesh)
  883. {
  884. for(c = 0; c<objectMesh.nPrimitives; c++)
  885. {
  886. int i;
  887. PrimitiveSingle * triangle = &mesh.primitives[mesh.nPrimitives++];
  888. mesh.AllocatePrimitive(triangle, objectMesh.primitives[c].type, objectMesh.primitives[c].nIndices);
  889. triangle->material = objectMesh.primitives[c].material;
  890. triangle->middle = objectMesh.primitives[c].middle;
  891. triangle->plane = objectMesh.primitives[c].plane;
  892. memcpy(triangle->indices, objectMesh.primitives[c].indices, objectMesh.primitives[c].nIndices * sizeof(uint16));
  893. /*
  894. *triangle = objectMesh.primitives[c];
  895. objectMesh.primitives[c].indices = null;
  896. objectMesh.primitives[c].data = null;
  897. */
  898. for(i = 0; i<triangle->nIndices; i++)
  899. triangle->indices[i] += (uint16)vertexOffset;
  900. mesh.UnlockPrimitive(triangle);
  901. }
  902. vertexOffset += objectMesh.nVertices;
  903. }
  904. for(child = children.first; child; child = child.next)
  905. {
  906. if(child.mesh)
  907. {
  908. for(c = 0; c<child.mesh.nPrimitives; c++)
  909. {
  910. int i;
  911. PrimitiveSingle * triangle = &mesh.primitives[mesh.nPrimitives++];
  912. mesh.AllocatePrimitive(triangle, child.mesh.primitives[c].type, child.mesh.primitives[c].nIndices);
  913. triangle->material = child.mesh.primitives[c].material ? child.mesh.primitives[c].material : child.material;
  914. triangle->middle = child.mesh.primitives[c].middle;
  915. triangle->plane = child.mesh.primitives[c].plane;
  916. memcpy(triangle->indices, child.mesh.primitives[c].indices, child.mesh.primitives[c].nIndices * sizeof(uint16));
  917. /*
  918. *triangle = child.mesh.primitives[c];
  919. child.mesh.primitives[c].indices = null;
  920. child.mesh.primitives[c].data = null;
  921. */
  922. for(i = 0; i<triangle->nIndices; i++)
  923. triangle->indices[i] += (uint16)vertexOffset;
  924. mesh.UnlockPrimitive(triangle);
  925. }
  926. vertexOffset += child.mesh.nVertices;
  927. }
  928. }
  929. // Free children
  930. for(child = children.first; child; child = nextChild)
  931. {
  932. nextChild = child.next;
  933. children.Remove(child);
  934. child.Free(displaySystem);
  935. }
  936. mesh.ApplyTranslucency(this);
  937. // this.flags.translucent = true;
  938. result = true;
  939. mesh.Unlock(flags);
  940. }
  941. if(freeMesh)
  942. {
  943. if(objectMesh.displaySystem)
  944. objectMesh.displaySystem.RemoveMesh(objectMesh);
  945. delete objectMesh;
  946. }
  947. SetMinMaxRadius(true);
  948. }
  949. return result;
  950. }
  951. void RotateEuler(Euler rotation, Euler min, Euler max)
  952. {
  953. Euler euler = eulerOrientation;//transform.orientation;
  954. euler.Add(euler, rotation);
  955. if(min && max)
  956. {
  957. if(min.pitch && max.pitch)
  958. euler.pitch = Min(Max(euler.pitch, min.pitch), max.pitch);
  959. if(min.yaw && max.yaw)
  960. euler.yaw = Min(Max(euler.yaw, min.yaw), max.yaw);
  961. if(min.roll && max.roll)
  962. euler.roll = Min(Max(euler.roll, min.roll), max.roll);
  963. }
  964. eulerOrientation = euler;
  965. transform.orientation = euler;
  966. UpdateTransform();
  967. }
  968. void Move(Vector3D direction)
  969. {
  970. Matrix matrix;
  971. Vector3D offset;
  972. matrix.RotationQuaternion(transform.orientation);
  973. offset.MultMatrix(direction, matrix);
  974. transform.position.Add(transform.position, offset);
  975. UpdateTransform();
  976. }
  977. void UpdateTransform(void)
  978. {
  979. SetTransformDirty();
  980. _UpdateTransform();
  981. SetMinMaxRadius(false);
  982. }
  983. void Animate(unsigned int frame)
  984. {
  985. if(this && startFrame != endFrame)
  986. {
  987. while(frame < startFrame) frame += (endFrame - startFrame + 1);
  988. while(frame > endFrame) frame -= (endFrame - startFrame + 1);
  989. this.frame = frame;
  990. _Animate(frame);
  991. _UpdateTransform();
  992. SetMinMaxRadius(false);
  993. }
  994. }
  995. void DoubleSided(bool flag)
  996. {
  997. if(this)
  998. {
  999. Object child;
  1000. mesh.DoubleSided(flag);
  1001. for(child = children.first; child; child = child.next)
  1002. child.DoubleSided(flag);
  1003. }
  1004. }
  1005. bool IntersectsGroundPolygon(int count, Pointf * pointfs)
  1006. {
  1007. bool result = false;
  1008. Pointf * p1;
  1009. Pointf * p2;
  1010. double minX = wmin.x, maxX = wmax.x;
  1011. double minY = wmin.z, maxY = wmax.z;
  1012. double delta = (maxX - minX)/2;
  1013. double x = (maxX + minX)/2, y = (maxY + minY)/2;
  1014. int c;
  1015. for(c = 0; c<count; c++)
  1016. {
  1017. double d;
  1018. p1 = &pointfs[c];
  1019. p2 = &pointfs[(c == count-1) ? 0 : (c+1)];
  1020. if( (p1->x < minX) && (p2->x < minX) )
  1021. {
  1022. if((p1->y <= y) && (p2->y > y) )
  1023. result ^= true;
  1024. else if( (p1->y > y) && (p2->y <= y) )
  1025. result ^= true;
  1026. }
  1027. else if(!((p1->x > maxX && p2->x > maxX) || (p1->y < minY && p2->y < minY) || (p1->y > maxY && p2->y > maxY)))
  1028. {
  1029. if(p1->y == p2->y)
  1030. {
  1031. d = y - p1->y;
  1032. if (d < 0) d = -d;
  1033. if (d < delta) return true;
  1034. }
  1035. else if(p1->x == p2->x)
  1036. {
  1037. d = x - p1->x;
  1038. if(d < 0) d = -d;
  1039. if(d < delta) return true;
  1040. else if(p1->x > x) ;
  1041. else if( (p1->y <= y) && (p2->y > y) )
  1042. result ^= true;
  1043. else if( (p1->y > y) && (p2->y <= y) )
  1044. result ^= true;
  1045. }
  1046. else
  1047. {
  1048. float a, b, dy, dx;
  1049. a = p2->y - p1->y;
  1050. b = p1->x - p2->x;
  1051. dy = a;
  1052. dx = -b;
  1053. d = a * x + b * y + (p2->x * p1->y) - (p2->y * p1->x);
  1054. if (a < 0) a = -a;
  1055. if (b < 0) b = -b;
  1056. if (d < 0) d = -d;
  1057. if(d < a * delta)
  1058. return true;
  1059. else if (d < b * delta)
  1060. return true;
  1061. else if( ( (p1->y <= y) && (p2->y > y) ) || ( (p1->y > y) && (p2->y <= y) ) )
  1062. {
  1063. double xdy;
  1064. xdy = (dx * (y - p1->y)) + (dy * p1->x);
  1065. if(dy < 0)
  1066. {
  1067. if(xdy > x * dy)
  1068. result ^= true;
  1069. }
  1070. else if(xdy < x * dy)
  1071. result ^= true;
  1072. }
  1073. }
  1074. }
  1075. }
  1076. return result;
  1077. }
  1078. property Transform transform { set { transform = value; } get { value = transform; } };
  1079. property Material material { set { material = value; } get { return material; } };
  1080. property Vector3Df max { get { value = max; } };
  1081. property Vector3Df min { get { value = min; } };
  1082. property Vector3Df center { get { value = center; } };
  1083. property float radius { get { return radius; } };
  1084. property Vector3D wmax { get { value = wmax; } };
  1085. property Vector3D wmin { get { value = wmin; } };
  1086. property Vector3D wcenter { get { value = wcenter; } };
  1087. property double wradius { get { return wradius; } };
  1088. property void * tag { set { tag = value; } get { return tag; } };
  1089. property int frame { set { Animate(value); } get { return frame; } };
  1090. property int startFrame { set { startFrame = value; } get { return startFrame; } };
  1091. property int endFrame { set { endFrame = value; } get { return endFrame; } };
  1092. property Mesh mesh { set { mesh = value; } get { return mesh; } };
  1093. property Camera camera { get { return camera; } }; // Fix this with inheritance? camera inherit from Object?
  1094. property Object firstChild { get { return children.first; } };
  1095. property Object next { get { return next; } };
  1096. property char * name { get { return name; } };
  1097. property Matrix matrix { get { value = matrix; } };
  1098. property Object cameraTarget { set { cameraTarget = value; } get { return cameraTarget; } };
  1099. property OldList * tracks { /* set { tracks = value; } */ get { return &tracks; } };
  1100. property ObjectFlags flags { set { flags = value; } get { return flags; } };
  1101. private:
  1102. Object()
  1103. {
  1104. children.offset = (uint)&((Object)0).prev;
  1105. transform.scaling = { 1, 1, 1 };
  1106. transform.orientation = { 1,0,0,0 };
  1107. flags.transform = true;
  1108. }
  1109. ~Object()
  1110. {
  1111. Free(null);
  1112. }
  1113. void SetTransformDirty()
  1114. {
  1115. Object child;
  1116. flags.transform = true;
  1117. for(child = children.first; child; child = child.next)
  1118. child.SetTransformDirty();
  1119. }
  1120. void _UpdateTransform()
  1121. {
  1122. if(flags.transform)
  1123. {
  1124. Object child;
  1125. Matrix matrix;
  1126. // Cameras / Spot Lights must update their target first
  1127. if(flags.camera && cameraTarget && cameraTarget.flags.transform)
  1128. cameraTarget.UpdateTransform();
  1129. else if(flags.light && light.flags.spot && light.target.flags.transform)
  1130. light.target._UpdateTransform();
  1131. if(flags.camera && cameraTarget)
  1132. {
  1133. // DeterMine angle to look at target
  1134. Vector3D position, direction;
  1135. if(flags.root || !parent)
  1136. position = transform.position;
  1137. else
  1138. position.MultMatrix(transform.position, parent.matrix);
  1139. direction.Subtract((Vector3D *)cameraTarget.matrix.m[3], position);
  1140. transform.orientation.RotationDirection(direction);
  1141. // Add the roll
  1142. transform.orientation.RotateRoll(roll);
  1143. }
  1144. if(flags.light && light.flags.spot)
  1145. {
  1146. // DeterMine angle to look at target
  1147. Vector3D position;
  1148. if(flags.root || !parent)
  1149. position = transform.position;
  1150. else
  1151. position.MultMatrix(transform.position, parent.matrix);
  1152. light.direction.Subtract((Vector3D *) light.target.matrix.m[3], position);
  1153. light.direction.Normalize(light.direction);
  1154. transform.orientation.RotationDirection(light.direction);
  1155. }
  1156. matrix.Identity();
  1157. matrix.Scale(transform.scaling.x, transform.scaling.y, transform.scaling.z);
  1158. matrix.Rotate(transform.orientation);
  1159. matrix.Translate(transform.position.x, transform.position.y, transform.position.z);
  1160. localMatrix = matrix;
  1161. // Compute transform (with ancestors)
  1162. if(flags.root || !parent)
  1163. this.matrix = matrix;
  1164. else
  1165. this.matrix.Multiply(matrix, parent.matrix);
  1166. flags.transform = false;
  1167. for(child = children.first; child; child = child.next)
  1168. {
  1169. if(child.flags.transform)
  1170. child._UpdateTransform();
  1171. }
  1172. }
  1173. }
  1174. void _Animate(unsigned int frame)
  1175. {
  1176. Object child;
  1177. FrameTrack track;
  1178. for(track = tracks.first; track; track = track.next)
  1179. {
  1180. unsigned int c;
  1181. if(track.numKeys)
  1182. {
  1183. unsigned int prev = 0, next = track.numKeys - 1;
  1184. FrameKey * prevKey = &track.keys[prev], * nextKey = &track.keys[next];
  1185. float t = 0;
  1186. for(c = 0; c<track.numKeys; c++)
  1187. {
  1188. FrameKey * key = track.keys + c;
  1189. if(key->frame <= frame) { prevKey = key; prev = c; }
  1190. if(key->frame >= frame) { nextKey = key; next = c; break; }
  1191. }
  1192. if(nextKey->frame != prevKey->frame)
  1193. t = ease((float) (frame - prevKey->frame) / (nextKey->frame - prevKey->frame), prevKey->easeFrom, nextKey->easeTo);
  1194. switch(track.type.type)
  1195. {
  1196. case position:
  1197. {
  1198. Vector3Df position;
  1199. track.Interpolate(position, prevKey->position, nextKey->position, prev, next, t);
  1200. transform.position = { (double)position.x, (double)position.y, (double)position.z };
  1201. break;
  1202. }
  1203. case scaling:
  1204. track.Interpolate(transform.scaling, prevKey->scaling, &nextKey->scaling, prev, next, t);
  1205. break;
  1206. case rotation:
  1207. track.InterpolateQuat(transform.orientation, prevKey->orientation, nextKey->orientation, prev, next, t);
  1208. break;
  1209. // Cameras
  1210. case roll:
  1211. roll = track.InterpolateFloat(prevKey->roll, nextKey->roll, prev, next, t);
  1212. break;
  1213. case fov:
  1214. {
  1215. camera.fov = track.InterpolateFloat(prevKey->fov, nextKey->fov, prev, next, t);
  1216. /*
  1217. double mm = (camera.fov - 5.05659508373109) / 1.13613250717301;
  1218. camera.fov = 1248.58921609766 * pow(mm, -0.895625414990581);
  1219. */
  1220. //camera.Setup(camera.width, camera.height, camera.origin);
  1221. break;
  1222. }
  1223. // Lights
  1224. case colorChange:
  1225. {
  1226. track.Interpolate((Vector3Df *)&light.diffuse,
  1227. (Vector3Df *)&prevKey->color, (Vector3Df *)&nextKey->color, prev, next, t);
  1228. light.specular = light.diffuse;
  1229. break;
  1230. }
  1231. case fallOff:
  1232. {
  1233. light.fallOff = track.InterpolateFloat(prevKey->fallOff, nextKey->fallOff, prev, next, t);
  1234. break;
  1235. }
  1236. case hotSpot:
  1237. {
  1238. light.hotSpot = track.InterpolateFloat(prevKey->hotSpot, nextKey->hotSpot, prev, next, t);
  1239. break;
  1240. }
  1241. }
  1242. }
  1243. }
  1244. for(child = children.first; child; child = child.next)
  1245. child._Animate(frame);
  1246. flags.transform = true;
  1247. }
  1248. // Private for now
  1249. FrustumPlacement InsideFrustum(Plane * planes)
  1250. {
  1251. FrustumPlacement result = inside;
  1252. int p;
  1253. // First test: Sphere
  1254. for(p = 0; p<6; p++)
  1255. {
  1256. Plane * plane = &planes[p];
  1257. double dot = plane->normal.DotProduct(wcenter);
  1258. double distance = dot + plane->d;
  1259. if(distance < -wradius)
  1260. {
  1261. result = outside;
  1262. break;
  1263. }
  1264. if(Abs(distance) < wradius)
  1265. result = intersecting;
  1266. }
  1267. if(result == intersecting)
  1268. {
  1269. // Second test: Bounding Box
  1270. Vector3D box[8] =
  1271. {
  1272. { wmin.x, wmin.y, wmin.z },
  1273. { wmin.x, wmin.y, wmax.z },
  1274. { wmin.x, wmax.y, wmin.z },
  1275. { wmin.x, wmax.y, wmax.z },
  1276. { wmax.x, wmin.y, wmin.z },
  1277. { wmax.x, wmin.y, wmax.z },
  1278. { wmax.x, wmax.y, wmin.z },
  1279. { wmax.x, wmax.y, wmax.z }
  1280. };
  1281. int numPlanesAllIn = 0;
  1282. for(p = 0; p < 6; p++)
  1283. {
  1284. Plane * plane = &planes[p];
  1285. int i;
  1286. int numGoodPoints = 0;
  1287. for(i = 0; i < 8; ++i)
  1288. {
  1289. double dot = plane->normal.DotProduct(box[i]);
  1290. double distance = dot + plane->d;
  1291. if(distance > -1)
  1292. numGoodPoints++;
  1293. }
  1294. if(!numGoodPoints)
  1295. {
  1296. result = outside;
  1297. break;
  1298. }
  1299. if(numGoodPoints == 8)
  1300. numPlanesAllIn++;
  1301. }
  1302. if(numPlanesAllIn == 6)
  1303. result = inside;
  1304. }
  1305. return result;
  1306. }
  1307. Object prev, next;
  1308. char * name;
  1309. Object parent;
  1310. OldList children;
  1311. ObjectFlags flags;
  1312. OldList tracks;
  1313. unsigned startFrame, endFrame;
  1314. int frame;
  1315. Vector3Df pivot;
  1316. Transform transform;
  1317. Matrix matrix;
  1318. Matrix localMatrix;
  1319. void * tag;
  1320. Vector3Df min, max, center;
  1321. Vector3D wmin, wmax, wcenter;
  1322. bool volume;
  1323. float radius;
  1324. double wradius;
  1325. ColorRGB ambient;
  1326. /*public */union
  1327. {
  1328. // Mesh
  1329. struct
  1330. {
  1331. Mesh mesh;
  1332. Material material;
  1333. };
  1334. // Light
  1335. Light light;
  1336. // Camera
  1337. struct
  1338. {
  1339. Camera camera;
  1340. Object cameraTarget;
  1341. double roll;
  1342. };
  1343. };
  1344. public property Light light
  1345. {
  1346. set
  1347. {
  1348. light = value;
  1349. }
  1350. get
  1351. {
  1352. value = light;
  1353. }
  1354. }
  1355. Euler eulerOrientation;
  1356. };