added everything

This commit is contained in:
Metario
2017-04-17 06:17:10 -06:00
commit 9c6ff74f19
6121 changed files with 1625704 additions and 0 deletions

View File

@ -0,0 +1,130 @@
#pragma warning ( disable: 4786 )
#include <vector>
#include <map>
#include <cmath>
#include "DTSMilkshapeMesh.h"
namespace DTS
{
// -----------------------------------------------------------------------
// Imports a Milkshape Mesh
// -----------------------------------------------------------------------
MilkshapeMesh::MilkshapeMesh (msMesh * mesh, int rootBone, float scaleFactor, bool WithMaterials) : Mesh (Mesh::T_Standard)
{
int v, n ;
int materialIndex = msMesh_GetMaterialIndex(mesh) ;
// Import vertex position and texture data
for (v = 0 ; v < msMesh_GetVertexCount(mesh) ; v++)
{
msVertex * vertex = msMesh_GetVertexAt(mesh, v) ;
msVec3 vector ;
msVertex_GetVertex (vertex, vector) ;
vector[0] *= scaleFactor ;
vector[1] *= scaleFactor ;
vector[2] *= scaleFactor ;
// Vertex weights, MS only supports one bone per vertex.
// All vertices in a skin mesh must be assigned to a bone,
// so if MS doesn't have one we'll assign it to the root.
vindex.push_back(verts.size());
int bone = msVertex_GetBoneIndex (vertex);
vbone.push_back(getVertexBone((bone >= 0)? bone: rootBone));
vweight.push_back(1.0);
// The MilkshapePoint class takes care of axis conversion
verts.push_back (MilkshapePoint(vector)) ;
// Texture coordinates
msVertex_GetTexCoords (vertex, vector) ;
tverts.push_back (Point2D(vector[0], vector[1])) ;
}
// Adjust our type. We default to a rigid mesh, but if the mesh
// is attached to more than one bone, we need to output as a skin
// mesh. Node index is managed by the getVertexBone method.
if (nodeIndex.size() > 1)
setType(T_Skin);
// Import normals (into a temporary vector)
std::vector<Point> msNormals ;
for (v = 0 ; v < msMesh_GetVertexNormalCount(mesh) ; v++)
{
msVec3 vector ;
msMesh_GetVertexNormalAt (mesh, v, vector) ;
msNormals.push_back (MilkshapePoint(vector)) ;
}
// Import primitives (as single triangles for now)
// While we're at it, use the triangle data to get per-vertex normals
std::vector<bool> vertexNormalFound (verts.size(), false) ;
normals.assign (verts.size(), Point()) ;
enormals.assign (verts.size(), '\0') ;
for (v = 0 ; v < msMesh_GetTriangleCount(mesh) ; v++)
{
msTriangle * triangle = msMesh_GetTriangleAt(mesh, v) ;
word ivertexes[3] ;
word inormals[3] ;
Primitive myTriangle ;
msTriangle_GetVertexIndices (triangle, ivertexes) ;
msTriangle_GetNormalIndices (triangle, inormals) ;
// Transform milkshape per-triangle normals to V12 per-vertex normals
// There could be many normals per vertex, interpolate them
for (n = 0 ; n < 3 ; n++)
{
if (!vertexNormalFound[ivertexes[n]])
{
vertexNormalFound[ivertexes[n]] = true ;
normals[ivertexes[n]] = msNormals[inormals[n]] ;
enormals[ivertexes[n]] = encodeNormal(msNormals[inormals[n]]) ;
}
else
{
Point midpoint = (normals[ivertexes[n]] + msNormals[inormals[n]]) / 2.0f ;
midpoint.normalize() ;
normals[ivertexes[n]] = midpoint ;
enormals[ivertexes[n]] = encodeNormal(midpoint) ;
}
}
// Create a triangle primitive for this triangle
myTriangle.firstElement = indices.size() ;
myTriangle.numElements = 3 ;
myTriangle.type = Primitive::Strip | Primitive::Indexed ;
if (WithMaterials && materialIndex >= 0)
myTriangle.type |= materialIndex ;
else
myTriangle.type |= Primitive::NoMaterial ;
indices.push_back (ivertexes[2]) ;
indices.push_back (ivertexes[1]) ;
indices.push_back (ivertexes[0]) ;
primitives.push_back (myTriangle) ;
}
// Other stuff we don't support
setFrames(1) ;
setParent(-1) ;
calculateBounds() ;
calculateCenter() ;
calculateRadius() ;
}
}

View File

@ -0,0 +1,38 @@
#ifndef __DTSMILKSHAPEMESH_H
#define __DTSMILKSHAPEMESH_H
#include "DTSShape.h"
#include "DTSQuaternion.h"
#include "msLib.h"
namespace DTS
{
//! Defines a point imported from Milkshape coordinates
struct MilkshapePoint : public Point
{
MilkshapePoint(const msVec3 p) : Point(-p[0], p[2], p[1]) {}
};
//! Defines a quaternion imported from Milkshape angles
struct MilkshapeQuaternion : public Quaternion
{
// Torque uses column vectors which means we need to flip
// the rotations
MilkshapeQuaternion(const msVec3 p) : Quaternion (p[0], -p[2], -p[1]) {}
};
//! Defines a Mesh imported from Milkshape
class MilkshapeMesh : public Mesh
{
public:
//! Create a standard mesh from a Milkshape group
MilkshapeMesh (msMesh *, int rootBone, float scaleFactor, bool WithMaterials) ;
};
}
#endif

View File

