private Mesh TransformMesh(WriterContext context, IMesh meshAsset, IList <IMaterialAsset> materials) { var gpuMesh = meshAsset.ToGpuMesh(); var mesh = context.ModelRoot.CreateMesh(meshAsset.Id); context.Meshes.Add(meshAsset, mesh); var memoryStream = new MemoryStream(4096); var bufferViewMap = new Dictionary <IBufferView, BufferVeiwData>(); using (var binaryWriter = new BinaryWriter(memoryStream)) { foreach (var bufferView in gpuMesh.BufferViews) { var bufferViewContext = new BufferVeiwData(); bufferViewMap[bufferView] = bufferViewContext; bufferViewContext.BufferByteOffset = (int)memoryStream.Position; foreach (var streamKey in bufferView.GetStreams()) { var stream = bufferView.GetStream(streamKey); var accessorData = new AccessorData(); accessorData.Key = streamKey; accessorData.AttributeKey = GetAttributeKey(streamKey); accessorData.Source = GetSource(accessorData.Key, stream); accessorData.Dimentions = GetDimensionType(stream.MetaInfo); accessorData.Encoding = accessorData.Source.Encoding; accessorData.Normalized = false; accessorData.ItemCount = stream.Count; if (bufferViewContext.ItemCount != 0 && bufferViewContext.ItemCount != stream.Count) { throw new InvalidOperationException( "Number of elements in stream should be constant for all streams in gpu buffer"); } bufferViewContext.ItemCount = stream.Count; accessorData.BufferByteOffset = bufferViewContext.Stride; bufferViewContext.Stride += accessorData.Source.ElementSizeInBytes; bufferViewContext.Accessors.Add(accessorData); } for (var i = 0; i < bufferViewContext.ItemCount; ++i) { foreach (var accessorData in bufferViewContext.Accessors) { accessorData.Source.WriteNext(binaryWriter); } } } } var buffer = mesh.LogicalParent.UseBuffer(memoryStream.ToArray()); foreach (var bufferVeiwData in bufferViewMap.Values) { var bufferView = mesh.LogicalParent.UseBufferView(buffer, bufferVeiwData.BufferByteOffset, null, bufferVeiwData.Stride, BufferMode.ARRAY_BUFFER); foreach (var data in bufferVeiwData.Accessors) { var accessor = mesh.LogicalParent.CreateAccessor(); accessor.SetVertexData(bufferView, data.BufferByteOffset, data.ItemCount, data.Dimentions, data.Encoding, data.Normalized); data.MemoryAccessor = accessor; } } for (var primitiveIndex = 0; primitiveIndex < gpuMesh.Primitives.Count; primitiveIndex++) { var gpuPrimitive = gpuMesh.Primitives[primitiveIndex]; var bufView = bufferViewMap[gpuPrimitive.BufferView]; var primitive = mesh.CreatePrimitive(); primitive.WithMaterial(context.Materials[materials[primitiveIndex % materials.Count]]); foreach (var accessor in bufView.Accessors) { primitive.SetVertexAccessor(accessor.AttributeKey, accessor.MemoryAccessor); } primitive.WithIndicesAccessor(GetPrimitiveType(gpuPrimitive.Topology), gpuPrimitive); } return(mesh); }
private Mesh TransformMesh(WriterContext context, IMesh meshAsset) { return(TransformMesh(context, meshAsset, context.MeshInstances[meshAsset])); }
private static bool TrySetupTexture(Material material, string key, SamplerParameters?samplerParameter, WriterContext context) { if (samplerParameter != null && samplerParameter.Value.Image != null) { material.WithChannelTexture(key, samplerParameter.Value.TextureCoordinate, context.Textures[samplerParameter.Value.Image]); return(true); } return(false); }
private void SetupMetallicRoughnessShader(Material material, MetallicRoughnessShader shader, WriterContext context) { material = material.WithPBRMetallicRoughness(); SetupDefaultShader(material, shader, context); TrySetupTexture(material, "BaseColor", shader.BaseColorTexture, context); material.WithChannelParameter("BaseColor", shader.BaseColorFactor); TrySetupTexture(material, "MetallicRoughness", shader.MetallicRoughnessTexture, context); material.WithChannelParameter("MetallicRoughness", new Vector4(shader.MetallicFactor, shader.RoughnessFactor, 0, 0)); }
private void SetupSpecularGlossinessShader(Material material, SpecularGlossinessShader shader, WriterContext context) { material = material.WithPBRSpecularGlossiness(); SetupDefaultShader(material, shader, context); TrySetupTexture(material, "Diffuse", shader.DiffuseTexture, context); material.WithChannelParameter("Diffuse", shader.DiffuseFactor); TrySetupTexture(material, "SpecularGlossiness", shader.SpecularGlossinessTexture, context); material.WithChannelParameter("SpecularGlossiness", new Vector4(shader.SpecularFactor, shader.GlossinessFactor)); }
public Task WriteAsync(Stream stream, IContentContainer content) { return(Task.Run(async() => { var context = new WriterContext { Container = content, ModelRoot = ModelRoot.CreateModel() }; foreach (var textureAsset in content.Images) { var image = context.ModelRoot.CreateImage(textureAsset.Id); image.SetSatelliteContent((await textureAsset.GetContentAsync()).ToArray()); context.Textures.Add(textureAsset, image); } foreach (var materialAsset in content.Materials) { var material = context.ModelRoot.CreateMaterial(materialAsset.Id); material.AlphaCutoff = materialAsset.AlphaCutoff; material.Alpha = GetAlphaMode(materialAsset.Alpha); material.DoubleSided = materialAsset.DoubleSided; if (materialAsset.Unlit) { material = material.WithUnlit(); } var metallicRoughnessShader = materialAsset.Shader as MetallicRoughnessShader; if (metallicRoughnessShader != null) { SetupMetallicRoughnessShader(material, metallicRoughnessShader, context); } else { var specularGlossinessShader = materialAsset.Shader as SpecularGlossinessShader; if (specularGlossinessShader != null) { SetupSpecularGlossinessShader(material, specularGlossinessShader, context); } else { material.WithDefault(); var defaultShader = materialAsset.Shader as ShaderAsset; if (defaultShader != null) { SetupDefaultShader(material, defaultShader, context); } } } context.Materials.Add(materialAsset, material); } foreach (var nodeAsset in GetAllNodes(content)) { if (nodeAsset.Mesh != null) { IList <IMaterialAsset> materials; if (context.MeshInstances.TryGetValue(nodeAsset.Mesh.Mesh, out materials)) { if (materials.Count != nodeAsset.Mesh.Materials.Count) { throw new FormatException("Mesh materials doesn't match all mesh instances"); } if (!materials.Zip(nodeAsset.Mesh.Materials, (a, b) => a == b).All(_ => _)) { throw new FormatException("Mesh materials doesn't match all mesh instances"); } continue; } context.MeshInstances.Add(nodeAsset.Mesh.Mesh, nodeAsset.Mesh.Materials); } } foreach (var meshAsset in content.Meshes) { TransformMesh(context, meshAsset); } foreach (var sceneAsset in content.Scenes) { var scene = context.ModelRoot.UseScene(sceneAsset.Id); if (context.ModelRoot.DefaultScene == null) { context.ModelRoot.DefaultScene = scene; } foreach (var nodeAsset in sceneAsset.ChildNodes) { TransformNode(context, nodeAsset, scene.CreateNode(nodeAsset.Id)); } } context.ModelRoot.WriteGLB(stream); })); }