예제 #1
0
        /// 
        /// <summary>
        /// Add a new cluster to the set of clusters which are getting rendered.  If the cluster has already been added, this is effectively a no-op
        /// </summary>
        /// 
        /// <param name="clusterBaseWorldPosition">
        /// The base position of the cluster in world coordaintes (i.e. the minimum corner of the cluster bounding box)
        /// </param>
        /// 
        /// <param name="clusterIndex">
        /// The integer ID of the cluster, used to index into lists of cluster specific data
        /// </param>
        /// 
        /// <param name="clusterCubeIndices">
        /// An array of indices into the input cubes list indicating which cubes make up a given cluster.  The array is 4 dimensional
        /// where array[clusterIndex, x, y, z] will get you the index of the cube at local grid position  x, y, z in the cluster (or
        /// -1 if there is no cube in that grid position)
        /// </param>
        /// 
        /// <param name="cubes">
        /// A master list of cubes that the clusterCubeIndices references
        /// </param>
        /// 
        /// <param name="graphicsDevice">
        /// A graphics device instance, needed to build up vertex buffer objects in advance
        /// </param>
        /// 
        public void AddActiveCluster(Vector3 clusterBaseWorldPosition, int clusterIndex, int[, , ,] clusterCubeIndices, Model[] cubes, GraphicsDevice graphicsDevice)
        {
            // Do nothing if the cluster has already been added
            if (_clusterRenderData.ContainsKey(clusterIndex))
            {
                return;
            }

            RenderData renderData = new RenderData();
            _clusterRenderData.Add(clusterIndex, renderData);

            BoundingBox clusterBoundingBox = new BoundingBox(
                new Vector3(
                    -(_cubeSize * _clusterXDimension / 2),
                    -(_cubeSize * _clusterYDimension / 2),
                    -(_cubeSize * _clusterZDimension / 2)),
                new Vector3(
                    _cubeSize * _clusterXDimension / 2,
                    _cubeSize * _clusterYDimension / 2,
                    _cubeSize * _clusterZDimension / 2));

            Vector3 clusterCentroid = clusterBaseWorldPosition + new Vector3(_clusterXDimension, _clusterYDimension, _clusterZDimension) * _cubeSize / 2;

            Octrees.Add(clusterIndex, new Octree(clusterBoundingBox, clusterCentroid));

            // Build up the different positions of each model used within a cluster
            ModelData clusterModelData = new ModelData();

            for (int x = 0; x < _clusterXDimension; ++x)
            {
                for (int y = 0; y < _clusterYDimension; ++y)
                {
                    for (int z = 0; z < _clusterZDimension; ++z)
                    {
                        int modelIndex = clusterCubeIndices[clusterIndex, x, y, z];

                        if (modelIndex != -1)
                        {
                            Model model = cubes[modelIndex];
                            int clusterModelIndex = clusterModelData.FindIndex(model);

                            if (clusterModelIndex == -1)
                            {
                                clusterModelData.Add(model, new List<Vector3>());
                                clusterModelIndex = clusterModelData.Count - 1;
                            }

                            clusterModelData.ModelPositions(clusterModelIndex).Add(new Vector3(
                                clusterBaseWorldPosition.X + (x * _cubeSize),
                                clusterBaseWorldPosition.Y + (y * _cubeSize),
                                clusterBaseWorldPosition.Z + (z * _cubeSize)));
                        }
                    }
                }
            }

            List<BoundingBox> boundingBoxes = new List<BoundingBox>();
            List<Vector3> cubePositions = new List<Vector3>();

            for (int modelIndex = 0; modelIndex < clusterModelData.Count; ++modelIndex)
            {
                Model model = clusterModelData.Models(modelIndex);
                List<Vector3> positions = clusterModelData.ModelPositions(modelIndex);

                List<VertexPositionNormalTexture> vertices;
                List<int> indices;
                GetModelVerticesAndIndices(model, out vertices, out indices);

                List<VertexPositionNormalTexture> finalVertices = new List<VertexPositionNormalTexture>();
                List<int> finalIndices = new List<int>();
                int vertexCount = vertices.Count;
                foreach (Vector3 position in positions)
                {
                    VertexPositionNormalTexture[] translatedCopy = new VertexPositionNormalTexture[vertices.Count];
                    vertices.CopyTo(translatedCopy);

                    Matrix translation = Matrix.CreateTranslation((position) + Vector3.One);
                    Vector3[] translatedPositions = new Vector3[translatedCopy.Length];
                    for (int i = 0; i < translatedCopy.Length; ++i)
                    {
                        translatedCopy[i].Position = Vector3.Transform(translatedCopy[i].Position, translation);
                        translatedPositions[i] = translatedCopy[i].Position;
                    }

                    boundingBoxes.Add(BoundingBox.CreateFromPoints(translatedPositions));
                    cubePositions.Add(position);

                    finalIndices.AddRange(indices);

                    for (int i = 0; i < indices.Count(); ++i)
                    {
                        indices[i] += (int)vertexCount;
                    }

                    finalVertices.AddRange(translatedCopy);
                }

                VertexBuffer newVertexBuffer = new VertexBuffer(graphicsDevice, typeof(VertexPositionNormalTexture), finalVertices.Count, BufferUsage.None);
                newVertexBuffer.SetData<VertexPositionNormalTexture>(finalVertices.ToArray());

                IndexBuffer newIndexBuffer = new IndexBuffer(graphicsDevice, typeof(int), finalIndices.Count, BufferUsage.None);
                newIndexBuffer.SetData<int>(finalIndices.ToArray());

                renderData.AddData(newVertexBuffer, newIndexBuffer, model);
            }

            Octrees[clusterIndex].AddItems(cubePositions.ToArray(), boundingBoxes.ToArray());
            int count = Octrees[clusterIndex].Count;

            _allModels.Clear();
            _allVertexBuffers.Clear();
            _allIndexBuffers.Clear();

            foreach (RenderData data in _clusterRenderData.Values)
            {
                ReadOnlyCollection<Model> models;
                ReadOnlyCollection<VertexBuffer> vertexBuffers;
                ReadOnlyCollection<IndexBuffer> indexBuffers;

                data.GetData(out vertexBuffers, out indexBuffers, out models);

                _allModels.AddRange(models);
                _allVertexBuffers.AddRange(vertexBuffers);
                _allIndexBuffers.AddRange(indexBuffers);
            }
        }
