示例#1
0
        protected override void OnUnload()
        {
            // Remove scene nodes from scene and dispose them.
            foreach (var node in _nodes)
            {
                if (node.Parent != null)
                {
                    node.Parent.Children.Remove(node);
                }

                node.Dispose(false);
            }

            _nodes = null;
        }
示例#2
0
    private void CreateScene()
    {
      var random = new Random(1234567);

      // 3 empty scene nodes act as the root nodes for 3 different scene graphs.
      _originalMeshNodes = new SceneNode { Children = new SceneNodeCollection() };
      _staticInstancingNodes = new SceneNode { Children = new SceneNodeCollection() };
      _staticBatchingNodes = new SceneNode { Children = new SceneNodeCollection() };

      // Load several model nodes. Each of these models contains only one mesh node.
      // Store the mesh nodes in a list.
      MeshNode[] meshNodePrototypes =
      {
        (MeshNode)ContentManager.Load<ModelNode>("Grass/Grass").Children[0],
        (MeshNode)ContentManager.Load<ModelNode>("Parviflora/Parviflora").Children[0],
        (MeshNode)ContentManager.Load<ModelNode>("PalmTree/palm_tree").Children[0],
        (MeshNode)ContentManager.Load<ModelNode>("Rock/rock_05").Children[0],
        (MeshNode)ContentManager.Load<ModelNode>("GlassBox/GlassBox").Children[0],
        (MeshNode)ContentManager.Load<ModelNode>("Building/wall_concrete_1").Children[0],
      };

      for (int meshIndex = 0; meshIndex < meshNodePrototypes.Length; meshIndex++)
      {
        var meshNode = meshNodePrototypes[meshIndex];
        var mesh = meshNode.Mesh;

        int numberOfInstances = (meshIndex == 0) ? 5000 : 200;
#else
        int numberOfInstances = (meshIndex == 0) ? 1000 : 50;


        int extent = (meshIndex < 2) ? 20 : 100;

        // Create a list of random scales and poses.
        var scales = new Vector3[numberOfInstances];
        var poses = new Pose[numberOfInstances];
        for (int i = 0; i < numberOfInstances; i++)
        {
          // Combine a random scale with the original scale of the mesh.
          scales[i] = new Vector3(random.NextFloat(0.5f, 1.2f)) * meshNode.ScaleWorld;

          // Combine a random pose with the original pose of the mesh.
          Vector3 position = new Vector3(random.NextFloat(-extent, extent), 0, random.NextFloat(-extent, extent));
          Matrix orientation = Matrix.CreateRotationY(random.NextFloat(0, ConstantsF.TwoPi));

          poses[i] = new Pose(position, orientation) * meshNode.PoseLocal;
        }

        // Strategy A or B: Create a MeshNode for each mesh instance.
        for (int i = 0; i < numberOfInstances; i++)
        {
          var clone = meshNode.Clone();
          clone.ScaleLocal = scales[i];
          clone.PoseLocal = poses[i];
          _originalMeshNodes.Children.Add(clone);
        }

        // Strategy C: Create one MeshInstancingNode which contains all instances for one mesh.
        var instances = new InstanceData[numberOfInstances];
        for (int i = 0; i < numberOfInstances; i++)
          instances[i] = new InstanceData(scales[i], poses[i], new Vector4(1));

        // Create MeshInstancingNode.
        var instancingMeshNode = new MeshInstancingNode<InstanceData>(mesh, instances)
        {
          // It is recommended to manually set a suitable pose and shape, so that
          // the bounding shape contains all instances.
          PoseLocal = new Pose(new Vector3(0, 2, 0)),
          Shape = new BoxShape(2 * extent, 4, 2 * extent),
        };
        _staticInstancingNodes.Children.Add(instancingMeshNode);

        // Strategy D: We merge all instances of the mesh into one huge static mesh.
        var mergedMesh = MeshHelper.Merge(mesh, scales, poses);
        _staticBatchingNodes.Children.Add(new MeshNode(mergedMesh));
      }

      // For static batching, instead of creating one merged mesh per mesh type,
      // we could also merge all mesh instances into a single huge static mesh.
      //var mergedMesh = MeshHelper.Merge(_originalMeshNodes.Children);
      //_staticBatchingNodes = new MeshNode(mergedMesh);
    }
示例#3
0
    protected override void OnUnload()
    {
      // Remove scene nodes from scene and dispose them.
      foreach (var node in _nodes)
      {
        if (node.Parent != null)
          node.Parent.Children.Remove(node);

        node.Dispose(false);
      }

      _nodes = null;
    }
