WorldRaycastDemo::WorldRaycastDemo(hkDemoEnvironment* env) : hkDefaultPhysicsDemo(env) { // // Setup the camera. // { hkVector4 from(30.0f, 8.0f, 25.0f); hkVector4 to ( 4.0f, 0.0f, -3.0f); hkVector4 up ( 0.0f, 1.0f, 0.0f); setupDefaultCameras(env, from, to, up); } // // Create the world. // { hkpWorldCinfo info; info.setupSolverInfo(hkpWorldCinfo::SOLVER_TYPE_4ITERS_MEDIUM); // Set gravity to zero so body floats. info.m_gravity.set(0.0f, 0.0f, 0.0f); info.setBroadPhaseWorldSize( 100.0f ); m_world = new hkpWorld(info); m_world->lock(); // Disable backface culling, since we have mopp's etc. setGraphicsState(HKG_ENABLED_CULLFACE, false); setupGraphics(); } // register all agents(however, we put all objects into the some group, // so no collision will be detected hkpAgentRegisterUtil::registerAllAgents( m_world->getCollisionDispatcher() ); // Add a collision filter to the world to allow the bodies interpenetrate { hkpGroupFilter* filter = new hkpGroupFilter(); filter->disableCollisionsBetween( hkpGroupFilterSetup::LAYER_DEBRIS, hkpGroupFilterSetup::LAYER_DEBRIS ); m_world->setCollisionFilter( filter ); filter->removeReference(); } // // Set the simulation time to 0 // m_time = 0; // // Create some bodies (reuse the ShapeRaycastApi demo) // createBodies(); m_world->unlock(); }
WorldSnapshotWithContactPointsDemo::WorldSnapshotWithContactPointsDemo( hkDemoEnvironment* env) : hkDefaultPhysicsDemo(env) { hkpWorld::IgnoreForceMultithreadedSimulation ignoreForceMultithreaded; // Setup the camera { hkVector4 from(10, -10, 6); hkVector4 to(0, 0, -4); hkVector4 up(0, 0, 1); setupDefaultCameras( env, from, to, up ); } // Load the startup scene { // Load the world. m_world = loadWorld(ORIGINAL_FILE, &m_physicsData, &m_loadedData); m_world->lock(); m_debugViewerNames.pushBack( hkpActiveContactPointViewer::getName() ); m_debugViewerNames.pushBack( hkpInactiveContactPointViewer::getName() ); // Disable culling setGraphicsState(HKG_ENABLED_CULLFACE, false); // Enable wire frame display mode setGraphicsState(HKG_ENABLED_WIREFRAME, true); // Setup graphics setupGraphics(); m_world->unlock(); } // Disable warning: 'm_contactRestingVelocity not set, setting it to REAL_MAX, so that the new collision restitution code will be disabled' hkError::getInstance().setEnabled(0xf03243ed, false); }
WorldRayCastMultithreadedDemo::WorldRayCastMultithreadedDemo(hkDemoEnvironment* env) : hkDefaultPhysicsDemo(env), m_semaphore(0,1000) { const WorldRayCastMultithreadedDemoVariant& variant = g_WorldRayCastMultithreadedDemoVariants[m_variantId]; // // Setup the camera. // { hkVector4 from(30.0f, 8.0f, 25.0f); hkVector4 to ( 4.0f, 0.0f, -3.0f); hkVector4 up ( 0.0f, 1.0f, 0.0f); setupDefaultCameras(env, from, to, up); } // // Create the world. // { hkpWorldCinfo info; info.setupSolverInfo(hkpWorldCinfo::SOLVER_TYPE_4ITERS_MEDIUM); // Set gravity to zero so body floats. info.m_gravity.set(0.0f, 0.0f, 0.0f); info.setBroadPhaseWorldSize( 100.0f ); m_world = new hkpWorld(info); m_world->lock(); // Disable backface culling, since we have mopp's etc. setGraphicsState(HKG_ENABLED_CULLFACE, false); setupGraphics(); } // register all agents(however, we put all objects into the some group, // so no collision will be detected hkpAgentRegisterUtil::registerAllAgents( m_world->getCollisionDispatcher() ); // Add a collision filter to the world to allow the bodies interpenetrate { hkpGroupFilter* filter = new hkpGroupFilter(); filter->disableCollisionsBetween( hkpGroupFilterSetup::LAYER_DEBRIS, hkpGroupFilterSetup::LAYER_DEBRIS ); m_world->setCollisionFilter( filter ); filter->removeReference(); } // // Set the simulation time to 0 // m_time = 0; // // Create some bodies (reuse the ShapeRayCastApi demo) // createBodies(); m_world->unlock(); hkpCollisionQueryJobQueueUtils::registerWithJobQueue(m_jobQueue); // Special case for this demo variant: we do not allow the # of active SPUs to drop to zero as this can cause a deadlock. if ( variant.m_demoType == WorldRayCastMultithreadedDemoVariant::MULTITHREADED_ON_SPU ) { m_allowZeroActiveSpus = false; } }
MoppInstancingDemo::MoppInstancingDemo(hkDemoEnvironment* env) : hkDefaultPhysicsDemo(env) { // Disable face culling setGraphicsState(HKG_ENABLED_CULLFACE, false); // // Setup the camera // { hkVector4 from(20.0f, 20.0f, -60.0f); hkVector4 to ( 0.0f, 0.0f, 0.0f); hkVector4 up ( 0.0f, 1.0f, 0.0f); setupDefaultCameras( env, from, to, up ); } // // Create the world // { hkpWorldCinfo info; info.m_gravity.set(0.0f, -9.5f, 0.0f); info.setBroadPhaseWorldSize(150.0f); info.setupSolverInfo( hkpWorldCinfo::SOLVER_TYPE_4ITERS_MEDIUM ); m_world = new hkpWorld( info ); m_world->lock(); // Register ALL agents (though some may not be necessary) hkpAgentRegisterUtil::registerAllAgents(m_world->getCollisionDispatcher()); setupGraphics(); } // // create the ground mopps // See the comments on createMoppShape() below. // m_originalMopp = createMoppShape(); m_smallMopp = createScaledMopp(m_originalMopp, .75f); m_bigMopp = createScaledMopp(m_originalMopp, 1.5f); hkpShape* shapes[3] = { m_originalMopp, m_smallMopp, m_bigMopp}; hkReal offsets[3] = {0.0f, -20.0f, 30.0f}; // // Create the fixed rigid bodies and add them to the world // for (int i=0; i<3; i++) { hkpRigidBodyCinfo groundInfo; groundInfo.m_motionType = hkpMotion::MOTION_FIXED; groundInfo.m_shape = shapes[i]; groundInfo.m_position.set(offsets[i],-2.6f,0.0f); m_fixedBodies[i] = new hkpRigidBody(groundInfo); m_world->addEntity( m_fixedBodies[i] ); // Drop some boxes on the mesh hkVector4 center(offsets[i] - 1.0f, 0, 2.5f); addBoxPile(10, center); } m_world->unlock(); }
MeshWeldingDemo::MeshWeldingDemo(hkDemoEnvironment* env) : hkDefaultPhysicsDemo(env) { const WeldingVariant& variant = g_variants[m_variantId]; // // Create the world. // { hkpWorldCinfo info; info.m_toiCollisionResponseRotateNormal = 0; info.m_gravity.setZero4(); if ( variant.m_weldingType == TWO_SIDED ) { info.m_enableToiWeldRejection = true; } m_world = new hkpWorld( info ); m_world->lock(); hkpAgentRegisterUtil::registerAllAgents(m_world->getCollisionDispatcher()); } // // Setup graphics // { // Disable culling setGraphicsState(HKG_ENABLED_CULLFACE, false); // Enable wire frame display mode setGraphicsState(HKG_ENABLED_WIREFRAME, true); // // Setup default camera // { hkVector4 from(0.0f, 30.0f, 10.0f); hkVector4 to(0,0,0); hkVector4 up(0.0f, 1.0f, 0.0f); setupDefaultCameras( env, from, to, up, 0.1f, 500.0f); } setupGraphics(); } // // Create self-propelled, moving block. // { hkVector4 posBlock(-7.8f, 1.0f, 0.0f); float mass = 1; float friction = 0.f; float restitution = 0; m_movingBody = createDynamicBox(posBlock, mass, friction, restitution, m_world); hkpCollidableQualityType qt = (variant.m_simulationType == CONTINUOUS) ? HK_COLLIDABLE_QUALITY_CRITICAL : HK_COLLIDABLE_QUALITY_DEBRIS; m_movingBody->setQualityType( qt ); m_world->addEntity( m_movingBody ); { PushAction* pushAction = new PushAction( m_movingBody ); m_world->addAction(pushAction); pushAction->removeReference(); } } // // Load simple mesh from xml file, create welding information, add welding utility and // insert it into world. // { hkVector4 posSimpleMesh(0, -1, 0); loadAndInitSimpleMesh(posSimpleMesh, m_world, m_ringData); } m_world->unlock(); m_bodySpeed = 0; }
TriSampledHeightFieldDemo::TriSampledHeightFieldDemo(hkDemoEnvironment* env) : hkDefaultPhysicsDemo(env, DEMO_FLAGS_NO_SERIALIZE) { // Disable face culling setGraphicsState(HKG_ENABLED_CULLFACE, false); // Setup a camera in the right place to see our demo. { hkVector4 from( -3.7f, 5, 17.6f ); hkVector4 to (-1.5f, 1, 1.1f ); hkVector4 up ( 0.0f, 1.0f, 0.0f); setupDefaultCameras(env, from, to, up); } { hkpWorldCinfo info; info.setBroadPhaseWorldSize( 100.0f ); info.m_collisionTolerance = 0.03f; m_world = new hkpWorld(info); m_world->lock(); setupGraphics(); } hkpAgentRegisterUtil::registerAllAgents( m_world->getCollisionDispatcher() ); // // Create two movable rigid bodies to fall on the two heightfields. // { hkVector4 halfExtents(1.f, .25f, 1.f ); hkpShape* shape = new hkpBoxShape( halfExtents , 0 ); for (int i = 0; i < 2; i++ ) { hkpRigidBodyCinfo ci; ci.m_motionType = hkpMotion::MOTION_SPHERE_INERTIA; ci.m_shape = shape; ci.m_mass = 4.f; hkpMassProperties m; hkpInertiaTensorComputer::computeShapeVolumeMassProperties(shape,4, m); ci.m_inertiaTensor = m.m_inertiaTensor; ci.m_position.set( hkReal(i * 7) - 5 , 4, 3 ); hkpRigidBody* body = new hkpRigidBody( ci ); m_world->addEntity(body); body->removeReference(); } shape->removeReference(); } { // Create our heightfield hkpSampledHeightFieldBaseCinfo ci; ci.m_xRes = 7; ci.m_zRes = 7; SimpleSampledHeightFieldShape* heightFieldShape = new SimpleSampledHeightFieldShape( ci ); { // // Create the first fixed rigid body, using the standard heightfield as the shape // hkpRigidBodyCinfo rci; rci.m_motionType = hkpMotion::MOTION_FIXED; rci.m_position.set(-8, 0, 0); rci.m_shape = heightFieldShape; rci.m_friction = 0.2f; hkpRigidBody* bodyA = new hkpRigidBody( rci ); m_world->addEntity(bodyA); bodyA->removeReference(); // // Create the second fixed rigid body, using the triSampledHeightfield // // Wrap the heightfield in a hkpTriSampledHeightFieldCollection: hkpTriSampledHeightFieldCollection* collection = new hkpTriSampledHeightFieldCollection( heightFieldShape ); // Now wrap the hkpTriSampledHeightFieldCollection in a hkpTriSampledHeightFieldBvTreeShape hkpTriSampledHeightFieldBvTreeShape* bvTree = new hkpTriSampledHeightFieldBvTreeShape( collection ); // Finally, assign the new hkpTriSampledHeightFieldBvTreeShape to be the rigid body's shape rci.m_shape = bvTree; rci.m_position.set(-1,0,0); hkpRigidBody* bodyB = new hkpRigidBody( rci ); m_world->addEntity(bodyB); bodyB->removeReference(); heightFieldShape->removeReference(); collection->removeReference(); bvTree->removeReference(); } hkString left("Standard heightfield."); m_env->m_textDisplay->outputText3D(left, -7, -.2f, 7, 0xffffffff, 2000); hkString right("Triangle heightfield."); m_env->m_textDisplay->outputText3D(right, -1, -.2f, 7, 0xffffffff, 2000); } m_world->unlock(); }
PlatformsCharacterRbDemo::PlatformsCharacterRbDemo(hkDemoEnvironment* env) : hkDefaultPhysicsDemo(env) { // Setup the graphics { // Disable back face culling setGraphicsState(HKG_ENABLED_CULLFACE, false); // don't really want shadows as makes it too dark forceShadowState(false); setupLights(m_env); // so that the extra lights are added // allow color change on precreated objects m_env->m_displayHandler->setAllowColorChangeOnPrecreated(true); } // Create the world { hkpWorldCinfo info; info.setBroadPhaseWorldSize( 350.0f ); info.m_gravity.set(0,0,-9.8f); info.m_collisionTolerance = 0.01f; m_world = new hkpWorld( info ); m_world->lock(); hkpAgentRegisterUtil::registerAllAgents(m_world->getCollisionDispatcher()); setupGraphics(); } // Load the level { m_loader = new hkLoader(); hkString assetFile = hkAssetManagementUtil::getFilePath("Resources/Physics/levels/test_platform.hkx"); hkRootLevelContainer* container = m_loader->load( assetFile.cString() ); HK_ASSERT2(0x27343437, container != HK_NULL , "Could not load asset"); hkxScene* scene = reinterpret_cast<hkxScene*>( container->findObjectByType( hkxSceneClass.getName() )); HK_ASSERT2(0x27343635, scene, "No scene loaded"); env->m_sceneConverter->convert( scene, hkgAssetConverter::CONVERT_ALL ); hkpPhysicsData* physics = reinterpret_cast<hkpPhysicsData*>( container->findObjectByType( hkpPhysicsDataClass.getName() )); HK_ASSERT2(0x27343635, physics, "No physics loaded"); // Physics if (physics) { const hkArray<hkpPhysicsSystem*>& psys = physics->getPhysicsSystems(); // Tie the two together for (int i=0; i<psys.getSize(); i++) { hkpPhysicsSystem* system = psys[i]; // Change the layer of the rigid bodies for (int rb=0; rb < system->getRigidBodies().getSize(); rb++) { const hkUlong id = hkUlong(system->getRigidBodies()[rb]->getCollidable()); HK_SET_OBJECT_COLOR(id,NORMAL_GRAY); m_objectIds.pushBack(id); } // Associate the display and physics (by name) if (scene) { addPrecreatedDisplayObjectsByName( psys[i]->getRigidBodies(), scene ); } // add the lot to the world m_world->addPhysicsSystem(system); } } } // Add horizontal keyframed platform { hkpShape* platform = new hkpBoxShape(hkVector4(1.5,2.5,0.25)); hkpRigidBodyCinfo rbci; rbci.m_shape = platform; rbci.m_motionType = hkpMotion::MOTION_KEYFRAMED; rbci.m_position.set(2.5f, 0.0f, 0.25f); rbci.m_friction = 1.0f; rbci.m_collisionFilterInfo = hkpGroupFilter::calcFilterInfo(hkpGroupFilter::calcFilterInfo(1)); m_horPlatform = new hkpRigidBody(rbci); platform->removeReference(); m_world->addEntity(m_horPlatform); m_horPlatform->removeReference(); } // Add vertical keyframed platform { hkpShape* platform = new hkpBoxShape(hkVector4(1.5,2.5,0.25)); hkpRigidBodyCinfo rbci; rbci.m_shape = platform; rbci.m_motionType = hkpMotion::MOTION_KEYFRAMED; rbci.m_position.set(-3.5f, 0.0f, 3.25f); rbci.m_friction = 1.0f; rbci.m_collisionFilterInfo = hkpGroupFilter::calcFilterInfo(hkpGroupFilter::calcFilterInfo(1)); m_verPlatform = new hkpRigidBody(rbci); platform->removeReference(); m_world->addEntity(m_verPlatform); m_verPlatform->removeReference(); } // Create a character rigid body { // Create a capsule to represent the character standing hkVector4 vertexA(0,0, 0.4f); hkVector4 vertexB(0,0,-0.4f); m_standShape = new hkpCapsuleShape(vertexA, vertexB, .6f); // Construct a character rigid body hkpCharacterRigidBodyCinfo info; info.m_mass = 100.0f; info.m_shape = m_standShape; info.m_maxForce = 1000.0f; info.m_up = UP; info.m_position.set(0.0f, 5.0f, 1.5f); info.m_maxSlope = HK_REAL_PI/2.0f; m_characterRigidBody = new hkpCharacterRigidBody( info ); m_world->addEntity( m_characterRigidBody->getRigidBody() ); } // Create the character state machine { hkpCharacterState* state; hkpCharacterStateManager* manager = new hkpCharacterStateManager(); state = new hkpCharacterStateOnGround(); manager->registerState( state, HK_CHARACTER_ON_GROUND); state->removeReference(); state = new hkpCharacterStateInAir(); manager->registerState( state, HK_CHARACTER_IN_AIR); state->removeReference(); state = new hkpCharacterStateJumping(); manager->registerState( state, HK_CHARACTER_JUMPING); state->removeReference(); state = new hkpCharacterStateClimbing(); manager->registerState( state, HK_CHARACTER_CLIMBING); state->removeReference(); m_characterContext = new hkpCharacterContext(manager, HK_CHARACTER_ON_GROUND); m_characterContext->setCharacterType(hkpCharacterContext::HK_CHARACTER_RIGIDBODY); manager->removeReference(); } // Set colors of platforms HK_SET_OBJECT_COLOR(hkUlong(m_verPlatform->getCollidable()),hkColor::BLUE); HK_SET_OBJECT_COLOR(hkUlong(m_horPlatform->getCollidable()),hkColor::GREEN); // Set global time m_time = 0.0f; // Initialize hkpSurfaceInfo for previous ground m_previousGround = new hkpSurfaceInfo(); m_framesInAir = 0; // Current camera angle about up m_currentAngle = HK_REAL_PI * 0.5f; m_world->unlock(); }
MirroredMotionDemo::MirroredMotionDemo( hkDemoEnvironment* env ) : hkDefaultAnimationDemo(env) { // Character parameters // const char *sceneFileName = "Resources/Animation/Scene/hkScene.hkx"; const char *rigFileName = "Resources/Animation/HavokGirl/hkRig.hkx"; const char *skinFileName = "Resources/Animation/HavokGirl/hkLowResSkin.hkx"; // Mirroring Parameters const char * leftPrefix[2] = { " L ", "EyeL" }; const char *rightPrefix[2] = { " R ", "EyeR" }; const int numPrefix = 2; const hkQuaternion mirrorAxis( 1.0f, 0.0f, 0.0f, 0.0f ); // Show backfaces so that you can see inside of things setGraphicsState( HKG_ENABLED_CULLFACE, false ); env->m_sceneConverter->setAllowTextureSharing( true ); env->m_sceneConverter->setAllowMaterialSharing( true ); // // Setup the camera // { hkVector4 from( 0,-6,1 ); hkVector4 to ( 0,0,0 ); hkVector4 up ( 0.0f, 0.0f, 1.0f ); setupDefaultCameras( env, from, to, up, 0.01f, 100 ); } m_loader = new hkLoader(); // Get the rig { hkString assetFile = hkAssetManagementUtil::getFilePath( rigFileName ); hkRootLevelContainer* container = m_loader->load( assetFile.cString() ); HK_ASSERT2(0x27343437, container != HK_NULL , "Could not load asset"); hkaAnimationContainer* ac = reinterpret_cast<hkaAnimationContainer*>( container->findObjectByType( hkaAnimationContainerClass.getName() )); HK_ASSERT2(0x27343435, ac && (ac->m_numSkeletons > 0), "No skeleton loaded"); m_skeleton = ac->m_skeletons[0]; } // Get the animation and the binding { hkString assetFile = hkAssetManagementUtil::getFilePath( g_variants[ env->m_variantId ].m_animationFileName ); hkRootLevelContainer* container = m_loader->load( assetFile.cString() ); HK_ASSERT2(0x27343437, container != HK_NULL , "Could not load asset"); hkaAnimationContainer* ac = reinterpret_cast<hkaAnimationContainer*>( container->findObjectByType( hkaAnimationContainerClass.getName() )); HK_ASSERT2(0x27343435, ac && (ac->m_numAnimations > 0 ), "No animation loaded"); m_animation[0] = ac->m_animations[0]; HK_ASSERT2(0x27343435, ac && (ac->m_numBindings > 0), "No binding loaded"); m_binding[0] = ac->m_bindings[0]; } // Create the mirrored animation and binding { hkObjectArray< hkString > ltag; hkObjectArray< hkString > rtag; for ( int j = 0; j < ( numPrefix ); j++ ) { ltag.pushBack( ( leftPrefix )[ j ] ); rtag.pushBack( ( rightPrefix )[ j ] ); } hkaMirroredSkeleton *mirroredSkeleton = new hkaMirroredSkeleton( m_skeleton ); mirroredSkeleton->computeBonePairingFromNames( ltag, rtag ); hkaMirroredAnimation *mirroredAnimation = new hkaMirroredAnimation( m_animation[0], m_binding[0], mirroredSkeleton ); mirroredSkeleton->removeReference(); mirroredSkeleton->setAllBoneInvariantsFromReferencePose( mirrorAxis, 0.0f ); m_binding[1] = mirroredAnimation->createMirroredBinding(); m_animation[1] = mirroredAnimation; } // Create the skeletons for ( int i = 0; i < 2; i++ ) { m_skeletonInstance[i] = new hkaAnimatedSkeleton( m_skeleton ); m_skeletonInstance[i]->setReferencePoseWeightThreshold( 0.1f ); } // Convert the skin (once for each character standard and mirrored) for ( int i = 0; i < 2; i++ ) { hkString assetFile = hkAssetManagementUtil::getFilePath( skinFileName ); hkRootLevelContainer* container = m_loader->load( assetFile.cString() ); if ( container != HK_NULL ) { HK_ASSERT2(0x27343437, container != HK_NULL , "Could not load asset"); hkxScene* scene = reinterpret_cast<hkxScene*>( container->findObjectByType( hkxSceneClass.getName() )); HK_ASSERT2(0x27343435, scene , "No scene loaded"); hkaAnimationContainer* ac = reinterpret_cast<hkaAnimationContainer*>( container->findObjectByType( hkaAnimationContainerClass.getName() )); HK_ASSERT2(0x27343435, ac && (ac->m_numSkins > 0), "No skins loaded"); m_numSkinBindings[i] = ac->m_numSkins; m_skinBindings[i] = ac->m_skins; m_numAttachments[i] = ac->m_numAttachments; m_attachments[i] = ac->m_attachments; // Make graphics output buffers for the skins env->m_sceneConverter->convert( scene ); // Handle the attachements for (int a=0; a < m_numAttachments[i]; ++a) { hkaBoneAttachment* ba = m_attachments[i][a]; hkgDisplayObject* hkgObject = HK_NULL; //Check the attachment is a mesh if ( hkString::strCmp(ba->m_attachment.m_class->getName(), hkxMeshClass.getName()) == 0) { hkgObject = env->m_sceneConverter->findFirstDisplayObjectUsingMesh((hkxMesh*)ba->m_attachment.m_object); if (hkgObject) { hkgObject->setStatusFlags( hkgObject->getStatusFlags() | HKG_DISPLAY_OBJECT_DYNAMIC); } } m_attachmentObjects[i].pushBack(hkgObject); } } else { m_numSkinBindings[i] = 0; m_skinBindings[i] = 0; m_numAttachments[i] = 0; } } // Grab the animations for ( int i = 0; i < 2; i++ ) { m_control[i] = new hkaDefaultAnimationControl( m_binding[i] ); m_control[i]->setMasterWeight( 1.0f ); m_control[i]->setPlaybackSpeed( 1.0f ); // Ease all controls out initially m_control[i]->easeIn(1.0f); m_skeletonInstance[i]->addAnimationControl( m_control[i] ); m_control[i]->removeReference(); // Set ease curves explicitly m_control[i]->setEaseInCurve(0, 0, 1, 1); // Smooth m_control[i]->setEaseOutCurve(1, 1, 0, 0); // Smooth m_accumulatedMotion[i].setIdentity(); } // make a world so that we can auto create a display world to hold the skin setupGraphics( ); m_axisCounter = 0; m_env = env; m_drawSkin = true; m_wireframe = false; m_timestep = 1.0f / 60.0f; m_useExtractedMotion = true; m_paused = false; m_separation = 1.0f; }
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; }
CharacterDemo::CharacterDemo(hkDemoEnvironment* env) : hkDefaultPhysicsDemo(env) { // // Setup the camera // { hkVector4 from( 0.0f, 20.0f, -80.0f); hkVector4 to ( 0.0f, 0.0f, 0.0f); hkVector4 up ( 0.0f, 1.0f, 0.0f); setupDefaultCameras( env, from, to, up ); // disable back face culling setGraphicsState(HKG_ENABLED_CULLFACE, false); // don't really want shadows as makes it too dark forceShadowState(false); setupLights(m_env); // so that the extra lights are added // float lightDir[] = { 0, -0.5f, -1 }; // setSoleDirectionLight(m_env, lightDir, 0xffffffff ); } // // Create the world // { hkpWorldCinfo info; info.setBroadPhaseWorldSize( 350.0f ); info.m_gravity.set(0,0,-9.8f); info.m_collisionTolerance = 0.1f; m_world = new hkpWorld( info ); m_world->lock(); hkpAgentRegisterUtil::registerAllAgents(m_world->getCollisionDispatcher()); setupGraphics(); } // Load the level { hkVector4 tkScaleFactor(.32f,.32f,.32f); hkString fullname("Resources/Physics/Tk/CharacterController/"); // We load our test case level. //fullname += "testcases.tk"; fullname += "level.tk"; hkpShape* moppShape = GameUtils::loadTK2MOPP(fullname.cString(),tkScaleFactor, -1.0f); HK_ASSERT2(0x64232cc0, moppShape,"TK file failed to load to MOPP in GameUtils::loadTK2MOPP."); hkpRigidBodyCinfo ci; ci.m_shape = moppShape; ci.m_motionType = hkpMotion::MOTION_FIXED; ci.m_collisionFilterInfo = hkpGroupFilter::calcFilterInfo( 0, 1 ); hkpRigidBody* entity = new hkpRigidBody(ci); moppShape->removeReference(); m_world->addEntity(entity); entity->removeReference(); } // Add a ladder hkVector4 baseSize( 1.0f, 0.5f, 3.6f); { hkpRigidBodyCinfo rci; rci.m_shape = new hkpBoxShape( baseSize ); rci.m_position.set(3.4f, 8.f, 2); rci.m_motionType = hkpMotion::MOTION_FIXED; hkpRigidBody* ladder = new hkpRigidBody(rci); rci.m_shape->removeReference(); m_world->addEntity(ladder)->removeReference(); // Add a property so we can identify this as a ladder hkpPropertyValue val(1); ladder->addProperty(HK_OBJECT_IS_LADDER, val); // Color the ladder so we can see it clearly HK_SET_OBJECT_COLOR((hkUlong)ladder->getCollidable(), 0x7f1f3f1f); } // // Create a character proxy object // { // Construct a shape hkVector4 vertexA(0,0, 0.4f); hkVector4 vertexB(0,0,-0.4f); // Create a capsule to represent the character standing m_standShape = new hkpCapsuleShape(vertexA, vertexB, .6f); // Create a capsule to represent the character crouching // Note that we create the smaller capsule with the base at the same position as the larger capsule. // This means we can simply swap the shapes without having to reposition the character proxy, // and if the character is standing on the ground, it will still be on the ground. vertexA.setZero4(); m_crouchShape = new hkpCapsuleShape(vertexA, vertexB, .6f); // Construct a Shape Phantom m_phantom = new hkpSimpleShapePhantom( m_standShape, hkTransform::getIdentity(), hkpGroupFilter::calcFilterInfo(0,2) ); // Add the phantom to the world m_world->addPhantom(m_phantom); m_phantom->removeReference(); // Construct a character proxy hkpCharacterProxyCinfo cpci; cpci.m_position.set(-9.1f, 35, .4f); cpci.m_staticFriction = 0.0f; cpci.m_dynamicFriction = 1.0f; cpci.m_up.setNeg4( m_world->getGravity() ); cpci.m_up.normalize3(); cpci.m_userPlanes = 4; cpci.m_maxSlope = HK_REAL_PI / 3.f; cpci.m_shapePhantom = m_phantom; m_characterProxy = new hkpCharacterProxy( cpci ); } // // Add in a custom friction model // { hkVector4 up( 0.f, 0.f, 1.f ); m_listener = new MyCharacterListener(); m_characterProxy->addCharacterProxyListener(m_listener); } // // Create the Character state machine and context // { hkpCharacterState* state; hkpCharacterStateManager* manager = new hkpCharacterStateManager(); state = new hkpCharacterStateOnGround(); manager->registerState( state, HK_CHARACTER_ON_GROUND); state->removeReference(); state = new hkpCharacterStateInAir(); manager->registerState( state, HK_CHARACTER_IN_AIR); state->removeReference(); state = new hkpCharacterStateJumping(); manager->registerState( state, HK_CHARACTER_JUMPING); state->removeReference(); state = new hkpCharacterStateClimbing(); manager->registerState( state, HK_CHARACTER_CLIMBING); state->removeReference(); m_characterContext = new hkpCharacterContext(manager, HK_CHARACTER_ON_GROUND); manager->removeReference(); } // Current camera angle about up m_currentAngle = HK_REAL_PI * 0.5f; m_world->unlock(); }
SimpleShapesDemo::SimpleShapesDemo(hkDemoEnvironment* env) : hkDefaultPhysicsDemo(env) { const ShapeVariant& variant = g_variants[m_variantId]; // Setup the camera. { hkVector4 from(0.0f, 5.0f, 10.0f); hkVector4 to (0.0f, 0.0f, 0.0f); hkVector4 up (0.0f, 1.0f, 0.0f); setupDefaultCameras(env, from, to, up); } // Create the world, setting gravity to zero so body floats. hkpWorldCinfo info; info.m_gravity.set(0.0f, 0.0f, 0.0f); info.setBroadPhaseWorldSize( 100.0f ); m_world = new hkpWorld(info); m_world->lock(); setupGraphics(); // Create the shape variant hkpShape* shape = 0; switch (variant.m_shapeType) { // Box case HK_SHAPE_BOX: { // Data specific to this shape. hkVector4 halfExtents(1.0f, 1.0f, 1.0f); /////////////////// SHAPE CONSTRUCTION //////////////// shape = new hkpBoxShape(halfExtents, 0 ); break; } // Sphere case HK_SHAPE_SPHERE: { // The box is of side 2, so we must bound it by a sphere of radius >= sqrt(3) hkReal radius = 1.75f; /////////////////// SHAPE CONSTRUCTION //////////////// shape = new hkpSphereShape(radius); break; } // Triangle case HK_SHAPE_TRIANGLE: { // Disable face culling setGraphicsState(HKG_ENABLED_CULLFACE, false); float vertices[] = { -0.5f, -0.5f, 0.0f, 0.0f, // v0 0.5f, -0.5f, 0.0f, 0.0f, // v1 0.0f, 0.5f, 0.0f, 0.0f, // v2 }; /////////////////// SHAPE CONSTRUCTION //////////////// shape = new hkpTriangleShape(); int index = 0; for (int i = 0; i < 3; i++) { static_cast<hkpTriangleShape*>(shape)->setVertex(i, hkVector4(vertices[index], vertices[index + 1], vertices[index + 2])); index = index + 4; } break; } // Capsule case HK_SHAPE_CAPSULE: { hkReal radius = 1.5f; hkVector4 top(0.0f, 1.5f, 0.0f); hkVector4 bottom(0.0f, -1.0f, 0.0f); /////////////////// SHAPE CONSTRUCTION //////////////// shape = new hkpCapsuleShape(top, bottom, radius); break; } // Cylinder case HK_SHAPE_CYLINDER: { hkReal radius = 1.5f; hkVector4 top(0.0f, 1.5f, 0.0f); hkVector4 bottom(0.0f, -1.0f, 0.0f); /////////////////// SHAPE CONSTRUCTION //////////////// shape = new hkpCylinderShape(top, bottom, radius); break; } // Convex vertices case HK_SHAPE_CONVEX_VERTICES: { // Data specific to this shape. int numVertices = 4; // 16 = 4 (size of "each float group", 3 for x,y,z, 1 for padding) * 4 (size of float) int stride = sizeof(float) * 4; float vertices[] = { // 4 vertices plus padding -2.0f, 2.0f, 1.0f, 0.0f, // v0 1.0f, 3.0f, 0.0f, 0.0f, // v1 0.0f, 1.0f, 3.0f, 0.0f, // v2 1.0f, 0.0f, 0.0f, 0.0f // v3 }; /////////////////// SHAPE CONSTRUCTION //////////////// hkStridedVertices stridedVerts; { stridedVerts.m_numVertices = numVertices; stridedVerts.m_striding = stride; stridedVerts.m_vertices = vertices; } shape = new hkpConvexVerticesShape(stridedVerts); break; } default: break; } // Make sure that a shape was created HK_ASSERT(0, shape); // To illustrate using the shape, first define a rigid body template. hkpRigidBodyCinfo rigidBodyInfo; rigidBodyInfo.m_position.set(0.0f, 0.0f, 0.0f); rigidBodyInfo.m_angularDamping = 0.0f; rigidBodyInfo.m_linearDamping = 0.0f; rigidBodyInfo.m_shape = shape; // Compute the rigid body inertia. rigidBodyInfo.m_motionType = hkpMotion::MOTION_BOX_INERTIA; hkpInertiaTensorComputer::setShapeVolumeMassProperties( rigidBodyInfo.m_shape, 100.0f, rigidBodyInfo ); // Create a rigid body (using the template above). hkpRigidBody* rigidBody = new hkpRigidBody(rigidBodyInfo); // Remove reference since the body now "owns" the Shape. shape->removeReference(); // Finally add body so we can see it, and remove reference since the world now "owns" it. m_world->addEntity(rigidBody); rigidBody->removeReference(); m_world->unlock(); }