@zephyr3d/scene 0.8.1 → 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (241) hide show
  1. package/dist/animation/animationset.js +563 -128
  2. package/dist/animation/animationset.js.map +1 -1
  3. package/dist/animation/cloth/gpu_cloth_system.js +2516 -0
  4. package/dist/animation/cloth/gpu_cloth_system.js.map +1 -0
  5. package/dist/animation/fixed_geometry_cache_track.js +138 -0
  6. package/dist/animation/fixed_geometry_cache_track.js.map +1 -0
  7. package/dist/animation/geometry_cache_utils.js +120 -0
  8. package/dist/animation/geometry_cache_utils.js.map +1 -0
  9. package/dist/animation/ik_modifier.js +9 -1
  10. package/dist/animation/ik_modifier.js.map +1 -1
  11. package/dist/animation/joint_dynamics/collision.js +469 -0
  12. package/dist/animation/joint_dynamics/collision.js.map +1 -0
  13. package/dist/animation/joint_dynamics/constraints.js +329 -0
  14. package/dist/animation/joint_dynamics/constraints.js.map +1 -0
  15. package/dist/animation/joint_dynamics/controller.js +699 -0
  16. package/dist/animation/joint_dynamics/controller.js.map +1 -0
  17. package/dist/animation/joint_dynamics/joint_dynamics_system.js +393 -0
  18. package/dist/animation/joint_dynamics/joint_dynamics_system.js.map +1 -0
  19. package/dist/animation/joint_dynamics/solver.js +794 -0
  20. package/dist/animation/joint_dynamics/solver.js.map +1 -0
  21. package/dist/animation/joint_dynamics/types.js +19 -0
  22. package/dist/animation/joint_dynamics/types.js.map +1 -0
  23. package/dist/animation/joint_dynamics/vrm_spring_bone.js +46 -0
  24. package/dist/animation/joint_dynamics/vrm_spring_bone.js.map +1 -0
  25. package/dist/animation/joint_dynamics_modifier.js +51 -0
  26. package/dist/animation/joint_dynamics_modifier.js.map +1 -0
  27. package/dist/animation/pca_geometry_cache_track.js +222 -0
  28. package/dist/animation/pca_geometry_cache_track.js.map +1 -0
  29. package/dist/animation/skeleton.js +1907 -3
  30. package/dist/animation/skeleton.js.map +1 -1
  31. package/dist/animation/skeleton_modifier.js +3 -5
  32. package/dist/animation/skeleton_modifier.js.map +1 -1
  33. package/dist/animation/spring/multi_chain_spring_system.js +2 -0
  34. package/dist/animation/spring/multi_chain_spring_system.js.map +1 -1
  35. package/dist/animation/spring/spring_chain.js +3 -2
  36. package/dist/animation/spring/spring_chain.js.map +1 -1
  37. package/dist/animation/spring/spring_collider.js +35 -5
  38. package/dist/animation/spring/spring_collider.js.map +1 -1
  39. package/dist/animation/spring/spring_particle.js +1 -0
  40. package/dist/animation/spring/spring_particle.js.map +1 -1
  41. package/dist/animation/spring/spring_system.js +325 -28
  42. package/dist/animation/spring/spring_system.js.map +1 -1
  43. package/dist/animation/spring2/collision.js +469 -0
  44. package/dist/animation/spring2/collision.js.map +1 -0
  45. package/dist/animation/spring2/constraints.js +329 -0
  46. package/dist/animation/spring2/constraints.js.map +1 -0
  47. package/dist/animation/spring2/controller.js +434 -0
  48. package/dist/animation/spring2/controller.js.map +1 -0
  49. package/dist/animation/spring2/math.js +16 -0
  50. package/dist/animation/spring2/math.js.map +1 -0
  51. package/dist/animation/spring2/solver.js +624 -0
  52. package/dist/animation/spring2/solver.js.map +1 -0
  53. package/dist/animation/spring2/spring_system.js +118 -0
  54. package/dist/animation/spring2/spring_system.js.map +1 -0
  55. package/dist/animation/spring2/types.js +19 -0
  56. package/dist/animation/spring2/types.js.map +1 -0
  57. package/dist/animation/spring_modifier.js +17 -1
  58. package/dist/animation/spring_modifier.js.map +1 -1
  59. package/dist/app/engine.js +42 -15
  60. package/dist/app/engine.js.map +1 -1
  61. package/dist/app/runtimescript.js +132 -1
  62. package/dist/app/runtimescript.js.map +1 -1
  63. package/dist/app/screen.js +3 -3
  64. package/dist/app/screen.js.map +1 -1
  65. package/dist/app/scriptingsystem.js +69 -37
  66. package/dist/app/scriptingsystem.js.map +1 -1
  67. package/dist/app/scriptregistry.js +157 -146
  68. package/dist/app/scriptregistry.js.map +1 -1
  69. package/dist/asset/assetmanager.js +2 -1
  70. package/dist/asset/assetmanager.js.map +1 -1
  71. package/dist/asset/loaders/zabc/zabc_loader.js +570 -0
  72. package/dist/asset/loaders/zabc/zabc_loader.js.map +1 -0
  73. package/dist/asset/model.js +192 -0
  74. package/dist/asset/model.js.map +1 -1
  75. package/dist/camera/base.js +26 -7
  76. package/dist/camera/base.js.map +1 -1
  77. package/dist/camera/camera.js +146 -24
  78. package/dist/camera/camera.js.map +1 -1
  79. package/dist/camera/fps.js +2 -2
  80. package/dist/camera/fps.js.map +1 -1
  81. package/dist/camera/orbit.js +2 -2
  82. package/dist/camera/orbit.js.map +1 -1
  83. package/dist/index.d.ts +11701 -8506
  84. package/dist/index.js +29 -8
  85. package/dist/index.js.map +1 -1
  86. package/dist/material/lambert.js +1 -1
  87. package/dist/material/lambert.js.map +1 -1
  88. package/dist/material/material.js +9 -3
  89. package/dist/material/material.js.map +1 -1
  90. package/dist/material/meshmaterial.js +54 -7
  91. package/dist/material/meshmaterial.js.map +1 -1
  92. package/dist/material/mixins/lightmodel/blinnphong.js +17 -7
  93. package/dist/material/mixins/lightmodel/blinnphong.js.map +1 -1
  94. package/dist/material/mixins/lightmodel/lambert.js +7 -2
  95. package/dist/material/mixins/lightmodel/lambert.js.map +1 -1
  96. package/dist/material/mixins/lightmodel/pbrblueprintmixin.js +108 -16
  97. package/dist/material/mixins/lightmodel/pbrblueprintmixin.js.map +1 -1
  98. package/dist/material/mixins/lightmodel/pbrmetallicroughness.js +222 -14
  99. package/dist/material/mixins/lightmodel/pbrmetallicroughness.js.map +1 -1
  100. package/dist/material/mixins/lightmodel/pbrspecularglossness.js +24 -12
  101. package/dist/material/mixins/lightmodel/pbrspecularglossness.js.map +1 -1
  102. package/dist/material/mixins/lit.js +11 -8
  103. package/dist/material/mixins/lit.js.map +1 -1
  104. package/dist/material/mixins/pbr/common.js +72 -5
  105. package/dist/material/mixins/pbr/common.js.map +1 -1
  106. package/dist/material/pbrblueprint.js +148 -1
  107. package/dist/material/pbrblueprint.js.map +1 -1
  108. package/dist/material/pbrmr.js +125 -2
  109. package/dist/material/pbrmr.js.map +1 -1
  110. package/dist/material/shader/helper.js +10 -4
  111. package/dist/material/shader/helper.js.map +1 -1
  112. package/dist/material/water.js +2 -2
  113. package/dist/material/water.js.map +1 -1
  114. package/dist/posteffect/coloradjust.js +145 -0
  115. package/dist/posteffect/coloradjust.js.map +1 -0
  116. package/dist/posteffect/taa.js +68 -32
  117. package/dist/posteffect/taa.js.map +1 -1
  118. package/dist/render/cluster_light.js +17 -12
  119. package/dist/render/cluster_light.js.map +1 -1
  120. package/dist/render/deferredlightpass.js +510 -0
  121. package/dist/render/deferredlightpass.js.map +1 -0
  122. package/dist/render/deferredshadowlightpass.js +428 -0
  123. package/dist/render/deferredshadowlightpass.js.map +1 -0
  124. package/dist/render/drawable.js.map +1 -1
  125. package/dist/render/drawable_mixin.js +21 -12
  126. package/dist/render/drawable_mixin.js.map +1 -1
  127. package/dist/render/envlight.js +20 -22
  128. package/dist/render/envlight.js.map +1 -1
  129. package/dist/render/gbufferpass.js +50 -0
  130. package/dist/render/gbufferpass.js.map +1 -0
  131. package/dist/render/lightpass.js +1 -2
  132. package/dist/render/lightpass.js.map +1 -1
  133. package/dist/render/primitive.js +1 -1
  134. package/dist/render/primitive.js.map +1 -1
  135. package/dist/render/render_queue.js +3 -2
  136. package/dist/render/render_queue.js.map +1 -1
  137. package/dist/render/renderer.js +5 -358
  138. package/dist/render/renderer.js.map +1 -1
  139. package/dist/render/rendergraph/executor.js +15 -12
  140. package/dist/render/rendergraph/executor.js.map +1 -1
  141. package/dist/render/rendergraph/forward_plus_builder.js +144 -88
  142. package/dist/render/rendergraph/forward_plus_builder.js.map +1 -1
  143. package/dist/render/rendergraph/history_resource_manager.js +178 -0
  144. package/dist/render/rendergraph/history_resource_manager.js.map +1 -0
  145. package/dist/render/rendergraph/rendergraph.js +12 -1
  146. package/dist/render/rendergraph/rendergraph.js.map +1 -1
  147. package/dist/render/rendergraph/types.js +2 -2
  148. package/dist/render/rendergraph/types.js.map +1 -1
  149. package/dist/render/sky.js +26 -9
  150. package/dist/render/sky.js.map +1 -1
  151. package/dist/scene/basesprite.js +4 -3
  152. package/dist/scene/basesprite.js.map +1 -1
  153. package/dist/scene/batchgroup.js +4 -4
  154. package/dist/scene/environment.js +7 -4
  155. package/dist/scene/environment.js.map +1 -1
  156. package/dist/scene/light.js +184 -18
  157. package/dist/scene/light.js.map +1 -1
  158. package/dist/scene/mesh.js +30 -0
  159. package/dist/scene/mesh.js.map +1 -1
  160. package/dist/scene/particlesys.js +3 -2
  161. package/dist/scene/particlesys.js.map +1 -1
  162. package/dist/scene/raycast_visitor.js +29 -3
  163. package/dist/scene/raycast_visitor.js.map +1 -1
  164. package/dist/scene/scene.js +86 -19
  165. package/dist/scene/scene.js.map +1 -1
  166. package/dist/scene/scene_node.js +87 -31
  167. package/dist/scene/scene_node.js.map +1 -1
  168. package/dist/scene/script_attachment.js +59 -0
  169. package/dist/scene/script_attachment.js.map +1 -0
  170. package/dist/scene/terrain-cm/grass.js +3 -2
  171. package/dist/scene/terrain-cm/grass.js.map +1 -1
  172. package/dist/scene/terrain-cm/terrain-cm.js +4 -3
  173. package/dist/scene/terrain-cm/terrain-cm.js.map +1 -1
  174. package/dist/scene/water.js +3 -2
  175. package/dist/scene/water.js.map +1 -1
  176. package/dist/shaders/shadow.js +2 -2
  177. package/dist/shaders/shadow.js.map +1 -1
  178. package/dist/shadow/shadowmapper.js +74 -4
  179. package/dist/shadow/shadowmapper.js.map +1 -1
  180. package/dist/shapes/box.js +163 -0
  181. package/dist/shapes/box.js.map +1 -1
  182. package/dist/shapes/capsule.js +216 -0
  183. package/dist/shapes/capsule.js.map +1 -0
  184. package/dist/shapes/cylinder.js +91 -0
  185. package/dist/shapes/cylinder.js.map +1 -1
  186. package/dist/shapes/plane.js +32 -0
  187. package/dist/shapes/plane.js.map +1 -1
  188. package/dist/shapes/tetrahedron.js +211 -0
  189. package/dist/shapes/tetrahedron.js.map +1 -1
  190. package/dist/shapes/torus.js +173 -0
  191. package/dist/shapes/torus.js.map +1 -1
  192. package/dist/utility/blueprint/common/math.js +111 -1
  193. package/dist/utility/blueprint/common/math.js.map +1 -1
  194. package/dist/utility/blueprint/material/inputs.js +235 -1
  195. package/dist/utility/blueprint/material/inputs.js.map +1 -1
  196. package/dist/utility/blueprint/material/ir.js +154 -10
  197. package/dist/utility/blueprint/material/ir.js.map +1 -1
  198. package/dist/utility/blueprint/material/texture.js +273 -19
  199. package/dist/utility/blueprint/material/texture.js.map +1 -1
  200. package/dist/utility/serialization/json.js +12 -2
  201. package/dist/utility/serialization/json.js.map +1 -1
  202. package/dist/utility/serialization/manager.js +30 -11
  203. package/dist/utility/serialization/manager.js.map +1 -1
  204. package/dist/utility/serialization/scene/animation.js +250 -7
  205. package/dist/utility/serialization/scene/animation.js.map +1 -1
  206. package/dist/utility/serialization/scene/batch.js +4 -2
  207. package/dist/utility/serialization/scene/batch.js.map +1 -1
  208. package/dist/utility/serialization/scene/camera.js +154 -2
  209. package/dist/utility/serialization/scene/camera.js.map +1 -1
  210. package/dist/utility/serialization/scene/cloth_script.js +834 -0
  211. package/dist/utility/serialization/scene/cloth_script.js.map +1 -0
  212. package/dist/utility/serialization/scene/common.js +7 -0
  213. package/dist/utility/serialization/scene/common.js.map +1 -1
  214. package/dist/utility/serialization/scene/light.js +120 -4
  215. package/dist/utility/serialization/scene/light.js.map +1 -1
  216. package/dist/utility/serialization/scene/material.js +453 -1
  217. package/dist/utility/serialization/scene/material.js.map +1 -1
  218. package/dist/utility/serialization/scene/mesh.js +4 -2
  219. package/dist/utility/serialization/scene/mesh.js.map +1 -1
  220. package/dist/utility/serialization/scene/node.js +298 -10
  221. package/dist/utility/serialization/scene/node.js.map +1 -1
  222. package/dist/utility/serialization/scene/particle.js +4 -2
  223. package/dist/utility/serialization/scene/particle.js.map +1 -1
  224. package/dist/utility/serialization/scene/primitive.js +100 -3
  225. package/dist/utility/serialization/scene/primitive.js.map +1 -1
  226. package/dist/utility/serialization/scene/scene.js +130 -3
  227. package/dist/utility/serialization/scene/scene.js.map +1 -1
  228. package/dist/utility/serialization/scene/script.js +66 -0
  229. package/dist/utility/serialization/scene/script.js.map +1 -0
  230. package/dist/utility/serialization/scene/spring_script.js +596 -0
  231. package/dist/utility/serialization/scene/spring_script.js.map +1 -0
  232. package/dist/utility/serialization/scene/sprite.js +5 -3
  233. package/dist/utility/serialization/scene/sprite.js.map +1 -1
  234. package/dist/utility/serialization/scene/terrain.js +4 -2
  235. package/dist/utility/serialization/scene/terrain.js.map +1 -1
  236. package/dist/utility/serialization/scene/water.js +4 -2
  237. package/dist/utility/serialization/scene/water.js.map +1 -1
  238. package/dist/utility/serialization/types.js.map +1 -1
  239. package/dist/values.js +5 -1
  240. package/dist/values.js.map +1 -1
  241. package/package.json +3 -3