示例#4
0
    protected override void OnLoad()
    {
      _scene = _services.GetInstance<IScene>();

      // Get a bounding shape for the cells. We use a box with the cell size and
      // make it bigger by some arbitrary values. The boxes must be bigger because
      // mesh instances can be placed on the cell boundary and when they are animated
      // tree branches can sway outside the cell bounds.
      var meshAabb = _mesh.BoundingShape.GetAabb();
      float meshWidth = new Vector2F(meshAabb.Extent.X, meshAabb.Extent.Z).Length * 1.5f;
      float meshHeight = meshAabb.Extent.Y * 1.7f;
      var boxShape = new BoxShape(_cellSize + meshWidth, meshHeight, _cellSize + meshWidth);

      // Create one MeshInstancingNode per cell and add random instances.
      _nodes = new MeshInstancingNode<InstanceData>[_numberOfCellsX, _numberOfCellsZ];
      float xOrigin = -(_numberOfCellsX * _cellSize) / 2;
      float zOrigin = -(_numberOfCellsZ * _cellSize) / 2;
      var random = new Random(_randomSeed);
      for (int x = 0; x < _numberOfCellsX; x++)
      {
        for (int z = 0; z < _numberOfCellsZ; z++)
        {
          var instances = new InstanceData[_numberOfInstancesPerCell];
          for (int i = 0; i < instances.Length; i++)
          {
            Vector3F scale = new Vector3F(random.NextFloat(0.5f, 1.5f));
            Pose pose = new Pose(new Vector3F(xOrigin + x * _cellSize + random.NextFloat(0, _cellSize),
                                              0,
                                              zOrigin + z * _cellSize + random.NextFloat(0, _cellSize)),
                                 Matrix33F.CreateRotationY(random.NextFloat(0, 10)));
            Vector4F color = new Vector4F(1);

            instances[i] = new InstanceData(scale, pose, color);
          }

          _nodes[x, z] = new MeshInstancingNode<InstanceData>(_mesh, instances)
          {
            PoseLocal = new Pose(new Vector3F(xOrigin + (0.5f + x) * _cellSize, 
                                              boxShape.WidthY / 2, 
                                              zOrigin + (0.5f + z) * _cellSize)),
            Shape = boxShape,
            CastsShadows = _castsShadows,
          };
          _scene.Children.Add(_nodes[x, z]);
        }
      }

      UpdateLodDistances();

      // ----- Add GUI controls to the Options window.
      var sampleFramework = _services.GetInstance<SampleFramework>();
      var optionsPanel = sampleFramework.AddOptions("Game Objects");
      var panel = SampleHelper.AddGroupBox(optionsPanel, "VegetationObject " + Name);

      SampleHelper.AddSlider(
        panel,
        "Min distance",
        "F2",
        0,
        100,
        MinDistance,
        value => MinDistance = value);

      SampleHelper.AddSlider(
        panel,
        "Max distance",
        "F2",
        0,
        100,
        MaxDistance,
        value => MaxDistance = value);
    }
示例#5
0
        protected override void OnLoad()
        {
            _scene = _services.GetInstance <IScene>();

            // Get a bounding shape for the cells. We use a box with the cell size and
            // make it bigger by some arbitrary values. The boxes must be bigger because
            // mesh instances can be placed on the cell boundary and when they are animated
            // tree branches can sway outside the cell bounds.
            var   meshAabb   = _mesh.BoundingShape.GetAabb();
            float meshWidth  = new Vector2F(meshAabb.Extent.X, meshAabb.Extent.Z).Length * 1.5f;
            float meshHeight = meshAabb.Extent.Y * 1.7f;
            var   boxShape   = new BoxShape(_cellSize + meshWidth, meshHeight, _cellSize + meshWidth);

            // Create one MeshInstancingNode per cell and add random instances.
            _nodes = new MeshInstancingNode <InstanceData> [_numberOfCellsX, _numberOfCellsZ];
            float xOrigin = -(_numberOfCellsX * _cellSize) / 2;
            float zOrigin = -(_numberOfCellsZ * _cellSize) / 2;
            var   random  = new Random(_randomSeed);

            for (int x = 0; x < _numberOfCellsX; x++)
            {
                for (int z = 0; z < _numberOfCellsZ; z++)
                {
                    var instances = new InstanceData[_numberOfInstancesPerCell];
                    for (int i = 0; i < instances.Length; i++)
                    {
                        Vector3F scale = new Vector3F(random.NextFloat(0.5f, 1.5f));
                        Pose     pose  = new Pose(new Vector3F(xOrigin + x * _cellSize + random.NextFloat(0, _cellSize),
                                                               0,
                                                               zOrigin + z * _cellSize + random.NextFloat(0, _cellSize)),
                                                  Matrix33F.CreateRotationY(random.NextFloat(0, 10)));
                        Vector4F color = new Vector4F(1);

                        instances[i] = new InstanceData(scale, pose, color);
                    }

                    _nodes[x, z] = new MeshInstancingNode <InstanceData>(_mesh, instances)
                    {
                        PoseLocal = new Pose(new Vector3F(xOrigin + (0.5f + x) * _cellSize,
                                                          boxShape.WidthY / 2,
                                                          zOrigin + (0.5f + z) * _cellSize)),
                        Shape        = boxShape,
                        CastsShadows = _castsShadows,
                    };
                    _scene.Children.Add(_nodes[x, z]);
                }
            }

            UpdateLodDistances();

            // ----- Add GUI controls to the Options window.
            var sampleFramework = _services.GetInstance <SampleFramework>();
            var optionsPanel    = sampleFramework.AddOptions("Game Objects");
            var panel           = SampleHelper.AddGroupBox(optionsPanel, "VegetationObject " + Name);

            SampleHelper.AddSlider(
                panel,
                "Min distance",
                "F2",
                0,
                100,
                MinDistance,
                value => MinDistance = value);

            SampleHelper.AddSlider(
                panel,
                "Max distance",
                "F2",
                0,
                100,
                MaxDistance,
                value => MaxDistance = value);
        }
