VPathObject.cpp
Engine/source/Verve/VPath/VPathObject.cpp
Public Variables
Public Functions
Detailed Description
Public Variables
EndImplementEnumType
U32 gOrientationTypeBits
Public Functions
ImplementEnumType(VPathObjectOrientationType , "" )
1 2//----------------------------------------------------------------------------- 3// Verve 4// Copyright (C) 2014 - Violent Tulip 5// 6// Permission is hereby granted, free of charge, to any person obtaining a copy 7// of this software and associated documentation files (the "Software"), to 8// deal in the Software without restriction, including without limitation the 9// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 10// sell copies of the Software, and to permit persons to whom the Software is 11// furnished to do so, subject to the following conditions: 12// 13// The above copyright notice and this permission notice shall be included in 14// all copies or substantial portions of the Software. 15// 16// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 21// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 22// IN THE SOFTWARE. 23//----------------------------------------------------------------------------- 24#include "VPathObject.h" 25#include "VPath.h" 26 27#include "core/stream/bitStream.h" 28#include "sim/netConnection.h" 29 30//----------------------------------------------------------------------------- 31 32static U32 gOrientationTypeBits = getBinLog2( getNextPow2( VPathObject::k_OrientationTypeSize ) ); 33 34//----------------------------------------------------------------------------- 35 36VPathObject::VPathObject( void ) : 37 mActive( false ), 38 mLastTime( 0 ), 39 mLastDelta( 0.f ), 40 mObject( NULL ), 41 mTimeInterp( 0.f ), 42 mPathInterp( 0.f ), 43 mPosition( 0.f, 0.f, 0.f ), 44 mOffset( 0.f, 0.f, 0.f ), 45 mOrientation( 0.f, 1.f, 0.f ), 46 mForward( true ), 47 mSpeed( 10.f ), 48 mSourceNode( 0 ), 49 mDestinationNode( 0 ), 50 mStartNode( 0 ), 51 mEndNode( 0 ) 52{ 53 // Init. 54 mOrientationMode.Type = k_OrientationToPath; 55 mOrientationMode.Object = NULL; 56 mOrientationMode.Point = Point3F::Zero; 57 58 // Set the initial mask. 59 mNetState.setMaskBits( k_StateInit ); 60 61 // Reset Time. 62 resetTime(); 63 64 // Reset Delta. 65 resetDelta(); 66 67 VECTOR_SET_ASSOCIATION( mNetState ); 68} 69 70VPathObject::~VPathObject( void ) 71{ 72 // Void. 73} 74 75//----------------------------------------------------------------------------- 76// 77// Network Methods. 78// 79//----------------------------------------------------------------------------- 80 81U32 VPathObject::packUpdate( NetConnection *pConnection, BitStream *pStream ) 82{ 83 // Init Return Mask. 84 U32 retMask = 0; 85 86 // Fetch State. 87 VNetStateInfo *state = getState( pConnection ); 88 89 // Write Active. 90 pStream->writeFlag( mActive ); 91 92 // Send Object Update? 93 if ( pStream->writeFlag( state->Mask & k_StateUpdateObject ) ) 94 { 95 // Successful Send? 96 bool success = false; 97 98 // Valid Object? 99 if ( !mObject ) 100 { 101 // No Object. 102 pStream->writeFlag( false ); 103 } 104 else 105 { 106 // Write Ghost Index. 107 const S32 ghostIndex = pConnection->getGhostIndex( mObject ); 108 if ( pStream->writeFlag( ghostIndex != -1 ) ) 109 { 110 // Write Ghost Id. 111 pStream->writeInt( ghostIndex, NetConnection::GhostIdBitSize ); 112 113 // Success! 114 success = true; 115 // Clear Update. 116 state->Mask &= ~<a href="/coding/class/structvpathobject/#structvpathobject_1acf711c693be92b0c218d6371d683c497a579474bcfe34691cd0ea99f7b3a7bb73">k_StateUpdateObject</a>; 117 } 118 } 119 120 if ( !success ) 121 { 122 // Try Again Later. 123 retMask |= VPath::ObjectUpdateMask; 124 } 125 } 126 127 // Send Mount Update? 128 if ( pStream->writeFlag( state->Mask & k_StateUpdateMount ) ) 129 { 130 // Successful Send? 131 bool success = false; 132 133 // Valid Objects? 134 if ( !mObject || !mObject->getObjectMount() || ( state->Mask & k_StateUpdateObject ) ) 135 { 136 // No Object. 137 pStream->writeFlag( false ); 138 } 139 else 140 { 141 // Write Ghost Index. 142 const S32 ghostIndex = pConnection->getGhostIndex( mObject->getObjectMount() ); 143 if ( pStream->writeFlag( ghostIndex != -1 ) ) 144 { 145 // Write Ghost Id. 146 pStream->writeInt( ghostIndex, NetConnection::GhostIdBitSize ); 147 // Write Mount Node. 148 pStream->writeInt( mObject->getMountNode(), SceneObject::NumMountPointBits ); 149 150 // Success! 151 success = true; 152 // Clear Update. 153 state->Mask &= ~<a href="/coding/class/structvpathobject/#structvpathobject_1acf711c693be92b0c218d6371d683c497a4ad23159bc855913ecd58dbb643db4cb">k_StateUpdateMount</a>; 154 } 155 } 156 157 if ( !success ) 158 { 159 // Try Again Later. 160 retMask |= VPath::ObjectUpdateMask; 161 } 162 } 163 164 // Send Position Update? 165 if ( pStream->writeFlag( state->Mask & k_StateUpdatePosition ) ) 166 { 167 // Write Position. 168 pStream->write( mTimeInterp ); 169 pStream->write( mPathInterp ); 170 171 pStream->write( mPosition.x ); 172 pStream->write( mPosition.y ); 173 pStream->write( mPosition.z ); 174 175 pStream->write( mOrientation.x ); 176 pStream->write( mOrientation.y ); 177 pStream->write( mOrientation.z ); 178 179 pStream->writeInt( mSourceNode, VPath::gMaxNodeBits ); 180 pStream->writeInt( mDestinationNode, VPath::gMaxNodeBits ); 181 182 // Clear Update. 183 state->Mask &= ~<a href="/coding/class/structvpathobject/#structvpathobject_1acf711c693be92b0c218d6371d683c497a705ae34141c4f6a284a0f656b092e460">k_StateUpdatePosition</a>; 184 } 185 186 // Send State Update? 187 if ( pStream->writeFlag( state->Mask & k_StateUpdateState ) ) 188 { 189 // Successful Send? 190 bool success = true; 191 192 // Write State. 193 pStream->writeInt( mOrientationMode.Type, gOrientationTypeBits ); 194 195 switch ( mOrientationMode.Type ) 196 { 197 case k_OrientationToObject : 198 { 199 // Write Ghost Index. 200 const S32 ghostIndex = pConnection->getGhostIndex( mOrientationMode.Object ); 201 if ( pStream->writeFlag( ghostIndex != -1 ) ) 202 { 203 pStream->writeInt( ghostIndex, NetConnection::GhostIdBitSize ); 204 } 205 else 206 { 207 // Failed. 208 success = false; 209 } 210 211 } break; 212 213 case k_OrientationToPoint : 214 { 215 // Write Point. 216 pStream->write( mOrientationMode.Point.x ); 217 pStream->write( mOrientationMode.Point.y ); 218 pStream->write( mOrientationMode.Point.z ); 219 220 } break; 221 } 222 223 pStream->writeFlag( mForward ); 224 pStream->write( mSpeed ); 225 226 // Write Offset. 227 pStream->write( mOffset.x ); 228 pStream->write( mOffset.y ); 229 pStream->write( mOffset.z ); 230 231 pStream->writeInt( mStartNode, VPath::gMaxNodeBits ); 232 pStream->writeInt( mEndNode, VPath::gMaxNodeBits ); 233 234 if ( success ) 235 { 236 // Clear Update. 237 state->Mask &= ~<a href="/coding/class/structvpathobject/#structvpathobject_1acf711c693be92b0c218d6371d683c497aeb785534ac8e27948cd84e4ec3b2a374">k_StateUpdateState</a>; 238 } 239 else 240 { 241 // Try Again Later. 242 retMask |= VPath::ObjectUpdateMask; 243 } 244 } 245 246 // Return Mask. 247 return retMask; 248} 249 250void VPathObject::unpackUpdate( NetConnection *pConnection, BitStream *pStream ) 251{ 252 // Read Active. 253 setActive( pStream->readFlag() ); 254 255 // Update Object? 256 if ( pStream->readFlag() ) 257 { 258 if ( pStream->readFlag() ) 259 { 260 // Read Ghost Index. 261 const S32 ghostIndex = pStream->readInt( NetConnection::GhostIdBitSize ); 262 263 // Resolve Object. 264 setObject( static_cast<SceneObject*>( pConnection->resolveGhost( ghostIndex ) ) ); 265 266 // Reset Delta. 267 resetDelta(); 268 } 269 else 270 { 271 // Clear Object. 272 mObject = NULL; 273 } 274 } 275 276 // Update Mount? 277 if ( pStream->readFlag() ) 278 { 279 if ( pStream->readFlag() ) 280 { 281 // Read Ghost Index. 282 const S32 ghostIndex = pStream->readInt( NetConnection::GhostIdBitSize ); 283 // Read Mount Node. 284 const S32 nodeIndex = pStream->readInt( SceneObject::NumMountPointBits ); 285 286 // Resolve Object. 287 SceneObject *mountObject = static_cast<SceneObject*>( pConnection->resolveGhost( ghostIndex ) ); 288 // Mount Object. 289 mountObject->mountObject( mObject, nodeIndex ); 290 } 291 else 292 { 293 // ... unmount? 294 } 295 } 296 297 // Update Position? 298 if ( pStream->readFlag() ) 299 { 300 // Read Updates. 301 pStream->read( &mTimeInterp ); 302 pStream->read( &mPathInterp ); 303 304 pStream->read( &mPosition.x ); 305 pStream->read( &mPosition.y ); 306 pStream->read( &mPosition.z ); 307 308 pStream->read( &mOrientation.x ); 309 pStream->read( &mOrientation.y ); 310 pStream->read( &mOrientation.z ); 311 312 mSourceNode = pStream->readInt( VPath::gMaxNodeBits ); 313 mDestinationNode = pStream->readInt( VPath::gMaxNodeBits ); 314 } 315 316 // Update Heading? 317 if ( pStream->readFlag() ) 318 { 319 // Read Orientation Mode. 320 mOrientationMode.Type = ( eOrientationType )pStream->readInt( gOrientationTypeBits ); 321 322 switch ( mOrientationMode.Type ) 323 { 324 case VPathObject::k_OrientationToObject : 325 { 326 if ( pStream->readFlag() ) 327 { 328 // Read Ghost Index. 329 const S32 ghostIndex = pStream->readInt( NetConnection::GhostIdBitSize ); 330 // Resolve Object. 331 mOrientationMode.Object = static_cast<SceneObject*>( pConnection->resolveGhost( ghostIndex ) ); 332 } 333 334 } break; 335 336 case VPathObject::k_OrientationToPoint : 337 { 338 // Read Point. 339 pStream->read( &mOrientationMode.Point.x ); 340 pStream->read( &mOrientationMode.Point.y ); 341 pStream->read( &mOrientationMode.Point.z ); 342 343 } break; 344 } 345 346 // Read Updates. 347 mForward = pStream->readFlag(); 348 349 pStream->read( &mSpeed ); 350 351 pStream->read( &mOffset.x ); 352 pStream->read( &mOffset.y ); 353 pStream->read( &mOffset.z ); 354 355 mStartNode = pStream->readInt( VPath::gMaxNodeBits ); 356 mEndNode = pStream->readInt( VPath::gMaxNodeBits ); 357 } 358} 359 360//----------------------------------------------------------------------------- 361// 362// Property Methods. 363// 364//----------------------------------------------------------------------------- 365 366Point3F VPathObject::getWorldPosition( void ) 367{ 368 return ( mPosition + mOffset ); 369} 370 371Point3F VPathObject::getRenderWorldPosition( const F32 &pDelta ) 372{ 373 return ( getPositionDelta( pDelta ) + mOffset ); 374} 375 376MatrixF VPathObject::getTransform( void ) 377{ 378 MatrixF mat( true ); 379 switch ( mOrientationMode.Type ) 380 { 381 case k_OrientationInterpolate : 382 case k_OrientationToObject : 383 case k_OrientationToPoint : 384 case k_OrientationToPath : 385 { 386 // Y-Axis. 387 VectorF yVec = mOrientation; 388 yVec.normalize(); 389 390 // X-Axis. 391 VectorF xVec = mCross( yVec, VPath::gBezierUp ); 392 xVec.normalize(); 393 394 // Z-Axis. 395 VectorF zVec = mCross( xVec, yVec ); 396 zVec.normalize(); 397 398 // Setup Object Transform. 399 mat.setColumn( 0, xVec ); 400 mat.setColumn( 1, yVec ); 401 mat.setColumn( 2, zVec ); 402 mat.setColumn( 3, getWorldPosition() ); 403 404 } break; 405 406 case k_OrientationFree : 407 { 408 // Fetch Current Transform. 409 mat = mObject->getTransform(); 410 mat.setPosition( getWorldPosition() ); 411 412 } break; 413 } 414 415 // Return. 416 return mat; 417} 418 419MatrixF VPathObject::getRenderTransform( const F32 &pDelta ) 420{ 421 MatrixF mat( true ); 422 switch ( mOrientationMode.Type ) 423 { 424 case k_OrientationInterpolate : 425 case k_OrientationToObject : 426 case k_OrientationToPoint : 427 case k_OrientationToPath : 428 { 429 // Y-Axis. 430 VectorF yVec = getOrientationDelta( pDelta ); 431 yVec.normalize(); 432 433 // X-Axis. 434 VectorF xVec = mCross( yVec, VPath::gBezierUp ); 435 xVec.normalize(); 436 437 // Z-Axis. 438 VectorF zVec = mCross( xVec, yVec ); 439 zVec.normalize(); 440 441 // Setup Object Transform. 442 mat.setColumn( 0, xVec ); 443 mat.setColumn( 1, yVec ); 444 mat.setColumn( 2, zVec ); 445 mat.setColumn( 3, getRenderWorldPosition( pDelta ) ); 446 447 } break; 448 449 case k_OrientationFree : 450 { 451 // Fetch Current Transform. 452 mat = mObject->getRenderTransform(); 453 mat.setPosition( getRenderWorldPosition( pDelta ) ); 454 455 } break; 456 } 457 458 // Return. 459 return mat; 460} 461 462void VPathObject::setActive( const bool &pActive ) 463{ 464 // Update? 465 if ( pActive != mActive ) 466 { 467 // Apply. 468 mActive = pActive; 469 // Flag Update. 470 setMaskBits( k_StateUpdatePosition ); 471 } 472} 473 474void VPathObject::setObject( SceneObject *pObject ) 475{ 476 // Update? 477 if ( pObject != mObject ) 478 { 479 // Apply. 480 mObject = pObject; 481 // Flag Update. 482 setMaskBits( k_StateUpdateObject ); 483 } 484} 485 486void VPathObject::setTimeInterp( const F32 &pInterp ) 487{ 488 // Update? 489 if ( mTimeInterp != pInterp ) 490 { 491 // Apply. 492 mTimeInterp = pInterp; 493 // Flag Update. 494 setMaskBits( k_StateUpdatePosition ); 495 } 496} 497 498void VPathObject::setPathInterp( const F32 &pInterp ) 499{ 500 // Update? 501 if ( mPathInterp != pInterp ) 502 { 503 // Apply. 504 mPathInterp = pInterp; 505 // Flag Update. 506 setMaskBits( k_StateUpdatePosition ); 507 } 508} 509 510void VPathObject::setPosition( const Point3F &pPosition ) 511{ 512 // Update? 513 if ( mPosition != pPosition ) 514 { 515 // Update. 516 mPosition = pPosition; 517 // Flag Update. 518 setMaskBits( k_StateUpdatePosition ); 519 } 520} 521 522void VPathObject::setOffset( const Point3F &pOffset ) 523{ 524 // Update? 525 if ( mOffset != pOffset ) 526 { 527 // Update. 528 mOffset = pOffset; 529 // Flag Update. 530 setMaskBits( k_StateUpdateState ); 531 } 532} 533 534void VPathObject::setOrientation( const VectorF &pOrientation ) 535{ 536 // Update? 537 if ( mOrientation != pOrientation ) 538 { 539 // Update. 540 mOrientation = pOrientation; 541 // Flag Update. 542 setMaskBits( k_StateUpdatePosition ); 543 } 544} 545 546void VPathObject::setOrientationMode( const eOrientationType &pType ) 547{ 548 // Update? 549 if ( mOrientationMode.Type != pType ) 550 { 551 // Update. 552 mOrientationMode.Type = pType; 553 // Flag Update. 554 setMaskBits( k_StateUpdateState ); 555 } 556} 557 558void VPathObject::setOrientationMode( const eOrientationType &pType, SceneObject *pObject ) 559{ 560 AssertFatal( ( pType == k_OrientationToObject ) && ( pObject != NULL ), "VPathObject::setOrientationMode() - Invalid mOrientation Type." ); 561 562 // Update? 563 if ( ( mOrientationMode.Type != pType ) || ( mOrientationMode.Object != pObject ) ) 564 { 565 // Update. 566 mOrientationMode.Type = pType; 567 mOrientationMode.Object = pObject; 568 // Flag Update. 569 setMaskBits( k_StateUpdateState ); 570 } 571} 572 573void VPathObject::setOrientationMode( const eOrientationType &pType, const Point3F &pPoint ) 574{ 575 AssertFatal( pType == k_OrientationToPoint, "VPathObject::setOrientationMode() - Invalid mOrientation Type." ); 576 577 // Update? 578 if ( ( mOrientationMode.Type != pType ) || ( mOrientationMode.Point != pPoint ) ) 579 { 580 // Update. 581 mOrientationMode.Type = pType; 582 mOrientationMode.Point = pPoint; 583 // Flag Update. 584 setMaskBits( k_StateUpdateState ); 585 } 586} 587 588void VPathObject::setForward( const bool &pForward ) 589{ 590 // Update? 591 if ( mForward != pForward ) 592 { 593 // Update. 594 mForward = pForward; 595 // Flag Update. 596 setMaskBits( k_StateUpdateState ); 597 } 598} 599 600void VPathObject::setSpeed( const F32 &pSpeed ) 601{ 602 // Update? 603 if ( mSpeed != pSpeed ) 604 { 605 // Update. 606 mSpeed = pSpeed; 607 // Flag Update. 608 setMaskBits( k_StateUpdateState ); 609 } 610} 611 612void VPathObject::setNode( const S32 &pSourceNodeIndex, const S32 &pDestinationNodeIndex ) 613{ 614 // Update? 615 if ( ( mSourceNode != pSourceNodeIndex ) || ( mDestinationNode != pDestinationNodeIndex ) ) 616 { 617 // Update. 618 mSourceNode = pSourceNodeIndex; 619 mDestinationNode = pDestinationNodeIndex; 620 // Flag Update. 621 setMaskBits( k_StateUpdatePosition ); 622 } 623} 624 625void VPathObject::setStartNode( const S32 &pNodeIndex ) 626{ 627 // Update? 628 if ( mStartNode != pNodeIndex ) 629 { 630 // Update. 631 mStartNode = pNodeIndex; 632 // Flag Update. 633 setMaskBits( k_StateUpdateState ); 634 } 635} 636 637void VPathObject::setEndNode( const S32 &pNodeIndex ) 638{ 639 // Update? 640 if ( mEndNode != pNodeIndex ) 641 { 642 // Update. 643 mEndNode = pNodeIndex; 644 // Flag Update. 645 setMaskBits( k_StateUpdateState ); 646 } 647} 648 649//----------------------------------------------------------------------------- 650// 651// Delta Methods. 652// 653//----------------------------------------------------------------------------- 654 655void VPathObject::resetDelta( void ) 656{ 657 mDelta.Position[0] = mPosition; 658 mDelta.Position[1] = mPosition; 659 mDelta.Orientation[0] = mOrientation; 660 mDelta.Orientation[1] = mOrientation; 661} 662 663void VPathObject::resetDelta( const Point3F &pPosition, const VectorF &pOrientation ) 664{ 665 mDelta.Position[0] = pPosition; 666 mDelta.Position[1] = pPosition; 667 mDelta.Orientation[0] = pOrientation; 668 mDelta.Orientation[1] = pOrientation; 669} 670 671void VPathObject::popDelta( void ) 672{ 673 mDelta.Position[0] = mDelta.Position[1]; 674 mDelta.Orientation[0] = mDelta.Orientation[1]; 675} 676 677void VPathObject::pushDelta( const Point3F &pPosition, const VectorF &pOrientation ) 678{ 679 mDelta.Position[1] = pPosition; 680 mDelta.Orientation[1] = pOrientation; 681} 682 683Point3F VPathObject::getPositionDelta( const F32 &pInterp ) 684{ 685 Point3F interpPosition; 686 interpPosition.interpolate( mDelta.Position[1], mDelta.Position[0], pInterp ); 687 688 return interpPosition; 689} 690 691VectorF VPathObject::getOrientationDelta( const F32 &pInterp ) 692{ 693 VectorF interpOrientation; 694 interpOrientation.interpolate( mDelta.Orientation[1], mDelta.Orientation[0], pInterp ); 695 interpOrientation.normalize(); 696 697 return interpOrientation; 698} 699 700//----------------------------------------------------------------------------- 701// 702// Enumeration Methods. 703// 704//----------------------------------------------------------------------------- 705 706// Implement the Orientation Type enum list. 707ImplementEnumType( VPathObjectOrientationType, "" ) 708 { VPathObject::k_OrientationFree, "FREE" }, 709 { VPathObject::k_OrientationInterpolate, "INTERPOLATE" }, 710 { VPathObject::k_OrientationToPath, "TOPATH" }, 711 { VPathObject::k_OrientationToObject, "TOOBJECT" }, 712 { VPathObject::k_OrientationToPoint, "TOPOINT" }, 713EndImplementEnumType; 714 715VPathObject::eOrientationType VPathObject::getOrientationTypeEnum( const char *pLabel ) 716{ 717 VPathObject::eOrientationType out; 718 if ( !castConsoleTypeFromString( out, pLabel ) ) 719 { 720 // Bah! 721 return VPathObject::k_OrientationFree; 722 } 723 724 // Return. 725 return out; 726} 727 728StringTableEntry VPathObject::getOrientationTypeLabel( const eOrientationType &pType ) 729{ 730 // Return. 731 return castConsoleTypeToString( pType ); 732} 733