You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
918 lines
36 KiB
918 lines
36 KiB
//========= Copyright Valve Corporation, All rights reserved. ============// |
|
// |
|
// Purpose: |
|
// |
|
//============================================================================= |
|
|
|
#ifndef DMELOG_H |
|
#define DMELOG_H |
|
#ifdef _WIN32 |
|
#pragma once |
|
#endif |
|
|
|
#include "datamodel/dmelement.h" |
|
#include "datamodel/dmattribute.h" |
|
#include "datamodel/dmattributevar.h" |
|
#include "datamodel/dmehandle.h" |
|
#include "interpolatortypes.h" |
|
#include "movieobjects/timeutils.h" |
|
#include "movieobjects/dmetimeselectiontimes.h" |
|
|
|
class IUniformRandomStream; |
|
|
|
template < class T > class CDmeTypedLog; |
|
|
|
enum |
|
{ |
|
FILTER_SMOOTH = 0, |
|
FILTER_JITTER, |
|
FILTER_SHARPEN, |
|
FILTER_SOFTEN, |
|
|
|
NUM_FILTERS |
|
}; |
|
|
|
enum RecordingMode_t |
|
{ |
|
RECORD_PRESET = 0, // Preset/fader slider being dragged |
|
RECORD_ATTRIBUTESLIDER, // Single attribute slider being dragged |
|
}; |
|
|
|
#define DMELOG_DEFAULT_THRESHHOLD 0.0001f |
|
|
|
class DmeLog_TimeSelection_t |
|
{ |
|
public: |
|
DmeLog_TimeSelection_t() : |
|
m_flIntensity( 1.0f ), |
|
m_bAttachedMode( true ), |
|
m_bTimeAdvancing( false ), |
|
m_bResampleMode( true ), |
|
m_nResampleInterval( DmeTime_t( .05f ) ),// 50 msec sampling interval by default |
|
m_flThreshold( DMELOG_DEFAULT_THRESHHOLD ), |
|
m_pPresetValue( 0 ), |
|
m_RecordingMode( RECORD_PRESET ) |
|
{ |
|
m_nTimes[ TS_LEFT_FALLOFF ] = m_nTimes[ TS_LEFT_HOLD ] = |
|
m_nTimes[ TS_RIGHT_HOLD ] = m_nTimes[ TS_RIGHT_FALLOFF ] = DmeTime_t( 0 ); |
|
m_nFalloffInterpolatorTypes[ 0 ] = m_nFalloffInterpolatorTypes[ 1 ] = INTERPOLATE_LINEAR_INTERP; |
|
} |
|
|
|
inline void ResetTimeAdvancing() |
|
{ |
|
// Reset the time advancing flag |
|
m_bTimeAdvancing = false; |
|
} |
|
|
|
inline void StartTimeAdvancing() |
|
{ |
|
m_bTimeAdvancing = true; |
|
} |
|
|
|
inline bool IsTimeAdvancing() const |
|
{ |
|
return m_bTimeAdvancing; |
|
} |
|
|
|
inline RecordingMode_t GetRecordingMode() const |
|
{ |
|
return m_RecordingMode; |
|
} |
|
|
|
void SetRecordingMode( RecordingMode_t mode ) |
|
{ |
|
m_RecordingMode = mode; |
|
} |
|
|
|
float GetAmountForTime( DmeTime_t curtime ) const; |
|
float AdjustFactorForInterpolatorType( float factor, int side ) const; |
|
|
|
// NOTE: See DmeTimeSelectionTimes_t for return values, 0 means before, 1= left fallof, 2=hold, 3=right falloff, 4=after |
|
int ComputeRegionForTime( DmeTime_t curtime ) const; |
|
|
|
DmeTime_t m_nTimes[ TS_TIME_COUNT ]; |
|
int m_nFalloffInterpolatorTypes[ 2 ]; |
|
DmeTime_t m_nResampleInterval; // Only used if m_bResampleMode is true |
|
float m_flIntensity; // How much to drive values toward m_HeadValue (generally 1.0f) |
|
float m_flThreshold; |
|
CDmAttribute* m_pPresetValue; |
|
|
|
bool m_bAttachedMode : 1; // Is the current time "attached" to the head position |
|
|
|
// Adds new, evenly spaced samples based on m_nResampleInterval |
|
// Also adds zero intensity samples at the falloff edges |
|
bool m_bResampleMode : 1; |
|
|
|
private: |
|
bool m_bTimeAdvancing : 1; // Has time ever been advancing |
|
RecordingMode_t m_RecordingMode; |
|
}; |
|
|
|
class CDmeChannel; |
|
class CDmeChannelsClip; |
|
class CDmeFilmClip; |
|
class CDmeLog; |
|
class CDmeLogLayer; |
|
|
|
struct LayerSelectionData_t |
|
{ |
|
LayerSelectionData_t(); |
|
void Release(); |
|
|
|
CDmeHandle< CDmeChannel > m_hChannel; |
|
CDmeHandle< CDmeChannelsClip > m_hOwner; |
|
CDmeHandle< CDmeFilmClip > m_hShot; |
|
CDmeHandle< CDmeLog > m_hLog; |
|
DmAttributeType_t m_DataType; |
|
int m_nDuration; |
|
int m_nHoldTimes[ 2 ]; |
|
DmeTime_t m_tStartOffset; |
|
|
|
// This is dynamic and needs to be released |
|
struct DataLayer_t |
|
{ |
|
DataLayer_t( float frac, CDmeLogLayer *layer ); |
|
|
|
float m_flStartFraction; |
|
CDmeHandle< CDmeLogLayer, true > m_hData; |
|
}; |
|
|
|
CUtlVector< DataLayer_t > m_vecData; |
|
}; |
|
|
|
//----------------------------------------------------------------------------- |
|
// CDmeLogLayer - abstract base class |
|
//----------------------------------------------------------------------------- |
|
abstract_class CDmeLogLayer : public CDmElement |
|
{ |
|
friend class CDmeLog; |
|
|
|
DEFINE_ELEMENT( CDmeLogLayer, CDmElement ); |
|
|
|
public: |
|
virtual void CopyLayer( const CDmeLogLayer *src ) = 0; |
|
virtual void CopyPartialLayer( const CDmeLogLayer *src, DmeTime_t startTime, DmeTime_t endTime, bool bRebaseTimestamps ) = 0; |
|
virtual void ExplodeLayer( const CDmeLogLayer *src, DmeTime_t startTime, DmeTime_t endTime, bool bRebaseTimestamps, DmeTime_t tResampleInterval ) = 0; |
|
virtual void InsertKeyFromLayer( DmeTime_t keyTime, const CDmeLogLayer *src, DmeTime_t srcKeyTime ) = 0; |
|
|
|
DmeTime_t GetBeginTime() const; |
|
DmeTime_t GetEndTime() const; |
|
int GetKeyCount() const; |
|
|
|
// Returns the index of a key closest to this time, within tolerance |
|
// NOTE: Insertion or removal may change this index! |
|
// Returns -1 if the time isn't within tolerance. |
|
int FindKeyWithinTolerance( DmeTime_t time, DmeTime_t nTolerance ); |
|
|
|
// Returns the type of attribute being logged |
|
virtual DmAttributeType_t GetDataType() const = 0; |
|
|
|
// Sets a key, removes all keys after this time |
|
virtual void SetKey( DmeTime_t time, const CDmAttribute *pAttr, uint index = 0, int curveType = CURVE_DEFAULT ) = 0; |
|
virtual bool SetDuplicateKeyAtTime( DmeTime_t time ) = 0; |
|
// This inserts a key using the current values to construct the proper value for the time |
|
virtual int InsertKeyAtTime( DmeTime_t nTime, int curveType = CURVE_DEFAULT ) = 0; |
|
|
|
// Sets the interpolated value of the log at the specified time into the attribute |
|
virtual void GetValue( DmeTime_t time, CDmAttribute *pAttr, uint index = 0 ) const = 0; |
|
|
|
virtual float GetComponent( DmeTime_t time, int componentIndex ) const = 0; |
|
|
|
// Returns the time at which a particular key occurs |
|
DmeTime_t GetKeyTime( int nKeyIndex ) const; |
|
void SetKeyTime( int nKeyIndex, DmeTime_t keyTime ); |
|
|
|
// Scale + bias key times |
|
void ScaleBiasKeyTimes( double flScale, DmeTime_t nBias ); |
|
|
|
// Removes a single key by index |
|
virtual void RemoveKey( int nKeyIndex, int nNumKeysToRemove = 1 ) = 0; |
|
|
|
// Removes all keys |
|
virtual void ClearKeys() = 0; |
|
|
|
virtual bool IsConstantValued() const = 0; |
|
virtual void RemoveRedundantKeys() = 0; |
|
virtual void RemoveRedundantKeys( float threshold ) = 0; |
|
|
|
// resampling and filtering |
|
virtual void Resample( DmeFramerate_t samplerate ) = 0; |
|
virtual void Filter( int nSampleRadius ) = 0; |
|
virtual void Filter2( DmeTime_t sampleRadius ) = 0; |
|
|
|
virtual void SetOwnerLog( CDmeLog *owner ) = 0; |
|
CDmeLog *GetOwnerLog(); |
|
const CDmeLog *GetOwnerLog() const; |
|
|
|
bool IsUsingCurveTypes() const; |
|
int GetDefaultCurveType() const; |
|
|
|
// Override curvetype for specific key |
|
void SetKeyCurveType( int nKeyIndex, int curveType ); |
|
int GetKeyCurveType( int nKeyIndex ) const; |
|
|
|
// Validates that all keys are correctly sorted in time |
|
bool ValidateKeys() const; |
|
|
|
// Removes all keys outside the specified time range |
|
void RemoveKeysOutsideRange( DmeTime_t tStart, DmeTime_t tEnd ); |
|
|
|
protected: |
|
int FindKey( DmeTime_t time ) const; |
|
|
|
void OnUsingCurveTypesChanged(); |
|
|
|
CDmeLog *m_pOwnerLog; |
|
|
|
mutable int m_lastKey; |
|
CDmaArray< int > m_times; |
|
CDmaArray< int > m_CurveTypes; |
|
}; |
|
|
|
template< class T > |
|
CDmeLogLayer *CreateLayer( CDmeTypedLog< T > *ownerLog ); |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// CDmeLogLayer - abstract base class |
|
//----------------------------------------------------------------------------- |
|
abstract_class CDmeCurveInfo : public CDmElement |
|
{ |
|
DEFINE_ELEMENT( CDmeCurveInfo, CDmElement ); |
|
|
|
public: |
|
// Global override for all keys unless overriden by specific key |
|
void SetDefaultCurveType( int curveType ); |
|
int GetDefaultCurveType() const; |
|
|
|
void SetMinValue( float val ); |
|
float GetMinValue() const; |
|
void SetMaxValue( float val ); |
|
float GetMaxValue() const; |
|
|
|
protected: |
|
CDmaVar< int > m_DefaultCurveType; |
|
|
|
CDmaVar< float > m_MinValue; |
|
CDmaVar< float > m_MaxValue; |
|
}; |
|
|
|
template <class T > class CDmeTypedLogLayer; |
|
|
|
//----------------------------------------------------------------------------- |
|
// CDmeLog - abstract base class |
|
//----------------------------------------------------------------------------- |
|
abstract_class CDmeLog : public CDmElement |
|
{ |
|
DEFINE_ELEMENT( CDmeLog, CDmElement ); |
|
|
|
public: |
|
int FindLayerForTime( DmeTime_t time ) const; |
|
int FindLayerForTimeSkippingTopmost( DmeTime_t time ) const; |
|
void FindLayersForTime( DmeTime_t time, CUtlVector< int >& list ) const; |
|
|
|
virtual void FinishTimeSelection( DmeTime_t tHeadPosition, DmeLog_TimeSelection_t& params ) = 0; // in attached, timeadvancing mode, we need to blend out of the final sample over the fadeout interval |
|
virtual void StampKeyAtHead( DmeTime_t tHeadPosition, DmeTime_t tPreviousHeadPosition, const DmeLog_TimeSelection_t& params, const CDmAttribute *pAttr, uint index = 0 ) = 0; |
|
virtual void FilterUsingTimeSelection( IUniformRandomStream *random, float flScale, const DmeLog_TimeSelection_t& params, int filterType, bool bResample, bool bApplyFalloff, const CDmeLogLayer *baseLayer, CDmeLogLayer *writeLayer ) = 0; |
|
virtual void FilterUsingTimeSelection( IUniformRandomStream *random, const DmeLog_TimeSelection_t& params, int filterType, bool bResample, bool bApplyFalloff ) = 0; |
|
virtual void StaggerUsingTimeSelection( const DmeLog_TimeSelection_t& params, DmeTime_t tStaggerAmount, const CDmeLogLayer *baseLayer, CDmeLogLayer *writeLayer ) = 0; |
|
virtual void RevealUsingTimeSelection( const DmeLog_TimeSelection_t ¶ms, CDmeLogLayer *savedLayer ) = 0; |
|
virtual void BlendLayersUsingTimeSelection( const DmeLog_TimeSelection_t ¶ms ) = 0; |
|
virtual void BlendLayersUsingTimeSelection( const CDmeLogLayer *firstLayer, const CDmeLogLayer *secondLayer, CDmeLogLayer *outputLayer, const DmeLog_TimeSelection_t ¶ms, bool bUseBaseLayerSamples, DmeTime_t tStartOffset ) = 0; |
|
virtual void BlendTimesUsingTimeSelection( const CDmeLogLayer *firstLayer, const CDmeLogLayer *secondLayer, CDmeLogLayer *outputLayer, const DmeLog_TimeSelection_t ¶ms, DmeTime_t tStartOffset ) = 0; |
|
virtual void PasteAndRescaleSamples( const CDmeLogLayer *src, const DmeLog_TimeSelection_t& srcParams, const DmeLog_TimeSelection_t& destParams, bool bBlendAreaInFalloffRegion ) = 0; |
|
virtual void PasteAndRescaleSamples( const CDmeLogLayer *pBaseLayer, const CDmeLogLayer *pDataLayer, CDmeLogLayer *pOutputLayer, const DmeLog_TimeSelection_t& srcParams, const DmeLog_TimeSelection_t& destParams, bool bBlendAreaInFalloffRegion ) = 0; |
|
virtual void BuildNormalizedLayer( CDmeTypedLogLayer< float > *target ) = 0; |
|
virtual void BuildCorrespondingLayer( const CDmeLogLayer *pReferenceLayer, const CDmeLogLayer *pDataLayer, CDmeLogLayer *pOutputLayer ) = 0; |
|
|
|
int GetTopmostLayer() const; |
|
int GetNumLayers() const; |
|
CDmeLogLayer *GetLayer( int index ); |
|
const CDmeLogLayer *GetLayer( int index ) const; |
|
|
|
DmeTime_t GetBeginTime() const; |
|
DmeTime_t GetEndTime() const; |
|
int GetKeyCount() const; |
|
|
|
bool IsEmpty() const; |
|
|
|
// Returns the index of a key closest to this time, within tolerance |
|
// NOTE: Insertion or removal may change this index! |
|
// Returns -1 if the time isn't within tolerance. |
|
virtual int FindKeyWithinTolerance( DmeTime_t time, DmeTime_t nTolerance ) = 0; |
|
|
|
// Returns the type of attribute being logged |
|
virtual DmAttributeType_t GetDataType() const = 0; |
|
|
|
// Sets a key, removes all keys after this time |
|
virtual void SetKey( DmeTime_t time, const CDmAttribute *pAttr, uint index = 0, int curveType = CURVE_DEFAULT ) = 0; |
|
virtual bool SetDuplicateKeyAtTime( DmeTime_t time ) = 0; |
|
virtual int InsertKeyAtTime( DmeTime_t nTime, int curveType = CURVE_DEFAULT ) = 0; |
|
// Sets the interpolated value of the log at the specified time into the attribute |
|
virtual void GetValue( DmeTime_t time, CDmAttribute *pAttr, uint index = 0 ) const = 0; |
|
virtual void GetValueSkippingTopmostLayer( DmeTime_t time, CDmAttribute *pAttr, uint index = 0 ) const = 0; |
|
|
|
virtual float GetComponent( DmeTime_t time, int componentIndex ) const = 0; |
|
|
|
// Returns the time at which a particular key occurs |
|
virtual DmeTime_t GetKeyTime( int nKeyIndex ) const = 0; |
|
virtual void SetKeyTime( int nKeyIndex, DmeTime_t keyTime ) = 0; |
|
|
|
// Override curvetype for specific key |
|
void SetKeyCurveType( int nKeyIndex, int curveType ); |
|
int GetKeyCurveType( int nKeyIndex ) const; |
|
|
|
// Removes a single key by index |
|
virtual void RemoveKey( int nKeyIndex, int nNumKeysToRemove = 1 ) = 0; |
|
|
|
// Removes all keys within the time range, returns true if keys were removed |
|
bool RemoveKeys( DmeTime_t tStartTime, DmeTime_t tEndTime ); |
|
|
|
// Removes all keys |
|
virtual void ClearKeys() = 0; |
|
|
|
// Scale + bias key times |
|
void ScaleBiasKeyTimes( double flScale, DmeTime_t nBias ); |
|
|
|
virtual float GetValueThreshold() const = 0; |
|
virtual void SetValueThreshold( float thresh ) = 0; |
|
virtual bool IsConstantValued() const = 0; |
|
virtual void RemoveRedundantKeys() = 0; |
|
virtual void RemoveRedundantKeys( float threshold ) = 0; |
|
|
|
// resampling and filtering |
|
virtual void Resample( DmeFramerate_t samplerate ) = 0; |
|
virtual void Filter( int nSampleRadius ) = 0; |
|
virtual void Filter2( DmeTime_t sampleRadius ) = 0; |
|
|
|
// Creates a log of a requested type |
|
static CDmeLog *CreateLog( DmAttributeType_t type, DmFileId_t fileid ); |
|
|
|
virtual CDmeLogLayer *AddNewLayer() = 0; |
|
enum |
|
{ |
|
FLATTEN_NODISCONTINUITY_FIXUP = (1<<0), // Don't add "helper" samples to preserve discontinuities. This occurs when the time selection is "detached" from the head position |
|
FLATTEN_SPEW = (1<<1), |
|
}; |
|
virtual void FlattenLayers( float threshold, int flags ) = 0; |
|
|
|
// Only used by undo system!!! |
|
virtual void AddLayerToTail( CDmeLogLayer *layer ) = 0; |
|
virtual CDmeLogLayer *RemoveLayerFromTail() = 0; |
|
virtual CDmeLogLayer *RemoveLayer( int iLayer ) = 0; |
|
|
|
|
|
// Resolve |
|
virtual void Resolve(); |
|
|
|
// curve info helpers |
|
bool IsUsingCurveTypes() const; |
|
const CDmeCurveInfo *GetCurveInfo() const; |
|
CDmeCurveInfo *GetCurveInfo(); |
|
virtual CDmeCurveInfo *GetOrCreateCurveInfo() = 0; |
|
virtual void SetCurveInfo( CDmeCurveInfo *pCurveInfo ) = 0; |
|
|
|
// accessors for CurveInfo data |
|
int GetDefaultCurveType() const; |
|
|
|
// FIXME - this should really be in the CurveInfo |
|
// but the animset editor currently asks for these, without having set a curveinfo... |
|
void SetMinValue( float val ); |
|
void SetMaxValue( float val ); |
|
float GetMinValue() const; |
|
float GetMaxValue() const; |
|
|
|
virtual bool HasDefaultValue() const = 0; |
|
|
|
|
|
protected: |
|
// int FindKey( DmeTime_t time ) const; |
|
|
|
void OnUsingCurveTypesChanged(); |
|
|
|
virtual void OnAttributeChanged( CDmAttribute *pAttribute ); |
|
|
|
CDmaElementArray< CDmeLogLayer > m_Layers; |
|
CDmaElement< CDmeCurveInfo > m_CurveInfo; |
|
}; |
|
|
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// CDmeTypedCurveInfo - implementation class for all logs |
|
//----------------------------------------------------------------------------- |
|
template< class T > |
|
class CDmeTypedCurveInfo : public CDmeCurveInfo |
|
{ |
|
DEFINE_ELEMENT( CDmeTypedCurveInfo, CDmeCurveInfo ); |
|
|
|
public: |
|
// For "faceposer" style left/right edges, this controls whether interpolators try to mimic faceposer left/right edge behavior |
|
void SetUseEdgeInfo( bool state ); |
|
bool IsUsingEdgeInfo() const; |
|
|
|
void SetEdgeInfo( int edge, bool active, const T& val, int curveType ); |
|
void GetEdgeInfo( int edge, bool& active, T& val, int& curveType ) const; |
|
|
|
void SetDefaultEdgeZeroValue( const T& val ); |
|
const T& GetDefaultEdgeZeroValue() const; |
|
|
|
void SetRightEdgeTime( DmeTime_t time ); |
|
DmeTime_t GetRightEdgeTime() const; |
|
|
|
bool IsEdgeActive( int edge ) const; |
|
void GetEdgeValue( int edge, T& value ) const; |
|
|
|
int GetEdgeCurveType( int edge ) const; |
|
void GetZeroValue( int side, T& val ) const; |
|
|
|
protected: |
|
CDmaVar< bool > m_bUseEdgeInfo; |
|
// Array of 2 for left/right edges... |
|
CDmaVar< bool > m_bEdgeActive[ 2 ]; |
|
CDmaVar< T > m_EdgeValue[ 2 ]; |
|
CDmaVar< int > m_EdgeCurveType[ 2 ]; |
|
CDmaVar< int > m_RightEdgeTime; |
|
CDmaVar< T > m_DefaultEdgeValue; |
|
}; |
|
|
|
|
|
// forward declaration |
|
template< class T > class CDmeTypedLog; |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// CDmeTypedLogLayer - implementation class for all logs |
|
//----------------------------------------------------------------------------- |
|
template< class T > |
|
class CDmeTypedLogLayer : public CDmeLogLayer |
|
{ |
|
DEFINE_ELEMENT( CDmeTypedLogLayer, CDmeLogLayer ); |
|
|
|
public: |
|
virtual void CopyLayer( const CDmeLogLayer *src ); |
|
virtual void CopyPartialLayer( const CDmeLogLayer *src, DmeTime_t startTime, DmeTime_t endTime, bool bRebaseTimestamps ); |
|
virtual void ExplodeLayer( const CDmeLogLayer *src, DmeTime_t startTime, DmeTime_t endTime, bool bRebaseTimestamps, DmeTime_t tResampleInterval ); |
|
virtual void InsertKeyFromLayer( DmeTime_t keyTime, const CDmeLogLayer *src, DmeTime_t srcKeyTime ); |
|
|
|
// Finds a key within tolerance, or adds one. Unlike SetKey, this will *not* delete keys after the specified time |
|
int FindOrAddKey( DmeTime_t nTime, DmeTime_t nTolerance, const T& value, int curveType = CURVE_DEFAULT ); |
|
|
|
// Sets a key, removes all keys after this time |
|
void SetKey( DmeTime_t time, const T& value, int curveType = CURVE_DEFAULT ); |
|
// This inserts a key using the current values to construct the proper value for the time |
|
virtual int InsertKeyAtTime( DmeTime_t nTime, int curveType = CURVE_DEFAULT ); |
|
|
|
void SetKeyValue( int nKey, const T& value ); |
|
|
|
const T& GetValue( DmeTime_t time ) const; |
|
|
|
const T& GetKeyValue( int nKeyIndex ) const; |
|
const T& GetValueSkippingKey( int nKeyToSkip ) const; |
|
|
|
// This inserts a key. Unlike SetKey, this will *not* delete keys after the specified time |
|
int InsertKey( DmeTime_t nTime, const T& value, int curveType = CURVE_DEFAULT ); |
|
|
|
// inherited from CDmeLog |
|
virtual void ClearKeys(); |
|
virtual void SetKey( DmeTime_t time, const CDmAttribute *pAttr, uint index = 0, int curveType = CURVE_DEFAULT ); |
|
virtual bool SetDuplicateKeyAtTime( DmeTime_t time ); |
|
virtual void GetValue( DmeTime_t time, CDmAttribute *pAttr, uint index = 0 ) const; |
|
virtual float GetComponent( DmeTime_t time, int componentIndex ) const; |
|
virtual DmAttributeType_t GetDataType() const; |
|
virtual bool IsConstantValued() const; |
|
virtual void RemoveRedundantKeys(); |
|
virtual void RemoveRedundantKeys( float threshold ); |
|
|
|
virtual void RemoveKey( int nKeyIndex, int nNumKeysToRemove = 1 ); |
|
virtual void Resample( DmeFramerate_t samplerate ); |
|
virtual void Filter( int nSampleRadius ); |
|
virtual void Filter2( DmeTime_t sampleRadius ); |
|
|
|
void RemoveKeys( DmeTime_t starttime ); |
|
|
|
// curve info helpers |
|
const CDmeTypedCurveInfo< T > *GetTypedCurveInfo() const; |
|
CDmeTypedCurveInfo< T > *GetTypedCurveInfo(); |
|
|
|
bool IsUsingEdgeInfo() const; |
|
void GetEdgeInfo( int edge, bool& active, T& val, int& curveType ) const; |
|
const T& GetDefaultEdgeZeroValue() const; |
|
DmeTime_t GetRightEdgeTime() const; |
|
|
|
void SetOwnerLog( CDmeLog *owner ); |
|
|
|
CDmeTypedLog< T > *GetTypedOwnerLog(); |
|
const CDmeTypedLog< T > *GetTypedOwnerLog() const; |
|
|
|
protected: |
|
|
|
int GetEdgeCurveType( int edge ) const; |
|
void GetZeroValue( int side, T& val ) const; |
|
|
|
void GetValueUsingCurveInfo( DmeTime_t time, T& out ) const; |
|
void GetValueUsingCurveInfoSkippingKey( int nKeyToSkip, T& out ) const; |
|
void GetBoundedSample( int keyindex, DmeTime_t& time, T& val, int& curveType ) const; |
|
|
|
void CurveSimplify_R( float thresholdSqr, int startPoint, int endPoint, CDmeTypedLogLayer< T > *output ); |
|
|
|
friend CDmeTypedLog< T >; |
|
|
|
protected: |
|
CDmaArray< T > m_values; |
|
}; |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// CDmeTypedLog - implementation class for all logs |
|
//----------------------------------------------------------------------------- |
|
template< class T > |
|
class CDmeTypedLog : public CDmeLog |
|
{ |
|
DEFINE_ELEMENT( CDmeTypedLog, CDmeLog ); |
|
|
|
public: |
|
|
|
virtual void OnAttributeArrayElementAdded( CDmAttribute *pAttribute, int nFirstElem, int nLastElem ); |
|
|
|
CDmeTypedLogLayer< T > *GetLayer( int index ); |
|
const CDmeTypedLogLayer< T > *GetLayer( int index ) const; |
|
|
|
void StampKeyAtHead( DmeTime_t tHeadPosition, DmeTime_t tPreviousHeadPosition, const DmeLog_TimeSelection_t& params, const T& value ); |
|
void StampKeyAtHead( DmeTime_t tHeadPosition, DmeTime_t tPreviousHeadPosition, const DmeLog_TimeSelection_t& params, const CDmAttribute *pAttr, uint index = 0 ); |
|
void FinishTimeSelection( DmeTime_t tHeadPosition, DmeLog_TimeSelection_t& params ); // in attached, timeadvancing mode, we need to blend out of the final sample over the fadeout interval |
|
void FilterUsingTimeSelection( IUniformRandomStream *random, float flScale, const DmeLog_TimeSelection_t& params, int filterType, bool bResample, bool bApplyFalloff, const CDmeLogLayer *baseLayer, CDmeLogLayer *writeLayer ); |
|
void FilterUsingTimeSelection( IUniformRandomStream *random, const DmeLog_TimeSelection_t& params, int filterType, bool bResample, bool bApplyFalloff ); |
|
void StaggerUsingTimeSelection( const DmeLog_TimeSelection_t& params, DmeTime_t tStaggerAmount, const CDmeLogLayer *baseLayer, CDmeLogLayer *writeLayer ); |
|
void RevealUsingTimeSelection( const DmeLog_TimeSelection_t ¶ms, CDmeLogLayer *savedLayer ); |
|
void BlendLayersUsingTimeSelection( const DmeLog_TimeSelection_t ¶ms ); |
|
void BlendLayersUsingTimeSelection( const CDmeLogLayer *firstLayer, const CDmeLogLayer *secondLayer, CDmeLogLayer *outputLayer, const DmeLog_TimeSelection_t ¶ms, bool bUseBaseLayerSamples, DmeTime_t tStartOffset ); |
|
void BlendTimesUsingTimeSelection( const CDmeLogLayer *firstLayer, const CDmeLogLayer *secondLayer, CDmeLogLayer *outputLayer, const DmeLog_TimeSelection_t ¶ms, DmeTime_t tStartOffset ); |
|
|
|
virtual void PasteAndRescaleSamples( const CDmeLogLayer *src, const DmeLog_TimeSelection_t& srcParams, const DmeLog_TimeSelection_t& destParams, bool bBlendAreaInFalloffRegion ); |
|
virtual void PasteAndRescaleSamples( const CDmeLogLayer *pBaseLayer, const CDmeLogLayer *pDataLayer, CDmeLogLayer *pOutputLayer, const DmeLog_TimeSelection_t& srcParams, const DmeLog_TimeSelection_t& destParams, bool bBlendAreaInFalloffRegion ); |
|
virtual void BuildCorrespondingLayer( const CDmeLogLayer *pReferenceLayer, const CDmeLogLayer *pDataLayer, CDmeLogLayer *pOutputLayer ); |
|
|
|
virtual void BuildNormalizedLayer( CDmeTypedLogLayer< float > *target ); |
|
|
|
// Finds a key within tolerance, or adds one. Unlike SetKey, this will *not* delete keys after the specified time |
|
int FindOrAddKey( DmeTime_t nTime, DmeTime_t nTolerance, const T& value, int curveType = CURVE_DEFAULT ); |
|
|
|
// Sets a key, removes all keys after this time |
|
void SetKey( DmeTime_t time, const T& value, int curveType = CURVE_DEFAULT ); |
|
int InsertKeyAtTime( DmeTime_t nTime, int curveType = CURVE_DEFAULT ); |
|
bool ValuesDiffer( const T& a, const T& b ) const; |
|
const T& GetValue( DmeTime_t time ) const; |
|
const T& GetValueSkippingTopmostLayer( DmeTime_t time ) const; |
|
|
|
const T& GetKeyValue( int nKeyIndex ) const; |
|
|
|
// This inserts a key. Unlike SetKey, this will *not* delete keys after the specified time |
|
int InsertKey( DmeTime_t nTime, const T& value, int curveType = CURVE_DEFAULT ); |
|
|
|
// inherited from CDmeLog |
|
virtual void ClearKeys(); |
|
virtual void SetKey( DmeTime_t time, const CDmAttribute *pAttr, uint index = 0, int curveType = CURVE_DEFAULT ); |
|
virtual bool SetDuplicateKeyAtTime( DmeTime_t time ); |
|
virtual void GetValue( DmeTime_t time, CDmAttribute *pAttr, uint index = 0 ) const; |
|
virtual void GetValueSkippingTopmostLayer( DmeTime_t time, CDmAttribute *pAttr, uint index = 0 ) const; |
|
virtual float GetComponent( DmeTime_t time, int componentIndex ) const; |
|
virtual DmAttributeType_t GetDataType() const; |
|
virtual float GetValueThreshold() const { return m_threshold; } |
|
virtual void SetValueThreshold( float thresh ); |
|
virtual bool IsConstantValued() const; |
|
virtual void RemoveRedundantKeys(); |
|
virtual void RemoveRedundantKeys( float threshold ); |
|
virtual void RemoveKey( int nKeyIndex, int nNumKeysToRemove = 1 ); |
|
virtual void Resample( DmeFramerate_t samplerate ); |
|
virtual void Filter( int nSampleRadius ); |
|
virtual void Filter2( DmeTime_t sampleRadius ); |
|
|
|
virtual int FindKeyWithinTolerance( DmeTime_t time, DmeTime_t nTolerance ); |
|
virtual DmeTime_t GetKeyTime( int nKeyIndex ) const; |
|
virtual void SetKeyTime( int nKeyIndex, DmeTime_t keyTime ); |
|
|
|
virtual CDmeLogLayer *AddNewLayer(); |
|
virtual void FlattenLayers( float threshhold, int flags ); |
|
|
|
// Only used by undo system!!! |
|
virtual void AddLayerToTail( CDmeLogLayer *layer ); |
|
virtual CDmeLogLayer *RemoveLayerFromTail(); |
|
virtual CDmeLogLayer *RemoveLayer( int iLayer ); |
|
|
|
// curve info helpers |
|
const CDmeTypedCurveInfo< T > *GetTypedCurveInfo() const; |
|
CDmeTypedCurveInfo< T > *GetTypedCurveInfo(); |
|
virtual CDmeCurveInfo *GetOrCreateCurveInfo(); |
|
virtual void SetCurveInfo( CDmeCurveInfo *pCurveInfo ); |
|
|
|
// For "faceposer" style left/right edges, this controls whether interpolators try to mimic faceposer left/right edge behavior |
|
void SetUseEdgeInfo( bool state ); |
|
bool IsUsingEdgeInfo() const; |
|
|
|
void SetEdgeInfo( int edge, bool active, const T& val, int curveType ); |
|
void GetEdgeInfo( int edge, bool& active, T& val, int& curveType ) const; |
|
|
|
void SetDefaultEdgeZeroValue( const T& val ); |
|
const T& GetDefaultEdgeZeroValue() const; |
|
|
|
void SetRightEdgeTime( DmeTime_t time ); |
|
DmeTime_t GetRightEdgeTime() const; |
|
|
|
bool IsEdgeActive( int edge ) const; |
|
void GetEdgeValue( int edge, T& value ) const; |
|
|
|
int GetEdgeCurveType( int edge ) const; |
|
void GetZeroValue( int side, T& val ) const; |
|
|
|
T ClampValue( const T& value ); |
|
|
|
void SetDefaultValue( const T& value ); |
|
const T& GetDefaultValue() const; |
|
bool HasDefaultValue() const; |
|
void ClearDefaultValue(); |
|
|
|
static void SetDefaultValueThreshold( float thresh ); |
|
static float GetDefaultValueThreshold(); |
|
|
|
static float s_defaultThreshold; |
|
|
|
protected: |
|
void RemoveKeys( DmeTime_t starttime ); |
|
|
|
void _StampKeyAtHeadResample( DmeTime_t tHeadPosition, const DmeLog_TimeSelection_t & params, const T& value, bool bSkipToHead, bool bClearPreviousKeys ); |
|
void _StampKeyAtHeadFilteredByTimeSelection( DmeTime_t tHeadPosition, DmeTime_t tPreviousHeadPosition, const DmeLog_TimeSelection_t & params, const T& value ); |
|
void _StampKeyFilteredByTimeSelection( CDmeTypedLogLayer< T > *pWriteLayer, DmeTime_t t, const DmeLog_TimeSelection_t ¶ms, const T& value, bool bForce = false ); |
|
|
|
protected: |
|
// this really only makes sense for some of our subclasses, basically those which have float data |
|
// anything else's threshhold is almost certainly 0, and that class just ignores m_threshold |
|
float m_threshold; |
|
|
|
CDmaVar< bool > m_UseDefaultValue; |
|
CDmaVar< T > m_DefaultValue; |
|
}; |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Template methods |
|
//----------------------------------------------------------------------------- |
|
template< class T > |
|
DmAttributeType_t CDmeTypedLogLayer<T>::GetDataType() const |
|
{ |
|
return CDmAttributeInfo< T >::AttributeType(); |
|
} |
|
|
|
template< class T > |
|
bool CDmeTypedLogLayer<T>::IsConstantValued() const |
|
{ |
|
if ( m_values.Count() < 2 ) |
|
return true; |
|
|
|
if ( m_values.Count() == 2 && !GetTypedOwnerLog()->ValuesDiffer( m_values[ 0 ], m_values[ 1 ] ) ) |
|
return true; |
|
|
|
// we're throwing away duplicate values during recording, so this is generally correct |
|
// although there are paths to set keys that don't use the duplicate test, so it's not 100% |
|
return false; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Template methods |
|
//----------------------------------------------------------------------------- |
|
template< class T > |
|
DmAttributeType_t CDmeTypedLog<T>::GetDataType() const |
|
{ |
|
return CDmAttributeInfo< T >::AttributeType(); |
|
} |
|
|
|
template< class T > |
|
void CDmeTypedLog<T>::SetDefaultValueThreshold( float thresh ) |
|
{ |
|
s_defaultThreshold = thresh; |
|
} |
|
|
|
template< class T > |
|
float CDmeTypedLog<T>::GetDefaultValueThreshold() |
|
{ |
|
return s_defaultThreshold; |
|
} |
|
|
|
template< class T > |
|
void CDmeTypedLog<T>::SetValueThreshold( float thresh ) |
|
{ |
|
m_threshold = thresh; |
|
} |
|
|
|
template< class T > |
|
bool CDmeTypedLog<T>::IsConstantValued() const |
|
{ |
|
int c = m_Layers.Count(); |
|
for ( int i = 0; i < c; ++i ) |
|
{ |
|
if ( !GetLayer( i )->IsConstantValued() ) |
|
return false; |
|
} |
|
|
|
return true; |
|
} |
|
|
|
template< class T > |
|
void CDmeTypedLog<T>::RemoveRedundantKeys() |
|
{ |
|
int bestLayer = GetTopmostLayer(); |
|
if ( bestLayer < 0 ) |
|
return; |
|
|
|
GetLayer( bestLayer )->RemoveRedundantKeys(); |
|
} |
|
|
|
template< class T > |
|
inline float Normalize( const T& val ) |
|
{ |
|
Assert( 0 ); |
|
return 0.5f; |
|
} |
|
|
|
// AT_INT |
|
// AT_FLOAT |
|
// AT_VECTOR* |
|
|
|
template<> |
|
inline float Normalize( const bool& val ) |
|
{ |
|
return val ? 1.0f : 0.0f; |
|
} |
|
|
|
template<> |
|
inline float Normalize( const Color& val ) |
|
{ |
|
float sum = 0.0f; |
|
for ( int i = 0 ; i < 4; ++i ) |
|
{ |
|
sum += val[ i ]; |
|
} |
|
sum /= 4.0f; |
|
return clamp( sum / 255.0f, 0.0f, 1.0f ); |
|
} |
|
|
|
template<> |
|
inline float Normalize( const QAngle& val ) |
|
{ |
|
float sum = 0.0f; |
|
for ( int i = 0 ; i < 3; ++i ) |
|
{ |
|
float ang = val[ i ]; |
|
if ( ang < 0.0f ) |
|
{ |
|
ang += 360.0f; |
|
} |
|
|
|
sum += ang; |
|
} |
|
return clamp( ( sum / 3.0f ) / 360.0f, 0.0f, 1.0f ); |
|
} |
|
|
|
template<> |
|
inline float Normalize( const Quaternion& val ) |
|
{ |
|
QAngle angle; |
|
QuaternionAngles( val, angle ); |
|
return Normalize( angle ); |
|
} |
|
|
|
template< class T > |
|
inline void CDmeTypedLog< T >::BuildNormalizedLayer( CDmeTypedLogLayer< float > *pTarget ) |
|
{ |
|
Assert( pTarget ); |
|
Assert( GetDataType() != AT_FLOAT ); |
|
|
|
CDmeTypedLogLayer< T > *pBaseLayer = static_cast< CDmeTypedLogLayer< T > * >( GetLayer( 0 ) ); |
|
if ( !pBaseLayer ) |
|
return; |
|
|
|
int kc = pBaseLayer->GetKeyCount(); |
|
for ( int i = 0; i < kc; ++i ) |
|
{ |
|
DmeTime_t tKeyTime = pBaseLayer->GetKeyTime( i ); |
|
T keyValue = pBaseLayer->GetKeyValue( i ); |
|
float flNormalized = Normalize( keyValue ); |
|
|
|
pTarget->InsertKey( tKeyTime, flNormalized ); |
|
} |
|
|
|
if ( HasDefaultValue() ) |
|
{ |
|
pTarget->GetTypedOwnerLog()->SetDefaultValue( Normalize( GetDefaultValue() ) ); |
|
} |
|
} |
|
|
|
// Generic implementations all stubbed |
|
// Forward declare specific typed instantiations for float types |
|
|
|
template< class T > T CDmeTypedLog< T >::ClampValue( const T& value ) { return value; } |
|
template<> float CDmeTypedLog< float >::ClampValue( const float& value ); |
|
|
|
|
|
template< class T > void CDmeTypedCurveInfo< T >::GetZeroValue( int side, T& val ) const{ Assert( 0 ); } |
|
template< class T > bool CDmeTypedCurveInfo< T >::IsEdgeActive( int edge ) const{ Assert( 0 ); return false; } |
|
template< class T > void CDmeTypedCurveInfo< T >::GetEdgeValue( int edge, T &value ) const{ Assert( 0 ); } |
|
|
|
template<> void CDmeTypedCurveInfo< float >::GetZeroValue( int side, float& val ) const; |
|
template<> bool CDmeTypedCurveInfo< float >::IsEdgeActive( int edge ) const; |
|
template<> void CDmeTypedCurveInfo< float >::GetEdgeValue( int edge, float &value ) const; |
|
|
|
template<> void CDmeTypedCurveInfo< Vector >::GetZeroValue( int side, Vector& val ) const; |
|
template<> void CDmeTypedCurveInfo< Quaternion >::GetZeroValue( int side, Quaternion& val ) const; |
|
|
|
template< class T > void CDmeTypedLogLayer< T >::GetValueUsingCurveInfo( DmeTime_t time, T& out ) const { Assert( 0 ); } |
|
template< class T > void CDmeTypedLogLayer< T >::GetValueUsingCurveInfoSkippingKey( int nKeyToSkip, T& out ) const { Assert( 0 ); } |
|
template<> void CDmeTypedLogLayer< float >::GetValueUsingCurveInfo( DmeTime_t time, float& out ) const; |
|
template<> void CDmeTypedLogLayer< float >::GetValueUsingCurveInfoSkippingKey( int nKeyToSkip, float& out ) const; |
|
|
|
template<> void CDmeTypedLogLayer< Vector >::GetValueUsingCurveInfo( DmeTime_t time, Vector& out ) const; |
|
template<> void CDmeTypedLogLayer< Vector >::GetValueUsingCurveInfoSkippingKey( int nKeyToSkip, Vector& out ) const; |
|
|
|
template<> void CDmeTypedLogLayer< Quaternion >::GetValueUsingCurveInfo( DmeTime_t time, Quaternion& out ) const; |
|
template<> void CDmeTypedLogLayer< Quaternion >::GetValueUsingCurveInfoSkippingKey( int nKeyToSkip, Quaternion& out ) const; |
|
|
|
template<class T> void CDmeTypedLogLayer< T >::CurveSimplify_R( float thresholdSqr, int startPoint, int endPoint, CDmeTypedLogLayer< T > *output ); |
|
template<> void CDmeTypedLogLayer< bool >::CurveSimplify_R( float thresholdSqr, int startPoint, int endPoint, CDmeTypedLogLayer< bool > *output ); |
|
template<> void CDmeTypedLogLayer< int >::CurveSimplify_R( float thresholdSqr, int startPoint, int endPoint, CDmeTypedLogLayer< int > *output ); |
|
template<> void CDmeTypedLogLayer< Color >::CurveSimplify_R( float thresholdSqr, int startPoint, int endPoint, CDmeTypedLogLayer< Color > *output ); |
|
template<> void CDmeTypedLogLayer< Quaternion >::CurveSimplify_R( float thresholdSqr, int startPoint, int endPoint, CDmeTypedLogLayer< Quaternion > *output ); |
|
template<> void CDmeTypedLogLayer< VMatrix >::CurveSimplify_R( float thresholdSqr, int startPoint, int endPoint, CDmeTypedLogLayer< VMatrix > *output ); |
|
|
|
template<> void CDmeTypedLog< Vector >::BuildNormalizedLayer( CDmeTypedLogLayer< float > *target ); |
|
template<> void CDmeTypedLog< Vector2D >::BuildNormalizedLayer( CDmeTypedLogLayer< float > *target ); |
|
template<> void CDmeTypedLog< Vector4D >::BuildNormalizedLayer( CDmeTypedLogLayer< float > *target ); |
|
template<> void CDmeTypedLog< float >::BuildNormalizedLayer( CDmeTypedLogLayer< float > *target ); |
|
template<> void CDmeTypedLog< int >::BuildNormalizedLayer( CDmeTypedLogLayer< float > *target ); |
|
|
|
//template<> void CDmeTypedLog< float >::FinishTimeSelection( DmeTime_t tHeadPosition, DmeLog_TimeSelection_t& params ); |
|
//template<> void CDmeTypedLog< bool >::_StampKeyAtHeadResample( const DmeLog_TimeSelection_t& params, const bool& value ) { Assert( 0 ); } |
|
|
|
//----------------------------------------------------------------------------- |
|
// typedefs for convenience (and so the user-supplied names match the programmer names) |
|
//----------------------------------------------------------------------------- |
|
typedef CDmeTypedLog<int> CDmeIntLog; |
|
typedef CDmeTypedLog<float> CDmeFloatLog; |
|
typedef CDmeTypedLog<bool> CDmeBoolLog; |
|
typedef CDmeTypedLog<Color> CDmeColorLog; |
|
typedef CDmeTypedLog<Vector2D> CDmeVector2Log; |
|
typedef CDmeTypedLog<Vector> CDmeVector3Log; |
|
typedef CDmeTypedLog<Vector4D> CDmeVector4Log; |
|
typedef CDmeTypedLog<QAngle> CDmeQAngleLog; |
|
typedef CDmeTypedLog<Quaternion> CDmeQuaternionLog; |
|
typedef CDmeTypedLog<VMatrix> CDmeVMatrixLog; |
|
typedef CDmeTypedLog<CUtlString> CDmeStringLog; |
|
|
|
//----------------------------------------------------------------------------- |
|
// typedefs for convenience (and so the user-supplied names match the programmer names) |
|
//----------------------------------------------------------------------------- |
|
typedef CDmeTypedLogLayer<int> CDmeIntLogLayer; |
|
typedef CDmeTypedLogLayer<float> CDmeFloatLogLayer; |
|
typedef CDmeTypedLogLayer<bool> CDmeBoolLogLayer; |
|
typedef CDmeTypedLogLayer<Color> CDmeColorLogLayer; |
|
typedef CDmeTypedLogLayer<Vector2D> CDmeVector2LogLayer; |
|
typedef CDmeTypedLogLayer<Vector> CDmeVector3LogLayer; |
|
typedef CDmeTypedLogLayer<Vector4D> CDmeVector4LogLayer; |
|
typedef CDmeTypedLogLayer<QAngle> CDmeQAngleLogLayer; |
|
typedef CDmeTypedLogLayer<Quaternion> CDmeQuaternionLogLayer; |
|
typedef CDmeTypedLogLayer<VMatrix> CDmeVMatrixLogLayer; |
|
typedef CDmeTypedLogLayer<CUtlString> CDmeStringLogLayer; |
|
|
|
//----------------------------------------------------------------------------- |
|
// typedefs for convenience (and so the user-supplied names match the programmer names) |
|
//----------------------------------------------------------------------------- |
|
typedef CDmeTypedCurveInfo<int> CDmeIntCurveInfo; |
|
typedef CDmeTypedCurveInfo<float> CDmeFloatCurveInfo; |
|
typedef CDmeTypedCurveInfo<bool> CDmeBoolCurveInfo; |
|
typedef CDmeTypedCurveInfo<Color> CDmeColorCurveInfo; |
|
typedef CDmeTypedCurveInfo<Vector2D> CDmeVector2CurveInfo; |
|
typedef CDmeTypedCurveInfo<Vector> CDmeVector3CurveInfo; |
|
typedef CDmeTypedCurveInfo<Vector4D> CDmeVector4CurveInfo; |
|
typedef CDmeTypedCurveInfo<QAngle> CDmeQAngleCurveInfo; |
|
typedef CDmeTypedCurveInfo<Quaternion> CDmeQuaternionCurveInfo; |
|
typedef CDmeTypedCurveInfo<VMatrix> CDmeVMatrixCurveInfo; |
|
typedef CDmeTypedCurveInfo<CUtlString> CDmeStringCurveInfo; |
|
|
|
// the following types are not supported |
|
// AT_ELEMENT, |
|
// AT_VOID, |
|
// AT_OBJECTID, |
|
// <all array types> |
|
|
|
//----------------------------------------------------------------------------- |
|
// Helpers for particular types of log layers |
|
//----------------------------------------------------------------------------- |
|
void GenerateRotationLog( CDmeQuaternionLogLayer *pLayer, const Vector &vecAxis, DmeTime_t pTime[4], float pRevolutionsPerSec[4] ); |
|
|
|
// rotates a position log |
|
void RotatePositionLog( CDmeVector3LogLayer *pPositionLog, const matrix3x4_t& matrix ); |
|
|
|
// rotates an orientation log |
|
void RotateOrientationLog( CDmeQuaternionLogLayer *pOrientationLog, const matrix3x4_t& matrix, bool bPreMultiply ); |
|
|
|
|
|
#endif // DMELOG_H
|
|
|