three-player-controller 0.1.6 → 0.1.8
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 +33 -25
- package/dist/index.d.mts +2 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.js +69 -81
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +69 -81
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,49 +1,57 @@
|
|
|
1
1
|
# three-player-controller
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
A lightweight third-person / first-person player controller, ready to use out of the box, based on three.js and three-mesh-bvh. It implements capsule-based character collision, BVH collision detection, character animations, first/third-person switching, and camera obstacle avoidance. This repository contains the library source code and example demos.
|
|
4
4
|
|
|
5
|
-
#
|
|
5
|
+
# Installation
|
|
6
6
|
|
|
7
7
|
npm install three-player-controller
|
|
8
8
|
|
|
9
|
-
#
|
|
9
|
+
# Demo
|
|
10
10
|
|
|
11
11
|
[Player Controller](https://hh-hang.github.io/three-player-controller/)
|
|
12
12
|
|
|
13
|
-
###
|
|
14
|
-

|
|
13
|
+
### Controls
|
|
15
14
|
|
|
16
|
-
|
|
17
|
-

|
|
15
|
+

|
|
18
16
|
|
|
19
|
-
|
|
17
|
+
### fly
|
|
18
|
+
|
|
19
|
+

|
|
20
|
+
|
|
21
|
+
### Third-person camera obstacle avoidance
|
|
22
|
+
|
|
23
|
+

|
|
24
|
+
|
|
25
|
+
# Usage
|
|
20
26
|
|
|
21
27
|
```js
|
|
22
28
|
import * as THREE from "three";
|
|
23
29
|
import { playerController } from "three-player-controller";
|
|
24
30
|
|
|
25
|
-
|
|
31
|
+
const player = playerController();
|
|
32
|
+
|
|
33
|
+
// Initialize the player controller
|
|
26
34
|
player.init({
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
35
|
+
scene, // three.js scene
|
|
36
|
+
camera, // three.js camera
|
|
37
|
+
controls, // three.js controls
|
|
38
|
+
playerModel: {
|
|
39
|
+
url: "./glb/person.glb", // model path
|
|
40
|
+
scale: 0.001, // model scale
|
|
41
|
+
idleAnim: "Idle_2", // idle animation name
|
|
42
|
+
walkAnim: "Walking_11", // walk animation name
|
|
43
|
+
runAnim: "Running_9", // run animation name
|
|
44
|
+
jumpAnim: "Jump_3", // jump animation name
|
|
45
|
+
},
|
|
46
|
+
initPos: pos, // initial position
|
|
39
47
|
});
|
|
40
48
|
|
|
41
|
-
//
|
|
49
|
+
// Call in the render loop
|
|
42
50
|
player.update();
|
|
43
|
-
|
|
44
51
|
```
|
|
45
|
-
|
|
52
|
+
|
|
53
|
+
# Thanks
|
|
46
54
|
|
|
47
55
|
[three-mesh-bvh](https://github.com/gkjohnson/three-mesh-bvh)
|
|
48
56
|
|
|
49
|
-
[three](https://github.com/mrdoob/three.js)
|
|
57
|
+
[three](https://github.com/mrdoob/three.js)
|
package/dist/index.d.mts
CHANGED
|
@@ -15,10 +15,11 @@ declare function playerController(): {
|
|
|
15
15
|
leftWalkAnim?: string;
|
|
16
16
|
rightWalkAnim?: string;
|
|
17
17
|
backwardAnim?: string;
|
|
18
|
+
flyAnim?: string;
|
|
19
|
+
flyIdleAnim?: string;
|
|
18
20
|
scale: number;
|
|
19
21
|
gravity?: number;
|
|
20
22
|
jumpHeight?: number;
|
|
21
|
-
highJumpHeight?: number;
|
|
22
23
|
speed?: number;
|
|
23
24
|
};
|
|
24
25
|
initPos?: THREE.Vector3;
|
package/dist/index.d.ts
CHANGED
|
@@ -15,10 +15,11 @@ declare function playerController(): {
|
|
|
15
15
|
leftWalkAnim?: string;
|
|
16
16
|
rightWalkAnim?: string;
|
|
17
17
|
backwardAnim?: string;
|
|
18
|
+
flyAnim?: string;
|
|
19
|
+
flyIdleAnim?: string;
|
|
18
20
|
scale: number;
|
|
19
21
|
gravity?: number;
|
|
20
22
|
jumpHeight?: number;
|
|
21
|
-
highJumpHeight?: number;
|
|
22
23
|
speed?: number;
|
|
23
24
|
};
|
|
24
25
|
initPos?: THREE.Vector3;
|
package/dist/index.js
CHANGED
|
@@ -63,6 +63,7 @@ var PlayerController = class {
|
|
|
63
63
|
// 状态开关
|
|
64
64
|
this.playerIsOnGround = false;
|
|
65
65
|
this.isupdate = true;
|
|
66
|
+
this.isFlying = false;
|
|
66
67
|
// 输入状态
|
|
67
68
|
this.fwdPressed = false;
|
|
68
69
|
this.bkdPressed = false;
|
|
@@ -71,8 +72,6 @@ var PlayerController = class {
|
|
|
71
72
|
this.spacePressed = false;
|
|
72
73
|
this.ctPressed = false;
|
|
73
74
|
this.shiftPressed = false;
|
|
74
|
-
this.sustainSpacePressed = false;
|
|
75
|
-
this.spaceLongPressTimer = null;
|
|
76
75
|
// 第三人称
|
|
77
76
|
this._camCollisionLerp = 0.18;
|
|
78
77
|
// 平滑系数
|
|
@@ -102,6 +101,7 @@ var PlayerController = class {
|
|
|
102
101
|
this.DIR_BKD = new THREE.Vector3(0, 0, 1);
|
|
103
102
|
this.DIR_LFT = new THREE.Vector3(-1, 0, 0);
|
|
104
103
|
this.DIR_RGT = new THREE.Vector3(1, 0, 0);
|
|
104
|
+
this.DIR_Y = new THREE.Vector3(0, 1, 0);
|
|
105
105
|
this._personToCam = new THREE.Vector3();
|
|
106
106
|
this._originTmp = new THREE.Vector3();
|
|
107
107
|
this._raycaster = new THREE.Raycaster(new THREE.Vector3(), new THREE.Vector3(0, -1, 0));
|
|
@@ -133,12 +133,11 @@ var PlayerController = class {
|
|
|
133
133
|
this.setAnimationByPressed();
|
|
134
134
|
break;
|
|
135
135
|
case "Space":
|
|
136
|
-
if (!this.
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
}
|
|
136
|
+
if (!this.playerIsOnGround || this.isFlying) return;
|
|
137
|
+
this.spacePressed = true;
|
|
138
|
+
this.playPersonAnimationByName("jumping");
|
|
139
|
+
this.playerVelocity.y = this.jumpHeight;
|
|
140
|
+
this.playerIsOnGround = false;
|
|
142
141
|
break;
|
|
143
142
|
case "ControlLeft":
|
|
144
143
|
this.ctPressed = true;
|
|
@@ -146,6 +145,10 @@ var PlayerController = class {
|
|
|
146
145
|
case "KeyV":
|
|
147
146
|
this.changeView();
|
|
148
147
|
break;
|
|
148
|
+
case "KeyF":
|
|
149
|
+
this.isFlying = !this.isFlying;
|
|
150
|
+
this.setAnimationByPressed();
|
|
151
|
+
break;
|
|
149
152
|
}
|
|
150
153
|
};
|
|
151
154
|
// 键盘抬起事件
|
|
@@ -172,12 +175,6 @@ var PlayerController = class {
|
|
|
172
175
|
this.setAnimationByPressed();
|
|
173
176
|
break;
|
|
174
177
|
case "Space":
|
|
175
|
-
if (this.spaceLongPressTimer) {
|
|
176
|
-
clearTimeout(this.spaceLongPressTimer);
|
|
177
|
-
this.spaceLongPressTimer = null;
|
|
178
|
-
}
|
|
179
|
-
this.spacePressed = false;
|
|
180
|
-
this.sustainSpacePressed = false;
|
|
181
178
|
break;
|
|
182
179
|
case "ControlLeft":
|
|
183
180
|
this.ctPressed = false;
|
|
@@ -186,6 +183,16 @@ var PlayerController = class {
|
|
|
186
183
|
};
|
|
187
184
|
// 根据按键设置人物动画
|
|
188
185
|
this.setAnimationByPressed = () => {
|
|
186
|
+
this._maxCamDistance = 440 * this.playerModel.scale;
|
|
187
|
+
if (this.isFlying) {
|
|
188
|
+
if (!this.fwdPressed) {
|
|
189
|
+
this.playPersonAnimationByName("flyidle");
|
|
190
|
+
return;
|
|
191
|
+
}
|
|
192
|
+
this.playPersonAnimationByName("flying");
|
|
193
|
+
this._maxCamDistance = 700 * this.playerModel.scale;
|
|
194
|
+
return;
|
|
195
|
+
}
|
|
189
196
|
if (this.playerIsOnGround) {
|
|
190
197
|
if (!this.fwdPressed && !this.bkdPressed && !this.lftPressed && !this.rgtPressed) {
|
|
191
198
|
this.playPersonAnimationByName("idle");
|
|
@@ -219,6 +226,8 @@ var PlayerController = class {
|
|
|
219
226
|
this.playPersonAnimationByName("walking_backward");
|
|
220
227
|
return;
|
|
221
228
|
}
|
|
229
|
+
} else {
|
|
230
|
+
this.playPersonAnimationByName("jumping");
|
|
222
231
|
}
|
|
223
232
|
};
|
|
224
233
|
// 鼠标移动事件
|
|
@@ -265,8 +274,7 @@ var PlayerController = class {
|
|
|
265
274
|
const s = this.playerModel.scale;
|
|
266
275
|
this.visualizeDepth = 0 * s;
|
|
267
276
|
this.gravity = opts.playerModel.gravity ? opts.playerModel.gravity * s : -2400 * s;
|
|
268
|
-
this.jumpHeight = opts.playerModel.jumpHeight ? opts.playerModel.jumpHeight * s :
|
|
269
|
-
this.highJumpHeight = opts.playerModel.highJumpHeight ? opts.playerModel.highJumpHeight * s : 1e3 * s;
|
|
277
|
+
this.jumpHeight = opts.playerModel.jumpHeight ? opts.playerModel.jumpHeight * s : 800 * s;
|
|
270
278
|
this.playerSpeed = opts.playerModel.speed ? opts.playerModel.speed * s : 400 * s;
|
|
271
279
|
this._camCollisionLerp = 0.18;
|
|
272
280
|
this._camEpsilon = 35 * s;
|
|
@@ -318,7 +326,7 @@ var PlayerController = class {
|
|
|
318
326
|
// 设置控制器
|
|
319
327
|
setControls() {
|
|
320
328
|
this.controls.enabled = false;
|
|
321
|
-
this.controls.maxPolarAngle = Math.PI * (
|
|
329
|
+
this.controls.maxPolarAngle = Math.PI * (300 / 360);
|
|
322
330
|
}
|
|
323
331
|
// 重置控制器
|
|
324
332
|
resetControls() {
|
|
@@ -358,6 +366,7 @@ var PlayerController = class {
|
|
|
358
366
|
this.reset();
|
|
359
367
|
this.personMixer = new THREE.AnimationMixer(this.person);
|
|
360
368
|
const animations = gltf.animations ?? [];
|
|
369
|
+
console.log("animations", animations);
|
|
361
370
|
this.personActions = /* @__PURE__ */ new Map();
|
|
362
371
|
const findClip = (name) => animations.find((a) => a.name === name);
|
|
363
372
|
const regs = [
|
|
@@ -367,7 +376,9 @@ var PlayerController = class {
|
|
|
367
376
|
[this.playerModel.rightWalkAnim || this.playerModel.walkAnim, "right_walking"],
|
|
368
377
|
[this.playerModel.backwardAnim || this.playerModel.walkAnim, "walking_backward"],
|
|
369
378
|
[this.playerModel.jumpAnim, "jumping"],
|
|
370
|
-
[this.playerModel.runAnim, "running"]
|
|
379
|
+
[this.playerModel.runAnim, "running"],
|
|
380
|
+
[this.playerModel.flyIdleAnim || this.playerModel.idleAnim, "flyidle"],
|
|
381
|
+
[this.playerModel.flyAnim || this.playerModel.idleAnim, "flying"]
|
|
371
382
|
];
|
|
372
383
|
for (const [key, clipName] of regs) {
|
|
373
384
|
const clip = findClip(key);
|
|
@@ -393,6 +404,8 @@ var PlayerController = class {
|
|
|
393
404
|
this.backwardAction = this.personActions.get("walking_backward");
|
|
394
405
|
this.jumpAction = this.personActions.get("jumping");
|
|
395
406
|
this.runAction = this.personActions.get("running");
|
|
407
|
+
this.flyidleAction = this.personActions.get("flyidle");
|
|
408
|
+
this.flyAction = this.personActions.get("flying");
|
|
396
409
|
this.idleAction.setEffectiveWeight(1);
|
|
397
410
|
this.idleAction.play();
|
|
398
411
|
this.actionState = this.idleAction;
|
|
@@ -447,6 +460,7 @@ var PlayerController = class {
|
|
|
447
460
|
material.transparent = true;
|
|
448
461
|
material.opacity = this.displayPlayer ? 0.5 : 0;
|
|
449
462
|
material.wireframe = true;
|
|
463
|
+
material.depthWrite = false;
|
|
450
464
|
const r = this.playerRadius * this.playerModel.scale;
|
|
451
465
|
const h = this.playerHeight * this.playerModel.scale;
|
|
452
466
|
this.player = new THREE.Mesh(new import_RoundedBoxGeometry.RoundedBoxGeometry(r * 2, h, r * 2, 1, 75), material);
|
|
@@ -469,10 +483,10 @@ var PlayerController = class {
|
|
|
469
483
|
}
|
|
470
484
|
// 每帧更新
|
|
471
485
|
async update(delta = clock.getDelta()) {
|
|
472
|
-
if (!this.isupdate || !this.player) return;
|
|
473
|
-
delta = Math.min(delta, 1 /
|
|
486
|
+
if (!this.isupdate || !this.player || !this.collider) return;
|
|
487
|
+
delta = Math.min(delta, 1 / 60);
|
|
488
|
+
if (!this.isFlying) this.player.position.addScaledVector(this.playerVelocity, delta);
|
|
474
489
|
this.updateMixers(delta);
|
|
475
|
-
if (!this.collider) return;
|
|
476
490
|
this.camera.getWorldDirection(this.camDir);
|
|
477
491
|
let angle = Math.atan2(this.camDir.z, this.camDir.x) + Math.PI / 2;
|
|
478
492
|
angle = 2 * Math.PI - angle;
|
|
@@ -481,31 +495,16 @@ var PlayerController = class {
|
|
|
481
495
|
if (this.bkdPressed) this.moveDir.add(this.DIR_BKD);
|
|
482
496
|
if (this.lftPressed) this.moveDir.add(this.DIR_LFT);
|
|
483
497
|
if (this.rgtPressed) this.moveDir.add(this.DIR_RGT);
|
|
484
|
-
if (this.
|
|
485
|
-
this.
|
|
486
|
-
setTimeout(() => {
|
|
487
|
-
this.playerVelocity.y = this.jumpHeight;
|
|
488
|
-
this.playerIsOnGround = false;
|
|
489
|
-
this.spacePressed = false;
|
|
490
|
-
this.player.position.addScaledVector(this.playerVelocity, delta);
|
|
491
|
-
this.player.updateMatrixWorld();
|
|
492
|
-
}, 200);
|
|
493
|
-
}
|
|
494
|
-
if (this.sustainSpacePressed && this.playerIsOnGround) {
|
|
495
|
-
this.playPersonAnimationByName("jumping");
|
|
496
|
-
setTimeout(() => {
|
|
497
|
-
this.playerVelocity.y = this.highJumpHeight;
|
|
498
|
-
this.playerIsOnGround = false;
|
|
499
|
-
this.spacePressed = false;
|
|
500
|
-
this.player.position.addScaledVector(this.playerVelocity, delta);
|
|
501
|
-
this.player.updateMatrixWorld();
|
|
502
|
-
}, 200);
|
|
498
|
+
if (this.isFlying && this.fwdPressed) {
|
|
499
|
+
this.moveDir.y = this.camDir.y;
|
|
503
500
|
}
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
this.
|
|
501
|
+
if (this.isFlying && this.fwdPressed) {
|
|
502
|
+
this.playerSpeed = this.shiftPressed ? 4e3 * this.playerModel.scale : 3e3 * this.playerModel.scale;
|
|
503
|
+
} else {
|
|
504
|
+
this.playerSpeed = this.shiftPressed ? 900 * this.playerModel.scale : 400 * this.playerModel.scale;
|
|
508
505
|
}
|
|
506
|
+
this.moveDir.normalize().applyAxisAngle(this.upVector, angle);
|
|
507
|
+
this.player.position.addScaledVector(this.moveDir, this.playerSpeed * delta);
|
|
509
508
|
let playerDistanceFromGround = Infinity;
|
|
510
509
|
this._originTmp.set(this.player.position.x, this.player.position.y, this.player.position.z);
|
|
511
510
|
this._raycaster.ray.origin.copy(this._originTmp);
|
|
@@ -517,27 +516,29 @@ var PlayerController = class {
|
|
|
517
516
|
const maxH = this.playerHeight * this.playerModel.scale * 0.9;
|
|
518
517
|
const h = this.playerHeight * this.playerModel.scale * 0.75;
|
|
519
518
|
const minH = this.playerHeight * this.playerModel.scale * 0.7;
|
|
520
|
-
if (
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
this.playerIsOnGround = false;
|
|
524
|
-
} else if (playerDistanceFromGround > h && playerDistanceFromGround < maxH) {
|
|
525
|
-
if (angle2 >= 0 && angle2 < 5) {
|
|
526
|
-
console.log("\u5E73\u5730");
|
|
519
|
+
if (this.isFlying) {
|
|
520
|
+
} else {
|
|
521
|
+
if (playerDistanceFromGround > maxH) {
|
|
527
522
|
this.playerVelocity.y += delta * this.gravity;
|
|
528
523
|
this.player.position.addScaledVector(this.playerVelocity, delta);
|
|
529
524
|
this.playerIsOnGround = false;
|
|
530
|
-
} else {
|
|
525
|
+
} else if (playerDistanceFromGround > h && playerDistanceFromGround < maxH) {
|
|
526
|
+
if (angle2 >= 0 && angle2 < 5) {
|
|
527
|
+
this.playerVelocity.y += delta * this.gravity;
|
|
528
|
+
this.player.position.addScaledVector(this.playerVelocity, delta);
|
|
529
|
+
this.playerIsOnGround = true;
|
|
530
|
+
} else {
|
|
531
|
+
this.playerVelocity.set(0, 0, 0);
|
|
532
|
+
this.playerIsOnGround = true;
|
|
533
|
+
}
|
|
534
|
+
} else if (playerDistanceFromGround > minH && playerDistanceFromGround < h) {
|
|
531
535
|
this.playerVelocity.set(0, 0, 0);
|
|
532
536
|
this.playerIsOnGround = true;
|
|
537
|
+
} else if (playerDistanceFromGround < minH) {
|
|
538
|
+
this.playerVelocity.set(0, 0, 0);
|
|
539
|
+
this.player.position.set(this.player.position.x, intersects[0].point.y + h, this.player.position.z);
|
|
540
|
+
this.playerIsOnGround = true;
|
|
533
541
|
}
|
|
534
|
-
} else if (playerDistanceFromGround > minH && playerDistanceFromGround < h) {
|
|
535
|
-
this.playerVelocity.set(0, 0, 0);
|
|
536
|
-
this.playerIsOnGround = true;
|
|
537
|
-
} else if (playerDistanceFromGround < minH) {
|
|
538
|
-
this.playerVelocity.set(0, 0, 0);
|
|
539
|
-
this.player.position.set(this.player.position.x, intersects[0].point.y + h, this.player.position.z);
|
|
540
|
-
this.playerIsOnGround = true;
|
|
541
542
|
}
|
|
542
543
|
}
|
|
543
544
|
this.player.updateMatrixWorld();
|
|
@@ -569,12 +570,9 @@ var PlayerController = class {
|
|
|
569
570
|
});
|
|
570
571
|
const newPosition = this.tempVector.copy(this.tempSegment.start).applyMatrix4(this.collider.matrixWorld);
|
|
571
572
|
const deltaVector = this.tempVector2.subVectors(newPosition, this.player.position);
|
|
572
|
-
const
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
const n = deltaVector.multiplyScalar(1 / len);
|
|
576
|
-
this.player.position.addScaledVector(n, offset);
|
|
577
|
-
}
|
|
573
|
+
const offset = Math.max(0, deltaVector.length() - 1e-5);
|
|
574
|
+
deltaVector.normalize().multiplyScalar(offset);
|
|
575
|
+
this.player.position.add(deltaVector);
|
|
578
576
|
if (!this.isFirstPerson && this.moveDir.lengthSq() > 0) {
|
|
579
577
|
this.camDir.y = 0;
|
|
580
578
|
this.camDir.normalize();
|
|
@@ -607,18 +605,15 @@ var PlayerController = class {
|
|
|
607
605
|
const targetCamPos = origin.clone().add(direction.clone().multiplyScalar(safeDist));
|
|
608
606
|
this.camera.position.lerp(targetCamPos, this._camCollisionLerp);
|
|
609
607
|
} else {
|
|
610
|
-
const dis = this.player.position.distanceTo(this.camera.position);
|
|
611
608
|
this._raycasterPersonToCam.far = this._maxCamDistance;
|
|
612
609
|
const intersectsMaxDis = this._raycasterPersonToCam.intersectObject(this.collider, false);
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
safeDist = hitMax.distance - this._camEpsilon;
|
|
618
|
-
}
|
|
619
|
-
const targetCamPos = origin.clone().add(direction.clone().multiplyScalar(safeDist));
|
|
620
|
-
this.camera.position.lerp(targetCamPos, this._camCollisionLerp);
|
|
610
|
+
let safeDist = this._maxCamDistance;
|
|
611
|
+
if (intersectsMaxDis.length) {
|
|
612
|
+
const hitMax = intersectsMaxDis[0];
|
|
613
|
+
safeDist = hitMax.distance - this._camEpsilon;
|
|
621
614
|
}
|
|
615
|
+
const targetCamPos = origin.clone().add(direction.clone().multiplyScalar(safeDist));
|
|
616
|
+
this.camera.position.lerp(targetCamPos, this._camCollisionLerp);
|
|
622
617
|
}
|
|
623
618
|
}
|
|
624
619
|
if (this.player.position.y < this.boundingBoxMinY - 1) {
|
|
@@ -684,7 +679,6 @@ var PlayerController = class {
|
|
|
684
679
|
// 更新模型动画
|
|
685
680
|
updateMixers(delta) {
|
|
686
681
|
if (this.personMixer) this.personMixer.update(delta);
|
|
687
|
-
if (this.droneMixer) this.droneMixer.update(delta);
|
|
688
682
|
}
|
|
689
683
|
// BVH构建
|
|
690
684
|
async createBVH(meshUrl = "") {
|
|
@@ -779,12 +773,6 @@ var PlayerController = class {
|
|
|
779
773
|
merged.boundsTree = new import_three_mesh_bvh.MeshBVH(merged);
|
|
780
774
|
this.collider = new THREE.Mesh(
|
|
781
775
|
merged,
|
|
782
|
-
// new THREE.MeshBasicMaterial({
|
|
783
|
-
// color: "red",
|
|
784
|
-
// opacity: 0.2,
|
|
785
|
-
// transparent: true,
|
|
786
|
-
// wireframe: false,
|
|
787
|
-
// })
|
|
788
776
|
new THREE.MeshBasicMaterial({
|
|
789
777
|
opacity: 0.5,
|
|
790
778
|
transparent: true,
|