예제 #1
0
    public ClosedFormIKSample(Microsoft.Xna.Framework.Game game)
      : base(game)
    {
      var modelNode = ContentManager.Load<ModelNode>("Dude/Dude");
      _meshNode = modelNode.GetSubtree().OfType<MeshNode>().First().Clone();
      _meshNode.PoseLocal = new Pose(new Vector3F(0, 0, 0));
      SampleHelper.EnablePerPixelLighting(_meshNode);
      GraphicsScreen.Scene.Children.Add(_meshNode);

      // Create the IK solver. The ClosedFormIKSolver uses an analytic solution to compute
      // IK for arbitrary long bone chains. It does not support bone rotation limits.
      _ikSolver = new ClosedFormIKSolver
      {
        SkeletonPose = _meshNode.SkeletonPose,

        // The chain starts at the upper arm.
        RootBoneIndex = 13,

        // The chain ends at the hand bone.
        TipBoneIndex = 15,

        // The offset from the hand center to the hand origin.
        TipOffset = new Vector3F(0.1f, 0, 0),
      };
    }
예제 #2
0
    public PassiveRagdollSample(Microsoft.Xna.Framework.Game game)
      : base(game)
    {
      GraphicsScreen.DrawReticle = true;

      // Add game objects which allow to shoot balls and grab rigid bodies.
      _ballShooterObject = new BallShooterObject(Services) { Speed = 10 };
      GameObjectService.Objects.Add(_ballShooterObject);
      _grabObject = new GrabObject(Services);
      GameObjectService.Objects.Add(_grabObject);

      var modelNode = ContentManager.Load<ModelNode>("Dude/Dude");
      _meshNode = modelNode.GetSubtree().OfType<MeshNode>().First().Clone();
      _meshNode.PoseLocal = new Pose(new Vector3F(0, 0, 0));
      SampleHelper.EnablePerPixelLighting(_meshNode);
      GraphicsScreen.Scene.Children.Add(_meshNode);

      // Create a ragdoll for the Dude model.
      _ragdoll = new Ragdoll();
      DudeRagdollCreator.Create(_meshNode.SkeletonPose, _ragdoll, Simulation, 0.571f);

      // Set the world space pose of the whole ragdoll. And copy the bone poses of the
      // current skeleton pose.
      _ragdoll.Pose = _meshNode.PoseWorld;
      _ragdoll.UpdateBodiesFromSkeleton(_meshNode.SkeletonPose);

      // Uncomment to disable dynamic movement (for debugging during ragdoll creation):
      //foreach (var body in _ragdoll.Bodies)
      //  if (body != null)
      //    body.MotionType = MotionType.Kinematic;

      // In this sample we use a passive ragdoll where we need joints to hold the
      // limbs together and limits to restrict angular movement.
      _ragdoll.EnableJoints();
      _ragdoll.EnableLimits();

      // Set all motors to constraint motors that only use damping. This adds a damping
      // effect to all ragdoll limbs.
      foreach (RagdollMotor motor in _ragdoll.Motors)
      {
        if (motor != null)
        {
          motor.Mode = RagdollMotorMode.Constraint;
          motor.ConstraintDamping = 5;
          motor.ConstraintSpring = 0;
        }
      }
      _ragdoll.EnableMotors();

      // Add rigid bodies and the constraints of the ragdoll to the simulation.
      _ragdoll.AddToSimulation(Simulation);

      // Add a rigid body.
      var box = new RigidBody(new BoxShape(0.4f, 0.4f, 0.4f))
      {
        Name = "Box",
        Pose = new Pose(new Vector3F(0, 3, 0)),
      };
      Simulation.RigidBodies.Add(box);
    }
예제 #3
0
    public CcdIKSample(Microsoft.Xna.Framework.Game game)
      : base(game)
    {
      var modelNode = ContentManager.Load<ModelNode>("Dude/Dude");
      _meshNode = modelNode.GetSubtree().OfType<MeshNode>().First().Clone();
      _meshNode.PoseLocal = new Pose(new Vector3F(0, 0, 0));
      SampleHelper.EnablePerPixelLighting(_meshNode);
      GraphicsScreen.Scene.Children.Add(_meshNode);

      // Create the IK solver. The CCD method can solve long bone chains with 
      // limits. 
      _ikSolver = new CcdIKSolver
      {
        SkeletonPose = _meshNode.SkeletonPose,

        // The chain starts at the upper arm.
        RootBoneIndex = 13,

        // The chain ends at the hand bone.
        TipBoneIndex = 15,

        // The offset from the hand center to the hand origin.
        TipOffset = new Vector3F(0.1f, 0, 0),

        // We can set a bone gain less than 1 to get a "smoother" result in most cases -
        // at the cost of more iterations.
        //BoneGain = 0.9f,

        // This solver uses an iterative method and will make up to 100 iterations if necessary.
        NumberOfIterations = 10,

        // A method that applies bone limits.
        LimitBoneTransforms = LimitBoneTransform,
      };
    }
예제 #4
0
    public SkeletonMappingSample(Microsoft.Xna.Framework.Game game)
      : base(game)
    {
      // Get dude model and start animation on the dude.
      var modelNode = ContentManager.Load<ModelNode>("Dude/Dude");
      _dudeMeshNode = modelNode.GetSubtree().OfType<MeshNode>().First().Clone();
      _dudeMeshNode.PoseLocal = new Pose(new Vector3F(-0.5f, 0, 0), Matrix33F.CreateRotationY(ConstantsF.Pi));
      SampleHelper.EnablePerPixelLighting(_dudeMeshNode);
      GraphicsScreen.Scene.Children.Add(_dudeMeshNode);

      var animations = _dudeMeshNode.Mesh.Animations;
      var loopingAnimation = new AnimationClip<SkeletonPose>(animations.Values.First())
      {
        LoopBehavior = LoopBehavior.Cycle,
        Duration = TimeSpan.MaxValue,
      };
      AnimationService.StartAnimation(loopingAnimation, (IAnimatableProperty)_dudeMeshNode.SkeletonPose);

      // Get marine model - do not start any animations on the marine model.
      modelNode = ContentManager.Load<ModelNode>("Marine/PlayerMarine");
      _marineMeshNode = modelNode.GetSubtree().OfType<MeshNode>().First().Clone();
      _marineMeshNode.PoseLocal = new Pose(new Vector3F(0.5f, 0, 0), Matrix33F.CreateRotationY(ConstantsF.Pi));
      SampleHelper.EnablePerPixelLighting(_marineMeshNode);
      GraphicsScreen.Scene.Children.Add(_marineMeshNode);

      CreateSkeletonMapper();
    }
예제 #5
0
    public BoneJiggleSample(Microsoft.Xna.Framework.Game game)
      : base(game)
    {
      var modelNode = ContentManager.Load<ModelNode>("Dude/Dude");
      _meshNode = modelNode.GetSubtree().OfType<MeshNode>().First().Clone();
      _meshNode.PoseLocal = new Pose(new Vector3F(0, 0, 0), Matrix33F.CreateRotationY(ConstantsF.Pi));
      SampleHelper.EnablePerPixelLighting(_meshNode);
      GraphicsScreen.Scene.Children.Add(_meshNode);

      var animations = _meshNode.Mesh.Animations;
      var walkAnimation = new AnimationClip<SkeletonPose>(animations.Values.First())
      {
        LoopBehavior = LoopBehavior.Cycle,
        Duration = TimeSpan.MaxValue,
      };
      _walkAnimationController = AnimationService.StartAnimation(walkAnimation, (IAnimatableProperty)_meshNode.SkeletonPose);
      _walkAnimationController.AutoRecycle();

      // Create a BoneJiggler instance for the head bone (bone index 7).
      _boneJiggler = new BoneJiggler(_meshNode.SkeletonPose, 7, new Vector3F(1.1f, 0, 0))
      {
        Spring = 100,
        Damping = 3,
      };
    }
