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