Esempio n. 1
0
        public void ExportMeshes(string path)
        {
            TestContext.CurrentContext.AttachShowDirLink();
            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");
                }
            }
        }
Esempio n. 2
0
        public void CreateSharedNodeInstanceScene()
        {
            // SceneBuilder API supports reusing a NodeBuilder in multiple instances with different content.
            // but glTF nodes can only hold one mesh per node, so if we find this case we need to internally
            // add an additional child node to give room to the the extra mesh.

            TestContext.CurrentContext.AttachShowDirLink();
            TestContext.CurrentContext.AttachGltfValidatorLinks();

            var m = MaterialBuilder.CreateDefault();

            var cube   = new Cube <MaterialBuilder>(m, 1.7f, 1.7f, 1.7f).ToMesh(Matrix4x4.Identity);
            var sphere = new IcoSphere <MaterialBuilder>(m).ToMesh(Matrix4x4.Identity);

            var armature1 = new NodeBuilder("Skeleton1");
            var joint0    = armature1
                            .CreateNode("Joint 0")
                            .WithLocalTranslation(new Vector3(0, 1, 0));

            var scene = new SceneBuilder();

            scene.AddRigidMesh(cube, joint0);
            scene.AddRigidMesh(sphere, joint0);

            scene.AttachToCurrentTest("instanced.glb");
            scene.AttachToCurrentTest("instanced.gltf");
        }
Esempio n. 3
0
        public void CreateAnimatedCubeScene()
        {
            TestContext.CurrentContext.AttachShowDirLink();
            TestContext.CurrentContext.AttachGltfValidatorLinks();

            var material = MaterialBuilder.CreateDefault();

            var mesh = new Cube <MaterialBuilder>(material)
                       .ToMesh(Matrix4x4.Identity);

            var pivot = new NodeBuilder();

            pivot.UseTranslation("track1")
            .WithPoint(0, Vector3.Zero)
            .WithPoint(1, Vector3.One);

            pivot.UseRotation("track1")
            .WithPoint(0, Quaternion.Identity)
            .WithPoint(1, Quaternion.CreateFromAxisAngle(Vector3.UnitY, 1.5f));

            pivot.UseScale("track1")
            .WithPoint(0, Vector3.One)
            .WithPoint(1, new Vector3(0.5f));

            var scene = new SceneBuilder();

            scene.AddRigidMesh(mesh, pivot);

            scene.AttachToCurrentTest("animated.glb");
            scene.AttachToCurrentTest("animated.gltf");
        }
Esempio n. 4
0
        public SceneBuilder DeepClone()
        {
            var clone = new SceneBuilder();

            clone._Name = this._Name;
            clone._Instances.AddRange(this._Instances.Select(item => item.DeepClone(this)));

            return(clone);
        }
Esempio n. 5
0
        internal InstanceBuilder DeepClone(SceneBuilder newParent)
        {
            var clone = new InstanceBuilder(newParent);

            clone._Name = this.Name;
            clone._ContentTransformer = this._ContentTransformer?.DeepClone();

            return(clone);
        }
Esempio n. 6
0
        public void CreateSceneWithRandomShapes()
        {
            TestContext.CurrentContext.AttachShowDirLink();
            TestContext.CurrentContext.AttachGltfValidatorLinks();

            var rnd = new Random(177);

            // create materials
            var materials = Enumerable
                            .Range(0, 10)
                            .Select(idx => new Materials.MaterialBuilder()
                                    .WithChannelParam("BaseColor", new Vector4(rnd.NextVector3(), 1)))
                            .ToList();

            // create scene

            var scene = new SceneBuilder();

            for (int i = 0; i < 100; ++i)
            {
                // create mesh
                var mat  = materials[rnd.Next(0, 10)];
                var mesh = VPOSNRM.CreateCompatibleMesh("shape");

                #if DEBUG
                mesh.VertexPreprocessor.SetValidationPreprocessors();
                #else
                mesh.VertexPreprocessor.SetSanitizerPreprocessors();
                #endif

                if ((i & 1) == 0)
                {
                    mesh.AddCube(mat, Matrix4x4.Identity);
                }
                else
                {
                    mesh.AddSphere(mat, 0.5f, Matrix4x4.Identity);
                }

                mesh.Validate();

                // create random transform
                var r     = rnd.NextVector3() * 5;
                var xform = Matrix4x4.CreateFromYawPitchRoll(r.X, r.Y, r.Z) * Matrix4x4.CreateTranslation(rnd.NextVector3() * 25);

                scene.AddRigidMesh(mesh, xform);
            }

            // save the model as GLB

            scene.AttachToCurrentTest("shapes.glb");
            scene.AttachToCurrentTest("shapes.plotly");
        }
