public FigurePickerObject(IGraphicsService graphicsService, Scene scene, Editor2DCameraObject cameraObject, DebugRenderer debugRenderer)
        {
            _cameraObject = cameraObject;
            _scene = scene;
            _debugRenderer = debugRenderer;

            // Create a collision domain which manages all collision objects used for
            // picking: the picking object and the collision objects for figure nodes.
            _collisionDomain = new CollisionDomain(new CollisionDetection());

            // Create the picking object:
            // The picking object represents the mouse cursor or the reticle. Usually 
            // a ray is used, but in this example we want to use a cylinder/cone. This 
            // allows to check which objects within a certain radius of the reticle. A 
            // picking cylinder/cone is helpful for touch devices where the picking is 
            // done with an imprecise input method like the human finger.

            // We want to pick objects in 10 pixel radius around the reticle. To determine 
            // the world space size of the required cylinder/cone, we can use the projection
            // and the viewport. 
            const float pickingRadius = 0.25f;
            var projection = _cameraObject.CameraNode.Camera.Projection;
            var viewport = graphicsService.GraphicsDevice.Viewport;

            Shape pickingShape;
            if (projection is OrthographicProjection)
            {
                // Use cylinder for orthographic projections:
                // The cylinder is centered at the camera position and reaches from the 
                // camera position to the camera far plane. A TransformedShape is used
                // to rotate and translate the cylinder.
                float radius = projection.Width / viewport.Width * pickingRadius;
                pickingShape = new TransformedShape(
                  new GeometricObject(
                    new CylinderShape(radius, projection.Far),
                    new Pose(new Vector3F(0, 0, -projection.Far / 2), Matrix33F.CreateRotationX(ConstantsF.PiOver2))));
            }
            else
            {
                // Use cone for perspective projections:
                // The cone tip is at the camera position and the cone base is at the 
                // camera far plane. 

                // Compute the radius at the far plane that projects to 10 pixels in screen space.
                float radius = viewport.Unproject(
                  new Vector3(viewport.Width / 2.0f + pickingRadius, viewport.Height / 2.0f, 1),
                  (Matrix)_cameraObject.CameraNode.Camera.Projection.ToMatrix44F(),
                  Matrix.Identity,
                  Matrix.Identity).X;

                // A transformed shape is used to rotate and translate the cone.
                pickingShape = new TransformedShape(
                  new GeometricObject(
                    new ConeShape(radius, projection.Far),
                    new Pose(new Vector3F(0, 0, -projection.Far), Matrix33F.CreateRotationX(ConstantsF.PiOver2))));
            }

            // Create collision object with the picking shape.
            _pickingObject = new CollisionObject(new GeometricObject(pickingShape, _cameraObject.CameraNode.PoseWorld));
        }
Beispiel #2
0
        /// <summary>
        /// Initializes a new instance of the <see cref="FigureRenderData"/> class.
        /// </summary>
        public FigureRenderData()
        {
            BoundingShape = new TransformedShape
              {
            Child = new GeometricObject(new BoxShape(new Vector3F(Single.MaxValue)))
              };

              // The HitShape is created on demand.
        }
Beispiel #3
0
        public void ApproximateAabbMass()
        {
            var s = new ConvexHullOfPoints(new[] { new Vector3F(1, 1, 1), new Vector3F(2, 4, 6) });
              float m0;
              Vector3F com0;
              Matrix33F i0;
              MassHelper.GetMass(s, new Vector3F(1.2f, 2.1f, 0.6f), 0.7f, true, 0.001f, 0, out m0, out com0, out i0);

              var s2 = new TransformedShape(new GeometricObject(new BoxShape(1, 3, 5), new Pose(new Vector3F(1.5f, 2.5f, 3.5f))));
              float m1;
              Vector3F com1;
              Matrix33F i1;
              MassHelper.GetMass(s2, new Vector3F(1.2f, 2.1f, 0.6f), 0.7f, true, 0.001f, 0, out m1, out com1, out i1);

              const float e = 0.0001f;
              Assert.IsTrue(Numeric.AreEqual(m0, m1, e * (1 + m0)));
              Assert.IsTrue(Vector3F.AreNumericallyEqual(com0, com1, e * (1 + com0.Length)));
              Assert.IsTrue(Matrix33F.AreNumericallyEqual(i0, i1, e * (1 + i0.Trace)));
        }
