tsShapeInstance.h
Engine/source/ts/tsShapeInstance.h
Classes:
class
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
TSObjectInstance
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
