Пример #1
0
        /// <summary>
        /// Writes <paramref name="model"/> to this context.
        /// </summary>
        /// <param name="baseName">The base name to use for asset files, without extension.</param>
        /// <param name="model">The <see cref="SCHEMA2"/> to write.</param>
        public void WriteBinarySchema2(string baseName, SCHEMA2 model)
        {
            Guard.NotNullOrEmpty(baseName, nameof(baseName));
            Guard.NotNull(model, nameof(model));

            model = this._PreprocessSchema2(model, this.ImageWriting == ResourceWriteMode.BufferView, true);
            Guard.NotNull(model, nameof(model));

            var ex = BinarySerialization.IsBinaryCompatible(model);

            if (ex != null)
            {
                throw ex;
            }

            model._PrepareBuffersForInternalWriting();

            model._PrepareImagesForWriting(this, baseName, ResourceWriteMode.Embedded);

            _ValidateBeforeWriting(model);

            using (var m = new MemoryStream())
            {
                using (var w = new BinaryWriter(m))
                {
                    BinarySerialization.WriteBinaryModel(w, model);
                }

                WriteAllBytesToEnd($"{baseName}.glb", m.ToArraySegment());
            }

            model._AfterWriting();
        }
Пример #2
0
        /// <summary>
        /// Writes <paramref name="model"/> to this context.
        /// </summary>
        /// <param name="baseName">The base name to use for asset files, without extension.</param>
        /// <param name="model">The <see cref="SCHEMA2"/> to write.</param>
        public void WriteTextSchema2(string baseName, SCHEMA2 model)
        {
            Guard.NotNullOrEmpty(baseName, nameof(baseName));
            Guard.NotNull(model, nameof(model));

            model = this._PreprocessSchema2(model, this.ImageWriting == ResourceWriteMode.BufferView, this.MergeBuffers);
            Guard.NotNull(model, nameof(model));

            model._PrepareBuffersForSatelliteWriting(this, baseName);

            model._PrepareImagesForWriting(this, baseName, ResourceWriteMode.SatelliteFile);

            using (var m = new MemoryStream())
            {
                model._WriteJSON(m, this.JsonIndented);

                /*
                 * using (var w = new StreamWriter(m))
                 * {
                 *  model._WriteJSON(w, this.JsonFormatting);
                 * }*/

                WriteAllBytesToEnd($"{baseName}.gltf", m.ToArraySegment());
            }

            model._AfterWriting();
        }
Пример #3
0
        /// <summary>
        /// This needs to be called immediately before writing to json,
        /// but immediately after preprocessing and buffer setup, so the model can be correctly validated.
        /// </summary>
        /// <param name="model">The model to validate.</param>
        private void _ValidateBeforeWriting(SCHEMA2 model)
        {
            if (_NoCloneWatchdog)
            {
                return;
            }

            if (this.Validation == SharpGLTF.Validation.ValidationMode.Skip)
            {
                return;
            }

            var vcontext = new Validation.ValidationResult(model, this.Validation);

            model.ValidateReferences(vcontext.GetContext());
            var ex = vcontext.Errors.FirstOrDefault();

            if (ex != null)
            {
                throw ex;
            }

            model.ValidateContent(vcontext.GetContext());
            ex = vcontext.Errors.FirstOrDefault();
            if (ex != null)
            {
                throw ex;
            }
        }
Пример #4
0
        private Material GetDefaultMaterial()
        {
            if (_DummyModel != null)
            {
                _DummyModel = ModelRoot.CreateModel();
                _DummyModel.CreateMaterial("Default");
            }

            return(_DummyModel.LogicalMaterials[0]);
        }
Пример #5
0
        private (SCHEMA2 Model, Validation.ValidationResult Validation) _Read(BYTES jsonUtf8Bytes)
        {
            Guard.NotNull(jsonUtf8Bytes, nameof(jsonUtf8Bytes));

            var root = new SCHEMA2();

            var vcontext = new Validation.ValidationResult(root, this.Validation);

            var reader = new Utf8JsonReader(jsonUtf8Bytes);

            if (!reader.Read())
            {
                vcontext.AddError(new Validation.ModelException(root, "Json is empty"));
                return(null, vcontext);
            }

            try
            {
                root.Deserialize(ref reader);
                root.OnDeserializationCompleted();
            }
            catch (JsonException rex)
            {
                vcontext.AddError(new Validation.SchemaException(root, rex));
                return(null, vcontext);
            }

            // schema validation

            root.ValidateReferences(vcontext.GetContext());
            var ex = vcontext.Errors.FirstOrDefault();

            if (ex != null)
            {
                return(null, vcontext);
            }

            // resolve external dependencies

            root._ResolveSatelliteDependencies(this);

            // full validation

            if (this.Validation != VALIDATIONMODE.Skip)
            {
                root.Validate(vcontext.GetContext());
                ex = vcontext.Errors.FirstOrDefault();
                if (ex != null)
                {
                    return(null, vcontext);
                }
            }

            return(root, vcontext);
        }