예제 #2
0
        ///
        /// <summary>
        /// Add a new cluster to the set of clusters which are getting rendered.  If the cluster has already been added, this is effectively a no-op
        /// </summary>
        ///
        /// <param name="clusterBaseWorldPosition">
        /// The base position of the cluster in world coordaintes (i.e. the minimum corner of the cluster bounding box)
        /// </param>
        ///
        /// <param name="clusterIndex">
        /// The integer ID of the cluster, used to index into lists of cluster specific data
        /// </param>
        ///
        /// <param name="clusterCubeIndices">
        /// An array of indices into the input cubes list indicating which cubes make up a given cluster.  The array is 4 dimensional
        /// where array[clusterIndex, x, y, z] will get you the index of the cube at local grid position  x, y, z in the cluster (or
        /// -1 if there is no cube in that grid position)
        /// </param>
        ///
        /// <param name="cubes">
        /// A master list of cubes that the clusterCubeIndices references
        /// </param>
        ///
        /// <param name="graphicsDevice">
        /// A graphics device instance, needed to build up vertex buffer objects in advance
        /// </param>
        ///
        public void AddActiveCluster(Vector3 clusterBaseWorldPosition, int clusterIndex, int[, , ,] clusterCubeIndices, Model[] cubes, GraphicsDevice graphicsDevice)
        {
            // Do nothing if the cluster has already been added
            if (_clusterRenderData.ContainsKey(clusterIndex))
            {
                return;
            }

            RenderData renderData = new RenderData();

            _clusterRenderData.Add(clusterIndex, renderData);

            BoundingBox clusterBoundingBox = new BoundingBox(
                new Vector3(
                    -(_cubeSize * _clusterXDimension / 2),
                    -(_cubeSize * _clusterYDimension / 2),
                    -(_cubeSize * _clusterZDimension / 2)),
                new Vector3(
                    _cubeSize * _clusterXDimension / 2,
                    _cubeSize * _clusterYDimension / 2,
                    _cubeSize * _clusterZDimension / 2));

            Vector3 clusterCentroid = clusterBaseWorldPosition + new Vector3(_clusterXDimension, _clusterYDimension, _clusterZDimension) * _cubeSize / 2;

            Octrees.Add(clusterIndex, new Octree(clusterBoundingBox, clusterCentroid));

            // Build up the different positions of each model used within a cluster
            ModelData clusterModelData = new ModelData();

            for (int x = 0; x < _clusterXDimension; ++x)
            {
                for (int y = 0; y < _clusterYDimension; ++y)
                {
                    for (int z = 0; z < _clusterZDimension; ++z)
                    {
                        int modelIndex = clusterCubeIndices[clusterIndex, x, y, z];

                        if (modelIndex != -1)
                        {
                            Model model             = cubes[modelIndex];
                            int   clusterModelIndex = clusterModelData.FindIndex(model);

                            if (clusterModelIndex == -1)
                            {
                                clusterModelData.Add(model, new List <Vector3>());
                                clusterModelIndex = clusterModelData.Count - 1;
                            }

                            clusterModelData.ModelPositions(clusterModelIndex).Add(new Vector3(
                                                                                       clusterBaseWorldPosition.X + (x * _cubeSize),
                                                                                       clusterBaseWorldPosition.Y + (y * _cubeSize),
                                                                                       clusterBaseWorldPosition.Z + (z * _cubeSize)));
                        }
                    }
                }
            }

            List <BoundingBox> boundingBoxes = new List <BoundingBox>();
            List <Vector3>     cubePositions = new List <Vector3>();

            for (int modelIndex = 0; modelIndex < clusterModelData.Count; ++modelIndex)
            {
                Model          model     = clusterModelData.Models(modelIndex);
                List <Vector3> positions = clusterModelData.ModelPositions(modelIndex);

                List <VertexPositionNormalTexture> vertices;
                List <int> indices;
                GetModelVerticesAndIndices(model, out vertices, out indices);

                List <VertexPositionNormalTexture> finalVertices = new List <VertexPositionNormalTexture>();
                List <int> finalIndices = new List <int>();
                int        vertexCount  = vertices.Count;
                foreach (Vector3 position in positions)
                {
                    VertexPositionNormalTexture[] translatedCopy = new VertexPositionNormalTexture[vertices.Count];
                    vertices.CopyTo(translatedCopy);

                    Matrix    translation         = Matrix.CreateTranslation((position) + Vector3.One);
                    Vector3[] translatedPositions = new Vector3[translatedCopy.Length];
                    for (int i = 0; i < translatedCopy.Length; ++i)
                    {
                        translatedCopy[i].Position = Vector3.Transform(translatedCopy[i].Position, translation);
                        translatedPositions[i]     = translatedCopy[i].Position;
                    }

                    boundingBoxes.Add(BoundingBox.CreateFromPoints(translatedPositions));
                    cubePositions.Add(position);

                    finalIndices.AddRange(indices);

                    for (int i = 0; i < indices.Count(); ++i)
                    {
                        indices[i] += (int)vertexCount;
                    }

                    finalVertices.AddRange(translatedCopy);
                }

                VertexBuffer newVertexBuffer = new VertexBuffer(graphicsDevice, typeof(VertexPositionNormalTexture), finalVertices.Count, BufferUsage.None);
                newVertexBuffer.SetData <VertexPositionNormalTexture>(finalVertices.ToArray());

                IndexBuffer newIndexBuffer = new IndexBuffer(graphicsDevice, typeof(int), finalIndices.Count, BufferUsage.None);
                newIndexBuffer.SetData <int>(finalIndices.ToArray());

                renderData.AddData(newVertexBuffer, newIndexBuffer, model);
            }

            Octrees[clusterIndex].AddItems(cubePositions.ToArray(), boundingBoxes.ToArray());
            int count = Octrees[clusterIndex].Count;

            _allModels.Clear();
            _allVertexBuffers.Clear();
            _allIndexBuffers.Clear();

            foreach (RenderData data in _clusterRenderData.Values)
            {
                ReadOnlyCollection <Model>        models;
                ReadOnlyCollection <VertexBuffer> vertexBuffers;
                ReadOnlyCollection <IndexBuffer>  indexBuffers;

                data.GetData(out vertexBuffers, out indexBuffers, out models);

                _allModels.AddRange(models);
                _allVertexBuffers.AddRange(vertexBuffers);
                _allIndexBuffers.AddRange(indexBuffers);
            }
        }