示例#1
0
hkDemo::Result ControlDemo::stepDemo()
{
	hkaPose pose (m_skeleton);

	// Advance the active animations
	for (int i=0; i < HK_NUM_CHARACTERS; i++)
	{
		m_skeletonInstance[i]->stepDeltaTime( m_timestep );

		// Sample the active animations and combine into a single pose
		m_skeletonInstance[i]->sampleAndCombineAnimations( pose.accessUnsyncedPoseLocalSpace().begin(), pose.getFloatSlotValues().begin()  );

		hkQsTransform worldFromModel (hkQsTransform::IDENTITY);
		worldFromModel.m_translation.set(0, i*2-4.0f ,0);
		AnimationUtils::drawPose( pose, worldFromModel, 0xffff0000 );
	} // all animations


	//draw the text
	for (int t=0; t < HK_NUM_CHARACTERS; t++)
	{
		hkString txt(description[t]);
		m_env->m_textDisplay->outputText3D( txt, 0, t*2-4.0f ,-1, 0xffffffff, 1);
	}

	// Destroy the controls after a period of time
	{
		static int countdown = 2000;
		countdown--;
		if (countdown == 0)
		{
			for (int i=0; i < HK_NUM_CHARACTERS; i++)
			{
				m_control[i]->removeReference();
			}
		}
	}
	return hkDemo::DEMO_OK;
}
hkDemo::Result SkeletonMappingDemo::stepDemo()
{
	// Advance the animation of both a high-res and low-res animated skeletons
	m_highAnimatedSkeleton->stepDeltaTime( m_timestep );
	m_lowAnimatedSkeleton->stepDeltaTime ( m_timestep );

	// HIGH LOW HIGH
	{
		// Transform used for display
		hkQsTransform worldFromModel (hkQsTransform::IDENTITY );

		// Get a high-res pose from the high resolution animated skeleton
		hkaPose poseHigh (m_highSkeleton);
		m_highAnimatedSkeleton->sampleAndCombineAnimations( poseHigh.accessUnsyncedPoseLocalSpace().begin(), poseHigh.getFloatSlotValues().begin());

		// Draw the high res pose
		AnimationUtils::drawPose( poseHigh, worldFromModel, 0x7fffffff);

		// Construct a low-res pose in the reference pose
		hkaPose poseLow (m_lowSkeleton);
		poseLow.setToReferencePose();

		// Map the high-res pos into the low-res pose
		m_highToLowMapper->mapPose(poseHigh, poseLow, hkaSkeletonMapper::CURRENT_POSE);

		// Draw the low res pose
		worldFromModel.m_translation.set(20,0,0);
		AnimationUtils::drawPose( poseLow, worldFromModel, 0x7f00ff00 );

		// Now, map the los-res pos back to the high-res pose
		m_lowToHighMapper->mapPose( poseLow, poseHigh, hkaSkeletonMapper::CURRENT_POSE);

		// Draw the high res pose
		worldFromModel.m_translation.set(40,0,0);
		AnimationUtils::drawPose( poseHigh, worldFromModel, 0x7fffffff );
	}

	// LOW HIGH LOW
	{
		// Transform used for display
		hkQsTransform worldFromModel (hkQsTransform::IDENTITY);

		// Get a low-res pose from the low resolution animated skeleton
		hkaPose poseLow (m_lowSkeleton);
		m_lowAnimatedSkeleton->sampleAndCombineAnimations( poseLow.accessUnsyncedPoseLocalSpace().begin(), poseLow.getFloatSlotValues().begin() );

		// Draw the low-res pose
		worldFromModel.m_translation.set(0, 0, 90);
		AnimationUtils::drawPose( poseLow, worldFromModel, 0x7f00ff00);

		// Construct a high-res pose in the reference pose
		hkaPose poseHigh (m_highSkeleton);
		poseHigh.setToReferencePose();

		// Map the low-res pos to the high-res
		m_lowToHighMapper->mapPose(poseLow, poseHigh, hkaSkeletonMapper::CURRENT_POSE);

		// Draw it
		worldFromModel.m_translation.set(20,0,90);
		AnimationUtils::drawPose( poseHigh, worldFromModel, 0x7fffffff );

		// Now, map the high-res pose back to the low-res pose
		m_highToLowMapper->mapPose(poseHigh, poseLow, hkaSkeletonMapper::CURRENT_POSE);

		// And draw the low-res pose
		worldFromModel.m_translation.set(40,0,90);
		AnimationUtils::drawPose( poseLow, worldFromModel, 0x7f00ff00 );
	}

	return DEMO_OK;
}
hkDemo::Result RagdollScalingDemo::stepDemo()
{
	// Handle button presses...
	hkReal& oldScale = m_scale;
	hkReal newScale = oldScale;
	static const hkReal slowFactor = hkMath::pow( 2.0f, 1.0f / 100.0f );
	static const hkReal fastFactor = hkMath::pow( 2.0f, 1.0f / 10.0f );

	if ( m_env->m_gamePad->isButtonPressed( HKG_PAD_DPAD_UP ) )
	{
		newScale *= slowFactor;
	}

	if ( m_env->m_gamePad->isButtonPressed( HKG_PAD_DPAD_DOWN ) )
	{
		newScale /= slowFactor;
	}

	if ( m_env->m_gamePad->wasButtonPressed( HKG_PAD_DPAD_RIGHT ) )
	{
		newScale *= fastFactor;
	}

	if ( m_env->m_gamePad->wasButtonPressed( HKG_PAD_DPAD_LEFT ) )
	{
		newScale /= fastFactor;
	}

	// Test if the user has requested scaling
	if ( newScale != oldScale )
	{
		const hkReal scale = newScale / oldScale;

		m_world->lock();

		// Use the ragdoll scaling utility
		m_ragdoll->addReference();
		m_ragdoll->removeFromWorld();
		hkaRagdollUtils::scaleRagdoll( m_ragdoll, scale );
		m_ragdoll->addToWorld( m_world, false );
		m_ragdoll->removeReference();

		m_world->unlock();
		
		// Scale the skeleton mapper
		hkaSkeletonMapperUtils::scaleMapping( *m_ragdollFromAnimation, scale );
		hkaSkeletonMapperUtils::scaleMapping( *m_animationFromRagdoll, scale );

		// Scale the reference poses of the animated and ragdoll characters
		hkaSampleAndCombineUtils::scaleTranslations( scale, m_ragdollSkeleton->m_referencePose, m_ragdollSkeleton->m_numBones );
		hkaSampleAndCombineUtils::scaleTranslations( scale, m_animationSkeleton->m_referencePose, m_animationSkeleton->m_numBones );

		// Update the scale value
		oldScale = newScale;
	}


	{
		// Sample the animation and drive the ragdolls to the desired pose
		hkaPose animationPose( m_animationSkeleton );
		hkaPose ragdollPose( m_ragdollSkeleton );
		hkaPose upsampledPose( m_animationSkeleton );
		
		// Sample the character's current animated pose
		m_character->sampleAndCombineAnimations( animationPose.accessUnsyncedPoseLocalSpace().begin(), HK_NULL );

		// Scale the bone lengths of the poses
		hkaSampleAndCombineUtils::scaleTranslations( m_scale, ragdollPose.accessUnsyncedPoseLocalSpace().begin(), m_ragdollSkeleton->m_numBones );
		hkaSampleAndCombineUtils::scaleTranslations( m_scale, animationPose.accessUnsyncedPoseLocalSpace().begin(), m_animationSkeleton->m_numBones );

		// Scale the root (necessary for skinning)
		animationPose.accessUnsyncedPoseLocalSpace()[ 0 ].m_scale.mul4( m_scale );

		// Convert the animation pose to a ragdoll pose
		m_ragdollFromAnimation->mapPose( animationPose.getSyncedPoseModelSpace().begin(), m_ragdollSkeleton->m_referencePose, ragdollPose.accessUnsyncedPoseModelSpace().begin(), hkaSkeletonMapper::CURRENT_POSE );

		// Map the ragdoll pose back to an animation pose
		m_animationFromRagdoll->mapPose( ragdollPose.getSyncedPoseModelSpace().begin(), m_animationSkeleton->m_referencePose, upsampledPose.accessUnsyncedPoseModelSpace().begin(), hkaSkeletonMapper::CURRENT_POSE );

		// Copy the scales back into the upsampled pose
		hkaRagdollUtils::copyScales( upsampledPose.accessUnsyncedPoseModelSpace().begin(), animationPose.getSyncedPoseModelSpace().begin(), m_animationSkeleton->m_numBones );

		// Draw the upsampled Pose
		{
			hkQsTransform animWorldFromModel( m_worldFromModel );
			animWorldFromModel.m_translation( 0 ) = -1.0f;
			
			AnimationUtils::drawPose( upsampledPose, animWorldFromModel );
		}

		// Skin the animation
		{
			hkTransform worldFromModel( m_worldFromModel.m_rotation, m_worldFromModel.m_translation );
			worldFromModel.getTranslation()( 0 ) = 1.0f;
			
			const hkQsTransform* poseModelSpace = upsampledPose.getSyncedPoseModelSpace().begin();
			
			// Construct the composite world transform
			hkLocalArray<hkTransform> compositeWorldInverse( m_animationSkeleton->m_numBones );
			compositeWorldInverse.setSize( m_animationSkeleton->m_numBones );

			for ( int i = 0; i < m_numSkinBindings; i++ )
			{
				// assumes either a straight map (null map) or a single one (1 palette)
				hkInt16* usedBones = m_skinBindings[i]->m_mappings? m_skinBindings[i]->m_mappings[0].m_mapping : HK_NULL;
				int numUsedBones = usedBones? m_skinBindings[i]->m_mappings[0].m_numMapping : m_animationSkeleton->m_numBones;

				// Multiply through by the bind pose inverse world inverse matrices
				for (int p=0; p < numUsedBones; p++)
				{
					int boneIndex = usedBones? usedBones[p] : p;
					compositeWorldInverse[p].setMul( poseModelSpace[ boneIndex ], m_skinBindings[i]->m_boneFromSkinMeshTransforms[ boneIndex ] );
				}

				AnimationUtils::skinMesh( *m_skinBindings[i]->m_mesh, worldFromModel, compositeWorldInverse.begin(), *m_env->m_sceneConverter );
			}
		}

		

		m_world->lock();

		m_ragdollRigidBodyController->driveToPose( m_timestep, ragdollPose.accessSyncedPoseLocalSpace().begin(), m_worldFromModel, HK_NULL );

		m_world->unlock();

		// Step the animation
		m_character->stepDeltaTime( m_timestep );
	}


	// Print the current scale factor
	{
		char buf[ 255 ];
		hkString::sprintf(buf, "Scale: %.3f", m_scale );
		const int h = m_env->m_window->getHeight();
		m_env->m_textDisplay->outputText( buf, 20, h-40, 0xffffffff, 1);
	}



	// Step the physics
	hkDefaultPhysicsDemo::stepDemo();

	return DEMO_OK;	// original animation demo return
}
示例#4
0
hkDemo::Result BindingDemo::stepDemo()
{
	hkReal w1 = m_control[0]->getMasterWeight();
	hkReal w2 = m_control[1]->getMasterWeight();

	const  hkReal inc = 0.01f;
	{
		const hkgPad* pad = m_env->m_gamePad;
		if ((pad->getButtonState() & HKG_PAD_DPAD_UP) != 0)
			w1+=inc;
		if ((pad->getButtonState() & HKG_PAD_DPAD_LEFT) != 0)
			w2+=inc;
		if ((pad->getButtonState() & HKG_PAD_DPAD_RIGHT) != 0)
			w2-=inc;
		if ((pad->getButtonState() & HKG_PAD_DPAD_DOWN) != 0)
			w1-=inc;

		//clamp
		w1 = (w1 > 1) ? 1 : w1;
		w1 = (w1 < 0) ? 0 : w1;
		w2 = (w2 > 1) ? 1 : w2;
		w2 = (w2 < 0) ? 0 : w2;
	}

	m_control[0]->setMasterWeight( w1 );
	m_control[1]->setMasterWeight( w2 );

	char buf[255];
	hkString::sprintf(buf, "wave weight :%0.3f idle weight:%0.3f fill thresh:%0.3f", w2, w1, m_skeletonInstance->getReferencePoseWeightThreshold());
	const int h = m_env->m_window->getHeight();
	m_env->m_textDisplay->outputText( buf, 20, h-40, 0xffffffff, 1);

	// Advance the active animations
	m_skeletonInstance->stepDeltaTime( .016f );

	const int boneCount = m_skeleton->m_numBones;

	// Sample the active animations and combine into a single pose
	hkaPose pose (m_skeleton);
	m_skeletonInstance->sampleAndCombineAnimations( pose.accessUnsyncedPoseLocalSpace().begin(), pose.getFloatSlotValues().begin()  );
	AnimationUtils::drawPose( pose, hkQsTransform::getIdentity(), 0xffff0000 );

	hkLocalArray<hkQsTransform> trackSample(boneCount);
	trackSample.setSizeUnchecked(boneCount);

	for (int i=0; i < NUM_ANIMS; i++)
	{
		trackSample.setSizeUnchecked( m_control[i]->getAnimationBinding()->m_animation->m_numberOfTransformTracks );
		m_binding[i]->m_animation->sampleTracks( m_control[i]->getLocalTime(), trackSample.begin(), HK_NULL , HK_NULL);

		pose.setToReferencePose();

		hkaAnimation* anim = m_binding[i]->m_animation;
		for (hkInt16 t=0; t < anim->m_numberOfTransformTracks; t++)
		{
			hkInt16 boneIdx = m_binding[i]->m_transformTrackToBoneIndices[t];
			if (boneIdx !=-1)
			{
				pose.setBoneLocalSpace(boneIdx, trackSample[t]);
			}
		}

		hkQsTransform worldFromModel (hkQsTransform::IDENTITY);
		worldFromModel.m_translation.set(i * 2.0f - 1.0f , 0, 0);

		hkReal gray = m_control[i]->getMasterWeight() * 0.4f + 0.6f;
		int color = hkColor::rgbFromFloats( gray, gray, gray );

		AnimationUtils::drawPose( pose, worldFromModel, color);
	}

	return hkDemo::DEMO_OK;
}
hkDemo::Result CompressionDemo::stepDemo()
{
	// Point local arrays on the scratchpad

	if ( m_env->m_gamePad->wasButtonPressed(HKG_PAD_BUTTON_0) )
	{
		m_currentAnimation = (m_currentAnimation-1+m_animationRecords.getSize())%(m_animationRecords.getSize());
		hkVector4 at = m_animationRecords[m_currentAnimation]->m_offset;
		lookAt( at );
	}

	if ( m_env->m_gamePad->wasButtonPressed(HKG_PAD_BUTTON_1) )
	{
		m_currentAnimation = (m_currentAnimation+1)%(m_animationRecords.getSize());
		hkVector4 at = m_animationRecords[m_currentAnimation]->m_offset;
		lookAt( at );
	}

	// Turn caching on / off
	if ( m_env->m_gamePad->wasButtonPressed(HKG_PAD_BUTTON_2) )
	{
		m_useCache = !m_useCache;
	}

	// print cache statistics with user input
	if( m_env->m_gamePad->wasButtonPressed( HKG_PAD_BUTTON_3 ) )
	{
		// display message to notify user of cache pool flush
		char buf[64];
		hkString::sprintf( buf, "The cache's statistics have been saved." );
		m_env->m_textDisplay->outputText( buf, 20, 180, 0xffffffff, 140);

		// print cache statistics
		hkOstream file("cacheStats.txt");
		m_cache->printCacheStats( &file );
	}

	hkaPose pose (m_skeleton);

	for (int i = 0; i < m_animationRecords.getSize(); ++i )
	{
		TestRecord* rec = m_animationRecords[i];
		hkaAnimatedSkeleton* inst = rec->m_animatedSkeleton;

		// Advance the animation
		rec->m_stopwatch.reset();
		rec->m_stopwatch.start();

		inst->stepDeltaTime( m_timestep );

		// Sample
		if ( m_useCache )
		{
			inst->sampleAndCombineAnimations( pose.accessUnsyncedPoseLocalSpace().begin(), pose.getFloatSlotValues().begin() , m_cache );	// using our cache
		}
		else
		{
			inst->sampleAndCombineAnimations( pose.accessUnsyncedPoseLocalSpace().begin(), pose.getFloatSlotValues().begin()  );
		}

		rec->m_stopwatch.stop();

		// Draw
		hkQsTransform worldFromModel (hkQsTransform::IDENTITY);
		worldFromModel.m_translation = rec->m_offset;
		hkUint32 color = (i == m_currentAnimation) ? 0xffff0000 : 0xffffffff;
		AnimationUtils::drawPose( pose, worldFromModel, color );

		const hkReal heightOffset = -1.0f;
		const hkReal widthOffset = -0.20f;
		hkString label( rec->m_name );
		label.setAsSubstr( 0, label.indexOf( ' ', 0 ) );
		hkVector4& textPos = m_animationRecords[i]->m_offset;
		m_env->m_textDisplay->outputText3D( label, textPos(0) + widthOffset, textPos(1), textPos(2) + heightOffset, 0xffffffff );
	}

	TestRecord* rec = m_animationRecords[m_currentAnimation];

	char msg[2048];

	hkUint64 ticks = rec->m_stopwatch.getElapsedTicks();
	double tpf = double(ticks/rec->m_stopwatch.getNumTimings());
	double tpms = double(rec->m_stopwatch.getTicksPerSecond()/1000000);
	double mspf = tpf / tpms;
	hkString::sprintf(msg, "%s\nbytes:%d\nratio:%.2f:1\nmicrosecs/f:%f\ncaching:%s", rec->m_name, rec->m_bytes, (hkReal)m_originalSize / rec->m_bytes, mspf, ((m_useCache) ? "enabled" : "disabled") );
	const int h = m_env->m_window->getHeight();
	m_env->m_textDisplay->outputText( msg, 20, h-100, 0xffffffff);

	return DEMO_OK;
}