2008-03-25 10:02:13 +00:00
|
|
|
|
|
|
|
#ifndef __DSC_H
|
|
|
|
#define __DSC_H
|
|
|
|
|
|
|
|
typedef unsigned long DWORD;
|
|
|
|
typedef unsigned char BYTE;
|
|
|
|
|
2008-04-18 11:11:48 +00:00
|
|
|
class Vector;
|
2009-04-14 04:19:23 +00:00
|
|
|
class Vector4;
|
2008-05-08 07:30:30 +00:00
|
|
|
class Point2d;
|
|
|
|
class hEntity;
|
2008-06-01 08:29:59 +00:00
|
|
|
class hParam;
|
2008-04-18 11:11:48 +00:00
|
|
|
|
|
|
|
class Quaternion {
|
|
|
|
public:
|
2008-05-05 06:18:01 +00:00
|
|
|
// a + (vx)*i + (vy)*j + (vz)*k
|
|
|
|
double w, vx, vy, vz;
|
2008-04-18 11:11:48 +00:00
|
|
|
|
2009-03-15 23:04:45 +00:00
|
|
|
static const Quaternion IDENTITY;
|
|
|
|
|
2008-06-01 08:45:11 +00:00
|
|
|
static Quaternion From(double w, double vx, double vy, double vz);
|
2008-06-02 03:31:37 +00:00
|
|
|
static Quaternion From(hParam w, hParam vx, hParam vy, hParam vz);
|
2008-06-01 08:45:11 +00:00
|
|
|
static Quaternion From(Vector u, Vector v);
|
2009-04-29 02:42:44 +00:00
|
|
|
static Quaternion From(Vector axis, double dtheta);
|
2008-04-18 11:11:48 +00:00
|
|
|
|
2008-05-05 06:18:01 +00:00
|
|
|
Quaternion Plus(Quaternion b);
|
|
|
|
Quaternion Minus(Quaternion b);
|
2008-04-18 11:11:48 +00:00
|
|
|
Quaternion ScaledBy(double s);
|
|
|
|
double Magnitude(void);
|
|
|
|
Quaternion WithMagnitude(double s);
|
|
|
|
|
|
|
|
// Call a rotation matrix [ u' v' n' ]'; this returns the first and
|
|
|
|
// second rows, where that matrix is generated by this quaternion
|
|
|
|
Vector RotationU(void);
|
|
|
|
Vector RotationV(void);
|
2008-05-05 06:18:01 +00:00
|
|
|
Vector RotationN(void);
|
2008-05-11 06:09:46 +00:00
|
|
|
Vector Rotate(Vector p);
|
|
|
|
|
2008-05-14 14:23:58 +00:00
|
|
|
Quaternion ToThe(double p);
|
|
|
|
Quaternion Inverse(void);
|
2008-05-11 06:09:46 +00:00
|
|
|
Quaternion Times(Quaternion b);
|
2008-04-18 11:11:48 +00:00
|
|
|
};
|
|
|
|
|
2008-03-28 10:00:37 +00:00
|
|
|
class Vector {
|
|
|
|
public:
|
2008-03-25 10:02:13 +00:00
|
|
|
double x, y, z;
|
2008-04-09 08:39:01 +00:00
|
|
|
|
2008-06-01 08:45:11 +00:00
|
|
|
static Vector From(double x, double y, double z);
|
|
|
|
static Vector From(hParam x, hParam y, hParam z);
|
2008-05-19 09:23:49 +00:00
|
|
|
static Vector AtIntersectionOfPlanes(Vector n1, double d1,
|
|
|
|
Vector n2, double d2);
|
2009-01-03 12:27:33 +00:00
|
|
|
static Vector AtIntersectionOfLines(Vector a0, Vector a1,
|
|
|
|
Vector b0, Vector b1,
|
2009-01-21 05:04:38 +00:00
|
|
|
bool *skew,
|
|
|
|
double *pa=NULL, double *pb=NULL);
|
2009-02-23 10:06:02 +00:00
|
|
|
static Vector AtIntersectionOfPlaneAndLine(Vector n, double d,
|
|
|
|
Vector p0, Vector p1,
|
|
|
|
bool *parallel);
|
2009-02-27 13:04:36 +00:00
|
|
|
static Vector AtIntersectionOfPlanes(Vector na, double da,
|
|
|
|
Vector nb, double db,
|
2009-03-15 23:04:45 +00:00
|
|
|
Vector nc, double dc, bool *parallel);
|
2008-03-27 09:53:51 +00:00
|
|
|
|
2008-07-06 07:56:24 +00:00
|
|
|
double Element(int i);
|
2008-09-09 05:19:54 +00:00
|
|
|
bool Equals(Vector v, double tol=LENGTH_EPS);
|
2008-07-06 07:56:24 +00:00
|
|
|
bool EqualsExactly(Vector v);
|
2008-04-01 10:48:44 +00:00
|
|
|
Vector Plus(Vector b);
|
|
|
|
Vector Minus(Vector b);
|
|
|
|
Vector Negated(void);
|
2008-03-27 09:53:51 +00:00
|
|
|
Vector Cross(Vector b);
|
2009-06-22 06:22:30 +00:00
|
|
|
double DirectionCosineWith(Vector b);
|
2008-04-01 10:48:44 +00:00
|
|
|
double Dot(Vector b);
|
|
|
|
Vector Normal(int which);
|
2008-06-06 11:35:28 +00:00
|
|
|
Vector RotatedAbout(Vector orig, Vector axis, double theta);
|
2008-03-27 09:53:51 +00:00
|
|
|
Vector RotatedAbout(Vector axis, double theta);
|
2008-06-21 10:18:20 +00:00
|
|
|
Vector DotInToCsys(Vector u, Vector v, Vector n);
|
|
|
|
Vector ScaleOutOfCsys(Vector u, Vector v, Vector n);
|
2008-06-06 11:35:28 +00:00
|
|
|
double DistanceToLine(Vector p0, Vector dp);
|
2009-06-21 09:02:36 +00:00
|
|
|
bool OnLineSegment(Vector a, Vector b, double tol=LENGTH_EPS);
|
2008-06-14 11:16:14 +00:00
|
|
|
Vector ClosestPointOnLine(Vector p0, Vector dp);
|
2008-03-27 09:53:51 +00:00
|
|
|
double Magnitude(void);
|
2008-07-06 07:56:24 +00:00
|
|
|
double MagSquared(void);
|
2008-04-14 10:28:32 +00:00
|
|
|
Vector WithMagnitude(double s);
|
2008-04-12 14:12:26 +00:00
|
|
|
Vector ScaledBy(double s);
|
2008-05-08 07:30:30 +00:00
|
|
|
Vector ProjectInto(hEntity wrkpl);
|
2008-05-17 11:15:14 +00:00
|
|
|
Vector ProjectVectorInto(hEntity wrkpl);
|
2008-05-08 08:12:23 +00:00
|
|
|
double DivPivoting(Vector delta);
|
2008-05-11 10:40:37 +00:00
|
|
|
Vector ClosestOrtho(void);
|
2009-01-21 05:04:38 +00:00
|
|
|
void MakeMaxMin(Vector *maxv, Vector *minv);
|
2009-01-27 07:59:58 +00:00
|
|
|
static bool BoundingBoxesDisjoint(Vector amax, Vector amin,
|
|
|
|
Vector bmax, Vector bmin);
|
2009-03-08 10:59:57 +00:00
|
|
|
static bool BoundingBoxIntersectsLine(Vector amax, Vector amin,
|
|
|
|
Vector p0, Vector p1, bool segment);
|
2009-01-21 05:04:38 +00:00
|
|
|
bool OutsideAndNotOn(Vector maxv, Vector minv);
|
2009-03-17 16:33:46 +00:00
|
|
|
Vector InPerspective(Vector u, Vector v, Vector n,
|
|
|
|
Vector origin, double cameraTan);
|
2008-05-12 10:01:44 +00:00
|
|
|
Point2d Project2d(Vector u, Vector v);
|
2009-02-01 05:13:43 +00:00
|
|
|
Point2d ProjectXy(void);
|
2009-04-14 04:19:23 +00:00
|
|
|
Vector4 Project4d(void);
|
|
|
|
};
|
|
|
|
|
|
|
|
class Vector4 {
|
|
|
|
public:
|
|
|
|
double w, x, y, z;
|
|
|
|
|
|
|
|
static Vector4 From(double w, double x, double y, double z);
|
|
|
|
static Vector4 From(double w, Vector v3);
|
|
|
|
static Vector4 Blend(Vector4 a, Vector4 b, double t);
|
|
|
|
|
|
|
|
Vector4 Plus(Vector4 b);
|
|
|
|
Vector4 Minus(Vector4 b);
|
|
|
|
Vector4 ScaledBy(double s);
|
|
|
|
Vector PerspectiveProject(void);
|
2008-03-28 10:00:37 +00:00
|
|
|
};
|
2008-03-25 10:02:13 +00:00
|
|
|
|
2008-03-28 10:00:37 +00:00
|
|
|
class Point2d {
|
|
|
|
public:
|
2008-03-27 09:53:51 +00:00
|
|
|
double x, y;
|
2008-04-12 14:12:26 +00:00
|
|
|
|
2009-03-14 20:01:20 +00:00
|
|
|
static Point2d From(double x, double y);
|
|
|
|
|
2008-04-12 14:12:26 +00:00
|
|
|
Point2d Plus(Point2d b);
|
|
|
|
Point2d Minus(Point2d b);
|
|
|
|
Point2d ScaledBy(double s);
|
2009-03-19 17:40:11 +00:00
|
|
|
double DivPivoting(Point2d delta);
|
2009-02-01 05:13:43 +00:00
|
|
|
double Dot(Point2d p);
|
2008-04-12 14:12:26 +00:00
|
|
|
double DistanceTo(Point2d p);
|
|
|
|
double DistanceToLine(Point2d p0, Point2d dp, bool segment);
|
2008-04-22 05:00:49 +00:00
|
|
|
double Magnitude(void);
|
2009-02-23 10:06:02 +00:00
|
|
|
double MagSquared(void);
|
2008-04-22 05:00:49 +00:00
|
|
|
Point2d WithMagnitude(double v);
|
2009-02-01 05:13:43 +00:00
|
|
|
Point2d Normal(void);
|
2009-02-23 10:06:02 +00:00
|
|
|
bool Equals(Point2d v, double tol=LENGTH_EPS);
|
2008-03-28 10:00:37 +00:00
|
|
|
};
|
2008-03-27 09:53:51 +00:00
|
|
|
|
2009-01-13 06:56:05 +00:00
|
|
|
// A simple list
|
|
|
|
template <class T>
|
|
|
|
class List {
|
|
|
|
public:
|
|
|
|
T *elem;
|
|
|
|
int n;
|
|
|
|
int elemsAllocated;
|
|
|
|
|
|
|
|
void Add(T *t) {
|
|
|
|
if(n >= elemsAllocated) {
|
|
|
|
elemsAllocated = (elemsAllocated + 32)*2;
|
|
|
|
elem = (T *)MemRealloc(elem, elemsAllocated*sizeof(elem[0]));
|
|
|
|
}
|
|
|
|
elem[n++] = *t;
|
|
|
|
}
|
|
|
|
|
2009-01-19 10:37:10 +00:00
|
|
|
T *First(void) {
|
|
|
|
return (n == 0) ? NULL : &(elem[0]);
|
|
|
|
}
|
|
|
|
T *NextAfter(T *prev) {
|
|
|
|
if(!prev) return NULL;
|
|
|
|
if(prev - elem == (n - 1)) return NULL;
|
|
|
|
return prev + 1;
|
|
|
|
}
|
|
|
|
|
2009-01-13 06:56:05 +00:00
|
|
|
void ClearTags(void) {
|
|
|
|
int i;
|
|
|
|
for(i = 0; i < n; i++) {
|
|
|
|
elem[i].tag = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Clear(void) {
|
|
|
|
if(elem) MemFree(elem);
|
|
|
|
elem = NULL;
|
|
|
|
n = elemsAllocated = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void RemoveTagged(void) {
|
|
|
|
int src, dest;
|
|
|
|
dest = 0;
|
|
|
|
for(src = 0; src < n; src++) {
|
|
|
|
if(elem[src].tag) {
|
|
|
|
// this item should be deleted
|
|
|
|
} else {
|
|
|
|
if(src != dest) {
|
|
|
|
elem[dest] = elem[src];
|
|
|
|
}
|
|
|
|
dest++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
n = dest;
|
|
|
|
// and elemsAllocated is untouched, because we didn't resize
|
|
|
|
}
|
2009-01-19 03:33:15 +00:00
|
|
|
|
|
|
|
void Reverse(void) {
|
|
|
|
int i;
|
|
|
|
for(i = 0; i < (n/2); i++) {
|
|
|
|
SWAP(T, elem[i], elem[(n-1)-i]);
|
|
|
|
}
|
|
|
|
}
|
2009-01-13 06:56:05 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
// A list, where each element has an integer identifier. The list is kept
|
|
|
|
// sorted by that identifier, and items can be looked up in log n time by
|
|
|
|
// id.
|
2008-03-28 10:00:37 +00:00
|
|
|
template <class T, class H>
|
|
|
|
class IdList {
|
|
|
|
public:
|
2008-04-18 07:21:17 +00:00
|
|
|
T *elem;
|
2008-04-18 11:11:48 +00:00
|
|
|
int n;
|
2008-04-18 07:21:17 +00:00
|
|
|
int elemsAllocated;
|
2008-03-26 09:18:12 +00:00
|
|
|
|
2008-04-09 08:39:01 +00:00
|
|
|
H AddAndAssignId(T *t) {
|
2008-03-28 10:00:37 +00:00
|
|
|
int i;
|
2008-04-09 08:39:01 +00:00
|
|
|
DWORD id = 0;
|
2008-03-28 10:00:37 +00:00
|
|
|
|
2008-04-18 11:11:48 +00:00
|
|
|
for(i = 0; i < n; i++) {
|
2008-04-18 07:21:17 +00:00
|
|
|
id = max(id, elem[i].h.v);
|
2008-03-28 10:00:37 +00:00
|
|
|
}
|
|
|
|
|
2008-04-09 08:39:01 +00:00
|
|
|
t->h.v = (id + 1);
|
|
|
|
Add(t);
|
2008-04-08 12:54:53 +00:00
|
|
|
|
2008-04-09 08:39:01 +00:00
|
|
|
return t->h;
|
2008-03-28 10:00:37 +00:00
|
|
|
}
|
|
|
|
|
2008-04-09 08:39:01 +00:00
|
|
|
void Add(T *t) {
|
2008-04-18 11:11:48 +00:00
|
|
|
if(n >= elemsAllocated) {
|
2008-03-28 10:00:37 +00:00
|
|
|
elemsAllocated = (elemsAllocated + 32)*2;
|
2008-04-18 07:21:17 +00:00
|
|
|
elem = (T *)MemRealloc(elem, elemsAllocated*sizeof(elem[0]));
|
2008-03-28 10:00:37 +00:00
|
|
|
}
|
|
|
|
|
2008-06-12 04:36:33 +00:00
|
|
|
int first = 0, last = n;
|
|
|
|
// We know that we must insert within the closed interval [first,last]
|
|
|
|
while(first != last) {
|
|
|
|
int mid = (first + last)/2;
|
|
|
|
H hm = elem[mid].h;
|
|
|
|
if(hm.v > t->h.v) {
|
|
|
|
last = mid;
|
|
|
|
} else if(hm.v < t->h.v) {
|
|
|
|
first = mid + 1;
|
|
|
|
} else {
|
2009-04-20 07:30:09 +00:00
|
|
|
dbp("can't insert in list; is handle %d not unique?", t->h.v);
|
2008-06-12 04:36:33 +00:00
|
|
|
oops();
|
2008-06-06 07:50:08 +00:00
|
|
|
}
|
|
|
|
}
|
2008-06-12 04:36:33 +00:00
|
|
|
int i = first;
|
|
|
|
|
2008-06-06 07:50:08 +00:00
|
|
|
memmove(elem+i+1, elem+i, (n-i)*sizeof(elem[0]));
|
|
|
|
elem[i] = *t;
|
2008-04-18 11:11:48 +00:00
|
|
|
n++;
|
2008-03-28 10:00:37 +00:00
|
|
|
}
|
2008-06-12 04:36:33 +00:00
|
|
|
|
2008-04-08 12:54:53 +00:00
|
|
|
T *FindById(H h) {
|
2008-04-13 10:57:41 +00:00
|
|
|
T *t = FindByIdNoOops(h);
|
|
|
|
if(!t) {
|
2008-04-19 11:09:47 +00:00
|
|
|
dbp("failed to look up item %08x, searched %d items", h.v, n);
|
2008-04-13 10:57:41 +00:00
|
|
|
oops();
|
|
|
|
}
|
|
|
|
return t;
|
|
|
|
}
|
|
|
|
|
|
|
|
T *FindByIdNoOops(H h) {
|
2008-06-06 07:50:08 +00:00
|
|
|
int first = 0, last = n-1;
|
|
|
|
while(first <= last) {
|
|
|
|
int mid = (first + last)/2;
|
|
|
|
H hm = elem[mid].h;
|
|
|
|
if(hm.v > h.v) {
|
|
|
|
last = mid-1; // and first stays the same
|
|
|
|
} else if(hm.v < h.v) {
|
|
|
|
first = mid+1; // and last stays the same
|
|
|
|
} else {
|
|
|
|
return &(elem[mid]);
|
2008-04-08 12:54:53 +00:00
|
|
|
}
|
|
|
|
}
|
2008-04-13 10:57:41 +00:00
|
|
|
return NULL;
|
2008-04-08 12:54:53 +00:00
|
|
|
}
|
|
|
|
|
2009-01-19 10:37:10 +00:00
|
|
|
T *First(void) {
|
|
|
|
return (n == 0) ? NULL : &(elem[0]);
|
|
|
|
}
|
|
|
|
T *NextAfter(T *prev) {
|
|
|
|
if(!prev) return NULL;
|
|
|
|
if(prev - elem == (n - 1)) return NULL;
|
|
|
|
return prev + 1;
|
|
|
|
}
|
|
|
|
|
2008-04-08 12:54:53 +00:00
|
|
|
void ClearTags(void) {
|
|
|
|
int i;
|
2008-04-18 11:11:48 +00:00
|
|
|
for(i = 0; i < n; i++) {
|
2008-04-08 12:54:53 +00:00
|
|
|
elem[i].tag = 0;
|
|
|
|
}
|
|
|
|
}
|
2008-03-28 10:00:37 +00:00
|
|
|
|
2008-04-14 10:28:32 +00:00
|
|
|
void Tag(H h, int tag) {
|
|
|
|
int i;
|
2008-04-18 11:11:48 +00:00
|
|
|
for(i = 0; i < n; i++) {
|
2008-04-18 07:21:17 +00:00
|
|
|
if(elem[i].h.v == h.v) {
|
2008-04-14 10:28:32 +00:00
|
|
|
elem[i].tag = tag;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-03-28 10:00:37 +00:00
|
|
|
void RemoveTagged(void) {
|
|
|
|
int src, dest;
|
|
|
|
dest = 0;
|
2008-04-18 11:11:48 +00:00
|
|
|
for(src = 0; src < n; src++) {
|
2008-03-28 10:00:37 +00:00
|
|
|
if(elem[src].tag) {
|
|
|
|
// this item should be deleted
|
|
|
|
} else {
|
|
|
|
if(src != dest) {
|
|
|
|
elem[dest] = elem[src];
|
|
|
|
}
|
|
|
|
dest++;
|
|
|
|
}
|
|
|
|
}
|
2008-04-18 11:11:48 +00:00
|
|
|
n = dest;
|
2008-04-08 12:54:53 +00:00
|
|
|
// and elemsAllocated is untouched, because we didn't resize
|
2008-03-28 10:00:37 +00:00
|
|
|
}
|
2008-05-17 06:04:55 +00:00
|
|
|
void RemoveById(H h) {
|
|
|
|
ClearTags();
|
|
|
|
FindById(h)->tag = 1;
|
|
|
|
RemoveTagged();
|
|
|
|
}
|
2008-03-28 10:00:37 +00:00
|
|
|
|
2008-04-13 10:57:41 +00:00
|
|
|
void MoveSelfInto(IdList<T,H> *l) {
|
|
|
|
memcpy(l, this, sizeof(*this));
|
2008-04-18 11:11:48 +00:00
|
|
|
elemsAllocated = n = 0;
|
2008-04-13 10:57:41 +00:00
|
|
|
elem = NULL;
|
|
|
|
}
|
|
|
|
|
2008-04-21 08:16:38 +00:00
|
|
|
void DeepCopyInto(IdList<T,H> *l) {
|
|
|
|
l->elem = (T *)MemAlloc(elemsAllocated * sizeof(elem[0]));
|
|
|
|
memcpy(l->elem, elem, elemsAllocated * sizeof(elem[0]));
|
|
|
|
l->elemsAllocated = elemsAllocated;
|
|
|
|
l->n = n;
|
|
|
|
}
|
|
|
|
|
2008-03-28 10:00:37 +00:00
|
|
|
void Clear(void) {
|
2008-04-18 11:11:48 +00:00
|
|
|
elemsAllocated = n = 0;
|
2008-05-07 04:17:29 +00:00
|
|
|
if(elem) MemFree(elem);
|
2008-04-12 16:28:48 +00:00
|
|
|
elem = NULL;
|
2008-03-28 10:00:37 +00:00
|
|
|
}
|
2008-03-26 09:18:12 +00:00
|
|
|
|
|
|
|
};
|
|
|
|
|
2008-04-08 12:54:53 +00:00
|
|
|
class NameStr {
|
|
|
|
public:
|
2008-06-12 08:58:58 +00:00
|
|
|
char str[64];
|
2008-04-08 12:54:53 +00:00
|
|
|
|
|
|
|
inline void strcpy(char *in) {
|
|
|
|
memcpy(str, in, min(strlen(in)+1, sizeof(str)));
|
|
|
|
str[sizeof(str)-1] = '\0';
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2008-03-25 10:02:13 +00:00
|
|
|
#endif
|