@ -0,0 +1,753 @@
#pragma warning ( disable: 4786 )
#include <windows.h>
#include <stack>
#include <string>
#include <vector>
#include <map>
#include <set>
#include <cmath>
#include <cassert>
#include "DTSShape.h"
#include "DTSBrushMesh.h"
#include "DTSMilkshapeMesh.h"
#include "DTSMilkshapeShape.h"
#include "msLib.h"
namespace DTS
{
// -----------------------------------------------------------------------
// Interpolation methods used to compute tween frames - phdana
void lerpTranslation(Point *out, Point &a, Point&b, float alpha)
{
out->x(a.x() + (b.x()-a.x()) * alpha);
out->y(a.y() + (b.y()-a.y()) * alpha);
out->z(a.z() + (b.z()-a.z()) * alpha);
}
void lerpTranslation(Point *out, Point &a, Point &b, int outFrame, int aFrame, int bFrame)
{
float alpha = (float)(outFrame - aFrame) / (float)(bFrame - aFrame);
lerpTranslation(out,a,b,alpha);
}
void lerpRotation(Quaternion *out, Quaternion &q1, Quaternion &q2, float alpha)
{
//-----------------------------------
// Calculate the cosine of the angle:
double cosOmega = q1.x() * q2.x() + q1.y() * q2.y() + q1.z() * q2.z() + q1.w() * q2.w();
//-----------------------------------
// adjust signs if necessary:
float sign2;
if ( cosOmega < 0.0 )
{
cosOmega = -cosOmega;
sign2 = -1.0f;
}
else
sign2 = 1.0f;
//-----------------------------------
// calculate interpolating coeffs:
double scale1, scale2;
if ( (1.0 - cosOmega) > 0.00001 )
{
// standard case
double omega = acos(cosOmega);
double sinOmega = sin(omega);
scale1 = sin((1.0 - alpha) * omega) / sinOmega;
scale2 = sign2 * sin(alpha * omega) / sinOmega;
}
else
{
// if quats are very close, just do linear interpolation
scale1 = 1.0 - alpha;
scale2 = sign2 * alpha;
}
//-----------------------------------
// actually do the interpolation:
out->x( float(scale1 * q1.x() + scale2 * q2.x()));
out->y( float(scale1 * q1.y() + scale2 * q2.y()));
out->z( float(scale1 * q1.z() + scale2 * q2.z()));
out->w( float(scale1 * q1.w() + scale2 * q2.w()));
}
void lerpRotation(Quaternion *out, Quaternion &a, Quaternion &b,
int outFrame, int aFrame, int bFrame)
{
float alpha = (float)(outFrame - aFrame) / (float)(bFrame - aFrame);
lerpRotation(out,a,b,alpha);
}
// -----------------------------------------------------------------------
int extractMeshFlags(char * name)
{
// Extract comma seperated flags embeded in the name. Anything after
// the ":" in the name is assumed to be flag arguments and stripped
// off the name.
int flags = 0;
char *ptr = strstr(name,":");
if (ptr)
{
*ptr = 0;
for (char *tok = strtok(ptr+1,","); tok != 0; tok = strtok(0,","))
{
// Strip lead/trailing white space
for (; isspace(*tok); tok++) ;
for (char* itr = tok + strlen(tok)-1; itr > tok && isspace(*itr); itr--)
*itr = 0;
//
if (!stricmp(tok,"billboard"))
flags |= Mesh::Billboard;
else
if (!stricmp(tok,"billboardz"))
flags |= Mesh::Billboard | Mesh::BillboardZ;
else
if (!stricmp(tok,"enormals"))
flags |= Mesh::EncodedNormals;
}
}
return flags;
}
void extractMaterialFlags(char * name, int& flags)
{
// Extract comma seperated flags embeded in the name. Anything after
// the ":" in the name is assumed to be flag arguments and stripped
// off the name.
char *ptr = strstr(name,":");
if (ptr)
{
*ptr = 0;
for (char *tok = strtok(ptr+1,","); tok != 0; tok = strtok(0,","))
{
// Strip lead/trailing white space
for (; isspace(*tok); tok++) ;
for (char* itr = tok + strlen(tok)-1; itr > tok && isspace(*itr); itr--)
*itr = 0;
if (!stricmp(tok,"add"))
flags |= Material::Additive;
else
if (!stricmp(tok,"sub"))
flags |= Material::Subtractive;
else
if (!stricmp(tok,"illum"))
flags |= Material::SelfIlluminating;
else
if (!stricmp(tok,"nomip"))
flags |= Material::NoMipMap;
else
if (!stricmp(tok,"mipzero"))
flags |= Material::MipMapZeroBorder;
}
}
}
// -----------------------------------------------------------------------
bool isBoneAnimated(msBone *bone, int start, int end)
{
// Returns true if the bone contains any key frames
// within the given time range.
int numPKeys = msBone_GetPositionKeyCount(bone);
for (int j = 0 ; j < numPKeys ; j++) {
msPositionKey * msKey = msBone_GetPositionKeyAt (bone, j);
// MS is one based, start/end 0 based..
if (msKey->fTime > start && msKey->fTime <= end)
return true;
}
int numRKeys = msBone_GetRotationKeyCount(bone);
for (int i = 0 ; i < numRKeys ; i++)
{
msRotationKey * msKey = msBone_GetRotationKeyAt (bone, i);
// MS is one based, start/end 0 based..
if (msKey->fTime > start && msKey->fTime <= end)
return true;
}
return false;
}
// -----------------------------------------------------------------------
// Imports a Milkshape Model
// -----------------------------------------------------------------------
MilkshapeShape::ImportConfig::ImportConfig ()
{
withMaterials = true ;
collisionType = C_None ;
collisionComplexity = 0.2f ;
collisionVisible = false ;
animation = true ;
reset();
}
void MilkshapeShape::ImportConfig::reset()
{
// Reset values that must be specified using opt: or seq:
scaleFactor = 0.1f ;
minimumSize = 0 ;
animationFPS = 15 ;
animationCyclic = false;
sequence.resize(0);
}
MilkshapeShape::MilkshapeShape (msModel * model, MilkshapeShape::ImportConfig config)
{
int i, j ;
char buffer[512] ;
int numBones = msModel_GetBoneCount(model) ;
int numMeshes = msModel_GetMeshCount(model) ;
int numMaterials = msModel_GetMaterialCount(model) ;
// --------------------------------------------------------
// Materials (optional)
// --------------------------------------------------------
if (config.withMaterials)
{
for (i = 0 ; i < numMaterials ; i++)
{
msMaterial * msMat = msModel_GetMaterialAt(model, i) ;
char textureName[MS_MAX_PATH+1] ;
// Check for "reserved" names first. Reserved names
// are special materials used to encode exporter options...
// a total hack, but what can you do?
msMaterial_GetName (msMat, textureName, MS_MAX_PATH);
if (!strncmp(textureName,"seq:",4) || !strncmp(textureName,"opt:",4))
continue;
// If no texture, use the material name
msMaterial_GetDiffuseTexture (msMat, textureName, MS_MAX_PATH) ;
if (!textureName[0])
{
msMaterial_GetName (msMat, textureName, MS_MAX_PATH) ;
// If no name, create one
if (!textureName[0])
strcpy (textureName, "Unnamed") ;
}
// Strip texture file extension
char * ptr = textureName + strlen(textureName) ;
while (ptr > textureName && *ptr != '.' && *ptr != '\\') ptr-- ;
if (*ptr == '.') *ptr = '\0' ;
// Strip texture file path
ptr = textureName + strlen(textureName) ;
while (ptr > textureName && *ptr != '\\') ptr-- ;
if (*ptr == '\\') memmove (textureName, ptr+1, strlen(ptr)+1) ;
// Create the material
Material mat ;
mat.name = textureName ;
mat.flags = Material::SWrap | Material::TWrap ;
mat.reflectance = materials.size() ;
mat.bump = -1 ;
mat.detail = -1 ;
mat.detailScale = 1.0f ;
// take the strength of the enviro mapping from the shininess
float shininess = msMaterial_GetShininess(msMat) / 128.0f;
if (shininess > 0.0f)
{
mat.reflection = shininess;
}
else
{
mat.flags |= Material::NeverEnvMap;
mat.reflection = 0.0f;
}
// look for tags in material name.. the tags are short because the max
// length of a material name is only 32 chars
char materialName[MS_MAX_PATH+1];
msMaterial_GetName (msMat, materialName, MS_MAX_PATH);
extractMaterialFlags(materialName, mat.flags);
// now check for transparency < 1.0
if (msMaterial_GetTransparency (msMat) < 1.0f)
mat.flags |= Material::Translucent;
materials.push_back(mat) ;
}
}
// --------------------------------------------------------
// Nodes & Bones
// --------------------------------------------------------
Node n ;
// Loop through first and import all the bones. I assume here
// that the parent joints always exist before their children.
// The Torque engine certainly expects nodes to be organized
// that way. Other parts of the code assume that Milkshape
// Joint index = Torque node index
assert(!nodes.size());
for (int bone_num = 0 ; bone_num < numBones ; bone_num++)
{
char bone_name[256];
char parent_name[256];
msBone * bone = msModel_GetBoneAt (model, bone_num) ;
msBone_GetName (bone, bone_name, 256) ;
msBone_GetParentName (bone, parent_name, 256);
// Create a node for this bone
n.parent = msModel_FindBoneByName (model, parent_name);
n.name = addName (bone_name) ;
nodes.push_back (n) ;
// Create the default position and rotation for the node
msVec3 pos ;
msVec3 rot ;
msBone_GetPosition (bone, pos) ;
msBone_GetRotation (bone, rot) ;
nodeDefTranslations.push_back(MilkshapePoint(pos) * config.scaleFactor) ;
nodeDefRotations.push_back(MilkshapeQuaternion(rot)) ;
}
// Add a default "root" node for shapes. All meshes need to
// be assigned to a node and the Root will be used to catch
// any mesh not assigned to a bone.
n.name = addName ("Root") ;
n.parent = -1;
nodes.push_back(n) ;
// Node indexes map one to one with the default rotation and
// tranlation arrays: push identity transform for the Root.
nodeDefRotations.push_back(Quaternion(0,0,0,1)) ;
nodeDefTranslations.push_back(Point(0,0,0)) ;
// --------------------------------------------------------
// Mesh objects.
// --------------------------------------------------------
Object o ;
for (i = 0 ; i < numMeshes ; i++)
{
msMesh * mesh = msModel_GetMeshAt(model, i) ;
msMesh_GetName (mesh, buffer, 510) ;
int flags = extractMeshFlags(buffer);
// Changed 01/16/2004 by Sven Knie
// Ignore meshes reserved for collision
if (!strnicmp(buffer,"Collision",9))
continue;
// added 01/16/2004 by Sven Knie
// Ignore meshes reserved for LoS collision
if (!strnicmp(buffer,"LoSCollision", 11))
continue;
// Get object struct ready. Objects are entities that
// represent renderable items. Objects can have more
// than one mesh to represent different detail levels.
o.name = addName(buffer) ;
o.numMeshes = 1 ;
o.firstMesh = meshes.size() ;
o.node = nodes.size() - 1;
// Process the raw data.
meshes.push_back(MilkshapeMesh(mesh, o.node, config.scaleFactor, config.withMaterials)) ;
Mesh& m = meshes.back();
m.setFlag(flags);
// Rigid meshes can be attached to a single node, in which
// case we need to transform the vertices into the node's
// local space.
if (m.getType() == Mesh::T_Standard)
{
o.node = m.getNodeIndex(0);
if (o.node != -1) {
// Transform the mesh into node space. The mesh vertices
// must all be relative to the bone their attached to.
Quaternion world_rot;
Point world_trans;
getNodeWorldPosRot(o.node,world_trans, world_rot);
m.translate(-world_trans);
m.rotate(world_rot.inverse());
}
}
// Skin meshes need transform information to be able to
// transform vertices into bone space (should fix the Torque
// engine to calculate these at load time).
if (m.getType() == Mesh::T_Skin)
{
for (int n = 0; n < m.getNodeIndexCount(); n++)
{
Quaternion world_rot;
Point world_trans;
getNodeWorldPosRot(m.getNodeIndex(n),world_trans, world_rot);
m.setNodeTransform(n,world_trans,world_rot);
}
}
objects.push_back(o) ;
}
// --------------------------------------------------------
// Detail levels
// Not fully supported, we'll just export all our current
// stuff as single detail level.
// --------------------------------------------------------
DetailLevel dl ;
dl.name = addName("Detail-1") ;
dl.size = 0 ; // Projected size of detail level
dl.objectDetail = 0 ;
dl.polyCount = 0 ;
dl.subshape = 0 ;
dl.maxError = -1 ;
dl.avgError = -1 ;
std::vector<Mesh>::iterator mesh_ptr ;
for (mesh_ptr = meshes.begin() ; mesh_ptr != meshes.end() ; mesh_ptr++)
dl.polyCount += mesh_ptr->getPolyCount() ;
detailLevels.push_back(dl) ;
// --------------------------------------------------------
// Collision detail levels and meshes (optional)
// --------------------------------------------------------
// Update our bounds values as we might use them to build
// a collision mesh.
calculateBounds() ;
calculateCenter() ;
calculateRadius() ;
calculateTubeRadius() ;
// Export every mesh called "Collision" as a collision mesh.
if (config.collisionType != Shape::C_None)
{
// Material for visible meshes
int meshMaterial = materials.size();
if (config.collisionVisible)
{
Material mat ;
mat.name = "Collision_Mesh" ;
mat.flags = Material::NeverEnvMap | Material::SelfIlluminating;
mat.reflectance = materials.size() ;
mat.bump = -1 ;
mat.detail = -1 ;
mat.reflection = 1.0f ;
mat.detailScale = 1.0f ;
materials.push_back(mat) ;
}
// Loop through all the meshes and extract those that will be used for collision
if (config.collisionType == Shape::C_Mesh)
{
int numCollisions = 1;
for (i = 0 ; i < numMeshes ; i++)
{
msMesh * mesh = msModel_GetMeshAt(model, i);
msMesh_GetName (mesh, buffer, 510) ;
// Changed 01/16/2004 by Sven Knie
bool colMesh = !strnicmp(buffer,"Collision", 9);
bool losMesh = !strnicmp(buffer,"LoSCollision", 11);
if (!colMesh && !losMesh)
continue;
Mesh* collmesh = new MilkshapeMesh(mesh, nodes.size() - 1, config.scaleFactor, true) ;
// Create the collision detail level
char detailName[256];
sprintf(detailName,colMesh? "Collision-%d": "LOS-%d", numCollisions++);
dl.name = addName(detailName) ;
// Changed 01/16/2004 by Sven Knie
dl.size = (float)numCollisions * (-1) ; // negativ sized detail levels are never rendered
dl.objectDetail = detailLevels.size() ;
dl.subshape = 0 ;
dl.polyCount = collmesh->getPolyCount() ;
detailLevels.push_back(dl) ;
// Create an object for the collision mesh and attach it to
// the "Root" node.
o.name = colMesh? addName("Col"): addName("LoSCol") ;
o.node = nodes.size() - 1 ;
o.firstMesh = meshes.size() ;
o.numMeshes = dl.objectDetail + 1 ;
objects.push_back(o) ;
// Create a renderable copy of the collision meshes
// for visible detail levels, or a null placeholder
for (int d = 0 ; d < dl.objectDetail ; d++)
if (config.collisionVisible)
{
meshes.push_back(*collmesh) ;
meshes[meshes.size()-1].setMaterial(meshMaterial) ;
}
else
meshes.push_back(Mesh(Mesh::T_Null)) ;
// Add the mesh to the list
meshes.push_back(*collmesh);
}
}
else
{
// Let's create the specified collision mesh type
Mesh* collmesh;
switch (config.collisionType)
{
case C_BBox:
collmesh = new BoxMesh(getBounds()) ;
break ;
case C_Cylinder:
collmesh = new CylinderMesh(getBounds(), getTubeRadius(), config.collisionComplexity) ;
break ;
default:
assert (0 && "Invalid collision mesh type") ;
}
// Create the collision detail level
dl.name = addName("Collision-1") ;
dl.size = -1 ; // -1 sized detail levels are never rendered
dl.objectDetail = detailLevels.size() ;
dl.subshape = 0 ;
dl.polyCount = collmesh->getPolyCount() ;
detailLevels.push_back(dl) ;
// Create an object for the collision mesh and attach it to
// the "Root" node.
o.name = addName("Col") ;
o.node = nodes.size() - 1 ;
o.firstMesh = meshes.size() ;
o.numMeshes = dl.objectDetail + 1 ;
objects.push_back(o) ;
// Create a renderable copy of the collision meshes
// for visible detail levels, or a null placeholder
for (int d = 0 ; d < dl.objectDetail ; d++)
if (config.collisionVisible)
{
meshes.push_back(*collmesh) ;
meshes[meshes.size()-1].setMaterial(meshMaterial) ;
}
else
meshes.push_back(Mesh(Mesh::T_Null)) ;
// Add the mesh to the list
meshes.push_back(*collmesh);
}
}
// --------------------------------------------------------
// Subshape and final stuff
// --------------------------------------------------------
// Create a subshape with everything
Subshape s ;
s.firstObject = 0 ;
s.firstNode = 0 ;
s.firstDecal = 0 ;
s.numNodes = nodes.size() ;
s.numObjects = objects.size() ;
s.numDecals = decals.size() ;
subshapes.push_back(s) ;
// Create an object state for each object (not sure about this)
ObjectState os ;
os.vis = 1.0f ;
os.frame = 0 ;
os.matFrame = 0 ;
for (i = 0 ; i < objects.size() ; i++)
objectStates.push_back(os) ;
// Recalculate bounds (they may have changed)
calculateBounds() ;
calculateCenter() ;
calculateRadius() ;
calculateTubeRadius() ;
setSmallestSize(config.minimumSize) ;
// --------------------------------------------------------
// Animation (optional)
// For each sequence, Torque wants an array of frame * nodes
// information for all nodes affected by that sequence. Node
// animation information can be translation, rotation, scale,
// visibility, material, etc.
//
// The sequence contains a "matters" array for each type of
// animation info. Each type has it's own array of frame * nodes
// which contains only the nodes affected by that type of
// information for the sequence. Since each array is NxN,
// if a node is animated on a single frame of the sequence, it
// will get an entry for every frame.
// --------------------------------------------------------
int frameCount = msModel_GetTotalFrames (model);
if (frameCount && numBones && config.animation)
{
// Process all the sequences.
for (int sc = 0; sc < config.sequence.size(); sc++)
{
MilkshapeShape::ImportConfig::Sequence& si = config.sequence[sc];
// Build the exported sequence structure
Sequence s;
s.flags = Sequence::UniformScale;
if (si.cyclic)
s.flags |= Sequence::Cyclic;
s.nameIndex = addName(si.name) ;
s.numKeyFrames = si.end - si.start;
s.duration = float(s.numKeyFrames) / si.fps;
s.baseTranslation = nodeTranslations.size() ;
s.baseRotation = nodeRotations.size();
// Count how many nodes are affected by the sequence and
// set the sequence.matter arrays to indicate which ones.
s.matters.translation.assign (nodes.size(), false);
s.matters.rotation.assign (nodes.size(), false);
int nodeCount = 0;
for (i = 0 ; i < numBones ; i++)
{
msBone * bone = msModel_GetBoneAt(model, i);
if (isBoneAnimated(bone,si.start,si.end))
{
// Milkshape seems to always produce rotation & position
// keys in pairs, so we'll just deal with them together.
s.matters.translation[i] = true;
s.matters.rotation[i] = true;
nodeCount++;
}
}
// Size arrays to hold keyframe * nodeCount
nodeTranslations.resize (nodeTranslations.size() + nodeCount * s.numKeyFrames);
nodeRotations.resize (nodeTranslations.size());
// Set the keyframe data for each affected bone. Unaffected
// bones are skipped so the final NxN array of transforms
// and rotations is "compressed", sort of. We could compress
// both the rotation and the position arrays individually,
// but MS seems to always generate the values in pairs, so
// we'll do them together. Though the msKey loops are seperate,
// just in case.
int index = 0;
for (i = 0 ; i < numBones ; i++)
{
msBone * bone = msModel_GetBoneAt(model, i) ;
if (isBoneAnimated(bone,si.start,si.end))
{
int numPKeys = msBone_GetPositionKeyCount(bone);
int numRKeys = msBone_GetRotationKeyCount(bone);
// Insert translation keys into the table.
Point *translations = &nodeTranslations[s.baseTranslation + index * s.numKeyFrames];
int lastFrame = 0;
for (j = 0 ; j < numPKeys ; j++)
{
msPositionKey * msKey = msBone_GetPositionKeyAt (bone, j);
int frame = int(msKey->fTime) - 1;
// Only want keys in the sequence range. If it's before
// our range, we'll put it into the 0 frame in case we don't
// get a key for that frame later.
if (frame >= si.end)
break;
if (frame < si.start)
frame = 0;
else
frame -= si.start;
// Store the total translation for the node and fill in
// the initial frame if this is the first key frame.
translations[frame] = nodeDefTranslations[i] +
nodeDefRotations[i].apply(MilkshapePoint(msKey->Position) * config.scaleFactor);
if (!j && frame > 0)
translations[0] = translations[frame];
// Interpolate the missing frames.
for (int f = lastFrame + 1; f < frame; f++)
lerpTranslation(&translations[f],translations[lastFrame],
translations[frame], f, lastFrame, frame);
lastFrame = frame;
}
// Duplicate the last frame to the end.
for (int t = lastFrame + 1; t < s.numKeyFrames; t++)
translations[t] = translations[lastFrame];
// Insert rotation keys into the table.
Quaternion *rotations = &nodeRotations[s.baseTranslation + index * s.numKeyFrames];
lastFrame = 0;
for (j = 0 ; j < numRKeys ; j++)
{
msRotationKey * msKey = msBone_GetRotationKeyAt (bone, j) ;
int frame = int(msKey->fTime) - 1;
// Only want keys in the sequence range. If it's before
// our range, we'll put it into the 0 frame in case we don't
// get a key for that frame later.
if (frame >= si.end)
break;
if (frame < si.start)
frame = 0;
else
frame -= si.start;
// Store the total rotation for the node and fill in
// the initial frame if this is the first key frame.
rotations[frame] = MilkshapeQuaternion(msKey->Rotation) * nodeDefRotations[i];
if (!j && frame > 0)
rotations[0] = rotations[frame];
// Interpolate the missing frames.
for (int f = lastFrame + 1; f < frame; f++)
lerpRotation(&rotations[f],rotations[lastFrame],
rotations[frame], f, lastFrame, frame);
lastFrame = frame;
}
// Duplicate the last frame to the end.
for (int r = lastFrame + 1; r < s.numKeyFrames; r++)
rotations[r] = rotations[lastFrame];
// Increment the position & rotation array index
index++;
}
}
sequences.push_back(s);
}
}
}
} // DTS namespace

