Torque3D Documentation / _generateds / tsShapeInstance.h

tsShapeInstance.h

Engine/source/ts/tsShapeInstance.h

More...

Classes:

class

An instance of a 3space shape.

class

These are set up by default based on shape data.

class

Base class for all renderable objects, including mesh objects and decal objects.

class

3space animation thread.

class

if in transition...

Public Typedefs

Detailed Description

Public Typedefs

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