splines.cpp 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245
  1. /*
  2. ===========================================================================
  3. Copyright (C) 1999-2005 Id Software, Inc.
  4. This file is part of Quake III Arena source code.
  5. Quake III Arena source code is free software; you can redistribute it
  6. and/or modify it under the terms of the GNU General Public License as
  7. published by the Free Software Foundation; either version 2 of the License,
  8. or (at your option) any later version.
  9. Quake III Arena source code is distributed in the hope that it will be
  10. useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with Foobar; if not, write to the Free Software
  15. Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  16. ===========================================================================
  17. */
  18. //#include "stdafx.h"
  19. //#include "qe3.h"
  20. #include "q_shared.h"
  21. #include "splines.h"
  22. extern "C" {
  23. int FS_Write( const void *buffer, int len, fileHandle_t h );
  24. int FS_ReadFile( const char *qpath, void **buffer );
  25. void FS_FreeFile( void *buffer );
  26. fileHandle_t FS_FOpenFileWrite( const char *filename );
  27. void FS_FCloseFile( fileHandle_t f );
  28. }
  29. float Q_fabs( float f ) {
  30. int tmp = * ( int * ) &f;
  31. tmp &= 0x7FFFFFFF;
  32. return * ( float * ) &tmp;
  33. }
  34. //#include "../shared/windings.h"
  35. //#include "../qcommon/qcommon.h"
  36. //#include "../sys/sys_public.h"
  37. //#include "../game/game_entity.h"
  38. idCameraDef splineList;
  39. idCameraDef *g_splineList = &splineList;
  40. idVec3_t idSplineList::zero(0,0,0);
  41. void glLabeledPoint(idVec3_t &color, idVec3_t &point, float size, const char *label) {
  42. qglColor3fv(color);
  43. qglPointSize(size);
  44. qglBegin(GL_POINTS);
  45. qglVertex3fv(point);
  46. qglEnd();
  47. idVec3_t v = point;
  48. v.x += 1;
  49. v.y += 1;
  50. v.z += 1;
  51. qglRasterPos3fv (v);
  52. qglCallLists (strlen(label), GL_UNSIGNED_BYTE, label);
  53. }
  54. void glBox(idVec3_t &color, idVec3_t &point, float size) {
  55. idVec3_t mins(point);
  56. idVec3_t maxs(point);
  57. mins[0] -= size;
  58. mins[1] += size;
  59. mins[2] -= size;
  60. maxs[0] += size;
  61. maxs[1] -= size;
  62. maxs[2] += size;
  63. qglColor3fv(color);
  64. qglBegin(GL_LINE_LOOP);
  65. qglVertex3f(mins[0],mins[1],mins[2]);
  66. qglVertex3f(maxs[0],mins[1],mins[2]);
  67. qglVertex3f(maxs[0],maxs[1],mins[2]);
  68. qglVertex3f(mins[0],maxs[1],mins[2]);
  69. qglEnd();
  70. qglBegin(GL_LINE_LOOP);
  71. qglVertex3f(mins[0],mins[1],maxs[2]);
  72. qglVertex3f(maxs[0],mins[1],maxs[2]);
  73. qglVertex3f(maxs[0],maxs[1],maxs[2]);
  74. qglVertex3f(mins[0],maxs[1],maxs[2]);
  75. qglEnd();
  76. qglBegin(GL_LINES);
  77. qglVertex3f(mins[0],mins[1],mins[2]);
  78. qglVertex3f(mins[0],mins[1],maxs[2]);
  79. qglVertex3f(mins[0],maxs[1],maxs[2]);
  80. qglVertex3f(mins[0],maxs[1],mins[2]);
  81. qglVertex3f(maxs[0],mins[1],mins[2]);
  82. qglVertex3f(maxs[0],mins[1],maxs[2]);
  83. qglVertex3f(maxs[0],maxs[1],maxs[2]);
  84. qglVertex3f(maxs[0],maxs[1],mins[2]);
  85. qglEnd();
  86. }
  87. void splineTest() {
  88. //g_splineList->load("p:/doom/base/maps/test_base1.camera");
  89. }
  90. void splineDraw() {
  91. //g_splineList->addToRenderer();
  92. }
  93. //extern void D_DebugLine( const idVec3_t &color, const idVec3_t &start, const idVec3_t &end );
  94. void debugLine(idVec3_t &color, float x, float y, float z, float x2, float y2, float z2) {
  95. idVec3_t from(x, y, z);
  96. idVec3_t to(x2, y2, z2);
  97. //D_DebugLine(color, from, to);
  98. }
  99. void idSplineList::addToRenderer() {
  100. if (controlPoints.Num() == 0) {
  101. return;
  102. }
  103. idVec3_t mins, maxs;
  104. idVec3_t yellow(1.0, 1.0, 0);
  105. idVec3_t white(1.0, 1.0, 1.0);
  106. int i;
  107. for(i = 0; i < controlPoints.Num(); i++) {
  108. VectorCopy(*controlPoints[i], mins);
  109. VectorCopy(mins, maxs);
  110. mins[0] -= 8;
  111. mins[1] += 8;
  112. mins[2] -= 8;
  113. maxs[0] += 8;
  114. maxs[1] -= 8;
  115. maxs[2] += 8;
  116. debugLine( yellow, mins[0], mins[1], mins[2], maxs[0], mins[1], mins[2]);
  117. debugLine( yellow, maxs[0], mins[1], mins[2], maxs[0], maxs[1], mins[2]);
  118. debugLine( yellow, maxs[0], maxs[1], mins[2], mins[0], maxs[1], mins[2]);
  119. debugLine( yellow, mins[0], maxs[1], mins[2], mins[0], mins[1], mins[2]);
  120. debugLine( yellow, mins[0], mins[1], maxs[2], maxs[0], mins[1], maxs[2]);
  121. debugLine( yellow, maxs[0], mins[1], maxs[2], maxs[0], maxs[1], maxs[2]);
  122. debugLine( yellow, maxs[0], maxs[1], maxs[2], mins[0], maxs[1], maxs[2]);
  123. debugLine( yellow, mins[0], maxs[1], maxs[2], mins[0], mins[1], maxs[2]);
  124. }
  125. int step = 0;
  126. idVec3_t step1;
  127. for(i = 3; i < controlPoints.Num(); i++) {
  128. for (float tension = 0.0f; tension < 1.001f; tension += 0.1f) {
  129. float x = 0;
  130. float y = 0;
  131. float z = 0;
  132. for (int j = 0; j < 4; j++) {
  133. x += controlPoints[i - (3 - j)]->x * calcSpline(j, tension);
  134. y += controlPoints[i - (3 - j)]->y * calcSpline(j, tension);
  135. z += controlPoints[i - (3 - j)]->z * calcSpline(j, tension);
  136. }
  137. if (step == 0) {
  138. step1[0] = x;
  139. step1[1] = y;
  140. step1[2] = z;
  141. step = 1;
  142. } else {
  143. debugLine( white, step1[0], step1[1], step1[2], x, y, z);
  144. step = 0;
  145. }
  146. }
  147. }
  148. }
  149. void idSplineList::buildSpline() {
  150. //int start = Sys_Milliseconds();
  151. clearSpline();
  152. for(int i = 3; i < controlPoints.Num(); i++) {
  153. for (float tension = 0.0f; tension < 1.001f; tension += granularity) {
  154. float x = 0;
  155. float y = 0;
  156. float z = 0;
  157. for (int j = 0; j < 4; j++) {
  158. x += controlPoints[i - (3 - j)]->x * calcSpline(j, tension);
  159. y += controlPoints[i - (3 - j)]->y * calcSpline(j, tension);
  160. z += controlPoints[i - (3 - j)]->z * calcSpline(j, tension);
  161. }
  162. splinePoints.Append(new idVec3_t(x, y, z));
  163. }
  164. }
  165. dirty = false;
  166. //Com_Printf("Spline build took %f seconds\n", (float)(Sys_Milliseconds() - start) / 1000);
  167. }
  168. void idSplineList::draw(bool editMode) {
  169. int i;
  170. vec4_t yellow(1, 1, 0, 1);
  171. if (controlPoints.Num() == 0) {
  172. return;
  173. }
  174. if (dirty) {
  175. buildSpline();
  176. }
  177. qglColor3fv(controlColor);
  178. qglPointSize(5);
  179. qglBegin(GL_POINTS);
  180. for (i = 0; i < controlPoints.Num(); i++) {
  181. qglVertex3fv(*controlPoints[i]);
  182. }
  183. qglEnd();
  184. if (editMode) {
  185. for(i = 0; i < controlPoints.Num(); i++) {
  186. glBox(activeColor, *controlPoints[i], 4);
  187. }
  188. }
  189. //Draw the curve
  190. qglColor3fv(pathColor);
  191. qglBegin(GL_LINE_STRIP);
  192. int count = splinePoints.Num();
  193. for (i = 0; i < count; i++) {
  194. qglVertex3fv(*splinePoints[i]);
  195. }
  196. qglEnd();
  197. if (editMode) {
  198. qglColor3fv(segmentColor);
  199. qglPointSize(3);
  200. qglBegin(GL_POINTS);
  201. for (i = 0; i < count; i++) {
  202. qglVertex3fv(*splinePoints[i]);
  203. }
  204. qglEnd();
  205. }
  206. if (count > 0) {
  207. //assert(activeSegment >=0 && activeSegment < count);
  208. if (activeSegment >=0 && activeSegment < count) {
  209. glBox(activeColor, *splinePoints[activeSegment], 6);
  210. glBox(yellow, *splinePoints[activeSegment], 8);
  211. }
  212. }
  213. }
  214. float idSplineList::totalDistance() {
  215. if (controlPoints.Num() == 0) {
  216. return 0.0;
  217. }
  218. if (dirty) {
  219. buildSpline();
  220. }
  221. float dist = 0.0;
  222. idVec3_t temp;
  223. int count = splinePoints.Num();
  224. for(int i = 1; i < count; i++) {
  225. temp = *splinePoints[i-1];
  226. temp -= *splinePoints[i];
  227. dist += temp.Length();
  228. }
  229. return dist;
  230. }
  231. void idSplineList::initPosition(long bt, long totalTime) {
  232. if (dirty) {
  233. buildSpline();
  234. }
  235. if (splinePoints.Num() == 0) {
  236. return;
  237. }
  238. baseTime = bt;
  239. time = totalTime;
  240. // calc distance to travel ( this will soon be broken into time segments )
  241. splineTime.Clear();
  242. splineTime.Append(0);
  243. float dist = totalDistance();
  244. float distSoFar = 0.0;
  245. idVec3_t temp;
  246. int count = splinePoints.Num();
  247. //for(int i = 2; i < count - 1; i++) {
  248. for(int i = 1; i < count; i++) {
  249. temp = *splinePoints[i-1];
  250. temp -= *splinePoints[i];
  251. distSoFar += temp.Length();
  252. float percent = distSoFar / dist;
  253. percent *= totalTime;
  254. splineTime.Append(percent + bt);
  255. }
  256. assert(splineTime.Num() == splinePoints.Num());
  257. activeSegment = 0;
  258. }
  259. float idSplineList::calcSpline(int step, float tension) {
  260. switch(step) {
  261. case 0: return (pow(1 - tension, 3)) / 6;
  262. case 1: return (3 * pow(tension, 3) - 6 * pow(tension, 2) + 4) / 6;
  263. case 2: return (-3 * pow(tension, 3) + 3 * pow(tension, 2) + 3 * tension + 1) / 6;
  264. case 3: return pow(tension, 3) / 6;
  265. }
  266. return 0.0;
  267. }
  268. void idSplineList::updateSelection(const idVec3_t &move) {
  269. if (selected) {
  270. dirty = true;
  271. VectorAdd(*selected, move, *selected);
  272. }
  273. }
  274. void idSplineList::setSelectedPoint(idVec3_t *p) {
  275. if (p) {
  276. p->Snap();
  277. for(int i = 0; i < controlPoints.Num(); i++) {
  278. if (*p == *controlPoints[i]) {
  279. selected = controlPoints[i];
  280. }
  281. }
  282. } else {
  283. selected = NULL;
  284. }
  285. }
  286. const idVec3_t *idSplineList::getPosition(long t) {
  287. static idVec3_t interpolatedPos;
  288. int count = splineTime.Num();
  289. if (count == 0) {
  290. return &zero;
  291. }
  292. assert(splineTime.Num() == splinePoints.Num());
  293. while (activeSegment < count) {
  294. if (splineTime[activeSegment] >= t) {
  295. if (activeSegment > 0 && activeSegment < count - 1) {
  296. float timeHi = splineTime[activeSegment + 1];
  297. float timeLo = splineTime[activeSegment - 1];
  298. //float percent = (float)(baseTime + time - t) / time;
  299. float percent = (timeHi - t) / (timeHi - timeLo);
  300. // pick two bounding points
  301. idVec3_t v1 = *splinePoints[activeSegment-1];
  302. idVec3_t v2 = *splinePoints[activeSegment+1];
  303. v2 *= (1.0 - percent);
  304. v1 *= percent;
  305. v2 += v1;
  306. interpolatedPos = v2;
  307. return &interpolatedPos;
  308. }
  309. return splinePoints[activeSegment];
  310. } else {
  311. activeSegment++;
  312. }
  313. }
  314. return splinePoints[count-1];
  315. }
  316. void idSplineList::parse(const char *(*text) ) {
  317. const char *token;
  318. //Com_MatchToken( text, "{" );
  319. do {
  320. token = Com_Parse( text );
  321. if ( !token[0] ) {
  322. break;
  323. }
  324. if ( !Q_stricmp (token, "}") ) {
  325. break;
  326. }
  327. do {
  328. // if token is not a brace, it is a key for a key/value pair
  329. if ( !token[0] || !Q_stricmp (token, "(") || !Q_stricmp(token, "}")) {
  330. break;
  331. }
  332. Com_UngetToken();
  333. idStr key = Com_ParseOnLine(text);
  334. const char *token = Com_Parse(text);
  335. if (Q_stricmp(key.c_str(), "granularity") == 0) {
  336. granularity = atof(token);
  337. } else if (Q_stricmp(key.c_str(), "name") == 0) {
  338. name = token;
  339. }
  340. token = Com_Parse(text);
  341. } while (1);
  342. if ( !Q_stricmp (token, "}") ) {
  343. break;
  344. }
  345. Com_UngetToken();
  346. // read the control point
  347. idVec3_t point;
  348. Com_Parse1DMatrix( text, 3, point );
  349. addPoint(point.x, point.y, point.z);
  350. } while (1);
  351. //Com_UngetToken();
  352. //Com_MatchToken( text, "}" );
  353. dirty = true;
  354. }
  355. void idSplineList::write(fileHandle_t file, const char *p) {
  356. idStr s = va("\t\t%s {\n", p);
  357. FS_Write(s.c_str(), s.length(), file);
  358. //s = va("\t\tname %s\n", name.c_str());
  359. //FS_Write(s.c_str(), s.length(), file);
  360. s = va("\t\t\tgranularity %f\n", granularity);
  361. FS_Write(s.c_str(), s.length(), file);
  362. int count = controlPoints.Num();
  363. for (int i = 0; i < count; i++) {
  364. s = va("\t\t\t( %f %f %f )\n", controlPoints[i]->x, controlPoints[i]->y, controlPoints[i]->z);
  365. FS_Write(s.c_str(), s.length(), file);
  366. }
  367. s = "\t\t}\n";
  368. FS_Write(s.c_str(), s.length(), file);
  369. }
  370. void idCameraDef::getActiveSegmentInfo(int segment, idVec3_t &origin, idVec3_t &direction, float *fov) {
  371. #if 0
  372. if (!cameraSpline.validTime()) {
  373. buildCamera();
  374. }
  375. double d = (double)segment / numSegments();
  376. getCameraInfo(d * totalTime * 1000, origin, direction, fov);
  377. #endif
  378. /*
  379. if (!cameraSpline.validTime()) {
  380. buildCamera();
  381. }
  382. origin = *cameraSpline.getSegmentPoint(segment);
  383. idVec3_t temp;
  384. int numTargets = getTargetSpline()->controlPoints.Num();
  385. int count = cameraSpline.splineTime.Num();
  386. if (numTargets == 0) {
  387. // follow the path
  388. if (cameraSpline.getActiveSegment() < count - 1) {
  389. temp = *cameraSpline.splinePoints[cameraSpline.getActiveSegment()+1];
  390. }
  391. } else if (numTargets == 1) {
  392. temp = *getTargetSpline()->controlPoints[0];
  393. } else {
  394. temp = *getTargetSpline()->getSegmentPoint(segment);
  395. }
  396. temp -= origin;
  397. temp.Normalize();
  398. direction = temp;
  399. */
  400. }
  401. bool idCameraDef::getCameraInfo(long time, idVec3_t &origin, idVec3_t &direction, float *fv) {
  402. if ((time - startTime) / 1000 > totalTime) {
  403. return false;
  404. }
  405. for (int i = 0; i < events.Num(); i++) {
  406. if (time >= startTime + events[i]->getTime() && !events[i]->getTriggered()) {
  407. events[i]->setTriggered(true);
  408. if (events[i]->getType() == idCameraEvent::EVENT_TARGET) {
  409. setActiveTargetByName(events[i]->getParam());
  410. getActiveTarget()->start(startTime + events[i]->getTime());
  411. //Com_Printf("Triggered event switch to target: %s\n",events[i]->getParam());
  412. } else if (events[i]->getType() == idCameraEvent::EVENT_TRIGGER) {
  413. //idEntity *ent = NULL;
  414. //ent = level.FindTarget( ent, events[i]->getParam());
  415. //if (ent) {
  416. // ent->signal( SIG_TRIGGER );
  417. // ent->ProcessEvent( &EV_Activate, world );
  418. //}
  419. } else if (events[i]->getType() == idCameraEvent::EVENT_FOV) {
  420. //*fv = fov = atof(events[i]->getParam());
  421. } else if (events[i]->getType() == idCameraEvent::EVENT_STOP) {
  422. return false;
  423. }
  424. }
  425. }
  426. origin = *cameraPosition->getPosition(time);
  427. *fv = fov.getFOV(time);
  428. idVec3_t temp = origin;
  429. int numTargets = targetPositions.Num();
  430. if (numTargets == 0) {
  431. /*
  432. // follow the path
  433. if (cameraSpline.getActiveSegment() < count - 1) {
  434. temp = *cameraSpline.splinePoints[cameraSpline.getActiveSegment()+1];
  435. if (temp == origin) {
  436. int index = cameraSpline.getActiveSegment() + 2;
  437. while (temp == origin && index < count - 1) {
  438. temp = *cameraSpline.splinePoints[index++];
  439. }
  440. }
  441. }
  442. */
  443. } else {
  444. temp = *getActiveTarget()->getPosition(time);
  445. }
  446. temp -= origin;
  447. temp.Normalize();
  448. direction = temp;
  449. return true;
  450. }
  451. bool idCameraDef::waitEvent(int index) {
  452. //for (int i = 0; i < events.Num(); i++) {
  453. // if (events[i]->getSegment() == index && events[i]->getType() == idCameraEvent::EVENT_WAIT) {
  454. // return true;
  455. // }
  456. //}
  457. return false;
  458. }
  459. #define NUM_CCELERATION_SEGS 10
  460. #define CELL_AMT 5
  461. void idCameraDef::buildCamera() {
  462. int i;
  463. int lastSwitch = 0;
  464. idList<float> waits;
  465. idList<int> targets;
  466. totalTime = baseTime;
  467. cameraPosition->setTime(totalTime * 1000);
  468. // we have a base time layout for the path and the target path
  469. // now we need to layer on any wait or speed changes
  470. for (i = 0; i < events.Num(); i++) {
  471. idCameraEvent *ev = events[i];
  472. events[i]->setTriggered(false);
  473. switch (events[i]->getType()) {
  474. case idCameraEvent::EVENT_TARGET : {
  475. targets.Append(i);
  476. break;
  477. }
  478. case idCameraEvent::EVENT_WAIT : {
  479. waits.Append(atof(events[i]->getParam()));
  480. cameraPosition->addVelocity(events[i]->getTime(), atof(events[i]->getParam()) * 1000, 0);
  481. break;
  482. }
  483. case idCameraEvent::EVENT_TARGETWAIT : {
  484. //targetWaits.Append(i);
  485. break;
  486. }
  487. case idCameraEvent::EVENT_SPEED : {
  488. /*
  489. // take the average delay between up to the next five segments
  490. float adjust = atof(events[i]->getParam());
  491. int index = events[i]->getSegment();
  492. total = 0;
  493. count = 0;
  494. // get total amount of time over the remainder of the segment
  495. for (j = index; j < cameraSpline.numSegments() - 1; j++) {
  496. total += cameraSpline.getSegmentTime(j + 1) - cameraSpline.getSegmentTime(j);
  497. count++;
  498. }
  499. // multiply that by the adjustment
  500. double newTotal = total * adjust;
  501. // what is the difference..
  502. newTotal -= total;
  503. totalTime += newTotal / 1000;
  504. // per segment difference
  505. newTotal /= count;
  506. int additive = newTotal;
  507. // now propogate that difference out to each segment
  508. for (j = index; j < cameraSpline.numSegments(); j++) {
  509. cameraSpline.addSegmentTime(j, additive);
  510. additive += newTotal;
  511. }
  512. break;
  513. */
  514. }
  515. }
  516. }
  517. for (i = 0; i < waits.Num(); i++) {
  518. totalTime += waits[i];
  519. }
  520. // on a new target switch, we need to take time to this point ( since last target switch )
  521. // and allocate it across the active target, then reset time to this point
  522. long timeSoFar = 0;
  523. long total = totalTime * 1000;
  524. for (i = 0; i < targets.Num(); i++) {
  525. long t;
  526. if (i < targets.Num() - 1) {
  527. t = events[targets[i+1]]->getTime();
  528. } else {
  529. t = total - timeSoFar;
  530. }
  531. // t is how much time to use for this target
  532. setActiveTargetByName(events[targets[i]]->getParam());
  533. getActiveTarget()->setTime(t);
  534. timeSoFar += t;
  535. }
  536. }
  537. void idCameraDef::startCamera(long t) {
  538. buildCamera();
  539. cameraPosition->start(t);
  540. //for (int i = 0; i < targetPositions.Num(); i++) {
  541. // targetPositions[i]->
  542. //}
  543. startTime = t;
  544. cameraRunning = true;
  545. }
  546. void idCameraDef::parse(const char *(*text) ) {
  547. const char *token;
  548. do {
  549. token = Com_Parse( text );
  550. if ( !token[0] ) {
  551. break;
  552. }
  553. if ( !Q_stricmp (token, "}") ) {
  554. break;
  555. }
  556. if (Q_stricmp(token, "time") == 0) {
  557. baseTime = Com_ParseFloat(text);
  558. }
  559. if (Q_stricmp(token, "camera_fixed") == 0) {
  560. cameraPosition = new idFixedPosition();
  561. cameraPosition->parse(text);
  562. }
  563. if (Q_stricmp(token, "camera_interpolated") == 0) {
  564. cameraPosition = new idInterpolatedPosition();
  565. cameraPosition->parse(text);
  566. }
  567. if (Q_stricmp(token, "camera_spline") == 0) {
  568. cameraPosition = new idSplinePosition();
  569. cameraPosition->parse(text);
  570. }
  571. if (Q_stricmp(token, "target_fixed") == 0) {
  572. idFixedPosition *pos = new idFixedPosition();
  573. pos->parse(text);
  574. targetPositions.Append(pos);
  575. }
  576. if (Q_stricmp(token, "target_interpolated") == 0) {
  577. idInterpolatedPosition *pos = new idInterpolatedPosition();
  578. pos->parse(text);
  579. targetPositions.Append(pos);
  580. }
  581. if (Q_stricmp(token, "target_spline") == 0) {
  582. idSplinePosition *pos = new idSplinePosition();
  583. pos->parse(text);
  584. targetPositions.Append(pos);
  585. }
  586. if (Q_stricmp(token, "fov") == 0) {
  587. fov.parse(text);
  588. }
  589. if (Q_stricmp(token, "event") == 0) {
  590. idCameraEvent *event = new idCameraEvent();
  591. event->parse(text);
  592. addEvent(event);
  593. }
  594. } while (1);
  595. Com_UngetToken();
  596. Com_MatchToken( text, "}" );
  597. }
  598. bool idCameraDef::load(const char *filename) {
  599. char *buf;
  600. const char *buf_p;
  601. int length = FS_ReadFile( filename, (void **)&buf );
  602. if ( !buf ) {
  603. return false;
  604. }
  605. clear();
  606. Com_BeginParseSession( filename );
  607. buf_p = buf;
  608. parse(&buf_p);
  609. Com_EndParseSession();
  610. FS_FreeFile( buf );
  611. return true;
  612. }
  613. void idCameraDef::save(const char *filename) {
  614. fileHandle_t file = FS_FOpenFileWrite(filename);
  615. if (file) {
  616. int i;
  617. idStr s = "cameraPathDef { \n";
  618. FS_Write(s.c_str(), s.length(), file);
  619. s = va("\ttime %f\n", baseTime);
  620. FS_Write(s.c_str(), s.length(), file);
  621. cameraPosition->write(file, va("camera_%s",cameraPosition->typeStr()));
  622. for (i = 0; i < numTargets(); i++) {
  623. targetPositions[i]->write(file, va("target_%s", targetPositions[i]->typeStr()));
  624. }
  625. for (i = 0; i < events.Num(); i++) {
  626. events[i]->write(file, "event");
  627. }
  628. fov.write(file, "fov");
  629. s = "}\n";
  630. FS_Write(s.c_str(), s.length(), file);
  631. }
  632. FS_FCloseFile(file);
  633. }
  634. int idCameraDef::sortEvents(const void *p1, const void *p2) {
  635. idCameraEvent *ev1 = (idCameraEvent*)(p1);
  636. idCameraEvent *ev2 = (idCameraEvent*)(p2);
  637. if (ev1->getTime() > ev2->getTime()) {
  638. return -1;
  639. }
  640. if (ev1->getTime() < ev2->getTime()) {
  641. return 1;
  642. }
  643. return 0;
  644. }
  645. void idCameraDef::addEvent(idCameraEvent *event) {
  646. events.Append(event);
  647. //events.Sort(&sortEvents);
  648. }
  649. void idCameraDef::addEvent(idCameraEvent::eventType t, const char *param, long time) {
  650. addEvent(new idCameraEvent(t, param, time));
  651. buildCamera();
  652. }
  653. const char *idCameraEvent::eventStr[] = {
  654. "NA",
  655. "WAIT",
  656. "TARGETWAIT",
  657. "SPEED",
  658. "TARGET",
  659. "SNAPTARGET",
  660. "FOV",
  661. "SCRIPT",
  662. "TRIGGER",
  663. "STOP"
  664. };
  665. void idCameraEvent::parse(const char *(*text) ) {
  666. const char *token;
  667. Com_MatchToken( text, "{" );
  668. do {
  669. token = Com_Parse( text );
  670. if ( !token[0] ) {
  671. break;
  672. }
  673. if ( !strcmp (token, "}") ) {
  674. break;
  675. }
  676. // here we may have to jump over brush epairs ( only used in editor )
  677. do {
  678. // if token is not a brace, it is a key for a key/value pair
  679. if ( !token[0] || !strcmp (token, "(") || !strcmp(token, "}")) {
  680. break;
  681. }
  682. Com_UngetToken();
  683. idStr key = Com_ParseOnLine(text);
  684. const char *token = Com_Parse(text);
  685. if (Q_stricmp(key.c_str(), "type") == 0) {
  686. type = static_cast<idCameraEvent::eventType>(atoi(token));
  687. } else if (Q_stricmp(key.c_str(), "param") == 0) {
  688. paramStr = token;
  689. } else if (Q_stricmp(key.c_str(), "time") == 0) {
  690. time = atoi(token);
  691. }
  692. token = Com_Parse(text);
  693. } while (1);
  694. if ( !strcmp (token, "}") ) {
  695. break;
  696. }
  697. } while (1);
  698. Com_UngetToken();
  699. Com_MatchToken( text, "}" );
  700. }
  701. void idCameraEvent::write(fileHandle_t file, const char *name) {
  702. idStr s = va("\t%s {\n", name);
  703. FS_Write(s.c_str(), s.length(), file);
  704. s = va("\t\ttype %d\n", static_cast<int>(type));
  705. FS_Write(s.c_str(), s.length(), file);
  706. s = va("\t\tparam %s\n", paramStr.c_str());
  707. FS_Write(s.c_str(), s.length(), file);
  708. s = va("\t\ttime %d\n", time);
  709. FS_Write(s.c_str(), s.length(), file);
  710. s = "\t}\n";
  711. FS_Write(s.c_str(), s.length(), file);
  712. }
  713. const char *idCameraPosition::positionStr[] = {
  714. "Fixed",
  715. "Interpolated",
  716. "Spline",
  717. };
  718. const idVec3_t *idInterpolatedPosition::getPosition(long t) {
  719. static idVec3_t interpolatedPos;
  720. float velocity = getVelocity(t);
  721. float timePassed = t - lastTime;
  722. lastTime = t;
  723. // convert to seconds
  724. timePassed /= 1000;
  725. float distToTravel = timePassed *= velocity;
  726. idVec3_t temp = startPos;
  727. temp -= endPos;
  728. float distance = temp.Length();
  729. distSoFar += distToTravel;
  730. float percent = (float)(distSoFar) / distance;
  731. if (percent > 1.0) {
  732. percent = 1.0;
  733. } else if (percent < 0.0) {
  734. percent = 0.0;
  735. }
  736. // the following line does a straigt calc on percentage of time
  737. // float percent = (float)(startTime + time - t) / time;
  738. idVec3_t v1 = startPos;
  739. idVec3_t v2 = endPos;
  740. v1 *= (1.0 - percent);
  741. v2 *= percent;
  742. v1 += v2;
  743. interpolatedPos = v1;
  744. return &interpolatedPos;
  745. }
  746. void idCameraFOV::parse(const char *(*text) ) {
  747. const char *token;
  748. Com_MatchToken( text, "{" );
  749. do {
  750. token = Com_Parse( text );
  751. if ( !token[0] ) {
  752. break;
  753. }
  754. if ( !strcmp (token, "}") ) {
  755. break;
  756. }
  757. // here we may have to jump over brush epairs ( only used in editor )
  758. do {
  759. // if token is not a brace, it is a key for a key/value pair
  760. if ( !token[0] || !strcmp (token, "(") || !strcmp(token, "}")) {
  761. break;
  762. }
  763. Com_UngetToken();
  764. idStr key = Com_ParseOnLine(text);
  765. const char *token = Com_Parse(text);
  766. if (Q_stricmp(key.c_str(), "fov") == 0) {
  767. fov = atof(token);
  768. } else if (Q_stricmp(key.c_str(), "startFOV") == 0) {
  769. startFOV = atof(token);
  770. } else if (Q_stricmp(key.c_str(), "endFOV") == 0) {
  771. endFOV = atof(token);
  772. } else if (Q_stricmp(key.c_str(), "time") == 0) {
  773. time = atoi(token);
  774. }
  775. token = Com_Parse(text);
  776. } while (1);
  777. if ( !strcmp (token, "}") ) {
  778. break;
  779. }
  780. } while (1);
  781. Com_UngetToken();
  782. Com_MatchToken( text, "}" );
  783. }
  784. bool idCameraPosition::parseToken(const char *key, const char *(*text)) {
  785. const char *token = Com_Parse(text);
  786. if (Q_stricmp(key, "time") == 0) {
  787. time = atol(token);
  788. return true;
  789. } else if (Q_stricmp(key, "type") == 0) {
  790. type = static_cast<idCameraPosition::positionType>(atoi(token));
  791. return true;
  792. } else if (Q_stricmp(key, "velocity") == 0) {
  793. long t = atol(token);
  794. token = Com_Parse(text);
  795. long d = atol(token);
  796. token = Com_Parse(text);
  797. float s = atof(token);
  798. addVelocity(t, d, s);
  799. return true;
  800. } else if (Q_stricmp(key, "baseVelocity") == 0) {
  801. baseVelocity = atof(token);
  802. return true;
  803. } else if (Q_stricmp(key, "name") == 0) {
  804. name = token;
  805. return true;
  806. } else if (Q_stricmp(key, "time") == 0) {
  807. time = atoi(token);
  808. return true;
  809. }
  810. Com_UngetToken();
  811. return false;
  812. }
  813. void idFixedPosition::parse(const char *(*text) ) {
  814. const char *token;
  815. Com_MatchToken( text, "{" );
  816. do {
  817. token = Com_Parse( text );
  818. if ( !token[0] ) {
  819. break;
  820. }
  821. if ( !strcmp (token, "}") ) {
  822. break;
  823. }
  824. // here we may have to jump over brush epairs ( only used in editor )
  825. do {
  826. // if token is not a brace, it is a key for a key/value pair
  827. if ( !token[0] || !strcmp (token, "(") || !strcmp(token, "}")) {
  828. break;
  829. }
  830. Com_UngetToken();
  831. idStr key = Com_ParseOnLine(text);
  832. const char *token = Com_Parse(text);
  833. if (Q_stricmp(key.c_str(), "pos") == 0) {
  834. Com_UngetToken();
  835. Com_Parse1DMatrix( text, 3, pos );
  836. } else {
  837. Com_UngetToken();
  838. idCameraPosition::parseToken(key.c_str(), text);
  839. }
  840. token = Com_Parse(text);
  841. } while (1);
  842. if ( !strcmp (token, "}") ) {
  843. break;
  844. }
  845. } while (1);
  846. Com_UngetToken();
  847. Com_MatchToken( text, "}" );
  848. }
  849. void idInterpolatedPosition::parse(const char *(*text) ) {
  850. const char *token;
  851. Com_MatchToken( text, "{" );
  852. do {
  853. token = Com_Parse( text );
  854. if ( !token[0] ) {
  855. break;
  856. }
  857. if ( !strcmp (token, "}") ) {
  858. break;
  859. }
  860. // here we may have to jump over brush epairs ( only used in editor )
  861. do {
  862. // if token is not a brace, it is a key for a key/value pair
  863. if ( !token[0] || !strcmp (token, "(") || !strcmp(token, "}")) {
  864. break;
  865. }
  866. Com_UngetToken();
  867. idStr key = Com_ParseOnLine(text);
  868. const char *token = Com_Parse(text);
  869. if (Q_stricmp(key.c_str(), "startPos") == 0) {
  870. Com_UngetToken();
  871. Com_Parse1DMatrix( text, 3, startPos );
  872. } else if (Q_stricmp(key.c_str(), "endPos") == 0) {
  873. Com_UngetToken();
  874. Com_Parse1DMatrix( text, 3, endPos );
  875. } else {
  876. Com_UngetToken();
  877. idCameraPosition::parseToken(key.c_str(), text);
  878. }
  879. token = Com_Parse(text);
  880. } while (1);
  881. if ( !strcmp (token, "}") ) {
  882. break;
  883. }
  884. } while (1);
  885. Com_UngetToken();
  886. Com_MatchToken( text, "}" );
  887. }
  888. void idSplinePosition::parse(const char *(*text) ) {
  889. const char *token;
  890. Com_MatchToken( text, "{" );
  891. do {
  892. token = Com_Parse( text );
  893. if ( !token[0] ) {
  894. break;
  895. }
  896. if ( !strcmp (token, "}") ) {
  897. break;
  898. }
  899. // here we may have to jump over brush epairs ( only used in editor )
  900. do {
  901. // if token is not a brace, it is a key for a key/value pair
  902. if ( !token[0] || !strcmp (token, "(") || !strcmp(token, "}")) {
  903. break;
  904. }
  905. Com_UngetToken();
  906. idStr key = Com_ParseOnLine(text);
  907. const char *token = Com_Parse(text);
  908. if (Q_stricmp(key.c_str(), "target") == 0) {
  909. target.parse(text);
  910. } else {
  911. Com_UngetToken();
  912. idCameraPosition::parseToken(key.c_str(), text);
  913. }
  914. token = Com_Parse(text);
  915. } while (1);
  916. if ( !strcmp (token, "}") ) {
  917. break;
  918. }
  919. } while (1);
  920. Com_UngetToken();
  921. Com_MatchToken( text, "}" );
  922. }
  923. void idCameraFOV::write(fileHandle_t file, const char *p) {
  924. idStr s = va("\t%s {\n", p);
  925. FS_Write(s.c_str(), s.length(), file);
  926. s = va("\t\tfov %f\n", fov);
  927. FS_Write(s.c_str(), s.length(), file);
  928. s = va("\t\tstartFOV %f\n", startFOV);
  929. FS_Write(s.c_str(), s.length(), file);
  930. s = va("\t\tendFOV %f\n", endFOV);
  931. FS_Write(s.c_str(), s.length(), file);
  932. s = va("\t\ttime %i\n", time);
  933. FS_Write(s.c_str(), s.length(), file);
  934. s = "\t}\n";
  935. FS_Write(s.c_str(), s.length(), file);
  936. }
  937. void idCameraPosition::write(fileHandle_t file, const char *p) {
  938. idStr s = va("\t\ttime %i\n", time);
  939. FS_Write(s.c_str(), s.length(), file);
  940. s = va("\t\ttype %i\n", static_cast<int>(type));
  941. FS_Write(s.c_str(), s.length(), file);
  942. s = va("\t\tname %s\n", name.c_str());
  943. FS_Write(s.c_str(), s.length(), file);
  944. s = va("\t\tbaseVelocity %f\n", baseVelocity);
  945. FS_Write(s.c_str(), s.length(), file);
  946. for (int i = 0; i < velocities.Num(); i++) {
  947. s = va("\t\tvelocity %i %i %f\n", velocities[i]->startTime, velocities[i]->time, velocities[i]->speed);
  948. FS_Write(s.c_str(), s.length(), file);
  949. }
  950. }
  951. void idFixedPosition::write(fileHandle_t file, const char *p) {
  952. idStr s = va("\t%s {\n", p);
  953. FS_Write(s.c_str(), s.length(), file);
  954. idCameraPosition::write(file, p);
  955. s = va("\t\tpos ( %f %f %f )\n", pos.x, pos.y, pos.z);
  956. FS_Write(s.c_str(), s.length(), file);
  957. s = "\t}\n";
  958. FS_Write(s.c_str(), s.length(), file);
  959. }
  960. void idInterpolatedPosition::write(fileHandle_t file, const char *p) {
  961. idStr s = va("\t%s {\n", p);
  962. FS_Write(s.c_str(), s.length(), file);
  963. idCameraPosition::write(file, p);
  964. s = va("\t\tstartPos ( %f %f %f )\n", startPos.x, startPos.y, startPos.z);
  965. FS_Write(s.c_str(), s.length(), file);
  966. s = va("\t\tendPos ( %f %f %f )\n", endPos.x, endPos.y, endPos.z);
  967. FS_Write(s.c_str(), s.length(), file);
  968. s = "\t}\n";
  969. FS_Write(s.c_str(), s.length(), file);
  970. }
  971. void idSplinePosition::write(fileHandle_t file, const char *p) {
  972. idStr s = va("\t%s {\n", p);
  973. FS_Write(s.c_str(), s.length(), file);
  974. idCameraPosition::write(file, p);
  975. target.write(file, "target");
  976. s = "\t}\n";
  977. FS_Write(s.c_str(), s.length(), file);
  978. }
  979. void idCameraDef::addTarget(const char *name, idCameraPosition::positionType type) {
  980. const char *text = (name == NULL) ? va("target0%d", numTargets()+1) : name;
  981. idCameraPosition *pos = newFromType(type);
  982. if (pos) {
  983. pos->setName(name);
  984. targetPositions.Append(pos);
  985. activeTarget = numTargets()-1;
  986. if (activeTarget == 0) {
  987. // first one
  988. addEvent(idCameraEvent::EVENT_TARGET, name, 0);
  989. }
  990. }
  991. }
  992. idCameraDef camera;
  993. extern "C" {
  994. qboolean loadCamera(const char *name) {
  995. camera.clear();
  996. return static_cast<qboolean>(camera.load(name));
  997. }
  998. qboolean getCameraInfo(int time, float *origin, float*angles) {
  999. idVec3_t dir, org;
  1000. org[0] = origin[0];
  1001. org[1] = origin[1];
  1002. org[2] = origin[2];
  1003. float fov = 90;
  1004. if (camera.getCameraInfo(time, org, dir, &fov)) {
  1005. origin[0] = org[0];
  1006. origin[1] = org[1];
  1007. origin[2] = org[2];
  1008. angles[1] = atan2 (dir[1], dir[0])*180/3.14159;
  1009. angles[0] = asin (dir[2])*180/3.14159;
  1010. return qtrue;
  1011. }
  1012. return qfalse;
  1013. }
  1014. void startCamera(int time) {
  1015. camera.startCamera(time);
  1016. }
  1017. }