Beispiel #1
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);
    }
Beispiel #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;
#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);
    }