@woosh/meep-engine 2.162.0 → 2.163.1
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.
- package/README.md +1 -1
- package/package.json +1 -1
- package/src/core/color/xyz/rgb_to_xyz.d.ts +3 -3
- package/src/core/color/xyz/rgb_to_xyz.d.ts.map +1 -1
- package/src/core/color/xyz/rgb_to_xyz.js +2 -2
- package/src/core/color/xyz/xyz_to_rgb.d.ts +3 -3
- package/src/core/color/xyz/xyz_to_rgb.d.ts.map +1 -1
- package/src/core/color/xyz/xyz_to_rgb.js +2 -2
- package/src/core/geom/vec3/v3_array_scale.d.ts +11 -0
- package/src/core/geom/vec3/v3_array_scale.d.ts.map +1 -0
- package/src/core/geom/vec3/v3_array_scale.js +18 -0
- package/src/engine/EngineHarness.js +3 -3
- package/src/engine/graphics/ecs/path/tube/build/makeTubeGeometry.js +218 -202
- package/src/engine/graphics/ecs/path/tube/build/make_cap.d.ts.map +1 -1
- package/src/engine/graphics/ecs/path/tube/build/make_cap.js +11 -2
- package/src/engine/graphics/sh3/path_tracer/make_sky_hosek.d.ts.map +1 -1
- package/src/engine/graphics/sh3/path_tracer/make_sky_hosek.js +45 -44
- package/src/engine/graphics/sh3/sky/hosek/sky_hosek_compute_irradiance_by_direction.d.ts +5 -7
- package/src/engine/graphics/sh3/sky/hosek/sky_hosek_compute_irradiance_by_direction.d.ts.map +1 -1
- package/src/engine/graphics/sh3/sky/hosek/sky_hosek_compute_irradiance_by_direction.js +388 -395
package/README.md
CHANGED
package/package.json
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
"description": "Pure JavaScript game engine. Fully featured and production ready.",
|
|
7
7
|
"type": "module",
|
|
8
8
|
"author": "Alexander Goldring",
|
|
9
|
-
"version": "2.
|
|
9
|
+
"version": "2.163.1",
|
|
10
10
|
"main": "build/meep.module.js",
|
|
11
11
|
"module": "build/meep.module.js",
|
|
12
12
|
"exports": {
|
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
* Assumes linear RGB space
|
|
4
4
|
* Assumes D65 standard illuminant
|
|
5
5
|
* @see https://www.image-engineering.de/library/technotes/958-how-to-convert-between-srgb-and-ciexyz
|
|
6
|
-
* @param {
|
|
7
|
-
* @param {
|
|
6
|
+
* @param {number[]|Float32Array|Float64Array} out
|
|
7
|
+
* @param {number[]|Float32Array|Float64Array} input
|
|
8
8
|
*/
|
|
9
|
-
export function rgb_to_xyz(out:
|
|
9
|
+
export function rgb_to_xyz(out: number[] | Float32Array | Float64Array, input: number[] | Float32Array | Float64Array): void;
|
|
10
10
|
//# sourceMappingURL=rgb_to_xyz.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rgb_to_xyz.d.ts","sourceRoot":"","sources":["../../../../../src/core/color/xyz/rgb_to_xyz.js"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,
|
|
1
|
+
{"version":3,"file":"rgb_to_xyz.d.ts","sourceRoot":"","sources":["../../../../../src/core/color/xyz/rgb_to_xyz.js"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,gCAHW,MAAM,EAAE,GAAC,YAAY,GAAC,YAAY,SAClC,MAAM,EAAE,GAAC,YAAY,GAAC,YAAY,QAW5C"}
|
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
* Assumes linear RGB space
|
|
4
4
|
* Assumes D65 standard illuminant
|
|
5
5
|
* @see https://www.image-engineering.de/library/technotes/958-how-to-convert-between-srgb-and-ciexyz
|
|
6
|
-
* @param {
|
|
7
|
-
* @param {
|
|
6
|
+
* @param {number[]|Float32Array|Float64Array} out
|
|
7
|
+
* @param {number[]|Float32Array|Float64Array} input
|
|
8
8
|
*/
|
|
9
9
|
export function rgb_to_xyz(out, input) {
|
|
10
10
|
|
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
* CIE color model to linear RGB
|
|
3
3
|
* Assumes D65 standard illuminant
|
|
4
4
|
* @see https://www.image-engineering.de/library/technotes/958-how-to-convert-between-srgb-and-ciexyz
|
|
5
|
-
* @param {
|
|
6
|
-
* @param {
|
|
5
|
+
* @param {number[]|Float32Array|Float64Array} out
|
|
6
|
+
* @param {number[]|Float32Array|Float64Array} input
|
|
7
7
|
*/
|
|
8
|
-
export function xyz_to_rgb(out:
|
|
8
|
+
export function xyz_to_rgb(out: number[] | Float32Array | Float64Array, input: number[] | Float32Array | Float64Array): void;
|
|
9
9
|
//# sourceMappingURL=xyz_to_rgb.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"xyz_to_rgb.d.ts","sourceRoot":"","sources":["../../../../../src/core/color/xyz/xyz_to_rgb.js"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,gCAHW,
|
|
1
|
+
{"version":3,"file":"xyz_to_rgb.d.ts","sourceRoot":"","sources":["../../../../../src/core/color/xyz/xyz_to_rgb.js"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,gCAHW,MAAM,EAAE,GAAC,YAAY,GAAC,YAAY,SAClC,MAAM,EAAE,GAAC,YAAY,GAAC,YAAY,QAU5C"}
|
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
* CIE color model to linear RGB
|
|
3
3
|
* Assumes D65 standard illuminant
|
|
4
4
|
* @see https://www.image-engineering.de/library/technotes/958-how-to-convert-between-srgb-and-ciexyz
|
|
5
|
-
* @param {
|
|
6
|
-
* @param {
|
|
5
|
+
* @param {number[]|Float32Array|Float64Array} out
|
|
6
|
+
* @param {number[]|Float32Array|Float64Array} input
|
|
7
7
|
*/
|
|
8
8
|
export function xyz_to_rgb(out, input) {
|
|
9
9
|
const x = input[0];
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Scale a 3d vector by a scalar, writing the result into `output`.
|
|
3
|
+
*
|
|
4
|
+
* @param {number[]|Float32Array} output
|
|
5
|
+
* @param {number} output_offset
|
|
6
|
+
* @param {number[]|Float32Array} input
|
|
7
|
+
* @param {number} input_offset
|
|
8
|
+
* @param {number} scalar
|
|
9
|
+
*/
|
|
10
|
+
export function v3_array_scale(output: number[] | Float32Array, output_offset: number, input: number[] | Float32Array, input_offset: number, scalar: number): void;
|
|
11
|
+
//# sourceMappingURL=v3_array_scale.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"v3_array_scale.d.ts","sourceRoot":"","sources":["../../../../../src/core/geom/vec3/v3_array_scale.js"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,uCANW,MAAM,EAAE,GAAC,YAAY,iBACrB,MAAM,SACN,MAAM,EAAE,GAAC,YAAY,gBACrB,MAAM,UACN,MAAM,QAUhB"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Scale a 3d vector by a scalar, writing the result into `output`.
|
|
3
|
+
*
|
|
4
|
+
* @param {number[]|Float32Array} output
|
|
5
|
+
* @param {number} output_offset
|
|
6
|
+
* @param {number[]|Float32Array} input
|
|
7
|
+
* @param {number} input_offset
|
|
8
|
+
* @param {number} scalar
|
|
9
|
+
*/
|
|
10
|
+
export function v3_array_scale(
|
|
11
|
+
output, output_offset,
|
|
12
|
+
input, input_offset,
|
|
13
|
+
scalar,
|
|
14
|
+
) {
|
|
15
|
+
output[output_offset] = input[input_offset] * scalar;
|
|
16
|
+
output[output_offset + 1] = input[input_offset + 1] * scalar;
|
|
17
|
+
output[output_offset + 2] = input[input_offset + 2] * scalar;
|
|
18
|
+
}
|
|
@@ -270,11 +270,11 @@ export class EngineHarness {
|
|
|
270
270
|
*/
|
|
271
271
|
static async buildBasics({
|
|
272
272
|
engine,
|
|
273
|
-
focus = new Vector3(
|
|
273
|
+
focus = new Vector3(0, 0, 0),
|
|
274
274
|
heightMap,
|
|
275
275
|
heightRange,
|
|
276
276
|
pitch = 0.7,
|
|
277
|
-
yaw =
|
|
277
|
+
yaw = 0,
|
|
278
278
|
distance = 10,
|
|
279
279
|
terrainSize = new Vector2(10, 10),
|
|
280
280
|
terrainResolution = 10,
|
|
@@ -287,7 +287,7 @@ export class EngineHarness {
|
|
|
287
287
|
cameraController = true,
|
|
288
288
|
cameraAutoClip = true,
|
|
289
289
|
shadowmapResolution,
|
|
290
|
-
showFps =
|
|
290
|
+
showFps = false
|
|
291
291
|
}) {
|
|
292
292
|
|
|
293
293
|
if (showFps) {
|
|
@@ -1,202 +1,218 @@
|
|
|
1
|
-
import { BufferGeometry, Vector3 } from "three";
|
|
2
|
-
import { assert } from "../../../../../../core/assert.js";
|
|
3
|
-
import { v3_angle_cos_between } from "../../../../../../core/geom/vec3/v3_angle_cos_between.js";
|
|
4
|
-
import { v3_length } from "../../../../../../core/geom/vec3/v3_length.js";
|
|
5
|
-
import { CapType } from "../CapType.js";
|
|
6
|
-
import { append_compute_cap_geometry_size, make_cap } from "./make_cap.js";
|
|
7
|
-
import { make_ring_faces } from "./make_ring_faces.js";
|
|
8
|
-
import { make_ring_vertices } from "./make_ring_vertices.js";
|
|
9
|
-
import { StreamGeometryBuilder } from "./StreamGeometryBuilder.js";
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
const v4_array = new Float32Array(4);
|
|
13
|
-
|
|
14
|
-
/**
|
|
15
|
-
* @see https://github.com/mrdoob/three.js/blob/master/src/geometries/TubeGeometry.js
|
|
16
|
-
* @see https://github.com/hofk/THREEg.js/blob/488f1128a25321a76888aa1fa19db64750318444/THREEg.js#L3483
|
|
17
|
-
* @param {Float32Array|number[]} in_positions
|
|
18
|
-
* @param {Vector3[]} in_normals
|
|
19
|
-
* @param {Vector3[]} in_binormals
|
|
20
|
-
* @param {Vector3[]} in_tangents
|
|
21
|
-
* @param {number[]} shape
|
|
22
|
-
* @param {number[]|Float32Array} shape_normal
|
|
23
|
-
* @param {number} shape_length
|
|
24
|
-
* @param {number[]|Float32Array} shape_transform
|
|
25
|
-
* @param {boolean} [closed]
|
|
26
|
-
* @param {CapType} [cap_type]
|
|
27
|
-
* @returns {BufferGeometry}
|
|
28
|
-
*/
|
|
29
|
-
export function makeTubeGeometry(
|
|
30
|
-
in_positions, in_normals, in_binormals, in_tangents,
|
|
31
|
-
shape, shape_normal, shape_length, shape_transform, closed = false, cap_type = CapType.Round
|
|
32
|
-
) {
|
|
33
|
-
assert.enum(cap_type, CapType, 'cap_type');
|
|
34
|
-
assert.isBoolean(closed, 'closed');
|
|
35
|
-
|
|
36
|
-
assert.isNumber(shape_length, 'shape_length');
|
|
37
|
-
assert.isArrayLike(shape, 'shape');
|
|
38
|
-
|
|
39
|
-
const out = new StreamGeometryBuilder();
|
|
40
|
-
|
|
41
|
-
// helper variables
|
|
42
|
-
|
|
43
|
-
const point_count = in_positions.length / 3;
|
|
44
|
-
const tubular_segments = point_count - 1;
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
const geometry_size = {
|
|
48
|
-
vertex_count: (tubular_segments + 1) * (shape_length + 1),
|
|
49
|
-
polygon_count: tubular_segments * shape_length * 2
|
|
50
|
-
};
|
|
51
|
-
|
|
52
|
-
if (!closed) {
|
|
53
|
-
append_compute_cap_geometry_size(2, geometry_size, shape_length, cap_type);
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
out.allocate(
|
|
57
|
-
geometry_size.vertex_count,
|
|
58
|
-
geometry_size.polygon_count
|
|
59
|
-
);
|
|
60
|
-
|
|
61
|
-
// create buffer data
|
|
62
|
-
|
|
63
|
-
if (!closed) {
|
|
64
|
-
// start cap
|
|
65
|
-
make_cap(
|
|
66
|
-
out, 0,
|
|
67
|
-
in_positions, in_normals, in_binormals, in_tangents,
|
|
68
|
-
shape, shape_normal, shape_length, shape_transform, 1, cap_type
|
|
69
|
-
);
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
const index_offset = out.cursor_vertices;
|
|
73
|
-
|
|
74
|
-
for (let i = 0; i < tubular_segments; i++) {
|
|
75
|
-
|
|
76
|
-
generateSegment(i);
|
|
77
|
-
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
// if the geometry is not closed, generate the last row of vertices and normals
|
|
81
|
-
// at the regular position on the given path
|
|
82
|
-
//
|
|
83
|
-
// if the geometry is closed, duplicate the first row of vertices and normals (uvs will differ)
|
|
84
|
-
|
|
85
|
-
generateSegment((closed === false) ? tubular_segments : 0);
|
|
86
|
-
|
|
87
|
-
// finally create faces
|
|
88
|
-
make_ring_faces(out, index_offset, tubular_segments, shape_length);
|
|
89
|
-
|
|
90
|
-
if (!closed) {
|
|
91
|
-
// end cap
|
|
92
|
-
make_cap(
|
|
93
|
-
out, point_count - 1,
|
|
94
|
-
in_positions, in_normals, in_binormals, in_tangents,
|
|
95
|
-
shape, shape_normal, shape_length, shape_transform, -1, cap_type
|
|
96
|
-
);
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
/**
|
|
100
|
-
*
|
|
101
|
-
* @param {number} i
|
|
102
|
-
*/
|
|
103
|
-
function generateSegment(i) {
|
|
104
|
-
|
|
105
|
-
// we use getPointAt to sample evenly distributed points from the given path
|
|
106
|
-
|
|
107
|
-
const i3 = i * 3;
|
|
108
|
-
|
|
109
|
-
const Px = in_positions[i3];
|
|
110
|
-
const Py = in_positions[i3 + 1];
|
|
111
|
-
const Pz = in_positions[i3 + 2];
|
|
112
|
-
|
|
113
|
-
// retrieve corresponding normal and binormal
|
|
114
|
-
|
|
115
|
-
const N = in_normals[i];
|
|
116
|
-
const B = in_binormals[i];
|
|
117
|
-
|
|
118
|
-
// generate normals and vertices for the current segment
|
|
119
|
-
compute_bend_normal(v4_array, i, tubular_segments, in_positions);
|
|
120
|
-
|
|
121
|
-
make_ring_vertices(
|
|
122
|
-
out,
|
|
123
|
-
Px, Py, Pz,
|
|
124
|
-
N, B, in_tangents[i],
|
|
125
|
-
i / tubular_segments, v4_array,
|
|
126
|
-
shape, shape_normal, shape_length, shape_transform
|
|
127
|
-
);
|
|
128
|
-
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
return out.build();
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
/**
|
|
137
|
-
*
|
|
138
|
-
* @param {number[]|Float32Array} out
|
|
139
|
-
* @param {number} index
|
|
140
|
-
* @param {number} index_count
|
|
141
|
-
* @param {number[]|Float32Array} positions
|
|
142
|
-
*/
|
|
143
|
-
function compute_bend_normal(
|
|
144
|
-
out,
|
|
145
|
-
index,
|
|
146
|
-
index_count,
|
|
147
|
-
positions
|
|
148
|
-
) {
|
|
149
|
-
if (index <= 0 || index >= index_count - 1) {
|
|
150
|
-
// end points, no bending
|
|
151
|
-
|
|
152
|
-
out[0] = 0;
|
|
153
|
-
out[1] = 1;
|
|
154
|
-
out[2] = 0;
|
|
155
|
-
out[3] = 0;
|
|
156
|
-
|
|
157
|
-
return;
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
const index_next = index + 1;
|
|
161
|
-
const index_prev = index - 1;
|
|
162
|
-
|
|
163
|
-
const address_current = index * 3;
|
|
164
|
-
const address_next = index_next * 3;
|
|
165
|
-
const address_prev = index_prev * 3;
|
|
166
|
-
|
|
167
|
-
const i0_x = positions[address_prev];
|
|
168
|
-
const i0_y = positions[address_prev + 1];
|
|
169
|
-
const i0_z = positions[address_prev + 2];
|
|
170
|
-
|
|
171
|
-
const i1_x = positions[address_current];
|
|
172
|
-
const i1_y = positions[address_current + 1];
|
|
173
|
-
const i1_z = positions[address_current + 2];
|
|
174
|
-
|
|
175
|
-
const i2_x = positions[address_next];
|
|
176
|
-
const i2_y = positions[address_next + 1];
|
|
177
|
-
const i2_z = positions[address_next + 2];
|
|
178
|
-
|
|
179
|
-
const d0_x = i0_x - i1_x;
|
|
180
|
-
const d0_y = i0_y - i1_y;
|
|
181
|
-
const d0_z = i0_z - i1_z;
|
|
182
|
-
|
|
183
|
-
const d1_x = i1_x - i2_x;
|
|
184
|
-
const d1_y = i1_y - i2_y;
|
|
185
|
-
const d1_z = i1_z - i2_z;
|
|
186
|
-
|
|
187
|
-
// compute rotation axis
|
|
188
|
-
const cross_x = d0_y * d1_z - d0_z * d1_y;
|
|
189
|
-
const cross_y = d0_z * d1_x - d0_x * d1_z;
|
|
190
|
-
const cross_z = d0_x * d1_y - d0_y * d1_x;
|
|
191
|
-
|
|
192
|
-
const angle = v3_angle_cos_between(d0_x, d0_y, d0_z, d1_x, d1_y, d1_z);
|
|
193
|
-
|
|
194
|
-
const
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
1
|
+
import { BufferGeometry, Vector3 } from "three";
|
|
2
|
+
import { assert } from "../../../../../../core/assert.js";
|
|
3
|
+
import { v3_angle_cos_between } from "../../../../../../core/geom/vec3/v3_angle_cos_between.js";
|
|
4
|
+
import { v3_length } from "../../../../../../core/geom/vec3/v3_length.js";
|
|
5
|
+
import { CapType } from "../CapType.js";
|
|
6
|
+
import { append_compute_cap_geometry_size, make_cap } from "./make_cap.js";
|
|
7
|
+
import { make_ring_faces } from "./make_ring_faces.js";
|
|
8
|
+
import { make_ring_vertices } from "./make_ring_vertices.js";
|
|
9
|
+
import { StreamGeometryBuilder } from "./StreamGeometryBuilder.js";
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
const v4_array = new Float32Array(4);
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* @see https://github.com/mrdoob/three.js/blob/master/src/geometries/TubeGeometry.js
|
|
16
|
+
* @see https://github.com/hofk/THREEg.js/blob/488f1128a25321a76888aa1fa19db64750318444/THREEg.js#L3483
|
|
17
|
+
* @param {Float32Array|number[]} in_positions
|
|
18
|
+
* @param {Vector3[]} in_normals
|
|
19
|
+
* @param {Vector3[]} in_binormals
|
|
20
|
+
* @param {Vector3[]} in_tangents
|
|
21
|
+
* @param {number[]} shape
|
|
22
|
+
* @param {number[]|Float32Array} shape_normal
|
|
23
|
+
* @param {number} shape_length
|
|
24
|
+
* @param {number[]|Float32Array} shape_transform
|
|
25
|
+
* @param {boolean} [closed]
|
|
26
|
+
* @param {CapType} [cap_type]
|
|
27
|
+
* @returns {BufferGeometry}
|
|
28
|
+
*/
|
|
29
|
+
export function makeTubeGeometry(
|
|
30
|
+
in_positions, in_normals, in_binormals, in_tangents,
|
|
31
|
+
shape, shape_normal, shape_length, shape_transform, closed = false, cap_type = CapType.Round
|
|
32
|
+
) {
|
|
33
|
+
assert.enum(cap_type, CapType, 'cap_type');
|
|
34
|
+
assert.isBoolean(closed, 'closed');
|
|
35
|
+
|
|
36
|
+
assert.isNumber(shape_length, 'shape_length');
|
|
37
|
+
assert.isArrayLike(shape, 'shape');
|
|
38
|
+
|
|
39
|
+
const out = new StreamGeometryBuilder();
|
|
40
|
+
|
|
41
|
+
// helper variables
|
|
42
|
+
|
|
43
|
+
const point_count = in_positions.length / 3;
|
|
44
|
+
const tubular_segments = point_count - 1;
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
const geometry_size = {
|
|
48
|
+
vertex_count: (tubular_segments + 1) * (shape_length + 1),
|
|
49
|
+
polygon_count: tubular_segments * shape_length * 2
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
if (!closed) {
|
|
53
|
+
append_compute_cap_geometry_size(2, geometry_size, shape_length, cap_type);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
out.allocate(
|
|
57
|
+
geometry_size.vertex_count,
|
|
58
|
+
geometry_size.polygon_count
|
|
59
|
+
);
|
|
60
|
+
|
|
61
|
+
// create buffer data
|
|
62
|
+
|
|
63
|
+
if (!closed) {
|
|
64
|
+
// start cap
|
|
65
|
+
make_cap(
|
|
66
|
+
out, 0,
|
|
67
|
+
in_positions, in_normals, in_binormals, in_tangents,
|
|
68
|
+
shape, shape_normal, shape_length, shape_transform, 1, cap_type
|
|
69
|
+
);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
const index_offset = out.cursor_vertices;
|
|
73
|
+
|
|
74
|
+
for (let i = 0; i < tubular_segments; i++) {
|
|
75
|
+
|
|
76
|
+
generateSegment(i);
|
|
77
|
+
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// if the geometry is not closed, generate the last row of vertices and normals
|
|
81
|
+
// at the regular position on the given path
|
|
82
|
+
//
|
|
83
|
+
// if the geometry is closed, duplicate the first row of vertices and normals (uvs will differ)
|
|
84
|
+
|
|
85
|
+
generateSegment((closed === false) ? tubular_segments : 0);
|
|
86
|
+
|
|
87
|
+
// finally create faces
|
|
88
|
+
make_ring_faces(out, index_offset, tubular_segments, shape_length);
|
|
89
|
+
|
|
90
|
+
if (!closed) {
|
|
91
|
+
// end cap
|
|
92
|
+
make_cap(
|
|
93
|
+
out, point_count - 1,
|
|
94
|
+
in_positions, in_normals, in_binormals, in_tangents,
|
|
95
|
+
shape, shape_normal, shape_length, shape_transform, -1, cap_type
|
|
96
|
+
);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
*
|
|
101
|
+
* @param {number} i
|
|
102
|
+
*/
|
|
103
|
+
function generateSegment(i) {
|
|
104
|
+
|
|
105
|
+
// we use getPointAt to sample evenly distributed points from the given path
|
|
106
|
+
|
|
107
|
+
const i3 = i * 3;
|
|
108
|
+
|
|
109
|
+
const Px = in_positions[i3];
|
|
110
|
+
const Py = in_positions[i3 + 1];
|
|
111
|
+
const Pz = in_positions[i3 + 2];
|
|
112
|
+
|
|
113
|
+
// retrieve corresponding normal and binormal
|
|
114
|
+
|
|
115
|
+
const N = in_normals[i];
|
|
116
|
+
const B = in_binormals[i];
|
|
117
|
+
|
|
118
|
+
// generate normals and vertices for the current segment
|
|
119
|
+
compute_bend_normal(v4_array, i, tubular_segments, in_positions);
|
|
120
|
+
|
|
121
|
+
make_ring_vertices(
|
|
122
|
+
out,
|
|
123
|
+
Px, Py, Pz,
|
|
124
|
+
N, B, in_tangents[i],
|
|
125
|
+
i / tubular_segments, v4_array,
|
|
126
|
+
shape, shape_normal, shape_length, shape_transform
|
|
127
|
+
);
|
|
128
|
+
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
return out.build();
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
*
|
|
138
|
+
* @param {number[]|Float32Array} out
|
|
139
|
+
* @param {number} index
|
|
140
|
+
* @param {number} index_count
|
|
141
|
+
* @param {number[]|Float32Array} positions
|
|
142
|
+
*/
|
|
143
|
+
function compute_bend_normal(
|
|
144
|
+
out,
|
|
145
|
+
index,
|
|
146
|
+
index_count,
|
|
147
|
+
positions
|
|
148
|
+
) {
|
|
149
|
+
if (index <= 0 || index >= index_count - 1) {
|
|
150
|
+
// end points, no bending
|
|
151
|
+
|
|
152
|
+
out[0] = 0;
|
|
153
|
+
out[1] = 1;
|
|
154
|
+
out[2] = 0;
|
|
155
|
+
out[3] = 0;
|
|
156
|
+
|
|
157
|
+
return;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
const index_next = index + 1;
|
|
161
|
+
const index_prev = index - 1;
|
|
162
|
+
|
|
163
|
+
const address_current = index * 3;
|
|
164
|
+
const address_next = index_next * 3;
|
|
165
|
+
const address_prev = index_prev * 3;
|
|
166
|
+
|
|
167
|
+
const i0_x = positions[address_prev];
|
|
168
|
+
const i0_y = positions[address_prev + 1];
|
|
169
|
+
const i0_z = positions[address_prev + 2];
|
|
170
|
+
|
|
171
|
+
const i1_x = positions[address_current];
|
|
172
|
+
const i1_y = positions[address_current + 1];
|
|
173
|
+
const i1_z = positions[address_current + 2];
|
|
174
|
+
|
|
175
|
+
const i2_x = positions[address_next];
|
|
176
|
+
const i2_y = positions[address_next + 1];
|
|
177
|
+
const i2_z = positions[address_next + 2];
|
|
178
|
+
|
|
179
|
+
const d0_x = i0_x - i1_x;
|
|
180
|
+
const d0_y = i0_y - i1_y;
|
|
181
|
+
const d0_z = i0_z - i1_z;
|
|
182
|
+
|
|
183
|
+
const d1_x = i1_x - i2_x;
|
|
184
|
+
const d1_y = i1_y - i2_y;
|
|
185
|
+
const d1_z = i1_z - i2_z;
|
|
186
|
+
|
|
187
|
+
// compute rotation axis
|
|
188
|
+
const cross_x = d0_y * d1_z - d0_z * d1_y;
|
|
189
|
+
const cross_y = d0_z * d1_x - d0_x * d1_z;
|
|
190
|
+
const cross_z = d0_x * d1_y - d0_y * d1_x;
|
|
191
|
+
|
|
192
|
+
const angle = v3_angle_cos_between(d0_x, d0_y, d0_z, d1_x, d1_y, d1_z);
|
|
193
|
+
|
|
194
|
+
const cross_length = v3_length(cross_x, cross_y, cross_z);
|
|
195
|
+
|
|
196
|
+
if (cross_length < 1e-10) {
|
|
197
|
+
// Collinear (or duplicate) neighbours: zero curvature, so no bend.
|
|
198
|
+
// The rotation axis is undefined here and computing it would be
|
|
199
|
+
// 0 / 0 = NaN, poisoning this ring's vertices (visible as shattered
|
|
200
|
+
// geometry on short / straight resampled segments, e.g. the animated
|
|
201
|
+
// marching dashes). Emit the same no-bend value the path ends use.
|
|
202
|
+
out[0] = 0;
|
|
203
|
+
out[1] = 1;
|
|
204
|
+
out[2] = 0;
|
|
205
|
+
out[3] = 0;
|
|
206
|
+
|
|
207
|
+
return;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
const length_inv = 1 / cross_length;
|
|
211
|
+
|
|
212
|
+
out[0] = cross_x * length_inv;
|
|
213
|
+
out[1] = cross_y * length_inv;
|
|
214
|
+
out[2] = cross_z * length_inv;
|
|
215
|
+
|
|
216
|
+
// bend amount
|
|
217
|
+
out[3] = (1 - Math.abs(angle)) * 0.5;
|
|
218
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"make_cap.d.ts","sourceRoot":"","sources":["../../../../../../../../src/engine/graphics/ecs/path/tube/build/make_cap.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"make_cap.d.ts","sourceRoot":"","sources":["../../../../../../../../src/engine/graphics/ecs/path/tube/build/make_cap.js"],"names":[],"mappings":"AAwQA;;;;;;;;;;;;;;GAcG;AACH,4DAbW,MAAM,gBACN,YAAY,GAAC,MAAM,EAAE,cACrB,OAAO,EAAE,gBACT,OAAO,EAAE,eAET,OAAO,EAAE,SACT,MAAM,EAAE,gBACR,MAAM,EAAE,GAAC,YAAY,gBACrB,MAAM,mBACN,MAAM,EAAE,GAAC,YAAY,aACrB,MAAM,QACN,OAAO,QA6BjB;AAED;;;;;;GAMG;AACH,wDALW,MAAM,OACN;IAAC,aAAa,EAAC,MAAM,CAAC;IAAC,YAAY,EAAC,MAAM,CAAA;CAAC,mBAC3C,MAAM,QACN,OAAO,QAiBjB;wBA1UuB,OAAO;wBAMP,eAAe"}
|
|
@@ -106,8 +106,17 @@ function make_cap_round(
|
|
|
106
106
|
tangent.multiplyScalar(-direction);
|
|
107
107
|
}
|
|
108
108
|
|
|
109
|
-
|
|
110
|
-
|
|
109
|
+
// Use the path frame's N/B directly for BOTH ends. The profile orientation
|
|
110
|
+
// must match the tube body it caps, otherwise the cap's cross-section is
|
|
111
|
+
// mis-aligned where it meets the body. Negating N/B for the end cap (as was
|
|
112
|
+
// done previously) point-reflects the profile in the N-B plane (a 180 degree
|
|
113
|
+
// turn about the tangent): invisible for a centrally-symmetric profile (a
|
|
114
|
+
// circle) but it twists the cap for any asymmetric one. The end cap's face
|
|
115
|
+
// winding is already corrected by the `j = cap_segment_count - i` ring-order
|
|
116
|
+
// reversal below (it advances the end-cap rings in the same direction vs `i`
|
|
117
|
+
// as the start cap), so no profile negation is needed.
|
|
118
|
+
const normal = N;
|
|
119
|
+
const binormal = B;
|
|
111
120
|
|
|
112
121
|
const angular_step_i = (Math.PI / 2) / cap_segment_count;
|
|
113
122
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"make_sky_hosek.d.ts","sourceRoot":"","sources":["../../../../../../src/engine/graphics/sh3/path_tracer/make_sky_hosek.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"make_sky_hosek.d.ts","sourceRoot":"","sources":["../../../../../../src/engine/graphics/sh3/path_tracer/make_sky_hosek.js"],"names":[],"mappings":"AASA,2LAmCC"}
|