View File

@ -0,0 +1,49 @@
#ifndef __DTSMILKSHAPESHAPE_H
#define __DTSMILKSHAPESHAPE_H
#include "DTSShape.h"
namespace DTS
{
class MilkshapeShape : public Shape
{
public:
//! Stores all the configuration data for the Milkshape constructor
struct ImportConfig
{
ImportConfig() ;
bool withMaterials ;
float scaleFactor ;
int minimumSize ;
int collisionType ;
float collisionComplexity ;
bool collisionVisible ;
bool animation ;
int animationFPS ;
bool animationCyclic ;
struct Sequence
{
std::string name;
int start;
int end;
bool cyclic;
int fps;
};
std::vector<Sequence> sequence;
void reset();
} ;
//! Import a milkshape mesh
MilkshapeShape (struct msModel *, ImportConfig) ;
};
}
#endif

View File

@ -0,0 +1,576 @@
#include <windows.h>
#include <commctrl.h>
#include <fstream>
#include <cstdio>
#include <cassert>
#include "resource.h"
#pragma warning ( disable: 4786 )
#include "DTSPlugin.h"
#include "DTSInterpolation.h"
using namespace DTS ;
HINSTANCE cDTSPlugin::hInstance ;
cDTSPlugin::cDTSPlugin()
{
model = 0 ;
}
const char * cDTSPlugin::GetTitle()
{
#ifdef DEBUG
return "Torque Game Engine DTS (Debug)..." ;
#else
return "Torque Game Engine DTS..." ;
#endif
}
int cDTSPlugin::GetType()
{
return cMsPlugIn::eTypeExport ;
}
// -----------------------------------------------------------------------
bool extractSequence(char * name,MilkshapeShape::ImportConfig::Sequence* seq)
{
// Seq: ambient=2-3, cyclic, fps=2
if (strncmp(name,"seq:",4))
return false;
bool named = false;
char *ptr = name+4;
for (char *tok = strtok(ptr,","); tok != 0; tok = strtok(0,","))
{
// Strip lead/trailing white space
for (; isspace(*tok); tok++);
for (char* itr = tok + strlen(tok)-1; itr > tok && isspace(*itr); itr--)
*itr = 0;
//
unsigned int fps;
char buff[256],start[50],end[50];
if (sscanf(tok,"%[a-zA-Z0-9]=%[0-9]-%[0-9]",buff,start,end) == 3)
{
seq->name = buff;
// Let the user specify start and end frames "base" 1, the
// structure requires "base" 0, and end to be one past the last
// frame.
seq->start = atoi(start) - 1;
seq->end = atoi(end);
named = true;
}
else
if (sscanf(tok,"fps=%d",&fps))
seq->fps = fps;
else
if (!strcmp(tok,"cyclic"))
seq->cyclic = true;
}
if (!named)
{
char buff[512];
sprintf(buff,"Malformed sequence material: %s",name);
MessageBox (NULL,buff,"Torque Game Engine (DTS) Exporter", MB_ICONSTOP | MB_OK) ;
}
return named;
}
bool extractOptions(char * name,MilkshapeShape::ImportConfig* config)
{
// opt: size=%d, size=%d, scale=%f, cyclic, fps=%d
if (strncmp(name,"opt:",4))
return false;
bool named = false;
char *ptr = name+4;
for (char *tok = strtok(ptr,","); tok != 0; tok = strtok(0,","))
{
// Strip lead/trailing white space
for (; isspace(*tok); tok++);
for (char* itr = tok + strlen(tok)-1; itr > tok && isspace(*itr); itr--)
*itr = 0;
//
int iv;
float fv;
if (sscanf(tok,"scale=%f",&fv))
config->scaleFactor = fv;
else
if (sscanf(tok,"size=%d",&iv))
config->minimumSize = iv;
else
if (sscanf(tok,"fps=%d",&iv))
config->animationFPS = iv;
else
if (!strcmp(tok,"cyclic"))
config->animationCyclic = true;
}
return named;
}
// --------------------------------------------------------------------------
// Settings dialog box
// --------------------------------------------------------------------------
static cDTSPlugin * currentPlugin = 0 ;
static BOOL CALLBACK dialogProc (HWND wnd, UINT msg, WPARAM wparam, LPARAM lparam)
{
assert (currentPlugin != 0) ;
return currentPlugin->settingsDialog(wnd, msg, wparam, lparam) ;
}
BOOL cDTSPlugin::settingsDialog (HWND wnd, UINT msg, WPARAM wparam, LPARAM lparam)
{
char buffer[512] ;
int i ;
switch (msg)
{
case WM_INITDIALOG:
{
savedConfig = config ;
// Initialize edit controls
sprintf (buffer, "%g", config.scaleFactor) ;
SendDlgItemMessage (wnd, IDC_FACTOR, WM_SETTEXT, 0, (LPARAM)&buffer) ;
EnableWindow (GetDlgItem(wnd, IDC_FACTOR), false) ;
sprintf (buffer, "%d", config.minimumSize) ;
SendDlgItemMessage (wnd, IDC_MINSIZE, WM_SETTEXT, 0, (LPARAM)&buffer) ;
EnableWindow (GetDlgItem(wnd, IDC_MINSIZE), false) ;
// Initialize check boxes
SendDlgItemMessage (wnd, IDC_CHECK_MATERIALS,
BM_SETCHECK, config.withMaterials, 0L) ;
SendDlgItemMessage (wnd, IDC_CHECK_COLLVISIBLE,
BM_SETCHECK, config.collisionVisible, 0L) ;
SendDlgItemMessage (wnd, IDC_CHECK_ANIMATION,
BM_SETCHECK, config.animation, 0L) ;
// Only enable the mesh option if there are meshes called "Collision"
bool collisionMesh = false;
for (i = 0 ; i < msModel_GetMeshCount(model) ; i++)
{
msMesh * mesh = msModel_GetMeshAt (model, i) ;
msMesh_GetName (mesh, buffer, 512) ;
if (!_strnicmp (buffer, "Collision", 9))
collisionMesh = true;
}
EnableWindow (GetDlgItem(wnd, IDC_COL_MESH),collisionMesh) ;
if (!collisionMesh && config.collisionType == Shape::C_Mesh)
config.collisionType = Shape::C_None;
// Initialize radio buttons
switch (config.collisionType)
{
case Shape::C_BBox:
SendDlgItemMessage (wnd, IDC_COL_BBOX, BM_SETCHECK, 1, 0L) ; break ;
case Shape::C_Cylinder:
SendDlgItemMessage (wnd, IDC_COL_CYLINDER, BM_SETCHECK, 1, 0L) ; break ;
case Shape::C_Mesh:
SendDlgItemMessage (wnd, IDC_COL_MESH, BM_SETCHECK, 1, 0L) ; break ;
default:
SendDlgItemMessage (wnd, IDC_COL_NONE, BM_SETCHECK, 1, 0L) ; break ;
}
// Disable/enable controls
switch (config.collisionType)
{
case Shape::C_Mesh:
EnableWindow (GetDlgItem(wnd, IDC_COMPLEXITY), FALSE) ;
EnableWindow (GetDlgItem(wnd, IDC_COMPLEXITYLABEL), FALSE) ;
EnableWindow (GetDlgItem(wnd, IDC_COMPLEXITYMIN), FALSE) ;
EnableWindow (GetDlgItem(wnd, IDC_COMPLEXITYMAX), FALSE) ;
EnableWindow (GetDlgItem(wnd, IDC_MESHES), TRUE) ;
break ;
case 0:
case Shape::C_BBox:
EnableWindow (GetDlgItem(wnd, IDC_COMPLEXITY), FALSE) ;
EnableWindow (GetDlgItem(wnd, IDC_COMPLEXITYLABEL), FALSE) ;
EnableWindow (GetDlgItem(wnd, IDC_COMPLEXITYMIN), FALSE) ;
EnableWindow (GetDlgItem(wnd, IDC_COMPLEXITYMAX), FALSE) ;
EnableWindow (GetDlgItem(wnd, IDC_MESHES), FALSE) ;
break ;
default:
EnableWindow (GetDlgItem(wnd, IDC_COMPLEXITY), TRUE) ;
EnableWindow (GetDlgItem(wnd, IDC_COMPLEXITYLABEL), TRUE) ;
EnableWindow (GetDlgItem(wnd, IDC_COMPLEXITYMIN), TRUE) ;
EnableWindow (GetDlgItem(wnd, IDC_COMPLEXITYMAX), TRUE) ;
EnableWindow (GetDlgItem(wnd, IDC_MESHES), FALSE) ;
break ;
}
// Animation Settings
sprintf (buffer, "%d", config.animationFPS) ;
SendDlgItemMessage (wnd, IDC_FPS, WM_SETTEXT, 0, (LPARAM)&buffer) ;
SendDlgItemMessage (wnd, IDC_CHECK_CYCLIC, BM_SETCHECK, config.animationCyclic, 0L) ;
EnableWindow (GetDlgItem(wnd, IDC_FPS), false) ;
EnableWindow (GetDlgItem(wnd, IDC_ANIMATION), false) ;
EnableWindow (GetDlgItem(wnd, IDC_CHECK_CYCLIC), false) ;
// Initialize trackbar
SendDlgItemMessage (wnd, IDC_COMPLEXITY, TBM_SETRANGE, FALSE, MAKELONG(0,10)) ;
SendDlgItemMessage (wnd, IDC_COMPLEXITY, TBM_SETPOS, TRUE, (int)(10.0f * config.collisionComplexity)) ;
// Initialize Animation Sequence list
struct {
char* name;
int width;
} columns[5] = {
{ "Name", 100 },
{ "Start", 40 },
{ "End", 40 },
{ "FPS", 40 },
{ "Cylic", 40 }
};
LVCOLUMN lvc;
lvc.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM;
for (int ic = 0; ic < 5; ic++)
{
// Columns
lvc.iSubItem = ic;
lvc.pszText = columns[ic].name;
lvc.cx = columns[ic].width;
lvc.fmt = (!ic)? LVCFMT_LEFT: LVCFMT_CENTER;
ListView_InsertColumn(GetDlgItem(wnd, IDC_SEQUENCE_LIST), ic, &lvc);
}
LVITEM lvi;
lvi.mask = LVIF_TEXT;
for (int sc = 0; sc < config.sequence.size(); sc++)
{
// List items
MilkshapeShape::ImportConfig::Sequence& si = config.sequence[sc];
lvi.iItem = sc;
lvi.iSubItem = 0;
lvi.pszText = const_cast<char*>(si.name.data());
ListView_InsertItem(GetDlgItem(wnd, IDC_SEQUENCE_LIST), &lvi);
char buffer[256];
lvi.pszText = buffer;
lvi.iSubItem = 1;
sprintf(buffer,"%d",si.start + 1);
ListView_SetItem(GetDlgItem(wnd, IDC_SEQUENCE_LIST), &lvi);
lvi.iSubItem = 2;
sprintf(buffer,"%d",si.end);
ListView_SetItem(GetDlgItem(wnd, IDC_SEQUENCE_LIST), &lvi);
lvi.iSubItem = 3;
sprintf(buffer,"%d",si.fps);
ListView_SetItem(GetDlgItem(wnd, IDC_SEQUENCE_LIST), &lvi);
lvi.iSubItem = 4;
sprintf(buffer,"%s",si.cyclic? "true": "false");
ListView_SetItem(GetDlgItem(wnd, IDC_SEQUENCE_LIST), &lvi);
}
break ;
}
case WM_COMMAND:
// Handle check boxes
if (HIWORD(wparam) == BN_CLICKED)
{
if (LOWORD(wparam) == IDC_CHECK_MATERIALS)
{
config.withMaterials =
(SendDlgItemMessage (wnd, IDC_CHECK_MATERIALS, BM_GETCHECK, 0, 0) == BST_CHECKED) ;
}
if (LOWORD(wparam) == IDC_CHECK_ANIMATION)
{
config.animation =
(SendDlgItemMessage (wnd, IDC_CHECK_ANIMATION, BM_GETCHECK, 0, 0) == BST_CHECKED) ;
}
if (LOWORD(wparam) == IDC_CHECK_CYCLIC)
{
config.animationCyclic =
(SendDlgItemMessage (wnd, IDC_CHECK_CYCLIC, BM_GETCHECK, 0, 0) == BST_CHECKED) ;
}
if (LOWORD(wparam) == IDC_CHECK_COLLVISIBLE)
{
config.collisionVisible =
(SendDlgItemMessage (wnd, IDC_CHECK_COLLVISIBLE, BM_GETCHECK, 0, 0) == BST_CHECKED) ;
}
}
// Handle radio buttons
if (HIWORD(wparam) == BN_CLICKED)
{
if (LOWORD(wparam) == IDC_COL_BBOX)
config.collisionType = Shape::C_BBox ;
if (LOWORD(wparam) == IDC_COL_CYLINDER)
config.collisionType = Shape::C_Cylinder ;
if (LOWORD(wparam) == IDC_COL_MESH)
config.collisionType = Shape::C_Mesh ;
if (LOWORD(wparam) == IDC_COL_NONE)
config.collisionType = Shape::C_None ;
// Disable/enable controls
switch (config.collisionType)
{
case Shape::C_Mesh:
EnableWindow (GetDlgItem(wnd, IDC_COMPLEXITY), FALSE) ;
EnableWindow (GetDlgItem(wnd, IDC_COMPLEXITYLABEL), FALSE) ;
EnableWindow (GetDlgItem(wnd, IDC_COMPLEXITYMIN), FALSE) ;
EnableWindow (GetDlgItem(wnd, IDC_COMPLEXITYMAX), FALSE) ;
EnableWindow (GetDlgItem(wnd, IDC_MESHES), TRUE) ;
break ;
case 0:
case Shape::C_BBox:
EnableWindow (GetDlgItem(wnd, IDC_COMPLEXITY), FALSE) ;
EnableWindow (GetDlgItem(wnd, IDC_COMPLEXITYLABEL), FALSE) ;
EnableWindow (GetDlgItem(wnd, IDC_COMPLEXITYMIN), FALSE) ;
EnableWindow (GetDlgItem(wnd, IDC_COMPLEXITYMAX), FALSE) ;
EnableWindow (GetDlgItem(wnd, IDC_MESHES), FALSE) ;
break ;
default:
EnableWindow (GetDlgItem(wnd, IDC_COMPLEXITY), TRUE) ;
EnableWindow (GetDlgItem(wnd, IDC_COMPLEXITYLABEL), TRUE) ;
EnableWindow (GetDlgItem(wnd, IDC_COMPLEXITYMIN), TRUE) ;
EnableWindow (GetDlgItem(wnd, IDC_COMPLEXITYMAX), TRUE) ;
EnableWindow (GetDlgItem(wnd, IDC_MESHES), FALSE) ;
break ;
}
}
// Handle buttons at the bottom of the dialog box
if (wparam == IDCANCEL)
{
config = savedConfig ;
EndDialog (wnd, IDCANCEL) ;
return TRUE ;
}
if (wparam == IDOK)
{
EndDialog (wnd, IDOK) ;
return TRUE ;
}
if (wparam == IDABOUT)
{
MessageBox (wnd,
"Torque Game Engine (DTS) Exporter\n\r"
"Version 1.3 \n\r"
"(C) GarageGames & Jos<6F> Luis Cebri<72>n 2001\n\r"
"____________________________________________________________\n\r\n\r"
"This is a work in progress, many DTS features are currently not yet supported.\n\r"
"Please check the www.garagegames.com web site for the latest information on this\n\r"
"exporter or the Torque engine in general.\n\r"
"\n\r"
"If you make the collision meshes visible, they are assigned a texture called\n\r"
"\"collision_mesh\". If this JPG, or PNG texture does not exists in the .DTS\n\r"
"directory, the collision mesh will appear grey in the engine.",
"Torque Game Engine (DTS) Exporter",
MB_OK | MB_ICONINFORMATION) ;
return TRUE ;
}
break ;
case WM_NOTIFY:
// Handle spin buttons
if (lparam)
{
LPNMHDR hdr = (LPNMHDR)lparam ;
if (hdr->code == UDN_DELTAPOS)
{
if (hdr->idFrom == IDC_FACTORSPIN)
{
LPNMUPDOWN delta = (LPNMUPDOWN)lparam ;
if (delta->iDelta > 0)
config.scaleFactor *= 2.0f ;
if (delta->iDelta < 0)
config.scaleFactor *= 0.5f ;
sprintf (buffer, "%g", config.scaleFactor) ;
SendDlgItemMessage (wnd, IDC_FACTOR, WM_SETTEXT, 0, (LPARAM)&buffer) ;
}
}
}
break ;
case WM_HSCROLL:
// Handle trackbar
if ((HWND)lparam == GetDlgItem(wnd, IDC_COMPLEXITY))
{
float pos = (float)SendDlgItemMessage(wnd, IDC_COMPLEXITY, TBM_GETPOS, 0, 0);
config.collisionComplexity = pos / 10.0f ;
}
break ;
}
return FALSE ;
}
// --------------------------------------------------------------------------
// Plugin entry point
// --------------------------------------------------------------------------
int cDTSPlugin::Execute (msModel * model)
{
if (!model)
return -1 ;
this->model = model ;
// Don't export an empty model
if (msModel_GetMeshCount(model) == 0)
{
MessageBox (NULL, "The model is empty. Nothing to export.",
"Torque Game Engine (DTS) Exporter", MB_ICONSTOP | MB_OK) ;
return 0 ;
}
// If there are any meshes called "Collision", use those for collision
for (int i = 0 ; i < msModel_GetMeshCount(model) ; i++)
{
char buffer[256] ;
msMesh * mesh = msModel_GetMeshAt (model, i) ;
msMesh_GetName (mesh, buffer, 256) ;
if (_strnicmp (buffer, "Collision", 9) == 0)
{
config.collisionType = Shape::C_Mesh ;
break;
}
}
// Register the common controls before use
// (it is safe to do this more than once)
INITCOMMONCONTROLSEX ic ;
ic.dwSize = sizeof(ic) ;
ic.dwICC = ICC_UPDOWN_CLASS | ICC_BAR_CLASSES ;
InitCommonControlsEx (&ic) ;
// Extract options and sequence information from the materials.
// The options are done first since they can effect the animation
// sequences and we don't want to be affected by material ordering.
int numMaterials = msModel_GetMaterialCount(model) ;
config.reset();
int i;
for (i = 0 ; i < numMaterials ; i++)
{
char name[MS_MAX_PATH+1];
msMaterial * msMat = msModel_GetMaterialAt(model, i);
msMaterial_GetName (msMat, name, MS_MAX_PATH);
extractOptions(name,&config);
}
for (i = 0 ; i < numMaterials ; i++)
{
char name[MS_MAX_PATH+1];
msMaterial * msMat = msModel_GetMaterialAt(model, i);
msMaterial_GetName (msMat, name, MS_MAX_PATH);
MilkshapeShape::ImportConfig::Sequence si;
si.fps = config.animationFPS;
si.cyclic = config.animationCyclic;
if (extractSequence(name,&si))
config.sequence.push_back(si);
}
// If there were no sequences the default is a looping ambient
// for the total timeline
if (!config.sequence.size())
{
MilkshapeShape::ImportConfig::Sequence si;
si.name = "Ambient";
si.start = 0;
si.end = msModel_GetTotalFrames (model);
si.cyclic = true;
si.fps = config.animationFPS;
config.sequence.push_back(si);
}
// Show a preferences dialog
currentPlugin = this ;
if (DialogBox (hInstance, MAKEINTRESOURCE(IDD_DIALOG), NULL, dialogProc) != IDOK)
{
currentPlugin = 0 ;
return 0 ;
}
currentPlugin = 0 ;
// Gets the file name
OPENFILENAME ofn ;
char szFile[512] = "" ;
ZeroMemory (&ofn, sizeof(ofn)) ;
ofn.lStructSize = sizeof(ofn) ;
ofn.hInstance = GetModuleHandle(NULL) ;
ofn.lpstrFilter = "DTS Files\0*.dts\0All\0*.*\0" ;
ofn.lpstrFile = szFile ;
ofn.Flags = OFN_PATHMUSTEXIST | OFN_ENABLESIZING | OFN_OVERWRITEPROMPT ;
ofn.nMaxFile = 500 ;
ofn.lpstrDefExt = "dts" ;
if (GetSaveFileName (&ofn) != 0)
{
std::ofstream file (szFile, std::ios::binary | std::ios::trunc | std::ios::out) ;
if (!file)
{
MessageBox (NULL, "Error creating the file.",
"Torque Game Engine (DTS) Exporter", MB_ICONSTOP | MB_OK) ;
return 0 ;
}
else
{
LoadCursor (hInstance, IDC_WAIT) ;
MilkshapeShape shape(model, config) ;
shape.save(file) ;
LoadCursor (hInstance, IDC_ARROW) ;
return 1 ;
}
}
return 0 ;
}
// --------------------------------------------------------------------------
// DLL entry point
// --------------------------------------------------------------------------
BOOL APIENTRY DllMain (HINSTANCE h, DWORD, LPVOID)
{
cDTSPlugin::setInstance(h) ;
return TRUE ;
}
cMsPlugIn * CreatePlugIn()
{
return new cDTSPlugin() ;
}