예제 #6
0
    public AttachmentSample(Microsoft.Xna.Framework.Game game)
      : base(game)
    {
      var modelNode = ContentManager.Load<ModelNode>("Marine/PlayerMarine");
      _meshNode = modelNode.GetSubtree().OfType<MeshNode>().First().Clone();
      SampleHelper.EnablePerPixelLighting(_meshNode);
      GraphicsScreen.Scene.Children.Add(_meshNode);

      // Play a looping 'Idle' animation.
      var animations = _meshNode.Mesh.Animations;
      var idleAnimation = animations["Idle"];
      var loopingAnimation = new AnimationClip<SkeletonPose>(idleAnimation)
      {
        LoopBehavior = LoopBehavior.Cycle,
        Duration = TimeSpan.MaxValue,
      };
      var animationController = AnimationService.StartAnimation(loopingAnimation, (IAnimatableProperty)_meshNode.SkeletonPose);
      animationController.UpdateAndApply();
      animationController.AutoRecycle();

      // Add weapon model to the scene graph under the node of the marine mesh.
      _weaponModelNode = ContentManager.Load<ModelNode>("Marine/Weapon/WeaponMachineGun").Clone();
      _meshNode.Children = new SceneNodeCollection();
      _meshNode.Children.Add(_weaponModelNode);
    }
예제 #7
0
    public TwoJointIKSample(Microsoft.Xna.Framework.Game game)
      : base(game)
    {
      var modelNode = ContentManager.Load<ModelNode>("Dude/Dude");
      _meshNode = modelNode.GetSubtree().OfType<MeshNode>().First().Clone();
      _meshNode.PoseLocal = new Pose(new Vector3F(0, 0, 0));
      SampleHelper.EnablePerPixelLighting(_meshNode);
      GraphicsScreen.Scene.Children.Add(_meshNode);

      // Create the IK solver. The TwoJointIkSolver is usually used for arms and legs.
      // it modifies two bones and supports limits for the second bone. 
      _ikSolver = new TwoJointIKSolver
      {
        SkeletonPose = _meshNode.SkeletonPose,

        // The chain starts at the upper leg.
        RootBoneIndex = 54,

        // The second bone modified bone is the lower leg.
        HingeBoneIndex = 55,

        // The chain ends at the foot bone.
        TipBoneIndex = 56,

        // The direction of the hinge axis (in bone space).
        HingeAxis = -Vector3F.UnitZ,

        // The hinge limits.
        MinHingeAngle = 0,
        MaxHingeAngle = ConstantsF.PiOver2,

        // The offset from the ankle to the bottom of the foot.
        TipOffset = new Vector3F(0.23f, 0, 0),
      };
    }
예제 #8
0
    public BindPoseSample(Microsoft.Xna.Framework.Game game)
      : base(game)
    {
      // Load dude model node.
      // This model uses the DigitalRune Model Processor. Several XML files (*.drmdl 
      // and *.drmat) in the folder of dude.fbx define the materials and other properties. 
      // The DigitalRune Model Processor also imports the animations of the dude model
      // and the *.drmdl can be used to specify how animations should be processed in 
      // the content pipeline.
      // The *.drmat files define the used effects and effect parameters. The effects 
      // must support mesh skinning.
      var sharedDudeModelNode = ContentManager.Load<ModelNode>("Dude/Dude");

      // Clone the dude model because objects returned by the ContentManager
      // are shared instances, and we do not want manipulate or animate this shared instance.
      var dudeModelNode = sharedDudeModelNode.Clone();

      // The loaded dude model is a scene graph which consists of a ModelNode
      // which has a single MeshNode as its child.
      _dudeMeshNode = (MeshNode)dudeModelNode.Children[0];
      // We could also get the MeshNode by name:
      _dudeMeshNode = (MeshNode)dudeModelNode.GetSceneNode("him");
      // Or using a more general LINQ query:
      _dudeMeshNode = dudeModelNode.GetSubtree().OfType<MeshNode>().First();

      // Set the world space position and orientation of the dude.
      _dudeMeshNode.PoseLocal = new Pose(new Vector3F(-1f, 0, 0));

      // The imported Mesh of the Dude has a Skeleton, which defines the bone hierarchy.
      var skeleton = _dudeMeshNode.Mesh.Skeleton;

      // The imported MeshNode has a SkeletonPose, which defines the current animation pose
      // (transformations of the bones). The default skeleton pose is the bind pose 
      // where all bone transformations are set to an identity transformation (no scale, 
      // no rotation, no translation).
      var skeletonPose = _dudeMeshNode.SkeletonPose;

      // Load the marine model:
      var marineModelNode = ContentManager.Load<ModelNode>("Marine/PlayerMarine").Clone();
      _marineMeshNode = marineModelNode.GetSubtree().OfType<MeshNode>().First();
      _marineMeshNode.PoseLocal = new Pose(new Vector3F(1f, 0, 0));

      // Enable per-pixel lighting.
      SampleHelper.EnablePerPixelLighting(_dudeMeshNode);
      SampleHelper.EnablePerPixelLighting(_marineMeshNode);

      // Add the to the scene graph, so that they are drawn by the graphics screen.
      // We can add the ModelNodes directly to the scene.
      //GraphicsScreen.Scene.Children.Add(dudeModelNode);
      //GraphicsScreen.Scene.Children.Add(marineModelNode);
      // Alternatively, we can detach the MeshNodes from their parent nodes and
      // add them directly to the scene graph. The parent ModelNodes basically empty
      // nodes, which are only used to load and group other nodes.
      _dudeMeshNode.Parent.Children.Remove(_dudeMeshNode);
      GraphicsScreen.Scene.Children.Add(_dudeMeshNode);
      _marineMeshNode.Parent.Children.Remove(_marineMeshNode);
      GraphicsScreen.Scene.Children.Add(_marineMeshNode);
    }
예제 #9
0
    public SkinnedEffectSample(Microsoft.Xna.Framework.Game game)
      : base(game)
    {
      SampleFramework.IsMouseVisible = false;
      GraphicsScreen.ClearBackground = true;
      GraphicsScreen.BackgroundColor = Color.CornflowerBlue;
      SetCamera(new Vector3F(1, 1, 3), 0.2f, 0);

      // Create a sky mesh and add an instance of this mesh to the scene.
      var skyMesh = ProceduralSkyDome.CreateMesh(GraphicsService, ContentManager.Load<Texture2D>("sky"));
      _sky = new MeshNode(skyMesh);
      _sky.Name = "Sky"; // Always set a name - very useful for debugging!
      GraphicsScreen.Scene.Children.Add(_sky);

      // Load the skinned model. This model is processed using the DigitalRune Model 
      // Processor - not the default XNA model processor!
      // In the folder that contains dude.fbx, there are several XML files (*.drmdl and *.drmat) 
      // which define the materials of the model. These material description files are 
      // automatically processed by the DigitalRune Model Processor. Please browse 
      // to the content folder and have a look at the *.drmdl and *.drmat files.
      var dudeModel = ContentManager.Load<ModelNode>("Dude/Dude");
      dudeModel = dudeModel.Clone();
      dudeModel.PoseWorld = new Pose(Matrix33F.CreateRotationY(ConstantsF.Pi));
      GraphicsScreen.Scene.Children.Add(dudeModel);

      // The dude model consists of a single mesh.
      var dudeMeshNode = dudeModel.GetSubtree().OfType<MeshNode>().First();
      var mesh = dudeMeshNode.Mesh;

      /*
        // The dude mesh consists of different materials (head, eyes, torso, ...).
        // We could change some of the material properties...
        foreach (var material in mesh.Materials)
        {
          // Get all SkinnedEffectBindings which wrap the XNA SkinnedEffect. 
          // A material can consist of several effects - one effect for each render pass.
          // (Per default there is only one render pass called "Default".)
          foreach (var effectBinding in material.EffectBindings.OfType<SkinnedEffectBinding>())
          {
            // We could change effect parameters here, for example:
            effectBinding.PreferPerPixelLighting = true;
          }
        }
      */

      // The DigitalRune Model Processor also loads animations.
      // Start the first animation of the dude and let it loop forever.
      // (We keep the animation controller to be able to stop the animation in 
      // Dispose() below.)
      var timeline = new TimelineClip(mesh.Animations.Values.First())
      {
        Duration = TimeSpan.MaxValue,
        LoopBehavior = LoopBehavior.Cycle,
      };
      _animationController = AnimationService.StartAnimation(timeline, (IAnimatableProperty)dudeMeshNode.SkeletonPose);
    }
예제 #10
0
    public SkeletonManipulationSample(Microsoft.Xna.Framework.Game game)
      : base(game)
    {
      var modelNode = ContentManager.Load<ModelNode>("Dude/Dude");
      _meshNode = modelNode.GetSubtree().OfType<MeshNode>().First().Clone();
      _meshNode.PoseLocal = new Pose(new Vector3F(-0.5f, 0, 0));
      SampleHelper.EnablePerPixelLighting(_meshNode);

      GraphicsScreen.Scene.Children.Add(_meshNode);
    }
