Quake-III-Arena

Quake III Arena GPL Source Release
Log | Files | Refs

splines.h (20842B)


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