VPathNode.cpp
Engine/source/Verve/VPath/VPathNode.cpp
Public Variables
Public Functions
Detailed Description
Public Variables
EndImplementEnumType
U32 gOrientationTypeBits
Public Functions
ImplementEnumType(VPathNodeOrientationType , "" )
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 "VPathNode.h" 25#include "VPath.h" 26 27#include "core/stream/bitStream.h" 28#include "core/strings/stringUnit.h" 29#include "sim/netConnection.h" 30 31//----------------------------------------------------------------------------- 32 33static U32 gOrientationTypeBits = getBinLog2( getNextPow2( VPathNode::k_OrientationTypeSize ) ); 34 35//----------------------------------------------------------------------------- 36 37VPathNode::VPathNode( void ) : 38 mPath( NULL ), 39 mLocalPosition( Point3F( 0.f, 0.f, 0.f ) ), 40 mLocalRotation( QuatF( 0.f, 0.f, 0.f, 1.f ) ), 41 mWorldPosition( Point3F( 0.f, 0.f, 0.f ) ), 42 mWorldRotation( QuatF( 0.f, 0.f, 0.f, 1.f ) ), 43 mWeight( 10.f ), 44 mLength( 0.f ) 45{ 46 // Init. 47 mOrientationMode.Type = k_OrientationFree; 48 mOrientationMode.Point = Point3F::Zero; 49 50 // Set the initial mask. 51 mNetState.setMaskBits( k_StateInit ); 52 53 VECTOR_SET_ASSOCIATION( mNetState ); 54} 55 56VPathNode::~VPathNode( void ) 57{ 58 mNetState.clear(); 59} 60 61//----------------------------------------------------------------------------- 62// 63// Network Methods. 64// 65//----------------------------------------------------------------------------- 66 67U32 VPathNode::packNode( NetConnection *pConnection, BitStream *pStream ) 68{ 69 // Init Return Mask. 70 U32 retMask = 0; 71 72 // Fetch State. 73 VNetStateInfo *state = getState( pConnection ); 74 75 // Note: This is out of sync with VPathNode::unpackUpdate(). 76 // If you're ever going to use these methods outside of VPath, you 77 // will need to read a flag *before* calling unpack! 78 79 // Was the Node Created? 80 if ( pStream->writeFlag( state->Mask & k_StateCreate ) ) 81 { 82 // Clear Update. 83 state->Mask &= ~<a href="/coding/class/classvpathnode/#classvpathnode_1ad7a443cb7ddf53085d112b8ee2544c6aae252bdfdb886d4ff52ee28bcc7b7d3ec">k_StateCreate</a>; 84 } 85 86 // Send mLocalPosition? 87 if ( pStream->writeFlag( state->Mask & k_StateUpdatePosition ) ) 88 { 89 // Write mLocalPosition. 90 pStream->write( mLocalPosition.x ); 91 pStream->write( mLocalPosition.y ); 92 pStream->write( mLocalPosition.z ); 93 94 // Clear Update. 95 state->Mask &= ~<a href="/coding/class/classvpathnode/#classvpathnode_1ad7a443cb7ddf53085d112b8ee2544c6aa5577a0041fd886afbebde93c33ecff96">k_StateUpdatePosition</a>; 96 } 97 98 // Send mLocalRotation? 99 if ( pStream->writeFlag( state->Mask & k_StateUpdateRotation ) ) 100 { 101 // Write mLocalRotation. 102 pStream->write( mLocalRotation.x ); 103 pStream->write( mLocalRotation.y ); 104 pStream->write( mLocalRotation.z ); 105 pStream->write( mLocalRotation.w ); 106 107 // Clear Update. 108 state->Mask &= ~<a href="/coding/class/classvpathnode/#classvpathnode_1ad7a443cb7ddf53085d112b8ee2544c6aa85a854fbb8c963be4c76a33a96b18197">k_StateUpdateRotation</a>; 109 } 110 111 // Send mWeight? 112 if ( pStream->writeFlag( state->Mask & k_StateUpdateWeight ) ) 113 { 114 // Write mWeight. 115 pStream->write( mWeight ); 116 117 // Clear Update. 118 state->Mask &= ~<a href="/coding/class/classvpathnode/#classvpathnode_1ad7a443cb7ddf53085d112b8ee2544c6aa19883acea9beef251492d041211e79d1">k_StateUpdateWeight</a>; 119 } 120 121 // Send Orientation Update? 122 if ( pStream->writeFlag( state->Mask & k_StateUpdateOrientation ) ) 123 { 124 // Clear Update? 125 bool clearUpdate = true; 126 127 // Write State. 128 pStream->writeInt( mOrientationMode.Type, gOrientationTypeBits ); 129 130 switch ( mOrientationMode.Type ) 131 { 132 case k_OrientationToPoint : 133 { 134 // Write Point. 135 pStream->write( mOrientationMode.Point.x ); 136 pStream->write( mOrientationMode.Point.y ); 137 pStream->write( mOrientationMode.Point.z ); 138 139 } break; 140 } 141 142 if ( clearUpdate ) 143 { 144 // Clear Update. 145 state->Mask &= ~<a href="/coding/class/classvpathnode/#classvpathnode_1ad7a443cb7ddf53085d112b8ee2544c6aad024363061a79b5680379c153b5e99f4">k_StateUpdateOrientation</a>; 146 } 147 } 148 149 // Return Mask. 150 return retMask; 151} 152 153void VPathNode::unpackNode( NetConnection *pConnection, BitStream *pStream ) 154{ 155 // Note: This is out of sync with VPathNode::packUpdate(). 156 // If you're ever going to use these methods outside of VPath, you 157 // will need to read a flag *before* calling unpack! 158 159 // Update World Data. 160 bool updateWorld = false; 161 162 // Update Local Position? 163 if ( pStream->readFlag() ) 164 { 165 // Read Local Position. 166 pStream->read( &mLocalPosition.x ); 167 pStream->read( &mLocalPosition.y ); 168 pStream->read( &mLocalPosition.z ); 169 170 updateWorld = true; 171 } 172 173 // Update Local Rotation? 174 if ( pStream->readFlag() ) 175 { 176 // Read Local Rotation. 177 pStream->read( &mLocalRotation.x ); 178 pStream->read( &mLocalRotation.y ); 179 pStream->read( &mLocalRotation.z ); 180 pStream->read( &mLocalRotation.w ); 181 182 updateWorld = true; 183 } 184 185 // Update Weight? 186 if ( pStream->readFlag() ) 187 { 188 // Read Weight. 189 pStream->read( &mWeight ); 190 } 191 192 // Update Orientation? 193 if ( pStream->readFlag() ) 194 { 195 // Read Orientation Mode. 196 mOrientationMode.Type = ( eOrientationType )pStream->readInt( gOrientationTypeBits ); 197 198 switch ( mOrientationMode.Type ) 199 { 200 case k_OrientationToPoint : 201 { 202 // Read Point. 203 pStream->read( &mOrientationMode.Point.x ); 204 pStream->read( &mOrientationMode.Point.y ); 205 pStream->read( &mOrientationMode.Point.z ); 206 207 } break; 208 } 209 } 210 211 if ( updateWorld ) 212 { 213 // Update World Position. 214 updateWorldData(); 215 } 216} 217 218String VPathNode::toString( void ) 219{ 220 String retBuffer; 221 222 // Buffer Node Properties. 223 // {Position} {Rotation} {Weight} 224 const AngAxisF aa( mLocalRotation ); 225 retBuffer = String::ToString( "%f %f %f %f %f %f %f %f", mLocalPosition.x, mLocalPosition.y, mLocalPosition.z, 226 aa.axis.x, aa.axis.y, aa.axis.z, aa.angle, 227 mWeight ); 228 229 // Add Tab. 230 retBuffer += "\t"; 231 232 // Determine the Type. 233 StringTableEntry typeString = getOrientationTypeLabel( mOrientationMode.Type ); 234 switch( mOrientationMode.Type ) 235 { 236 case k_OrientationFree : 237 { 238 // Buffer String. 239 retBuffer += typeString; 240 241 } break; 242 243 case k_OrientationToPoint: 244 { 245 // Fetch Point. 246 const Point3F &lookAtPoint = mOrientationMode.Point; 247 248 // Buffer String. 249 retBuffer += String::ToString( "%s %f %f %f", typeString, lookAtPoint.x, lookAtPoint.y, lookAtPoint.z ); 250 251 } break; 252 } 253 254 // Return String. 255 return retBuffer; 256} 257 258bool VPathNode::fromString( const String &pString ) 259{ 260 // Split Data. 261 // {Position} {Rotation} {Weight} 262 const char *baseData = StringUnit::getUnit( pString.c_str(), 0, "\t" ); 263 264 Point3F pos; 265 AngAxisF aa; 266 F32 weight; 267 268 // Scan Base. 269 dSscanf( baseData, "%g %g %g %g %g %g %g %g", &pos.x, &pos.y, &pos.z, 270 &aa.axis.x, &aa.axis.y, &aa.axis.z, &aa.angle, 271 &weight ); 272 273 // Apply Changes. 274 setLocalPosition( pos ); 275 setLocalRotation( QuatF( aa ) ); 276 setWeight( weight ); 277 278 // Fetch Orientation Data. 279 String orientationData = StringUnit::getUnit( pString.c_str(), 1, "\t" ); 280 281 // Fetch Orientation Type. 282 String orientationTypeString = orientationData; 283 if ( orientationData.find( " " ) ) 284 { 285 // Use First Word. 286 orientationTypeString = orientationData.substr( 0, orientationData.find( " " ) ); 287 } 288 289 // Set Orientation Type. 290 const eOrientationType &orientationType = getOrientationTypeEnum( orientationTypeString.c_str() ); 291 switch( orientationType ) 292 { 293 case k_OrientationFree : 294 { 295 // Apply Mode. 296 setOrientationMode( orientationType ); 297 298 } break; 299 300 case k_OrientationToPoint: 301 { 302 // Fetch Point. 303 Point3F lookAtPoint; 304 // Buffer String. 305 dSscanf( orientationData.c_str(), "%*s %f %f %f", &lookAtPoint.x, &lookAtPoint.y, &lookAtPoint.z ); 306 307 // Apply Mode. 308 setOrientationMode( orientationType, lookAtPoint ); 309 310 } break; 311 } 312 313 return true; 314} 315 316//----------------------------------------------------------------------------- 317// 318// Property Methods. 319// 320//----------------------------------------------------------------------------- 321 322Point3F VPathNode::getWorldPosition( void ) const 323{ 324 return mWorldPosition; 325} 326 327QuatF VPathNode::getWorldRotation( void ) const 328{ 329 return mWorldRotation; 330} 331 332MatrixF VPathNode::getWorldTransform( void ) const 333{ 334 MatrixF mat; 335 getWorldRotation().setMatrix( &mat ); 336 mat.setPosition( getWorldPosition() ); 337 338 return mat; 339} 340 341void VPathNode::setLocalPosition( const Point3F &pPosition ) 342{ 343 // Update? 344 if ( mLocalPosition != pPosition ) 345 { 346 // Apply. 347 mLocalPosition = pPosition; 348 349 // Update World Position. 350 updateWorldData(); 351 352 // Flag Update. 353 setMaskBits( k_StateUpdatePosition ); 354 } 355} 356 357void VPathNode::setLocalRotation( const QuatF &pRotation ) 358{ 359 // Update? 360 if ( mLocalRotation != pRotation ) 361 { 362 // Apply. 363 mLocalRotation = pRotation; 364 365 // Update World Rotation. 366 updateWorldData(); 367 368 // Flag Update. 369 setMaskBits( k_StateUpdateRotation ); 370 } 371} 372 373void VPathNode::setWeight( const F32 &pWeight ) 374{ 375 // Update? 376 if ( mWeight != pWeight ) 377 { 378 // Apply. 379 mWeight = pWeight; 380 381 // Flag Update. 382 setMaskBits( k_StateUpdateWeight ); 383 } 384} 385 386void VPathNode::setOrientationMode( const eOrientationType &pType ) 387{ 388 // Update? 389 if ( mOrientationMode.Type != pType ) 390 { 391 // Update. 392 mOrientationMode.Type = pType; 393 394 // Flag Update. 395 setMaskBits( k_StateUpdateOrientation ); 396 } 397} 398 399void VPathNode::setOrientationMode( const eOrientationType &pType, const Point3F &pPoint ) 400{ 401 AssertFatal( pType == k_OrientationToPoint, "VPathNode::setOrientationMode() - Invalid mOrientation Type." ); 402 403 // Update? 404 if ( ( mOrientationMode.Type != pType ) || ( mOrientationMode.Point != pPoint ) ) 405 { 406 // Update. 407 mOrientationMode.Type = pType; 408 mOrientationMode.Point = pPoint; 409 410 // Flag Update. 411 setMaskBits( k_StateUpdateOrientation ); 412 } 413} 414 415void VPathNode::updateWorldData( void ) 416{ 417 if ( !mPath ) 418 { 419 setWorldPosition( getLocalPosition() ); 420 setWorldRotation( getLocalRotation() ); 421 return; 422 } 423 424 // Fetch Path Details. 425 const MatrixF &pathTransform = mPath->getTransform(); 426 const QuatF &pathRotation( pathTransform ); 427 428 // Calculate the World Position. 429 Point3F newPosition = getLocalPosition(); 430 newPosition.convolve( mPath->getScale() ); 431 pathTransform.mulP( newPosition ); 432 433 // Calculate the new Rotation. 434 QuatF newRotation; 435 newRotation.mul( getLocalRotation(), pathRotation ); 436 437 // Apply. 438 setWorldPosition( newPosition ); 439 setWorldRotation( newRotation ); 440} 441 442//----------------------------------------------------------------------------- 443// 444// Enumeration Methods. 445// 446//----------------------------------------------------------------------------- 447 448// Implement the Orientation Type enum list. 449ImplementEnumType( VPathNodeOrientationType,"" ) 450 { VPathNode::k_OrientationFree, "FREE" }, 451 { VPathNode::k_OrientationToPoint, "TOPOINT" }, 452EndImplementEnumType; 453 454VPathNode::eOrientationType VPathNode::getOrientationTypeEnum( const char *pLabel ) 455{ 456 VPathNode::eOrientationType out; 457 if ( !castConsoleTypeFromString( out, pLabel ) ) 458 { 459 // Bah! 460 return VPathNode::k_OrientationFree; 461 } 462 463 // Return. 464 return out; 465} 466 467StringTableEntry VPathNode::getOrientationTypeLabel( const eOrientationType &pType ) 468{ 469 // Return. 470 return castConsoleTypeToString( pType ); 471} 472