예제 #11
0
    private void CreateParticleSystem()
    {
      // Load a sphere model.
      var modelNode = ContentManager.Load<ModelNode>("Particles/Sphere");
      var meshNode = (MeshNode)modelNode.Children[0];

      // Add gravity and damping to the physics simulation.
      Simulation.ForceEffects.Add(new Gravity());
      Simulation.ForceEffects.Add(new Damping());

      // Create two instances of the sphere model.
      _meshNode0 = meshNode.Clone();
      GraphicsScreen.Scene.Children.Add(_meshNode0);
      _meshNode1 = meshNode.Clone();
      GraphicsScreen.Scene.Children.Add(_meshNode1);

      // Create a rigid body for the left sphere.
      _rigidBody0 = new RigidBody(new SphereShape(0.5f))
      {
        Pose = new Pose(new Vector3F(-3, 4, 0)),
      };
      Simulation.RigidBodies.Add(_rigidBody0);

      // Create a rigid body for the right sphere. (Sharing the same shape, mass and material.)
      _rigidBody1 = new RigidBody(_rigidBody0.Shape, _rigidBody0.MassFrame, _rigidBody0.Material)
      {
        Pose = new Pose(new Vector3F(3, 4, 0)),
      };
      Simulation.RigidBodies.Add(_rigidBody1);

      // Extract basic triangle mesh from the sphere model.
      var triangleMesh = meshNode.Mesh.Submeshes[0].ToTriangleMesh();

      // Create a particle system for the left ball. This particle system uses
      // ReferenceFrame == ParticleReferenceFrame.World - which is the default for all 
      // particle systems. Particles are all relative to world space. The particle system pose 
      // determines the start positions and direction (when the StartPositionEffector and 
      // StartDirectionEffector are in use). Particles do not move with the particle system.
      _particleSystem0 = GlowingMeshEffect.Create(triangleMesh, ContentManager);
      _particleSystem0.ReferenceFrame = ParticleReferenceFrame.World;
      ParticleSystemService.ParticleSystems.Add(_particleSystem0);

      _particleSystemNode0 = new ParticleSystemNode(_particleSystem0);
      _meshNode0.Children = new SceneNodeCollection { _particleSystemNode0 };

      // Create a particle system for the right ball. This particle system uses
      // ReferenceFrame == ParticleReferenceFrame.Local. Particles are all relative to the 
      // particle system pose. Particles move with the particle system.
      _particleSystem1 = GlowingMeshEffect.Create(triangleMesh, ContentManager);
      _particleSystem1.ReferenceFrame = ParticleReferenceFrame.Local;
      ParticleSystemService.ParticleSystems.Add(_particleSystem1);

      _particleSystemNode1 = new ParticleSystemNode(_particleSystem1);
      _meshNode1.Children = new SceneNodeCollection { _particleSystemNode1 };
    }
예제 #12
0
    public MixingSample(Microsoft.Xna.Framework.Game game)
      : base(game)
    {
      var modelNode = ContentManager.Load<ModelNode>("Marine/PlayerMarine");
      _meshNode = modelNode.GetSubtree().OfType<MeshNode>().First().Clone();
      SampleHelper.EnablePerPixelLighting(_meshNode);
      GraphicsScreen.Scene.Children.Add(_meshNode);

      var animations = _meshNode.Mesh.Animations;
      _runAnimation = new AnimationClip<SkeletonPose>(animations["Run"])
      {
        LoopBehavior = LoopBehavior.Cycle,
        Duration = TimeSpan.MaxValue,
      };
      _idleAnimation = new AnimationClip<SkeletonPose>(animations["Idle"])
      {
        LoopBehavior = LoopBehavior.Cycle,
        Duration = TimeSpan.MaxValue,
      };

      // Create a 'Shoot' animation that only affects the upper body.
      var shootAnimation = animations["Shoot"];

      // The SkeletonKeyFrameAnimations allows to set a weight for each bone channel. 
      // For the 'Shoot' animation, we set the weight to 0 for all bones that are 
      // not descendants of the second spine bone (bone index 2). That means, the 
      // animation affects only the upper body bones and is disabled on the lower 
      // body bones.
      for (int i = 0; i < _meshNode.Mesh.Skeleton.NumberOfBones; i++)
      {
        if (!SkeletonHelper.IsAncestorOrSelf(_meshNode.SkeletonPose, 2, i))
          shootAnimation.SetWeight(i, 0);
      }

      var loopedShootingAnimation = new AnimationClip<SkeletonPose>(shootAnimation)
      {
        LoopBehavior = LoopBehavior.Cycle,
        Duration = TimeSpan.MaxValue,
      };

      // Start 'Idle' animation.
      _idleAnimationController = AnimationService.StartAnimation(_idleAnimation, (IAnimatableProperty)_meshNode.SkeletonPose);
      _idleAnimationController.AutoRecycle();

      // Start looping the 'Shoot' animation. We use a Compose transition. This will add the 
      // 'Shoot' animation to the animation composition chain and keeping all other playing 
      // animations.
      // The 'Idle' animation animates the whole skeleton. The 'Shoot' animation replaces 
      // the 'Idle' animation on the bones of the upper body.
      AnimationService.StartAnimation(loopedShootingAnimation,
                                      (IAnimatableProperty)_meshNode.SkeletonPose,
                                      AnimationTransitions.Compose()
                                     ).AutoRecycle();
    }
예제 #13
0
    public CollisionDetectionOnlyRagdollSample(Microsoft.Xna.Framework.Game game)
      : base(game)
    {
      GraphicsScreen.DrawReticle = true;
      SetCamera(new Vector3F(0, 1, 6), 0, 0);

      // Add a game object which allows to shoot balls.
      _ballShooterObject = new BallShooterObject(Services);
      GameObjectService.Objects.Add(_ballShooterObject);

      var modelNode = ContentManager.Load<ModelNode>("Dude/Dude");
      _meshNode = modelNode.GetSubtree().OfType<MeshNode>().First().Clone();
      _meshNode.PoseLocal = new Pose(new Vector3F(0, 0, 0), Matrix33F.CreateRotationY(ConstantsF.Pi));
      SampleHelper.EnablePerPixelLighting(_meshNode);
      GraphicsScreen.Scene.Children.Add(_meshNode);

      var animations = _meshNode.Mesh.Animations;
      var loopingAnimation = new AnimationClip<SkeletonPose>(animations.Values.First())
      {
        LoopBehavior = LoopBehavior.Cycle,
        Duration = TimeSpan.MaxValue,
      };
      AnimationService.StartAnimation(loopingAnimation, (IAnimatableProperty)_meshNode.SkeletonPose);

      // Create a ragdoll for the Dude model.
      _ragdoll = new Ragdoll();
      DudeRagdollCreator.Create(_meshNode.SkeletonPose, _ragdoll, Simulation, 0.571f);

      // Set the world space pose of the whole ragdoll. 
      _ragdoll.Pose = _meshNode.PoseWorld;
      // And copy the bone poses of the current skeleton pose.
      _ragdoll.UpdateBodiesFromSkeleton(_meshNode.SkeletonPose);

      foreach (var body in _ragdoll.Bodies)
      {
        if (body != null)
        {
          // Set all bodies to kinematic - they should not be affected by forces.
          body.MotionType = MotionType.Kinematic;

          // Disable collision response.
          body.CollisionResponseEnabled = false;
        }
      }

      // In this sample, we do not need joints, limits or motors.
      _ragdoll.DisableJoints();
      _ragdoll.DisableLimits();
      _ragdoll.DisableMotors();

      // Add ragdoll rigid bodies to the simulation.
      _ragdoll.AddToSimulation(Simulation);
    }
