public void CreateSceneWithAnimatedMeshBuilder()
        {
            TestContext.CurrentContext.AttachShowDirLink();
            TestContext.CurrentContext.AttachGltfValidatorLinks();

            // create a material
            var material1 = new MaterialBuilder("material1").WithChannelParam(KnownChannel.BaseColor, Vector4.One);

            // create a mesh
            var meshBuilder = new MeshBuilder <VPOSNRM>("mesh1");

            meshBuilder.VertexPreprocessor.SetValidationPreprocessors();

            meshBuilder.AddCube(material1, Matrix4x4.Identity);
            meshBuilder.Validate();

            // create an animated node

            var keyframes = new Dictionary <Single, Vector3>()
            {
                [1] = new Vector3(0, 0, 0),
                [2] = new Vector3(50, 0, 0),
                [3] = new Vector3(0, 50, 0),
                [4] = new Vector3(0, 0, 0),
            };

            var pivot = new NodeBuilder("RootNode").WithLocalTranslation("track1", keyframes);

            Assert.AreEqual(4, pivot.UseTranslation("track1").Keys.Count);

            // create scene

            var scene = new SceneBuilder();

            scene.AddRigidMesh(meshBuilder, pivot);

            scene.AttachToCurrentTest("result.glb");
            scene.AttachToCurrentTest("result.gltf");
        }
