Example #1
0
        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");
                }
            }
        }
Example #2
0
        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);
        }
Example #3
0
        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);
        }
Example #4
0
        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);
            }
        }
Example #5
0
 public void LoadModels()
 {
     foreach (var f in TestFiles.GetSampleModelsPaths())
     {
         var root = Schema2.ModelRoot.Load(f);
         Assert.NotNull(root);
     }
 }
Example #6
0
 public void LoadModels()
 {
     foreach (var f in TestFiles.GetSampleModelsPaths())
     {
         var root = GltfUtils.LoadModel(f);
         Assert.NotNull(root);
     }
 }
Example #7
0
        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()));
        }
Example #8
0
        // [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);
            }
        }
Example #9
0
        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();
        }
Example #10
0
        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));
        }
Example #11
0
        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");
        }
Example #12
0
        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"));
        }
Example #13
0
        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);
        }
Example #14
0
        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);
        }
Example #15
0
        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");
            }
        }
Example #16
0
        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);
            }
        }
Example #17
0
        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");
        }
Example #18
0
        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
        }
Example #19
0
        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();
        }
Example #20
0
        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);
                }
            }
        }
Example #21
0
        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();
            }
        }