예제 #14
0
    // OnLoad() is called when the GameObject is added to the IGameObjectService.
    protected override void OnLoad()
    {
      var graphicsService = _services.GetInstance<IGraphicsService>();
      var gameObjectService = _services.GetInstance<IGameObjectService>();
      var content = _services.GetInstance<ContentManager>();

      // Check if the game object manager has another ProceduralObject instance.
      var otherProceduralObject = gameObjectService.Objects
                                                   .OfType<ProceduralObject>()
                                                   .FirstOrDefault(o => o != this);
      Mesh mesh;
      if (otherProceduralObject != null)
      {
        // This ProceduralObject is not the first. We re-use rigid body data and 
        // the mesh from the existing instance.
        var otherBody = otherProceduralObject._rigidBody;
        _rigidBody = new RigidBody(otherBody.Shape, otherBody.MassFrame, otherBody.Material);
        mesh = otherProceduralObject._meshNode.Mesh;
      }
      else
      {
        // This is the first ProceduralObject instance. 
        // Create a a new rigid body.
        var shape = new MinkowskiSumShape(new GeometricObject(new SphereShape(0.05f)), new GeometricObject(new BoxShape(0.5f, 0.5f, 0.5f)));
        _rigidBody = new RigidBody(shape);

        // Create a new mesh. See SampleHelper.CreateMesh for more details.
        mesh = SampleHelper.CreateMesh(content, graphicsService, _rigidBody.Shape);
        mesh.Name = "ProceduralObject";
      }

      // Create a scene graph node for the mesh.
      _meshNode = new MeshNode(mesh);

      // Set a random pose.
      var randomPosition = new Vector3F(
        RandomHelper.Random.NextFloat(-10, 10),
        RandomHelper.Random.NextFloat(2, 5),
        RandomHelper.Random.NextFloat(-20, 0));
      _rigidBody.Pose = new Pose(randomPosition, RandomHelper.Random.NextQuaternionF());
      _meshNode.PoseWorld = _rigidBody.Pose;

      // Add mesh node to scene graph.
      var scene = _services.GetInstance<IScene>();
      scene.Children.Add(_meshNode);

      // Add rigid body to the physics simulation.
      var simulation = _services.GetInstance<Simulation>();
      simulation.RigidBodies.Add(_rigidBody);
    }
예제 #15
0
    public CompressionSample(Microsoft.Xna.Framework.Game game)
      : base(game)
    {
      var modelNode = ContentManager.Load<ModelNode>("Dude/Dude");
      SampleHelper.EnablePerPixelLighting(modelNode);

      _meshNodeUncompressed = modelNode.GetSubtree().OfType<MeshNode>().First().Clone();
      _meshNodeUncompressed.PoseLocal = new Pose(new Vector3F(-0.5f, 0, 0), Matrix33F.CreateRotationY(ConstantsF.Pi));
      GraphicsScreen.Scene.Children.Add(_meshNodeUncompressed);

      _meshNodeCompressed = _meshNodeUncompressed.Clone();
      _meshNodeCompressed.PoseLocal = new Pose(new Vector3F(0.5f, 0, 0), Matrix33F.CreateRotationY(ConstantsF.Pi));
      GraphicsScreen.Scene.Children.Add(_meshNodeCompressed);

      Dictionary<string, SkeletonKeyFrameAnimation> animations = _meshNodeUncompressed.Mesh.Animations;
      _animation = animations.Values.First();
      
      RestartAnimations();
    }
예제 #16
0
    public CharacterCrossFadeSample(Microsoft.Xna.Framework.Game game)
      : base(game)
    {
      var modelNode = ContentManager.Load<ModelNode>("Marine/PlayerMarine");
      _meshNode = modelNode.GetSubtree().OfType<MeshNode>().First().Clone();
      SampleHelper.EnablePerPixelLighting(_meshNode);
      GraphicsScreen.Scene.Children.Add(_meshNode);

      Dictionary<string, SkeletonKeyFrameAnimation> animations = _meshNode.Mesh.Animations;

      // Create a looping 'Idle' animation.
      _idleAnimation = new AnimationClip<SkeletonPose>(animations["Idle"])
      {
        LoopBehavior = LoopBehavior.Cycle,
        Duration = TimeSpan.MaxValue,
      };

      // Create a looping 'Run' animation.
      _runAnimation = new AnimationClip<SkeletonPose>(animations["Run"])
      {
        LoopBehavior = LoopBehavior.Cycle,
        Duration = TimeSpan.MaxValue,
      };

      // Combine the 'Aim' and 'Shoot' animation. The 'Aim' animation should start immediately. 
      // The 'Shoot' animation should start after 0.3 seconds.
      // (Animations can be combined by creating timeline groups. All timelines/animations 
      // in a timeline group are played simultaneously. AnimationClips can be used to 
      // arrange animations on a timeline. The property Delay, for example, can be used to
      // set the begin time.)
      _aimAndShootAnimation = new TimelineGroup();
      _aimAndShootAnimation.Add(animations["Aim"]);
      _aimAndShootAnimation.Add(new AnimationClip<SkeletonPose>(animations["Shoot"]) { Delay = TimeSpan.FromSeconds(0.3) });

      // Start 'Idle' animation. We use a Replace transition with a fade-in.
      _idleAnimationController = AnimationService.StartAnimation(
        _idleAnimation,
        (IAnimatableProperty)_meshNode.SkeletonPose,
        AnimationTransitions.Replace(TimeSpan.FromSeconds(0.5)));

      _idleAnimationController.AutoRecycle();
    }
예제 #17
0
    public AutoRagdollShapesSample(Microsoft.Xna.Framework.Game game)
      : base(game)
    {
      var modelNode = ContentManager.Load<ModelNode>("Dude/Dude");
      _meshNode = modelNode.GetSubtree().OfType<MeshNode>().First().Clone();
      _meshNode.PoseLocal = new Pose(new Vector3F(0, 0, 0), Matrix33F.CreateRotationY(ConstantsF.Pi));
      SampleHelper.EnablePerPixelLighting(_meshNode);
      GraphicsScreen.Scene.Children.Add(_meshNode);

      var animations = _meshNode.Mesh.Animations;
      var loopingAnimation = new AnimationClip<SkeletonPose>(animations.Values.First())
      {
        LoopBehavior = LoopBehavior.Cycle,
        Duration = TimeSpan.MaxValue,
      };
      var animationController = AnimationService.StartAnimation(loopingAnimation, (IAnimatableProperty)_meshNode.SkeletonPose);
      animationController.AutoRecycle();
      animationController.UpdateAndApply();

      // Create a ragdoll for the Dude model.
      _ragdoll = CreateRagdoll(_meshNode);

      // Set the world space pose of the whole ragdoll. 
      _ragdoll.Pose = _meshNode.PoseWorld;
      // And copy the bone poses of the current skeleton pose.
      _ragdoll.UpdateBodiesFromSkeleton(_meshNode.SkeletonPose);

      foreach (var body in _ragdoll.Bodies)
      {
        if (body != null)
        {
          // Set all bodies to kinematic - they should not be affected by forces.
          body.MotionType = MotionType.Kinematic;

          // Disable collision response.
          body.CollisionResponseEnabled = false;
        }
      }

      // Add ragdoll rigid bodies to the simulation.
      _ragdoll.AddToSimulation(Simulation);
    }
예제 #18
0
    public AvatarAttachmentSample(Microsoft.Xna.Framework.Game game)
      : base(game)
    {
      SampleFramework.IsMouseVisible = false;

      // This sample uses Scene and MeshRenderer for rendering the attached models.
      _scene = new Scene();
      _meshRenderer = new MeshRenderer();

      // Add a custom game object which controls the camera.
      _cameraObject = new CameraObject(Services);
      _cameraObject.ResetPose(new Vector3F(0, 1, -3), ConstantsF.Pi, 0);
      GameObjectService.Objects.Add(_cameraObject);

      // Create a random avatar.
      _avatarDescription = AvatarDescription.CreateRandom();
      _avatarRenderer = new AvatarRenderer(_avatarDescription);

      // Load walk animation using the content pipeline.
      TimelineGroup animation = ContentManager.Load<TimelineGroup>("XboxAvatars/Walk");

      // Create a looping walk animation.
      _walkAnimation = new TimelineClip(animation)
      {
        LoopBehavior = LoopBehavior.Cycle,  // Cycle Walk animation...
        Duration = TimeSpan.MaxValue,       // ...forever.
      };

      var baseballBatModelNode = ContentManager.Load<ModelNode>("XboxAvatars/BaseballBat").Clone();
      _baseballBatMeshNode = baseballBatModelNode.GetChildren().OfType<MeshNode>().First();

      // If we only render the baseball bat, it appears black. We need to add it to
      // a scene with some lights. (The lights do not affect the avatar.)
      SceneSample.InitializeDefaultXnaLights(_scene);

      // We must detach the mesh node from its current parent (the model node) before
      // we can add it to the scene.
      _baseballBatMeshNode.Parent.Children.Remove(_baseballBatMeshNode);
      _scene.Children.Add(_baseballBatMeshNode);
    }