Пример #6
0
        /// <summary>
        /// Prepares the model for writing with the appropiate settings, creating a defensive copy if neccesary.
        /// </summary>
        /// <param name="model">The source <see cref="SCHEMA2"/> instance.</param>
        /// <param name="imagesAsBufferViews">true if images should be stored as buffer views.</param>
        /// <param name="mergeBuffers">true if it's required the model must have a single buffer.</param>
        /// <returns>The source <see cref="SCHEMA2"/> instance, or a cloned and modified instance if current settings required it.</returns>
        private SCHEMA2 _PreprocessSchema2(SCHEMA2 model, bool imagesAsBufferViews, bool mergeBuffers)
        {
            Guard.NotNull(model, nameof(model));

            foreach (var img in model.LogicalImages)
            {
                if (!img._HasContent)
                {
                    throw new Validation.DataException(img, "Image Content is missing.");
                }
            }

            // check if we need to modify the model before saving it,
            // in order to create a defensive copy.

            if (model.LogicalImages.Count == 0)
            {
                imagesAsBufferViews = false;
            }
            if (model.LogicalBuffers.Count <= 1 && !imagesAsBufferViews)
            {
                mergeBuffers = false;
            }

            if (mergeBuffers | imagesAsBufferViews)
            {
                // cloning check is done to prevent cloning from entering in an infinite loop where each clone attempt triggers another clone request.
                if (_NoCloneWatchdog)
                {
                    throw new InvalidOperationException($"Current settings require creating a densive copy before model modification, but calling {nameof(SCHEMA2.DeepClone)} is not allowed with the current settings.");
                }

                model = model.DeepClone();
            }

            if (imagesAsBufferViews)
            {
                model.MergeImages();
            }
            if (mergeBuffers)
            {
                model.MergeBuffers();
            }

            if (this._UpdateSupportedExtensions)
            {
                model.UpdateExtensionsSupport();
            }

            return(model);
        }
Пример #7
0
        public static void MustShareLogicalParent(Schema2.ModelRoot a, string aName, Schema2.LogicalChildOfRoot b, string bName)
        {
            if (a is null)
            {
                throw new ArgumentNullException(aName);
            }
            if (b is null)
            {
                throw new ArgumentNullException(bName);
            }

            if (a != b.LogicalParent)
            {
                throw new ArgumentException("LogicalParent mismatch", bName);
            }
        }
Пример #8
0
        public static void AttachToCurrentTest(this Schema2.ModelRoot model, string fileName)
        {
            // find the output path for the current test
            fileName = TestContext.CurrentContext.GetAttachmentPath(fileName, true);

            if (fileName.ToLower().EndsWith(".glb"))
            {
                model.SaveGLB(fileName);
            }
            else if (fileName.ToLower().EndsWith(".gltf"))
            {
                model.Save(fileName, new Schema2.WriteSettings {
                    JsonIndented = true
                });
            }
            else if (fileName.ToLower().EndsWith(".obj"))
            {
                fileName = fileName.Replace(" ", "_");
                Schema2.Schema2Toolkit.SaveAsWavefront(model, fileName);
            }

            // Attach the saved file to the current test
            TestContext.AddTestAttachment(fileName);

            if (fileName.ToLower().EndsWith(".obj"))
            {
                return;
            }

            var report = gltf_validator.ValidateFile(fileName);

            if (report == null)
            {
                return;
            }

            if (report.HasErrors || report.HasWarnings)
            {
                TestContext.WriteLine(report.ToString());
            }

            Assert.IsFalse(report.HasErrors);
        }
Пример #9
0
        public static void AttachToCurrentTest(this Schema2.ModelRoot model, string fileName)
        {
            // find the output path for the current test
            fileName = NUnit.Framework.TestContext.CurrentContext.GetAttachmentPath(fileName, true);

            if (fileName.ToLower().EndsWith(".glb"))
            {
                model.SaveGLB(fileName);
            }
            else if (fileName.ToLower().EndsWith(".gltf"))
            {
                model.SaveGLTF(fileName, Newtonsoft.Json.Formatting.Indented);
            }
            else if (fileName.ToLower().EndsWith(".obj"))
            {
                Schema2.Schema2Toolkit.SaveAsWavefront(model, fileName);
            }

            // Attach the saved file to the current test
            NUnit.Framework.TestContext.AddTestAttachment(fileName);
        }
