Main Page | Class Hierarchy | Alphabetical List | Data Structures | Directories | File List | Data Fields | Globals

splines.cpp

Go to the documentation of this file.
00001 /*
00002 ===========================================================================
00003 Copyright (C) 1999-2005 Id Software, Inc.
00004 
00005 This file is part of Quake III Arena source code.
00006 
00007 Quake III Arena source code is free software; you can redistribute it
00008 and/or modify it under the terms of the GNU General Public License as
00009 published by the Free Software Foundation; either version 2 of the License,
00010 or (at your option) any later version.
00011 
00012 Quake III Arena source code is distributed in the hope that it will be
00013 useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
00014 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015 GNU General Public License for more details.
00016 
00017 You should have received a copy of the GNU General Public License
00018 along with Foobar; if not, write to the Free Software
00019 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
00020 ===========================================================================
00021 */
00022 
00023 //#include "stdafx.h"
00024 //#include "qe3.h"
00025 
00026 #include "q_shared.h"
00027 #include "splines.h"
00028 
00029 extern "C" {
00030 int FS_Write( const void *buffer, int len, fileHandle_t h );
00031 int FS_ReadFile( const char *qpath, void **buffer );
00032 void FS_FreeFile( void *buffer );
00033 fileHandle_t FS_FOpenFileWrite( const char *filename );
00034 void FS_FCloseFile( fileHandle_t f );
00035 }
00036 
00037 float Q_fabs( float f ) {
00038     int tmp = * ( int * ) &f;
00039     tmp &= 0x7FFFFFFF;
00040     return * ( float * ) &tmp;
00041 }
00042 
00043 
00044 //#include "../shared/windings.h"
00045 //#include "../qcommon/qcommon.h"
00046 //#include "../sys/sys_public.h"
00047 //#include "../game/game_entity.h"
00048 
00049 idCameraDef splineList;
00050 idCameraDef *g_splineList = &splineList;
00051 
00052 idVec3_t idSplineList::zero(0,0,0);
00053 
00054 void glLabeledPoint(idVec3_t &color, idVec3_t &point, float size, const char *label) {
00055     qglColor3fv(color);
00056     qglPointSize(size);
00057     qglBegin(GL_POINTS);
00058     qglVertex3fv(point);
00059     qglEnd();
00060     idVec3_t v = point;
00061     v.x += 1;
00062     v.y += 1;
00063     v.z += 1;
00064     qglRasterPos3fv (v);
00065     qglCallLists (strlen(label), GL_UNSIGNED_BYTE, label);
00066 }
00067 
00068 
00069 void glBox(idVec3_t &color, idVec3_t &point, float size) {
00070     idVec3_t mins(point);
00071     idVec3_t maxs(point);
00072     mins[0] -= size;
00073     mins[1] += size;
00074     mins[2] -= size;
00075     maxs[0] += size;
00076     maxs[1] -= size;
00077     maxs[2] += size;
00078     qglColor3fv(color);
00079     qglBegin(GL_LINE_LOOP);
00080     qglVertex3f(mins[0],mins[1],mins[2]);
00081     qglVertex3f(maxs[0],mins[1],mins[2]);
00082     qglVertex3f(maxs[0],maxs[1],mins[2]);
00083     qglVertex3f(mins[0],maxs[1],mins[2]);
00084     qglEnd();
00085     qglBegin(GL_LINE_LOOP);
00086     qglVertex3f(mins[0],mins[1],maxs[2]);
00087     qglVertex3f(maxs[0],mins[1],maxs[2]);
00088     qglVertex3f(maxs[0],maxs[1],maxs[2]);
00089     qglVertex3f(mins[0],maxs[1],maxs[2]);
00090     qglEnd();
00091 
00092     qglBegin(GL_LINES);
00093     qglVertex3f(mins[0],mins[1],mins[2]);
00094     qglVertex3f(mins[0],mins[1],maxs[2]);
00095     qglVertex3f(mins[0],maxs[1],maxs[2]);
00096     qglVertex3f(mins[0],maxs[1],mins[2]);
00097     qglVertex3f(maxs[0],mins[1],mins[2]);
00098     qglVertex3f(maxs[0],mins[1],maxs[2]);
00099     qglVertex3f(maxs[0],maxs[1],maxs[2]);
00100     qglVertex3f(maxs[0],maxs[1],mins[2]);
00101     qglEnd();
00102 
00103 }
00104 
00105 void splineTest() {
00106     //g_splineList->load("p:/doom/base/maps/test_base1.camera");
00107 }
00108 
00109 void splineDraw() {
00110     //g_splineList->addToRenderer();
00111 }
00112 
00113 
00114 //extern void D_DebugLine( const idVec3_t &color, const idVec3_t &start, const idVec3_t &end );
00115 
00116 void debugLine(idVec3_t &color, float x, float y, float z, float x2, float y2, float z2) {
00117     idVec3_t from(x, y, z);
00118     idVec3_t to(x2, y2, z2);
00119     //D_DebugLine(color, from, to);
00120 }
00121 
00122 void idSplineList::addToRenderer() {
00123 
00124     if (controlPoints.Num() == 0) {
00125         return;
00126     }
00127 
00128     idVec3_t mins, maxs;
00129     idVec3_t yellow(1.0, 1.0, 0);
00130     idVec3_t white(1.0, 1.0, 1.0);
00131         int i;
00132         
00133     for(i = 0; i < controlPoints.Num(); i++) {
00134         VectorCopy(*controlPoints[i], mins);
00135         VectorCopy(mins, maxs);
00136         mins[0] -= 8;
00137         mins[1] += 8;
00138         mins[2] -= 8;
00139         maxs[0] += 8;
00140         maxs[1] -= 8;
00141         maxs[2] += 8;
00142         debugLine( yellow, mins[0], mins[1], mins[2], maxs[0], mins[1], mins[2]);
00143         debugLine( yellow, maxs[0], mins[1], mins[2], maxs[0], maxs[1], mins[2]);
00144         debugLine( yellow, maxs[0], maxs[1], mins[2], mins[0], maxs[1], mins[2]);
00145         debugLine( yellow, mins[0], maxs[1], mins[2], mins[0], mins[1], mins[2]);
00146         
00147         debugLine( yellow, mins[0], mins[1], maxs[2], maxs[0], mins[1], maxs[2]);
00148         debugLine( yellow, maxs[0], mins[1], maxs[2], maxs[0], maxs[1], maxs[2]);
00149         debugLine( yellow, maxs[0], maxs[1], maxs[2], mins[0], maxs[1], maxs[2]);
00150         debugLine( yellow, mins[0], maxs[1], maxs[2], mins[0], mins[1], maxs[2]);
00151         
00152     }
00153 
00154     int step = 0;
00155     idVec3_t step1;
00156     for(i = 3; i < controlPoints.Num(); i++) {
00157         for (float tension = 0.0f; tension < 1.001f; tension += 0.1f) {
00158             float x = 0;
00159             float y = 0;
00160             float z = 0;
00161             for (int j = 0; j < 4; j++) {
00162                 x += controlPoints[i - (3 - j)]->x * calcSpline(j, tension);
00163                 y += controlPoints[i - (3 - j)]->y * calcSpline(j, tension);
00164                 z += controlPoints[i - (3 - j)]->z * calcSpline(j, tension);
00165             }
00166             if (step == 0) {
00167                 step1[0] = x;
00168                 step1[1] = y;
00169                 step1[2] = z;
00170                 step = 1;
00171             } else {
00172                 debugLine( white, step1[0], step1[1], step1[2], x, y, z);
00173                 step = 0;
00174             }
00175 
00176         }
00177     }
00178 }
00179 
00180 void idSplineList::buildSpline() {
00181     //int start = Sys_Milliseconds();
00182     clearSpline();
00183     for(int i = 3; i < controlPoints.Num(); i++) {
00184         for (float tension = 0.0f; tension < 1.001f; tension += granularity) {
00185             float x = 0;
00186             float y = 0;
00187             float z = 0;
00188             for (int j = 0; j < 4; j++) {
00189                 x += controlPoints[i - (3 - j)]->x * calcSpline(j, tension);
00190                 y += controlPoints[i - (3 - j)]->y * calcSpline(j, tension);
00191                 z += controlPoints[i - (3 - j)]->z * calcSpline(j, tension);
00192             }
00193             splinePoints.Append(new idVec3_t(x, y, z));
00194         }
00195     }
00196     dirty = false;
00197     //Com_Printf("Spline build took %f seconds\n", (float)(Sys_Milliseconds() - start) / 1000);
00198 }
00199 
00200 
00201 void idSplineList::draw(bool editMode) {
00202     int i;
00203     vec4_t yellow(1, 1, 0, 1);
00204         
00205     if (controlPoints.Num() == 0) {
00206         return;
00207     }
00208 
00209     if (dirty) {
00210         buildSpline();
00211     }
00212 
00213 
00214     qglColor3fv(controlColor);
00215     qglPointSize(5);
00216     
00217     qglBegin(GL_POINTS);
00218     for (i = 0; i < controlPoints.Num(); i++) {
00219         qglVertex3fv(*controlPoints[i]);
00220     }
00221     qglEnd();
00222     
00223     if (editMode) {
00224         for(i = 0; i < controlPoints.Num(); i++) {
00225             glBox(activeColor, *controlPoints[i], 4);
00226         }
00227     }
00228 
00229     //Draw the curve
00230     qglColor3fv(pathColor);
00231     qglBegin(GL_LINE_STRIP);
00232     int count = splinePoints.Num();
00233     for (i = 0; i < count; i++) {
00234         qglVertex3fv(*splinePoints[i]);
00235     }
00236     qglEnd();
00237 
00238     if (editMode) {
00239         qglColor3fv(segmentColor);
00240         qglPointSize(3);
00241         qglBegin(GL_POINTS);
00242         for (i = 0; i < count; i++) {
00243             qglVertex3fv(*splinePoints[i]);
00244         }
00245         qglEnd();
00246     }
00247     if (count > 0) {
00248         //assert(activeSegment >=0 && activeSegment < count);
00249         if (activeSegment >=0 && activeSegment < count) {
00250             glBox(activeColor, *splinePoints[activeSegment], 6);
00251             glBox(yellow, *splinePoints[activeSegment], 8);
00252         }
00253     }
00254 
00255 }
00256 
00257 float idSplineList::totalDistance() {
00258 
00259     if (controlPoints.Num() == 0) {
00260         return 0.0;
00261     }
00262 
00263     if (dirty) {
00264         buildSpline();
00265     }
00266 
00267     float dist = 0.0;
00268     idVec3_t temp;
00269     int count = splinePoints.Num();
00270     for(int i = 1; i < count; i++) {
00271         temp = *splinePoints[i-1];
00272         temp -= *splinePoints[i];
00273         dist += temp.Length();
00274     }
00275     return dist;
00276 }
00277 
00278 void idSplineList::initPosition(long bt, long totalTime) {
00279 
00280     if (dirty) {
00281         buildSpline();
00282     }
00283 
00284     if (splinePoints.Num() == 0) {
00285         return;
00286     }
00287 
00288     baseTime = bt;
00289     time = totalTime;
00290 
00291     // calc distance to travel ( this will soon be broken into time segments )
00292     splineTime.Clear();
00293     splineTime.Append(0);
00294     float dist = totalDistance();
00295     float distSoFar = 0.0;
00296     idVec3_t temp;
00297     int count = splinePoints.Num();
00298     //for(int i = 2; i < count - 1; i++) {
00299     for(int i = 1; i < count; i++) {
00300         temp = *splinePoints[i-1];
00301         temp -= *splinePoints[i];
00302         distSoFar += temp.Length();
00303         float percent = distSoFar / dist;
00304         percent *= totalTime;
00305         splineTime.Append(percent + bt);
00306     }
00307     assert(splineTime.Num() == splinePoints.Num());
00308     activeSegment = 0;
00309 }
00310 
00311 
00312 
00313 float idSplineList::calcSpline(int step, float tension) {
00314     switch(step) {
00315         case 0: return (pow(1 - tension, 3)) / 6;
00316         case 1: return (3 * pow(tension, 3) - 6 * pow(tension, 2) + 4) / 6;
00317         case 2: return (-3 * pow(tension, 3) + 3 * pow(tension, 2) + 3 * tension + 1) / 6;
00318         case 3: return pow(tension, 3) / 6;
00319     }
00320     return 0.0;
00321 }
00322 
00323 
00324 
00325 void idSplineList::updateSelection(const idVec3_t &move) {
00326     if (selected) {
00327         dirty = true;
00328         VectorAdd(*selected, move, *selected);
00329     }
00330 }
00331 
00332 
00333 void idSplineList::setSelectedPoint(idVec3_t *p) {
00334     if (p) {
00335         p->Snap();
00336         for(int i = 0; i < controlPoints.Num(); i++) {
00337             if (*p == *controlPoints[i]) {
00338                 selected = controlPoints[i];
00339             }
00340         }
00341     } else {
00342         selected = NULL;
00343     }
00344 }
00345 
00346 const idVec3_t *idSplineList::getPosition(long t) {
00347     static idVec3_t interpolatedPos;
00348 
00349     int count = splineTime.Num();
00350     if (count == 0) {
00351         return &zero;
00352     }
00353 
00354     assert(splineTime.Num() == splinePoints.Num());
00355 
00356     while (activeSegment < count) {
00357         if (splineTime[activeSegment] >= t) {
00358             if (activeSegment > 0 && activeSegment < count - 1) {
00359                 float timeHi = splineTime[activeSegment + 1];
00360                 float timeLo = splineTime[activeSegment - 1];
00361                 //float percent = (float)(baseTime + time - t) / time;
00362                 float percent = (timeHi - t) / (timeHi - timeLo); 
00363                 // pick two bounding points
00364                 idVec3_t v1 = *splinePoints[activeSegment-1];
00365                 idVec3_t v2 = *splinePoints[activeSegment+1];
00366                 v2 *= (1.0 - percent);
00367                 v1 *= percent;
00368                 v2 += v1;
00369                 interpolatedPos = v2;
00370                 return &interpolatedPos;
00371             }
00372             return splinePoints[activeSegment];
00373         } else {
00374             activeSegment++;
00375         }
00376     }
00377     return splinePoints[count-1];
00378 }
00379 
00380 void idSplineList::parse(const char *(*text)  ) {
00381     const char *token;
00382     //Com_MatchToken( text, "{" );
00383     do {
00384         token = Com_Parse( text );
00385     
00386         if ( !token[0] ) {
00387             break;
00388         }
00389         if ( !Q_stricmp (token, "}") ) {
00390             break;
00391         }
00392 
00393         do {
00394             // if token is not a brace, it is a key for a key/value pair
00395             if ( !token[0] || !Q_stricmp (token, "(") || !Q_stricmp(token, "}")) {
00396                 break;
00397             }
00398 
00399             Com_UngetToken();
00400             idStr key = Com_ParseOnLine(text);
00401             const char *token = Com_Parse(text);
00402             if (Q_stricmp(key.c_str(), "granularity") == 0) {
00403                 granularity = atof(token);
00404             } else if (Q_stricmp(key.c_str(), "name") == 0) {
00405                 name = token;
00406             }
00407             token = Com_Parse(text);
00408 
00409         } while (1);
00410 
00411         if ( !Q_stricmp (token, "}") ) {
00412             break;
00413         }
00414 
00415         Com_UngetToken();
00416         // read the control point
00417         idVec3_t point;
00418         Com_Parse1DMatrix( text, 3, point );
00419         addPoint(point.x, point.y, point.z);
00420     } while (1);
00421  
00422     //Com_UngetToken();
00423     //Com_MatchToken( text, "}" );
00424     dirty = true;
00425 }
00426 
00427 void idSplineList::write(fileHandle_t file, const char *p) {
00428     idStr s = va("\t\t%s {\n", p);
00429     FS_Write(s.c_str(), s.length(), file);
00430     //s = va("\t\tname %s\n", name.c_str());
00431     //FS_Write(s.c_str(), s.length(), file);
00432     s = va("\t\t\tgranularity %f\n", granularity);
00433     FS_Write(s.c_str(), s.length(), file);
00434     int count = controlPoints.Num();
00435     for (int i = 0; i < count; i++) {
00436         s = va("\t\t\t( %f %f %f )\n", controlPoints[i]->x, controlPoints[i]->y, controlPoints[i]->z);
00437         FS_Write(s.c_str(), s.length(), file);
00438     }
00439     s = "\t\t}\n";
00440     FS_Write(s.c_str(), s.length(), file);
00441 }
00442 
00443 
00444 void idCameraDef::getActiveSegmentInfo(int segment, idVec3_t &origin, idVec3_t &direction, float *fov) {
00445 #if 0
00446     if (!cameraSpline.validTime()) {
00447         buildCamera();
00448     }
00449     double d = (double)segment / numSegments();
00450     getCameraInfo(d * totalTime * 1000, origin, direction, fov);
00451 #endif
00452 /*
00453     if (!cameraSpline.validTime()) {
00454         buildCamera();
00455     }
00456     origin = *cameraSpline.getSegmentPoint(segment);
00457     
00458 
00459     idVec3_t temp;
00460 
00461     int numTargets = getTargetSpline()->controlPoints.Num();
00462     int count = cameraSpline.splineTime.Num();
00463     if (numTargets == 0) {
00464         // follow the path
00465         if (cameraSpline.getActiveSegment() < count - 1) {
00466             temp = *cameraSpline.splinePoints[cameraSpline.getActiveSegment()+1];
00467         }
00468     } else if (numTargets == 1) {
00469         temp = *getTargetSpline()->controlPoints[0];
00470     } else {
00471         temp = *getTargetSpline()->getSegmentPoint(segment);
00472     }
00473 
00474     temp -= origin;
00475     temp.Normalize();
00476     direction = temp;
00477 */
00478 }
00479 
00480 bool idCameraDef::getCameraInfo(long time, idVec3_t &origin, idVec3_t &direction, float *fv) {
00481 
00482 
00483     if ((time - startTime) / 1000 > totalTime) {
00484         return false;
00485     }
00486 
00487 
00488     for (int i = 0; i < events.Num(); i++) {
00489         if (time >= startTime + events[i]->getTime() && !events[i]->getTriggered()) {
00490             events[i]->setTriggered(true);
00491             if (events[i]->getType() == idCameraEvent::EVENT_TARGET) {
00492                 setActiveTargetByName(events[i]->getParam());
00493                 getActiveTarget()->start(startTime + events[i]->getTime());
00494                 //Com_Printf("Triggered event switch to target: %s\n",events[i]->getParam());
00495             } else if (events[i]->getType() == idCameraEvent::EVENT_TRIGGER) {
00496                 //idEntity *ent = NULL;
00497                 //ent = level.FindTarget( ent, events[i]->getParam());
00498                 //if (ent) {
00499                 //  ent->signal( SIG_TRIGGER );
00500                 //  ent->ProcessEvent( &EV_Activate, world );
00501                 //}
00502             } else if (events[i]->getType() == idCameraEvent::EVENT_FOV) {
00503                 //*fv = fov = atof(events[i]->getParam());
00504             } else if (events[i]->getType() == idCameraEvent::EVENT_STOP) {
00505                 return false;
00506             }
00507         }
00508     }
00509 
00510     origin = *cameraPosition->getPosition(time);
00511     
00512     *fv = fov.getFOV(time);
00513 
00514     idVec3_t temp = origin;
00515 
00516     int numTargets = targetPositions.Num();
00517     if (numTargets == 0) {
00518 /*
00519         // follow the path
00520         if (cameraSpline.getActiveSegment() < count - 1) {
00521             temp = *cameraSpline.splinePoints[cameraSpline.getActiveSegment()+1];
00522             if (temp == origin) {
00523                 int index = cameraSpline.getActiveSegment() + 2;
00524                 while (temp == origin && index < count - 1) {
00525                     temp = *cameraSpline.splinePoints[index++];
00526                 }
00527             }
00528         }
00529 */
00530     } else {
00531         temp = *getActiveTarget()->getPosition(time);
00532     }
00533     
00534     temp -= origin;
00535     temp.Normalize();
00536     direction = temp;
00537 
00538     return true;
00539 }
00540 
00541 bool idCameraDef::waitEvent(int index) {
00542     //for (int i = 0; i < events.Num(); i++) {
00543     //  if (events[i]->getSegment() == index && events[i]->getType() == idCameraEvent::EVENT_WAIT) {
00544     //      return true;
00545     //  }
00546     //}
00547     return false;
00548 }
00549 
00550 
00551 #define NUM_CCELERATION_SEGS 10
00552 #define CELL_AMT 5
00553 
00554 void idCameraDef::buildCamera() {
00555     int i;
00556     int lastSwitch = 0;
00557     idList<float> waits;
00558     idList<int> targets;
00559 
00560     totalTime = baseTime;
00561     cameraPosition->setTime(totalTime * 1000);
00562     // we have a base time layout for the path and the target path
00563     // now we need to layer on any wait or speed changes
00564     for (i = 0; i < events.Num(); i++) {
00565         idCameraEvent *ev = events[i];
00566         events[i]->setTriggered(false);
00567         switch (events[i]->getType()) {
00568             case idCameraEvent::EVENT_TARGET : {
00569                 targets.Append(i);
00570                 break;
00571             }
00572             case idCameraEvent::EVENT_WAIT : {
00573                 waits.Append(atof(events[i]->getParam()));
00574                 cameraPosition->addVelocity(events[i]->getTime(), atof(events[i]->getParam()) * 1000, 0);
00575                 break;
00576             }
00577             case idCameraEvent::EVENT_TARGETWAIT : {
00578                 //targetWaits.Append(i);
00579                 break;
00580             }
00581             case idCameraEvent::EVENT_SPEED : {
00582 /*
00583                 // take the average delay between up to the next five segments
00584                 float adjust = atof(events[i]->getParam());
00585                 int index = events[i]->getSegment();
00586                 total = 0;
00587                 count = 0;
00588 
00589                 // get total amount of time over the remainder of the segment
00590                 for (j = index; j < cameraSpline.numSegments() - 1; j++) {
00591                     total += cameraSpline.getSegmentTime(j + 1) - cameraSpline.getSegmentTime(j);
00592                     count++;
00593                 }
00594 
00595                 // multiply that by the adjustment
00596                 double newTotal = total * adjust;
00597                 // what is the difference.. 
00598                 newTotal -= total;
00599                 totalTime += newTotal / 1000;
00600 
00601                 // per segment difference
00602                 newTotal /= count;
00603                 int additive = newTotal;
00604 
00605                 // now propogate that difference out to each segment
00606                 for (j = index; j < cameraSpline.numSegments(); j++) {
00607                     cameraSpline.addSegmentTime(j, additive);
00608                     additive += newTotal;
00609                 }
00610                 break;
00611 */
00612             }
00613         }
00614     }
00615 
00616 
00617     for (i = 0; i < waits.Num(); i++) {
00618         totalTime += waits[i];
00619     }
00620 
00621     // on a new target switch, we need to take time to this point ( since last target switch ) 
00622     // and allocate it across the active target, then reset time to this point
00623     long timeSoFar = 0;
00624     long total = totalTime * 1000;
00625     for (i = 0; i < targets.Num(); i++) {
00626         long t;
00627         if (i < targets.Num() - 1) {
00628             t = events[targets[i+1]]->getTime();
00629         } else {
00630             t = total - timeSoFar;
00631         }
00632         // t is how much time to use for this target
00633         setActiveTargetByName(events[targets[i]]->getParam());
00634         getActiveTarget()->setTime(t);
00635         timeSoFar += t;
00636     }
00637 
00638     
00639 }
00640 
00641 void idCameraDef::startCamera(long t) {
00642     buildCamera();
00643     cameraPosition->start(t);
00644     //for (int i = 0; i < targetPositions.Num(); i++) {
00645     //  targetPositions[i]->
00646     //}
00647     startTime = t;
00648     cameraRunning = true;
00649 }
00650 
00651 
00652 void idCameraDef::parse(const char *(*text)  ) {
00653 
00654     const char  *token;
00655     do {
00656         token = Com_Parse( text );
00657     
00658         if ( !token[0] ) {
00659             break;
00660         }
00661         if ( !Q_stricmp (token, "}") ) {
00662             break;
00663         }
00664 
00665         if (Q_stricmp(token, "time") == 0) {
00666             baseTime = Com_ParseFloat(text);
00667         }
00668 
00669         if (Q_stricmp(token, "camera_fixed") == 0) {
00670             cameraPosition = new idFixedPosition();
00671             cameraPosition->parse(text);
00672         }
00673 
00674         if (Q_stricmp(token, "camera_interpolated") == 0) {
00675             cameraPosition = new idInterpolatedPosition();
00676             cameraPosition->parse(text);
00677         }
00678 
00679         if (Q_stricmp(token, "camera_spline") == 0) {
00680             cameraPosition = new idSplinePosition();
00681             cameraPosition->parse(text);
00682         }
00683 
00684         if (Q_stricmp(token, "target_fixed") == 0) {
00685             idFixedPosition *pos = new idFixedPosition();
00686             pos->parse(text);
00687             targetPositions.Append(pos);
00688         }
00689         
00690         if (Q_stricmp(token, "target_interpolated") == 0) {
00691             idInterpolatedPosition *pos = new idInterpolatedPosition();
00692             pos->parse(text);
00693             targetPositions.Append(pos);
00694         }
00695 
00696         if (Q_stricmp(token, "target_spline") == 0) {
00697             idSplinePosition *pos = new idSplinePosition();
00698             pos->parse(text);
00699             targetPositions.Append(pos);
00700         }
00701 
00702         if (Q_stricmp(token, "fov") == 0) {
00703             fov.parse(text);
00704         }
00705 
00706         if (Q_stricmp(token, "event") == 0) {
00707             idCameraEvent *event = new idCameraEvent();
00708             event->parse(text);
00709             addEvent(event);
00710         }
00711 
00712 
00713     } while (1);
00714 
00715     Com_UngetToken();
00716     Com_MatchToken( text, "}" );
00717 
00718 }
00719 
00720 bool idCameraDef::load(const char *filename) {
00721     char *buf;
00722     const char *buf_p;
00723     int length = FS_ReadFile( filename, (void **)&buf );
00724     if ( !buf ) {
00725         return false;
00726     }
00727 
00728     clear();
00729     Com_BeginParseSession( filename );
00730     buf_p = buf;
00731     parse(&buf_p);
00732     Com_EndParseSession();
00733     FS_FreeFile( buf );
00734 
00735     return true;
00736 }
00737 
00738 void idCameraDef::save(const char *filename) {
00739     fileHandle_t file = FS_FOpenFileWrite(filename);
00740     if (file) {
00741         int i;
00742         idStr s = "cameraPathDef { \n"; 
00743         FS_Write(s.c_str(), s.length(), file);
00744         s = va("\ttime %f\n", baseTime);
00745         FS_Write(s.c_str(), s.length(), file);
00746 
00747         cameraPosition->write(file, va("camera_%s",cameraPosition->typeStr()));
00748 
00749         for (i = 0; i < numTargets(); i++) {
00750             targetPositions[i]->write(file, va("target_%s", targetPositions[i]->typeStr()));
00751         }
00752 
00753         for (i = 0; i < events.Num(); i++) {
00754             events[i]->write(file, "event");
00755         }
00756 
00757         fov.write(file, "fov");
00758 
00759         s = "}\n";
00760         FS_Write(s.c_str(), s.length(), file);
00761     }
00762     FS_FCloseFile(file);
00763 }
00764 
00765 int idCameraDef::sortEvents(const void *p1, const void *p2) {
00766     idCameraEvent *ev1 = (idCameraEvent*)(p1);
00767     idCameraEvent *ev2 = (idCameraEvent*)(p2);
00768 
00769     if (ev1->getTime() > ev2->getTime()) {
00770         return -1;
00771     }
00772     if (ev1->getTime() < ev2->getTime()) {
00773         return 1;
00774     }
00775     return 0; 
00776 }
00777 
00778 void idCameraDef::addEvent(idCameraEvent *event) {
00779     events.Append(event);
00780     //events.Sort(&sortEvents);
00781 
00782 }
00783 void idCameraDef::addEvent(idCameraEvent::eventType t, const char *param, long time) {
00784     addEvent(new idCameraEvent(t, param, time));
00785     buildCamera();
00786 }
00787 
00788 
00789 const char *idCameraEvent::eventStr[] = {
00790     "NA",
00791     "WAIT",
00792     "TARGETWAIT",
00793     "SPEED",
00794     "TARGET",
00795     "SNAPTARGET",
00796     "FOV",
00797     "SCRIPT",
00798     "TRIGGER",
00799     "STOP"
00800 };
00801 
00802 void idCameraEvent::parse(const char *(*text)  ) {
00803     const char *token;
00804     Com_MatchToken( text, "{" );
00805     do {
00806         token = Com_Parse( text );
00807     
00808         if ( !token[0] ) {
00809             break;
00810         }
00811         if ( !strcmp (token, "}") ) {
00812             break;
00813         }
00814 
00815         // here we may have to jump over brush epairs ( only used in editor )
00816         do {
00817             // if token is not a brace, it is a key for a key/value pair
00818             if ( !token[0] || !strcmp (token, "(") || !strcmp(token, "}")) {
00819                 break;
00820             }
00821 
00822             Com_UngetToken();
00823             idStr key = Com_ParseOnLine(text);
00824             const char *token = Com_Parse(text);
00825             if (Q_stricmp(key.c_str(), "type") == 0) {
00826                 type = static_cast<idCameraEvent::eventType>(atoi(token));
00827             } else if (Q_stricmp(key.c_str(), "param") == 0) {
00828                 paramStr = token;
00829             } else if (Q_stricmp(key.c_str(), "time") == 0) {
00830                 time = atoi(token);
00831             }
00832             token = Com_Parse(text);
00833 
00834         } while (1);
00835 
00836         if ( !strcmp (token, "}") ) {
00837             break;
00838         }
00839 
00840     } while (1);
00841  
00842     Com_UngetToken();
00843     Com_MatchToken( text, "}" );
00844 }
00845 
00846 void idCameraEvent::write(fileHandle_t file, const char *name) {
00847     idStr s = va("\t%s {\n", name);
00848     FS_Write(s.c_str(), s.length(), file);
00849     s = va("\t\ttype %d\n", static_cast<int>(type));
00850     FS_Write(s.c_str(), s.length(), file);
00851     s = va("\t\tparam %s\n", paramStr.c_str());
00852     FS_Write(s.c_str(), s.length(), file);
00853     s = va("\t\ttime %d\n", time);
00854     FS_Write(s.c_str(), s.length(), file);
00855     s = "\t}\n";
00856     FS_Write(s.c_str(), s.length(), file);
00857 }
00858 
00859 
00860 const char *idCameraPosition::positionStr[] = {
00861     "Fixed",
00862     "Interpolated",
00863     "Spline",
00864 };
00865 
00866 
00867 
00868 const idVec3_t *idInterpolatedPosition::getPosition(long t) { 
00869     static idVec3_t interpolatedPos;
00870 
00871     float velocity = getVelocity(t);
00872     float timePassed = t - lastTime;
00873     lastTime = t;
00874 
00875     // convert to seconds   
00876     timePassed /= 1000;
00877 
00878     float distToTravel = timePassed *= velocity;
00879 
00880     idVec3_t temp = startPos;
00881     temp -= endPos;
00882     float distance = temp.Length();
00883 
00884     distSoFar += distToTravel;
00885     float percent = (float)(distSoFar) / distance;
00886 
00887     if (percent > 1.0) {
00888         percent = 1.0;
00889     } else if (percent < 0.0) {
00890         percent = 0.0;
00891     }
00892 
00893     // the following line does a straigt calc on percentage of time
00894     // float percent = (float)(startTime + time - t) / time;
00895 
00896     idVec3_t v1 = startPos;
00897     idVec3_t v2 = endPos;
00898     v1 *= (1.0 - percent);
00899     v2 *= percent;
00900     v1 += v2;
00901     interpolatedPos = v1;
00902     return &interpolatedPos;
00903 }
00904 
00905 
00906 void idCameraFOV::parse(const char *(*text)  ) {
00907     const char *token;
00908     Com_MatchToken( text, "{" );
00909     do {
00910         token = Com_Parse( text );
00911     
00912         if ( !token[0] ) {
00913             break;
00914         }
00915         if ( !strcmp (token, "}") ) {
00916             break;
00917         }
00918 
00919         // here we may have to jump over brush epairs ( only used in editor )
00920         do {
00921             // if token is not a brace, it is a key for a key/value pair
00922             if ( !token[0] || !strcmp (token, "(") || !strcmp(token, "}")) {
00923                 break;
00924             }
00925 
00926             Com_UngetToken();
00927             idStr key = Com_ParseOnLine(text);
00928             const char *token = Com_Parse(text);
00929             if (Q_stricmp(key.c_str(), "fov") == 0) {
00930                 fov = atof(token);
00931             } else if (Q_stricmp(key.c_str(), "startFOV") == 0) {
00932                 startFOV = atof(token);
00933             } else if (Q_stricmp(key.c_str(), "endFOV") == 0) {
00934                 endFOV = atof(token);
00935             } else if (Q_stricmp(key.c_str(), "time") == 0) {
00936                 time = atoi(token);
00937             }
00938             token = Com_Parse(text);
00939 
00940         } while (1);
00941 
00942         if ( !strcmp (token, "}") ) {
00943             break;
00944         }
00945 
00946     } while (1);
00947  
00948     Com_UngetToken();
00949     Com_MatchToken( text, "}" );
00950 }
00951 
00952 bool idCameraPosition::parseToken(const char *key, const char *(*text)) {
00953     const char *token = Com_Parse(text);
00954     if (Q_stricmp(key, "time") == 0) {
00955         time = atol(token);
00956         return true;
00957     } else if (Q_stricmp(key, "type") == 0) {
00958         type = static_cast<idCameraPosition::positionType>(atoi(token));
00959         return true;
00960     } else if (Q_stricmp(key, "velocity") == 0) {
00961         long t = atol(token);
00962         token = Com_Parse(text);
00963         long d = atol(token);
00964         token = Com_Parse(text);
00965         float s = atof(token);
00966         addVelocity(t, d, s);
00967         return true;
00968     } else if (Q_stricmp(key, "baseVelocity") == 0) {
00969         baseVelocity = atof(token);
00970         return true;
00971     } else if (Q_stricmp(key, "name") == 0) {
00972         name = token;
00973         return true;
00974     } else if (Q_stricmp(key, "time") == 0) {
00975         time = atoi(token);
00976         return true;
00977     }
00978     Com_UngetToken();
00979     return false;
00980 }
00981 
00982 
00983 
00984 void idFixedPosition::parse(const char *(*text)  ) {
00985     const char *token;
00986     Com_MatchToken( text, "{" );
00987     do {
00988         token = Com_Parse( text );
00989     
00990         if ( !token[0] ) {
00991             break;
00992         }
00993         if ( !strcmp (token, "}") ) {
00994             break;
00995         }
00996 
00997         // here we may have to jump over brush epairs ( only used in editor )
00998         do {
00999             // if token is not a brace, it is a key for a key/value pair
01000             if ( !token[0] || !strcmp (token, "(") || !strcmp(token, "}")) {
01001                 break;
01002             }
01003 
01004             Com_UngetToken();
01005             idStr key = Com_ParseOnLine(text);
01006             
01007             const char *token = Com_Parse(text);
01008             if (Q_stricmp(key.c_str(), "pos") == 0) {
01009                 Com_UngetToken();
01010                 Com_Parse1DMatrix( text, 3, pos );
01011             } else {
01012                 Com_UngetToken();
01013                 idCameraPosition::parseToken(key.c_str(), text);    
01014             }
01015             token = Com_Parse(text);
01016 
01017         } while (1);
01018 
01019         if ( !strcmp (token, "}") ) {
01020             break;
01021         }
01022 
01023     } while (1);
01024  
01025     Com_UngetToken();
01026     Com_MatchToken( text, "}" );
01027 }
01028 
01029 void idInterpolatedPosition::parse(const char *(*text)  ) {
01030     const char *token;
01031     Com_MatchToken( text, "{" );
01032     do {
01033         token = Com_Parse( text );
01034     
01035         if ( !token[0] ) {
01036             break;
01037         }
01038         if ( !strcmp (token, "}") ) {
01039             break;
01040         }
01041 
01042         // here we may have to jump over brush epairs ( only used in editor )
01043         do {
01044             // if token is not a brace, it is a key for a key/value pair
01045             if ( !token[0] || !strcmp (token, "(") || !strcmp(token, "}")) {
01046                 break;
01047             }
01048 
01049             Com_UngetToken();
01050             idStr key = Com_ParseOnLine(text);
01051             
01052             const char *token = Com_Parse(text);
01053             if (Q_stricmp(key.c_str(), "startPos") == 0) {
01054                 Com_UngetToken();
01055                 Com_Parse1DMatrix( text, 3, startPos );
01056             } else if (Q_stricmp(key.c_str(), "endPos") == 0) {
01057                 Com_UngetToken();
01058                 Com_Parse1DMatrix( text, 3, endPos );
01059             } else {
01060                 Com_UngetToken();
01061                 idCameraPosition::parseToken(key.c_str(), text);    
01062             }
01063             token = Com_Parse(text);
01064 
01065         } while (1);
01066 
01067         if ( !strcmp (token, "}") ) {
01068             break;
01069         }
01070 
01071     } while (1);
01072  
01073     Com_UngetToken();
01074     Com_MatchToken( text, "}" );
01075 }
01076 
01077 
01078 void idSplinePosition::parse(const char *(*text)  ) {
01079     const char *token;
01080     Com_MatchToken( text, "{" );
01081     do {
01082         token = Com_Parse( text );
01083     
01084         if ( !token[0] ) {
01085             break;
01086         }
01087         if ( !strcmp (token, "}") ) {
01088             break;
01089         }
01090 
01091         // here we may have to jump over brush epairs ( only used in editor )
01092         do {
01093             // if token is not a brace, it is a key for a key/value pair
01094             if ( !token[0] || !strcmp (token, "(") || !strcmp(token, "}")) {
01095                 break;
01096             }
01097 
01098             Com_UngetToken();
01099             idStr key = Com_ParseOnLine(text);
01100             
01101             const char *token = Com_Parse(text);
01102             if (Q_stricmp(key.c_str(), "target") == 0) {
01103                 target.parse(text);
01104             } else {
01105                 Com_UngetToken();
01106                 idCameraPosition::parseToken(key.c_str(), text);    
01107             }
01108             token = Com_Parse(text);
01109 
01110         } while (1);
01111 
01112         if ( !strcmp (token, "}") ) {
01113             break;
01114         }
01115 
01116     } while (1);
01117  
01118     Com_UngetToken();
01119     Com_MatchToken( text, "}" );
01120 }
01121 
01122 
01123 
01124 void idCameraFOV::write(fileHandle_t file, const char *p) {
01125     idStr s = va("\t%s {\n", p);
01126     FS_Write(s.c_str(), s.length(), file);
01127     
01128     s = va("\t\tfov %f\n", fov);
01129     FS_Write(s.c_str(), s.length(), file);
01130 
01131     s = va("\t\tstartFOV %f\n", startFOV);
01132     FS_Write(s.c_str(), s.length(), file);
01133 
01134     s = va("\t\tendFOV %f\n", endFOV);
01135     FS_Write(s.c_str(), s.length(), file);
01136 
01137     s = va("\t\ttime %i\n", time);
01138     FS_Write(s.c_str(), s.length(), file);
01139 
01140     s = "\t}\n";
01141     FS_Write(s.c_str(), s.length(), file);
01142 }
01143 
01144 
01145 void idCameraPosition::write(fileHandle_t file, const char *p) {
01146     
01147     idStr s = va("\t\ttime %i\n", time);
01148     FS_Write(s.c_str(), s.length(), file);
01149 
01150     s = va("\t\ttype %i\n", static_cast<int>(type));
01151     FS_Write(s.c_str(), s.length(), file);
01152 
01153     s = va("\t\tname %s\n", name.c_str());
01154     FS_Write(s.c_str(), s.length(), file);
01155 
01156     s = va("\t\tbaseVelocity %f\n", baseVelocity);
01157     FS_Write(s.c_str(), s.length(), file);
01158 
01159     for (int i = 0; i < velocities.Num(); i++) {
01160         s = va("\t\tvelocity %i %i %f\n", velocities[i]->startTime, velocities[i]->time, velocities[i]->speed);
01161         FS_Write(s.c_str(), s.length(), file);
01162     }
01163 
01164 }
01165 
01166 void idFixedPosition::write(fileHandle_t file, const char *p) {
01167     idStr s = va("\t%s {\n", p);
01168     FS_Write(s.c_str(), s.length(), file);
01169     idCameraPosition::write(file, p);
01170     s = va("\t\tpos ( %f %f %f )\n", pos.x, pos.y, pos.z);
01171     FS_Write(s.c_str(), s.length(), file);
01172     s = "\t}\n";
01173     FS_Write(s.c_str(), s.length(), file);
01174 }
01175 
01176 void idInterpolatedPosition::write(fileHandle_t file, const char *p) {
01177     idStr s = va("\t%s {\n", p);
01178     FS_Write(s.c_str(), s.length(), file);
01179     idCameraPosition::write(file, p);
01180     s = va("\t\tstartPos ( %f %f %f )\n", startPos.x, startPos.y, startPos.z);
01181     FS_Write(s.c_str(), s.length(), file);
01182     s = va("\t\tendPos ( %f %f %f )\n", endPos.x, endPos.y, endPos.z);
01183     FS_Write(s.c_str(), s.length(), file);
01184     s = "\t}\n";
01185     FS_Write(s.c_str(), s.length(), file);
01186 }
01187 
01188 void idSplinePosition::write(fileHandle_t file, const char *p) {
01189     idStr s = va("\t%s {\n", p);
01190     FS_Write(s.c_str(), s.length(), file);
01191     idCameraPosition::write(file, p);
01192     target.write(file, "target");
01193     s = "\t}\n";
01194     FS_Write(s.c_str(), s.length(), file);
01195 }
01196 
01197 void idCameraDef::addTarget(const char *name, idCameraPosition::positionType type) {
01198     const char *text = (name == NULL) ? va("target0%d", numTargets()+1) : name;
01199     idCameraPosition *pos = newFromType(type);
01200     if (pos) {
01201         pos->setName(name);
01202         targetPositions.Append(pos);
01203         activeTarget = numTargets()-1;
01204         if (activeTarget == 0) {
01205             // first one
01206             addEvent(idCameraEvent::EVENT_TARGET, name, 0);
01207         }
01208     }
01209 }
01210 
01211 
01212 
01213 idCameraDef camera;
01214 
01215 extern "C" {
01216 qboolean loadCamera(const char *name) {
01217   camera.clear();
01218   return static_cast<qboolean>(camera.load(name));
01219 }
01220 
01221 qboolean getCameraInfo(int time, float *origin, float*angles) {
01222     idVec3_t dir, org;
01223     org[0] = origin[0];
01224     org[1] = origin[1];
01225     org[2] = origin[2];
01226     float fov = 90;
01227     if (camera.getCameraInfo(time, org, dir, &fov)) {
01228         origin[0] = org[0];
01229         origin[1] = org[1];
01230         origin[2] = org[2];
01231         angles[1] = atan2 (dir[1], dir[0])*180/3.14159;
01232         angles[0] = asin (dir[2])*180/3.14159;
01233         return qtrue;
01234     }
01235     return qfalse;
01236 }
01237 
01238 void startCamera(int time) {
01239     camera.startCamera(time);
01240 }
01241 
01242 }
01243 
01244 

Generated on Thu Aug 25 12:37:59 2005 for Quake III Arena by  doxygen 1.3.9.1