示例#6
0
    private void CreateScene()
    {
      var random = new Random(1234567);

      // 3 empty scene nodes act as the root nodes for 3 different scene graphs.
      _originalMeshNodes = new SceneNode { Children = new SceneNodeCollection() };
      _staticInstancingNodes = new SceneNode { Children = new SceneNodeCollection() };
      _staticBatchingNodes = new SceneNode { Children = new SceneNodeCollection() };

      // Load several model nodes. Each of these models contains only one mesh node.
      // Store the mesh nodes in a list.
      MeshNode[] meshNodePrototypes =
      {
        (MeshNode)ContentManager.Load<ModelNode>("Grass/Grass").Children[0],
        (MeshNode)ContentManager.Load<ModelNode>("Parviflora/Parviflora").Children[0],
        (MeshNode)ContentManager.Load<ModelNode>("PalmTree/palm_tree").Children[0],
        (MeshNode)ContentManager.Load<ModelNode>("Rock/rock_05").Children[0],
        (MeshNode)ContentManager.Load<ModelNode>("GlassBox/GlassBox").Children[0],
        (MeshNode)ContentManager.Load<ModelNode>("Building/wall_concrete_1").Children[0],
      };

      for (int meshIndex = 0; meshIndex < meshNodePrototypes.Length; meshIndex++)
      {
        var meshNode = meshNodePrototypes[meshIndex];
        var mesh = meshNode.Mesh;
#if WINDOWS
        int numberOfInstances = (meshIndex == 0) ? 5000 : 200;
#else
        int numberOfInstances = (meshIndex == 0) ? 1000 : 50;
#endif

        int extent = (meshIndex < 2) ? 20 : 100;

        // Create a list of random scales and poses.
        var scales = new Vector3F[numberOfInstances];
        var poses = new Pose[numberOfInstances];
        for (int i = 0; i < numberOfInstances; i++)
        {
          // Combine a random scale with the original scale of the mesh.
          scales[i] = new Vector3F(random.NextFloat(0.5f, 1.2f)) * meshNode.ScaleWorld;

          // Combine a random pose with the original pose of the mesh.
          Vector3F position = new Vector3F(random.NextFloat(-extent, extent), 0, random.NextFloat(-extent, extent));
          Matrix33F orientation = Matrix33F.CreateRotationY(random.NextFloat(0, ConstantsF.TwoPi));

          poses[i] = new Pose(position, orientation) * meshNode.PoseLocal;
        }

        // Strategy A or B: Create a MeshNode for each mesh instance.
        for (int i = 0; i < numberOfInstances; i++)
        {
          var clone = meshNode.Clone();
          clone.ScaleLocal = scales[i];
          clone.PoseLocal = poses[i];
          _originalMeshNodes.Children.Add(clone);
        }

        // Strategy C: Create one MeshInstancingNode which contains all instances for one mesh.
        var instances = new InstanceData[numberOfInstances];
        for (int i = 0; i < numberOfInstances; i++)
          instances[i] = new InstanceData(scales[i], poses[i], new Vector4F(1));

        // Create MeshInstancingNode.
        var instancingMeshNode = new MeshInstancingNode<InstanceData>(mesh, instances)
        {
          // It is recommended to manually set a suitable pose and shape, so that
          // the bounding shape contains all instances.
          PoseLocal = new Pose(new Vector3F(0, 2, 0)),
          Shape = new BoxShape(2 * extent, 4, 2 * extent),
        };
        _staticInstancingNodes.Children.Add(instancingMeshNode);

        // Strategy D: We merge all instances of the mesh into one huge static mesh.
        var mergedMesh = MeshHelper.Merge(mesh, scales, poses);
        _staticBatchingNodes.Children.Add(new MeshNode(mergedMesh));
      }

      // For static batching, instead of creating one merged mesh per mesh type,
      // we could also merge all mesh instances into a single huge static mesh.
      //var mergedMesh = MeshHelper.Merge(_originalMeshNodes.Children);
      //_staticBatchingNodes = new MeshNode(mergedMesh);
    }