Initial commit
This commit is contained in:
462
Torque/SDK/lib/dtsSDK/DTSMesh.cpp
Normal file
462
Torque/SDK/lib/dtsSDK/DTSMesh.cpp
Normal 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);
|
||||
}
|
||||
|
||||
};
|
||||
Reference in New Issue
Block a user