예제 #1
0
        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);
        }
예제 #2
0
 private Mesh TransformMesh(WriterContext context, IMesh meshAsset)
 {
     return(TransformMesh(context, meshAsset, context.MeshInstances[meshAsset]));
 }
예제 #3
0
        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);
        }
예제 #4
0
        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));
        }
예제 #5
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));
        }
예제 #6
0
        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);
            }));
        }