Exemplo n.º 1
0
    private bool _cullingEnabled = true;   // True to use frustum culling. False to disable frustum culling.


    public FrustumCullingSample(Microsoft.Xna.Framework.Game game)
      : base(game)
    {
      GraphicsScreen.ClearBackground = true;
      GraphicsScreen.BackgroundColor = Color.CornflowerBlue;

      // The top-down camera.
      var orthographicProjection = new OrthographicProjection();
      orthographicProjection.Set(
        LevelSize * 1.1f * GraphicsService.GraphicsDevice.Viewport.AspectRatio,
        LevelSize * 1.1f,
        1,
        10000f);
      var topDownCamera = new Camera(orthographicProjection);
      _topDownCameraNode = new CameraNode(topDownCamera)
      {
        View = Matrix44F.CreateLookAt(new Vector3F(0, 1000, 0), new Vector3F(0, 0, 0), -Vector3F.UnitZ),
      };

      // The perspective camera moving through the scene.
      var perspectiveProjection = new PerspectiveProjection();
      perspectiveProjection.SetFieldOfView(
        MathHelper.ToRadians(45),
        GraphicsService.GraphicsDevice.Viewport.AspectRatio,
        1,
        500);
      var sceneCamera = new Camera(perspectiveProjection);
      _sceneCameraNode = new CameraNode(sceneCamera);

      // Initialize collision detection.
      // We use one collision domain that manages all objects.
      _domain = new CollisionDomain(new CollisionDetection())
      {
        // We exchange the default broad phase with a DualPartition. The DualPartition
        // has special support for frustum culling.
        BroadPhase = new DualPartition<CollisionObject>(),
      };

      // Create a lot of random objects and add them to the collision domain.
      RandomHelper.Random = new Random(12345);
      for (int i = 0; i < NumberOfObjects; i++)
      {
        // A real scene consists of a lot of complex objects such as characters, vehicles,
        // buildings, lights, etc. When doing frustum culling we need to test each objects against
        // the viewing frustum. If it intersects with the viewing frustum, the object is visible
        // from the camera's point of view. However, in practice we do not test the exact object
        // against the viewing frustum. Each objects is approximated by a simpler shape. In our
        // example, we assume that each object is approximated with an oriented bounding box.
        // (We could also use an other shape, such as a bounding sphere.)

        // Create a random box.
        Shape randomShape = new BoxShape(RandomHelper.Random.NextVector3F(1, 10));

        // Create a random position.
        Vector3F randomPosition;
        randomPosition.X = RandomHelper.Random.NextFloat(-LevelSize / 2, LevelSize / 2);
        randomPosition.Y = RandomHelper.Random.NextFloat(0, 2);
        randomPosition.Z = RandomHelper.Random.NextFloat(-LevelSize / 2, LevelSize / 2);

        // Create a random orientation.
        QuaternionF randomOrientation = RandomHelper.Random.NextQuaternionF();

        // Create object and add it to collision domain.
        var geometricObject = new GeometricObject(randomShape, new Pose(randomPosition, randomOrientation));
        var collisionObject = new CollisionObject(geometricObject)
        {
          CollisionGroup = 0,
        };
        _domain.CollisionObjects.Add(collisionObject);
      }

      // Per default, the collision domain computes collision between all objects. 
      // In this sample we do not need this information and disable it with a collision 
      // filter.
      // In a real application, we would use this collision information for rendering,
      // for example, to find out which lights overlap with which meshes, etc.
      var filter = new CollisionFilter();
      // Disable collision between objects in collision group 0.
      filter.Set(0, 0, false);
      _domain.CollisionDetection.CollisionFilter = filter;

      // Start with the scene camera.
      GraphicsScreen.CameraNode = _sceneCameraNode;

      // We will collect a few statistics for debugging.
      Profiler.SetFormat("NoCull", 1000, "Time in ms to submit DebugRenderer draw jobs without frustum culling.");
      Profiler.SetFormat("WithCull", 1000, "Time in ms to submit DebugRenderer draw jobs with frustum culling.");
    }
Exemplo n.º 2
0
    public CollisionFilterSample(Microsoft.Xna.Framework.Game game)
      : base(game)
    {
      SampleFramework.IsMouseVisible = false;
      GraphicsScreen.ClearBackground = true;
      GraphicsScreen.BackgroundColor = Color.Gray;
      GraphicsScreen.DrawReticle = true;
      SetCamera(new Vector3F(0, 0, 10), 0, 0);

      // ----- Initialize collision detection system.
      // We use one collision domain that manages all objects.
      var domain = new CollisionDomain();

      // Let's set a filter which disables collision between object in the same collision group.
      // We can use a broad phase or a narrow phase filter:

      // Option A) Broad phase filter
      // The collision detection broad phase computes bounding box overlaps. 
      // A broad phase filter is best used if the filtering rules are simple and do not change 
      // during the runtime of your application.
      //domain.BroadPhase.Filter = new DelegatePairFilter<CollisionObject>(
      //  pair => pair.First.CollisionGroup != pair.Second.CollisionGroup);

      // Option B) Narrow phase filter
      // The collision detection narrow phase computes contacts between objects where the broad
      // phase has detected a bounding box overlap. Use a narrow phase filter if the filtering rules 
      // are complex or can change during the runtime of your application.
      var filter = new CollisionFilter();
      // Disable collision between objects in the same groups.
      filter.Set(0, 0, false);
      filter.Set(1, 1, false);
      filter.Set(2, 2, false);
      filter.Set(3, 3, false);
      domain.CollisionDetection.CollisionFilter = filter;

      // Create a random list of points.
      var points = new List<Vector3F>();
      for (int i = 0; i < 100; i++)
        points.Add(RandomHelper.Random.NextVector3F(-1.5f, 1.5f));

      // Add lots of spheres to the collision domain. Assign spheres to different collision groups.
      var random = new Random();
      var sphereShape = new SphereShape(0.7f);
      for (int i = 0; i < 20; i++)
      {
        var randomPosition = new Vector3F(random.NextFloat(-6, 6), random.NextFloat(-3, 3), 0);
        var geometricObject = new GeometricObject(sphereShape, new Pose(randomPosition));
        var collisionObject = new CollisionObject(geometricObject)
        {
          // A collision group is simply an integer. We can assign collision objects to collision
          // groups to control the collision filtering.
          CollisionGroup = random.NextInteger(0, 3),
        };
        domain.CollisionObjects.Add(collisionObject);
      }

      // Compute collisions. (The objects do not move in this sample. Therefore, we only have to 
      // call Update once.)
      domain.Update(0);

      // Draw objects. The color depends on the collision group.
      var debugRenderer = GraphicsScreen.DebugRenderer;
      debugRenderer.Clear();
      foreach (var collisionObject in domain.CollisionObjects)
      {
        Color color;
        switch (collisionObject.CollisionGroup)
        {
          case 0: color = Color.LightBlue; break;
          case 1: color = Color.Yellow; break;
          case 2: color = Color.Orange; break;
          default: color = Color.LightGreen; break;
        }

        debugRenderer.DrawObject(collisionObject.GeometricObject, color, false, false);
      }

      debugRenderer.DrawContacts(domain.ContactSets, 0.1f, Color.Red, true);
    }