// Creates a test scene with a lot of randomly placed objects. internal static void CreateScene(ServiceContainer services, ContentManager content, DeferredGraphicsScreen graphicsScreen) { var gameObjectService = services.GetInstance<IGameObjectService>(); var graphicsService = services.GetInstance<IGraphicsService>(); gameObjectService.Objects.Add(new DynamicSkyObject(services, true, false, true) { EnableAmbientLight = false, // Disable ambient light of sky to make shadows more visible. EnableCloudShadows = false }); gameObjectService.Objects.Add(new GroundObject(services)); gameObjectService.Objects.Add(new DynamicObject(services, 1)); gameObjectService.Objects.Add(new DynamicObject(services, 2)); gameObjectService.Objects.Add(new DynamicObject(services, 3)); gameObjectService.Objects.Add(new DynamicObject(services, 5)); gameObjectService.Objects.Add(new DynamicObject(services, 6)); gameObjectService.Objects.Add(new DynamicObject(services, 7)); gameObjectService.Objects.Add(new ObjectCreatorObject(services)); gameObjectService.Objects.Add(new LavaBallsObject(services)); var random = new Random(); // Spheres var sphereMesh = SampleHelper.CreateMesh(content, graphicsService, new SphereShape(1)); for (int i = 0; i < 100; i++) { Vector3F position = new Vector3F(random.NextFloat(-100, 100), random.NextFloat(0, 3), random.NextFloat(-100, 100)); float scale = random.NextFloat(0.5f, 3f); var meshNode = new MeshNode(sphereMesh) { PoseLocal = new Pose(position), ScaleLocal = new Vector3F(scale), IsStatic = true, }; graphicsScreen.Scene.Children.Add(meshNode); } // Boxes var boxMesh = SampleHelper.CreateMesh(content, graphicsService, new BoxShape(1, 1, 1)); for (int i = 0; i < 100; i++) { Vector3F position = new Vector3F(random.NextFloat(-100, 100), random.NextFloat(0, 3), random.NextFloat(-100, 100)); QuaternionF orientation = random.NextQuaternionF(); Vector3F scale = random.NextVector3F(0.1f, 4f); var meshNode = new MeshNode(boxMesh) { PoseLocal = new Pose(position, orientation), ScaleLocal = scale, IsStatic = true, }; graphicsScreen.Scene.Children.Add(meshNode); } // Height field with smooth hills. var numberOfSamplesX = 20; var numberOfSamplesZ = 20; var samples = new float[numberOfSamplesX * numberOfSamplesZ]; for (int z = 0; z < numberOfSamplesZ; z++) { for (int x = 0; x < numberOfSamplesX; x++) { if (x == 0 || z == 0 || x == 19 || z == 19) { // Set this boundary elements to a low height, so that the height field is connected // to the ground. samples[z * numberOfSamplesX + x] = -1; } else { // A sine/cosine function that creates some interesting waves. samples[z * numberOfSamplesX + x] = 1 + (float)(Math.Cos(z / 2f) * Math.Sin(x / 2f) * 1); } } } var heightField = new HeightField(0, 0, 20, 20, samples, numberOfSamplesX, numberOfSamplesZ); var heightFieldMesh = SampleHelper.CreateMesh(content, graphicsService, heightField); var heightFieldMeshNode = new MeshNode(heightFieldMesh) { PoseLocal = new Pose(new Vector3F(20, 0, -20)), ScaleLocal = new Vector3F(1, 2, 1), IsStatic = true, }; graphicsScreen.Scene.Children.Add(heightFieldMeshNode); // Dudes. for (int i = 0; i < 10; i++) { Vector3F position = new Vector3F(random.NextFloat(-20, 20), 0, random.NextFloat(-20, 20)); Matrix33F orientation = Matrix33F.CreateRotationY(random.NextFloat(0, ConstantsF.TwoPi)); gameObjectService.Objects.Add(new DudeObject(services) { Pose = new Pose(position, orientation) }); } // Palm trees. for (int i = 0; i < 100; i++) { Vector3F position = new Vector3F(random.NextFloat(-80, 80), 0, random.NextFloat(-100, 100)); Matrix33F orientation = Matrix33F.CreateRotationY(random.NextFloat(0, ConstantsF.TwoPi)); float scale = random.NextFloat(0.5f, 1.2f); gameObjectService.Objects.Add(new StaticObject(services, "PalmTree/palm_tree", scale, new Pose(position, orientation))); } // Rocks for (int i = 0; i < 100; i++) { Vector3F position = new Vector3F(random.NextFloat(-80, 80), 1, random.NextFloat(-100, 100)); QuaternionF orientation = RandomHelper.Random.NextQuaternionF(); float scale = random.NextFloat(0.5f, 1.2f); gameObjectService.Objects.Add(new StaticObject(services, "Rock/rock_05", scale, new Pose(position, orientation))); } // Grass for (int i = 0; i < 100; i++) { Vector3F position = new Vector3F(random.NextFloat(-20, 20), 0, random.NextFloat(-20, 20)); Matrix33F orientation = Matrix33F.CreateRotationY(random.NextFloat(0, ConstantsF.TwoPi)); float scale = random.NextFloat(0.5f, 1.2f); gameObjectService.Objects.Add(new StaticObject(services, "Grass/Grass", scale, new Pose(position, orientation))); } // More plants for (int i = 0; i < 100; i++) { Vector3F position = new Vector3F(random.NextFloat(-20, 20), 0, random.NextFloat(-20, 20)); Matrix33F orientation = Matrix33F.CreateRotationY(random.NextFloat(0, ConstantsF.TwoPi)); float scale = random.NextFloat(0.5f, 1.2f); gameObjectService.Objects.Add(new StaticObject(services, "Parviflora/Parviflora", scale, new Pose(position, orientation))); } // "Skyscrapers" for (int i = 0; i < 20; i++) { Vector3F position = new Vector3F(random.NextFloat(90, 100), 0, random.NextFloat(-100, 100)); Matrix33F orientation = Matrix33F.CreateRotationY(random.NextFloat(0, ConstantsF.TwoPi)); Vector3F scale = new Vector3F(random.NextFloat(6, 20), random.NextFloat(10, 100), random.NextFloat(6, 20)); var meshNode = new MeshNode(boxMesh) { PoseLocal = new Pose(position, orientation), ScaleLocal = scale, IsStatic = true, UserFlags = 1, // Mark the distant huge objects. Used in render callbacks in the CompositeShadowSample. }; graphicsScreen.Scene.Children.Add(meshNode); } // "Hills" for (int i = 0; i < 20; i++) { Vector3F position = new Vector3F(random.NextFloat(-90, -100), 0, random.NextFloat(-100, 100)); Vector3F scale = new Vector3F(random.NextFloat(10, 20), random.NextFloat(10, 30), random.NextFloat(10, 20)); var meshNode = new MeshNode(sphereMesh) { PoseLocal = new Pose(position), ScaleLocal = scale, IsStatic = true, UserFlags = 1, // Mark the distant huge objects. Used in render callbacks in the CompositeShadowSample. }; graphicsScreen.Scene.Children.Add(meshNode); } }
// 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; } }
public void NoiseRange3D() { double min = double.MaxValue; double max = double.MinValue; var random = new Random(15485863); for (int i = 0; i < 10000000; i++) { var v = random.NextVector3F(0, 255); var n = PerlinNoise.Compute(v.X, v.Y, v.Z); min = Math.Min(min, n); max = Math.Max(max, n); } Assert.IsTrue(min < 0 && min >= -1); Assert.IsTrue(max > 0 && max <= 1); }
public override void Update(GameTime gameTime) { Random random = new Random(1234567); // The debug renderer stores all draw commands. In this sample we recreate // the draw jobs each frame. --> Clear draw jobs of last frame. _debugRenderer.Clear(); // The DebugRenderer can draw stuff "in" the scene (enabled z test) or "over" // the scene (disabled z test). // Draw some points and line "in" and "over" the scene. for (int i = 0; i < 10; i++) { var position = new Vector3F(-6, 0, -3) + random.NextVector3F(-0.5f, 0.5f); _debugRenderer.DrawPoint(position, Color.Green, false); } for (int i = 0; i < 10; i++) { var position = new Vector3F(-4, 0, -3) + random.NextVector3F(-0.5f, 0.5f); _debugRenderer.DrawPoint(position, Color.Yellow, true); } for (int i = 0; i < 10; i++) { var start = new Vector3F(-2, 0, -3) + random.NextVector3F(-0.5f, 0.5f); var end = new Vector3F(-2, 0, -3) + random.NextVector3F(-0.5f, 0.5f); _debugRenderer.DrawLine(start, end, Color.Green, false); } for (int i = 0; i < 10; i++) { var start = new Vector3F(0, 0, -3) + random.NextVector3F(-0.5f, 0.5f); var end = new Vector3F(0, 0, -3) + random.NextVector3F(-0.5f, 0.5f); _debugRenderer.DrawLine(start, end, Color.Yellow, true); } // Text without a specified position is drawn at a default position. _debugRenderer.DefaultTextPosition = new Vector2F(10, 100); _debugRenderer.DrawText("White objects are positioned in screen space."); _debugRenderer.DrawText("Yellow objects are positioned in world space. Depth test disabled."); _debugRenderer.DrawText("Other objects are positioned in world space. Depth test enabled."); // Text can also be drawn in world space coordinates or in screen space coordinates. _debugRenderer.DrawText("WorldSpacePosition (0, 0, 0)", new Vector3F(0, 0, 0), Color.Green, false); _debugRenderer.DrawText("WorldSpacePosition (0, 0, -1)", new Vector3F(0, 0, -1), Color.Yellow, true); _debugRenderer.DrawText("ScreenPosition (600, 40)", new Vector2F(600, 40), Color.White); _debugRenderer.DrawText("ScreenPosition (640, 360)", new Vector2F(640, 360), Color.White); // It is often useful to copy textures to the screen for debugging. _debugRenderer.DrawTexture(NoiseHelper.GetGrainTexture(GraphicsService, 128), new Rectangle(1000, 10, 128, 128)); // Axes can be drawn to display poses (positions and orientations). _debugRenderer.DrawAxes(new Pose(new Vector3F(0, 0, 0)), 1, true); // Axis-aligned bounding boxes (AABB) _debugRenderer.DrawAabb(new Aabb(new Vector3F(-0.5f), new Vector3F(0.5f)), new Pose(new Vector3F(2, 0, -3)), Color.Green, false); _debugRenderer.DrawAabb(new Aabb(new Vector3F(-0.5f), new Vector3F(0.5f)), new Pose(new Vector3F(4, 0, -3)), Color.Yellow, true); // Box shapes var orientation = random.NextQuaternionF(); _debugRenderer.DrawBox(1, 1, 1, new Pose(new Vector3F(-6, 0, -5), orientation), new Color(255, 0, 0, 100), false, false); _debugRenderer.DrawBox(1, 1, 1, new Pose(new Vector3F(-6, 0, -5), orientation), Color.Green, true, false); _debugRenderer.DrawBox(1, 1, 1, new Pose(new Vector3F(-4, 0, -5), orientation), Color.Yellow, true, true); // View volumes (frustums) var viewVolume = new PerspectiveViewVolume(1, 2, 0.1f, 1f); _debugRenderer.DrawViewVolume(viewVolume, new Pose(new Vector3F(-2, 0, -5), orientation), new Color(0, 255, 0, 100), false, false); _debugRenderer.DrawViewVolume(viewVolume, new Pose(new Vector3F(-2, 0, -5), orientation), Color.Green, true, false); _debugRenderer.DrawViewVolume(viewVolume, new Pose(new Vector3F(0, 0, -5), orientation), Color.Yellow, true, true); // Spheres _debugRenderer.DrawSphere(0.5f, new Pose(new Vector3F(2, 0, -5), orientation), new Color(0, 0, 255, 100), false, false); _debugRenderer.DrawSphere(0.5f, new Pose(new Vector3F(2, 0, -5), orientation), Color.Green, true, false); _debugRenderer.DrawSphere(0.5f, new Pose(new Vector3F(4, 0, -5), orientation), Color.Yellow, true, true); // Capsules _debugRenderer.DrawCapsule(0.3f, 1, new Pose(new Vector3F(-6, 0, -7), orientation), new Color(255, 255, 0, 100), false, false); _debugRenderer.DrawCapsule(0.3f, 1, new Pose(new Vector3F(-6, 0, -7), orientation), Color.Green, true, false); _debugRenderer.DrawCapsule(0.3f, 1, new Pose(new Vector3F(-4, 0, -7), orientation), Color.Yellow, true, true); // Cylinders _debugRenderer.DrawCylinder(0.3f, 1, new Pose(new Vector3F(-2, 0, -7), orientation), new Color(255, 0, 255, 100), false, false); _debugRenderer.DrawCylinder(0.3f, 1, new Pose(new Vector3F(-2, 0, -7), orientation), Color.Green, true, false); _debugRenderer.DrawCylinder(0.3f, 1, new Pose(new Vector3F(0, 0, -7), orientation), Color.Yellow, true, true); // Cones _debugRenderer.DrawCone(0.3f, 1, new Pose(new Vector3F(2, 0, -7), orientation), new Color(0, 255, 255, 100), false, false); _debugRenderer.DrawCone(0.3f, 1, new Pose(new Vector3F(2, 0, -7), orientation), Color.Green, true, false); _debugRenderer.DrawCone(0.3f, 1, new Pose(new Vector3F(4, 0, -7), orientation), Color.Yellow, true, true); // The debug renderer can draw any IGeometricObjects, like SceneNodes, RigidBodies, etc. _debugRenderer.DrawObject(_geometricObject, Color.Brown, false, false); _debugRenderer.DrawObject(_geometricObject, Color.Yellow, true, true); // The debug renderer can also an XNA model (without materials). _debugRenderer.DrawModel(_xnaModel, new Pose(new Vector3F(0, 2, -2), orientation), new Vector3F(1, 2, 1), new Color(128, 255, 64, 100), false, false); _debugRenderer.DrawModel(_xnaModel, new Pose(new Vector3F(0, 2, -2), orientation), new Vector3F(1, 2, 1), Color.LightCyan, true, false); // Draw a DigitalRune model. _debugRenderer.DrawModel(_modelNode, Color.Peru, true, false); // Draw the bounding shapes of the meshes in this model. foreach (var node in _modelNode.GetSubtree()) _debugRenderer.DrawObject(node, Color.PeachPuff, true, false); }
// Creates a lot of random objects. private void CreateRandomObjects() { var random = new Random(12345); for (int i = 0; i < NumberOfObjects; i++) { // Randomly choose a shape. Shape randomShape; switch (random.Next(0, 7)) { case 0: // Box randomShape = new BoxShape(ObjectSize, ObjectSize * 2, ObjectSize * 3); break; case 1: // Capsule randomShape = new CapsuleShape(0.3f * ObjectSize, 2 * ObjectSize); break; case 2: // Cone randomShape = new ConeShape(1 * ObjectSize, 2 * ObjectSize); break; case 3: // Cylinder randomShape = new CylinderShape(0.4f * ObjectSize, 2 * ObjectSize); break; case 4: // Sphere randomShape = 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)); randomShape = 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)))); randomShape = composite; break; default: #if WINDOWS Trace.Fail("Ups, we shouldn't land here :-("); #endif randomShape = new SphereShape(); break; } // 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 = randomShape, LinearVelocity = random.NextQuaternionF().Rotate(new Vector3F(MaxLinearVelocity, 0, 0)), AngularVelocity = random.NextQuaternionF().Rotate(Vector3F.Forward) * RandomHelper.Random.NextFloat(0, MaxAngularVelocity), }; // Add collision object to collision domain. _domain.CollisionObjects.Add(new CollisionObject(newObject)); // We will collect a few statistics for debugging. Profiler.SetFormat("NumObjects", 1, "The total number of objects."); Profiler.SetFormat("NumObjectPairs", 1, "The number of objects pairs, which have to be checked."); Profiler.SetFormat("BroadPhasePairs", 1, "The number of overlaps reported by the broad phase."); Profiler.SetFormat("ContactSetCount", 1, "The number of actual collisions."); } }
public void RandomizedMassSceneUpdate() { const int NumberOfSceneNodes = 6; const int NumberOfSteps = 10000; const float Saturation = 0.7f; // Percent of scene nodes which should be in the scene. var random = new Random(1234567); var scene = new Scene(); int numberOfNodesInScene = 0; var nodes = new TestSceneNode[NumberOfSceneNodes]; // Create random nodes. for (int i = 0; i < NumberOfSceneNodes; i++) { var node = new TestSceneNode(); nodes[i] = node; var position = random.NextVector3F(-1000, 1000); var orientation = random.NextQuaternionF(); node.PoseLocal = new Pose(position, orientation); float p = random.NextFloat(0, 1); if (p < 0.1f) node.Shape = Shape.Empty; else if (p < 0.2f) node.Shape = Shape.Infinite; //else if (p < 0.21f) //{ // node.Shape = new BoxShape(float.PositiveInfinity, 1, 1); // // Remove orientation - otherwise we get infinite AABB. // node.PoseLocal = new Pose(node.PoseLocal.Position); // var aabb = node.Aabb; // var isValid = node.Aabb.Extent.IsNaN; //} else node.Shape = new SphereShape(random.NextFloat(0, 10)); } for (int updateIndex = 0; updateIndex < NumberOfSteps; updateIndex++) { for (int i = 0; i < NumberOfSceneNodes; i++) { var node = nodes[i]; // Add if (node.Parent == null) { if (random.NextFloat(0, 1) < 0.1f) // 10 percent change to add. { numberOfNodesInScene++; scene.Children.Add(node); } } // Remove if (node.Parent != null && ((float)numberOfNodesInScene) / (float)NumberOfSceneNodes > Saturation) { if (random.NextFloat(0, 1) < 0.1f) // 10 percent change to remove. { numberOfNodesInScene--; node.Parent.Children.Remove(node); } } // Move //if (node.IsInScene) { if (random.NextFloat(0, 1) < 0.5f) // 50% change to move { var pose = node.PoseWorld; pose.Position += random.NextVector3F(0, 10); node.PoseWorld = pose; } if (random.NextFloat(0, 1) < 0.1f) // 50% change to scale { node.ScaleLocal = random.NextVector3F(0.5f, 1.5f); } } } scene.Update(TimeSpan.FromSeconds(0.016666666f)); } }
public void RandomizedMassSceneUpdate2() { const int NumberOfSceneNodes = 10; const int NumberOfSteps = 10000; const float WorldSize = 1000; var random = new Random(123457); var scene = new Scene(); scene.EnableMultithreading = false; var nodes = new TestSceneNode[NumberOfSceneNodes]; // Create random nodes. for (int i = 0; i < NumberOfSceneNodes; i++) { var node = new TestSceneNode(); nodes[i] = node; var position = random.NextVector3F(0, WorldSize); var orientation = random.NextQuaternionF(); node.PoseLocal = new Pose(position, orientation); float p = random.NextFloat(0, 100); if (p < 0.1f) node.Shape = Shape.Empty; else if (p < 0.2f) node.Shape = Shape.Infinite; else if (p < 0.6f) node.Shape = new BoxShape(random.NextVector3F(0, WorldSize)); else node.Shape = new SphereShape(random.NextFloat(0, WorldSize)); } var projection = new PerspectiveProjection(); projection.SetFieldOfView(0.8f, 1, WorldSize / 10000, WorldSize); var camera = new Camera(projection); var cameraNode = new CameraNode(camera); for (int updateIndex = 0; updateIndex < NumberOfSteps; updateIndex++) { int actionsPerFrame = random.NextInteger(0, 100); for (int i = 0; i < actionsPerFrame; i++) { var node = nodes[random.Next(0, NumberOfSceneNodes)]; const int numberOfActions = 100; int action = random.Next(0, numberOfActions); //scene.Validate(); if (action == 0) { // Add if (node.Parent == null) { scene.Children.Add(node); //scene.Validate(); } } else if (action == 1) { // Remove if (node.Parent != null) { node.Parent.Children.Remove(node); //scene.Validate(); } } else if (action == 2) { // Move var pose = node.PoseWorld; pose.Position = random.NextVector3F(0, WorldSize); node.PoseWorld = pose; //scene.Validate(); } else if (action == 3) { // Very small Move var pose = node.PoseWorld; const float maxDistance = WorldSize / 10000; pose.Position += random.NextVector3F(-maxDistance, maxDistance); node.PoseWorld = pose; //scene.Validate(); } else if (action == 4) { // Small Move var pose = node.PoseWorld; const float maxDistance = WorldSize / 100; pose.Position += random.NextVector3F(-maxDistance, maxDistance); node.PoseWorld = pose; //scene.Validate(); } else if (action == 5) { // Scale node.ScaleLocal = random.NextVector3F(0.0f, 10f); //scene.Validate(); } else if (action == 6) { // Rotate node.PoseWorld = new Pose(node.PoseWorld.Position, random.NextQuaternionF()); //scene.Validate(); } else if (action == 7) { // Query var query = scene.Query<CameraFrustumQuery>(cameraNode, null); //Debug.WriteLine("Camera queried nodes: " + query.SceneNodes.Count); //scene.Validate(); } else if (action == 8) { // Move camera. cameraNode.PoseWorld = new Pose(random.NextVector3F(0, WorldSize), random.NextQuaternionF()); //scene.Validate(); } else if (action == 9) { // Change shape. int type = random.NextInteger(0, 5); if (type == 0) node.Shape = new BoxShape(random.NextVector3F(0, WorldSize)); else if (type == 1) node.Shape = new SphereShape(random.NextFloat(0, WorldSize)); else if (type == 2) node.Shape = new BoxShape(new Vector3F(Single.MaxValue)); else if (type == 3) node.Shape = new BoxShape(new Vector3F(0)); else if (type == 4) node.Shape = Shape.Empty; //scene.Validate(); } else if (action == 10) { // Add to random parent. if (node.Parent == null) { var randomParent = nodes[random.NextInteger(0, NumberOfSceneNodes - 1)]; // Avoid loops: bool isLoop = node.GetSubtree().Contains(randomParent); if (!isLoop) { if (randomParent.Children == null) randomParent.Children = new SceneNodeCollection(); randomParent.Children.Add(node); } } } else if (action == 11) { if (node.Parent != null && node.Parent != scene) node.Parent.Children.Remove(node); } else if (action == 13) { if (random.NextInteger(0, 100) < 5) scene.Children.Clear(); } else if (action == 14) { if (random.NextInteger(0, 100) < 5) scene.Children = new SceneNodeCollection(); } } //Debug.WriteLine("Number of nodes in scene: " + scene.GetDescendants().Count()); //scene.Validate(); scene.Update(TimeSpan.FromSeconds(0.016666666f)); //scene.Validate(); } }
public void CompressEmptySrtKeyFrameAnimation2() { var random = new Random(12345); // Animation with 1 keyframe, which is not Identity. var srtKeyFrameAnimation = new SrtKeyFrameAnimation(); var time = TimeSpan.FromTicks(100000); var value = new SrtTransform(random.NextVector3F(-2, 2), random.NextQuaternionF(), random.NextVector3F(-10, 10)); srtKeyFrameAnimation.KeyFrames.Add(new KeyFrame<SrtTransform>(time, value)); var srtAnimation = AnimationHelper.Compress(srtKeyFrameAnimation, 2, 360, 10); Assert.IsNotNull(srtAnimation); Assert.AreEqual(srtKeyFrameAnimation.GetTotalDuration(), srtAnimation.GetTotalDuration()); var defaultSource = SrtTransform.Identity; var defaultTarget = SrtTransform.Identity; var result = new SrtTransform(); srtAnimation.GetValue(time, ref defaultSource, ref defaultTarget, ref result); Assert.AreEqual(srtKeyFrameAnimation.KeyFrames[0].Value, result); }
private static void InsertRandomKeyFrames(Random random, SrtKeyFrameAnimation animation, TimeSpan time0, TimeSpan time1, float scaleThreshold, float rotationThreshold, float translationThreshold) { rotationThreshold = MathHelper.ToRadians(rotationThreshold); var defaultSource = SrtTransform.Identity; var defaultTarget = SrtTransform.Identity; var value = new SrtTransform(); int insertionIndex = 0; for (int i = 0; i < animation.KeyFrames.Count; i++) { if (animation.KeyFrames[i].Time == time0) { insertionIndex = i + 1; break; } } Debug.Assert(insertionIndex > 0); const int numberOfKeyFrames = 2; long tickIncrement = (time1 - time0).Ticks / (numberOfKeyFrames + 1); for (int i = 0; i < numberOfKeyFrames; i++) { var time = TimeSpan.FromTicks(time0.Ticks + (i + 1) * tickIncrement); Debug.Assert(time0 < time && time < time1); // Get interpolated animation value. animation.GetValue(time, ref defaultSource, ref defaultTarget, ref value); // Apply small variation (within thresholds). value.Scale += random.NextVector3F(-1, 1).Normalized * (scaleThreshold / 2); value.Rotation = QuaternionF.CreateRotation(random.NextVector3F(-1, 1), rotationThreshold / 2) * value.Rotation; value.Translation += random.NextVector3F(-1, 1).Normalized * (translationThreshold / 2); animation.KeyFrames.Insert(insertionIndex, new KeyFrame<SrtTransform>(time, value)); insertionIndex++; } }