Esempio n. 7
0
        public void CreateAllAnimationTypesScene()
        {
            // 3D View 7.1908.9012.0 has an issue displaying off-center meshes with animated morph targets.

            TestContext.CurrentContext.AttachShowDirLink();
            TestContext.CurrentContext.AttachGltfValidatorLinks();

            // create two materials

            var pink = new MaterialBuilder("material1")
                       .WithChannelParam(KnownChannel.BaseColor, new Vector4(1, 0, 1, 1));

            var yellow = new MaterialBuilder("material2")
                         .WithChannelParam(KnownChannel.BaseColor, new Vector4(1, 1, 0, 1));

            var scene = new SceneBuilder();

            var mesh1 = VPOSNRM.CreateCompatibleMesh("shape1");

            mesh1.AddCube(MaterialBuilder.CreateDefault(), Matrix4x4.Identity);
            var inst1 = scene.AddRigidMesh(mesh1, Matrix4x4.Identity);

            var mesh2 = VPOSNRM.CreateCompatibleMesh("shape2");

            mesh2.AddCube(pink, Matrix4x4.Identity);
            var inst2 = scene.AddRigidMesh(mesh2, Matrix4x4.CreateTranslation(2, 0, 0));

            scene.AttachToCurrentTest("static.glb");
            scene.AttachToCurrentTest("static.gltf");

            var morphBuilder = mesh2.UseMorphTarget(0);

            morphBuilder.SetVertexDelta(morphBuilder.Positions.ElementAt(0), (Vector3.UnitY, Vector3.Zero));
            morphBuilder.SetVertexDelta(morphBuilder.Positions.ElementAt(1), (Vector3.UnitY, Vector3.Zero));
            morphBuilder.SetVertexDelta(morphBuilder.Positions.ElementAt(2), (Vector3.UnitY, Vector3.Zero));
            morphBuilder.SetVertexDelta(morphBuilder.Positions.ElementAt(3), (Vector3.UnitY, Vector3.Zero));

            inst2.Content.UseMorphing().Value = Transforms.SparseWeight8.Create(1);

            var curve = inst2.Content.UseMorphing().UseTrackBuilder("Default");

            curve.SetPoint(0, Transforms.SparseWeight8.Create(0));
            curve.SetPoint(1, Transforms.SparseWeight8.Create(1));
            curve.SetPoint(2, Transforms.SparseWeight8.Create(0));

            var gltf = scene.ToGltf2();

            // Assert.AreEqual(1, gltf.LogicalMeshes[1].MorphWeights[0]);

            scene.AttachToCurrentTest("mopth.glb");
            scene.AttachToCurrentTest("mopth.gltf");
        }
Esempio n. 8
0
        public SceneBuilder DeepClone()
        {
            var clone = new SceneBuilder();

            clone._Name = this._Name;

            foreach (var inst in this._Instances)
            {
                inst._CopyTo(clone);
            }

            return(clone);
        }
Esempio n. 9
0
        public void AddScene(Scene dstScene, SceneBuilder srcScene)
        {
            _Nodes.Clear();
            AddArmatureResources(dstScene.CreateNode, new[] { srcScene });

            var schema2Instances = srcScene
                                   .Instances
                                   .OfType <IOperator <Scene> >();

            foreach (var inst in schema2Instances)
            {
                inst.Setup(dstScene, this);
            }
        }
Esempio n. 10
0
        public void CreateCubeScene()
        {
            TestContext.CurrentContext.AttachShowDirLink();
            TestContext.CurrentContext.AttachGltfValidatorLinks();

            var mesh = new Cube <MaterialBuilder>(MaterialBuilder.CreateDefault())
                       .ToMesh(Matrix4x4.Identity);

            var scene = new SceneBuilder();

            scene.AddMesh(mesh, Matrix4x4.Identity);

            scene.AttachToCurrentTest("cube.glb");
        }
Esempio n. 11
0
        public static SceneBuilder CreateFrom(Scene srcScene)
        {
            if (srcScene == null)
            {
                return(null);
            }

            // Process armatures

            var dstNodes = new Dictionary <Node, NodeBuilder>();

            foreach (var srcArmature in srcScene.VisualChildren)
            {
                var dstArmature = new NodeBuilder();
                _CopyToNodeBuilder(dstArmature, srcArmature, dstNodes);
            }

            // TODO: we must also process the armatures of every skin, in case the joints are outside the scene.

            var dstScene = new SceneBuilder();

            dstScene.SetNameAndExtrasFrom(srcScene);

            // process mesh instances
            var srcMeshInstances = Node.Flatten(srcScene)
                                   .Where(item => item.Mesh != null)
                                   .ToList();

            _AddMeshInstances(dstScene, dstNodes, srcMeshInstances);

            // process cameras
            var srcCameraInstances = Node.Flatten(srcScene)
                                     .Where(item => item.Camera != null)
                                     .ToList();

            _AddCameraInstances(dstScene, dstNodes, srcCameraInstances);

            var srcLightInstances = Node.Flatten(srcScene)
                                    .Where(item => item.PunctualLight != null)
                                    .ToList();

            _AddLightInstances(dstScene, dstNodes, srcCameraInstances);

            #if DEBUG
            dstScene._VerifyConversion(srcScene);
            #endif

            return(dstScene);
        }
Esempio n. 12
0
        public void TestCreateEmptyMesh()
        {
            // create a scenebuilder with an empty mesh
            var sb = new SceneBuilder();

            sb.AddRigidMesh(VPOSNRM.CreateCompatibleMesh("Empty"), Matrix4x4.Identity);

            var schema = sb.ToGltf2();

            Assert.AreEqual(0, schema.LogicalMeshes.Count, "SceneBuilder should detect empty meshes and remove them.");

            schema.CreateMesh("Empty2");

            var fileName = AttachmentInfo.From("empty.glb").File.FullName;

            Assert.Throws <SharpGLTF.Validation.SchemaException>(() => schema.SaveGLB(fileName));
        }