@@ -27,6 +27,97 @@ import { Shape } from './shape.js';
27
27
  /** type of the shape */ get type() {
28
28
  return 'Cylinder';
29
29
  }
30
+ /**
31
+ * {@inheritDoc Primitive.raycast}
32
+ * @override
33
+ *
34
+ * Analytically intersects a ray with a cone frustum (or cylinder when
35
+ * topRadius === bottomRadius) including the optional top and bottom caps.
36
+ *
37
+ * The frustum axis is the Y axis. At y=0 the cross-section radius equals
38
+ * `bottomRadius`; at y=height it equals `topRadius`.
39
+ * Both ends are offset by `anchor`: the bottom cap sits at y = -anchor*height
40
+ * and the top cap at y = (1-anchor)*height.
41
+ */ raycast(ray) {
42
+ const opt = this._options;
43
+ const R0 = opt.bottomRadius ?? 1;
44
+ const R1 = opt.topRadius ?? 1;
45
+ const H = opt.height ?? 1;
46
+ const anchor = opt.anchor ?? 0;
47
+ const yBot = -anchor * H;
48
+ const yTop = yBot + H;
49
+ const ox = ray.origin.x;
50
+ const oy = ray.origin.y;
51
+ const oz = ray.origin.z;
52
+ const dx = ray.direction.x;
53
+ const dy = ray.direction.y;
54
+ const dz = ray.direction.z;
55
+ // radius varies linearly with y: r(y) = R0 + k*(y - yBot)
56
+ const k = (R1 - R0) / H;
57
+ const ry = oy - yBot;
58
+ // Side surface: (ox+t*dx)^2+(oz+t*dz)^2 = (R0+k*(ry+t*dy))^2
59
+ // => A*t^2 + B*t + C = 0
60
+ const rO = R0 + k * ry;
61
+ const A = dx * dx + dz * dz - k * k * dy * dy;
62
+ const B = 2 * (ox * dx + oz * dz - rO * k * dy);
63
+ const C = ox * ox + oz * oz - rO * rO;
64
+ let tMin = Infinity;
65
+ const eps = 1e-10;
66
+ if (Math.abs(A) > eps) {
67
+ const disc = B * B - 4 * A * C;
68
+ if (disc >= 0) {
69
+ const sqrtDisc = Math.sqrt(disc);
70
+ const invA2 = 1 / (2 * A);
71
+ for (const sign of [
72
+ -1,
73
+ 1
74
+ ]){
75
+ const t = (-B + sign * sqrtDisc) * invA2;
76
+ if (t >= 0) {
77
+ const hitY = oy + t * dy;
78
+ if (hitY >= yBot - eps && hitY <= yTop + eps) {
79
+ tMin = Math.min(tMin, t);
80
+ }
81
+ }
82
+ }
83
+ }
84
+ } else if (Math.abs(B) > eps) {
85
+ const t = -C / B;
86
+ if (t >= 0) {
87
+ const hitY = oy + t * dy;
88
+ if (hitY >= yBot - eps && hitY <= yTop + eps) {
89
+ tMin = Math.min(tMin, t);
90
+ }
91
+ }
92
+ }
93
+ // Bottom cap
94
+ if (opt.bottomCap !== false && R0 > eps) {
95
+ if (Math.abs(dy) > eps) {
96
+ const t = (yBot - oy) / dy;
97
+ if (t >= 0) {
98
+ const hx = ox + t * dx;
99
+ const hz = oz + t * dz;
100
+ if (hx * hx + hz * hz <= R0 * R0) {
101
+ tMin = Math.min(tMin, t);
102
+ }
103
+ }
104
+ }
105
+ }
106
+ // Top cap
107
+ if (opt.topCap !== false && R1 > eps) {
108
+ if (Math.abs(dy) > eps) {
109
+ const t = (yTop - oy) / dy;
110
+ if (t >= 0) {
111
+ const hx = ox + t * dx;
112
+ const hz = oz + t * dz;
113
+ if (hx * hx + hz * hz <= R1 * R1) {
114
+ tMin = Math.min(tMin, t);
115
+ }
116
+ }
117
+ }
118
+ }
119
+ return isFinite(tMin) ? tMin : null;
120
+ }
30
121
  /** @internal */ static addPatch(radialDetail, x, y, indices, indexOffset) {
31
122
  const stride = radialDetail + 1;
32
123
  const lt = (y + 1) * stride + x;
@@ -1 +1 @@
1
- {"version":3,"file":"cylinder.js","sources":["../../src/shapes/cylinder.ts"],"sourcesContent":["import type { AABB, Clonable } from '@zephyr3d/base';\r\nimport type { ShapeCreationOptions } from './shape';\r\nimport { Shape } from './shape';\r\n\r\n/**\r\n * Creation options for cylinder shape\r\n * @public\r\n */\r\nexport interface CylinderCreationOptions extends ShapeCreationOptions {\r\n /** Top radius, default is 1.0 **/\r\n bottomRadius?: number;\r\n /** Bottom radius, default is 1.0 */\r\n topRadius?: number;\r\n /** Generate top cap, default is true */\r\n topCap?: boolean;\r\n /** Generate bottom cap, default is true */\r\n bottomCap?: boolean;\r\n /** Height, default is 1.0 */\r\n height?: number;\r\n /** Height detail, default is 1 */\r\n heightDetail?: number;\r\n /** Radial detail, default is 20 */\r\n radialDetail?: number;\r\n /** Anchor point, default is 0 */\r\n anchor?: number;\r\n}\r\n\r\n/**\r\n * Box shape\r\n * @public\r\n */\r\nexport class CylinderShape extends Shape<CylinderCreationOptions> implements Clonable<CylinderShape> {\r\n static _defaultOptions = {\r\n ...Shape._defaultOptions,\r\n topCap: true,\r\n bottomCap: true,\r\n bottomRadius: 1,\r\n topRadius: 1,\r\n heightDetail: 1,\r\n radialDetail: 20,\r\n height: 1,\r\n anchor: 0\r\n };\r\n /**\r\n * Creates an instance of cylinder shape\r\n * @param options - The creation options\r\n */\r\n constructor(options?: CylinderCreationOptions) {\r\n super(options);\r\n }\r\n clone() {\r\n return new CylinderShape(this._options) as this;\r\n }\r\n /** type of the shape */\r\n get type() {\r\n return 'Cylinder' as const;\r\n }\r\n /** @internal */\r\n private static addPatch(\r\n radialDetail: number,\r\n x: number,\r\n y: number,\r\n indices: number[],\r\n indexOffset: number\r\n ) {\r\n const stride = radialDetail + 1;\r\n const lt = (y + 1) * stride + x;\r\n const rt = lt + 1;\r\n const lb = lt - stride;\r\n const rb = lb + 1;\r\n indices?.push(\r\n lt + indexOffset,\r\n lb + indexOffset,\r\n rb + indexOffset,\r\n lt + indexOffset,\r\n rb + indexOffset,\r\n rt + indexOffset\r\n );\r\n }\r\n /**\r\n * Generates the data for the cylinder shape\r\n * @param vertices - vertex positions\r\n * @param normals - vertex normals\r\n * @param uvs - vertex uvs\r\n * @param indices - vertex indices\r\n */\r\n static generateData(\r\n opt: CylinderCreationOptions,\r\n vertices: number[],\r\n normals: number[],\r\n tangents: number[],\r\n uvs: number[],\r\n indices: number[],\r\n bbox?: AABB,\r\n indexOffset?: number,\r\n vertexCallback?: (index: number, x: number, y: number, z: number) => void\r\n ) {\r\n const options = Object.assign({}, this._defaultOptions, opt ?? {});\r\n indexOffset = indexOffset ?? 0;\r\n const start = vertices.length;\r\n\r\n const slope = (options.topRadius - options.bottomRadius) / options.height;\r\n for (let y = 0; y <= options.heightDetail; y++) {\r\n const v = y / options.heightDetail;\r\n const radius = (options.topRadius - options.bottomRadius) * v + options.bottomRadius;\r\n for (let x = 0; x <= options.radialDetail; x++) {\r\n const u = x / options.radialDetail;\r\n const theta = u * Math.PI * 2;\r\n const sinTheta = Math.sin(theta);\r\n const cosTheta = Math.cos(theta);\r\n const m = 1 / Math.hypot(sinTheta, slope, cosTheta);\r\n vertices?.push(radius * sinTheta, (v - options.anchor) * options.height, radius * cosTheta);\r\n normals?.push(sinTheta * m, slope * m, cosTheta * m);\r\n uvs?.push(u, 1 - v);\r\n tangents?.push(cosTheta, 0.0, -sinTheta, 1.0);\r\n if (y < options.heightDetail && x < options.radialDetail) {\r\n this.addPatch(options.radialDetail, x, y, indices, indexOffset);\r\n }\r\n }\r\n }\r\n\r\n const sideVertexCount = (options.heightDetail + 1) * (options.radialDetail + 1);\r\n let currentVertexOffset = start + sideVertexCount;\r\n if (options.bottomCap) {\r\n vertices?.push(0, -options.anchor * options.height, 0);\r\n normals?.push(0, -1, 0);\r\n uvs?.push(0.5, 0.5);\r\n tangents?.push(1, 0, 0, 1);\r\n\r\n const bottomCenterIndex = currentVertexOffset - start;\r\n currentVertexOffset++;\r\n\r\n for (let i = 0; i <= options.radialDetail; i++) {\r\n const theta = (i / options.radialDetail) * Math.PI * 2;\r\n const sinTheta = Math.sin(theta);\r\n const cosTheta = Math.cos(theta);\r\n vertices?.push(\r\n options.bottomRadius * sinTheta,\r\n -options.anchor * options.height,\r\n options.bottomRadius * cosTheta\r\n );\r\n normals?.push(0, -1, 0);\r\n uvs?.push(0.5 + 0.5 * sinTheta, 0.5 + 0.5 * cosTheta);\r\n tangents?.push(1, 0, 0, 1);\r\n currentVertexOffset++;\r\n\r\n if (i < options.radialDetail) {\r\n indices?.push(\r\n bottomCenterIndex + indexOffset,\r\n bottomCenterIndex + i + 2 + indexOffset,\r\n bottomCenterIndex + i + 1 + indexOffset\r\n );\r\n }\r\n }\r\n }\r\n\r\n if (options.topCap) {\r\n vertices?.push(0, (1 - options.anchor) * options.height, 0);\r\n normals?.push(0, 1, 0);\r\n uvs?.push(0.5, 0.5);\r\n tangents?.push(1, 0, 0, 1);\r\n const topCenterIndex = currentVertexOffset - start;\r\n currentVertexOffset++;\r\n\r\n for (let i = 0; i <= options.radialDetail; i++) {\r\n const theta = (i / options.radialDetail) * Math.PI * 2;\r\n const sinTheta = Math.sin(theta);\r\n const cosTheta = Math.cos(theta);\r\n vertices?.push(\r\n options.topRadius * sinTheta,\r\n (1 - options.anchor) * options.height,\r\n options.topRadius * cosTheta\r\n );\r\n normals?.push(0, 1, 0);\r\n uvs?.push(0.5 + 0.5 * sinTheta, 0.5 + 0.5 * cosTheta);\r\n tangents?.push(1, 0, 0, 1);\r\n currentVertexOffset++;\r\n\r\n if (i < options.radialDetail) {\r\n indices?.push(\r\n topCenterIndex + indexOffset,\r\n topCenterIndex + i + 1 + indexOffset,\r\n topCenterIndex + i + 2 + indexOffset\r\n );\r\n }\r\n }\r\n }\r\n\r\n Shape._transform(options.transform, vertices, normals, start);\r\n if (bbox || vertexCallback) {\r\n for (let i = start; i < vertices.length - 2; i += 3) {\r\n if (bbox) {\r\n bbox.minPoint.x = Math.min(bbox.minPoint.x, vertices[i]);\r\n bbox.minPoint.y = Math.min(bbox.minPoint.y, vertices[i + 1]);\r\n bbox.minPoint.z = Math.min(bbox.minPoint.z, vertices[i + 2]);\r\n bbox.maxPoint.x = Math.max(bbox.maxPoint.x, vertices[i]);\r\n bbox.maxPoint.y = Math.max(bbox.maxPoint.y, vertices[i + 1]);\r\n bbox.maxPoint.z = Math.max(bbox.maxPoint.z, vertices[i + 2]);\r\n }\r\n vertexCallback?.((i - start) / 3, vertices[i], vertices[i + 1], vertices[i + 2]);\r\n }\r\n }\r\n return 'triangle-list' as const;\r\n }\r\n}\r\n"],"names":["CylinderShape","Shape","_defaultOptions","topCap","bottomCap","bottomRadius","topRadius","heightDetail","radialDetail","height","anchor","options","clone","_options","type","addPatch","x","y","indices","indexOffset","stride","lt","rt","lb","rb","push","generateData","opt","vertices","normals","tangents","uvs","bbox","vertexCallback","Object","assign","start","length","slope","v","radius","u","theta","Math","PI","sinTheta","sin","cosTheta","cos","m","hypot","sideVertexCount","currentVertexOffset","bottomCenterIndex","i","topCenterIndex","_transform","transform","minPoint","min","z","maxPoint","max"],"mappings":"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"}
1
+ {"version":3,"file":"cylinder.js","sources":["../../src/shapes/cylinder.ts"],"sourcesContent":["import type { AABB, Clonable, Ray } from '@zephyr3d/base';\r\nimport type { ShapeCreationOptions } from './shape';\r\nimport { Shape } from './shape';\r\n\r\n/**\r\n * Creation options for cylinder shape\r\n * @public\r\n */\r\nexport interface CylinderCreationOptions extends ShapeCreationOptions {\r\n /** Top radius, default is 1.0 **/\r\n bottomRadius?: number;\r\n /** Bottom radius, default is 1.0 */\r\n topRadius?: number;\r\n /** Generate top cap, default is true */\r\n topCap?: boolean;\r\n /** Generate bottom cap, default is true */\r\n bottomCap?: boolean;\r\n /** Height, default is 1.0 */\r\n height?: number;\r\n /** Height detail, default is 1 */\r\n heightDetail?: number;\r\n /** Radial detail, default is 20 */\r\n radialDetail?: number;\r\n /** Anchor point, default is 0 */\r\n anchor?: number;\r\n}\r\n\r\n/**\r\n * Box shape\r\n * @public\r\n */\r\nexport class CylinderShape extends Shape<CylinderCreationOptions> implements Clonable<CylinderShape> {\r\n static _defaultOptions = {\r\n ...Shape._defaultOptions,\r\n topCap: true,\r\n bottomCap: true,\r\n bottomRadius: 1,\r\n topRadius: 1,\r\n heightDetail: 1,\r\n radialDetail: 20,\r\n height: 1,\r\n anchor: 0\r\n };\r\n /**\r\n * Creates an instance of cylinder shape\r\n * @param options - The creation options\r\n */\r\n constructor(options?: CylinderCreationOptions) {\r\n super(options);\r\n }\r\n clone() {\r\n return new CylinderShape(this._options) as this;\r\n }\r\n /** type of the shape */\r\n get type() {\r\n return 'Cylinder' as const;\r\n }\r\n /**\r\n * {@inheritDoc Primitive.raycast}\r\n * @override\r\n *\r\n * Analytically intersects a ray with a cone frustum (or cylinder when\r\n * topRadius === bottomRadius) including the optional top and bottom caps.\r\n *\r\n * The frustum axis is the Y axis. At y=0 the cross-section radius equals\r\n * `bottomRadius`; at y=height it equals `topRadius`.\r\n * Both ends are offset by `anchor`: the bottom cap sits at y = -anchor*height\r\n * and the top cap at y = (1-anchor)*height.\r\n */\r\n raycast(ray: Ray) {\r\n const opt = this._options;\r\n const R0 = opt.bottomRadius ?? 1;\r\n const R1 = opt.topRadius ?? 1;\r\n const H = opt.height ?? 1;\r\n const anchor = opt.anchor ?? 0;\r\n const yBot = -anchor * H;\r\n const yTop = yBot + H;\r\n\r\n const ox = ray.origin.x;\r\n const oy = ray.origin.y;\r\n const oz = ray.origin.z;\r\n const dx = ray.direction.x;\r\n const dy = ray.direction.y;\r\n const dz = ray.direction.z;\r\n\r\n // radius varies linearly with y: r(y) = R0 + k*(y - yBot)\r\n const k = (R1 - R0) / H;\r\n const ry = oy - yBot;\r\n\r\n // Side surface: (ox+t*dx)^2+(oz+t*dz)^2 = (R0+k*(ry+t*dy))^2\r\n // => A*t^2 + B*t + C = 0\r\n const rO = R0 + k * ry;\r\n const A = dx * dx + dz * dz - k * k * dy * dy;\r\n const B = 2 * (ox * dx + oz * dz - rO * k * dy);\r\n const C = ox * ox + oz * oz - rO * rO;\r\n\r\n let tMin = Infinity;\r\n\r\n const eps = 1e-10;\r\n if (Math.abs(A) > eps) {\r\n const disc = B * B - 4 * A * C;\r\n if (disc >= 0) {\r\n const sqrtDisc = Math.sqrt(disc);\r\n const invA2 = 1 / (2 * A);\r\n for (const sign of [-1, 1]) {\r\n const t = (-B + sign * sqrtDisc) * invA2;\r\n if (t >= 0) {\r\n const hitY = oy + t * dy;\r\n if (hitY >= yBot - eps && hitY <= yTop + eps) {\r\n tMin = Math.min(tMin, t);\r\n }\r\n }\r\n }\r\n }\r\n } else if (Math.abs(B) > eps) {\r\n const t = -C / B;\r\n if (t >= 0) {\r\n const hitY = oy + t * dy;\r\n if (hitY >= yBot - eps && hitY <= yTop + eps) {\r\n tMin = Math.min(tMin, t);\r\n }\r\n }\r\n }\r\n\r\n // Bottom cap\r\n if (opt.bottomCap !== false && R0 > eps) {\r\n if (Math.abs(dy) > eps) {\r\n const t = (yBot - oy) / dy;\r\n if (t >= 0) {\r\n const hx = ox + t * dx;\r\n const hz = oz + t * dz;\r\n if (hx * hx + hz * hz <= R0 * R0) {\r\n tMin = Math.min(tMin, t);\r\n }\r\n }\r\n }\r\n }\r\n\r\n // Top cap\r\n if (opt.topCap !== false && R1 > eps) {\r\n if (Math.abs(dy) > eps) {\r\n const t = (yTop - oy) / dy;\r\n if (t >= 0) {\r\n const hx = ox + t * dx;\r\n const hz = oz + t * dz;\r\n if (hx * hx + hz * hz <= R1 * R1) {\r\n tMin = Math.min(tMin, t);\r\n }\r\n }\r\n }\r\n }\r\n\r\n return isFinite(tMin) ? tMin : null;\r\n }\r\n /** @internal */\r\n private static addPatch(\r\n radialDetail: number,\r\n x: number,\r\n y: number,\r\n indices: number[],\r\n indexOffset: number\r\n ) {\r\n const stride = radialDetail + 1;\r\n const lt = (y + 1) * stride + x;\r\n const rt = lt + 1;\r\n const lb = lt - stride;\r\n const rb = lb + 1;\r\n indices?.push(\r\n lt + indexOffset,\r\n lb + indexOffset,\r\n rb + indexOffset,\r\n lt + indexOffset,\r\n rb + indexOffset,\r\n rt + indexOffset\r\n );\r\n }\r\n /**\r\n * Generates the data for the cylinder shape\r\n * @param vertices - vertex positions\r\n * @param normals - vertex normals\r\n * @param uvs - vertex uvs\r\n * @param indices - vertex indices\r\n */\r\n static generateData(\r\n opt: CylinderCreationOptions,\r\n vertices: number[],\r\n normals: number[],\r\n tangents: number[],\r\n uvs: number[],\r\n indices: number[],\r\n bbox?: AABB,\r\n indexOffset?: number,\r\n vertexCallback?: (index: number, x: number, y: number, z: number) => void\r\n ) {\r\n const options = Object.assign({}, this._defaultOptions, opt ?? {});\r\n indexOffset = indexOffset ?? 0;\r\n const start = vertices.length;\r\n\r\n const slope = (options.topRadius - options.bottomRadius) / options.height;\r\n for (let y = 0; y <= options.heightDetail; y++) {\r\n const v = y / options.heightDetail;\r\n const radius = (options.topRadius - options.bottomRadius) * v + options.bottomRadius;\r\n for (let x = 0; x <= options.radialDetail; x++) {\r\n const u = x / options.radialDetail;\r\n const theta = u * Math.PI * 2;\r\n const sinTheta = Math.sin(theta);\r\n const cosTheta = Math.cos(theta);\r\n const m = 1 / Math.hypot(sinTheta, slope, cosTheta);\r\n vertices?.push(radius * sinTheta, (v - options.anchor) * options.height, radius * cosTheta);\r\n normals?.push(sinTheta * m, slope * m, cosTheta * m);\r\n uvs?.push(u, 1 - v);\r\n tangents?.push(cosTheta, 0.0, -sinTheta, 1.0);\r\n if (y < options.heightDetail && x < options.radialDetail) {\r\n this.addPatch(options.radialDetail, x, y, indices, indexOffset);\r\n }\r\n }\r\n }\r\n\r\n const sideVertexCount = (options.heightDetail + 1) * (options.radialDetail + 1);\r\n let currentVertexOffset = start + sideVertexCount;\r\n if (options.bottomCap) {\r\n vertices?.push(0, -options.anchor * options.height, 0);\r\n normals?.push(0, -1, 0);\r\n uvs?.push(0.5, 0.5);\r\n tangents?.push(1, 0, 0, 1);\r\n\r\n const bottomCenterIndex = currentVertexOffset - start;\r\n currentVertexOffset++;\r\n\r\n for (let i = 0; i <= options.radialDetail; i++) {\r\n const theta = (i / options.radialDetail) * Math.PI * 2;\r\n const sinTheta = Math.sin(theta);\r\n const cosTheta = Math.cos(theta);\r\n vertices?.push(\r\n options.bottomRadius * sinTheta,\r\n -options.anchor * options.height,\r\n options.bottomRadius * cosTheta\r\n );\r\n normals?.push(0, -1, 0);\r\n uvs?.push(0.5 + 0.5 * sinTheta, 0.5 + 0.5 * cosTheta);\r\n tangents?.push(1, 0, 0, 1);\r\n currentVertexOffset++;\r\n\r\n if (i < options.radialDetail) {\r\n indices?.push(\r\n bottomCenterIndex + indexOffset,\r\n bottomCenterIndex + i + 2 + indexOffset,\r\n bottomCenterIndex + i + 1 + indexOffset\r\n );\r\n }\r\n }\r\n }\r\n\r\n if (options.topCap) {\r\n vertices?.push(0, (1 - options.anchor) * options.height, 0);\r\n normals?.push(0, 1, 0);\r\n uvs?.push(0.5, 0.5);\r\n tangents?.push(1, 0, 0, 1);\r\n const topCenterIndex = currentVertexOffset - start;\r\n currentVertexOffset++;\r\n\r\n for (let i = 0; i <= options.radialDetail; i++) {\r\n const theta = (i / options.radialDetail) * Math.PI * 2;\r\n const sinTheta = Math.sin(theta);\r\n const cosTheta = Math.cos(theta);\r\n vertices?.push(\r\n options.topRadius * sinTheta,\r\n (1 - options.anchor) * options.height,\r\n options.topRadius * cosTheta\r\n );\r\n normals?.push(0, 1, 0);\r\n uvs?.push(0.5 + 0.5 * sinTheta, 0.5 + 0.5 * cosTheta);\r\n tangents?.push(1, 0, 0, 1);\r\n currentVertexOffset++;\r\n\r\n if (i < options.radialDetail) {\r\n indices?.push(\r\n topCenterIndex + indexOffset,\r\n topCenterIndex + i + 1 + indexOffset,\r\n topCenterIndex + i + 2 + indexOffset\r\n );\r\n }\r\n }\r\n }\r\n\r\n Shape._transform(options.transform, vertices, normals, start);\r\n if (bbox || vertexCallback) {\r\n for (let i = start; i < vertices.length - 2; i += 3) {\r\n if (bbox) {\r\n bbox.minPoint.x = Math.min(bbox.minPoint.x, vertices[i]);\r\n bbox.minPoint.y = Math.min(bbox.minPoint.y, vertices[i + 1]);\r\n bbox.minPoint.z = Math.min(bbox.minPoint.z, vertices[i + 2]);\r\n bbox.maxPoint.x = Math.max(bbox.maxPoint.x, vertices[i]);\r\n bbox.maxPoint.y = Math.max(bbox.maxPoint.y, vertices[i + 1]);\r\n bbox.maxPoint.z = Math.max(bbox.maxPoint.z, vertices[i + 2]);\r\n }\r\n vertexCallback?.((i - start) / 3, vertices[i], vertices[i + 1], vertices[i + 2]);\r\n }\r\n }\r\n return 'triangle-list' as const;\r\n }\r\n}\r\n"],"names":["CylinderShape","Shape","_defaultOptions","topCap","bottomCap","bottomRadius","topRadius","heightDetail","radialDetail","height","anchor","options","clone","_options","type","raycast","ray","opt","R0","R1","H","yBot","yTop","ox","origin","x","oy","y","oz","z","dx","direction","dy","dz","k","ry","rO","A","B","C","tMin","Infinity","eps","Math","abs","disc","sqrtDisc","sqrt","invA2","sign","t","hitY","min","hx","hz","isFinite","addPatch","indices","indexOffset","stride","lt","rt","lb","rb","push","generateData","vertices","normals","tangents","uvs","bbox","vertexCallback","Object","assign","start","length","slope","v","radius","u","theta","PI","sinTheta","sin","cosTheta","cos","m","hypot","sideVertexCount","currentVertexOffset","bottomCenterIndex","i","topCenterIndex","_transform","transform","minPoint","maxPoint","max"],"mappings":"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"}
@@ -24,6 +24,38 @@ import { Shape } from './shape.js';
24
24
  return 'Plane';
25
25
  }
