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. enum
  308. {
  309. MaskNodeRotation = 0x01,
  310. MaskNodePosX = 0x02,
  311. MaskNodePosY = 0x04,
  312. MaskNodePosZ = 0x08,
  313. MaskNodeBlend = 0x10,
  314. MaskNodeAll = MaskNodeRotation|MaskNodePosX|MaskNodePosY|MaskNodePosZ|MaskNodeBlend,
  315. MaskNodeAllButBlend = MaskNodeRotation|MaskNodePosX|MaskNodePosY|MaskNodePosZ,
  316. MaskNodeAllButRotation = MaskNodePosX|MaskNodePosY|MaskNodePosZ|MaskNodeBlend,
  317. MaskNodeAllButPosX = MaskNodeRotation|MaskNodePosY|MaskNodePosZ|MaskNodeBlend,
  318. MaskNodeAllButPosY = MaskNodeRotation|MaskNodePosX|MaskNodePosZ|MaskNodeBlend,
  319. MaskNodeAllButPosZ = MaskNodeRotation|MaskNodePosX|MaskNodePosY|MaskNodeBlend,
  320. MaskNodeHandsOff = 0x20, ///< meaning, don't even set to default, programmer controls it (blend still applies)
  321. MaskNodeCallback = 0x40 ///< meaning, get local transform via callback function (see setCallback)
  322. ///< callback data2 is node index, callback return value is pointer to local transform
  323. ///< Note: won't get this callback everytime you animate...application responsibility
  324. ///< to make sure matrix pointer continues to point to valid and updated local transform
  325. };
  326. /// @name Node Masking
  327. /// set node masking...
  328. /// @{
  329. void setNodeAnimationState(S32 nodeIndex, U32 animationState, TSCallback * callback = NULL);
  330. U32 getNodeAnimationState(S32 nodeIndex);
  331. /// @}
  332. /// @name Trigger states
  333. /// check trigger value
  334. /// @{
  335. bool getTriggerState(U32 stateNum, bool clearState = true);
  336. void setTriggerState(U32 stateNum, bool on);
  337. void setTriggerStateBit(U32 stateBit, bool on);
  338. /// @}
  339. /// @name Debris Management
  340. /// @{
  341. void incDebrisRefCount() { ++debrisRefCount; }
  342. void decDebrisRefCount() { debrisRefCount > 0 ? --debrisRefCount : 0; }
  343. U32 getDebrisRefCount() const { return debrisRefCount; }
  344. /// @}
  345. /// @name AlphaAlways
  346. /// AlphaAlways allows the entire model to become translucent at the same value
  347. /// @{
  348. void setAlphaAlways(F32 value) { mAlphaAlways = (value<0.99f); mAlphaAlwaysValue = value; }
  349. F32 getAlphaAlwaysValue() const { return mAlphaAlways ? mAlphaAlwaysValue : 1.0f; }
  350. bool getAlphaAlways() const { return mAlphaAlways; }
  351. /// @}
  352. //-------------------------------------------------------------------------------------
  353. // private methods for setting up and affecting animation
  354. //-------------------------------------------------------------------------------------
  355. private:
  356. /// @name Private animation methods
  357. /// These are private methods for setting up and affecting animation
  358. /// @{
  359. void sortThreads();
  360. void updateTransitions();
  361. void handleDefaultScale(S32 a, S32 b, TSIntegerSet & scaleBeenSet);
  362. void updateTransitionNodeTransforms(TSIntegerSet& transitionNodes);
  363. void handleTransitionNodes(S32 a, S32 b);
  364. void handleNodeScale(S32 a, S32 b);
  365. void handleAnimatedScale(TSThread *, S32 a, S32 b, TSIntegerSet &);
  366. void handleMaskedPositionNode(TSThread *, S32 nodeIndex, S32 offset);
  367. void handleBlendSequence(TSThread *, S32 a, S32 b);
  368. void checkScaleCurrentlyAnimated();
  369. /// @}
  370. //-------------------------------------------------------------------------------------
  371. // animate, render, & detail control
  372. //-------------------------------------------------------------------------------------
  373. public:
  374. struct RenderData
  375. {
  376. MeshObjectInstance* currentObjectInstance;
  377. S32 detailLevel;
  378. S32 materialIndex;
  379. const Point3F * objectScale;
  380. };
  381. /// Scale pixel size by this amount when selecting
  382. /// detail levels.
  383. static F32 smDetailAdjust;
  384. /// If this is set to a positive pixel value shapes
  385. /// with a smaller pixel size than this will skip
  386. /// rendering entirely.
  387. static F32 smSmallestVisiblePixelSize;
  388. /// never choose detail level number below this value (except if
  389. /// only way to get a visible detail)
  390. static S32 smNumSkipRenderDetails;
  391. /// For debugging / metrics.
  392. static F32 smLastScreenErrorTolerance;
  393. static F32 smLastScaledDistance;
  394. static F32 smLastPixelSize;
  395. /// Debugging
  396. /// @{
  397. /// Renders the vertex normals assuming the GFX state
  398. /// is setup for rendering in model space.
  399. void renderDebugNormals( F32 normalScalar, S32 dl );
  400. /// Render all node transforms as small axis gizmos. It is recommended
  401. /// that prior to calling this, shapeInstance::animate is called so that
  402. /// nodes are in object space and that the GFX state is setup for
  403. /// rendering in model space.
  404. void renderDebugNodes();
  405. /// Print mesh data to the console, valid String parameters
  406. /// are Visible, Hidden, or All.
  407. void listMeshes( const String &state ) const;
  408. /// @}
  409. void render( const TSRenderState &rdata );
  410. void render( const TSRenderState &rdata, S32 dl, F32 intraDL = 0.0f );
  411. bool bufferNeedsUpdate(S32 objectDetail, S32 start, S32 end);
  412. void animate() { animate( mCurrentDetailLevel ); }
  413. void animate(S32 dl);
  414. void animateNodes(S32 ss);
  415. void animateVisibility(S32 ss);
  416. void animateFrame(S32 ss);
  417. void animateMatFrame(S32 ss);
  418. void animateSubtrees(bool forceFull = true);
  419. void animateNodeSubtrees(bool forceFull = true);
  420. /// Sets the 'forceHidden' state on the named mesh.
  421. /// @see MeshObjectInstance::forceHidden
  422. void setMeshForceHidden( const char *meshName, bool hidden );
  423. /// Sets the 'forceHidden' state on a mesh.
  424. /// @see MeshObjectInstance::forceHidden
  425. void setMeshForceHidden( S32 meshIndex, bool hidden );
  426. /// @name Animation Scale
  427. /// Query about animated scale
  428. /// @{
  429. bool animatesScale() { return (mShape->mFlags & TSShape::AnyScale) != 0; }
  430. bool animatesUniformScale() { return (mShape->mFlags & TSShape::UniformScale) != 0; }
  431. bool animatesAlignedScale() { return (mShape->mFlags & TSShape::AlignedScale) != 0; }
  432. bool animatesArbitraryScale() { return (mShape->mFlags & TSShape::ArbitraryScale) != 0; }
  433. bool scaleCurrentlyAnimated() { return mScaleCurrentlyAnimated; }
  434. /// @}
  435. //
  436. bool inTransition() { return !mTransitionThreads.empty(); }
  437. /// @name Ground Transforms
  438. /// The animator of a model can make the bounding box
  439. /// animate along with the object. Doing so will move the object with the bounding box.
  440. /// The ground transform turns the world bounding box into the post-animation bounding box
  441. /// when such a technique is used. However, few models actually use this technique.
  442. /// @{
  443. void animateGround(); ///< clears previous ground transform
  444. MatrixF & getGroundTransform() { return mGroundTransform; }
  445. void deltaGround(TSThread *, F32 start, F32 end, MatrixF * mat = NULL);
  446. void deltaGround1(TSThread *, F32 start, F32 end, MatrixF& mat);
  447. /// @}
  448. U32 getNumDetails() const { return mShape ? mShape->details.size() : 0; }
  449. S32 getCurrentDetail() const { return mCurrentDetailLevel; }
  450. F32 getCurrentIntraDetail() const { return mCurrentIntraDetailLevel; }
  451. void setCurrentDetail( S32 dl, F32 intraDL = 1.0f );
  452. /// Helper function which internally calls setDetailFromDistance.
  453. S32 setDetailFromPosAndScale( const SceneRenderState *state,
  454. const Point3F &pos,
  455. const Point3F &scale );
  456. /// Selects the current detail level using the scaled
  457. /// distance between your object and the camera.
  458. ///
  459. /// @see TSShape::Detail.
  460. S32 setDetailFromDistance( const SceneRenderState *state, F32 scaledDist );
  461. /// Sets the current detail level using the legacy screen error metric.
  462. S32 setDetailFromScreenError( F32 errorTOL );
  463. enum
  464. {
  465. TransformDirty = BIT(0),
  466. VisDirty = BIT(1),
  467. FrameDirty = BIT(2),
  468. MatFrameDirty = BIT(3),
  469. ThreadDirty = BIT(4),
  470. AllDirtyMask = TransformDirty | VisDirty | FrameDirty | MatFrameDirty | ThreadDirty
  471. };
  472. U32 * mDirtyFlags;
  473. void setDirty(U32 dirty);
  474. void clearDirty(U32 dirty);
  475. //-------------------------------------------------------------------------------------
  476. // collision interface routines
  477. //-------------------------------------------------------------------------------------
  478. public:
  479. bool buildPolyList(AbstractPolyList *, S32 dl);
  480. bool getFeatures(const MatrixF& mat, const Point3F& n, ConvexFeature*, S32 dl);
  481. bool castRay(const Point3F & start, const Point3F & end, RayInfo *,S32 dl);
  482. bool castRayRendered(const Point3F & start, const Point3F & end, RayInfo *,S32 dl);
  483. bool quickLOS(const Point3F & start, const Point3F & end, S32 dl) { return castRay(start,end,NULL,dl); }
  484. Point3F support(const Point3F & v, S32 dl);
  485. void computeBounds(S32 dl, Box3F & bounds); ///< uses current transforms to compute bounding box around a detail level
  486. ///< see like named method on shape if you want to use default transforms
  487. bool buildPolyListOpcode( S32 dl, AbstractPolyList *polyList, const Box3F &box );
  488. bool castRayOpcode( S32 objectDetail, const Point3F & start, const Point3F & end, RayInfo *);
  489. bool buildConvexOpcode( const MatrixF &objMat, const Point3F &objScale, S32 objectDetail, const Box3F &bounds, Convex *c, Convex *list );
  490. //-------------------------------------------------------------------------------------
  491. // Thread Control
  492. //-------------------------------------------------------------------------------------
  493. /// @name Thread Control
  494. /// Threads! In order to animate an object, first you need to have an animation in the object.
  495. /// Then, you need to get the TSShape of the object:
  496. /// @code
  497. /// TSShape* shape = mShapeInstance->getShape());
  498. /// @endcode
  499. /// Next, get the sequence and store::
  500. /// @code
  501. /// S32 seq = shape->findSequence("foo"));
  502. /// @endcode
  503. /// Create a new thread (if needed):
  504. /// @code
  505. /// TSThread* thread = mShapeInstance->addThread();
  506. /// @endcode
  507. /// Finally, set the position in the sequence:
  508. /// @code
  509. /// mShapeInstance->setSequence(thread, seq, 0)
  510. /// @endcode
  511. /// @{
  512. public:
  513. TSThread * addThread(); ///< Create a new thread
  514. TSThread * getThread(S32 threadNumber); ///< @note threads can change order, best to hold
  515. ///< onto a thread from the start
  516. void destroyThread(TSThread * thread); ///< Destroy a thread!
  517. U32 threadCount(); ///< How many threads are there?
  518. void setSequence(TSThread *, S32 seq, F32 pos);///< Get the thread a sequence
  519. /// Transition to a sequence
  520. void transitionToSequence(TSThread *, S32 seq, F32 pos, F32 duration, bool continuePlay);
  521. void clearTransition(TSThread *); ///< Stop transitions
  522. U32 getSequence(TSThread *); ///< Get the sequence of the thread
  523. void setBlendEnabled(TSThread *, bool blendOn);///< Set whether or not the thread will blend
  524. bool getBlendEnabled(TSThread *); ///< Does this thread blend?
  525. void setPriority(TSThread *, F32 priority); ///< Set thread priority
  526. F32 getPriority(TSThread * thread); ///< Get thread priority
  527. F32 getTime(TSThread * thread); ///< Get how long the thread has been playing
  528. F32 getPos(TSThread * thread); ///< Get the position in the thread
  529. void setTime(TSThread * thread, F32 time); ///< Set how long into the thread to use
  530. void setPos(TSThread * thread, F32 pos); ///< Set the position of the thread
  531. bool isInTransition(TSThread * thread); ///< Is this thread in transition?
  532. F32 getTimeScale(TSThread * thread); ///< Get the time scale of the thread
  533. void setTimeScale(TSThread * thread, F32); ///< Set the time scale of the thread
  534. F32 getDuration(TSThread * thread); ///< Get the duration of the thread
  535. F32 getScaledDuration(TSThread * thread); ///< Get the duration of the thread with the scale factored in
  536. S32 getKeyframeCount(TSThread * thread); ///< Get the number of keyframes
  537. S32 getKeyframeNumber(TSThread * thread); ///< Get which keyframe the thread is on
  538. /// Set which keyframe the thread is on
  539. void setKeyframeNumber(TSThread * thread, S32 kf);
  540. void advanceTime(F32 delta, TSThread *); ///< advance time on a particular thread
  541. void advanceTime(F32 delta); ///< advance time on all threads
  542. void advancePos(F32 delta, TSThread *); ///< advance pos on a particular thread
  543. void advancePos(F32 delta); ///< advance pos on all threads
  544. /// @}
  545. //-------------------------------------------------------------------------------------
  546. // constructors, destructors, initialization, io
  547. //-------------------------------------------------------------------------------------
  548. TSShapeInstance( const Resource<TSShape> & shape, bool loadMaterials = true);
  549. TSShapeInstance( TSShape * pShape, bool loadMaterials = true);
  550. ~TSShapeInstance();
  551. void buildInstanceData(TSShape *, bool loadMaterials);
  552. void initNodeTransforms();
  553. void initMeshObjects();
  554. void dump(Stream &);
  555. void dumpNode(Stream &, S32 level, S32 nodeIndex, Vector<S32> & detailSizes);
  556. void *mData; ///< available for use by app...initialized to 0
  557. void prepCollision();
  558. //-------------------------------------------------------------------------------------
  559. // accumulation
  560. //-------------------------------------------------------------------------------------
  561. bool hasAccumulation();
  562. // provides access to full mTriggerStates mask.
  563. U32 getTriggerStateMask() const { return mTriggerStates; }
  564. };
  565. //-------------------------------------------------------------------------------------
  566. // Thread class
  567. //-------------------------------------------------------------------------------------
  568. /// 3space animation thread.
  569. ///
  570. /// An animation thread: runtime data associated with a single sequence that is
  571. /// running (or two sequences if in transition between them).
  572. ///
  573. /// A shape instance can have multiple threads running. When multiple threads are running,
  574. /// which thread/sequence controls which node or object is determined based
  575. /// on priority of the sequence.
  576. ///
  577. /// @note all thread data and methods are private (but TSShapeInstance is a friend).
  578. /// Users should treat thread pointers like keys -- they are used to ID
  579. /// the thread when interfacing with the shape, but are not manipulated
  580. /// by anything but the TSShapeInstance. See "Thread control" methods
  581. /// for more info on controlling threads.
  582. class TSThread
  583. {
  584. friend class TSShapeInstance;
  585. S32 priority;
  586. TSShapeInstance * mShapeInstance; ///< Instance of the shape that this thread animates
  587. S32 sequence; ///< Sequence this thread will perform
  588. F32 mSeqPos;
  589. F32 timeScale; ///< How fast to play through the sequence
  590. S32 keyNum1; ///< Keyframe at or before current position
  591. S32 keyNum2; ///< Keyframe at or after current position
  592. F32 keyPos;
  593. bool blendDisabled; ///< Blend with other sequences?
  594. /// if in transition...
  595. struct TransitionData
  596. {
  597. bool inTransition;
  598. F32 duration;
  599. F32 pos;
  600. F32 direction;
  601. F32 targetScale; ///< time scale for sequence we are transitioning to (during transition only)
  602. ///< this is either 1 or 0 (if 1 target sequence plays as we transition, if 0 it doesn't)
  603. TSIntegerSet oldRotationNodes; ///< nodes controlled by this thread pre-transition
  604. TSIntegerSet oldTranslationNodes; ///< nodes controlled by this thread pre-transition
  605. TSIntegerSet oldScaleNodes; ///< nodes controlled by this thread pre-transition
  606. U32 oldSequence; ///< sequence that was set before transition began
  607. F32 oldPos; ///< position of sequence before transition began
  608. } transitionData;
  609. struct
  610. {
  611. F32 start;
  612. F32 end;
  613. S32 loop;
  614. } path;
  615. bool makePath;
  616. /// given a position on the thread, choose correct keyframes
  617. /// slight difference between one-shot and cyclic sequences -- see comments below for details
  618. void selectKeyframes(F32 pos, const TSSequence * seq, S32 * k1, S32 * k2, F32 * kpos);
  619. void getGround(F32 p, MatrixF * pMat);
  620. /// @name Triggers
  621. /// Triggers are used to do something once a certain animation point has been reached.
  622. ///
  623. /// For example, when the player's foot animation hits the ground, a foot puff and
  624. /// foot print are triggered from the thread.
  625. ///
  626. /// These are called by advancePos()
  627. /// @{
  628. void animateTriggers();
  629. void activateTriggers(F32 a, F32 b);
  630. /// @}
  631. TSThread(TSShapeInstance*);
  632. TSThread() {}
  633. void setSequence(S32 seq, F32 pos);
  634. void transitionToSequence(S32 seq, F32 pos, F32 duration, bool continuePlay);
  635. void advanceTime(F32 delta);
  636. void advancePos(F32 delta);
  637. F32 getTime();
  638. F32 getPos();
  639. void setTime(F32);
  640. void setPos(F32);
  641. bool isInTransition();
  642. F32 getTimeScale();
  643. void setTimeScale(F32);
  644. F32 getDuration();
  645. F32 getScaledDuration();
  646. S32 getKeyframeCount();
  647. S32 getKeyframeNumber();
  648. void setKeyframeNumber(S32 kf);
  649. public:
  650. TSShapeInstance * getShapeInstance() { return mShapeInstance; }
  651. bool hasSequence() const { return sequence >= 0; }
  652. U32 getSeqIndex() const { return sequence; }
  653. const TSSequence* getSequence() const { return &(mShapeInstance->mShape->sequences[sequence]); }
  654. const String& getSequenceName() const { return mShapeInstance->mShape->getSequenceName(sequence); }
  655. S32 operator<(const TSThread &) const;
  656. };
  657. typedef TSShapeInstance::ObjectInstance TSObjectInstance;
  658. #endif // _TSSHAPEINSTANCE_H_