123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470 |
- //-----------------------------------------------------------------------------
- // Verve
- // Copyright (C) 2014 - Violent Tulip
- //
- // Permission is hereby granted, free of charge, to any person obtaining a copy
- // of this software and associated documentation files (the "Software"), to
- // deal in the Software without restriction, including without limitation the
- // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- // sell copies of the Software, and to permit persons to whom the Software is
- // furnished to do so, subject to the following conditions:
- //
- // The above copyright notice and this permission notice shall be included in
- // all copies or substantial portions of the Software.
- //
- // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- // IN THE SOFTWARE.
- //-----------------------------------------------------------------------------
- #include "VPathNode.h"
- #include "VPath.h"
- #include "core/stream/bitStream.h"
- #include "core/strings/stringUnit.h"
- #include "sim/netConnection.h"
- //-----------------------------------------------------------------------------
- static U32 gOrientationTypeBits = getBinLog2( getNextPow2( VPathNode::k_OrientationTypeSize ) );
- //-----------------------------------------------------------------------------
- VPathNode::VPathNode( void ) :
- mPath( NULL ),
- mLocalPosition( Point3F( 0.f, 0.f, 0.f ) ),
- mLocalRotation( QuatF( 0.f, 0.f, 0.f, 1.f ) ),
- mWorldPosition( Point3F( 0.f, 0.f, 0.f ) ),
- mWorldRotation( QuatF( 0.f, 0.f, 0.f, 1.f ) ),
- mWeight( 10.f ),
- mLength( 0.f )
- {
- // Init.
- mOrientationMode.Type = k_OrientationFree;
- mOrientationMode.Point = Point3F::Zero;
- // Set the initial mask.
- mNetState.setMaskBits( k_StateInit );
- VECTOR_SET_ASSOCIATION( mNetState );
- }
- VPathNode::~VPathNode( void )
- {
- mNetState.clear();
- }
- //-----------------------------------------------------------------------------
- //
- // Network Methods.
- //
- //-----------------------------------------------------------------------------
- U32 VPathNode::packNode( NetConnection *pConnection, BitStream *pStream )
- {
- // Init Return Mask.
- U32 retMask = 0;
- // Fetch State.
- VNetStateInfo *state = getState( pConnection );
- // Note: This is out of sync with VPathNode::unpackUpdate().
- // If you're ever going to use these methods outside of VPath, you
- // will need to read a flag *before* calling unpack!
- // Was the Node Created?
- if ( pStream->writeFlag( state->Mask & k_StateCreate ) )
- {
- // Clear Update.
- state->Mask &= ~k_StateCreate;
- }
- // Send mLocalPosition?
- if ( pStream->writeFlag( state->Mask & k_StateUpdatePosition ) )
- {
- // Write mLocalPosition.
- pStream->write( mLocalPosition.x );
- pStream->write( mLocalPosition.y );
- pStream->write( mLocalPosition.z );
- // Clear Update.
- state->Mask &= ~k_StateUpdatePosition;
- }
- // Send mLocalRotation?
- if ( pStream->writeFlag( state->Mask & k_StateUpdateRotation ) )
- {
- // Write mLocalRotation.
- pStream->write( mLocalRotation.x );
- pStream->write( mLocalRotation.y );
- pStream->write( mLocalRotation.z );
- pStream->write( mLocalRotation.w );
- // Clear Update.
- state->Mask &= ~k_StateUpdateRotation;
- }
- // Send mWeight?
- if ( pStream->writeFlag( state->Mask & k_StateUpdateWeight ) )
- {
- // Write mWeight.
- pStream->write( mWeight );
- // Clear Update.
- state->Mask &= ~k_StateUpdateWeight;
- }
- // Send Orientation Update?
- if ( pStream->writeFlag( state->Mask & k_StateUpdateOrientation ) )
- {
- // Clear Update?
- bool clearUpdate = true;
- // Write State.
- pStream->writeInt( mOrientationMode.Type, gOrientationTypeBits );
- switch ( mOrientationMode.Type )
- {
- case k_OrientationToPoint :
- {
- // Write Point.
- pStream->write( mOrientationMode.Point.x );
- pStream->write( mOrientationMode.Point.y );
- pStream->write( mOrientationMode.Point.z );
- } break;
- }
- if ( clearUpdate )
- {
- // Clear Update.
- state->Mask &= ~k_StateUpdateOrientation;
- }
- }
- // Return Mask.
- return retMask;
- }
- void VPathNode::unpackNode( NetConnection *pConnection, BitStream *pStream )
- {
- // Note: This is out of sync with VPathNode::packUpdate().
- // If you're ever going to use these methods outside of VPath, you
- // will need to read a flag *before* calling unpack!
- // Update World Data.
- bool updateWorld = false;
- // Update Local Position?
- if ( pStream->readFlag() )
- {
- // Read Local Position.
- pStream->read( &mLocalPosition.x );
- pStream->read( &mLocalPosition.y );
- pStream->read( &mLocalPosition.z );
- updateWorld = true;
- }
-
- // Update Local Rotation?
- if ( pStream->readFlag() )
- {
- // Read Local Rotation.
- pStream->read( &mLocalRotation.x );
- pStream->read( &mLocalRotation.y );
- pStream->read( &mLocalRotation.z );
- pStream->read( &mLocalRotation.w );
- updateWorld = true;
- }
-
- // Update Weight?
- if ( pStream->readFlag() )
- {
- // Read Weight.
- pStream->read( &mWeight );
- }
-
- // Update Orientation?
- if ( pStream->readFlag() )
- {
- // Read Orientation Mode.
- mOrientationMode.Type = ( eOrientationType )pStream->readInt( gOrientationTypeBits );
- switch ( mOrientationMode.Type )
- {
- case k_OrientationToPoint :
- {
- // Read Point.
- pStream->read( &mOrientationMode.Point.x );
- pStream->read( &mOrientationMode.Point.y );
- pStream->read( &mOrientationMode.Point.z );
- } break;
- }
- }
- if ( updateWorld )
- {
- // Update World Position.
- updateWorldData();
- }
- }
- String VPathNode::toString( void )
- {
- String retBuffer;
- // Buffer Node Properties.
- // {Position} {Rotation} {Weight}
- const AngAxisF aa( mLocalRotation );
- retBuffer = String::ToString( "%f %f %f %f %f %f %f %f", mLocalPosition.x, mLocalPosition.y, mLocalPosition.z,
- aa.axis.x, aa.axis.y, aa.axis.z, aa.angle,
- mWeight );
- // Add Tab.
- retBuffer += "\t";
- // Determine the Type.
- StringTableEntry typeString = getOrientationTypeLabel( mOrientationMode.Type );
- switch( mOrientationMode.Type )
- {
- case k_OrientationFree :
- {
- // Buffer String.
- retBuffer += typeString;
- } break;
- case k_OrientationToPoint:
- {
- // Fetch Point.
- const Point3F &lookAtPoint = mOrientationMode.Point;
- // Buffer String.
- retBuffer += String::ToString( "%s %f %f %f", typeString, lookAtPoint.x, lookAtPoint.y, lookAtPoint.z );
- } break;
- }
- // Return String.
- return retBuffer;
- }
- bool VPathNode::fromString( const String &pString )
- {
- // Split Data.
- // {Position} {Rotation} {Weight}
- const char *baseData = StringUnit::getUnit( pString.c_str(), 0, "\t" );
- Point3F pos;
- AngAxisF aa;
- F32 weight;
- // Scan Base.
- dSscanf( baseData, "%g %g %g %g %g %g %g %g", &pos.x, &pos.y, &pos.z,
- &aa.axis.x, &aa.axis.y, &aa.axis.z, &aa.angle,
- &weight );
- // Apply Changes.
- setLocalPosition( pos );
- setLocalRotation( QuatF( aa ) );
- setWeight( weight );
- // Fetch Orientation Data.
- String orientationData = StringUnit::getUnit( pString.c_str(), 1, "\t" );
- // Fetch Orientation Type.
- String orientationTypeString = orientationData;
- if ( orientationData.find( " " ) )
- {
- // Use First Word.
- orientationTypeString = orientationData.substr( 0, orientationData.find( " " ) );
- }
- // Set Orientation Type.
- const eOrientationType &orientationType = getOrientationTypeEnum( orientationTypeString.c_str() );
- switch( orientationType )
- {
- case k_OrientationFree :
- {
- // Apply Mode.
- setOrientationMode( orientationType );
- } break;
- case k_OrientationToPoint:
- {
- // Fetch Point.
- Point3F lookAtPoint;
- // Buffer String.
- dSscanf( orientationData.c_str(), "%*s %f %f %f", &lookAtPoint.x, &lookAtPoint.y, &lookAtPoint.z );
- // Apply Mode.
- setOrientationMode( orientationType, lookAtPoint );
- } break;
- }
- return true;
- }
- //-----------------------------------------------------------------------------
- //
- // Property Methods.
- //
- //-----------------------------------------------------------------------------
- Point3F VPathNode::getWorldPosition( void ) const
- {
- return mWorldPosition;
- }
- QuatF VPathNode::getWorldRotation( void ) const
- {
- return mWorldRotation;
- }
- MatrixF VPathNode::getWorldTransform( void ) const
- {
- MatrixF mat;
- getWorldRotation().setMatrix( &mat );
- mat.setPosition( getWorldPosition() );
- return mat;
- }
- void VPathNode::setLocalPosition( const Point3F &pPosition )
- {
- // Update?
- if ( mLocalPosition != pPosition )
- {
- // Apply.
- mLocalPosition = pPosition;
- // Update World Position.
- updateWorldData();
- // Flag Update.
- setMaskBits( k_StateUpdatePosition );
- }
- }
- void VPathNode::setLocalRotation( const QuatF &pRotation )
- {
- // Update?
- if ( mLocalRotation != pRotation )
- {
- // Apply.
- mLocalRotation = pRotation;
- // Update World Rotation.
- updateWorldData();
- // Flag Update.
- setMaskBits( k_StateUpdateRotation );
- }
- }
- void VPathNode::setWeight( const F32 &pWeight )
- {
- // Update?
- if ( mWeight != pWeight )
- {
- // Apply.
- mWeight = pWeight;
- // Flag Update.
- setMaskBits( k_StateUpdateWeight );
- }
- }
- void VPathNode::setOrientationMode( const eOrientationType &pType )
- {
- // Update?
- if ( mOrientationMode.Type != pType )
- {
- // Update.
- mOrientationMode.Type = pType;
- // Flag Update.
- setMaskBits( k_StateUpdateOrientation );
- }
- }
- void VPathNode::setOrientationMode( const eOrientationType &pType, const Point3F &pPoint )
- {
- AssertFatal( pType == k_OrientationToPoint, "VPathNode::setOrientationMode() - Invalid mOrientation Type." );
- // Update?
- if ( ( mOrientationMode.Type != pType ) || ( mOrientationMode.Point != pPoint ) )
- {
- // Update.
- mOrientationMode.Type = pType;
- mOrientationMode.Point = pPoint;
- // Flag Update.
- setMaskBits( k_StateUpdateOrientation );
- }
- }
- void VPathNode::updateWorldData( void )
- {
- if ( !mPath )
- {
- setWorldPosition( getLocalPosition() );
- setWorldRotation( getLocalRotation() );
- return;
- }
- // Fetch Path Details.
- const MatrixF &pathTransform = mPath->getTransform();
- const QuatF &pathRotation( pathTransform );
- // Calculate the World Position.
- Point3F newPosition = getLocalPosition();
- newPosition.convolve( mPath->getScale() );
- pathTransform.mulP( newPosition );
- // Calculate the new Rotation.
- QuatF newRotation;
- newRotation.mul( getLocalRotation(), pathRotation );
- // Apply.
- setWorldPosition( newPosition );
- setWorldRotation( newRotation );
- }
- //-----------------------------------------------------------------------------
- //
- // Enumeration Methods.
- //
- //-----------------------------------------------------------------------------
- // Implement the Orientation Type enum list.
- ImplementEnumType( VPathNodeOrientationType,"" )
- { VPathNode::k_OrientationFree, "FREE" },
- { VPathNode::k_OrientationToPoint, "TOPOINT" },
- EndImplementEnumType;
- VPathNode::eOrientationType VPathNode::getOrientationTypeEnum( const char *pLabel )
- {
- VPathNode::eOrientationType out;
- if ( !castConsoleTypeFromString( out, pLabel ) )
- {
- // Bah!
- return VPathNode::k_OrientationFree;
- }
- // Return.
- return out;
- }
- StringTableEntry VPathNode::getOrientationTypeLabel( const eOrientationType &pType )
- {
- // Return.
- return castConsoleTypeToString( pType );
- }
|