2 ===========================================================================
5 Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
7 This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
9 Doom 3 Source Code is free software: you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
14 Doom 3 Source Code is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
22 In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
24 If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
26 ===========================================================================
29 #include "../../idlib/precompiled.h"
34 idCameraDef splineList;
35 idCameraDef *g_splineList = &splineList;
42 void glLabeledPoint(idVec4 &color, idVec3 &point, float size, const char *label) {
43 qglColor3fv( color.ToFloatPtr() );
45 qglBegin( GL_POINTS );
46 qglVertex3fv( point.ToFloatPtr() );
52 qglRasterPos3fv( v.ToFloatPtr() );
53 qglCallLists( strlen(label), GL_UNSIGNED_BYTE, label );
61 void glBox(idVec4 &color, idVec3 &point, float size) {
71 qglGetFloatv(GL_CURRENT_COLOR, saveColor.ToFloatPtr());
72 qglColor3fv( color.ToFloatPtr() );
73 qglBegin(GL_LINE_LOOP);
74 qglVertex3f(mins[0],mins[1],mins[2]);
75 qglVertex3f(maxs[0],mins[1],mins[2]);
76 qglVertex3f(maxs[0],maxs[1],mins[2]);
77 qglVertex3f(mins[0],maxs[1],mins[2]);
79 qglBegin(GL_LINE_LOOP);
80 qglVertex3f(mins[0],mins[1],maxs[2]);
81 qglVertex3f(maxs[0],mins[1],maxs[2]);
82 qglVertex3f(maxs[0],maxs[1],maxs[2]);
83 qglVertex3f(mins[0],maxs[1],maxs[2]);
87 qglVertex3f(mins[0],mins[1],mins[2]);
88 qglVertex3f(mins[0],mins[1],maxs[2]);
89 qglVertex3f(mins[0],maxs[1],maxs[2]);
90 qglVertex3f(mins[0],maxs[1],mins[2]);
91 qglVertex3f(maxs[0],mins[1],mins[2]);
92 qglVertex3f(maxs[0],mins[1],maxs[2]);
93 qglVertex3f(maxs[0],maxs[1],maxs[2]);
94 qglVertex3f(maxs[0],maxs[1],mins[2]);
96 qglColor4fv(saveColor.ToFloatPtr());
106 //g_splineList->load("p:/doom/base/maps/test_base1.camera");
115 //g_splineList->addToRenderer();
123 void debugLine(idVec4 &color, float x, float y, float z, float x2, float y2, float z2) {
124 idVec3 from(x, y, z);
125 idVec3 to(x2, y2, z2);
126 session->rw->DebugLine(color, from, to);
131 =================================================================================
135 =================================================================================
140 idPointListInterface::selectPointByRay
143 int idPointListInterface::selectPointByRay(const idVec3 &origin, const idVec3 &direction, bool single) {
148 // find the point closest to the ray
153 for (i=0; i < count; i++) {
157 d = DotProduct(temp, direction);
158 VectorMA (origin, d, direction, temp);
168 selectPoint(besti, single);
176 idPointListInterface::isPointSelected
179 int idPointListInterface::isPointSelected(int index) {
180 int count = selectedPoints.Num();
181 for (int i = 0; i < count; i++) {
182 if (selectedPoints[i] == index) {
191 idPointListInterface::selectPoint
194 int idPointListInterface::selectPoint(int index, bool single) {
195 if (index >= 0 && index < numPoints()) {
199 if (isPointSelected(index) >= 0) {
200 selectedPoints.Remove(index);
203 return selectedPoints.Append(index);
210 idPointListInterface::selectAll
213 void idPointListInterface::selectAll() {
214 selectedPoints.Clear();
215 for (int i = 0; i < numPoints(); i++) {
216 selectedPoints.Append(i);
222 idPointListInterface::deselectAll
225 void idPointListInterface::deselectAll() {
226 selectedPoints.Clear();
231 idPointListInterface::getSelectedPoint
234 idVec3 *idPointListInterface::getSelectedPoint( int index ) {
235 assert(index >= 0 && index < numSelectedPoints());
236 return getPoint(selectedPoints[index]);
241 idPointListInterface::updateSelection
244 void idPointListInterface::updateSelection(const idVec3 &move) {
245 int count = selectedPoints.Num();
246 for (int i = 0; i < count; i++) {
247 *getPoint(selectedPoints[i]) += move;
253 idPointListInterface::drawSelection
256 void idPointListInterface::drawSelection() {
257 int count = selectedPoints.Num();
258 for (int i = 0; i < count; i++) {
259 glBox(colorRed, *getPoint(selectedPoints[i]), 4);
264 =================================================================================
268 =================================================================================
273 idSplineList::clearControl
276 void idSplineList::clearControl() {
277 for (int i = 0; i < controlPoints.Num(); i++) {
278 delete controlPoints[i];
280 controlPoints.Clear();
285 idSplineList::clearSpline
288 void idSplineList::clearSpline() {
289 for (int i = 0; i < splinePoints.Num(); i++) {
290 delete splinePoints[i];
292 splinePoints.Clear();
300 void idSplineList::clear() {
307 granularity = 0.025f;
308 pathColor = idVec4(1.0f, 0.5f, 0.0f, 1.0f);
309 controlColor = idVec4(0.7f, 0.0f, 1.0f, 1.0f);
310 segmentColor = idVec4(0.0f, 0.0f, 1.0f, 1.0);
311 activeColor = idVec4(1.0f, 0.0f, 0.0f, 1.0f);
316 idSplineList::setColors
319 void idSplineList::setColors(idVec4 &path, idVec4 &segment, idVec4 &control, idVec4 &active) {
321 segmentColor = segment;
322 controlColor = control;
323 activeColor = active;
328 idSplineList::validTime
331 bool idSplineList::validTime() {
335 // gcc doesn't allow static casting away from bools
336 // why? I've no idea...
337 return (bool)(splineTime.Num() > 0 && splineTime.Num() == splinePoints.Num());
342 idSplineList::addToRenderer
345 void idSplineList::addToRenderer() {
349 if (controlPoints.Num() == 0) {
353 for(i = 0; i < controlPoints.Num(); i++) {
354 VectorCopy(*controlPoints[i], mins);
355 VectorCopy(mins, maxs);
362 debugLine( colorYellow, mins[0], mins[1], mins[2], maxs[0], mins[1], mins[2]);
363 debugLine( colorYellow, maxs[0], mins[1], mins[2], maxs[0], maxs[1], mins[2]);
364 debugLine( colorYellow, maxs[0], maxs[1], mins[2], mins[0], maxs[1], mins[2]);
365 debugLine( colorYellow, mins[0], maxs[1], mins[2], mins[0], mins[1], mins[2]);
367 debugLine( colorYellow, mins[0], mins[1], maxs[2], maxs[0], mins[1], maxs[2]);
368 debugLine( colorYellow, maxs[0], mins[1], maxs[2], maxs[0], maxs[1], maxs[2]);
369 debugLine( colorYellow, maxs[0], maxs[1], maxs[2], mins[0], maxs[1], maxs[2]);
370 debugLine( colorYellow, mins[0], maxs[1], maxs[2], mins[0], mins[1], maxs[2]);
376 for(i = 3; i < controlPoints.Num(); i++) {
377 for (float tension = 0.0f; tension < 1.001f; tension += 0.1f) {
381 for (int j = 0; j < 4; j++) {
382 x += controlPoints[i - (3 - j)]->x * calcSpline(j, tension);
383 y += controlPoints[i - (3 - j)]->y * calcSpline(j, tension);
384 z += controlPoints[i - (3 - j)]->z * calcSpline(j, tension);
392 debugLine( colorWhite, step1[0], step1[1], step1[2], x, y, z);
402 idSplineList::buildSpline
405 void idSplineList::buildSpline() {
406 int start = Sys_Milliseconds();
408 for(int i = 3; i < controlPoints.Num(); i++) {
409 for (float tension = 0.0f; tension < 1.001f; tension += granularity) {
413 for (int j = 0; j < 4; j++) {
414 x += controlPoints[i - (3 - j)]->x * calcSpline(j, tension);
415 y += controlPoints[i - (3 - j)]->y * calcSpline(j, tension);
416 z += controlPoints[i - (3 - j)]->z * calcSpline(j, tension);
418 splinePoints.Append(new idVec3(x, y, z));
422 //common->Printf("Spline build took %f seconds\n", (float)(Sys_Milliseconds() - start) / 1000);
430 void idSplineList::draw(bool editMode) {
433 if (controlPoints.Num() == 0) {
442 qglColor3fv( controlColor.ToFloatPtr() );
446 for (i = 0; i < controlPoints.Num(); i++) {
447 qglVertex3fv( (*controlPoints[i]).ToFloatPtr() );
452 for(i = 0; i < controlPoints.Num(); i++) {
453 glBox(activeColor, *controlPoints[i], 4);
458 qglColor3fv( pathColor.ToFloatPtr() );
459 qglBegin(GL_LINE_STRIP);
460 int count = splinePoints.Num();
461 for (i = 0; i < count; i++) {
462 qglVertex3fv( (*splinePoints[i]).ToFloatPtr() );
467 qglColor3fv( segmentColor.ToFloatPtr() );
470 for (i = 0; i < count; i++) {
471 qglVertex3fv( (*splinePoints[i]).ToFloatPtr() );
476 //assert(activeSegment >=0 && activeSegment < count);
477 if (activeSegment >=0 && activeSegment < count) {
478 glBox(activeColor, *splinePoints[activeSegment], 6);
479 glBox(colorYellow, *splinePoints[activeSegment], 8);
487 idSplineList::totalDistance
490 float idSplineList::totalDistance() {
492 // FIXME: save dist and return
494 if (controlPoints.Num() == 0) {
504 int count = splinePoints.Num();
505 for(int i = 1; i < count; i++) {
506 temp = *splinePoints[i-1];
507 temp -= *splinePoints[i];
508 dist += temp.Length();
515 idSplineList::initPosition
518 void idSplineList::initPosition(long bt, long totalTime) {
524 if (splinePoints.Num() == 0) {
531 // calc distance to travel ( this will soon be broken into time segments )
533 splineTime.Append(bt);
534 double dist = totalDistance();
535 double distSoFar = 0.0;
537 int count = splinePoints.Num();
538 //for(int i = 2; i < count - 1; i++) {
539 for(int i = 1; i < count; i++) {
540 temp = *splinePoints[i-1];
541 temp -= *splinePoints[i];
542 distSoFar += temp.Length();
543 double percent = distSoFar / dist;
544 percent *= totalTime;
545 splineTime.Append(percent + bt);
547 assert(splineTime.Num() == splinePoints.Num());
553 idSplineList::calcSpline
556 float idSplineList::calcSpline(int step, float tension) {
558 case 0: return (pow(1 - tension, 3)) / 6;
559 case 1: return (3 * pow(tension, 3) - 6 * pow(tension, 2) + 4) / 6;
560 case 2: return (-3 * pow(tension, 3) + 3 * pow(tension, 2) + 3 * tension + 1) / 6;
561 case 3: return pow(tension, 3) / 6;
568 idSplineList::updateSelection
571 void idSplineList::updateSelection(const idVec3 &move) {
574 VectorAdd(*selected, move, *selected);
580 idSplineList::setSelectedPoint
583 void idSplineList::setSelectedPoint(idVec3 *p) {
586 for(int i = 0; i < controlPoints.Num(); i++) {
587 if ( (*p).Compare( *controlPoints[i], VECTOR_EPSILON ) ) {
588 selected = controlPoints[i];
598 idSplineList::getPosition
601 const idVec3 *idSplineList::getPosition(long t) {
602 static idVec3 interpolatedPos;
604 int count = splineTime.Num();
609 assert(splineTime.Num() == splinePoints.Num());
612 float velocity = getVelocity(t);
613 float timePassed = t - lastTime;
616 // convert to seconds
619 float distToTravel = timePassed * velocity;
621 distSoFar += distToTravel;
622 float tempDistance = 0;
625 int count = splinePoints.Num();
626 //for(int i = 2; i < count - 1; i++) {
627 for(int i = 1; i < count; i++) {
628 temp = *splinePoints[i-1];
629 temp -= *splinePoints[i];
630 tempDistance += temp.Length();
631 if (tempDistance >= distSoFar) {
637 interpolatedPos = splinePoints[i-1];
639 double timeHi = splineTime[i + 1];
640 double timeLo = splineTime[i - 1];
641 double percent = (timeHi - t) / (timeHi - timeLo);
642 idVec3 v1 = *splinePoints[i - 1];
643 idVec3 v2 = *splinePoints[i + 1];
644 v2 *= (1.0f - percent);
647 interpolatedPos = v2;
649 return &interpolatedPos;
652 while (activeSegment < count) {
653 if (splineTime[activeSegment] >= t) {
654 if (activeSegment > 0 && activeSegment < count - 1) {
655 double timeHi = splineTime[activeSegment + 1];
656 double timeLo = splineTime[activeSegment - 1];
657 //float percent = (float)(baseTime + time - t) / time;
658 double percent = (timeHi - t) / (timeHi - timeLo);
659 // pick two bounding points
660 idVec3 v1 = *splinePoints[activeSegment-1];
661 idVec3 v2 = *splinePoints[activeSegment+1];
662 v2 *= (1.0f - percent);
665 interpolatedPos = v2;
666 return &interpolatedPos;
668 return splinePoints[activeSegment];
673 return splinePoints[count-1];
682 void idSplineList::parse( idParser *src ) {
686 src->ExpectTokenString( "{" );
689 if ( !src->ExpectAnyToken( &token ) ) {
692 if ( token == "}" ) {
695 // if token is not a brace, it is a key for a key/value pair
696 if ( token == "(" ) {
697 src->UnreadToken( &token );
698 // read the control point
700 src->Parse1DMatrix( 3, point.ToFloatPtr() );
701 addPoint(point.x, point.y, point.z);
705 src->ReadTokenOnLine( &token );
706 if ( !key.Icmp( "granularity" ) ) {
707 granularity = atof(token.c_str());
709 else if ( !key.Icmp( "name" ) ) {
713 src->Error( "unknown spline list key: %s", key.c_str() );
726 void idSplineList::write( idFile *f, const char *p) {
727 f->Printf( "\t\t%s {\n", p );
729 //f->Printf( "\t\tname %s\n", name.c_str() );
730 f->Printf( "\t\t\tgranularity %f\n", granularity );
731 int count = controlPoints.Num();
732 for (int i = 0; i < count; i++) {
733 f->Printf( "\t\t\t( %f %f %f )\n", controlPoints[i]->x, controlPoints[i]->y, controlPoints[i]->z );
735 f->Printf( "\t\t}\n" );
739 =================================================================================
743 =================================================================================
751 void idCameraDef::clear() {
752 currentCameraPosition = 0;
753 cameraRunning = false;
754 lastDirection.Zero();
760 for (i = 0; i < targetPositions.Num(); i++) {
761 delete targetPositions[i];
763 for (i = 0; i < events.Num(); i++) {
766 delete cameraPosition;
767 cameraPosition = NULL;
769 targetPositions.Clear();
774 idCameraDef::startNewCamera
777 idCameraPosition *idCameraDef::startNewCamera( idCameraPosition::positionType type ) {
779 if (type == idCameraPosition::SPLINE) {
780 cameraPosition = new idSplinePosition();
781 } else if (type == idCameraPosition::INTERPOLATED) {
782 cameraPosition = new idInterpolatedPosition();
784 cameraPosition = new idFixedPosition();
786 return cameraPosition;
791 idCameraDef::addTarget
794 void idCameraDef::addTarget(const char *name, idCameraPosition::positionType type) {
795 const char *text = (name == NULL) ? va("target0%d", numTargets()+1) : name;
796 idCameraPosition *pos = newFromType(type);
799 targetPositions.Append(pos);
800 activeTarget = numTargets()-1;
801 if (activeTarget == 0) {
803 addEvent(idCameraEvent::EVENT_TARGET, name, 0);
810 idCameraDef::getActiveTarget
813 idCameraPosition *idCameraDef::getActiveTarget() {
814 if (targetPositions.Num() == 0) {
815 addTarget(NULL, idCameraPosition::FIXED);
817 return targetPositions[activeTarget];
822 idCameraDef::getActiveTarget
825 idCameraPosition *idCameraDef::getActiveTarget(int index) {
826 if (targetPositions.Num() == 0) {
827 addTarget(NULL, idCameraPosition::FIXED);
828 return targetPositions[0];
830 return targetPositions[index];
835 idCameraDef::setActiveTargetByName
838 void idCameraDef::setActiveTargetByName( const char *name ) {
839 for (int i = 0; i < targetPositions.Num(); i++) {
840 if (idStr::Icmp(name, targetPositions[i]->getName()) == 0) {
849 idCameraDef::setActiveTarget
852 void idCameraDef::setActiveTarget( int index ) {
853 assert(index >= 0 && index < targetPositions.Num());
854 activeTarget = index;
862 void idCameraDef::draw( bool editMode ) {
863 // gcc doesn't allow casting away from bools
864 // why? I've no idea...
865 if (cameraPosition) {
866 cameraPosition->draw((bool)((editMode || cameraRunning) && cameraEdit));
867 int count = targetPositions.Num();
868 for (int i = 0; i < count; i++) {
869 targetPositions[i]->draw((bool)((editMode || cameraRunning) && i == activeTarget && !cameraEdit));
876 idCameraDef::numPoints
879 int idCameraDef::numPoints() {
881 return cameraPosition->numPoints();
883 return getActiveTarget()->numPoints();
888 idCameraDef::getPoint
891 const idVec3 *idCameraDef::getPoint(int index) {
893 return cameraPosition->getPoint(index);
895 return getActiveTarget()->getPoint(index);
900 idCameraDef::stopEdit
903 void idCameraDef::stopEdit() {
906 cameraPosition->stopEdit();
908 getActiveTarget()->stopEdit();
914 idCameraDef::startEdit
917 void idCameraDef::startEdit(bool camera) {
920 cameraPosition->startEdit();
921 for (int i = 0; i < targetPositions.Num(); i++) {
922 targetPositions[i]->stopEdit();
925 getActiveTarget()->startEdit();
926 cameraPosition->stopEdit();
933 idCameraDef::getPositionObj
936 idCameraPosition *idCameraDef::getPositionObj() {
937 if (cameraPosition == NULL) {
938 cameraPosition = new idFixedPosition();
940 return cameraPosition;
945 idCameraDef::getActiveSegmentInfo
948 void idCameraDef::getActiveSegmentInfo(int segment, idVec3 &origin, idVec3 &direction, float *fov) {
950 if (!cameraSpline.validTime()) {
953 double d = (double)segment / numSegments();
954 getCameraInfo(d * totalTime * 1000, origin, direction, fov);
957 if (!cameraSpline.validTime()) {
960 origin = *cameraSpline.getSegmentPoint(segment);
965 int numTargets = getTargetSpline()->controlPoints.Num();
966 int count = cameraSpline.splineTime.Num();
967 if (numTargets == 0) {
969 if (cameraSpline.getActiveSegment() < count - 1) {
970 temp = *cameraSpline.splinePoints[cameraSpline.getActiveSegment()+1];
972 } else if (numTargets == 1) {
973 temp = *getTargetSpline()->controlPoints[0];
975 temp = *getTargetSpline()->getSegmentPoint(segment);
986 idCameraDef::getCameraInfo
989 bool idCameraDef::getCameraInfo(long time, idVec3 &origin, idVec3 &direction, float *fv) {
993 if ((time - startTime) / 1000 <= totalTime) {
995 for( i = 0; i < events.Num(); i++ ) {
996 if (time >= startTime + events[i]->getTime() && !events[i]->getTriggered()) {
997 events[i]->setTriggered(true);
998 if (events[i]->getType() == idCameraEvent::EVENT_TARGET) {
999 setActiveTargetByName(events[i]->getParam());
1000 getActiveTarget()->start(startTime + events[i]->getTime());
1001 //common->Printf("Triggered event switch to target: %s\n",events[i]->getParam());
1002 } else if (events[i]->getType() == idCameraEvent::EVENT_TRIGGER) {
1004 //FIXME: seperate game and editor spline code
1006 ent = gameLocal.FindEntity( events[i]->getParam() );
1008 ent->Signal( SIG_TRIGGER );
1009 ent->ProcessEvent( &EV_Activate, gameLocal.world );
1012 } else if (events[i]->getType() == idCameraEvent::EVENT_FOV) {
1013 memset(buff, 0, sizeof(buff));
1014 strcpy(buff, events[i]->getParam());
1015 const char *param1 = strtok(buff, " \t,\0");
1016 const char *param2 = strtok(NULL, " \t,\0");
1017 fov.reset(fov.GetFOV(time), atof(param1), time, atoi(param2));
1018 //*fv = fov = atof(events[i]->getParam());
1019 } else if (events[i]->getType() == idCameraEvent::EVENT_CAMERA) {
1020 } else if (events[i]->getType() == idCameraEvent::EVENT_STOP) {
1028 origin = *cameraPosition->getPosition(time);
1030 *fv = fov.GetFOV(time);
1032 idVec3 temp = origin;
1034 int numTargets = targetPositions.Num();
1035 if (numTargets == 0) {
1038 if (cameraSpline.getActiveSegment() < count - 1) {
1039 temp = *cameraSpline.splinePoints[cameraSpline.getActiveSegment()+1];
1040 if (temp == origin) {
1041 int index = cameraSpline.getActiveSegment() + 2;
1042 while (temp == origin && index < count - 1) {
1043 temp = *cameraSpline.splinePoints[index++];
1049 temp = *getActiveTarget()->getPosition(time);
1061 idCameraDef::waitEvent
1064 bool idCameraDef::waitEvent(int index) {
1065 //for (int i = 0; i < events.Num(); i++) {
1066 // if (events[i]->getSegment() == index && events[i]->getType() == idCameraEvent::EVENT_WAIT) {
1075 idCameraDef::buildCamera
1078 #define NUM_CCELERATION_SEGS 10
1081 void idCameraDef::buildCamera() {
1084 idList<float> waits;
1085 idList<int> targets;
1087 totalTime = baseTime;
1088 cameraPosition->setTime(totalTime * 1000);
1089 // we have a base time layout for the path and the target path
1090 // now we need to layer on any wait or speed changes
1091 for (i = 0; i < events.Num(); i++) {
1092 idCameraEvent *ev = events[i];
1093 events[i]->setTriggered(false);
1094 switch (events[i]->getType()) {
1095 case idCameraEvent::EVENT_TARGET : {
1099 case idCameraEvent::EVENT_FEATHER : {
1103 float stepGoal = cameraPosition->getBaseVelocity() / (1000 / loopTime);
1104 while (startTime <= 1000) {
1105 cameraPosition->addVelocity(startTime, loopTime, speed);
1107 if (speed > cameraPosition->getBaseVelocity()) {
1108 speed = cameraPosition->getBaseVelocity();
1110 startTime += loopTime;
1113 startTime = totalTime * 1000 - 1000;
1114 long endTime = startTime + 1000;
1115 speed = cameraPosition->getBaseVelocity();
1116 while (startTime < endTime) {
1121 cameraPosition->addVelocity(startTime, loopTime, speed);
1122 startTime += loopTime;
1127 case idCameraEvent::EVENT_WAIT : {
1128 waits.Append(atof(events[i]->getParam()));
1130 //FIXME: this is quite hacky for Wolf E3, accel and decel needs
1131 // do be parameter based etc..
1132 long startTime = events[i]->getTime() - 1000;
1133 if (startTime < 0) {
1136 float speed = cameraPosition->getBaseVelocity();
1138 float steps = speed / ((events[i]->getTime() - startTime) / loopTime);
1139 while (startTime <= events[i]->getTime() - loopTime) {
1140 cameraPosition->addVelocity(startTime, loopTime, speed);
1142 startTime += loopTime;
1144 cameraPosition->addVelocity(events[i]->getTime(), atof(events[i]->getParam()) * 1000, 0);
1146 startTime = events[i]->getTime() + atof(events[i]->getParam()) * 1000;
1147 long endTime = startTime + 1000;
1149 while (startTime <= endTime) {
1150 cameraPosition->addVelocity(startTime, loopTime, speed);
1152 startTime += loopTime;
1156 case idCameraEvent::EVENT_TARGETWAIT : {
1157 //targetWaits.Append(i);
1160 case idCameraEvent::EVENT_SPEED : {
1162 // take the average delay between up to the next five segments
1163 float adjust = atof(events[i]->getParam());
1164 int index = events[i]->getSegment();
1168 // get total amount of time over the remainder of the segment
1169 for (j = index; j < cameraSpline.numSegments() - 1; j++) {
1170 total += cameraSpline.getSegmentTime(j + 1) - cameraSpline.getSegmentTime(j);
1174 // multiply that by the adjustment
1175 double newTotal = total * adjust;
1176 // what is the difference..
1178 totalTime += newTotal / 1000;
1180 // per segment difference
1182 int additive = newTotal;
1184 // now propogate that difference out to each segment
1185 for (j = index; j < cameraSpline.numSegments(); j++) {
1186 cameraSpline.addSegmentTime(j, additive);
1187 additive += newTotal;
1196 for (i = 0; i < waits.Num(); i++) {
1197 totalTime += waits[i];
1200 // on a new target switch, we need to take time to this point ( since last target switch )
1201 // and allocate it across the active target, then reset time to this point
1203 long total = totalTime * 1000;
1204 for (i = 0; i < targets.Num(); i++) {
1206 if (i < targets.Num() - 1) {
1207 t = events[targets[i+1]]->getTime();
1209 t = total - timeSoFar;
1211 // t is how much time to use for this target
1212 setActiveTargetByName(events[targets[i]]->getParam());
1213 getActiveTarget()->setTime(t);
1220 idCameraDef::startCamera
1223 void idCameraDef::startCamera(long t) {
1224 cameraPosition->clearVelocities();
1225 cameraPosition->start(t);
1227 //for (int i = 0; i < targetPositions.Num(); i++) {
1228 // targetPositions[i]->
1231 cameraRunning = true;
1239 void idCameraDef::parse( idParser *src ) {
1242 src->ReadToken(&token);
1243 src->ExpectTokenString( "{" );
1246 src->ExpectAnyToken( &token );
1248 if ( token == "}" ) {
1251 else if ( !token.Icmp( "time" ) ) {
1252 baseTime = src->ParseFloat();
1254 else if ( !token.Icmp( "camera_fixed") ) {
1255 cameraPosition = new idFixedPosition();
1256 cameraPosition->parse( src );
1258 else if ( !token.Icmp( "camera_interpolated") ) {
1259 cameraPosition = new idInterpolatedPosition();
1260 cameraPosition->parse( src );
1262 else if ( !token.Icmp( "camera_spline") ) {
1263 cameraPosition = new idSplinePosition();
1264 cameraPosition->parse( src );
1266 else if ( !token.Icmp( "target_fixed") ) {
1267 idFixedPosition *pos = new idFixedPosition();
1269 targetPositions.Append(pos);
1271 else if ( !token.Icmp( "target_interpolated") ) {
1272 idInterpolatedPosition *pos = new idInterpolatedPosition();
1274 targetPositions.Append(pos);
1276 else if ( !token.Icmp( "target_spline") ) {
1277 idSplinePosition *pos = new idSplinePosition();
1279 targetPositions.Append(pos);
1281 else if ( !token.Icmp( "fov") ) {
1284 else if ( !token.Icmp( "event") ) {
1285 idCameraEvent *event = new idCameraEvent();
1286 event->parse( src );
1290 src->Error( "unknown camera def: %s", token.c_str() );
1295 if ( !cameraPosition ) {
1296 common->Printf( "no camera position specified\n" );
1297 // prevent a crash later on
1298 cameraPosition = new idFixedPosition();
1307 bool idCameraDef::load( const char *filename ) {
1310 src = new idParser( filename, LEXFL_NOSTRINGCONCAT | LEXFL_NOSTRINGESCAPECHARS | LEXFL_ALLOWPATHNAMES );
1311 if ( !src->IsLoaded() ) {
1312 common->Printf( "couldn't load %s\n", filename );
1330 void idCameraDef::save(const char *filename) {
1331 idFile *f = fileSystem->OpenFileWrite( filename, "fs_devpath" );
1334 f->Printf( "cameraPathDef { \n" );
1335 f->Printf( "\ttime %f\n", baseTime );
1337 cameraPosition->write( f, va("camera_%s",cameraPosition->typeStr()) );
1339 for (i = 0; i < numTargets(); i++) {
1340 targetPositions[i]->write( f, va("target_%s", targetPositions[i]->typeStr()) );
1343 for (i = 0; i < events.Num(); i++) {
1344 events[i]->write( f, "event" );
1347 fov.write( f, "fov" );
1351 fileSystem->CloseFile( f );
1356 idCameraDef::sortEvents
1359 int idCameraDef::sortEvents(const void *p1, const void *p2) {
1360 idCameraEvent *ev1 = (idCameraEvent*)(p1);
1361 idCameraEvent *ev2 = (idCameraEvent*)(p2);
1363 if (ev1->getTime() > ev2->getTime()) {
1366 if (ev1->getTime() < ev2->getTime()) {
1374 idCameraDef::addEvent
1377 void idCameraDef::addEvent(idCameraEvent *event) {
1378 events.Append(event);
1379 //events.Sort(&sortEvents);
1385 idCameraDef::addEvent
1388 void idCameraDef::addEvent(idCameraEvent::eventType t, const char *param, long time) {
1389 addEvent(new idCameraEvent(t, param, time));
1395 idCameraDef::newFromType
1398 idCameraPosition *idCameraDef::newFromType( idCameraPosition::positionType t ) {
1400 case idCameraPosition::FIXED : return new idFixedPosition();
1401 case idCameraPosition::INTERPOLATED : return new idInterpolatedPosition();
1402 case idCameraPosition::SPLINE : return new idSplinePosition();
1409 =================================================================================
1413 =================================================================================
1418 idCameraEvent::eventStr
1421 const char *idCameraEvent::eventStr[] = {
1440 idCameraEvent::parse
1443 void idCameraEvent::parse( idParser *src ) {
1447 src->ExpectTokenString( "{" );
1451 if ( !src->ExpectAnyToken( &token ) ) {
1454 if ( token == "}" ) {
1459 src->ReadTokenOnLine( &token );
1460 if ( !key.Icmp( "type" ) ) {
1461 type = static_cast<idCameraEvent::eventType>(atoi(token.c_str()));
1463 else if ( !key.Icmp( "param" ) ) {
1466 else if ( !key.Icmp( "time" ) ) {
1467 time = atoi(token.c_str());
1470 src->Error( "unknown camera event key: %s", key.c_str() );
1478 idCameraEvent::write
1481 void idCameraEvent::write( idFile *f, const char *name) {
1482 f->Printf( "\t%s {\n", name );
1483 f->Printf( "\t\ttype %d\n", static_cast<int>(type) );
1484 f->Printf( "\t\tparam \"%s\"\n", paramStr.c_str() );
1485 f->Printf( "\t\ttime %d\n", time );
1486 f->Printf( "\t}\n" );
1490 =================================================================================
1494 =================================================================================
1499 idCameraPosition::positionStr
1502 const char *idCameraPosition::positionStr[] = {
1510 idCameraPosition::positionStr
1513 void idCameraPosition::clearVelocities() {
1514 for (int i = 0; i < velocities.Num(); i++) {
1515 delete velocities[i];
1516 velocities[i] = NULL;
1523 idCameraPosition::positionStr
1526 float idCameraPosition::getVelocity( long t ) {
1527 long check = t - startTime;
1528 for ( int i = 0; i < velocities.Num(); i++ ) {
1529 if (check >= velocities[i]->startTime && check <= velocities[i]->startTime + velocities[i]->time) {
1530 return velocities[i]->speed;
1533 return baseVelocity;
1538 idCameraPosition::parseToken
1541 bool idCameraPosition::parseToken( const idStr &key, idParser *src ) {
1544 if ( !key.Icmp( "time" ) ) {
1545 time = src->ParseInt();
1548 else if ( !key.Icmp( "type" ) ) {
1549 type = static_cast<idCameraPosition::positionType> ( src->ParseInt() );
1552 else if ( !key.Icmp( "velocity" ) ) {
1553 long t = atol(token);
1554 long d = src->ParseInt();
1555 float s = src->ParseFloat();
1556 addVelocity(t, d, s);
1559 else if ( !key.Icmp( "baseVelocity" ) ) {
1560 baseVelocity = src->ParseFloat();
1563 else if ( !key.Icmp( "name" ) ) {
1564 src->ReadToken( &token );
1568 else if ( !key.Icmp( "time" ) ) {
1569 time = src->ParseInt();
1573 src->Error( "unknown camera position key: %s", key.c_str() );
1580 idCameraPosition::write
1583 void idCameraPosition::write( idFile *f, const char *p ) {
1584 f->Printf( "\t\ttime %i\n", time );
1585 f->Printf( "\t\ttype %i\n", static_cast<int>(type) );
1586 f->Printf( "\t\tname %s\n", name.c_str() );
1587 f->Printf( "\t\tbaseVelocity %f\n", baseVelocity );
1588 for (int i = 0; i < velocities.Num(); i++) {
1589 f->Printf( "\t\tvelocity %i %i %f\n", velocities[i]->startTime, velocities[i]->time, velocities[i]->speed );
1594 =================================================================================
1596 idInterpolatedPosition
1598 =================================================================================
1603 idInterpolatedPosition::getPoint
1606 idVec3 *idInterpolatedPosition::getPoint( int index ) {
1607 assert( index >= 0 && index < 2 );
1616 idInterpolatedPosition::addPoint
1619 void idInterpolatedPosition::addPoint( const float x, const float y, const float z ) {
1621 startPos.Set(x, y, z);
1624 endPos.Set(x, y, z);
1631 idInterpolatedPosition::addPoint
1634 void idInterpolatedPosition::addPoint( const idVec3 &v ) {
1647 idInterpolatedPosition::draw
1650 void idInterpolatedPosition::draw( bool editMode ) {
1651 glLabeledPoint(colorBlue, startPos, (editMode) ? 5 : 3, "Start interpolated");
1652 glLabeledPoint(colorBlue, endPos, (editMode) ? 5 : 3, "End interpolated");
1654 qglVertex3fv( startPos.ToFloatPtr() );
1655 qglVertex3fv( endPos.ToFloatPtr() );
1661 idInterpolatedPosition::start
1664 void idInterpolatedPosition::start( long t ) {
1665 idCameraPosition::start(t);
1666 lastTime = startTime;
1668 idVec3 temp = startPos;
1670 calcVelocity(temp.Length());
1675 idInterpolatedPosition::getPosition
1678 const idVec3 *idInterpolatedPosition::getPosition( long t ) {
1679 static idVec3 interpolatedPos;
1681 if (t - startTime > 6000) {
1685 float velocity = getVelocity(t);
1686 float timePassed = t - lastTime;
1689 // convert to seconds
1692 if (velocity != getBaseVelocity()) {
1696 float distToTravel = timePassed * velocity;
1698 idVec3 temp = startPos;
1700 float distance = temp.Length();
1702 distSoFar += distToTravel;
1703 float percent = (float)(distSoFar) / distance;
1705 if ( percent > 1.0f ) {
1707 } else if ( percent < 0.0f ) {
1711 // the following line does a straigt calc on percentage of time
1712 // float percent = (float)(startTime + time - t) / time;
1714 idVec3 v1 = startPos;
1716 v1 *= (1.0f - percent);
1719 interpolatedPos = v1;
1720 return &interpolatedPos;
1725 idInterpolatedPosition::parse
1728 void idInterpolatedPosition::parse( idParser *src ) {
1731 src->ExpectTokenString( "{" );
1733 if ( !src->ExpectAnyToken( &token ) ) {
1736 if ( token == "}" ) {
1740 if ( !token.Icmp( "startPos" ) ) {
1741 src->Parse1DMatrix( 3, startPos.ToFloatPtr() );
1743 else if ( !token.Icmp( "endPos" ) ) {
1744 src->Parse1DMatrix( 3, endPos.ToFloatPtr() );
1747 idCameraPosition::parseToken( token, src);
1754 idInterpolatedPosition::write
1757 void idInterpolatedPosition::write( idFile *f, const char *p ) {
1758 f->Printf( "\t%s {\n", p );
1759 idCameraPosition::write( f, p );
1760 f->Printf( "\t\tstartPos ( %f %f %f )\n", startPos.x, startPos.y, startPos.z );
1761 f->Printf( "\t\tendPos ( %f %f %f )\n", endPos.x, endPos.y, endPos.z );
1762 f->Printf( "\t}\n" );
1766 =================================================================================
1770 =================================================================================
1778 float idCameraFOV::GetFOV( long t ) {
1781 float percent = (t - startTime) / length;
1782 if ( percent < 0.0f ) {
1784 } else if ( percent > 1.0f ) {
1787 float temp = endFOV - startFOV;
1789 fov = startFOV + temp;
1799 void idCameraFOV::reset( float startfov, float endfov, int start, int len ) {
1800 startFOV = startfov;
1811 void idCameraFOV::parse( idParser *src ) {
1814 src->ExpectTokenString( "{" );
1816 if ( !src->ExpectAnyToken( &token ) ) {
1819 if ( token == "}" ) {
1823 if ( !token.Icmp( "fov" ) ) {
1824 fov = src->ParseFloat();
1826 else if ( !token.Icmp( "startFOV" ) ) {
1827 startFOV = src->ParseFloat();
1829 else if ( !token.Icmp( "endFOV" ) ) {
1830 endFOV = src->ParseFloat();
1832 else if ( !token.Icmp( "time" ) ) {
1833 time = src->ParseInt();
1836 src->Error( "unknown camera FOV key: %s", token.c_str() );
1847 void idCameraFOV::write( idFile *f, const char *p ) {
1848 f->Printf( "\t%s {\n", p );
1849 f->Printf( "\t\tfov %f\n", fov );
1850 f->Printf( "\t\tstartFOV %f\n", startFOV );
1851 f->Printf( "\t\tendFOV %f\n", endFOV );
1852 f->Printf( "\t\ttime %i\n", time );
1853 f->Printf( "\t}\n" );
1857 =================================================================================
1861 =================================================================================
1866 idFixedPosition::parse
1869 void idFixedPosition::parse( idParser *src ) {
1872 src->ExpectTokenString( "{" );
1874 if ( !src->ExpectAnyToken( &token ) ) {
1877 if ( token == "}" ) {
1881 if ( !token.Icmp( "pos" ) ) {
1882 src->Parse1DMatrix( 3, pos.ToFloatPtr() );
1885 idCameraPosition::parseToken( token, src );
1892 idFixedPosition::write
1895 void idFixedPosition::write( idFile *f, const char *p ) {
1896 f->Printf( "\t%s {\n", p );
1897 idCameraPosition::write( f, p );
1898 f->Printf( "\t\tpos ( %f %f %f )\n", pos.x, pos.y, pos.z );
1899 f->Printf( "\t}\n" );
1903 =================================================================================
1907 =================================================================================
1912 idSplinePosition::start
1915 void idSplinePosition::start( long t ) {
1916 idCameraPosition::start( t );
1917 target.initPosition(t, time);
1918 lastTime = startTime;
1920 calcVelocity(target.totalDistance());
1925 idSplinePosition::parse
1928 void idSplinePosition::parse( idParser *src ) {
1931 src->ExpectTokenString( "{" );
1933 if ( !src->ExpectAnyToken( &token ) ) {
1936 if ( token == "}" ) {
1939 if ( !token.Icmp( "target" ) ) {
1940 target.parse( src );
1943 idCameraPosition::parseToken( token, src );
1950 idSplinePosition::write
1953 void idSplinePosition::write( idFile *f, const char *p ) {
1954 f->Printf( "\t%s {\n", p );
1955 idCameraPosition::write( f, p );
1956 target.write( f, "target" );
1957 f->Printf( "\t}\n" );
1962 idSplinePosition::getPosition
1965 const idVec3 *idSplinePosition::getPosition(long t) {
1966 static idVec3 interpolatedPos;
1968 float velocity = getVelocity(t);
1969 float timePassed = t - lastTime;
1972 // convert to seconds
1975 float distToTravel = timePassed * velocity;
1977 distSoFar += distToTravel;
1978 double tempDistance = target.totalDistance();
1980 double percent = (double)(distSoFar) / tempDistance;
1982 double targetDistance = percent * tempDistance;
1985 double lastDistance1,lastDistance2;
1986 lastDistance1 = lastDistance2 = 0;
1987 //FIXME: calc distances on spline build
1989 int count = target.numSegments();
1990 //for(int i = 2; i < count - 1; i++) {
1992 for( i = 1; i < count; i++) {
1993 temp = *target.getSegmentPoint(i-1);
1994 temp -= *target.getSegmentPoint(i);
1995 tempDistance += temp.Length();
1997 lastDistance1 = tempDistance;
1999 lastDistance2 = tempDistance;
2001 if (tempDistance >= targetDistance) {
2006 if (i >= count - 1) {
2007 interpolatedPos = *target.getSegmentPoint(i-1);
2010 double timeHi = target.getSegmentTime(i + 1);
2011 double timeLo = target.getSegmentTime(i - 1);
2012 double percent = (timeHi - t) / (timeHi - timeLo);
2013 idVec3 v1 = *target.getSegmentPoint(i - 1);
2014 idVec3 v2 = *target.getSegmentPoint(i + 1);
2015 v2 *= (1.0f - percent);
2018 interpolatedPos = v2;
2020 if (lastDistance1 > lastDistance2) {
2021 double d = lastDistance2;
2022 lastDistance2 = lastDistance1;
2026 idVec3 v1 = *target.getSegmentPoint(i - 1);
2027 idVec3 v2 = *target.getSegmentPoint(i);
2028 double percent = (lastDistance2 - targetDistance) / (lastDistance2 - lastDistance1);
2029 v2 *= (1.0f - percent);
2032 interpolatedPos = v2;
2035 return &interpolatedPos;