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

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