splines.cpp 29 KB

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