hkDemo::Result HardwareSkinningDemo::stepDemo()
{
	// Advance the active animations
	if (m_canSkin)
	{
		m_skeletonInstance->stepDeltaTime( .016f );

		hkaPose pose (m_skeleton);

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

		// Grab the pose in model space
		const hkArray<hkQsTransform>& poseModelSpace = pose.getSyncedPoseModelSpace();

		const int numSkins = m_numSkinBindings;
		for (int i=0; i < numSkins; i++)
		{
			const hkxMesh* inputMesh = m_skinBindings[i]->m_mesh;
			int numBones = m_skinBindings[i]->m_numBoneFromSkinMeshTransforms;

			// Compute the skinning matrix palette
			hkLocalArray<hkTransform> compositeWorldInverse( numBones );
			compositeWorldInverse.setSize( numBones );

			// Multiply through by the bind pose inverse world inverse matrices, according to the skel to mesh bone mapping
			for (int p=0; p < numBones; p++)
			{
				compositeWorldInverse[p].setMul( poseModelSpace[ p ], m_skinBindings[i]->m_boneFromSkinMeshTransforms[ p ] );
			}

			// reflect the matrices in the palette used by the shader
			m_env->m_sceneConverter->updateSkin( inputMesh, compositeWorldInverse, hkTransform::getIdentity() );
		}
	}

	return hkDemo::DEMO_OK;
}
hkDemo::Result MotionExtractionDemo::stepDemo()
{
	static hkReal val = 0.0f;

	hkReal stickX = m_env->m_gamePad->getStickPosX(1);
	val += (stickX - val) * 0.3f;

	hkReal leftWeight = (val < 0) ? -val : 0;
	hkReal rightWeight = (val > 0) ? val : 0;

	m_control[1]->setMasterWeight( leftWeight );
	m_control[2]->setMasterWeight( rightWeight );

	// Grab accumulated motion
	{
		hkQsTransform deltaMotion;
		deltaMotion.setIdentity();
		m_skeletonInstance->getDeltaReferenceFrame( m_timestep, deltaMotion);
		m_currentMotion.setMulEq(deltaMotion);
	}

	// Show the extracted motion for the next 2 seconds

	const hkReal freq = 60;
	hkVector4 lp = m_currentMotion.getTranslation();

	for (hkReal tm = 0.0f; tm < 2.0f; tm += 1.0f / freq)
	{
		hkQsTransform deltaMotion;
		deltaMotion.setIdentity();
		m_skeletonInstance->getDeltaReferenceFrame(tm, deltaMotion);
		hkVector4 p;
		p.setTransformedPos(m_currentMotion, deltaMotion.getTranslation());

		HK_DISPLAY_LINE( lp, p, 0xffff0f0f);
		lp = p;
	}

	// Advance the active animations
	m_skeletonInstance->stepDeltaTime( m_timestep );

	hkaPose pose (m_skeleton);

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

	// Skin
	{
		// Work with the pose in Model space
		const hkArray<hkQsTransform>& poseInWorld = pose.getSyncedPoseModelSpace();

		// Construct the composite world transform
		const int boneCount = m_skeleton->m_numBones;
		hkLocalArray<hkTransform> compositeWorldInverse( boneCount );
		compositeWorldInverse.setSize( boneCount );

		// Convert accumlated info to graphics matrix
		hkTransform graphicsTransform;
		m_currentMotion.copyToTransform(graphicsTransform);

		// Skin the meshes
		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 : boneCount;

			// 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( poseInWorld[ boneIndex ], m_skinBindings[i]->m_boneFromSkinMeshTransforms[ boneIndex ] );
			}

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

	return hkDemo::DEMO_OK;
}
Пример #3
0
hkDemo::Result LookAtDemo::stepDemo()
{
	// Advance the active animations
	m_skeletonInstance->stepDeltaTime( 0.016f );

	int boneCount = m_skeleton->m_numBones;	
	hkaPose pose (m_skeleton);

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

	// m_targetPosition is similar to camera
	hkVector4 newTargetPosition;
	m_env->m_window->getCurrentViewport()->getCamera()->getFrom((float*)&newTargetPosition);

	hkaLookAtIkSolver::Setup setup;
	setup.m_fwdLS.set(0,1,0);
	setup.m_eyePositionLS.set(0.1f,0.1f,0);
	setup.m_limitAxisMS.setRotatedDir(pose.getBoneModelSpace(m_neckIndex).getRotation(), hkVector4(0,1,0));
	setup.m_limitAngle = HK_REAL_PI / 3.0f;

	// Check if the angle-limited variant is in use
	if ( m_variantId == 0 )
	{
		// Solve normally
		hkaLookAtIkSolver::solve (setup, newTargetPosition, 1.0f, pose.accessBoneModelSpace(m_headIndex, hkaPose::PROPAGATE), HK_NULL );
	}
	else
	{
		// Define the range of motion
		hkaLookAtIkSolver::RangeLimits range;
		range.m_limitAngleLeft = 90.0f * HK_REAL_DEG_TO_RAD;
		range.m_limitAngleRight = -90.0f * HK_REAL_DEG_TO_RAD;
		range.m_limitAngleUp = 30.0f * HK_REAL_DEG_TO_RAD;
		range.m_limitAngleDown = -10.0f * HK_REAL_DEG_TO_RAD;

		hkVector4 upLS;
		upLS.set(1,0,0);
		range.m_upAxisMS.setRotatedDir(pose.getBoneModelSpace(m_neckIndex).getRotation(), upLS);

		// Solve using user-defined range of motion
		hkaLookAtIkSolver::solve (setup, newTargetPosition, 1.0f, pose.accessBoneModelSpace(m_headIndex, hkaPose::PROPAGATE), &range );
	}


	setup.m_fwdLS.set(0,-1,0);
	setup.m_eyePositionLS.set(0.0f,0.0f,0);
	setup.m_limitAxisMS.setRotatedDir(pose.getBoneModelSpace(m_headIndex).getRotation(), hkVector4(0,1,0));
	setup.m_limitAngle = HK_REAL_PI / 10.0f;
	hkaLookAtIkSolver::solve (setup, newTargetPosition, 1.0f, pose.accessBoneModelSpace(m_rEyeIndex, hkaPose::PROPAGATE));

	setup.m_fwdLS.set(0,-1,0);
	setup.m_eyePositionLS.set(0.0f,0.0f,0);
	setup.m_limitAxisMS.setRotatedDir(pose.getBoneModelSpace(m_headIndex).getRotation(), hkVector4(0,1,0));
	setup.m_limitAngle = HK_REAL_PI / 10.0f;
	hkaLookAtIkSolver::solve (setup, newTargetPosition, 1.0f, pose.accessBoneModelSpace(m_lEyeIndex, hkaPose::PROPAGATE));
	
	//
	// draw the skeleton pose
	//
	AnimationUtils::drawPose( pose, hkQsTransform::getIdentity() );

	// Skin
	{
		// Work with the pose in world
		const hkArray<hkQsTransform>& poseInWorld = pose.getSyncedPoseModelSpace();

		// Construct the composite world transform
		hkLocalArray<hkTransform> compositeWorldInverse( boneCount );
		compositeWorldInverse.setSize( boneCount );

		// Skin the meshes
		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 : boneCount;

			// 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( poseInWorld[ boneIndex ], m_skinBindings[i]->m_boneFromSkinMeshTransforms[ boneIndex ] );
			}

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

	}

	// Move the attachments
	{
		HK_ALIGN(float f[16], 16);
		for (int a=0; a < m_numAttachments; a++)
		{
			if (m_attachmentObjects[a])
			{
				hkaBoneAttachment* ba = m_attachments[a];  
				pose.getBoneModelSpace( ba->m_boneIndex ).get4x4ColumnMajor(f);
				hkMatrix4 worldFromBone; worldFromBone.set4x4ColumnMajor(f);
				hkMatrix4 worldFromAttachment; worldFromAttachment.setMul(worldFromBone, ba->m_boneFromAttachment);
				m_env->m_sceneConverter->updateAttachment(m_attachmentObjects[a], worldFromAttachment);
			}
		}
	}

	return hkDemo::DEMO_OK;
}
Пример #4
0
hkDemo::Result NormalBlendingDemo::stepDemo()
{

	hkReal runWeight = m_control[HK_RUN_ANIM]->getMasterWeight();

	// Update input
	{
		const  hkReal inc = 0.01f;
		const hkgPad* pad = m_env->m_gamePad;
		if ((pad->getButtonState() & HKG_PAD_DPAD_UP) != 0)
			runWeight+=inc;
		if ((pad->getButtonState() & HKG_PAD_DPAD_DOWN) != 0)
			runWeight-=inc;

		runWeight = hkMath::min2(runWeight, 1.0f);
		runWeight = hkMath::max2(runWeight, 0.0f);
	}

	const hkReal walkWeight = 1.0f - runWeight;

	// Set the animation weights
	{
		m_control[HK_RUN_ANIM]->setMasterWeight( runWeight );
		m_control[HK_WALK_ANIM]->setMasterWeight( walkWeight );
	}

	// Sync playback speeds
	{
		const hkReal runPeriod = m_control[HK_RUN_ANIM]->getAnimationBinding()->m_animation->m_duration;
		const hkReal walkPeriod = m_control[HK_WALK_ANIM]->getAnimationBinding()->m_animation->m_duration;

		const hkReal totalW = runWeight+walkWeight+1e-6f;
		const hkReal walkP = walkWeight / totalW;
		const hkReal runP = runWeight / totalW;
		const hkReal runWalkRatio = runPeriod / walkPeriod;
		m_control[HK_RUN_ANIM]->setPlaybackSpeed( (1-runP) * runWalkRatio + runP );
		m_control[HK_WALK_ANIM]->setPlaybackSpeed( (1-walkP) * (1.0f / runWalkRatio) + walkP );
	}

	// Show blend ratio
	{
		char buf[255];
		hkString::sprintf(buf, "run:%0.3f walk:%0.3f", runWeight, walkWeight);

		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( m_timestep );

	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() );

	// Construct the composite world transform
	hkLocalArray<hkTransform> compositeWorldInverse( boneCount );
	compositeWorldInverse.setSize( boneCount );

	const hkArray<hkQsTransform>& poseInWorld = pose.getSyncedPoseModelSpace();

	// Skin the meshes
	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 : boneCount;

		// 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( poseInWorld[ boneIndex ], m_skinBindings[i]->m_boneFromSkinMeshTransforms[ boneIndex ] );
		}

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

	return hkDemo::DEMO_OK;
}
Пример #5
0
hkDemo::Result EaseCurvesDemo::stepDemo()
{

	// Display current settings
	{
		char buf[255];
		for (int i=0; i< NUM_ANIMS; i++)
		{
			hkString::sprintf(buf, "anim%d:%0.3f", i, m_control[i]->getWeight());
			m_env->m_textDisplay->outputText( buf, 10, 240+14*i, curveCols[i], 1);
		}
	}

	// Check user input
	{
		for (int i=0; i < 3; i++)
		{
			if (m_env->m_gamePad->wasButtonPressed( 1 << (i+1) ))
			{
				if (( m_control[i]->getEaseStatus() == hkaDefaultAnimationControl::EASING_IN ) ||
					( m_control[i]->getEaseStatus() == hkaDefaultAnimationControl::EASED_IN ))
				{
					m_control[i]->easeOut( 1.0f );
				}
				else
				{
					m_control[i]->easeIn( 1.0f );
				}
			}
		}
	}

	const int boneCount = m_skeleton->m_numBones;

	// Advance the active animations
	m_skeletonInstance->stepDeltaTime( 1.0f / 60.0f );

	// 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() );

	// Construct the composite world transform
	hkLocalArray<hkTransform> compositeWorldInverse( boneCount );
	compositeWorldInverse.setSize( boneCount );

	const hkArray<hkQsTransform>& poseModelSpace = pose.getSyncedPoseModelSpace();

	// Skin the meshes
	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 : boneCount;

		// 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, hkTransform::getIdentity(), compositeWorldInverse.begin(), *m_env->m_sceneConverter );
	}

	// Show curves
	{
		int* data = reinterpret_cast<int*>(m_texture->getDataPointer());

		//Shuffle Texture
		for (int w=0; w< GRAPH_CANVAS_WIDTH-1; w++)
		{
			for (int h=0; h< GRAPH_CANVAS_HEIGHT; h++)
			{
				data[h * GRAPH_CANVAS_WIDTH + w] = data[h * GRAPH_CANVAS_WIDTH + w+1];
			}
		}

		// Clear the line
		for (int h=0; h< GRAPH_CANVAS_HEIGHT; h++)
		{
			data[h * GRAPH_CANVAS_WIDTH + GRAPH_CANVAS_WIDTH-1] = 0xff7f7f7f;
		}

		// Take a new sample
		for (int c=0; c< 3; c++)
		{
			int y = (int)(m_control[c]->getWeight() * (GRAPH_CANVAS_HEIGHT-5));
			data[(GRAPH_CANVAS_HEIGHT-2 - (y+c+1)) * GRAPH_CANVAS_WIDTH + GRAPH_CANVAS_WIDTH-1] = curveCols[c];
			data[(GRAPH_CANVAS_HEIGHT-2 - (y+c)) * GRAPH_CANVAS_WIDTH + GRAPH_CANVAS_WIDTH-1] &= 0xff0f0f0f;
		}
	}

	m_context->lock();

	if (m_textureRealized)
	{
		m_texture->free();
	}
	m_texture->realize(true);
	m_textureRealized = true;
	drawTexture( m_texture );

	m_context->unlock();

	return hkDemo::DEMO_OK;
}
hkDemo::Result MirroredMotionDemo::stepDemo()
{
	// Check user input
	{
		if (m_env->m_gamePad->wasButtonPressed( HKG_PAD_BUTTON_1 ))
		{
			for ( int i = 0; i < 2; i++ )
			{
				if (( m_control[i]->getEaseStatus() == hkaDefaultAnimationControl::EASING_IN ) ||
					( m_control[i]->getEaseStatus() == hkaDefaultAnimationControl::EASED_IN ))
				{
					m_control[i]->easeOut( .5f );
				}
				else
				{
					m_control[i]->easeIn( .5f );
				}
			}
		}

		if (m_env->m_gamePad->wasButtonPressed( HKG_PAD_BUTTON_2 ))
		{
			m_wireframe = !m_wireframe;
			setGraphicsState( HKG_ENABLED_WIREFRAME, m_wireframe );
		}

		if (m_env->m_gamePad->wasButtonPressed( HKG_PAD_BUTTON_3 ))
		{
			m_drawSkin = !m_drawSkin;
		}

		if ( m_env->m_gamePad->wasButtonPressed( HKG_PAD_BUTTON_0 ) )
		{
			m_useExtractedMotion = !m_useExtractedMotion;
		}

		if ( m_env->m_gamePad->wasButtonPressed( HKG_PAD_BUTTON_L1 ) )
		{
			m_accumulatedMotion[0].setIdentity();
			m_accumulatedMotion[1].setIdentity();
		}

		if ( m_env->m_gamePad->wasButtonPressed( HKG_PAD_BUTTON_R1 ) )
		{
			m_paused = !m_paused;

			if ( m_paused )
			{
				m_timestep = 0;
			}
			else
			{
				m_timestep = 1.0f / 60.0f;
			}
		}


	}

	const int boneCount = m_skeleton->m_numBones;

	for ( int j = 0; j < 2; j++ )
	{
		// Grab accumulated motion
		{
			hkQsTransform deltaMotion;
			deltaMotion.setIdentity();
			m_skeletonInstance[j]->getDeltaReferenceFrame( m_timestep, deltaMotion );
			m_accumulatedMotion[j].setMulEq( deltaMotion );
		}

		// Advance the active animations
		m_skeletonInstance[j]->stepDeltaTime( m_timestep );

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

		hkReal separation = m_separation * hkReal( 2*j-1 );

		hkQsTransform Q( hkQsTransform::IDENTITY );
		Q.m_translation.set( separation, 0, 0 );

		if ( m_useExtractedMotion )
		{
			Q.setMulEq( m_accumulatedMotion[j] );
		}

		pose.syncModelSpace();

		AnimationUtils::drawPose( pose, Q );
		// Test if the skin is to be drawn
		if ( !m_drawSkin )
		{
			Q.m_translation( 2 ) -= 2.0f * m_separation;
		}

		// Construct the composite world transform
		hkLocalArray<hkTransform> compositeWorldInverse( boneCount );
		compositeWorldInverse.setSize( boneCount );

		const hkArray<hkQsTransform>& poseModelSpace = pose.getSyncedPoseModelSpace();

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

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

			AnimationUtils::skinMesh( *m_skinBindings[j][i]->m_mesh, hkTransform( Q.m_rotation, hkVector4( Q.m_translation(0), Q.m_translation(1), Q.m_translation(2), 1 ) ), compositeWorldInverse.begin(), *m_env->m_sceneConverter );
		}

		// Move the attachments
		{
			HK_ALIGN(float f[16], 16);
			for (int a=0; a < m_numAttachments[j]; a++)
			{
				if (m_attachmentObjects[j][a])
				{
					hkaBoneAttachment* ba = m_attachments[j][a];
					hkQsTransform modelFromBone = pose.getBoneModelSpace( ba->m_boneIndex );
					hkQsTransform worldFromBoneQs;
					worldFromBoneQs.setMul( Q, modelFromBone );
					worldFromBoneQs.get4x4ColumnMajor(f);
					hkMatrix4 worldFromBone; worldFromBone.set4x4ColumnMajor(f);
					hkMatrix4 worldFromAttachment; worldFromAttachment.setMul(worldFromBone, ba->m_boneFromAttachment);
					m_env->m_sceneConverter->updateAttachment(m_attachmentObjects[j][a], worldFromAttachment);
				}
			}
		}


	}

	return hkDemo::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
}
Пример #8
0
hkDemo::Result BasicMovementDemo::stepDemo()
{
	// for PlayStation(R)2 metrowerks
	pushDoubleConversionCheck( false );

	// Display current settings
	{
		char buf[255];
		for (int i=0; i< NUM_ANIMS; i++)
		{
			hkString::sprintf(buf, "anim%d: %0.3f", i, m_control[i]->getWeight());
			const int h = m_env->m_window->getHeight();
			m_env->m_textDisplay->outputText( buf, 20, h-70+16*i, curveCols[i], 1);
		}
	}

	popDoubleConversionCheck();

	// Handle the keys
	{
		bool jumping = (m_control[1]->getWeight() > 0.001f);

		if (!jumping)
		{
			hkVector4 upVec(0,0,1);
			hkReal up, turn;
			up = m_env->m_gamePad->getStickPosY( 1 ); // 1 is the only one on PSP

			const hkBool upPressed = (up > 0.0f);
			const hkBool easeIn = (m_control[0]->getEaseStatus() == hkaDefaultAnimationControl::EASING_IN ) || ( m_control[0]->getEaseStatus() == hkaDefaultAnimationControl::EASED_IN );
			if ( easeIn  && ( !upPressed ))
			{
				// Ease in stand
				m_control[0]->easeOut( 0.9f );
			}
			else if (( !easeIn )  && upPressed )
			{
				// Ease in walk cycle
				m_control[0]->easeIn( 0.9f );
			}

			turn = m_env->m_gamePad->getStickPosX(1);

			turn *= -5.0f * HK_REAL_PI / 180.0f * m_control[0]->getWeight();

			hkQuaternion q;
			q.setAxisAngle(upVec, turn);
			m_currentMotion.m_rotation.mul(q);
		}
		else
		{
			hkReal remaining = m_control[1]->getAnimationBinding()->m_animation->m_duration - m_control[1]->getLocalTime();

			// If we've played through then fade out
			const hkBool easeIn = (m_control[1]->getEaseStatus() == hkaDefaultAnimationControl::EASING_IN ) || ( m_control[1]->getEaseStatus() == hkaDefaultAnimationControl::EASED_IN );
			if ( easeIn && (remaining < 0.2f))
			{
				m_control[1]->easeOut( remaining );
				m_control[0]->setLocalTime( m_control[0]->getAnimationBinding()->m_animation->m_duration - remaining );
				m_control[0]->easeIn( remaining );
			}


		}

		if (m_env->m_gamePad->wasButtonPressed( HKG_PAD_BUTTON_2) && !jumping)
		{
			// Reset jump animation and play
			m_control[1]->setLocalTime(0.0f);

			m_control[1]->easeIn( 0.1f );
			m_control[0]->easeOut( 0.1f );
		}

		if (m_env->m_gamePad->wasButtonPressed( HKG_PAD_BUTTON_1))
		{
			m_currentMotion.setIdentity();
		}

	}

	// Grab accumulated motion
	{
		hkQsTransform deltaMotion;
		deltaMotion.setIdentity();
		m_skeletonInstance->getDeltaReferenceFrame( m_timestep, deltaMotion);

		hkQsTransform temp;
		temp.setMul(m_currentMotion, deltaMotion);
		m_currentMotion = temp;
	}

	const int boneCount = m_skeleton->m_numBones;

	// Advance the active animations
	m_skeletonInstance->stepDeltaTime( 1.0f / 60.0f );

	// 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() );

	// Construct the composite world transform
	hkLocalArray<hkTransform> compositeWorldInverse( boneCount );
	compositeWorldInverse.setSize( boneCount );

	// Convert accumlated info to graphics matrix
	hkTransform graphicsTransform;
	m_currentMotion.copyToTransform(graphicsTransform);

	// Skin the meshes
	{
		const hkArray<hkQsTransform>& poseInWorld = pose.getSyncedPoseModelSpace();

		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 : boneCount;

			// 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( poseInWorld[ boneIndex ], m_skinBindings[i]->m_boneFromSkinMeshTransforms[ boneIndex ] );
			}


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

	return hkDemo::DEMO_OK;
}
Пример #9
0
hkDemo::Result AdditiveBlendingDemo::stepDemo()
{
	hkReal w1 = m_control[HK_ADDITIVE_ANIM]->getMasterWeight();

	// Update input
	{
		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_DOWN) != 0)
			w1-=inc;

		w1 = hkMath::min2(w1, 1.0f);
		w1 = hkMath::max2(w1, 0.0f);
	}


	// Set the additive animation weight
	{
		m_control[HK_ADDITIVE_ANIM]->setMasterWeight( w1 );
	}

	// Show animation weight
	{
		char buf[255];
		hkString::sprintf( buf, "weight:%0.3f", w1 );

		const int h = m_env->m_window->getHeight();
		m_env->m_textDisplay->outputText( buf, 20, h-40, 0xffffffff, 1);
	}

	// Advance the active controls
	m_skeletonInstance->stepDeltaTime( m_timestep );

	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() );

	// Construct the composite world transform
	hkLocalArray<hkTransform> compositeWorldInverse( boneCount );
	compositeWorldInverse.setSize( boneCount );

	const hkArray<hkQsTransform>& poseInWorld = pose.getSyncedPoseModelSpace();

	// Skin the meshes
	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 : boneCount;

		// 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( poseInWorld[ boneIndex ], m_skinBindings[i]->m_boneFromSkinMeshTransforms[ boneIndex ] );
		}

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

	// Move the attachments
	{
		HK_ALIGN(float f[16], 16);
		for (int a=0; a < m_numAttachments; a++)
		{
			if (m_attachmentObjects[a])
			{
				hkaBoneAttachment* ba = m_attachments[a];
				pose.getBoneModelSpace( ba->m_boneIndex ).get4x4ColumnMajor(f);
				hkMatrix4 worldFromBone; worldFromBone.set4x4ColumnMajor(f);
				hkMatrix4 worldFromAttachment; worldFromAttachment.setMul(worldFromBone, ba->m_boneFromAttachment);
				m_env->m_sceneConverter->updateAttachment(m_attachmentObjects[a], worldFromAttachment);
			}
		}
	}

	return hkDemo::DEMO_OK;
}