Beispiel #4
0
    /// <summary>
    /// Gets a bounding shape that matches the specified AABB.
    /// </summary>
    /// <param name="aabb">The AABB.</param>
    /// <returns>A box or transformed box that matches the specified AABB.</returns>
    private Shape GetBoundingShape(Aabb aabb)
    {
      // Get existing shape objects to avoid unnecessary memory allocation.
      BoxShape boxShape;
      GeometricObject geometricObject = null;
      TransformedShape transformedShape = null;
      if (Shape is BoxShape)
      {
        boxShape = (BoxShape)Shape;
      }
      else if (Shape is TransformedShape)
      {
        transformedShape = (TransformedShape)Shape;
        geometricObject = (GeometricObject)transformedShape.Child;
        boxShape = (BoxShape)geometricObject.Shape;
      }
      else
      {
        boxShape = new BoxShape();
      }

      // Make box the size of the AABB.
      boxShape.Extent = aabb.Extent;

      if (aabb.Center.IsNumericallyZero)
      {
        // Bounding box is centered at origin.
        return boxShape;
      }
      
      // Apply offset to bounding box.
      if (transformedShape == null)
      {
        geometricObject = new GeometricObject(boxShape, new Pose(aabb.Center));
        transformedShape = new TransformedShape(geometricObject);
      }
      else
      {
        geometricObject.Shape = boxShape;
        geometricObject.Pose = new Pose(aabb.Center);
      }

      return transformedShape;
    }
Beispiel #5
0
    // 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;
      }
    }
Beispiel #6
0
        /// <summary>
        /// Gets a bounding shape that matches the specified AABB.
        /// </summary>
        /// <param name="aabb">The AABB.</param>
        /// <returns>A box or transformed box that matches the specified AABB.</returns>
        private Shape GetBoundingShape(Aabb aabb)
        {
            // The AABB of the LOD is real world size including scaling. We have to undo
              // the scale because this LodGroupNode also applies the same scale.
              var unscaledCenter = aabb.Center / ScaleWorld;
              var unscaledExtent = aabb.Extent / ScaleWorld;

              // Get existing shape objects to avoid unnecessary memory allocation.
              BoxShape boxShape;
              GeometricObject geometricObject = null;
              TransformedShape transformedShape = null;
              if (Shape is BoxShape)
              {
            boxShape = (BoxShape)Shape;
              }
              else if (Shape is TransformedShape)
              {
            transformedShape = (TransformedShape)Shape;
            geometricObject = (GeometricObject)transformedShape.Child;
            boxShape = (BoxShape)geometricObject.Shape;
              }
              else
              {
            boxShape = new BoxShape();
              }

              // Make bounding box the size of the unscaled AABB.
              boxShape.Extent = unscaledExtent;

              if (unscaledCenter.IsNumericallyZero)
              {
            // Bounding box is centered at origin.
            return boxShape;
              }

              // Apply offset to bounding box.
              if (transformedShape == null)
              {
            geometricObject = new GeometricObject(boxShape, new Pose(unscaledCenter));
            transformedShape = new TransformedShape(geometricObject);
              }
              else
              {
            geometricObject.Shape = boxShape;
            geometricObject.Pose = new Pose(unscaledCenter);
              }

              return transformedShape;
        }
Beispiel #7
0
 public void TransformedShapeNonuniformScaleWithRotationNotSupported()
 {
     var s = new TransformedShape(new GeometricObject(new BoxShape(3, 2, 1), new Vector3F(0.7f, 0.8f, 0.9f), new Pose(new Vector3F(-1, 7, 4), QuaternionF.CreateRotationX(1))));
       float m0;
       Vector3F com0;
       Matrix33F i0;
       MassHelper.GetMass(s, new Vector3F(2, 2.1f, 2.8f), 1, true, 0.001f, 10, out m0, out com0, out i0);
 }
Beispiel #8
0
 public void TransformedShapeNegativeScalingNotSupported()
 {
     var s = new TransformedShape(new GeometricObject(new BoxShape(3, 2, 1), new Vector3F(0.7f, 0.8f, 0.9f), new Pose(new Vector3F(-1, 7, 4))));
       float m0;
       Vector3F com0;
       Matrix33F i0;
       MassHelper.GetMass(s, new Vector3F(2, 2.1f, -2.8f), 1, true, 0.001f, 10, out m0, out com0, out i0);
 }