예제 #19
0
    public JacobianTransposeIKSample(Microsoft.Xna.Framework.Game game)
      : base(game)
    {
      var modelNode = ContentManager.Load<ModelNode>("Dude/Dude");
      _meshNode = modelNode.GetSubtree().OfType<MeshNode>().First().Clone();
      _meshNode.PoseLocal = new Pose(new Vector3F(0, 0, 0));
      SampleHelper.EnablePerPixelLighting(_meshNode);
      GraphicsScreen.Scene.Children.Add(_meshNode);

      // Create the IK solver. The JacobianTranspose method can solve long bone chains with 
      // limits. It allocates heap memory as is not recommended for performance critical 
      // console or phone games.
      _ikSolver = new JacobianTransposeIKSolver
      {
        SkeletonPose = _meshNode.SkeletonPose,

        // The chain starts at the upper arm.
        RootBoneIndex = 13,

        // The chain ends at the hand bone.
        TipBoneIndex = 15,

        // The offset from the hand center to the hand origin.
        TipOffset = new Vector3F(0.1f, 0, 0),

        // This solver uses an iterative method and will make up to 100 iterations if necessary.
        NumberOfIterations = 100,

        // This parameter must be hand-tuned. Make it too large and the solver is unstable.
        // Make it too low and the solver needs a crazy amount of iterations.
        StepSize = 1,

        // A method that applies bone limits.
        LimitBoneTransforms = LimitBoneTransform,
      };
    }
예제 #20
0
    private void InitializeModels()
    {
      var contentManager = Services.GetInstance<ContentManager>();

      var dudeModelNode = contentManager.Load<ModelNode>("Dude/Dude");
      _meshNodeA = dudeModelNode.GetSubtree().OfType<MeshNode>().First().Clone();
      _meshNodeA.PoseLocal = new Pose(new Vector3F(0, 0, 0));
      SampleHelper.EnablePerPixelLighting(_meshNodeA);
      GraphicsScreen.Scene.Children.Add(_meshNodeA);

      var marineModelNode = contentManager.Load<ModelNode>("Marine/PlayerMarine");
      _meshNodeB = marineModelNode.GetSubtree().OfType<MeshNode>().First().Clone();
      _meshNodeB.PoseLocal = new Pose(new Vector3F(0, 0, 0));
      SampleHelper.EnablePerPixelLighting(_meshNodeB);
      GraphicsScreen.Scene.Children.Add(_meshNodeB);
    }
예제 #21
0
    private void InitializeModelAndRagdoll()
    {
      // Load Dude model.
      var contentManager = Services.GetInstance<ContentManager>();
      var dudeModelNode = contentManager.Load<ModelNode>("Dude/Dude");
      _meshNode = dudeModelNode.GetSubtree().OfType<MeshNode>().First().Clone();
      _meshNode.PoseLocal = new Pose(new Vector3F(0, 0, 0));
      SampleHelper.EnablePerPixelLighting(_meshNode);
      GraphicsScreen.Scene.Children.Add(_meshNode);

      // Create a ragdoll for the Dude model.
      _ragdoll = new Ragdoll();
      DudeRagdollCreator.Create(_meshNode.SkeletonPose, _ragdoll, Simulation, 0.571f);

      // Set the world space pose of the whole ragdoll. And copy the bone poses of the
      // current skeleton pose.
      _ragdoll.Pose = _meshNode.PoseWorld;
      _ragdoll.UpdateBodiesFromSkeleton(_meshNode.SkeletonPose);

      // Disable sleeping.
      foreach (var body in _ragdoll.Bodies)
      {
        if (body != null)
        {
          body.CanSleep = false;
          //body.CollisionResponseEnabled = false;
        }
      }

      // The pelvis bone (index 1) is updated directly from the Kinect hip center.
      _ragdoll.Bodies[1].MotionType = MotionType.Kinematic;

      // In this sample we use a passive ragdoll where we need joints to hold the
      // limbs together and limits to restrict angular movement.
      _ragdoll.EnableJoints();
      _ragdoll.EnableLimits();

      // Set all motors to constraint motors that only use damping. This adds a damping
      // effect to all ragdoll limbs.
      foreach (RagdollMotor motor in _ragdoll.Motors)
      {
        if (motor != null)
        {
          motor.Mode = RagdollMotorMode.Constraint;
          motor.ConstraintDamping = 100;
          motor.ConstraintSpring = 0;
        }
      }
      _ragdoll.EnableMotors();

      // Add rigid bodies and the constraints of the ragdoll to the simulation.
      _ragdoll.AddToSimulation(Simulation);
    }
예제 #22
0
    // Creates a test scene with a lot of randomly placed objects.
    internal static void CreateScene(ServiceContainer services, ContentManager content, DeferredGraphicsScreen graphicsScreen)
    {
      var gameObjectService = services.GetInstance<IGameObjectService>();
      var graphicsService = services.GetInstance<IGraphicsService>();

      gameObjectService.Objects.Add(new DynamicSkyObject(services, true, false, true)
      {
        EnableAmbientLight = false, // Disable ambient light of sky to make shadows more visible.
        EnableCloudShadows = false
      });

      gameObjectService.Objects.Add(new GroundObject(services));
      gameObjectService.Objects.Add(new DynamicObject(services, 1));
      gameObjectService.Objects.Add(new DynamicObject(services, 2));
      gameObjectService.Objects.Add(new DynamicObject(services, 3));
      gameObjectService.Objects.Add(new DynamicObject(services, 5));
      gameObjectService.Objects.Add(new DynamicObject(services, 6));
      gameObjectService.Objects.Add(new DynamicObject(services, 7));
      gameObjectService.Objects.Add(new ObjectCreatorObject(services));
      gameObjectService.Objects.Add(new LavaBallsObject(services));

      var random = new Random();

      // Spheres
      var sphereMesh = SampleHelper.CreateMesh(content, graphicsService, new SphereShape(1));
      for (int i = 0; i < 100; i++)
      {
        Vector3F position = new Vector3F(random.NextFloat(-100, 100), random.NextFloat(0, 3), random.NextFloat(-100, 100));
        float scale = random.NextFloat(0.5f, 3f);
        var meshNode = new MeshNode(sphereMesh)
        {
          PoseLocal = new Pose(position),
          ScaleLocal = new Vector3F(scale),
          IsStatic = true,
        };
        graphicsScreen.Scene.Children.Add(meshNode);
      }

      // Boxes
      var boxMesh = SampleHelper.CreateMesh(content, graphicsService, new BoxShape(1, 1, 1));
      for (int i = 0; i < 100; i++)
      {
        Vector3F position = new Vector3F(random.NextFloat(-100, 100), random.NextFloat(0, 3), random.NextFloat(-100, 100));
        QuaternionF orientation = random.NextQuaternionF();
        Vector3F scale = random.NextVector3F(0.1f, 4f);
        var meshNode = new MeshNode(boxMesh)
        {
          PoseLocal = new Pose(position, orientation),
          ScaleLocal = scale,
          IsStatic = true,
        };
        graphicsScreen.Scene.Children.Add(meshNode);
      }

      // Height field with smooth hills.
      var numberOfSamplesX = 20;
      var numberOfSamplesZ = 20;
      var samples = new float[numberOfSamplesX * numberOfSamplesZ];
      for (int z = 0; z < numberOfSamplesZ; z++)
      {
        for (int x = 0; x < numberOfSamplesX; x++)
        {
          if (x == 0 || z == 0 || x == 19 || z == 19)
          {
            // Set this boundary elements to a low height, so that the height field is connected
            // to the ground.
            samples[z * numberOfSamplesX + x] = -1;
          }
          else
          {
            // A sine/cosine function that creates some interesting waves.
            samples[z * numberOfSamplesX + x] = 1 + (float)(Math.Cos(z / 2f) * Math.Sin(x / 2f) * 1);
          }
        }
      }
      var heightField = new HeightField(0, 0, 20, 20, samples, numberOfSamplesX, numberOfSamplesZ);
      var heightFieldMesh = SampleHelper.CreateMesh(content, graphicsService, heightField);
      var heightFieldMeshNode = new MeshNode(heightFieldMesh)
      {
        PoseLocal = new Pose(new Vector3F(20, 0, -20)),
        ScaleLocal = new Vector3F(1, 2, 1),
        IsStatic = true,
      };
      graphicsScreen.Scene.Children.Add(heightFieldMeshNode);

      // Dudes.
      for (int i = 0; i < 10; i++)
      {
        Vector3F position = new Vector3F(random.NextFloat(-20, 20), 0, random.NextFloat(-20, 20));
        Matrix33F orientation = Matrix33F.CreateRotationY(random.NextFloat(0, ConstantsF.TwoPi));
        gameObjectService.Objects.Add(new DudeObject(services) { Pose = new Pose(position, orientation) });
      }

      // Palm trees.
      for (int i = 0; i < 100; i++)
      {
        Vector3F position = new Vector3F(random.NextFloat(-80, 80), 0, random.NextFloat(-100, 100));
        Matrix33F orientation = Matrix33F.CreateRotationY(random.NextFloat(0, ConstantsF.TwoPi));
        float scale = random.NextFloat(0.5f, 1.2f);
        gameObjectService.Objects.Add(new StaticObject(services, "PalmTree/palm_tree", scale, new Pose(position, orientation)));
      }

      // Rocks
      for (int i = 0; i < 100; i++)
      {
        Vector3F position = new Vector3F(random.NextFloat(-80, 80), 1, random.NextFloat(-100, 100));
        QuaternionF orientation = RandomHelper.Random.NextQuaternionF();
        float scale = random.NextFloat(0.5f, 1.2f);
        gameObjectService.Objects.Add(new StaticObject(services, "Rock/rock_05", scale, new Pose(position, orientation)));
      }

      // Grass
      for (int i = 0; i < 100; i++)
      {
        Vector3F position = new Vector3F(random.NextFloat(-20, 20), 0, random.NextFloat(-20, 20));
        Matrix33F orientation = Matrix33F.CreateRotationY(random.NextFloat(0, ConstantsF.TwoPi));
        float scale = random.NextFloat(0.5f, 1.2f);
        gameObjectService.Objects.Add(new StaticObject(services, "Grass/Grass", scale, new Pose(position, orientation)));
      }

      // More plants
      for (int i = 0; i < 100; i++)
      {
        Vector3F position = new Vector3F(random.NextFloat(-20, 20), 0, random.NextFloat(-20, 20));
        Matrix33F orientation = Matrix33F.CreateRotationY(random.NextFloat(0, ConstantsF.TwoPi));
        float scale = random.NextFloat(0.5f, 1.2f);
        gameObjectService.Objects.Add(new StaticObject(services, "Parviflora/Parviflora", scale, new Pose(position, orientation)));
      }

      // "Skyscrapers"
      for (int i = 0; i < 20; i++)
      {
        Vector3F position = new Vector3F(random.NextFloat(90, 100), 0, random.NextFloat(-100, 100));
        Matrix33F orientation = Matrix33F.CreateRotationY(random.NextFloat(0, ConstantsF.TwoPi));
        Vector3F scale = new Vector3F(random.NextFloat(6, 20), random.NextFloat(10, 100), random.NextFloat(6, 20));
        var meshNode = new MeshNode(boxMesh)
        {
          PoseLocal = new Pose(position, orientation),
          ScaleLocal = scale,
          IsStatic = true,
          UserFlags = 1, // Mark the distant huge objects. Used in render callbacks in the CompositeShadowSample.
        };
        graphicsScreen.Scene.Children.Add(meshNode);
      }

      // "Hills"
      for (int i = 0; i < 20; i++)
      {
        Vector3F position = new Vector3F(random.NextFloat(-90, -100), 0, random.NextFloat(-100, 100));
        Vector3F scale = new Vector3F(random.NextFloat(10, 20), random.NextFloat(10, 30), random.NextFloat(10, 20));
        var meshNode = new MeshNode(sphereMesh)
        {
          PoseLocal = new Pose(position),
          ScaleLocal = scale,
          IsStatic = true,
          UserFlags = 1, // Mark the distant huge objects. Used in render callbacks in the CompositeShadowSample.
        };
        graphicsScreen.Scene.Children.Add(meshNode);
      }
    }
