Program.cs 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Numerics;
  5. using SharpGLTF.Schema2;
  6. using SharpGLTF.Geometry;
  7. using SharpGLTF.Geometry.VertexTypes;
  8. namespace InfiniteSkinnedTentacle
  9. {
  10. using VERTEX = VertexBuilder<VertexPosition, VertexColor1, VertexJoints8x4>;
  11. using MESH = MeshBuilder<VertexPosition, VertexColor1, VertexJoints8x4>;
  12. class Program
  13. {
  14. // Skinning use cases and examples: https://github.com/KhronosGroup/glTF/issues/1403
  15. // hierarchy created:
  16. // Mesh1
  17. // Skin1─> Armature1
  18. // Skin2─> Armature2
  19. // Skin3─> Armature3
  20. // Scene
  21. // ├── Armature1
  22. // │ ├── Bone1
  23. // │ ├── Bone2
  24. // │ └── Bone3
  25. // ├── SkinnedMesh1─> Mesh1, Skin1
  26. // ├── Armature2
  27. // │ ├── Bone1
  28. // │ ├── Bone2
  29. // │ └── Bone3
  30. // ├── SkinnedMesh2─> Mesh1, Skin2
  31. // ├── Armature3
  32. // │ ├── Bone1
  33. // │ ├── Bone2
  34. // │ └── Bone3
  35. // └── SkinnedMesh3─> Mesh1, Skin3
  36. // ...
  37. static void Main(string[] args)
  38. {
  39. var model = ModelRoot.CreateModel();
  40. var scene = model.UseScene("default");
  41. var mesh = model
  42. .CreateMeshes(CreateMesh(10))
  43. .First();
  44. RecusiveTentacle(scene, scene, Matrix4x4.CreateTranslation(+25, 0, +25), mesh, Quaternion.CreateFromYawPitchRoll(0f, 0.2f, 0f), 2);
  45. RecusiveTentacle(scene, scene, Matrix4x4.CreateTranslation(-25, 0, +25), mesh, Quaternion.CreateFromYawPitchRoll(0.2f, 0f, 0f), 2);
  46. RecusiveTentacle(scene, scene, Matrix4x4.CreateTranslation(-25, 0, -25), mesh, Quaternion.CreateFromYawPitchRoll(0f, 0f, 0.2f), 2);
  47. RecusiveTentacle(scene, scene, Matrix4x4.CreateTranslation(+25, 0, -25), mesh, Quaternion.CreateFromYawPitchRoll(0.2f, 0f, 0f), 2);
  48. model.SaveGLB("recursive tentacles.glb");
  49. model.SaveAsWavefront("recursive_tentacles_at_000.obj", model.LogicalAnimations[0], 0);
  50. model.SaveAsWavefront("recursive_tentacles_at_025.obj", model.LogicalAnimations[0], 0.25f);
  51. model.SaveAsWavefront("recursive_tentacles_at_050.obj", model.LogicalAnimations[0], 0.50f);
  52. model.SaveAsWavefront("recursive_tentacles_at_075.obj", model.LogicalAnimations[0], 0.75f);
  53. model.SaveAsWavefront("recursive_tentacles_at_100.obj", model.LogicalAnimations[0], 1);
  54. }
  55. static void RecusiveTentacle(Scene scene, IVisualNodeContainer parent, Matrix4x4 offset, Mesh mesh, Quaternion anim, int repeat)
  56. {
  57. parent = parent
  58. .CreateNode()
  59. .WithLocalTransform(offset);
  60. parent = AddTentacleSkeleton(scene, parent as Node, mesh, anim);
  61. if (repeat == 0) return;
  62. var scale = Matrix4x4.CreateScale(0.2f);
  63. RecusiveTentacle(scene, parent, Matrix4x4.CreateTranslation(+15, 0, +15) * scale, mesh, Quaternion.CreateFromYawPitchRoll(0f, 0.2f, 0f), repeat - 1);
  64. RecusiveTentacle(scene, parent, Matrix4x4.CreateTranslation(-15, 0, +15) * scale, mesh, Quaternion.CreateFromYawPitchRoll(0.2f, 0f, 0f), repeat - 1);
  65. RecusiveTentacle(scene, parent, Matrix4x4.CreateTranslation(-15, 0, -15) * scale, mesh, Quaternion.CreateFromYawPitchRoll(0f, 0f, 0.2f), repeat - 1);
  66. RecusiveTentacle(scene, parent, Matrix4x4.CreateTranslation(+15, 0, -15) * scale, mesh, Quaternion.CreateFromYawPitchRoll(0.2f, 0f, 0f), repeat - 1);
  67. }
  68. static Node AddTentacleSkeleton(Scene scene, Node skeleton, Mesh mesh, Quaternion anim)
  69. {
  70. var bindings = new List<Node>();
  71. Node bone = null;
  72. for (int i = 0; i < 10; ++i)
  73. {
  74. if (bone == null)
  75. {
  76. bone = skeleton;
  77. }
  78. else
  79. {
  80. bone = bone.CreateNode();
  81. bone.LocalTransform = Matrix4x4.CreateTranslation(0, 10, 0);
  82. }
  83. bone.WithRotationAnimation("Track0", (0, Quaternion.Identity), (1, anim), (2, Quaternion.Identity));
  84. bindings.Add(bone);
  85. }
  86. scene
  87. .CreateNode()
  88. .WithSkinnedMesh(mesh, bindings.ToArray());
  89. return bindings.Last();
  90. }
  91. static MESH CreateMesh(int boneCount)
  92. {
  93. var mesh = new MESH("skinned mesh");
  94. mesh.VertexPreprocessor.SetDebugPreprocessors();
  95. var prim = mesh.UsePrimitive(new SharpGLTF.Materials.MaterialBuilder("Default"));
  96. var a0 = default(VERTEX);
  97. var a1 = default(VERTEX);
  98. var a2 = default(VERTEX);
  99. var a3 = default(VERTEX);
  100. for (int i = 0; i < boneCount; ++i)
  101. {
  102. var b0 = new VERTEX(new Vector3(-5, i * 10, -5), Vector4.One, (i, 1));
  103. var b1 = new VERTEX(new Vector3(+5, i * 10, -5), Vector4.One, (i, 1));
  104. var b2 = new VERTEX(new Vector3(+5, i * 10, +5), Vector4.One, (i, 1));
  105. var b3 = new VERTEX(new Vector3(-5, i * 10, +5), Vector4.One, (i, 1));
  106. if (i == 0)
  107. {
  108. prim.AddConvexPolygon(b0, b1, b2, b3);
  109. }
  110. else
  111. {
  112. prim.AddConvexPolygon(b0, b1, a1, a0);
  113. prim.AddConvexPolygon(b1, b2, a2, a1);
  114. prim.AddConvexPolygon(b2, b3, a3, a2);
  115. prim.AddConvexPolygon(b3, b0, a0, a3);
  116. }
  117. a0 = b0;
  118. a1 = b1;
  119. a2 = b2;
  120. a3 = b3;
  121. }
  122. prim.AddConvexPolygon(a3, a2, a1, a0);
  123. return mesh;
  124. }
  125. }
  126. static class ToolkitUtils
  127. {
  128. public static void AddConvexPolygon<TMaterial, TvG, TvM, TvS>(this PrimitiveBuilder<TMaterial, TvG, TvM, TvS> primitive, params VertexBuilder<TvG, TvM, TvS>[] vertices)
  129. where TvG : struct, IVertexGeometry
  130. where TvM : struct, IVertexMaterial
  131. where TvS : struct, IVertexSkinning
  132. {
  133. for (int i = 2; i < vertices.Length; ++i)
  134. {
  135. var a = vertices[0];
  136. var b = vertices[i - 1];
  137. var c = vertices[i];
  138. primitive.AddTriangle(a, b, c);
  139. }
  140. }
  141. }
  142. }