Beispiel #9
0
        public void TransformedShapeMassWithScaling()
        {
            var s = new TransformedShape(new GeometricObject(new BoxShape(3, 2, 1), new Vector3F(0.7f), new Pose(new Vector3F(-1, 7, 4), RandomHelper.Random.NextQuaternionF())));
              float m0;
              Vector3F com0;
              Matrix33F i0;
              MassHelper.GetMass(s, new Vector3F(2), 1, true, 0.001f, 10, out m0, out com0, out i0);

              var m = s.GetMesh(0.001f, 6);
              m.Transform(Matrix44F.CreateScale(2));
              float m1;
              Vector3F com1;
              Matrix33F i1;
              MassHelper.GetMass(m, out m1, out com1, out i1);

              const float e = 0.01f;
              Assert.IsTrue(Numeric.AreEqual(m0, m1, e * (1 + m0)));
              Assert.IsTrue(Vector3F.AreNumericallyEqual(com0, com1, e * (1 + com0.Length)));
              Assert.IsTrue(Matrix33F.AreNumericallyEqual(i0, i1, e * (1 + i0.Trace)));
        }
Beispiel #10
0
    public IntersectionSample(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, 10);
      _cameraObject.ResetPose(new Vector3F(0, 0, -4), ConstantsF.Pi, 0);
      GameObjectService.Objects.Add(_cameraObject);

      // Create a new scene with some lights.
      _scene = new Scene();
      SceneSample.InitializeDefaultXnaLights(_scene);

      _meshRenderer = new MeshRenderer();
      _debugRenderer = new DebugRenderer(GraphicsService, null);

      _intersectionRenderer = new IntersectionRenderer(GraphicsService, ContentManager)
      {
        DownsampleFactor = 1,
      };

      //_submeshA = MeshHelper.CreateSubmesh(GraphicsService.GraphicsDevice, new SphereShape(0.5f).GetMesh(0.001f, 5), MathHelper.ToRadians(70));
      //_submeshB = MeshHelper.CreateSubmesh(GraphicsService.GraphicsDevice, new BoxShape(1, 1, 2).GetMesh(0.001f, 5), MathHelper.ToRadians(70));

      var meshNodeA = CreateMeshNode(new[]
      {
        MeshHelper.CreateTorus(GraphicsService.GraphicsDevice, 1, 0.3f, 30),
        MeshHelper.CreateSubmesh(GraphicsService.GraphicsDevice, new BoxShape(1, 1, 2).GetMesh(0.001f, 5), MathHelper.ToRadians(70)),
      },
      Color.DarkBlue);
      meshNodeA.PoseWorld = new Pose(RandomHelper.Random.NextVector3F(-0.5f, 0.5f),
                                    RandomHelper.Random.NextQuaternionF());
      _scene.Children.Add(meshNodeA);
      _debugRenderer.DrawObject(meshNodeA, Color.Green, true, false);

      var shape = new TransformedShape(
        new GeometricObject(new SphereShape(0.5f), new Pose(new Vector3F(1, 0, 0))));
      var meshNodeB = CreateMeshNode(new[]
      {
        MeshHelper.CreateTorus(GraphicsService.GraphicsDevice, 1, 0.3f, 30),
        MeshHelper.CreateSubmesh(GraphicsService.GraphicsDevice, shape.GetMesh(0.001f, 4), MathHelper.ToRadians(90)),
      },
      Color.Gray);
      meshNodeB.PoseWorld = new Pose(RandomHelper.Random.NextVector3F(-1f, 1f),
                                    RandomHelper.Random.NextQuaternionF());
      _scene.Children.Add(meshNodeB);
      _debugRenderer.DrawObject(meshNodeB, Color.Green, true, false);

      var meshNodeC = CreateMeshNode(new[]
      {
        MeshHelper.CreateBox(GraphicsService.GraphicsDevice),
        MeshHelper.CreateSubmesh(GraphicsService.GraphicsDevice, new BoxShape(1, 1, 2).GetMesh(0.001f, 5), MathHelper.ToRadians(70))
      },
      Color.DarkGreen);
      meshNodeC.PoseWorld = new Pose(RandomHelper.Random.NextVector3F(-1f, 1f),
                                    RandomHelper.Random.NextQuaternionF());
      meshNodeC.ScaleLocal = new Vector3F(0.1f, 1f, 0.5f);
      _scene.Children.Add(meshNodeC);
      _debugRenderer.DrawObject(meshNodeC, Color.Green, true, false);

      _meshNodePairs.Add(new Pair<MeshNode>(meshNodeA, meshNodeB));
      _meshNodePairs.Add(new Pair<MeshNode>(meshNodeA, meshNodeC));
      _meshNodePairs.Add(new Pair<MeshNode>(meshNodeB, meshNodeC));

      CreateGuiControls();
    }
