]> de.git.xonotic.org Git - xonotic/netradiant.git/blobdiff - libs/splines/splines.h
eol style
[xonotic/netradiant.git] / libs / splines / splines.h
index da7c2e5b5775803a2ce927aa8a5a3f9c6f54050f..548084923db9a444ccbe7600cf8fbe0d2e201c25 100644 (file)
-#ifndef __SPLINES_H\r
-#define __SPLINES_H\r
-\r
-#define GTKRADIANT\r
-\r
-#ifndef CAMERA_PLUGIN\r
-#ifdef GTKRADIANT\r
-#include "misc_def.h"\r
-#include "igl_to_qgl.h"\r
-#endif\r
-#endif\r
-\r
-#include "util_list.h"\r
-#include "util_str.h"\r
-#include "math_vector.h"\r
-\r
-typedef int fileHandle_t;\r
-\r
-extern void glBox(idVec3 &color, idVec3 &point, float size);\r
-extern void glLabeledPoint(idVec3 &color, idVec3 &point, float size, const char *label);\r
-\r
-static idVec4 blue(0, 0, 1, 1);\r
-static idVec4 red(1, 0, 0, 1);\r
-\r
-class idPointListInterface {\r
-public:\r
-       idPointListInterface() {\r
-               selectedPoints.Clear();\r
-       };\r
-       virtual ~idPointListInterface() {};\r
-       \r
-       virtual int numPoints() {\r
-               return 0;\r
-       }\r
-       \r
-       virtual void addPoint(const float x, const float y, const float z) {}\r
-       virtual void addPoint(const idVec3 &v) {}\r
-       virtual void removePoint(int index) {}\r
-       virtual idVec3 *getPoint(int index) { return NULL; }\r
-       \r
-       int     selectPointByRay(float ox, float oy, float oz, float dx, float dy, float dz, bool single) {\r
-               idVec3 origin(ox, oy, oz);\r
-               idVec3 dir(dx, dy, dz);\r
-               return selectPointByRay(origin, dir, single);\r
-       }\r
-\r
-       int     selectPointByRay(const idVec3 origin, const idVec3 direction, bool single) {\r
-               int             i, besti, count;\r
-               float   d, bestd;\r
-               idVec3  temp, temp2;\r
-\r
-               // find the point closest to the ray\r
-               besti = -1;\r
-               bestd = 8;\r
-               count = numPoints();\r
-\r
-               for (i=0; i < count; i++) {\r
-                       temp = *getPoint(i);\r
-                       temp2 = temp;\r
-                       temp -= origin;\r
-                       d = DotProduct(temp, direction);\r
-                       __VectorMA (origin, d, direction, temp);\r
-                       temp2 -= temp;\r
-                       d = temp2.Length();\r
-                       if (d <= bestd) {\r
-                               bestd = d;\r
-                               besti = i;\r
-                       }\r
-               }\r
-\r
-               if (besti >= 0) {\r
-                       selectPoint(besti, single);\r
-               }\r
-\r
-               return besti;\r
-       }\r
-\r
-       int isPointSelected(int index) {\r
-               int count = selectedPoints.Num();\r
-               for (int i = 0; i < count; i++) {\r
-                       if (selectedPoints[i] == index) {\r
-                               return i;\r
-                       }\r
-               }\r
-               return -1;\r
-       }\r
-       \r
-       int selectPoint(int index, bool single) {\r
-               if (index >= 0 && index < numPoints()) {\r
-                       if (single) {\r
-                               deselectAll();\r
-                       } else {\r
-                               if (isPointSelected(index) >= 0) {\r
-                                       selectedPoints.Remove(index);\r
-                               }\r
-                       }\r
-                       return selectedPoints.Append(index);\r
-               }\r
-               return -1;\r
-       }\r
-       \r
-       void selectAll() {\r
-               selectedPoints.Clear();\r
-               for (int i = 0; i < numPoints(); i++) {\r
-                       selectedPoints.Append(i);\r
-               }\r
-       }\r
-\r
-       void deselectAll() {\r
-               selectedPoints.Clear();\r
-       }\r
-\r
-       int numSelectedPoints();\r
-    \r
-       idVec3 *getSelectedPoint(int index) {\r
-               assert(index >= 0 && index < numSelectedPoints());\r
-               return getPoint(selectedPoints[index]);\r
-       }\r
-       \r
-       virtual void updateSelection(float x, float y, float z) {\r
-               idVec3 move(x, y, z);\r
-               updateSelection(move);\r
-       }\r
-\r
-       virtual void updateSelection(const idVec3 &move) {\r
-               int count = selectedPoints.Num();\r
-               for (int i = 0; i < count; i++) {\r
-                       *getPoint(selectedPoints[i]) += move;\r
-               }\r
-       }\r
-\r
-       void drawSelection() {\r
-               int count = selectedPoints.Num();\r
-               for (int i = 0; i < count; i++) {\r
-                       glBox(red, *getPoint(selectedPoints[i]), 4);\r
-               }\r
-       }\r
-\r
-protected:\r
-       idList<int> selectedPoints;\r
-\r
-};\r
-\r
-\r
-class idSplineList {\r
-\r
-public:\r
-\r
-       idSplineList() {\r
-               clear();\r
-       }\r
-\r
-       idSplineList(const char *p) {\r
-               clear();\r
-               name = p;\r
-       };\r
-\r
-       ~idSplineList() {\r
-               clear();\r
-       };\r
-\r
-       void clearControl() {\r
-               for (int i = 0; i < controlPoints.Num(); i++) {\r
-                       delete controlPoints[i];\r
-               }\r
-               controlPoints.Clear();\r
-       }\r
-\r
-       void clearSpline() {\r
-               for (int i = 0; i < splinePoints.Num(); i++) {\r
-                       delete splinePoints[i];\r
-               }\r
-               splinePoints.Clear();\r
-       }\r
-\r
-       void parse(const char *(*text));\r
-       void write(fileHandle_t file, const char *name);\r
-\r
-       void clear() {\r
-               clearControl();\r
-               clearSpline();\r
-               splineTime.Clear();\r
-               selected = NULL;\r
-               dirty = true;\r
-               activeSegment = 0;\r
-               granularity = 0.025f;\r
-               pathColor.set(1.0f, 0.5f, 0.0f);\r
-               controlColor.set(0.7f, 0.0f, 1.0f);\r
-               segmentColor.set(0.0f, 0.0f, 1.0f);\r
-               activeColor.set(1.0f, 0.0f, 0.0f);\r
-       }\r
-\r
-       void initPosition(long startTime, long totalTime);\r
-       const idVec3 *getPosition(long time);\r
-\r
-\r
-       void draw(bool editMode);\r
-       void addToRenderer();\r
-\r
-       void setSelectedPoint(idVec3 *p);\r
-       idVec3 *getSelectedPoint() {\r
-         return selected;\r
-       }\r
-\r
-       void addPoint(const idVec3 &v) {\r
-               controlPoints.Append(new idVec3(v));\r
-               dirty = true;\r
-       }\r
-\r
-       void addPoint(float x, float y, float z) {\r
-               controlPoints.Append(new idVec3(x, y, z));\r
-               dirty = true;\r
-       }\r
-\r
-       void updateSelection(const idVec3 &move);\r
-\r
-       void startEdit() {\r
-               editMode = true;\r
-       }\r
-               \r
-       void stopEdit() {\r
-               editMode = false;\r
-       }\r
-\r
-       void buildSpline();\r
-\r
-       void setGranularity(float f) {\r
-               granularity = f;\r
-       }\r
-\r
-       float getGranularity() {\r
-               return granularity;\r
-       }\r
-\r
-       int numPoints() {\r
-               return controlPoints.Num();\r
-       }\r
-\r
-       idVec3 *getPoint(int index) {\r
-               assert(index >= 0 && index < controlPoints.Num());\r
-               return controlPoints[index];\r
-       }\r
-\r
-       idVec3 *getSegmentPoint(int index) {\r
-               assert(index >= 0 && index < splinePoints.Num());\r
-               return splinePoints[index];\r
-       }\r
-\r
-\r
-       void setSegmentTime(int index, int time) {\r
-               assert(index >= 0 && index < splinePoints.Num());\r
-               splineTime[index] = time;\r
-       }\r
-\r
-       int getSegmentTime(int index) {\r
-               assert(index >= 0 && index < splinePoints.Num());\r
-               return (int)splineTime[index];\r
-       }\r
-       void addSegmentTime(int index, int time) {\r
-               assert(index >= 0 && index < splinePoints.Num());\r
-               splineTime[index] += time;\r
-       }\r
-\r
-       float totalDistance();\r
-\r
-       static idVec3 zero;\r
-\r
-       int getActiveSegment() {\r
-               return activeSegment;\r
-       }\r
-\r
-       void setActiveSegment(int i) {\r
-               //assert(i >= 0 && (splinePoints.Num() > 0 && i < splinePoints.Num()));\r
-               activeSegment = i;\r
-       }\r
-\r
-       int numSegments() {\r
-               return splinePoints.Num();\r
-       }\r
-\r
-       void setColors(idVec3 &path, idVec3 &segment, idVec3 &control, idVec3 &active) {\r
-               pathColor = path;\r
-               segmentColor = segment;\r
-               controlColor = control;\r
-               activeColor = active;\r
-       }\r
-\r
-       const char *getName() {\r
-               return name.c_str();\r
-       }\r
-\r
-       void setName(const char *p) {\r
-               name = p;\r
-       }\r
-\r
-       bool validTime() {\r
-               if (dirty) {\r
-                       buildSpline();\r
-               }\r
-               // gcc doesn't allow static casting away from bools\r
-               // why?  I've no idea...\r
-               return (bool)(splineTime.Num() > 0 && splineTime.Num() == splinePoints.Num());\r
-       }\r
-\r
-       void setTime(long t) {\r
-               time = t;\r
-       }\r
-\r
-       void setBaseTime(long t) {\r
-               baseTime = t;\r
-       }\r
-\r
-protected:\r
-       idStr name;\r
-       float calcSpline(int step, float tension);\r
-       idList<idVec3*> controlPoints;\r
-       idList<idVec3*> splinePoints;\r
-       idList<double> splineTime;\r
-       idVec3 *selected;\r
-       idVec3 pathColor, segmentColor, controlColor, activeColor;\r
-       float granularity;\r
-       bool editMode;\r
-       bool dirty;\r
-       int activeSegment;\r
-       long baseTime;\r
-       long time;\r
-       friend class idCamera;\r
-};\r
-\r
-// time in milliseconds \r
-// velocity where 1.0 equal rough walking speed\r
-struct idVelocity {\r
-       idVelocity(long start, long duration, float s) {\r
-               startTime = start;\r
-               time = duration;\r
-               speed = s;\r
-       }\r
-       long    startTime;\r
-       long    time;\r
-       float   speed;\r
-};\r
-\r
-// can either be a look at or origin position for a camera\r
-// \r
-class idCameraPosition : public idPointListInterface {\r
-public:\r
-       \r
-       virtual void clearVelocities() {\r
-               for (int i = 0; i < velocities.Num(); i++) {\r
-                       delete velocities[i];\r
-                       velocities[i] = NULL;\r
-               }\r
-               velocities.Clear();\r
-       }\r
-\r
-       virtual void clear() {\r
-               editMode = false;\r
-               clearVelocities();\r
-       }\r
-\r
-       idCameraPosition(const char *p) {\r
-               name = p;\r
-       }\r
-\r
-       idCameraPosition() {\r
-               time = 0;\r
-               name = "position";\r
-       }\r
-\r
-       idCameraPosition(long t) {\r
-               time = t;\r
-       }\r
-\r
-       virtual ~idCameraPosition() {\r
-               clear();\r
-       }\r
-\r
-       \r
-       // this can be done with RTTI syntax but i like the derived classes setting a type\r
-       // makes serialization a bit easier to see\r
-       //\r
-       enum positionType {\r
-               FIXED = 0x00,\r
-               INTERPOLATED,\r
-               SPLINE,\r
-               POSITION_COUNT\r
-       };\r
-\r
-\r
-       virtual void start(long t) {\r
-               startTime = t;\r
-       }\r
-\r
-       long getTime() {\r
-               return time;\r
-       }\r
-\r
-       virtual void setTime(long t) {\r
-               time = t;\r
-       }\r
-\r
-       float getBaseVelocity() {\r
-               return baseVelocity;\r
-       }\r
-\r
-       float getVelocity(long t) {\r
-               long check = t - startTime;\r
-               for (int i = 0; i < velocities.Num(); i++) {\r
-                       if (check >= velocities[i]->startTime && check <= velocities[i]->startTime + velocities[i]->time) {\r
-                               return velocities[i]->speed;\r
-                       }\r
-               }\r
-               return baseVelocity;\r
-       }\r
-\r
-       void addVelocity(long start, long duration, float speed) {\r
-               velocities.Append(new idVelocity(start, duration, speed));\r
-       }\r
-\r
-       virtual const idVec3 *getPosition(long t) { \r
-               assert(true);\r
-               return NULL;\r
-       }\r
-\r
-       virtual void draw(bool editMode) {};\r
-\r
-       virtual void parse(const char *(*text)) {};\r
-       virtual void write(fileHandle_t file, const char *name);\r
-       virtual bool parseToken(const char *key, const char *(*text));\r
-\r
-       const char *getName() {\r
-               return name.c_str();\r
-       }\r
-\r
-       void setName(const char *p) {\r
-               name = p;\r
-       }\r
-\r
-       virtual void startEdit() {\r
-               editMode = true;\r
-       }\r
-\r
-       virtual void stopEdit() {\r
-               editMode = false;\r
-       }\r
-\r
-       virtual void draw() {};\r
-\r
-       const char *typeStr() {\r
-               return positionStr[static_cast<int>(type)];\r
-       }\r
-\r
-       void calcVelocity(float distance) {\r
-               float secs = (float)time / 1000;\r
-               baseVelocity = distance / secs;\r
-       }\r
-\r
-protected:\r
-       static const char* positionStr[POSITION_COUNT];\r
-       long            startTime;\r
-       long            time;\r
-       idCameraPosition::positionType type;\r
-       idStr           name;\r
-       bool    editMode;\r
-       idList<idVelocity*> velocities;\r
-       float           baseVelocity;\r
-};\r
-\r
-class idFixedPosition : public idCameraPosition {\r
-public:\r
-\r
-       void init() {\r
-               pos.Zero();\r
-               type = idCameraPosition::FIXED;\r
-       }\r
-       \r
-       idFixedPosition() : idCameraPosition() {\r
-               init();\r
-       }\r
-       \r
-       idFixedPosition(idVec3 p) : idCameraPosition() {\r
-               init();\r
-               pos = p;\r
-       }\r
-\r
-       virtual void addPoint(const idVec3 &v) {\r
-               pos = v;\r
-       }\r
-       \r
-       virtual void addPoint(const float x, const float y, const float z) {\r
-               pos.set(x, y, z);\r
-       }\r
-\r
-\r
-       ~idFixedPosition() {\r
-       }\r
-\r
-       virtual const idVec3 *getPosition(long t) { \r
-               return &pos;\r
-       }\r
-\r
-       void parse(const char *(*text));\r
-       void write(fileHandle_t file, const char *name);\r
-\r
-       virtual int numPoints() {\r
-               return 1;\r
-       }\r
-\r
-       virtual idVec3 *getPoint(int index) {\r
-               if (index != 0) {\r
-                       assert(true);\r
-               };\r
-               return &pos;\r
-       }\r
-\r
-       virtual void draw(bool editMode) {\r
-               glLabeledPoint(blue, pos, (editMode) ? 5 : 3, "Fixed point");\r
-       }\r
-\r
-protected:\r
-       idVec3 pos;\r
-};\r
-\r
-class idInterpolatedPosition : public idCameraPosition {\r
-public:\r
-\r
-       void init() {\r
-               type = idCameraPosition::INTERPOLATED;\r
-               first = true;\r
-               startPos.Zero();\r
-               endPos.Zero();\r
-       }\r
-       \r
-       idInterpolatedPosition() : idCameraPosition() {\r
-               init();\r
-       }\r
-       \r
-       idInterpolatedPosition(idVec3 start, idVec3 end, long time) : idCameraPosition(time) {\r
-               init();\r
-               startPos = start;\r
-               endPos = end;\r
-       }\r
-\r
-       ~idInterpolatedPosition() {\r
-       }\r
-\r
-       virtual const idVec3 *getPosition(long t);\r
-\r
-       void parse(const char *(*text));\r
-       void write(fileHandle_t file, const char *name);\r
-\r
-       virtual int numPoints() {\r
-               return 2;\r
-       }\r
-\r
-       virtual idVec3 *getPoint(int index) {\r
-               assert(index >= 0 && index < 2);\r
-               if (index == 0) {\r
-                       return &startPos;\r
-               }\r
-               return &endPos;\r
-       }\r
-\r
-       virtual void addPoint(const float x, const float y, const float z) {\r
-               if (first) {\r
-                       startPos.set(x, y, z);\r
-                       first = false;\r
-               } else {\r
-                       endPos.set(x, y, z);\r
-                       first = true;\r
-               }\r
-       }\r
-\r
-       virtual void addPoint(const idVec3 &v) {\r
-               if (first) {\r
-                       startPos = v;\r
-                       first = false;\r
-               } else {\r
-                       endPos = v;\r
-                       first = true;\r
-               }\r
-       }\r
-\r
-       virtual void draw(bool editMode) {\r
-               glLabeledPoint(blue, startPos, (editMode) ? 5 : 3, "Start interpolated");\r
-               glLabeledPoint(blue, endPos, (editMode) ? 5 : 3, "End interpolated");\r
-               qglBegin(GL_LINES);\r
-               qglVertex3fv(startPos);\r
-               qglVertex3fv(endPos);\r
-               qglEnd();\r
-       }\r
-\r
-       virtual void start(long t) {\r
-               idCameraPosition::start(t);\r
-               lastTime = startTime;\r
-               distSoFar = 0.0;\r
-               idVec3 temp = startPos;\r
-               temp -= endPos;\r
-               calcVelocity(temp.Length());\r
-       }\r
-\r
-protected:\r
-       bool first;\r
-       idVec3 startPos;\r
-       idVec3 endPos;\r
-       long lastTime;\r
-       float distSoFar;\r
-};\r
-\r
-class idSplinePosition : public idCameraPosition {\r
-public:\r
-\r
-       void init() {\r
-               type = idCameraPosition::SPLINE;\r
-       }\r
-       \r
-       idSplinePosition() : idCameraPosition() {\r
-               init();\r
-       }\r
-       \r
-       idSplinePosition(long time) : idCameraPosition(time) {\r
-               init();\r
-       }\r
-\r
-       ~idSplinePosition() {\r
-       }\r
-\r
-       virtual void start(long t) {\r
-               idCameraPosition::start(t);\r
-               target.initPosition(t, time);\r
-               lastTime = startTime;\r
-               distSoFar = 0.0;\r
-               calcVelocity(target.totalDistance());\r
-       }\r
-\r
-       //virtual const idVec3 *getPosition(long t) { \r
-       //      return target.getPosition(t);\r
-       //}\r
-       virtual const idVec3 *getPosition(long t);\r
-\r
-\r
-       //virtual const idVec3 *getPosition(long t) const { \r
-\r
-       void addControlPoint(idVec3 &v) {\r
-               target.addPoint(v);\r
-       }\r
-\r
-       void parse(const char *(*text));\r
-       void write(fileHandle_t file, const char *name);\r
-\r
-       virtual int numPoints() {\r
-               return target.numPoints();\r
-       }\r
-\r
-       virtual idVec3 *getPoint(int index) {\r
-               return target.getPoint(index);\r
-       }\r
-\r
-       virtual void addPoint(const idVec3 &v) {\r
-               target.addPoint(v);\r
-       }\r
-\r
-       virtual void addPoint(const float x, const float y, const float z) {\r
-               target.addPoint(x, y, z);\r
-       }\r
-\r
-       virtual void draw(bool editMode) {\r
-               target.draw(editMode);\r
-       }\r
-\r
-       virtual void updateSelection(const idVec3 &move) {\r
-               idCameraPosition::updateSelection(move);\r
-               target.buildSpline();\r
-       }\r
-\r
-protected:\r
-       idSplineList target;\r
-       long lastTime;\r
-       float distSoFar;\r
-};\r
-\r
-class idCameraFOV {\r
-public:\r
-       \r
-       idCameraFOV() {\r
-               time = 0;\r
-               length = 0;\r
-               fov = 90;\r
-       }\r
-\r
-       idCameraFOV(int v) {\r
-               time = 0;\r
-               length = 0;\r
-               fov = v;\r
-       }\r
-\r
-       idCameraFOV(int s, int e, long t) {\r
-               startFOV = s;\r
-               endFOV = e;\r
-               length = t;\r
-       }\r
-\r
-\r
-       ~idCameraFOV(){}\r
-\r
-       void setFOV(float f) {\r
-               fov = f;\r
-       }\r
-\r
-       float getFOV(long t) {\r
-               if (length) {\r
-                       float percent = (t - startTime) / length;\r
-                       if (percent < 0.0) {\r
-                               percent = 0.0;\r
-                       } else if (percent > 1.0) {\r
-                               percent = 1.0;\r
-                       }\r
-                       float temp = endFOV - startFOV;\r
-                       temp *= percent;\r
-                       fov = startFOV + temp;\r
-\r
-                       if (percent == 1.0) {\r
-                               length = 0.0;\r
-                       }\r
-               }\r
-               return fov;\r
-       }\r
-\r
-       void start(long t) {\r
-               startTime = t;\r
-       }\r
-\r
-       void reset(float startfov, float endfov, int start, float len) {\r
-               startFOV = startfov;\r
-               endFOV = endfov;\r
-               startTime = start;\r
-               length = len * 1000;\r
-       }\r
-\r
-       void parse(const char *(*text));\r
-       void write(fileHandle_t file, const char *name);\r
-\r
-protected:\r
-       float fov;\r
-       float startFOV;\r
-       float endFOV;\r
-       int startTime;\r
-       int time;\r
-       float length;\r
-};\r
-\r
-\r
-\r
-\r
-class idCameraEvent {\r
-public:                                                // parameters\r
-       enum eventType {\r
-               EVENT_NA = 0x00,\r
-               EVENT_WAIT,                     // \r
-               EVENT_TARGETWAIT,       // \r
-               EVENT_SPEED,            // \r
-               EVENT_TARGET,           // char(name)\r
-               EVENT_SNAPTARGET,       // \r
-               EVENT_FOV,                      // int(time), int(targetfov)\r
-               EVENT_CMD,                      // \r
-               EVENT_TRIGGER,          // \r
-               EVENT_STOP,                     // \r
-               EVENT_CAMERA,           // \r
-               EVENT_FADEOUT,          // int(time)\r
-               EVENT_FADEIN,           // int(time)\r
-               EVENT_FEATHER,          // \r
-               EVENT_COUNT                     \r
-       };\r
-\r
-       static const char* eventStr[EVENT_COUNT];\r
-\r
-       idCameraEvent() {\r
-               paramStr = "";\r
-               type = EVENT_NA;\r
-               time = 0;\r
-       }\r
-\r
-       idCameraEvent(eventType t, const char *param, long n) {\r
-               type = t;\r
-               paramStr = param;\r
-               time = n;\r
-       }\r
-\r
-       ~idCameraEvent() {};\r
-\r
-       eventType getType() {\r
-               return type;\r
-       }\r
-\r
-       const char *typeStr() {\r
-               return eventStr[static_cast<int>(type)];\r
-       }\r
-\r
-       const char *getParam() {\r
-               return paramStr.c_str();\r
-       }\r
-\r
-       long getTime() {\r
-               return time;\r
-       }\r
-\r
-       void setTime(long n) {\r
-               time = n;\r
-       }\r
-\r
-       void parse(const char *(*text));\r
-       void write(fileHandle_t file, const char *name);\r
-\r
-       void setTriggered(bool b) {\r
-               triggered = b;\r
-       }\r
-\r
-       bool getTriggered() {\r
-               return triggered;\r
-       }\r
-\r
-protected:\r
-       eventType type;\r
-       idStr paramStr;\r
-       long time;\r
-       bool triggered;\r
-\r
-};\r
-\r
-class idCameraDef {\r
-public:\r
-\r
-       void clear() {\r
-               currentCameraPosition = 0;\r
-               cameraRunning = false;\r
-               lastDirection.Zero();\r
-               baseTime = 30;\r
-               activeTarget = 0;\r
-               name = "camera01";\r
-               fov.setFOV(90);\r
-               int i;\r
-               for (i = 0; i < targetPositions.Num(); i++) {\r
-                       delete targetPositions[i];\r
-               }\r
-               for (i = 0; i < events.Num(); i++) {\r
-                       delete events[i];\r
-               }\r
-               delete cameraPosition;\r
-               cameraPosition = NULL;\r
-               events.Clear();\r
-               targetPositions.Clear();\r
-       }\r
-\r
-       idCameraPosition *startNewCamera(idCameraPosition::positionType type) {\r
-               clear();\r
-               if (type == idCameraPosition::SPLINE) {\r
-                       cameraPosition = new idSplinePosition();\r
-               } else if (type == idCameraPosition::INTERPOLATED) {\r
-                       cameraPosition = new idInterpolatedPosition();\r
-               } else {\r
-                       cameraPosition = new idFixedPosition();\r
-               }\r
-               return cameraPosition;\r
-       }\r
-\r
-       idCameraDef() {\r
-               cameraPosition = NULL;\r
-               clear();\r
-       }\r
-\r
-       ~idCameraDef() {\r
-               clear();\r
-       }\r
-\r
-       void addEvent(idCameraEvent::eventType t, const char *param, long time);\r
-\r
-       void addEvent(idCameraEvent *event);\r
-\r
-       void removeEvent( int index);\r
-\r
-       static int sortEvents(const void *p1, const void *p2);\r
-\r
-       int numEvents() {\r
-               return events.Num();\r
-       }\r
-\r
-       idCameraEvent *getEvent(int index) {\r
-               assert(index >= 0 && index < events.Num());\r
-               return events[index];\r
-       }\r
-\r
-       void parse(const char *(*text));\r
-       bool load(const char *filename);\r
-       void save(const char *filename);\r
-\r
-       void buildCamera();\r
-\r
-       //idSplineList *getcameraPosition() {\r
-       //      return &cameraPosition;\r
-       //}\r
-\r
-       static idCameraPosition *newFromType(idCameraPosition::positionType t) {\r
-               switch (t) {\r
-                       case idCameraPosition::FIXED : return new idFixedPosition();\r
-                       case idCameraPosition::INTERPOLATED : return new idInterpolatedPosition();\r
-                       case idCameraPosition::SPLINE : return new idSplinePosition();\r
-      default:\r
-        break;\r
-               };\r
-               return NULL;\r
-       }\r
-\r
-       void addTarget(const char *name, idCameraPosition::positionType type);\r
-\r
-       idCameraPosition *getActiveTarget() {\r
-               if (targetPositions.Num() == 0) {\r
-                       addTarget(NULL, idCameraPosition::FIXED);\r
-               }\r
-               return targetPositions[activeTarget];\r
-       }\r
-\r
-       idCameraPosition *getActiveTarget(int index) {\r
-               if (targetPositions.Num() == 0) {\r
-                       addTarget(NULL, idCameraPosition::FIXED);\r
-                       return targetPositions[0];\r
-               }\r
-               return targetPositions[index];\r
-       }\r
-\r
-       int numTargets() {\r
-               return targetPositions.Num();\r
-       }\r
-\r
-\r
-       void setActiveTargetByName(const char *name) {\r
-               for (int i = 0; i < targetPositions.Num(); i++) {\r
-                       if (Q_stricmp(name, targetPositions[i]->getName()) == 0) {\r
-                               setActiveTarget(i);\r
-                               return;\r
-                       }\r
-               }\r
-       }\r
-\r
-       void setActiveTarget(int index) {\r
-               assert(index >= 0 && index < targetPositions.Num());\r
-               activeTarget = index;\r
-       }\r
-\r
-       void setRunning(bool b) {\r
-               cameraRunning = b;\r
-       }\r
-\r
-       void setBaseTime(float f) {\r
-               baseTime = f;\r
-       }\r
-\r
-       float getBaseTime() {\r
-               return baseTime;\r
-       }\r
-\r
-       float getTotalTime() {\r
-               return totalTime;\r
-       }\r
-       \r
-       void startCamera(long t);\r
-       void stopCamera() {\r
-               cameraRunning = true;\r
-       }\r
-       void getActiveSegmentInfo(int segment, idVec3 &origin, idVec3 &direction, float *fv);\r
-\r
-       bool getCameraInfo(long time, idVec3 &origin, idVec3 &direction, float *fv);\r
-       bool getCameraInfo(long time, float *origin, float *direction, float *fv) {\r
-               idVec3 org, dir;\r
-               org[0] = origin[0];\r
-               org[1] = origin[1];\r
-               org[2] = origin[2];\r
-               dir[0] = direction[0];\r
-               dir[1] = direction[1];\r
-               dir[2] = direction[2];\r
-               bool b = getCameraInfo(time, org, dir, fv);\r
-               origin[0] = org[0];\r
-               origin[1] = org[1];\r
-               origin[2] = org[2];\r
-               direction[0] = dir[0];\r
-               direction[1] = dir[1];\r
-               direction[2] = dir[2];\r
-               return b;\r
-       }\r
-\r
-       void draw(bool editMode) {\r
-                // gcc doesn't allow casting away from bools\r
-                // why?  I've no idea...\r
-               if (cameraPosition) {\r
-                       cameraPosition->draw((bool)((editMode || cameraRunning) && cameraEdit));\r
-                       int count = targetPositions.Num();\r
-                       for (int i = 0; i < count; i++) {\r
-                               targetPositions[i]->draw((bool)((editMode || cameraRunning) && i == activeTarget && !cameraEdit));\r
-                       }\r
-               }\r
-       }\r
-\r
-/*\r
-       int numSegments() {\r
-               if (cameraEdit) {\r
-                       return cameraPosition.numSegments();\r
-               }\r
-               return getTargetSpline()->numSegments();\r
-       }\r
-\r
-       int getActiveSegment() {\r
-               if (cameraEdit) {\r
-                       return cameraPosition.getActiveSegment();\r
-               }\r
-               return getTargetSpline()->getActiveSegment();\r
-       }\r
-\r
-       void setActiveSegment(int i) {\r
-               if (cameraEdit) {\r
-                       cameraPosition.setActiveSegment(i);\r
-               } else {\r
-                       getTargetSpline()->setActiveSegment(i);\r
-               }\r
-       }\r
-*/\r
-       int numPoints() {\r
-               if (cameraEdit) {\r
-                       return cameraPosition->numPoints();\r
-               }\r
-               return getActiveTarget()->numPoints();\r
-       }\r
-\r
-       const idVec3 *getPoint(int index) {\r
-               if (cameraEdit) {\r
-                       return cameraPosition->getPoint(index);\r
-               }\r
-               return getActiveTarget()->getPoint(index);\r
-       }\r
-\r
-       void stopEdit() {\r
-               editMode = false;\r
-               if (cameraEdit) {\r
-                       cameraPosition->stopEdit();\r
-               } else {\r
-                       getActiveTarget()->stopEdit();\r
-               }\r
-       }\r
-\r
-       void startEdit(bool camera) {\r
-               cameraEdit = camera;\r
-               if (camera) {\r
-                       cameraPosition->startEdit();\r
-                       for (int i = 0; i < targetPositions.Num(); i++) {\r
-                               targetPositions[i]->stopEdit();\r
-                       }\r
-               } else {\r
-                       getActiveTarget()->startEdit();\r
-                       cameraPosition->stopEdit();\r
-               }\r
-               editMode = true;\r
-       }\r
-\r
-       bool waitEvent(int index);\r
-\r
-       const char *getName() {\r
-               return name.c_str();\r
-       }\r
-\r
-       void setName(const char *p) {\r
-               name = p;\r
-       }\r
-\r
-       idCameraPosition *getPositionObj() {\r
-               if (cameraPosition == NULL) {\r
-                       cameraPosition = new idFixedPosition();\r
-               }\r
-               return cameraPosition;\r
-       }\r
-\r
-protected:\r
-       idStr name;\r
-       int currentCameraPosition;\r
-       idVec3 lastDirection;\r
-       bool cameraRunning;\r
-       idCameraPosition *cameraPosition;\r
-       idList<idCameraPosition*> targetPositions;\r
-       idList<idCameraEvent*> events;\r
-       idCameraFOV fov;\r
-       int activeTarget;\r
-       float totalTime;\r
-       float baseTime;\r
-       long startTime;\r
-\r
-       bool cameraEdit;\r
-       bool editMode;\r
-};\r
-\r
-extern bool g_splineMode;\r
-\r
-extern idCameraDef *g_splineList;\r
-\r
-\r
-#endif\r
+#ifndef __SPLINES_H
+#define __SPLINES_H
+
+#define GTKRADIANT
+
+#ifndef CAMERA_PLUGIN
+#ifdef GTKRADIANT
+#include "misc_def.h"
+#include "igl_to_qgl.h"
+#endif
+#endif
+
+#include "util_list.h"
+#include "util_str.h"
+#include "math_vector.h"
+
+typedef int fileHandle_t;
+
+extern void glBox(idVec3 &color, idVec3 &point, float size);
+extern void glLabeledPoint(idVec3 &color, idVec3 &point, float size, const char *label);
+
+static idVec4 blue(0, 0, 1, 1);
+static idVec4 red(1, 0, 0, 1);
+
+class idPointListInterface {
+public:
+       idPointListInterface() {
+               selectedPoints.Clear();
+       };
+       virtual ~idPointListInterface() {};
+       
+       virtual int numPoints() {
+               return 0;
+       }
+       
+       virtual void addPoint(const float x, const float y, const float z) {}
+       virtual void addPoint(const idVec3 &v) {}
+       virtual void removePoint(int index) {}
+       virtual idVec3 *getPoint(int index) { return NULL; }
+       
+       int     selectPointByRay(float ox, float oy, float oz, float dx, float dy, float dz, bool single) {
+               idVec3 origin(ox, oy, oz);
+               idVec3 dir(dx, dy, dz);
+               return selectPointByRay(origin, dir, single);
+       }
+
+       int     selectPointByRay(const idVec3 origin, const idVec3 direction, bool single) {
+               int             i, besti, count;
+               float   d, bestd;
+               idVec3  temp, temp2;
+
+               // find the point closest to the ray
+               besti = -1;
+               bestd = 8;
+               count = numPoints();
+
+               for (i=0; i < count; i++) {
+                       temp = *getPoint(i);
+                       temp2 = temp;
+                       temp -= origin;
+                       d = DotProduct(temp, direction);
+                       __VectorMA (origin, d, direction, temp);
+                       temp2 -= temp;
+                       d = temp2.Length();
+                       if (d <= bestd) {
+                               bestd = d;
+                               besti = i;
+                       }
+               }
+
+               if (besti >= 0) {
+                       selectPoint(besti, single);
+               }
+
+               return besti;
+       }
+
+       int isPointSelected(int index) {
+               int count = selectedPoints.Num();
+               for (int i = 0; i < count; i++) {
+                       if (selectedPoints[i] == index) {
+                               return i;
+                       }
+               }
+               return -1;
+       }
+       
+       int selectPoint(int index, bool single) {
+               if (index >= 0 && index < numPoints()) {
+                       if (single) {
+                               deselectAll();
+                       } else {
+                               if (isPointSelected(index) >= 0) {
+                                       selectedPoints.Remove(index);
+                               }
+                       }
+                       return selectedPoints.Append(index);
+               }
+               return -1;
+       }
+       
+       void selectAll() {
+               selectedPoints.Clear();
+               for (int i = 0; i < numPoints(); i++) {
+                       selectedPoints.Append(i);
+               }
+       }
+
+       void deselectAll() {
+               selectedPoints.Clear();
+       }
+
+       int numSelectedPoints();
+    
+       idVec3 *getSelectedPoint(int index) {
+               assert(index >= 0 && index < numSelectedPoints());
+               return getPoint(selectedPoints[index]);
+       }
+       
+       virtual void updateSelection(float x, float y, float z) {
+               idVec3 move(x, y, z);
+               updateSelection(move);
+       }
+
+       virtual void updateSelection(const idVec3 &move) {
+               int count = selectedPoints.Num();
+               for (int i = 0; i < count; i++) {
+                       *getPoint(selectedPoints[i]) += move;
+               }
+       }
+
+       void drawSelection() {
+               int count = selectedPoints.Num();
+               for (int i = 0; i < count; i++) {
+                       glBox(red, *getPoint(selectedPoints[i]), 4);
+               }
+       }
+
+protected:
+       idList<int> selectedPoints;
+
+};
+
+
+class idSplineList {
+
+public:
+
+       idSplineList() {
+               clear();
+       }
+
+       idSplineList(const char *p) {
+               clear();
+               name = p;
+       };
+
+       ~idSplineList() {
+               clear();
+       };
+
+       void clearControl() {
+               for (int i = 0; i < controlPoints.Num(); i++) {
+                       delete controlPoints[i];
+               }
+               controlPoints.Clear();
+       }
+
+       void clearSpline() {
+               for (int i = 0; i < splinePoints.Num(); i++) {
+                       delete splinePoints[i];
+               }
+               splinePoints.Clear();
+       }
+
+       void parse(const char *(*text));
+       void write(fileHandle_t file, const char *name);
+
+       void clear() {
+               clearControl();
+               clearSpline();
+               splineTime.Clear();
+               selected = NULL;
+               dirty = true;
+               activeSegment = 0;
+               granularity = 0.025f;
+               pathColor.set(1.0f, 0.5f, 0.0f);
+               controlColor.set(0.7f, 0.0f, 1.0f);
+               segmentColor.set(0.0f, 0.0f, 1.0f);
+               activeColor.set(1.0f, 0.0f, 0.0f);
+       }
+
+       void initPosition(long startTime, long totalTime);
+       const idVec3 *getPosition(long time);
+
+
+       void draw(bool editMode);
+       void addToRenderer();
+
+       void setSelectedPoint(idVec3 *p);
+       idVec3 *getSelectedPoint() {
+         return selected;
+       }
+
+       void addPoint(const idVec3 &v) {
+               controlPoints.Append(new idVec3(v));
+               dirty = true;
+       }
+
+       void addPoint(float x, float y, float z) {
+               controlPoints.Append(new idVec3(x, y, z));
+               dirty = true;
+       }
+
+       void updateSelection(const idVec3 &move);
+
+       void startEdit() {
+               editMode = true;
+       }
+               
+       void stopEdit() {
+               editMode = false;
+       }
+
+       void buildSpline();
+
+       void setGranularity(float f) {
+               granularity = f;
+       }
+
+       float getGranularity() {
+               return granularity;
+       }
+
+       int numPoints() {
+               return controlPoints.Num();
+       }
+
+       idVec3 *getPoint(int index) {
+               assert(index >= 0 && index < controlPoints.Num());
+               return controlPoints[index];
+       }
+
+       idVec3 *getSegmentPoint(int index) {
+               assert(index >= 0 && index < splinePoints.Num());
+               return splinePoints[index];
+       }
+
+
+       void setSegmentTime(int index, int time) {
+               assert(index >= 0 && index < splinePoints.Num());
+               splineTime[index] = time;
+       }
+
+       int getSegmentTime(int index) {
+               assert(index >= 0 && index < splinePoints.Num());
+               return (int)splineTime[index];
+       }
+       void addSegmentTime(int index, int time) {
+               assert(index >= 0 && index < splinePoints.Num());
+               splineTime[index] += time;
+       }
+
+       float totalDistance();
+
+       static idVec3 zero;
+
+       int getActiveSegment() {
+               return activeSegment;
+       }
+
+       void setActiveSegment(int i) {
+               //assert(i >= 0 && (splinePoints.Num() > 0 && i < splinePoints.Num()));
+               activeSegment = i;
+       }
+
+       int numSegments() {
+               return splinePoints.Num();
+       }
+
+       void setColors(idVec3 &path, idVec3 &segment, idVec3 &control, idVec3 &active) {
+               pathColor = path;
+               segmentColor = segment;
+               controlColor = control;
+               activeColor = active;
+       }
+
+       const char *getName() {
+               return name.c_str();
+       }
+
+       void setName(const char *p) {
+               name = p;
+       }
+
+       bool validTime() {
+               if (dirty) {
+                       buildSpline();
+               }
+               // gcc doesn't allow static casting away from bools
+               // why?  I've no idea...
+               return (bool)(splineTime.Num() > 0 && splineTime.Num() == splinePoints.Num());
+       }
+
+       void setTime(long t) {
+               time = t;
+       }
+
+       void setBaseTime(long t) {
+               baseTime = t;
+       }
+
+protected:
+       idStr name;
+       float calcSpline(int step, float tension);
+       idList<idVec3*> controlPoints;
+       idList<idVec3*> splinePoints;
+       idList<double> splineTime;
+       idVec3 *selected;
+       idVec3 pathColor, segmentColor, controlColor, activeColor;
+       float granularity;
+       bool editMode;
+       bool dirty;
+       int activeSegment;
+       long baseTime;
+       long time;
+       friend class idCamera;
+};
+
+// time in milliseconds 
+// velocity where 1.0 equal rough walking speed
+struct idVelocity {
+       idVelocity(long start, long duration, float s) {
+               startTime = start;
+               time = duration;
+               speed = s;
+       }
+       long    startTime;
+       long    time;
+       float   speed;
+};
+
+// can either be a look at or origin position for a camera
+// 
+class idCameraPosition : public idPointListInterface {
+public:
+       
+       virtual void clearVelocities() {
+               for (int i = 0; i < velocities.Num(); i++) {
+                       delete velocities[i];
+                       velocities[i] = NULL;
+               }
+               velocities.Clear();
+       }
+
+       virtual void clear() {
+               editMode = false;
+               clearVelocities();
+       }
+
+       idCameraPosition(const char *p) {
+               name = p;
+       }
+
+       idCameraPosition() {
+               time = 0;
+               name = "position";
+       }
+
+       idCameraPosition(long t) {
+               time = t;
+       }
+
+       virtual ~idCameraPosition() {
+               clear();
+       }
+
+       
+       // this can be done with RTTI syntax but i like the derived classes setting a type
+       // makes serialization a bit easier to see
+       //
+       enum positionType {
+               FIXED = 0x00,
+               INTERPOLATED,
+               SPLINE,
+               POSITION_COUNT
+       };
+
+
+       virtual void start(long t) {
+               startTime = t;
+       }
+
+       long getTime() {
+               return time;
+       }
+
+       virtual void setTime(long t) {
+               time = t;
+       }
+
+       float getBaseVelocity() {
+               return baseVelocity;
+       }
+
+       float getVelocity(long t) {
+               long check = t - startTime;
+               for (int i = 0; i < velocities.Num(); i++) {
+                       if (check >= velocities[i]->startTime && check <= velocities[i]->startTime + velocities[i]->time) {
+                               return velocities[i]->speed;
+                       }
+               }
+               return baseVelocity;
+       }
+
+       void addVelocity(long start, long duration, float speed) {
+               velocities.Append(new idVelocity(start, duration, speed));
+       }
+
+       virtual const idVec3 *getPosition(long t) { 
+               assert(true);
+               return NULL;
+       }
+
+       virtual void draw(bool editMode) {};
+
+       virtual void parse(const char *(*text)) {};
+       virtual void write(fileHandle_t file, const char *name);
+       virtual bool parseToken(const char *key, const char *(*text));
+
+       const char *getName() {
+               return name.c_str();
+       }
+
+       void setName(const char *p) {
+               name = p;
+       }
+
+       virtual void startEdit() {
+               editMode = true;
+       }
+
+       virtual void stopEdit() {
+               editMode = false;
+       }
+
+       virtual void draw() {};
+
+       const char *typeStr() {
+               return positionStr[static_cast<int>(type)];
+       }
+
+       void calcVelocity(float distance) {
+               float secs = (float)time / 1000;
+               baseVelocity = distance / secs;
+       }
+
+protected:
+       static const char* positionStr[POSITION_COUNT];
+       long            startTime;
+       long            time;
+       idCameraPosition::positionType type;
+       idStr           name;
+       bool    editMode;
+       idList<idVelocity*> velocities;
+       float           baseVelocity;
+};
+
+class idFixedPosition : public idCameraPosition {
+public:
+
+       void init() {
+               pos.Zero();
+               type = idCameraPosition::FIXED;
+       }
+       
+       idFixedPosition() : idCameraPosition() {
+               init();
+       }
+       
+       idFixedPosition(idVec3 p) : idCameraPosition() {
+               init();
+               pos = p;
+       }
+
+       virtual void addPoint(const idVec3 &v) {
+               pos = v;
+       }
+       
+       virtual void addPoint(const float x, const float y, const float z) {
+               pos.set(x, y, z);
+       }
+
+
+       ~idFixedPosition() {
+       }
+
+       virtual const idVec3 *getPosition(long t) { 
+               return &pos;
+       }
+
+       void parse(const char *(*text));
+       void write(fileHandle_t file, const char *name);
+
+       virtual int numPoints() {
+               return 1;
+       }
+
+       virtual idVec3 *getPoint(int index) {
+               if (index != 0) {
+                       assert(true);
+               };
+               return &pos;
+       }
+
+       virtual void draw(bool editMode) {
+               glLabeledPoint(blue, pos, (editMode) ? 5 : 3, "Fixed point");
+       }
+
+protected:
+       idVec3 pos;
+};
+
+class idInterpolatedPosition : public idCameraPosition {
+public:
+
+       void init() {
+               type = idCameraPosition::INTERPOLATED;
+               first = true;
+               startPos.Zero();
+               endPos.Zero();
+       }
+       
+       idInterpolatedPosition() : idCameraPosition() {
+               init();
+       }
+       
+       idInterpolatedPosition(idVec3 start, idVec3 end, long time) : idCameraPosition(time) {
+               init();
+               startPos = start;
+               endPos = end;
+       }
+
+       ~idInterpolatedPosition() {
+       }
+
+       virtual const idVec3 *getPosition(long t);
+
+       void parse(const char *(*text));
+       void write(fileHandle_t file, const char *name);
+
+       virtual int numPoints() {
+               return 2;
+       }
+
+       virtual idVec3 *getPoint(int index) {
+               assert(index >= 0 && index < 2);
+               if (index == 0) {
+                       return &startPos;
+               }
+               return &endPos;
+       }
+
+       virtual void addPoint(const float x, const float y, const float z) {
+               if (first) {
+                       startPos.set(x, y, z);
+                       first = false;
+               } else {
+                       endPos.set(x, y, z);
+                       first = true;
+               }
+       }
+
+       virtual void addPoint(const idVec3 &v) {
+               if (first) {
+                       startPos = v;
+                       first = false;
+               } else {
+                       endPos = v;
+                       first = true;
+               }
+       }
+
+       virtual void draw(bool editMode) {
+               glLabeledPoint(blue, startPos, (editMode) ? 5 : 3, "Start interpolated");
+               glLabeledPoint(blue, endPos, (editMode) ? 5 : 3, "End interpolated");
+               qglBegin(GL_LINES);
+               qglVertex3fv(startPos);
+               qglVertex3fv(endPos);
+               qglEnd();
+       }
+
+       virtual void start(long t) {
+               idCameraPosition::start(t);
+               lastTime = startTime;
+               distSoFar = 0.0;
+               idVec3 temp = startPos;
+               temp -= endPos;
+               calcVelocity(temp.Length());
+       }
+
+protected:
+       bool first;
+       idVec3 startPos;
+       idVec3 endPos;
+       long lastTime;
+       float distSoFar;
+};
+
+class idSplinePosition : public idCameraPosition {
+public:
+
+       void init() {
+               type = idCameraPosition::SPLINE;
+       }
+       
+       idSplinePosition() : idCameraPosition() {
+               init();
+       }
+       
+       idSplinePosition(long time) : idCameraPosition(time) {
+               init();
+       }
+
+       ~idSplinePosition() {
+       }
+
+       virtual void start(long t) {
+               idCameraPosition::start(t);
+               target.initPosition(t, time);
+               lastTime = startTime;
+               distSoFar = 0.0;
+               calcVelocity(target.totalDistance());
+       }
+
+       //virtual const idVec3 *getPosition(long t) { 
+       //      return target.getPosition(t);
+       //}
+       virtual const idVec3 *getPosition(long t);
+
+
+       //virtual const idVec3 *getPosition(long t) const { 
+
+       void addControlPoint(idVec3 &v) {
+               target.addPoint(v);
+       }
+
+       void parse(const char *(*text));
+       void write(fileHandle_t file, const char *name);
+
+       virtual int numPoints() {
+               return target.numPoints();
+       }
+
+       virtual idVec3 *getPoint(int index) {
+               return target.getPoint(index);
+       }
+
+       virtual void addPoint(const idVec3 &v) {
+               target.addPoint(v);
+       }
+
+       virtual void addPoint(const float x, const float y, const float z) {
+               target.addPoint(x, y, z);
+       }
+
+       virtual void draw(bool editMode) {
+               target.draw(editMode);
+       }
+
+       virtual void updateSelection(const idVec3 &move) {
+               idCameraPosition::updateSelection(move);
+               target.buildSpline();
+       }
+
+protected:
+       idSplineList target;
+       long lastTime;
+       float distSoFar;
+};
+
+class idCameraFOV {
+public:
+       
+       idCameraFOV() {
+               time = 0;
+               length = 0;
+               fov = 90;
+       }
+
+       idCameraFOV(int v) {
+               time = 0;
+               length = 0;
+               fov = v;
+       }
+
+       idCameraFOV(int s, int e, long t) {
+               startFOV = s;
+               endFOV = e;
+               length = t;
+       }
+
+
+       ~idCameraFOV(){}
+
+       void setFOV(float f) {
+               fov = f;
+       }
+
+       float getFOV(long t) {
+               if (length) {
+                       float percent = (t - startTime) / length;
+                       if (percent < 0.0) {
+                               percent = 0.0;
+                       } else if (percent > 1.0) {
+                               percent = 1.0;
+                       }
+                       float temp = endFOV - startFOV;
+                       temp *= percent;
+                       fov = startFOV + temp;
+
+                       if (percent == 1.0) {
+                               length = 0.0;
+                       }
+               }
+               return fov;
+       }
+
+       void start(long t) {
+               startTime = t;
+       }
+
+       void reset(float startfov, float endfov, int start, float len) {
+               startFOV = startfov;
+               endFOV = endfov;
+               startTime = start;
+               length = len * 1000;
+       }
+
+       void parse(const char *(*text));
+       void write(fileHandle_t file, const char *name);
+
+protected:
+       float fov;
+       float startFOV;
+       float endFOV;
+       int startTime;
+       int time;
+       float length;
+};
+
+
+
+
+class idCameraEvent {
+public:                                                // parameters
+       enum eventType {
+               EVENT_NA = 0x00,
+               EVENT_WAIT,                     // 
+               EVENT_TARGETWAIT,       // 
+               EVENT_SPEED,            // 
+               EVENT_TARGET,           // char(name)
+               EVENT_SNAPTARGET,       // 
+               EVENT_FOV,                      // int(time), int(targetfov)
+               EVENT_CMD,                      // 
+               EVENT_TRIGGER,          // 
+               EVENT_STOP,                     // 
+               EVENT_CAMERA,           // 
+               EVENT_FADEOUT,          // int(time)
+               EVENT_FADEIN,           // int(time)
+               EVENT_FEATHER,          // 
+               EVENT_COUNT                     
+       };
+
+       static const char* eventStr[EVENT_COUNT];
+
+       idCameraEvent() {
+               paramStr = "";
+               type = EVENT_NA;
+               time = 0;
+       }
+
+       idCameraEvent(eventType t, const char *param, long n) {
+               type = t;
+               paramStr = param;
+               time = n;
+       }
+
+       ~idCameraEvent() {};
+
+       eventType getType() {
+               return type;
+       }
+
+       const char *typeStr() {
+               return eventStr[static_cast<int>(type)];
+       }
+
+       const char *getParam() {
+               return paramStr.c_str();
+       }
+
+       long getTime() {
+               return time;
+       }
+
+       void setTime(long n) {
+               time = n;
+       }
+
+       void parse(const char *(*text));
+       void write(fileHandle_t file, const char *name);
+
+       void setTriggered(bool b) {
+               triggered = b;
+       }
+
+       bool getTriggered() {
+               return triggered;
+       }
+
+protected:
+       eventType type;
+       idStr paramStr;
+       long time;
+       bool triggered;
+
+};
+
+class idCameraDef {
+public:
+
+       void clear() {
+               currentCameraPosition = 0;
+               cameraRunning = false;
+               lastDirection.Zero();
+               baseTime = 30;
+               activeTarget = 0;
+               name = "camera01";
+               fov.setFOV(90);
+               int i;
+               for (i = 0; i < targetPositions.Num(); i++) {
+                       delete targetPositions[i];
+               }
+               for (i = 0; i < events.Num(); i++) {
+                       delete events[i];
+               }
+               delete cameraPosition;
+               cameraPosition = NULL;
+               events.Clear();
+               targetPositions.Clear();
+       }
+
+       idCameraPosition *startNewCamera(idCameraPosition::positionType type) {
+               clear();
+               if (type == idCameraPosition::SPLINE) {
+                       cameraPosition = new idSplinePosition();
+               } else if (type == idCameraPosition::INTERPOLATED) {
+                       cameraPosition = new idInterpolatedPosition();
+               } else {
+                       cameraPosition = new idFixedPosition();
+               }
+               return cameraPosition;
+       }
+
+       idCameraDef() {
+               cameraPosition = NULL;
+               clear();
+       }
+
+       ~idCameraDef() {
+               clear();
+       }
+
+       void addEvent(idCameraEvent::eventType t, const char *param, long time);
+
+       void addEvent(idCameraEvent *event);
+
+       void removeEvent( int index);
+
+       static int sortEvents(const void *p1, const void *p2);
+
+       int numEvents() {
+               return events.Num();
+       }
+
+       idCameraEvent *getEvent(int index) {
+               assert(index >= 0 && index < events.Num());
+               return events[index];
+       }
+
+       void parse(const char *(*text));
+       bool load(const char *filename);
+       void save(const char *filename);
+
+       void buildCamera();
+
+       //idSplineList *getcameraPosition() {
+       //      return &cameraPosition;
+       //}
+
+       static idCameraPosition *newFromType(idCameraPosition::positionType t) {
+               switch (t) {
+                       case idCameraPosition::FIXED : return new idFixedPosition();
+                       case idCameraPosition::INTERPOLATED : return new idInterpolatedPosition();
+                       case idCameraPosition::SPLINE : return new idSplinePosition();
+      default:
+        break;
+               };
+               return NULL;
+       }
+
+       void addTarget(const char *name, idCameraPosition::positionType type);
+
+       idCameraPosition *getActiveTarget() {
+               if (targetPositions.Num() == 0) {
+                       addTarget(NULL, idCameraPosition::FIXED);
+               }
+               return targetPositions[activeTarget];
+       }
+
+       idCameraPosition *getActiveTarget(int index) {
+               if (targetPositions.Num() == 0) {
+                       addTarget(NULL, idCameraPosition::FIXED);
+                       return targetPositions[0];
+               }
+               return targetPositions[index];
+       }
+
+       int numTargets() {
+               return targetPositions.Num();
+       }
+
+
+       void setActiveTargetByName(const char *name) {
+               for (int i = 0; i < targetPositions.Num(); i++) {
+                       if (Q_stricmp(name, targetPositions[i]->getName()) == 0) {
+                               setActiveTarget(i);
+                               return;
+                       }
+               }
+       }
+
+       void setActiveTarget(int index) {
+               assert(index >= 0 && index < targetPositions.Num());
+               activeTarget = index;
+       }
+
+       void setRunning(bool b) {
+               cameraRunning = b;
+       }
+
+       void setBaseTime(float f) {
+               baseTime = f;
+       }
+
+       float getBaseTime() {
+               return baseTime;
+       }
+
+       float getTotalTime() {
+               return totalTime;
+       }
+       
+       void startCamera(long t);
+       void stopCamera() {
+               cameraRunning = true;
+       }
+       void getActiveSegmentInfo(int segment, idVec3 &origin, idVec3 &direction, float *fv);
+
+       bool getCameraInfo(long time, idVec3 &origin, idVec3 &direction, float *fv);
+       bool getCameraInfo(long time, float *origin, float *direction, float *fv) {
+               idVec3 org, dir;
+               org[0] = origin[0];
+               org[1] = origin[1];
+               org[2] = origin[2];
+               dir[0] = direction[0];
+               dir[1] = direction[1];
+               dir[2] = direction[2];
+               bool b = getCameraInfo(time, org, dir, fv);
+               origin[0] = org[0];
+               origin[1] = org[1];
+               origin[2] = org[2];
+               direction[0] = dir[0];
+               direction[1] = dir[1];
+               direction[2] = dir[2];
+               return b;
+       }
+
+       void draw(bool editMode) {
+                // gcc doesn't allow casting away from bools
+                // why?  I've no idea...
+               if (cameraPosition) {
+                       cameraPosition->draw((bool)((editMode || cameraRunning) && cameraEdit));
+                       int count = targetPositions.Num();
+                       for (int i = 0; i < count; i++) {
+                               targetPositions[i]->draw((bool)((editMode || cameraRunning) && i == activeTarget && !cameraEdit));
+                       }
+               }
+       }
+
+/*
+       int numSegments() {
+               if (cameraEdit) {
+                       return cameraPosition.numSegments();
+               }
+               return getTargetSpline()->numSegments();
+       }
+
+       int getActiveSegment() {
+               if (cameraEdit) {
+                       return cameraPosition.getActiveSegment();
+               }
+               return getTargetSpline()->getActiveSegment();
+       }
+
+       void setActiveSegment(int i) {
+               if (cameraEdit) {
+                       cameraPosition.setActiveSegment(i);
+               } else {
+                       getTargetSpline()->setActiveSegment(i);
+               }
+       }
+*/
+       int numPoints() {
+               if (cameraEdit) {
+                       return cameraPosition->numPoints();
+               }
+               return getActiveTarget()->numPoints();
+       }
+
+       const idVec3 *getPoint(int index) {
+               if (cameraEdit) {
+                       return cameraPosition->getPoint(index);
+               }
+               return getActiveTarget()->getPoint(index);
+       }
+
+       void stopEdit() {
+               editMode = false;
+               if (cameraEdit) {
+                       cameraPosition->stopEdit();
+               } else {
+                       getActiveTarget()->stopEdit();
+               }
+       }
+
+       void startEdit(bool camera) {
+               cameraEdit = camera;
+               if (camera) {
+                       cameraPosition->startEdit();
+                       for (int i = 0; i < targetPositions.Num(); i++) {
+                               targetPositions[i]->stopEdit();
+                       }
+               } else {
+                       getActiveTarget()->startEdit();
+                       cameraPosition->stopEdit();
+               }
+               editMode = true;
+       }
+
+       bool waitEvent(int index);
+
+       const char *getName() {
+               return name.c_str();
+       }
+
+       void setName(const char *p) {
+               name = p;
+       }
+
+       idCameraPosition *getPositionObj() {
+               if (cameraPosition == NULL) {
+                       cameraPosition = new idFixedPosition();
+               }
+               return cameraPosition;
+       }
+
+protected:
+       idStr name;
+       int currentCameraPosition;
+       idVec3 lastDirection;
+       bool cameraRunning;
+       idCameraPosition *cameraPosition;
+       idList<idCameraPosition*> targetPositions;
+       idList<idCameraEvent*> events;
+       idCameraFOV fov;
+       int activeTarget;
+       float totalTime;
+       float baseTime;
+       long startTime;
+
+       bool cameraEdit;
+       bool editMode;
+};
+
+extern bool g_splineMode;
+
+extern idCameraDef *g_splineList;
+
+
+#endif