Пример #10
0
        public static void AttachToCurrentTest(this Schema2.ModelRoot model, string fileName)
        {
            // find the output path for the current test
            fileName = TestContext.CurrentContext.GetAttachmentPath(fileName, true);

            if (fileName.ToLower().EndsWith(".glb"))
            {
                model.SaveGLB(fileName);
            }
            else if (fileName.ToLower().EndsWith(".gltf"))
            {
                model.Save(fileName, new Schema2.WriteSettings {
                    JsonIndented = true
                });
            }
            else if (fileName.ToLower().EndsWith(".obj"))
            {
                fileName = fileName.Replace(" ", "_");
                Schema2.Schema2Toolkit.SaveAsWavefront(model, fileName);
            }

            // Attach the saved file to the current test
            TestContext.AddTestAttachment(fileName);
        }
Пример #11
0
        private (SCHEMA2 Model, Validation.ValidationResult Validation) _Read(ReadOnlyMemory <Byte> jsonUtf8Bytes)
        {
            var root     = new SCHEMA2();
            var vcontext = new Validation.ValidationResult(root, this.Validation);

            #if !SUPRESSTRYCATCH
            try {
            #endif

            if (jsonUtf8Bytes.IsEmpty)
            {
                throw new System.Text.Json.JsonException("JSon is empty.");
            }

            var reader = new Utf8JsonReader(jsonUtf8Bytes.Span);

            if (!reader.Read())
            {
                vcontext.SetError(new Validation.SchemaException(root, "Json is empty"));
                return(null, vcontext);
            }

            root.Deserialize(ref reader);
            root.OnDeserializationCompleted();

            // binary chunk check

            foreach (var b in root.LogicalBuffers)
            {
                b.OnValidateBinaryChunk(vcontext.GetContext(), this._BinaryChunk);
            }

            // schema validation

            if (this._CheckSupportedExtensions)
            {
                root._ValidateExtensions(vcontext.GetContext());
                var ex = vcontext.Errors.FirstOrDefault();
                if (ex != null)
                {
                    return(null, vcontext);
                }
            }

            // we must do a basic validation before resolving external dependencies

            if (true)
            {
                root.ValidateReferences(vcontext.GetContext());
                var ex = vcontext.Errors.FirstOrDefault();
                if (ex != null)
                {
                    return(null, vcontext);
                }
            }

            // resolve external dependencies

            root._ResolveSatelliteDependencies(this);

            // full validation

            if (this.Validation != VALIDATIONMODE.Skip)
            {
                root.ValidateContent(vcontext.GetContext());
                var ex = vcontext.Errors.FirstOrDefault();
                if (ex != null)
                {
                    return(null, vcontext);
                }
            }

            #if !SUPRESSTRYCATCH
        }

        catch (JsonException rex)
        {
            vcontext.SetError(new Validation.SchemaException(root, rex));
            return(null, vcontext);
        }
        catch (System.FormatException fex)
        {
            vcontext.SetError(new Validation.ModelException(null, fex));
            return(null, vcontext);
        }
        catch (ArgumentException aex)
        {
            vcontext.SetError(new Validation.ModelException(root, aex));
            return(null, vcontext);
        }
        catch (Validation.ModelException mex)
        {
            vcontext.SetError(mex);
            return(null, vcontext);
        }
            #endif

            return(root, vcontext);
        }
Пример #12
0
        public ModelRoot CloneGlbWithMesh(SharpGLTF.Schema2.ModelRoot inputModel, Triangulation outTriangulation)
        {
            ModelRoot outputModel = CloneWithMesh(inputModel, new IndexedTriangulation(outTriangulation));

            return(outputModel);
        }
Пример #13
0
        /// <summary>
        /// Creates or reuses an <see cref="Image"/> with the image content set by <paramref name="image"/>
        /// </summary>
        /// <param name="root">The <see cref="ModelRoot"/> root instance.</param>
        /// <param name="image">A buffer containing the bytes of the image file.</param>
        /// <returns>A <see cref="Image"/> instance.</returns>
        public static Image UseImageWithContent(this ModelRoot root, Memory.MemoryImage image)
        {
            Guard.NotNull(root, nameof(root));

            return(root.UseImage(image));
        }
Пример #14
0
        /// <summary>
        /// Creates or reuses an <see cref="Image"/> with the image content set by <paramref name="imageContent"/>
        /// </summary>
        /// <param name="root">The <see cref="ModelRoot"/> root instance.</param>
        /// <param name="imageContent">A buffer containing the bytes of the image file.</param>
        /// <returns>A <see cref="Image"/> instance.</returns>
        public static Image UseImageWithContent(this ModelRoot root, Byte[] imageContent)
        {
            Guard.NotNull(root, nameof(root));

            return(root.UseImage(new ArraySegment <byte>(imageContent)));
        }
