예제 #1
0
/** 
 * Resamples animation until maximum error is smaller than specified value. 
 * @param maxErr Maximum absolute error
 */
static void resampleFloatKeys( KeyFrameContainer& anim, Interval range, float maxErr, const Vector<float>& frames )
{
	TimeValue dticks = SGEXPORT_TICKS_PER_SAMPLE;
	int frame = range.Start() / dticks;
	require( frame >= 0 && frame < frames.size() );
	TimeValue rangeLen = (range.Duration()/SGEXPORT_TICKS_PER_SAMPLE)*SGEXPORT_TICKS_PER_SAMPLE;

	for ( TimeValue ticks = range.Start() ; ticks < range.End() ; ticks += dticks )
	{
		if ( ticks > range.End() )
			ticks = range.End();

		// find out error (distance) between real and sampled animation
		require( frame >= 0 && frame < frames.size() );
		float realValue = frames[frame++];
		float sampledValue = 0.f;
		anim.getValue( TicksToSec(ticks), &sampledValue, 1 );
		float err = Math::abs( realValue - sampledValue );

		// sample more accurately if needed
		if ( err > maxErr && rangeLen > dticks )
		{
			TimeValue halfRange = alignTicks( (range.End() + range.Start())/2 );
			anim.insertKey( KeyFrame( TicksToSec(halfRange), INTERP_TYPE, &frames[halfRange/dticks], 1 ) );

			if ( ticks <= halfRange )
				resampleFloatKeys( anim, Interval(range.Start(),halfRange), maxErr, frames );
			else
				resampleFloatKeys( anim, Interval(halfRange,range.End()), maxErr, frames );
		}

		if ( ticks == range.End() )
			break;
	}
}
예제 #2
0
파일: floatmc.cpp 프로젝트: 2asoft/xray
void FloatMC::BeginCapture(Interval record,TimeValue sampSize)
	{
	// Set the base point to the controller value at the start time.
	cont->GetValue(record.Start(),&base,FOREVER,CTRL_ABSOLUTE);	

	// Allocate a data buffer
	sampleCount = record.Duration()/sampSize + 1;
	data = new float[sampleCount];
	for (int i=0; i<sampleCount; i++) data[i] = 0.0f;
	}
예제 #3
0
파일: scalemc.cpp 프로젝트: 2asoft/xray
void ScaleMC::BeginCapture(Interval record,TimeValue sampSize)
	{
	// Set the base point to the controller value at the start time.
	ScaleValue s;
	cont->GetValue(record.Start(),&s,FOREVER,CTRL_ABSOLUTE);	
	base = s.s;

	// Allocate a data buffer
	sampleCount = record.Duration()/sampSize + 1;
	data = new Point3[sampleCount];
	for (int i=0; i<sampleCount; i++) data[i] = Point3(1,1,1);
	}
예제 #4
0
파일: rotmc.cpp 프로젝트: 2asoft/xray
void RotationMC::BeginCapture(Interval record,TimeValue sampSize)
	{
	// Set the base point to the controller value at the start time.
	Quat q;
	cont->GetValue(record.Start(),&q,FOREVER,CTRL_ABSOLUTE);	
	QuatToEuler(q,base);

	// Allocate a data buffer
	sampleCount = record.Duration()/sampSize + 1;
	data = new Point3[sampleCount];
	for (int i=0; i<sampleCount; i++) data[i] = Point3(0,0,0);
	}
예제 #5
0
/** 
 * Resamples animation until maximum error is smaller than specified angle (radians). 
 * @param maxErr Maximum absolute error (radians).
 */
