/// /// <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); } }
/// /// <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); } }