Exemple #2
0
        public void ZipRoundtripTest()
        {
            // create a model

            var mesh = new MeshBuilder <Geometry.VertexTypes.VertexPositionNormal, Geometry.VertexTypes.VertexEmpty, Geometry.VertexTypes.VertexEmpty>("SphereMesh");

            mesh.AddSphere(Materials.MaterialBuilder.CreateDefault(), 50, System.Numerics.Matrix4x4.Identity);

            var scene = new SceneBuilder();

            scene.AddRigidMesh(mesh, System.Numerics.Matrix4x4.Identity).WithName("Sphere");

            Schema2.ModelRoot model = scene.ToGltf2();

            Assert.AreEqual("SphereMesh", model.LogicalMeshes[0].Name);
            Assert.AreEqual("Sphere", model.LogicalNodes[0].Name);

            model = _ZipRoundtrip(model);

            Assert.AreEqual("SphereMesh", model.LogicalMeshes[0].Name);
            Assert.AreEqual("Sphere", model.LogicalNodes[0].Name);
        }
        public void ColorTest()
        {
            var p1 = new Point(0, 0, 0);
            var p2 = new Point(1, 1, 0);
            var p3 = new Point(1, 0, 0);

            var triangle1 = new Triangle(p1, p2, p3, 100);

            p1 = new Point(5, 5, 0);
            p2 = new Point(6, 6, 0);
            p3 = new Point(6, 5, 0);

            var triangle2 = new Triangle(p1, p2, p3, 100);

            var materialGreen = new MaterialBuilder().
                                WithDoubleSide(true).
                                WithMetallicRoughnessShader().
                                WithChannelParam("BaseColor", new Vector4(0, 1, 0, 1));

            var materialWhite = new MaterialBuilder().
                                WithDoubleSide(true).
                                WithMetallicRoughnessShader().
                                WithChannelParam("BaseColor", new Vector4(1, 1, 1, 1));

            var mesh = new MeshBuilder <VertexPositionNormal>("mesh");

            DrawTriangle(triangle1, materialWhite, mesh);
            DrawTriangle(triangle2, materialGreen, mesh);
            var scene = new SceneBuilder();

            scene.AddRigidMesh(mesh, Matrix4x4.Identity);

            // act
            var model = scene.ToGltf2();

            // assert
            Assert.AreEqual(2, model.LogicalMeshes[0].Primitives.Count);
        }
        public void CreateMeshWithRandomCubes()
        {
            TestContext.CurrentContext.AttachShowDirLink();
            TestContext.CurrentContext.AttachGltfValidatorLinks();

            var rnd = new Random();

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

            // create a mesh
            var cubes = new MeshBuilder <VPOSNRM>("cube");

            cubes.VertexPreprocessor.SetValidationPreprocessors();

            for (int i = 0; i < 100; ++i)
            {
                var r     = rnd.NextVector3() * 5;
                var m     = materials[rnd.Next(0, 10)];
                var xform = Matrix4x4.CreateFromYawPitchRoll(r.X, r.Y, r.Z) * Matrix4x4.CreateTranslation(rnd.NextVector3() * 25);
                cubes.AddCube(m, xform);
            }

            cubes.Validate();

            var scene = new SceneBuilder();

            scene.AddRigidMesh(cubes, Matrix4x4.Identity);

            // save the model as GLB
            scene.AttachToCurrentTest("cubes.glb");
            scene.AttachToCurrentTest("cubes.gltf");
            scene.AttachToCurrentTest("cubes.plotly");
        }
        public void Export(AnalysisLayered analysis, string filePath)
        {
            // solution
            var sol = analysis.SolutionLay;
            // scene
            var scene = new SceneBuilder();

            if (analysis.Content is BoxProperties boxProperties)
            {
                var colors     = boxProperties.Colors;
                var colorFilet = boxProperties.Colors[0];
                var colorTape  = boxProperties.TapeColor;

                var meshPallet = BuildPalletMesh(analysis.Container as PalletProperties);
                var meshCase   = BuildCaseMesh("Case", (float)boxProperties.Length, (float)boxProperties.Width, (float)boxProperties.Height,
                                               colors, 0.0f, colorFilet,
                                               boxProperties.TapeWidth.Activated ? (float)boxProperties.TapeWidth.Value : 0.0f, colorTape);
                var meshesInterlayer = BuildInterlayerMeshes(analysis);

                // add pallet mesh
                scene.AddRigidMesh(meshPallet, Matrix4x4.Identity);
                // add cases (+ interlayers) mesh

                var layers = sol.Layers;
                foreach (ILayer layer in layers)
                {
                    if (layer is Layer3DBox layerBox)
                    {
                        foreach (var bPosition in layerBox)
                        {
                            scene.AddRigidMesh(meshCase, BoxPositionToMatrix4x4(bPosition));
                        }
                    }
                    else if (layer is Layer3DBoxIndexed layerBoxi)
                    {
                        foreach (var bposi in layerBoxi)
                        {
                            scene.AddRigidMesh(meshCase, BoxPositionToMatrix4x4(bposi.BPos));
                        }
                    }
                    else if (layer is InterlayerPos interlayerPos)
                    {
                        var interlayerProp = sol.Interlayers[interlayerPos.TypeId];
                        var bPosition      = new BoxPosition(new Vector3D(
                                                                 0.5 * (analysis.ContainerDimensions.X - interlayerProp.Length)
                                                                 , 0.5 * (analysis.ContainerDimensions.Y - interlayerProp.Width)
                                                                 , interlayerPos.ZLow),
                                                             HalfAxis.HAxis.AXIS_X_P, HalfAxis.HAxis.AXIS_Y_P);
                        scene.AddRigidMesh(meshesInterlayer[interlayerPos.TypeId], BoxPositionToMatrix4x4(bPosition));
                    }
                }
            }
            // add pallet cap if any
            if (analysis is AnalysisCasePallet analysisCasePallet && analysisCasePallet.HasPalletCap)
            {
                var capProperties = analysisCasePallet.PalletCapProperties;
                var bPosition     = new BoxPosition(new Vector3D(
                                                        0.5 * (analysisCasePallet.PalletProperties.Length - capProperties.Length),
                                                        0.5 * (analysisCasePallet.PalletProperties.Width - capProperties.Width),
                                                        sol.BBoxLoad.PtMax.Z - capProperties.InsideHeight)
                                                    , HalfAxis.HAxis.AXIS_X_P, HalfAxis.HAxis.AXIS_Y_P
                                                    );

                scene.AddRigidMesh(BuildPalletCapMesh(
                                       (float)capProperties.Length, (float)capProperties.Width, (float)capProperties.Height,
                                       (float)capProperties.InsideLength, (float)capProperties.InsideWidth, (float)capProperties.InsideHeight,
                                       capProperties.Color),
                                   BoxPositionToMatrix4x4(bPosition));
            }
            // save model
            var model = scene.ToGltf2();

            model.Save(filePath);
        }
