public void CreateAnimatedCubeScene() { 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"); }
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.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"); }
public void CreateCubeSceneWithExtras() { TestContext.CurrentContext.AttachShowDirLink(); 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"); }
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"); }
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"); }
public void ExportMeshes(string path) { TestContext.CurrentContext.AttachGltfValidatorLinks(); path = TestFiles .GetSampleModelsPaths() .FirstOrDefault(item => item.Contains(path)); // load the glTF model var srcModel = ModelRoot.Load(path, Validation.ValidationMode.TryFix); Assert.NotNull(srcModel); srcModel.AttachToCurrentTest("GearBoxAssy.plotly"); // convert it to a SceneBuilder so we can manipulate it: var srcScene = srcModel.DefaultScene.ToSceneBuilder(); // export all the individual meshes to OBJ: for (int i = 0; i < srcScene.Instances.Count; ++i) { var inst = srcScene.Instances[i].Content; // scan for meshes: if (inst.Content is MeshContent mesh) { var newScene = new SceneBuilder(); newScene.AddRigidMesh(mesh.Mesh, inst.GetPoseWorldMatrix()); newScene.AttachToCurrentTest($"result_{i}.obj"); } } }
public void CreateCubeScene() { TestContext.CurrentContext.AttachGltfValidatorLinks(); var material = MaterialBuilder.CreateDefault(); var mesh = new Cube <MaterialBuilder>(material).ToMesh(Matrix4x4.Identity); var scene = new SceneBuilder(); scene.AddRigidMesh(mesh, Matrix4x4.Identity); scene.AttachToCurrentTest("cube.glb"); scene.AttachToCurrentTest("cube.gltf"); scene.AttachToCurrentTest("cube.plotly"); }
public void CreateNonConvexQuadsScene() { TestContext.CurrentContext.AttachShowDirLink(); TestContext.CurrentContext.AttachGltfValidatorLinks(); 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.AddRigidMesh(mesh, Matrix4x4.Identity); scene.AttachToCurrentTest("NonConvexQuads.glb"); scene.AttachToCurrentTest("NonConvexQuads.gltf"); }
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"); }
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"); }
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"); }
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"); }