Beispiel #11
0
        private void Update(bool invalidateRenderData)
        {
            if (invalidateRenderData)
            RenderData.SafeDispose();

              // Update shape.
              if (Volume == null)
              {
            // Use a PlaneShape for an infinite ocean.

            var planeShape = Shape as PlaneShape;
            if (planeShape != null)
            {
              planeShape.Normal = new Vector3F(0, 1, 0);
              planeShape.DistanceFromOrigin = ExtraHeight;
            }
            else
            {
              Shape = new PlaneShape(new Vector3F(0, 1, 0), ExtraHeight);
            }

            return;
              }

              // Check if we have a valid AABB.
              var aabb = Volume.GetAabb();

              if (!Numeric.IsZeroOrPositiveFinite(aabb.Extent.LengthSquared))
            throw new GraphicsException("Invalid water volume. The water volume must be a finite shape or null.");

              // Apply ExtraHeight. We also apply it horizontally because choppy waves
              // move vertices horizontally too.
              aabb.Minimum.X -= ExtraHeight;

              // Minimum y should be at least max y - ExtraHeight.
              aabb.Minimum.Y = Math.Min(aabb.Minimum.Y, aabb.Maximum.Y - ExtraHeight);
              aabb.Minimum.Z -= ExtraHeight;
              aabb.Maximum.X += ExtraHeight;
              aabb.Maximum.Y += ExtraHeight;
              aabb.Maximum.Z += ExtraHeight;

              // Create shape from volume AABB.
              if (aabb.Center.IsNumericallyZero)
              {
            // Use BoxShape.
            var boxShape = Shape as BoxShape;
            if (boxShape != null)
              boxShape.Extent = aabb.Extent;
            else
              Shape = new BoxShape(aabb.Extent);
              }
              else
              {
            BoxShape boxShape = null;
            var transformedShape = Shape as TransformedShape;
            if (transformedShape != null)
              boxShape = transformedShape.Child.Shape as BoxShape;

            if (boxShape != null)
            {
              boxShape.Extent = aabb.Extent;
              ((GeometricObject)transformedShape.Child).Pose = new Pose(aabb.Center);
            }
            else
            {
              Shape = new TransformedShape(
            new GeometricObject(new BoxShape(aabb.Extent), new Pose(aabb.Center)));
            }
              }
        }
Beispiel #12
0
        public void TransformedShapeTest()
        {
            var c = new TransformedShape();

              Assert.AreEqual(0, c.GetVolume(0.1f, 10));

              c.Child = new GeometricObject(
              new BoxShape(1, 2, 3),
              new Vector3F(10, 10, 10),
              new Pose(new Vector3F(1, 2, 3), RandomHelper.Random.NextQuaternionF()));

              var v0 = c.GetVolume(0.001f, 10);

              Assert.AreEqual(10 * 20 * 30, v0);
        }