Exemple #6
0
        public void CreateSceneWithSharedBuffers()
        {
            TestContext.CurrentContext.AttachShowDirLink();
            TestContext.CurrentContext.AttachGltfValidatorLinks();

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

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

            // create several meshes
            var meshBuilder1 = new MeshBuilder <VPOSNRM>("mesh1");

            meshBuilder1.VertexPreprocessor.SetDebugPreprocessors();
            var meshBuilder2 = new MeshBuilder <VPOSNRM>("mesh2");

            meshBuilder2.VertexPreprocessor.SetDebugPreprocessors();
            var meshBuilder3 = new MeshBuilder <VPOSNRM>("mesh3");

            meshBuilder3.VertexPreprocessor.SetDebugPreprocessors();
            var meshBuilder4 = new MeshBuilder <VPOSNRM>("mesh4");

            meshBuilder4.VertexPreprocessor.SetDebugPreprocessors();

            meshBuilder1.AddCube(material1, Matrix4x4.Identity);
            meshBuilder2.AddCube(material2, Matrix4x4.Identity);
            meshBuilder3.AddSphere(material1, 0.5f, Matrix4x4.Identity);
            meshBuilder4.AddSphere(material2, 0.5f, Matrix4x4.Identity);

            meshBuilder1.Validate();
            meshBuilder2.Validate();
            meshBuilder3.Validate();
            meshBuilder4.Validate();

            // create scene nodes
            var pivot1 = new NodeBuilder("Cube1").WithLocalTranslation(new Vector3(-5, 0, 0));
            var pivot2 = new NodeBuilder("Cube2").WithLocalTranslation(new Vector3(0, 5, 0));
            var pivot3 = new NodeBuilder("SPhere1").WithLocalTranslation(new Vector3(+5, 0, 0));
            var pivot4 = new NodeBuilder("SPhere2").WithLocalTranslation(new Vector3(0, -5, 0));

            // create the scene:

            var scene = new SceneBuilder();

            scene.AddRigidMesh(meshBuilder1, pivot1);
            scene.AddRigidMesh(meshBuilder2, pivot2);
            scene.AddRigidMesh(meshBuilder3, pivot3);
            scene.AddRigidMesh(meshBuilder4, pivot4);

            // convert to gltf2

            var model = scene.ToGltf2();

            model.MergeBuffers();

            // checks
            Assert.AreEqual(1, model.LogicalBuffers.Count);
            Assert.AreEqual(2, model.LogicalBufferViews.Count);
            Assert.IsTrue(model.LogicalBufferViews[0].IsVertexBuffer);
            Assert.IsTrue(model.LogicalBufferViews[1].IsIndexBuffer);
            Assert.AreEqual(2, model.LogicalMaterials.Count);

            model.AttachToCurrentTest("result.glb");
            model.AttachToCurrentTest("result.gltf");
        }
Exemple #7
0
        public void WriteTwoModelsWithSharedTexture()
        {
            TestContext.CurrentContext.AttachShowDirLink();
            TestContext.CurrentContext.AttachGltfValidatorLinks();

            var tex1Bytes = System.IO.File.ReadAllBytes(System.IO.Path.Combine(AssetsPath, "shannon.png"));
            var tex2Bytes = System.IO.File.ReadAllBytes(System.IO.Path.Combine(AssetsPath, "Texture1.jpg"));

            var tex1 = tex1Bytes.AttachToCurrentTest("shared-shannon.png");
            var tex2 = tex2Bytes.AttachToCurrentTest("subdir\\shared-in-dir-Texture1.jpg");

            // create a material using our shared texture
            var material1 = new MaterialBuilder()
                            .WithUnlitShader()
                            .WithBaseColor(tex1);

            // create a material using our shared texture
            var material2 = new MaterialBuilder()
                            .WithUnlitShader()
                            .WithBaseColor(tex2);

            // create a simple cube mesh
            var mesh1 = new Cube <MaterialBuilder>(material1).ToMesh(Matrix4x4.Identity);
            var mesh2 = new Cube <MaterialBuilder>(material2).ToMesh(Matrix4x4.Identity);
            var scene = new SceneBuilder();

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

            var gltf = scene.ToGltf2();

            // define the texture sharing hook; this is a pretty naive approach, but it's good
            // enough to demonstrate how it works.

            string imageSharingHook(WriteContext ctx, string uri, Memory.MemoryImage image)
            {
                Assert.IsTrue(new string[] { tex1, tex2 }.Contains(image.SourcePath));

                if (File.Exists(image.SourcePath))
                {
                    // image.SourcePath is an absolute path, we must make it relative to ctx.CurrentDirectory

                    var currDir = ctx.CurrentDirectory.FullName + "\\";

                    // if the shared texture can be reached by the model in its directory, reuse the texture.
                    if (image.SourcePath.StartsWith(currDir, StringComparison.OrdinalIgnoreCase))
                    {
                        // we've found the shared texture!, return the uri relative to the model:
                        return(image.SourcePath.Substring(currDir.Length));
                    }

                    // TODO: Here we could also try to find a texture equivalent to MemoryImage in the
                    // CurrentDirectory even if it has a different name, to minimize texture duplication.
                }

                // we were unable to reuse the shared texture,
                // default to write our own texture.

                image.SaveToFile(Path.Combine(ctx.CurrentDirectory.FullName, uri));

                return(uri);
            }

            var settings = new WriteSettings();

            settings.ImageWriting       = ResourceWriteMode.SatelliteFile;
            settings.ImageWriteCallback = imageSharingHook;

            // save the model several times:

            var path1 = gltf.AttachToCurrentTest("model1.glb", settings);
            var path2 = gltf.AttachToCurrentTest("model2.glb", settings);
            var path3 = gltf.AttachToCurrentTest("model3.gltf", settings);

            var satellites1 = ModelRoot.GetSatellitePaths(path1);
            var satellites2 = ModelRoot.GetSatellitePaths(path2);
            var satellites3 = ModelRoot.GetSatellitePaths(path3);

            Assert.IsTrue(satellites1.Contains("shared-shannon.png"));
            Assert.IsTrue(satellites1.Contains("subdir/shared-in-dir-Texture1.jpg"));

            Assert.IsTrue(satellites2.Contains("shared-shannon.png"));
            Assert.IsTrue(satellites2.Contains("subdir/shared-in-dir-Texture1.jpg"));

            Assert.IsTrue(satellites3.Contains("shared-shannon.png"));
            Assert.IsTrue(satellites3.Contains("subdir/shared-in-dir-Texture1.jpg"));
        }
