/// <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(); }
/// <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(); }
/// <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; } }
private Material GetDefaultMaterial() { if (_DummyModel != null) { _DummyModel = ModelRoot.CreateModel(); _DummyModel.CreateMaterial("Default"); } return(_DummyModel.LogicalMaterials[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); }
/// <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); }
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); } }
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); }
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); }
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); }
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); }
public ModelRoot CloneGlbWithMesh(SharpGLTF.Schema2.ModelRoot inputModel, Triangulation outTriangulation) { ModelRoot outputModel = CloneWithMesh(inputModel, new IndexedTriangulation(outTriangulation)); return(outputModel); }
/// <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)); }
/// <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))); }
/// <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)); }
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); } }
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); }
public static Mesh CreateMesh(this ModelRoot root, IMeshBuilder <Materials.MaterialBuilder> mesh) { return(root.CreateMeshes(mesh)[0]); }
public static Mesh CreateMesh <TMaterial>(this ModelRoot root, Converter <TMaterial, Material> materialEvaluator, IMeshBuilder <TMaterial> mesh) { return(root.CreateMeshes(materialEvaluator, mesh)[0]); }
internal KHR_lights_punctualglTFextension(ModelRoot root) { _lights = new ChildrenCollection <PunctualLight, ModelRoot>(root); }