Beispiel #13
0
        private void RenderSurface(WaterNode node, CameraNode cameraNode, bool isCameraUnderwater)
        {
            var graphicsDevice = _graphicsService.GraphicsDevice;
              var projection = cameraNode.Camera.Projection;

              graphicsDevice.RasterizerState = RasterizerState.CullNone;
              //graphicsDevice.RasterizerState = isCameraUnderwater ? RasterizerState.CullClockwise : RasterizerState.CullCounterClockwise;
              //graphicsDevice.RasterizerState = GraphicsHelper.RasterizerStateWireFrame;

              graphicsDevice.DepthStencilState = node.DepthBufferWriteEnable
                                         ? DepthStencilState.Default
                                         : DepthStencilState.DepthRead;

              // TODO: Support gamma corrected LDR rendering.
              //if (context.IsHdrEnabled()) _passGamma...

              if (node.Volume != null)
              {
            // ----- Render with user-defined water volume.
            var data = ((WaterRenderData)node.RenderData);

            _parameterWorld.SetValue((Matrix)(
              node.PoseWorld
              * Matrix44F.CreateScale(node.ScaleWorld)
              * data.SubmeshMatrix));
            ApplySurfacePass(node, false);
            data.Submesh.Draw();
              }
              else if (node.Waves == null || node.Waves.DisplacementMap == null)
              {
            // ----- Infinite ocean without displacement map.
            // Draw using simple, gigantic quad.
            if (_quadSubmesh == null)
            {
              // This is the really lazy way to get a quad submesh. :-P
              var quadShape = new TransformedShape(new GeometricObject(
            new RectangleShape(1, 1),
            new Pose(Matrix33F.CreateRotationX(-ConstantsF.PiOver2)))).GetMesh(0.001f, 4);

              _quadSubmesh = MeshHelper.CreateSubmesh(graphicsDevice, quadShape, -1);
            }

            // Position the quad under the camera and choose a size large enough to cover everything.
            Vector3F position = cameraNode.PoseWorld.Position;
            position.Y = node.PoseWorld.Position.Y;

            // Add a bit to make sure that the surface is rendered above the underwater geometry.
            // Without the epsilon if the camera cuts the surface, there might be a horizontal ~1 pixel
            // line when the surface quad ends before the underwater shape.
            position.Y += Numeric.EpsilonF * 10;

            float farPlaneRadius =
              new Vector3F(Math.Max(Math.Abs(projection.Right), Math.Abs(projection.Left)),
                       Math.Max(Math.Abs(projection.Top), Math.Abs(projection.Bottom)),
                       projection.Far
                      ).Length;
            float size = 2 * farPlaneRadius;

            Matrix44F world = Matrix44F.CreateTranslation(position) * Matrix44F.CreateScale(size, 1, size);
            _parameterWorld.SetValue((Matrix)world);

            ApplySurfacePass(node, false);
            _quadSubmesh.Draw();
              }
              else
              {
            // ----- Use Projected Grid.
            if (SetProjectedGridParameters(node, cameraNode, isCameraUnderwater))
            {
              ApplySurfacePass(node, true);
              ProjectedGridParameters.Submesh.Draw();
            }
              }
        }
Beispiel #14
0
    public WaterSample(Microsoft.Xna.Framework.Game game)
      : base(game)
    {
      SampleFramework.IsMouseVisible = false;
      _graphicsScreen = new DeferredGraphicsScreen(Services);
      _graphicsScreen.DrawReticle = true;
      GraphicsService.Screens.Insert(0, _graphicsScreen);
      GameObjectService.Objects.Add(new DeferredGraphicsOptionsObject(Services));

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

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

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

      // More standard objects.
      GameObjectService.Objects.Add(new GrabObject(Services));
      GameObjectService.Objects.Add(new ObjectCreatorObject(Services));
      //GameObjectService.Objects.Add(new StaticSkyObject(Services));
      var dynamicSkyObject = new DynamicSkyObject(Services, true, false, true);
      GameObjectService.Objects.Add(dynamicSkyObject);

      // Add a ground plane with some detail to see the water refractions.
      Simulation.RigidBodies.Add(new RigidBody(new PlaneShape(new Vector3F(0, 1, 0), 0)));
      GameObjectService.Objects.Add(new StaticObject(Services, "Gravel/Gravel", 1, new Pose(new Vector3F(0, 0.001f, 0))));

      GameObjectService.Objects.Add(new DudeObject(Services));
      GameObjectService.Objects.Add(new DynamicObject(Services, 1));
      GameObjectService.Objects.Add(new DynamicObject(Services, 2));
      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 FogObject(Services) { AttachToCamera = true });

      // The LavaBalls class controls all lava ball instances.
      var lavaBalls = new LavaBallsObject(Services);
      GameObjectService.Objects.Add(lavaBalls);

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

      // Define the appearance of the water.
      var water = new Water
      {
        SpecularColor = new Vector3F(10f),

        // Small water ripples/waves are created using scrolling normal maps.
        NormalMap0 = ContentManager.Load<Texture2D>("Water/Wave0"),
        NormalMap1 = ContentManager.Load<Texture2D>("Water/Wave1"),
        NormalMap0Scale = 1.8f,
        NormalMap1Scale = 2.2f,
        NormalMap0Velocity = new Vector3F(-0.02f, 0, 0.03f),
        NormalMap1Velocity = new Vector3F(0.02f, 0, -0.03f),
        NormalMap0Strength = 0.5f,
        NormalMap1Strength = 0.5f,

        ReflectionDistortion = 0.2f,
        ReflectionColor = new Vector3F(0.7f),
        RefractionDistortion = 0.05f,
      };

      // Create a box-shaped body of water.
      // We use a TransformedShape containing a BoxShape because the top of the 
      // water body must be at height 0.
      var shape = new TransformedShape(new GeometricObject(
        new BoxShape(10, 1, 20),
        new Pose(new Vector3F(0, -0.5f, 0))));
      _waterNode0 = new WaterNode(water, shape)
      {
        PoseWorld = new Pose(new Vector3F(-1, 0.5f, 0), Matrix33F.CreateRotationY(0.1f)),
        SkyboxReflection = _graphicsScreen.Scene.GetDescendants().OfType<SkyboxNode>().First(),
        DepthBufferWriteEnable = true,
      };
      _graphicsScreen.Scene.Children.Add(_waterNode0);

      // Optional: Create a WaterFlow to move the water using a flow texture.
      _waterFlow0 = new WaterFlow
      {
        FlowMapSpeed = 0.5f,
        FlowMap = GenerateFlowMap(),
        CycleDuration = 3f,
        NoiseMapStrength = 0.1f,
        NoiseMapScale = 0.5f,
      };
      _waterNode0.Flow = _waterFlow0;

      // Optional: Use a planar reflection instead of the skybox reflection.
      // We add a PlanarReflectionNode as a child of the WaterNode.
      var renderToTexture = new RenderToTexture
      {
        Texture = new RenderTarget2D(GraphicsService.GraphicsDevice, 512, 512, false, SurfaceFormat.HdrBlendable, DepthFormat.None),
      };
      var planarReflectionNode = new PlanarReflectionNode(renderToTexture)
      {
        // Same shape as WaterNode.
        Shape = _waterNode0.Shape,

        // Reflection plane is horizontal.
        NormalLocal = new Vector3F(0, 1, 0),
      };
      _waterNode0.PlanarReflection = planarReflectionNode;
      _waterNode0.Children = new SceneNodeCollection(1) { planarReflectionNode };

      // Create a short river with an inclined water surface.
      // Using a WaterFlow with a SurfaceSlopeSpeed, the water automatically flows
      // down the inclined surface.
      _waterNode1 = new WaterNode(water, GetSpiralShape())
      {
        PoseWorld = new Pose(new Vector3F(10, 1.5f, 0), Matrix33F.CreateRotationY(0.1f)),
        EnableUnderwaterEffect = false,
        SkyboxReflection = _graphicsScreen.Scene.GetDescendants().OfType<SkyboxNode>().First(),
        Flow = new WaterFlow
        {
          SurfaceSlopeSpeed = 0.5f,
          CycleDuration = 2f,
          NoiseMapStrength = 0.1f,
          NoiseMapScale = 1,
        }
      };
      _graphicsScreen.Scene.Children.Add(_waterNode1);
    }