Exemple #8
0
        public void SaveToGltf2(string path, string texturePath)
        {
            var textures  = new List <(string, Texture)>();
            var converter = new ImageConverter(texturePath);
            var scene     = new SceneBuilder();
            // var materials = new DictionaryEntry();
            var materials = new MaterialBuilder[Materials.Length];

            var skin   = CreateSkin();
            int meshId = 0;

            foreach (var mesh in Meshes)
            {
                // Console.WriteLine("Process mesh " + meshId);
                int counter = 0;
                foreach (var submesh in mesh.Submeshes)
                {
                    var mat = materials[submesh.Material.Id] ?? InitializeMaterial(submesh.Material, materials, converter);
                    materials[submesh.Material.Id] = mat;


                    if (submesh.Vertices.FirstOrDefault().BoneIndices != null)
                    {
                        var glbMesh   = new MeshBuilder <VertexPositionNormal, VertexTexture1, VertexJoints4>($"{submesh.Name}");
                        var primitive = glbMesh.UsePrimitive(mat);
                        var vertices  = submesh.Vertices
                                        .Select(v => new VertexBuilder <VertexPositionNormal, VertexTexture1, VertexJoints4>(
                                                    new VertexPositionNormal(v.Position, v.Normal),
                                                    new VertexTexture1(new Vector2(v.Uv0.X, 1 - v.Uv0.Y)),
                                                    new VertexJoints4(
                                                        (v.BoneIndices[0], v.BoneWeights[0]),
                                                        (v.BoneIndices[1], v.BoneWeights[1]),
                                                        (v.BoneIndices[2], v.BoneWeights[2]),
                                                        (v.BoneIndices[3], v.BoneWeights[3])
                                                        )
                                                    )).ToArray();
                        var t = submesh.Triangles;
                        for (int i = 0; i < t.GetLength(0); i++)
                        {
                            primitive.AddTriangle(vertices[t[i, 0]], vertices[t[i, 1]], vertices[t[i, 2]]);
                        }

                        scene.AddSkinnedMesh(glbMesh, null, Matrix4x4.Identity, skin);
                    }
                    else
                    {
                        var glbMesh   = new MeshBuilder <VertexPositionNormal, VertexTexture1, VertexEmpty>($"{submesh.Name}");
                        var primitive = glbMesh.UsePrimitive(mat);

                        var vertices = submesh.Vertices
                                       .Select(v => new VertexBuilder <VertexPositionNormal, VertexTexture1, VertexEmpty>(
                                                   new VertexPositionNormal(v.Position, v.Normal),
                                                   new VertexTexture1(new Vector2(v.Uv0.X, 1 - v.Uv0.Y))
                                                   )).ToArray();
                        var t = submesh.Triangles;
                        for (int i = 0; i < t.GetLength(0); i++)
                        {
                            primitive.AddTriangle(vertices[t[i, 0]], vertices[t[i, 1]], vertices[t[i, 2]]);
                        }

                        scene.AddRigidMesh(glbMesh, null, submesh.Transform);
                    }
                }

                meshId++;
            }

            // Console.WriteLine("Save...");
            var gltf2 = scene.ToGltf2();

            // Fix skin
            var firstSkin = gltf2.LogicalSkins.FirstOrDefault();

            foreach (var node in gltf2.LogicalNodes)
            {
                if (node.Skin != null)
                {
                    node.Skin = firstSkin;
                }
            }

            // Fix texture naming (sadl, very inefficient...)
            foreach (var tex in gltf2.LogicalTextures)
            {
                var name = converter.GetName(tex.PrimaryImage.Content.Content.ToArray());
                if (name != null)
                {
                    tex.Name = name;
                    tex.PrimaryImage.Name = name;
                }
                else
                {
                    Console.WriteLine("Texture not found.");
                }
            }

            gltf2.Save(Path.GetFullPath(path), new WriteSettings()
            {
                ImageWriting = ResourceWriteMode.Default,
                Validation   = ValidationMode.Strict
            });
        }