26
26
  /**
27
+ * {@inheritDoc Primitive.raycast}
28
+ * @override
29
+ *
30
+ * Intersects the ray with the finite XZ plane (y = 0) whose bounds are
31
+ * determined by size/anchor options.
32
+ */ raycast(ray) {
33
+ const opt = this._options;
34
+ const sizeX = Math.abs(opt.sizeX || opt.size || 1);
35
+ const sizeY = Math.abs(opt.sizeY || opt.size || 1);
36
+ const anchorX = opt.anchorX ?? opt.anchor ?? 0.5;
37
+ const anchorY = opt.anchorY ?? opt.anchor ?? 0.5;
38
+ const minX = -anchorX * sizeX;
39
+ const maxX = minX + sizeX;
40
+ const minZ = -anchorY * sizeY;
41
+ const maxZ = minZ + sizeY;
42
+ // Plane is y = 0 (XZ plane)
43
+ const dy = ray.direction.y;
44
+ if (Math.abs(dy) < 1e-10) {
45
+ return null;
46
+ } // ray parallel to plane
47
+ const t = -ray.origin.y / dy;
48
+ if (t < 0) {
49
+ return null;
50
+ }
51
+ const hx = ray.origin.x + t * ray.direction.x;
52
+ const hz = ray.origin.z + t * ray.direction.z;
53
+ if (hx < minX || hx > maxX || hz < minZ || hz > maxZ) {
54
+ return null;
55
+ }
56
+ return t;
57
+ }
58
+ /**
27
59
  * Generates the data for the cylinder shape
28
60
  * @param vertices - vertex positions
29
61
  * @param normals - vertex normals
@@ -1 +1 @@
1
- {"version":3,"file":"plane.js","sources":["../../src/shapes/plane.ts"],"sourcesContent":["import type { AABB, Clonable } from '@zephyr3d/base';\r\nimport type { ShapeCreationOptions } from './shape';\r\nimport { Shape } from './shape';\r\n\r\n/**\r\n * Creation options for plane shapes\r\n * @public\r\n */\r\nexport interface PlaneCreationOptions extends ShapeCreationOptions {\r\n /** Default size of axis x and axis y, default is 1 */\r\n size?: number;\r\n /** Size of axis x, default value equals to size */\r\n sizeX?: number;\r\n /** Size of axis y, default value equals to size */\r\n sizeY?: number;\r\n /** Resolution, default is 1 */\r\n resolution?: number;\r\n /** Resolution X, default value equals to resolution */\r\n resolutionX?: number;\r\n /** Resolution Y, default value equals to resolution */\r\n resolutionY?: number;\r\n /** Whether this plane have front side, default is true */\r\n twoSided?: boolean;\r\n /** Anchor, default is 0.5 */\r\n anchor?: number;\r\n /** Anchor X, default value equals to anchor */\r\n anchorX?: number;\r\n /** Anchor Z, default value equals to anchor */\r\n anchorY?: number;\r\n}\r\n\r\n/**\r\n * The plane shape\r\n * @public\r\n */\r\nexport class PlaneShape extends Shape<PlaneCreationOptions> implements Clonable<PlaneShape> {\r\n static _defaultOptions = {\r\n ...Shape._defaultOptions,\r\n size: 1,\r\n resolution: 1,\r\n twoSided: false,\r\n anchor: 0.5\r\n };\r\n /**\r\n * Creates an instance of plane shape\r\n * @param options - The creation options\r\n */\r\n constructor(options?: PlaneCreationOptions) {\r\n super(options);\r\n }\r\n clone() {\r\n return new PlaneShape(this._options) as this;\r\n }\r\n /** type of the shape */\r\n get type() {\r\n return 'Plane' as const;\r\n }\r\n /**\r\n * Generates the data for the cylinder shape\r\n * @param vertices - vertex positions\r\n * @param normals - vertex normals\r\n * @param uvs - vertex uvs\r\n * @param indices - vertex indices\r\n */\r\n static generateData(\r\n opt: PlaneCreationOptions,\r\n vertices: number[],\r\n normals: number[],\r\n tangents: number[],\r\n uvs: number[],\r\n indices: number[],\r\n bbox?: AABB,\r\n indexOffset?: number,\r\n vertexCallback?: (index: number, x: number, y: number, z: number) => void\r\n ) {\r\n const options = Object.assign({}, this._defaultOptions, opt ?? {});\r\n indexOffset = indexOffset ?? 0;\r\n const start = vertices.length;\r\n const sizeX = Math.abs(options.sizeX || options.size) || 1;\r\n const sizeY = Math.abs(options.sizeY || options.size) || 1;\r\n const anchorX = options.anchorX ?? options.anchor;\r\n const anchorY = options.anchorY ?? options.anchor;\r\n const minX = -anchorX * sizeX;\r\n const maxX = minX + sizeX;\r\n const minY = -anchorY * sizeY;\r\n const maxY = minY + sizeY;\r\n const resolutionX = Math.max(options.resolutionX ?? options.resolution, 1);\r\n const resolutionY = Math.max(options.resolutionY ?? options.resolution, 1);\r\n const dx = (maxX - minX) / resolutionX;\r\n const dy = (maxY - minY) / resolutionY;\r\n for (let i = 0; i <= resolutionX; i++) {\r\n for (let j = 0; j <= resolutionY; j++) {\r\n uvs?.push(i / resolutionX, j / resolutionY);\r\n vertices?.push(minX + dx * i, 0, minY + dy * j);\r\n normals?.push(0, 1, 0);\r\n tangents?.push(1, 0, 0, 1);\r\n }\r\n }\r\n if (indices) {\r\n for (let i = 0; i < resolutionX; i++) {\r\n for (let j = 0; j < resolutionY; j++) {\r\n const tl = j * (resolutionY + 1) + i;\r\n const tr = (j + 1) * (resolutionY + 1) + i;\r\n const bl = tl + 1;\r\n const br = tr + 1;\r\n indices.push(\r\n tl + indexOffset,\r\n bl + indexOffset,\r\n br + indexOffset,\r\n tl + indexOffset,\r\n br + indexOffset,\r\n tr + indexOffset\r\n );\r\n if (options.twoSided) {\r\n indices.push(\r\n tl + indexOffset,\r\n br + indexOffset,\r\n bl + indexOffset,\r\n tl + indexOffset,\r\n tr + indexOffset,\r\n br + indexOffset\r\n );\r\n }\r\n }\r\n }\r\n }\r\n Shape._transform(options.transform, vertices, normals, start);\r\n if (bbox || vertexCallback) {\r\n for (let i = start; i < vertices.length - 2; i += 3) {\r\n if (bbox) {\r\n bbox.minPoint.x = Math.min(bbox.minPoint.x, vertices[i]);\r\n bbox.minPoint.y = Math.min(bbox.minPoint.y, vertices[i + 1]);\r\n bbox.minPoint.z = Math.min(bbox.minPoint.z, vertices[i + 2]);\r\n bbox.maxPoint.x = Math.max(bbox.maxPoint.x, vertices[i]);\r\n bbox.maxPoint.y = Math.max(bbox.maxPoint.y, vertices[i + 1]);\r\n bbox.maxPoint.z = Math.max(bbox.maxPoint.z, vertices[i + 2]);\r\n }\r\n vertexCallback?.((i - start) / 3, vertices[i], vertices[i + 1], vertices[i + 2]);\r\n }\r\n }\r\n return 'triangle-list' as const;\r\n }\r\n}\r\n"],"names":["PlaneShape","Shape","_defaultOptions","size","resolution","twoSided","anchor","options","clone","_options","type","generateData","opt","vertices","normals","tangents","uvs","indices","bbox","indexOffset","vertexCallback","Object","assign","start","length","sizeX","Math","abs","sizeY","anchorX","anchorY","minX","maxX","minY","maxY","resolutionX","max","resolutionY","dx","dy","i","j","push","tl","tr","bl","br","_transform","transform","minPoint","x","min","y","z","maxPoint"],"mappings":"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"}
1
+ {"version":3,"file":"plane.js","sources":["../../src/shapes/plane.ts"],"sourcesContent":["import type { AABB, Clonable, Ray } from '@zephyr3d/base';\r\nimport type { ShapeCreationOptions } from './shape';\r\nimport { Shape } from './shape';\r\n\r\n/**\r\n * Creation options for plane shapes\r\n * @public\r\n */\r\nexport interface PlaneCreationOptions extends ShapeCreationOptions {\r\n /** Default size of axis x and axis y, default is 1 */\r\n size?: number;\r\n /** Size of axis x, default value equals to size */\r\n sizeX?: number;\r\n /** Size of axis y, default value equals to size */\r\n sizeY?: number;\r\n /** Resolution, default is 1 */\r\n resolution?: number;\r\n /** Resolution X, default value equals to resolution */\r\n resolutionX?: number;\r\n /** Resolution Y, default value equals to resolution */\r\n resolutionY?: number;\r\n /** Whether this plane have front side, default is true */\r\n twoSided?: boolean;\r\n /** Anchor, default is 0.5 */\r\n anchor?: number;\r\n /** Anchor X, default value equals to anchor */\r\n anchorX?: number;\r\n /** Anchor Z, default value equals to anchor */\r\n anchorY?: number;\r\n}\r\n\r\n/**\r\n * The plane shape\r\n * @public\r\n */\r\nexport class PlaneShape extends Shape<PlaneCreationOptions> implements Clonable<PlaneShape> {\r\n static _defaultOptions = {\r\n ...Shape._defaultOptions,\r\n size: 1,\r\n resolution: 1,\r\n twoSided: false,\r\n anchor: 0.5\r\n };\r\n /**\r\n * Creates an instance of plane shape\r\n * @param options - The creation options\r\n */\r\n constructor(options?: PlaneCreationOptions) {\r\n super(options);\r\n }\r\n clone() {\r\n return new PlaneShape(this._options) as this;\r\n }\r\n /** type of the shape */\r\n get type() {\r\n return 'Plane' as const;\r\n }\r\n /**\r\n * {@inheritDoc Primitive.raycast}\r\n * @override\r\n *\r\n * Intersects the ray with the finite XZ plane (y = 0) whose bounds are\r\n * determined by size/anchor options.\r\n */\r\n raycast(ray: Ray) {\r\n const opt = this._options;\r\n const sizeX = Math.abs(opt.sizeX || opt.size || 1);\r\n const sizeY = Math.abs(opt.sizeY || opt.size || 1);\r\n const anchorX = opt.anchorX ?? opt.anchor ?? 0.5;\r\n const anchorY = opt.anchorY ?? opt.anchor ?? 0.5;\r\n const minX = -anchorX * sizeX;\r\n const maxX = minX + sizeX;\r\n const minZ = -anchorY * sizeY;\r\n const maxZ = minZ + sizeY;\r\n\r\n // Plane is y = 0 (XZ plane)\r\n const dy = ray.direction.y;\r\n if (Math.abs(dy) < 1e-10) {\r\n return null;\r\n } // ray parallel to plane\r\n\r\n const t = -ray.origin.y / dy;\r\n if (t < 0) {\r\n return null;\r\n }\r\n\r\n const hx = ray.origin.x + t * ray.direction.x;\r\n const hz = ray.origin.z + t * ray.direction.z;\r\n if (hx < minX || hx > maxX || hz < minZ || hz > maxZ) {\r\n return null;\r\n }\r\n\r\n return t;\r\n }\r\n /**\r\n * Generates the data for the cylinder shape\r\n * @param vertices - vertex positions\r\n * @param normals - vertex normals\r\n * @param uvs - vertex uvs\r\n * @param indices - vertex indices\r\n */\r\n static generateData(\r\n opt: PlaneCreationOptions,\r\n vertices: number[],\r\n normals: number[],\r\n tangents: number[],\r\n uvs: number[],\r\n indices: number[],\r\n bbox?: AABB,\r\n indexOffset?: number,\r\n vertexCallback?: (index: number, x: number, y: number, z: number) => void\r\n ) {\r\n const options = Object.assign({}, this._defaultOptions, opt ?? {});\r\n indexOffset = indexOffset ?? 0;\r\n const start = vertices.length;\r\n const sizeX = Math.abs(options.sizeX || options.size) || 1;\r\n const sizeY = Math.abs(options.sizeY || options.size) || 1;\r\n const anchorX = options.anchorX ?? options.anchor;\r\n const anchorY = options.anchorY ?? options.anchor;\r\n const minX = -anchorX * sizeX;\r\n const maxX = minX + sizeX;\r\n const minY = -anchorY * sizeY;\r\n const maxY = minY + sizeY;\r\n const resolutionX = Math.max(options.resolutionX ?? options.resolution, 1);\r\n const resolutionY = Math.max(options.resolutionY ?? options.resolution, 1);\r\n const dx = (maxX - minX) / resolutionX;\r\n const dy = (maxY - minY) / resolutionY;\r\n for (let i = 0; i <= resolutionX; i++) {\r\n for (let j = 0; j <= resolutionY; j++) {\r\n uvs?.push(i / resolutionX, j / resolutionY);\r\n vertices?.push(minX + dx * i, 0, minY + dy * j);\r\n normals?.push(0, 1, 0);\r\n tangents?.push(1, 0, 0, 1);\r\n }\r\n }\r\n if (indices) {\r\n for (let i = 0; i < resolutionX; i++) {\r\n for (let j = 0; j < resolutionY; j++) {\r\n const tl = j * (resolutionY + 1) + i;\r\n const tr = (j + 1) * (resolutionY + 1) + i;\r\n const bl = tl + 1;\r\n const br = tr + 1;\r\n indices.push(\r\n tl + indexOffset,\r\n bl + indexOffset,\r\n br + indexOffset,\r\n tl + indexOffset,\r\n br + indexOffset,\r\n tr + indexOffset\r\n );\r\n if (options.twoSided) {\r\n indices.push(\r\n tl + indexOffset,\r\n br + indexOffset,\r\n bl + indexOffset,\r\n tl + indexOffset,\r\n tr + indexOffset,\r\n br + indexOffset\r\n );\r\n }\r\n }\r\n }\r\n }\r\n Shape._transform(options.transform, vertices, normals, start);\r\n if (bbox || vertexCallback) {\r\n for (let i = start; i < vertices.length - 2; i += 3) {\r\n if (bbox) {\r\n bbox.minPoint.x = Math.min(bbox.minPoint.x, vertices[i]);\r\n bbox.minPoint.y = Math.min(bbox.minPoint.y, vertices[i + 1]);\r\n bbox.minPoint.z = Math.min(bbox.minPoint.z, vertices[i + 2]);\r\n bbox.maxPoint.x = Math.max(bbox.maxPoint.x, vertices[i]);\r\n bbox.maxPoint.y = Math.max(bbox.maxPoint.y, vertices[i + 1]);\r\n bbox.maxPoint.z = Math.max(bbox.maxPoint.z, vertices[i + 2]);\r\n }\r\n vertexCallback?.((i - start) / 3, vertices[i], vertices[i + 1], vertices[i + 2]);\r\n }\r\n }\r\n return 'triangle-list' as const;\r\n }\r\n}\r\n"],"names":["PlaneShape","Shape","_defaultOptions","size","resolution","twoSided","anchor","options","clone","_options","type","raycast","ray","opt","sizeX","Math","abs","sizeY","anchorX","anchorY","minX","maxX","minZ","maxZ","dy","direction","y","t","origin","hx","x","hz","z","generateData","vertices","normals","tangents","uvs","indices","bbox","indexOffset","vertexCallback","Object","assign","start","length","minY","maxY","resolutionX","max","resolutionY","dx","i","j","push","tl","tr","bl","br","_transform","transform","minPoint","min","maxPoint"],"mappings":"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"}
@@ -20,6 +20,119 @@ import { Shape } from './shape.js';
20
20
  get type() {
21
21
  return 'Tetrahedron';
22
22
  }