예제 #23
0
    private static void SetReflectionEffectParameters(MeshNode meshNode, PlanarReflectionNode planarReflectionNode)
    {
      // Loop through the materials of the mesh. The material uses the effect 
      // GroundReflective/MaterialReflective.fx.
      foreach (var materialInstance in meshNode.MaterialInstances)
      {
        // Get effect binding for the "Material" render pass. (Not the "GBuffer" or other passes.)
        var effectBinding = materialInstance["Material"];

        // Set reflection texture and size parameters.
        var texture = (Texture2D)planarReflectionNode.RenderToTexture.Texture;
        effectBinding.Set<Texture>("ReflectionTexture", texture);
        effectBinding.Set<Vector2>("ReflectionTextureSize", new Vector2(texture.Width, texture.Height));

        // The reflection texture matrix and the reflection normal may change over
        // time. Therefore, we need to set a delegate that updates the value once
        // per frame.
        effectBinding.Set<Matrix>("ReflectionMatrix", (binding, context) => (Matrix)planarReflectionNode.RenderToTexture.TextureMatrix);
        effectBinding.Set<Vector3>("ReflectionNormal", (binding, context) => (Vector3)planarReflectionNode.NormalWorld);
      }
    }
예제 #24
0
    private Ragdoll CreateRagdoll(MeshNode meshNode)
    {
      var mesh = meshNode.Mesh;
      var skeleton = mesh.Skeleton;

      // Extract the vertices from the mesh sorted per bone.
      var verticesPerBone = new List<Vector3F>[skeleton.NumberOfBones];
      // Also get the AABB of the model.
      Aabb? aabb = null;
      foreach (var submesh in mesh.Submeshes)
      {
        // Get vertex element info.
        var vertexDeclaration = submesh.VertexBuffer.VertexDeclaration;
        var vertexElements = vertexDeclaration.GetVertexElements();

        // Get the vertex positions.
        var positionElement = vertexElements.First(e => e.VertexElementUsage == VertexElementUsage.Position);
        if (positionElement.VertexElementFormat != VertexElementFormat.Vector3)
          throw new NotSupportedException("For vertex positions only VertexElementFormat.Vector3 is supported.");
        var positions = new Vector3[submesh.VertexCount];
        submesh.VertexBuffer.GetData(
          submesh.StartVertex * vertexDeclaration.VertexStride + positionElement.Offset,
          positions,
          0,
          submesh.VertexCount,
          vertexDeclaration.VertexStride);

        // Get the bone indices.
        var boneIndexElement = vertexElements.First(e => e.VertexElementUsage == VertexElementUsage.BlendIndices);
        if (boneIndexElement.VertexElementFormat != VertexElementFormat.Byte4)
          throw new NotSupportedException();
        var boneIndicesArray = new Byte4[submesh.VertexCount];
        submesh.VertexBuffer.GetData(
          submesh.StartVertex * vertexDeclaration.VertexStride + boneIndexElement.Offset,
          boneIndicesArray,
          0,
          submesh.VertexCount,
          vertexDeclaration.VertexStride);

        // Get the bone weights.
        var boneWeightElement = vertexElements.First(e => e.VertexElementUsage == VertexElementUsage.BlendWeight);
        if (boneWeightElement.VertexElementFormat != VertexElementFormat.Vector4)
          throw new NotSupportedException();
        var boneWeightsArray = new Vector4[submesh.VertexCount];
        submesh.VertexBuffer.GetData(
          submesh.StartVertex * vertexDeclaration.VertexStride + boneWeightElement.Offset,
          boneWeightsArray,
          0,
          submesh.VertexCount,
          vertexDeclaration.VertexStride);

        // Sort the vertices per bone. 
        for (int i = 0; i < submesh.VertexCount; i++)
        {
          var vertex = (Vector3F)positions[i];

          // Here, we only check the first bone index. We could also check the
          // bone weights to add the vertex to all bone vertex lists where the 
          // weight is high...
          Vector4 boneIndices = boneIndicesArray[i].ToVector4();
          //Vector4 boneWeights = boneWeightsArray[i];
          int boneIndex = (int)boneIndices.X;
          if (verticesPerBone[boneIndex] == null)
            verticesPerBone[boneIndex] = new List<Vector3F>();
          verticesPerBone[boneIndex].Add(vertex);

          // Add vertex to AABB.
          if (aabb == null)
            aabb = new Aabb(vertex, vertex);
          else
            aabb.Value.Grow(vertex);
        }
      }

      // We create a body for each bone with vertices.
      int numberOfBodies = verticesPerBone.Count(vertices => vertices != null);

      // We use the same mass properties for all bodies. This is not realistic but more stable 
      // because large mass differences or thin bodies (arms!) are less stable.
      // We use the mass properties of sphere proportional to the size of the model.
      const float totalMass = 80;     // The total mass of the ragdoll.
      var massFrame = MassFrame.FromShapeAndMass(new SphereShape(aabb.Value.Extent.Y / 8), Vector3F.One, totalMass / numberOfBodies, 0.1f, 1);

      var material = new UniformMaterial();

      Ragdoll ragdoll = new Ragdoll();
      for (int boneIndex = 0; boneIndex < skeleton.NumberOfBones; boneIndex++)
      {
        var boneVertices = verticesPerBone[boneIndex];
        if (boneVertices != null)
        {
          var bindPoseInverse = (Pose)skeleton.GetBindPoseAbsoluteInverse(boneIndex);

          // Compute bounding capsule.
          //float radius;
          //float height;
          //Pose pose;
          //GeometryHelper.ComputeBoundingCapsule(boneVertices, out radius, out height, out pose);
          //Shape shape = new TransformedShape(new GeometricObject(new CapsuleShape(radius, height), pose));

          // Compute convex hull.
          var points = GeometryHelper.CreateConvexHull(boneVertices, 32, 0).ToTriangleMesh().Vertices;
          Shape shape = new ConvexHullOfPoints(points.Count > 0 ? points : boneVertices);

          ragdoll.Bodies.Add(new RigidBody(shape, massFrame, material));
          ragdoll.BodyOffsets.Add(bindPoseInverse);
        }
        else
        {
          ragdoll.Bodies.Add(null);
          ragdoll.BodyOffsets.Add(Pose.Identity);
        }
      }

      return ragdoll;
    }
