added everything
This commit is contained in:
130
tools/ms2dtsExporter/DTSMilkshapeMesh.cpp
Executable file
130
tools/ms2dtsExporter/DTSMilkshapeMesh.cpp
Executable 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() ;
|
||||
}
|
||||
}
|
38
tools/ms2dtsExporter/DTSMilkshapeMesh.h
Executable file
38
tools/ms2dtsExporter/DTSMilkshapeMesh.h
Executable 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
|
753
tools/ms2dtsExporter/DTSMilkshapeShape.cpp
Executable file
753
tools/ms2dtsExporter/DTSMilkshapeShape.cpp
Executable 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
|
49
tools/ms2dtsExporter/DTSMilkshapeShape.h
Executable file
49
tools/ms2dtsExporter/DTSMilkshapeShape.h
Executable 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
|
576
tools/ms2dtsExporter/DTSPlugin.cpp
Executable file
576
tools/ms2dtsExporter/DTSPlugin.cpp
Executable 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() ;
|
||||
}
|
40
tools/ms2dtsExporter/DTSPlugin.h
Executable file
40
tools/ms2dtsExporter/DTSPlugin.h
Executable 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 ;
|
||||
} ;
|
46
tools/ms2dtsExporter/changelog.txt
Executable file
46
tools/ms2dtsExporter/changelog.txt
Executable 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
|
||||
|
6
tools/ms2dtsExporter/ms2dtsExporter.def
Executable file
6
tools/ms2dtsExporter/ms2dtsExporter.def
Executable file
@ -0,0 +1,6 @@
|
||||
DESCRIPTION 'V12 Engine MilkShape Shape Exporter'
|
||||
|
||||
VERSION 1.0
|
||||
|
||||
EXPORTS
|
||||
CreatePlugIn
|
332
tools/ms2dtsExporter/msLIB/msLib.h
Executable file
332
tools/ms2dtsExporter/msLIB/msLib.h
Executable 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__ */
|
BIN
tools/ms2dtsExporter/msLIB/msModelLib.lib
Executable file
BIN
tools/ms2dtsExporter/msLIB/msModelLib.lib
Executable file
Binary file not shown.
35
tools/ms2dtsExporter/msLIB/msPlugIn.h
Executable file
35
tools/ms2dtsExporter/msLIB/msPlugIn.h
Executable 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
166
tools/ms2dtsExporter/readme.txt
Executable 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
39
tools/ms2dtsExporter/resource.h
Executable 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
148
tools/ms2dtsExporter/resource.rc
Executable 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
|
||||
|
Reference in New Issue
Block a user