| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157 |
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Numerics;
- using SharpGLTF.Schema2;
- using SharpGLTF.Geometry;
- using SharpGLTF.Geometry.VertexTypes;
- namespace InfiniteSkinnedTentacle
- {
- using VERTEX = VertexBuilder<VertexPosition, VertexColor1, VertexJoints4>;
- using MESH = MeshBuilder<VertexPosition, VertexColor1, VertexJoints4>;
- class Program
- {
- // Skinning use cases and examples: https://github.com/KhronosGroup/glTF/issues/1403
- // hierarchy created:
- // Mesh1
- // Skin1─> Armature1
- // Skin2─> Armature2
- // Skin3─> Armature3
- // Scene
- // ├── Armature1
- // │ ├── Bone1
- // │ ├── Bone2
- // │ └── Bone3
- // ├── SkinnedMesh1─> Mesh1, Skin1
- // ├── Armature2
- // │ ├── Bone1
- // │ ├── Bone2
- // │ └── Bone3
- // ├── SkinnedMesh2─> Mesh1, Skin2
- // ├── Armature3
- // │ ├── Bone1
- // │ ├── Bone2
- // │ └── Bone3
- // └── SkinnedMesh3─> Mesh1, Skin3
- // ...
- static void Main(string[] args)
- {
- var model = ModelRoot.CreateModel();
- var scene = model.UseScene("default");
- var mesh = model
- .CreateMeshes(CreateMesh(10))
- .First();
- RecusiveTentacle(scene, scene, Matrix4x4.CreateTranslation(+25, 0, +25), mesh, Quaternion.CreateFromYawPitchRoll(0f, 0.2f, 0f), 2);
- RecusiveTentacle(scene, scene, Matrix4x4.CreateTranslation(-25, 0, +25), mesh, Quaternion.CreateFromYawPitchRoll(0.2f, 0f, 0f), 2);
- RecusiveTentacle(scene, scene, Matrix4x4.CreateTranslation(-25, 0, -25), mesh, Quaternion.CreateFromYawPitchRoll(0f, 0f, 0.2f), 2);
- RecusiveTentacle(scene, scene, Matrix4x4.CreateTranslation(+25, 0, -25), mesh, Quaternion.CreateFromYawPitchRoll(0.2f, 0f, 0f), 2);
- model.SaveGLB("recursive tentacles.glb");
- model.SaveGLTF("recursive tentacles.gltf");
- model.SaveAsWavefront("recursive_tentacles_at_000.obj", model.LogicalAnimations[0], 0);
- model.SaveAsWavefront("recursive_tentacles_at_025.obj", model.LogicalAnimations[0], 0.25f);
- model.SaveAsWavefront("recursive_tentacles_at_050.obj", model.LogicalAnimations[0], 0.50f);
- model.SaveAsWavefront("recursive_tentacles_at_075.obj", model.LogicalAnimations[0], 0.75f);
- model.SaveAsWavefront("recursive_tentacles_at_100.obj", model.LogicalAnimations[0], 1);
- }
-
- static void RecusiveTentacle(Scene scene, IVisualNodeContainer parent, Matrix4x4 offset, Mesh mesh, Quaternion anim, int repeat)
- {
- parent = parent
- .CreateNode()
- .WithLocalTransform(offset);
- parent = AddTentacleSkeleton(scene, parent as Node, mesh, anim);
- if (repeat == 0) return;
- var scale = Matrix4x4.CreateScale(0.2f);
- RecusiveTentacle(scene, parent, Matrix4x4.CreateTranslation(+15, 0, +15) * scale, mesh, Quaternion.CreateFromYawPitchRoll(0f, 0.2f, 0f), repeat - 1);
- RecusiveTentacle(scene, parent, Matrix4x4.CreateTranslation(-15, 0, +15) * scale, mesh, Quaternion.CreateFromYawPitchRoll(0.2f, 0f, 0f), repeat - 1);
- RecusiveTentacle(scene, parent, Matrix4x4.CreateTranslation(-15, 0, -15) * scale, mesh, Quaternion.CreateFromYawPitchRoll(0f, 0f, 0.2f), repeat - 1);
- RecusiveTentacle(scene, parent, Matrix4x4.CreateTranslation(+15, 0, -15) * scale, mesh, Quaternion.CreateFromYawPitchRoll(0.2f, 0f, 0f), repeat - 1);
- }
- static Node AddTentacleSkeleton(Scene scene, Node skeleton, Mesh mesh, Quaternion anim)
- {
- var bindings = new List<Node>();
- Node bone = null;
- for (int i = 0; i < 10; ++i)
- {
- if (bone == null)
- {
- bone = skeleton;
- }
- else
- {
- bone = bone.CreateNode();
- bone.LocalTransform = Matrix4x4.CreateTranslation(0, 10, 0);
- }
- bone.WithRotationAnimation("Track0", (0, Quaternion.Identity), (1, anim), (2, Quaternion.Identity));
- bindings.Add(bone);
- }
- scene
- .CreateNode()
- .WithSkinnedMesh(mesh, skeleton.WorldMatrix, bindings.ToArray());
- return bindings.Last();
- }
- static MESH CreateMesh(int boneCount)
- {
- var mesh = new MESH("skinned mesh");
- mesh.VertexPreprocessor.SetValidationPreprocessors();
- var prim = mesh.UsePrimitive(new SharpGLTF.Materials.MaterialBuilder("Default"));
- var a0 = default(VERTEX);
- var a1 = default(VERTEX);
- var a2 = default(VERTEX);
- var a3 = default(VERTEX);
- for (int i = 0; i < boneCount; ++i)
- {
- var b0 = new VERTEX(new Vector3(-5, i * 10, -5), Vector4.One, (i, 1));
- var b1 = new VERTEX(new Vector3(+5, i * 10, -5), Vector4.One, (i, 1));
- var b2 = new VERTEX(new Vector3(+5, i * 10, +5), Vector4.One, (i, 1));
- var b3 = new VERTEX(new Vector3(-5, i * 10, +5), Vector4.One, (i, 1));
- if (i == 0)
- {
- prim.AddQuadrangle(b0, b1, b2, b3);
- }
- else
- {
- prim.AddQuadrangle(b0, b1, a1, a0);
- prim.AddQuadrangle(b1, b2, a2, a1);
- prim.AddQuadrangle(b2, b3, a3, a2);
- prim.AddQuadrangle(b3, b0, a0, a3);
- }
- a0 = b0;
- a1 = b1;
- a2 = b2;
- a3 = b3;
- }
- prim.AddQuadrangle(a3, a2, a1, a0);
- return mesh;
- }
- }
- }
|