mirror of
https://github.com/UberGames/GtkRadiant.git
synced 2024-11-23 20:32:42 +00:00
1121 lines
21 KiB
C
1121 lines
21 KiB
C
|
/*
|
||
|
Copyright (C) 1999-2006 Id Software, Inc. and contributors.
|
||
|
For a list of contributors, see the accompanying CONTRIBUTORS file.
|
||
|
|
||
|
This file is part of GtkRadiant.
|
||
|
|
||
|
GtkRadiant is free software; you can redistribute it and/or modify
|
||
|
it under the terms of the GNU General Public License as published by
|
||
|
the Free Software Foundation; either version 2 of the License, or
|
||
|
(at your option) any later version.
|
||
|
|
||
|
GtkRadiant is distributed in the hope that it will be useful,
|
||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
|
GNU General Public License for more details.
|
||
|
|
||
|
You should have received a copy of the GNU General Public License
|
||
|
along with GtkRadiant; if not, write to the Free Software
|
||
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||
|
*/
|
||
|
|
||
|
#ifndef __SPLINES_H
|
||
|
#define __SPLINES_H
|
||
|
|
||
|
#define GTKRADIANT
|
||
|
|
||
|
#ifdef GTKRADIANT
|
||
|
#include "igl.h"
|
||
|
#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");
|
||
|
glBegin(GL_LINES);
|
||
|
glVertex3fv(startPos);
|
||
|
glVertex3fv(endPos);
|
||
|
glEnd();
|
||
|
}
|
||
|
|
||
|
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
|