23
+ /**
24
+ * {@inheritDoc Primitive.raycast}
25
+ * @override
26
+ *
27
+ * Tests each triangular face of the tetrahedron with the Möller–Trumbore
28
+ * algorithm and returns the smallest non-negative t.
29
+ */ raycast(ray) {
30
+ const opt = this._options;
31
+ const height = opt.height ?? 1;
32
+ const sizeX = opt.sizeX ?? 1;
33
+ const sizeZ = opt.sizeZ ?? 1;
34
+ const top = [
35
+ 0,
36
+ height,
37
+ 0
38
+ ];
39
+ const p0 = [
40
+ sizeX,
41
+ 0,
42
+ sizeZ
43
+ ]; // pxpz
44
+ const p1 = [
45
+ sizeX,
46
+ 0,
47
+ -sizeZ
48
+ ]; // pxnz
49
+ const p2 = [
50
+ -sizeX,
51
+ 0,
52
+ -sizeZ
53
+ ]; // nxnz
54
+ const p3 = [
55
+ -sizeX,
56
+ 0,
57
+ sizeZ
58
+ ]; // nxpz
59
+ // All six faces (4 side triangles + 2 bottom triangles)
60
+ const faces = [
61
+ [
62
+ top,
63
+ p0,
64
+ p1
65
+ ],
66
+ [
67
+ top,
68
+ p1,
69
+ p2
70
+ ],
71
+ [
72
+ top,
73
+ p2,
74
+ p3
75
+ ],
76
+ [
77
+ top,
78
+ p3,
79
+ p0
80
+ ],
81
+ [
82
+ p0,
83
+ p3,
84
+ p1
85
+ ],
86
+ [
87
+ p1,
88
+ p3,
89
+ p2
90
+ ] // bottom tri 2: pxnz -> nxpz -> nxnz
91
+ ];
92
+ let tMin = Infinity;
93
+ for (const [v0, v1, v2] of faces){
94
+ const t = TetrahedronShape._rayTriangle(ray, v0, v1, v2);
95
+ if (t !== null && t < tMin) {
96
+ tMin = t;
97
+ }
98
+ }
99
+ return isFinite(tMin) ? tMin : null;
100
+ }
101
+ /**
102
+ * @internal Möller–Trumbore ray-triangle intersection.
103
+ * Returns t >= 0 on hit, null otherwise.
104
+ */ static _rayTriangle(ray, v0, v1, v2) {
105
+ const eps = 1e-8;
106
+ const e1x = v1[0] - v0[0], e1y = v1[1] - v0[1], e1z = v1[2] - v0[2];
107
+ const e2x = v2[0] - v0[0], e2y = v2[1] - v0[1], e2z = v2[2] - v0[2];
108
+ const dx = ray.direction.x, dy = ray.direction.y, dz = ray.direction.z;
109
+ // h = D × e2
110
+ const hx = dy * e2z - dz * e2y;
111
+ const hy = dz * e2x - dx * e2z;
112
+ const hz = dx * e2y - dy * e2x;
113
+ const det = e1x * hx + e1y * hy + e1z * hz;
114
+ if (Math.abs(det) < eps) {
115
+ return null;
116
+ }
117
+ const invDet = 1 / det;
118
+ const sx = ray.origin.x - v0[0];
119
+ const sy = ray.origin.y - v0[1];
120
+ const sz = ray.origin.z - v0[2];
121
+ const u = (sx * hx + sy * hy + sz * hz) * invDet;
122
+ if (u < 0 || u > 1) {
123
+ return null;
124
+ }
125
+ // q = s × e1
126
+ const qx = sy * e1z - sz * e1y;
127
+ const qy = sz * e1x - sx * e1z;
128
+ const qz = sx * e1y - sy * e1x;
129
+ const v = (dx * qx + dy * qy + dz * qz) * invDet;
130
+ if (v < 0 || u + v > 1) {
131
+ return null;
132
+ }
133
+ const t = (e2x * qx + e2y * qy + e2z * qz) * invDet;
134
+ return t >= 0 ? t : null;
135
+ }
23
136
  static calculateTriangleNormal(v0, v1, v2) {
24
137
  const edge1 = Vector3.sub(v1, v0);
25
138
  const edge2 = Vector3.sub(v2, v0);
@@ -145,6 +258,104 @@ import { Shape } from './shape.js';
145
258
  get type() {
146
259
  return 'TetrahedronFrame';
147
260
  }
261
+ /**
262
+ * {@inheritDoc Primitive.raycast}
263
+ * @override
264
+ *
265
+ * Tests each triangular face of the tetrahedron with the Möller–Trumbore
266
+ * algorithm and returns the smallest non-negative t.
267
+ * The wireframe has the same overall geometry as the solid version.
268
+ */ raycast(ray) {
269
+ const opt = this._options;
270
+ const height = opt.height ?? 1;
271
+ const sizeX = opt.sizeX ?? 1;
272
+ const sizeZ = opt.sizeZ ?? 1;
273
+ const top = [
274
+ 0,
275
+ height,
276
+ 0
277
+ ];
278
+ const p0 = [
279
+ sizeX,
280
+ 0,
281
+ sizeZ
282
+ ];
283
+ const p1 = [
284
+ sizeX,
285
+ 0,
286
+ -sizeZ
287
+ ];
288
+ const p2 = [
289
+ -sizeX,
290
+ 0,
291
+ -sizeZ
292
+ ];
293
+ const p3 = [
294
+ -sizeX,
295
+ 0,
296
+ sizeZ
297
+ ];
298
+ const faces = [
299
+ [
300
+ top,
301
+ p0,
302
+ p1
303
+ ],
304
+ [
305
+ top,
306
+ p1,
307
+ p2
308
+ ],
309
+ [
310
+ top,
311
+ p2,
312
+ p3
313
+ ],
314
+ [
315
+ top,
316
+ p3,
317
+ p0
318
+ ]
319
+ ];
320
+ let tMin = Infinity;
321
+ for (const [v0, v1, v2] of faces){
322
+ const t = TetrahedronFrameShape._rayTriangle(ray, v0, v1, v2);
323
+ if (t !== null && t < tMin) {
324
+ tMin = t;
325
+ }
326
+ }
327
+ return isFinite(tMin) ? tMin : null;
328
+ }
329
+ /** @internal Möller–Trumbore ray-triangle intersection */ static _rayTriangle(ray, v0, v1, v2) {
330
+ const eps = 1e-8;
331
+ const e1x = v1[0] - v0[0], e1y = v1[1] - v0[1], e1z = v1[2] - v0[2];
332
+ const e2x = v2[0] - v0[0], e2y = v2[1] - v0[1], e2z = v2[2] - v0[2];
333
+ const dx = ray.direction.x, dy = ray.direction.y, dz = ray.direction.z;
334
+ const hx = dy * e2z - dz * e2y;
335
+ const hy = dz * e2x - dx * e2z;
336
+ const hz = dx * e2y - dy * e2x;
337
+ const det = e1x * hx + e1y * hy + e1z * hz;
338
+ if (Math.abs(det) < eps) {
339
+ return null;
340
+ }
341
+ const invDet = 1 / det;
342
+ const sx = ray.origin.x - v0[0];
343
+ const sy = ray.origin.y - v0[1];
344
+ const sz = ray.origin.z - v0[2];
345
+ const u = (sx * hx + sy * hy + sz * hz) * invDet;
346
+ if (u < 0 || u > 1) {
347
+ return null;
348
+ }
349
+ const qx = sy * e1z - sz * e1y;
350
+ const qy = sz * e1x - sx * e1z;
351
+ const qz = sx * e1y - sy * e1x;
352
+ const v = (dx * qx + dy * qy + dz * qz) * invDet;
353
+ if (v < 0 || u + v > 1) {
354
+ return null;
355
+ }
356
+ const t = (e2x * qx + e2y * qy + e2z * qz) * invDet;
357
+ return t >= 0 ? t : null;
358
+ }
148
359
  static calculateTriangleNormal(v0, v1, v2) {
149
360
  const edge1 = Vector3.sub(v1, v0);
150
361
  const edge2 = Vector3.sub(v2, v0);