Esempio n. 13
0
        public void CreateSceneWithMixedVertexFormats()
        {
            TestContext.CurrentContext.AttachGltfValidatorLinks();

            var scene = new SceneBuilder();

            var mesh1 = new MeshBuilder <VertexPosition, VertexEmpty, VertexEmpty>();
            var mesh2 = new MeshBuilder <VertexPositionNormal, VertexEmpty, VertexEmpty>();

            mesh1.AddCube(MaterialBuilder.CreateDefault(), Matrix4x4.Identity);
            mesh2.AddCube(MaterialBuilder.CreateDefault(), Matrix4x4.Identity);

            scene.AddRigidMesh(mesh1, Matrix4x4.CreateTranslation(-2, 0, 0));
            scene.AddRigidMesh(mesh2, Matrix4x4.CreateTranslation(2, 0, 0));

            scene.AttachToCurrentTest("scene.glb");
        }
Esempio n. 14
0
        public void CreateQuadsScene()
        {
            TestContext.CurrentContext.AttachShowDirLink();
            TestContext.CurrentContext.AttachGltfValidatorLinks();

            // this test checks that non convex quads are created correctly.

            var mesh = new MeshBuilder <VertexPosition>();
            var prim = mesh.UsePrimitive(MaterialBuilder.CreateDefault());

            var idx = prim.AddQuadrangle(new VertexPosition(0, -1, 0), new VertexPosition(1, 0, 0), new VertexPosition(0, 1, 0), new VertexPosition(-1, 0, 0));

            Assert.AreEqual((0, 1, 2, 3), idx);

            idx = prim.AddQuadrangle(new VertexPosition(0, -1, 1), new VertexPosition(1, 0, 1), new VertexPosition(0, 1, 1), new VertexPosition(0.5f, 0, 1));
            Assert.AreEqual((4, 5, 6, 7), idx);

            idx = prim.AddQuadrangle(new VertexPosition(0, 0.5f, 2), new VertexPosition(1, 0, 2), new VertexPosition(0, 1, 2), new VertexPosition(-1, 0, 2));
            Assert.AreEqual((8, 9, 10, 11), idx);

            idx = prim.AddQuadrangle(new VertexPosition(1, 0, 3), new VertexPosition(0, 1, 3), new VertexPosition(0.5f, 0, 3), new VertexPosition(0, -1, 3));
            Assert.AreEqual((12, 13, 14, 15), idx);

            idx = prim.AddQuadrangle(new VertexPosition(1, 0, 4), new VertexPosition(1, 0, 4), new VertexPosition(0, 1, 4), new VertexPosition(-1, 0, 4));
            Assert.AreEqual((-1, 16, 17, 18), idx);

            idx = prim.AddQuadrangle(new VertexPosition(1, 0, 4), new VertexPosition(1, 0, 4), new VertexPosition(0, 1, 4), new VertexPosition(0, 1, 4));
            Assert.AreEqual((-1, -1, -1, -1), idx);

            idx = prim.AddQuadrangle(new VertexPosition(0, 0, 5), new VertexPosition(10, -1, 5), new VertexPosition(9, 0, 5), new VertexPosition(10, 1, 5));
            Assert.AreEqual((19, 20, 21, 22), idx);

            idx = prim.AddQuadrangle(new VertexPosition(10, -1, 6), new VertexPosition(9, 0, 6), new VertexPosition(10, 1, 6), new VertexPosition(0, 0, 6));
            Assert.AreEqual((23, 24, 25, 26), idx);

            var scene = new SceneBuilder();

            scene.AddMesh(mesh, Matrix4x4.Identity);

            scene.AttachToCurrentTest("cube.glb");
        }
