//----------------------------------------------------------------------------- // Torque Game Engine // Copyright (C) GarageGames.com, Inc. //----------------------------------------------------------------------------- // The ShapeMimic tries to hold court in both the App world and // the Torque three-space world. It holds a shape tree isomorphic // to what the shape will look like when exported, but maintains // links to App objects and delays computing certain things // until the tsshape is finally created in generateShape(). #ifndef SHAPEMIMIC_H_ #define SHAPEMIMIC_H_ #include "DTSTypes.h" #include "DTSShape.h" #include "DTSPlusTypes.h" #include "DTSUtil.h" #include "appNode.h" #include "appMesh.h" #include "appSequence.h" #include "appIfl.h" #include "appConfig.h" namespace DTS { struct IflMimic { AppIfl * appIfl; S32 materialSlot; }; struct SkinMimic { typedef std::vector WeightList; AppMesh * appMesh; Mesh * skinMesh; S32 detailSize; S32 skinNum; S32 meshNum; F32 multiResPercent; std::vector faces; std::vector verts; std::vector normals; std::vector tverts; std::vector indices; std::vector smoothingGroups; std::vector vertId; std::vector bones; std::vector weights; ~SkinMimic() { for (U32 i=0;i smoothingGroups; std::vector remap; std::vector vertId; F32 multiResPercent; Matrix<4,4,F32> objectOffset; // NOTE: not valid till late in the game MeshMimic(AppMesh * mesh) { appMesh = mesh; skinMimic = NULL; tsMesh = NULL; multiResPercent = 1.0f; } }; struct ObjectMimic { enum { MaxDetails=20 }; struct Detail { S32 size; F32 multiResPercent; MeshMimic * mesh; }; // object name char * name; char * fullName; // name of object in tree // each object has several meshes attached S32 numDetails; Detail details[MaxDetails]; // we'll check the object against this list in the end std::vector * validDetails; AppNode * inTreeNode; // this is the node that sits in the shape's node hierrarchy AppMesh * inTreeMesh; // this is the mesh that sits in the shape's node hierrarchy // The next two items are used for sorting objects // objects are sorted by subTreeNum first, and then // priority (smallest to highest in both cases). S32 subtreeNum; U32 priority; // The node in the 3D app this object hangs on (i.e., the one in the shape not // the loose objects that make up the detail levels). AppNode * appParent; // Similar to above: the app node that corresponds to tsNode that will // be our parent. Starts out the same as appParent, but is revised // as we prune unwanted nodes from the tree structure. AppNode * appTSParent; // ts node index we hang off S32 tsNodeIndex; S32 tsObjectIndex; // This is the eventual payoff DTS::Object * tsObject; // bool isBone; bool isSkin; AppMesh * getSkin() { for (S32 dl=0; dlskinMimic ? details[dl].mesh->skinMimic->appMesh : NULL; return NULL; } ~ObjectMimic() { delete [] name; delete [] fullName; for (S32 i=0;i objects; }; class ShapeMimic { struct Subtree { std::vector validDetails; std::vector detailNames; std::vector detailNodes; NodeMimic start; }; std::vector subtrees; std::vector objectList; std::vector skins; std::vector iflList; std::vector sequences; std::vector materials; AppNode * boundsNode; // this gets filled in late in the game // it holds the nodes that actually go into the shape // in the order they appear in the shape std::vector nodes; static std::vector nodeRotCache; static std::vector nodeTransCache; static std::vector nodeScaleRotCache; static std::vector nodeScaleCache; static std::vector cutNodes; static std::vector cutNodesParents; // error control //void setExportError(const char * errStr) { AppConfig::SetExportError(errStr); } //const char * getError() { return AppConfig::GetExportError(); } //bool isError() { return AppConfig::IsExportError(); } // called by generateShape void generateBounds(Shape * shape); void generateDetails(Shape * shape); void generateSubtrees(Shape * shape); void generateObjects(Shape * shape); void generateDefaultStates(Shape * shape); void generateIflMaterials(Shape * shape); void generateSequences(Shape * shape); void generateMaterialList(Shape * shape); void generateSkins(Shape * shape); void optimizeMeshes(Shape * shape); void convertSortObjects(Shape * shape); void initShape(Shape*); // deeper generate methods... void generateBillboardDetail(AppNode * detailNode, DetailLevel & detail); void sortTSDetails(std::vector & details); void setObjectPriorities(std::vector & objects); void sortObjectList(std::vector & objects); void generateNodeTransform(NodeMimic *, const AppTime & time, bool blend, const AppTime & blendReferenceTime, Quaternion & rot, Point3D & trans, Quaternion & qrot, Point3D & scale); void generateObjectState(ObjectMimic *, const AppTime & time, Shape *, bool addFrame, bool addMatFrame); // generate animation data void generateFrame(ObjectMimic *, const AppTime & time, bool addFrame, bool addMatFrame); void generateGroundAnimation(Shape *, Sequence &, AppSequenceData &); void generateObjectAnimation(Shape *, Sequence &, AppSequenceData &); void generateFrameTriggers(Shape *, Sequence &, AppSequenceData &, AppSequence *); void generateNodeAnimation(Shape *, Sequence &, AppSequenceData &); // add transform data void addNodeRotation(NodeMimic *, const AppTime & time, Shape *, bool blend, Quaternion & rot, bool defaultVal); void addNodeTranslation(NodeMimic *, const AppTime & time, Shape *, bool blend, Point3D & trans, bool defaultVal); void addNodeUniformScale(NodeMimic *, const AppTime & time, Shape *, bool blend, F32 scale); void addNodeAlignedScale(NodeMimic *, const AppTime & time, Shape *, bool blend, Point3D & scale); void addNodeArbitraryScale(NodeMimic *, const AppTime & time, Shape *, bool blend, Quaternion & qrot, Point3D & scale); // membership tests for animation void setIflMembership(Shape *, Sequence &, AppSequenceData &, S32 & iflCount); S32 setObjectMembership(Shape *, Sequence &, AppSequenceData &, S32 & objectCount); void setNodeMembership(Shape *, Sequence &, AppSequenceData &, S32 & rotCount, S32 & transCount, S32 & uniformScaleCount, S32 & alignedScaleCount, S32 & arbitraryScaleCount); void setRotationMembership(Shape *, Sequence &, AppSequenceData &, S32 & rotCount); void setTranslationMembership(Shape *, Sequence &, AppSequenceData &, S32 & transCount); void setScaleMembership(Sequence &, AppSequenceData &, S32 & arbitraryScale, S32 & alignedScale, S32 & uniformScale); bool animatesAlignedScale(AppSequenceData &); bool animatesArbitraryScale(AppSequenceData &); S32 setUniformScaleMembership(Sequence &, AppSequenceData &); S32 setAlignedScaleMembership(Sequence &, AppSequenceData &); S32 setArbitraryScaleMembership(Sequence &, AppSequenceData &); // add material from mesh S32 addFaceMaterial(AppMesh *,S32 faceNum); S32 addMaterial(Material mat); // utility methods void fillNodeTransformCache(std::vector &, Sequence &, AppSequenceData &); ObjectMimic * addObject(AppNode *, AppMesh *, std::vector * validDetails); ObjectMimic * addObject(AppNode * node, AppMesh * mesh, std::vector * validDetails, bool multiRes, S32 multiResSize=-1, F32 multiResPercent=1.0f); ObjectMimic * getObject(AppNode *, AppMesh *, char * name, S32 size, S32 * detailNum, F32 multiResPercent, bool matchFullName = true, bool isBone=false, bool isSkin=false); ObjectMimic * addBoneObject(AppNode * node, S32 subtreeNum); MeshMimic * addSkinObject(SkinMimic * skinMimic); S32 addName(const char *, Shape * shape); void computeNormals(std::vector &, std::vector & indices, std::vector & verts, std::vector & norms, std::vector & smooth, S32 vertsPerFrame, S32 numFrames); void copyWeightsToVerts(SkinMimic * skinMimic); void collapseVertices(Mesh *, std::vector & smooth, std::vector & remap, std::vector * vertId); bool vertexSame(Point3D & v1, Point3D & v2, Point2D & tv1, Point2D & tv2, U32 smooth1, U32 smooth2, Point3D & norm1, Point3D & norm2, U32 idx1, U32 idx2, std::vector * vertId); void stripify(std::vector &, std::vector & indices); void decimate(Mesh * mesh, F32 percentage); void collapseTransforms(); bool cut(NodeMimic * mimicNode); void snip(NodeMimic * nodeMimic); bool testCutNodes(AppSequenceData & seqData); NodeMimic * findNextNode(NodeMimic *); void dumpShapeNode(Shape * shape, S32 level, S32 nodeIndex, std::vector & detailSizes); void dumpShape(Shape * shape); void getMultiResData(AppNode * node, std::vector & multiResSize, std::vector & multiResPercent); void getMultiResData(AppMesh * node, std::vector & multiResSize, std::vector & multiResPercent); public: ShapeMimic(); ~ShapeMimic(); // add shape items as we walk the scene void addBounds(AppNode * appNode) { boundsNode=appNode; } void addSubtree(AppNode * appNode); void addNode(NodeMimic *,AppNode *, std::vector &,bool); void addMesh(AppNode * node, AppMesh * mesh) { addObject(node,mesh,NULL); } void addSkin(AppMesh * mesh); void addSkin(AppMesh * mesh, bool multiRes, S32 multiResSize=-1, F32 multiResPercent=1.0f); void addSequence(AppSequence * sequence) { sequences.push_back(sequence); } // the payoff...call after adding all of the above Shape * generateShape(); }; }; // namespace DTS #endif