예제 #25
0
    public ActiveRagdollSample(Microsoft.Xna.Framework.Game game)
      : base(game)
    {
      GraphicsScreen.DrawReticle = true;

      // Add game objects which allow to shoot balls and grab rigid bodies.
      _ballShooterObject = new BallShooterObject(Services) { Speed = 10 };
      GameObjectService.Objects.Add(_ballShooterObject);
      _grabObject = new GrabObject(Services);
      GameObjectService.Objects.Add(_grabObject);

      var modelNode = ContentManager.Load<ModelNode>("Dude/Dude");
      _meshNode = modelNode.GetSubtree().OfType<MeshNode>().First().Clone();
      _meshNode.PoseLocal = new Pose(new Vector3F(0, 0, 0));
      SampleHelper.EnablePerPixelLighting(_meshNode);
      GraphicsScreen.Scene.Children.Add(_meshNode);

      // Create a copy of the dude's skeleton.
      _targetSkeletonPose = SkeletonPose.Create(_meshNode.Mesh.Skeleton);

      // Animate the _targetSkeletonPose.
      var animations = _meshNode.Mesh.Animations;
      var loopingAnimation = new AnimationClip<SkeletonPose>(animations.Values.First())
      {
        LoopBehavior = LoopBehavior.Cycle,
        Duration = TimeSpan.MaxValue,
      };
      AnimationService.StartAnimation(loopingAnimation, (IAnimatableProperty)_targetSkeletonPose);

      // Create a ragdoll for the Dude model.
      _ragdoll = new Ragdoll();
      DudeRagdollCreator.Create(_targetSkeletonPose, _ragdoll, Simulation, 0.571f);

      // Set the world space pose of the whole ragdoll. And copy the bone poses of the
      // current skeleton pose.
      _ragdoll.Pose = _meshNode.PoseWorld;
      _ragdoll.UpdateBodiesFromSkeleton(_targetSkeletonPose);

      // In this sample we use an active ragdoll. We need joints because constraint ragdoll
      // motors only affect the body rotations.
      _ragdoll.EnableJoints();

      // We disable limits. If limits are enabled, the ragdoll could get unstable if 
      // the animation tries to move a limb beyond an allowed limit. (This happens if
      // a pose in the animation violates one of our limits.)
      _ragdoll.DisableLimits();

      // Set all motors to constraint motors. Constraint motors are like springs that
      // rotate the limbs to a target position.
      foreach (RagdollMotor motor in _ragdoll.Motors)
      {
        if (motor != null)
        {
          motor.Mode = RagdollMotorMode.Constraint;
          motor.ConstraintDamping = 10000;
          motor.ConstraintSpring = 100000;
        }
      }
      _ragdoll.EnableMotors();

      // Add rigid bodies and the constraints of the ragdoll to the simulation.
      _ragdoll.AddToSimulation(Simulation);

      // Add a rigid body.
      var box = new RigidBody(new BoxShape(0.4f, 0.4f, 0.4f))
      {
        Name = "Box",
        Pose = new Pose(new Vector3F(0, 3, 0)),
      };
      Simulation.RigidBodies.Add(box);
    }
예제 #26
0
    public LookAtIKSample(Microsoft.Xna.Framework.Game game)
      : base(game)
    {
      var modelNode = ContentManager.Load<ModelNode>("Dude/Dude");
      _meshNode = modelNode.GetSubtree().OfType<MeshNode>().First().Clone();
      _meshNode.PoseLocal = new Pose(new Vector3F(0, 0, 0), Matrix33F.CreateRotationY(ConstantsF.Pi));
      SampleHelper.EnablePerPixelLighting(_meshNode);
      GraphicsScreen.Scene.Children.Add(_meshNode);

      var animations = _meshNode.Mesh.Animations;
      var loopingAnimation = new AnimationClip<SkeletonPose>(animations.Values.First())
      {
        LoopBehavior = LoopBehavior.Cycle,
        Duration = TimeSpan.MaxValue,
      };
      AnimationService.StartAnimation(loopingAnimation, (IAnimatableProperty)_meshNode.SkeletonPose);

      // Create LookAtIKSolvers for some spine bones, the neck and the head.

      _spine1IK = new LookAtIKSolver
      {
        SkeletonPose = _meshNode.SkeletonPose,
        BoneIndex = 3,

        // The bone space axis that points in look direction.
        Forward = Vector3F.UnitY,

        // The bone space axis that points in up direction
        Up = Vector3F.UnitX,

        // An arbitrary rotation limit.
        Limit = ConstantsF.PiOver4,

        // We use a weight of 1 for the head, and lower weights for all other bones. Thus, most
        // of the looking will be done by the head bone, and the influence on the other bones is
        // smaller.
        Weight = 0.2f,

        // It is important to set the EyeOffsets. If we do not set EyeOffsets, the IK solver 
        // assumes that the eyes are positioned in the origin of the bone. 
        // Approximate EyeOffsets are sufficient.
        EyeOffset = new Vector3F(0.8f, 0, 0),
      };

      _spine2IK = new LookAtIKSolver
      {
        SkeletonPose = _meshNode.SkeletonPose,
        BoneIndex = 4,
        Forward = Vector3F.UnitY,
        Up = Vector3F.UnitX,
        Limit = ConstantsF.PiOver4,
        Weight = 0.2f,
        EyeOffset = new Vector3F(0.64f, 0, 0),
      };

      _spine3IK = new LookAtIKSolver
      {
        SkeletonPose = _meshNode.SkeletonPose,
        BoneIndex = 5,
        Forward = Vector3F.UnitY,
        Up = Vector3F.UnitX,
        Limit = ConstantsF.PiOver4,
        Weight = 0.3f,
        EyeOffset = new Vector3F(0.48f, 0, 0),
      };

      _neckIK = new LookAtIKSolver
      {
        SkeletonPose = _meshNode.SkeletonPose,
        BoneIndex = 6,
        Forward = Vector3F.UnitY,
        Up = Vector3F.UnitX,
        Limit = ConstantsF.PiOver4,
        Weight = 0.4f,
        EyeOffset = new Vector3F(0.32f, 0, 0),
      };

      _headIK = new LookAtIKSolver
      {
        SkeletonPose = _meshNode.SkeletonPose,
        BoneIndex = 7,
        Forward = Vector3F.UnitY,
        Up = Vector3F.UnitX,
        EyeOffset = new Vector3F(0.16f, 0.16f, 0),
        Weight = 1.0f,
        Limit = ConstantsF.PiOver4,
      };
    }
