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"); }
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); }
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"); }
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")); }
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 }); }
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); }