mirror of
https://github.com/TorqueGameEngines/Torque3D.git
synced 2026-06-02 02:56:37 +00:00
final setup for assimp Added assimp importers and exporters, removed defaulting to all Added compression to tshape added dts version to tshape and cmake Update assimpShapeLoader.cpp quick fix fix previewing dsq ground work automatically export dsq files for animations Groundwork Adds the same sort of model for registering loaders and exporters as is set out on gbitmap Added a bit more safety around the assimp matrix fix to convert incoming models to torques coordinate system.
769 lines
27 KiB
C++
769 lines
27 KiB
C++
//-----------------------------------------------------------------------------
|
|
// Copyright (c) 2012 GarageGames, LLC
|
|
//
|
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
// of this software and associated documentation files (the "Software"), to
|
|
// deal in the Software without restriction, including without limitation the
|
|
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
|
// sell copies of the Software, and to permit persons to whom the Software is
|
|
// furnished to do so, subject to the following conditions:
|
|
//
|
|
// The above copyright notice and this permission notice shall be included in
|
|
// all copies or substantial portions of the Software.
|
|
//
|
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
|
// IN THE SOFTWARE.
|
|
//-----------------------------------------------------------------------------
|
|
|
|
#ifndef _TSSHAPE_H_
|
|
#define _TSSHAPE_H_
|
|
|
|
#ifndef _TSMESH_H_
|
|
#include "ts/tsMesh.h"
|
|
#endif
|
|
#ifndef _TSINTEGERSET_H_
|
|
#include "ts/tsIntegerSet.h"
|
|
#endif
|
|
#ifndef _TSTRANSFORM_H_
|
|
#include "ts/tsTransform.h"
|
|
#endif
|
|
#ifndef _TSSHAPEALLOC_H_
|
|
#include "ts/tsShapeAlloc.h"
|
|
#endif
|
|
|
|
|
|
#define DTS_EXPORTER_CURRENT_VERSION 124
|
|
|
|
class TSMaterialList;
|
|
class TSLastDetail;
|
|
class PhysicsCollision;
|
|
|
|
//
|
|
struct CollisionShapeInfo
|
|
{
|
|
S32 colNode;
|
|
PhysicsCollision *colShape;
|
|
};
|
|
|
|
/// Data storage helper for main shape buffer
|
|
struct TSShapeVertexArray
|
|
{
|
|
U8 *base;
|
|
U32 size;
|
|
bool vertexDataReady;
|
|
|
|
TSShapeVertexArray() : base(NULL), size(0), vertexDataReady(false) {}
|
|
virtual ~TSShapeVertexArray() { set(NULL, 0); }
|
|
|
|
virtual void set(void *b, U32 s, bool autoFree = true)
|
|
{
|
|
if (base && autoFree)
|
|
dFree_aligned(base);
|
|
base = reinterpret_cast<U8 *>(b);
|
|
size = s;
|
|
}
|
|
};
|
|
|
|
/// TSShape stores generic data for a 3space model.
|
|
///
|
|
/// TSShape and TSShapeInstance act in conjunction to allow the rendering and
|
|
/// manipulation of a three dimensional model.
|
|
///
|
|
/// @note The material lists are the only thing that is not loaded in TSShape.
|
|
/// instead, they are loaded in TSShapeInstance because of a former restriction
|
|
/// on the resource manager where only one file could be opened at a time.
|
|
/// The resource manager restriction has been resolved, but the material
|
|
/// lists are still loaded in TSShapeInstance.
|
|
///
|
|
/// @see TSShapeInstance for a further discussion of the 3space system.
|
|
class TSShape
|
|
{
|
|
public:
|
|
enum
|
|
{
|
|
UniformScale = BIT(0),
|
|
AlignedScale = BIT(1),
|
|
ArbitraryScale = BIT(2),
|
|
Blend = BIT(3),
|
|
Cyclic = BIT(4),
|
|
MakePath = BIT(5),
|
|
HasTranslucency= BIT(6),
|
|
AnyScale = UniformScale | AlignedScale | ArbitraryScale
|
|
};
|
|
|
|
struct ShapeFormat
|
|
{
|
|
String mName;
|
|
String mExtension;
|
|
};
|
|
|
|
struct ShapeRegistration
|
|
{
|
|
typedef bool(*ReadShape)(const Torque::Path& path, TSShape*& shape);
|
|
typedef bool(*WriteShape)(const Torque::Path& path, TSShape* shape);
|
|
Vector<ShapeFormat> extensions; ///< the list of file extensions for this Loader [these should be lower case]
|
|
Vector<ShapeFormat> export_extensions; ///< the list of file extensions for this Loader [these should be lower case]
|
|
|
|
ReadShape readFunc; ///< the read function to read from a file.
|
|
WriteShape writeFunc; ///< the write function to write to a file.
|
|
|
|
ShapeRegistration()
|
|
{
|
|
readFunc = NULL;
|
|
writeFunc = NULL;
|
|
VECTOR_SET_ASSOCIATION(extensions);
|
|
VECTOR_SET_ASSOCIATION(export_extensions);
|
|
}
|
|
};
|
|
|
|
static void sRegisterFormat(const ShapeRegistration& reg);
|
|
static const ShapeRegistration* sFindRegInfo(const String& extension, bool exporting = false);
|
|
static Vector<ShapeRegistration> sRegistrations;
|
|
|
|
/// Nodes hold the transforms in the shape's tree. They are the bones of the skeleton.
|
|
struct Node
|
|
{
|
|
S32 nameIndex;
|
|
S32 parentIndex;
|
|
|
|
// computed at runtime
|
|
S32 firstObject;
|
|
S32 firstChild;
|
|
S32 nextSibling;
|
|
};
|
|
|
|
/// Objects hold renderable items (in particular meshes).
|
|
///
|
|
/// Each object has a number of meshes associated with it.
|
|
/// Each mesh corresponds to a different detail level.
|
|
///
|
|
/// meshIndicesIndex points to numMeshes consecutive indices
|
|
/// into the meshList and meshType vectors. It indexes the
|
|
/// meshIndexList vector (meshIndexList is merely a clearinghouse
|
|
/// for the object's mesh lists). Some indices may correspond to
|
|
/// no mesh -- which means no mesh will be drawn for the part for
|
|
/// the given detail level. See comments on the meshIndexList
|
|
/// for how null meshes are coded.
|
|
///
|
|
/// @note Things are stored this way so that there are no pointers.
|
|
/// This makes serialization to disk dramatically simpler.
|
|
struct Object
|
|
{
|
|
S32 nameIndex;
|
|
S32 numMeshes;
|
|
S32 startMeshIndex; ///< Index into meshes array.
|
|
S32 nodeIndex;
|
|
|
|
// computed at load
|
|
S32 nextSibling;
|
|
S32 firstDecal; // DEPRECATED
|
|
};
|
|
|
|
/// A Sequence holds all the information necessary to perform a particular animation (sequence).
|
|
///
|
|
/// Sequences index a range of keyframes. Keyframes are assumed to be equally spaced in time.
|
|
///
|
|
/// Each node and object is either a member of the sequence or not. If not, they are set to
|
|
/// default values when we switch to the sequence unless they are members of some other active sequence.
|
|
/// Blended sequences "add" a transform to the current transform of a node. Any object animation of
|
|
/// a blended sequence over-rides any existing object state. Blended sequences are always
|
|
/// applied after non-blended sequences.
|
|
struct Sequence
|
|
{
|
|
S32 nameIndex;
|
|
S32 numKeyframes;
|
|
F32 duration;
|
|
S32 baseRotation;
|
|
S32 baseTranslation;
|
|
S32 baseScale;
|
|
S32 baseObjectState;
|
|
S32 baseDecalState; // DEPRECATED
|
|
S32 firstGroundFrame;
|
|
S32 numGroundFrames;
|
|
S32 firstTrigger;
|
|
S32 numTriggers;
|
|
F32 toolBegin;
|
|
|
|
/// @name Bitsets
|
|
/// These bitsets code whether this sequence cares about certain aspects of animation
|
|
/// e.g., the rotation, translation, or scale of node transforms,
|
|
/// or the visibility, frame or material frame of objects.
|
|
/// @{
|
|
|
|
TSIntegerSet rotationMatters; ///< Set of nodes
|
|
TSIntegerSet translationMatters; ///< Set of nodes
|
|
TSIntegerSet scaleMatters; ///< Set of nodes
|
|
TSIntegerSet visMatters; ///< Set of objects
|
|
TSIntegerSet frameMatters; ///< Set of objects
|
|
TSIntegerSet matFrameMatters; ///< Set of objects
|
|
/// @}
|
|
|
|
S32 priority;
|
|
U32 flags;
|
|
U32 dirtyFlags; ///< determined at load time
|
|
|
|
/// @name Source Data
|
|
/// Store some information about where the sequence data came from (used by
|
|
/// TSShapeConstructor and the Shape Editor)
|
|
/// @{
|
|
struct SeqSourceData
|
|
{
|
|
String from; // The source sequence (ie. a DSQ file)
|
|
S32 start; // The first frame in the source sequence
|
|
S32 end; // The last frame in the source sequence
|
|
S32 total; // The total number of frames in the source sequence
|
|
String blendSeq; // The blend reference sequence
|
|
S32 blendFrame; // The blend reference frame
|
|
SeqSourceData() : from("\t"), start(0), end(0), total(0), blendSeq(""), blendFrame(0) { }
|
|
} sourceData;
|
|
|
|
/// @name Flag Tests
|
|
/// Each of these tests a different flag against the object's flag list
|
|
/// to determine the attributes of the given object.
|
|
/// @{
|
|
|
|
bool testFlags(U32 comp) const { return (flags&comp)!=0; }
|
|
bool animatesScale() const { return testFlags(AnyScale); }
|
|
bool animatesUniformScale() const { return testFlags(UniformScale); }
|
|
bool animatesAlignedScale() const { return testFlags(AlignedScale); }
|
|
bool animatesArbitraryScale() const { return testFlags(ArbitraryScale); }
|
|
bool isBlend() const { return testFlags(Blend); }
|
|
bool isCyclic() const { return testFlags(Cyclic); }
|
|
bool makePath() const { return testFlags(MakePath); }
|
|
/// @}
|
|
|
|
/// @name IO
|
|
/// @{
|
|
|
|
void read(Stream *, bool readNameIndex = true);
|
|
void write(Stream *, bool writeNameIndex = true) const;
|
|
/// @}
|
|
};
|
|
|
|
/// Describes state of an individual object. Includes everything in an object that can be
|
|
/// controlled by animation.
|
|
struct ObjectState
|
|
{
|
|
F32 vis;
|
|
S32 frameIndex;
|
|
S32 matFrameIndex;
|
|
};
|
|
|
|
/// When time on a sequence advances past a certain point, a trigger takes effect and changes
|
|
/// one of the state variables to on or off. (State variables found in TSShapeInstance::mTriggerStates)
|
|
struct Trigger
|
|
{
|
|
enum TriggerStates
|
|
{
|
|
StateOn = BIT(31),
|
|
InvertOnReverse = BIT(30),
|
|
StateMask = BIT(30)-1
|
|
};
|
|
|
|
U32 state; ///< One of TriggerStates
|
|
F32 pos;
|
|
};
|
|
|
|
/// Details are used for render detail selection.
|
|
///
|
|
/// As the projected size of the shape changes,
|
|
/// a different node structure can be used (subShape) and a different objectDetail can be selected
|
|
/// for each object drawn. Either of these two parameters can also stay constant, but presumably
|
|
/// not both. If size is negative then the detail level will never be selected by the standard
|
|
/// detail selection process. It will have to be selected by name. Such details are "utility
|
|
/// details" because they exist to hold data (node positions or collision information) but not
|
|
/// normally to be drawn. By default there will always be a "Ground" utility detail.
|
|
///
|
|
/// Note that this struct should always be 32bit aligned
|
|
/// as its required by assembleShape/disassembleShape.
|
|
struct Detail
|
|
{
|
|
S32 nameIndex;
|
|
S32 subShapeNum;
|
|
S32 objectDetailNum;
|
|
F32 size;
|
|
F32 averageError;
|
|
F32 maxError;
|
|
S32 polyCount;
|
|
|
|
/// These values are new autobillboard settings stored
|
|
/// as part of the Detail struct in version 26 and above.
|
|
/// @{
|
|
|
|
S32 bbDimension; ///< The size of the autobillboard image.
|
|
S32 bbDetailLevel; ///< The detail to render as the autobillboard.
|
|
U32 bbEquatorSteps; ///< The number of autobillboard images to capture around the equator.
|
|
U32 bbPolarSteps; ///< The number of autobillboard images to capture along the pole.
|
|
F32 bbPolarAngle; ///< The angle in radians at which the top/bottom autobillboard images should be displayed.
|
|
U32 bbIncludePoles; ///< If non-zero then top and bottom images are generated for the autobillboard.
|
|
|
|
/// @}
|
|
};
|
|
|
|
/// @name Collision Accelerators
|
|
///
|
|
/// For speeding up buildpolylist and support calls.
|
|
/// @{
|
|
struct ConvexHullAccelerator {
|
|
S32 numVerts;
|
|
Point3F* vertexList;
|
|
Point3F* normalList;
|
|
U8** emitStrings;
|
|
};
|
|
ConvexHullAccelerator* getAccelerator(S32 dl);
|
|
/// @}
|
|
|
|
|
|
/// @name Shape Vector Data
|
|
/// @{
|
|
|
|
Vector<Node> nodes;
|
|
Vector<Object> objects;
|
|
Vector<ObjectState> objectStates;
|
|
Vector<S32> subShapeFirstNode;
|
|
Vector<S32> subShapeFirstObject;
|
|
Vector<S32> detailFirstSkin;
|
|
Vector<S32> subShapeNumNodes;
|
|
Vector<S32> subShapeNumObjects;
|
|
Vector<Detail> details;
|
|
Vector<Quat16> defaultRotations;
|
|
Vector<Point3F> defaultTranslations;
|
|
|
|
/// @}
|
|
|
|
/// These are set up at load time, but memory is allocated along with loaded data
|
|
/// @{
|
|
|
|
Vector<S32> subShapeFirstTranslucentObject;
|
|
Vector<TSMesh*> meshes;
|
|
|
|
/// @}
|
|
|
|
/// @name Alpha Vectors
|
|
/// these vectors describe how to transition between detail
|
|
/// levels using alpha. "alpha-in" next detail as intraDL goes
|
|
/// from alphaIn+alphaOut to alphaOut. "alpha-out" current
|
|
/// detail level as intraDL goes from alphaOut to 0.
|
|
/// @note
|
|
/// - intraDL is at 1 when if shape were any closer to us we'd be at dl-1
|
|
/// - intraDL is at 0 when if shape were any farther away we'd be at dl+1
|
|
/// @{
|
|
|
|
Vector<F32> alphaIn;
|
|
Vector<F32> alphaOut
|
|
;
|
|
/// @}
|
|
|
|
/// @name Resizeable vectors
|
|
/// @{
|
|
|
|
Vector<Sequence> sequences;
|
|
Vector<Quat16> nodeRotations;
|
|
Vector<Point3F> nodeTranslations;
|
|
Vector<F32> nodeUniformScales;
|
|
Vector<Point3F> nodeAlignedScales;
|
|
Vector<Quat16> nodeArbitraryScaleRots;
|
|
Vector<Point3F> nodeArbitraryScaleFactors;
|
|
Vector<Quat16> groundRotations;
|
|
Vector<Point3F> groundTranslations;
|
|
Vector<Trigger> triggers;
|
|
Vector<TSLastDetail*> billboardDetails;
|
|
Vector<ConvexHullAccelerator*> detailCollisionAccelerators;
|
|
Vector<String> names;
|
|
|
|
/// @}
|
|
|
|
TSMaterialList * materialList;
|
|
|
|
/// @name Bounding
|
|
/// @{
|
|
|
|
F32 mRadius;
|
|
F32 tubeRadius;
|
|
Point3F center;
|
|
Box3F mBounds;
|
|
|
|
/// @}
|
|
|
|
// various...
|
|
U32 mExporterVersion;
|
|
F32 mSmallestVisibleSize; ///< Computed at load time from details vector.
|
|
S32 mSmallestVisibleDL; ///< @see mSmallestVisibleSize
|
|
S32 mReadVersion; ///< File version that this shape was read from.
|
|
U32 mFlags; ///< hasTranslucancy
|
|
U32 data; ///< User-defined data storage.
|
|
|
|
/// If enabled detail selection will use the
|
|
/// legacy screen error method for lod.
|
|
/// @see setDetailFromScreenError
|
|
bool mUseDetailFromScreenError;
|
|
|
|
// TODO: This would be nice as Tuple<>
|
|
struct LodPair
|
|
{
|
|
S8 level; // -1 to 128
|
|
U8 intra; // encoded 0 to 1
|
|
|
|
inline void set( S32 dl, F32 intraDL )
|
|
{
|
|
level = (S8)dl;
|
|
intra = (S8)( intraDL * 255.0f );
|
|
}
|
|
|
|
inline void get( S32 &dl, F32 &intraDL )
|
|
{
|
|
dl = level;
|
|
intraDL = (F32)intra / 255.0f;
|
|
}
|
|
};
|
|
|
|
/// The lod lookup table where we mark down the detail
|
|
/// level and intra-detail level for each pixel size.
|
|
Vector<LodPair> mDetailLevelLookup;
|
|
|
|
/// The GFX vertex format for all detail meshes in the shape.
|
|
/// @see initVertexFeatures()
|
|
GFXVertexFormat mVertexFormat;
|
|
TSBasicVertexFormat mBasicVertexFormat;
|
|
U32 mVertexSize;
|
|
|
|
S8* mShapeData;
|
|
U32 mShapeDataSize;
|
|
|
|
|
|
// Processed vertex data
|
|
TSShapeVertexArray mShapeVertexData;
|
|
TSVertexBufferHandle mShapeVertexBuffer;
|
|
GFXPrimitiveBufferHandle mShapeVertexIndices;
|
|
|
|
bool mSequencesConstructed;
|
|
bool mNeedReinit;
|
|
|
|
|
|
// shape class has few methods --
|
|
// just constructor/destructor, io, and lookup methods
|
|
|
|
// constructor/destructor
|
|
TSShape();
|
|
~TSShape();
|
|
void compressionKey(U8* keyOut, U32 keyLen);
|
|
void xorBufferAtOffset(void* data, U32 byteCount, U32 startOffset, const U8* key, U32 keyLen);
|
|
void init();
|
|
void initMaterialList(); ///< you can swap in a new material list, but call this if you do
|
|
void finalizeEditable();
|
|
bool preloadMaterialList(const Torque::Path &path); ///< called to preload and validate the materials in the mat list
|
|
|
|
void setupBillboardDetails( const String &cachePath );
|
|
|
|
void setupBillboardDetails(const String& cachePath, const String& diffsePath, const String& normalPath);
|
|
|
|
/// Inits object list (no geometry buffers)
|
|
void initObjects();
|
|
|
|
/// Initializes the main vertex buffer
|
|
void initVertexBuffers();
|
|
|
|
/// Loads shape vertex data into specified buffer
|
|
void getVertexBuffer(TSVertexBufferHandle &vb, GFXBufferType bufferType);
|
|
|
|
/// Called from init() to calcuate the GFX vertex features for
|
|
/// all detail meshes in the shape.
|
|
void initVertexFeatures();
|
|
|
|
/// Inits basic buffer pointers on load
|
|
void initVertexBufferPointers();
|
|
|
|
bool getSequencesConstructed() const { return mSequencesConstructed; }
|
|
void setSequencesConstructed(const bool c) { mSequencesConstructed = c; }
|
|
|
|
/// @name Lookup Animation Info
|
|
/// indexed by keyframe number and offset (which object/node/decal
|
|
/// of the animated objects/nodes/decals you want information for).
|
|
/// @{
|
|
|
|
QuatF & getRotation(const Sequence & seq, S32 keyframeNum, S32 rotNum, QuatF *) const;
|
|
const Point3F & getTranslation(const Sequence & seq, S32 keyframeNum, S32 tranNum) const;
|
|
F32 getUniformScale(const Sequence & seq, S32 keyframeNum, S32 scaleNum) const;
|
|
const Point3F & getAlignedScale(const Sequence & seq, S32 keyframeNum, S32 scaleNum) const;
|
|
TSScale & getArbitraryScale(const Sequence & seq, S32 keyframeNum, S32 scaleNum, TSScale *) const;
|
|
const ObjectState & getObjectState(const Sequence & seq, S32 keyframeNum, S32 objectNum) const;
|
|
/// @}
|
|
|
|
/// build LOS collision detail
|
|
void computeAccelerator(S32 dl);
|
|
bool buildConvexHull(S32 dl) const;
|
|
void computeBounds(S32 dl, Box3F & bounds) const; // uses default transforms to compute bounding box around a detail level
|
|
// see like named method on shapeInstance if you want to use animated transforms
|
|
|
|
/// Used to find collision detail meshes in the DTS.
|
|
///
|
|
/// @param useVisibleMesh If true return the highest visible detail level.
|
|
/// @param outDetails The output detail index vector.
|
|
/// @param outLOSDetails The optional output LOS detail vector.
|
|
///
|
|
void findColDetails(bool useVisibleMesh, Vector<S32>* outDetails, Vector<S32>* outLOSDetails, S32 specifiedLOD = 0 ) const;
|
|
|
|
/// Builds a physics collision shape at the requested scale.
|
|
///
|
|
/// If using the visible mesh one or more triangle meshes are created
|
|
/// from the first visible detail level.
|
|
///
|
|
/// If using collision meshes we look for mesh names prefixed with the
|
|
/// following hints:
|
|
//
|
|
/// "colbox"
|
|
/// "colsphere"
|
|
/// "colcapsule"
|
|
/// "colmesh"
|
|
///
|
|
/// In the case of the primitives the mesh bounding box is used to generate
|
|
/// a box, sphere, or capsule collision shape. The "colmesh" will create a
|
|
/// concave triangle mesh for collision.
|
|
///
|
|
/// Any other named collision shape is interpreted as a regular convex hull.
|
|
///
|
|
/// @return The collision object or NULL if no collision data could be generated.
|
|
///
|
|
PhysicsCollision* buildColShape( bool useVisibleMesh, const Point3F &scale );
|
|
|
|
/// Like buildColShape except we build one PhysicsCollision object per
|
|
/// collision node.
|
|
///
|
|
/// Results are returned by filling in the CollisionShapeInfo Vector, which also
|
|
/// specifies the collision node index for each PhysicsCollision built.
|
|
///
|
|
void buildColShapes( bool useVisibleMesh, const Point3F &scale, Vector< CollisionShapeInfo > *list );
|
|
|
|
/// For internal use.
|
|
PhysicsCollision* _buildColShapes( bool useVisibleMesh, const Point3F &scale, Vector< CollisionShapeInfo > *list, bool perMesh );
|
|
|
|
/// @name Lookup Methods
|
|
/// @{
|
|
|
|
/// Returns index into the name vector that equals the passed name.
|
|
S32 findName( const String &name ) const;
|
|
|
|
/// Returns name string at the passed name vector index.
|
|
const String& getName( S32 nameIndex ) const;
|
|
|
|
/// Returns name string for mesh at the passed index.
|
|
const String& getMeshName( S32 meshIndex ) const;
|
|
|
|
/// Returns name string for node at the passed index.
|
|
const String& getNodeName( S32 nodeIndex ) const;
|
|
|
|
/// Returns name string for sequence at the passed index.
|
|
const String& getSequenceName( S32 seqIndex ) const;
|
|
|
|
S32 getTargetCount() const;
|
|
const String& getTargetName( S32 mapToNameIndex ) const;
|
|
|
|
S32 findNode(S32 nameIndex) const;
|
|
S32 findNode(const String &name) const { return findNode(findName(name)); }
|
|
|
|
S32 findObject(S32 nameIndex) const;
|
|
S32 findObject(const String &name) const { return findObject(findName(name)); }
|
|
|
|
S32 findDetail(S32 nameIndex) const;
|
|
S32 findDetail(const String &name) const { return findDetail(findName(name)); }
|
|
S32 findDetailBySize(S32 size) const;
|
|
|
|
S32 findSequence(S32 nameIndex) const;
|
|
S32 findSequence(const String &name) const { return findSequence(findName(name)); }
|
|
|
|
S32 getSubShapeForNode(S32 nodeIndex);
|
|
S32 getSubShapeForObject(S32 objIndex);
|
|
void getSubShapeDetails(S32 subShapeIndex, Vector<S32>& validDetails);
|
|
|
|
void getNodeWorldTransform(S32 nodeIndex, MatrixF* mat) const;
|
|
void getNodeKeyframe(S32 nodeIndex, const TSShape::Sequence& seq, S32 keyframe, MatrixF* mat) const;
|
|
void getNodeObjects(S32 nodeIndex, Vector<S32>& nodeObjects);
|
|
void getNodeChildren(S32 nodeIndex, Vector<S32>& nodeChildren);
|
|
|
|
void getObjectDetails(S32 objIndex, Vector<S32>& objDetails);
|
|
|
|
bool findMeshIndex(const String &meshName, S32& objIndex, S32& meshIndex);
|
|
TSMesh* findMesh(const String &meshName);
|
|
|
|
bool hasTranslucency() const { return (mFlags & HasTranslucency)!=0; }
|
|
|
|
const GFXVertexFormat* getVertexFormat() const { return &mVertexFormat; }
|
|
|
|
/// @}
|
|
|
|
/// @name Alpha Transitions
|
|
/// These control default values for alpha transitions between detail levels
|
|
/// @{
|
|
|
|
static F32 smAlphaOutLastDetail;
|
|
static F32 smAlphaInBillboard;
|
|
static F32 smAlphaOutBillboard;
|
|
static F32 smAlphaInDefault;
|
|
static F32 smAlphaOutDefault;
|
|
/// @}
|
|
|
|
/// don't load this many of the highest detail levels (although we always
|
|
/// load one renderable detail if there is one)
|
|
static S32 smNumSkipLoadDetails;
|
|
|
|
/// by default we initialize shape when we read...
|
|
static bool smInitOnRead;
|
|
|
|
/// Enables hardware skinning features
|
|
static bool smUseHardwareSkinning;
|
|
|
|
/// Determines maximum number of bones to use in hardware skinning shaders
|
|
static U32 smMaxSkinBones;
|
|
|
|
/// @name Version Info
|
|
/// @{
|
|
|
|
/// Most recent version...the one we write
|
|
static S32 smVersion;
|
|
/// Version currently being read, only valid during read
|
|
static S32 smReadVersion;
|
|
static const U32 smMostRecentExporterVersion;
|
|
///@}
|
|
|
|
/// @name Persist Methods
|
|
/// Methods for saving/loading shapes to/from streams
|
|
/// @{
|
|
|
|
bool canWriteOldFormat() const;
|
|
void write(Stream *, bool saveOldFormat=false);
|
|
bool read(Stream *);
|
|
void readOldShape(Stream * s, S32 * &, S16 * &, S8 * &, S32 &, S32 &, S32 &);
|
|
void writeName(Stream *, S32 nameIndex);
|
|
S32 readName(Stream *, bool addName);
|
|
|
|
/// Initializes our TSShape to be ready to receive put mesh data
|
|
void createEmptyShape();
|
|
|
|
void exportSequences(Stream *);
|
|
void exportSequence(Stream * s, const TSShape::Sequence& seq, bool saveOldFormat);
|
|
bool importSequences(Stream *, const String& sequencePath);
|
|
|
|
/// @}
|
|
|
|
/// @name Persist Helper Functions
|
|
/// @{
|
|
|
|
static TSShapeAlloc smTSAlloc;
|
|
|
|
void fixEndian(S32 *, S16 *, S8 *, S32, S32, S32);
|
|
/// @}
|
|
|
|
/// @name Memory Buffer Transfer Methods
|
|
/// uses TSShape::Alloc structure
|
|
/// @{
|
|
|
|
void assembleShape();
|
|
void disassembleShape();
|
|
///@}
|
|
|
|
/// mem buffer transfer helper (indicate when we don't want to include a particular mesh/decal)
|
|
bool checkSkip(S32 meshNum, S32 & curObject, S32 skipDL);
|
|
|
|
void fixupOldSkins(S32 numMeshes, S32 numSkins, S32 numDetails, S32 * detFirstSkin, S32 * detailNumSkins);
|
|
|
|
/// @name Shape Editing
|
|
/// @{
|
|
S32 addName(const String& name);
|
|
bool removeName(const String& name);
|
|
void updateSmallestVisibleDL();
|
|
S32 addDetail(const String& dname, S32 size, S32 subShapeNum);
|
|
|
|
S32 addImposter( const String& cachePath,
|
|
S32 size,
|
|
S32 numEquatorSteps,
|
|
S32 numPolarSteps,
|
|
S32 dl,
|
|
S32 dim,
|
|
bool includePoles,
|
|
F32 polarAngle );
|
|
bool removeImposter();
|
|
|
|
bool renameNode(const String& oldName, const String& newName);
|
|
bool renameObject(const String& oldName, const String& newName);
|
|
bool renameDetail(const String& oldName, const String& newName);
|
|
bool renameSequence(const String& oldName, const String& newName);
|
|
|
|
bool setNodeTransform(const String& name, const Point3F& pos, const QuatF& rot);
|
|
bool addNode(const String& name, const String& parentName, const Point3F& pos, const QuatF& rot);
|
|
bool removeNode(const String& name);
|
|
|
|
S32 addObject(const String& objName, S32 subShapeIndex);
|
|
void addMeshToObject(S32 objIndex, S32 meshIndex, TSMesh* mesh);
|
|
void removeMeshFromObject(S32 objIndex, S32 meshIndex);
|
|
bool setObjectNode(const String& objName, const String& nodeName);
|
|
bool removeObject(const String& objName);
|
|
|
|
TSMesh* copyMesh( const TSMesh* srcMesh ) const;
|
|
bool addMesh(TSShape* srcShape, const String& srcMeshName, const String& meshName);
|
|
bool addMesh(TSMesh* mesh, const String& meshName);
|
|
bool setMeshSize(const String& meshName, S32 size);
|
|
bool removeMesh(const String& meshName);
|
|
|
|
S32 setDetailSize(S32 oldSize, S32 newSize);
|
|
bool removeDetail(S32 size);
|
|
|
|
static bool isShapeFileType(Torque::Path filePath);
|
|
bool addSequence(const Torque::Path& path, const String& assetId, const String& fromSeq, const String& name, S32 startFrame, S32 endFrame, bool padRotKeys, bool padTransKeys);
|
|
bool removeSequence(const String& name);
|
|
|
|
bool addTrigger(const String& seqName, S32 keyframe, S32 state);
|
|
bool removeTrigger(const String& seqName, S32 keyframe, S32 state);
|
|
|
|
bool setSequenceBlend(const String& seqName, bool blend, const String& blendRefSeqName, S32 blendRefFrame);
|
|
bool setSequenceGroundSpeed(const String& seqName, const Point3F& trans, const Point3F& rot);
|
|
|
|
void makeEditable();
|
|
bool needsReinit();
|
|
bool needsBufferUpdate();
|
|
/// @}
|
|
};
|
|
|
|
|
|
#define TSNode TSShape::Node
|
|
#define TSObject TSShape::Object
|
|
#define TSSequence TSShape::Sequence
|
|
#define TSDetail TSShape::Detail
|
|
|
|
inline QuatF & TSShape::getRotation(const Sequence & seq, S32 keyframeNum, S32 rotNum, QuatF * quat) const
|
|
{
|
|
return nodeRotations[seq.baseRotation + rotNum*seq.numKeyframes + keyframeNum].getQuatF(quat);
|
|
}
|
|
|
|
inline const Point3F & TSShape::getTranslation(const Sequence & seq, S32 keyframeNum, S32 tranNum) const
|
|
{
|
|
return nodeTranslations[seq.baseTranslation + tranNum*seq.numKeyframes + keyframeNum];
|
|
}
|
|
|
|
inline F32 TSShape::getUniformScale(const Sequence & seq, S32 keyframeNum, S32 scaleNum) const
|
|
{
|
|
return nodeUniformScales[seq.baseScale + scaleNum*seq.numKeyframes + keyframeNum];
|
|
}
|
|
|
|
inline const Point3F & TSShape::getAlignedScale(const Sequence & seq, S32 keyframeNum, S32 scaleNum) const
|
|
{
|
|
return nodeAlignedScales[seq.baseScale + scaleNum*seq.numKeyframes + keyframeNum];
|
|
}
|
|
|
|
inline TSScale & TSShape::getArbitraryScale(const Sequence & seq, S32 keyframeNum, S32 scaleNum, TSScale * scale) const
|
|
{
|
|
nodeArbitraryScaleRots[seq.baseScale + scaleNum*seq.numKeyframes + keyframeNum].getQuatF(&scale->mRotate);
|
|
scale->mScale = nodeArbitraryScaleFactors[seq.baseScale + scaleNum*seq.numKeyframes + keyframeNum];
|
|
return *scale;
|
|
}
|
|
|
|
inline const TSShape::ObjectState & TSShape::getObjectState(const Sequence & seq, S32 keyframeNum, S32 objectNum) const
|
|
{
|
|
return objectStates[seq.baseObjectState + objectNum*seq.numKeyframes + keyframeNum];
|
|
}
|
|
|
|
#endif
|