public SmokeSample(Microsoft.Xna.Framework.Game game) : base(game) { // Create a single particle system and add it multiple times to the scene // graph ("instancing"). By default, all instances look identical. The // properties ParticleSystemNode.Color/Alpha/AngleOffset can be used to // render the particles with some variations. _particleSystem = Smoke.Create(ContentManager); ParticleSystemService.ParticleSystems.Add(_particleSystem); _particleSystemNode0 = new ParticleSystemNode(_particleSystem); GraphicsScreen.Scene.Children.Add(_particleSystemNode0); _particleSystemNode1 = new ParticleSystemNode(_particleSystem); _particleSystemNode1.PoseWorld = new Pose(new Vector3F(5, 0, -5)); _particleSystemNode1.Color = new Vector3F(0.9f, 0.8f, 0.7f); _particleSystemNode1.Alpha = 0.8f; _particleSystemNode1.AngleOffset = 0.3f; GraphicsScreen.Scene.Children.Add(_particleSystemNode1); _particleSystemNode2 = new ParticleSystemNode(_particleSystem); _particleSystemNode2.PoseWorld = new Pose(new Vector3F(-10, 5, -5), Matrix33F.CreateRotationZ(-ConstantsF.PiOver2)); _particleSystemNode2.Color = new Vector3F(0.5f, 0.5f, 0.5f); _particleSystemNode2.AngleOffset = 0.6f; GraphicsScreen.Scene.Children.Add(_particleSystemNode2); }
public CollisionDetectionSample(Microsoft.Xna.Framework.Game game) : base(game) { SampleFramework.IsMouseVisible = false; GraphicsScreen.ClearBackground = true; GraphicsScreen.BackgroundColor = Color.CornflowerBlue; SetCamera(new Vector3F(0, 1, 10), 0, 0); // ----- Initialize collision detection and create objects. // Create a geometric object with a box shape. // Position it on the left with an arbitrary rotation. var geometricObjectA = new GeometricObject( new BoxShape(1, 2, 3), new Pose(new Vector3F(-2, -1, 0), Matrix33F.CreateRotationZ(0.1f))); // Create a geometric object with a capsule shape. // Position it on the right with an arbitrary rotation. var geometricObjectB = new GeometricObject( new CapsuleShape(1, 3), new Pose(new Vector3F(2, -1, 0), Matrix33F.CreateRotationZ(-0.2f))); // Create a geometric object with a complex shape that is the convex hull of // a circle and a rectangle. Position it on the top with an arbitrary rotation. // (A ConvexHullOfShapes is a collection of different shapes with different // positions and orientations. The ConvexHullOfShapes combines these shapes // into a single shape by building their convex hull.) var complexShape = new ConvexHullOfShapes(); complexShape.Children.Add(new GeometricObject(new RectangleShape(1, 1), new Pose(new Vector3F(0, 0, 1)))); complexShape.Children.Add(new GeometricObject(new CircleShape(1), new Pose(new Vector3F(0, 0, -1)))); var geometricObjectC = new GeometricObject( complexShape, new Pose(new Vector3F(0, 2, 0), QuaternionF.CreateRotation(Vector3F.UnitZ, new Vector3F(1, 1, 1)))); // Create collision objects for the geometric objects. // (A collision object is just a wrapper around the geometric object that // stores additional information that is required by the collision detection.) _collisionObjectA = new CollisionObject(geometricObjectA); _collisionObjectB = new CollisionObject(geometricObjectB); _collisionObjectC = new CollisionObject(geometricObjectC); // Create a collision detection. // (The CollisionDetection stores general parameters and it can be used to // perform closest-point and contact queries.) _collisionDetection = new CollisionDetection(); // Create a new collision domain and add the collision objects. // (A CollisionDomain manages multiple collision objects. It improves the // performance of contact queries by reusing results of the last frame.) _domain = new CollisionDomain(_collisionDetection); _domain.CollisionObjects.Add(_collisionObjectA); _domain.CollisionObjects.Add(_collisionObjectB); _domain.CollisionObjects.Add(_collisionObjectC); }
public void CreateRotationZ() { float angle = (float)MathHelper.ToRadians(30); Matrix33F m = Matrix33F.CreateRotationZ(angle); Assert.IsTrue(Vector3F.AreNumericallyEqual(new Vector3F((float)Math.Cos(angle), (float)Math.Sin(angle), 0), m * Vector3F.UnitX)); QuaternionF q = QuaternionF.CreateRotation(Vector3F.UnitZ, angle); Assert.IsTrue(Vector3F.AreNumericallyEqual(q.Rotate(Vector3F.One), m * Vector3F.One)); Assert.IsTrue(Matrix33F.AreNumericallyEqual(Matrix33F.CreateRotation(Vector3F.UnitZ, angle), m)); }
/// <summary> /// Adds test objects (walls, palm trees, ...) to the scene. /// </summary> private void AddTestObjects() { // Add a few palm trees. Random random = new Random(12345); for (int i = 0; i < 10; i++) { Vector3F position = new Vector3F(3.5f, 0, 2.5f - i / 2.0f); Matrix33F orientation = Matrix33F.CreateRotationY(random.NextFloat(0, ConstantsF.TwoPi)); float scale = random.NextFloat(0.5f, 1.2f); Pose pose = _globalRotation * new Pose(position, orientation); GameObjectService.Objects.Add(new StaticObject(Services, "PalmTree/palm_tree", scale, pose)); } // Add a vertical concrete wall. GameObjectService.Objects.Add( new StaticObject( Services, "Building/concrete_small_window_1", #if XNA new Vector3F(1.0f, 1.6f, 1.8f), _globalRotation * new Pose(new Vector3F(3.5f, 1.8f, -4f), Matrix33F.CreateRotationY(0)), #else new Vector3F(1.8f, 1.6f, 1.0f), _globalRotation * new Pose(new Vector3F(3.5f, 1.8f, -4f), Matrix33F.CreateRotationY(ConstantsF.PiOver2)), #endif true, false)); // Add a vertical brick wall. GameObjectService.Objects.Add( new StaticObject( Services, "Building/wall_brick_1", new Vector3F(1.8f, 1.6f, 1), _globalRotation * new Pose(new Vector3F(-3f, 1.8f, -4f), Matrix33F.CreateRotationY(ConstantsF.PiOver2)), true, false)); // Create a ceiling using a rotated wall. GameObjectService.Objects.Add( new StaticObject( Services, "Building/wall_brick_1", new Vector3F(1.8f, 2.8f, 1), _globalRotation * new Pose(new Vector3F(0.3f, 4, -4), Matrix33F.CreateRotationZ(ConstantsF.PiOver2) * Matrix33F.CreateRotationY(ConstantsF.PiOver2)), true, false)); }
private void UpdateEphemeris() { #if XBOX _ephemeris.Time = new DateTimeOffset(_time.Ticks, TimeSpan.Zero); #else _ephemeris.Time = _time; #endif _ephemeris.Update(); var sunDirection = (Vector3F)_ephemeris.SunDirectionRefracted; var sunUp = sunDirection.Orthonormal1; var moonDirection = (Vector3F)_ephemeris.MoonPosition.Normalized; var moonUp = (Vector3F)_ephemeris.EquatorialToWorld.TransformDirection(Vector3D.Up); #if true _starfield.PoseWorld = new Pose((Matrix33F)_ephemeris.EquatorialToWorld.Minor); _sun.LookAt((Vector3F)_ephemeris.SunDirectionRefracted, sunUp); _moon.SunDirection = (Vector3F)_ephemeris.SunPosition.Normalized; #else Vector3F sunRotationAxis = new Vector3F(0, -0.1f, 1).Normalized; float hour = (float)_time.TimeOfDay.TotalHours / 24; Matrix33F sunRotation = Matrix33F.CreateRotation(sunRotationAxis, hour * ConstantsF.TwoPi - ConstantsF.PiOver2); _starfield.Orientation = sunRotation; _sun.Direction = sunRotation * new Vector3F(1, 0, 0); _moon.SunDirection = _sun.Direction; #endif _milkyWaySkybox.PoseWorld = new Pose( (Matrix33F)_ephemeris.EquatorialToWorld.Minor * Matrix33F.CreateRotationZ(ConstantsF.PiOver2) * Matrix33F.CreateRotationX(ConstantsF.PiOver2)); _moon.LookAt(moonDirection, moonUp); _cieSkyFilter.SunDirection = sunDirection; _gradientSky.SunDirection = sunDirection; _gradientTextureSky.SunDirection = sunDirection; _gradientTextureSky.TimeOfDay = _time.TimeOfDay; _scatteringSky.SunDirection = sunDirection; _cloudLayerNode.SunDirection = _scatteringSky.SunDirection; _cloudLayerNode.SunLight = ChangeSaturation(_scatteringSky.GetSunlight() / 5f, 1); //_cloudPlaneRenderer.Color = new Vector4F(ChangeSaturation(_scatteringSky.GetFogColor(128), 0.9f) * 1.0f, 1); //Vector3F c = (_scatteringSky.GetFogColor(128) + _scatteringSky.GetSunlight() / 10) / 2; //_cloudPlaneRenderer.Color = new Vector4F(c, 1); _cloudLayerNode.AmbientLight = _scatteringSky.GetAmbientLight(1024) / 6f; //_cloudLayerNode.AmbientLight = _scatteringSky.GetFogColor(128) * _scatteringSky.GetAmbientLight(256).Length / 6f; }
private static Pose GetRandomPose() { // Get a random position. const float decalAreaSize = 20; var randomPosition = new Vector3F( RandomHelper.Random.NextFloat(-decalAreaSize, decalAreaSize), 0, RandomHelper.Random.NextFloat(-decalAreaSize, 0)); // Decals are project along the forward (-z) direction. // To project onto the terrain we have to point the decal down. var downOrientation = Matrix33F.CreateRotationX(-ConstantsF.PiOver2); // Get a random rotation around z. var randomOrientation = Matrix33F.CreateRotationZ(RandomHelper.Random.NextFloat(0, ConstantsF.TwoPi)); return(new Pose(randomPosition, downOrientation * randomOrientation)); }
/// <summary> /// Converts this render transformation to a 3x3 matrix. /// </summary> /// <returns> /// A 3x3-matrix that represents the same transformation. /// </returns> public Matrix33F ToMatrix33F() { Matrix33F t = new Matrix33F(1, 0, Translation.X, 0, 1, Translation.Y, 0, 0, 1); Matrix33F o = new Matrix33F(1, 0, Origin.X, 0, 1, Origin.Y, 0, 0, 1); Matrix33F s = new Matrix33F(Scale.X, 0, 0, 0, Scale.Y, 0, 0, 0, 1); Matrix33F r = Matrix33F.CreateRotationZ(Rotation); Matrix33F minusO = new Matrix33F(1, 0, -Origin.X, 0, 1, -Origin.Y, 0, 0, 1); return(t * o * r * s * minusO); }
public ContinuousCollisionDetectionSample(Microsoft.Xna.Framework.Game game) : base(game) { GraphicsScreen.ClearBackground = true; SetCamera(new Vector3F(0, 1, 10), 0, 0); // ----- Initialize collision detection and create objects. // Create a geometric object with a capsule shape. // Position it on the top with an arbitrary rotation. _startPoseA = new Pose(new Vector3F(0, 2, 0), Matrix33F.CreateRotationZ(0.1f)); var geometricObjectA = new GeometricObject(new CapsuleShape(0.2f, 1), _startPoseA); _collisionObjectA = new CollisionObject(geometricObjectA); // Object A moves to the bottom of the screen. _targetPoseA = new Pose(new Vector3F(0, -2, 0), Matrix33F.CreateRotationZ(0.63f)); // Create a geometric object with a composite shape. // Position it on the left with an arbitrary rotation. _startPoseB = new Pose(new Vector3F(-3, -1, 0), Matrix33F.CreateRotationZ(0.2f)); var composite = new CompositeShape(); composite.Children.Add(new GeometricObject(new BoxShape(0.1f, 1, 0.1f), new Pose(new Vector3F(-0.75f, 0.5f, -0.5f)))); composite.Children.Add(new GeometricObject(new BoxShape(0.1f, 1, 0.1f), new Pose(new Vector3F(0.75f, 0.5f, -0.5f)))); composite.Children.Add(new GeometricObject(new BoxShape(0.1f, 1, 0.1f), new Pose(new Vector3F(-0.75f, 0.5f, 0.5f)))); composite.Children.Add(new GeometricObject(new BoxShape(0.1f, 1, 0.1f), new Pose(new Vector3F(0.75f, 0.5f, 0.5f)))); composite.Children.Add(new GeometricObject(new BoxShape(1.8f, 0.1f, 1.1f), new Pose(new Vector3F(0, 1f, 0)))); var geometricObjectB = new GeometricObject(composite, _startPoseB); // Object B moves to the left of the screen. _targetPoseB = new Pose(new Vector3F(3, -1, 0), Matrix33F.CreateRotationZ(0.3f)); // Create collision objects for the geometric objects. // (A collision object is just a wrapper around the geometric object that stores additional // information that is required by the collision detection.) _collisionObjectA = new CollisionObject(geometricObjectA); _collisionObjectB = new CollisionObject(geometricObjectB); // Create a collision detection. // (The CollisionDetection stores general parameters and it can be used to perform // closest-point and contact queries.) _collisionDetection = new CollisionDetection(); }
public CustomSceneNodeSample(Microsoft.Xna.Framework.Game game) : base(game) { SampleFramework.IsMouseVisible = false; var delegateGraphicsScreen = new DelegateGraphicsScreen(GraphicsService) { RenderCallback = Render, }; GraphicsService.Screens.Insert(0, delegateGraphicsScreen); // Add a custom game object which controls the camera. _cameraObject = new CameraObject(Services); GameObjectService.Objects.Add(_cameraObject); // Create a new empty scene. _scene = new Scene(); // Add the camera node to the scene. _scene.Children.Add(_cameraObject.CameraNode); // Add a few TextNodes. Position them along a circle. for (int i = 0; i < 36; i++) { Vector3F position = Matrix33F.CreateRotationZ(MathHelper.ToRadians((float)i * 10)) * new Vector3F(1, 0, 0); var textNode = new TextNode { PoseLocal = new Pose(position), Color = Color.Yellow, Text = i.ToString() }; _scene.Children.Add(textNode); } // Initialize the TextRenderer. var spriteFont = UIContentManager.Load <SpriteFont>("UI Themes/BlendBlue/Default"); _textRenderer = new TextRenderer(GraphicsService, spriteFont); // For debugging: _debugRenderer = new DebugRenderer(GraphicsService, spriteFont); }
public ConstraintCarSample(Microsoft.Xna.Framework.Game game) : base(game) { // Add basic force effects. Simulation.ForceEffects.Add(new Gravity()); Simulation.ForceEffects.Add(new Damping()); // Create a material with high friction - this will be used for the ground and the wheels // to give the wheels some traction. UniformMaterial roughMaterial = new UniformMaterial { DynamicFriction = 1, StaticFriction = 1, }; // Add a ground plane. RigidBody groundPlane = new RigidBody(new PlaneShape(Vector3F.UnitY, 0), null, roughMaterial) { MotionType = MotionType.Static, }; Simulation.RigidBodies.Add(groundPlane); // Now, we build a car out of one box for the chassis and 4 cylindric wheels. // Front wheels are fixed with Hinge2Joints and motorized with AngularVelocityMotors. // Back wheels are fixed with HingeJoints and not motorized. - This creates a sloppy // car configuration. Please note that cars for racing games are not normally built with // simple constraints - nevertheless, it is funny to do and play with it. // Check out the "Vehicle Sample" (not included in this project)! The "Vehicle Sample" // provides a robust ray-car implementation.) // ----- Chassis BoxShape chassisShape = new BoxShape(1.7f, 1, 4f); MassFrame chassisMass = MassFrame.FromShapeAndDensity(chassisShape, Vector3F.One, 200, 0.01f, 3); // Here is a trick: The car topples over very easily. By lowering the center of mass we // make it more stable. chassisMass.Pose = new Pose(new Vector3F(0, -1, 0)); RigidBody chassis = new RigidBody(chassisShape, chassisMass, null) { Pose = new Pose(new Vector3F(0, 1, 0)), }; Simulation.RigidBodies.Add(chassis); // ------ Wheels CylinderShape cylinderShape = new CylinderShape(0.4f, 0.3f); MassFrame wheelMass = MassFrame.FromShapeAndDensity(cylinderShape, Vector3F.One, 500, 0.01f, 3); RigidBody wheelFrontLeft = new RigidBody(cylinderShape, wheelMass, roughMaterial) { Pose = new Pose(new Vector3F(0, 1, 0), Matrix33F.CreateRotationZ(ConstantsF.PiOver2)), }; Simulation.RigidBodies.Add(wheelFrontLeft); RigidBody wheelFrontRight = new RigidBody(cylinderShape, wheelMass, roughMaterial) { Pose = new Pose(new Vector3F(0, 1, 0), Matrix33F.CreateRotationZ(ConstantsF.PiOver2)), }; Simulation.RigidBodies.Add(wheelFrontRight); RigidBody wheelBackLeft = new RigidBody(cylinderShape, wheelMass, roughMaterial) { Pose = new Pose(new Vector3F(0, 1, 0), Matrix33F.CreateRotationZ(ConstantsF.PiOver2)), }; Simulation.RigidBodies.Add(wheelBackLeft); RigidBody wheelBackRight = new RigidBody(cylinderShape, wheelMass, roughMaterial) { Pose = new Pose(new Vector3F(0, 1, 0), Matrix33F.CreateRotationZ(ConstantsF.PiOver2)), }; Simulation.RigidBodies.Add(wheelBackRight); // ----- Hinge2Joints for the front wheels. // A Hinge2Joint allows a limited rotation on the first constraint axis - the steering // axis. The second constraint axis is locked and the third constraint axis is the // rotation axis of the wheels. _frontLeftHinge = new Hinge2Joint { BodyA = chassis, // --> To define the constraint anchor orientation for the chassis: // The columns are the axes. We set the local y axis in the first column. This is // steering axis. In the last column we set the -x axis. This is the wheel rotation axis. // In the middle column is a vector that is normal to the first and last axis. // (All three columns are orthonormal and form a valid rotation matrix.) AnchorPoseALocal = new Pose(new Vector3F(-0.9f, -0.4f, -1.4f), new Matrix33F(0, 0, -1, 1, 0, 0, 0, -1, 0)), BodyB = wheelFrontLeft, // --> To define the constraint anchor orientation for the chassis: // The columns are the axes. We set the local x axis in the first column. This is // steering axis. In the last column we set the y axis. This is the wheel rotation axis. // (In local space of a cylinder the cylinder axis is the +y axis.) // In the middle column is a vector that is normal to the first and last axis. // (All three columns are orthonormal and form a valid rotation matrix.) AnchorPoseBLocal = new Pose(new Matrix33F(1, 0, 0, 0, 0, 1, 0, -1, 0)), CollisionEnabled = false, Minimum = new Vector2F(-0.7f, float.NegativeInfinity), Maximum = new Vector2F(0.7f, float.PositiveInfinity), }; Simulation.Constraints.Add(_frontLeftHinge); _frontRightHinge = new Hinge2Joint { BodyA = chassis, BodyB = wheelFrontRight, AnchorPoseALocal = new Pose(new Vector3F(0.9f, -0.4f, -1.4f), new Matrix33F(0, 0, -1, 1, 0, 0, 0, -1, 0)), AnchorPoseBLocal = new Pose(new Matrix33F(1, 0, 0, 0, 0, 1, 0, -1, 0)), CollisionEnabled = false, Minimum = new Vector2F(-0.7f, float.NegativeInfinity), Maximum = new Vector2F(0.7f, float.PositiveInfinity), }; Simulation.Constraints.Add(_frontRightHinge); // ----- HingeJoints for the back wheels. // Hinges allow free rotation on the first constraint axis. HingeJoint backLeftHinge = new HingeJoint { BodyA = chassis, AnchorPoseALocal = new Pose(new Vector3F(-0.9f, -0.4f, 1.4f)), BodyB = wheelBackLeft, // --> To define the constraint anchor orientation: // The columns are the axes. We set the local y axis in the first column. This is // cylinder axis and should be the hinge axis. In the other two columns we set two // orthonormal vectors. // (All three columns are orthonormal and form a valid rotation matrix.) AnchorPoseBLocal = new Pose(new Matrix33F(0, 0, 1, 1, 0, 0, 0, 1, 0)), CollisionEnabled = false, }; Simulation.Constraints.Add(backLeftHinge); HingeJoint backRightHinge = new HingeJoint { BodyA = chassis, AnchorPoseALocal = new Pose(new Vector3F(0.9f, -0.4f, 1.4f)), BodyB = wheelBackRight, AnchorPoseBLocal = new Pose(new Matrix33F(0, 0, 1, 1, 0, 0, 0, 1, 0)), CollisionEnabled = false, }; Simulation.Constraints.Add(backRightHinge); // ----- Motors for the front wheels. // (Motor axes and target velocities are set in Update() below.) _frontLeftMotor = new AngularVelocityMotor { BodyA = chassis, BodyB = wheelFrontLeft, CollisionEnabled = false, // We use "single axis mode", which means the motor drives only on axis and does not // block motion orthogonal to this axis. - Rotation about the orthogonal axes is already // controlled by the Hinge2Joint. UseSingleAxisMode = true, // The motor has only limited power: MaxForce = 50000, }; Simulation.Constraints.Add(_frontLeftMotor); _frontRightMotor = new AngularVelocityMotor { BodyA = chassis, BodyB = wheelFrontRight, CollisionEnabled = false, UseSingleAxisMode = true, MaxForce = 50000, }; Simulation.Constraints.Add(_frontRightMotor); // ----- Drop a few boxes to create obstacles. BoxShape boxShape = new BoxShape(1, 1, 1); MassFrame boxMass = MassFrame.FromShapeAndDensity(boxShape, Vector3F.One, 100, 0.01f, 3); for (int i = 0; i < 20; i++) { Vector3F position = RandomHelper.Random.NextVector3F(-20, 20); position.Y = 5; QuaternionF orientation = RandomHelper.Random.NextQuaternionF(); RigidBody body = new RigidBody(boxShape, boxMass, null) { Pose = new Pose(position, orientation), }; Simulation.RigidBodies.Add(body); } }
private void UpdateSky() { // Update ephemeris model. #if XBOX _ephemeris.Time = new DateTimeOffset(_time.Ticks, TimeSpan.Zero); #else _ephemeris.Time = _time; #endif _ephemeris.Update(); // Update rotation of milky way. We also need to add an offset because the // cube map texture is rotated. _milkyWayNode.PoseWorld = new Pose( (Matrix33F)_ephemeris.EquatorialToWorld.Minor * Matrix33F.CreateRotationZ(ConstantsF.PiOver2 + -0.004f) * Matrix33F.CreateRotationX(ConstantsF.PiOver2 + -0.002f)); // Update rotation of stars. _starfieldNode.PoseWorld = new Pose((Matrix33F)_ephemeris.EquatorialToWorld.Minor); // Update direction of sun. SunDirection = (Vector3F)_ephemeris.SunDirectionRefracted; var sunUp = SunDirection.Orthonormal1; _sunNode.LookAt(SunDirection, sunUp); // Update direction of moon. var moonDirection = (Vector3F)_ephemeris.MoonPosition.Normalized; var moonUp = (Vector3F)_ephemeris.EquatorialToWorld.TransformDirection(Vector3D.Up); _moonNode.LookAt(moonDirection, moonUp); // The moon needs to know the sun position and brightness to compute the moon phase. _moonNode.SunDirection = (Vector3F)_ephemeris.SunPosition.Normalized; _moonNode.SunLight = Ephemeris.ExtraterrestrialSunlight * SunlightScale; // The ScatteringSky needs the sun direction and brightness to compute the sky colors. _scatteringSkyNode.SunDirection = SunDirection; _scatteringSkyNode.SunColor = Ephemeris.ExtraterrestrialSunlight * ScatteringSkyLightScale; // Update the light directions. _sunlightNode.LookAt(-SunDirection, sunUp); _moonlightNode.LookAt(-moonDirection, moonUp); // The ScatteringSkyNode can compute the actual sunlight. SunLight = _scatteringSkyNode.GetSunlight(); // Undo the ScatteringSkyLightScale and apply a custom scale for the sunlight. SunLight = SunLight / ScatteringSkyLightScale * SunlightScale; // The ScatteringSkyNode can also compute the ambient light by sampling the // sky hemisphere. AmbientLight = _scatteringSkyNode.GetAmbientLight(256); AmbientLight = AmbientLight / ScatteringSkyLightScale * SunlightScale; // Desaturate the ambient light to avoid very blue shadows. AmbientLight = InterpolationHelper.Lerp( new Vector3F(Vector3F.Dot(AmbientLight, GraphicsHelper.LuminanceWeights)), AmbientLight, 0.5f); // The Ephemeris model can compute the actual moonlight. Vector3F moonlight, moonAmbient; Ephemeris.GetMoonlight( _scatteringSkyNode.ObserverAltitude, 2.2f, _ephemeris.MoonPosition, (float)_ephemeris.MoonPhaseAngle, out moonlight, out moonAmbient); moonlight *= MoonlightScale; moonAmbient *= MoonlightScale; // Scale sun light to 0 at horizon. var directionalLightColor = SunLight; directionalLightColor *= MathHelper.Clamp(SunDirection.Y / 0.1f, 0, 1); var directionalLight = ((DirectionalLight)_sunlightNode.Light); directionalLight.Color = directionalLightColor; ((DirectionalLight)_moonlightNode.Light).Color = moonlight; ((AmbientLight)_ambientLightNode.Light).Color = AmbientLight + moonAmbient + LightPollution; // Use the sunlight color to create a bright sun disk. var sunDiskColor = SunLight; sunDiskColor.TryNormalize(); _sunNode.GlowColor0 = sunDiskColor * Ephemeris.ExtraterrestrialSunlight.Length * SunlightScale * 10; if (_enableClouds) { // Update lighting info of cloud layer nodes. _cloudLayerNode0.SunDirection = SunDirection; _cloudLayerNode0.SunLight = SunLight; _cloudLayerNode0.AmbientLight = AmbientLight; // The second cloud layer uses simple unlit clouds (only ambient lighting). _cloudLayerNode1.SunDirection = SunDirection; _cloudLayerNode1.SunLight = Vector3F.Zero; _cloudLayerNode1.AmbientLight = AmbientLight + SunLight; // Use the cloud map as the texture for the directional light to create cloud shadows. if (EnableCloudShadows) { directionalLight.Texture = _cloudLayerNode0.CloudMap.Texture; } else { directionalLight.Texture = null; } // Compute a texture offset so that the current sun position and the projected cloud // shadows match. // Since sky dome is always centered on the camera, position the sunlight node in // line with the camera. var cameraPosition = _cameraObject.CameraNode.PoseWorld.Position; var upVector = Vector3F.AreNumericallyEqual(SunDirection, Vector3F.UnitZ) ? Vector3F.UnitY : Vector3F.UnitZ; _sunlightNode.LookAt(cameraPosition + SunDirection, cameraPosition, upVector); // Choose a scale for the cloud shadows. directionalLight.TextureScale = new Vector2F(-1000); // Get the scaled texture offset for the sun direction. directionalLight.TextureOffset = _cloudLayerNode0.GetTextureCoordinates(SunDirection) * directionalLight.TextureScale; } // The ScatteringSkyNode can also estimate a fog color by sampling the horizon colors. Vector3F fogColor = _scatteringSkyNode.GetFogColor(256, FogSampleAngle); // Desaturate the fog color. fogColor = InterpolationHelper.Lerp( new Vector3F(Vector3F.Dot(fogColor, GraphicsHelper.LuminanceWeights)), fogColor, FogSaturation); // Find any FogNode in the scene and update its fog color. foreach (var fogNode in ((Scene)_scene).GetSubtree().OfType <FogNode>()) { var fog = fogNode.Fog; fog.Color0 = fog.Color1 = new Vector4F(fogColor, 1); fog.ScatteringSymmetry = FogScatteringSymmetry; } // TODO: If the fog is dense, reduce the direct light and increase the ambient light. }
/// <summary> /// Creates a <see cref="Ragdoll"/> for an Xbox LIVE Avatar. (Only available on Xbox 360.) /// </summary> /// <param name="skeleton">The skeleton of the Xbox LIVE Avatar.</param> /// <param name="simulation">The simulation.</param> /// <returns>The avatar ragdoll.</returns> /// <exception cref="ArgumentNullException"> /// <paramref name="skeleton"/> or <paramref name="simulation"/> is /// <see langword="null"/>. /// </exception> /// <remarks> /// This method is available only in the Xbox 360 build of the /// DigitalRune.Physics.Specialized.dll. /// </remarks> public static Ragdoll CreateAvatarRagdoll(Skeleton skeleton, Simulation simulation) { if (skeleton == null) { throw new ArgumentNullException("skeleton"); } if (simulation == null) { throw new ArgumentNullException("simulation"); } var ragdoll = new Ragdoll(); // The lists ragdoll.Bodies, ragdoll.BodyOffsets and _motors contain one entry per bone - even if there // is no RigidBody for this bone. - This wastes memory but simplifies the code. for (int i = 0; i < AvatarRenderer.BoneCount; i++) { ragdoll.Bodies.Add(null); ragdoll.BodyOffsets.Add(Pose.Identity); ragdoll.Joints.Add(null); ragdoll.Limits.Add(null); ragdoll.Motors.Add(null); } // ----- Create bodies. // We use the same mass for all bodies. This is not physically correct but it makes the // simulation more stable, for several reasons: // - It is better to avoid large mass differences. Therefore, all limbs have the same mass. // - Capsule shapes have a low inertia value about their height axis. This causes instability // and it is better to use larger inertia values. var massFrame = MassFrame.FromShapeAndMass(new SphereShape(0.2f), Vector3F.One, 4, 0.1f, 1); // Use standard material. var material = new UniformMaterial(); // Create rigid bodies for the important bones. The shapes have been manually adapted to // produce useful results for thin and overweight avatars. // Without offset, the bodies are centered at the joint. ragdoll.BodyOffsets stores an offset pose // for each body. Instead, we could use TransformedShape but we can easily handle that // ourselves. // The collar bones are special, they use dummy shapes and are only used to connect the // shoulder bones. ragdoll.Bodies[(int)AvatarBone.Root] = new RigidBody(new BoxShape(0.22f, 0.16f, 0.16f), massFrame, material); ragdoll.BodyOffsets[(int)AvatarBone.Root] = new Pose(new Vector3F(0, -0.08f, -0.01f), QuaternionF.CreateRotationX(-0.0f)); ragdoll.Bodies[(int)AvatarBone.BackLower] = new RigidBody(new BoxShape(0.22f, 0.16f, 0.16f), massFrame, material); ragdoll.BodyOffsets[(int)AvatarBone.BackLower] = new Pose(new Vector3F(0, 0.08f, -0.01f), QuaternionF.CreateRotationX(-0.0f)); ragdoll.Bodies[(int)AvatarBone.BackUpper] = new RigidBody(new BoxShape(0.22f, 0.16f, 0.16f), massFrame, material); ragdoll.BodyOffsets[(int)AvatarBone.BackUpper] = new Pose(new Vector3F(0, 0.08f, -0.01f), QuaternionF.CreateRotationX(-0.1f)); ragdoll.Bodies[(int)AvatarBone.Neck] = new RigidBody(new CapsuleShape(0.04f, 0.09f), massFrame, material); ragdoll.Bodies[(int)AvatarBone.Head] = new RigidBody(new SphereShape(0.15f), massFrame, material); ragdoll.BodyOffsets[(int)AvatarBone.Head] = new Pose(new Vector3F(0, 0.1f, 0)); ragdoll.Bodies[(int)AvatarBone.CollarLeft] = new RigidBody(Shape.Empty, massFrame, material); ragdoll.Bodies[(int)AvatarBone.CollarRight] = new RigidBody(Shape.Empty, massFrame, material); ragdoll.Bodies[(int)AvatarBone.ShoulderLeft] = new RigidBody(new CapsuleShape(0.04f, 0.25f), massFrame, material); ragdoll.BodyOffsets[(int)AvatarBone.ShoulderLeft] = new Pose(new Vector3F(0.08f, 0, -0.02f), QuaternionF.CreateRotationZ(ConstantsF.PiOver2)); ragdoll.Bodies[(int)AvatarBone.ShoulderRight] = new RigidBody(new CapsuleShape(0.04f, 0.25f), massFrame, material); ragdoll.BodyOffsets[(int)AvatarBone.ShoulderRight] = new Pose(new Vector3F(-0.08f, 0, -0.02f), QuaternionF.CreateRotationZ(ConstantsF.PiOver2)); ragdoll.Bodies[(int)AvatarBone.ElbowLeft] = new RigidBody(new CapsuleShape(0.04f, 0.21f), massFrame, material); ragdoll.BodyOffsets[(int)AvatarBone.ElbowLeft] = new Pose(new Vector3F(0.06f, 0, -0.02f), QuaternionF.CreateRotationZ(ConstantsF.PiOver2)); ragdoll.Bodies[(int)AvatarBone.ElbowRight] = new RigidBody(new CapsuleShape(0.04f, 0.21f), massFrame, material); ragdoll.BodyOffsets[(int)AvatarBone.ElbowRight] = new Pose(new Vector3F(-0.06f, 0, -0.02f), QuaternionF.CreateRotationZ(ConstantsF.PiOver2)); ragdoll.Bodies[(int)AvatarBone.WristLeft] = new RigidBody(new BoxShape(0.1f, 0.04f, 0.1f), massFrame, material); ragdoll.BodyOffsets[(int)AvatarBone.WristLeft] = new Pose(new Vector3F(0.06f, -0.02f, -0.01f), QuaternionF.CreateRotationZ(0.0f)); ragdoll.Bodies[(int)AvatarBone.WristRight] = new RigidBody(new BoxShape(0.1f, 0.04f, 0.1f), massFrame, material); ragdoll.BodyOffsets[(int)AvatarBone.WristRight] = new Pose(new Vector3F(-0.06f, -0.02f, -0.01f), QuaternionF.CreateRotationZ(0.0f)); ragdoll.Bodies[(int)AvatarBone.HipLeft] = new RigidBody(new CapsuleShape(0.06f, 0.34f), massFrame, material); ragdoll.BodyOffsets[(int)AvatarBone.HipLeft] = new Pose(new Vector3F(0, -0.14f, -0.02f), QuaternionF.CreateRotationX(0.1f)); ragdoll.Bodies[(int)AvatarBone.HipRight] = new RigidBody(new CapsuleShape(0.06f, 0.34f), massFrame, material); ragdoll.BodyOffsets[(int)AvatarBone.HipRight] = new Pose(new Vector3F(0, -0.14f, -0.02f), QuaternionF.CreateRotationX(0.1f)); ragdoll.Bodies[(int)AvatarBone.KneeLeft] = new RigidBody(new CapsuleShape(0.06f, 0.36f), massFrame, material); ragdoll.BodyOffsets[(int)AvatarBone.KneeLeft] = new Pose(new Vector3F(0, -0.18f, -0.04f), QuaternionF.CreateRotationX(0.1f)); ragdoll.Bodies[(int)AvatarBone.KneeRight] = new RigidBody(new CapsuleShape(0.06f, 0.36f), massFrame, material); ragdoll.BodyOffsets[(int)AvatarBone.KneeRight] = new Pose(new Vector3F(0, -0.18f, -0.04f), QuaternionF.CreateRotationX(0.1f)); ragdoll.Bodies[(int)AvatarBone.AnkleLeft] = new RigidBody(new BoxShape(0.1f, 0.06f, 0.22f), massFrame, material); ragdoll.BodyOffsets[(int)AvatarBone.AnkleLeft] = new Pose(new Vector3F(0, -0.07f, 0.05f), QuaternionF.CreateRotationZ(0)); ragdoll.Bodies[(int)AvatarBone.AnkleRight] = new RigidBody(new BoxShape(0.1f, 0.06f, 0.22f), massFrame, material); ragdoll.BodyOffsets[(int)AvatarBone.AnkleRight] = new Pose(new Vector3F(0, -0.07f, 0.05f), QuaternionF.CreateRotationZ(0)); // ----- Add joint constraints. const float jointErrorReduction = 0.2f; const float jointSoftness = 0.0001f; AddJoint(ragdoll, skeleton, AvatarBone.Root, AvatarBone.BackLower, jointErrorReduction, jointSoftness); AddJoint(ragdoll, skeleton, AvatarBone.BackLower, AvatarBone.BackUpper, jointErrorReduction, jointSoftness); AddJoint(ragdoll, skeleton, AvatarBone.BackUpper, AvatarBone.Neck, 0.6f, 0.000001f); AddJoint(ragdoll, skeleton, AvatarBone.Neck, AvatarBone.Head, 0.6f, 0.000001f); AddJoint(ragdoll, skeleton, AvatarBone.BackUpper, AvatarBone.CollarLeft, jointErrorReduction, jointSoftness); AddJoint(ragdoll, skeleton, AvatarBone.BackUpper, AvatarBone.CollarRight, jointErrorReduction, jointSoftness); AddJoint(ragdoll, skeleton, AvatarBone.CollarLeft, AvatarBone.ShoulderLeft, jointErrorReduction, jointSoftness); AddJoint(ragdoll, skeleton, AvatarBone.CollarRight, AvatarBone.ShoulderRight, jointErrorReduction, jointSoftness); AddJoint(ragdoll, skeleton, AvatarBone.ShoulderLeft, AvatarBone.ElbowLeft, jointErrorReduction, jointSoftness); AddJoint(ragdoll, skeleton, AvatarBone.ShoulderRight, AvatarBone.ElbowRight, jointErrorReduction, jointSoftness); AddJoint(ragdoll, skeleton, AvatarBone.ElbowLeft, AvatarBone.WristLeft, jointErrorReduction, jointSoftness); AddJoint(ragdoll, skeleton, AvatarBone.ElbowRight, AvatarBone.WristRight, jointErrorReduction, jointSoftness); AddJoint(ragdoll, skeleton, AvatarBone.Root, AvatarBone.HipLeft, jointErrorReduction, jointSoftness); AddJoint(ragdoll, skeleton, AvatarBone.Root, AvatarBone.HipRight, jointErrorReduction, jointSoftness); AddJoint(ragdoll, skeleton, AvatarBone.HipLeft, AvatarBone.KneeLeft, jointErrorReduction, jointSoftness); AddJoint(ragdoll, skeleton, AvatarBone.HipRight, AvatarBone.KneeRight, jointErrorReduction, jointSoftness); AddJoint(ragdoll, skeleton, AvatarBone.KneeLeft, AvatarBone.AnkleLeft, jointErrorReduction, jointSoftness); AddJoint(ragdoll, skeleton, AvatarBone.KneeRight, AvatarBone.AnkleRight, jointErrorReduction, jointSoftness); // ----- Add constraint limits. // We use TwistSwingLimits to define an allowed twist and swing cone for the joints. // Exceptions are the back and knees, where we use AngularLimits to create hinges. // (We could also create a hinge with a TwistSwingLimit where the twist axis is the hinge // axis and no swing is allowed - but AngularLimits create more stable hinges.) // Another exception are the collar bones joint. We use AngularLimits to disallow any // rotations. AddAngularLimit(ragdoll, skeleton, AvatarBone.Root, AvatarBone.BackLower, skeleton.GetBindPoseAbsoluteInverse((int)AvatarBone.BackLower).Rotation.Conjugated.ToRotationMatrix33(), skeleton.GetBindPoseAbsoluteInverse((int)AvatarBone.BackLower).Rotation.Conjugated.ToRotationMatrix33(), new Vector3F(-0.3f, 0, 0), new Vector3F(0.3f, 0, 0)); AddAngularLimit(ragdoll, skeleton, AvatarBone.BackLower, AvatarBone.BackUpper, skeleton.GetBindPoseAbsoluteInverse((int)AvatarBone.BackUpper).Rotation.Conjugated.ToRotationMatrix33(), skeleton.GetBindPoseAbsoluteInverse((int)AvatarBone.BackUpper).Rotation.Conjugated.ToRotationMatrix33(), new Vector3F(-0.3f, 0, 0), new Vector3F(0.4f, 0, 0)); var rotationZ90Degrees = Matrix33F.CreateRotationZ(ConstantsF.PiOver2); AddTwistSwingLimit(ragdoll, skeleton, AvatarBone.BackUpper, AvatarBone.Neck, rotationZ90Degrees, rotationZ90Degrees, new Vector3F(-0.1f, -0.3f, -0.3f), new Vector3F(+0.1f, +0.3f, +0.3f)); AddTwistSwingLimit(ragdoll, skeleton, AvatarBone.Neck, AvatarBone.Head, rotationZ90Degrees, rotationZ90Degrees, new Vector3F(-0.1f, -0.6f, -0.6f), new Vector3F(+0.1f, +0.6f, +0.6f)); AddTwistSwingLimit(ragdoll, skeleton, AvatarBone.BackUpper, AvatarBone.CollarLeft, skeleton.GetBindPoseAbsoluteInverse((int)AvatarBone.CollarLeft).Rotation.Conjugated.ToRotationMatrix33(), skeleton.GetBindPoseAbsoluteInverse((int)AvatarBone.CollarLeft).Rotation.Conjugated.ToRotationMatrix33(), new Vector3F(0), new Vector3F(0)); AddTwistSwingLimit(ragdoll, skeleton, AvatarBone.BackUpper, AvatarBone.CollarRight, skeleton.GetBindPoseAbsoluteInverse((int)AvatarBone.CollarRight).Rotation.Conjugated.ToRotationMatrix33(), skeleton.GetBindPoseAbsoluteInverse((int)AvatarBone.CollarRight).Rotation.Conjugated.ToRotationMatrix33(), new Vector3F(0), new Vector3F(0)); AddTwistSwingLimit(ragdoll, skeleton, AvatarBone.CollarLeft, AvatarBone.ShoulderLeft, Matrix33F.Identity, Matrix33F.CreateRotationY(0.7f), new Vector3F(-0.7f, -1.2f, -1.2f), new Vector3F(+0.7f, +1.2f, +1.2f)); AddTwistSwingLimit(ragdoll, skeleton, AvatarBone.CollarRight, AvatarBone.ShoulderRight, Matrix33F.Identity, Matrix33F.CreateRotationY(-0.7f), new Vector3F(-0.7f, -1.2f, -1.2f), new Vector3F(+0.7f, +1.2f, +1.2f)); AddTwistSwingLimit(ragdoll, skeleton, AvatarBone.ShoulderLeft, AvatarBone.ElbowLeft, Matrix33F.Identity, Matrix33F.CreateRotationY(1.2f), new Vector3F(-0.7f, -1.2f, -1.2f), new Vector3F(+0.7f, +1.2f, +1.2f)); AddTwistSwingLimit(ragdoll, skeleton, AvatarBone.ShoulderRight, AvatarBone.ElbowRight, Matrix33F.Identity, Matrix33F.CreateRotationY(-1.2f), new Vector3F(-0.7f, -1.2f, -1.2f), new Vector3F(+0.7f, +1.2f, +1.2f)); AddTwistSwingLimit(ragdoll, skeleton, AvatarBone.ElbowLeft, AvatarBone.WristLeft, Matrix33F.Identity, Matrix33F.Identity, new Vector3F(-0.7f, -0.7f, -0.7f), new Vector3F(+0.7f, +0.7f, +0.7f)); AddTwistSwingLimit(ragdoll, skeleton, AvatarBone.ElbowRight, AvatarBone.WristRight, Matrix33F.Identity, Matrix33F.Identity, new Vector3F(-0.7f, -0.7f, -0.7f), new Vector3F(+0.7f, +0.7f, +0.7f)); AddTwistSwingLimit(ragdoll, skeleton, AvatarBone.Root, AvatarBone.HipLeft, rotationZ90Degrees, Matrix33F.CreateRotationX(-1.2f) * Matrix33F.CreateRotationZ(ConstantsF.PiOver2 + 0.2f), new Vector3F(-0.1f, -1.5f, -0.7f), new Vector3F(+0.1f, +1.5f, +0.7f)); AddTwistSwingLimit(ragdoll, skeleton, AvatarBone.Root, AvatarBone.HipRight, rotationZ90Degrees, Matrix33F.CreateRotationX(-1.2f) * Matrix33F.CreateRotationZ(ConstantsF.PiOver2 - 0.2f), new Vector3F(-0.1f, -1.5f, -0.7f), new Vector3F(+0.1f, +1.5f, +0.7f)); AddAngularLimit(ragdoll, skeleton, AvatarBone.HipLeft, AvatarBone.KneeLeft, skeleton.GetBindPoseAbsoluteInverse((int)AvatarBone.KneeLeft).Rotation.Conjugated.ToRotationMatrix33(), skeleton.GetBindPoseAbsoluteInverse((int)AvatarBone.KneeLeft).Rotation.Conjugated.ToRotationMatrix33(), new Vector3F(0, 0, 0), new Vector3F(2.2f, 0, 0)); AddAngularLimit(ragdoll, skeleton, AvatarBone.HipRight, AvatarBone.KneeRight, skeleton.GetBindPoseAbsoluteInverse((int)AvatarBone.KneeRight).Rotation.Conjugated.ToRotationMatrix33(), skeleton.GetBindPoseAbsoluteInverse((int)AvatarBone.KneeRight).Rotation.Conjugated.ToRotationMatrix33(), new Vector3F(0, 0, 0), new Vector3F(2.2f, 0, 0)); AddTwistSwingLimit(ragdoll, skeleton, AvatarBone.KneeLeft, AvatarBone.AnkleLeft, rotationZ90Degrees, rotationZ90Degrees, new Vector3F(-0.1f, -0.7f, -0.3f), new Vector3F(+0.1f, +0.7f, +0.3f)); AddTwistSwingLimit(ragdoll, skeleton, AvatarBone.KneeRight, AvatarBone.AnkleRight, rotationZ90Degrees, rotationZ90Degrees, new Vector3F(-0.1f, -0.7f, -0.3f), new Vector3F(+0.1f, +0.7f, +0.3f)); // ----- Add motors // We use QuaternionMotors to create forces that rotate the bones into desired poses. // This can be used for damping, spring or animating the ragdoll. AddMotor(ragdoll, (AvatarBone)(-1), AvatarBone.Root); AddMotor(ragdoll, AvatarBone.Root, AvatarBone.BackLower); AddMotor(ragdoll, AvatarBone.BackLower, AvatarBone.BackUpper); AddMotor(ragdoll, AvatarBone.BackUpper, AvatarBone.Neck); AddMotor(ragdoll, AvatarBone.Neck, AvatarBone.Head); AddMotor(ragdoll, AvatarBone.BackUpper, AvatarBone.CollarLeft); AddMotor(ragdoll, AvatarBone.BackUpper, AvatarBone.CollarRight); AddMotor(ragdoll, AvatarBone.CollarLeft, AvatarBone.ShoulderLeft); AddMotor(ragdoll, AvatarBone.CollarRight, AvatarBone.ShoulderRight); AddMotor(ragdoll, AvatarBone.ShoulderLeft, AvatarBone.ElbowLeft); AddMotor(ragdoll, AvatarBone.ShoulderRight, AvatarBone.ElbowRight); AddMotor(ragdoll, AvatarBone.ElbowLeft, AvatarBone.WristLeft); AddMotor(ragdoll, AvatarBone.ElbowRight, AvatarBone.WristRight); AddMotor(ragdoll, AvatarBone.Root, AvatarBone.HipLeft); AddMotor(ragdoll, AvatarBone.Root, AvatarBone.HipRight); AddMotor(ragdoll, AvatarBone.HipLeft, AvatarBone.KneeLeft); AddMotor(ragdoll, AvatarBone.HipRight, AvatarBone.KneeRight); AddMotor(ragdoll, AvatarBone.KneeLeft, AvatarBone.AnkleLeft); AddMotor(ragdoll, AvatarBone.KneeRight, AvatarBone.AnkleRight); // ----- Set collision filters. // Collisions between connected bones have been disabled with Constraint.CollisionEnabled // = false in the joints. We need to disable a few other collisions. // Following bodies do not collide with anything. They are only used to connect other // bones. ragdoll.Bodies[(int)AvatarBone.Neck].CollisionObject.Enabled = false; ragdoll.Bodies[(int)AvatarBone.CollarLeft].CollisionObject.Enabled = false; ragdoll.Bodies[(int)AvatarBone.CollarRight].CollisionObject.Enabled = false; // We disable filters for following body pairs because they are usually penetrating each // other, which needs to be ignored. var filter = simulation.CollisionDomain.CollisionDetection.CollisionFilter as CollisionFilter; if (filter != null) { filter.Set(ragdoll.Bodies[(int)AvatarBone.BackUpper].CollisionObject, ragdoll.Bodies[(int)AvatarBone.ShoulderLeft].CollisionObject, false); filter.Set(ragdoll.Bodies[(int)AvatarBone.BackUpper].CollisionObject, ragdoll.Bodies[(int)AvatarBone.ShoulderRight].CollisionObject, false); } return(ragdoll); }
public ShapesSample(Microsoft.Xna.Framework.Game game) : base(game) { // Add basic force effects. Simulation.ForceEffects.Add(new Gravity()); Simulation.ForceEffects.Add(new Damping()); // Add a ground plane. RigidBody groundPlane = new RigidBody(new PlaneShape(Vector3F.UnitY, 0)) { Name = "GroundPlane", // Names are not required but helpful for debugging. MotionType = MotionType.Static, }; Simulation.RigidBodies.Add(groundPlane); // ----- Add a sphere. Shape sphere = new SphereShape(0.5f); Simulation.RigidBodies.Add(new RigidBody(sphere)); // ----- Add a box. BoxShape box = new BoxShape(0.5f, 0.9f, 0.7f); Simulation.RigidBodies.Add(new RigidBody(box)); // ----- Add a capsule. CapsuleShape capsule = new CapsuleShape(0.4f, 1.2f); Simulation.RigidBodies.Add(new RigidBody(capsule)); // ----- Add a cone. ConeShape cone = new ConeShape(0.5f, 1f); Simulation.RigidBodies.Add(new RigidBody(cone)); // ----- Add a cylinder. CylinderShape cylinder = new CylinderShape(0.3f, 1f); Simulation.RigidBodies.Add(new RigidBody(cylinder)); // ----- Add a convex hull of random points. ConvexHullOfPoints convexHullOfPoints = new ConvexHullOfPoints(); for (int i = 0; i < 20; i++) { convexHullOfPoints.Points.Add(RandomHelper.Random.NextVector3F(-0.5f, 0.5f)); } Simulation.RigidBodies.Add(new RigidBody(convexHullOfPoints)); // ----- Add a convex polyhedron. // (A ConvexPolyhedron is similar to the ConvexHullOfPoints. The difference is that // the points in a ConvexHullOfPoints can be changed at runtime. A ConvexPolyhedron // cannot be changed at runtime, but it is faster.) List <Vector3F> points = new List <Vector3F>(); for (int i = 0; i < 20; i++) { points.Add(RandomHelper.Random.NextVector3F(-0.7f, 0.7f)); } ConvexPolyhedron convexPolyhedron = new ConvexPolyhedron(points); Simulation.RigidBodies.Add(new RigidBody(convexPolyhedron)); // ----- Add a composite shape (a table that consists of 5 boxes). CompositeShape composite = new CompositeShape(); composite.Children.Add(new GeometricObject(new BoxShape(0.1f, 0.8f, 0.1f), new Pose(new Vector3F(-0.75f, 0.4f, -0.5f)))); composite.Children.Add(new GeometricObject(new BoxShape(0.1f, 0.8f, 0.1f), new Pose(new Vector3F(0.75f, 0.4f, -0.5f)))); composite.Children.Add(new GeometricObject(new BoxShape(0.1f, 0.8f, 0.1f), new Pose(new Vector3F(-0.75f, 0.4f, 0.5f)))); composite.Children.Add(new GeometricObject(new BoxShape(0.1f, 0.8f, 0.1f), new Pose(new Vector3F(0.75f, 0.4f, 0.5f)))); composite.Children.Add(new GeometricObject(new BoxShape(1.8f, 0.1f, 1.1f), new Pose(new Vector3F(0, 0.8f, 0)))); Simulation.RigidBodies.Add(new RigidBody(composite)); // ----- Add a convex hull of multiple shapes. ConvexHullOfShapes convexHullOfShapes = new ConvexHullOfShapes(); convexHullOfShapes.Children.Add(new GeometricObject(new CylinderShape(0.2f, 0.8f), new Pose(new Vector3F(-0.4f, 0, 0)))); convexHullOfShapes.Children.Add(new GeometricObject(new CylinderShape(0.2f, 0.8f), new Pose(new Vector3F(+0.4f, 0, 0)))); Simulation.RigidBodies.Add(new RigidBody(convexHullOfShapes)); // ----- Add the Minkowski sum of two shapes. // (The Minkowski sum is a mathematical operation that combines two shapes. // Here a circle is combined with a sphere. The result is a wheel.) MinkowskiSumShape minkowskiSum = new MinkowskiSumShape(); minkowskiSum.ObjectA = new GeometricObject(new SphereShape(0.2f), Pose.Identity); minkowskiSum.ObjectB = new GeometricObject(new CircleShape(0.5f), Pose.Identity); Simulation.RigidBodies.Add(new RigidBody(minkowskiSum)); // Create another Minkowski sum. (Here a small sphere is added to a box to create a // box with rounded corners.) minkowskiSum = new MinkowskiSumShape(); minkowskiSum.ObjectA = new GeometricObject(new SphereShape(0.1f), Pose.Identity); minkowskiSum.ObjectB = new GeometricObject(new BoxShape(0.2f, 0.5f, 0.8f), Pose.Identity); Simulation.RigidBodies.Add(new RigidBody(minkowskiSum)); // ----- Add a triangle mesh. // A triangle mesh could be loaded from a file or built from an XNA model. // Here we first create a composite shape and convert the shape into a triangle // mesh. (Any Shape in DigitalRune.Geometry can be converted to a triangle mesh.) CompositeShape dumbbell = new CompositeShape(); dumbbell.Children.Add(new GeometricObject(new SphereShape(0.4f), new Pose(new Vector3F(0.6f, 0.0f, 0.0f)))); dumbbell.Children.Add(new GeometricObject(new SphereShape(0.4f), new Pose(new Vector3F(-0.6f, 0.0f, 0.0f)))); dumbbell.Children.Add(new GeometricObject(new CylinderShape(0.1f, 0.6f), new Pose(Matrix33F.CreateRotationZ(ConstantsF.PiOver2)))); TriangleMeshShape triangleMeshShape = new TriangleMeshShape(dumbbell.GetMesh(0.01f, 2)); // Optional: We can enable "contact welding". When this flag is enabled, the triangle shape // precomputes additional internal information for the mesh. The collision detection will // be able to compute better contacts (e.g. better normal vectors at triangle edges). // Pro: Collision detection can compute better contact information. // Con: Contact welding information needs a bit of memory. And the collision detection is // a bit slower. triangleMeshShape.EnableContactWelding = true; // Optional: Assign a spatial partitioning scheme to the triangle mesh. (A spatial partition // adds an additional memory overhead, but it improves collision detection speed tremendously!) triangleMeshShape.Partition = new AabbTree <int>(); Simulation.RigidBodies.Add(new RigidBody(triangleMeshShape)); // ----- Set random positions/orientations. // (Start with the second object. The first object is the ground plane which should // not be changed.) for (int i = 1; i < Simulation.RigidBodies.Count; i++) { RigidBody body = Simulation.RigidBodies[i]; Vector3F position = RandomHelper.Random.NextVector3F(-3, 3); position.Y = 3; // Position the objects 3m above ground. QuaternionF orientation = RandomHelper.Random.NextQuaternionF(); body.Pose = new Pose(position, orientation); } }
public void Orthogonalize() { var m = Matrix33F.CreateRotationX(0.1f) * Matrix33F.CreateRotationY(20) * Matrix33F.CreateRotationZ(1000); // Introduce error. m.M01 += 0.1f; m.M22 += 0.1f; Assert.IsFalse(m.IsOrthogonal); Assert.IsFalse(m.IsRotation); m.Orthogonalize(); Assert.IsTrue(m.IsOrthogonal); Assert.IsTrue(m.IsRotation); // Orthogonalizing and orthogonal matrix does not change the matrix. var n = m; n.Orthogonalize(); Assert.IsTrue(Matrix33F.AreNumericallyEqual(m, n)); }
// Add a flower shape. private void CreateFlower() { // Define single flower petal. var petalPath = new Path2F { new PathKey2F { Parameter = 0, Interpolation = SplineInterpolation.Bezier, Point = new Vector2F(0, 0), TangentIn = new Vector2F(0, 0), TangentOut = new Vector2F(-0.2f, 0.2f) }, new PathKey2F { Parameter = 1, Interpolation = SplineInterpolation.Bezier, Point = new Vector2F(0, 1), TangentIn = new Vector2F(-0.3f, 1.1f), TangentOut = new Vector2F(0.3f, 1.1f) }, new PathKey2F { Parameter = 2, Interpolation = SplineInterpolation.Bezier, Point = new Vector2F(0, 0), TangentIn = new Vector2F(0.2f, 0.2f), TangentOut = new Vector2F(0, 0) } }; var petal = new PathFigure2F(); petal.Segments.Add(petalPath); // Duplicate and rotate flower petal several times. const int numberOfPetals = 9; var flower = new CompositeFigure(); flower.Children.Add(petal); for (int i = 1; i < numberOfPetals; i++) { var transformedPetal = new TransformedFigure(petal) { Pose = new Pose(Matrix33F.CreateRotationZ(i * ConstantsF.TwoPi / numberOfPetals)) }; flower.Children.Add(transformedPetal); } var flowerNode = new FigureNode(flower) { Name = "Flower", StrokeThickness = 2, StrokeColor = new Vector3F(1, 0.2f, 0.2f), FillColor = new Vector3F(1, 0.5f, 0.5f), FillAlpha = 1, PoseLocal = new Pose(new Vector3F(3, 1, 0)), ScaleLocal = new Vector3F(0.5f) }; _scene.Children.Add(flowerNode); }
//-------------------------------------------------------------- #region Creation & Cleanup //-------------------------------------------------------------- /// <summary> /// Initializes a new instance of the <see cref="SsaoFilter"/> class. /// </summary> /// <param name="graphicsService">The graphics service.</param> /// <exception cref="ArgumentNullException"> /// <paramref name="graphicsService"/> is <see langword="null"/>. /// </exception> public SsaoFilter(IGraphicsService graphicsService) : base(graphicsService) { _effect = GraphicsService.Content.Load <Effect>("DigitalRune/PostProcessing/SsaoFilter"); _farParameter = _effect.Parameters["Far"]; _radiusParameter = _effect.Parameters["Radius"]; _strengthParameter = _effect.Parameters["Strength"]; _maxDistancesParameter = _effect.Parameters["MaxDistances"]; _viewportSizeParameter = _effect.Parameters["ViewportSize"]; _sourceTextureParameter = _effect.Parameters["SourceTexture"]; _gBuffer0Parameter = _effect.Parameters["GBuffer0"]; _occlusionTextureParameter = _effect.Parameters["OcclusionTexture"]; _createLinesAPass = _effect.CurrentTechnique.Passes["CreateLinesA"]; _createLinesBPass = _effect.CurrentTechnique.Passes["CreateLinesB"]; _blurHorizontalPass = _effect.CurrentTechnique.Passes["BlurHorizontal"]; _blurVerticalPass = _effect.CurrentTechnique.Passes["BlurVertical"]; _combinePass = _effect.CurrentTechnique.Passes["Combine"]; _copyPass = _effect.CurrentTechnique.Passes["Copy"]; Radii = new Vector2F(0.01f, 0.02f); MaxDistances = new Vector2F(0.5f, 1.0f); Strength = 1f; NumberOfBlurPasses = 1; DownsampleFactor = 2; Quality = 2; Scale = new Vector2F(0.5f, 2f); CombineWithSource = true; _blur = new Blur(graphicsService); _blur.InitializeGaussianBlur(7, 7 / 3, true); _copyFilter = PostProcessHelper.GetCopyFilter(graphicsService); _downsampleFilter = PostProcessHelper.GetDownsampleFilter(graphicsService); Random random = new Random(123456); Vector3[] vectors = new Vector3[9]; // 16 random vectors for Crytek-style point samples. //for (int i = 0; i < vectors.Length; i++) // vectors[i] = (Vector3)random.NextQuaternionF().Rotate(Vector3F.One).Normalized; // //* random.NextFloat(0.5f, 1) // Note: StarCraft 2 uses varying length to vary the sample offset length. // We create rotated random vectors with uniform distribution in 360°. Each random vector // is further rotated with small random angle. float jitterAngle = ConstantsF.TwoPi / vectors.Length / 4; for (int i = 0; i < vectors.Length; i++) { vectors[i] = (Vector3)(Matrix33F.CreateRotationZ(ConstantsF.TwoPi * i / vectors.Length + random.NextFloat(-jitterAngle, jitterAngle)) * new Vector3F(1, 0, 0)).Normalized; } // Permute randomVectors. for (int i = 0; i < vectors.Length; i++) { MathHelper.Swap(ref vectors[i], ref vectors[random.Next(i, vectors.Length - 1)]); } // Scale random vectors. for (int i = 0; i < vectors.Length; i++) { vectors[i].Z = random.NextFloat(Scale.X, Scale.Y); } _effect.Parameters["RandomVectors"].SetValue(vectors); }
// Add a 3D coordinate cross. private void CreateGizmo(SpriteFont spriteFont) { var gizmoNode = new SceneNode { Name = "Gizmo", Children = new SceneNodeCollection(), PoseLocal = new Pose(new Vector3F(3, 2, 0)), ScaleLocal = new Vector3F(0.5f) }; // Red arrow var arrow = new PathFigure2F(); arrow.Segments.Add(new LineSegment2F { Point1 = new Vector2F(0, 0), Point2 = new Vector2F(1, 0) }); arrow.Segments.Add(new LineSegment2F { Point1 = new Vector2F(1, 0), Point2 = new Vector2F(0.9f, 0.02f) }); arrow.Segments.Add(new LineSegment2F { Point1 = new Vector2F(1, 0), Point2 = new Vector2F(0.9f, -0.02f) }); var figureNode = new FigureNode(arrow) { Name = "Gizmo X", StrokeThickness = 2, StrokeColor = new Vector3F(1, 0, 0), PoseLocal = new Pose(new Vector3F(0, 0, 0)) }; gizmoNode.Children.Add(figureNode); // Green arrow var transformedArrow = new TransformedFigure(arrow) { Pose = new Pose(Matrix33F.CreateRotationZ(MathHelper.ToRadians(90))) }; figureNode = new FigureNode(transformedArrow) { Name = "Gizmo Y", StrokeThickness = 2, StrokeColor = new Vector3F(0, 1, 0), PoseLocal = new Pose(new Vector3F(0, 0, 0)) }; gizmoNode.Children.Add(figureNode); // Blue arrow transformedArrow = new TransformedFigure(arrow) { Pose = new Pose(Matrix33F.CreateRotationY(MathHelper.ToRadians(-90))) }; figureNode = new FigureNode(transformedArrow) { Name = "Gizmo Z", StrokeThickness = 2, StrokeColor = new Vector3F(0, 0, 1), PoseLocal = new Pose(new Vector3F(0, 0, 0)) }; gizmoNode.Children.Add(figureNode); // Red arc var arc = new PathFigure2F(); arc.Segments.Add( new StrokedSegment2F( new LineSegment2F { Point1 = new Vector2F(0, 0), Point2 = new Vector2F(1, 0), }, false)); arc.Segments.Add( new ArcSegment2F { Point1 = new Vector2F(1, 0), Point2 = new Vector2F(0, 1), Radius = new Vector2F(1, 1) }); arc.Segments.Add( new StrokedSegment2F( new LineSegment2F { Point1 = new Vector2F(0, 1), Point2 = new Vector2F(0, 0), }, false)); var transformedArc = new TransformedFigure(arc) { Scale = new Vector3F(0.333f), Pose = new Pose(Matrix33F.CreateRotationY(MathHelper.ToRadians(-90))) }; figureNode = new FigureNode(transformedArc) { Name = "Gizmo YZ", StrokeThickness = 2, StrokeColor = new Vector3F(1, 0, 0), FillColor = new Vector3F(1, 0, 0), FillAlpha = 0.5f, PoseLocal = new Pose(new Vector3F(0, 0, 0)) }; gizmoNode.Children.Add(figureNode); // Green arc transformedArc = new TransformedFigure(arc) { Scale = new Vector3F(0.333f), Pose = new Pose(Matrix33F.CreateRotationX(MathHelper.ToRadians(90))) }; figureNode = new FigureNode(transformedArc) { Name = "Gizmo XZ", StrokeThickness = 2, StrokeColor = new Vector3F(0, 1, 0), FillColor = new Vector3F(0, 1, 0), FillAlpha = 0.5f, PoseLocal = new Pose(new Vector3F(0, 0, 0)) }; gizmoNode.Children.Add(figureNode); // Blue arc transformedArc = new TransformedFigure(arc) { Scale = new Vector3F(0.333f), }; figureNode = new FigureNode(transformedArc) { Name = "Gizmo XY", StrokeThickness = 2, StrokeColor = new Vector3F(0, 0, 1), FillColor = new Vector3F(0, 0, 1), FillAlpha = 0.5f, PoseLocal = new Pose(new Vector3F(0, 0, 0)) }; gizmoNode.Children.Add(figureNode); // Labels "X", "Y", "Z" var spriteNode = new SpriteNode(new TextSprite("X", spriteFont)) { Color = new Vector3F(1, 0, 0), Origin = new Vector2F(0, 1), PoseLocal = new Pose(new Vector3F(1, 0, 0)) }; gizmoNode.Children.Add(spriteNode); spriteNode = new SpriteNode(new TextSprite("Y", spriteFont)) { Color = new Vector3F(0, 1, 0), Origin = new Vector2F(0, 1), PoseLocal = new Pose(new Vector3F(0, 1, 0)) }; gizmoNode.Children.Add(spriteNode); spriteNode = new SpriteNode(new TextSprite("Z", spriteFont)) { Color = new Vector3F(0, 0, 1), Origin = new Vector2F(0, 1), PoseLocal = new Pose(new Vector3F(0, 0, 1)) }; gizmoNode.Children.Add(spriteNode); _scene.Children.Add(gizmoNode); }
public BillboardSample(Microsoft.Xna.Framework.Game game) : base(game) { _delegateGraphicsScreen = new DelegateGraphicsScreen(GraphicsService) { RenderCallback = Render, }; GraphicsService.Screens.Insert(0, _delegateGraphicsScreen); // Add a custom game object which controls the camera. _cameraObject = new CameraObject(Services); GameObjectService.Objects.Add(_cameraObject); // In this example we need three renderers: // The MeshRenderer handles MeshNodes. _meshRenderer = new MeshRenderer(); // The BillboardRenderer handles BillboardNodes and ParticleSystemNodes. _billboardRenderer = new BillboardRenderer(GraphicsService, 2048); // The DebugRenderer is used to draw text. var spriteFont = UIContentManager.Load <SpriteFont>("Default"); _debugRenderer = new DebugRenderer(GraphicsService, spriteFont); // Create a new empty scene. _scene = new Scene(); // Add the camera node to the scene. _scene.Children.Add(_cameraObject.CameraNode); // Add a few models to the scene. var sandbox = ContentManager.Load <ModelNode>("Sandbox/Sandbox").Clone(); _scene.Children.Add(sandbox); // Add some lights to the scene which have the same properties as the lights // of BasicEffect.EnableDefaultLighting(). SceneSample.InitializeDefaultXnaLights(_scene); var texture = new PackedTexture(ContentManager.Load <Texture2D>("Billboard/BillboardReference")); // ----- View plane-aligned billboards with variations. // View plane-aligned billboards are rendered parallel to the screen. // The up-axis of the BillboardNode determines the up direction of the // billboard. var pose0 = new Pose(new Vector3F(-9, 1.0f, 1.5f)); var pose1 = pose0; var billboard = new ImageBillboard(texture); var billboardNode = new BillboardNode(billboard); billboardNode.Name = "View plane-aligned\nVarying color\nVarying alpha"; billboardNode.PoseWorld = pose1; _scene.Children.Add(billboardNode); pose1.Position.Z -= 1; billboardNode = new BillboardNode(billboard); billboardNode.PoseWorld = pose1; billboardNode.Color = new Vector3F(1, 0, 0); billboardNode.Alpha = 0.9f; _scene.Children.Add(billboardNode); pose1.Position.Z -= 1; billboardNode = new BillboardNode(billboard); billboardNode.PoseWorld = pose1; billboardNode.Color = new Vector3F(0, 1, 0); billboardNode.Alpha = 0.7f; _scene.Children.Add(billboardNode); pose1.Position.Z -= 1; billboardNode = new BillboardNode(billboard); billboardNode.PoseWorld = pose1; billboardNode.Color = new Vector3F(0, 0, 1); billboardNode.Alpha = 0.3f; _scene.Children.Add(billboardNode); // ----- View plane-aligned billboards with different blend modes // blend mode = 0 ... additive blend // blend mode = 1 ... alpha blend pose0.Position.X += 2; pose1 = pose0; billboard = new ImageBillboard(texture); billboard.BlendMode = 0.0f; billboardNode = new BillboardNode(billboard); billboardNode.Name = "View plane-aligned\nVarying blend mode"; billboardNode.PoseWorld = pose1; _scene.Children.Add(billboardNode); pose1.Position.Z -= 1; billboard = new ImageBillboard(texture); billboard.BlendMode = 0.333f; billboardNode = new BillboardNode(billboard); billboardNode.PoseWorld = pose1; _scene.Children.Add(billboardNode); pose1.Position.Z -= 1; billboard = new ImageBillboard(texture); billboard.BlendMode = 0.667f; billboardNode = new BillboardNode(billboard); billboardNode.PoseWorld = pose1; _scene.Children.Add(billboardNode); pose1.Position.Z -= 1; billboard = new ImageBillboard(texture); billboard.BlendMode = 1.0f; billboardNode = new BillboardNode(billboard); billboardNode.PoseWorld = pose1; _scene.Children.Add(billboardNode); // ----- View plane-aligned billboards with alpha test pose0.Position.X += 2; pose1 = pose0; billboard = new ImageBillboard(texture); billboard.AlphaTest = 0.9f; billboardNode = new BillboardNode(billboard); billboardNode.Name = "View plane-aligned\nVarying reference alpha"; billboardNode.PoseWorld = pose1; _scene.Children.Add(billboardNode); pose1.Position.Z -= 1; billboard = new ImageBillboard(texture); billboard.AlphaTest = 0.667f; billboardNode = new BillboardNode(billboard); billboardNode.PoseWorld = pose1; _scene.Children.Add(billboardNode); pose1.Position.Z -= 1; billboard = new ImageBillboard(texture); billboard.AlphaTest = 0.333f; billboardNode = new BillboardNode(billboard); billboardNode.PoseWorld = pose1; _scene.Children.Add(billboardNode); pose1.Position.Z -= 1; billboard = new ImageBillboard(texture); billboard.AlphaTest = 0.0f; billboardNode = new BillboardNode(billboard); billboardNode.PoseWorld = pose1; _scene.Children.Add(billboardNode); // ----- View plane-aligned billboards with different scale and rotation pose0.Position.X += 2; pose1 = pose0; billboard = new ImageBillboard(texture); billboard.Orientation = BillboardOrientation.ViewPlaneAligned; billboardNode = new BillboardNode(billboard); billboardNode.Name = "View plane-aligned\nVarying scale\nVarying rotation"; billboardNode.PoseWorld = pose1; billboardNode.ScaleLocal = new Vector3F(0.4f); _scene.Children.Add(billboardNode); pose1.Position.Z -= 1; billboardNode = billboardNode.Clone(); billboardNode.Name = null; billboardNode.PoseWorld = pose1 * new Pose(Matrix33F.CreateRotationZ(MathHelper.ToRadians(-15))); billboardNode.ScaleLocal = new Vector3F(0.6f); _scene.Children.Add(billboardNode); pose1.Position.Z -= 1; billboardNode = billboardNode.Clone(); billboardNode.Name = null; billboardNode.PoseWorld = pose1 * new Pose(Matrix33F.CreateRotationZ(MathHelper.ToRadians(-30))); billboardNode.ScaleLocal = new Vector3F(0.8f); _scene.Children.Add(billboardNode); pose1.Position.Z -= 1; billboardNode = billboardNode.Clone(); billboardNode.Name = null; billboardNode.PoseWorld = pose1 * new Pose(Matrix33F.CreateRotationZ(MathHelper.ToRadians(-45))); billboardNode.ScaleLocal = new Vector3F(1.0f); _scene.Children.Add(billboardNode); // ----- Viewpoint-oriented billboards // Viewpoint-orientated billboards always face the player. (The face normal // points directly to the camera.) pose0.Position.X += 2; pose1 = pose0; billboard = new ImageBillboard(texture); billboard.Orientation = BillboardOrientation.ViewpointOriented; billboardNode = new BillboardNode(billboard); billboardNode.Name = "Viewpoint-oriented"; billboardNode.PoseWorld = pose1; _scene.Children.Add(billboardNode); pose1.Position.Z -= 1; billboardNode = new BillboardNode(billboard); billboardNode.PoseWorld = pose1; _scene.Children.Add(billboardNode); pose1.Position.Z -= 1; billboardNode = new BillboardNode(billboard); billboardNode.PoseWorld = pose1; _scene.Children.Add(billboardNode); pose1.Position.Z -= 1; billboardNode = new BillboardNode(billboard); billboardNode.PoseWorld = pose1; _scene.Children.Add(billboardNode); // ----- Screen-aligned billboards // View plane-aligned billboards and screen-aligned billboards are similar. The // billboards are rendered parallel to the screen. The orientation can be changed // by rotating the BillboardNode. The difference is that the orientation of view // plane-aligned billboards is relative to world space and the orientation of // screen-aligned billboards is relative to view space. // Screen-aligned billboards are, for example, used for text label. pose0.Position.X += 2; pose1 = pose0; billboard = new ImageBillboard(texture); billboard.Orientation = BillboardOrientation.ScreenAligned; billboardNode = new BillboardNode(billboard); billboardNode.Name = "Screen-aligned"; billboardNode.PoseWorld = pose1; _scene.Children.Add(billboardNode); pose1.Position.Z -= 1; billboardNode = new BillboardNode(billboard); billboardNode.PoseWorld = pose1; _scene.Children.Add(billboardNode); pose1.Position.Z -= 1; billboardNode = new BillboardNode(billboard); billboardNode.PoseWorld = pose1; _scene.Children.Add(billboardNode); pose1.Position.Z -= 1; billboardNode = new BillboardNode(billboard); billboardNode.PoseWorld = pose1; _scene.Children.Add(billboardNode); // ----- Axial, view plane-aligned billboards pose0.Position.X += 2; pose1 = pose0; billboard = new ImageBillboard(texture); billboard.Orientation = BillboardOrientation.AxialViewPlaneAligned; billboardNode = new BillboardNode(billboard); billboardNode.Name = "Axial, view plane-aligned"; billboardNode.PoseWorld = pose1; _scene.Children.Add(billboardNode); pose1.Position.Z -= 1; billboardNode = billboardNode.Clone(); billboardNode.Name = null; billboardNode.PoseWorld = pose1; _scene.Children.Add(billboardNode); pose1.Position.Z -= 1; billboardNode = new BillboardNode(billboard); billboardNode.PoseWorld = pose1; _scene.Children.Add(billboardNode); pose1.Position.Z -= 1; billboardNode = new BillboardNode(billboard); billboardNode.PoseWorld = pose1; _scene.Children.Add(billboardNode); // ----- Axial, viewpoint-oriented billboards pose0.Position.X += 2; pose1 = pose0; billboard = new ImageBillboard(texture); billboard.Orientation = BillboardOrientation.AxialViewpointOriented; billboardNode = new BillboardNode(billboard); billboardNode.Name = "Axial, viewpoint-oriented"; billboardNode.PoseWorld = pose1; _scene.Children.Add(billboardNode); pose1.Position.Z -= 1; billboardNode = new BillboardNode(billboard); billboardNode.PoseWorld = pose1; _scene.Children.Add(billboardNode); pose1.Position.Z -= 1; billboardNode = new BillboardNode(billboard); billboardNode.PoseWorld = pose1; _scene.Children.Add(billboardNode); pose1.Position.Z -= 1; billboardNode = new BillboardNode(billboard); billboardNode.PoseWorld = pose1; _scene.Children.Add(billboardNode); // ----- World-oriented billboards // World-oriented billboards have a fixed orientation in world space. The // orientation is determine by the BillboardNode. pose0.Position.X += 2; pose1 = pose0; pose1.Orientation *= Matrix33F.CreateRotationY(0.2f); billboard = new ImageBillboard(texture); billboard.Orientation = BillboardOrientation.WorldOriented; billboardNode = new BillboardNode(billboard); billboardNode.Name = "World-oriented"; billboardNode.PoseWorld = pose1; _scene.Children.Add(billboardNode); pose1.Position.Z -= 1; pose1.Orientation *= Matrix33F.CreateRotationY(0.2f); billboardNode = new BillboardNode(billboard); billboardNode.PoseWorld = pose1 * new Pose(Matrix33F.CreateRotationZ(MathHelper.ToRadians(15))); _scene.Children.Add(billboardNode); pose1.Position.Z -= 1; pose1.Orientation *= Matrix33F.CreateRotationY(0.2f); billboardNode = new BillboardNode(billboard); billboardNode.PoseWorld = pose1 * new Pose(Matrix33F.CreateRotationZ(MathHelper.ToRadians(30))); _scene.Children.Add(billboardNode); pose1.Position.Z -= 1; pose1.Orientation *= Matrix33F.CreateRotationY(0.2f); billboardNode = new BillboardNode(billboard); billboardNode.PoseWorld = pose1 * new Pose(Matrix33F.CreateRotationZ(MathHelper.ToRadians(45))); _scene.Children.Add(billboardNode); // ----- Animated billboards // DigitalRune Graphics supports "texture atlases". I.e. textures can be packed // together into a single, larger texture file. A PackedTexture can describe a // single texture packed into a texture atlas or a tile set packed into a // texture atlas. In this example the "beeWingFlap" is a set of three tiles. // Tile sets can be used for sprite animations. (The animation is set below in // Update().) pose0.Position.X += 2; pose1 = pose0; texture = new PackedTexture("Bee", ContentManager.Load <Texture2D>("Particles/beeWingFlap"), Vector2F.Zero, Vector2F.One, 3, 1); _animatedBillboard = new ImageBillboard(texture); billboardNode = new BillboardNode(_animatedBillboard); billboardNode.Name = "Animated billboards"; billboardNode.PoseWorld = pose1; _scene.Children.Add(billboardNode); pose1.Position.Z -= 1; billboardNode = new BillboardNode(_animatedBillboard); billboardNode.PoseWorld = pose1; _scene.Children.Add(billboardNode); pose1.Position.Z -= 1; billboardNode = new BillboardNode(_animatedBillboard); billboardNode.PoseWorld = pose1; _scene.Children.Add(billboardNode); // Use DebugRenderer to draw node names above billboard nodes. foreach (var node in _scene.GetDescendants().OfType <BillboardNode>()) { _debugRenderer.DrawText(node.Name, node.PoseWorld.Position + new Vector3F(0, 1, 0), new Vector2F(0.5f), Color.Yellow, false); } }
public void AddRagdoll(float scale, Vector3F ragdollPosition) { // Ragdolls are usually used in games to create realistic death animations of // characters. The character is usually rendered using a skinned triangle mesh. // But in the physics simulation the body parts of the character are represented // using simple shapes, such as spheres, capsules, boxes, or convex polyhedra, // which are connected with joints. // The physics simulations computes how these parts collide and fall. The positions // and orientations are then read back each frame to update the animation of the // triangle mesh. // In this example the ragdoll is built from spheres, capsules and boxes. The // rigid bodies are created in code. In practice, ragdolls should be built using // external tools, such as a 3D modeller or a game editor. #region ----- Create rigid bodies for the most relevant body parts ----- BoxShape pelvisShape = new BoxShape(0.3f * scale, 0.22f * scale, 0.20f * scale); MassFrame pelvisMass = MassFrame.FromShapeAndDensity(pelvisShape, Vector3F.One, Density, 0.01f, 3); RigidBody pelvis = new RigidBody(pelvisShape, pelvisMass, null) { Pose = new Pose(new Vector3F(0f, 0.01f * scale, -0.03f * scale) + ragdollPosition), }; Simulation.RigidBodies.Add(pelvis); BoxShape torsoShape = new BoxShape(0.35f * scale, 0.22f * scale, 0.44f * scale); MassFrame torsoMass = MassFrame.FromShapeAndDensity(torsoShape, Vector3F.One, Density, 0.01f, 3); RigidBody torso = new RigidBody(torsoShape, torsoMass, null) { Pose = new Pose(new Vector3F(0f, 0.01f * scale, -0.4f * scale) + ragdollPosition), }; Simulation.RigidBodies.Add(torso); SphereShape headShape = new SphereShape(0.13f * scale); MassFrame headMass = MassFrame.FromShapeAndDensity(headShape, Vector3F.One, Density, 0.01f, 3); RigidBody head = new RigidBody(headShape, headMass, null) { Pose = new Pose(new Vector3F(0f * scale, 0f, -0.776f * scale) + ragdollPosition), }; Simulation.RigidBodies.Add(head); CapsuleShape upperArmShape = new CapsuleShape(0.08f * scale, 0.3f * scale); MassFrame upperArmMass = MassFrame.FromShapeAndDensity(upperArmShape, Vector3F.One, Density, 0.01f, 3); RigidBody leftUpperArm = new RigidBody(upperArmShape, upperArmMass, null) { Pose = new Pose(new Vector3F(-0.32f * scale, 0.06f * scale, -0.53f * scale) + ragdollPosition, Matrix33F.CreateRotationZ(ConstantsF.PiOver2)), }; Simulation.RigidBodies.Add(leftUpperArm); RigidBody rightUpperArm = new RigidBody(upperArmShape, upperArmMass, null) { Pose = new Pose(new Vector3F(0.32f * scale, 0.06f * scale, -0.53f * scale) + ragdollPosition, Matrix33F.CreateRotationZ(ConstantsF.PiOver2)), }; Simulation.RigidBodies.Add(rightUpperArm); CapsuleShape lowerArmShape = new CapsuleShape(0.08f * scale, 0.4f * scale); MassFrame lowerArmMass = MassFrame.FromShapeAndDensity(lowerArmShape, Vector3F.One, Density, 0.01f, 3); RigidBody leftLowerArm = new RigidBody(lowerArmShape, lowerArmMass, null) { Pose = new Pose(new Vector3F(-0.62f * scale, 0.06f * scale, -0.53f * scale) + ragdollPosition, Matrix33F.CreateRotationZ(ConstantsF.PiOver2)), }; Simulation.RigidBodies.Add(leftLowerArm); RigidBody rightLowerArm = new RigidBody(lowerArmShape, lowerArmMass, null) { Pose = new Pose(new Vector3F(0.62f * scale, 0.06f * scale, -0.53f * scale) + ragdollPosition, Matrix33F.CreateRotationZ(ConstantsF.PiOver2)), }; Simulation.RigidBodies.Add(rightLowerArm); CapsuleShape upperLegShape = new CapsuleShape(0.09f * scale, 0.5f * scale); MassFrame upperLegMass = MassFrame.FromShapeAndDensity(upperLegShape, Vector3F.One, Density, 0.01f, 3); RigidBody leftUpperLeg = new RigidBody(upperLegShape, upperLegMass, null) { Pose = new Pose(new Vector3F(-0.10f * scale, 0.01f * scale, 0.233f * scale) + ragdollPosition, Matrix33F.CreateRotationX(ConstantsF.PiOver2)), }; Simulation.RigidBodies.Add(leftUpperLeg); RigidBody rightUpperLeg = new RigidBody(upperLegShape, upperLegMass, null) { Pose = new Pose(new Vector3F(0.10f * scale, 0.01f * scale, 0.233f * scale) + ragdollPosition, Matrix33F.CreateRotationX(ConstantsF.PiOver2)), }; Simulation.RigidBodies.Add(rightUpperLeg); CapsuleShape lowerLegShape = new CapsuleShape(0.08f * scale, 0.4f * scale); MassFrame lowerLegMass = MassFrame.FromShapeAndDensity(pelvisShape, Vector3F.One, Density, 0.01f, 3); RigidBody leftLowerLeg = new RigidBody(lowerLegShape, lowerLegMass, null) { Pose = new Pose(new Vector3F(-0.11f * scale, 0.01f * scale, 0.7f * scale) + ragdollPosition, Matrix33F.CreateRotationX(ConstantsF.PiOver2)), }; Simulation.RigidBodies.Add(leftLowerLeg); RigidBody rightLowerLeg = new RigidBody(lowerLegShape, lowerLegMass, null) { Pose = new Pose(new Vector3F(0.11f * scale, 0.01f * scale, 0.7f * scale) + ragdollPosition, Matrix33F.CreateRotationX(ConstantsF.PiOver2)), }; Simulation.RigidBodies.Add(rightLowerLeg); BoxShape footShape = new BoxShape(0.12f * scale, 0.28f * scale, 0.07f * scale); MassFrame footMass = MassFrame.FromShapeAndDensity(footShape, Vector3F.One, Density, 0.01f, 3); RigidBody leftFoot = new RigidBody(footShape, footMass, null) { Pose = new Pose(new Vector3F(-0.11f * scale, -0.06f * scale, 0.94f * scale) + ragdollPosition), }; Simulation.RigidBodies.Add(leftFoot); RigidBody rightFoot = new RigidBody(footShape, footMass, null) { Pose = new Pose(new Vector3F(0.11f * scale, -0.06f * scale, 0.94f * scale) + ragdollPosition), }; Simulation.RigidBodies.Add(rightFoot); #endregion #region ----- Add joints between body parts ----- Vector3F pelvisJointPosition = new Vector3F(0f, 0.026f * scale, -0.115f * scale) + ragdollPosition; HingeJoint pelvisJoint = new HingeJoint { BodyA = torso, BodyB = pelvis, AnchorPoseALocal = new Pose(torso.Pose.ToLocalPosition(pelvisJointPosition)), AnchorPoseBLocal = new Pose(pelvis.Pose.ToLocalPosition(pelvisJointPosition)), Minimum = -0.5f, Maximum = 1.1f, CollisionEnabled = false, ErrorReduction = JointErrorReduction, Softness = JointSoftness, MaxForce = JointMaxForce, }; Simulation.Constraints.Add(pelvisJoint); Vector3F neckJointPosition = new Vector3F(0f, 0.026f * scale, -0.690f * scale) + ragdollPosition; HingeJoint neckJoint = new HingeJoint { BodyA = head, BodyB = torso, AnchorPoseALocal = new Pose(head.Pose.ToLocalPosition(neckJointPosition)), AnchorPoseBLocal = new Pose(torso.Pose.ToLocalPosition(neckJointPosition)), Minimum = -1f, Maximum = 1f, CollisionEnabled = false, ErrorReduction = JointErrorReduction, Softness = JointSoftness, MaxForce = JointMaxForce, }; Simulation.Constraints.Add(neckJoint); Vector3F leftShoulderJointPosition = new Vector3F(-0.193f * scale, 0.056f * scale, -0.528f * scale) + ragdollPosition; Vector3F leftShoulderJointAxis = new Vector3F(0, -1, -1).Normalized; Matrix33F leftShoulderJointOrientation = new Matrix33F(); leftShoulderJointOrientation.SetColumn(0, leftShoulderJointAxis); leftShoulderJointOrientation.SetColumn(1, leftShoulderJointAxis.Orthonormal1); leftShoulderJointOrientation.SetColumn(2, leftShoulderJointAxis.Orthonormal2); BallJoint leftShoulderJoint = new BallJoint { BodyA = leftUpperArm, BodyB = torso, AnchorPositionALocal = leftUpperArm.Pose.ToLocalPosition(leftShoulderJointPosition), AnchorPositionBLocal = torso.Pose.ToLocalPosition(leftShoulderJointPosition), CollisionEnabled = false, ErrorReduction = JointErrorReduction, Softness = JointSoftness, MaxForce = JointMaxForce, }; Simulation.Constraints.Add(leftShoulderJoint); Vector3F rightShoulderJointPosition = new Vector3F(0.193f * scale, 0.056f * scale, -0.528f * scale) + ragdollPosition; Vector3F rightShoulderJointAxis = new Vector3F(0, 1, 1).Normalized; Matrix33F rightShoulderJointOrientation = new Matrix33F(); rightShoulderJointOrientation.SetColumn(0, rightShoulderJointAxis); rightShoulderJointOrientation.SetColumn(1, rightShoulderJointAxis.Orthonormal1); rightShoulderJointOrientation.SetColumn(2, rightShoulderJointAxis.Orthonormal2); BallJoint rightShoulderJoint = new BallJoint { BodyA = rightUpperArm, BodyB = torso, AnchorPositionALocal = rightUpperArm.Pose.ToLocalPosition(rightShoulderJointPosition), AnchorPositionBLocal = torso.Pose.ToLocalPosition(rightShoulderJointPosition), CollisionEnabled = false, ErrorReduction = JointErrorReduction, Softness = JointSoftness, MaxForce = JointMaxForce, }; Simulation.Constraints.Add(rightShoulderJoint); Vector3F leftElbowJointPosition = new Vector3F(-0.451f * scale, 0.071f * scale, -0.538f * scale) + ragdollPosition; Matrix33F elbowAxisOrientation = new Matrix33F(0, 0, -1, 0, 1, 0, 1, 0, 0); HingeJoint leftElbowJoint = new HingeJoint { BodyA = leftLowerArm, BodyB = leftUpperArm, AnchorPoseALocal = new Pose(leftLowerArm.Pose.ToLocalPosition(leftElbowJointPosition), leftLowerArm.Pose.Orientation.Inverse * elbowAxisOrientation), AnchorPoseBLocal = new Pose(leftUpperArm.Pose.ToLocalPosition(leftElbowJointPosition), leftUpperArm.Pose.Orientation.Inverse * elbowAxisOrientation), Minimum = -2, Maximum = 0, CollisionEnabled = false, ErrorReduction = JointErrorReduction, Softness = JointSoftness, MaxForce = JointMaxForce, }; Simulation.Constraints.Add(leftElbowJoint); Vector3F rightElbowJointPosition = new Vector3F(0.451f * scale, 0.071f * scale, -0.538f * scale) + ragdollPosition; HingeJoint rightElbowJoint = new HingeJoint { BodyA = rightLowerArm, BodyB = rightUpperArm, AnchorPoseALocal = new Pose(rightLowerArm.Pose.ToLocalPosition(rightElbowJointPosition), rightLowerArm.Pose.Orientation.Inverse * elbowAxisOrientation), AnchorPoseBLocal = new Pose(rightUpperArm.Pose.ToLocalPosition(rightElbowJointPosition), rightUpperArm.Pose.Orientation.Inverse * elbowAxisOrientation), Minimum = 0, Maximum = 2, CollisionEnabled = false, ErrorReduction = JointErrorReduction, Softness = JointSoftness, MaxForce = JointMaxForce, }; Simulation.Constraints.Add(rightElbowJoint); Vector3F leftHipJointPosition = new Vector3F(-0.107f * scale, 0.049f * scale, 0.026f * scale) + ragdollPosition; HingeJoint leftHipJoint = new HingeJoint { BodyA = pelvis, BodyB = leftUpperLeg, AnchorPoseALocal = new Pose(pelvis.Pose.ToLocalPosition(leftHipJointPosition)), AnchorPoseBLocal = new Pose(leftUpperLeg.Pose.ToLocalPosition(leftHipJointPosition), leftUpperLeg.Pose.Orientation.Inverse), Minimum = -0.1f, Maximum = 1.2f, CollisionEnabled = false, ErrorReduction = JointErrorReduction, Softness = JointSoftness, MaxForce = JointMaxForce, }; Simulation.Constraints.Add(leftHipJoint); Vector3F rightHipJointPosition = new Vector3F(0.107f * scale, 0.049f * scale, 0.026f * scale) + ragdollPosition; HingeJoint rightHipJoint = new HingeJoint { BodyA = pelvis, BodyB = rightUpperLeg, AnchorPoseALocal = new Pose(pelvis.Pose.ToLocalPosition(rightHipJointPosition)), AnchorPoseBLocal = new Pose(rightUpperLeg.Pose.ToLocalPosition(rightHipJointPosition), rightUpperLeg.Pose.Orientation.Inverse), Minimum = -0.1f, Maximum = 1.2f, CollisionEnabled = false, ErrorReduction = JointErrorReduction, Softness = JointSoftness, MaxForce = JointMaxForce, }; Simulation.Constraints.Add(rightHipJoint); Vector3F leftKneeJointPosition = new Vector3F(-0.118f * scale, -0.012f * scale, 0.439f * scale) + ragdollPosition; HingeJoint leftKneeJoint = new HingeJoint { BodyA = leftLowerLeg, BodyB = leftUpperLeg, AnchorPoseALocal = new Pose(leftLowerLeg.Pose.ToLocalPosition(leftKneeJointPosition)), AnchorPoseBLocal = new Pose(leftUpperLeg.Pose.ToLocalPosition(leftKneeJointPosition)), Minimum = 0, Maximum = 1.7f, CollisionEnabled = false, ErrorReduction = JointErrorReduction, Softness = JointSoftness, MaxForce = JointMaxForce, }; Simulation.Constraints.Add(leftKneeJoint); Vector3F rightKneeJointPosition = new Vector3F(0.118f * scale, -0.012f * scale, 0.439f * scale) + ragdollPosition; HingeJoint rightKneeJoint = new HingeJoint { BodyA = rightLowerLeg, BodyB = rightUpperLeg, AnchorPoseALocal = new Pose(rightLowerLeg.Pose.ToLocalPosition(rightKneeJointPosition)), AnchorPoseBLocal = new Pose(rightUpperLeg.Pose.ToLocalPosition(rightKneeJointPosition)), Minimum = 0, Maximum = 1.7f, CollisionEnabled = false, ErrorReduction = JointErrorReduction, Softness = JointSoftness, MaxForce = JointMaxForce, }; Simulation.Constraints.Add(rightKneeJoint); Vector3F leftAnkleJointPosition = new Vector3F(-0.118f * scale, -0.016f * scale, 0.861f * scale) + ragdollPosition; HingeJoint leftAnkleJoint = new HingeJoint { BodyA = leftFoot, BodyB = leftLowerLeg, AnchorPoseALocal = new Pose(leftFoot.Pose.ToLocalPosition(leftAnkleJointPosition)), AnchorPoseBLocal = new Pose(leftLowerLeg.Pose.ToLocalPosition(leftAnkleJointPosition), leftLowerLeg.Pose.Orientation.Inverse), Minimum = -0.4f, Maximum = 0.9f, CollisionEnabled = false, ErrorReduction = JointErrorReduction, Softness = JointSoftness, MaxForce = JointMaxForce, }; Simulation.Constraints.Add(leftAnkleJoint); Vector3F rightAnkleJointPosition = new Vector3F(0.118f * scale, -0.016f * scale, 0.861f * scale) + ragdollPosition; HingeJoint rightAnkleJoint = new HingeJoint { BodyA = rightFoot, BodyB = rightLowerLeg, AnchorPoseALocal = new Pose(rightFoot.Pose.ToLocalPosition(rightAnkleJointPosition)), AnchorPoseBLocal = new Pose(rightLowerLeg.Pose.ToLocalPosition(rightAnkleJointPosition), rightLowerLeg.Pose.Orientation.Inverse), Minimum = -0.4f, Maximum = 0.9f, CollisionEnabled = false, ErrorReduction = JointErrorReduction, Softness = JointSoftness, MaxForce = JointMaxForce, }; Simulation.Constraints.Add(rightAnkleJoint); #endregion #region ----- Add damping to improve stability ----- if (DampingEnabled) { // Damping removes jiggling and improves stability. AddDamping(pelvis, torso); AddDamping(torso, head); AddDamping(torso, leftUpperArm); AddDamping(leftUpperArm, leftLowerArm); AddDamping(torso, rightUpperArm); AddDamping(rightUpperArm, rightLowerArm); AddDamping(pelvis, leftUpperLeg); AddDamping(pelvis, rightUpperLeg); AddDamping(leftUpperLeg, leftLowerLeg); AddDamping(rightUpperLeg, rightLowerLeg); AddDamping(leftLowerLeg, leftFoot); AddDamping(rightLowerLeg, rightFoot); } #endregion }
public BridgeSample(Microsoft.Xna.Framework.Game game) : base(game) { // Add basic force effects. Simulation.ForceEffects.Add(new Gravity()); Simulation.ForceEffects.Add(new Damping()); // Add a ground plane. RigidBody groundPlane = new RigidBody(new PlaneShape(Vector3F.UnitY, 0)) { Name = "GroundPlane", // Names are not required but helpful for debugging. MotionType = MotionType.Static, }; Simulation.RigidBodies.Add(groundPlane); // We add another damping effect that acts only on the suspension bridge parts. // This damping uses higher damping factors than the standard damping. It makes the // bridge movement smoother and more stable. // We use a ListAreaOfEffect. So the additional damping acts only on bodies in this list. ListAreaOfEffect boardList = new ListAreaOfEffect(new List <RigidBody>()); Damping damping = new Damping { AreaOfEffect = boardList, AngularDamping = 1f, LinearDamping = 0.5f }; Simulation.ForceEffects.Add(damping); const int numberOfBoards = 20; BoxShape boardShape = new BoxShape(0.8f, 0.1f, 1.5f); RigidBody lastBoard = null; for (int i = 0; i < numberOfBoards; i++) { // A single plank of the bridge. RigidBody body = new RigidBody(boardShape) { Pose = new Pose(new Vector3F(-10 + boardShape.WidthX * i, 4, 0)) }; Simulation.RigidBodies.Add(body); // Add the body to the list of the additional damping force effect. boardList.RigidBodies.Add(body); if (lastBoard != null) { // Connect the last body with current body using a hinge. HingeJoint hinge = new HingeJoint { BodyA = lastBoard, // The attachment point is at the right side of the board. // --> To define the constraint anchor orientation: // The columns are the axes. We set the local z axis in the first column. This is // the hinge axis. In the other two columns we set two orthonormal vectors. // (All three columns are orthonormal and form a valid rotation matrix.) AnchorPoseALocal = new Pose(new Vector3F(boardShape.WidthX / 2, 0, 0), new Matrix33F(0, 0, -1, 0, 1, 0, 1, 0, 0)), BodyB = body, // The attachment point is at the left side of the board. // The anchor orientation is defined as above. AnchorPoseBLocal = new Pose(new Vector3F(-boardShape.WidthX / 2, 0, 0), new Matrix33F(0, 0, -1, 0, 1, 0, 1, 0, 0)), CollisionEnabled = false, // ErrorReduction and Softness are tweaked to get a stable and smooth bridge // movement. ErrorReduction = 0.3f, Softness = 0.00005f, }; Simulation.Constraints.Add(hinge); } else if (i == 0) { // To attach the bridge somewhere, connect the the first board to a fixed position in the // world. HingeJoint hinge = new HingeJoint { BodyA = Simulation.World, AnchorPoseALocal = new Pose(new Vector3F(-9, 3, 0), new Matrix33F(0, 0, -1, 0, 1, 0, 1, 0, 0)), BodyB = body, AnchorPoseBLocal = new Pose(new Vector3F(-boardShape.WidthX / 2, 0, 0), new Matrix33F(0, 0, -1, 0, 1, 0, 1, 0, 0)), }; Simulation.Constraints.Add(hinge); } if (i == numberOfBoards - 1) { // To attach the bridge somewhere, connect the the last board to a fixed position in the // world. HingeJoint hinge = new HingeJoint { BodyA = Simulation.World, AnchorPoseALocal = new Pose(new Vector3F(9, 3, 0), new Matrix33F(0, 0, -1, 0, 1, 0, 1, 0, 0)), BodyB = body, AnchorPoseBLocal = new Pose(new Vector3F(boardShape.WidthX / 2, 0, 0), new Matrix33F(0, 0, -1, 0, 1, 0, 1, 0, 0)), }; Simulation.Constraints.Add(hinge); } lastBoard = body; } // The bridge is ready. // Now, add some ramps so that the character controller can walk up to the bridge. BoxShape rampShape = new BoxShape(10, 10, 2); RigidBody ramp0 = new RigidBody(rampShape) { Pose = new Pose(new Vector3F(-12.5f, -3f, 0), Matrix33F.CreateRotationZ(0.3f)), MotionType = MotionType.Static, }; Simulation.RigidBodies.Add(ramp0); RigidBody ramp1 = new RigidBody(rampShape) { Pose = new Pose(new Vector3F(12.5f, -3f, 0), Matrix33F.CreateRotationZ(-0.3f)), MotionType = MotionType.Static, }; Simulation.RigidBodies.Add(ramp1); // Drop a few light boxes onto the bridge. BoxShape boxShape = new BoxShape(1, 1, 1); MassFrame boxMass = MassFrame.FromShapeAndDensity(boxShape, Vector3F.One, 100, 0.01f, 3); for (int i = 0; i < 10; i++) { Vector3F randomPosition = new Vector3F(RandomHelper.Random.NextFloat(-10, 10), 5, 0); QuaternionF randomOrientation = RandomHelper.Random.NextQuaternionF(); RigidBody body = new RigidBody(boxShape, boxMass, null) { Pose = new Pose(randomPosition, randomOrientation), }; Simulation.RigidBodies.Add(body); } }
public ConstraintSample2(Microsoft.Xna.Framework.Game game) : base(game) { // Add basic force effects. Simulation.ForceEffects.Add(new Gravity()); Simulation.ForceEffects.Add(new Damping()); // Add a ground plane. RigidBody groundPlane = new RigidBody(new PlaneShape(Vector3F.UnitY, 0)) { Name = "GroundPlane", // Names are not required but helpful for debugging. MotionType = MotionType.Static, }; Simulation.RigidBodies.Add(groundPlane); // ----- PointOnLineConstraint RigidBody box0 = new RigidBody(new BoxShape(0.1f, 0.5f, 6)) { Pose = new Pose(new Vector3F(-4, 3, 0)), MotionType = MotionType.Static, }; Simulation.RigidBodies.Add(box0); RigidBody sphere0 = new RigidBody(new SphereShape(0.5f)) { Pose = new Pose(new Vector3F(-4, 2, 0)) }; Simulation.RigidBodies.Add(sphere0); PointOnLineConstraint pointOnLineConstraint = new PointOnLineConstraint { BodyA = box0, // The line goes through this point: AnchorPositionALocal = new Vector3F(0, -0.25f, 0), BodyB = sphere0, AnchorPositionBLocal = new Vector3F(0, 0.5f, 0), // The line axis: AxisALocal = Vector3F.UnitZ, // The movement on the line axis: Minimum = -3, Maximum = +3, CollisionEnabled = false, }; Simulation.Constraints.Add(pointOnLineConstraint); // ----- PointOnPlaneConstraint RigidBody box1 = new RigidBody(new BoxShape(2f, 0.5f, 6)) { Pose = new Pose(new Vector3F(-1, 3, 0)), MotionType = MotionType.Static, }; Simulation.RigidBodies.Add(box1); RigidBody sphere1 = new RigidBody(new SphereShape(0.5f)) { Pose = new Pose(new Vector3F(-1, 2, 0)) }; Simulation.RigidBodies.Add(sphere1); PointOnPlaneConstraint pointOnPlaneConstraint = new PointOnPlaneConstraint { BodyA = box1, // The plane goes through this point: AnchorPositionALocal = new Vector3F(0, -0.25f, 0), BodyB = sphere1, AnchorPositionBLocal = new Vector3F(0, 0.5f, 0), // Two orthonormal vectors that define the plane: XAxisALocal = Vector3F.UnitX, YAxisALocal = Vector3F.UnitZ, // Limits for the x axis and y axis movement: Minimum = new Vector2F(-1, -3), Maximum = new Vector2F(1, 3), CollisionEnabled = false, }; Simulation.Constraints.Add(pointOnPlaneConstraint); // ----- NoRotationConstraint // This constraint keeps two rotations synchronized. RigidBody box2 = new RigidBody(new BoxShape(1, 1, 1)) { Pose = new Pose(new Vector3F(2, 3, 0)), }; Simulation.RigidBodies.Add(box2); RigidBody box3 = new RigidBody(new BoxShape(1, 1, 1)) { Pose = new Pose(new Vector3F(2.5f, 2, 0)) }; Simulation.RigidBodies.Add(box3); NoRotationConstraint noRotationConstraint = new NoRotationConstraint { BodyA = box2, BodyB = box3, CollisionEnabled = true, }; Simulation.Constraints.Add(noRotationConstraint); // ----- Distance limit. // Here, the distance of two cone tips is kept at a constant distance. RigidBody cone0 = new RigidBody(new ConeShape(0.5f, 1f)) { Pose = new Pose(new Vector3F(4, 3, 0), Matrix33F.CreateRotationZ(ConstantsF.Pi)), MotionType = MotionType.Static, }; Simulation.RigidBodies.Add(cone0); RigidBody cone1 = new RigidBody(new ConeShape(0.5f, 1f)) { Pose = new Pose(new Vector3F(4, 0, 0)) }; Simulation.RigidBodies.Add(cone1); DistanceLimit distanceLimit = new DistanceLimit { BodyA = cone0, BodyB = cone1, // The attachment points are the tips of the cones. AnchorPositionALocal = new Vector3F(0, 1, 0), AnchorPositionBLocal = new Vector3F(0, 1, 0), // The tips should always have a distance of 0.5 units. MinDistance = 0.5f, MaxDistance = 0.5f, }; Simulation.Constraints.Add(distanceLimit); }
/// <summary> /// Initializes the ragdoll for the given skeleton pose. /// </summary> /// <param name="skeletonPose">The skeleton pose.</param> /// <param name="ragdoll">The ragdoll.</param> /// <param name="simulation">The simulation in which the ragdoll will be used.</param> /// <param name="scale">A scaling factor to scale the size of the ragdoll.</param> public static void Create(SkeletonPose skeletonPose, Ragdoll ragdoll, Simulation simulation, float scale) { var skeleton = skeletonPose.Skeleton; const float totalMass = 80; // The total mass of the ragdoll. const int numberOfBodies = 17; // Get distance from foot to head as a measure for the size of the ragdoll. int head = skeleton.GetIndex("Head"); int footLeft = skeleton.GetIndex("L_Ankle1"); var headPosition = skeletonPose.GetBonePoseAbsolute(head).Translation; var footPosition = skeletonPose.GetBonePoseAbsolute(footLeft).Translation; var headToFootDistance = (headPosition - footPosition).Length; // 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. var massFrame = MassFrame.FromShapeAndMass(new SphereShape(headToFootDistance / 8), Vector3F.One, totalMass / numberOfBodies, 0.1f, 1); var material = new UniformMaterial(); #region ----- Add Bodies and Body Offsets ----- var numberOfBones = skeleton.NumberOfBones; ragdoll.Bodies.AddRange(Enumerable.Repeat <RigidBody>(null, numberOfBones)); ragdoll.BodyOffsets.AddRange(Enumerable.Repeat(Pose.Identity, numberOfBones)); var pelvis = skeleton.GetIndex("Pelvis"); ragdoll.Bodies[pelvis] = new RigidBody(new BoxShape(0.3f * scale, 0.4f * scale, 0.55f * scale), massFrame, material); ragdoll.BodyOffsets[pelvis] = new Pose(new Vector3F(0, 0, 0)); var backLower = skeleton.GetIndex("Spine"); ragdoll.Bodies[backLower] = new RigidBody(new BoxShape(0.36f * scale, 0.4f * scale, 0.55f * scale), massFrame, material); ragdoll.BodyOffsets[backLower] = new Pose(new Vector3F(0.18f * scale, 0, 0)); var backUpper = skeleton.GetIndex("Spine2"); ragdoll.Bodies[backUpper] = new RigidBody(new BoxShape(0.5f * scale, 0.4f * scale, 0.65f * scale), massFrame, material); ragdoll.BodyOffsets[backUpper] = new Pose(new Vector3F(0.25f * scale, 0, 0)); var neck = skeleton.GetIndex("Neck"); ragdoll.Bodies[neck] = new RigidBody(new CapsuleShape(0.12f * scale, 0.3f * scale), massFrame, material); ragdoll.BodyOffsets[neck] = new Pose(new Vector3F(0.15f * scale, 0, 0), QuaternionF.CreateRotationZ(ConstantsF.PiOver2)); ragdoll.Bodies[neck].CollisionObject.Enabled = false; ragdoll.Bodies[head] = new RigidBody(new SphereShape(0.2f * scale), massFrame, material); ragdoll.BodyOffsets[head] = new Pose(new Vector3F(0.15f * scale, 0.02f * scale, 0)); var armUpperLeft = skeleton.GetIndex("L_UpperArm"); ragdoll.Bodies[armUpperLeft] = new RigidBody(new CapsuleShape(0.12f * scale, 0.6f * scale), massFrame, material); ragdoll.BodyOffsets[armUpperLeft] = new Pose(new Vector3F(0.2f * scale, 0, 0), QuaternionF.CreateRotationZ(ConstantsF.PiOver2)); var armLowerLeft = skeleton.GetIndex("L_Forearm"); ragdoll.Bodies[armLowerLeft] = new RigidBody(new CapsuleShape(0.08f * scale, 0.5f * scale), massFrame, material); ragdoll.BodyOffsets[armLowerLeft] = new Pose(new Vector3F(0.2f * scale, 0, 0), QuaternionF.CreateRotationZ(ConstantsF.PiOver2)); var handLeft = skeleton.GetIndex("L_Hand"); ragdoll.Bodies[handLeft] = new RigidBody(new BoxShape(0.2f * scale, 0.06f * scale, 0.15f * scale), massFrame, material); ragdoll.BodyOffsets[handLeft] = new Pose(new Vector3F(0.1f * scale, 0, 0)); var armUpperRight = skeleton.GetIndex("R_UpperArm"); ragdoll.Bodies[armUpperRight] = new RigidBody(new CapsuleShape(0.12f * scale, 0.6f * scale), massFrame, material); ragdoll.BodyOffsets[armUpperRight] = new Pose(new Vector3F(0.2f * scale, 0, 0), QuaternionF.CreateRotationZ(ConstantsF.PiOver2)); var armLowerRight = skeleton.GetIndex("R_Forearm"); ragdoll.Bodies[armLowerRight] = new RigidBody(new CapsuleShape(0.08f * scale, 0.5f * scale), massFrame, material); ragdoll.BodyOffsets[armLowerRight] = new Pose(new Vector3F(0.2f * scale, 0, 0), QuaternionF.CreateRotationZ(ConstantsF.PiOver2)); var handRight = skeleton.GetIndex("R_Hand"); ragdoll.Bodies[handRight] = new RigidBody(new BoxShape(0.2f * scale, 0.06f * scale, 0.15f * scale), massFrame, material); ragdoll.BodyOffsets[handRight] = new Pose(new Vector3F(0.1f * scale, 0, 0)); var legUpperLeft = skeleton.GetIndex("L_Thigh1"); ragdoll.Bodies[legUpperLeft] = new RigidBody(new CapsuleShape(0.16f * scale, 0.8f * scale), massFrame, material); ragdoll.BodyOffsets[legUpperLeft] = new Pose(new Vector3F(0.4f * scale, 0, 0), QuaternionF.CreateRotationZ(ConstantsF.PiOver2)); var legLowerLeft = skeleton.GetIndex("L_Knee2"); ragdoll.Bodies[legLowerLeft] = new RigidBody(new CapsuleShape(0.12f * scale, 0.65f * scale), massFrame, material); ragdoll.BodyOffsets[legLowerLeft] = new Pose(new Vector3F(0.32f * scale, 0, 0), QuaternionF.CreateRotationZ(ConstantsF.PiOver2)); //var footLeft = skeleton.GetIndex("L_Ankle1"); ragdoll.Bodies[footLeft] = new RigidBody(new BoxShape(0.20f * scale, 0.5f * scale, 0.3f * scale), massFrame, material); ragdoll.BodyOffsets[footLeft] = new Pose(new Vector3F(0.16f * scale, 0.15f * scale, 0)); var legUpperRight = skeleton.GetIndex("R_Thigh"); ragdoll.Bodies[legUpperRight] = new RigidBody(new CapsuleShape(0.16f * scale, 0.8f * scale), massFrame, material); ragdoll.BodyOffsets[legUpperRight] = new Pose(new Vector3F(0.4f * scale, 0, 0), QuaternionF.CreateRotationZ(ConstantsF.PiOver2)); var legLowerRight = skeleton.GetIndex("R_Knee"); ragdoll.Bodies[legLowerRight] = new RigidBody(new CapsuleShape(0.12f * scale, 0.65f * scale), massFrame, material); ragdoll.BodyOffsets[legLowerRight] = new Pose(new Vector3F(0.32f * scale, 0, 0), QuaternionF.CreateRotationZ(ConstantsF.PiOver2)); var footRight = skeleton.GetIndex("R_Ankle"); ragdoll.Bodies[footRight] = new RigidBody(new BoxShape(0.20f * scale, 0.5f * scale, 0.3f * scale), massFrame, material); ragdoll.BodyOffsets[footRight] = new Pose(new Vector3F(0.16f * scale, 0.15f * scale, 0)); #endregion #region ----- Set Collision Filters ----- // Collisions between connected bodies will be disabled in AddJoint(). (A BallJoint // has a property CollisionEnabled which decides whether connected bodies can // collide.) // But we need to disable some more collision between bodies that are not directly // connected but still too close to each other. var filter = (ICollisionFilter)simulation.CollisionDomain.CollisionDetection.CollisionFilter; filter.Set(ragdoll.Bodies[backUpper].CollisionObject, ragdoll.Bodies[head].CollisionObject, false); filter.Set(ragdoll.Bodies[armUpperRight].CollisionObject, ragdoll.Bodies[backLower].CollisionObject, false); filter.Set(ragdoll.Bodies[armUpperLeft].CollisionObject, ragdoll.Bodies[backLower].CollisionObject, false); filter.Set(ragdoll.Bodies[legUpperLeft].CollisionObject, ragdoll.Bodies[legUpperRight].CollisionObject, false); #endregion #region ----- Add Joints ----- AddJoint(skeletonPose, ragdoll, pelvis, backLower); AddJoint(skeletonPose, ragdoll, backLower, backUpper); AddJoint(skeletonPose, ragdoll, backUpper, neck); AddJoint(skeletonPose, ragdoll, neck, head); AddJoint(skeletonPose, ragdoll, backUpper, armUpperLeft); AddJoint(skeletonPose, ragdoll, armUpperLeft, armLowerLeft); AddJoint(skeletonPose, ragdoll, armLowerLeft, handLeft); AddJoint(skeletonPose, ragdoll, backUpper, armUpperRight); AddJoint(skeletonPose, ragdoll, armUpperRight, armLowerRight); AddJoint(skeletonPose, ragdoll, armLowerRight, handRight); AddJoint(skeletonPose, ragdoll, pelvis, legUpperLeft); AddJoint(skeletonPose, ragdoll, legUpperLeft, legLowerLeft); AddJoint(skeletonPose, ragdoll, legLowerLeft, footLeft); AddJoint(skeletonPose, ragdoll, pelvis, legUpperRight); AddJoint(skeletonPose, ragdoll, legUpperRight, legLowerRight); AddJoint(skeletonPose, ragdoll, legLowerRight, footRight); #endregion #region ----- Add Limits ----- // Choosing limits is difficult. // We create hinge limits with AngularLimits in the back and in the knee. // For all other joints we use TwistSwingLimits with symmetric cones. AddAngularLimit(skeletonPose, ragdoll, pelvis, backLower, new Vector3F(0, 0, -0.3f), new Vector3F(0, 0, 0.3f)); AddAngularLimit(skeletonPose, ragdoll, backLower, backUpper, new Vector3F(0, 0, -0.3f), new Vector3F(0, 0, 0.4f)); AddAngularLimit(skeletonPose, ragdoll, backUpper, neck, new Vector3F(0, 0, -0.3f), new Vector3F(0, 0, 0.3f)); AddTwistSwingLimit(ragdoll, neck, head, Matrix33F.Identity, Matrix33F.Identity, new Vector3F(-0.1f, -0.5f, -0.7f), new Vector3F(0.1f, 0.5f, 0.7f)); var parentBindPoseAbsolute = (Pose)skeleton.GetBindPoseAbsoluteInverse(backUpper).Inverse; var childBindPoseAbsolute = (Pose)skeleton.GetBindPoseAbsoluteInverse(armUpperLeft).Inverse; var bindPoseRelative = parentBindPoseAbsolute.Inverse * childBindPoseAbsolute; AddTwistSwingLimit(ragdoll, backUpper, armUpperLeft, bindPoseRelative.Orientation * Matrix33F.CreateRotationY(-0.5f) * Matrix33F.CreateRotationZ(-0.5f), Matrix33F.Identity, new Vector3F(-0.7f, -1.2f, -1.2f), new Vector3F(0.7f, 1.2f, 1.2f)); AddTwistSwingLimit(ragdoll, armUpperLeft, armLowerLeft, Matrix33F.CreateRotationZ(-1.2f), Matrix33F.Identity, new Vector3F(-0.3f, -1.2f, -1.2f), new Vector3F(0.3f, 1.2f, 1.2f)); AddTwistSwingLimit(ragdoll, armLowerLeft, handLeft, Matrix33F.Identity, Matrix33F.CreateRotationX(+ConstantsF.PiOver2), new Vector3F(-0.3f, -0.7f, -0.7f), new Vector3F(0.3f, 0.7f, 0.7f)); parentBindPoseAbsolute = (Pose)skeleton.GetBindPoseAbsoluteInverse(backUpper).Inverse; childBindPoseAbsolute = (Pose)skeleton.GetBindPoseAbsoluteInverse(armUpperRight).Inverse; bindPoseRelative = parentBindPoseAbsolute.Inverse * childBindPoseAbsolute; AddTwistSwingLimit(ragdoll, backUpper, armUpperRight, bindPoseRelative.Orientation * Matrix33F.CreateRotationY(0.5f) * Matrix33F.CreateRotationZ(-0.5f), Matrix33F.Identity, new Vector3F(-0.7f, -1.2f, -1.2f), new Vector3F(0.7f, 1.2f, 1.2f)); AddTwistSwingLimit(ragdoll, armUpperRight, armLowerRight, Matrix33F.CreateRotationZ(-1.2f), Matrix33F.Identity, new Vector3F(-0.3f, -1.2f, -1.2f), new Vector3F(0.3f, 1.2f, 1.2f)); AddTwistSwingLimit(ragdoll, armLowerRight, handRight, Matrix33F.Identity, Matrix33F.CreateRotationX(-ConstantsF.PiOver2), new Vector3F(-0.3f, -0.7f, -0.7f), new Vector3F(0.3f, 0.7f, 0.7f)); parentBindPoseAbsolute = (Pose)skeleton.GetBindPoseAbsoluteInverse(pelvis).Inverse; childBindPoseAbsolute = (Pose)skeleton.GetBindPoseAbsoluteInverse(legUpperLeft).Inverse; bindPoseRelative = parentBindPoseAbsolute.Inverse * childBindPoseAbsolute; AddTwistSwingLimit(ragdoll, pelvis, legUpperLeft, bindPoseRelative.Orientation * Matrix33F.CreateRotationZ(1.2f), Matrix33F.Identity, new Vector3F(-0.1f, -0.7f, -1.5f), new Vector3F(+0.1f, +0.7f, +1.5f)); AddAngularLimit(skeletonPose, ragdoll, legUpperLeft, legLowerLeft, new Vector3F(0, 0, -2.2f), new Vector3F(0, 0, 0.0f)); AddTwistSwingLimit(ragdoll, legLowerLeft, footLeft, Matrix33F.Identity, Matrix33F.Identity, new Vector3F(-0.1f, -0.3f, -0.7f), new Vector3F(0.1f, 0.3f, 0.7f)); parentBindPoseAbsolute = (Pose)skeleton.GetBindPoseAbsoluteInverse(pelvis).Inverse; childBindPoseAbsolute = (Pose)skeleton.GetBindPoseAbsoluteInverse(legUpperRight).Inverse; bindPoseRelative = parentBindPoseAbsolute.Inverse * childBindPoseAbsolute; AddTwistSwingLimit(ragdoll, pelvis, legUpperRight, bindPoseRelative.Orientation * Matrix33F.CreateRotationZ(1.2f), Matrix33F.Identity, new Vector3F(-0.1f, -0.7f, -1.5f), new Vector3F(+0.1f, +0.7f, +1.5f)); AddAngularLimit(skeletonPose, ragdoll, legUpperRight, legLowerRight, new Vector3F(0, 0, -2.2f), new Vector3F(0, 0, 0.0f)); AddTwistSwingLimit(ragdoll, legLowerRight, footRight, Matrix33F.Identity, Matrix33F.Identity, new Vector3F(-0.1f, -0.3f, -0.7f), new Vector3F(0.1f, 0.3f, 0.7f)); #endregion #region ----- Add Motors ----- ragdoll.Motors.AddRange(Enumerable.Repeat <RagdollMotor>(null, numberOfBones)); ragdoll.Motors[pelvis] = new RagdollMotor(pelvis, -1); ragdoll.Motors[backLower] = new RagdollMotor(backLower, pelvis); ragdoll.Motors[backUpper] = new RagdollMotor(backUpper, backLower); ragdoll.Motors[neck] = new RagdollMotor(neck, backUpper); ragdoll.Motors[head] = new RagdollMotor(head, neck); ragdoll.Motors[armUpperLeft] = new RagdollMotor(armUpperLeft, backUpper); ragdoll.Motors[armLowerLeft] = new RagdollMotor(armLowerLeft, armUpperLeft); ragdoll.Motors[handLeft] = new RagdollMotor(handLeft, armLowerLeft); ragdoll.Motors[armUpperRight] = new RagdollMotor(armUpperRight, backUpper); ragdoll.Motors[armLowerRight] = new RagdollMotor(armLowerRight, armUpperRight); ragdoll.Motors[handRight] = new RagdollMotor(handRight, armLowerRight); ragdoll.Motors[legUpperLeft] = new RagdollMotor(legUpperLeft, pelvis); ragdoll.Motors[legLowerLeft] = new RagdollMotor(legLowerLeft, legUpperLeft); ragdoll.Motors[footLeft] = new RagdollMotor(footLeft, legLowerLeft); ragdoll.Motors[legUpperRight] = new RagdollMotor(legUpperRight, pelvis); ragdoll.Motors[legLowerRight] = new RagdollMotor(legLowerRight, legUpperRight); ragdoll.Motors[footRight] = new RagdollMotor(footRight, legLowerRight); #endregion }
// Creates a lot of random objects. private void CreateRandomObjects() { var random = new Random(); var isFirstHeightField = true; int currentShape = 0; int numberOfObjects = 0; while (true) { numberOfObjects++; if (numberOfObjects > ObjectsPerType) { currentShape++; numberOfObjects = 0; } Shape shape; switch (currentShape) { case 0: // Box shape = new BoxShape(ObjectSize, ObjectSize * 2, ObjectSize * 3); break; case 1: // Capsule shape = new CapsuleShape(0.3f * ObjectSize, 2 * ObjectSize); break; case 2: // Cone shape = new ConeShape(1 * ObjectSize, 2 * ObjectSize); break; case 3: // Cylinder shape = new CylinderShape(0.4f * ObjectSize, 2 * ObjectSize); break; case 4: // Sphere shape = new SphereShape(ObjectSize); break; case 5: // Convex hull of several points. ConvexHullOfPoints hull = new ConvexHullOfPoints(); hull.Points.Add(new Vector3F(-1 * ObjectSize, -2 * ObjectSize, -1 * ObjectSize)); hull.Points.Add(new Vector3F(2 * ObjectSize, -1 * ObjectSize, -0.5f * ObjectSize)); hull.Points.Add(new Vector3F(1 * ObjectSize, 2 * ObjectSize, 1 * ObjectSize)); hull.Points.Add(new Vector3F(-1 * ObjectSize, 2 * ObjectSize, 1 * ObjectSize)); hull.Points.Add(new Vector3F(-1 * ObjectSize, 0.7f * ObjectSize, -0.6f * ObjectSize)); shape = hull; break; case 6: // A composite shape: two boxes that form a "T" shape. var composite = new CompositeShape(); composite.Children.Add( new GeometricObject( new BoxShape(ObjectSize, 3 * ObjectSize, ObjectSize), new Pose(new Vector3F(0, 0, 0)))); composite.Children.Add( new GeometricObject( new BoxShape(2 * ObjectSize, ObjectSize, ObjectSize), new Pose(new Vector3F(0, 2 * ObjectSize, 0)))); shape = composite; break; case 7: shape = new CircleShape(ObjectSize); break; case 8: { var compBvh = new CompositeShape(); compBvh.Children.Add(new GeometricObject(new BoxShape(0.5f, 1, 0.5f), new Pose(new Vector3F(0, 0.5f, 0), Matrix33F.Identity))); compBvh.Children.Add(new GeometricObject(new BoxShape(0.8f, 0.5f, 0.5f), new Pose(new Vector3F(0.5f, 0.7f, 0), Matrix33F.CreateRotationZ(-MathHelper.ToRadians(15))))); compBvh.Children.Add(new GeometricObject(new SphereShape(0.3f), new Pose(new Vector3F(0, 1.15f, 0), Matrix33F.Identity))); compBvh.Children.Add(new GeometricObject(new CapsuleShape(0.2f, 1), new Pose(new Vector3F(0.6f, 1.15f, 0), Matrix33F.CreateRotationX(0.3f)))); compBvh.Partition = new AabbTree <int>(); shape = compBvh; break; } case 9: CompositeShape comp = new CompositeShape(); comp.Children.Add(new GeometricObject(new BoxShape(0.5f * ObjectSize, 1 * ObjectSize, 0.5f * ObjectSize), new Pose(new Vector3F(0, 0.5f * ObjectSize, 0), QuaternionF.Identity))); comp.Children.Add(new GeometricObject(new BoxShape(0.8f * ObjectSize, 0.5f * ObjectSize, 0.5f * ObjectSize), new Pose(new Vector3F(0.3f * ObjectSize, 0.7f * ObjectSize, 0), QuaternionF.CreateRotationZ(-MathHelper.ToRadians(45))))); comp.Children.Add(new GeometricObject(new SphereShape(0.3f * ObjectSize), new Pose(new Vector3F(0, 1.15f * ObjectSize, 0), QuaternionF.Identity))); shape = comp; break; case 10: shape = new ConvexHullOfPoints(new[] { new Vector3F(-1 * ObjectSize, -2 * ObjectSize, -1 * ObjectSize), new Vector3F(2 * ObjectSize, -1 * ObjectSize, -0.5f * ObjectSize), new Vector3F(1 * ObjectSize, 2 * ObjectSize, 1 * ObjectSize), new Vector3F(-1 * ObjectSize, 2 * ObjectSize, 1 * ObjectSize), new Vector3F(-1 * ObjectSize, 0.7f * ObjectSize, -0.6f * ObjectSize) }); break; case 11: ConvexHullOfShapes shapeHull = new ConvexHullOfShapes(); shapeHull.Children.Add(new GeometricObject(new SphereShape(0.3f * ObjectSize), new Pose(new Vector3F(0, 2 * ObjectSize, 0), Matrix33F.Identity))); shapeHull.Children.Add(new GeometricObject(new BoxShape(1 * ObjectSize, 2 * ObjectSize, 3 * ObjectSize), Pose.Identity)); shape = shapeHull; break; case 12: shape = Shape.Empty; break; case 13: var numberOfSamplesX = 10; var numberOfSamplesZ = 10; var samples = new float[numberOfSamplesX * numberOfSamplesZ]; for (int z = 0; z < numberOfSamplesZ; z++) { for (int x = 0; x < numberOfSamplesX; x++) { samples[z * numberOfSamplesX + x] = (float)(Math.Cos(z / 3f) * Math.Sin(x / 2f) * BoxSize / 6); } } HeightField heightField = new HeightField(0, 0, 2 * BoxSize, 2 * BoxSize, samples, numberOfSamplesX, numberOfSamplesZ); shape = heightField; break; //case 14: //shape = new LineShape(new Vector3F(0.1f, 0.2f, 0.3f), new Vector3F(0.1f, 0.2f, -0.3f).Normalized); //break; case 15: shape = new LineSegmentShape( new Vector3F(0.1f, 0.2f, 0.3f), new Vector3F(0.1f, 0.2f, 0.3f) + 3 * ObjectSize * new Vector3F(0.1f, 0.2f, -0.3f)); break; case 16: shape = new MinkowskiDifferenceShape { ObjectA = new GeometricObject(new SphereShape(0.1f * ObjectSize)), ObjectB = new GeometricObject(new BoxShape(1 * ObjectSize, 2 * ObjectSize, 3 * ObjectSize)) }; break; case 17: shape = new MinkowskiSumShape { ObjectA = new GeometricObject(new SphereShape(0.1f * ObjectSize)), ObjectB = new GeometricObject(new BoxShape(1 * ObjectSize, 2 * ObjectSize, 3 * ObjectSize)), }; break; case 18: shape = new OrthographicViewVolume(0, ObjectSize, 0, ObjectSize, ObjectSize / 2, ObjectSize * 2); break; case 19: shape = new PerspectiveViewVolume(MathHelper.ToRadians(60f), 16f / 10, ObjectSize / 2, ObjectSize * 3); break; case 20: shape = new PointShape(0.1f, 0.3f, 0.2f); break; case 21: shape = new RayShape(new Vector3F(0.2f, 0, -0.12f), new Vector3F(1, 2, 3).Normalized, ObjectSize * 2); break; case 22: shape = new RayShape(new Vector3F(0.2f, 0, -0.12f), new Vector3F(1, 2, 3).Normalized, ObjectSize * 2) { StopsAtFirstHit = true }; break; case 23: shape = new RectangleShape(ObjectSize, ObjectSize * 2); break; case 24: shape = new TransformedShape( new GeometricObject( new BoxShape(1 * ObjectSize, 2 * ObjectSize, 3 * ObjectSize), new Pose(new Vector3F(0.1f, 1, -0.2f)))); break; case 25: shape = new TriangleShape( new Vector3F(ObjectSize, 0, 0), new Vector3F(0, ObjectSize, 0), new Vector3F(ObjectSize, ObjectSize, ObjectSize)); break; //case 26: // { // // Create a composite object from which we get the mesh. // CompositeShape compBvh = new CompositeShape(); // compBvh.Children.Add(new GeometricObject(new BoxShape(0.5f, 1, 0.5f), new Pose(new Vector3F(0, 0.5f, 0), Matrix33F.Identity))); // compBvh.Children.Add( // new GeometricObject( // new BoxShape(0.8f, 0.5f, 0.5f), // new Pose(new Vector3F(0.5f, 0.7f, 0), Matrix33F.CreateRotationZ(-(float)MathHelper.ToRadians(15))))); // compBvh.Children.Add(new GeometricObject(new SphereShape(0.3f), new Pose(new Vector3F(0, 1.15f, 0), Matrix33F.Identity))); // compBvh.Children.Add( // new GeometricObject(new CapsuleShape(0.2f, 1), new Pose(new Vector3F(0.6f, 1.15f, 0), Matrix33F.CreateRotationX(0.3f)))); // TriangleMeshShape meshBvhShape = new TriangleMeshShape { Mesh = compBvh.GetMesh(0.01f, 3) }; // meshBvhShape.Partition = new AabbTree<int>(); // shape = meshBvhShape; // break; // } //case 27: // { // // Create a composite object from which we get the mesh. // CompositeShape compBvh = new CompositeShape(); // compBvh.Children.Add(new GeometricObject(new BoxShape(0.5f, 1, 0.5f), new Pose(new Vector3F(0, 0.5f, 0), QuaternionF.Identity))); // compBvh.Children.Add( // new GeometricObject( // new BoxShape(0.8f, 0.5f, 0.5f), // new Pose(new Vector3F(0.5f, 0.7f, 0), QuaternionF.CreateRotationZ(-(float)MathHelper.ToRadians(15))))); // compBvh.Children.Add(new GeometricObject(new SphereShape(0.3f), new Pose(new Vector3F(0, 1.15f, 0), QuaternionF.Identity))); // compBvh.Children.Add( // new GeometricObject(new CapsuleShape(0.2f, 1), new Pose(new Vector3F(0.6f, 1.15f, 0), QuaternionF.CreateRotationX(0.3f)))); // TriangleMeshShape meshBvhShape = new TriangleMeshShape { Mesh = compBvh.GetMesh(0.01f, 3) }; // meshBvhShape.Partition = new AabbTree<int>(); // shape = meshBvhShape; // break; // } case 28: shape = new ConvexPolyhedron(new[] { new Vector3F(-1 * ObjectSize, -2 * ObjectSize, -1 * ObjectSize), new Vector3F(2 * ObjectSize, -1 * ObjectSize, -0.5f * ObjectSize), new Vector3F(1 * ObjectSize, 2 * ObjectSize, 1 * ObjectSize), new Vector3F(-1 * ObjectSize, 2 * ObjectSize, 1 * ObjectSize), new Vector3F(-1 * ObjectSize, 0.7f * ObjectSize, -0.6f * ObjectSize) }); break; case 29: return; default: currentShape++; continue; } // Create an object with the random shape, pose, color and velocity. Pose randomPose = new Pose( random.NextVector3F(-BoxSize + ObjectSize * 2, BoxSize - ObjectSize * 2), random.NextQuaternionF()); var newObject = new MovingGeometricObject { Pose = randomPose, Shape = shape, LinearVelocity = random.NextQuaternionF().Rotate(new Vector3F(MaxLinearVelocity, 0, 0)), AngularVelocity = random.NextQuaternionF().Rotate(Vector3F.Forward) * RandomHelper.Random.NextFloat(0, MaxAngularVelocity), }; if (RandomHelper.Random.NextBool()) { newObject.LinearVelocity = Vector3F.Zero; } if (RandomHelper.Random.NextBool()) { newObject.AngularVelocity = Vector3F.Zero; } if (shape is LineShape || shape is HeightField) { // Do not move lines or the height field. newObject.LinearVelocity = Vector3F.Zero; newObject.AngularVelocity = Vector3F.Zero; } // Create only 1 heightField! if (shape is HeightField) { if (isFirstHeightField) { isFirstHeightField = true; newObject.Pose = new Pose(new Vector3F(-BoxSize, -BoxSize, -BoxSize)); } else { currentShape++; numberOfObjects = 0; continue; } } // Add collision object to collision domain. _domain.CollisionObjects.Add(new CollisionObject(newObject)); //co.Type = CollisionObjectType.Trigger; //co.Name = "Object" + shape.GetType().Name + "_" + i; } }
/// <summary> /// Initializes the physics simulation. /// </summary> private void InitializePhysics() { // Add a gravity force. _gravity = new Gravity { Acceleration = new Vector3F(0, -GravityAcceleration, 0) }; Simulation.ForceEffects.Add(_gravity); // Add a damping force. Simulation.ForceEffects.Add(new Damping()); // Add a few spheres. Simulation.RigidBodies.Add(new RigidBody(new SphereShape(0.3f)) { Pose = new Pose(new Vector3F(0, 1, 0)), }); Simulation.RigidBodies.Add(new RigidBody(new SphereShape(0.2f)) { Pose = new Pose(new Vector3F(1, 1, 0)), }); Simulation.RigidBodies.Add(new RigidBody(new SphereShape(0.4f)) { Pose = new Pose(new Vector3F(0, 1, 2)), }); // Add ragdoll. AddRagdoll(1, new Vector3F(0, 2, 0)); // The Simulation performs 2 sub-time-steps per frame because we have set // the FixedTimeStep of the simulation to 1/60 s and the TargetElapsedTime of the game // is 1/30 s (30 Hz). In the event SubTimeStepFinished, we call our method // HandleBreakableJoints() to check the forces in the joints and disable constraints where // the force is too large. // Instead, we could also call HandleBreakableJoints() in the Update() method of the game // but then it is only called with the 30 Hz of the game. It is more accurate to call the // method at the end of each simulation sub-time-step (60 Hz). Simulation.SubTimeStepFinished += (s, e) => HandleBreakableJoints(); // Add 6 planes that keep the bodies inside the visible area. The exact positions and angles // have been determined by experimentation. var groundPlane = new RigidBody(new PlaneShape(Vector3F.UnitY, 0)) { Name = "GroundPlane", MotionType = MotionType.Static, }; Simulation.RigidBodies.Add(groundPlane); var nearPlane = new RigidBody(new PlaneShape(-Vector3F.UnitY, -8)) { Name = "NearPlane", MotionType = MotionType.Static, }; Simulation.RigidBodies.Add(nearPlane); var leftPlane = new RigidBody(new PlaneShape(Matrix33F.CreateRotationZ(MathHelper.ToRadians(-22f)) * Vector3F.UnitX, -4.8f)) { Name = "LeftPlane", MotionType = MotionType.Static, }; Simulation.RigidBodies.Add(leftPlane); var rightPlane = new RigidBody(new PlaneShape(Matrix33F.CreateRotationZ(MathHelper.ToRadians(22f)) * -Vector3F.UnitX, -4.8f)) { Name = "RightPlane", MotionType = MotionType.Static, }; Simulation.RigidBodies.Add(rightPlane); var topPlane = new RigidBody(new PlaneShape(Matrix33F.CreateRotationX(MathHelper.ToRadians(14f)) * Vector3F.UnitZ, -3f)) { Name = "TopPlane", MotionType = MotionType.Static, }; Simulation.RigidBodies.Add(topPlane); var bottomPlane = new RigidBody(new PlaneShape(Matrix33F.CreateRotationX(MathHelper.ToRadians(-14f)) * -Vector3F.UnitZ, -3f)) { Name = "BottomPlane", MotionType = MotionType.Static, }; Simulation.RigidBodies.Add(bottomPlane); }
public CompositeMaterial2Sample(Microsoft.Xna.Framework.Game game) : base(game) { // Add basic force effects. Simulation.ForceEffects.Add(new Gravity()); Simulation.ForceEffects.Add(new Damping()); // Add a ground plane. RigidBody groundPlane = new RigidBody(new PlaneShape(new Vector3F(0, 1, 0.25f).Normalized, 0)) { Name = "GroundPlane", // Names are not required but helpful for debugging. MotionType = MotionType.Static, }; // Adjust the coefficients of friction of the ground plane. ((UniformMaterial)groundPlane.Material).DynamicFriction = 0.5f; ((UniformMaterial)groundPlane.Material).StaticFriction = 0.5f; Simulation.RigidBodies.Add(groundPlane); // Prepare two materials: a slippery material and a rough material. UniformMaterial slipperyMaterial = new UniformMaterial { DynamicFriction = 0.001f, StaticFriction = 0.001f, }; UniformMaterial roughMaterial = new UniformMaterial { DynamicFriction = 1, StaticFriction = 1, }; // Create a rigid body that consists of multiple shapes: Two boxes and a cylinder between them. CompositeShape compositeShape = new CompositeShape(); compositeShape.Children.Add(new GeometricObject(new BoxShape(1f, 1f, 1f), new Pose(new Vector3F(1.5f, 0f, 0f)))); compositeShape.Children.Add(new GeometricObject(new BoxShape(1f, 1, 1f), new Pose(new Vector3F(-1.5f, 0f, 0f)))); compositeShape.Children.Add(new GeometricObject(new CylinderShape(0.1f, 2), new Pose(Matrix33F.CreateRotationZ(ConstantsF.PiOver2)))); // A CompositeMaterial is used to assign a different material to each shape. CompositeMaterial compositeMaterial = new CompositeMaterial(); compositeMaterial.Materials.Add(roughMaterial); // Assign the rough material to the first box. compositeMaterial.Materials.Add(slipperyMaterial); // Assign the slippery material to the second box. compositeMaterial.Materials.Add(null); // Use whatever is default for the handle between the boxes. RigidBody body = new RigidBody(compositeShape, null, compositeMaterial) { Pose = new Pose(new Vector3F(0, 2.2f, -5)), }; Simulation.RigidBodies.Add(body); }