View File

@ -0,0 +1,40 @@
#include "msLib.h"
#include "msPlugIn.h"
#include "DTSMilkshapeShape.h"
//! Implements the Milkshape exporter plugin
using namespace DTS ;
class cDTSPlugin : public cMsPlugIn
{
public:
cDTSPlugin() ;
//! Gets the plugin type (exporter)
virtual int GetType() ;
//! Gets the plugin title ("V12 Exporter")
virtual const char * GetTitle() ;
//! Does all the work (displays the settings dialog box and does the export)
virtual int Execute (msModel * pModel) ;
//! We need the hInstance of the DLL. The WinMain function call this.
static void setInstance(HINSTANCE h) { hInstance = h ; }
//! The settings dialog procedure
BOOL settingsDialog (HWND wnd, UINT msg, WPARAM wparam, LPARAM lparam) ;
private:
static HINSTANCE hInstance ;
MilkshapeShape::ImportConfig config ;
MilkshapeShape::ImportConfig savedConfig ;
msModel * model ;
} ;

View File

@ -0,0 +1,46 @@
==============================================================================
This file contains change information for the Torque DTS file exporter
for Milkshape v1.5.8
The original version of this code was written be Jos<6F> Luis Cebri<72>n who
has graciously allowed us to integrate his code into the Torque SDK.
Jos<EFBFBD> did an awesome job of putting this tool together and the GG staff
is very gratefull for the work he's put in to it.
tg = Tim Gift
rjp = Ryan J. Parker
==============================================================================
- rjp: Moved dtsSDK from tools/ms2dtsExporter to lib/
- tg: Fixed duplicate DTS name strings
- tg: Fixed problem with sequences including incorrect bones.
- tg: Fixed incorrect sequence range display in dialog box
- tg: Fixed problem with rotations in multi-sequence animations
- tg: Added support for export options using named materials.
- tg: Added multi-sequence support using named materials.
- tg: The debug build DLL now includes the work debug in the name it exports to MS.
- tg: Added support for mesh flags. These are added to a mesh's name and are
comma delimited after a colon, for example "name: flag1,flag2". Current
flags are "Billboard", "BillboardZ", "ENormals"
- tg: Since MS doesn't allow you to shrink the grid below 1, I've changed the
default scale to 0.1
- tg: Created a new project file for the Torque SDK workspace.
- tg: Now automatically selects any mesh called "Collision" as the collision mesh.
- tg: Fixed sequence "matters" arrays to export individually (was all the same)
- tg: The animation now only includes information for affected nodes.
- tg: Simplified bone-import code (now assumes parents exist before child)
- tg: Removed extra node creation, all meshes not attached to bones are assigned
to the root node.
- tg: Changed axis orientation, Milkshape X,Y,Z = Torque -X,Z,Y
- tg: Added animation cyclic flag to export dialog box.
- tg: Fixed bounds, radius & tubeRadius to use node transforms
- tg: Got rid of unused node initialization (siblings, firstMesh, etc)
- tg: Fixed quaternion vertex rotation to be Torque compatible.
- tg: Re-organized bone/mesh management for better support of different
mesh types. Initial version supports standalone rigid meshes, or
rigid meshes attached to a bone. For a rigid mesh to be associated
with a bone, all it's vertices must be assigned to that bone.
- tg: Initial import of MilkShape exorter from Jos<6F> Luis Cebri<72>n