예제 #27
0
    public KinematicRagdollSample(Microsoft.Xna.Framework.Game game)
      : base(game)
    {
      GraphicsScreen.DrawReticle = true;

      // Add game objects which allow to shoot balls and grab rigid bodies.
      _ballShooterObject = new BallShooterObject(Services) { Speed = 10 };
      GameObjectService.Objects.Add(_ballShooterObject);
      _grabObject = new GrabObject(Services);
      GameObjectService.Objects.Add(_grabObject);

      var modelNode = ContentManager.Load<ModelNode>("Dude/Dude");
      _meshNode = modelNode.GetSubtree().OfType<MeshNode>().First().Clone();
      _meshNode.PoseLocal = new Pose(new Vector3F(0, 0, 0), Matrix33F.CreateRotationY(ConstantsF.Pi));
      SampleHelper.EnablePerPixelLighting(_meshNode);
      GraphicsScreen.Scene.Children.Add(_meshNode);

      var animations = _meshNode.Mesh.Animations;
      var loopingAnimation = new AnimationClip<SkeletonPose>(animations.Values.First())
      {
        LoopBehavior = LoopBehavior.Cycle,
        Duration = TimeSpan.MaxValue,
      };
      var animationController = AnimationService.StartAnimation(loopingAnimation, (IAnimatableProperty)_meshNode.SkeletonPose);
      animationController.UpdateAndApply();

      // Create a ragdoll for the Dude model.
      _ragdoll = new Ragdoll();
      DudeRagdollCreator.Create(_meshNode.SkeletonPose, _ragdoll, Simulation, 0.571f);

      // Set the world space pose of the whole ragdoll. And copy the bone poses of the
      // current skeleton pose.
      _ragdoll.Pose = _meshNode.PoseWorld;
      _ragdoll.UpdateBodiesFromSkeleton(_meshNode.SkeletonPose);

      // Set all bodies to kinematic -  they should not be affected by forces.
      foreach (var body in _ragdoll.Bodies)
      {
        if (body != null)
        {
          body.MotionType = MotionType.Kinematic;
        }
      }

      // Set all motors to velocity motors. Velocity motors change RigidBody.LinearVelocity
      // RigidBody.AngularVelocity to move the rigid bodies. 
      foreach (RagdollMotor motor in _ragdoll.Motors)
      {
        if (motor != null)
        {
          motor.Mode = RagdollMotorMode.Velocity;
        }
      }
      _ragdoll.EnableMotors();

      // In this sample, we do not need joints or limits.
      _ragdoll.DisableJoints();
      _ragdoll.DisableLimits();

      // Add ragdoll rigid bodies to the simulation.
      _ragdoll.AddToSimulation(Simulation);

      // Add a rigid body.
      var box = new RigidBody(new BoxShape(0.4f, 0.4f, 0.4f))
      {
        Name = "Box",
        Pose = new Pose(new Vector3F(0, 3, 0)),
      };
      Simulation.RigidBodies.Add(box);
    }
예제 #28
0
    public ParallaxMappingSample(Microsoft.Xna.Framework.Game game)
      : base(game)
    {
      SampleFramework.IsMouseVisible = false;

      _graphicsScreen = new DeferredGraphicsScreen(Services);
      _graphicsScreen.DrawReticle = true;
      GraphicsService.Screens.Insert(0, _graphicsScreen);
      GameObjectService.Objects.Add(new DeferredGraphicsOptionsObject(Services));

      Services.Register(typeof(DebugRenderer), null, _graphicsScreen.DebugRenderer);
      Services.Register(typeof(IScene), null, _graphicsScreen.Scene);

      // Add gravity and damping to the physics Simulation.
      Simulation.ForceEffects.Add(new Gravity());
      Simulation.ForceEffects.Add(new Damping());

      // Add a custom game object which controls the camera.
      var cameraGameObject = new CameraObject(Services);
      GameObjectService.Objects.Add(cameraGameObject);
      _graphicsScreen.ActiveCameraNode = cameraGameObject.CameraNode;

      GameObjectService.Objects.Add(new GrabObject(Services));
      GameObjectService.Objects.Add(new ObjectCreatorObject(Services));
      GameObjectService.Objects.Add(new DynamicSkyObject(Services, false, false, true));
      GameObjectService.Objects.Add(new DynamicObject(Services, 1));
      GameObjectService.Objects.Add(new DynamicObject(Services, 1));
      GameObjectService.Objects.Add(new DynamicObject(Services, 1));
      GameObjectService.Objects.Add(new DynamicObject(Services, 2));
      GameObjectService.Objects.Add(new DynamicObject(Services, 2));
      GameObjectService.Objects.Add(new DynamicObject(Services, 2));

      // Add a few palm trees.
      Random random = new Random(12345);
      for (int i = 0; i < 10; i++)
      {
        Vector3F position = new Vector3F(random.NextFloat(-3, -8), 0, random.NextFloat(0, -5));
        Matrix33F orientation = Matrix33F.CreateRotationY(random.NextFloat(0, ConstantsF.TwoPi));
        float scale = random.NextFloat(0.5f, 1.2f);
        GameObjectService.Objects.Add(new StaticObject(Services, "PalmTree/palm_tree", scale, new Pose(position, orientation)));
      }

      // Load ground model which uses normal mapping.
      var modelNode = ContentManager.Load<ModelNode>("Parallax/Ground");
      _meshNode = modelNode.Children.OfType<MeshNode>().First().Clone();
      _meshNode.ScaleLocal = new Vector3F(0.1f);
      _meshNode.IsStatic = true;

      Debug.Assert(_meshNode.Mesh.Materials.Count == 1, "Mesh should have only one material.");

      // Load materials with normal mapping, parallax mapping and parallax occlusion mapping.
      _normalMaterial = ContentManager.Load<Material>("Parallax/Normal").Clone();
      _parallaxMappingMaterial = ContentManager.Load<Material>("Parallax/PM").Clone();
      _parallaxOcclusionMappingMaterial = ContentManager.Load<Material>("Parallax/POM").Clone();

      // Get default values from materials.
      var parameterBindings = _parallaxOcclusionMappingMaterial["Material"].ParameterBindings;
      _heightScale = ((ConstParameterBinding<float>)parameterBindings["HeightScale"]).Value;
      _heightBias = ((ConstParameterBinding<float>)parameterBindings["HeightBias"]).Value;
      _lodThreshold = ((ConstParameterBinding<int>)parameterBindings["LodThreshold"]).Value;
      _maxSamples = ((ConstParameterBinding<int>)parameterBindings["MaxSamples"]).Value;
      _shadowStrength = ((ConstParameterBinding<float>)parameterBindings["ShadowStrength"]).Value;

      // Start test with POM material.
      _currentMaterialIndex = 2;
      UpdateMesh();

      // Add nodes to scene graph.
      _graphicsScreen.Scene.Children.Add(_meshNode);

      // Create rigid body for ground plane.
      Simulation.RigidBodies.Add(new RigidBody(new PlaneShape(Vector3F.UnitY, 0))
      {
        MotionType = MotionType.Static,
      });
    }
예제 #29
0
    // Checks if an effect of the uses the "SourceTexture" effect parameter.
    // This method assumes that the parameter "SourceTexture" is a "global" parameter
    // which means that it is stored with the effect (not in the Materials and not
    // in the MaterialInstances). 
    // TODO: To improve performance, make this check only once and store a flag in the
    // SceneNode.UserFlags.
    private bool RequiresSourceTexture(MeshNode meshNode, RenderContext context)
    {
      foreach (var material in meshNode.Mesh.Materials)
      {
        EffectBinding effectBinding;
        if (material.TryGet(context.RenderPass, out effectBinding))
        {
          var effect = material[context.RenderPass].Effect;
          var parameterBindings = effect.GetParameterBindings();
          foreach (var binding in parameterBindings)
            if (binding.Description.Semantic == DefaultEffectParameterSemantics.SourceTexture)
              return true;
        }
      }

      return false;
    }
예제 #30
0
    internal static void CorrectWorldSpacePose(MeshNode meshNode, Ragdoll ragdoll)
    {
      // Notes:
      // The Ragdoll class is simply a container for rigid bodies, joints, limits, motors, etc.
      // It has a Ragdoll.Pose property that determines the world space pose of the model.
      // The Ragdoll class does not update this property. It only reads it.
      // Let's say the ragdoll and model are created at the world space origin. Then the user
      // grabs the ragdoll and throws it 100 units away. Then the Ragdoll.Pose (and the root bone)
      // is still at the origin and the first body (the pelvis) is 100 units away. 
      // You can observe this if you comment out this method and look at the debug rendering of 
      // the skeleton.
      // To avoid this we correct the Ragdoll.Pose and make sure that it is always near the 
      // pelvis bone.

      int pelvis = meshNode.SkeletonPose.Skeleton.GetIndex("Pelvis");
      SrtTransform pelvisBindPoseAbsoluteInverse = meshNode.SkeletonPose.Skeleton.GetBindPoseAbsoluteInverse(pelvis);
      ragdoll.Pose = ragdoll.Bodies[pelvis].Pose * ragdoll.BodyOffsets[pelvis].Inverse * (Pose)pelvisBindPoseAbsoluteInverse;
      meshNode.PoseWorld = ragdoll.Pose;
    }