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