View File

@ -0,0 +1,6 @@
DESCRIPTION 'V12 Engine MilkShape Shape Exporter'
VERSION 1.0
EXPORTS
CreatePlugIn

View File

@ -0,0 +1,332 @@
/**********************************************************************
*
* MilkShape 3D Model Import/Export API
*
* May 10 2000, Mete Ciragan, chUmbaLum sOft
*
**********************************************************************/
#ifndef __MSLIB_H__
#define __MSLIB_H__
#ifdef MSLIB_EXPORTS
#define MSLIB_API __declspec(dllexport)
#else
#define MSLIB_API __declspec(dllimport)
#endif /* MSLIB_EXPORTS */
#ifdef WIN32
#include <pshpack1.h>
#endif /* WIN32 */
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
/**********************************************************************
*
* Constants
*
**********************************************************************/
#define MS_MAX_NAME 32
#define MS_MAX_PATH 256
/**********************************************************************
*
* Types
*
**********************************************************************/
#ifndef byte
typedef unsigned char byte;
#endif /* byte */
#ifndef word
typedef unsigned short word;
#endif /* word */
typedef float msVec4[4];
typedef float msVec3[3];
typedef float msVec2[2];
/* msFlag */
typedef enum {
eSelected = 1, eSelected2 = 2, eHidden = 4, eDirty = 8, eAveraged = 16, eUnused = 32
} msFlag;
/* msVertex */
typedef struct msVertex
{
byte nFlags;
msVec3 Vertex;
float u, v;
char nBoneIndex;
} msVertex;
/* msTriangle */
typedef struct
{
word nFlags;
word nVertexIndices[3];
word nNormalIndices[3];
msVec3 Normal;
byte nSmoothingGroup;
} msTriangle;
/* msMesh */
typedef struct msMesh
{
byte nFlags;
char szName[MS_MAX_NAME];
char nMaterialIndex;
word nNumVertices;
word nNumAllocedVertices;
msVertex* pVertices;
word nNumNormals;
word nNumAllocedNormals;
msVec3* pNormals;
word nNumTriangles;
word nNumAllocedTriangles;
msTriangle* pTriangles;
} msMesh;
/* msMaterial */
typedef struct msMaterial
{
int nFlags;
char szName[MS_MAX_NAME];
msVec4 Ambient;
msVec4 Diffuse;
msVec4 Specular;
msVec4 Emissive;
float fShininess;
float fTransparency;
char szDiffuseTexture[MS_MAX_PATH];
char szAlphaTexture[MS_MAX_PATH];
int nName;
} msMaterial;
/* msPositionKey */
typedef struct msPositionKey
{
float fTime;
msVec3 Position;
} msPositionKey;
/* msRotationKey */
typedef struct msRotationKey
{
float fTime;
msVec3 Rotation;
} msRotationKey;
/* msBone */
typedef struct msBone
{
int nFlags;
char szName[MS_MAX_NAME];
char szParentName[MS_MAX_NAME];
msVec3 Position;
msVec3 Rotation;
int nNumPositionKeys;
int nNumAllocedPositionKeys;
msPositionKey* pPositionKeys;
int nNumRotationKeys;
int nNumAllocedRotationKeys;
msRotationKey* pRotationKeys;
} msBone;
/* msModel */
typedef struct msModel
{
int nNumMeshes;
int nNumAllocedMeshes;
msMesh* pMeshes;
int nNumMaterials;
int nNumAllocedMaterials;
msMaterial* pMaterials;
int nNumBones;
int nNumAllocedBones;
msBone* pBones;
int nFrame;
int nTotalFrames;
msVec3 Position;
msVec3 Rotation;
} msModel;
/**********************************************************************
*
* MilkShape 3D Interface
*
**********************************************************************/
/**********************************************************************
* msModel
**********************************************************************/
MSLIB_API void msModel_Destroy (msModel *pModel);
MSLIB_API int msModel_GetMeshCount (msModel *pModel);
MSLIB_API int msModel_AddMesh (msModel *pModel);
MSLIB_API msMesh* msModel_GetMeshAt (msModel *pModel, int nIndex);
MSLIB_API int msModel_FindMeshByName (msModel *pModel, const char *szName);
MSLIB_API int msModel_GetMaterialCount (msModel *pModel);
MSLIB_API int msModel_AddMaterial (msModel *pModel);
MSLIB_API msMaterial* msModel_GetMaterialAt (msModel *pModel, int nIndex);
MSLIB_API int msModel_FindMaterialByName (msModel *pModel, const char *szName);
MSLIB_API int msModel_GetBoneCount (msModel *pModel);
MSLIB_API int msModel_AddBone (msModel *pModel);
MSLIB_API msBone* msModel_GetBoneAt (msModel *pModel, int nIndex);
MSLIB_API int msModel_FindBoneByName (msModel *pModel, const char *szName);
MSLIB_API int msModel_SetFrame (msModel *pModel, int nFrame);
MSLIB_API int msModel_GetFrame (msModel *pModel);
MSLIB_API int msModel_SetTotalFrames (msModel *pModel, int nTotalFrames);
MSLIB_API int msModel_GetTotalFrames (msModel *pModel);
MSLIB_API void msModel_SetPosition (msModel *pModel, msVec3 Position);
MSLIB_API void msModel_GetPosition (msModel *pModel, msVec3 Position);
MSLIB_API void msModel_SetRotation (msModel *pModel, msVec3 Rotation);
MSLIB_API void msModel_GetRotation (msModel *pModel, msVec3 Rotation);
/**********************************************************************
* msMesh
**********************************************************************/
MSLIB_API void msMesh_Destroy (msMesh *pMesh);
MSLIB_API void msMesh_SetFlags (msMesh *pMesh, byte nFlags);
MSLIB_API byte msMesh_GetFlags (msMesh *pMesh);
MSLIB_API void msMesh_SetName (msMesh *pMesh, const char *szName);
MSLIB_API void msMesh_GetName (msMesh *pMesh, char *szName, int nMaxLength);
MSLIB_API void msMesh_SetMaterialIndex (msMesh *pMesh, int nIndex);
MSLIB_API int msMesh_GetMaterialIndex (msMesh *pMesh);
MSLIB_API int msMesh_GetVertexCount (msMesh *pMesh);
MSLIB_API int msMesh_AddVertex (msMesh *pMesh);
MSLIB_API msVertex* msMesh_GetVertexAt (msMesh *pMesh, int nIndex);
MSLIB_API msVertex* msMesh_GetInterpolatedVertexAt (msMesh *pMesh, int nIndex); // NOT YET IMPLEMENTED
MSLIB_API int msMesh_GetTriangleCount (msMesh *pMesh);
MSLIB_API int msMesh_AddTriangle (msMesh *pMesh);
MSLIB_API msTriangle* msMesh_GetTriangleAt (msMesh *pMesh, int nIndex);
MSLIB_API int msMesh_GetVertexNormalCount (msMesh *pMesh);
MSLIB_API int msMesh_AddVertexNormal (msMesh *pMesh);
MSLIB_API void msMesh_SetVertexNormalAt (msMesh *pMesh, int nIndex, msVec3 Normal);
MSLIB_API void msMesh_GetVertexNormalAt (msMesh *pMesh, int nIndex, msVec3 Normal);
MSLIB_API void msMesh_GetInterpolatedVertexNormalAt (msMesh *pMesh, int nIndex, msVec3 Normal); // NOT YET IMPLEMENTED
/**********************************************************************
* msTriangle
**********************************************************************/
MSLIB_API void msTriangle_SetFlags (msTriangle* pTriangle, word nFlags);
MSLIB_API word msTriangle_GetFlags (msTriangle* pTriangle);
MSLIB_API void msTriangle_SetVertexIndices (msTriangle *pTriangle, word nIndices[]);
MSLIB_API void msTriangle_GetVertexIndices (msTriangle *pTriangle, word nIndices[]);
MSLIB_API void msTriangle_SetNormalIndices (msTriangle *pTriangle, word nNormalIndices[]);
MSLIB_API void msTriangle_GetNormalIndices (msTriangle *pTriangle, word nNormalIndices[]);
MSLIB_API void msTriangle_SetSmoothingGroup (msTriangle *pTriangle, byte nSmoothingGroup);
MSLIB_API byte msTriangle_GetSmoothingGroup (msTriangle *pTriangle);
/**********************************************************************
* msVertex
**********************************************************************/
MSLIB_API void msVertex_SetFlags (msVertex* pVertex, byte nFlags);
MSLIB_API byte msVertex_GetFlags (msVertex* pVertex);
MSLIB_API void msVertex_SetVertex (msVertex* pVertex, msVec3 Vertex);
MSLIB_API void msVertex_GetVertex (msVertex* pVertex, msVec3 Vertex);
MSLIB_API void msVertex_SetTexCoords (msVertex* pVertex, msVec2 st);
MSLIB_API void msVertex_GetTexCoords (msVertex* pVertex, msVec2 st);
MSLIB_API int msVertex_SetBoneIndex (msVertex* pVertex, int nBoneIndex);
MSLIB_API int msVertex_GetBoneIndex (msVertex* pVertex);
/**********************************************************************
* msMaterial
**********************************************************************/
MSLIB_API void msMaterial_SetName (msMaterial *pMaterial, const char *szName);
MSLIB_API void msMaterial_GetName (msMaterial *pMaterial, char *szName, int nMaxLength);
MSLIB_API void msMaterial_SetAmbient (msMaterial *pMaterial, msVec4 Ambient);
MSLIB_API void msMaterial_SetAmbient (msMaterial *pMaterial, msVec4 Ambient);
MSLIB_API void msMaterial_GetAmbient (msMaterial *pMaterial, msVec4 Ambient);
MSLIB_API void msMaterial_SetDiffuse (msMaterial *pMaterial, msVec4 Diffuse);
MSLIB_API void msMaterial_GetDiffuse (msMaterial *pMaterial, msVec4 Diffuse);
MSLIB_API void msMaterial_SetSpecular (msMaterial *pMaterial, msVec4 Specular);
MSLIB_API void msMaterial_GetSpecular (msMaterial *pMaterial, msVec4 Specular);
MSLIB_API void msMaterial_SetEmissive (msMaterial *pMaterial, msVec4 Emissive);
MSLIB_API void msMaterial_GetEmissive (msMaterial *pMaterial, msVec4 Emissive);
MSLIB_API void msMaterial_SetShininess (msMaterial *pMaterial, float fShininess);
MSLIB_API float msMaterial_GetShininess (msMaterial *pMaterial);
MSLIB_API void msMaterial_SetTransparency (msMaterial *pMaterial, float fTransparency);
MSLIB_API float msMaterial_GetTransparency (msMaterial *pMaterial);
MSLIB_API void msMaterial_SetDiffuseTexture (msMaterial *pMaterial, const char *szDiffuseTexture);
MSLIB_API void msMaterial_GetDiffuseTexture (msMaterial *pMaterial, char *szDiffuseTexture, int nMaxLength);
MSLIB_API void msMaterial_SetAlphaTexture (msMaterial *pMaterial, const char *szAlphaTexture);
MSLIB_API void msMaterial_GetAlphaTexture (msMaterial *pMaterial, char *szAlphaTexture, int nMaxLength);
/**********************************************************************
* msBone
**********************************************************************/
MSLIB_API void msBone_Destroy (msBone *pBone);
MSLIB_API void msBone_SetFlags (msBone *pBone, int nFlags);
MSLIB_API int msBone_GetFlags (msBone *pBone);
MSLIB_API void msBone_SetName (msBone *pBone, const char *szName);
MSLIB_API void msBone_GetName (msBone *pBone, char *szName, int nMaxLength);
MSLIB_API void msBone_SetParentName (msBone *pBone, const char *szParentName);
MSLIB_API void msBone_GetParentName (msBone *pBone, char *szParentName, int nMaxLength);
MSLIB_API void msBone_SetPosition (msBone *pBone, msVec3 Position);
MSLIB_API void msBone_GetPosition (msBone *pBone, msVec3 Position);
MSLIB_API void msBone_GetInterpolatedPosition (msBone *pBone, msVec3 Position); // NOT YET IMPLEMENTED
MSLIB_API void msBone_SetRotation (msBone *pBone, msVec3 Rotation);
MSLIB_API void msBone_GetRotation (msBone *pBone, msVec3 Rotation);
MSLIB_API void msBone_GetInterpolatedRotation (msBone *pBone, msVec3 Rotation); // NOT YET IMPLEMENTED
MSLIB_API int msBone_GetPositionKeyCount (msBone *pBone);
MSLIB_API int msBone_AddPositionKey (msBone *pBone, float fTime, msVec3 Position);
MSLIB_API msPositionKey* msBone_GetPositionKeyAt (msBone *pBone, int nIndex);
MSLIB_API int msBone_GetRotationKeyCount (msBone *pBone);
MSLIB_API int msBone_AddRotationKey (msBone *pBone, float fTime, msVec3 Rotation);
MSLIB_API msRotationKey* msBone_GetRotationKeyAt (msBone *pBone, int nIndex);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#ifdef WIN32
#include <poppack.h>
#endif /* WIN32 */
#endif /* __MSLIB_H__ */

