Apply scale when exporting to DTS from 3dsMax
by J "hplus" W · 11/13/2006 (4:45 pm) · 3 comments
Warning: I have not been able to test this patch very extensively, because I don't have a lot of DTS content in Max. I will update this once more users have tested it!
I have uploaded a compiled zip file (with both debug and release mode exporters) to my web site. You might want to try that, rather than typing in all these changes. The exporter is compiled for 3dsMax 8 (service pack 3). Choose only one, extract it from the zip file, and put it in your Max plugins folder.
Here is the patch:
I have uploaded a compiled zip file (with both debug and release mode exporters) to my web site. You might want to try that, rather than typing in all these changes. The exporter is compiled for 3dsMax 8 (service pack 3). Choose only one, extract it from the zip file, and put it in your Max plugins folder.
Here is the patch:
Index: ShapeMimic.cc
===================================================================
--- ShapeMimic.cc (revision 592)
+++ ShapeMimic.cc (working copy)
@@ -1090,9 +1090,7 @@
faces[j] = mesh.faces[j];
for (j=0; j<mesh.getNumVerts(); j++)
{
- verts[j].x = mesh.getVert(j).x;
- verts[j].y = mesh.getVert(j).y;
- verts[j].z = mesh.getVert(j).z;
+ verts[j] = getScaledVertex(mesh.getVert(j));
}
if (delTri)
@@ -1910,12 +1908,12 @@
Mesh & maxMesh = tri->mesh;
// get offset matrix
- Matrix3 toBounds = boundsNode->GetNodeTM(DEFAULT_TIME);
+ Matrix3 toBounds = getScaledNodeMatrixAtTime(boundsNode, DEFAULT_TIME);
zapScale(toBounds);
toBounds = Inverse(toBounds);
Matrix3 fromObj = multiResPercent<0.0f ?
- pNode->GetObjTMAfterWSM(DEFAULT_TIME) :
- getMultiRes(pNode)->multiResNode->GetObjTMAfterWSM(DEFAULT_TIME);
+ scaleNodeMatrix(pNode->GetObjTMAfterWSM(DEFAULT_TIME)) :
+ scaleNodeMatrix(getMultiRes(pNode)->multiResNode->GetObjTMAfterWSM(DEFAULT_TIME));
fromObj *= toBounds;
meshMimic->objectOffset = fromObj;
@@ -2024,8 +2022,8 @@
for (i=0; i<newWeights.size(); i++)
newWeights[i] = new SkinMimic::WeightList;
- Matrix3 skinT = skinNode->GetObjTMAfterWSM(DEFAULT_TIME);
- Matrix3 multiT = multiResNode->GetObjTMAfterWSM(DEFAULT_TIME);
+ Matrix3 skinT = scaleNodeMatrix(skinNode->GetObjTMAfterWSM(DEFAULT_TIME));
+ Matrix3 multiT = scaleNodeMatrix(multiResNode->GetObjTMAfterWSM(DEFAULT_TIME));
for (i=0; i<triMR->mesh.getNumVerts(); i++)
{
@@ -2034,8 +2032,8 @@
S32 idx = -1;
for (j=0; j<triSkin->mesh.getNumVerts(); j++)
{
- Point3F skinVert = Point3ToPoint3F(triSkin->mesh.verts[j] * skinT,skinVert);
- Point3F multiVert = Point3ToPoint3F(triMR->mesh.verts[i] * multiT,multiVert);
+ Point3F skinVert = Point3ToPoint3F(scaleNodeVector(triSkin->mesh.verts[j]) * skinT,skinVert);
+ Point3F multiVert = Point3ToPoint3F(scaleNodeVector(triMR->mesh.verts[i]) * multiT,multiVert);
Point3F delta = skinVert - multiVert;
F32 d = delta.x*delta.x + delta.y*delta.y + delta.z*delta.z;
if (d<closest)
@@ -2837,7 +2835,7 @@
// get object offset
Matrix3 objectOffset(true);
- Point3 pos = boundsNode->GetObjOffsetPos();
+ Point3 pos = scaleNodeVector(boundsNode->GetObjOffsetPos());
objectOffset.PreTranslate(pos);
Quat quat = boundsNode->GetObjOffsetRot();
PreRotateMatrix(objectOffset,quat);
@@ -2846,11 +2844,12 @@
// find min and max verts
S32 i;
- Point3F minVert = Point3ToPoint3F(maxMesh.verts[0] * objectOffset,minVert);
+ Point3F minVert;
+ minVert = Point3ToPoint3F(scaleNodeVector(maxMesh.verts[0]) * objectOffset, minVert);
Point3F maxVert = minVert;
for (i=1; i<maxMesh.numVerts; i++)
{
- Point3F v = Point3ToPoint3F(maxMesh.verts[i] * objectOffset,v);
+ Point3F v = Point3ToPoint3F(scaleNodeVector(maxMesh.verts[i]) * objectOffset,v);
minVert.setMin(v);
maxVert.setMax(v);
}
@@ -2869,7 +2868,7 @@
F32 radius2;
for (i=0; i<maxMesh.numVerts; i++)
{
- Point3F v2 = Point3ToPoint3F(maxMesh.verts[i] * objectOffset,v2);
+ Point3F v2 = Point3ToPoint3F(scaleNodeVector(maxMesh.verts[i]) * objectOffset,v2);
Point3F radial3 = v2 - pShape->center;
radius2 = mDot(radial3,radial3);
if (radius2 > maxRadius2)
@@ -2882,7 +2881,7 @@
for (i=0; i<maxMesh.numVerts; i++)
{
Point2F radial2;
- Point3 maxV = maxMesh.verts[i] * objectOffset;
+ Point3 maxV = scaleNodeVector(maxMesh.verts[i]) * objectOffset;
radial2.x = maxV.x - pShape->center.x;
radial2.y = maxV.y - pShape->center.y;
radius2 = radial2.x * radial2.x + radial2.y * radial2.y;
@@ -3115,9 +3114,12 @@
// maxParent transform).
Matrix3 m1,m2;
- m1 = pObject->maxParent->GetNodeTM(DEFAULT_TIME);
+ m1 = getScaledNodeMatrixAtTime(pObject->maxParent, DEFAULT_TIME);
+ // It may seem as if zapScale() will undo the work done by getScaled...
+ // but the getScaled... function only scales the translation, which is
+ // un-touched by zapScale().
zapScale(m1);
- m2 = pObject->maxTSParent->GetNodeTM(DEFAULT_TIME);
+ m2 = getScaledNodeMatrixAtTime(pObject->maxTSParent, DEFAULT_TIME);
zapScale(m2);
m2 = Inverse(m2);
m1 *= m2;
@@ -3491,11 +3493,11 @@
objectOffset = om->objectOffset;
else
{
- Matrix3 mat = om->inTreeNode->GetNodeTM(DEFAULT_TIME);
+ Matrix3 mat = getScaledNodeMatrixAtTime(om->inTreeNode, DEFAULT_TIME);
zapScale(mat);
mat = Inverse(mat);
- objectOffset = meshNode->GetObjTMAfterWSM(DEFAULT_TIME);
+ objectOffset = getScaledNodeMatrixAtTime(meshNode, DEFAULT_TIME);
objectOffset *= mat;
// check to see if in tree version's parent was deleted
@@ -3504,9 +3506,9 @@
if (om->maxParent != om->maxTSParent)
{
Matrix3 m1,m2;
- m1 = om->maxParent->GetNodeTM(DEFAULT_TIME);
+ m1 = getScaledNodeMatrixAtTime(om->maxParent, DEFAULT_TIME);
zapScale(m1);
- m2 = om->maxTSParent->GetNodeTM(DEFAULT_TIME);
+ m2 = getScaledNodeMatrixAtTime(om->maxTSParent, DEFAULT_TIME);
zapScale(m2);
m2 = Inverse(m2);
m1 *= m2;
@@ -3586,6 +3588,7 @@
start = tsMesh->verts.size();
tsMesh->verts.setSize(start+verts.size());
for (i=0; i<verts.size(); i++)
+ // generateNodeFaces() already scales the vectors
Point3ToPoint3F(verts[i],tsMesh->verts[i+start]);
tsMesh->numFrames++;
@@ -3727,9 +3730,9 @@
idx1 = idx2;
idx2 = tmp;
}
- verts.push_back(maxMesh.verts[idx0] * objectOffset);
- verts.push_back(maxMesh.verts[idx1] * objectOffset);
- verts.push_back(maxMesh.verts[idx2] * objectOffset);
+ verts.push_back(scaleNodeVector(maxMesh.verts[idx0]) * objectOffset);
+ verts.push_back(scaleNodeVector(maxMesh.verts[idx1]) * objectOffset);
+ verts.push_back(scaleNodeVector(maxMesh.verts[idx2]) * objectOffset);
// add smoothing group for vertices
smooth.push_back(maxFace.smGroup);
@@ -5180,7 +5183,7 @@
// does this sequence animate the bounds node, if so, add ground transform
Interval test = range;
S32 midpoint = (range.Start() + range.End()) / 2;
- boundsNode->GetNodeTM(midpoint,&test);
+ getScaledNodeMatrixAtTime(boundsNode, midpoint, &test);
if ( test.Start()==range.Start() && test.End()==range.End() )
// no ground animation
return;
@@ -5539,13 +5542,13 @@
S32 matIndex = -1;
gDecalInfo.decalNode = decalNode;
gDecalInfo.filter = NULL;
- gDecalInfo.pos = Point3ToPoint3F(decalNode->GetNodeTM(time).GetTrans(),gDecalInfo.pos);
- gDecalInfo.x = Point3ToPoint3F(decalNode->GetNodeTM(time).GetRow(0),gDecalInfo.x);
- gDecalInfo.y = Point3ToPoint3F(decalNode->GetNodeTM(time).GetRow(1),gDecalInfo.y);
- gDecalInfo.z = Point3ToPoint3F(decalNode->GetNodeTM(time).GetRow(2),gDecalInfo.z);
+ gDecalInfo.pos = Point3ToPoint3F(getScaledNodeMatrixAtTime(decalNode, time).GetTrans(),gDecalInfo.pos);
+ gDecalInfo.x = Point3ToPoint3F(getScaledNodeMatrixAtTime(decalNode, time).GetRow(0),gDecalInfo.x);
+ gDecalInfo.y = Point3ToPoint3F(getScaledNodeMatrixAtTime(decalNode, time).GetRow(1),gDecalInfo.y);
+ gDecalInfo.z = Point3ToPoint3F(getScaledNodeMatrixAtTime(decalNode, time).GetRow(2),gDecalInfo.z);
if (!decalNode->GetUserPropFloat("DECAL::MAX_ANGLE",gDecalInfo.maxAngle))
gDecalInfo.maxAngle = 90.0f;
- gDecalInfo.minCos = mCos( gDecalInfo.maxAngle * M_PI / 180.0f);
+ gDecalInfo.minCos = mCos(gDecalInfo.maxAngle * M_PI / 180.0f);
if (decalNode->GetObjectRef()->FindBaseObject()->ClassID() == Class_ID(SPHERE_CLASS_ID,0))
{
@@ -5583,7 +5586,8 @@
Vector<Point3F> normals;
Vector<U32> smooth;
cullOffTile = false; // temporarily disable this...
- generateFaces(decalNode,tri->mesh,decalNode->GetObjTMAfterWSM(time),gDecalInfo.faces,normals,gDecalInfo.verts,gDecalInfo.tverts,gDecalInfo.indices,smooth);
+ generateFaces(decalNode,tri->mesh,scaleNodeMatrix(decalNode->GetObjTMAfterWSM(time)),
+ gDecalInfo.faces,normals,gDecalInfo.verts,gDecalInfo.tverts,gDecalInfo.indices,smooth);
cullOffTile=true; // re-enable it...
dumpMask = saveDump;
if (delTri)
@@ -5655,9 +5659,10 @@
U32 idx0 = decalIndices[decalFaces[i].start+0];
U32 idx1 = decalIndices[decalFaces[i].start+1];
U32 idx2 = decalIndices[decalFaces[i].start+2];
- Point3F v10 = Point3ToPoint3F(decalVerts[idx1]-decalVerts[idx0],v10);
- Point3F v20 = Point3ToPoint3F(decalVerts[idx2]-decalVerts[idx0],v20);
- Point3F v0 = Point3ToPoint3F(decalVerts[idx0],v0);
+ // decalVerts are already scaled by generateFaces()
+ Point3F v10 = Point3ToPoint3F(decalVerts[idx1]-decalVerts[idx0], v10);
+ Point3F v20 = Point3ToPoint3F(decalVerts[idx2]-decalVerts[idx0], v20);
+ Point3F v0 = Point3ToPoint3F(decalVerts[idx0], v0);
mCross(v20,v10,&n[i]);
n[i].normalize();
k[i] = mDot(v0,n[i]);
@@ -5691,7 +5696,8 @@
bool delTri;
TriObject * tri = getTriObject(target,time,multiResVerts,delTri);
- generateFaces(target,tri->mesh,target->GetObjTMAfterWSM(time),meshFaces,normals,meshVerts,meshTVerts,meshIndices,smooth);
+ generateFaces(target,tri->mesh,scaleNodeMatrix(target->GetObjTMAfterWSM(time)),
+ meshFaces,normals,meshVerts,meshTVerts,meshIndices,smooth);
if (delTri)
delete tri;
@@ -5725,9 +5731,10 @@
U32 idx0 = meshIndices[start+0];
U32 idx1 = meshIndices[start+1];
U32 idx2 = meshIndices[start+2];
- Point3F v0 = Point3ToPoint3F(meshVerts[idx0],v0);
- Point3F v1 = Point3ToPoint3F(meshVerts[idx1],v1);
- Point3F v2 = Point3ToPoint3F(meshVerts[idx2],v2);
+ // meshVerts are pre-scaled by generateFaces()
+ Point3F v0 = Point3ToPoint3F(meshVerts[idx0], v0);
+ Point3F v1 = Point3ToPoint3F(meshVerts[idx1], v1);
+ Point3F v2 = Point3ToPoint3F(meshVerts[idx2], v2);
Point3F faceNormal;
mCross(v2-v0,v1-v0,&faceNormal);
if (mDot(faceNormal,faceNormal)>0.00000001f)
@@ -5779,7 +5786,7 @@
// RIGHT HERE!
// Get rid of tverts and generate texgen info instead
//---------------------------------------------------
- Matrix3 mat3 = dom->targetObject->maxTSParent->GetNodeTM(time);
+ Matrix3 mat3 = getScaledNodeMatrixAtTime(dom->targetObject->maxTSParent, time);
zapScale(mat3);
MatrixF invMat = convertToMatrixF(mat3,invMat);
invMat.inverse();
@@ -5861,6 +5868,7 @@
// use first face of decal to determine texgen coords...
S32 start = gDecalInfo.faces[0].start;
+ // gDecalInfo.verts are pre-scaled by generateFaces()
Point3F v0 = Point3ToPoint3F(gDecalInfo.verts[gDecalInfo.indices[start+0]],v0);
invMat.mulP(v0);
Point3F v1 = Point3ToPoint3F(gDecalInfo.verts[gDecalInfo.indices[start+1]],v1);
@@ -5945,6 +5953,7 @@
U32 idx0 = decalIndices[decalFaces[i].start+0];
U32 idx1 = decalIndices[decalFaces[i].start+1];
U32 idx2 = decalIndices[decalFaces[i].start+2];
+ // decalVerts are pre-scaled by generateFaces()
Point3F v0 = Point3ToPoint3F(decalVerts[idx0],v0);
Point3F v1 = Point3ToPoint3F(decalVerts[idx1],v1);
Point3F v2 = Point3ToPoint3F(decalVerts[idx2],v2);
@@ -6002,7 +6011,7 @@
case CylinderDecal:
{
// just like sphere decal, except project vert onto cylinder axis and use that as pos
- Point3F pt = Point3ToPoint3F(vert,pt);
+ Point3F pt = Point3ToPoint3F(vert, pt);
F32 t = mDot(pt,gDecalInfo.z) - mDot(gDecalInfo.pos,gDecalInfo.z);
a = gDecalInfo.z;
a *= t;
@@ -6019,14 +6028,14 @@
return false;
// we're on closest face (closest in the sense of pointing nearest to the same direction)
// just do plane map...
- a = Point3ToPoint3F(vert,a);
+ a = Point3ToPoint3F(vert, a);
ray = n[decalFaceIdx];
break;
}
case PlaneDecal:
{
- a = Point3ToPoint3F(vert,a);
+ a = Point3ToPoint3F(vert, a);
ray = n[decalFaceIdx];
break;
}
@@ -6060,7 +6069,7 @@
Vector<Point3F> & n = gDecalInfo.n;
Vector<F32> & k = gDecalInfo.k;
- Point3F p = Point3ToPoint3F(vert,p);
+ Point3F p = Point3ToPoint3F(vert, p);
if (n.size() && mDot(normal,n[0])<gDecalInfo.minCos)
// facing wrong way -- or too much the wrong way, anyway
@@ -6076,9 +6085,10 @@
U32 idx0 = decalIndices[decalFaces[0].start+0];
U32 idx1 = decalIndices[decalFaces[0].start+1];
U32 idx2 = decalIndices[decalFaces[0].start+2];
- Point3F v0 = Point3ToPoint3F(decalVerts[idx0],v0);
- Point3F v1 = Point3ToPoint3F(decalVerts[idx1],v1);
- Point3F v2 = Point3ToPoint3F(decalVerts[idx2],v2);
+ // decalVerts are pre-scaled by generateFaces()
+ Point3F v0 = Point3ToPoint3F(decalVerts[idx0], v0);
+ Point3F v1 = Point3ToPoint3F(decalVerts[idx1], v1);
+ Point3F v2 = Point3ToPoint3F(decalVerts[idx2], v2);
// find edges of triangle...assume not co-linear.
Point3F edge1 = v1-v0;
@@ -6588,6 +6598,7 @@
skinMesh->initialVerts.setSize(skin->verts.size());
for (j=0; j<skin->verts.size(); j++)
+ // skin->verts was scaled by generateFaces()
Point3ToPoint3F(skin->verts[j],skinMesh->initialVerts[j]);
// how many verts in the next smallest version of us
@@ -6634,9 +6645,9 @@
}
skinMesh->nodeIndex.push_back(k);
- Matrix3 boundsTransform = boundsNode->GetNodeTM( DEFAULT_TIME );
+ Matrix3 boundsTransform = getScaledNodeMatrixAtTime(boundsNode, DEFAULT_TIME);
zapScale(boundsTransform);
- Matrix3 invBoneTransform = skin->bones[j]->GetNodeTM( DEFAULT_TIME );
+ Matrix3 invBoneTransform = getScaledNodeMatrixAtTime(skin->bones[j], DEFAULT_TIME);
zapScale(invBoneTransform);
invBoneTransform = Inverse(invBoneTransform);
Index: maxUtil.cc
===================================================================
--- maxUtil.cc (revision 592)
+++ maxUtil.cc (working copy)
@@ -60,7 +60,7 @@
void getNodeTransform(INode *pNode, S32 time, Quat16 & rot, Point3F & trans, Quat16 & srot, Point3F & scale)
{
- Matrix3 nodeMat = pNode->GetNodeTM( time );
+ Matrix3 nodeMat = getScaledNodeMatrixAtTime(pNode, time);
convertToTransform(nodeMat,rot,trans,srot,scale);
}
@@ -116,7 +116,7 @@
bounds.max.set(-10E30f,-10E30f,-10E30f);
for (S32 i=0; i<mesh.numVerts; i++)
{
- Point3F v = Point3ToPoint3F(mesh.verts[i],v);
+ Point3F v = getScaledVertex(mesh.verts[i]);
bounds.min.setMin(v);
bounds.max.setMax(v);
}
@@ -202,8 +202,8 @@
// in order to avoid recomputing matrix at default time over and over, we assume that the first request
// for the matrix will be at the default time, and thereafter, we will pass that matrix in and reuse it...
- Matrix3 m1 = pNode->GetNodeTM(time);
- Matrix3 m2 = parent ? parent->GetNodeTM(time) : Matrix3(true);
+ Matrix3 m1 = getScaledNodeMatrixAtTime(pNode, time);
+ Matrix3 m2 = parent ? getScaledNodeMatrixAtTime(parent, time) : Matrix3(true);
if (time==DEFAULT_TIME)
{
decomp_affine(m1,&a10);
@@ -257,18 +257,18 @@
// multiply in any scaling on the node transform because
// the scaling will be stripped out when making a tsshape
- Matrix3 nodeMat = pNode->GetNodeTM(DEFAULT_TIME);
+ Matrix3 nodeMat = getScaledNodeMatrixAtTime(pNode, DEFAULT_TIME);
zapScale(nodeMat);
nodeMat = Inverse(nodeMat);
- mat = pNode->GetObjTMAfterWSM(DEFAULT_TIME);
+ mat = scaleNodeMatrix(pNode->GetObjTMAfterWSM(DEFAULT_TIME));
mat *= nodeMat;
}
void getDeltaTransform(INode * pNode, S32 time1, S32 time2, Quat16 & rot, Point3F & trans, Quat16 & srot, Point3F & scale)
{
- Matrix3 m1 = pNode->GetNodeTM(time2);
- Matrix3 m2 = pNode->GetNodeTM(time1);
+ Matrix3 m1 = getScaledNodeMatrixAtTime(pNode, time2);
+ Matrix3 m2 = getScaledNodeMatrixAtTime(pNode, time1);
m2 = Inverse(m2);
m1 *= m2;
convertToTransform(m1,rot,trans,srot,scale);
@@ -680,13 +680,62 @@
}
+static float gWorldScale = 1.0f;
+Matrix3 getScaledNodeMatrixAtTime(INode * node, S32 time, Interval * valid)
+{
+ Matrix3 ret = node->GetNodeTM(time, valid);
+ // Don't need to change any IDENT flags, because scaling
+ // the translation doesn't change whether translation is
+ // identity or not.
+ MRow & mr = ret.GetAddr()[3];
+ mr[0] *= gWorldScale;
+ mr[1] *= gWorldScale;
+ mr[2] *= gWorldScale;
+ return ret;
+}
+Matrix3 scaleNodeMatrix(Matrix3 const & mtx)
+{
+ Matrix3 ret = mtx;
+ // Don't need to change any IDENT flags, because scaling
+ // the translation doesn't change whether translation is
+ // identity or not.
+ MRow & mr = ret.GetAddr()[3];
+ mr[0] *= gWorldScale;
+ mr[1] *= gWorldScale;
+ mr[2] *= gWorldScale;
+ return ret;
+}
+Point3F getScaledVertex(Point3 const & v3)
+{
+ return Point3F(v3.x * gWorldScale, v3.y * gWorldScale, v3.z * gWorldScale);
+}
+Point3 scaleNodeVector(Point3 const & v3)
+{
+ return v3 * gWorldScale;
+}
+float getScaleFactor()
+{
+ return gWorldScale;
+}
+void setScaleFactor(float scale)
+{
+ gWorldScale = fabsf(scale);
+}
+
+
+
+
+
+
+
+
// deal with some unresolved externals...
#include "platform/event.h"
#include "core/bitStream.h"
Index: main.cc
===================================================================
--- main.cc (revision 592)
+++ main.cc (working copy)
@@ -430,6 +430,12 @@
}
cheapSemaphore = 1;
+ // Get the Max system scale, and convert it to meters.
+ float scale = GetMasterScale(UNITS_METERS);
+ if (scale <= 0) scale = 1;
+ SceneEnumProc::printDump(PDAlways,avar("\r\nScene scale: %.2f units per meter.\r\n", scale));
+ setScaleFactor(scale);
+
char filename[1024];
dStrcpy(filename,fname);
char * ch = filename;
Index: maxUtil.h
===================================================================
--- maxUtil.h (revision 592)
+++ maxUtil.h (working copy)
@@ -64,4 +64,44 @@
extern bool pointInPoly(const Point3F & point, const Point3F & normal, const Point3F * verts, U32 n);
+/// getScaledNodeMatrixAtTime() adjusts a given matrix for the difference
+/// in scale between Max system units and Torque game units.
+/// @param node The Max node to extract the matrix from.
+/// @param time The time at which to extract the matrix.
+/// @param valid out: the interval during which the matrix is valid.
+/// @return The matrix, with the translation part scaled.
+/// @note Use this function instead of Max GetNodeTM().
+/// @see setScaleFactor()
+extern Matrix3 getScaledNodeMatrixAtTime(INode * node, S32 time, Interval * valid = 0);
+/// Scale a given matrix translation by the set scale factor.
+/// This can be used when you're getting a matrix from some other
+/// place than GetNodeTM().
+/// @param mtx The matrix to convert.
+/// @return The converted matrix.
+extern Matrix3 scaleNodeMatrix(Matrix3 const & mtx);
+/// getScaledVertex() adjusts the given vertex to the scale used by Torque.
+/// Typically use this instead of Point3ToPoint3F().
+/// @param v3 The Max vector to scale.
+/// @return The Torque-space vector.
+/// @see setScaleFactor()
+extern Point3F getScaledVertex(Point3 const & v3);
+/// Scale the given vector by the node scale factor. This is useful
+/// when using Max vectors other than vertices, that still express
+/// positions (and thus should be scaled by world scale).
+/// @param v3 The Max vector to scale.
+/// @return The scaled position, still as a Max vector.
+extern Point3 scaleNodeVector(Point3 const & v3);
+/// getScaleFactor() returns the current scale factor in effect. For example,
+/// if the Max system unit is inches, and Torque units are meters, then the
+/// value returned would be approximately 1.0/40.0.
+/// @return The scaling factor applied to all positional data.
+extern float getScaleFactor();
+/// Set the scale factor to apply to all vertices and matrices. For example,
+/// if the system unit scale is set to centimeters, the object will be
+/// divided by 100 in each direction (to scale to meters), so set the scale
+/// factor to 1.0/100.0. This scale only works if the code properly uses
+/// getScaledNodeMatrixAtTime() and getScaledVertex().
+/// @param scale The factor to apply.
+extern void setScaleFactor(float scale);
+
#endif // _DYN_MAX_UTIL_H
#2
06/04/2009 (10:40 pm)
Looking at this: Why was this never merged into the base exporter? Building characters at system scale 1.0 meters is feakin' annoying! (And no art that you buy is going to be built like that -- inches or centimeters for the win!)
#3
Interesting addition, thanks!
09/08/2009 (5:48 pm)
Good question, I guess the planned move to Collada made them threat anything regarding the DTS exporters as low priority.Interesting addition, thanks!

Torque 3D Owner Jeff Loveless