tsShapeInstance.h 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821
  1. //-----------------------------------------------------------------------------
  2. // Copyright (c) 2012 GarageGames, LLC
  3. //
  4. // Permission is hereby granted, free of charge, to any person obtaining a copy
  5. // of this software and associated documentation files (the "Software"), to
  6. // deal in the Software without restriction, including without limitation the
  7. // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  8. // sell copies of the Software, and to permit persons to whom the Software is
  9. // furnished to do so, subject to the following conditions:
  10. //
  11. // The above copyright notice and this permission notice shall be included in
  12. // all copies or substantial portions of the Software.
  13. //
  14. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  19. // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  20. // IN THE SOFTWARE.
  21. //-----------------------------------------------------------------------------
  22. //~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
  23. // Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames
  24. // Copyright (C) 2015 Faust Logic, Inc.
  25. //~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
  26. #ifndef _TSSHAPEINSTANCE_H_
  27. #define _TSSHAPEINSTANCE_H_
  28. #ifndef __RESOURCE_H__
  29. #include "core/resource.h"
  30. #endif
  31. #ifndef _TSSHAPE_H_
  32. #include "ts/tsShape.h"
  33. #endif
  34. #ifndef _TSINTEGERSET_H_
  35. #include "ts/tsIntegerSet.h"
  36. #endif
  37. #ifndef _CONSOLE_H_
  38. #include "console/console.h"
  39. #endif
  40. #ifndef _GBITMAP_H_
  41. #include "gfx/bitmap/gBitmap.h"
  42. #endif
  43. #ifndef _TSRENDERDATA_H_
  44. #include "ts/tsRenderState.h"
  45. #endif
  46. #ifndef _TSMATERIALLIST_H_
  47. #include "ts/tsMaterialList.h"
  48. #endif
  49. class RenderItem;
  50. class TSThread;
  51. class ConvexFeature;
  52. class SceneRenderState;
  53. class FeatureSet;
  54. //-------------------------------------------------------------------------------------
  55. // Instance versions of shape objects
  56. //-------------------------------------------------------------------------------------
  57. class TSCallback
  58. {
  59. public:
  60. virtual ~TSCallback() {}
  61. virtual void setNodeTransform(TSShapeInstance * si, S32 nodeIndex, MatrixF & localTransform) = 0;
  62. };
  63. /// An instance of a 3space shape.
  64. ///
  65. /// @section TSShapeInstance_intro Introduction
  66. ///
  67. /// A 3space model represents a significant amount of data. There are multiple meshes,
  68. /// skeleton information, as well as animation data. Some of this, like the skeletal
  69. /// transforms, are unique for each instance of the model (as different instances are
  70. /// likely to be in different states of animation), while most of it, like texturing
  71. /// information and vertex data, is the same amongst all instances of the shape.
  72. ///
  73. /// To keep this data from being replicated for every instance of a 3shape object, Torque
  74. /// uses the ResManager to instantiate and track TSShape objects. TSShape handles reading
  75. /// and writing 3space models, as well as keeping track of static model data, as discussed
  76. /// above. TSShapeInstance keeps track of all instance specific data, such as the currently
  77. /// playing sequences or the active node transforms.
  78. ///
  79. /// TSShapeInstance contains all the functionality for 3space models, while TSShape acts as
  80. /// a repository for common data.
  81. ///
  82. /// @section TSShapeInstance_functionality What Does TSShapeInstance Do?
  83. ///
  84. /// TSShapeInstance handles several areas of functionality:
  85. /// - Collision.
  86. /// - Rendering.
  87. /// - Animation.
  88. /// - Updating skeletal transforms.
  89. /// - Ballooning (see setShapeBalloon() and getShapeBalloon())
  90. ///
  91. /// For an excellent example of how to render a TSShape in game, see TSStatic. For examples
  92. /// of how to procedurally animate models, look at Player::updateLookAnimation().
  93. class TSShapeInstance
  94. {
  95. public:
  96. struct ObjectInstance;
  97. friend class TSThread;
  98. friend class TSLastDetail;
  99. friend class TSPartInstance;
  100. /// Base class for all renderable objects, including mesh objects and decal objects.
  101. ///
  102. /// An ObjectInstance points to the renderable items in the shape...
  103. struct ObjectInstance
  104. {
  105. virtual ~ObjectInstance() {}
  106. /// this needs to be set before using an objectInstance...tells us where to
  107. /// look for the transforms...gets set be shape instance 'setStatics' method
  108. const Vector<MatrixF> *mTransforms;
  109. S32 nodeIndex;
  110. /// Gets the transform of this object
  111. inline const MatrixF& getTransform() const
  112. {
  113. return nodeIndex < 0 ? MatrixF::Identity : (*mTransforms)[ nodeIndex ];
  114. }
  115. /// @name Render Functions
  116. /// @{
  117. /// Render! This draws the base-textured object.
  118. virtual void render( S32 objectDetail, TSVertexBufferHandle &vb, TSMaterialList *, TSRenderState &rdata, F32 alpha, const char *meshName );
  119. /// Updates the vertex buffer data for this mesh (used for software skinning)
  120. virtual void updateVertexBuffer( S32 objectDetail, U8 *buffer );
  121. virtual bool bufferNeedsUpdate( S32 objectDetail );
  122. /// @}
  123. /// @name Collision Routines
  124. /// @{
  125. virtual bool buildPolyList( S32 objectDetail, AbstractPolyList *polyList, U32 &surfaceKey, TSMaterialList *materials );
  126. virtual bool getFeatures( S32 objectDetail, const MatrixF &mat, const Point3F &n, ConvexFeature *feature, U32 &surfaceKey );
  127. virtual void support( S32 od, const Point3F &v, F32 *currMaxDP, Point3F *currSupport );
  128. virtual bool buildPolyListOpcode( S32 objectDetail, AbstractPolyList *polyList, U32 &surfaceKey, TSMaterialList *materials );
  129. virtual bool castRayOpcode( S32 objectDetail, const Point3F &start, const Point3F &end, RayInfo *info, TSMaterialList *materials );
  130. virtual bool buildConvexOpcode( const MatrixF &mat, S32 objectDetail, const Box3F &bounds, Convex *c, Convex *list );
  131. /// Ray cast for collision detection
  132. virtual bool castRay( S32 objectDetail, const Point3F &start, const Point3F &end, RayInfo *info, TSMaterialList* materials ) = 0;
  133. /// @}
  134. };
  135. /// These are set up by default based on shape data
  136. struct MeshObjectInstance : ObjectInstance
  137. {
  138. TSMesh * const * meshList; ///< one mesh per detail level... Null entries allowed.
  139. const TSObject * object;
  140. S32 frame;
  141. S32 matFrame;
  142. F32 visible;
  143. S32 mLastObjectDetail;
  144. /// If true this mesh is forced to be hidden
  145. /// regardless of the animation state.
  146. bool forceHidden;
  147. /// The time at which this mesh
  148. /// was last rendered.
  149. U32 mLastTime;
  150. Vector<MatrixF> mActiveTransforms;
  151. MeshObjectInstance();
  152. virtual ~MeshObjectInstance() {}
  153. void render( S32 objectDetail, TSVertexBufferHandle &vb, TSMaterialList *, TSRenderState &rdata, F32 alpha, const char *meshName );
  154. void updateVertexBuffer( S32 objectDetail, U8 *buffer );
  155. bool bufferNeedsUpdate(S32 objectDetail);
  156. /// Gets the mesh with specified detail level
  157. TSMesh * getMesh(S32 num) const { return num<object->numMeshes ? *(meshList+num) : NULL; }
  158. /// @name Collision Routines
  159. /// @{
  160. bool buildPolyList( S32 objectDetail, AbstractPolyList *polyList, U32 &surfaceKey, TSMaterialList *materials );
  161. bool getFeatures( S32 objectDetail, const MatrixF &mat, const Point3F &n, ConvexFeature *feature, U32 &surfaceKey );
  162. void support( S32 od, const Point3F &v, F32 *currMaxDP, Point3F *currSupport );
  163. bool castRay( S32 objectDetail, const Point3F &start, const Point3F &end, RayInfo *info, TSMaterialList *materials );
  164. bool castRayRendered( S32 objectDetail, const Point3F &start, const Point3F &end, RayInfo *info, TSMaterialList *materials );
  165. bool buildPolyListOpcode( S32 objectDetail, AbstractPolyList *polyList, const Box3F &box, TSMaterialList* materials );
  166. bool castRayOpcode( S32 objectDetail, const Point3F &start, const Point3F &end, RayInfo *info, TSMaterialList *materials );
  167. bool buildConvexOpcode( const MatrixF &mat, S32 objectDetail, const Box3F &bounds, Convex *c, Convex *list );
  168. /// @}
  169. };
  170. protected:
  171. struct TSCallbackRecord
  172. {
  173. TSCallback * callback;
  174. S32 nodeIndex;
  175. };
  176. //-------------------------------------------------------------------------------------
  177. // Lists used for storage of transforms, nodes, objects, etc...
  178. //-------------------------------------------------------------------------------------
  179. public:
  180. Vector<MeshObjectInstance> mMeshObjects;
  181. /// storage space for node transforms
  182. Vector<MatrixF> mNodeTransforms;
  183. /// @name Reference Transform Vectors
  184. /// unused until first transition
  185. /// @{
  186. Vector<Quat16> mNodeReferenceRotations;
  187. Vector<Point3F> mNodeReferenceTranslations;
  188. Vector<F32> mNodeReferenceUniformScales;
  189. Vector<Point3F> mNodeReferenceScaleFactors;
  190. Vector<Quat16> mNodeReferenceArbitraryScaleRots;
  191. /// @}
  192. /// @name Workspace for Node Transforms
  193. /// @{
  194. static Vector<QuatF> smNodeCurrentRotations;
  195. static Vector<Point3F> smNodeCurrentTranslations;
  196. static Vector<F32> smNodeCurrentUniformScales;
  197. static Vector<Point3F> smNodeCurrentAlignedScales;
  198. static Vector<TSScale> smNodeCurrentArbitraryScales;
  199. static Vector<MatrixF> smNodeLocalTransforms;
  200. static TSIntegerSet smNodeLocalTransformDirty;
  201. /// @}
  202. /// @name Threads
  203. /// keep track of who controls what on currently animating shape
  204. /// @{
  205. static Vector<TSThread*> smRotationThreads;
  206. static Vector<TSThread*> smTranslationThreads;
  207. static Vector<TSThread*> smScaleThreads;
  208. /// @}
  209. TSMaterialList* mMaterialList; ///< by default, points to hShape material list
  210. //-------------------------------------------------------------------------------------
  211. // Misc.
  212. //-------------------------------------------------------------------------------------
  213. protected:
  214. /// @name Ground Transform Data
  215. /// @{
  216. MatrixF mGroundTransform;
  217. TSThread * mGroundThread;
  218. /// @}
  219. bool mScaleCurrentlyAnimated;
  220. S32 mCurrentDetailLevel;
  221. /// 0-1, how far along from current to next (higher) detail level...
  222. ///
  223. /// 0=at this dl, 1=at higher detail level, where higher means bigger size on screen
  224. /// for dl=0, we use twice detail level 0's size as the size of the "next" dl
  225. F32 mCurrentIntraDetailLevel;
  226. /// This is only valid when the instance was created from
  227. /// a resource. Else it is null.
  228. Resource<TSShape> mShapeResource;
  229. /// This should always point to a valid shape and should
  230. /// equal mShapeResource if it was created from a resource.
  231. TSShape *mShape;
  232. /// Vertex buffer used for software skinning this instance
  233. TSVertexBufferHandle mSoftwareVertexBuffer;
  234. bool mOwnMaterialList; ///< Does this own the material list pointer?
  235. bool mUseOwnBuffer; ///< Force using our own copy of the vertex buffer
  236. bool mAlphaAlways;
  237. F32 mAlphaAlwaysValue;
  238. bool mUseOverrideTexture;
  239. U32 debrisRefCount;
  240. // the threads...
  241. Vector<TSThread*> mThreadList;
  242. Vector<TSThread*> mTransitionThreads;
  243. /// @name Transition nodes
  244. /// keep track of nodes that are involved in a transition
  245. ///
  246. /// @note this only tracks nodes we're transitioning from...
  247. /// nodes we're transitioning to are implicitly handled
  248. /// (i.e., we don't need to keep track of them)
  249. /// @{
  250. TSIntegerSet mTransitionRotationNodes;
  251. TSIntegerSet mTransitionTranslationNodes;
  252. TSIntegerSet mTransitionScaleNodes;
  253. /// @}
  254. /// keep track of nodes with animation restrictions put on them
  255. TSIntegerSet mMaskRotationNodes;
  256. TSIntegerSet mMaskPosXNodes;
  257. TSIntegerSet mMaskPosYNodes;
  258. TSIntegerSet mMaskPosZNodes;
  259. TSIntegerSet mDisableBlendNodes;
  260. TSIntegerSet mHandsOffNodes; ///< Nodes that aren't animated through threads automatically
  261. TSIntegerSet mCallbackNodes;
  262. // node callbacks
  263. Vector<TSCallbackRecord> mNodeCallbacks;
  264. /// state variables
  265. U32 mTriggerStates;
  266. bool initGround();
  267. void addPath(TSThread * gt, F32 start, F32 end, MatrixF * mat = NULL);
  268. public:
  269. TSShape* getShape() const { return mShape; }
  270. TSMaterialList* getMaterialList() const { return mMaterialList; }
  271. /// Set the material list without taking ownership.
  272. /// @see cloneMaterialList
  273. void setMaterialList( TSMaterialList *matList );
  274. /// Call this to own the material list -- i.e., we'll make a copy of the
  275. /// currently set material list and be responsible for deleting it. You
  276. /// can pass an optional feature set for initializing the cloned materials.
  277. void cloneMaterialList( const FeatureSet *features = NULL );
  278. /// Initializes or re-initializes the material list with
  279. /// an optional feature set.
  280. void initMaterialList( const FeatureSet *features = NULL );
  281. void setUseOwnBuffer();
  282. bool ownMaterialList() const { return mOwnMaterialList; }
  283. /// Get the number of material targets in this shape instance
  284. S32 getTargetCount() const
  285. {
  286. if ( mOwnMaterialList )
  287. return getMaterialList()->size();
  288. else
  289. return getShape()->getTargetCount();
  290. }
  291. /// Get the indexed material target (may differ from the base TSShape material
  292. /// list if this instance has been reskinned).
  293. const String& getTargetName( S32 mapToNameIndex ) const
  294. {
  295. if ( mOwnMaterialList )
  296. {
  297. if ( mapToNameIndex < 0 || mapToNameIndex >= getMaterialList()->size() )
  298. return String::EmptyString;
  299. return getMaterialList()->getMaterialName( mapToNameIndex );
  300. }
  301. else
  302. {
  303. return getShape()->getTargetName( mapToNameIndex );
  304. }
  305. }
  306. void reSkin( String newBaseName, String oldBaseName = String::EmptyString );
  307. void resetMaterialList();
  308. enum
  309. {
  310. MaskNodeRotation = 0x01,
  311. MaskNodePosX = 0x02,
  312. MaskNodePosY = 0x04,
  313. MaskNodePosZ = 0x08,
  314. MaskNodeBlend = 0x10,
  315. MaskNodeAll = MaskNodeRotation|MaskNodePosX|MaskNodePosY|MaskNodePosZ|MaskNodeBlend,
  316. MaskNodeAllButBlend = MaskNodeRotation|MaskNodePosX|MaskNodePosY|MaskNodePosZ,
  317. MaskNodeAllButRotation = MaskNodePosX|MaskNodePosY|MaskNodePosZ|MaskNodeBlend,
  318. MaskNodeAllButPosX = MaskNodeRotation|MaskNodePosY|MaskNodePosZ|MaskNodeBlend,
  319. MaskNodeAllButPosY = MaskNodeRotation|MaskNodePosX|MaskNodePosZ|MaskNodeBlend,
  320. MaskNodeAllButPosZ = MaskNodeRotation|MaskNodePosX|MaskNodePosY|MaskNodeBlend,
  321. MaskNodeHandsOff = 0x20, ///< meaning, don't even set to default, programmer controls it (blend still applies)
  322. MaskNodeCallback = 0x40 ///< meaning, get local transform via callback function (see setCallback)
  323. ///< callback data2 is node index, callback return value is pointer to local transform
  324. ///< Note: won't get this callback everytime you animate...application responsibility
  325. ///< to make sure matrix pointer continues to point to valid and updated local transform
  326. };
  327. /// @name Node Masking
  328. /// set node masking...
  329. /// @{
  330. void setNodeAnimationState(S32 nodeIndex, U32 animationState, TSCallback * callback = NULL);
  331. U32 getNodeAnimationState(S32 nodeIndex);
  332. /// @}
  333. /// @name Trigger states
  334. /// check trigger value
  335. /// @{
  336. bool getTriggerState(U32 stateNum, bool clearState = true);
  337. void setTriggerState(U32 stateNum, bool on);
  338. void setTriggerStateBit(U32 stateBit, bool on);
  339. /// @}
  340. /// @name Debris Management
  341. /// @{
  342. void incDebrisRefCount() { ++debrisRefCount; }
  343. void decDebrisRefCount() { debrisRefCount > 0 ? --debrisRefCount : 0; }
  344. U32 getDebrisRefCount() const { return debrisRefCount; }
  345. /// @}
  346. /// @name AlphaAlways
  347. /// AlphaAlways allows the entire model to become translucent at the same value
  348. /// @{
  349. void setAlphaAlways(F32 value) { mAlphaAlways = (value<0.99f); mAlphaAlwaysValue = value; }
  350. F32 getAlphaAlwaysValue() const { return mAlphaAlways ? mAlphaAlwaysValue : 1.0f; }
  351. bool getAlphaAlways() const { return mAlphaAlways; }
  352. /// @}
  353. //-------------------------------------------------------------------------------------
  354. // private methods for setting up and affecting animation
  355. //-------------------------------------------------------------------------------------
  356. private:
  357. /// @name Private animation methods
  358. /// These are private methods for setting up and affecting animation
  359. /// @{
  360. void sortThreads();
  361. void updateTransitions();
  362. void handleDefaultScale(S32 a, S32 b, TSIntegerSet & scaleBeenSet);
  363. void updateTransitionNodeTransforms(TSIntegerSet& transitionNodes);
  364. void handleTransitionNodes(S32 a, S32 b);
  365. void handleNodeScale(S32 a, S32 b);
  366. void handleAnimatedScale(TSThread *, S32 a, S32 b, TSIntegerSet &);
  367. void handleMaskedPositionNode(TSThread *, S32 nodeIndex, S32 offset);
  368. void handleBlendSequence(TSThread *, S32 a, S32 b);
  369. void checkScaleCurrentlyAnimated();
  370. /// @}
  371. //-------------------------------------------------------------------------------------
  372. // animate, render, & detail control
  373. //-------------------------------------------------------------------------------------
  374. public:
  375. struct RenderData
  376. {
  377. MeshObjectInstance* currentObjectInstance;
  378. S32 detailLevel;
  379. S32 materialIndex;
  380. const Point3F * objectScale;
  381. };
  382. /// Scale pixel size by this amount when selecting
  383. /// detail levels.
  384. static F32 smDetailAdjust;
  385. /// If this is set to a positive pixel value shapes
  386. /// with a smaller pixel size than this will skip
  387. /// rendering entirely.
  388. static F32 smSmallestVisiblePixelSize;
  389. /// never choose detail level number below this value (except if
  390. /// only way to get a visible detail)
  391. static S32 smNumSkipRenderDetails;
  392. /// For debugging / metrics.
  393. static F32 smLastScreenErrorTolerance;
  394. static F32 smLastScaledDistance;
  395. static F32 smLastPixelSize;
  396. /// Debugging
  397. /// @{
  398. /// Renders the vertex normals assuming the GFX state
  399. /// is setup for rendering in model space.
  400. void renderDebugNormals( F32 normalScalar, S32 dl );
  401. /// Render all node transforms as small axis gizmos. It is recommended
  402. /// that prior to calling this, shapeInstance::animate is called so that
  403. /// nodes are in object space and that the GFX state is setup for
  404. /// rendering in model space.
  405. void renderDebugNodes();
  406. /// Print mesh data to the console, valid String parameters
  407. /// are Visible, Hidden, or All.
  408. void listMeshes( const String &state ) const;
  409. /// @}
  410. void render( const TSRenderState &rdata );
  411. void render( const TSRenderState &rdata, S32 dl, F32 intraDL = 0.0f );
  412. bool bufferNeedsUpdate(S32 objectDetail, S32 start, S32 end);
  413. void animate() { animate( mCurrentDetailLevel ); }
  414. void animate(S32 dl);
  415. void animateNodes(S32 ss);
  416. void animateVisibility(S32 ss);
  417. void animateFrame(S32 ss);
  418. void animateMatFrame(S32 ss);
  419. void animateSubtrees(bool forceFull = true);
  420. void animateNodeSubtrees(bool forceFull = true);
  421. /// Sets the 'forceHidden' state on the named mesh.
  422. /// @see MeshObjectInstance::forceHidden
  423. void setMeshForceHidden( const char *meshName, bool hidden );
  424. /// Sets the 'forceHidden' state on a mesh.
  425. /// @see MeshObjectInstance::forceHidden
  426. void setMeshForceHidden( S32 meshIndex, bool hidden );
  427. /// @name Animation Scale
  428. /// Query about animated scale
  429. /// @{
  430. bool animatesScale() { return (mShape->mFlags & TSShape::AnyScale) != 0; }
  431. bool animatesUniformScale() { return (mShape->mFlags & TSShape::UniformScale) != 0; }
  432. bool animatesAlignedScale() { return (mShape->mFlags & TSShape::AlignedScale) != 0; }
  433. bool animatesArbitraryScale() { return (mShape->mFlags & TSShape::ArbitraryScale) != 0; }
  434. bool scaleCurrentlyAnimated() { return mScaleCurrentlyAnimated; }
  435. /// @}
  436. //
  437. bool inTransition() { return !mTransitionThreads.empty(); }
  438. /// @name Ground Transforms
  439. /// The animator of a model can make the bounding box
  440. /// animate along with the object. Doing so will move the object with the bounding box.
  441. /// The ground transform turns the world bounding box into the post-animation bounding box
  442. /// when such a technique is used. However, few models actually use this technique.
  443. /// @{
  444. void animateGround(); ///< clears previous ground transform
  445. MatrixF & getGroundTransform() { return mGroundTransform; }
  446. void deltaGround(TSThread *, F32 start, F32 end, MatrixF * mat = NULL);
  447. void deltaGround1(TSThread *, F32 start, F32 end, MatrixF& mat);
  448. /// @}
  449. U32 getNumDetails() const { return mShape ? mShape->details.size() : 0; }
  450. S32 getCurrentDetail() const { return mCurrentDetailLevel; }
  451. F32 getCurrentIntraDetail() const { return mCurrentIntraDetailLevel; }
  452. void setCurrentDetail( S32 dl, F32 intraDL = 1.0f );
  453. /// Helper function which internally calls setDetailFromDistance.
  454. S32 setDetailFromPosAndScale( const SceneRenderState *state,
  455. const Point3F &pos,
  456. const Point3F &scale );
  457. /// Selects the current detail level using the scaled
  458. /// distance between your object and the camera.
  459. ///
  460. /// @see TSShape::Detail.
  461. S32 setDetailFromDistance( const SceneRenderState *state, F32 scaledDist );
  462. /// Sets the current detail level using the legacy screen error metric.
  463. S32 setDetailFromScreenError( F32 errorTOL );
  464. enum
  465. {
  466. TransformDirty = BIT(0),
  467. VisDirty = BIT(1),
  468. FrameDirty = BIT(2),
  469. MatFrameDirty = BIT(3),
  470. ThreadDirty = BIT(4),
  471. AllDirtyMask = TransformDirty | VisDirty | FrameDirty | MatFrameDirty | ThreadDirty
  472. };
  473. U32 * mDirtyFlags;
  474. void setDirty(U32 dirty);
  475. void clearDirty(U32 dirty);
  476. //-------------------------------------------------------------------------------------
  477. // collision interface routines
  478. //-------------------------------------------------------------------------------------
  479. public:
  480. bool buildPolyList(AbstractPolyList *, S32 dl);
  481. bool getFeatures(const MatrixF& mat, const Point3F& n, ConvexFeature*, S32 dl);
  482. bool castRay(const Point3F & start, const Point3F & end, RayInfo *,S32 dl);
  483. bool castRayRendered(const Point3F & start, const Point3F & end, RayInfo *,S32 dl);
  484. bool quickLOS(const Point3F & start, const Point3F & end, S32 dl) { return castRay(start,end,NULL,dl); }
  485. Point3F support(const Point3F & v, S32 dl);
  486. void computeBounds(S32 dl, Box3F & bounds); ///< uses current transforms to compute bounding box around a detail level
  487. ///< see like named method on shape if you want to use default transforms
  488. bool buildPolyListOpcode( S32 dl, AbstractPolyList *polyList, const Box3F &box );
  489. bool castRayOpcode( S32 objectDetail, const Point3F & start, const Point3F & end, RayInfo *);
  490. bool buildConvexOpcode( const MatrixF &objMat, const Point3F &objScale, S32 objectDetail, const Box3F &bounds, Convex *c, Convex *list );
  491. //-------------------------------------------------------------------------------------
  492. // Thread Control
  493. //-------------------------------------------------------------------------------------
  494. /// @name Thread Control
  495. /// Threads! In order to animate an object, first you need to have an animation in the object.
  496. /// Then, you need to get the TSShape of the object:
  497. /// @code
  498. /// TSShape* shape = mShapeInstance->getShape());
  499. /// @endcode
  500. /// Next, get the sequence and store::
  501. /// @code
  502. /// S32 seq = shape->findSequence("foo"));
  503. /// @endcode
  504. /// Create a new thread (if needed):
  505. /// @code
  506. /// TSThread* thread = mShapeInstance->addThread();
  507. /// @endcode
  508. /// Finally, set the position in the sequence:
  509. /// @code
  510. /// mShapeInstance->setSequence(thread, seq, 0)
  511. /// @endcode
  512. /// @{
  513. public:
  514. TSThread * addThread(); ///< Create a new thread
  515. TSThread * getThread(S32 threadNumber); ///< @note threads can change order, best to hold
  516. ///< onto a thread from the start
  517. void destroyThread(TSThread * thread); ///< Destroy a thread!
  518. U32 threadCount(); ///< How many threads are there?
  519. void setSequence(TSThread *, S32 seq, F32 pos);///< Get the thread a sequence
  520. /// Transition to a sequence
  521. void transitionToSequence(TSThread *, S32 seq, F32 pos, F32 duration, bool continuePlay);
  522. void clearTransition(TSThread *); ///< Stop transitions
  523. U32 getSequence(TSThread *); ///< Get the sequence of the thread
  524. void setBlendEnabled(TSThread *, bool blendOn);///< Set whether or not the thread will blend
  525. bool getBlendEnabled(TSThread *); ///< Does this thread blend?
  526. void setPriority(TSThread *, F32 priority); ///< Set thread priority
  527. F32 getPriority(TSThread * thread); ///< Get thread priority
  528. F32 getTime(TSThread * thread); ///< Get how long the thread has been playing
  529. F32 getPos(TSThread * thread); ///< Get the position in the thread
  530. void setTime(TSThread * thread, F32 time); ///< Set how long into the thread to use
  531. void setPos(TSThread * thread, F32 pos); ///< Set the position of the thread
  532. bool isInTransition(TSThread * thread); ///< Is this thread in transition?
  533. F32 getTimeScale(TSThread * thread); ///< Get the time scale of the thread
  534. void setTimeScale(TSThread * thread, F32); ///< Set the time scale of the thread
  535. F32 getDuration(TSThread * thread); ///< Get the duration of the thread
  536. F32 getScaledDuration(TSThread * thread); ///< Get the duration of the thread with the scale factored in
  537. S32 getKeyframeCount(TSThread * thread); ///< Get the number of keyframes
  538. S32 getKeyframeNumber(TSThread * thread); ///< Get which keyframe the thread is on
  539. /// Set which keyframe the thread is on
  540. void setKeyframeNumber(TSThread * thread, S32 kf);
  541. void advanceTime(F32 delta, TSThread *); ///< advance time on a particular thread
  542. void advanceTime(F32 delta); ///< advance time on all threads
  543. void advancePos(F32 delta, TSThread *); ///< advance pos on a particular thread
  544. void advancePos(F32 delta); ///< advance pos on all threads
  545. /// @}
  546. //-------------------------------------------------------------------------------------
  547. // constructors, destructors, initialization, io
  548. //-------------------------------------------------------------------------------------
  549. TSShapeInstance( const Resource<TSShape> & shape, bool loadMaterials = true);
  550. TSShapeInstance( TSShape * pShape, bool loadMaterials = true);
  551. ~TSShapeInstance();
  552. void buildInstanceData(TSShape *, bool loadMaterials);
  553. void initNodeTransforms();
  554. void initMeshObjects();
  555. void dump(Stream &);
  556. void dumpNode(Stream &, S32 level, S32 nodeIndex, Vector<S32> & detailSizes);
  557. void *mData; ///< available for use by app...initialized to 0
  558. void prepCollision();
  559. //-------------------------------------------------------------------------------------
  560. // accumulation
  561. //-------------------------------------------------------------------------------------
  562. bool hasAccumulation();
  563. // provides access to full mTriggerStates mask.
  564. U32 getTriggerStateMask() const { return mTriggerStates; }
  565. };
  566. //-------------------------------------------------------------------------------------
  567. // Thread class
  568. //-------------------------------------------------------------------------------------
  569. /// 3space animation thread.
  570. ///
  571. /// An animation thread: runtime data associated with a single sequence that is
  572. /// running (or two sequences if in transition between them).
  573. ///
  574. /// A shape instance can have multiple threads running. When multiple threads are running,
  575. /// which thread/sequence controls which node or object is determined based
  576. /// on priority of the sequence.
  577. ///
  578. /// @note all thread data and methods are private (but TSShapeInstance is a friend).
  579. /// Users should treat thread pointers like keys -- they are used to ID
  580. /// the thread when interfacing with the shape, but are not manipulated
  581. /// by anything but the TSShapeInstance. See "Thread control" methods
  582. /// for more info on controlling threads.
  583. class TSThread
  584. {
  585. friend class TSShapeInstance;
  586. S32 priority;
  587. TSShapeInstance * mShapeInstance; ///< Instance of the shape that this thread animates
  588. S32 sequence; ///< Sequence this thread will perform
  589. F32 mSeqPos;
  590. F32 timeScale; ///< How fast to play through the sequence
  591. S32 keyNum1; ///< Keyframe at or before current position
  592. S32 keyNum2; ///< Keyframe at or after current position
  593. F32 keyPos;
  594. bool blendDisabled; ///< Blend with other sequences?
  595. /// if in transition...
  596. struct TransitionData
  597. {
  598. bool inTransition;
  599. F32 duration;
  600. F32 pos;
  601. F32 direction;
  602. F32 targetScale; ///< time scale for sequence we are transitioning to (during transition only)
  603. ///< this is either 1 or 0 (if 1 target sequence plays as we transition, if 0 it doesn't)
  604. TSIntegerSet oldRotationNodes; ///< nodes controlled by this thread pre-transition
  605. TSIntegerSet oldTranslationNodes; ///< nodes controlled by this thread pre-transition
  606. TSIntegerSet oldScaleNodes; ///< nodes controlled by this thread pre-transition
  607. U32 oldSequence; ///< sequence that was set before transition began
  608. F32 oldPos; ///< position of sequence before transition began
  609. } transitionData;
  610. struct
  611. {
  612. F32 start;
  613. F32 end;
  614. S32 loop;
  615. } path;
  616. bool makePath;
  617. /// given a position on the thread, choose correct keyframes
  618. /// slight difference between one-shot and cyclic sequences -- see comments below for details
  619. void selectKeyframes(F32 pos, const TSSequence * seq, S32 * k1, S32 * k2, F32 * kpos);
  620. void getGround(F32 p, MatrixF * pMat);
  621. /// @name Triggers
  622. /// Triggers are used to do something once a certain animation point has been reached.
  623. ///
  624. /// For example, when the player's foot animation hits the ground, a foot puff and
  625. /// foot print are triggered from the thread.
  626. ///
  627. /// These are called by advancePos()
  628. /// @{
  629. void animateTriggers();
  630. void activateTriggers(F32 a, F32 b);
  631. /// @}
  632. TSThread(TSShapeInstance*);
  633. TSThread() {}
  634. void setSequence(S32 seq, F32 pos);
  635. void transitionToSequence(S32 seq, F32 pos, F32 duration, bool continuePlay);
  636. void advanceTime(F32 delta);
  637. void advancePos(F32 delta);
  638. F32 getTime();
  639. F32 getPos();
  640. void setTime(F32);
  641. void setPos(F32);
  642. bool isInTransition();
  643. F32 getTimeScale();
  644. void setTimeScale(F32);
  645. F32 getDuration();
  646. F32 getScaledDuration();
  647. S32 getKeyframeCount();
  648. S32 getKeyframeNumber();
  649. void setKeyframeNumber(S32 kf);
  650. public:
  651. TSShapeInstance * getShapeInstance() { return mShapeInstance; }
  652. bool hasSequence() const { return sequence >= 0; }
  653. U32 getSeqIndex() const { return sequence; }
  654. const TSSequence* getSequence() const { return &(mShapeInstance->mShape->sequences[sequence]); }
  655. const String& getSequenceName() const { return mShapeInstance->mShape->getSequenceName(sequence); }
  656. S32 operator<(const TSThread &) const;
  657. };
  658. typedef TSShapeInstance::ObjectInstance TSObjectInstance;
  659. #endif // _TSSHAPEINSTANCE_H_