Пример #15
0
        /// <summary>
        /// Creates or reuses an <see cref="Image"/> with the file set by <paramref name="filePath"/>
        /// </summary>
        /// <param name="root">The <see cref="ModelRoot"/> root instance.</param>
        /// <param name="filePath">A valid file path pointing to a valid image</param>
        /// <returns>A <see cref="Image"/> instance.</returns>
        public static Image UseImageWithFile(this ModelRoot root, string filePath)
        {
            var content = System.IO.File.ReadAllBytes(filePath);

            return(root.UseImageWithContent(content));
        }
Пример #16
0
        public static string AttachToCurrentTest(this Schema2.ModelRoot model, string fileName, WriteSettings settings = null)
        {
            // find the output path for the current test
            fileName = TestContext.CurrentContext.GetAttachmentPath(fileName, true);

            if (fileName.ToLower().EndsWith(".glb"))
            {
                model.SaveGLB(fileName, settings);
            }
            else if (fileName.ToLower().EndsWith(".gltf"))
            {
                if (settings == null)
                {
                    settings = new WriteSettings {
                        JsonIndented = true
                    }
                }
                ;

                model.Save(fileName, settings);
            }
            else if (fileName.ToLower().EndsWith(".obj"))
            {
                fileName = fileName.Replace(" ", "_");
                Schema2.Schema2Toolkit.SaveAsWavefront(model, fileName);
            }
            else if (fileName.ToLower().EndsWith(".plotly"))
            {
                fileName = fileName.Replace(".plotly", ".html");

                var html = model.DefaultScene
                           .ToPlotly()
                           .ToHtml();

                System.IO.File.WriteAllText(fileName, html);
            }

            // Attach the saved file to the current test
            TestContext.AddTestAttachment(fileName);

            if (fileName.ToLower().EndsWith(".obj"))
            {
                return(fileName);
            }

            var report = gltf_validator.ValidateFile(fileName);

            if (report == null)
            {
                return(fileName);
            }

            if (report.HasErrors || report.HasWarnings)
            {
                TestContext.WriteLine(report.ToString());
            }

            Assert.IsFalse(report.HasErrors);

            return(fileName);
        }
    }
Пример #17
0
        private (SCHEMA2 Model, Validation.ValidationResult Validation) _Read(ReadOnlyMemory <Byte> jsonUtf8Bytes)
        {
            var root = new SCHEMA2();

            var vcontext = new Validation.ValidationResult(root, this.Validation);

            if (jsonUtf8Bytes.IsEmpty)
            {
                vcontext.AddError(new Validation.SchemaException(null, "JSon is empty."));
            }

            var reader = new Utf8JsonReader(jsonUtf8Bytes.Span);

            try
            {
                if (!reader.Read())
                {
                    vcontext.AddError(new Validation.SchemaException(root, "Json is empty"));
                    return(null, vcontext);
                }

                root.Deserialize(ref reader);
                root.OnDeserializationCompleted();
            }
            catch (JsonException rex)
            {
                vcontext.AddError(new Validation.SchemaException(root, rex));
                return(null, vcontext);
            }

            // binary chunk check

            foreach (var b in root.LogicalBuffers)
            {
                b.OnValidateBinaryChunk(vcontext.GetContext(root), this._BinaryChunk);
            }

            // schema validation

            root.ValidateReferences(vcontext.GetContext());
            var ex = vcontext.Errors.FirstOrDefault();

            if (ex != null)
            {
                return(null, vcontext);
            }

            // resolve external dependencies

            root._ResolveSatelliteDependencies(this);

            // full validation

            if (this.Validation != VALIDATIONMODE.Skip)
            {
                root.Validate(vcontext.GetContext());
                ex = vcontext.Errors.FirstOrDefault();
                if (ex != null)
                {
                    return(null, vcontext);
                }
            }

            return(root, vcontext);
        }
Пример #18
0
 public static Mesh CreateMesh(this ModelRoot root, IMeshBuilder <Materials.MaterialBuilder> mesh)
 {
     return(root.CreateMeshes(mesh)[0]);
 }
Пример #19
0
 public static Mesh CreateMesh <TMaterial>(this ModelRoot root, Converter <TMaterial, Material> materialEvaluator, IMeshBuilder <TMaterial> mesh)
 {
     return(root.CreateMeshes(materialEvaluator, mesh)[0]);
 }
Пример #20
0
 internal KHR_lights_punctualglTFextension(ModelRoot root)
 {
     _lights = new ChildrenCollection <PunctualLight, ModelRoot>(root);
 }