Binary file not shown.

View File

@ -0,0 +1,35 @@
#ifndef __MS_PLUGIN_H__
#define __MS_PLUGIN_H__
struct msModel;
class cMsPlugIn
{
public:
enum
{
eTypeImport = 1,
eTypeExport = 2,
eTypeTool = 3,
};
public:
cMsPlugIn () {};
virtual ~cMsPlugIn () {};
public:
virtual int GetType () = 0;
virtual const char * GetTitle () = 0;
virtual int Execute (msModel* pModel) = 0;
};
typedef cMsPlugIn* (*FN_CREATE_PLUGIN)();
///cMsPlugIn *CreatePlugIn ();
#endif // __MS_PLUGIN_H__

166
tools/ms2dtsExporter/readme.txt Executable file
View File

@ -0,0 +1,166 @@
==============================================================================
This is the exporter DLL for the MilkShape 3D modeler available
from chUmbaLum sOft : //www.swissquake.ch/chumbalum-soft/
The original version of this code was written be Jos<6F> Luis Cebri<72>n who
has graciously allowed us to integrate his code into the Torque SDK.
Jos<EFBFBD> did an awesome job of putting this tool together and the GG staff
is very gratefull for the work he's put in to it.
If you look through the code, you'll notice a little complexity in the
DTS file format. A little background is in order... the dts format was
originally designed to reduce load time processing. This means that the
DTS format is almost a direct representation of how the TS engine stores
data in memory. This does reduce load times, but also ties the file
format to the run-time implementation, which is not really a good idea.
Changes in run-time implementation, and the pre-processing needed for
the run-time data, resulted in un-planned changes and re-structuring of
the DTS file format. These changes leave us with a file format which
leaves much to be desired.
To help reduce the complications involved in writing new exporters,
the MilkShape exporter is divided into a base DTS "SDK", which provides
the core support needed to deal with DTS files, and a small set of
MilkShape specific files which do the actual conversion. The long term
goal is split this DTS SDK into a seperate library to be shared between
exporter projects.
Current Functionality
---------------------
The exporter is currently in it's 1.0 "beta" phase. Which means it's
usable. Though there is much functinality to add, and several outstanding
issues. Maybe "alpha" might be more appropriate :)
- The exporter only exports diffuse texture materials.
- Multi-sequence animations
- Animation only supports bone animation (no texture, texture coor,
vertex morphing or mesh visibility)
- Support for single collision mesh
- Named nodes.
Exporter Flags & Animation Sequences
------------------------------------
Since MilkShape does not directly support a number of Torque engine features
so the tool has been extended through the use of "hacks". These are described
more fully below but essentially fall into two categories: mesh flags embeded
in the mesh's name, and specially named materials which are used to declare
animation sequences and exporter options.
Multi-Sequence Animations
-------------------------
Material with special names can be used to declare sequence information.
These materials are ignored during export and are solely used to declare
animation sequences. Sequence materials are named as follows:
seq: option, option, ...
All other properties of the material are ignored. The following options are recognized:
name=start-end This declares the name of the sequence followed by
the starting and ending key frames. This option must
exist for the sequence declaration to be valid.
fps=n The number of frames/second. This value affects the
duration and playback speed of the sequence.
cyclic Sequences are non-cyclic by default. Cyclic animations
automatically loop back to the start and never end.
Examples of valid sequence declarations:
"seq: fire=1-4"
"seq: rotate=5-8, cyclic, fps=2"
"seq: reload=9-12, fps=5"
Setting Export Options
----------------------
Materials with special names can be used to set several export options.
These materials are ignored during export and are solely used to set otoins. Option materials are named as follows:
opt: option, option, ...
All other properties of the material are ignored. The following options are recognized:
scale=n Shape scale factor, where n is a floating point value.
The default scale value is 0.1
size=n The minimum visible pixel size, default is 0
fps=n The default frames/second value for animations. Each
animation sequence may set this value, but if it's
not defined by the sequence, this default value is used.
cyclic The default animation looping flag. Each animation
sequence may set this value, but if it's not defined
by the sequence, this default value is used.
There may be more than one option material. If the same options are set on mulitple materials, then the last one in the material list is the value used.
Examples of valid material names:
"opt: fps=10, cyclic"
"opt: scale=1"
Mesh Option Flags
-----------------
Mesh may have additional flags embedded in the mesh (or group) name. The mesh name follows the following format:
name: flag, flag, ...
where the : and flags are optional. The following flags are recognized:
Billboard The mesh always faces the viewer
BillboardZ The mesh faces the viewer but is only rotated around
the mesh's Z axis.
ENormals Encodes vertex normals. This flag is deprecated and
should not be used, unless you know what your doing.
Examples of legal mesh/group names:
"box" Just called box
"leaf: Billboard" Leaf that always faces the viewer
"leaf: BillboardZ" Z axis rotated facing leaf
Meshes by defualt do not have any of these flags set.
Issues & Future Developement
----------------------------
- Split off the DTS SDK into it's own library and continue to refine
it's functionality and API.
- Triangle strips. This is probably the biggest outstanding issue.
Every mesh triangle is emitted as it's own triangle strip. This is
very bad :( Triangles need to be stripped by material. Support
should be added to the DTSMesh class.
- Detail support. Need to add support for progressive meshes. The
DTSMesh class should automatically produce decimated sub-details
based off the original art.
- DSQ exporting. DSQ files are essentially animation sequence files.
They only contain animation sequence information and can be loaded into
a shape at run-time. The same DSQ can be loaded into multiple shapes
allowing animations to be shared.
- Multiple collision meshes. The exporter currently selects the first
mesh named "collision" as a collision mesh. The torque engine actually
allows multiple collision meshes per shape and the exporter should
export all meshes named "collision" as collision meshes.
- Billboard meshes are mesh which the Torque engine automatically
rotates at run time to face the camera. There needs to be some way
of marking meshes. This could be as simple as naming them "billboard".
- Alpha BSP (or ordered) meshes. Alpha textured triangles need to be
rendered in back to front order at run-time for them to render correctly.
The dts file can contain BSP tree meshes used for this purpose.
- Better material support. There are number of material features (besides
animation) which MS doesn't support, these include multiple UV mapping
options, environment mapping flags, addative vs. blended alpha, etc.

39
tools/ms2dtsExporter/resource.h Executable file
View File

@ -0,0 +1,39 @@
//{{NO_DEPENDENCIES}}
// Microsoft Developer Studio generated include file.
// Used by resource.rc
//
#define IDABOUT 3
#define IDD_DIALOG 101
#define IDC_MINSIZE 1000
#define IDC_CHECK_MATERIALS 1001
#define IDC_FACTOR 1002
#define IDC_CHECK_COLLVISIBLE 1003
#define IDC_CHECK_JOINMESHES 1004
#define IDC_FPS 1005
#define IDC_CHECK_ANIMATION 1006
#define IDC_ANIMATION 1007
#define IDC_CHECK_CYCLIC 1008
#define IDC_COMPLEXITY 1009
#define IDC_MESHES 1010
#define IDC_DETAILSSPIN 1012
#define IDC_FACTORSPIN 1013
#define IDC_COMPLEXITYLABEL 1014
#define IDC_COMPLEXITYMIN 1015
#define IDC_COMPLEXITYMAX 1016
#define IDC_FACTORSPIN2 1017
#define IDC_SEQUENCE_LIST 1020
#define IDC_COL_NONE 1100
#define IDC_COL_BBOX 1101
#define IDC_COL_CYLINDER 1102
#define IDC_COL_MESH 1104
// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 105
#define _APS_NEXT_COMMAND_VALUE 40001
#define _APS_NEXT_CONTROL_VALUE 1021
#define _APS_NEXT_SYMED_VALUE 101
#endif
#endif

148
tools/ms2dtsExporter/resource.rc Executable file
View File

@ -0,0 +1,148 @@
//Microsoft Developer Studio generated resource script.
//
#include "resource.h"
#define APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 2 resource.
//
#include "windows.h"
#include "winres.h"
/////////////////////////////////////////////////////////////////////////////
#undef APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
// English (U.S.) resources
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
#ifdef _WIN32
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
#pragma code_page(1252)
#endif //_WIN32
/////////////////////////////////////////////////////////////////////////////
//
// Dialog
//
IDD_DIALOG DIALOG DISCARDABLE 0, 0, 368, 239
STYLE DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "Torque Game Engine (DTS) Exporter"
FONT 8, "MS Sans Serif"
BEGIN
CONTROL "&None",IDC_COL_NONE,"Button",BS_AUTORADIOBUTTON,18,20,
61,10
CONTROL "&Bounding box",IDC_COL_BBOX,"Button",BS_AUTORADIOBUTTON,
18,33,61,10
CONTROL "&Cylinder",IDC_COL_CYLINDER,"Button",BS_AUTORADIOBUTTON,
18,46,61,10
CONTROL "&Collision Meshes",IDC_COL_MESH,"Button",
BS_AUTORADIOBUTTON,18,59,69,10
CONTROL "Slider1",IDC_COMPLEXITY,"msctls_trackbar32",
TBS_AUTOTICKS | WS_TABSTOP,85,33,100,18
GROUPBOX "Other Settings",IDC_STATIC,7,141,194,62
LTEXT "Global scale factor :",IDC_STATIC,17,155,64,8
EDITTEXT IDC_FACTOR,117,153,67,12,ES_AUTOHSCROLL
LTEXT "Minimum visible size (pixels) :",IDC_STATIC,17,170,91,8
EDITTEXT IDC_MINSIZE,117,168,67,12,ES_AUTOHSCROLL
CONTROL "&Export material information",IDC_CHECK_MATERIALS,
"Button",BS_AUTOCHECKBOX | WS_TABSTOP,18,188,98,10
DEFPUSHBUTTON "OK",IDOK,13,213,50,14
PUSHBUTTON "Cancel",IDCANCEL,76,213,50,14
PUSHBUTTON "About...",IDABOUT,139,213,50,14
GROUPBOX "Collision Mesh",IDC_STATIC,7,7,194,86
LTEXT "Complexity",IDC_COMPLEXITYLABEL,117,17,35,10
LTEXT "Min",IDC_COMPLEXITYMIN,88,23,14,10
LTEXT "Max",IDC_COMPLEXITYMAX,165,22,20,10
CONTROL "Create a visible copy of the collision mesh",
IDC_CHECK_COLLVISIBLE,"Button",BS_AUTOCHECKBOX |
WS_TABSTOP,18,76,147,10
GROUPBOX "Animation Settings",IDC_STATIC,7,96,194,42
LTEXT "Frames per second :",IDC_STATIC,18,109,65,8
EDITTEXT IDC_FPS,117,107,67,12,ES_AUTOHSCROLL
CONTROL "&Export animation",IDC_CHECK_ANIMATION,"Button",
BS_AUTOCHECKBOX | WS_TABSTOP,18,122,68,10
CONTROL "&Cyclic",IDC_CHECK_CYCLIC,"Button",BS_AUTOCHECKBOX |
WS_TABSTOP,118,122,35,10
GROUPBOX "Animation Sequences",IDC_STATIC,207,7,146,197
CONTROL "List2",IDC_SEQUENCE_LIST,"SysListView32",LVS_REPORT |
WS_BORDER | WS_TABSTOP,216,17,131,181
END
/////////////////////////////////////////////////////////////////////////////
//
// DESIGNINFO
//
#ifdef APSTUDIO_INVOKED
GUIDELINES DESIGNINFO DISCARDABLE
BEGIN
IDD_DIALOG, DIALOG
BEGIN
LEFTMARGIN, 7
RIGHTMARGIN, 358
VERTGUIDE, 18
VERTGUIDE, 118
VERTGUIDE, 185
TOPMARGIN, 7
BOTTOMMARGIN, 232
END
END
#endif // APSTUDIO_INVOKED
#endif // English (U.S.) resources
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
// Spanish (Modern) resources
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ESN)
#ifdef _WIN32
LANGUAGE LANG_SPANISH, SUBLANG_SPANISH_MODERN
#pragma code_page(1252)
#endif //_WIN32
#ifdef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// TEXTINCLUDE
//
1 TEXTINCLUDE DISCARDABLE
BEGIN
"resource.h\0"
END
2 TEXTINCLUDE DISCARDABLE
BEGIN
"#include ""afxres.h""\r\n"
"\0"
END
3 TEXTINCLUDE DISCARDABLE
BEGIN
"\r\n"
"\0"
END
#endif // APSTUDIO_INVOKED
#endif // Spanish (Modern) resources
/////////////////////////////////////////////////////////////////////////////
#ifndef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 3 resource.
//
/////////////////////////////////////////////////////////////////////////////
#endif // not APSTUDIO_INVOKED