Beispiel #15
0
 //--------------------------------------------------------------
 /// <summary>
 /// Initializes a new instance of the <see cref="Spotlight"/> class.
 /// </summary>
 public Spotlight()
 {
     Color = Vector3F.One;
       DiffuseIntensity = 1;
       SpecularIntensity = 1;
       HdrScale = 1;
       _falloffAngle = 20.0f * ConstantsF.Pi / 180;
       Shape = new TransformedShape(new GeometricObject(new ConeShape((float)Math.Tan(MathHelper.ToRadians(30)) * 5, 5), new Pose(new Vector3F(0, 0, -5), QuaternionF.CreateRotationX(ConstantsF.PiOver2))));
       Attenuation = 2;
 }
        private void SynchronizeShape()
        {
            Debug.Assert(ParticleSystem != null);

              // Note: Scene does not allow TransformedShapes with infinite shapes.
              // --> Handle infinite shapes explicitly. (The code below only checks for InfiniteShape.
              // LineShape or PlaneShape will raise an exception in Scene!)

              if (ParticleSystem.ReferenceFrame == ParticleReferenceFrame.Local || ParticleSystem.Shape is InfiniteShape)
              {
            Shape = ParticleSystem.Shape;
              }
              else
              {
            // Particles are simulated in world space. ParticleSystem.Shape must not be scale by
            // SceneNode.ScaleWorld. --> Add a TransformedShape that negates the scale.
            var transformedShape = Shape as TransformedShape;
            if (transformedShape == null)
            {
              transformedShape = new TransformedShape(new GeometricObject());
              Shape = transformedShape;
            }

            var geometricObject = transformedShape.Child as GeometricObject;
            if (geometricObject == null)
            {
              geometricObject = new GeometricObject();
              transformedShape.Child = geometricObject;
            }

            geometricObject.Shape = ParticleSystem.Shape;
            geometricObject.Scale = Vector3F.One / ScaleWorld;
              }
        }