public static bool VerifyVertexStruct <T>(VertexRuntimeTypes vertexType) where T : struct { string typeName = typeof(T).Name; string enumName = vertexType.ToString(); return(typeName.Equals(enumName)); }
//TODO: Refactor renderFlag preEffectsInstancingFlag and instancingFlag into an class/struct public ModelRuntimeDescriptor(Model <T, RealtimeMaterial> modelIn, string vShaderName, string fShaderName, VertexRuntimeTypes vertexRuntimeType, PrimitiveTopology primitiveTopology, RenderDescription renderDescription, InstancingRenderDescription instancingRenderDescription) { if (!Verifier.VerifyVertexStruct <T>(vertexRuntimeType)) { throw new ArgumentException($"Type Mismatch ModelRuntimeDescriptor"); } Model = modelIn; Length = modelIn.MeshCount; TotalInstanceCount = 1; _vertexShaderName = vShaderName; _fragmentShaderName = fShaderName; VertexRuntimeType = vertexRuntimeType; PrimitiveTopology = primitiveTopology; RenderDescription = renderDescription; PreEffectsFlag = RenderFlags.PRE_EFFECTS_MASK & renderDescription.RenderModeFlag; PreEffectsInstancingFlag = instancingRenderDescription.PreEffectsFlag; InstancingDataFlag = instancingRenderDescription.RenderModeFlag; var preEffectsInstancing = RenderFlags.GetAllPreEffectFor(PreEffectsInstancingFlag); VertexBufferList = new List <DeviceBuffer>(); IndexBufferList = new List <DeviceBuffer>(); Pipelines = new Pipeline[RenderFlags.EFFCTS_TOTAL_COUNT]; InstanceBufferLists = new List <DeviceBuffer> [RenderFlags.EFFCTS_TOTAL_COUNT]; InstanceBufferLists[RenderFlags.NORMAL_ARRAY_INDEX] = new List <DeviceBuffer>(); foreach (var preEffect in preEffectsInstancing) { InstanceBufferLists[RenderFlags.GetArrayIndexForFlag(preEffect)] = new List <DeviceBuffer>(); } InstanceBuffers = new DeviceBuffer[RenderFlags.EFFCTS_TOTAL_COUNT][]; TextureResourceSetsList = new List <ResourceSet>(); VertexInstanceLayoutGenerationList = new EventHandlerList(); VertexPreEffectsInstanceLayoutGenerationList = new EventHandlerList(); VertexPreEffectShaders = new Shader[RenderFlags.PRE_EFFCTS_TOTAL_COUNT]; GeometryPreEffectShaders = new Shader[RenderFlags.PRE_EFFCTS_TOTAL_COUNT]; FragmentPreEffectShaders = new Shader[RenderFlags.PRE_EFFCTS_TOTAL_COUNT]; // Reserve first spot for base vertex geometry //TODO: Make on list VertexLayouts = new VertexLayoutDescription[InstancingDataFlags.GetSizeOfPreEffectFlag(InstancingDataFlag) + 1]; VertexPreEffectsLayouts = new VertexLayoutDescription[RenderFlags.GetSizeOfPreEffectFlag(PreEffectsInstancingFlag) + 1]; EffectResourceSets = new ResourceSet[RenderFlags.EFFCTS_TOTAL_COUNT][]; for (int i = 0; i < RenderFlags.EFFCTS_TOTAL_COUNT; i++) { EffectResourceSets[i] = new ResourceSet[0]; } }
public static void GenerateRenderCommandsForModelDescriptor <T>(CommandList commandList, ModelRuntimeDescriptor <T>[] descriptorArray, SceneRuntimeDescriptor sceneRuntimeDescriptor, RenderDescription renderDescription, VertexRuntimeTypes vertexRuntimeType) where T : struct, VertexLocateable { for (int j = 0; j < descriptorArray.Length; j++) { var modelState = descriptorArray[j]; var modelRenderFlag = modelState.RenderDescription.RenderModeFlag; var currentRenderState = modelRenderFlag & renderDescription.RenderModeFlag; if (currentRenderState == RenderFlags.NONE) { continue; } var renderStateArrayIndex = RenderFlags.GetArrayIndexForFlag(currentRenderState); commandList.SetPipeline(modelState.Pipelines[renderStateArrayIndex]); var effectsInstanceBuffer = modelState.InstanceBuffers[renderStateArrayIndex]; // We assume one other vertex buffer has been bound or will be bound. for (int i = 0; i < effectsInstanceBuffer.Length; i++) { commandList.SetVertexBuffer(i.ToUnsigned() + 1, effectsInstanceBuffer[i]); } var effectSets = modelState.EffectResourceSets[renderStateArrayIndex]; var model = modelState.Model; for (int i = 0; i < model.MeshCount; i++) { if (!model.GetMeshBVH(i).AABBIsValid) { continue; } var mesh = model.GetMesh(i); var material = model.GetMaterial(i); //TODO: @Investiagte this if ((renderDescription.RenderModeFlag & RenderFlags.SHADOW_MAP) == RenderFlags.SHADOW_MAP || (renderDescription.RenderModeFlag & RenderFlags.OMNI_SHADOW_MAPS) == RenderFlags.OMNI_SHADOW_MAPS || vertexRuntimeType == VertexRuntimeTypes.VertexPositionColor) { RenderCommandGenerator.GenerateCommandsForMesh_Inline( commandList, modelState, i, sceneRuntimeDescriptor, effectSets, mesh, modelState.TotalInstanceCount ); } else { switch (vertexRuntimeType) { case VertexRuntimeTypes.VertexPosition: RenderCommandGenerator.GenerateCommandsForP_Inline( commandList, modelState as ModelRuntimeDescriptor <VertexPosition>, i, sceneRuntimeDescriptor, effectSets, mesh as Mesh <VertexPosition>, modelState.TotalInstanceCount ); break; case VertexRuntimeTypes.VertexPositionTexture: RenderCommandGenerator.GenerateCommandsForPT_Inline( commandList, modelState as ModelRuntimeDescriptor <VertexPositionTexture>, i, sceneRuntimeDescriptor, effectSets, mesh as Mesh <VertexPositionTexture>, modelState.TotalInstanceCount ); break; case VertexRuntimeTypes.VertexPositionNormal: RenderCommandGenerator.GenerateCommandsForPN_Inline( commandList, modelState as ModelRuntimeDescriptor <VertexPositionNormal>, i, sceneRuntimeDescriptor, effectSets, material, mesh as Mesh <VertexPositionNormal>, modelState.TotalInstanceCount ); break; case VertexRuntimeTypes.VertexPositionNormalTextureTangentBitangent: RenderCommandGenerator.GenerateCommandsForPNTTB_Inline( commandList, modelState as ModelRuntimeDescriptor <VertexPositionNormalTextureTangentBitangent>, i, sceneRuntimeDescriptor, effectSets, material, mesh as Mesh <VertexPositionNormalTextureTangentBitangent>, modelState.TotalInstanceCount ); break; default: var errorStr = "Type: " + typeof(T).Name + " not implemented"; throw new System.NotImplementedException(errorStr); } } } } }
public static LoadedModels <RealtimeMaterial> LoadRealtimeModelsFromFile(string baseDirectory, string localPath, PostProcessSteps flags = DefaultPostProcessSteps) { string filePath = Path.Combine(baseDirectory, localPath); string[] directoryStructure = localPath.Split('/'); string modelDir = directoryStructure[0]; AssimpContext assimpContext = new AssimpContext(); Assimp.Scene pScene = assimpContext.ImportFile(filePath, flags); //TODO: Identify meshcount for each vertex type. Have to preprocess int meshCount = pScene.MeshCount; var loadedMeshCounts = pScene.GetHenzaiMeshCounts(); int meshCountP = loadedMeshCounts.meshCountP; int meshCountPC = loadedMeshCounts.meshCountPC; int meshCountPN = loadedMeshCounts.meshCountPN; int meshCountPT = loadedMeshCounts.meshCountPT; int meshCountPNT = loadedMeshCounts.meshCountPNT; int meshCountPNTTB = loadedMeshCounts.meshCountPNTTB; Mesh <VertexPosition>[] meshesP = new Mesh <VertexPosition> [meshCountP]; Mesh <VertexPositionColor>[] meshesPC = new Mesh <VertexPositionColor> [meshCountPC]; Mesh <VertexPositionNormal>[] meshesPN = new Mesh <VertexPositionNormal> [meshCountPN]; Mesh <VertexPositionTexture>[] meshesPT = new Mesh <VertexPositionTexture> [meshCountPT]; Mesh <VertexPositionNormalTexture>[] meshesPNT = new Mesh <VertexPositionNormalTexture> [meshCountPNT]; Mesh <VertexPositionNormalTextureTangentBitangent>[] meshesPNTTB = new Mesh <VertexPositionNormalTextureTangentBitangent> [meshCountPNTTB]; RealtimeMaterial[] materialsP = new RealtimeMaterial[meshCountP]; RealtimeMaterial[] materialsPC = new RealtimeMaterial[meshCountPC]; RealtimeMaterial[] materialsPN = new RealtimeMaterial[meshCountPN]; RealtimeMaterial[] materialsPT = new RealtimeMaterial[meshCountPT]; RealtimeMaterial[] materialsPNT = new RealtimeMaterial[meshCountPNT]; RealtimeMaterial[] materialsPNTTB = new RealtimeMaterial[meshCountPNTTB]; ushort[][] meshIndiciesP = new ushort[meshCountP][]; ushort[][] meshIndiciesPC = new ushort[meshCountPC][]; ushort[][] meshIndiciesPN = new ushort[meshCountPN][]; ushort[][] meshIndiciesPT = new ushort[meshCountPT][]; ushort[][] meshIndiciesPNT = new ushort[meshCountPNT][]; ushort[][] meshIndiciesPNTTB = new ushort[meshCountPNTTB][]; int meshIndiciesP_Counter = 0; int meshIndiciesPC_Counter = 0; int meshIndiciesPN_Counter = 0; int meshIndiciesPT_Counter = 0; int meshIndiciesPNT_Counter = 0; int meshIndiciesPNTTB_Counter = 0; var loadedModels = new LoadedModels <RealtimeMaterial>(); VertexPosition[] meshDefinitionP = new VertexPosition[0]; VertexPositionColor[] meshDefinitionPC = new VertexPositionColor[0]; VertexPositionNormal[] meshDefinitionPN = new VertexPositionNormal[0]; VertexPositionTexture[] meshDefinitionPT = new VertexPositionTexture[0]; VertexPositionNormalTexture[] meshDefinitionPNT = new VertexPositionNormalTexture[0]; VertexPositionNormalTextureTangentBitangent[] meshDefinitionPNTTB = new VertexPositionNormalTextureTangentBitangent[0]; for (int i = 0; i < meshCount; i++) { var aiMesh = pScene.Meshes[i]; var vertexCount = aiMesh.VertexCount; if (vertexCount == 0) { Console.Error.WriteLine("Mesh has no verticies"); continue; } Assimp.Material aiMaterial = pScene.Materials[aiMesh.MaterialIndex]; Core.Materials.RealtimeMaterial material = aiMaterial.ToRealtimeMaterial(); VertexRuntimeTypes henzaiVertexType = aiMaterial.ToHenzaiVertexType(); switch (henzaiVertexType) { case VertexRuntimeTypes.VertexPosition: meshDefinitionP = new VertexPosition[vertexCount]; break; case VertexRuntimeTypes.VertexPositionColor: meshDefinitionPC = new VertexPositionColor[vertexCount]; break; case VertexRuntimeTypes.VertexPositionTexture: meshDefinitionPT = new VertexPositionTexture[vertexCount]; break; case VertexRuntimeTypes.VertexPositionNormalTexture: meshDefinitionPNT = new VertexPositionNormalTexture[vertexCount]; break; case VertexRuntimeTypes.VertexPositionNormal: meshDefinitionPN = new VertexPositionNormal[vertexCount]; break; case VertexRuntimeTypes.VertexPositionNormalTextureTangentBitangent: meshDefinitionPNTTB = new VertexPositionNormalTextureTangentBitangent[vertexCount]; break; default: throw new NotImplementedException($"{henzaiVertexType.ToString("g")} not implemented"); } for (int j = 0; j < vertexCount; j++) { byte[] bytes = GenerateVertexBytesArrayFromAssimp(henzaiVertexType, aiMesh, j); switch (henzaiVertexType) { case VertexRuntimeTypes.VertexPosition: meshDefinitionP[j] = ByteMarshal.ByteArrayToStructure <VertexPosition>(bytes); break; case VertexRuntimeTypes.VertexPositionColor: meshDefinitionPC[j] = ByteMarshal.ByteArrayToStructure <VertexPositionColor>(bytes); break; case VertexRuntimeTypes.VertexPositionTexture: meshDefinitionPT[j] = ByteMarshal.ByteArrayToStructure <VertexPositionTexture>(bytes); break; case VertexRuntimeTypes.VertexPositionNormalTexture: meshDefinitionPNT[j] = ByteMarshal.ByteArrayToStructure <VertexPositionNormalTexture>(bytes); break; case VertexRuntimeTypes.VertexPositionNormal: meshDefinitionPN[j] = ByteMarshal.ByteArrayToStructure <VertexPositionNormal>(bytes); break; case VertexRuntimeTypes.VertexPositionNormalTextureTangentBitangent: meshDefinitionPNTTB[j] = ByteMarshal.ByteArrayToStructure <VertexPositionNormalTextureTangentBitangent>(bytes); break; default: throw new NotImplementedException($"{henzaiVertexType.ToString("g")} not implemented"); } } var faceCount = aiMesh.FaceCount; switch (henzaiVertexType) { case VertexRuntimeTypes.VertexPosition: materialsP[meshIndiciesP_Counter] = material; meshIndiciesP[meshIndiciesP_Counter] = new ushort[3 * faceCount]; for (int j = 0; j < faceCount; j++) { var face = aiMesh.Faces[j]; if (face.IndexCount != 3) { Console.Error.WriteLine("Loading Assimp: Face index count != 3!"); continue; } meshIndiciesP[meshIndiciesP_Counter][3 * j + 0] = face.Indices[0].ToUnsignedShort(); meshIndiciesP[meshIndiciesP_Counter][3 * j + 1] = face.Indices[1].ToUnsignedShort(); meshIndiciesP[meshIndiciesP_Counter][3 * j + 2] = face.Indices[2].ToUnsignedShort(); } meshesP[meshIndiciesP_Counter] = new Mesh <VertexPosition>(meshDefinitionP, meshIndiciesP[meshIndiciesP_Counter]); meshIndiciesP_Counter++; break; case VertexRuntimeTypes.VertexPositionColor: materialsPC[meshIndiciesPC_Counter] = material; meshIndiciesPC[meshIndiciesPC_Counter] = new ushort[3 * faceCount]; for (int j = 0; j < faceCount; j++) { var face = aiMesh.Faces[j]; if (face.IndexCount != 3) { Console.Error.WriteLine("Loading Assimp: Face index count != 3!"); continue; } meshIndiciesPC[meshIndiciesPC_Counter][3 * j + 0] = face.Indices[0].ToUnsignedShort(); meshIndiciesPC[meshIndiciesPC_Counter][3 * j + 1] = face.Indices[1].ToUnsignedShort(); meshIndiciesPC[meshIndiciesPC_Counter][3 * j + 2] = face.Indices[2].ToUnsignedShort(); } meshesPC[meshIndiciesPC_Counter] = new Mesh <VertexPositionColor>(meshDefinitionPC, meshIndiciesPC[meshIndiciesPC_Counter]); meshIndiciesPC_Counter++; break; case VertexRuntimeTypes.VertexPositionTexture: materialsPT[meshIndiciesPT_Counter] = material; meshIndiciesPT[meshIndiciesPT_Counter] = new ushort[3 * faceCount]; for (int j = 0; j < faceCount; j++) { var face = aiMesh.Faces[j]; if (face.IndexCount != 3) { Console.Error.WriteLine("Loading Assimp: Face index count != 3!"); continue; } meshIndiciesPT[meshIndiciesPT_Counter][3 * j + 0] = face.Indices[0].ToUnsignedShort(); meshIndiciesPT[meshIndiciesPT_Counter][3 * j + 1] = face.Indices[1].ToUnsignedShort(); meshIndiciesPT[meshIndiciesPT_Counter][3 * j + 2] = face.Indices[2].ToUnsignedShort(); } meshesPT[meshIndiciesPT_Counter] = new Mesh <VertexPositionTexture>(meshDefinitionPT, meshIndiciesPT[meshIndiciesPT_Counter]); meshIndiciesPT_Counter++; break; case VertexRuntimeTypes.VertexPositionNormalTexture: materialsPNT[meshIndiciesPNT_Counter] = material; meshIndiciesPNT[meshIndiciesPNT_Counter] = new ushort[3 * faceCount]; for (int j = 0; j < faceCount; j++) { var face = aiMesh.Faces[j]; if (face.IndexCount != 3) { Console.Error.WriteLine("Loading Assimp: Face index count != 3!"); continue; } meshIndiciesPNT[meshIndiciesPNT_Counter][3 * j + 0] = face.Indices[0].ToUnsignedShort(); meshIndiciesPNT[meshIndiciesPNT_Counter][3 * j + 1] = face.Indices[1].ToUnsignedShort(); meshIndiciesPNT[meshIndiciesPNT_Counter][3 * j + 2] = face.Indices[2].ToUnsignedShort(); } meshesPNT[meshIndiciesPNT_Counter] = new Mesh <VertexPositionNormalTexture>(meshDefinitionPNT, meshIndiciesPNT[meshIndiciesPNT_Counter]); meshIndiciesPNT_Counter++; break; case VertexRuntimeTypes.VertexPositionNormal: materialsPN[meshIndiciesPN_Counter] = material; meshIndiciesPN[meshIndiciesPN_Counter] = new ushort[3 * faceCount]; for (int j = 0; j < faceCount; j++) { var face = aiMesh.Faces[j]; if (face.IndexCount != 3) { Console.Error.WriteLine("Loading Assimp: Face index count != 3!"); continue; } meshIndiciesPN[meshIndiciesPN_Counter][3 * j + 0] = face.Indices[0].ToUnsignedShort(); meshIndiciesPN[meshIndiciesPN_Counter][3 * j + 1] = face.Indices[1].ToUnsignedShort(); meshIndiciesPN[meshIndiciesPN_Counter][3 * j + 2] = face.Indices[2].ToUnsignedShort(); } meshesPN[meshIndiciesPN_Counter] = new Mesh <VertexPositionNormal>(meshDefinitionPN, meshIndiciesPN[meshIndiciesPN_Counter]); meshIndiciesPN_Counter++; break; case VertexRuntimeTypes.VertexPositionNormalTextureTangentBitangent: materialsPNTTB[meshIndiciesPNTTB_Counter] = material; meshIndiciesPNTTB[meshIndiciesPNTTB_Counter] = new ushort[3 * faceCount]; for (int j = 0; j < faceCount; j++) { var face = aiMesh.Faces[j]; if (face.IndexCount != 3) { Console.Error.WriteLine("Loading Assimp: Face index count != 3!"); continue; } meshIndiciesPNTTB[meshIndiciesPNTTB_Counter][3 * j + 0] = face.Indices[0].ToUnsignedShort(); meshIndiciesPNTTB[meshIndiciesPNTTB_Counter][3 * j + 1] = face.Indices[1].ToUnsignedShort(); meshIndiciesPNTTB[meshIndiciesPNTTB_Counter][3 * j + 2] = face.Indices[2].ToUnsignedShort(); } meshesPNTTB[meshIndiciesPNTTB_Counter] = new Mesh <VertexPositionNormalTextureTangentBitangent>(meshDefinitionPNTTB, meshIndiciesPNTTB[meshIndiciesPNTTB_Counter]); meshIndiciesPNTTB_Counter++; break; default: throw new NotImplementedException($"{henzaiVertexType.ToString("g")} not implemented"); } } if (meshCountP > 0) { loadedModels.modelP = new Model <VertexPosition, RealtimeMaterial>(modelDir, meshesP, materialsP); } if (meshCountPC > 0) { loadedModels.modelPC = new Model <VertexPositionColor, RealtimeMaterial>(modelDir, meshesPC, materialsPC); } if (meshCountPN > 0) { loadedModels.modelPN = new Model <VertexPositionNormal, RealtimeMaterial>(modelDir, meshesPN, materialsPN); } if (meshCountPT > 0) { loadedModels.modelPT = new Model <VertexPositionTexture, RealtimeMaterial>(modelDir, meshesPT, materialsPT); } if (meshCountPNT > 0) { loadedModels.modelPNT = new Model <VertexPositionNormalTexture, RealtimeMaterial>(modelDir, meshesPNT, materialsPNT); } if (meshCountPNTTB > 0) { loadedModels.modelPNTTB = new Model <VertexPositionNormalTextureTangentBitangent, RealtimeMaterial>(modelDir, meshesPNTTB, materialsPNTTB); } return(loadedModels); }
public static Model <T, RealtimeMaterial> LoadFromFileWithRealtimeMaterial <T>(string baseDirectory, string localPath, VertexRuntimeTypes vertexType, PostProcessSteps flags = DefaultPostProcessSteps) where T : struct, VertexLocateable { if (!Verifier.VerifyVertexStruct <T>(vertexType)) { throw new ArgumentException($"Vertex Type Mismatch AssimpLoader"); } string filePath = Path.Combine(baseDirectory, localPath); string[] directoryStructure = localPath.Split('/'); string modelDir = directoryStructure[0]; AssimpContext assimpContext = new AssimpContext(); Assimp.Scene pScene = assimpContext.ImportFile(filePath, flags); int meshCount = pScene.MeshCount; Mesh <T>[] meshes = new Mesh <T> [meshCount]; RealtimeMaterial[] materials = new RealtimeMaterial[meshCount]; ushort[][] meshIndicies = new ushort[meshCount][]; for (int i = 0; i < meshCount; i++) { var aiMesh = pScene.Meshes[i]; var vertexCount = aiMesh.VertexCount; if (vertexCount == 0) { continue; } Assimp.Material aiMaterial = pScene.Materials[aiMesh.MaterialIndex]; var material = aiMaterial.ToRealtimeMaterial(); T[] meshDefinition = new T[vertexCount]; for (int j = 0; j < vertexCount; j++) { byte[] bytes = GenerateVertexBytesArrayFromAssimp(vertexType, aiMesh, j); meshDefinition[j] = ByteMarshal.ByteArrayToStructure <T>(bytes); } materials[i] = material; var faceCount = aiMesh.FaceCount; meshIndicies[i] = new ushort[3 * faceCount]; for (int j = 0; j < faceCount; j++) { var face = aiMesh.Faces[j]; if (face.IndexCount != 3) { Console.Error.WriteLine("Loading Assimp: Face index count != 3!"); continue; } meshIndicies[i][3 * j + 0] = face.Indices[0].ToUnsignedShort(); meshIndicies[i][3 * j + 1] = face.Indices[1].ToUnsignedShort(); meshIndicies[i][3 * j + 2] = face.Indices[2].ToUnsignedShort(); } meshes[i] = new Mesh <T>(meshDefinition, meshIndicies[i]); } return(new Model <T, RealtimeMaterial>(modelDir, meshes, materials)); }
//private const PostProcessSteps DefaultPostProcessSteps // = PostProcessSteps.None; //TODO: add support for VertexPosition Type public static byte[] GenerateVertexBytesArrayFromAssimp(VertexRuntimeTypes henzaiVertexType, Assimp.Mesh aiMesh, int index) { Vector3D pPos = aiMesh.Vertices[index]; Vector3D pNormal = aiMesh.Normals[index]; Vector3D pTexCoord = aiMesh.HasTextureCoords(0) ? aiMesh.TextureCoordinateChannels[0][index] : Zero3D; Color4D pColor = aiMesh.HasVertexColors(0) ? aiMesh.VertexColorChannels[0][index] : Nocolor; Vector3D pTangent = aiMesh.HasTangentBasis ? aiMesh.Tangents[index] : Zero3D; Vector3D pBiTangent = aiMesh.HasTangentBasis ? aiMesh.BiTangents[index] : Zero3D; byte[] bytes; byte[] posAsBytes = ByteMarshal.StructToBytes(pPos); byte[] colorAsBytes = ByteMarshal.StructToBytes(pColor); byte[] normalAsBytes = ByteMarshal.StructToBytes(pNormal); byte[] texCoordAsBytes = ByteMarshal.StructToBytes(pTexCoord.ToVector2()); byte[] tangentAsBytes = ByteMarshal.StructToBytes(pTangent); byte[] bitangentAsBytes = ByteMarshal.StructToBytes(pBiTangent); switch (henzaiVertexType) { case VertexRuntimeTypes.VertexPosition: bytes = new byte[VertexPosition.SizeInBytes]; Array.Copy(posAsBytes, 0, bytes, VertexPosition.PositionOffset, posAsBytes.Length); break; case VertexRuntimeTypes.VertexPositionColor: bytes = new byte[VertexPositionColor.SizeInBytes]; Array.Copy(posAsBytes, 0, bytes, VertexPositionColor.PositionOffset, posAsBytes.Length); Array.Copy(colorAsBytes, 0, bytes, VertexPositionColor.ColorOffset, colorAsBytes.Length); break; case VertexRuntimeTypes.VertexPositionTexture: bytes = new byte[VertexPositionTexture.SizeInBytes]; Array.Copy(posAsBytes, 0, bytes, VertexPositionTexture.PositionOffset, posAsBytes.Length); Array.Copy(texCoordAsBytes, 0, bytes, VertexPositionTexture.TextureCoordinatesOffset, texCoordAsBytes.Length); break; case VertexRuntimeTypes.VertexPositionNormalTexture: bytes = new byte[VertexPositionNormalTexture.SizeInBytes]; Array.Copy(posAsBytes, 0, bytes, VertexPositionNormalTexture.PositionOffset, posAsBytes.Length); Array.Copy(normalAsBytes, 0, bytes, VertexPositionNormalTexture.NormalOffset, normalAsBytes.Length); Array.Copy(texCoordAsBytes, 0, bytes, VertexPositionNormalTexture.TextureCoordinatesOffset, texCoordAsBytes.Length); break; case VertexRuntimeTypes.VertexPositionNormal: bytes = new byte[VertexPositionNormal.SizeInBytes]; Array.Copy(posAsBytes, 0, bytes, VertexPositionNormal.PositionOffset, posAsBytes.Length); Array.Copy(normalAsBytes, 0, bytes, VertexPositionNormal.NormalOffset, normalAsBytes.Length); break; case VertexRuntimeTypes.VertexPositionNormalTextureTangent: bytes = new byte[VertexPositionNormalTextureTangent.SizeInBytes]; Array.Copy(posAsBytes, 0, bytes, VertexPositionNormalTextureTangent.PositionOffset, posAsBytes.Length); Array.Copy(normalAsBytes, 0, bytes, VertexPositionNormalTextureTangent.NormalOffset, normalAsBytes.Length); Array.Copy(texCoordAsBytes, 0, bytes, VertexPositionNormalTextureTangent.TextureCoordinatesOffset, texCoordAsBytes.Length); Array.Copy(tangentAsBytes, 0, bytes, VertexPositionNormalTextureTangent.TangentOffset, tangentAsBytes.Length); break; case VertexRuntimeTypes.VertexPositionNormalTextureTangentBitangent: bytes = new byte[VertexPositionNormalTextureTangentBitangent.SizeInBytes]; Array.Copy(posAsBytes, 0, bytes, VertexPositionNormalTextureTangentBitangent.PositionOffset, posAsBytes.Length); Array.Copy(normalAsBytes, 0, bytes, VertexPositionNormalTextureTangentBitangent.NormalOffset, normalAsBytes.Length); Array.Copy(texCoordAsBytes, 0, bytes, VertexPositionNormalTextureTangentBitangent.TextureCoordinatesOffset, texCoordAsBytes.Length); Array.Copy(tangentAsBytes, 0, bytes, VertexPositionNormalTextureTangentBitangent.TangentOffset, tangentAsBytes.Length); Array.Copy(bitangentAsBytes, 0, bytes, VertexPositionNormalTextureTangentBitangent.BitangentOffset, bitangentAsBytes.Length); break; default: throw new NotImplementedException($"{henzaiVertexType.ToString("g")} not implemented"); } return(bytes); }