public void DrawInstancedModels(Camera camera, List <ModelData> modelsData, float?alphaThreshold) { ModelShader modelShader = alphaThreshold.HasValue ? m_shaderAlphaTested : m_shaderOpaque; modelShader.LightDirection1 = -Vector3.TransformNormal(LightingManager.DirectionToLight1, camera.ViewMatrix); modelShader.LightDirection2 = -Vector3.TransformNormal(LightingManager.DirectionToLight2, camera.ViewMatrix); modelShader.FogColor = new Vector3(m_subsystemSky.ViewFogColor); modelShader.FogStartInvLength = new Vector2(m_subsystemSky.ViewFogRange.X, 1f / (m_subsystemSky.ViewFogRange.Y - m_subsystemSky.ViewFogRange.X)); modelShader.FogYMultiplier = m_subsystemSky.VisibilityRangeYMultiplier; modelShader.WorldUp = Vector3.TransformNormal(Vector3.UnitY, camera.ViewMatrix); modelShader.Transforms.View = Matrix.Identity; modelShader.Transforms.Projection = camera.ProjectionMatrix; modelShader.SamplerState = SamplerState.PointClamp; if (alphaThreshold.HasValue) { modelShader.AlphaThreshold = alphaThreshold.Value; } foreach (ModelData modelsDatum in modelsData) { ComponentModel componentModel = modelsDatum.ComponentModel; Vector3 v = componentModel.DiffuseColor.HasValue ? componentModel.DiffuseColor.Value : Vector3.One; float num = componentModel.Opacity.HasValue ? componentModel.Opacity.Value : 1f; modelShader.InstancesCount = componentModel.AbsoluteBoneTransformsForCamera.Length; modelShader.MaterialColor = new Vector4(v * num, num); modelShader.EmissionColor = (componentModel.EmissionColor.HasValue ? componentModel.EmissionColor.Value : Vector4.Zero); modelShader.AmbientLightColor = new Vector3(LightingManager.LightAmbient * modelsDatum.Light); modelShader.DiffuseLightColor1 = new Vector3(modelsDatum.Light); modelShader.DiffuseLightColor2 = new Vector3(modelsDatum.Light); modelShader.Texture = componentModel.TextureOverride; Array.Copy(componentModel.AbsoluteBoneTransformsForCamera, modelShader.Transforms.World, componentModel.AbsoluteBoneTransformsForCamera.Length); InstancedModelData instancedModelData = InstancedModelsManager.GetInstancedModelData(componentModel.Model, componentModel.MeshDrawOrders); Display.DrawIndexed(PrimitiveType.TriangleList, modelShader, instancedModelData.VertexBuffer, instancedModelData.IndexBuffer, 0, instancedModelData.IndexBuffer.IndicesCount); ModelsDrawn++; } }
public static InstancedModelData CreateInstancedModelData(Model model, int[] meshDrawOrders) { DynamicArray <InstancedVertex> dynamicArray = new DynamicArray <InstancedVertex>(); DynamicArray <ushort> dynamicArray2 = new DynamicArray <ushort>(); for (int i = 0; i < meshDrawOrders.Length; i++) { ModelMesh modelMesh = model.Meshes[meshDrawOrders[i]]; foreach (ModelMeshPart meshPart in modelMesh.MeshParts) { _ = dynamicArray.Count; VertexBuffer vertexBuffer = meshPart.VertexBuffer; IndexBuffer indexBuffer = meshPart.IndexBuffer; ReadOnlyList <VertexElement> vertexElements = vertexBuffer.VertexDeclaration.VertexElements; ushort[] indexData = BlockMesh.GetIndexData <ushort>(indexBuffer); Dictionary <ushort, ushort> dictionary = new Dictionary <ushort, ushort>(); if (vertexElements.Count != 3 || vertexElements[0].Offset != 0 || !(vertexElements[0].Semantic == VertexElementSemantic.Position.GetSemanticString()) || vertexElements[1].Offset != 12 || !(vertexElements[1].Semantic == VertexElementSemantic.Normal.GetSemanticString()) || vertexElements[2].Offset != 24 || !(vertexElements[2].Semantic == VertexElementSemantic.TextureCoordinate.GetSemanticString())) { throw new InvalidOperationException("Unsupported vertex format."); } SourceModelVertex[] vertexData = BlockMesh.GetVertexData <SourceModelVertex>(vertexBuffer); for (int j = meshPart.StartIndex; j < meshPart.StartIndex + meshPart.IndicesCount; j++) { ushort num = indexData[j]; if (!dictionary.ContainsKey(num)) { dictionary.Add(num, (ushort)dynamicArray.Count); InstancedVertex item = default(InstancedVertex); SourceModelVertex sourceModelVertex = vertexData[num]; item.X = sourceModelVertex.X; item.Y = sourceModelVertex.Y; item.Z = sourceModelVertex.Z; item.Nx = sourceModelVertex.Nx; item.Ny = sourceModelVertex.Ny; item.Nz = sourceModelVertex.Nz; item.Tx = sourceModelVertex.Tx; item.Ty = sourceModelVertex.Ty; item.Instance = modelMesh.ParentBone.Index; dynamicArray.Add(item); } } for (int k = 0; k < meshPart.IndicesCount / 3; k++) { dynamicArray2.Add(dictionary[indexData[meshPart.StartIndex + 3 * k]]); dynamicArray2.Add(dictionary[indexData[meshPart.StartIndex + 3 * k + 1]]); dynamicArray2.Add(dictionary[indexData[meshPart.StartIndex + 3 * k + 2]]); } } } InstancedModelData instancedModelData = new InstancedModelData(); instancedModelData.VertexBuffer = new VertexBuffer(InstancedModelData.VertexDeclaration, dynamicArray.Count); instancedModelData.IndexBuffer = new IndexBuffer(IndexFormat.SixteenBits, dynamicArray2.Count); instancedModelData.VertexBuffer.SetData(dynamicArray.Array, 0, dynamicArray.Count); instancedModelData.IndexBuffer.SetData(dynamicArray2.Array, 0, dynamicArray2.Count); return(instancedModelData); }