@woosh/meep-engine 2.33.1 → 2.33.5
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/core/bvh2/aabb3/AABB3.js +18 -0
- package/core/bvh2/aabb3/aabb3_intersects_frustum.js +38 -0
- package/core/collection/array/copyArray.js +2 -2
- package/core/collection/table/RowFirstTableSpec.js +8 -0
- package/core/geom/3d/aabb/aabb3_compute_projected_area.js +11 -10
- package/core/geom/3d/aabb/aabb3_estimate_projected_area2.js +59 -0
- package/core/geom/3d/aabb/aabb3_matrix4_project.js +33 -0
- package/core/geom/3d/aabb/aabb3_matrix4_project.spec.js +41 -0
- package/core/geom/3d/plane/plane3_lerp.js +2 -2
- package/core/geom/3d/topology/TopoTriangle.js +2 -2
- package/core/geom/AABB2.d.ts +2 -0
- package/core/geom/Matrix4.js +4 -4
- package/core/geom/Vector3.js +5 -5
- package/core/model/reactive/model/terminal/ReactiveReference.js +7 -1
- package/engine/asset/loaders/GLTFAssetLoader.js +3 -3
- package/engine/asset/loaders/material/TextureAttachmensByMaterialType.js +11 -1
- package/engine/asset/loaders/material/TextureAttachment.js +12 -1
- package/engine/asset/loaders/material/computeTextureEquality.js +1 -1
- package/engine/asset/loaders/material/computeTextureHash.js +16 -14
- package/engine/asset/loaders/material/traverseMaterialTextures.js +2 -2
- package/engine/ecs/animation/OneBoneSurfaceAlignmentSolver.js +2 -2
- package/engine/ecs/animation/TwoBoneInverseKinematicsSolver.js +4 -4
- package/engine/graphics/GraphicsEngine.d.ts +2 -2
- package/engine/graphics/GraphicsEngine.js +20 -62
- package/engine/graphics/filter/FlipArrayInPlace.js +25 -0
- package/engine/graphics/filter/FlipArrayViaCanvas.js +13 -0
- package/engine/graphics/filter/ImageFilter.js +20 -51
- package/engine/graphics/geometry/bvh/buffered/BVHGeometryRaycaster.js +2 -2
- package/engine/graphics/material/optimization/MaterialOptimizationContext.js +598 -0
- package/engine/graphics/micron/build/PatchRepresentation.js +4 -43
- package/engine/graphics/micron/build/buildMicronGeometryFromBufferGeometry.js +3 -70
- package/engine/graphics/micron/build/compute_buffer_geometry_byte_size.js +16 -0
- package/engine/graphics/micron/format/MicronGeometryBufferAttributeSpec.js +1 -1
- package/engine/graphics/micron/format/MicronGeometryPatch.js +9 -5
- package/engine/graphics/micron/prototypeVirtualGeometry.js +19 -12
- package/engine/graphics/micron/render/RefinementSpec.js +104 -33
- package/engine/graphics/micron/render/VirtualGeometryBuilder.js +12 -21
- package/engine/graphics/micron/render/instanced/AttributeDataTexture.js +2 -4
- package/engine/graphics/micron/render/instanced/PatchDataTextures.js +1 -0
- package/engine/graphics/micron/render/instanced/ThreeInstancedAdapter.js +1 -29
- package/engine/graphics/micron/render/refinement/ActivePatchList.js +41 -138
- package/engine/graphics/micron/render/refinement/ActivePatchRecord.js +4 -2
- package/engine/graphics/micron/render/refinement/is_patch_facing_back.js +43 -0
- package/engine/graphics/micron/render/refinement/is_patch_visible.js +37 -0
- package/engine/graphics/micron/util/unit_hemioct.spec.js +2 -2
- package/engine/graphics/render/buffer/buffers/NormalFrameBuffer.js +12 -2
- package/engine/graphics/render/buffer/buffers/prototypeNormalFrameBuffer.js +8 -10
- package/engine/graphics/render/forward_plus/LightManager.js +5 -7
- package/engine/graphics/render/forward_plus/data/NumericType.js +9 -0
- package/engine/graphics/render/forward_plus/{TextureBackedMemoryRegion.js → data/TextureBackedMemoryRegion.js} +11 -190
- package/engine/graphics/render/forward_plus/data/channelCountToThreIntegerTextureType.js +16 -0
- package/engine/graphics/render/forward_plus/data/computeDataType.js +36 -0
- package/engine/graphics/render/forward_plus/data/computeThreeTextureFormat.js +18 -0
- package/engine/graphics/render/forward_plus/data/computeThreeTextureInternalFormatFromDataType.js +63 -0
- package/engine/graphics/render/forward_plus/data/computeThreeTextureTypeFromDataType.js +41 -0
- package/engine/graphics/render/forward_plus/plugin/ptototypeFPPlugin.js +1 -1
- package/engine/graphics/render/utils/ThreeBypassRenderer.js +1 -3
- package/engine/graphics/render/visibility/VisibilityComputer.js +11 -0
- package/engine/graphics/render/visibility/hiz/buffer/HierarchicalZBuffer.js +198 -0
- package/engine/graphics/render/visibility/hiz/buffer/ReductionShader.js +51 -0
- package/engine/graphics/render/visibility/hiz/buildCanvasViewFromTexture.js +179 -0
- package/engine/graphics/render/visibility/hiz/prototypeHiZ.js +435 -0
- package/engine/graphics/render/visibility/hiz/query/BatchOcclusionQuery.js +174 -0
- package/engine/graphics/render/visibility/hiz/query/QueryShader.js +173 -0
- package/engine/graphics/texture/atlas/TextureAtlas.js +1 -1
- package/engine/graphics/texture/cubemap/buildCubeURLs.js +13 -0
- package/engine/graphics/texture/cubemap/load_environment_map.d.ts +8 -0
- package/engine/graphics/texture/cubemap/load_environment_map.js +137 -0
- package/engine/graphics/texture/sampler/convertTexture2Sampler2D.js +8 -4
- package/engine/graphics/texture/virtual/v2/ShaderUsage.js +6 -5
- package/engine/graphics/texture/virtual/v2/prototype.js +16 -6
- package/package.json +1 -1
- package/view/elements/progress/segmented/SegmentedResourceBarView.js +50 -15
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { assert } from "../../../core/assert.js";
|
|
2
|
-
import Vector3, { v3_dot,
|
|
2
|
+
import Vector3, { v3_dot, v3_length } from "../../../core/geom/Vector3.js";
|
|
3
3
|
import { clamp } from "../../../core/math/clamp.js";
|
|
4
4
|
import { inverseLerp } from "../../../core/math/inverseLerp.js";
|
|
5
5
|
import Quaternion from "../../../core/geom/Quaternion.js";
|
|
@@ -41,7 +41,7 @@ function computeInteriorAngle(a, b, c) {
|
|
|
41
41
|
const d_ab_z = a.z - b.z;
|
|
42
42
|
|
|
43
43
|
//normalize AB delta vector
|
|
44
|
-
const d_ab_length =
|
|
44
|
+
const d_ab_length = v3_length(d_ab_x, d_ab_y, d_ab_z);
|
|
45
45
|
|
|
46
46
|
const nd_ab_x = d_ab_x / d_ab_length;
|
|
47
47
|
const nd_ab_y = d_ab_y / d_ab_length;
|
|
@@ -53,7 +53,7 @@ function computeInteriorAngle(a, b, c) {
|
|
|
53
53
|
const d_cb_z = c.z - b.z;
|
|
54
54
|
|
|
55
55
|
//normalize CB delta vector
|
|
56
|
-
const d_cb_length =
|
|
56
|
+
const d_cb_length = v3_length(d_cb_x, d_cb_y, d_cb_z);
|
|
57
57
|
|
|
58
58
|
const nd_cb_x = d_cb_x / d_cb_length;
|
|
59
59
|
const nd_cb_y = d_cb_y / d_cb_length;
|
|
@@ -266,7 +266,7 @@ export class TwoBoneInverseKinematicsSolver extends IKSolver {
|
|
|
266
266
|
//check if current effector position is above the contact point
|
|
267
267
|
const dot_contact_side = v3_dot(directionX, directionY, directionZ, delta_contact_c_x, delta_contact_c_y, delta_contact_c_z);
|
|
268
268
|
|
|
269
|
-
const delta_contact_c_length =
|
|
269
|
+
const delta_contact_c_length = v3_length(delta_contact_c_x, delta_contact_c_y, delta_contact_c_z);
|
|
270
270
|
|
|
271
271
|
let influence;
|
|
272
272
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {PerspectiveCamera,
|
|
1
|
+
import {PerspectiveCamera, Scene, WebGLRenderer, WebGLRenderTarget} from "three";
|
|
2
2
|
import {RenderLayerManager} from "./render/layers/RenderLayerManager";
|
|
3
3
|
import Vector3 from "../../core/geom/Vector3";
|
|
4
4
|
import Vector2 from "../../core/geom/Vector2";
|
|
@@ -17,7 +17,7 @@ export class GraphicsEngine {
|
|
|
17
17
|
public needDraw: boolean
|
|
18
18
|
public autoDraw: boolean
|
|
19
19
|
|
|
20
|
-
render(renderTarget?:
|
|
20
|
+
render(renderTarget?: WebGLRenderTarget): void
|
|
21
21
|
|
|
22
22
|
normalizeViewportPoint(input: Vector3 | Vector2, result: Vector2 | Vector3): void
|
|
23
23
|
|
|
@@ -4,14 +4,11 @@
|
|
|
4
4
|
|
|
5
5
|
|
|
6
6
|
import {
|
|
7
|
-
CubeTextureLoader,
|
|
8
7
|
Group,
|
|
9
8
|
LinearEncoding,
|
|
10
9
|
NoToneMapping,
|
|
11
|
-
PMREMGenerator,
|
|
12
10
|
Raycaster as ThreeRaycaster,
|
|
13
11
|
Scene as ThreeScene,
|
|
14
|
-
sRGBEncoding,
|
|
15
12
|
Vector3 as ThreeVector3,
|
|
16
13
|
VSMShadowMap,
|
|
17
14
|
WebGLRenderer,
|
|
@@ -36,27 +33,13 @@ import { renderTextureToScreenQuad } from "./render/utils/renderTextureToScreenQ
|
|
|
36
33
|
import { globalMetrics } from "../metrics/GlobalMetrics.js";
|
|
37
34
|
import { MetricsCategory } from "../metrics/MetricsCategory.js";
|
|
38
35
|
import Vector1 from "../../core/geom/Vector1.js";
|
|
39
|
-
import { noop } from "../../core/function/Functions.js";
|
|
40
36
|
import { NormalFrameBuffer } from "./render/buffer/buffers/NormalFrameBuffer.js";
|
|
41
37
|
import { MaterialManager } from "./material/manager/MaterialManager.js";
|
|
42
38
|
import { CoalesceTextures } from "./material/manager/compilers/CoalesceTextures.js";
|
|
43
39
|
import { ShadowMapRenderer } from "./shadows/ShadowMapRenderer.js";
|
|
44
40
|
import { CameraViewManager } from "./render/view/CameraViewManager.js";
|
|
45
41
|
import { StandardFrameBuffers } from "./StandardFrameBuffers.js";
|
|
46
|
-
|
|
47
|
-
/**
|
|
48
|
-
*
|
|
49
|
-
* @param {String} path
|
|
50
|
-
* @param {String} format
|
|
51
|
-
* @returns {String[]}
|
|
52
|
-
*/
|
|
53
|
-
export function buildCubeURLs(path, format) {
|
|
54
|
-
return [
|
|
55
|
-
path + "posx" + format, path + "negx" + format,
|
|
56
|
-
path + "posy" + format, path + "negy" + format,
|
|
57
|
-
path + "posz" + format, path + "negz" + format
|
|
58
|
-
];
|
|
59
|
-
}
|
|
42
|
+
import { load_environment_map } from "./texture/cubemap/load_environment_map.js";
|
|
60
43
|
|
|
61
44
|
/**
|
|
62
45
|
*
|
|
@@ -259,54 +242,21 @@ GraphicsEngine.prototype.getRenderer = function () {
|
|
|
259
242
|
|
|
260
243
|
/**
|
|
261
244
|
*
|
|
262
|
-
* @param {string[]} paths
|
|
263
|
-
* @
|
|
264
|
-
*/
|
|
265
|
-
function load_cube_texture(paths) {
|
|
266
|
-
const cubeTextureLoader = new CubeTextureLoader();
|
|
267
|
-
return new Promise((resolve, reject) => {
|
|
268
|
-
|
|
269
|
-
cubeTextureLoader.load(
|
|
270
|
-
paths,
|
|
271
|
-
texture => {
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
resolve(texture);
|
|
275
|
-
},
|
|
276
|
-
noop,
|
|
277
|
-
reject
|
|
278
|
-
);
|
|
279
|
-
});
|
|
280
|
-
}
|
|
281
|
-
|
|
282
|
-
/**
|
|
283
|
-
*
|
|
284
|
-
* @param {string[]} paths URLs to faces of the cubemap
|
|
285
|
-
* @returns {Promise<void>}
|
|
245
|
+
* @param {string[]|string} paths URLs to faces of the cubemap
|
|
246
|
+
* @returns {Promise<Texture>}
|
|
286
247
|
*/
|
|
287
248
|
GraphicsEngine.prototype.loadEnvironmentMap = async function (paths) {
|
|
288
249
|
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
cube_texture.encoding = sRGBEncoding;
|
|
296
|
-
|
|
297
|
-
// generate pre-filtered cubemap
|
|
298
|
-
const pmremGenerator = new PMREMGenerator(this.renderer);
|
|
299
|
-
pmremGenerator.compileCubemapShader();
|
|
300
|
-
|
|
301
|
-
const cube_rt = pmremGenerator.fromCubemap(cube_texture);
|
|
302
|
-
|
|
303
|
-
// cleanup
|
|
304
|
-
cube_texture.dispose();
|
|
305
|
-
pmremGenerator.dispose();
|
|
250
|
+
const { filtered } = await load_environment_map({
|
|
251
|
+
path: paths,
|
|
252
|
+
renderer: this.renderer,
|
|
253
|
+
original: false,
|
|
254
|
+
filtered: true
|
|
255
|
+
});
|
|
306
256
|
|
|
307
|
-
|
|
308
|
-
this.scene.environment = cube_rt.texture;
|
|
257
|
+
this.scene.environment = filtered;
|
|
309
258
|
|
|
259
|
+
return filtered;
|
|
310
260
|
}
|
|
311
261
|
|
|
312
262
|
GraphicsEngine.prototype.updateSize = function () {
|
|
@@ -618,11 +568,19 @@ GraphicsEngine.prototype.renderOpaque = function () {
|
|
|
618
568
|
* Renders assets that (may) contain transparent fragments
|
|
619
569
|
*/
|
|
620
570
|
GraphicsEngine.prototype.renderTransparent = function () {
|
|
571
|
+
const scene = this.scene;
|
|
572
|
+
|
|
573
|
+
const _background = scene.background;
|
|
574
|
+
scene.background = null;
|
|
575
|
+
|
|
621
576
|
this.prepareRenderPass(RenderPassType.Transparent);
|
|
622
577
|
|
|
623
578
|
const renderer = this.renderer;
|
|
624
579
|
|
|
625
|
-
renderer.render(
|
|
580
|
+
renderer.render(scene, this.camera);
|
|
581
|
+
|
|
582
|
+
// restore background
|
|
583
|
+
scene.background = _background;
|
|
626
584
|
|
|
627
585
|
// TODO render transparent objects into a buffer, to be able to apply post-fx
|
|
628
586
|
};
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @param {Uint8Array} input
|
|
3
|
+
* @param {number} width
|
|
4
|
+
* @param {number} height
|
|
5
|
+
* @param {number} channel_count
|
|
6
|
+
*/
|
|
7
|
+
export function flipArrayInPlace(input, width, height, channel_count = 4) {
|
|
8
|
+
const rowLength = width * channel_count;
|
|
9
|
+
let t, x0, x1;
|
|
10
|
+
let i = 0;
|
|
11
|
+
const l = height >> 1;
|
|
12
|
+
|
|
13
|
+
for (; i < l; i++) {
|
|
14
|
+
//swap lines
|
|
15
|
+
const k = (height - i - 1) * rowLength;
|
|
16
|
+
const m = i * rowLength;
|
|
17
|
+
for (let j = 0; j < rowLength; j++) {
|
|
18
|
+
x0 = m + j;
|
|
19
|
+
x1 = k + j;
|
|
20
|
+
t = input[x0];
|
|
21
|
+
input[x0] = input[x1];
|
|
22
|
+
input[x1] = t;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
function flipArrayViaCanvas(input, width, height) {
|
|
2
|
+
const canvas = document.createElement("canvas");
|
|
3
|
+
const c = canvas.getContext('2d');
|
|
4
|
+
const imageData = c.createImageData(width, height);
|
|
5
|
+
imageData.data.set(input);
|
|
6
|
+
c.putImageData(imageData, 0, 0);
|
|
7
|
+
c.translate(0, height);
|
|
8
|
+
c.scale(1, -1);
|
|
9
|
+
c.drawImage(canvas, 0, 0);
|
|
10
|
+
const imgd = c.getImageData(0, 0, width, height);
|
|
11
|
+
|
|
12
|
+
return imgd.data;
|
|
13
|
+
}
|
|
@@ -3,59 +3,25 @@
|
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
5
|
|
|
6
|
-
import {
|
|
7
|
-
|
|
8
|
-
Mesh,
|
|
9
|
-
OrthographicCamera,
|
|
10
|
-
PlaneBufferGeometry,
|
|
11
|
-
Scene,
|
|
12
|
-
ShaderMaterial,
|
|
13
|
-
WebGLRenderTarget
|
|
14
|
-
} from 'three';
|
|
15
|
-
|
|
16
|
-
export function flipArrayInPlace(input, width, height) {
|
|
17
|
-
const rowLength = width * 4;
|
|
18
|
-
let t, x0, x1;
|
|
19
|
-
let i = 0;
|
|
20
|
-
const l = height >> 1;
|
|
21
|
-
for (; i < l; i++) {
|
|
22
|
-
//swap lines
|
|
23
|
-
const k = (height - i - 1) * rowLength;
|
|
24
|
-
const m = i * rowLength;
|
|
25
|
-
for (let j = 0; j < rowLength; j++) {
|
|
26
|
-
x0 = m + j;
|
|
27
|
-
x1 = k + j;
|
|
28
|
-
t = input[x0];
|
|
29
|
-
input[x0] = input[x1];
|
|
30
|
-
input[x1] = t;
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
function flipArrayViaCanvas(input, width, height) {
|
|
36
|
-
const canvas = document.createElement("canvas");
|
|
37
|
-
const c = canvas.getContext('2d');
|
|
38
|
-
const imageData = c.createImageData(width, height);
|
|
39
|
-
imageData.data.set(input);
|
|
40
|
-
c.putImageData(imageData, 0, 0);
|
|
41
|
-
c.translate(0, height);
|
|
42
|
-
c.scale(1, -1);
|
|
43
|
-
c.drawImage(canvas, 0, 0);
|
|
44
|
-
const imgd = c.getImageData(0, 0, width, height);
|
|
45
|
-
|
|
46
|
-
return imgd.data;
|
|
47
|
-
}
|
|
6
|
+
import { LinearFilter, Mesh, OrthographicCamera, Scene, ShaderMaterial, WebGLRenderTarget } from 'three';
|
|
7
|
+
import { FULL_SCREEN_TRIANGLE_GEOMETRY } from "../geometry/FULL_SCREEN_TRIANGLE_GEOMETRY.js";
|
|
48
8
|
|
|
49
9
|
/**
|
|
50
10
|
*
|
|
51
11
|
* @param {WebGLRenderer} renderer
|
|
52
12
|
* @param {number} width
|
|
53
13
|
* @param {number} height
|
|
54
|
-
* @param processShader
|
|
14
|
+
* @param {{vertexShader:string,fragmentShader:string, uniforms?:Object, defines?:Object}} processShader
|
|
55
15
|
* @param {Uint8Array} [destination]
|
|
56
16
|
* @return {{array: Uint8Array, renderer: WebGLRenderer}}
|
|
57
17
|
*/
|
|
58
|
-
function processTexture(
|
|
18
|
+
function processTexture(
|
|
19
|
+
renderer,
|
|
20
|
+
width,
|
|
21
|
+
height,
|
|
22
|
+
processShader,
|
|
23
|
+
destination
|
|
24
|
+
) {
|
|
59
25
|
if (destination === undefined) {
|
|
60
26
|
destination = new Uint8Array(width * height * 4);
|
|
61
27
|
}
|
|
@@ -72,9 +38,10 @@ function processTexture(renderer, width, height, processShader, destination) {
|
|
|
72
38
|
material.lights = false;
|
|
73
39
|
material.fog = false;
|
|
74
40
|
|
|
75
|
-
const quad = new Mesh(
|
|
41
|
+
const quad = new Mesh(FULL_SCREEN_TRIANGLE_GEOMETRY, material);
|
|
76
42
|
|
|
77
43
|
scene.add(quad);
|
|
44
|
+
|
|
78
45
|
//render
|
|
79
46
|
const renderTargetOptions = {
|
|
80
47
|
generateMipmaps: false,
|
|
@@ -82,28 +49,30 @@ function processTexture(renderer, width, height, processShader, destination) {
|
|
|
82
49
|
stencilBuffer: false,
|
|
83
50
|
depthBuffer: false
|
|
84
51
|
};
|
|
52
|
+
|
|
85
53
|
const renderTarget = new WebGLRenderTarget(width, height, renderTargetOptions);
|
|
86
54
|
|
|
55
|
+
const __rt = renderer.getRenderTarget(); // remember old renderer state
|
|
56
|
+
|
|
87
57
|
renderer.setRenderTarget(renderTarget);
|
|
88
58
|
|
|
89
59
|
renderer.render(scene, camera);
|
|
90
60
|
|
|
91
61
|
const gl = renderer.getContext();
|
|
62
|
+
|
|
92
63
|
//void readPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, ArrayBufferView? pixels)
|
|
93
64
|
gl.readPixels(0, 0, width, height, gl.RGBA, gl.UNSIGNED_BYTE, destination);
|
|
94
65
|
|
|
95
|
-
renderer
|
|
66
|
+
// restore renderer state
|
|
67
|
+
renderer.setRenderTarget(__rt);
|
|
96
68
|
|
|
97
|
-
//
|
|
98
|
-
|
|
99
|
-
//uint8Array = flipArrayViaCanvas(uint8Array, width, height);
|
|
100
|
-
//
|
|
69
|
+
// cleanup resources
|
|
101
70
|
renderTarget.dispose();
|
|
102
71
|
material.dispose();
|
|
72
|
+
|
|
103
73
|
return {
|
|
104
74
|
array: destination,
|
|
105
75
|
graphics: renderer
|
|
106
|
-
//renderTarget: renderTarget
|
|
107
76
|
};
|
|
108
77
|
}
|
|
109
78
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import Vector3, {
|
|
1
|
+
import Vector3, { v3_length } from "../../../../../core/geom/Vector3.js";
|
|
2
2
|
|
|
3
3
|
import { Vector3 as ThreeVector3 } from 'three';
|
|
4
4
|
import { rayTriangleIntersection } from "../../../../../core/geom/GeometryMath.js";
|
|
@@ -60,7 +60,7 @@ function bindGeometryFaceNormal(indices, normals, index) {
|
|
|
60
60
|
const nsZ = (naZ + nbZ + ncZ);
|
|
61
61
|
|
|
62
62
|
//normalize
|
|
63
|
-
const l =
|
|
63
|
+
const l = v3_length(nsX, nsY, nsZ);
|
|
64
64
|
const m = 1 / l;
|
|
65
65
|
|
|
66
66
|
const nx = nsX * m;
|