5 public enum FrustumPlacement { outside, inside, intersecting };
7 public class ObjectFormat
9 class_data char * extension;
10 class_property char * extension
12 set { class_data(extension) = value; }
13 get { return class_data(extension); }
16 virtual bool ::Load(Object object, char * fileName, DisplaySystem displaySystem);
19 // TODO: Review these:
20 public class ObjectFlags
23 bool root:1, viewSpace:1, ownMesh:1, translucent:1, flipWindings:1, keysLoaded:1, transform:1, mesh:1, light:1, camera:1;
27 public struct Transform
30 Quaternion orientation;
34 /*static float ease(float t, float a, float b)
39 if (s == 0.0f) return t;
46 if (t < a) return (k/a)*t*t;
47 if (t < 1.0f - b) return k*(2.0f * t - a);
49 return 1.0f - (k/b)*t*t;
52 public enum FrameTrackType : uint16 { position = 1, rotation, scaling, fov, roll, colorChange, morph, hotSpot, fallOff, hide };
54 public class FrameTrackBits
60 public struct FrameKey
63 float tension, continuity, bias;
64 float easeFrom, easeTo;
68 Quaternion orientation;
78 enum SplinePart { splinePoint, splineA, splineB };
80 public class FrameTrack : struct
82 FrameTrack prev, next;
98 float GetFloat(SplinePart what, unsigned int n)
101 FrameKey *kn_1, *kn, *kn1;
108 if(what == splinePoint)
120 value *= 1.0f - kn->tension;
125 kn_1 = &keys[numKeys-2];
126 d1 = keys[numKeys-1].frame - kn_1->frame;
127 d2 = kn1->frame - kn->frame;
135 a1 = GetFloat(splineA, 1);
139 value *= 1.0f - kn->tension;
143 else if(n == numKeys-1)
151 value *= 1.0f - kn->tension;
157 d1 = kn->frame - kn_1->frame;
158 d2 = kn1->frame - keys[0].frame;
166 bn_1 = GetFloat(splineB, n-1);
170 value *= 1.0f - kn->tension;
178 d1 = kn->frame - kn_1->frame;
179 d2 = kn1->frame - kn->frame;
199 adjust = 0.5f + (1.0f - Abs(C))*(adjust - 0.5f);
202 part1 *= (1.0f + kn->bias)*(1.0f - C);
205 part2 *= (1.0f - kn->bias)*(1.0f + C);
207 value = part1 + part2;
208 value *= (1.0f - kn->tension)*adjust;
214 void GetVector(Vector3Df vector, SplinePart what, unsigned int n)
216 FrameKey *kn_1, *kn, *kn1;
217 Vector3Df *pn_1, *pn, *pn1;
223 if(what == splinePoint)
230 pn1 = &kn1->position;
234 vector.Subtract(pn1, pn);
235 vector.Scale(vector, 1.0f - kn->tension);
240 kn_1 = &keys[numKeys-2];
241 d1 = keys[numKeys-1].frame - kn_1->frame;
242 d2 = kn1->frame - kn->frame;
247 vector.Subtract(pn1, pn);
248 vector.Scale(vector, 1.5f);
250 GetVector(a1, splineA, 1);
253 vector.Subtract(vector, a1);
254 vector.Scale(vector, 1.0f - kn->tension);
258 else if(n == numKeys-1)
261 pn_1 = &kn_1->position;
265 vector.Subtract(pn, pn_1);
266 vector.Scale(vector, 1.0f - kn->tension);
272 d1 = kn->frame - kn_1->frame;
273 d2 = kn1->frame - keys[0].frame;
278 vector.Subtract(pn, pn_1);
279 vector.Scale(vector, 1.5f);
281 GetVector(&bn_1, splineB, n-1);
282 bn_1.Scale(bn_1, 0.5f);
284 vector.Subtract(vector, bn_1);
285 vector.Scale(vector, 1.0f - kn->tension);
293 d1 = kn->frame - kn_1->frame;
294 d2 = kn1->frame - kn->frame;
298 Vector3Df part1, part2;
300 pn_1 = &kn_1->position;
301 pn1 = &kn1->position;
314 adjust = 0.5f + (1.0f - Abs(C))*(adjust - 0.5f);
316 part1.Subtract(pn, pn_1);
317 part1.Scale(part1, (1.0f + kn->bias)*(1.0f - C));
319 part2.Subtract(pn1, pn);
320 part2.Scale(part2, (1.0f - kn->bias)*(1.0f + C));
322 vector.Add(part1, part2);
323 vector.Scale(vector, (1.0f - kn->tension)*adjust);
328 void GetQuaternion(Quaternion quat, SplinePart what, unsigned int n)
330 FrameKey *kn_1, *kn, *kn1;
331 Quaternion *qn_1, *qn, *qn1;
335 qn = &kn->orientation;
337 if (what == splinePoint)
345 if (!(type.loop) || numKeys <= 2)
347 qn1 = &kn1->orientation;
348 quat.Slerp(qn, qn1, (1.0f - kn->tension)*(1.0f + kn->continuity*kn->bias)/3.0f);
353 kn_1= &keys[numKeys-2];
354 d1 = keys[numKeys-1].frame - kn_1->frame;
355 d2 = kn1->frame - kn->frame;
358 else if (n == numKeys-1)
362 if (!(type.loop) || numKeys <= 2)
364 qn_1 = &kn_1->orientation;
365 quat.Slerp(qn, qn_1, (1.0f - kn->tension)*(1.0f - kn->continuity*kn->bias)/3.0f);
371 d1 = kn->frame - kn_1->frame;
372 d2 = kn1->frame - keys[0].frame;
379 d1 = kn->frame - kn_1->frame;
380 d2 = kn1->frame - kn->frame;
384 Quaternion g1, g2, tmp;
386 qn_1 = &kn_1->orientation;
387 qn1 = &kn1->orientation;
400 adjust = 0.5f + (1.0f - Abs(kn->continuity))*(adjust - 0.5f);
402 g1.Slerp(qn, qn_1,-(1.0f + kn->bias)/3.0f);
403 g2.Slerp(qn, qn1 , (1.0f - kn->bias)/3.0f);
404 tmp.Slerp(g1, g2, 0.5f + f*0.5f*kn->continuity);
405 quat.Slerp(qn, &tmp, f*(kn->tension - 1.0f)*adjust*2.0f);
410 void Interpolate(Vector3Df vector, Vector3Df prevVector, Vector3Df nextVector, int prev, int next, float t)
416 Vector3Df p1 = prevVector, p2 = nextVector;
419 GetVector(r1, splineB, prev);
420 GetVector(r2, splineA, next);
422 p1.Scale(p1, 2*t*t*t - 3*t*t + 1);
423 p2.Scale(p2,-2*t*t*t + 3*t*t);
425 r1.Scale(r1, t*t*t - 2*t*t + t);
426 r2.Scale(r2, t*t*t - t*t);
429 vector.Add(vector, r1);
430 vector.Add(vector, p2);
431 vector.Add(vector, r2);
435 void InterpolateQuat(Quaternion quat, Quaternion prevQuat, Quaternion nextQuat, int prev, int next, float t)
442 Quaternion q0, q1, q2;
444 GetQuaternion(b, splineB, prev);
445 GetQuaternion(a, splineA, next);
447 q0.Slerp(prevQuat, b, t);
449 q2.Slerp(a, nextQuat, t);
454 quat.Slerp(q0, q1, t);
458 float InterpolateFloat(float prevValue, float nextValue, int prev, int next, float t)
465 float p1 = prevValue, p2 = nextValue;
467 float r1 = GetFloat(splineB, prev);
468 float r2 = GetFloat(splineA, next);
470 p1 *= 2*t*t*t - 3*t*t + 1;
471 p2 *= -2*t*t*t + 3*t*t;
473 r1 *= t*t*t - 2*t*t + t;
476 value = p1 + r1 + p2 + r2;
482 static bool FindMaterialAndType(Mesh mesh, Material material, PrimitiveGroupType type)
484 PrimitiveGroup group;
485 for(group = mesh.groups.first; group; group = group.next)
486 if(group.material == material && group.type == type)
494 void SetMinMaxRadius(bool processMesh)
498 if(flags.mesh && mesh)
501 mesh.SetMinMaxRadius();
508 min = { MAXFLOAT, MAXFLOAT, MAXFLOAT };
509 max = { -MAXFLOAT, -MAXFLOAT, -MAXFLOAT };
512 for(child = children.first; child; child = child.next)
514 child.SetMinMaxRadius(processMesh);
518 // Child Local + Child Object Transform
519 Vector3Df points[8] =
521 { child.min.x, child.min.y, child.min.z },
522 { child.min.x, child.min.y, child.max.z },
523 { child.min.x, child.max.y, child.min.z },
524 { child.min.x, child.max.y, child.max.z },
525 { child.max.x, child.min.y, child.min.z },
526 { child.max.x, child.min.y, child.max.z },
527 { child.max.x, child.max.y, child.min.z },
528 { child.max.x, child.max.y, child.max.z }
534 point.MultMatrix(points[c], child.localMatrix);
536 if(point.x < this.min.x) this.min.x = point.x;
537 if(point.y < this.min.y) this.min.y = point.y;
538 if(point.z < this.min.z) this.min.z = point.z;
540 if(point.x > this.max.x) this.max.x = point.x;
541 if(point.y > this.max.y) this.max.y = point.y;
542 if(point.z > this.max.z) this.max.z = point.z;
550 Vector3Df points[8] =
552 { min.x, min.y, min.z },
553 { min.x, min.y, max.z },
554 { min.x, max.y, min.z },
555 { min.x, max.y, max.z },
556 { max.x, min.y, min.z },
557 { max.x, min.y, max.z },
558 { max.x, max.y, min.z },
559 { max.x, max.y, max.z }
561 Vector3Df halfExtent;
562 Vector3D halfExtentd;
565 center.Add(min, max);
566 center.Scale(center, 0.5f);
567 halfExtent.Subtract(max, min);
568 halfExtent.Scale(halfExtent, 0.5f);
569 radius = halfExtent.length;
573 Vector3D min { MAXFLOAT, MAXFLOAT, MAXFLOAT };
574 Vector3D max { -MAXFLOAT, -MAXFLOAT, -MAXFLOAT };
579 point.MultMatrixf(points[c], matrix);
581 if(point.x < min.x) min.x = point.x;
582 if(point.y < min.y) min.y = point.y;
583 if(point.z < min.z) min.z = point.z;
585 if(point.x > max.x) max.x = point.x;
586 if(point.y > max.y) max.y = point.y;
587 if(point.z > max.z) max.z = point.z;
592 wcenter.Add(wmin, wmax);
593 wcenter.Scale(wcenter, 0.5f);
595 halfExtentd.Subtract(wmax, wmin);
596 halfExtentd.Scale(halfExtentd, 0.5);
597 wradius = halfExtentd.length;
601 void Duplicate(Object model)
609 flags.ownMesh = false;
614 radius = model.radius;
616 transform = model.transform;
618 for(modelChild = model.children.first; modelChild; modelChild = modelChild.next)
620 Object child { parent = this };
621 child.Duplicate(modelChild);
622 children.AddName(child);
627 void Free(DisplaySystem displaySystem)
633 while((child = children.first))
635 children.Remove(child);
636 child.Free(displaySystem);
640 DisplaySystem meshDisplaySystem = mesh.displaySystem;
642 if(meshDisplaySystem)
643 meshDisplaySystem.RemoveMesh(mesh);
647 tracks.Free(FrameTrack::Free);
653 bool Load(char * fileName, char * type, DisplaySystem displaySystem)
655 char ext[MAX_EXTENSION];
656 subclass(ObjectFormat) format;
660 if(!type && fileName)
662 type = GetExtension(fileName, ext);
666 for(link = class(ObjectFormat).derivatives.first; link; link = link.next)
669 if(format.extension && !strcmp(format.extension, type))
672 if(!link) format = null;
676 if((format.Load(this, fileName, displaySystem)))
680 ErrorLogCode(GERR_LOAD_OBJECT_FAILED, fileName);*/
684 void FreeMesh(DisplaySystem displaySystem)
690 for(child = children.first; child; child = child.next)
691 child.FreeMesh(displaySystem);
695 Object Find(char * name)
701 if(this.name && !strcmp(this.name, name))
705 for(child = children.first; child; child = child.next)
707 Object result = child.Find(name);
716 void Initialize(void)
720 transform.scaling = { 1, 1, 1 };
721 transform.orientation = { 1,0,0,0 };
723 flags.transform = true;
728 Mesh InitializeMesh(DisplaySystem displaySystem)
736 flags.ownMesh = true;
740 FillBytes(mesh, 0, sizeof(class Mesh));
741 displaySystem.AddMesh(mesh);
749 void AddName(Object object, char * name)
751 // TODO: Watch Out For this
752 // Object object = children.FindName(name, false);
755 char * newName = CopyString(name);
756 object.name = newName;
758 children.AddName(object);
760 children.Add(object);
761 object.parent = this;
762 object.flags.transform = true;
766 // TODO: Add support to Merge Vertex Colors mesh feature
767 bool Merge(DisplaySystem displaySystem)
775 Object child, nextChild;
777 MeshFeatures flags = 0;
778 Mesh objectMesh = mesh;
779 bool freeMesh = this.flags.ownMesh;
782 this.flags.ownMesh = true;
783 this.flags.mesh = true;
784 displaySystem.AddMesh(mesh);
786 // Count total number of vertices
789 flags |= objectMesh.flags;
790 nVertices += objectMesh.nVertices;
793 for(child = children.first; child; child = child.next)
795 child.Merge(displaySystem);
798 nVertices += child.mesh.nVertices;
799 flags |= child.mesh.flags;
803 if(mesh.Allocate(flags, nVertices, displaySystem))
807 int vertexOffset = 0;
808 PrimitiveGroup group = null;
815 for(c = 0; c<objectMesh.nVertices; c++)
817 mesh.vertices[nVertices] = objectMesh.vertices[c];
819 if(objectMesh.normals)
820 mesh.normals[nVertices] = objectMesh.normals[c];
821 if(objectMesh.texCoords)
822 mesh.texCoords[nVertices] = objectMesh.texCoords[c];
828 for(child = children.first; child; child = child.next)
830 Matrix matrix, normalMatrix;
833 matrix.Scale(child.transform.scaling.x, child.transform.scaling.y, child.transform.scaling.z);
835 matrix.Rotate(child.transform.orientation);
837 normalMatrix = matrix;
839 matrix.Translate(child.transform.position.x, child.transform.position.y, child.transform.position.z);
842 for(c = 0; c<child.mesh.nVertices; c++)
844 mesh.vertices[nVertices].MultMatrix(child.mesh.vertices[c], matrix);
845 if(child.mesh.normals)
846 mesh.normals[nVertices].MultMatrix(child.mesh.normals[c], normalMatrix);
847 if(child.mesh.texCoords)
848 mesh.texCoords[nVertices] = child.mesh.texCoords[c];
854 // Merge Indexed Primitive Groups
858 PrimitiveGroupType type;
859 Material material = null;
860 bool foundGroup = false;
862 // Find first group type/material to process and determine how many indices are required
865 for(group = objectMesh.groups.first; group; group = group.next)
867 if(!foundGroup && !(group.type.vertexRange))
869 if(!FindMaterialAndType(mesh, group.material, group.type))
871 material = group.material;
873 nIndices += group.nIndices;
877 else if(material == group.material && type == group.type)
878 nIndices += group.nIndices;
882 for(child = children.first; child; child = child.next)
886 for(group = child.mesh.groups.first; group; group = group.next)
888 if(!foundGroup && !(group.type.vertexRange))
890 if(!FindMaterialAndType(mesh, group.material ? group.material : child.material, group.type))
892 material = group.material ? group.material : child.material;
894 nIndices += group.nIndices;
898 else if(material == (group.material ? group.material : child.material) && type == group.type)
899 nIndices += group.nIndices;
904 // Merge with all similar groups
907 PrimitiveGroup newGroup = mesh.AddPrimitiveGroup(type, nIndices);
910 newGroup.material = material;
917 for(group = objectMesh.groups.first; group; group = group.next)
919 if(newGroup.material == group.material && newGroup.type == group.type)
922 for(c = 0; c<group.nIndices; c++)
923 newGroup.indices[nIndices++] = group.indices[c] + (uint16)vertexOffset;
926 vertexOffset += objectMesh.nVertices;
929 for(child = children.first; child; child = child.next)
933 for(group = child.mesh.groups.first; group; group = group.next)
935 if(newGroup.material == (group.material ? group.material : child.material) &&
936 newGroup.type == group.type)
939 for(c = 0; c<group.nIndices; c++)
940 newGroup.indices[nIndices++] = group.indices[c] + (uint16)vertexOffset;
943 vertexOffset += child.mesh.nVertices;
946 mesh.UnlockPrimitiveGroup(newGroup);
953 // Merge Non-Indexed Primitive Groups
958 for(group = objectMesh.groups.first; group; group = group.next)
960 if(group.type.vertexRange)
962 PrimitiveGroup newGroup = mesh.AddPrimitiveGroup(group.type, 0);
965 newGroup.material = group.material;
966 newGroup.nVertices = group.nVertices;
967 newGroup.first = group.first + vertexOffset;
971 vertexOffset += objectMesh.nVertices;
974 for(child = children.first; child; child = child.next)
978 for(group = child.mesh.groups.first; group; group = group.next)
980 if(group.type.vertexRange)
982 PrimitiveGroup newGroup = mesh.AddPrimitiveGroup(group.type, 0);
985 newGroup.material = group.material ? group.material : child.material;
986 newGroup.nVertices = group.nVertices;
987 newGroup.first = group.first + vertexOffset;
991 vertexOffset += child.mesh.nVertices;
997 nTriangles = objectMesh.nPrimitives;
999 for(child = children.first; child; child = child.next)
1002 nTriangles += child.mesh.nPrimitives;
1004 mesh.primitives = new PrimitiveSingle[nTriangles];
1005 mesh.nPrimitives = 0;
1009 for(c = 0; c<objectMesh.nPrimitives; c++)
1012 PrimitiveSingle * triangle = &mesh.primitives[mesh.nPrimitives++];
1014 mesh.AllocatePrimitive(triangle, objectMesh.primitives[c].type, objectMesh.primitives[c].nIndices);
1015 triangle->material = objectMesh.primitives[c].material;
1016 triangle->middle = objectMesh.primitives[c].middle;
1017 triangle->plane = objectMesh.primitives[c].plane;
1019 memcpy(triangle->indices, objectMesh.primitives[c].indices, objectMesh.primitives[c].nIndices * sizeof(uint16));
1022 *triangle = objectMesh.primitives[c];
1023 objectMesh.primitives[c].indices = null;
1024 objectMesh.primitives[c].data = null;
1027 for(i = 0; i<triangle->nIndices; i++)
1028 triangle->indices[i] += (uint16)vertexOffset;
1029 mesh.UnlockPrimitive(triangle);
1031 vertexOffset += objectMesh.nVertices;
1033 for(child = children.first; child; child = child.next)
1037 for(c = 0; c<child.mesh.nPrimitives; c++)
1040 PrimitiveSingle * triangle = &mesh.primitives[mesh.nPrimitives++];
1042 mesh.AllocatePrimitive(triangle, child.mesh.primitives[c].type, child.mesh.primitives[c].nIndices);
1043 triangle->material = child.mesh.primitives[c].material ? child.mesh.primitives[c].material : child.material;
1044 triangle->middle = child.mesh.primitives[c].middle;
1045 triangle->plane = child.mesh.primitives[c].plane;
1046 memcpy(triangle->indices, child.mesh.primitives[c].indices, child.mesh.primitives[c].nIndices * sizeof(uint16));
1049 *triangle = child.mesh.primitives[c];
1050 child.mesh.primitives[c].indices = null;
1051 child.mesh.primitives[c].data = null;
1054 for(i = 0; i<triangle->nIndices; i++)
1055 triangle->indices[i] += (uint16)vertexOffset;
1056 mesh.UnlockPrimitive(triangle);
1058 vertexOffset += child.mesh.nVertices;
1063 for(child = children.first; child; child = nextChild)
1065 nextChild = child.next;
1066 children.Remove(child);
1067 child.Free(displaySystem);
1070 mesh.ApplyTranslucency(this);
1071 // this.flags.translucent = true;
1079 if(objectMesh.displaySystem)
1080 objectMesh.displaySystem.RemoveMesh(objectMesh);
1083 SetMinMaxRadius(true);
1088 void RotateEuler(Euler rotation, Euler min, Euler max)
1090 Euler euler = eulerOrientation;//transform.orientation;
1091 euler.Add(euler, rotation);
1095 if(min.pitch && max.pitch)
1096 euler.pitch = Min(Max(euler.pitch, min.pitch), max.pitch);
1097 if(min.yaw && max.yaw)
1098 euler.yaw = Min(Max(euler.yaw, min.yaw), max.yaw);
1099 if(min.roll && max.roll)
1100 euler.roll = Min(Max(euler.roll, min.roll), max.roll);
1103 eulerOrientation = euler;
1104 transform.orientation = euler;
1108 void Move(Vector3D direction)
1113 matrix.RotationQuaternion(transform.orientation);
1114 offset.MultMatrix(direction, matrix);
1115 transform.position.Add(transform.position, offset);
1119 void UpdateTransform(void)
1121 SetTransformDirty();
1123 SetMinMaxRadius(false);
1126 void Animate(unsigned int frame)
1128 if(this && startFrame != endFrame)
1130 while(frame < startFrame) frame += (endFrame - startFrame + 1);
1131 while(frame > endFrame) frame -= (endFrame - startFrame + 1);
1136 SetMinMaxRadius(false);
1140 void DoubleSided(bool flag)
1145 mesh.DoubleSided(flag);
1146 for(child = children.first; child; child = child.next)
1147 child.DoubleSided(flag);
1151 bool IntersectsGroundPolygon(int count, Pointf * pointfs)
1153 bool result = false;
1157 double minX = wmin.x, maxX = wmax.x;
1158 double minY = wmin.z, maxY = wmax.z;
1159 double delta = (maxX - minX)/2;
1160 double x = (maxX + minX)/2, y = (maxY + minY)/2;
1162 for(c = 0; c<count; c++)
1166 p2 = &pointfs[(c == count-1) ? 0 : (c+1)];
1168 if( (p1->x < minX) && (p2->x < minX) )
1170 if((p1->y <= y) && (p2->y > y) )
1172 else if( (p1->y > y) && (p2->y <= y) )
1175 else if(!((p1->x > maxX && p2->x > maxX) || (p1->y < minY && p2->y < minY) || (p1->y > maxY && p2->y > maxY)))
1181 if (d < delta) return true;
1183 else if(p1->x == p2->x)
1187 if(d < delta) return true;
1188 else if(p1->x > x) ;
1189 else if( (p1->y <= y) && (p2->y > y) )
1191 else if( (p1->y > y) && (p2->y <= y) )
1202 d = a * x + b * y + (p2->x * p1->y) - (p2->y * p1->x);
1209 else if (d < b * delta)
1211 else if( ( (p1->y <= y) && (p2->y > y) ) || ( (p1->y > y) && (p2->y <= y) ) )
1215 xdy = (dx * (y - p1->y)) + (dy * p1->x);
1221 else if(xdy < x * dy)
1230 property Transform transform { set { transform = value; } get { value = transform; } };
1231 property Material material { set { material = value; } get { return material; } };
1232 property Vector3Df max { get { value = max; } };
1233 property Vector3Df min { get { value = min; } };
1234 property Vector3Df center { get { value = center; } };
1235 property float radius { get { return radius; } };
1237 property Vector3D wmax { get { value = wmax; } };
1238 property Vector3D wmin { get { value = wmin; } };
1239 property Vector3D wcenter { get { value = wcenter; } };
1240 property double wradius { get { return wradius; } };
1242 property void * tag { set { tag = value; } get { return tag; } };
1243 property int frame { set { Animate(value); } get { return frame; } };
1244 property int startFrame { set { startFrame = value; } get { return startFrame; } };
1245 property int endFrame { set { endFrame = value; } get { return endFrame; } };
1247 property Mesh mesh { set { mesh = value; } get { return mesh; } };
1248 property Camera camera { get { return camera; } }; // Fix this with inheritance? camera inherit from Object?
1249 property Object firstChild { get { return children.first; } };
1250 property Object next { get { return next; } };
1251 property char * name { get { return name; } };
1252 property Matrix matrix { get { value = matrix; } };
1253 property Object cameraTarget { set { cameraTarget = value; } get { return cameraTarget; } };
1254 property OldList * tracks { /* set { tracks = value; } */ get { return &tracks; } };
1255 property ObjectFlags flags { set { flags = value; } get { return flags; } };
1260 children.offset = (uint)&((Object)0).prev;
1261 transform.scaling = { 1, 1, 1 };
1262 transform.orientation = { 1,0,0,0 };
1263 flags.transform = true;
1271 void SetTransformDirty()
1274 flags.transform = true;
1275 for(child = children.first; child; child = child.next)
1276 child.SetTransformDirty();
1279 void _UpdateTransform()
1286 // Cameras / Spot Lights must update their target first
1287 if(flags.camera && cameraTarget && cameraTarget.flags.transform)
1288 cameraTarget.UpdateTransform();
1289 else if(flags.light && light.flags.spot && light.target.flags.transform)
1290 light.target._UpdateTransform();
1292 if(flags.camera && cameraTarget)
1294 // DeterMine angle to look at target
1295 Vector3D position, direction;
1296 if(flags.root || !parent)
1297 position = transform.position;
1299 position.MultMatrix(transform.position, parent.matrix);
1301 direction.Subtract((Vector3D *)cameraTarget.matrix.m[3], position);
1302 transform.orientation.RotationDirection(direction);
1305 transform.orientation.RotateRoll(roll);
1308 if(flags.light && light.flags.spot)
1310 // DeterMine angle to look at target
1312 if(flags.root || !parent)
1313 position = transform.position;
1315 position.MultMatrix(transform.position, parent.matrix);
1317 light.direction.Subtract((Vector3D *) light.target.matrix.m[3], position);
1318 light.direction.Normalize(light.direction);
1319 transform.orientation.RotationDirection(light.direction);
1323 matrix.Scale(transform.scaling.x, transform.scaling.y, transform.scaling.z);
1324 matrix.Rotate(transform.orientation);
1325 matrix.Translate(transform.position.x, transform.position.y, transform.position.z);
1327 localMatrix = matrix;
1329 // Compute transform (with ancestors)
1330 if(flags.root || !parent)
1331 this.matrix = matrix;
1333 this.matrix.Multiply(matrix, parent.matrix);
1335 flags.transform = false;
1337 for(child = children.first; child; child = child.next)
1339 if(child.flags.transform)
1340 child._UpdateTransform();
1345 void _Animate(unsigned int frame)
1350 for(track = tracks.first; track; track = track.next)
1356 unsigned int prev = 0, next = track.numKeys - 1;
1357 FrameKey * prevKey = &track.keys[prev], * nextKey = &track.keys[next];
1360 for(c = 0; c<track.numKeys; c++)
1362 FrameKey * key = track.keys + c;
1363 if(key->frame <= frame) { prevKey = key; prev = c; }
1364 if(key->frame >= frame) { nextKey = key; next = c; break; }
1367 if(nextKey->frame != prevKey->frame)
1368 t = ease((float) (frame - prevKey->frame) / (nextKey->frame - prevKey->frame), prevKey->easeFrom, nextKey->easeTo);
1370 switch(track.type.type)
1375 track.Interpolate(position, prevKey->position, nextKey->position, prev, next, t);
1376 transform.position = { (double)position.x, (double)position.y, (double)position.z };
1380 track.Interpolate(transform.scaling, prevKey->scaling, &nextKey->scaling, prev, next, t);
1383 track.InterpolateQuat(transform.orientation, prevKey->orientation, nextKey->orientation, prev, next, t);
1387 roll = track.InterpolateFloat(prevKey->roll, nextKey->roll, prev, next, t);
1391 camera.fov = track.InterpolateFloat(prevKey->fov, nextKey->fov, prev, next, t);
1393 double mm = (camera.fov - 5.05659508373109) / 1.13613250717301;
1394 camera.fov = 1248.58921609766 * pow(mm, -0.895625414990581);
1396 //camera.Setup(camera.width, camera.height, camera.origin);
1402 track.Interpolate((Vector3Df *)&light.diffuse,
1403 (Vector3Df *)&prevKey->color, (Vector3Df *)&nextKey->color, prev, next, t);
1404 light.specular = light.diffuse;
1409 light.fallOff = track.InterpolateFloat(prevKey->fallOff, nextKey->fallOff, prev, next, t);
1414 light.hotSpot = track.InterpolateFloat(prevKey->hotSpot, nextKey->hotSpot, prev, next, t);
1421 for(child = children.first; child; child = child.next)
1422 child._Animate(frame);
1424 flags.transform = true;
1428 FrustumPlacement InsideFrustum(Plane * planes)
1430 FrustumPlacement result = inside;
1433 // First test: Sphere
1434 for(p = 0; p<6; p++)
1436 Plane * plane = &planes[p];
1437 double dot = plane->normal.DotProduct(wcenter);
1438 double distance = dot + plane->d;
1439 if(distance < -wradius)
1444 if(Abs(distance) < wradius)
1445 result = intersecting;
1448 if(result == intersecting)
1450 // Second test: Bounding Box
1453 { wmin.x, wmin.y, wmin.z },
1454 { wmin.x, wmin.y, wmax.z },
1455 { wmin.x, wmax.y, wmin.z },
1456 { wmin.x, wmax.y, wmax.z },
1457 { wmax.x, wmin.y, wmin.z },
1458 { wmax.x, wmin.y, wmax.z },
1459 { wmax.x, wmax.y, wmin.z },
1460 { wmax.x, wmax.y, wmax.z }
1462 int numPlanesAllIn = 0;
1463 for(p = 0; p < 6; p++)
1465 Plane * plane = &planes[p];
1467 int numGoodPoints = 0;
1468 for(i = 0; i < 8; ++i)
1470 double dot = plane->normal.DotProduct(box[i]);
1471 double distance = dot + plane->d;
1480 if(numGoodPoints == 8)
1483 if(numPlanesAllIn == 6)
1497 unsigned startFrame, endFrame;
1500 Transform transform;
1504 Vector3Df min, max, center;
1505 Vector3D wmin, wmax, wcenter;
1528 Object cameraTarget;
1533 public property Light light
1545 Euler eulerOrientation;