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//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~// 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