Initial commit
This commit is contained in:
188
lib/dtsSDK/DTSBrushMesh.cpp
Executable file
188
lib/dtsSDK/DTSBrushMesh.cpp
Executable file
@ -0,0 +1,188 @@
|
||||
|
||||
#pragma warning ( disable: 4786 )
|
||||
#include <vector>
|
||||
#include <cmath>
|
||||
|
||||
#include "DTSBrushMesh.h"
|
||||
|
||||
#ifndef M_PI
|
||||
#define M_PI 3.1415926535f
|
||||
#endif
|
||||
|
||||
namespace DTS
|
||||
{
|
||||
|
||||
void BrushMesh::addVertex(float x, float y, float z)
|
||||
{
|
||||
verts.push_back(Point(x, y, z));
|
||||
tverts.push_back(Point2D(x+z, y+z));
|
||||
Point normal = Point(x, y, z) - getCenter() ;
|
||||
normal.normalize() ;
|
||||
normals.push_back(normal) ;
|
||||
enormals.push_back(encodeNormal(normal)) ;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// Creates a vertical cylinder
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
CylinderMesh::CylinderMesh (Box &_bounds, float _radius, float _complexity)
|
||||
{
|
||||
setRadius (_radius) ;
|
||||
setBounds (_bounds) ;
|
||||
setCenter (_bounds.min.midpoint(_bounds.max)) ;
|
||||
|
||||
complexity = _complexity ;
|
||||
|
||||
construct() ;
|
||||
}
|
||||
|
||||
void CylinderMesh::construct()
|
||||
{
|
||||
int i, firstTop ;
|
||||
int steps = (unsigned int)(complexity * 64.0f) ;
|
||||
float angle ;
|
||||
Point normal ;
|
||||
Box bounds = getBounds() ;
|
||||
Point center = getCenter() ;
|
||||
float radius = getRadius() ;
|
||||
|
||||
Primitive p ;
|
||||
p.type = Primitive::NoMaterial | Primitive::Strip | Primitive::Indexed ;
|
||||
|
||||
if (steps < 4) steps = 4 ;
|
||||
if (steps > 64) steps = 64 ;
|
||||
steps &= ~1 ;
|
||||
|
||||
// Bottom
|
||||
addVertex (center.x(), center.y(), bounds.min.z()) ;
|
||||
for (angle = 0.0f, i = 0 ; i < steps ; i++, angle += 2.0f*M_PI/(float)steps)
|
||||
{
|
||||
addVertex (cosf(angle)*radius + center.x(), sinf(angle)*radius + center.y(),
|
||||
bounds.min.z()) ;
|
||||
}
|
||||
|
||||
for (i = 1 ; i <= steps ; i++)
|
||||
{
|
||||
p.firstElement = indices.size() ;
|
||||
p.numElements = 3 ;
|
||||
indices.push_back (0) ;
|
||||
indices.push_back (i) ;
|
||||
indices.push_back (i == steps ? 1 : i+1) ;
|
||||
primitives.push_back(p) ;
|
||||
}
|
||||
|
||||
// Top
|
||||
firstTop = verts.size() ;
|
||||
addVertex (center.x(), center.y(), bounds.max.z()) ;
|
||||
for (angle = 0.0f, i = 0 ; i < steps ; i++, angle += 2.0f*M_PI/(float)steps)
|
||||
{
|
||||
addVertex (cosf(angle)*radius + center.x(), sinf(angle)*radius + center.y(),
|
||||
bounds.max.z()) ;
|
||||
}
|
||||
|
||||
for (i = 1 ; i <= steps ; i++)
|
||||
{
|
||||
p.firstElement = indices.size() ;
|
||||
p.numElements = 3 ;
|
||||
indices.push_back (firstTop) ;
|
||||
indices.push_back (firstTop+(i == steps ? 1 : i+1)) ;
|
||||
indices.push_back (firstTop+i) ;
|
||||
primitives.push_back(p) ;
|
||||
}
|
||||
|
||||
// Walls
|
||||
int pos ;
|
||||
for (pos = indices.size(), i = 0 ; i < steps-1 ; i++, pos += 4)
|
||||
{
|
||||
indices.push_back (i+1) ;
|
||||
indices.push_back (firstTop+i+1) ;
|
||||
indices.push_back (i+2) ;
|
||||
indices.push_back (firstTop+i+2) ;
|
||||
p.firstElement = pos ;
|
||||
p.numElements = 4 ;
|
||||
primitives.push_back(p) ;
|
||||
}
|
||||
indices.push_back (i+1) ;
|
||||
indices.push_back (firstTop+i+1) ;
|
||||
indices.push_back (1) ;
|
||||
indices.push_back (firstTop+1) ;
|
||||
p.firstElement = pos ;
|
||||
p.numElements = 4 ;
|
||||
primitives.push_back(p) ;
|
||||
|
||||
// Other stuff
|
||||
|
||||
setFrames (1) ;
|
||||
setParent (-1) ;
|
||||
calculateBounds() ;
|
||||
calculateCenter() ;
|
||||
calculateRadius() ;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// Creates a box
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
BoxMesh::BoxMesh (Box & _bounds)
|
||||
{
|
||||
setBounds(_bounds) ;
|
||||
construct() ;
|
||||
}
|
||||
|
||||
void BoxMesh::construct()
|
||||
{
|
||||
int i ;
|
||||
Box bounds = getBounds() ;
|
||||
Point center = (bounds.max - bounds.min) / 2 ;
|
||||
|
||||
// Vertex
|
||||
verts.push_back(Point(bounds.min.x(), bounds.min.y(), bounds.min.z()));
|
||||
verts.push_back(Point(bounds.max.x(), bounds.min.y(), bounds.min.z()));
|
||||
verts.push_back(Point(bounds.min.x(), bounds.max.y(), bounds.min.z()));
|
||||
verts.push_back(Point(bounds.max.x(), bounds.max.y(), bounds.min.z()));
|
||||
verts.push_back(Point(bounds.min.x(), bounds.min.y(), bounds.max.z()));
|
||||
verts.push_back(Point(bounds.max.x(), bounds.min.y(), bounds.max.z()));
|
||||
verts.push_back(Point(bounds.min.x(), bounds.max.y(), bounds.max.z()));
|
||||
verts.push_back(Point(bounds.max.x(), bounds.max.y(), bounds.max.z()));
|
||||
|
||||
// Texture coordinates
|
||||
for (i = 0 ; i < 8 ; i++)
|
||||
tverts.push_back(Point2D(0,0));
|
||||
|
||||
// Indices
|
||||
int inds[] = { 0, 4, 1, 5, 3, 7, 2, 6, 0, 4, 6, 7, 4, 5, 0, 1, 2, 3 } ;
|
||||
for (i = 0 ; i < sizeof(inds)/sizeof(inds[0]) ; i++)
|
||||
indices.push_back(inds[i]);
|
||||
|
||||
// Primitives
|
||||
Primitive p ;
|
||||
p.firstElement = 0 ;
|
||||
p.numElements = 10 ;
|
||||
p.type = Primitive::NoMaterial | Primitive::Strip | Primitive::Indexed ;
|
||||
primitives.push_back(p) ;
|
||||
p.firstElement = 10 ;
|
||||
p.numElements = 4 ;
|
||||
primitives.push_back(p) ;
|
||||
p.firstElement = 14 ;
|
||||
primitives.push_back(p) ;
|
||||
|
||||
// Normals
|
||||
std::vector<Point>::iterator ptr ;
|
||||
for (ptr = verts.begin() ; ptr != verts.end() ; ptr++)
|
||||
{
|
||||
Point normal ;
|
||||
normal = *ptr - center ;
|
||||
normal.normalize() ;
|
||||
normals.push_back (normal) ;
|
||||
enormals.push_back (encodeNormal(normal)) ;
|
||||
}
|
||||
|
||||
// Other stuff
|
||||
setFrames (1) ;
|
||||
setParent (-1) ;
|
||||
calculateCenter() ;
|
||||
calculateRadius() ;
|
||||
}
|
||||
|
||||
}
|
51
lib/dtsSDK/DTSBrushMesh.h
Executable file
51
lib/dtsSDK/DTSBrushMesh.h
Executable file
@ -0,0 +1,51 @@
|
||||
#ifndef __DTSBRUSHMESH_H
|
||||
#define __DTSBRUSHMESH_H
|
||||
|
||||
#include "DTSMesh.h"
|
||||
|
||||
namespace DTS
|
||||
{
|
||||
class BrushMesh : public Mesh
|
||||
{
|
||||
public:
|
||||
|
||||
//! Creates an standard mesh by default
|
||||
BrushMesh() : Mesh(T_Standard) {}
|
||||
|
||||
//! Creates (or recreates) the mesh
|
||||
virtual void construct() = 0 ;
|
||||
|
||||
protected:
|
||||
|
||||
//! Create a new vertex with convenient (altough arbitrary) normal/texture data
|
||||
void addVertex (float, float, float) ;
|
||||
};
|
||||
|
||||
class CylinderMesh : public BrushMesh
|
||||
{
|
||||
public:
|
||||
|
||||
//! Create a standard mesh as a cylinder (the box is used for the center and Z range)
|
||||
CylinderMesh (Box &, float radius, float complexity = 0.25f) ;
|
||||
|
||||
//! Creates (or recreates) the mesh
|
||||
virtual void construct() ;
|
||||
|
||||
private:
|
||||
|
||||
float complexity ;
|
||||
};
|
||||
|
||||
class BoxMesh : public BrushMesh
|
||||
{
|
||||
public:
|
||||
|
||||
//! Create a standard mesh as a box
|
||||
BoxMesh (Box &) ;
|
||||
|
||||
//! Creates (or recreates) the mesh
|
||||
virtual void construct() ;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
85
lib/dtsSDK/DTSEndian.h
Executable file
85
lib/dtsSDK/DTSEndian.h
Executable file
@ -0,0 +1,85 @@
|
||||
#ifndef __DTSENDIAN_H
|
||||
#define __DTSENDIAN_H
|
||||
|
||||
// Big endian support. Note that one should not hold onto the
|
||||
// returned reference in the FIX_ENDIAN methods. Return reference
|
||||
// to a static variable so that one can use & operator on return value.
|
||||
|
||||
namespace DTS
|
||||
{
|
||||
|
||||
inline bool isLittleEndian()
|
||||
{
|
||||
int test = 1;
|
||||
char * t0 = (char*)&test;
|
||||
++*t0;
|
||||
return (test==2);
|
||||
}
|
||||
inline void FIX_ENDIAN2(void * val)
|
||||
{
|
||||
char * ptr = (char*)val;
|
||||
char tmp = ptr[0];
|
||||
ptr[0] = ptr[1];
|
||||
ptr[1] = tmp;
|
||||
}
|
||||
|
||||
inline void FIX_ENDIAN4(void * val)
|
||||
{
|
||||
char * ptr = (char*)val;
|
||||
char tmp = ptr[0];
|
||||
ptr[0] = ptr[3];
|
||||
ptr[3] = tmp;
|
||||
tmp = ptr[1];
|
||||
ptr[1] = ptr[2];
|
||||
ptr[2] = tmp;
|
||||
}
|
||||
|
||||
inline short & FIX_ENDIAN(short val)
|
||||
{
|
||||
if (!isLittleEndian())
|
||||
FIX_ENDIAN2(&val);
|
||||
static short out;
|
||||
out = val;
|
||||
return out;
|
||||
}
|
||||
|
||||
inline unsigned short & FIX_ENDIAN(unsigned short val)
|
||||
{
|
||||
return (unsigned short&)FIX_ENDIAN(short(val));
|
||||
}
|
||||
|
||||
inline int & FIX_ENDIAN(int val)
|
||||
{
|
||||
if (!isLittleEndian())
|
||||
FIX_ENDIAN4(&val);
|
||||
static int out;
|
||||
out = val;
|
||||
return out;
|
||||
}
|
||||
|
||||
inline unsigned int & FIX_ENDIAN(unsigned int val)
|
||||
{
|
||||
return (unsigned int&)FIX_ENDIAN( int(val));
|
||||
}
|
||||
|
||||
inline float & FIX_ENDIAN(float val)
|
||||
{
|
||||
if (!isLittleEndian())
|
||||
FIX_ENDIAN4(&val);
|
||||
static float out;
|
||||
out = val;
|
||||
return out;
|
||||
}
|
||||
|
||||
#ifdef __APPLE__
|
||||
inline int & FIX_ENDIAN(size_t val)
|
||||
{
|
||||
static int out;
|
||||
out = val;
|
||||
if (!isLittleEndian())
|
||||
FIX_ENDIAN4(&out);
|
||||
return out;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#endif
|
346
lib/dtsSDK/DTSInputStream.h
Executable file
346
lib/dtsSDK/DTSInputStream.h
Executable file
@ -0,0 +1,346 @@
|
||||
#ifndef __DTSINPUTSTREAM_H
|
||||
#define __DTSINPUTSTREAM_H
|
||||
|
||||
#include <cassert>
|
||||
#include <vector>
|
||||
#include <fstream>
|
||||
|
||||
#include "DTSShape.h"
|
||||
|
||||
namespace DTS
|
||||
{
|
||||
// -------------------------------------------------------------------------
|
||||
// class InputStream
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
/*! This is more or less a quick hack to provide future loading
|
||||
features to the library. Refere to the OutputStream for info,
|
||||
this is almost a copy of that.
|
||||
*/
|
||||
|
||||
class InputStream
|
||||
{
|
||||
public:
|
||||
|
||||
//! Load the stream.
|
||||
InputStream (std::istream &) ;
|
||||
~InputStream () ;
|
||||
|
||||
int version() { return DTSVersion ; }
|
||||
|
||||
//! Read "count" dwords (= count x 4 bytes). A null pointer is OK
|
||||
void read (int *, int count) ;
|
||||
|
||||
//! Read "count" words (= count x 2 bytes). A null pointer is OK
|
||||
void read (short *, int count) ;
|
||||
|
||||
//! Read "count" bytes . A null pointer is OK
|
||||
void read (char *, int count) ;
|
||||
|
||||
//! Read one dword . A null pointer is used to discard the value
|
||||
InputStream & operator >> (int &value) { read(&value, 1) ; return *this ; }
|
||||
|
||||
//! Read one word
|
||||
InputStream & operator >> (short &value) { read(&value, 1) ; return *this ; }
|
||||
InputStream & operator >> (unsigned short &value) { read((short*)&value, 1) ; return *this ; }
|
||||
|
||||
//! Read one byte
|
||||
InputStream & operator >> (char &value) { read(&value, 1) ; return *this ; }
|
||||
|
||||
//! Read one dword (1 float == 32 bits)
|
||||
InputStream & operator >> (float &value)
|
||||
{
|
||||
read((int *)&value, 1) ;
|
||||
return *this ;
|
||||
}
|
||||
|
||||
//! Read one byte (provided for convenience)
|
||||
InputStream & operator >> (unsigned char &value)
|
||||
{
|
||||
read((char *)&value, 1) ;
|
||||
return *this ;
|
||||
}
|
||||
|
||||
//! Read a string (1 byte len first, then n byte-sized characters)
|
||||
InputStream & operator >> (std::string &s) ;
|
||||
|
||||
// Operators to read some usual structs
|
||||
|
||||
InputStream & operator >> (Point &) ;
|
||||
InputStream & operator >> (Point2D &) ;
|
||||
InputStream & operator >> (Box &) ;
|
||||
InputStream & operator >> (Quaternion &) ;
|
||||
InputStream & operator >> (Node &) ;
|
||||
InputStream & operator >> (Object &) ;
|
||||
InputStream & operator >> (Decal &) ;
|
||||
InputStream & operator >> (IFLMaterial &) ;
|
||||
InputStream & operator >> (DecalState &) ;
|
||||
InputStream & operator >> (DetailLevel &) ;
|
||||
InputStream & operator >> (ObjectState &) ;
|
||||
InputStream & operator >> (Subshape &) ;
|
||||
InputStream & operator >> (Trigger &) ;
|
||||
InputStream & operator >> (Primitive &) ;
|
||||
InputStream & operator >> (Mesh &) ;
|
||||
|
||||
//! Stores checkpoint values in the streams
|
||||
void readCheck (int checkPoint = -1) ;
|
||||
|
||||
private:
|
||||
|
||||
std::istream & in ;
|
||||
int DTSVersion ;
|
||||
int checkCount ;
|
||||
|
||||
// Pointers to the 3 memory buffers
|
||||
|
||||
int * Buffer32 ;
|
||||
short * Buffer16 ;
|
||||
char * Buffer8 ;
|
||||
|
||||
// Values allocated in each buffer
|
||||
|
||||
unsigned long Allocated32 ;
|
||||
unsigned long Allocated16 ;
|
||||
unsigned long Allocated8 ;
|
||||
|
||||
// Values actually used in each buffer
|
||||
|
||||
unsigned long Used32 ;
|
||||
unsigned long Used16 ;
|
||||
unsigned long Used8 ;
|
||||
};
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// Construction and destruction
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
inline InputStream::InputStream (std::istream & s) : in(s)
|
||||
{
|
||||
int totalSize ;
|
||||
int offset16 ;
|
||||
int offset8 ;
|
||||
|
||||
// Read the header
|
||||
|
||||
in.read ((char *) &DTSVersion, 4) ;
|
||||
in.read ((char *) &totalSize, 4) ;
|
||||
in.read ((char *) &offset16, 4) ;
|
||||
in.read ((char *) &offset8, 4) ;
|
||||
|
||||
// Create buffers
|
||||
|
||||
Allocated32 = offset16 ;
|
||||
Allocated16 = (offset8-offset16) * 2 ;
|
||||
Allocated8 = (totalSize-offset8) * 4 ;
|
||||
|
||||
Buffer32 = new int [Allocated32] ;
|
||||
Buffer16 = new short [Allocated16] ;
|
||||
Buffer8 = new char [Allocated8] ;
|
||||
|
||||
// Read the data
|
||||
|
||||
in.read ((char *) Buffer32, 4 * Allocated32) ;
|
||||
in.read ((char *) Buffer16, 2 * Allocated16) ;
|
||||
in.read (Buffer8, Allocated8) ;
|
||||
|
||||
checkCount = 0 ;
|
||||
Used32 = 0 ;
|
||||
Used16 = 0 ;
|
||||
Used8 = 0 ;
|
||||
}
|
||||
|
||||
inline InputStream::~InputStream()
|
||||
{
|
||||
delete [] Buffer8 ;
|
||||
delete [] Buffer16 ;
|
||||
delete [] Buffer32 ;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// Read functions
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
inline void InputStream::read (int * data, int count)
|
||||
{
|
||||
assert (count > 0) ;
|
||||
assert (Used32+count < Allocated32) ;
|
||||
if (data != 0)
|
||||
memcpy (data, Buffer32 + Used32, sizeof(int) * count) ;
|
||||
Used32 += count ;
|
||||
}
|
||||
|
||||
// The other read methods are exactly the same, except for the buffer used
|
||||
|
||||
inline void InputStream::read (short * data, int count)
|
||||
{
|
||||
assert (count > 0) ;
|
||||
assert (Used16 < Allocated16) ;
|
||||
if (data != 0)
|
||||
memcpy (data, Buffer16 + Used16, sizeof(short) * count) ;
|
||||
Used16 += count ;
|
||||
}
|
||||
|
||||
inline void InputStream::read (char * data, int count)
|
||||
{
|
||||
assert (count > 0) ;
|
||||
assert (Used8 < Allocated8) ;
|
||||
if (data == 0)
|
||||
memcpy (data, Buffer8 + Used8, sizeof(char) * count) ;
|
||||
Used8 += count ;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// Read operators
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
inline InputStream & InputStream::operator >> (Point &p)
|
||||
{
|
||||
float x, y, z ;
|
||||
(*this) >> x >> y >> z ;
|
||||
p.x(x) ;
|
||||
p.y(y) ;
|
||||
p.z(z) ;
|
||||
return *this ;
|
||||
}
|
||||
|
||||
inline InputStream & InputStream::operator >> (Point2D &p)
|
||||
{
|
||||
float x, y ;
|
||||
(*this) >> x >> y ;
|
||||
p.x(x) ;
|
||||
p.y(y) ;
|
||||
return *this ;
|
||||
}
|
||||
|
||||
inline InputStream & InputStream::operator >> (Box &b)
|
||||
{
|
||||
return (*this) >> b.min >> b.max ;
|
||||
}
|
||||
|
||||
inline InputStream & InputStream::operator >> (Quaternion &q)
|
||||
{
|
||||
short x, y, z, w ;
|
||||
(*this) >> x >> y >> z >> w ;
|
||||
q.x(x / 32767.0f) ;
|
||||
q.y(y / 32767.0f) ;
|
||||
q.z(z / 32767.0f) ;
|
||||
q.w(w / 32767.0f) ;
|
||||
return (*this) ;
|
||||
}
|
||||
|
||||
inline InputStream & InputStream::operator >> (Node &n)
|
||||
{
|
||||
return (*this) >> n.name >> n.parent >> n.firstObject
|
||||
>> n.child >> n.sibling ;
|
||||
}
|
||||
|
||||
inline InputStream & InputStream::operator >> (Object &o)
|
||||
{
|
||||
return (*this) >> o.name >> o.numMeshes >> o.firstMesh
|
||||
>> o.node >> o.sibling >> o.firstDecal ;
|
||||
}
|
||||
|
||||
inline InputStream & InputStream::operator >> (Decal &d)
|
||||
{
|
||||
return (*this) >> d.name >> d.numMeshes >> d.firstMesh
|
||||
>> d.object >> d.sibling ;
|
||||
}
|
||||
|
||||
inline InputStream & InputStream::operator >> (IFLMaterial &m)
|
||||
{
|
||||
return (*this) >> m.name >> m.slot >> m.firstFrame
|
||||
>> m.time >> m.numFrames ;
|
||||
}
|
||||
|
||||
inline InputStream & InputStream::operator >> (Subshape &s)
|
||||
{
|
||||
assert (0 && "Subshapes should be written in block") ;
|
||||
}
|
||||
|
||||
inline InputStream & InputStream::operator >> (Trigger &d)
|
||||
{
|
||||
return (*this) >> d.state >> d.pos ;
|
||||
}
|
||||
|
||||
inline InputStream & InputStream::operator >> (DecalState &d)
|
||||
{
|
||||
return (*this) >> d.frame ;
|
||||
}
|
||||
|
||||
inline InputStream & InputStream::operator >> (ObjectState &o)
|
||||
{
|
||||
return (*this) >> o.vis >> o.frame >> o.matFrame ;
|
||||
}
|
||||
|
||||
inline InputStream & InputStream::operator >> (DetailLevel &d)
|
||||
{
|
||||
return (*this) >> d.name >> d.subshape >> d.objectDetail >> d.size
|
||||
>> d.avgError >> d.maxError >> d.polyCount ;
|
||||
}
|
||||
|
||||
inline InputStream & InputStream::operator >> (Primitive &p)
|
||||
{
|
||||
return (*this) >> p.firstElement >> p.numElements >> p.type ;
|
||||
}
|
||||
|
||||
inline InputStream & InputStream::operator >> (Mesh &m)
|
||||
{
|
||||
m.read(*this) ;
|
||||
return *this ;
|
||||
}
|
||||
|
||||
inline InputStream & InputStream::operator >> (std::string &s)
|
||||
{
|
||||
char c ;
|
||||
|
||||
for (s = "" ;;)
|
||||
{
|
||||
(*this) >> c ;
|
||||
if (!c) break ;
|
||||
s += c ;
|
||||
}
|
||||
return *this ;
|
||||
}
|
||||
|
||||
template <class type>
|
||||
inline InputStream & operator >> (InputStream & in, std::vector<type> &v)
|
||||
{
|
||||
std::vector<type>::iterator pos = v.begin() ;
|
||||
while (pos != v.end())
|
||||
{
|
||||
in >> *pos++ ;
|
||||
}
|
||||
return in ;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// Checkpoints and alignment
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
/*! Sometimes during the storing process, a checkpoint value is
|
||||
stored to all the buffers at the same time. This check helps
|
||||
to determine if the files are not corrupted. */
|
||||
|
||||
inline void InputStream::readCheck(int checkPoint)
|
||||
{
|
||||
if (checkPoint >= 0)
|
||||
assert (checkPoint == checkCount) ;
|
||||
|
||||
int checkCount_int ;
|
||||
short checkCount_short ;
|
||||
char checkCount_char ;
|
||||
|
||||
(*this) >> checkCount_int ;
|
||||
(*this) >> checkCount_short ;
|
||||
(*this) >> checkCount_char ;
|
||||
|
||||
assert (checkCount_char == (char) checkCount) ;
|
||||
assert (checkCount_short == (short)checkCount) ;
|
||||
assert (checkCount_int == (int) checkCount) ;
|
||||
|
||||
checkCount++ ;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
50
lib/dtsSDK/DTSInterpolation.h
Executable file
50
lib/dtsSDK/DTSInterpolation.h
Executable file
@ -0,0 +1,50 @@
|
||||
#ifndef __DTS_INTERPOLATION_H
|
||||
#define __DTS_INTERPOLATION_H
|
||||
|
||||
#include <cmath>
|
||||
|
||||
namespace DTS
|
||||
{
|
||||
//! Not really a class, but a bunch of static interpolation functions
|
||||
|
||||
struct Interpolation
|
||||
{
|
||||
template <class type>
|
||||
static inline type linear (const type &a, const type &b, float s)
|
||||
{
|
||||
return s*a + (1-s)*b ;
|
||||
}
|
||||
|
||||
template <class type>
|
||||
static inline type quadratic (const type &a, const type &b, float s)
|
||||
{
|
||||
return sqrt( s*a*a + (1-s)*b*b );
|
||||
}
|
||||
|
||||
template <class type>
|
||||
static inline type spherical (const type &a, const type &b, float s)
|
||||
{
|
||||
return exp( s*ln(a) + (1-s)*ln(b) );
|
||||
}
|
||||
|
||||
template <class type>
|
||||
static inline type bezier (const type &a, const type &b, const type &ac, const type &bc, float s)
|
||||
{
|
||||
return (-1*s*s*s +3*s*s -3*s +1) * a
|
||||
+ (+3*s*s*s -6*s*s +3*s ) * b
|
||||
+ (-3*s*s*s +3*s*s ) * ac
|
||||
+ (+1*s*s*s ) * bc ;
|
||||
}
|
||||
|
||||
template <class type>
|
||||
static inline type hermite (const type &a, const type &b, const type &at, const type &bt, float s)
|
||||
{
|
||||
return (+2*s*s*s -3*s*s +1) * a
|
||||
+ (-2*s*s*s +3*s*s ) * b
|
||||
+ (+1*s*s*s -2*s*s +s ) * at
|
||||
+ (+1*s*s*s -1*s*s ) * bt ;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
15
lib/dtsSDK/DTSMatrix.cpp
Executable file
15
lib/dtsSDK/DTSMatrix.cpp
Executable file
@ -0,0 +1,15 @@
|
||||
|
||||
#pragma warning ( disable: 4786 )
|
||||
#include <vector>
|
||||
#include <cmath>
|
||||
|
||||
#include "DTSMatrix.h"
|
||||
|
||||
namespace DTS
|
||||
{
|
||||
void test()
|
||||
{
|
||||
Matrix<4,4> m ;
|
||||
m.inverse() ;
|
||||
}
|
||||
}
|
343
lib/dtsSDK/DTSMatrix.h
Executable file
343
lib/dtsSDK/DTSMatrix.h
Executable file
@ -0,0 +1,343 @@
|
||||
#ifndef __DTSMATRIX_H
|
||||
#define __DTSMATRIX_H
|
||||
|
||||
#include <iomanip>
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <ostream>
|
||||
#include <cmath>
|
||||
#include <cassert>
|
||||
|
||||
#include "DTSVector.h"
|
||||
#include "DTSPoint.h"
|
||||
|
||||
namespace DTS
|
||||
{
|
||||
//! Defines matrices
|
||||
|
||||
template <int rows=4, int cols=4, class type=float>
|
||||
class Matrix : public Vector<Vector<type,cols>, rows>
|
||||
{
|
||||
public:
|
||||
|
||||
typedef Vector<type,cols> Row ;
|
||||
typedef type Cell ;
|
||||
|
||||
Matrix() { /* No initialization */ }
|
||||
|
||||
Vector<type,rows> col (int n) {
|
||||
assert (n >= 0 && n < rows) ;
|
||||
|
||||
Vector<type,rows> result ;
|
||||
for (int r = 0 ; r < rows ; r++)
|
||||
result[r] = (*this)[r][n] ;
|
||||
return result ;
|
||||
}
|
||||
|
||||
void setCol (int n,Vector<type,rows> col) {
|
||||
assert (n >= 0 && n < rows) ;
|
||||
|
||||
for (int r = 0 ; r < rows ; r++)
|
||||
(*this)[r][n] = col[r];
|
||||
}
|
||||
|
||||
Matrix(const type *p) {
|
||||
for (int r = 0 ; r < rows ; r++)
|
||||
for (int c = 0 ; c < cols ; c++)
|
||||
(*this)[r][c] = *p++ ;
|
||||
}
|
||||
|
||||
inline static Matrix<rows,cols,type> identity() {
|
||||
Matrix <rows,cols,type> result ;
|
||||
for (int r = 0 ; r < rows ; r++)
|
||||
for (int c = 0 ; c < cols ; c++)
|
||||
result[r][c] = type(r == c ? 1 : 0) ;
|
||||
return result ;
|
||||
}
|
||||
|
||||
Matrix <rows, cols, type> transpose() const
|
||||
{
|
||||
Matrix <rows,cols,type> result ;
|
||||
for (int r = 0 ; r < rows ; r++)
|
||||
for (int c = 0 ; c < cols ; c++)
|
||||
result[c][r] = (*this)[r][c] ;
|
||||
return result ;
|
||||
}
|
||||
|
||||
type determinant() const ;
|
||||
|
||||
Matrix <rows, cols, type> inverse() const ;
|
||||
|
||||
//!{ Matrix operators
|
||||
|
||||
Matrix<rows,cols,type> & operator = (const Matrix<rows,cols,type> &a) {
|
||||
for (int r = 0 ; r < rows ; r++)
|
||||
for (int c = 0 ; c < cols ; c++)
|
||||
(*this)[r][c] = a[r][c] ;
|
||||
return *this ;
|
||||
}
|
||||
|
||||
template <int rows2, int cols2>
|
||||
Matrix<rows,cols2,type>
|
||||
operator * (const Matrix<rows2,cols2,type> &b)
|
||||
{
|
||||
Matrix<rows,cols2,type> result ;
|
||||
|
||||
assert (rows2 == cols) ;
|
||||
for (int r = 0 ; r < rows ; r++)
|
||||
{
|
||||
for (int c = 0 ; c < cols2 ; c++)
|
||||
{
|
||||
type cell = (*this)[r][0] * b[0][c] ;
|
||||
for (int e = 1 ; e < cols ; e++)
|
||||
cell += (*this)[r][e] * b[e][c] ;
|
||||
result[r][c] = cell ;
|
||||
}
|
||||
}
|
||||
return result ;
|
||||
}
|
||||
|
||||
Vector<type,rows> operator * (const Vector<type,rows> &v)
|
||||
{
|
||||
Vector<type,rows> result ;
|
||||
for (int r = 0 ; r < rows ; r++)
|
||||
{
|
||||
type cell = (*this)[r][0] * v[0] ;
|
||||
for (int e = 1 ; e < cols ; e++)
|
||||
cell += (*this)[r][e] * v[e] ;
|
||||
result[r] = cell ;
|
||||
}
|
||||
return result ;
|
||||
}
|
||||
|
||||
// Not needed -- and doesn't work with vc7
|
||||
//template <int rows2, int cols2>
|
||||
//operator *= (const Matrix<rows2,cols2,type> &a) { (*this) = (*this) * a ; }
|
||||
|
||||
Matrix<rows,cols,type> operator + (const Matrix<rows,cols,type> &b)
|
||||
{
|
||||
Matrix<rows,cols2,type> result ;
|
||||
for (int r = 0 ; r < rows ; r++)
|
||||
for (int c = 0 ; c < cols2 ; c++)
|
||||
result[r][c] = (*this)[r][c] + b[r][c] ;
|
||||
return result ;
|
||||
}
|
||||
|
||||
Matrix<rows,cols,type> operator += (const Matrix<rows,cols,type> &b)
|
||||
{
|
||||
Matrix<rows,cols2,type> result ;
|
||||
for (int r = 0 ; r < rows ; r++)
|
||||
for (int c = 0 ; c < cols2 ; c++)
|
||||
(*this)[r][c] += b[r][c] ;
|
||||
return result ;
|
||||
}
|
||||
|
||||
Matrix<rows,cols,type> operator - (const Matrix<rows,cols,type> &b)
|
||||
{
|
||||
Matrix<rows,cols2,type> result ;
|
||||
for (int r = 0 ; r < rows ; r++)
|
||||
for (int c = 0 ; c < cols2 ; c++)
|
||||
result[r][c] = (*this)[r][c] - b[r][c] ;
|
||||
return result ;
|
||||
}
|
||||
|
||||
Matrix<rows,cols,type> operator -= (const Matrix<rows,cols,type> &b)
|
||||
{
|
||||
Matrix<rows,cols2,type> result ;
|
||||
for (int r = 0 ; r < rows ; r++)
|
||||
for (int c = 0 ; c < cols2 ; c++)
|
||||
(*this)[r][c] -= b[r][c] ;
|
||||
return result ;
|
||||
}
|
||||
|
||||
//!}
|
||||
|
||||
inline static Matrix<4,4> rotationX(float angle)
|
||||
{
|
||||
float cells[] = {
|
||||
1, 0, 0, 0,
|
||||
0, cosf(angle), -sinf(angle), 0,
|
||||
0, sinf(angle), cosf(angle), 0,
|
||||
0, 0, 0, 1
|
||||
} ;
|
||||
return Matrix<4,4> (cells) ;
|
||||
}
|
||||
|
||||
inline static Matrix<4,4> rotationZ(float angle)
|
||||
{
|
||||
float cells[] = {
|
||||
cosf(angle), -sinf(angle), 0, 0,
|
||||
sinf(angle), cosf(angle), 0, 0,
|
||||
0, 0, 1, 0,
|
||||
0, 0, 0, 1
|
||||
} ;
|
||||
return Matrix<4,4> (cells) ;
|
||||
}
|
||||
|
||||
inline static Matrix<4,4> rotationY(float angle)
|
||||
{
|
||||
float cells[] = {
|
||||
cosf(angle), 0, -sinf(angle), 0,
|
||||
0, 1, 0, 0,
|
||||
sinf(angle), 0, cosf(angle), 0,
|
||||
0, 0, 0, 1
|
||||
} ;
|
||||
return Matrix<4,4> (cells) ;
|
||||
}
|
||||
};
|
||||
|
||||
template <int rows, int cols, class type>
|
||||
type Matrix<rows,cols,type>::determinant() const
|
||||
{
|
||||
int r, c, f ;
|
||||
type result = 0 ;
|
||||
const Matrix<rows,cols,type> &m = *this ;
|
||||
|
||||
assert (rows == cols) ;
|
||||
switch (rows)
|
||||
{
|
||||
case 1:
|
||||
return m[0][0] ;
|
||||
case 2:
|
||||
return m[0][0]*m[1][1] - m[0][1]*m[1][0] ;
|
||||
case 3:
|
||||
return m[0][0] * ( m[1][1]*m[2][2] - m[1][2]*m[2][1] )
|
||||
- m[0][1] * ( m[1][0]*m[2][2] - m[1][2]*m[2][0] )
|
||||
+ m[0][2] * ( m[1][0]*m[2][1] - m[1][1]*m[2][0] ) ;
|
||||
|
||||
#define GREATER_ORDER(o) \
|
||||
case o: \
|
||||
for (f = 0 ; f < o ; f++) \
|
||||
{ \
|
||||
type data[(o-1)*(o-1)], *ptr = data ; \
|
||||
for (r = 0 ; r < o ; r++) \
|
||||
{ \
|
||||
if (r == f) continue ; \
|
||||
for (c = 1 ; c < o ; c++) \
|
||||
*ptr++ = m[r][c] ; \
|
||||
} \
|
||||
result += m[f][0] * Matrix<o-1,o-1,type>(data) \
|
||||
.determinant() * ((f&1) ? -1:1) ; \
|
||||
} \
|
||||
return result ;
|
||||
|
||||
GREATER_ORDER(4)
|
||||
GREATER_ORDER(5)
|
||||
GREATER_ORDER(6)
|
||||
GREATER_ORDER(7)
|
||||
GREATER_ORDER(8)
|
||||
GREATER_ORDER(9)
|
||||
|
||||
#undef GREATER_ORDER
|
||||
|
||||
default:
|
||||
return 0 ;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template <int rows, int cols, class type>
|
||||
Matrix<rows,cols,type> Matrix<rows,cols,type>::inverse() const
|
||||
{
|
||||
int r, c, r2, c2 ;
|
||||
type det = determinant() ;
|
||||
type p[rows][cols] ;
|
||||
|
||||
const Matrix<rows,cols,type> &m = *this ;
|
||||
|
||||
assert (rows == cols) ;
|
||||
assert (det != 0) ;
|
||||
|
||||
switch (rows)
|
||||
{
|
||||
case 1:
|
||||
p[0][0] = m[0][0]/det ;
|
||||
break ;
|
||||
case 2:
|
||||
p[0][0] = m[1][1] / det ;
|
||||
p[0][1] = -m[0][1] / det ;
|
||||
p[1][0] = -m[1][0] / det ;
|
||||
p[1][1] = m[0][0] / det ;
|
||||
break ;
|
||||
case 3:
|
||||
p[0][0] = ( m[1][1]*m[2][2] - m[1][2]*m[2][1] ) / det ;
|
||||
p[1][0] = -( m[1][0]*m[2][2] - m[1][2]*m[2][0] ) / det ;
|
||||
p[2][0] = ( m[1][0]*m[2][1] - m[1][1]*m[2][0] ) / det ;
|
||||
p[0][1] = -( m[0][1]*m[2][2] - m[0][2]*m[2][1] ) / det ;
|
||||
p[1][1] = ( m[0][0]*m[2][2] - m[0][2]*m[2][0] ) / det ;
|
||||
p[2][1] = -( m[0][0]*m[2][1] - m[0][1]*m[2][0] ) / det ;
|
||||
p[0][2] = ( m[0][1]*m[1][2] - m[0][2]*m[1][1] ) / det ;
|
||||
p[1][2] = -( m[0][0]*m[1][2] - m[0][2]*m[1][0] ) / det ;
|
||||
p[2][2] = ( m[0][0]*m[1][1] - m[0][1]*m[1][0] ) / det ;
|
||||
break ;
|
||||
|
||||
#define GREATER_ORDER(o) \
|
||||
case o: \
|
||||
for (r = 0 ; r < o ; r++) \
|
||||
{ \
|
||||
for (c = 0 ; c < o ; c++) \
|
||||
{ \
|
||||
type data[o*o], *ptr = data ; \
|
||||
for (r2 = 0 ; r2 < o ; r2++) \
|
||||
{ \
|
||||
if (r2 == r) continue ; \
|
||||
for (c2 = 0 ; c2 < o ; c2++) \
|
||||
{ \
|
||||
if (c2 == c) continue ; \
|
||||
*ptr++ = m[r2][c2] ; \
|
||||
} \
|
||||
} \
|
||||
type sign = 1-((r+c)%2)*2 ; \
|
||||
p[c][r] = Matrix<o-1,o-1,type>(data) \
|
||||
.determinant() * sign / det ; \
|
||||
} \
|
||||
} \
|
||||
break ;
|
||||
|
||||
GREATER_ORDER(4)
|
||||
GREATER_ORDER(5)
|
||||
GREATER_ORDER(6)
|
||||
GREATER_ORDER(7)
|
||||
GREATER_ORDER(8)
|
||||
GREATER_ORDER(9)
|
||||
|
||||
#undef GREATER_ORDER
|
||||
|
||||
default:
|
||||
return 0 ;
|
||||
}
|
||||
|
||||
return Matrix<rows,cols,type> (&p[0][0]) ;
|
||||
}
|
||||
|
||||
template <int rows, int cols, class type>
|
||||
std::ostream & operator << (std::ostream &out, const Matrix<rows,cols,type> &m)
|
||||
{
|
||||
out << std::setprecision(2) << std::setiosflags(std::ios::fixed) ;
|
||||
for (int r = 0 ; r < rows ; r++)
|
||||
{
|
||||
out << "| " ;
|
||||
for (int c = 0 ; c < cols ; c++)
|
||||
out << std::setw(7) << m[r][c] << ' ' ;
|
||||
out << "|\n" ;
|
||||
}
|
||||
return out ;
|
||||
}
|
||||
|
||||
inline Point operator * (const Point &p, const Matrix<> &m)
|
||||
{
|
||||
Point result ;
|
||||
result.x( p.x()*m[0][0] + p.y()*m[0][1] + p.z()*m[0][2] + m[0][3] ) ;
|
||||
result.y( p.x()*m[1][0] + p.y()*m[1][1] + p.z()*m[1][2] + m[1][3] ) ;
|
||||
result.z( p.x()*m[2][0] + p.y()*m[2][1] + p.z()*m[2][2] + m[2][3] ) ;
|
||||
return result ;
|
||||
}
|
||||
|
||||
inline Point operator * (const Matrix<> &m, const Point &p)
|
||||
{
|
||||
return p * m ;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
462
lib/dtsSDK/DTSMesh.cpp
Executable file
462
lib/dtsSDK/DTSMesh.cpp
Executable file
@ -0,0 +1,462 @@
|
||||
|
||||
#pragma warning ( disable: 4786 )
|
||||
#include <vector>
|
||||
#include <cmath>
|
||||
|
||||
#include "DTSMesh.h"
|
||||
#include "DTSOutputStream.h"
|
||||
#include "DTSInputStream.h"
|
||||
|
||||
namespace DTS
|
||||
{
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// Normal encoding transformation
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
#include "DTSNormalTable.cpp"
|
||||
|
||||
char Mesh::encodeNormal(const Point & normal)
|
||||
{
|
||||
unsigned char bestIndex = 0;
|
||||
float bestDot = -10E30F ;
|
||||
|
||||
for (int i = 0 ; i < 256 ; i++)
|
||||
{
|
||||
float dot =
|
||||
( normal.x() * normalTable[i][0]
|
||||
+ normal.y() * normalTable[i][1]
|
||||
+ normal.z() * normalTable[i][2] ) ;
|
||||
|
||||
if (dot > bestDot)
|
||||
{
|
||||
bestIndex = i;
|
||||
bestDot = dot;
|
||||
}
|
||||
}
|
||||
|
||||
return * (char*)&bestIndex;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// Searchs for minor and maximum vertex coordinates
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
void Mesh::calculateBounds()
|
||||
{
|
||||
std::vector<Point>::iterator vertex ;
|
||||
|
||||
bounds.max = Point(-10E30F, -10E30F, -10E30F) ;
|
||||
bounds.min = Point( 10E30F, 10E30F, 10E30F) ;
|
||||
for (vertex = verts.begin() ; vertex != verts.end() ; vertex++)
|
||||
{
|
||||
if (vertex->x() < bounds.min.x())
|
||||
bounds.min.x(vertex->x()) ;
|
||||
if (vertex->y() < bounds.min.y())
|
||||
bounds.min.y(vertex->y()) ;
|
||||
if (vertex->z() < bounds.min.z())
|
||||
bounds.min.z(vertex->z()) ;
|
||||
if (vertex->x() > bounds.max.x())
|
||||
bounds.max.x(vertex->x()) ;
|
||||
if (vertex->y() > bounds.max.y())
|
||||
bounds.max.y(vertex->y()) ;
|
||||
if (vertex->z() > bounds.max.z())
|
||||
bounds.max.z(vertex->z()) ;
|
||||
}
|
||||
}
|
||||
|
||||
Box Mesh::getBounds(Point trans,Quaternion rot) const
|
||||
{
|
||||
// Compute the bounding box using the given transform.
|
||||
Box bounds2;
|
||||
bounds2.max = Point(-10E30F, -10E30F, -10E30F) ;
|
||||
bounds2.min = Point( 10E30F, 10E30F, 10E30F) ;
|
||||
|
||||
std::vector<Point>::const_iterator vertex ;
|
||||
for (vertex = verts.begin() ; vertex != verts.end() ; vertex++)
|
||||
{
|
||||
Point tv = rot.apply(*vertex) + trans;
|
||||
|
||||
if (tv.x() < bounds2.min.x())
|
||||
bounds2.min.x(tv.x()) ;
|
||||
if (tv.y() < bounds2.min.y())
|
||||
bounds2.min.y(tv.y()) ;
|
||||
if (tv.z() < bounds2.min.z())
|
||||
bounds2.min.z(tv.z()) ;
|
||||
if (tv.x() > bounds2.max.x())
|
||||
bounds2.max.x(tv.x()) ;
|
||||
if (tv.y() > bounds2.max.y())
|
||||
bounds2.max.y(tv.y()) ;
|
||||
if (tv.z() > bounds2.max.z())
|
||||
bounds2.max.z(tv.z()) ;
|
||||
}
|
||||
return bounds2;
|
||||
}
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// Calculates center of bounding box
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
void Mesh::calculateCenter()
|
||||
{
|
||||
center = bounds.max.midpoint(bounds.min) ;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// Search for the maximum vertex distance from center
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
void Mesh::calculateRadius()
|
||||
{
|
||||
radius = getRadiusFrom(Point(0,0,0),Quaternion::identity,center) ;
|
||||
}
|
||||
|
||||
float Mesh::getRadiusFrom(Point trans, Quaternion rot, Point center) const
|
||||
{
|
||||
std::vector<Point>::const_iterator vertex ;
|
||||
|
||||
float radius = 0.0F ;
|
||||
for (vertex = verts.begin() ; vertex != verts.end() ; vertex++)
|
||||
{
|
||||
Point tv = rot.apply(*vertex) + trans;
|
||||
float distance = (tv - center).length() ;
|
||||
if (distance > radius)
|
||||
radius = distance ;
|
||||
}
|
||||
return radius ;
|
||||
}
|
||||
|
||||
float Mesh::getTubeRadius() const
|
||||
{
|
||||
std::vector<Point>::const_iterator vertex ;
|
||||
|
||||
float radius = 0.0F ;
|
||||
for (vertex = verts.begin() ; vertex != verts.end() ; vertex++)
|
||||
{
|
||||
float distance = (*vertex - center).length(2) ;
|
||||
if (distance > radius)
|
||||
radius = distance ;
|
||||
}
|
||||
return radius ;
|
||||
}
|
||||
|
||||
float Mesh::getTubeRadiusFrom(Point trans, Quaternion rot, Point center) const
|
||||
{
|
||||
std::vector<Point>::const_iterator vertex ;
|
||||
|
||||
float radius = 0.0F ;
|
||||
for (vertex = verts.begin() ; vertex != verts.end() ; vertex++)
|
||||
{
|
||||
Point tv = rot.apply(*vertex) + trans;
|
||||
float distance = (tv - center).length(2) ;
|
||||
if (distance > radius)
|
||||
radius = distance ;
|
||||
}
|
||||
return radius ;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// Calculate the polygon count
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
int Mesh::getPolyCount() const
|
||||
{
|
||||
int count = 0 ;
|
||||
|
||||
std::vector<Primitive>::const_iterator p ;
|
||||
for (p = primitives.begin() ; p != primitives.end() ; p++)
|
||||
{
|
||||
if (p->type & Primitive::Strip)
|
||||
count += p->numElements - 2 ;
|
||||
else
|
||||
count += p->numElements / 3 ;
|
||||
}
|
||||
return count ;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// Creates an empty mesh
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
Mesh::Mesh(Type t)
|
||||
{
|
||||
bounds.min = Point(0,0,0) ;
|
||||
bounds.max = Point(0,0,0) ;
|
||||
center = Point(0,0,0) ;
|
||||
radius = 0.0f ;
|
||||
numFrames = 1 ;
|
||||
matFrames = 1 ;
|
||||
vertsPerFrame = 0 ;
|
||||
parent = -1 ;
|
||||
flags = 0 ;
|
||||
type = t ;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// Joins another mesh with this one
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
Mesh & Mesh::operator += (const Mesh & m)
|
||||
{
|
||||
int firstIndex = indices.size();
|
||||
int firstVertex = verts.size() ;
|
||||
int firstPrimit = primitives.size() ;
|
||||
int i ;
|
||||
|
||||
verts.insert (verts.end(), m.verts.begin(), m.verts.end()) ;
|
||||
tverts.insert (tverts.end(), m.tverts.begin(), m.tverts.end()) ;
|
||||
indices.insert (indices.end(), m.indices.begin(), m.indices.end()) ;
|
||||
normals.insert (normals.end(), m.normals.begin(), m.normals.end()) ;
|
||||
enormals.insert (enormals.end(), m.enormals.begin(), m.enormals.end()) ;
|
||||
primitives.insert (primitives.end(), m.primitives.begin(), m.primitives.end()) ;
|
||||
|
||||
for (i = firstIndex ; i < indices.size() ; i++)
|
||||
indices[i] += firstVertex ;
|
||||
for (i = firstPrimit ; i < primitives.size() ; i++)
|
||||
primitives[i].firstElement += firstIndex ;
|
||||
|
||||
calculateBounds() ;
|
||||
calculateCenter() ;
|
||||
calculateRadius() ;
|
||||
|
||||
vertsPerFrame = verts.size() ;
|
||||
|
||||
return *this ;
|
||||
}
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// Input/output
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
void Mesh::read (InputStream &stream)
|
||||
{
|
||||
stream >> type ;
|
||||
if (type == T_Null) return ;
|
||||
|
||||
stream.readCheck() ;
|
||||
|
||||
// Header & Bounds
|
||||
|
||||
stream >> numFrames >> matFrames >> parent ;
|
||||
stream >> bounds >> center ;
|
||||
|
||||
int radiusInt ;
|
||||
stream >> radiusInt ;
|
||||
radius = (float)radiusInt ;
|
||||
|
||||
// Vertexes
|
||||
|
||||
int numVertexes ;
|
||||
stream >> numVertexes ;
|
||||
verts.resize (numVertexes) ;
|
||||
stream >> verts ;
|
||||
|
||||
// Texture coordinates
|
||||
|
||||
int numTVerts ;
|
||||
stream >> numTVerts ;
|
||||
tverts.resize (numTVerts) ;
|
||||
stream >> tverts ;
|
||||
|
||||
// Normals
|
||||
|
||||
normals.resize (numVertexes) ;
|
||||
enormals.resize (numVertexes) ;
|
||||
stream >> normals ;
|
||||
stream >> enormals ;
|
||||
|
||||
// Primitives and other stuff
|
||||
|
||||
int numPrimitives ;
|
||||
stream >> numPrimitives ;
|
||||
primitives.resize (numPrimitives) ;
|
||||
stream >> primitives ;
|
||||
|
||||
int numIndices ;
|
||||
stream >> numIndices ;
|
||||
indices.resize (numIndices) ;
|
||||
stream >> indices ;
|
||||
|
||||
int numMIndices ;
|
||||
stream >> numMIndices ;
|
||||
mindices.resize (numMIndices) ;
|
||||
stream >> mindices ;
|
||||
|
||||
stream >> vertsPerFrame >> flags ;
|
||||
stream.readCheck() ;
|
||||
}
|
||||
|
||||
void Mesh::save (OutputStream &stream) const
|
||||
{
|
||||
// Mesh Type
|
||||
|
||||
stream << type ;
|
||||
if (type == T_Null) return ; // Null mesh has no data
|
||||
|
||||
stream.storeCheck() ;
|
||||
|
||||
// Header
|
||||
|
||||
stream << numFrames << matFrames << parent ; // Header
|
||||
stream << bounds << center << (int)radius ; // Bounds
|
||||
|
||||
// Vertexes
|
||||
|
||||
stream << (int) verts.size() ;
|
||||
stream << verts ;
|
||||
|
||||
// Texture coordinates
|
||||
|
||||
assert (tverts.size() == verts.size()) ;
|
||||
|
||||
stream << (int) tverts.size() ;
|
||||
stream << tverts ;
|
||||
|
||||
// Normals
|
||||
|
||||
assert (normals.size() == verts.size()) ;
|
||||
assert (enormals.size() == verts.size()) ;
|
||||
|
||||
stream << normals ;
|
||||
stream << enormals ;
|
||||
|
||||
// Primitives
|
||||
|
||||
stream << (int) primitives.size() ;
|
||||
stream << primitives ;
|
||||
stream << (int) indices.size() ;
|
||||
stream << indices ;
|
||||
stream << (int) mindices.size() ;
|
||||
stream << mindices ;
|
||||
|
||||
// Other small stuff
|
||||
|
||||
stream << vertsPerFrame << flags ;
|
||||
|
||||
stream.storeCheck() ;
|
||||
|
||||
// Skin Mesh support
|
||||
if (type == T_Skin) {
|
||||
|
||||
// Initial skin vertices & normals of affected vertices.
|
||||
// Yes, we did just write these out, but this is what it wants.
|
||||
stream << (int) verts.size() ;
|
||||
stream << verts;
|
||||
stream << normals;
|
||||
stream << enormals;
|
||||
|
||||
// Inverse world transforms for bones used in vertex weighting
|
||||
assert(nodeTransform.size() == nodeIndex.size());
|
||||
|
||||
stream << (int) nodeIndex.size();
|
||||
for (int n = 0; n < nodeIndex.size(); n++)
|
||||
stream << nodeTransform[n];
|
||||
|
||||
// Vertex tuples. If this more than one entry per vertex, then
|
||||
// these tables should be sorted by vindex.
|
||||
assert (vweight.size() == vindex.size());
|
||||
assert (vbone.size() == vindex.size());
|
||||
|
||||
stream << (int) vindex.size();
|
||||
stream << vindex;
|
||||
stream << vbone;
|
||||
stream << vweight;
|
||||
|
||||
// Vertex bone to node table
|
||||
stream << (int) nodeIndex.size();
|
||||
stream << nodeIndex;
|
||||
|
||||
stream.storeCheck();
|
||||
}
|
||||
if (type == T_Sorted) {
|
||||
stream << (int) clusters.size();
|
||||
stream << clusters;
|
||||
stream << (int) startCluster.size();
|
||||
stream << startCluster;
|
||||
stream << (int) firstVerts.size();
|
||||
stream << firstVerts;
|
||||
|
||||
stream << (int) numVerts.size();
|
||||
stream << numVerts;
|
||||
|
||||
stream << (int) firstTVerts.size();
|
||||
stream << firstTVerts;
|
||||
|
||||
stream << (int) 0; // alwaysWriteDepth deprecated
|
||||
|
||||
stream.storeCheck();
|
||||
}
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// Utility stuff
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
void Mesh::setMaterial (int n)
|
||||
{
|
||||
std::vector<Primitive>::iterator p ;
|
||||
for (p = primitives.begin() ; p != primitives.end() ; p++)
|
||||
{
|
||||
p->type = (p->type & ~Primitive::MaterialMask) |
|
||||
(n & Primitive::MaterialMask) ;
|
||||
|
||||
// Just in case
|
||||
p->type &= ~Primitive::NoMaterial ;
|
||||
}
|
||||
}
|
||||
|
||||
void Mesh::translate(const Point n)
|
||||
{
|
||||
std::vector<Point>::iterator v ;
|
||||
for (v = verts.begin() ; v != verts.end() ; v++)
|
||||
*v += n ;
|
||||
|
||||
calculateBounds() ;
|
||||
calculateCenter() ;
|
||||
calculateRadius() ;
|
||||
}
|
||||
|
||||
void Mesh::rotate (const Quaternion &q)
|
||||
{
|
||||
std::vector<Point>::iterator v ;
|
||||
for (v = verts.begin() ; v != verts.end() ; v++)
|
||||
*v = q.apply(*v);
|
||||
|
||||
calculateBounds() ;
|
||||
calculateCenter() ;
|
||||
calculateRadius() ;
|
||||
}
|
||||
|
||||
int Mesh::getVertexBone(int node)
|
||||
{
|
||||
// Finds the bone index in the table, or adds it if it's
|
||||
// not there. The vertex bone & nodeIndex list are here to
|
||||
// track which bones are used by this mesh.
|
||||
int b = 0;
|
||||
for (; b < nodeIndex.size(); b++)
|
||||
if (nodeIndex[b] == node)
|
||||
return b;
|
||||
nodeIndex.push_back(node);
|
||||
nodeTransform.push_back(Matrix<4,4>::identity());
|
||||
return b;
|
||||
}
|
||||
|
||||
void Mesh::setNodeTransform(int node,Point t, Quaternion q)
|
||||
{
|
||||
// Build inverse transform, the mesh wants to be able to
|
||||
// transform the vertices into node space.
|
||||
assert(node < nodeTransform.size());
|
||||
t = q.inverse().apply(-t);
|
||||
Matrix<4,4>::Row row;
|
||||
row[0] = t.x(); row[1] = t.y(); row[2] = t.z(); row[3] = 1;
|
||||
|
||||
// The toMatrix builds a transposed transform from what we
|
||||
// want, so we need to pass the original quaternion to get
|
||||
// the inverse.
|
||||
nodeTransform[node] = q.toMatrix();
|
||||
nodeTransform[node].setCol(3,row);
|
||||
}
|
||||
|
||||
};
|
200
lib/dtsSDK/DTSMesh.h
Executable file
200
lib/dtsSDK/DTSMesh.h
Executable file
@ -0,0 +1,200 @@
|
||||
#ifndef __DTSMESH_H
|
||||
#define __DTSMESH_H
|
||||
|
||||
|
||||
#include "DTSPoint.h"
|
||||
#include "DTSMatrix.h"
|
||||
|
||||
namespace DTS
|
||||
{
|
||||
// Forward reference;
|
||||
class Quaternion;
|
||||
|
||||
//! Defines a primitive as stored in the DTS file
|
||||
|
||||
struct Primitive
|
||||
{
|
||||
short firstElement ; //!< Number of consecutive indices used
|
||||
short numElements ; //!< Number of the first index
|
||||
int type ; //!< Type of primitive and number of material used
|
||||
|
||||
enum /* type */
|
||||
{
|
||||
Triangles = 0x00000000,
|
||||
Strip = 0x40000000,
|
||||
Fan = 0x80000000, //!< WARNING! May not be supported
|
||||
TypeMask = 0xC0000000,
|
||||
|
||||
Indexed = 0x20000000, //!< WARNING! Non-indexed primitives not supported in the engine
|
||||
NoMaterial = 0x10000000,
|
||||
MaterialMask = 0x0FFFFFFF,
|
||||
};
|
||||
};
|
||||
|
||||
//! Defines type used by sort meshes (cluster of faces that are rendered together)
|
||||
|
||||
struct Cluster
|
||||
{
|
||||
int startPrimitive;
|
||||
int endPrimitive;
|
||||
Point3D normal;
|
||||
float k;
|
||||
int frontCluster; ///< go to this cluster if in front of plane, if frontCluster<0, no cluster
|
||||
int backCluster; ///< go to this cluster if in back of plane, if backCluster<0, no cluster
|
||||
///< if frontCluster==backCluster, no plane to test against...
|
||||
};
|
||||
|
||||
//! Defines a Mesh as stored in the DTS file
|
||||
// Skin render...
|
||||
// NodeIndex loop
|
||||
// Vb[n] = nodeTransform[nodeIndex[n]] * InitialTransform[n]
|
||||
// Vertex loop
|
||||
// v[vindex[n]] += initialVerts[n] * Vb[boneIndex[n]] * weight[n]
|
||||
|
||||
class Mesh
|
||||
{
|
||||
friend class ShapeMimic;
|
||||
friend class TranslucentSort;
|
||||
|
||||
public:
|
||||
|
||||
//! Mesh types
|
||||
enum Type
|
||||
{
|
||||
T_Standard = 0, //!< Rigid mesh
|
||||
T_Skin = 1, //!< TODO: Skined (mesh with bones)
|
||||
T_Decal = 2, //!< DEPRECATED
|
||||
T_Sorted = 3, //!< BSP Sorted for correct alpha rendering
|
||||
T_Null = 4 //!< Null mesh, used in collision objects as the visible meshes
|
||||
};
|
||||
|
||||
//!< Mesh flags
|
||||
enum Flag
|
||||
{
|
||||
Billboard = 0x80000000, //!< Mesh always faces the camera
|
||||
HasDetail = 0x40000000, //!< Mesh use Detailmap, search for Detailmap reference in Material
|
||||
BillboardZ = 0x20000000, //!< If billboard, only rotate around Z axis
|
||||
EncodedNormals = 0x10000000, //!< Mesh uses encoded normals
|
||||
} ;
|
||||
|
||||
|
||||
//! Create an empty mesh of the given type
|
||||
Mesh (Type t = T_Null) ;
|
||||
|
||||
//! Change object type
|
||||
Type getType() { return (Type)type; }
|
||||
void setType(Type t) { type = t; }
|
||||
|
||||
//! Set mesh flags
|
||||
void setFlag(int f) { flags |= f; }
|
||||
|
||||
//! Save the mesh to a special DTS stream
|
||||
void save (class OutputStream &) const ;
|
||||
|
||||
//! Read the mesh from a special DTS stream
|
||||
void read (class InputStream &stream) ;
|
||||
|
||||
//! Calculates and returns the number of polygons
|
||||
int getPolyCount() const ;
|
||||
|
||||
//! Get the radius of the bounding sphere
|
||||
float getRadius() const { return radius ; }
|
||||
|
||||
//! Get the center point of mesh (and mesh's bounding sphere)
|
||||
Point getCenter() const { return center ; }
|
||||
|
||||
//! Get the bounding box of the mesh
|
||||
Box getBounds() const { return bounds ; }
|
||||
|
||||
//! Get the transformed bounding box of the mesh
|
||||
Box getBounds(Point, Quaternion) const;
|
||||
|
||||
//! Calculate the radius of a bounding sphere, if it is centered in the given point
|
||||
float getRadiusFrom(Point, Quaternion, Point center) const ;
|
||||
|
||||
//! Get the tube radius (radius of bounding cylinder)
|
||||
float getTubeRadius() const ;
|
||||
|
||||
//! Calculate the radius of a bounding cylinder, if it is centered in the given point
|
||||
float getTubeRadiusFrom(Point, Quaternion, Point center) const ;
|
||||
|
||||
//! Joins another mesh with this one (imports all vertexes and triangles)
|
||||
Mesh & operator += (const Mesh &) ;
|
||||
|
||||
//! Change the material of the mesh
|
||||
void setMaterial(int n) ;
|
||||
|
||||
//! Move all the vertexes in a direction
|
||||
void translate(const Point n) ;
|
||||
|
||||
//! Rotates all vertexes
|
||||
void rotate (const class Quaternion &q) ;
|
||||
|
||||
//! Return a vertex bone number for the given node
|
||||
int getVertexBone(int node);
|
||||
|
||||
//! Return the node for a given vertex bone
|
||||
int getNodeIndexCount() { return nodeIndex.size(); }
|
||||
int getNodeIndex(int node) {
|
||||
return (node >= 0 && node < nodeIndex.size())? nodeIndex[node]: -1;
|
||||
}
|
||||
void setNodeTransform(int node,Point t, Quaternion q);
|
||||
|
||||
protected:
|
||||
|
||||
void setCenter(Point c) { center = c; }
|
||||
void setBounds(Box b) { bounds = b; }
|
||||
void setRadius(float r) { radius = r; }
|
||||
void setFrames(int n) { numFrames = n ; vertsPerFrame = verts.size()/n ; }
|
||||
void setParent(int n) { parent = n; }
|
||||
|
||||
protected:
|
||||
|
||||
void calculateBounds() ;
|
||||
void calculateCenter() ;
|
||||
void calculateRadius() ;
|
||||
|
||||
static char encodeNormal(const Point &) ;
|
||||
|
||||
std::vector <Point> verts ; //!< Contains all mesh vertexes
|
||||
std::vector <Point2D> tverts ; //!< Texture coordinates s, t for each vertex
|
||||
std::vector <Point> normals ; //!< Normals for each vertex
|
||||
std::vector <char> enormals ; //!< Encoded normals (see encodeNormal)
|
||||
std::vector <Primitive> primitives; //!< Mesh primitives
|
||||
std::vector <unsigned short> indices ; //!< Vertex index array, for primitives
|
||||
std::vector <unsigned short> mindices ; //!< ?
|
||||
|
||||
// Extended data used by Skin Meshes
|
||||
|
||||
std::vector <int> vindex; //!< Vertex index
|
||||
std::vector <int> vbone; //!< Vertex vbone
|
||||
std::vector <float> vweight; //!< Vertex weight
|
||||
std::vector <int> nodeIndex; //!< vbone -> node
|
||||
std::vector <Matrix<4,4> > nodeTransform; //!<
|
||||
|
||||
// Extended data used by sort Meshes
|
||||
|
||||
std::vector <Cluster> clusters; ///< All of the clusters of primitives to be drawn
|
||||
std::vector <int> startCluster; ///< indexed by frame number
|
||||
std::vector <int> firstVerts; ///< indexed by frame number
|
||||
std::vector <int> numVerts; ///< indexed by frame number
|
||||
std::vector <int> firstTVerts; ///< indexed by frame number or matFrame number, depending on which one animates (never both)
|
||||
|
||||
private:
|
||||
|
||||
int type ;
|
||||
int numFrames ;
|
||||
int matFrames ;
|
||||
int parent ;
|
||||
Box bounds ;
|
||||
Point center ;
|
||||
float radius ;
|
||||
|
||||
int vertsPerFrame ;
|
||||
int flags ;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
261
lib/dtsSDK/DTSNormalTable.cpp
Executable file
261
lib/dtsSDK/DTSNormalTable.cpp
Executable file
@ -0,0 +1,261 @@
|
||||
|
||||
const static float normalTable[256][3] =
|
||||
{
|
||||
{ 0.565061f, -0.270644f, -0.779396f },
|
||||
{ -0.309804f, -0.731114f, 0.607860f },
|
||||
{ -0.867412f, 0.472957f, 0.154619f },
|
||||
{ -0.757488f, 0.498188f, -0.421925f },
|
||||
{ 0.306834f, -0.915340f, 0.260778f },
|
||||
{ 0.098754f, 0.639153f, -0.762713f },
|
||||
{ 0.713706f, -0.558862f, -0.422252f },
|
||||
{ -0.890431f, -0.407603f, -0.202466f },
|
||||
{ 0.848050f, -0.487612f, -0.207475f },
|
||||
{ -0.232226f, 0.776855f, 0.585293f },
|
||||
{ -0.940195f, 0.304490f, -0.152706f },
|
||||
{ 0.602019f, -0.491878f, -0.628991f },
|
||||
{ -0.096835f, -0.494354f, -0.863850f },
|
||||
{ 0.026630f, -0.323659f, -0.945799f },
|
||||
{ 0.019208f, 0.909386f, 0.415510f },
|
||||
{ 0.854440f, 0.491730f, 0.167731f },
|
||||
{ -0.418835f, 0.866521f, -0.271512f },
|
||||
{ 0.465024f, 0.409667f, 0.784809f },
|
||||
{ -0.674391f, -0.691087f, -0.259992f },
|
||||
{ 0.303858f, -0.869270f, -0.389922f },
|
||||
{ 0.991333f, 0.090061f, -0.095640f },
|
||||
{ -0.275924f, -0.369550f, 0.887298f },
|
||||
{ 0.426545f, -0.465962f, 0.775202f },
|
||||
{ -0.482741f, -0.873278f, -0.065920f },
|
||||
{ 0.063616f, 0.932012f, -0.356800f },
|
||||
{ 0.624786f, -0.061315f, 0.778385f },
|
||||
{ -0.530300f, 0.416850f, 0.738253f },
|
||||
{ 0.312144f, -0.757028f, -0.573999f },
|
||||
{ 0.399288f, -0.587091f, -0.704197f },
|
||||
{ -0.132698f, 0.482877f, 0.865576f },
|
||||
{ 0.950966f, 0.306530f, 0.041268f },
|
||||
{ -0.015923f, -0.144300f, 0.989406f },
|
||||
{ -0.407522f, -0.854193f, 0.322925f },
|
||||
{ -0.932398f, 0.220464f, 0.286408f },
|
||||
{ 0.477509f, 0.876580f, 0.059936f },
|
||||
{ 0.337133f, 0.932606f, -0.128796f },
|
||||
{ -0.638117f, 0.199338f, 0.743687f },
|
||||
{ -0.677454f, 0.445349f, 0.585423f },
|
||||
{ -0.446715f, 0.889059f, -0.100099f },
|
||||
{ -0.410024f, 0.909168f, 0.072759f },
|
||||
{ 0.708462f, 0.702103f, -0.071641f },
|
||||
{ -0.048801f, -0.903683f, -0.425411f },
|
||||
{ -0.513681f, -0.646901f, 0.563606f },
|
||||
{ -0.080022f, 0.000676f, -0.996793f },
|
||||
{ 0.066966f, -0.991150f, -0.114615f },
|
||||
{ -0.245220f, 0.639318f, -0.728793f },
|
||||
{ 0.250978f, 0.855979f, 0.452006f },
|
||||
{ -0.123547f, 0.982443f, -0.139791f },
|
||||
{ -0.794825f, 0.030254f, -0.606084f },
|
||||
{ -0.772905f, 0.547941f, 0.319967f },
|
||||
{ 0.916347f, 0.369614f, -0.153928f },
|
||||
{ -0.388203f, 0.105395f, 0.915527f },
|
||||
{ -0.700468f, -0.709334f, 0.078677f },
|
||||
{ -0.816193f, 0.390455f, 0.425880f },
|
||||
{ -0.043007f, 0.769222f, -0.637533f },
|
||||
{ 0.911444f, 0.113150f, 0.395560f },
|
||||
{ 0.845801f, 0.156091f, -0.510153f },
|
||||
{ 0.829801f, -0.029340f, 0.557287f },
|
||||
{ 0.259529f, 0.416263f, 0.871418f },
|
||||
{ 0.231128f, -0.845982f, 0.480515f },
|
||||
{ -0.626203f, -0.646168f, 0.436277f },
|
||||
{ -0.197047f, -0.065791f, 0.978184f },
|
||||
{ -0.255692f, -0.637488f, -0.726794f },
|
||||
{ 0.530662f, -0.844385f, -0.073567f },
|
||||
{ -0.779887f, 0.617067f, -0.104899f },
|
||||
{ 0.739908f, 0.113984f, 0.662982f },
|
||||
{ -0.218801f, 0.930194f, -0.294729f },
|
||||
{ -0.374231f, 0.818666f, 0.435589f },
|
||||
{ -0.720250f, -0.028285f, 0.693137f },
|
||||
{ 0.075389f, 0.415049f, 0.906670f },
|
||||
{ -0.539724f, -0.106620f, 0.835063f },
|
||||
{ -0.452612f, -0.754669f, -0.474991f },
|
||||
{ 0.682822f, 0.581234f, -0.442629f },
|
||||
{ 0.002435f, -0.618462f, -0.785811f },
|
||||
{ -0.397631f, 0.110766f, -0.910835f },
|
||||
{ 0.133935f, -0.985438f, 0.104754f },
|
||||
{ 0.759098f, -0.608004f, 0.232595f },
|
||||
{ -0.825239f, -0.256087f, 0.503388f },
|
||||
{ 0.101693f, -0.565568f, 0.818408f },
|
||||
{ 0.386377f, 0.793546f, -0.470104f },
|
||||
{ -0.520516f, -0.840690f, 0.149346f },
|
||||
{ -0.784549f, -0.479672f, 0.392935f },
|
||||
{ -0.325322f, -0.927581f, -0.183735f },
|
||||
{ -0.069294f, -0.428541f, 0.900861f },
|
||||
{ 0.993354f, -0.115023f, -0.004288f },
|
||||
{ -0.123896f, -0.700568f, 0.702747f },
|
||||
{ -0.438031f, -0.120880f, -0.890795f },
|
||||
{ 0.063314f, 0.813233f, 0.578484f },
|
||||
{ 0.322045f, 0.889086f, -0.325289f },
|
||||
{ -0.133521f, 0.875063f, -0.465228f },
|
||||
{ 0.637155f, 0.564814f, 0.524422f },
|
||||
{ 0.260092f, -0.669353f, 0.695930f },
|
||||
{ 0.953195f, 0.040485f, -0.299634f },
|
||||
{ -0.840665f, -0.076509f, 0.536124f },
|
||||
{ -0.971350f, 0.202093f, 0.125047f },
|
||||
{ -0.804307f, -0.396312f, -0.442749f },
|
||||
{ -0.936746f, 0.069572f, 0.343027f },
|
||||
{ 0.426545f, -0.465962f, 0.775202f },
|
||||
{ 0.794542f, -0.227450f, 0.563000f },
|
||||
{ -0.892172f, 0.091169f, -0.442399f },
|
||||
{ -0.312654f, 0.541264f, 0.780564f },
|
||||
{ 0.590603f, -0.735618f, -0.331743f },
|
||||
{ -0.098040f, -0.986713f, 0.129558f },
|
||||
{ 0.569646f, 0.283078f, -0.771603f },
|
||||
{ 0.431051f, -0.407385f, -0.805129f },
|
||||
{ -0.162087f, -0.938749f, -0.304104f },
|
||||
{ 0.241533f, -0.359509f, 0.901341f },
|
||||
{ -0.576191f, 0.614939f, 0.538380f },
|
||||
{ -0.025110f, 0.085740f, 0.996001f },
|
||||
{ -0.352693f, -0.198168f, 0.914515f },
|
||||
{ -0.604577f, 0.700711f, 0.378802f },
|
||||
{ 0.465024f, 0.409667f, 0.784809f },
|
||||
{ -0.254684f, -0.030474f, -0.966544f },
|
||||
{ -0.604789f, 0.791809f, 0.085259f },
|
||||
{ -0.705147f, -0.399298f, 0.585943f },
|
||||
{ 0.185691f, 0.017236f, -0.982457f },
|
||||
{ 0.044588f, 0.973094f, 0.226052f },
|
||||
{ -0.405463f, 0.642367f, 0.650357f },
|
||||
{ -0.563959f, 0.599136f, -0.568319f },
|
||||
{ 0.367162f, -0.072253f, -0.927347f },
|
||||
{ 0.960429f, -0.213570f, -0.178783f },
|
||||
{ -0.192629f, 0.906005f, 0.376893f },
|
||||
{ -0.199718f, -0.359865f, -0.911378f },
|
||||
{ 0.485072f, 0.121233f, -0.866030f },
|
||||
{ 0.467163f, -0.874294f, 0.131792f },
|
||||
{ -0.638953f, -0.716603f, 0.279677f },
|
||||
{ -0.622710f, 0.047813f, -0.780990f },
|
||||
{ 0.828724f, -0.054433f, -0.557004f },
|
||||
{ 0.130241f, 0.991080f, 0.028245f },
|
||||
{ 0.310995f, -0.950076f, -0.025242f },
|
||||
{ 0.818118f, 0.275336f, 0.504850f },
|
||||
{ 0.676328f, 0.387023f, 0.626733f },
|
||||
{ -0.100433f, 0.495114f, -0.863004f },
|
||||
{ -0.949609f, -0.240681f, -0.200786f },
|
||||
{ -0.102610f, 0.261831f, -0.959644f },
|
||||
{ -0.845732f, -0.493136f, 0.203850f },
|
||||
{ 0.672617f, -0.738838f, 0.041290f },
|
||||
{ 0.380465f, 0.875938f, 0.296613f },
|
||||
{ -0.811223f, 0.262027f, -0.522742f },
|
||||
{ -0.074423f, -0.775670f, -0.626736f },
|
||||
{ -0.286499f, 0.755850f, -0.588735f },
|
||||
{ 0.291182f, -0.276189f, -0.915933f },
|
||||
{ -0.638117f, 0.199338f, 0.743687f },
|
||||
{ 0.439922f, -0.864433f, -0.243359f },
|
||||
{ 0.177649f, 0.206919f, 0.962094f },
|
||||
{ 0.277107f, 0.948521f, 0.153361f },
|
||||
{ 0.507629f, 0.661918f, -0.551523f },
|
||||
{ -0.503110f, -0.579308f, -0.641313f },
|
||||
{ 0.600522f, 0.736495f, -0.311364f },
|
||||
{ -0.691096f, -0.715301f, -0.103592f },
|
||||
{ -0.041083f, -0.858497f, 0.511171f },
|
||||
{ 0.207773f, -0.480062f, -0.852274f },
|
||||
{ 0.795719f, 0.464614f, 0.388543f },
|
||||
{ -0.100433f, 0.495114f, -0.863004f },
|
||||
{ 0.703249f, 0.065157f, -0.707951f },
|
||||
{ -0.324171f, -0.941112f, 0.096024f },
|
||||
{ -0.134933f, -0.940212f, 0.312722f },
|
||||
{ -0.438240f, 0.752088f, -0.492249f },
|
||||
{ 0.964762f, -0.198855f, 0.172311f },
|
||||
{ -0.831799f, 0.196807f, 0.519015f },
|
||||
{ -0.508008f, 0.819902f, 0.263986f },
|
||||
{ 0.471075f, -0.001146f, 0.882092f },
|
||||
{ 0.919512f, 0.246162f, -0.306435f },
|
||||
{ -0.960050f, 0.279828f, -0.001187f },
|
||||
{ 0.110232f, -0.847535f, -0.519165f },
|
||||
{ 0.208229f, 0.697360f, 0.685806f },
|
||||
{ -0.199680f, -0.560621f, 0.803637f },
|
||||
{ 0.170135f, -0.679985f, -0.713214f },
|
||||
{ 0.758371f, -0.494907f, 0.424195f },
|
||||
{ 0.077734f, -0.755978f, 0.649965f },
|
||||
{ 0.612831f, -0.672475f, 0.414987f },
|
||||
{ 0.142776f, 0.836698f, -0.528726f },
|
||||
{ -0.765185f, 0.635778f, 0.101382f },
|
||||
{ 0.669873f, -0.419737f, 0.612447f },
|
||||
{ 0.593549f, 0.194879f, 0.780847f },
|
||||
{ 0.646930f, 0.752173f, 0.125368f },
|
||||
{ 0.837721f, 0.545266f, -0.030127f },
|
||||
{ 0.541505f, 0.768070f, 0.341820f },
|
||||
{ 0.760679f, -0.365715f, -0.536301f },
|
||||
{ 0.381516f, 0.640377f, 0.666605f },
|
||||
{ 0.565794f, -0.072415f, -0.821361f },
|
||||
{ -0.466072f, -0.401588f, 0.788356f },
|
||||
{ 0.987146f, 0.096290f, 0.127560f },
|
||||
{ 0.509709f, -0.688886f, -0.515396f },
|
||||
{ -0.135132f, -0.988046f, -0.074192f },
|
||||
{ 0.600499f, 0.476471f, -0.642166f },
|
||||
{ -0.732326f, -0.275320f, -0.622815f },
|
||||
{ -0.881141f, -0.470404f, 0.048078f },
|
||||
{ 0.051548f, 0.601042f, 0.797553f },
|
||||
{ 0.402027f, -0.763183f, 0.505891f },
|
||||
{ 0.404233f, -0.208288f, 0.890624f },
|
||||
{ -0.311793f, 0.343843f, 0.885752f },
|
||||
{ 0.098132f, -0.937014f, 0.335223f },
|
||||
{ 0.537158f, 0.830585f, -0.146936f },
|
||||
{ 0.725277f, 0.298172f, -0.620538f },
|
||||
{ -0.882025f, 0.342976f, -0.323110f },
|
||||
{ -0.668829f, 0.424296f, -0.610443f },
|
||||
{ -0.408835f, -0.476442f, -0.778368f },
|
||||
{ 0.809472f, 0.397249f, -0.432375f },
|
||||
{ -0.909184f, -0.205938f, -0.361903f },
|
||||
{ 0.866930f, -0.347934f, -0.356895f },
|
||||
{ 0.911660f, -0.141281f, -0.385897f },
|
||||
{ -0.431404f, -0.844074f, -0.318480f },
|
||||
{ -0.950593f, -0.073496f, 0.301614f },
|
||||
{ -0.719716f, 0.626915f, -0.298305f },
|
||||
{ -0.779887f, 0.617067f, -0.104899f },
|
||||
{ -0.475899f, -0.542630f, 0.692151f },
|
||||
{ 0.081952f, -0.157248f, -0.984153f },
|
||||
{ 0.923990f, -0.381662f, -0.024025f },
|
||||
{ -0.957998f, 0.120979f, -0.260008f },
|
||||
{ 0.306601f, 0.227975f, -0.924134f },
|
||||
{ -0.141244f, 0.989182f, 0.039601f },
|
||||
{ 0.077097f, 0.186288f, -0.979466f },
|
||||
{ -0.630407f, -0.259801f, 0.731499f },
|
||||
{ 0.718150f, 0.637408f, 0.279233f },
|
||||
{ 0.340946f, 0.110494f, 0.933567f },
|
||||
{ -0.396671f, 0.503020f, -0.767869f },
|
||||
{ 0.636943f, -0.245005f, 0.730942f },
|
||||
{ -0.849605f, -0.518660f, -0.095724f },
|
||||
{ -0.388203f, 0.105395f, 0.915527f },
|
||||
{ -0.280671f, -0.776541f, -0.564099f },
|
||||
{ -0.601680f, 0.215451f, -0.769131f },
|
||||
{ -0.660112f, -0.632371f, -0.405412f },
|
||||
{ 0.921096f, 0.284072f, 0.266242f },
|
||||
{ 0.074850f, -0.300846f, 0.950731f },
|
||||
{ 0.943952f, -0.067062f, 0.323198f },
|
||||
{ -0.917838f, -0.254589f, 0.304561f },
|
||||
{ 0.889843f, -0.409008f, 0.202219f },
|
||||
{ -0.565849f, 0.753721f, -0.334246f },
|
||||
{ 0.791460f, 0.555918f, -0.254060f },
|
||||
{ 0.261936f, 0.703590f, -0.660568f },
|
||||
{ -0.234406f, 0.952084f, 0.196444f },
|
||||
{ 0.111205f, 0.979492f, -0.168014f },
|
||||
{ -0.869844f, -0.109095f, -0.481113f },
|
||||
{ -0.337728f, -0.269701f, -0.901777f },
|
||||
{ 0.366793f, 0.408875f, -0.835634f },
|
||||
{ -0.098749f, 0.261316f, 0.960189f },
|
||||
{ -0.272379f, -0.847100f, 0.456324f },
|
||||
{ -0.319506f, 0.287444f, -0.902935f },
|
||||
{ 0.873383f, -0.294109f, 0.388203f },
|
||||
{ -0.088950f, 0.710450f, 0.698104f },
|
||||
{ 0.551238f, -0.786552f, 0.278340f },
|
||||
{ 0.724436f, -0.663575f, -0.186712f },
|
||||
{ 0.529741f, -0.606539f, 0.592861f },
|
||||
{ -0.949743f, -0.282514f, 0.134809f },
|
||||
{ 0.155047f, 0.419442f, -0.894443f },
|
||||
{ -0.562653f, -0.329139f, -0.758346f },
|
||||
{ 0.816407f, -0.576953f, 0.024576f },
|
||||
{ 0.178550f, -0.950242f, -0.255266f },
|
||||
{ 0.479571f, 0.706691f, 0.520192f },
|
||||
{ 0.391687f, 0.559884f, -0.730145f },
|
||||
{ 0.724872f, -0.205570f, -0.657496f },
|
||||
{ -0.663196f, -0.517587f, -0.540624f },
|
||||
{ -0.660054f, -0.122486f, -0.741165f },
|
||||
{ -0.531989f, 0.374711f, -0.759328f },
|
||||
{ 0.194979f, -0.059120f, 0.979024f }
|
||||
} ;
|
||||
|
436
lib/dtsSDK/DTSOutputStream.h
Executable file
436
lib/dtsSDK/DTSOutputStream.h
Executable file
@ -0,0 +1,436 @@
|
||||
#ifndef __DTSOUTPUTSTREAM_H
|
||||
#define __DTSOUTPUTSTREAM_H
|
||||
|
||||
#include <cassert>
|
||||
#include <vector>
|
||||
#include <fstream>
|
||||
|
||||
#include "DTSShape.h"
|
||||
#include "DTSQuaternion.h"
|
||||
#include "DTSMatrix.h"
|
||||
#include "DTSEndian.h"
|
||||
|
||||
namespace DTS
|
||||
{
|
||||
// -------------------------------------------------------------------------
|
||||
// class OutputStream
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
/*! The DTS file format stores in separate buffers values of 8, 16 or 32
|
||||
bits of length, in order to speed up loading in non-Intel platforms.
|
||||
In order to create a DTS file you should create the three buffers in
|
||||
memory and then begin writting the data using helper functions. This
|
||||
mimics the way the data is retrieved in the engine.
|
||||
|
||||
This class provides the needed functionality. Simply create a
|
||||
OutputStream object and write the data using the "write" method,
|
||||
that stores the values in the correct buffer. The "flush" method
|
||||
creates finally the file in the format expected by the V12 engine.
|
||||
|
||||
The class knowns about all DTS namespace simple objects and can
|
||||
save them (operator <<) in the expected format.
|
||||
|
||||
*** WARNING *** THIS CODE IS NOT PORTABLE
|
||||
|
||||
This code assumes a little-endian 32 bits machine
|
||||
*/
|
||||
|
||||
class OutputStream
|
||||
{
|
||||
public:
|
||||
|
||||
//! Initialize the stream. The version number is written in the header
|
||||
OutputStream (std::ostream &, int DTSVersion = 24) ;
|
||||
~OutputStream () ;
|
||||
|
||||
//! Wite "count" dwords (= count x 4 bytes)
|
||||
void write (const int *, int count) ;
|
||||
|
||||
//! Write "count" words (= count x 2 bytes)
|
||||
void write (const short *, int count) ;
|
||||
|
||||
//! Write "count" bytes
|
||||
void write (const char *, int count) ;
|
||||
|
||||
//! Write one dword
|
||||
OutputStream & operator << (const int value) { write(&value, 1) ; return *this ; }
|
||||
|
||||
//! Write one word
|
||||
OutputStream & operator << (const short value) { write(&value, 1) ; return *this ; }
|
||||
OutputStream & operator << (const unsigned short value) { write((const short*)&value, 1) ; return *this ; }
|
||||
|
||||
//! Write one byte
|
||||
OutputStream & operator << (const char value) { write(&value, 1) ; return *this ; }
|
||||
|
||||
//! Write one dword (1 float == 32 bits)
|
||||
OutputStream & operator << (const float value)
|
||||
{
|
||||
write((int *)&value, 1) ;
|
||||
return *this ;
|
||||
}
|
||||
|
||||
//! Write one byte (provided for convenience)
|
||||
OutputStream & operator << (const unsigned char value)
|
||||
{
|
||||
write((char *)&value, 1) ;
|
||||
return *this ;
|
||||
}
|
||||
|
||||
//! Write a string (1 byte len first, then n byte-sized characters)
|
||||
OutputStream & operator << (const std::string &s) ;
|
||||
|
||||
// Operators to write some usual structs
|
||||
|
||||
OutputStream & operator << (const Point &) ;
|
||||
OutputStream & operator << (const Point2D &) ;
|
||||
OutputStream & operator << (const Box &) ;
|
||||
OutputStream & operator << (const Quaternion &) ;
|
||||
OutputStream & operator << (const Node &) ;
|
||||
OutputStream & operator << (const Object &) ;
|
||||
OutputStream & operator << (const Decal &) ;
|
||||
OutputStream & operator << (const IFLMaterial &) ;
|
||||
OutputStream & operator << (const DecalState &) ;
|
||||
OutputStream & operator << (const DetailLevel &) ;
|
||||
OutputStream & operator << (const ObjectState &) ;
|
||||
OutputStream & operator << (const Subshape &) ;
|
||||
OutputStream & operator << (const Trigger &) ;
|
||||
OutputStream & operator << (const Primitive &) ;
|
||||
OutputStream & operator << (const Mesh &) ;
|
||||
OutputStream & operator << (const Cluster &) ;
|
||||
OutputStream & operator << (const Matrix<4,4> &) ;
|
||||
|
||||
//! Stores checkpoint values in the streams
|
||||
void storeCheck (int checkPoint = -1) ;
|
||||
|
||||
//! When you're finished, call this method to create the file
|
||||
//! You'll still need to write the sequence data to the stream, next
|
||||
void flush () ;
|
||||
|
||||
private:
|
||||
|
||||
std::ostream & out ;
|
||||
int DTSVersion ;
|
||||
int checkCount ;
|
||||
|
||||
// Pointers to the 3 memory buffers
|
||||
|
||||
int * Buffer32 ;
|
||||
short * Buffer16 ;
|
||||
char * Buffer8 ;
|
||||
|
||||
// Values allocated in each buffer
|
||||
|
||||
unsigned long Allocated32 ;
|
||||
unsigned long Allocated16 ;
|
||||
unsigned long Allocated8 ;
|
||||
|
||||
// Values actually used in each buffer
|
||||
|
||||
unsigned long Used32 ;
|
||||
unsigned long Used16 ;
|
||||
unsigned long Used8 ;
|
||||
};
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// Construction and destruction
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
inline OutputStream::OutputStream (std::ostream & s, int version)
|
||||
: out(s), DTSVersion(version)
|
||||
{
|
||||
// Versions 17 and down don't use the buffers
|
||||
|
||||
assert (version >= 18) ;
|
||||
|
||||
// Create buffers with some unused space in
|
||||
|
||||
Buffer32 = new int [64] ;
|
||||
Buffer16 = new short [128] ;
|
||||
Buffer8 = new char [256] ;
|
||||
|
||||
Allocated32 = 64 ;
|
||||
Allocated16 = 128 ;
|
||||
Allocated8 = 256 ;
|
||||
|
||||
Used32 = 0 ;
|
||||
Used16 = 0 ;
|
||||
Used8 = 0 ;
|
||||
|
||||
checkCount = 0 ;
|
||||
}
|
||||
|
||||
inline OutputStream::~OutputStream()
|
||||
{
|
||||
delete [] Buffer8 ;
|
||||
delete [] Buffer16 ;
|
||||
delete [] Buffer32 ;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// Write functions
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
/*! All 32 bits dwords must be written to the internal 32-bits buffer
|
||||
so they can be reversed in a single pass in big-endian machines */
|
||||
inline void OutputStream::write (const int * data, int count)
|
||||
{
|
||||
assert (count > 0) ;
|
||||
assert (data != 0) ;
|
||||
|
||||
if (Used32 + count > Allocated32)
|
||||
{
|
||||
// Not enough space allocated. Alloc a bigger buffer,
|
||||
// with a multiple of 64 number of elements, but enough
|
||||
// to add the new data, and swap the old buffer for it
|
||||
|
||||
Allocated32 = ((Used32 + count) & ~63) + 64 ;
|
||||
assert (Allocated32 > Used32 + count) ;
|
||||
int * NewBuffer32 = new int[Allocated32] ;
|
||||
memcpy (NewBuffer32, Buffer32, sizeof(int) * Used32) ;
|
||||
delete [] Buffer32 ;
|
||||
Buffer32 = NewBuffer32 ;
|
||||
}
|
||||
|
||||
// Add the new data to the buffer
|
||||
|
||||
memcpy (Buffer32 + Used32, data, sizeof(int) * count) ;
|
||||
Used32 += count ;
|
||||
}
|
||||
|
||||
// The other write methods are exactly the same, except for the buffer used
|
||||
|
||||
inline void OutputStream::write (const short * data, int count)
|
||||
{
|
||||
assert (count > 0) ;
|
||||
assert (data != 0) ;
|
||||
|
||||
if (Used16 + count > Allocated16)
|
||||
{
|
||||
Allocated16 = ((Used16 + count) & ~63) + 64 ;
|
||||
assert (Allocated16 > Used16 + count) ;
|
||||
short * NewBuffer16 = new short[Allocated16] ;
|
||||
memcpy (NewBuffer16, Buffer16, sizeof(short) * Used16) ;
|
||||
delete [] Buffer16 ;
|
||||
Buffer16 = NewBuffer16 ;
|
||||
}
|
||||
|
||||
memcpy (Buffer16 + Used16, data, sizeof(short) * count) ;
|
||||
Used16 += count ;
|
||||
}
|
||||
|
||||
inline void OutputStream::write (const char * data, int count)
|
||||
{
|
||||
assert (count > 0) ;
|
||||
assert (data != 0) ;
|
||||
|
||||
if (Used8 + count > Allocated8)
|
||||
{
|
||||
Allocated8 = ((Used8 + count) & ~63) + 64 ;
|
||||
assert (Allocated8 > Used8 + count) ;
|
||||
char * NewBuffer8 = new char[Allocated8] ;
|
||||
memcpy (NewBuffer8, Buffer8, sizeof(char) * Used8) ;
|
||||
delete [] Buffer8 ;
|
||||
Buffer8 = NewBuffer8 ;
|
||||
}
|
||||
|
||||
memcpy (Buffer8 + Used8, data, sizeof(char) * count) ;
|
||||
Used8 += count ;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// Write operators
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
inline OutputStream & OutputStream::operator << (const Point &p)
|
||||
{
|
||||
return (*this) << p.x() << p.y() << p.z() ;
|
||||
}
|
||||
|
||||
inline OutputStream & OutputStream::operator << (const Point2D &p)
|
||||
{
|
||||
return (*this) << p.x() << p.y() ;
|
||||
}
|
||||
|
||||
inline OutputStream & OutputStream::operator << (const Box &b)
|
||||
{
|
||||
return (*this) << b.min << b.max ;
|
||||
}
|
||||
|
||||
inline OutputStream & OutputStream::operator << (const Quaternion &q)
|
||||
{
|
||||
return (*this) << (short)(q.x() * 32767.0f)
|
||||
<< (short)(q.y() * 32767.0f)
|
||||
<< (short)(q.z() * 32767.0f)
|
||||
<< (short)(q.w() * 32767.0f) ;
|
||||
}
|
||||
|
||||
inline OutputStream & OutputStream::operator << (const Node &n)
|
||||
{
|
||||
return (*this) << n.name << n.parent << n.firstObject
|
||||
<< n.child << n.sibling ;
|
||||
}
|
||||
|
||||
inline OutputStream & OutputStream::operator << (const Object &o)
|
||||
{
|
||||
return (*this) << o.name << o.numMeshes << o.firstMesh
|
||||
<< o.node << o.sibling << o.firstDecal ;
|
||||
}
|
||||
|
||||
inline OutputStream & OutputStream::operator << (const Decal &d)
|
||||
{
|
||||
return (*this) << d.name << d.numMeshes << d.firstMesh
|
||||
<< d.object << d.sibling ;
|
||||
}
|
||||
|
||||
inline OutputStream & OutputStream::operator << (const IFLMaterial &m)
|
||||
{
|
||||
return (*this) << m.name << m.slot << m.firstFrame
|
||||
<< m.time << m.numFrames ;
|
||||
}
|
||||
|
||||
inline OutputStream & OutputStream::operator << (const Subshape &s)
|
||||
{
|
||||
assert (0 && "Subshapes should be written in block") ;
|
||||
}
|
||||
|
||||
inline OutputStream & OutputStream::operator << (const Trigger &d)
|
||||
{
|
||||
return (*this) << d.state << d.pos ;
|
||||
}
|
||||
|
||||
inline OutputStream & OutputStream::operator << (const DecalState &d)
|
||||
{
|
||||
return (*this) << d.frame ;
|
||||
}
|
||||
|
||||
inline OutputStream & OutputStream::operator << (const ObjectState &o)
|
||||
{
|
||||
return (*this) << o.vis << o.frame << o.matFrame ;
|
||||
}
|
||||
|
||||
inline OutputStream & OutputStream::operator << (const DetailLevel &d)
|
||||
{
|
||||
return (*this) << d.name << d.subshape << d.objectDetail << d.size
|
||||
<< d.avgError << d.maxError << d.polyCount ;
|
||||
}
|
||||
|
||||
inline OutputStream & OutputStream::operator << (const Primitive &p)
|
||||
{
|
||||
return (*this) << p.firstElement << p.numElements << p.type ;
|
||||
}
|
||||
|
||||
inline OutputStream & OutputStream::operator << (const Mesh &m)
|
||||
{
|
||||
m.save(*this) ;
|
||||
return *this ;
|
||||
}
|
||||
|
||||
inline OutputStream & OutputStream::operator << (const Cluster &c)
|
||||
{
|
||||
return *this << c.startPrimitive << c.endPrimitive << c.normal << c.k << c.frontCluster << c.backCluster;
|
||||
}
|
||||
|
||||
inline OutputStream & OutputStream::operator << (const std::string &s)
|
||||
{
|
||||
std::string::const_iterator pos = s.begin() ;
|
||||
while (pos != s.end()) (*this) << *pos++ ;
|
||||
(*this) << '\x00' ;
|
||||
return *this ;
|
||||
}
|
||||
|
||||
template <class type>
|
||||
inline OutputStream & operator << (OutputStream & out, const std::vector<type> &v)
|
||||
{
|
||||
std::vector<type>::const_iterator pos = v.begin() ;
|
||||
while (pos != v.end())
|
||||
{
|
||||
out << *pos++ ;
|
||||
}
|
||||
return out ;
|
||||
}
|
||||
|
||||
inline OutputStream & OutputStream::operator << (const Matrix<4,4> &m)
|
||||
{
|
||||
for (int r = 0 ; r < 4 ; r++)
|
||||
for (int c = 0 ; c < 4 ; c++)
|
||||
(*this) << m[r][c];
|
||||
return *this;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// Checkpoints and alignment
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
/*! Sometimes during the storing process, a checkpoint value is
|
||||
stored to all the buffers at the same time. This check helps
|
||||
to determine if the files are not corrupted. */
|
||||
|
||||
inline void OutputStream::storeCheck(int checkPoint)
|
||||
{
|
||||
if (checkPoint >= 0)
|
||||
assert (checkPoint == checkCount) ;
|
||||
|
||||
(*this) << (int) checkCount ;
|
||||
(*this) << (short) checkCount ;
|
||||
(*this) << (char) checkCount ;
|
||||
|
||||
checkCount++ ;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// Flush method
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
/*! The file format wants a header with the version number, total size
|
||||
of all three buffers (in dwords), and the offsets of the 16-bits
|
||||
and 8-bits buffers, followed with the buffer data itself.
|
||||
|
||||
There is additional information that is stored after this data,
|
||||
but we don't know about it here */
|
||||
|
||||
inline void OutputStream::flush ()
|
||||
{
|
||||
int totalSize ;
|
||||
int offset16 ;
|
||||
int offset8 ;
|
||||
int i;
|
||||
|
||||
// Force all buffers to have a size multiple of 4 bytes
|
||||
|
||||
if (Used16 & 0x0001) (*this) << (short)0 ;
|
||||
while (Used8 & 0x0003) (*this) << (char) 0 ;
|
||||
|
||||
// Compute the header values (in dwords)
|
||||
|
||||
offset16 = Used32 ;
|
||||
offset8 = Used32 + Used16/2 ;
|
||||
totalSize = Used32 + Used16/2 + Used8/4 ;
|
||||
|
||||
// Fix endian...
|
||||
if (!isLittleEndian())
|
||||
{
|
||||
for (i=0; i<Used16; i++)
|
||||
Buffer16[i] = FIX_ENDIAN(Buffer16[i]);
|
||||
for (i=0; i<Used32; i++)
|
||||
Buffer32[i] = FIX_ENDIAN(Buffer32[i]);
|
||||
}
|
||||
|
||||
// Write the resulting data to the file
|
||||
|
||||
std::streampos pos = out.tellp() ;
|
||||
out.write ((char *) &FIX_ENDIAN(DTSVersion), 4) ;
|
||||
out.write ((char *) &FIX_ENDIAN(totalSize), 4) ;
|
||||
out.write ((char *) &FIX_ENDIAN(offset16), 4) ;
|
||||
out.write ((char *) &FIX_ENDIAN(offset8), 4) ;
|
||||
out.write ((char *) Buffer32, 4 * Used32) ;
|
||||
out.write ((char *) Buffer16, 2 * Used16) ;
|
||||
out.write (Buffer8, Used8) ;
|
||||
std::streampos endpos = out.tellp() ;
|
||||
|
||||
assert ((endpos - pos) == (std::streampos)(4*Used32 + 2*Used16 + 1*Used8 + 16)) ;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
75
lib/dtsSDK/DTSPoint.h
Executable file
75
lib/dtsSDK/DTSPoint.h
Executable file
@ -0,0 +1,75 @@
|
||||
#ifndef __DTSPOINT_H
|
||||
#define __DTSPOINT_H
|
||||
|
||||
#include <iomanip>
|
||||
#include <iostream>
|
||||
|
||||
#include "DTSVector.h"
|
||||
|
||||
namespace DTS
|
||||
{
|
||||
class Point3D : public Vector<float, 3>
|
||||
{
|
||||
public:
|
||||
|
||||
Point3D() {}
|
||||
Point3D(const Point3D &n) : Vector<float,3>(n) {}
|
||||
Point3D(const Vector<float,3> &n) : Vector<float,3>(n) {}
|
||||
Point3D(float x, float y, float z) { set (0,x), set(1,y), set(2,z); }
|
||||
|
||||
float x() const { return get(0); }
|
||||
float y() const { return get(1); }
|
||||
float z() const { return get(2); }
|
||||
void x(float n) { set (0, n) ; }
|
||||
void y(float n) { set (1, n) ; }
|
||||
void z(float n) { set (2, n) ; }
|
||||
};
|
||||
|
||||
typedef Point3D Point ;
|
||||
|
||||
class Point2D : public Vector<float, 2>
|
||||
{
|
||||
public:
|
||||
|
||||
Point2D() {}
|
||||
Point2D(const Point2D &n) : Vector<float,2>(n) {}
|
||||
Point2D(const Vector<float,2> &n) : Vector<float,2>(n) {}
|
||||
Point2D(float x, float y) { set(0,x), set(1,y); }
|
||||
|
||||
float x() const { return get(0); }
|
||||
float y() const { return get(1); }
|
||||
void x(float n) { set (0, n) ; }
|
||||
void y(float n) { set (1, n) ; }
|
||||
};
|
||||
|
||||
//! Defines a box in space. Used for bounding boxes.
|
||||
|
||||
struct Box
|
||||
{
|
||||
Point min, max ;
|
||||
|
||||
Box() {}
|
||||
|
||||
//! Create a box from two size in space. Note that no check is done,
|
||||
//! the two size need to define a correct box (min < max)
|
||||
Box(Point MIN, Point MAX) { min = MIN; max = MAX; }
|
||||
};
|
||||
|
||||
inline std::ostream & operator << (std::ostream &out, const Point3D &q)
|
||||
{
|
||||
out << std::setprecision(2) << std::setiosflags(std::ios::fixed) ;
|
||||
return out << "< " << q.x() << ", " << q.y() << ", " << q.z() << " >" ;
|
||||
}
|
||||
inline std::ostream & operator << (std::ostream &out, const Point2D &q)
|
||||
{
|
||||
out << std::setprecision(2) << std::setiosflags(std::ios::fixed) ;
|
||||
return out << "< " << q.x() << ", " << q.y() << " >" ;
|
||||
}
|
||||
inline std::ostream & operator << (std::ostream &out, const Box &q)
|
||||
{
|
||||
out << std::setprecision(2) << std::setiosflags(std::ios::fixed) ;
|
||||
return out << "( " << q.min << " - " ;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
140
lib/dtsSDK/DTSQuaternion.cpp
Executable file
140
lib/dtsSDK/DTSQuaternion.cpp
Executable file
@ -0,0 +1,140 @@
|
||||
|
||||
#pragma warning ( disable: 4786 )
|
||||
#include <vector>
|
||||
#include <cmath>
|
||||
|
||||
#include "DTSQuaternion.h"
|
||||
|
||||
namespace DTS
|
||||
{
|
||||
Quaternion Quaternion::identity (0,0,0,1) ;
|
||||
|
||||
/*! Create a quaternion from three spherical rotation angles
|
||||
(XY rotation angle, latitude and longitude) in radians */
|
||||
|
||||
Quaternion::Quaternion (float angle, float latitude, float longitude)
|
||||
{
|
||||
Quaternion x (Point( 1, 0, 0), angle) ;
|
||||
Quaternion y (Point( 0, 1, 0), latitude) ;
|
||||
Quaternion z (Point( 0, 0, 1), longitude) ;
|
||||
|
||||
// This order is a little wierd, but we flip the x & y
|
||||
// axis when importing from MilkShape.
|
||||
(*this) = x * z * y;
|
||||
}
|
||||
|
||||
/*! Calculate the angle in radians between this and another quaternion */
|
||||
|
||||
float Quaternion::angleBetween (const Quaternion &b) const
|
||||
{
|
||||
return acos (x()*b.x() + y()*b.y() + z()*b.z() + w()*b.w()) ;
|
||||
}
|
||||
|
||||
/*! Calculate the rotation matrix */
|
||||
|
||||
Matrix<4,4> Quaternion::toMatrix () const
|
||||
{
|
||||
float xx = x() * x() ;
|
||||
float xy = x() * y(), yy = y() * y() ;
|
||||
float xz = x() * z(), yz = y() * z(), zz = z() * z() ;
|
||||
float xw = x() * w(), yw = y() * w(), zw = z() * w(), ww = w() * w() ;
|
||||
|
||||
Matrix<4,4>::Cell data[] = {
|
||||
1 - 2 * (yy+zz), 2 * (xy-zw), 2 * (xz+yw), 0,
|
||||
2 * (xy+zw), 1 - 2 * (xx+zz), 2 * (yz-xw), 0,
|
||||
2 * (xz-yw), 2 * (yz+xw), 1 - 2 * (xx+yy), 0,
|
||||
0, 0, 0, 1
|
||||
} ;
|
||||
return Matrix<4,4>(data) ;
|
||||
}
|
||||
|
||||
/*! Create a quaternion from a rotation matrix */
|
||||
|
||||
Quaternion::Quaternion (const Matrix<> &m)
|
||||
{
|
||||
fromMatrix(m) ;
|
||||
}
|
||||
|
||||
void Quaternion::fromAxis (Point axis, float angle)
|
||||
{
|
||||
axis.normalize() ;
|
||||
float s = sin(angle / 2.0f) ;
|
||||
x(axis.x() * s) ;
|
||||
y(axis.y() * s) ;
|
||||
z(axis.z() * s) ;
|
||||
w(cos(angle / 2.0f)) ;
|
||||
}
|
||||
|
||||
void Quaternion::fromMatrix (const Matrix<> &m)
|
||||
{
|
||||
float qw2 = (1+ m[0][0] + m[1][1] + m[2][2]) * 0.25f ;
|
||||
float qx2 = qw2 - 0.5f * (m[1][1] + m[2][2]) ;
|
||||
float qy2 = qw2 - 0.5f * (m[0][0] + m[2][2]) ;
|
||||
float qz2 = qw2 - 0.5f * (m[0][0] + m[1][1]) ;
|
||||
float s ;
|
||||
|
||||
if (qw2 > qx2 && qw2 > qy2 && qw2 > qz2)
|
||||
{
|
||||
w( sqrtf(qw2) ); s = 0.25f / w() ;
|
||||
x( (m[2][1] - m[1][2]) * s );
|
||||
y( (m[0][2] - m[2][0]) * s );
|
||||
z( (m[1][0] - m[0][1]) * s );
|
||||
}
|
||||
else if (qx2 > qy2 && qx2 > qz2)
|
||||
{
|
||||
x( sqrtf(qx2) ); s = 0.25f / x() ;
|
||||
w( (m[2][1] - m[1][2]) * s );
|
||||
y( (m[0][1] - m[1][0]) * s );
|
||||
z( (m[2][0] - m[0][2]) * s );
|
||||
}
|
||||
else if (qy2 > qz2)
|
||||
{
|
||||
y( sqrtf(qy2) ); s = 0.25f / y() ;
|
||||
w( (m[0][2] - m[2][0]) * s );
|
||||
x( (m[0][1] - m[1][0]) * s );
|
||||
z( (m[1][2] - m[2][1]) * s );
|
||||
}
|
||||
else
|
||||
{
|
||||
z( sqrtf(qz2) ); s = 0.25f / z() ;
|
||||
w( (m[1][0] - m[0][1]) * s );
|
||||
x( (m[0][2] - m[2][0]) * s );
|
||||
y( (m[1][2] - m[2][1]) * s );
|
||||
}
|
||||
|
||||
//normalize() ;
|
||||
}
|
||||
|
||||
/*! Return the inverse of a quaternion */
|
||||
|
||||
Quaternion Quaternion::inverse() const
|
||||
{
|
||||
float norm = x()*x() + y()*y() + z()*z() + w()*w() ;
|
||||
|
||||
return conjugate() * (1.0f / norm) ;
|
||||
}
|
||||
|
||||
Quaternion operator * (const Quaternion &a, const Quaternion &b)
|
||||
{
|
||||
return Quaternion (
|
||||
+a[0]*b[3] +a[1]*b[2] -a[2]*b[1] +a[3]*b[0],
|
||||
-a[0]*b[2] +a[1]*b[3] +a[2]*b[0] +a[3]*b[1],
|
||||
+a[0]*b[1] -a[1]*b[0] +a[2]*b[3] +a[3]*b[2],
|
||||
-a[0]*b[0] -a[1]*b[1] -a[2]*b[2] +a[3]*b[3]
|
||||
) ;
|
||||
}
|
||||
|
||||
Point Quaternion::apply (const Point &v) const
|
||||
{
|
||||
// Torque uses column vectors, which means quaternions
|
||||
// rotate backwards from what you might normally expect.
|
||||
Quaternion q(v.x(), v.y(), v.z(), 0) ;
|
||||
Quaternion r = conjugate() * q * (*this);
|
||||
return Point(r.x(), r.y(), r.z()) ;
|
||||
|
||||
// The following should give the same result:
|
||||
//Matrix<> m = toMatrix() ;
|
||||
//return m * v ;
|
||||
}
|
||||
|
||||
}
|
59
lib/dtsSDK/DTSQuaternion.h
Executable file
59
lib/dtsSDK/DTSQuaternion.h
Executable file
@ -0,0 +1,59 @@
|
||||
#ifndef __DTSQUATERNION_H
|
||||
#define __DTSQUATERNION_H
|
||||
|
||||
#include "DTSVector.h"
|
||||
#include "DTSMatrix.h"
|
||||
#include "DTSPoint.h"
|
||||
|
||||
namespace DTS
|
||||
{
|
||||
//! Defines a quaternion. Used for rotation information.
|
||||
|
||||
class Quaternion : public Vector <float, 4>
|
||||
{
|
||||
public:
|
||||
|
||||
Quaternion() {}
|
||||
Quaternion(const Quaternion &n) : Vector<float,4>(n) {}
|
||||
Quaternion(const Vector<float,4> &n) : Vector<float,4>(n) {}
|
||||
Quaternion(float X, float Y, float Z, float W) { x(X),y(Y),z(Z),w(W); }
|
||||
Quaternion(float angle, float latitude, float longitude) ;
|
||||
Quaternion(const Matrix<4,4> &m) ;
|
||||
Quaternion(const Point &axis, float angle) { fromAxis(axis,angle); }
|
||||
|
||||
float x() const { return get(0); }
|
||||
float y() const { return get(1); }
|
||||
float z() const { return get(2); }
|
||||
float w() const { return get(3); }
|
||||
void x(float n) { set (0, n) ; }
|
||||
void y(float n) { set (1, n) ; }
|
||||
void z(float n) { set (2, n) ; }
|
||||
void w(float n) { set (3, n) ; }
|
||||
|
||||
// -------------------------------------------------------------
|
||||
|
||||
Quaternion conjugate() const { return Quaternion (-x(),-y(),-z(),w()) ; }
|
||||
Quaternion inverse() const ;
|
||||
Matrix<4,4> toMatrix() const ;
|
||||
void fromMatrix (const Matrix<4,4> &m) ;
|
||||
void fromAxis (Point axis, float angle) ;
|
||||
float angleBetween (const Quaternion &) const ;
|
||||
Point apply (const Point &) const ;
|
||||
|
||||
friend Quaternion operator * (const Quaternion &a, const Quaternion &b) ;
|
||||
Quaternion & operator *= (const Quaternion &a) { return (*this) = (*this) * a; }
|
||||
|
||||
// -------------------------------------------------------------
|
||||
|
||||
static Quaternion identity ;
|
||||
};
|
||||
|
||||
|
||||
inline std::ostream & operator << (std::ostream &out, const Quaternion &q)
|
||||
{
|
||||
out << std::setprecision(2) << std::setiosflags(std::ios::fixed) ;
|
||||
return out << "[ " << q.x() << ' ' << q.y() << ' ' << q.z() << ' ' << q.w() << " ]" ;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
776
lib/dtsSDK/DTSShape.cpp
Executable file
776
lib/dtsSDK/DTSShape.cpp
Executable file
@ -0,0 +1,776 @@
|
||||
|
||||
#pragma warning ( disable: 4786 )
|
||||
|
||||
#include "DTSShape.h"
|
||||
#include "DTSBrushMesh.h"
|
||||
#include "DTSOutputStream.h"
|
||||
#include "DTSInputStream.h"
|
||||
#include "DTSEndian.h"
|
||||
#include "DTSTypes.h"
|
||||
|
||||
#include <map>
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
// Helper macro -- assumes output stream "out"
|
||||
#define writeEndian(a,sz) out.write((char*) &FIX_ENDIAN(a),sz)
|
||||
|
||||
namespace DTS
|
||||
{
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// Constructor (create an empty shape)
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
Shape::Shape()
|
||||
{
|
||||
}
|
||||
|
||||
Sequence::Sequence()
|
||||
{
|
||||
baseDecalState = 0 ;
|
||||
baseObjectState = 0 ;
|
||||
baseRotation = 0 ;
|
||||
baseScale = 0 ;
|
||||
baseTranslation = 0 ;
|
||||
duration = 1.0f ;
|
||||
firstGroundFrame = 0 ;
|
||||
flags = 0 ;
|
||||
nameIndex = 0 ;
|
||||
numGroundFrames = 0 ;
|
||||
numKeyFrames = 0 ;
|
||||
priority = 1 ;
|
||||
toolBegin = 0.0f ;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// Loads a DTS file
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
void Shape::read (std::istream &in)
|
||||
{
|
||||
InputStream stream(in) ;
|
||||
int version = stream.version() ;
|
||||
|
||||
if (version < 19)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
MessageBox (NULL, "The DTS file is of a older, unsupported version", "Error",
|
||||
MB_ICONHAND | MB_OK) ;
|
||||
#else
|
||||
assert(0 && "The DTS file is of a older, unsupported version");
|
||||
#endif
|
||||
|
||||
return ;
|
||||
}
|
||||
|
||||
// Header
|
||||
|
||||
int numNodes ;
|
||||
int numObjects ;
|
||||
int numDecals ;
|
||||
int numSubshapes ;
|
||||
int numIFLmaterials ;
|
||||
int numNodeRotations ;
|
||||
int numNodeTranslations ;
|
||||
int numNodeScalesUniform ;
|
||||
int numNodeScalesAligned ;
|
||||
int numNodeScalesArbitrary ;
|
||||
int numGroundFrames ;
|
||||
int numObjectStates ;
|
||||
int numDecalStates ;
|
||||
int numTriggers ;
|
||||
int numDetailLevels ;
|
||||
int numMeshes ;
|
||||
int numSkins ;
|
||||
int numNames ;
|
||||
|
||||
stream >> numNodes >> numObjects >> numDecals >> numSubshapes >> numIFLmaterials ;
|
||||
|
||||
if (version < 22)
|
||||
{
|
||||
stream >> numNodeRotations ;
|
||||
numNodeRotations -= numNodes ;
|
||||
numNodeTranslations = numNodeRotations ;
|
||||
numNodeScalesUniform = 0 ;
|
||||
numNodeScalesAligned = 0 ;
|
||||
numNodeScalesArbitrary = 0 ;
|
||||
numGroundFrames = 0 ;
|
||||
}
|
||||
else
|
||||
{
|
||||
stream >> numNodeRotations ;
|
||||
stream >> numNodeTranslations ;
|
||||
stream >> numNodeScalesUniform ;
|
||||
stream >> numNodeScalesAligned ;
|
||||
stream >> numNodeScalesArbitrary ;
|
||||
if (version > 23)
|
||||
stream >> numGroundFrames ;
|
||||
}
|
||||
|
||||
stream >> numObjectStates ;
|
||||
stream >> numDecalStates ;
|
||||
stream >> numTriggers ;
|
||||
stream >> numDetailLevels ;
|
||||
stream >> numMeshes ;
|
||||
|
||||
if (version < 23)
|
||||
stream >> numSkins ;
|
||||
else
|
||||
numSkins = 0 ;
|
||||
|
||||
stream >> numNames ;
|
||||
|
||||
int smallestSizeInt ;
|
||||
stream >> smallestSizeInt ;
|
||||
stream >> smallestDetailLevel ;
|
||||
smallestSize = (float)smallestSizeInt ;
|
||||
|
||||
stream.readCheck(0) ;
|
||||
|
||||
// Bounds
|
||||
|
||||
stream >> radius ;
|
||||
stream >> tubeRadius ;
|
||||
stream >> center ;
|
||||
stream >> bounds ;
|
||||
|
||||
stream.readCheck(1) ;
|
||||
|
||||
// Nodes
|
||||
|
||||
nodes.resize(numNodes) ;
|
||||
stream >> nodes ;
|
||||
stream.readCheck(2) ;
|
||||
|
||||
// Objects
|
||||
|
||||
objects.resize(numObjects) ;
|
||||
stream >> objects ;
|
||||
stream.readCheck(3) ;
|
||||
|
||||
// Decals
|
||||
|
||||
decals.resize(numDecals) ;
|
||||
stream >> decals ;
|
||||
stream.readCheck(4) ;
|
||||
|
||||
// IFL Materials
|
||||
|
||||
IFLmaterials.resize(numIFLmaterials) ;
|
||||
stream >> IFLmaterials ;
|
||||
stream.readCheck(5) ;
|
||||
|
||||
// Subshapes
|
||||
|
||||
subshapes.resize(numSubshapes) ;
|
||||
std::vector<Subshape>::iterator shape ;
|
||||
for (shape = subshapes.begin() ; shape != subshapes.end() ; shape++)
|
||||
stream >> shape->firstNode ;
|
||||
for (shape = subshapes.begin() ; shape != subshapes.end() ; shape++)
|
||||
stream >> shape->firstObject ;
|
||||
for (shape = subshapes.begin() ; shape != subshapes.end() ; shape++)
|
||||
stream >> shape->firstDecal ;
|
||||
stream.readCheck(6) ;
|
||||
for (shape = subshapes.begin() ; shape != subshapes.end() ; shape++)
|
||||
stream >> shape->numNodes ;
|
||||
for (shape = subshapes.begin() ; shape != subshapes.end() ; shape++)
|
||||
stream >> shape->numObjects ;
|
||||
for (shape = subshapes.begin() ; shape != subshapes.end() ; shape++)
|
||||
stream >> shape->numDecals ;
|
||||
stream.readCheck(7) ;
|
||||
|
||||
// MeshIndexList (obsolete data)
|
||||
|
||||
if (version < 16)
|
||||
{
|
||||
int size, temp ;
|
||||
stream >> size ;
|
||||
while (size--) stream >> temp ;
|
||||
}
|
||||
|
||||
// Default translations and rotations
|
||||
|
||||
nodeDefRotations.resize(numNodes) ;
|
||||
nodeDefTranslations.resize(numNodes) ;
|
||||
|
||||
for (int n = 0 ; n < nodes.size() ; n++)
|
||||
{
|
||||
stream >> nodeDefRotations[n] ;
|
||||
stream >> nodeDefTranslations[n] ;
|
||||
}
|
||||
|
||||
// Animation translations and rotations
|
||||
|
||||
nodeTranslations.resize(numNodeTranslations) ;
|
||||
nodeRotations.resize(numNodeRotations) ;
|
||||
stream >> nodeTranslations ;
|
||||
stream >> nodeRotations ;
|
||||
stream.readCheck(8) ;
|
||||
|
||||
// Default scales
|
||||
|
||||
nodeScalesUniform.resize (numNodeScalesUniform) ;
|
||||
nodeScalesAligned.resize (numNodeScalesAligned) ;
|
||||
nodeScalesArbitrary.resize (numNodeScalesArbitrary) ;
|
||||
|
||||
if (version > 21)
|
||||
{
|
||||
stream >> numNodeScalesUniform ;
|
||||
stream >> numNodeScalesAligned ;
|
||||
stream >> numNodeScalesArbitrary ;
|
||||
stream.readCheck(9) ;
|
||||
}
|
||||
|
||||
// Ground transformations
|
||||
|
||||
groundTranslations.resize (numGroundFrames) ;
|
||||
groundRotations.resize (numGroundFrames) ;
|
||||
|
||||
if (version > 23)
|
||||
{
|
||||
stream >> groundTranslations ;
|
||||
stream >> groundRotations ;
|
||||
stream.readCheck() ;
|
||||
}
|
||||
|
||||
// Object states
|
||||
|
||||
objectStates.resize (numObjectStates) ;
|
||||
stream >> objectStates ;
|
||||
stream.readCheck() ;
|
||||
|
||||
// Decal states
|
||||
|
||||
decalStates.resize (numDecalStates) ;
|
||||
stream >> decalStates ;
|
||||
stream.readCheck() ;
|
||||
|
||||
// Triggers
|
||||
|
||||
triggers.resize (numTriggers) ;
|
||||
stream >> triggers ;
|
||||
stream.readCheck() ;
|
||||
|
||||
// Detail Levels
|
||||
|
||||
detailLevels.resize (numDetailLevels) ;
|
||||
stream >> detailLevels ;
|
||||
stream.readCheck() ;
|
||||
|
||||
// Meshes
|
||||
|
||||
meshes.resize (numMeshes) ;
|
||||
stream >> meshes ;
|
||||
stream.readCheck() ;
|
||||
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// Saves a DTS file
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
void Shape::save (std::ostream & out) const
|
||||
{
|
||||
OutputStream stream (out, 24) ;
|
||||
|
||||
// Header
|
||||
|
||||
stream << (int) nodes.size() ;
|
||||
stream << (int) objects.size() ;
|
||||
stream << (int) decals.size() ;
|
||||
stream << (int) subshapes.size() ;
|
||||
stream << (int) IFLmaterials.size() ;
|
||||
stream << (int) nodeRotations.size() ;
|
||||
stream << (int) nodeTranslations.size() ;
|
||||
stream << (int) nodeScalesUniform.size() ;
|
||||
stream << (int) nodeScalesAligned.size() ;
|
||||
stream << (int) nodeScalesArbitrary.size() ;
|
||||
stream << (int) groundTranslations.size() ;
|
||||
stream << (int) objectStates.size() ;
|
||||
stream << (int) decalStates.size() ;
|
||||
stream << (int) triggers.size() ;
|
||||
stream << (int) detailLevels.size() ;
|
||||
stream << (int) meshes.size() ;
|
||||
stream << (int) names.size() ;
|
||||
stream << (int) smallestSize ;
|
||||
stream << smallestDetailLevel ;
|
||||
|
||||
stream.storeCheck(0) ;
|
||||
|
||||
// Bounds
|
||||
|
||||
stream << radius ;
|
||||
stream << tubeRadius ;
|
||||
stream << center ;
|
||||
stream << bounds ;
|
||||
|
||||
stream.storeCheck(1) ;
|
||||
|
||||
// Nodes
|
||||
|
||||
stream << nodes ;
|
||||
stream.storeCheck(2) ;
|
||||
|
||||
// Objects
|
||||
|
||||
stream << objects ;
|
||||
stream.storeCheck(3) ;
|
||||
|
||||
// Decals
|
||||
|
||||
stream << decals ;
|
||||
stream.storeCheck(4) ;
|
||||
|
||||
// IFL Materials
|
||||
|
||||
stream << IFLmaterials ;
|
||||
stream.storeCheck(5) ;
|
||||
|
||||
// Subshapes
|
||||
|
||||
std::vector<Subshape>::const_iterator shape ;
|
||||
for (shape = subshapes.begin() ; shape != subshapes.end() ; shape++)
|
||||
stream << shape->firstNode ;
|
||||
for (shape = subshapes.begin() ; shape != subshapes.end() ; shape++)
|
||||
stream << shape->firstObject ;
|
||||
for (shape = subshapes.begin() ; shape != subshapes.end() ; shape++)
|
||||
stream << shape->firstDecal ;
|
||||
stream.storeCheck(6) ;
|
||||
for (shape = subshapes.begin() ; shape != subshapes.end() ; shape++)
|
||||
stream << shape->numNodes ;
|
||||
for (shape = subshapes.begin() ; shape != subshapes.end() ; shape++)
|
||||
stream << shape->numObjects ;
|
||||
for (shape = subshapes.begin() ; shape != subshapes.end() ; shape++)
|
||||
stream << shape->numDecals ;
|
||||
stream.storeCheck(7) ;
|
||||
|
||||
// Default translations and rotations
|
||||
|
||||
assert (nodeDefRotations.size() == nodes.size()) ;
|
||||
assert (nodeDefTranslations.size() == nodes.size()) ;
|
||||
|
||||
for (int n = 0 ; n < nodes.size() ; n++)
|
||||
{
|
||||
stream << nodeDefRotations[n] ;
|
||||
stream << nodeDefTranslations[n] ;
|
||||
}
|
||||
|
||||
// Animation translations and rotations
|
||||
|
||||
stream << nodeTranslations ; // As current position, we store the same values
|
||||
stream << nodeRotations ;
|
||||
stream.storeCheck(8) ;
|
||||
|
||||
// Default scales
|
||||
|
||||
stream << nodeScalesUniform ;
|
||||
stream << nodeScalesAligned ;
|
||||
stream << nodeScalesArbitrary ;
|
||||
stream << nodeScaleRotsArbitrary ;
|
||||
stream.storeCheck(9) ;
|
||||
|
||||
// Ground transformations
|
||||
|
||||
stream << groundTranslations ;
|
||||
stream << groundRotations ;
|
||||
stream.storeCheck(10) ;
|
||||
|
||||
// Object states
|
||||
|
||||
stream << objectStates ;
|
||||
stream.storeCheck(11) ;
|
||||
|
||||
// Decal states
|
||||
|
||||
stream << decalStates ;
|
||||
stream.storeCheck(12) ;
|
||||
|
||||
// Triggers
|
||||
|
||||
stream << triggers ;
|
||||
stream.storeCheck(13) ;
|
||||
|
||||
// Detail levels
|
||||
|
||||
stream << detailLevels ;
|
||||
stream.storeCheck(14) ;
|
||||
|
||||
// Meshes
|
||||
|
||||
stream << meshes ;
|
||||
stream.storeCheck() ; // Many checks stored within the meshes
|
||||
|
||||
// Names
|
||||
|
||||
stream << names ;
|
||||
stream.storeCheck() ;
|
||||
|
||||
// Finished with the 3-buffer stuff
|
||||
|
||||
stream.flush() ;
|
||||
|
||||
// Sequences
|
||||
|
||||
int numSequences = sequences.size() ;
|
||||
out.write ((char *)&FIX_ENDIAN(numSequences), 4) ;
|
||||
|
||||
for (int seq = 0 ; seq < sequences.size() ; seq++)
|
||||
{
|
||||
const Sequence &p = sequences[seq] ;
|
||||
|
||||
out.write ((char *) &FIX_ENDIAN(p.nameIndex), 4) ;
|
||||
out.write ((char *) &FIX_ENDIAN(p.flags), 4) ;
|
||||
out.write ((char *) &FIX_ENDIAN(p.numKeyFrames), 4) ;
|
||||
out.write ((char *) &FIX_ENDIAN(p.duration), 4) ;
|
||||
out.write ((char *) &FIX_ENDIAN(p.priority), 4) ;
|
||||
out.write ((char *) &FIX_ENDIAN(p.firstGroundFrame), 4) ;
|
||||
out.write ((char *) &FIX_ENDIAN(p.numGroundFrames), 4) ;
|
||||
out.write ((char *) &FIX_ENDIAN(p.baseRotation), 4) ;
|
||||
out.write ((char *) &FIX_ENDIAN(p.baseTranslation), 4) ;
|
||||
out.write ((char *) &FIX_ENDIAN(p.baseScale), 4) ;
|
||||
out.write ((char *) &FIX_ENDIAN(p.baseObjectState), 4) ;
|
||||
out.write ((char *) &FIX_ENDIAN(p.baseDecalState), 4) ;
|
||||
out.write ((char *) &FIX_ENDIAN(p.firstTrigger), 4) ;
|
||||
out.write ((char *) &FIX_ENDIAN(p.numTriggers), 4) ;
|
||||
out.write ((char *) &FIX_ENDIAN(p.toolBegin), 4) ;
|
||||
|
||||
write(out,&p.matters.rotation);
|
||||
write(out,&p.matters.translation);
|
||||
write(out,&p.matters.scale);
|
||||
write(out,&p.matters.decal);
|
||||
write(out,&p.matters.ifl);
|
||||
write(out,&p.matters.vis);
|
||||
write(out,&p.matters.frame);
|
||||
write(out,&p.matters.matframe);
|
||||
}
|
||||
|
||||
// Materials
|
||||
|
||||
char materialListVersion = 1 ;
|
||||
out.write (&materialListVersion, 1) ;
|
||||
int count = materials.size() ;
|
||||
out.write ((char *) &FIX_ENDIAN(count), 4) ;
|
||||
|
||||
std::vector<Material>::const_iterator mat ;
|
||||
for (mat = materials.begin() ; mat != materials.end() ; mat++)
|
||||
{
|
||||
char length = mat->name.size() ;
|
||||
out.write (&length, 1) ;
|
||||
std::string::const_iterator pos = mat->name.begin() ;
|
||||
while (pos != mat->name.end())
|
||||
out.write (&*(pos++), 1) ;
|
||||
}
|
||||
for (mat = materials.begin() ; mat != materials.end() ; mat++)
|
||||
out.write ((char *) &FIX_ENDIAN(mat->flags), 4) ;
|
||||
for (mat = materials.begin() ; mat != materials.end() ; mat++)
|
||||
out.write ((char *) &FIX_ENDIAN(mat->reflectance), 4) ;
|
||||
for (mat = materials.begin() ; mat != materials.end() ; mat++)
|
||||
out.write ((char *) &FIX_ENDIAN(mat->bump), 4) ;
|
||||
for (mat = materials.begin() ; mat != materials.end() ; mat++)
|
||||
out.write ((char *) &FIX_ENDIAN(mat->detail), 4) ;
|
||||
for (mat = materials.begin() ; mat != materials.end() ; mat++)
|
||||
out.write ((char *) &FIX_ENDIAN(mat->detailScale), 4) ;
|
||||
for (mat = materials.begin() ; mat != materials.end() ; mat++)
|
||||
out.write ((char *) &FIX_ENDIAN(mat->reflection), 4) ;
|
||||
|
||||
// Done!
|
||||
}
|
||||
|
||||
void Shape::saveSequences(std::ostream & out) const
|
||||
{
|
||||
int i;
|
||||
|
||||
// write version info
|
||||
writeEndian((int)24,4);
|
||||
|
||||
// write node names
|
||||
// -- this is how we will map imported sequence nodes to shape nodes
|
||||
writeEndian(nodes.size(),4);
|
||||
for (i=0; i<nodes.size(); i++)
|
||||
{
|
||||
const char * name = names[nodes[i].name].c_str();
|
||||
writeEndian(strlen(name),4);
|
||||
out.write(name,strlen(name));
|
||||
}
|
||||
|
||||
// legacy write -- write zero objects, don't pretend to support object export anymore
|
||||
writeEndian((int)0,4);
|
||||
|
||||
// on import, we will need to adjust keyframe data based on number of
|
||||
// nodes/objects in this shape...number of nodes can be inferred from
|
||||
// above, but number of objects cannot be. Write that quantity here:
|
||||
writeEndian(objects.size(),4);
|
||||
|
||||
writeEndian(nodeRotations.size(),4);
|
||||
for (i=0; i<nodeRotations.size(); i++)
|
||||
{
|
||||
writeEndian((short)(nodeRotations[i].x() * 32767.0f),2);
|
||||
writeEndian((short)(nodeRotations[i].y() * 32767.0f),2);
|
||||
writeEndian((short)(nodeRotations[i].z() * 32767.0f),2);
|
||||
writeEndian((short)(nodeRotations[i].w() * 32767.0f),2);
|
||||
}
|
||||
|
||||
writeEndian(nodeTranslations.size(),4);
|
||||
for (i=0; i<nodeTranslations.size(); i++)
|
||||
{
|
||||
writeEndian(nodeTranslations[i].x(),4);
|
||||
writeEndian(nodeTranslations[i].y(),4);
|
||||
writeEndian(nodeTranslations[i].z(),4);
|
||||
}
|
||||
|
||||
writeEndian(nodeScalesUniform.size(),4);
|
||||
for (i=0; i<nodeScalesUniform.size(); i++)
|
||||
{
|
||||
writeEndian(nodeScalesUniform[i],4);
|
||||
}
|
||||
|
||||
writeEndian(nodeScalesAligned.size(),4);
|
||||
for (i=0; i<nodeScalesAligned.size(); i++)
|
||||
{
|
||||
writeEndian(nodeScalesAligned[i].x(),4);
|
||||
writeEndian(nodeScalesAligned[i].y(),4);
|
||||
writeEndian(nodeScalesAligned[i].z(),4);
|
||||
}
|
||||
|
||||
writeEndian(nodeScaleRotsArbitrary.size(),4);
|
||||
for (i=0; i<nodeScaleRotsArbitrary.size(); i++)
|
||||
{
|
||||
writeEndian((short)(nodeScaleRotsArbitrary[i].x() * 32767.0f),2);
|
||||
writeEndian((short)(nodeScaleRotsArbitrary[i].y() * 32767.0f),2);
|
||||
writeEndian((short)(nodeScaleRotsArbitrary[i].z() * 32767.0f),2);
|
||||
writeEndian((short)(nodeScaleRotsArbitrary[i].w() * 32767.0f),2);
|
||||
}
|
||||
// same number as above...
|
||||
for (i=0; i<nodeScalesArbitrary.size(); i++)
|
||||
{
|
||||
writeEndian(nodeScalesArbitrary[i].x(),4);
|
||||
writeEndian(nodeScalesArbitrary[i].y(),4);
|
||||
writeEndian(nodeScalesArbitrary[i].z(),4);
|
||||
}
|
||||
|
||||
writeEndian(groundTranslations.size(),4);
|
||||
for (i=0; i<groundTranslations.size(); i++)
|
||||
{
|
||||
writeEndian(groundTranslations[i].x(),4);
|
||||
writeEndian(groundTranslations[i].y(),4);
|
||||
writeEndian(groundTranslations[i].z(),4);
|
||||
}
|
||||
// same number as above
|
||||
for (i=0; i<groundRotations.size(); i++)
|
||||
{
|
||||
writeEndian((short)(groundRotations[i].x() * 32767.0f),2);
|
||||
writeEndian((short)(groundRotations[i].y() * 32767.0f),2);
|
||||
writeEndian((short)(groundRotations[i].z() * 32767.0f),2);
|
||||
writeEndian((short)(groundRotations[i].w() * 32767.0f),2);
|
||||
}
|
||||
|
||||
// legacy write -- write zero objects, don't pretend to support object export anymore
|
||||
writeEndian((int)0,4);
|
||||
|
||||
// Sequences
|
||||
|
||||
int numSequences = sequences.size() ;
|
||||
writeEndian(numSequences,4);
|
||||
|
||||
for (int seq = 0 ; seq < sequences.size() ; seq++)
|
||||
{
|
||||
const Sequence &p = sequences[seq] ;
|
||||
|
||||
// write sequence name
|
||||
const char * seqname = names[p.nameIndex].c_str();
|
||||
writeEndian(strlen(seqname),4);
|
||||
out.write((char*)seqname,strlen(seqname));
|
||||
|
||||
// skip name index...
|
||||
writeEndian(p.flags,4);
|
||||
writeEndian(p.numKeyFrames,4);
|
||||
writeEndian(p.duration,4);
|
||||
writeEndian(p.priority,4);
|
||||
writeEndian(p.firstGroundFrame,4);
|
||||
writeEndian(p.numGroundFrames,4);
|
||||
writeEndian(p.baseRotation,4);
|
||||
writeEndian(p.baseTranslation,4);
|
||||
writeEndian(p.baseScale,4);
|
||||
writeEndian(p.baseObjectState,4);
|
||||
writeEndian(p.baseDecalState,4);
|
||||
writeEndian(p.firstTrigger,4);
|
||||
writeEndian(p.numTriggers,4);
|
||||
writeEndian(p.toolBegin,4);
|
||||
|
||||
write(out,&p.matters.rotation);
|
||||
write(out,&p.matters.translation);
|
||||
write(out,&p.matters.scale);
|
||||
write(out,&p.matters.decal);
|
||||
write(out,&p.matters.ifl);
|
||||
write(out,&p.matters.vis);
|
||||
write(out,&p.matters.frame);
|
||||
write(out,&p.matters.matframe);
|
||||
}
|
||||
|
||||
writeEndian(triggers.size(),4);
|
||||
for (i=0; i<triggers.size(); i++)
|
||||
{
|
||||
writeEndian(triggers[i].state,4);
|
||||
writeEndian(triggers[i].pos,4);
|
||||
}
|
||||
}
|
||||
|
||||
void Shape::write (std::ostream & out,const std::vector<bool> * ptr) const
|
||||
{
|
||||
// Save out the bool array as an array of bits, in 32bit chunks.
|
||||
int words[32], use = ptr->size() / 32 ;
|
||||
if (use * 32 < ptr->size()) use++ ;
|
||||
|
||||
memset(words, 0, sizeof(words));
|
||||
for (int i = 0 ; i < ptr->size() ; i++)
|
||||
if ((*ptr)[i])
|
||||
words[i >> 5] |= 1 << (i & 31);
|
||||
for (int j = 0; j < sizeof(words)/sizeof(int); j++)
|
||||
words[j] = FIX_ENDIAN(words[j]);
|
||||
|
||||
|
||||
out.write ((char *)&FIX_ENDIAN(use), 4) ;
|
||||
out.write ((char *)&FIX_ENDIAN(use), 4) ;
|
||||
if (use > 0)
|
||||
out.write ((char *)&words, 4*use) ;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// Utility methods
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
int Shape::addName (std::string s)
|
||||
{
|
||||
// Don't store duplicated names
|
||||
|
||||
for (int i = 0 ; i < names.size() ; i++)
|
||||
{
|
||||
#if _WIN32
|
||||
if (!stricmp(names[i].data(),s.data()))
|
||||
#else
|
||||
if (!strcasecmp(names[i].data(),s.data()))
|
||||
#endif
|
||||
return i ;
|
||||
}
|
||||
names.push_back(s) ;
|
||||
return names.size() - 1 ;
|
||||
}
|
||||
|
||||
void Shape::calculateBounds()
|
||||
{
|
||||
if (!objects.size()) return ;
|
||||
|
||||
bounds.max = Point(-10E30F, -10E30F, -10E30F) ;
|
||||
bounds.min = Point( 10E30F, 10E30F, 10E30F) ;
|
||||
|
||||
// Iterate through the objects instead of the meshes
|
||||
// so we can easily get the default transforms.
|
||||
for (int i = 0 ; i < objects.size() ; i++)
|
||||
{
|
||||
const Object &obj = objects[i];
|
||||
|
||||
Point trans;
|
||||
Quaternion rot;
|
||||
getNodeWorldPosRot(obj.node,trans,rot);
|
||||
|
||||
for (int j = 0 ; j < obj.numMeshes ; j++)
|
||||
{
|
||||
Box bounds2 = meshes[obj.firstMesh + j].getBounds(trans,rot) ;
|
||||
bounds.min.x(min(bounds.min.x(), bounds2.min.x())) ;
|
||||
bounds.min.y(min(bounds.min.y(), bounds2.min.y())) ;
|
||||
bounds.min.z(min(bounds.min.z(), bounds2.min.z())) ;
|
||||
bounds.max.x(max(bounds.max.x(), bounds2.max.x())) ;
|
||||
bounds.max.y(max(bounds.max.y(), bounds2.max.y())) ;
|
||||
bounds.max.z(max(bounds.max.z(), bounds2.max.z())) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Shape::calculateCenter()
|
||||
{
|
||||
center = bounds.min.midpoint(bounds.max) ;
|
||||
}
|
||||
|
||||
void Shape::calculateTubeRadius()
|
||||
{
|
||||
float maxRadius = 0.0f ;
|
||||
|
||||
for (int i = 0 ; i < objects.size() ; i++)
|
||||
{
|
||||
const Object &obj = objects[i];
|
||||
|
||||
Point trans;
|
||||
Quaternion rot;
|
||||
getNodeWorldPosRot(obj.node,trans,rot);
|
||||
|
||||
for (int j = 0 ; j < obj.numMeshes ; j++)
|
||||
{
|
||||
const Mesh &m = meshes[obj.firstMesh + j];
|
||||
float meshRadius = m.getTubeRadiusFrom(trans,rot,center) ;
|
||||
if (meshRadius > maxRadius)
|
||||
maxRadius = meshRadius ;
|
||||
}
|
||||
}
|
||||
tubeRadius = maxRadius ;
|
||||
}
|
||||
|
||||
void Shape::calculateRadius()
|
||||
{
|
||||
float maxRadius = 0.0f ;
|
||||
|
||||
for (int i = 0 ; i < objects.size() ; i++)
|
||||
{
|
||||
const Object &obj = objects[i];
|
||||
|
||||
Point trans;
|
||||
Quaternion rot;
|
||||
getNodeWorldPosRot(obj.node,trans,rot);
|
||||
|
||||
for (int j = 0 ; j < obj.numMeshes ; j++)
|
||||
{
|
||||
const Mesh &m = meshes[obj.firstMesh + j];
|
||||
float meshRadius = m.getRadiusFrom(trans,rot,center) ;
|
||||
if (meshRadius > maxRadius)
|
||||
maxRadius = meshRadius ;
|
||||
}
|
||||
}
|
||||
radius = maxRadius ;
|
||||
}
|
||||
|
||||
void Shape::setSmallestSize(int pixels)
|
||||
{
|
||||
if (pixels < 1)
|
||||
pixels = 1;
|
||||
|
||||
smallestSize = pixels;
|
||||
|
||||
int i=0;
|
||||
|
||||
for (i = 0; i < detailLevels.size(); i++)
|
||||
{
|
||||
if (detailLevels[i].size < pixels)
|
||||
break ;
|
||||
}
|
||||
smallestDetailLevel = i;
|
||||
}
|
||||
|
||||
void Shape::getNodeWorldPosRot(int n, Point &trans, Quaternion &rot)
|
||||
{
|
||||
// Build total translation & rotation for this node
|
||||
std::vector <int> nidx;
|
||||
nidx.push_back(n);
|
||||
while ((n = nodes[n].parent) >= 0)
|
||||
nidx.push_back(n);
|
||||
|
||||
trans = Point(0,0,0);
|
||||
rot = Quaternion::identity;
|
||||
for (int i = nidx.size() - 1; i >= 0; i--)
|
||||
{
|
||||
trans += rot.apply(nodeDefTranslations[nidx[i]]);
|
||||
rot = nodeDefRotations[nidx[i]] * rot;
|
||||
}
|
||||
}
|
||||
}
|
280
lib/dtsSDK/DTSShape.h
Executable file
280
lib/dtsSDK/DTSShape.h
Executable file
@ -0,0 +1,280 @@
|
||||
#ifndef __DTS_SHAPE_H
|
||||
#define __DTS_SHAPE_H
|
||||
|
||||
#include "DTSPoint.h"
|
||||
#include "DTSQuaternion.h"
|
||||
#include "DTSMesh.h"
|
||||
|
||||
namespace DTS
|
||||
{
|
||||
//! Defines a tree node, as stored in the DTS file
|
||||
|
||||
struct Node
|
||||
{
|
||||
int name ; //!< Index of its name in the DTS string table
|
||||
int parent ; //!< Number of the parent node, -1 if it is root
|
||||
int firstObject ; //!< Deprecated: set to -1 (Note: not quite true, used in TSShape, set on load, but not used by exporter)
|
||||
int child ; //!< Deprecated: set to -1 (Note: not quite true, used in TSShape, set on load, but not used by exporter)
|
||||
int sibling ; //!< Deprecated: set to -1 (Note: not quite true, used in TSShape, set on load, but not used by exporter)
|
||||
Node() {
|
||||
// These values unused in data file
|
||||
firstObject = child = sibling = -1;
|
||||
}
|
||||
};
|
||||
|
||||
//! Defines an object, as stored in the DTS file
|
||||
|
||||
struct Object
|
||||
{
|
||||
int name ; //!< Index of its name in the DTS string table
|
||||
int numMeshes ; //!< Number of meshes (only one mesh is used for detail level)
|
||||
int firstMesh ; //!< Number of the first mesh (they must be consecutive)
|
||||
int node ; //!< Number of the node where the object is stored
|
||||
int sibling ; //!< Deprecated: set to -1. (Note: not quite true, used in TSShape, set on load, but not used by exporter)
|
||||
int firstDecal ; //!< Deprecated: set to -1
|
||||
Object() {
|
||||
// These values unused in data file
|
||||
firstDecal = sibling = -1;
|
||||
}
|
||||
};
|
||||
|
||||
//! Defines a decal, as stored in the DTS file. DEPRECATED.
|
||||
|
||||
struct Decal
|
||||
{
|
||||
int name ;
|
||||
int numMeshes ;
|
||||
int firstMesh ;
|
||||
int object ;
|
||||
int sibling ;
|
||||
};
|
||||
|
||||
//! Defines a material, as stored in the DTS file
|
||||
|
||||
struct Material
|
||||
{
|
||||
std::string name ; //!< Texture name. Materials don't use the DTS string table
|
||||
|
||||
int flags ; //!< Boolean properties
|
||||
int reflectance ; //!< Number of reflectance map (?)
|
||||
int bump ; //!< Number of bump map (?) or -1 if none
|
||||
int detail ; //!< Index of the material, which stores the Detailmap for this material or -1 if none
|
||||
float detailScale ; //!< Scale of the Detailmap, Default = 1.0f
|
||||
float reflection ; //!< ?
|
||||
|
||||
enum //!< Material flags
|
||||
{
|
||||
SWrap = 0x00000001,
|
||||
TWrap = 0x00000002,
|
||||
Translucent = 0x00000004,
|
||||
Additive = 0x00000008,
|
||||
Subtractive = 0x00000010,
|
||||
SelfIlluminating = 0x00000020,
|
||||
NeverEnvMap = 0x00000040,
|
||||
NoMipMap = 0x00000080,
|
||||
MipMapZeroBorder = 0x00000100,
|
||||
IFLMaterial = 0x08000000,
|
||||
IFLFrame = 0x10000000,
|
||||
DetailMap = 0x20000000,
|
||||
BumpMap = 0x40000000,
|
||||
ReflectanceMap = 0x80000000,
|
||||
AuxiliaryMask = 0xE0000000
|
||||
};
|
||||
};
|
||||
|
||||
//! Defines an animated material as stored in the DTS file
|
||||
|
||||
struct IFLMaterial
|
||||
{
|
||||
int name ;
|
||||
int slot ;
|
||||
int firstFrame ;
|
||||
int time ;
|
||||
int numFrames ;
|
||||
};
|
||||
|
||||
//! Defines a detail level as stored in the DTS file
|
||||
|
||||
struct DetailLevel
|
||||
{
|
||||
int name ; //!< Index of the name in the DTS string table
|
||||
int subshape ; //!< Number of the subshape it belongs
|
||||
int objectDetail ; //!< Number of object mesh to draw for each object
|
||||
float size ; //!< Minimum pixel size (store details from big to small)
|
||||
float avgError ; //!< Don't know, use -1
|
||||
float maxError ; //!< Don't know, use -1
|
||||
int polyCount ; //!< Polygon count of the meshes to draw.
|
||||
};
|
||||
|
||||
//! Defines a subshape as stored in the DTS file. A subshape defines a range
|
||||
//! of nodes and objects.
|
||||
|
||||
struct Subshape
|
||||
{
|
||||
int firstNode ;
|
||||
int firstObject ;
|
||||
int firstDecal ;
|
||||
int numNodes ;
|
||||
int numObjects ;
|
||||
int numDecals ;
|
||||
int firstTranslucent ; //!< Not used/stored (?)
|
||||
};
|
||||
|
||||
//! Defines an object state as stored in the DTS file.
|
||||
//! Not sure about what does, but it may be related to animated materials.
|
||||
|
||||
struct ObjectState
|
||||
{
|
||||
float vis ;
|
||||
int frame ;
|
||||
int matFrame ;
|
||||
};
|
||||
|
||||
//! Defines a decal state as stored in the DTS file. DEPRECATED.
|
||||
|
||||
struct DecalState
|
||||
{
|
||||
int frame ;
|
||||
};
|
||||
|
||||
//! Defines a trigger as stored in the DTS file.
|
||||
|
||||
struct Trigger
|
||||
{
|
||||
int state ;
|
||||
float pos ;
|
||||
};
|
||||
|
||||
//! Defines a sequence as stored in the DTS file
|
||||
|
||||
struct Sequence
|
||||
{
|
||||
int nameIndex ;
|
||||
int flags ;
|
||||
int numKeyFrames ;
|
||||
float duration ;
|
||||
int priority ;
|
||||
int firstGroundFrame ;
|
||||
int numGroundFrames ;
|
||||
int baseRotation ;
|
||||
int baseTranslation ;
|
||||
int baseScale ;
|
||||
int baseObjectState ;
|
||||
int baseDecalState ;
|
||||
int firstTrigger ;
|
||||
int numTriggers ;
|
||||
float toolBegin ;
|
||||
|
||||
enum /* flags */
|
||||
{
|
||||
UniformScale = 0x0001,
|
||||
AlignedScale = 0x0002,
|
||||
ArbitraryScale = 0x0004,
|
||||
Blend = 0x0008,
|
||||
Cyclic = 0x0010,
|
||||
MakePath = 0x0020,
|
||||
IFLInit = 0x0040,
|
||||
HasTranslucency = 0x0080
|
||||
};
|
||||
|
||||
struct matters_array {
|
||||
std::vector<bool> rotation ;
|
||||
std::vector<bool> translation ;
|
||||
std::vector<bool> scale ;
|
||||
std::vector<bool> decal ;
|
||||
std::vector<bool> ifl ;
|
||||
std::vector<bool> vis ;
|
||||
std::vector<bool> frame ;
|
||||
std::vector<bool> matframe ;
|
||||
}
|
||||
matters ;
|
||||
|
||||
Sequence() ;
|
||||
};
|
||||
|
||||
//! Defines a DTS shape
|
||||
|
||||
class Shape
|
||||
{
|
||||
friend class ShapeMimic;
|
||||
friend class AppConfig;
|
||||
|
||||
public:
|
||||
|
||||
enum //! ImportConfig collision types
|
||||
{
|
||||
C_None = 0,
|
||||
C_BBox,
|
||||
C_Cylinder,
|
||||
C_Mesh
|
||||
} ;
|
||||
|
||||
//! Create an empty shape
|
||||
Shape () ;
|
||||
|
||||
//! Write the shape to a file or stream
|
||||
void save (std::ostream & out) const ;
|
||||
|
||||
//! Write the shape's sequences to a file or stream
|
||||
void saveSequences (std::ostream & out) const ;
|
||||
|
||||
//! Read the shape from a file or stream
|
||||
void read (std::istream & in) ;
|
||||
|
||||
Box getBounds() const { return bounds; }
|
||||
float getRadius() const { return radius; }
|
||||
float getTubeRadius() const { return tubeRadius; }
|
||||
|
||||
protected:
|
||||
|
||||
int addName (std::string s) ;
|
||||
|
||||
void calculateBounds() ;
|
||||
void calculateRadius() ;
|
||||
void calculateTubeRadius() ;
|
||||
void calculateCenter() ;
|
||||
void setSmallestSize(int) ;
|
||||
void setCenter(Point &p) { center = p; }
|
||||
void getNodeWorldPosRot(int n,Point &trans, Quaternion &rot);
|
||||
void write(std::ostream & out,const std::vector<bool> * ptr) const;
|
||||
|
||||
protected:
|
||||
|
||||
std::vector <Node> nodes ;
|
||||
std::vector <Object> objects ;
|
||||
std::vector <Decal> decals ;
|
||||
std::vector <Subshape> subshapes ;
|
||||
std::vector <IFLMaterial> IFLmaterials ;
|
||||
std::vector <Material> materials ;
|
||||
std::vector <Quaternion> nodeDefRotations ;
|
||||
std::vector <Point> nodeDefTranslations ;
|
||||
std::vector <Quaternion> nodeRotations ;
|
||||
std::vector <Point> nodeTranslations ;
|
||||
std::vector <float> nodeScalesUniform ;
|
||||
std::vector <Point> nodeScalesAligned ;
|
||||
std::vector <Point> nodeScalesArbitrary ;
|
||||
std::vector <Quaternion> nodeScaleRotsArbitrary ;
|
||||
std::vector <Quaternion> groundRotations ;
|
||||
std::vector <Point> groundTranslations ;
|
||||
std::vector <ObjectState> objectStates ;
|
||||
std::vector <DecalState> decalStates ;
|
||||
std::vector <Trigger> triggers ;
|
||||
std::vector <DetailLevel> detailLevels ;
|
||||
std::vector <Mesh> meshes ;
|
||||
std::vector <Sequence> sequences ;
|
||||
std::vector <std::string> names ;
|
||||
|
||||
private:
|
||||
|
||||
float smallestSize ;
|
||||
int smallestDetailLevel ;
|
||||
|
||||
float radius ;
|
||||
float tubeRadius ;
|
||||
Point center ;
|
||||
Box bounds ;
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
29
lib/dtsSDK/DTSTypes.h
Executable file
29
lib/dtsSDK/DTSTypes.h
Executable file
@ -0,0 +1,29 @@
|
||||
#ifndef __DTSTYPES_H
|
||||
#define __DTSTYPES_H
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <ostream>
|
||||
#include <cmath>
|
||||
#include <cassert>
|
||||
|
||||
#include "DTSPoint.h"
|
||||
|
||||
#ifndef _WIN32
|
||||
#define __cdecl
|
||||
#define strnicmp strncasecmp
|
||||
#define stricmp strcasecmp
|
||||
inline float min(float a, float b) { return a<b ? a : b; }
|
||||
inline float max(float a, float b) { return a>b ? a : b; }
|
||||
#endif
|
||||
|
||||
//! The DTS namespace implements all the classes needed to load a DTS model
|
||||
//! and to create one from the Milkshape data. There are many basic classes
|
||||
//! here, such as Point or Quaternion.
|
||||
|
||||
namespace DTS
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
#endif
|
238
lib/dtsSDK/DTSVector.h
Executable file
238
lib/dtsSDK/DTSVector.h
Executable file
@ -0,0 +1,238 @@
|
||||
#ifndef __DTSVECTOR_H
|
||||
#define __DTSVECTOR_H
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <ostream>
|
||||
#include <cmath>
|
||||
|
||||
namespace DTS
|
||||
{
|
||||
|
||||
//! Defines a generic vector class
|
||||
|
||||
template <class type, int size> class Vector
|
||||
{
|
||||
public:
|
||||
|
||||
//! Create a null vector
|
||||
Vector () {
|
||||
// No initialization. Derivated classes have no overhead.
|
||||
}
|
||||
|
||||
//! Create a vector from a data array
|
||||
Vector (const type *d) {
|
||||
for (int n = 0 ; n < size ; n++) members[n] = d[n] ;
|
||||
}
|
||||
|
||||
//! Create a point with given space coordinates
|
||||
Vector<type, size> (const Vector<type, size> &v) {
|
||||
for (int n = 0 ; n < size ; n++) members[n] = v.members[n] ;
|
||||
}
|
||||
|
||||
//! Member access
|
||||
const type & get (int n) const { return members[n] ; }
|
||||
type & operator[] (int n) { return members[n] ; }
|
||||
const type & operator[] (int n) const { return members[n] ; }
|
||||
void set (int n, type value) { members[n] = value ; }
|
||||
|
||||
//!{ Member operators *************************************************
|
||||
|
||||
Vector<type, size> operator - () const {
|
||||
Vector<type, size> r ;
|
||||
for (int n = 0 ; n < size ; n++) r.members[n] = -members[n];
|
||||
return r ;
|
||||
}
|
||||
Vector<type, size> & operator = (const Vector<type, size> &v) {
|
||||
for (int n = 0 ; n < size ; n++) members[n] = v.members[n] ;
|
||||
return *this ;
|
||||
}
|
||||
Vector<type, size> & operator += (const Vector<type, size> &r) {
|
||||
for (int n = 0 ; n < size ; n++) members[n] += r.members[n];
|
||||
return *this ;
|
||||
}
|
||||
Vector<type, size> & operator -= (const Vector<type, size> &r) {
|
||||
for (int n = 0 ; n < size ; n++) members[n] -= r.members[n];
|
||||
return *this ;
|
||||
}
|
||||
Vector<type, size> & operator *= (const type r) {
|
||||
for (int n = 0 ; n < size ; n++) members[n] *= r;
|
||||
return *this ;
|
||||
}
|
||||
Vector<type, size> & operator /= (const type r) {
|
||||
for (int n = 0 ; n < size ; n++) members[n] /= r;
|
||||
return *this ;
|
||||
}
|
||||
//!}
|
||||
//!{ Non-member operators *********************************************
|
||||
|
||||
friend bool operator < (const Vector<type,size> &a, const Vector<type,size> &b) {
|
||||
for (int n = 0 ; n < size ; n++) if (a.members[n] < b.members[n]) return true ;
|
||||
return false ;
|
||||
}
|
||||
friend bool operator > (const Vector<type,size> &a, const Vector<type,size> &b) {
|
||||
for (int n = 0 ; n < size ; n++) if (a.members[n] < b.members[n]) return false ;
|
||||
return a[n] != b[n] ;
|
||||
}
|
||||
friend bool operator == (const Vector<type,size> &a, const Vector<type,size> &b) {
|
||||
for (int n = 0 ; n < size ; n++) if (a.members[n] != b.members[n]) return false ;
|
||||
return true ;
|
||||
}
|
||||
friend bool operator != (const Vector<type,size> &a, const Vector<type,size> &b) {
|
||||
for (int n = 0 ; n < size ; n++) if (a.members[n] != b.members[n]) return true ;
|
||||
return false ;
|
||||
}
|
||||
//!}
|
||||
//!{ Vector utilities *************************************************
|
||||
|
||||
//! Normalize the vector (reduce it to 1 unit in length)
|
||||
void normalize() ;
|
||||
|
||||
//! Length of the vector
|
||||
type length(int nc = size) const ;
|
||||
|
||||
//! Dot product
|
||||
type dot (const Vector<type, size> &r) const ;
|
||||
|
||||
//! Angle in radians between two vectors
|
||||
type angle (const Vector<type, size> &r) const ;
|
||||
|
||||
//! Middle point between two points/vectors
|
||||
Vector<type, size> midpoint (const Vector<type, size> & p) const ;
|
||||
|
||||
//! Some sintactic sugar stuff
|
||||
bool isPerpendicular (Vector<type, size> &r) const { return dot(r) == 0.0f ; }
|
||||
|
||||
//! Returns true if all members are 0 (do not use operator (bool))
|
||||
bool isNull() const ;
|
||||
|
||||
private:
|
||||
|
||||
type members[size] ;
|
||||
};
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// Implementation
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
template <class type, int size>
|
||||
inline Vector<type, size> operator + (const Vector<type, size> &a, const Vector<type, size> &b)
|
||||
{
|
||||
Vector<type, size> result ;
|
||||
for (int n = 0 ; n < size ; n++)
|
||||
result.set (n, a.get(n) + b.get(n)) ;
|
||||
return result ;
|
||||
}
|
||||
|
||||
template <class type, int size>
|
||||
inline Vector<type, size> operator - (const Vector<type, size> &a, const Vector<type, size> &b)
|
||||
{
|
||||
Vector<type, size> result ;
|
||||
for (int n = 0 ; n < size ; n++)
|
||||
result.set (n, a.get(n) - b.get(n)) ;
|
||||
return result ;
|
||||
}
|
||||
|
||||
template <class type, int size>
|
||||
inline bool operator == (const Vector<type, size> &a, const Vector<type, size> &b)
|
||||
{
|
||||
for (int n = 0 ; n < size ; n++)
|
||||
if (a.members[n] != b.members[n]) return false ;
|
||||
return true ;
|
||||
}
|
||||
|
||||
template <class type, int size>
|
||||
inline bool operator != (const Vector<type, size> &a, const Vector<type, size> &b)
|
||||
{
|
||||
for (int n = 0 ; n < size ; n++)
|
||||
if (a.members[n] != b.members[n]) return true ;
|
||||
return false ;
|
||||
}
|
||||
|
||||
//! Multiply by constant
|
||||
|
||||
template <class type, int size>
|
||||
inline Vector<type, size> operator * (const Vector<type, size> &p, float c)
|
||||
{
|
||||
Vector<type, size> result ;
|
||||
for (int n = 0 ; n < size ; n++)
|
||||
result.set (n, p.get(n) * c) ;
|
||||
return result ;
|
||||
}
|
||||
|
||||
//! Divide by constant
|
||||
|
||||
template <class type, int size>
|
||||
inline Vector<type, size> operator / (const Vector<type, size> &p, float c)
|
||||
{
|
||||
Vector<type, size> result ;
|
||||
for (int n = 0 ; n < size ; n++)
|
||||
result.set (n, p.get(n) / c) ;
|
||||
return result ;
|
||||
}
|
||||
|
||||
//! Dot product
|
||||
|
||||
template <class type, int size>
|
||||
inline type Vector<type, size>::dot (const Vector<type, size> &r) const
|
||||
{
|
||||
type result = r.members[0] * members[0] ;
|
||||
for (int n = 1 ; n < size ; n++)
|
||||
result += r.members[n] * members[n] ;
|
||||
return result ;
|
||||
}
|
||||
|
||||
//! Length
|
||||
|
||||
template <class type, int size>
|
||||
inline type Vector<type, size>::length(int nc) const
|
||||
{
|
||||
type result = members[0] * members[0] ;
|
||||
for (int n = 1 ; n < nc ; n++)
|
||||
result += members[n] * members[n] ;
|
||||
return sqrt(result) ;
|
||||
}
|
||||
|
||||
//! Angle between two vectors
|
||||
|
||||
template <class type, int size>
|
||||
inline type Vector<type, size>::angle (const Vector<type, size> &r) const
|
||||
{
|
||||
return acos (dot(r) / length() / r.length()) ;
|
||||
}
|
||||
|
||||
//! Angle between two vectors
|
||||
|
||||
template <class type, int size>
|
||||
inline Vector<type,size> Vector<type, size>::midpoint (const Vector<type, size> &r) const
|
||||
{
|
||||
Vector<type,size> result ;
|
||||
for (int n = 0 ; n < size ; n++)
|
||||
result.set (n, (r.members[n] - members[n])/2 + members[n]) ;
|
||||
return result ;
|
||||
}
|
||||
|
||||
//! Normalices a vector. If it is a null vector (0, 0, 0) then it is left untouched
|
||||
|
||||
template <class type, int size>
|
||||
inline void Vector<type, size>::normalize()
|
||||
{
|
||||
float dist = length() ;
|
||||
|
||||
if (dist != 0.0f)
|
||||
{
|
||||
for (int n = 0 ; n < size ; n++)
|
||||
members[n] /= dist ;
|
||||
}
|
||||
}
|
||||
|
||||
template <class type, int size>
|
||||
inline bool Vector<type,size>::isNull() const
|
||||
{
|
||||
for (int n = 0 ; n < size ; n++)
|
||||
if (members[n] != 0) return false ;
|
||||
return true ;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
Reference in New Issue
Block a user