6 #ifndef CAMERA_PLUGIN
\r
8 #include "misc_def.h"
\r
9 #include "igl_to_qgl.h"
\r
13 #include "util_list.h"
\r
14 #include "util_str.h"
\r
15 #include "math_vector.h"
\r
17 typedef int fileHandle_t;
\r
19 extern void glBox(idVec3 &color, idVec3 &point, float size);
\r
20 extern void glLabeledPoint(idVec3 &color, idVec3 &point, float size, const char *label);
\r
22 static idVec4 blue(0, 0, 1, 1);
\r
23 static idVec4 red(1, 0, 0, 1);
\r
25 class idPointListInterface {
\r
27 idPointListInterface() {
\r
28 selectedPoints.Clear();
\r
30 virtual ~idPointListInterface() {};
\r
32 virtual int numPoints() {
\r
36 virtual void addPoint(const float x, const float y, const float z) {}
\r
37 virtual void addPoint(const idVec3 &v) {}
\r
38 virtual void removePoint(int index) {}
\r
39 virtual idVec3 *getPoint(int index) { return NULL; }
\r
41 int selectPointByRay(float ox, float oy, float oz, float dx, float dy, float dz, bool single) {
\r
42 idVec3 origin(ox, oy, oz);
\r
43 idVec3 dir(dx, dy, dz);
\r
44 return selectPointByRay(origin, dir, single);
\r
47 int selectPointByRay(const idVec3 origin, const idVec3 direction, bool single) {
\r
48 int i, besti, count;
\r
52 // find the point closest to the ray
\r
55 count = numPoints();
\r
57 for (i=0; i < count; i++) {
\r
58 temp = *getPoint(i);
\r
61 d = DotProduct(temp, direction);
\r
62 __VectorMA (origin, d, direction, temp);
\r
72 selectPoint(besti, single);
\r
78 int isPointSelected(int index) {
\r
79 int count = selectedPoints.Num();
\r
80 for (int i = 0; i < count; i++) {
\r
81 if (selectedPoints[i] == index) {
\r
88 int selectPoint(int index, bool single) {
\r
89 if (index >= 0 && index < numPoints()) {
\r
93 if (isPointSelected(index) >= 0) {
\r
94 selectedPoints.Remove(index);
\r
97 return selectedPoints.Append(index);
\r
103 selectedPoints.Clear();
\r
104 for (int i = 0; i < numPoints(); i++) {
\r
105 selectedPoints.Append(i);
\r
109 void deselectAll() {
\r
110 selectedPoints.Clear();
\r
113 int numSelectedPoints();
\r
115 idVec3 *getSelectedPoint(int index) {
\r
116 assert(index >= 0 && index < numSelectedPoints());
\r
117 return getPoint(selectedPoints[index]);
\r
120 virtual void updateSelection(float x, float y, float z) {
\r
121 idVec3 move(x, y, z);
\r
122 updateSelection(move);
\r
125 virtual void updateSelection(const idVec3 &move) {
\r
126 int count = selectedPoints.Num();
\r
127 for (int i = 0; i < count; i++) {
\r
128 *getPoint(selectedPoints[i]) += move;
\r
132 void drawSelection() {
\r
133 int count = selectedPoints.Num();
\r
134 for (int i = 0; i < count; i++) {
\r
135 glBox(red, *getPoint(selectedPoints[i]), 4);
\r
140 idList<int> selectedPoints;
\r
145 class idSplineList {
\r
153 idSplineList(const char *p) {
\r
162 void clearControl() {
\r
163 for (int i = 0; i < controlPoints.Num(); i++) {
\r
164 delete controlPoints[i];
\r
166 controlPoints.Clear();
\r
169 void clearSpline() {
\r
170 for (int i = 0; i < splinePoints.Num(); i++) {
\r
171 delete splinePoints[i];
\r
173 splinePoints.Clear();
\r
176 void parse(const char *(*text));
\r
177 void write(fileHandle_t file, const char *name);
\r
182 splineTime.Clear();
\r
186 granularity = 0.025f;
\r
187 pathColor.set(1.0f, 0.5f, 0.0f);
\r
188 controlColor.set(0.7f, 0.0f, 1.0f);
\r
189 segmentColor.set(0.0f, 0.0f, 1.0f);
\r
190 activeColor.set(1.0f, 0.0f, 0.0f);
\r
193 void initPosition(long startTime, long totalTime);
\r
194 const idVec3 *getPosition(long time);
\r
197 void draw(bool editMode);
\r
198 void addToRenderer();
\r
200 void setSelectedPoint(idVec3 *p);
\r
201 idVec3 *getSelectedPoint() {
\r
205 void addPoint(const idVec3 &v) {
\r
206 controlPoints.Append(new idVec3(v));
\r
210 void addPoint(float x, float y, float z) {
\r
211 controlPoints.Append(new idVec3(x, y, z));
\r
215 void updateSelection(const idVec3 &move);
\r
225 void buildSpline();
\r
227 void setGranularity(float f) {
\r
231 float getGranularity() {
\r
232 return granularity;
\r
236 return controlPoints.Num();
\r
239 idVec3 *getPoint(int index) {
\r
240 assert(index >= 0 && index < controlPoints.Num());
\r
241 return controlPoints[index];
\r
244 idVec3 *getSegmentPoint(int index) {
\r
245 assert(index >= 0 && index < splinePoints.Num());
\r
246 return splinePoints[index];
\r
250 void setSegmentTime(int index, int time) {
\r
251 assert(index >= 0 && index < splinePoints.Num());
\r
252 splineTime[index] = time;
\r
255 int getSegmentTime(int index) {
\r
256 assert(index >= 0 && index < splinePoints.Num());
\r
257 return (int)splineTime[index];
\r
259 void addSegmentTime(int index, int time) {
\r
260 assert(index >= 0 && index < splinePoints.Num());
\r
261 splineTime[index] += time;
\r
264 float totalDistance();
\r
266 static idVec3 zero;
\r
268 int getActiveSegment() {
\r
269 return activeSegment;
\r
272 void setActiveSegment(int i) {
\r
273 //assert(i >= 0 && (splinePoints.Num() > 0 && i < splinePoints.Num()));
\r
277 int numSegments() {
\r
278 return splinePoints.Num();
\r
281 void setColors(idVec3 &path, idVec3 &segment, idVec3 &control, idVec3 &active) {
\r
283 segmentColor = segment;
\r
284 controlColor = control;
\r
285 activeColor = active;
\r
288 const char *getName() {
\r
289 return name.c_str();
\r
292 void setName(const char *p) {
\r
300 // gcc doesn't allow static casting away from bools
\r
301 // why? I've no idea...
\r
302 return (bool)(splineTime.Num() > 0 && splineTime.Num() == splinePoints.Num());
\r
305 void setTime(long t) {
\r
309 void setBaseTime(long t) {
\r
315 float calcSpline(int step, float tension);
\r
316 idList<idVec3*> controlPoints;
\r
317 idList<idVec3*> splinePoints;
\r
318 idList<double> splineTime;
\r
320 idVec3 pathColor, segmentColor, controlColor, activeColor;
\r
327 friend class idCamera;
\r
330 // time in milliseconds
\r
331 // velocity where 1.0 equal rough walking speed
\r
332 struct idVelocity {
\r
333 idVelocity(long start, long duration, float s) {
\r
343 // can either be a look at or origin position for a camera
\r
345 class idCameraPosition : public idPointListInterface {
\r
348 virtual void clearVelocities() {
\r
349 for (int i = 0; i < velocities.Num(); i++) {
\r
350 delete velocities[i];
\r
351 velocities[i] = NULL;
\r
353 velocities.Clear();
\r
356 virtual void clear() {
\r
361 idCameraPosition(const char *p) {
\r
365 idCameraPosition() {
\r
370 idCameraPosition(long t) {
\r
374 virtual ~idCameraPosition() {
\r
379 // this can be done with RTTI syntax but i like the derived classes setting a type
\r
380 // makes serialization a bit easier to see
\r
382 enum positionType {
\r
390 virtual void start(long t) {
\r
398 virtual void setTime(long t) {
\r
402 float getBaseVelocity() {
\r
403 return baseVelocity;
\r
406 float getVelocity(long t) {
\r
407 long check = t - startTime;
\r
408 for (int i = 0; i < velocities.Num(); i++) {
\r
409 if (check >= velocities[i]->startTime && check <= velocities[i]->startTime + velocities[i]->time) {
\r
410 return velocities[i]->speed;
\r
413 return baseVelocity;
\r
416 void addVelocity(long start, long duration, float speed) {
\r
417 velocities.Append(new idVelocity(start, duration, speed));
\r
420 virtual const idVec3 *getPosition(long t) {
\r
425 virtual void draw(bool editMode) {};
\r
427 virtual void parse(const char *(*text)) {};
\r
428 virtual void write(fileHandle_t file, const char *name);
\r
429 virtual bool parseToken(const char *key, const char *(*text));
\r
431 const char *getName() {
\r
432 return name.c_str();
\r
435 void setName(const char *p) {
\r
439 virtual void startEdit() {
\r
443 virtual void stopEdit() {
\r
447 virtual void draw() {};
\r
449 const char *typeStr() {
\r
450 return positionStr[static_cast<int>(type)];
\r
453 void calcVelocity(float distance) {
\r
454 float secs = (float)time / 1000;
\r
455 baseVelocity = distance / secs;
\r
459 static const char* positionStr[POSITION_COUNT];
\r
462 idCameraPosition::positionType type;
\r
465 idList<idVelocity*> velocities;
\r
466 float baseVelocity;
\r
469 class idFixedPosition : public idCameraPosition {
\r
474 type = idCameraPosition::FIXED;
\r
477 idFixedPosition() : idCameraPosition() {
\r
481 idFixedPosition(idVec3 p) : idCameraPosition() {
\r
486 virtual void addPoint(const idVec3 &v) {
\r
490 virtual void addPoint(const float x, const float y, const float z) {
\r
495 ~idFixedPosition() {
\r
498 virtual const idVec3 *getPosition(long t) {
\r
502 void parse(const char *(*text));
\r
503 void write(fileHandle_t file, const char *name);
\r
505 virtual int numPoints() {
\r
509 virtual idVec3 *getPoint(int index) {
\r
516 virtual void draw(bool editMode) {
\r
517 glLabeledPoint(blue, pos, (editMode) ? 5 : 3, "Fixed point");
\r
524 class idInterpolatedPosition : public idCameraPosition {
\r
528 type = idCameraPosition::INTERPOLATED;
\r
534 idInterpolatedPosition() : idCameraPosition() {
\r
538 idInterpolatedPosition(idVec3 start, idVec3 end, long time) : idCameraPosition(time) {
\r
544 ~idInterpolatedPosition() {
\r
547 virtual const idVec3 *getPosition(long t);
\r
549 void parse(const char *(*text));
\r
550 void write(fileHandle_t file, const char *name);
\r
552 virtual int numPoints() {
\r
556 virtual idVec3 *getPoint(int index) {
\r
557 assert(index >= 0 && index < 2);
\r
564 virtual void addPoint(const float x, const float y, const float z) {
\r
566 startPos.set(x, y, z);
\r
569 endPos.set(x, y, z);
\r
574 virtual void addPoint(const idVec3 &v) {
\r
584 virtual void draw(bool editMode) {
\r
585 glLabeledPoint(blue, startPos, (editMode) ? 5 : 3, "Start interpolated");
\r
586 glLabeledPoint(blue, endPos, (editMode) ? 5 : 3, "End interpolated");
\r
587 qglBegin(GL_LINES);
\r
588 qglVertex3fv(startPos);
\r
589 qglVertex3fv(endPos);
\r
593 virtual void start(long t) {
\r
594 idCameraPosition::start(t);
\r
595 lastTime = startTime;
\r
597 idVec3 temp = startPos;
\r
599 calcVelocity(temp.Length());
\r
610 class idSplinePosition : public idCameraPosition {
\r
614 type = idCameraPosition::SPLINE;
\r
617 idSplinePosition() : idCameraPosition() {
\r
621 idSplinePosition(long time) : idCameraPosition(time) {
\r
625 ~idSplinePosition() {
\r
628 virtual void start(long t) {
\r
629 idCameraPosition::start(t);
\r
630 target.initPosition(t, time);
\r
631 lastTime = startTime;
\r
633 calcVelocity(target.totalDistance());
\r
636 //virtual const idVec3 *getPosition(long t) {
\r
637 // return target.getPosition(t);
\r
639 virtual const idVec3 *getPosition(long t);
\r
642 //virtual const idVec3 *getPosition(long t) const {
\r
644 void addControlPoint(idVec3 &v) {
\r
645 target.addPoint(v);
\r
648 void parse(const char *(*text));
\r
649 void write(fileHandle_t file, const char *name);
\r
651 virtual int numPoints() {
\r
652 return target.numPoints();
\r
655 virtual idVec3 *getPoint(int index) {
\r
656 return target.getPoint(index);
\r
659 virtual void addPoint(const idVec3 &v) {
\r
660 target.addPoint(v);
\r
663 virtual void addPoint(const float x, const float y, const float z) {
\r
664 target.addPoint(x, y, z);
\r
667 virtual void draw(bool editMode) {
\r
668 target.draw(editMode);
\r
671 virtual void updateSelection(const idVec3 &move) {
\r
672 idCameraPosition::updateSelection(move);
\r
673 target.buildSpline();
\r
677 idSplineList target;
\r
682 class idCameraFOV {
\r
691 idCameraFOV(int v) {
\r
697 idCameraFOV(int s, int e, long t) {
\r
706 void setFOV(float f) {
\r
710 float getFOV(long t) {
\r
712 float percent = (t - startTime) / length;
\r
713 if (percent < 0.0) {
\r
715 } else if (percent > 1.0) {
\r
718 float temp = endFOV - startFOV;
\r
720 fov = startFOV + temp;
\r
722 if (percent == 1.0) {
\r
729 void start(long t) {
\r
733 void reset(float startfov, float endfov, int start, float len) {
\r
734 startFOV = startfov;
\r
737 length = len * 1000;
\r
740 void parse(const char *(*text));
\r
741 void write(fileHandle_t file, const char *name);
\r
755 class idCameraEvent {
\r
756 public: // parameters
\r
760 EVENT_TARGETWAIT, //
\r
762 EVENT_TARGET, // char(name)
\r
763 EVENT_SNAPTARGET, //
\r
764 EVENT_FOV, // int(time), int(targetfov)
\r
769 EVENT_FADEOUT, // int(time)
\r
770 EVENT_FADEIN, // int(time)
\r
775 static const char* eventStr[EVENT_COUNT];
\r
783 idCameraEvent(eventType t, const char *param, long n) {
\r
789 ~idCameraEvent() {};
\r
791 eventType getType() {
\r
795 const char *typeStr() {
\r
796 return eventStr[static_cast<int>(type)];
\r
799 const char *getParam() {
\r
800 return paramStr.c_str();
\r
807 void setTime(long n) {
\r
811 void parse(const char *(*text));
\r
812 void write(fileHandle_t file, const char *name);
\r
814 void setTriggered(bool b) {
\r
818 bool getTriggered() {
\r
830 class idCameraDef {
\r
834 currentCameraPosition = 0;
\r
835 cameraRunning = false;
\r
836 lastDirection.Zero();
\r
842 for (i = 0; i < targetPositions.Num(); i++) {
\r
843 delete targetPositions[i];
\r
845 for (i = 0; i < events.Num(); i++) {
\r
848 delete cameraPosition;
\r
849 cameraPosition = NULL;
\r
851 targetPositions.Clear();
\r
854 idCameraPosition *startNewCamera(idCameraPosition::positionType type) {
\r
856 if (type == idCameraPosition::SPLINE) {
\r
857 cameraPosition = new idSplinePosition();
\r
858 } else if (type == idCameraPosition::INTERPOLATED) {
\r
859 cameraPosition = new idInterpolatedPosition();
\r
861 cameraPosition = new idFixedPosition();
\r
863 return cameraPosition;
\r
867 cameraPosition = NULL;
\r
875 void addEvent(idCameraEvent::eventType t, const char *param, long time);
\r
877 void addEvent(idCameraEvent *event);
\r
879 void removeEvent( int index);
\r
881 static int sortEvents(const void *p1, const void *p2);
\r
884 return events.Num();
\r
887 idCameraEvent *getEvent(int index) {
\r
888 assert(index >= 0 && index < events.Num());
\r
889 return events[index];
\r
892 void parse(const char *(*text));
\r
893 bool load(const char *filename);
\r
894 void save(const char *filename);
\r
896 void buildCamera();
\r
898 //idSplineList *getcameraPosition() {
\r
899 // return &cameraPosition;
\r
902 static idCameraPosition *newFromType(idCameraPosition::positionType t) {
\r
904 case idCameraPosition::FIXED : return new idFixedPosition();
\r
905 case idCameraPosition::INTERPOLATED : return new idInterpolatedPosition();
\r
906 case idCameraPosition::SPLINE : return new idSplinePosition();
\r
913 void addTarget(const char *name, idCameraPosition::positionType type);
\r
915 idCameraPosition *getActiveTarget() {
\r
916 if (targetPositions.Num() == 0) {
\r
917 addTarget(NULL, idCameraPosition::FIXED);
\r
919 return targetPositions[activeTarget];
\r
922 idCameraPosition *getActiveTarget(int index) {
\r
923 if (targetPositions.Num() == 0) {
\r
924 addTarget(NULL, idCameraPosition::FIXED);
\r
925 return targetPositions[0];
\r
927 return targetPositions[index];
\r
931 return targetPositions.Num();
\r
935 void setActiveTargetByName(const char *name) {
\r
936 for (int i = 0; i < targetPositions.Num(); i++) {
\r
937 if (Q_stricmp(name, targetPositions[i]->getName()) == 0) {
\r
938 setActiveTarget(i);
\r
944 void setActiveTarget(int index) {
\r
945 assert(index >= 0 && index < targetPositions.Num());
\r
946 activeTarget = index;
\r
949 void setRunning(bool b) {
\r
953 void setBaseTime(float f) {
\r
957 float getBaseTime() {
\r
961 float getTotalTime() {
\r
965 void startCamera(long t);
\r
966 void stopCamera() {
\r
967 cameraRunning = true;
\r
969 void getActiveSegmentInfo(int segment, idVec3 &origin, idVec3 &direction, float *fv);
\r
971 bool getCameraInfo(long time, idVec3 &origin, idVec3 &direction, float *fv);
\r
972 bool getCameraInfo(long time, float *origin, float *direction, float *fv) {
\r
974 org[0] = origin[0];
\r
975 org[1] = origin[1];
\r
976 org[2] = origin[2];
\r
977 dir[0] = direction[0];
\r
978 dir[1] = direction[1];
\r
979 dir[2] = direction[2];
\r
980 bool b = getCameraInfo(time, org, dir, fv);
\r
981 origin[0] = org[0];
\r
982 origin[1] = org[1];
\r
983 origin[2] = org[2];
\r
984 direction[0] = dir[0];
\r
985 direction[1] = dir[1];
\r
986 direction[2] = dir[2];
\r
990 void draw(bool editMode) {
\r
991 // gcc doesn't allow casting away from bools
\r
992 // why? I've no idea...
\r
993 if (cameraPosition) {
\r
994 cameraPosition->draw((bool)((editMode || cameraRunning) && cameraEdit));
\r
995 int count = targetPositions.Num();
\r
996 for (int i = 0; i < count; i++) {
\r
997 targetPositions[i]->draw((bool)((editMode || cameraRunning) && i == activeTarget && !cameraEdit));
\r
1003 int numSegments() {
\r
1005 return cameraPosition.numSegments();
\r
1007 return getTargetSpline()->numSegments();
\r
1010 int getActiveSegment() {
\r
1012 return cameraPosition.getActiveSegment();
\r
1014 return getTargetSpline()->getActiveSegment();
\r
1017 void setActiveSegment(int i) {
\r
1019 cameraPosition.setActiveSegment(i);
\r
1021 getTargetSpline()->setActiveSegment(i);
\r
1027 return cameraPosition->numPoints();
\r
1029 return getActiveTarget()->numPoints();
\r
1032 const idVec3 *getPoint(int index) {
\r
1034 return cameraPosition->getPoint(index);
\r
1036 return getActiveTarget()->getPoint(index);
\r
1042 cameraPosition->stopEdit();
\r
1044 getActiveTarget()->stopEdit();
\r
1048 void startEdit(bool camera) {
\r
1049 cameraEdit = camera;
\r
1051 cameraPosition->startEdit();
\r
1052 for (int i = 0; i < targetPositions.Num(); i++) {
\r
1053 targetPositions[i]->stopEdit();
\r
1056 getActiveTarget()->startEdit();
\r
1057 cameraPosition->stopEdit();
\r
1062 bool waitEvent(int index);
\r
1064 const char *getName() {
\r
1065 return name.c_str();
\r
1068 void setName(const char *p) {
\r
1072 idCameraPosition *getPositionObj() {
\r
1073 if (cameraPosition == NULL) {
\r
1074 cameraPosition = new idFixedPosition();
\r
1076 return cameraPosition;
\r
1081 int currentCameraPosition;
\r
1082 idVec3 lastDirection;
\r
1083 bool cameraRunning;
\r
1084 idCameraPosition *cameraPosition;
\r
1085 idList<idCameraPosition*> targetPositions;
\r
1086 idList<idCameraEvent*> events;
\r
1097 extern bool g_splineMode;
\r
1099 extern idCameraDef *g_splineList;
\r