Quake-III-Arena

Quake III Arena GPL Source Release
Log | Files | Refs

splines.h (20759B)


      1 /*
      2 ===========================================================================
      3 Copyright (C) 1999-2005 Id Software, Inc.
      4 
      5 This file is part of Quake III Arena source code.
      6 
      7 Quake III Arena source code is free software; you can redistribute it
      8 and/or modify it under the terms of the GNU General Public License as
      9 published by the Free Software Foundation; either version 2 of the License,
     10 or (at your option) any later version.
     11 
     12 Quake III Arena source code is distributed in the hope that it will be
     13 useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
     14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     15 GNU General Public License for more details.
     16 
     17 You should have received a copy of the GNU General Public License
     18 along with Foobar; if not, write to the Free Software
     19 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
     20 ===========================================================================
     21 */
     22 #ifndef __SPLINES_H
     23 #define __SPLINES_H
     24 
     25 extern "C" {
     26 #ifdef Q3RADIANT
     27 #include "../qgl.h"
     28 #else
     29 //#include "../renderer/qgl.h"
     30 #endif
     31 }
     32 #include "util_list.h"
     33 #include "util_str.h"
     34 #include "math_vector.h"
     35 
     36 typedef int fileHandle_t;
     37 
     38 //extern void glBox(idVec3_t &color, idVec3_t &point, float size);
     39 //extern void glLabeledPoint(idVec3_t &color, idVec3_t &point, float size, const char *label);
     40 
     41 static vec4_t blue(0, 0, 1, 1);
     42 static vec4_t red(1, 0, 0, 1);
     43 
     44 class idPointListInterface {
     45 public:
     46 	idPointListInterface() {
     47 		selectedPoints.Clear();
     48 	}
     49 	virtual ~idPointListInterface() {}
     50 	
     51 	virtual int numPoints() {
     52 		return 0;
     53 	}
     54 	
     55 	virtual void addPoint(const float x, const float y, const float z) {}
     56 	virtual void addPoint(const idVec3_t &v) {}
     57 	virtual void removePoint(int index) {}
     58 	virtual idVec3_t *getPoint(int index) { return NULL; }
     59 	
     60 	int	selectPointByRay(float ox, float oy, float oz, float dx, float dy, float dz, bool single) {
     61 		idVec3_t origin(ox, oy, oz);
     62 		idVec3_t dir(dx, dy, dz);
     63 		return selectPointByRay(origin, dir, single);
     64 	}
     65 
     66 	int	selectPointByRay(const idVec3_t origin, const idVec3_t direction, bool single) {
     67 		int		i, besti, count;
     68 		float	d, bestd;
     69 		idVec3_t	temp, temp2;
     70 
     71 		// find the point closest to the ray
     72 		besti = -1;
     73 		bestd = 8;
     74 		count = numPoints();
     75 
     76 		for (i=0; i < count; i++) {
     77 			temp = *getPoint(i);
     78 			temp2 = temp;
     79 			temp -= origin;
     80 			d = DotProduct(temp, direction);
     81 			__VectorMA (origin, d, direction, temp);
     82 			temp2 -= temp;
     83 			d = temp2.Length();
     84 			if (d <= bestd) {
     85 				bestd = d;
     86 				besti = i;
     87 			}
     88 		}
     89 
     90 		if (besti >= 0) {
     91 			selectPoint(besti, single);
     92 		}
     93 
     94 		return besti;
     95 	}
     96 
     97 	int isPointSelected(int index) {
     98 		int count = selectedPoints.Num();
     99 		for (int i = 0; i < count; i++) {
    100 			if (selectedPoints[i] == index) {
    101 				return i;
    102 			}
    103 		}
    104 		return -1;
    105 	}
    106 	
    107 	int selectPoint(int index, bool single) {
    108 		if (index >= 0 && index < numPoints()) {
    109 			if (single) {
    110 				deselectAll();
    111 			} else {
    112 				if (isPointSelected(index) >= 0) {
    113 					selectedPoints.Remove(index);
    114 				}
    115 			}
    116 			return selectedPoints.Append(index);
    117 		}
    118 		return -1;
    119 	}
    120 	
    121 	void selectAll() {
    122 		selectedPoints.Clear();
    123 		for (int i = 0; i < numPoints(); i++) {
    124 			selectedPoints.Append(i);
    125 		}
    126 	}
    127 
    128 	void deselectAll() {
    129 		selectedPoints.Clear();
    130 	}
    131 
    132 	virtual void updateSelection(float x, float y, float z) {
    133 		idVec3_t move(x, y, z);
    134 		updateSelection(move);
    135 	}
    136 
    137 	virtual void updateSelection(const idVec3_t &move) {
    138 		int count = selectedPoints.Num();
    139 		for (int i = 0; i < count; i++) {
    140 			*getPoint(selectedPoints[i]) += move;
    141 		}
    142 	}
    143 /*
    144 	void drawSelection() {
    145 		int count = selectedPoints.Num();
    146 		for (int i = 0; i < count; i++) {
    147 			glBox(red, *getPoint(selectedPoints[i]), 4);
    148 		}
    149 	}
    150 */
    151 protected:
    152 	idList<int> selectedPoints;
    153 
    154 };
    155 
    156 
    157 class idSplineList {
    158 
    159 public:
    160 
    161 	idSplineList() {
    162 		clear();
    163 	}
    164 
    165 	idSplineList(const char *p) {
    166 		clear();
    167 		name = p;
    168 	};
    169 
    170 	~idSplineList() {
    171 		clear();
    172 	};
    173 
    174 	void clearControl() {
    175 		for (int i = 0; i < controlPoints.Num(); i++) {
    176 			delete controlPoints[i];
    177 		}
    178 		controlPoints.Clear();
    179 	}
    180 
    181 	void clearSpline() {
    182 		for (int i = 0; i < splinePoints.Num(); i++) {
    183 			delete splinePoints[i];
    184 		}
    185 		splinePoints.Clear();
    186 	}
    187 
    188 	void parse(const char *(*text));
    189 	void write(fileHandle_t file, const char *name);
    190 
    191 	void clear() {
    192 		clearControl();
    193 		clearSpline();
    194 		splineTime.Clear();
    195 		selected = NULL;
    196 		dirty = true;
    197 		activeSegment = 0;
    198 		granularity = 0.025;
    199 		pathColor.set(1.0, 0.5, 0.0);
    200 		controlColor.set(0.7, 0.0, 1.0);
    201 		segmentColor.set(0.0, 0.0, 1.0);
    202 		activeColor.set(1.0, 0.0, 0.0);
    203 	}
    204 
    205 	void initPosition(long startTime, long totalTime);
    206 	const idVec3_t *getPosition(long time);
    207 
    208 
    209 //	void draw(bool editMode);
    210 	void addToRenderer();
    211 
    212 	void setSelectedPoint(idVec3_t *p);
    213 	idVec3_t *getSelectedPoint() {
    214 	  return selected;
    215 	}
    216 
    217 	void addPoint(const idVec3_t &v) {
    218 		controlPoints.Append(new idVec3_t(v));
    219 		dirty = true;
    220 	}
    221 
    222 	void addPoint(float x, float y, float z) {
    223 		controlPoints.Append(new idVec3_t(x, y, z));
    224 		dirty = true;
    225 	}
    226 
    227 	void updateSelection(const idVec3_t &move);
    228 
    229 	void startEdit() {
    230 		editMode = true;
    231 	}
    232 		
    233 	void stopEdit() {
    234 		editMode = false;
    235 	}
    236 
    237 	void buildSpline();
    238 
    239 	void setGranularity(float f) {
    240 		granularity = f;
    241 	}
    242 
    243 	float getGranularity() {
    244 		return granularity;
    245 	}
    246 
    247 	int numPoints() {
    248 		return controlPoints.Num();
    249 	}
    250 
    251 	idVec3_t *getPoint(int index) {
    252 		assert(index >= 0 && index < controlPoints.Num());
    253 		return controlPoints[index];
    254 	}
    255 
    256 	idVec3_t *getSegmentPoint(int index) {
    257 		assert(index >= 0 && index < splinePoints.Num());
    258 		return splinePoints[index];
    259 	}
    260 
    261 
    262 	void setSegmentTime(int index, int time) {
    263 		assert(index >= 0 && index < splinePoints.Num());
    264 		splineTime[index] = time;
    265 	}
    266 
    267 	double getSegmentTime(int index) {
    268 		assert(index >= 0 && index < splinePoints.Num());
    269 		return splineTime[index];
    270 	}
    271 	void addSegmentTime(int index, int time) {
    272 		assert(index >= 0 && index < splinePoints.Num());
    273 		splineTime[index] += time;
    274 	}
    275 
    276 	float totalDistance();
    277 
    278 	static idVec3_t zero;
    279 
    280 	int getActiveSegment() {
    281 		return activeSegment;
    282 	}
    283 
    284 	void setActiveSegment(int i) {
    285 		//assert(i >= 0 && (splinePoints.Num() > 0 && i < splinePoints.Num()));
    286 		activeSegment = i;
    287 	}
    288 
    289 	int numSegments() {
    290 		return splinePoints.Num();
    291 	}
    292 
    293 	void setColors(idVec3_t &path, idVec3_t &segment, idVec3_t &control, idVec3_t &active) {
    294 		pathColor = path;
    295 		segmentColor = segment;
    296 		controlColor = control;
    297 		activeColor = active;
    298 	}
    299 
    300 	const char *getName() {
    301 		return name.c_str();
    302 	}
    303 
    304 	void setName(const char *p) {
    305 		name = p;
    306 	}
    307 
    308 	bool validTime() {
    309 		if (dirty) {
    310 			buildSpline();
    311 		}
    312 		// gcc doesn't allow static casting away from bools
    313 		// why?  I've no idea...
    314 		return (bool)(splineTime.Num() > 0 && splineTime.Num() == splinePoints.Num());
    315 	}
    316 
    317 	void setTime(long t) {
    318 		time = t;
    319 	}
    320 
    321 	void setBaseTime(long t) {
    322 		baseTime = t;
    323 	}
    324 
    325 protected:
    326 	idStr name;
    327 	float calcSpline(int step, float tension);
    328 	idList<idVec3_t*> controlPoints;
    329 	idList<idVec3_t*> splinePoints;
    330 	idList<double> splineTime;
    331 	idVec3_t *selected;
    332 	idVec3_t pathColor, segmentColor, controlColor, activeColor;
    333 	float granularity;
    334 	bool editMode;
    335 	bool dirty;
    336 	int activeSegment;
    337 	long baseTime;
    338 	long time;
    339 	friend class idCamera;
    340 };
    341 
    342 // time in milliseconds 
    343 // velocity where 1.0 equal rough walking speed
    344 struct idVelocity {
    345 	idVelocity(long start, long duration, float s) {
    346 		startTime = start;
    347 		time = duration;
    348 		speed = s;
    349 	}
    350 	long	startTime;
    351 	long	time;
    352 	float	speed;
    353 };
    354 
    355 // can either be a look at or origin position for a camera
    356 // 
    357 class idCameraPosition : public idPointListInterface {
    358 public:
    359 	
    360 	virtual void clear() {
    361 		editMode = false;
    362 		for (int i = 0; i < velocities.Num(); i++) {
    363 			delete velocities[i];
    364 			velocities[i] = NULL;
    365 		}
    366 		velocities.Clear();
    367 	}
    368 
    369 	idCameraPosition(const char *p) {
    370 		name = p;
    371 	}
    372 
    373 	idCameraPosition() {
    374 		time = 0;
    375 		name = "position";
    376 	}
    377 
    378 	idCameraPosition(long t) {
    379 		time = t;
    380 	}
    381 
    382 	virtual ~idCameraPosition() {
    383 		clear();
    384 	}
    385 
    386 	
    387 	// this can be done with RTTI syntax but i like the derived classes setting a type
    388 	// makes serialization a bit easier to see
    389 	//
    390 	enum positionType {
    391 		FIXED = 0x00,
    392 		INTERPOLATED,
    393 		SPLINE,
    394 		POSITION_COUNT
    395 	};
    396 
    397 
    398 	virtual void start(long t) {
    399 		startTime = t;
    400 	}
    401 
    402 	long getTime() {
    403 		return time;
    404 	}
    405 
    406 	virtual void setTime(long t) {
    407 		time = t;
    408 	}
    409 
    410 	float getVelocity(long t) {
    411 		long check = t - startTime;
    412 		for (int i = 0; i < velocities.Num(); i++) {
    413 			if (check >= velocities[i]->startTime && check <= velocities[i]->startTime + velocities[i]->time) {
    414 				return velocities[i]->speed;
    415 			}
    416 		}
    417 		return baseVelocity;
    418 	}
    419 
    420 	void addVelocity(long start, long duration, float speed) {
    421 		velocities.Append(new idVelocity(start, duration, speed));
    422 	}
    423 
    424 	virtual const idVec3_t *getPosition(long t) { 
    425 		assert(true);
    426 		return NULL;
    427 	}
    428 
    429 //	virtual void draw(bool editMode) {};
    430 
    431 	virtual void parse(const char *(*text)) {};
    432 	virtual void write(fileHandle_t file, const char *name);
    433 	virtual bool parseToken(const char *key, const char *(*text));
    434 
    435 	const char *getName() {
    436 		return name.c_str();
    437 	}
    438 
    439 	void setName(const char *p) {
    440 		name = p;
    441 	}
    442 
    443 	virtual void startEdit() {
    444 		editMode = true;
    445 	}
    446 
    447 	virtual void stopEdit() {
    448 		editMode = false;
    449 	}
    450 
    451 //	virtual void draw() {};
    452 
    453 	const char *typeStr() {
    454 		return positionStr[static_cast<int>(type)];
    455 	}
    456 
    457 	void calcVelocity(float distance) {
    458 		float secs = (float)time / 1000;
    459 		baseVelocity = distance / secs;
    460 	}
    461 
    462 protected:
    463 	static const char* positionStr[POSITION_COUNT];
    464 	long		startTime;
    465 	long		time;
    466 	idCameraPosition::positionType type;
    467 	idStr		name;
    468 	bool	editMode;
    469 	idList<idVelocity*> velocities;
    470 	float		baseVelocity;
    471 };
    472 
    473 class idFixedPosition : public idCameraPosition {
    474 public:
    475 
    476 	void init() {
    477 		pos.Zero();
    478 		type = idCameraPosition::FIXED;
    479 	}
    480 	
    481 	idFixedPosition() : idCameraPosition() {
    482 		init();
    483 	}
    484 	
    485 	idFixedPosition(idVec3_t p) : idCameraPosition() {
    486 		init();
    487 		pos = p;
    488 	}
    489 
    490 	virtual void addPoint(const idVec3_t &v) {
    491 		pos = v;
    492 	}
    493 	
    494 	virtual void addPoint(const float x, const float y, const float z) {
    495 		pos.set(x, y, z);
    496 	}
    497 
    498 
    499 	~idFixedPosition() {
    500 	}
    501 
    502 	virtual const idVec3_t *getPosition(long t) { 
    503 		return &pos;
    504 	}
    505 
    506 	void parse(const char *(*text));
    507 	void write(fileHandle_t file, const char *name);
    508 
    509 	virtual int numPoints() {
    510 		return 1;
    511 	}
    512 
    513 	virtual idVec3_t *getPoint(int index) {
    514 		if (index != 0) {
    515 			assert(true);
    516 		};
    517 		return &pos;
    518 	}
    519 /*
    520 	virtual void draw(bool editMode) {
    521 		glLabeledPoint(blue, pos, (editMode) ? 5 : 3, "Fixed point");
    522 	}
    523 */
    524 protected:
    525 	idVec3_t pos;
    526 };
    527 
    528 class idInterpolatedPosition : public idCameraPosition {
    529 public:
    530 
    531 	void init() {
    532 		type = idCameraPosition::INTERPOLATED;
    533 		first = true;
    534 		startPos.Zero();
    535 		endPos.Zero();
    536 	}
    537 	
    538 	idInterpolatedPosition() : idCameraPosition() {
    539 		init();
    540 	}
    541 	
    542 	idInterpolatedPosition(idVec3_t start, idVec3_t end, long time) : idCameraPosition(time) {
    543 		init();
    544 		startPos = start;
    545 		endPos = end;
    546 	}
    547 
    548 	~idInterpolatedPosition() {
    549 	}
    550 
    551 	virtual const idVec3_t *getPosition(long t);
    552 
    553 	void parse(const char *(*text));
    554 	void write(fileHandle_t file, const char *name);
    555 
    556 	virtual int numPoints() {
    557 		return 2;
    558 	}
    559 
    560 	virtual idVec3_t *getPoint(int index) {
    561 		assert(index >= 0 && index < 2);
    562 		if (index == 0) {
    563 			return &startPos;
    564 		}
    565 		return &endPos;
    566 	}
    567 
    568 	virtual void addPoint(const float x, const float y, const float z) {
    569 		if (first) {
    570 			startPos.set(x, y, z);
    571 			first = false;
    572 		} else {
    573 			endPos.set(x, y, z);
    574 			first = true;
    575 		}
    576 	}
    577 
    578 	virtual void addPoint(const idVec3_t &v) {
    579 		if (first) {
    580 			startPos = v;
    581 			first = false;
    582 		} else {
    583 			endPos = v;
    584 			first = true;
    585 		}
    586 	}
    587 /*
    588 	virtual void draw(bool editMode) {
    589 		glLabeledPoint(blue, startPos, (editMode) ? 5 : 3, "Start interpolated");
    590 		glLabeledPoint(blue, endPos, (editMode) ? 5 : 3, "End interpolated");
    591 		qglBegin(GL_LINES);
    592 		qglVertex3fv(startPos);
    593 		qglVertex3fv(endPos);
    594 		qglEnd();
    595 	}
    596 */
    597 	virtual void start(long t) {
    598 		idCameraPosition::start(t);
    599 		lastTime = startTime;
    600 		distSoFar = 0.0;
    601 		idVec3_t temp = startPos;
    602 		temp -= endPos;
    603 		calcVelocity(temp.Length());
    604 	}
    605 
    606 protected:
    607 	bool first;
    608 	idVec3_t startPos;
    609 	idVec3_t endPos;
    610 	long lastTime;
    611 	float distSoFar;
    612 };
    613 
    614 class idSplinePosition : public idCameraPosition {
    615 public:
    616 
    617 	void init() {
    618 		type = idCameraPosition::SPLINE;
    619 	}
    620 	
    621 	idSplinePosition() : idCameraPosition() {
    622 		init();
    623 	}
    624 	
    625 	idSplinePosition(long time) : idCameraPosition(time) {
    626 		init();
    627 	}
    628 
    629 	~idSplinePosition() {
    630 	}
    631 
    632 	virtual void start(long t) {
    633 		idCameraPosition::start(t);
    634 		target.initPosition(t, time);
    635 		calcVelocity(target.totalDistance());
    636 	}
    637 
    638 	virtual const idVec3_t *getPosition(long t) { 
    639 		return target.getPosition(t);
    640 	}
    641 
    642 	//virtual const idVec3_t *getPosition(long t) const { 
    643 
    644 	void addControlPoint(idVec3_t &v) {
    645 		target.addPoint(v);
    646 	}
    647 
    648 	void parse(const char *(*text));
    649 	void write(fileHandle_t file, const char *name);
    650 
    651 	virtual int numPoints() {
    652 		return target.numPoints();
    653 	}
    654 
    655 	virtual idVec3_t *getPoint(int index) {
    656 		return target.getPoint(index);
    657 	}
    658 
    659 	virtual void addPoint(const idVec3_t &v) {
    660 		target.addPoint(v);
    661 	}
    662 
    663 	virtual void addPoint(const float x, const float y, const float z) {
    664 		target.addPoint(x, y, z);
    665 	}
    666 
    667 /*	virtual void draw(bool editMode) {
    668 		target.draw(editMode);
    669 	}
    670 */
    671 	virtual void updateSelection(const idVec3_t &move) {
    672 		idCameraPosition::updateSelection(move);
    673 		target.buildSpline();
    674 	}
    675 
    676 protected:
    677 	idSplineList target;
    678 };
    679 
    680 class idCameraFOV {
    681 public:
    682 	
    683 	idCameraFOV() {
    684 		time = 0;
    685 		fov = 90;
    686 	}
    687 
    688 	idCameraFOV(int v) {
    689 		time = 0;
    690 		fov = v;
    691 	}
    692 
    693 	idCameraFOV(int s, int e, long t) {
    694 		startFOV = s;
    695 		endFOV = e;
    696 		time = t;
    697 	}
    698 
    699 
    700 	~idCameraFOV(){}
    701 
    702 	void setFOV(float f) {
    703 		fov = f;
    704 	}
    705 
    706 	float getFOV(long t) {
    707 		if (time) {
    708 			assert(startTime);
    709 			float percent = t / startTime;
    710 			float temp = startFOV - endFOV;
    711 			temp *= percent;
    712 			fov = startFOV + temp;
    713 		}
    714 		return fov;
    715 	}
    716 
    717 	void start(long t) {
    718 		startTime = t;
    719 	}
    720 
    721 	void parse(const char *(*text));
    722 	void write(fileHandle_t file, const char *name);
    723 
    724 protected:
    725 	float fov;
    726 	float startFOV;
    727 	float endFOV;
    728 	int startTime;
    729 	int time;
    730 };
    731 
    732 
    733 
    734 
    735 class idCameraEvent {
    736 public:
    737 	enum eventType {
    738 		EVENT_NA = 0x00,
    739 		EVENT_WAIT,
    740 		EVENT_TARGETWAIT,
    741 		EVENT_SPEED,
    742 		EVENT_TARGET,
    743 		EVENT_SNAPTARGET,
    744 		EVENT_FOV,
    745 		EVENT_SCRIPT,
    746 		EVENT_TRIGGER,
    747 		EVENT_STOP,
    748 		EVENT_COUNT
    749 	};
    750 
    751 	static const char* eventStr[EVENT_COUNT];
    752 
    753 	idCameraEvent() {
    754 		paramStr = "";
    755 		type = EVENT_NA;
    756 		time = 0;
    757 	}
    758 
    759 	idCameraEvent(eventType t, const char *param, long n) {
    760 		type = t;
    761 		paramStr = param;
    762 		time = n;
    763 	}
    764 
    765 	~idCameraEvent() {};
    766 
    767 	eventType getType() {
    768 		return type;
    769 	}
    770 
    771 	const char *typeStr() {
    772 		return eventStr[static_cast<int>(type)];
    773 	}
    774 
    775 	const char *getParam() {
    776 		return paramStr.c_str();
    777 	}
    778 
    779 	long getTime() {
    780 		return time;
    781 	}
    782 
    783 	void setTime(long n) {
    784 		time = n;
    785 	}
    786 
    787 	void parse(const char *(*text));
    788 	void write(fileHandle_t file, const char *name);
    789 
    790 	void setTriggered(bool b) {
    791 		triggered = b;
    792 	}
    793 
    794 	bool getTriggered() {
    795 		return triggered;
    796 	}
    797 
    798 protected:
    799 	eventType type;
    800 	idStr paramStr;
    801 	long time;
    802 	bool triggered;
    803 
    804 };
    805 
    806 class idCameraDef {
    807 public:
    808 
    809 	void clear() {
    810 		currentCameraPosition = 0;
    811 		cameraRunning = false;
    812 		lastDirection.Zero();
    813 		baseTime = 30;
    814 		activeTarget = 0;
    815 		name = "camera01";
    816 		fov.setFOV(90);
    817 		int i;
    818 		for (i = 0; i < targetPositions.Num(); i++) {
    819 			delete targetPositions[i];
    820 		}
    821 		for (i = 0; i < events.Num(); i++) {
    822 			delete events[i];
    823 		}
    824 		delete cameraPosition;
    825 		cameraPosition = NULL;
    826 		events.Clear();
    827 		targetPositions.Clear();
    828 	}
    829 
    830 	idCameraPosition *startNewCamera(idCameraPosition::positionType type) {
    831 		clear();
    832 		if (type == idCameraPosition::SPLINE) {
    833 			cameraPosition = new idSplinePosition();
    834 		} else if (type == idCameraPosition::INTERPOLATED) {
    835 			cameraPosition = new idInterpolatedPosition();
    836 		} else {
    837 			cameraPosition = new idFixedPosition();
    838 		}
    839 		return cameraPosition;
    840 	}
    841 
    842 	idCameraDef() {
    843 		clear();
    844 	}
    845 
    846 	~idCameraDef() {
    847 		clear();
    848 	}
    849 
    850 	void addEvent(idCameraEvent::eventType t, const char *param, long time);
    851 
    852 	void addEvent(idCameraEvent *event);
    853 
    854 	static int sortEvents(const void *p1, const void *p2);
    855 
    856 	int numEvents() {
    857 		return events.Num();
    858 	}
    859 
    860 	idCameraEvent *getEvent(int index) {
    861 		assert(index >= 0 && index < events.Num());
    862 		return events[index];
    863 	}
    864 
    865 	void parse(const char *(*text));
    866 	qboolean load(const char *filename);
    867 	void save(const char *filename);
    868 
    869 	void buildCamera();
    870 
    871 	//idSplineList *getcameraPosition() {
    872 	//	return &cameraPosition;
    873 	//}
    874 
    875 	static idCameraPosition *newFromType(idCameraPosition::positionType t) {
    876 		switch (t) {
    877 			case idCameraPosition::FIXED : return new idFixedPosition();
    878 			case idCameraPosition::INTERPOLATED : return new idInterpolatedPosition();
    879     case idCameraPosition::SPLINE : return new idSplinePosition();
    880     default:
    881         break;
    882 		};
    883 		return NULL;
    884 	}
    885 
    886 	void addTarget(const char *name, idCameraPosition::positionType type);
    887 
    888 	idCameraPosition *getActiveTarget() {
    889 		if (targetPositions.Num() == 0) {
    890 			addTarget(NULL, idCameraPosition::FIXED);
    891 		}
    892 		return targetPositions[activeTarget];
    893 	}
    894 
    895 	idCameraPosition *getActiveTarget(int index) {
    896 		if (targetPositions.Num() == 0) {
    897 			addTarget(NULL, idCameraPosition::FIXED);
    898 			return targetPositions[0];
    899 		}
    900 		return targetPositions[index];
    901 	}
    902 
    903 	int numTargets() {
    904 		return targetPositions.Num();
    905 	}
    906 
    907 
    908 	void setActiveTargetByName(const char *name) {
    909 		for (int i = 0; i < targetPositions.Num(); i++) {
    910 			if (Q_stricmp(name, targetPositions[i]->getName()) == 0) {
    911 				setActiveTarget(i);
    912 				return;
    913 			}
    914 		}
    915 	}
    916 
    917 	void setActiveTarget(int index) {
    918 		assert(index >= 0 && index < targetPositions.Num());
    919 		activeTarget = index;
    920 	}
    921 
    922 	void setRunning(bool b) {
    923 		cameraRunning = b;
    924 	}
    925 
    926 	void setBaseTime(float f) {
    927 		baseTime = f;
    928 	}
    929 
    930 	float getBaseTime() {
    931 		return baseTime;
    932 	}
    933 
    934 	float getTotalTime() {
    935 		return totalTime;
    936 	}
    937 	
    938 	void startCamera(long t);
    939 	void stopCamera() {
    940 		cameraRunning = true;
    941 	}
    942 	void getActiveSegmentInfo(int segment, idVec3_t &origin, idVec3_t &direction, float *fv);
    943 
    944 	bool getCameraInfo(long time, idVec3_t &origin, idVec3_t &direction, float *fv);
    945 	bool getCameraInfo(long time, float *origin, float *direction, float *fv) {
    946 		idVec3_t org, dir;
    947 		org[0] = origin[0];
    948 		org[1] = origin[1];
    949 		org[2] = origin[2];
    950 		dir[0] = direction[0];
    951 		dir[1] = direction[1];
    952 		dir[2] = direction[2];
    953 		bool b = getCameraInfo(time, org, dir, fv);
    954 		origin[0] = org[0];
    955 		origin[1] = org[1];
    956 		origin[2] = org[2];
    957 		direction[0] = dir[0];
    958 		direction[1] = dir[1];
    959 		direction[2] = dir[2];
    960 		return b;
    961 	}
    962 /*
    963 	void draw(bool editMode) {
    964                 // gcc doesn't allow casting away from bools
    965                 // why?  I've no idea...
    966 		if (cameraPosition) {
    967 			cameraPosition->draw((bool)((editMode || cameraRunning) && cameraEdit));
    968 			int count = targetPositions.Num();
    969 			for (int i = 0; i < count; i++) {
    970 				targetPositions[i]->draw((bool)((editMode || cameraRunning) && i == activeTarget && !cameraEdit));
    971 			}
    972 		}
    973 	}
    974 */
    975 /*
    976 	int numSegments() {
    977 		if (cameraEdit) {
    978 			return cameraPosition.numSegments();
    979 		}
    980 		return getTargetSpline()->numSegments();
    981 	}
    982 
    983 	int getActiveSegment() {
    984 		if (cameraEdit) {
    985 			return cameraPosition.getActiveSegment();
    986 		}
    987 		return getTargetSpline()->getActiveSegment();
    988 	}
    989 
    990 	void setActiveSegment(int i) {
    991 		if (cameraEdit) {
    992 			cameraPosition.setActiveSegment(i);
    993 		} else {
    994 			getTargetSpline()->setActiveSegment(i);
    995 		}
    996 	}
    997 */
    998 	int numPoints() {
    999 		if (cameraEdit) {
   1000 			return cameraPosition->numPoints();
   1001 		}
   1002 		return getActiveTarget()->numPoints();
   1003 	}
   1004 
   1005 	const idVec3_t *getPoint(int index) {
   1006 		if (cameraEdit) {
   1007 			return cameraPosition->getPoint(index);
   1008 		}
   1009 		return getActiveTarget()->getPoint(index);
   1010 	}
   1011 
   1012 	void stopEdit() {
   1013 		editMode = false;
   1014 		if (cameraEdit) {
   1015 			cameraPosition->stopEdit();
   1016 		} else {
   1017 			getActiveTarget()->stopEdit();
   1018 		}
   1019 	}
   1020 
   1021 	void startEdit(bool camera) {
   1022 		cameraEdit = camera;
   1023 		if (camera) {
   1024 			cameraPosition->startEdit();
   1025 			for (int i = 0; i < targetPositions.Num(); i++) {
   1026 				targetPositions[i]->stopEdit();
   1027 			}
   1028 		} else {
   1029 			getActiveTarget()->startEdit();
   1030 			cameraPosition->stopEdit();
   1031 		}
   1032 		editMode = true;
   1033 	}
   1034 
   1035 	bool waitEvent(int index);
   1036 
   1037 	const char *getName() {
   1038 		return name.c_str();
   1039 	}
   1040 
   1041 	void setName(const char *p) {
   1042 		name = p;
   1043 	}
   1044 
   1045 	idCameraPosition *getPositionObj() {
   1046 		if (cameraPosition == NULL) {
   1047 			cameraPosition = new idFixedPosition();
   1048 		}
   1049 		return cameraPosition;
   1050 	}
   1051 
   1052 protected:
   1053 	idStr name;
   1054 	int currentCameraPosition;
   1055 	idVec3_t lastDirection;
   1056 	bool cameraRunning;
   1057 	idCameraPosition *cameraPosition;
   1058 	idList<idCameraPosition*> targetPositions;
   1059 	idList<idCameraEvent*> events;
   1060 	idCameraFOV fov;
   1061 	int activeTarget;
   1062 	float totalTime;
   1063 	float baseTime;
   1064 	long startTime;
   1065 
   1066 	bool cameraEdit;
   1067 	bool editMode;
   1068 };
   1069 
   1070 extern bool g_splineMode;
   1071 
   1072 extern idCameraDef *g_splineList;
   1073 
   1074 
   1075 #endif