public void ExportMeshes(string path) { TestContext.CurrentContext.AttachGltfValidatorLinks(); path = TestFiles .GetSampleModelsPaths() .FirstOrDefault(item => item.Contains(path)); // load the glTF model var srcModel = ModelRoot.Load(path, Validation.ValidationMode.TryFix); Assert.NotNull(srcModel); srcModel.AttachToCurrentTest("GearBoxAssy.plotly"); // convert it to a SceneBuilder so we can manipulate it: var srcScene = srcModel.DefaultScene.ToSceneBuilder(); // export all the individual meshes to OBJ: for (int i = 0; i < srcScene.Instances.Count; ++i) { var inst = srcScene.Instances[i].Content; // scan for meshes: if (inst.Content is MeshContent mesh) { var newScene = new SceneBuilder(); newScene.AddRigidMesh(mesh.Mesh, inst.GetPoseWorldMatrix()); newScene.AttachToCurrentTest($"result_{i}.obj"); } } }
public void LoadSuzanneTest() { var path1 = TestFiles.GetSampleModelsPaths().First(item => item.EndsWith("Suzanne.gltf")); var suzanne1 = ModelRoot.Load(path1, ValidationMode.TryFix); var suzanne1Mem = suzanne1.LogicalBuffers.Sum(item => item.Content.Length); // direct save-load var path2 = suzanne1 .AttachToCurrentTest("suzanne2.glb"); var suzanne2 = ModelRoot.Load(path2); var suzanne2Mem = suzanne1.LogicalBuffers.Sum(item => item.Content.Length); Assert.AreEqual(suzanne1Mem, suzanne2Mem); Assert.AreEqual(suzanne1.LogicalMeshes.Count, suzanne2.LogicalMeshes.Count); // scenebuilder roundtrip var path3 = Scenes.SceneBuilder .CreateFrom(suzanne1.DefaultScene) .ToGltf2() .AttachToCurrentTest("suzanne.glb"); var suzanne3 = ModelRoot.Load(path3); var suzanne3Mem = suzanne1.LogicalBuffers.Sum(item => item.Content.Length); Assert.AreEqual(suzanne1Mem, suzanne3Mem); Assert.AreEqual(suzanne1.LogicalMeshes.Count, suzanne3.LogicalMeshes.Count); }
public void TestMemoryIsolation() { // this tests checks if, after creating a template from a scene, // there's any reference from the template to the source model // that prevents the source model to be garbage collected. (SceneTemplate, WeakReference <Schema2.ModelRoot>) scopedLoad() { var path = TestFiles.GetSampleModelsPaths() .FirstOrDefault(item => item.Contains("BrainStem.glb")); var result = LoadModelTemplate(path); GC.Collect(); GC.WaitForFullGCComplete(); return(result); } var result = scopedLoad(); GC.Collect(); GC.WaitForFullGCComplete(); Assert.IsFalse(result.Item2.TryGetTarget(out Schema2.ModelRoot model)); Assert.Null(model); }
public void LoadModelsWithAnimations(string path) { TestContext.CurrentContext.AttachShowDirLink(); path = TestFiles .GetSampleModelsPaths() .FirstOrDefault(item => item.Contains(path)); var model = ModelRoot.Load(path); Assert.NotNull(model); path = System.IO.Path.GetFileNameWithoutExtension(path); model.AttachToCurrentTest(path + ".glb"); var triangles = model.DefaultScene .EvaluateTriangles <Geometry.VertexTypes.VertexPosition, Geometry.VertexTypes.VertexEmpty>() .ToArray(); var anim = model.LogicalAnimations[0]; var duration = anim.Duration; for (int i = 0; i < 10; ++i) { var t = duration * i / 10; int tt = (int)(t * 1000.0f); model.AttachToCurrentTest($"{path} at {tt}.obj", anim, t); } }
public void LoadModels() { foreach (var f in TestFiles.GetSampleModelsPaths()) { var root = Schema2.ModelRoot.Load(f); Assert.NotNull(root); } }
public void LoadModels() { foreach (var f in TestFiles.GetSampleModelsPaths()) { var root = GltfUtils.LoadModel(f); Assert.NotNull(root); } }
public void LoadBrokenFile() { var f = TestFiles.GetSampleModelsPaths().First(item => item.EndsWith(".gltf")); var json = System.IO.File.ReadAllText(f); // break the file json = json.Substring(0, json.Length - 40); Assert.Throws <Validation.SchemaException>(() => Schema2.ModelRoot.ParseGLTF(json, new Schema2.ReadSettings())); }
// [TestCase("\\glTF-Quantized\\")] // removed from tests // [TestCase("\\glTF-pbrSpecularGlossiness\\")] // removed from tests public void LoadModelsFromKhronosSamples(string section) { TestContext.CurrentContext.AttachGltfValidatorLinks(); foreach (var f in TestFiles.GetSampleModelsPaths()) { if (!f.Contains(section)) { continue; } _LoadModel(f); } }
public void TestLoadSparseModel() { var path = TestFiles.GetSampleModelsPaths().FirstOrDefault(item => item.Contains("SimpleSparseAccessor.gltf")); var model = ModelRoot.Load(path); Assert.NotNull(model); var primitive = model.LogicalMeshes[0].Primitives[0]; var accessor = primitive.GetVertexAccessor("POSITION"); var basePositions = accessor._GetMemoryAccessor().AsVector3Array(); var positions = accessor.AsVector3Array(); }
public static void TestMeshDecoding() { var modelPath = TestFiles.GetSampleModelsPaths() .FirstOrDefault(item => item.Contains("BrainStem.glb")); var model = Schema2.ModelRoot.Load(modelPath); model.AttachToCurrentTest("reference.plotly"); var scene = model.DefaultScene; var decodedMeshes = scene.LogicalParent.LogicalMeshes.Decode(); var sceneTemplate = SceneTemplate.Create(scene); var sceneInstance = sceneTemplate.CreateInstance(); var duration = sceneInstance.Armature.AnimationTracks[0].Duration; sceneInstance.Armature.SetAnimationFrame(0, duration / 2); IEnumerable <(Vector3, Vector3, Vector3, int)> evaluateTriangles(DrawableInstance inst) { var mesh = decodedMeshes[inst.Template.LogicalMeshIndex]; foreach (var prim in mesh.Primitives) { foreach (var(idxA, idxB, idxC) in prim.TriangleIndices) { var posA = prim.GetPosition(idxA, inst.Transform); var posB = prim.GetPosition(idxB, inst.Transform); var posC = prim.GetPosition(idxC, inst.Transform); yield return(posA, posB, posC, 0xb0b0b0); } } } var worldTriangles = sceneInstance.SelectMany(item => evaluateTriangles(item)); var scenePlot = new PlotlyScene(); scenePlot.AppendTriangles(worldTriangles, c => c); scenePlot .ToHtml() .AttachToCurrentTest("result.html", (content, finfo) => System.IO.File.WriteAllText(finfo.FullName, content)); }
public void LoadGeneratedTangetsTest(string fileName) { var path = TestFiles.GetSampleModelsPaths().FirstOrDefault(item => item.EndsWith(fileName)); var model = ModelRoot.Load(path); var mesh = model.DefaultScene .EvaluateTriangles <Geometry.VertexTypes.VertexPositionNormalTangent, Geometry.VertexTypes.VertexTexture1>() .ToMeshBuilder(); var editableScene = new Scenes.SceneBuilder(); editableScene.AddRigidMesh(mesh, Matrix4x4.Identity); model.AttachToCurrentTest("original.glb"); editableScene.ToGltf2().AttachToCurrentTest("WithTangents.glb"); }
public void LoadModelWithMorphTargets() { var path = TestFiles .GetSampleModelsPaths() .FirstOrDefault(item => item.Contains("MorphPrimitivesTest.glb")); var model = ModelRoot.Load(path); Assert.NotNull(model); var triangles = model.DefaultScene .EvaluateTriangles <Geometry.VertexTypes.VertexPosition, Geometry.VertexTypes.VertexEmpty>(null, null, 0) .ToArray(); model.AttachToCurrentTest(System.IO.Path.ChangeExtension(System.IO.Path.GetFileName(path), ".obj")); model.AttachToCurrentTest(System.IO.Path.ChangeExtension(System.IO.Path.GetFileName(path), ".glb")); }
public void TestLoadUnlitModel() { var f = TestFiles.GetSampleModelsPaths() .FirstOrDefault(item => item.EndsWith(@"UnlitTest\glTF-Binary\UnlitTest.glb")); var model = ModelRoot.Load(f); Assert.NotNull(model); Assert.IsTrue(model.LogicalMaterials[0].Unlit); // do a model roundtrip var modelBis = ModelRoot.ParseGLB(model.WriteGLB()); Assert.NotNull(modelBis); Assert.IsTrue(modelBis.LogicalMaterials[0].Unlit); }
public void LoadMultiUVTexture() { var path = TestFiles .GetSampleModelsPaths() .FirstOrDefault(item => item.Contains("TextureTransformMultiTest.glb")); var model = ModelRoot.Load(path); Assert.NotNull(model); var materials = model.LogicalMaterials; var normalTest0Mat = materials.FirstOrDefault(item => item.Name == "NormalTest0Mat"); var normalTest0Mat_normal = normalTest0Mat.FindChannel("Normal").Value; var normalTest0Mat_normal_xform = normalTest0Mat_normal.TextureTransform; Assert.NotNull(normalTest0Mat_normal_xform); }
public void TestLoadSampleModels(string section) { TestContext.CurrentContext.AttachShowDirLink(); TestContext.CurrentContext.AttachGltfValidatorLink(); foreach (var f in TestFiles.GetSampleModelsPaths()) { if (!f.Contains(section)) { continue; } var perf = System.Diagnostics.Stopwatch.StartNew(); var model = ModelRoot.Load(f); Assert.NotNull(model); var perf_load = perf.ElapsedMilliseconds; // do a model clone and compare it _AssertAreEqual(model, model.DeepClone()); var perf_clone = perf.ElapsedMilliseconds; // check extensions used if (!model.ExtensionsUsed.Contains("EXT_lights_image_based")) { var detectedExtensions = model.RetrieveUsedExtensions().ToArray(); CollectionAssert.AreEquivalent(model.ExtensionsUsed, detectedExtensions); } // evaluate and save all the triangles to a Wavefront Object model.AttachToCurrentTest(System.IO.Path.ChangeExtension(System.IO.Path.GetFileName(f), ".obj")); var perf_wavefront = perf.ElapsedMilliseconds; model.AttachToCurrentTest(System.IO.Path.ChangeExtension(System.IO.Path.GetFileName(f), ".glb")); var perf_glb = perf.ElapsedMilliseconds; TestContext.Progress.WriteLine($"processed {f.ToShortDisplayPath()} - Load:{perf_load}ms Clone:{perf_clone}ms S.obj:{perf_wavefront}ms S.glb:{perf_glb}ms"); } }
public static void TestMeshDecodingBounds() { var modelPath = TestFiles.GetSampleModelsPaths() .FirstOrDefault(item => item.Contains("BrainStem.glb")); var model = Schema2.ModelRoot.Load(modelPath); var(center, radius) = model.DefaultScene.EvaluateBoundingSphere(0.25f); var sceneTemplate = SceneTemplate.Create(model.DefaultScene); var sceneInstance = sceneTemplate.CreateInstance(); sceneInstance.Armature.SetAnimationFrame(0, 0.1f); var vertices = sceneInstance.GetWorldVertices(model.LogicalMeshes.Decode()).ToList(); foreach (var p in vertices) { var d = (p - center).Length(); Assert.LessOrEqual(d, radius + 0.0001f); } }
public void LoadModelsWithExtensions(string filePath) { TestContext.CurrentContext.AttachGltfValidatorLinks(); filePath = TestFiles .GetSampleModelsPaths() .FirstOrDefault(item => item.EndsWith(filePath)); var model = ModelRoot.Load(filePath); Assert.NotNull(model); // do a model clone and compare it _AssertAreEqual(model, model.DeepClone()); // evaluate and save all the triangles to a Wavefront Object filePath = System.IO.Path.GetFileNameWithoutExtension(filePath); model.AttachToCurrentTest(filePath + "_wf.obj"); model.AttachToCurrentTest(filePath + ".glb"); model.AttachToCurrentTest(filePath + ".gltf"); }
public void LoadAndSaveToMemory() { var path = TestFiles.GetSampleModelsPaths().FirstOrDefault(item => item.EndsWith("Avocado.glb")); var model = ModelRoot.Load(path); // model.LogicalImages[0].TransferToSatelliteFile(); // TODO // we will use this dictionary as our in-memory model container. var dictionary = new Dictionary <string, ArraySegment <Byte> >(); // write to dictionary var wcontext = WriteContext.CreateFromDictionary(dictionary); model.Save("avocado.gltf", wcontext); Assert.IsTrue(dictionary.ContainsKey("avocado.gltf")); Assert.IsTrue(dictionary.ContainsKey("avocado.bin")); // read back from dictionary var rcontext = ReadContext.CreateFromDictionary(dictionary); var model2 = ModelRoot.Load("avocado.gltf", rcontext); // TODO: verify }
public void TestLoadSpecialCaseModels(string filePath) { TestContext.CurrentContext.AttachShowDirLink(); TestContext.CurrentContext.AttachGltfValidatorLink(); var f = TestFiles.GetSampleModelsPaths() .FirstOrDefault(item => item.EndsWith(filePath)); var model = ModelRoot.Load(f); Assert.NotNull(model); // evaluate and save all the triangles to a Wavefront Object model.AttachToCurrentTest(System.IO.Path.ChangeExtension(System.IO.Path.GetFileName(f), ".obj")); model.AttachToCurrentTest(System.IO.Path.ChangeExtension(System.IO.Path.GetFileName(f), ".glb")); model.AttachToCurrentTest(System.IO.Path.ChangeExtension(System.IO.Path.GetFileName(f), ".gltf")); // do a model roundtrip var bytes = model.WriteGLB(); var modelBis = ModelRoot.ParseGLB(bytes); // clone var cloned = model.DeepClone(); }
public void TestRoundTrip(string path) { TestContext.CurrentContext.AttachGltfValidatorLinks(); path = TestFiles .GetSampleModelsPaths() .FirstOrDefault(item => item.Contains(path)); var srcModel = Schema2.ModelRoot.Load(path, Validation.ValidationMode.TryFix); Assert.NotNull(srcModel); // perform roundtrip var srcScene = Toolkit.ToSceneBuilder(srcModel.DefaultScene); var rowModel = srcScene.ToGltf2(); var settings = SceneBuilderSchema2Settings.Default; settings.UseStridedBuffers = false; var colModel = srcScene.ToGltf2(settings); var rowScene = Toolkit.ToSceneBuilder(rowModel.DefaultScene); var colScene = Toolkit.ToSceneBuilder(colModel.DefaultScene); // compare files var srcTris = srcModel.DefaultScene.EvaluateTriangles().ToList(); var rowTris = rowModel.DefaultScene.EvaluateTriangles().ToList(); var colTris = colModel.DefaultScene.EvaluateTriangles().ToList(); Assert.AreEqual(srcTris.Count, rowTris.Count); Assert.AreEqual(srcTris.Count, colTris.Count); var srcRep = Reporting.ModelReport.CreateReportFrom(srcModel); var rowRep = Reporting.ModelReport.CreateReportFrom(rowModel); var colRep = Reporting.ModelReport.CreateReportFrom(colModel); Assert.AreEqual(srcRep.NumTriangles, rowRep.NumTriangles); NumericsAssert.AreEqual(srcRep.Bounds.Min, rowRep.Bounds.Min, 0.0001f); NumericsAssert.AreEqual(srcRep.Bounds.Max, rowRep.Bounds.Max, 0.0001f); // save file path = System.IO.Path.GetFileNameWithoutExtension(path); srcModel.AttachToCurrentTest(path + "_src" + ".plotly"); srcModel.AttachToCurrentTest(path + "_src" + ".glb"); rowModel.AttachToCurrentTest(path + "_row" + ".glb"); colModel.AttachToCurrentTest(path + "_col" + ".glb"); srcModel.AttachToCurrentTest(path + "_src" + ".gltf"); rowModel.AttachToCurrentTest(path + "_row" + ".gltf"); colModel.AttachToCurrentTest(path + "_col" + ".gltf"); srcModel.AttachToCurrentTest(path + "_src" + ".obj"); rowModel.AttachToCurrentTest(path + "_row" + ".obj"); colModel.AttachToCurrentTest(path + "_col" + ".obj"); if (srcModel.LogicalAnimations.Count > 0) { srcModel.AttachToCurrentTest(path + "_src_at01" + ".obj", srcModel.LogicalAnimations[0], 0.1f); if (rowModel.LogicalAnimations.Count > 0) { rowModel.AttachToCurrentTest(path + "_row_at01" + ".obj", rowModel.LogicalAnimations[0], 0.1f); } } }
public void LoadAnimatedMorphCube() { TestContext.CurrentContext.AttachShowDirLink(); var path = TestFiles .GetSampleModelsPaths() .FirstOrDefault(item => item.Contains("AnimatedMorphCube.glb")); var model = ModelRoot.Load(path); Assert.NotNull(model); var anim = model.LogicalAnimations[0]; var node = model.LogicalNodes[0]; var acc_master = node.Mesh.Primitives[0].GetVertexAccessor("POSITION"); var acc_morph0 = node.Mesh.Primitives[0].GetMorphTargetAccessors(0)["POSITION"]; var acc_morph1 = node.Mesh.Primitives[0].GetMorphTargetAccessors(1)["POSITION"]; var pos_master = acc_master.AsVector3Array(); var pos_morph0 = acc_morph0.AsVector3Array(); var pos_morph1 = acc_morph1.AsVector3Array(); // pos_master var instance = Runtime.SceneTemplate .Create(model.DefaultScene) .CreateInstance(); var pvrt = node.Mesh.Primitives[0].GetVertexColumns(); for (float t = 0; t < 5; t += 0.25f) { instance.Armature.SetAnimationFrame(anim.LogicalIndex, t); var nodexform = instance.GetDrawableInstance(0).Transform; TestContext.WriteLine($"Animation at {t}"); var curves = node.GetCurveSamplers(anim); if (t < anim.Duration) { var mw = curves.GetMorphingSampler <float[]>() .CreateCurveSampler() .GetPoint(t); TestContext.WriteLine($" Morph Weights: {mw[0]} {mw[1]}"); } var msw = curves.GetMorphingSampler <Transforms.SparseWeight8>() .CreateCurveSampler() .GetPoint(t); TestContext.WriteLine($" Morph Sparse : {msw.Weight0} {msw.Weight1}"); var triangles = model.DefaultScene .EvaluateTriangles <Geometry.VertexTypes.VertexPosition, Geometry.VertexTypes.VertexEmpty>(null, anim, t) .ToList(); var vertices = triangles .SelectMany(item => new[] { item.A.Position, item.B.Position, item.C.Position }) .Distinct() .ToList(); foreach (var v in vertices) { TestContext.WriteLine($"{v}"); } TestContext.WriteLine(); } }