Exemple #9
0
        public static void CreateWithDegeneratedTriangle()
        {
            // create materials

            var material1 = new Materials.MaterialBuilder()
                            .WithMetallicRoughnessShader()
                            .WithChannelParam(Materials.KnownChannel.BaseColor, Materials.KnownProperty.RGBA, Vector4.One * 0.5f);

            var material2 = new Materials.MaterialBuilder()
                            .WithMetallicRoughnessShader()
                            .WithChannelParam(Materials.KnownChannel.BaseColor, Materials.KnownProperty.RGBA, Vector4.One * 0.7f);

            // create a mesh with degenerated triangles

            var validTriangle =
                (
                    new Vector3(4373.192624189425f, 5522.678275192156f, -359.8238015332605f),
                    new Vector3(4370.978060142137f, 5522.723320999183f, -359.89184701762827f),
                    new Vector3(4364.615741107147f, 5511.510615546256f, -359.08922455413233f)
                );

            var degeneratedTriangle =
                (
                    new Vector3(4374.713581837248f, 5519.741978117265f, -360.87014389818034f),
                    new Vector3(4373.187151107471f, 5521.493282925338f, -355.70835120644153f),
                    new Vector3(4373.187151107471f, 5521.493282925338f, -355.70835120644153f)
                );

            var mesh = new MeshBuilder <VertexPosition>("mesh");

            mesh.VertexPreprocessor.SetValidationPreprocessors();

            var validIndices = mesh.UsePrimitive(material1)
                               .AddTriangle
                               (
                new VertexPosition(validTriangle.Item1),
                new VertexPosition(validTriangle.Item2),
                new VertexPosition(validTriangle.Item3)
                               );

            Assert.GreaterOrEqual(validIndices.A, 0);
            Assert.GreaterOrEqual(validIndices.B, 0);
            Assert.GreaterOrEqual(validIndices.C, 0);

            var degenIndices = mesh.UsePrimitive(material2)
                               .AddTriangle
                               (
                new VertexPosition(degeneratedTriangle.Item1),
                new VertexPosition(degeneratedTriangle.Item2),
                new VertexPosition(degeneratedTriangle.Item3)
                               );

            Assert.Less(degenIndices.A, 0);
            Assert.Less(degenIndices.B, 0);
            Assert.Less(degenIndices.C, 0);

            // create scene:

            var scene = new SceneBuilder();

            scene.AddRigidMesh(mesh, Matrix4x4.Identity);

            // check gltf2

            var model = scene.ToGltf2();

            Assert.AreEqual(1, model.LogicalMeshes[0].Primitives.Count);
        }
 public void OnBodyBegin(IBody2 body, MaterialBuilder docMatBuilder, Matrix4x4 postion)
 {
     _sceneBuilder.AddRigidMesh(body.GetBodyMeshBuilder(docMatBuilder), postion);
 }