Esempio n. 15
0
        private static void _AddMeshInstances(SceneBuilder dstScene, IReadOnlyDictionary <Node, NodeBuilder> dstNodes, IReadOnlyList <Node> srcInstances)
        {
            var dstMeshes = srcInstances
                            .Select(item => item.Mesh)
                            .Distinct()
                            .ToDictionary(item => item, item => item.ToMeshBuilder());

            foreach (var srcInstance in srcInstances)
            {
                var dstMesh = dstMeshes[srcInstance.Mesh];

                if (srcInstance.Skin == null)
                {
                    var dstNode = dstNodes[srcInstance];
                    var dstInst = dstScene.AddRigidMesh(dstMesh, dstNode);

                    _CopyMorphingAnimation(dstInst, srcInstance);
                }
                else
                {
                    var joints = new (NodeBuilder, Matrix4x4)[srcInstance.Skin.JointsCount];
Esempio n. 16
0
        private static void _AddMeshInstances(SceneBuilder dstScene, IEnumerable <Node> srcNodes, IReadOnlyDictionary <Node, NodeBuilder> nodesDict, IReadOnlyDictionary <Node, MESHBUILDER> meshesDict)
        {
            foreach (var srcNode in srcNodes)
            {
                if (!meshesDict.TryGetValue(srcNode, out var dstMesh))
                {
                    continue;                                                    // nothing to do.
                }
                if (srcNode.Skin == null)
                {
                    // rigid mesh instance

                    var dstNode = nodesDict[srcNode];

                    var gpuInstancing = srcNode.GetGpuInstancing();

                    if (gpuInstancing == null)
                    {
                        var dstInstance = dstScene.AddRigidMesh(dstMesh, dstNode);

                        _CopyMorphingAnimation(dstInstance, srcNode);
                    }
                    else
                    {
                        // use gpu instancing extension

                        foreach (var xinst in gpuInstancing.LocalTransforms)
                        {
                            var dstInstance = dstScene.AddRigidMesh(dstMesh, dstNode, xinst);

                            // if we add morphing to the mesh, all meshes would morph simultaneously??
                            _CopyMorphingAnimation(dstInstance, srcNode);
                        }
                    }
                }
                else
                {
                    // skinned mesh instance

                    var joints = new (NodeBuilder, Matrix4x4)[srcNode.Skin.JointsCount];
Esempio n. 17
0
        private static void _AddMeshInstances(SceneBuilder dstScene, IReadOnlyDictionary <Node, NodeBuilder> dstNodes, IReadOnlyList <Node> srcInstances)
        {
            var dstMeshes = srcInstances
                            .Select(item => item.Mesh)
                            .Distinct()
                            .ToDictionary(item => item, item => item.ToMeshBuilder());

            foreach (var srcInstance in srcInstances)
            {
                var dstMesh = dstMeshes[srcInstance.Mesh];

                if (srcInstance.Skin == null)
                {
                    var dstNode = dstNodes[srcInstance];

                    var gpuInstancing = srcInstance.GetGpuInstancing();

                    if (gpuInstancing != null)
                    {
                        foreach (var xinst in gpuInstancing.LocalTransforms)
                        {
                            var dstInst = dstScene.AddRigidMesh(dstMesh, dstNode, xinst);

                            // if we add morphing the the mesh, all meshes would morph simultaneously??
                            _CopyMorphingAnimation(dstInst, srcInstance);
                        }
                    }
                    else
                    {
                        var dstInst = dstScene.AddRigidMesh(dstMesh, dstNode);

                        _CopyMorphingAnimation(dstInst, srcInstance);
                    }
                }
                else
                {
                    var joints = new (NodeBuilder, Matrix4x4)[srcInstance.Skin.JointsCount];
Esempio n. 18
0
        public void CreateCubeSceneWithExtras()
        {
            TestContext.CurrentContext.AttachGltfValidatorLinks();

            var material = MaterialBuilder.CreateDefault();

            material.Name   = "hello name";
            material.Extras = IO.JsonContent.Serialize(new KeyValuePair <string, int>("hello", 16));

            var mesh = new Cube <MaterialBuilder>(material).ToMesh(Matrix4x4.Identity);

            mesh.Name   = "world name";
            mesh.Extras = "world extras";

            var scene = new SceneBuilder();

            scene.AddRigidMesh(mesh, Matrix4x4.Identity)
            .WithName("Cube")
            .WithExtras(17);

            scene.AttachToCurrentTest("cube.glb");
            scene.AttachToCurrentTest("cube.gltf");
            scene.AttachToCurrentTest("cube.plotly");
        }
Esempio n. 19
0
        public void AddScene(Scene dstScene, SceneBuilder srcScene)
        {
            _Nodes.Clear();
            AddArmatureResources(new[] { srcScene }, () => dstScene.CreateNode());

            // gather single operators (RigidTransformer and SkinnedTransformer)

            var srcSingleOperators = srcScene
                                     .Instances
                                     .Select(item => item.Content)
                                     .Where(item => !Geometry.MeshBuilderToolkit.IsEmpty(item.GetGeometryAsset()))
                                     .OfType <IOperator <Scene> >();

            // gather multi operators (Fixed Transformer)

            var srcChildren = srcScene
                              .Instances
                              .Select(item => item.Content)
                              .Where(item => !Geometry.MeshBuilderToolkit.IsEmpty(item.GetGeometryAsset()))
                              .OfType <FixedTransformer>();

            var srcMultiOperators = _MeshInstancing.CreateFrom(srcChildren, this.GpuMeshInstancingMinCount);

            // apply operators

            var srcOperators = srcSingleOperators.Concat(srcMultiOperators);

            foreach (var op in srcOperators)
            {
                op.ApplyTo(dstScene, this);
            }

            #if DEBUG
            srcScene._VerifyConversion(dstScene);
            #endif
        }
Esempio n. 20
0
        public void AddScene(Scene dstScene, SceneBuilder srcScene, bool useStridedBuffers = true)
        {
            // gather all unique MeshBuilders

            var srcMeshes = srcScene.Instances
                            .Select(item => item.Content?.GetGeometryAsset())
                            .Where(item => item != null)
                            .Distinct()
                            .ToArray();

            // gather all unique MaterialBuilders

            var materialGroups = srcMeshes
                                 .SelectMany(item => item.Primitives)
                                 .Where(item => !Geometry.MeshBuilderToolkit.IsEmpty(item))
                                 .Select(item => item.Material)
                                 .Distinct()
                                 .ToList()
                                 // group by equal content, to reduce material splitting whenever possible.
                                 .GroupBy(item => item, Materials.MaterialBuilder.ContentComparer);

            // create a Schema2.Material for every MaterialBuilder.

            foreach (var mg in materialGroups)
            {
                var val = dstScene.LogicalParent.CreateMaterial(mg.Key);
                foreach (var key in mg)
                {
                    _Materials[key] = val;
                }
            }

            // create a Schema2.Mesh for every MeshBuilder.

            var dstMeshes = dstScene.LogicalParent.CreateMeshes(mat => _Materials[mat], useStridedBuffers, srcMeshes);

            for (int i = 0; i < srcMeshes.Length; ++i)
            {
                _Meshes[srcMeshes[i]] = dstMeshes[i];
            }

            // TODO: here we could check that every dstMesh has been correctly created.

            // gather all NodeBuilder unique armatures

            var armatures = srcScene.Instances
                            .Select(item => item.Content?.GetArmatureAsset())
                            .Where(item => item != null)
                            .Select(item => item.Root)
                            .Distinct()
                            .ToList();

            // create Schema2.Node trees for every armature

            foreach (var armature in armatures)
            {
                CreateArmature(dstScene, armature);
            }

            // process instances

            var schema2Instances = srcScene
                                   .Instances
                                   .OfType <IOperator <Scene> >();

            foreach (var inst in schema2Instances)
            {
                inst.Setup(dstScene, this);
            }
        }
Esempio n. 21
0
        public void CreateAllAnimationTypesScene()
        {
            // 3D View 7.1908.9012.0 has an issue displaying off-center meshes with animated morph targets.

            TestContext.CurrentContext.AttachGltfValidatorLinks();

            // create two materials

            var pink = new MaterialBuilder("material1")
                       .WithChannelParam(KnownChannel.BaseColor, KnownProperty.RGBA, new Vector4(1, 0, 1, 1));

            var yellow = new MaterialBuilder("material2")
                         .WithChannelParam(KnownChannel.BaseColor, KnownProperty.RGBA, new Vector4(1, 1, 0, 1));

            var mesh1 = VPOSNRM.CreateCompatibleMesh("shape1");

            mesh1.AddCube(pink, Matrix4x4.Identity);

            var mesh2 = VPOSNRM.CreateCompatibleMesh("shape2");

            mesh2.AddCube(yellow, Matrix4x4.Identity);

            var scene = new SceneBuilder();

            var inst1 = scene.AddRigidMesh(mesh1, Matrix4x4.Identity);

            // meshes intended to support animation must be created using an armature
            var armature = new NodeBuilder();

            armature.LocalTransform = Matrix4x4.CreateTranslation(2, 0, 0);
            var inst2 = scene.AddRigidMesh(mesh2, armature);

            scene.AttachToCurrentTest("static.glb");
            scene.AttachToCurrentTest("static.gltf");

            // up to this point, the scene has two plain unanimated cubes.

            var morphBuilder = mesh2.UseMorphTarget(0);

            morphBuilder.SetVertexDelta(morphBuilder.Positions.ElementAt(0), (Vector3.UnitY, Vector3.Zero));
            morphBuilder.SetVertexDelta(morphBuilder.Positions.ElementAt(1), (Vector3.UnitY, Vector3.Zero));
            morphBuilder.SetVertexDelta(morphBuilder.Positions.ElementAt(2), (Vector3.UnitY, Vector3.Zero));
            morphBuilder.SetVertexDelta(morphBuilder.Positions.ElementAt(3), (Vector3.UnitY, Vector3.Zero));

            // set default value.
            inst2.Content.UseMorphing().SetValue(1);

            // ser animation curve.
            var curve = inst2.Content.UseMorphing().UseTrackBuilder("Default");

            curve.SetPoint(0, true, 0);
            curve.SetPoint(1, true, 1);
            curve.SetPoint(2, true, 0);

            var gltf = scene.ToGltf2();

            TestContext.WriteLine(gltf.GetJsonPreview());

            var meshIdx = 1;

            Assert.AreEqual(1, gltf.LogicalMeshes[meshIdx].Primitives[0].MorphTargetsCount);
            Assert.AreEqual(1, gltf.LogicalMeshes[meshIdx].MorphWeights[0]);
            Assert.AreEqual(1, gltf.LogicalAnimations.Count);

            scene.AttachToCurrentTest("mopth.glb");
            scene.AttachToCurrentTest("mopth.gltf");
        }
Esempio n. 22
0
        public void CreateDoubleSkinnedScene()
        {
            TestContext.CurrentContext.AttachGltfValidatorLinks();

            // create two materials

            var pink = new MaterialBuilder("material1")
                       .WithChannelParam(KnownChannel.BaseColor, KnownProperty.RGBA, new Vector4(1, 0, 1, 1))
                       .WithDoubleSide(true);

            var yellow = new MaterialBuilder("material2")
                         .WithChannelParam(KnownChannel.BaseColor, KnownProperty.RGBA, new Vector4(1, 1, 0, 1))
                         .WithDoubleSide(true);

            // create the mesh

            const int jointIdx0 = 0; // index of joint node 0
            const int jointIdx1 = 1; // index of joint node 1
            const int jointIdx2 = 2; // index of joint node 2

            var v1 = new SKINNEDVERTEX4(new Vector3(-10, 0, +10), (jointIdx0, 1));
            var v2 = new SKINNEDVERTEX4(new Vector3(+10, 0, +10), (jointIdx0, 1));
            var v3 = new SKINNEDVERTEX4(new Vector3(+10, 0, -10), (jointIdx0, 1));
            var v4 = new SKINNEDVERTEX4(new Vector3(-10, 0, -10), (jointIdx0, 1));

            var v5 = new SKINNEDVERTEX4(new Vector3(-10, 40, +10), (jointIdx0, 0.5f), (jointIdx1, 0.5f));
            var v6 = new SKINNEDVERTEX4(new Vector3(+10, 40, +10), (jointIdx0, 0.5f), (jointIdx1, 0.5f));
            var v7 = new SKINNEDVERTEX4(new Vector3(+10, 40, -10), (jointIdx0, 0.5f), (jointIdx1, 0.5f));
            var v8 = new SKINNEDVERTEX4(new Vector3(-10, 40, -10), (jointIdx0, 0.5f), (jointIdx1, 0.5f));

            var v9  = new SKINNEDVERTEX4(new Vector3(-5, 80, +5), (jointIdx2, 1));
            var v10 = new SKINNEDVERTEX4(new Vector3(+5, 80, +5), (jointIdx2, 1));
            var v11 = new SKINNEDVERTEX4(new Vector3(+5, 80, -5), (jointIdx2, 1));
            var v12 = new SKINNEDVERTEX4(new Vector3(-5, 80, -5), (jointIdx2, 1));

            var mesh = SKINNEDVERTEX4.CreateCompatibleMesh("mesh1");

            #if DEBUG
            mesh.VertexPreprocessor.SetValidationPreprocessors();
            #else
            mesh.VertexPreprocessor.SetSanitizerPreprocessors();
            #endif

            mesh.UsePrimitive(pink).AddQuadrangle(v1, v2, v6, v5);
            mesh.UsePrimitive(pink).AddQuadrangle(v2, v3, v7, v6);
            mesh.UsePrimitive(pink).AddQuadrangle(v3, v4, v8, v7);
            mesh.UsePrimitive(pink).AddQuadrangle(v4, v1, v5, v8);

            mesh.UsePrimitive(yellow).AddQuadrangle(v5, v6, v10, v9);
            mesh.UsePrimitive(yellow).AddQuadrangle(v6, v7, v11, v10);
            mesh.UsePrimitive(yellow).AddQuadrangle(v7, v8, v12, v11);
            mesh.UsePrimitive(yellow).AddQuadrangle(v8, v5, v9, v12);

            mesh.Validate();

            // create the skeleton armature 1 for the skinned mesh.

            var armature1 = new NodeBuilder("Skeleton1");
            var joint0    = armature1.CreateNode("Joint 0").WithLocalTranslation(new Vector3(0, 0, 0)); // jointIdx0
            var joint1    = joint0.CreateNode("Joint 1").WithLocalTranslation(new Vector3(0, 40, 0));   // jointIdx1
            var joint2    = joint1.CreateNode("Joint 2").WithLocalTranslation(new Vector3(0, 40, 0));   // jointIdx2

            joint1.UseRotation("Base Track")
            .WithPoint(1, Quaternion.Identity)
            .WithPoint(2, Quaternion.CreateFromYawPitchRoll(0, 1, 0))
            .WithPoint(3, Quaternion.CreateFromYawPitchRoll(0, 0, 1))
            .WithPoint(4, Quaternion.Identity);

            // create the skeleton armature 2 for the skinned mesh.

            var armature2 = new NodeBuilder("Skeleton2").WithLocalTranslation(new Vector3(100, 0, 0));
            var joint3    = armature2.CreateNode("Joint 3").WithLocalTranslation(new Vector3(0, 0, 0)); // jointIdx0
            var joint4    = joint3.CreateNode("Joint 4").WithLocalTranslation(new Vector3(0, 40, 0));   // jointIdx1
            var joint5    = joint4.CreateNode("Joint 5").WithLocalTranslation(new Vector3(0, 40, 0));   // jointIdx2

            joint4.UseRotation("Base Track")
            .WithPoint(1, Quaternion.Identity)
            .WithPoint(2, Quaternion.CreateFromYawPitchRoll(0, 1, 0))
            .WithPoint(3, Quaternion.CreateFromYawPitchRoll(0, 0, 1))
            .WithPoint(4, Quaternion.Identity);

            // create scene

            var scene = new SceneBuilder();

            scene.AddSkinnedMesh
            (
                mesh,
                armature1.WorldMatrix,
                joint0, // joint used for skinning joint index 0
                joint1, // joint used for skinning joint index 1
                joint2  // joint used for skinning joint index 2
            );

            scene.AddSkinnedMesh
            (
                mesh,
                armature2.WorldMatrix,
                joint3, // joint used for skinning joint index 0
                joint4, // joint used for skinning joint index 1
                joint5  // joint used for skinning joint index 2
            );

            scene.AttachToCurrentTest("skinned.glb");
            scene.AttachToCurrentTest("skinned.gltf");
        }
Esempio n. 23
0
        public void CreateSceneWithRandomShapes(bool useGpuInstancing)
        {
            TestContext.CurrentContext.AttachGltfValidatorLinks();

            var rnd = new Random(177);

            // create materials

            var materials = Enumerable
                            .Range(0, 10)
                            .Select(idx => new MaterialBuilder()
                                    .WithChannelParam(KnownChannel.BaseColor, KnownProperty.RGBA, new Vector4(rnd.NextVector3(), 1)))
                            .ToList();

            // create meshes

            var sphereMeshes = Enumerable
                               .Range(0, 10)
                               .Select(idx => materials[idx])
                               .Select(mat =>
            {
                var mesh = VPOSNRM.CreateCompatibleMesh("shape");
                    #if DEBUG
                mesh.VertexPreprocessor.SetValidationPreprocessors();
                    #else
                mesh.VertexPreprocessor.SetSanitizerPreprocessors();
                    #endif
                mesh.AddSphere(mat, 0.5f, Matrix4x4.Identity);
                mesh.Validate();
                return(mesh);
            });

            var cubeMeshes = Enumerable
                             .Range(0, 10)
                             .Select(idx => materials[idx])
                             .Select(mat =>
            {
                var mesh = VPOSNRM.CreateCompatibleMesh("shape");
                    #if DEBUG
                mesh.VertexPreprocessor.SetValidationPreprocessors();
                    #else
                mesh.VertexPreprocessor.SetSanitizerPreprocessors();
                    #endif
                mesh.AddCube(mat, Matrix4x4.Identity);
                mesh.Validate();
                return(mesh);
            });

            var meshes = sphereMeshes.Concat(cubeMeshes).ToArray();

            // create scene

            var scene = new SceneBuilder();

            for (int i = 0; i < 100; ++i)
            {
                var mesh = meshes[rnd.Next(0, 20)];

                // create random transform
                var r = rnd.NextQuaternion();
                var t = rnd.NextVector3() * 25;

                scene.AddRigidMesh(mesh, (r, t));
            }

            // collapse to glTF


            var gltf = scene.ToGltf2(useGpuInstancing ? SceneBuilderSchema2Settings.WithGpuInstancing : SceneBuilderSchema2Settings.Default);

            var bounds = Runtime.MeshDecoder.EvaluateBoundingBox(gltf.DefaultScene);

            // Assert.AreEqual(defaultBounds,instancedBounds);

            // save the model as GLB

            gltf.AttachToCurrentTest("shapes.glb");
            scene.AttachToCurrentTest("shapes.plotly");
        }
Esempio n. 24
0
        public static void AttachToCurrentTest(this Scenes.SceneBuilder scene, string fileName)
        {
            var model = scene.ToSchema2();

            model.AttachToCurrentTest(fileName);
        }
Esempio n. 25
0
        internal static void _AddCameraTo(CameraTransform3D?_Camera, GLTFWriteSettings?settings, SharpGLTF.Scenes.SceneBuilder scene)
        {
            if (!_Camera.HasValue)
            {
                return;
            }

            var vcam = _Camera.Value;

            var camNode = new SharpGLTF.Scenes.NodeBuilder("CameraNode");

            camNode.WorldMatrix = vcam.WorldMatrix;

            var cam = vcam;

            cam.WorldMatrix = Matrix4x4.Identity;
            vcam            = cam;

            if (vcam.TryGetPerspectiveFieldOfView(out var vfov))
            {
                var persp = new SharpGLTF.Scenes.CameraBuilder.Perspective(null, vfov, 0.1f);

                scene.AddCamera(persp, camNode);
            }

            else if (vcam.TryGetOrthographicScale(out var oscale))
            {
                var ortho = new SharpGLTF.Scenes.CameraBuilder.Orthographic(oscale, oscale, 0.1f, 1000);

                scene.AddCamera(ortho, camNode);
            }

            if ((settings?.CameraSize ?? 0) > 0)
            {
                var camMesh = new GltfMeshScene3D();

                vcam.DrawCameraTo(camMesh, settings.Value.CameraSize.Value);
                vcam.DrawFustrumTo(camMesh, settings.Value.CameraSize.Value * 0.05f, System.Drawing.Color.Yellow);

                scene.AddRigidMesh(camMesh.Mesh, camNode);
            }

            if (Matrix4x4.Invert(_Camera.Value.AxisMatrix, out var invMatrix))
            {
                // scene.ApplyBasisTransform(invMatrix);
            }
        }
Esempio n. 26
0
        public ModelRoot SceneGroup(
            List <Vitaboy.Mesh> meshes,
            List <Vitaboy.Animation> animations,
            List <Microsoft.Xna.Framework.Graphics.Texture2D> textures,
            Vitaboy.Skeleton skel
            )
        {
            var builder = new SharpGLTF.Scenes.SceneBuilder();

            var framerate = 1 / 36f;

            var nodes      = new Dictionary <Vitaboy.Bone, NodeBuilder>();
            var transforms = new List <Matrix4x4>();

            skel.ComputeBonePositions(skel.RootBone, Microsoft.Xna.Framework.Matrix.Identity);

            ConvertBone(nodes, skel.RootBone, new NodeBuilder(skel.RootBone.Name));

            //animations must be uploaded as part of the bone. add them as animation tracks to the existing nodes

            var timeprops = new Dictionary <string, float>();

            var useAnimID = animations.Count > 1;

            foreach (var anim in animations)
            {
                var name = anim.XSkillName ?? anim.Name;
                foreach (var motion in anim.Motions)
                {
                    //find the bone we're creating a curve for
                    var bone = nodes.Values.FirstOrDefault(x => x.Name == motion.BoneName);
                    if (bone == null)
                    {
                        continue;               //cannot add this curve to a bone
                    }
                    var root  = bone.Name == "ROOT";
                    var scale = RecursiveScale(bone.Parent);

                    if (motion.TimeProperties != null)
                    {
                        foreach (var tps in motion.TimeProperties)
                        {
                            foreach (var tp in tps.Items)
                            {
                                foreach (var prop in tp.Properties.Items)
                                {
                                    foreach (var keyPair in prop.KeyPairs)
                                    {
                                        var   tpname = name + "/" + tp.ID.ToString() + "/" + keyPair.Key;
                                        float value  = 1;
                                        if (!float.TryParse(keyPair.Value, out value))
                                        {
                                            value   = 1;
                                            tpname += "=" + keyPair.Value;
                                        }
                                        timeprops[tpname] = value;
                                    }
                                }
                            }
                        }
                    }

                    //create curves for rotation and translation

                    CurveBuilder <Vector3>    transCurve = null;
                    CurveBuilder <Quaternion> rotCurve   = null;
                    if (motion.HasTranslation)
                    {
                        transCurve = bone.Translation.UseTrackBuilder(name);
                    }
                    if (motion.HasRotation)
                    {
                        rotCurve = bone.Rotation.UseTrackBuilder(name);
                    }

                    for (int i = 0; i < motion.FrameCount; i++)
                    {
                        var     quat  = new Quaternion();
                        Vector3 trans = new Vector3();
                        if (rotCurve != null)
                        {
                            quat = QuatConvert(anim.Rotations[i + motion.FirstRotationIndex]);
                        }
                        if (transCurve != null)
                        {
                            trans = Vec3Convert(anim.Translations[i + motion.FirstTranslationIndex]) / scale;
                        }
                        if (root)
                        {
                            quat  = RotateQ * quat;
                            trans = Vector3.Transform(trans, RotateM);
                        }
                        rotCurve?.SetPoint(i * framerate, quat, true);
                        transCurve?.SetPoint(i * framerate, trans, true);
                    }
                    if (bone.Name == "R_LEG")
                    {
                    }
                }
            }

            var resultMeshes = new List <MeshBuilder <VertexPositionNormal, VertexTexture1, VertexJoints8x4> >();

            var orderedBones = skel.Bones.Select(x => nodes[x]).ToArray();
            var world        = Matrix4x4.Identity; //Matrix4x4.CreateFromAxisAngle(new Vector3(0, 1, 0), (float)Math.PI / 2f);
            var outMesh      = new MeshBuilder <VertexPositionNormal, VertexTexture1, VertexJoints8x4>("Avatar");

            var meshi = 0;

            foreach (var mesh in meshes)
            {
                var tex  = textures[meshi++];
                var data = TextureToPng(tex);

                var material = new MaterialBuilder(mesh.SkinName ?? ("mesh_" + meshi));
                var mtex     = material.UseChannel(KnownChannels.BaseColor).UseTexture().WithPrimaryImage(new ArraySegment <byte>(data));
                var prim     = outMesh.UsePrimitive(material, 3);

                //todo: blend verts
                var previous = new List <VertexBuilder <VertexPositionNormal, VertexTexture1, VertexJoints8x4> >();
                for (int i = 0; i < mesh.IndexBuffer.Length; i++)
                {
                    var point    = mesh.IndexBuffer[(i / 3) * 3 + (2 - (i % 3))]; //flip triangles
                    var vert     = mesh.VertexBuffer[point];
                    var texc     = new Vector2(vert.TextureCoordinate.X, vert.TextureCoordinate.Y);
                    var boneInd  = (int)vert.Parameters.X;
                    var blendInd = (int)vert.Parameters.Y;
                    var mat      = skel.Bones[boneInd].AbsoluteMatrix * RotateMX;
                    var bmat     = skel.Bones[blendInd].AbsoluteMatrix * RotateMX;
                    VertexBuilder <VertexPositionNormal, VertexTexture1, VertexJoints8x4> nvert =
                        (
                            new VertexPositionNormal(
                                Vector3.Lerp(Vec3Convert(Microsoft.Xna.Framework.Vector3.Transform(vert.Position, mat)),
                                             Vec3Convert(Microsoft.Xna.Framework.Vector3.Transform(vert.BvPosition, bmat)),
                                             vert.Parameters.Z),
                                Vector3.Lerp(Vec3Convert(Microsoft.Xna.Framework.Vector3.TransformNormal(vert.Normal, mat)),
                                             Vec3Convert(Microsoft.Xna.Framework.Vector3.TransformNormal(vert.BvNormal, bmat)),
                                             vert.Parameters.Z)
                                ),
                            new VertexTexture1(texc),
                            new VertexJoints8x4(new SharpGLTF.Transforms.SparseWeight8(new Vector4(boneInd, blendInd, 0, 0), new Vector4(1 - vert.Parameters.Z, vert.Parameters.Z, 0, 0)))
                        );
                    if (previous.Count == 2)
                    {
                        prim.AddTriangle(previous[0], previous[1], nvert);
                        previous.Clear();
                    }
                    else
                    {
                        previous.Add(nvert);
                    }
                }
            }
            var skin = builder.AddSkinnedMesh(outMesh, world, orderedBones);

            skin.Name = "Skeleton";
            var schema = builder.ToSchema2();

            /*
             * var children = schema.LogicalScenes.FirstOrDefault().VisualChildren;
             * foreach (var child in children)
             * {
             *  if (child.Skin == null) { //armature
             *      var extras = child.TryUseExtrasAsDictionary(true);
             *      foreach (var tp in timeprops)
             *      {
             *          extras.Add(tp.Key, tp.Value);
             *      }
             *  }
             * }
             */

            //var extras = schema.LogicalNodes.FirstOrDefault(x => x.Name == "ROOT").TryUseExtrasAsDictionary(true);
            var extras = schema.LogicalScenes.FirstOrDefault().TryUseExtrasAsDictionary(true);

            foreach (var tp in timeprops)
            {
                extras.Add(tp.Key, tp.Value);
            }

            return(schema);
        }
Esempio n. 27
0
 internal InstanceBuilder(SceneBuilder parent)
 {
     _Parent = parent;
 }