VPathNode.cpp

Engine/source/Verve/VPath/VPathNode.cpp

More...

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