static void resampleRotationKeys( KeyFrameContainer& anim, Interval range, float maxErr, const Vector<Matrix4x4>& tm )
{
	TimeValue dticks = SGEXPORT_TICKS_PER_SAMPLE;
	int frame = range.Start() / dticks;
	require( frame >= 0 && frame < tm.size() );
	TimeValue rangeLen = (range.Duration()/SGEXPORT_TICKS_PER_SAMPLE)*SGEXPORT_TICKS_PER_SAMPLE;

	for ( TimeValue ticks = range.Start() ; ticks < range.End() ; ticks += dticks )
	{
		if ( ticks > range.End() )
			ticks = range.End();

		// find out error (distance) between real and sampled animation
		require( frame >= 0 && frame < tm.size() );
		const Matrix4x4& m = tm[frame++];
		Matrix3x3 ref = m.rotation().orthonormalize();
		float q[4];
		anim.getValue( TicksToSec(ticks), q, 4 );
		Matrix3x3 cmp( Quaternion(q[0],q[1],q[2],q[3]) );
		float xang = Math::abs( Math::acos( clamp(cmp.getColumn(0).dot(ref.getColumn(0)), -1.f, 1.f) ) );
		float yang = Math::abs( Math::acos( clamp(cmp.getColumn(1).dot(ref.getColumn(1)), -1.f, 1.f) ) );
		float zang = Math::abs( Math::acos( clamp(cmp.getColumn(2).dot(ref.getColumn(2)), -1.f, 1.f) ) );
		float err = xang;
		if ( yang > err )
			err = yang;
		if ( zang > err )
			err = zang;

		// sample more accurately if needed
		if ( err > maxErr && rangeLen > dticks )
		{
			TimeValue halfRange = alignTicks( (range.End() + range.Start())/2 );
			AnimExportUtil::addRotationKey( anim, tm[halfRange/dticks], TicksToSec(halfRange) );
			if ( ticks <= halfRange )
				resampleRotationKeys( anim, Interval(range.Start(),halfRange), maxErr, tm );
			else
				resampleRotationKeys( anim, Interval(halfRange,range.End()), maxErr, tm );
		}

		if ( ticks == range.End() )
			break;
	}
}
예제 #6
0
/** 
 * Resamples animation until maximum error is smaller than specified value. 
 * @param maxErr Maximum relative error, i.e. 0.05f == 5%.
 */
static void resampleScaleKeys( KeyFrameContainer& anim, Interval range, float maxErr, const Vector<Matrix4x4>& tm )
{
	TimeValue dticks = SGEXPORT_TICKS_PER_SAMPLE;
	int frame = range.Start() / dticks;
	require( frame >= 0 && frame < tm.size() );
	TimeValue rangeLen = (range.Duration()/SGEXPORT_TICKS_PER_SAMPLE)*SGEXPORT_TICKS_PER_SAMPLE;

	for ( TimeValue ticks = range.Start() ; ticks < range.End() ; ticks += dticks )
	{
		if ( ticks > range.End() )
			ticks = range.End();

		// find out error (distance) between real and sampled animation
		require( frame >= 0 && frame < tm.size() );
		const Matrix4x4& m = tm[frame++];
		Vector3 ref;
		Vector3 a;
		a = getAxis(m,0); ref[0] = a.dot(normalize0(a));
		a = getAxis(m,1); ref[1] = a.dot(normalize0(a));
		a = getAxis(m,2); ref[2] = a.dot(normalize0(a));
		float cmp[3];
		anim.getValue( TicksToSec(ticks), cmp, 3 );
		float err = (Vector3(cmp[0],cmp[1],cmp[2]) - ref).length();
		if ( ref.length() > Float::MIN_VALUE )
			err /= ref.length();

		// sample more accurately if needed
		if ( err > maxErr && rangeLen > dticks )
		{
			TimeValue halfRange = alignTicks( (range.End() + range.Start())/2 );
			AnimExportUtil::addScaleKey( anim, tm[halfRange/dticks], TicksToSec(halfRange) );
			if ( ticks <= halfRange )
				resampleScaleKeys( anim, Interval(range.Start(),halfRange), maxErr, tm );
			else
				resampleScaleKeys( anim, Interval(halfRange,range.End()), maxErr, tm );
		}

		if ( ticks == range.End() )
			break;
	}
}