tsShapeInstance.h 30 KB

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