three-base 2.0.1 → 2.0.2
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/ApngTexture.d.ts +13 -0
- package/ApngTexture.js +61 -0
- package/ApngTexture.ts +91 -0
- package/ApngTextureManage.d.ts +18 -0
- package/ApngTextureManage.js +87 -0
- package/ApngTextureManage.ts +130 -0
- package/EventMesh.d.ts +18 -0
- package/EventMesh.js +59 -0
- package/EventMesh.ts +79 -0
- package/ExtrudeMesh.d.ts +111 -0
- package/ExtrudeMesh.js +363 -0
- package/ExtrudeMesh.ts +571 -0
- package/FPScontrol.d.ts +44 -0
- package/FPScontrol.js +170 -0
- package/FPScontrol.ts +209 -0
- package/InstancedGroupMesh.d.ts +10 -0
- package/InstancedGroupMesh.js +63 -0
- package/InstancedGroupMesh.ts +80 -0
- package/KeyFrameAnimation.d.ts +25 -0
- package/KeyFrameAnimation.js +78 -0
- package/KeyFrameAnimation.ts +122 -0
- package/PlaneModal1/PlaneModal1.d.ts +31 -0
- package/PlaneModal1/PlaneModal1.js +105 -0
- package/PlaneModal1/PlaneModal1.ts +151 -0
- package/PlaneModal1/index.d.ts +1 -0
- package/PlaneModal1/index.js +1 -0
- package/PlaneModal1/index.ts +1 -0
- package/PlaneModal1/planeModal.png +0 -0
- package/PlaneText.d.ts +37 -0
- package/PlaneText.js +30 -0
- package/PlaneText.ts +58 -0
- package/PlaneWithHtml.d.ts +11 -0
- package/PlaneWithHtml.js +67 -0
- package/PlaneWithHtml.ts +84 -0
- package/PointLight/PointLight.d.ts +13 -0
- package/PointLight/PointLight.js +63 -0
- package/PointLight/PointLight.ts +74 -0
- package/PointLight/index.d.ts +1 -0
- package/PointLight/index.js +1 -0
- package/PointLight/index.ts +1 -0
- package/PointLight/pointLight_map.png +0 -0
- package/Sky/Sky.d.ts +13 -0
- package/Sky/Sky.js +28 -0
- package/Sky/Sky.ts +36 -0
- package/Sky/bluesky.jpg +0 -0
- package/Sky/index.d.ts +1 -0
- package/Sky/index.js +1 -0
- package/Sky/index.ts +1 -0
- package/SpriteModal1/SpriteModal1.d.ts +30 -0
- package/SpriteModal1/SpriteModal1.js +110 -0
- package/SpriteModal1/SpriteModal1.ts +160 -0
- package/SpriteModal1/index.d.ts +1 -0
- package/SpriteModal1/index.js +1 -0
- package/SpriteModal1/index.ts +1 -0
- package/SpriteModal1/spriteModal1.png +0 -0
- package/SpriteText.d.ts +45 -0
- package/SpriteText.js +162 -0
- package/SpriteText.ts +189 -0
- package/SpriteText2.d.ts +47 -0
- package/SpriteText2.js +197 -0
- package/SpriteText2.ts +236 -0
- package/Text3D/Text3D.d.ts +20 -0
- package/Text3D/Text3D.js +62 -0
- package/Text3D/Text3D.ts +93 -0
- package/Text3D/fontController.d.ts +59 -0
- package/Text3D/fontController.js +200 -0
- package/Text3D/fontController.ts +285 -0
- package/Text3D/gentilis.json +811 -0
- package/Text3D/index.d.ts +1 -0
- package/Text3D/index.js +1 -0
- package/Text3D/index.ts +1 -0
- package/ThreeBase.d.ts +61 -0
- package/ThreeBase.js +401 -0
- package/ThreeBase.ts +482 -0
- package/ThreeMouse.d.ts +39 -0
- package/ThreeMouse.js +359 -0
- package/ThreeMouse.ts +465 -0
- package/Transition.d.ts +43 -0
- package/Transition.js +196 -0
- package/Transition.ts +268 -0
- package/index.d.ts +1 -0
- package/keyContorls.d.ts +25 -0
- package/keyContorls.js +98 -0
- package/keyContorls.ts +127 -0
- package/package.json +15 -20
- package/pass/FullScreenQuad.d.ts +7 -0
- package/pass/FullScreenQuad.js +25 -0
- package/pass/FullScreenQuad.ts +33 -0
- package/pass/stroke_pass.d.ts +2 -0
- package/pass/stroke_pass.js +190 -0
- package/pass/stroke_pass.ts +211 -0
- package/shaders.d.ts +17 -0
- package/shaders.js +245 -0
- package/shaders.ts +264 -0
- package/threeLoader.d.ts +20 -0
- package/threeLoader.js +118 -0
- package/threeLoader.ts +147 -0
- package/threeUtils.d.ts +44 -0
- package/threeUtils.js +233 -0
- package/threeUtils.ts +271 -0
- package/tsconfig.json +39 -0
package/FPScontrol.js
ADDED
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* @Author: xiaosihan
|
|
3
|
+
* @Date: 2022-05-04 23:01:36
|
|
4
|
+
* @Last Modified by: xiaosihan
|
|
5
|
+
* @Last Modified time: 2022-06-06 13:32:08
|
|
6
|
+
*/
|
|
7
|
+
import { Clock, EventDispatcher, Vector3 } from "three";
|
|
8
|
+
import { Capsule } from "three/examples/jsm/math/Capsule";
|
|
9
|
+
import { Octree } from "three/examples/jsm/math/Octree";
|
|
10
|
+
import { clamp, degToRad } from "three/src/math/MathUtils";
|
|
11
|
+
/**
|
|
12
|
+
* 第一人称控制器
|
|
13
|
+
*
|
|
14
|
+
* @export
|
|
15
|
+
* @class FPScontrol
|
|
16
|
+
* @extends {EventDispatcher}
|
|
17
|
+
*/
|
|
18
|
+
export default class FPScontrol extends EventDispatcher {
|
|
19
|
+
canvas;
|
|
20
|
+
constructor(camera, canvas) {
|
|
21
|
+
super();
|
|
22
|
+
// 相机对象
|
|
23
|
+
this.camera = camera;
|
|
24
|
+
this.camera.rotation.order = 'YXZ';
|
|
25
|
+
this.canvas = canvas;
|
|
26
|
+
this.init(canvas);
|
|
27
|
+
}
|
|
28
|
+
// 是否启用
|
|
29
|
+
enable = false;
|
|
30
|
+
GRAVITY = 30; // 重力
|
|
31
|
+
STEPS_PER_FRAME = 5; // 速度
|
|
32
|
+
camera;
|
|
33
|
+
// 世界八叉树对象
|
|
34
|
+
worldOctree = new Octree();
|
|
35
|
+
// 用户自己的碰撞体积
|
|
36
|
+
playerCollider = new Capsule(new Vector3(0, 0.35, 0), new Vector3(0, 1, 0), 0.35);
|
|
37
|
+
// 时钟对象
|
|
38
|
+
clock = new Clock();
|
|
39
|
+
playerVelocity = new Vector3();
|
|
40
|
+
playerDirection = new Vector3();
|
|
41
|
+
playerOnFloor = false;
|
|
42
|
+
mouseTime = 0;
|
|
43
|
+
isMousedown = false;
|
|
44
|
+
keyStates = {};
|
|
45
|
+
init(canvas) {
|
|
46
|
+
this.playerCollider.end.set(0, 1, 0);
|
|
47
|
+
document.addEventListener('keydown', this.keydown);
|
|
48
|
+
document.addEventListener('keyup', this.keyup);
|
|
49
|
+
canvas.addEventListener('pointerdown', this.mousedown);
|
|
50
|
+
document.addEventListener('pointerup', this.mouseup);
|
|
51
|
+
document.body.addEventListener('pointermove', this.mousemove);
|
|
52
|
+
this.enable = true;
|
|
53
|
+
}
|
|
54
|
+
keydown = (event) => {
|
|
55
|
+
this.keyStates[event.code] = true;
|
|
56
|
+
};
|
|
57
|
+
keyup = (event) => {
|
|
58
|
+
this.keyStates[event.code] = false;
|
|
59
|
+
};
|
|
60
|
+
mousedown = () => {
|
|
61
|
+
this.isMousedown = true;
|
|
62
|
+
this.mouseTime = performance.now();
|
|
63
|
+
};
|
|
64
|
+
mouseup = () => {
|
|
65
|
+
this.isMousedown = false;
|
|
66
|
+
};
|
|
67
|
+
mousemove = (event) => {
|
|
68
|
+
if (this.enable && this.isMousedown) {
|
|
69
|
+
this.camera.rotation.y -= event.movementX / 500;
|
|
70
|
+
this.camera.rotation.x -= event.movementY / 500;
|
|
71
|
+
}
|
|
72
|
+
};
|
|
73
|
+
// 设置 八叉树 节点
|
|
74
|
+
fromGraphNode(object3d) {
|
|
75
|
+
this.worldOctree.fromGraphNode(object3d);
|
|
76
|
+
}
|
|
77
|
+
// 获取前进的向量
|
|
78
|
+
getForwardVector = () => {
|
|
79
|
+
this.camera.getWorldDirection(this.playerDirection);
|
|
80
|
+
this.playerDirection.y = 0;
|
|
81
|
+
this.playerDirection.normalize();
|
|
82
|
+
return this.playerDirection;
|
|
83
|
+
};
|
|
84
|
+
// 获取 后退的向量
|
|
85
|
+
getSideVector = () => {
|
|
86
|
+
this.camera.getWorldDirection(this.playerDirection);
|
|
87
|
+
this.playerDirection.y = 0;
|
|
88
|
+
this.playerDirection.normalize();
|
|
89
|
+
this.playerDirection.cross(this.camera.up);
|
|
90
|
+
return this.playerDirection;
|
|
91
|
+
};
|
|
92
|
+
// 玩家移动控制器
|
|
93
|
+
controls = (deltaTime) => {
|
|
94
|
+
const speedDelta = deltaTime * (this.playerOnFloor ? 25 : 8);
|
|
95
|
+
if (this.keyStates['KeyW']) {
|
|
96
|
+
this.playerVelocity.add(this.getForwardVector().multiplyScalar(speedDelta));
|
|
97
|
+
}
|
|
98
|
+
if (this.keyStates['KeyS']) {
|
|
99
|
+
this.playerVelocity.add(this.getForwardVector().multiplyScalar(-speedDelta));
|
|
100
|
+
}
|
|
101
|
+
if (this.keyStates['KeyA']) {
|
|
102
|
+
this.playerVelocity.add(this.getSideVector().multiplyScalar(-speedDelta));
|
|
103
|
+
}
|
|
104
|
+
if (this.keyStates['KeyD']) {
|
|
105
|
+
this.playerVelocity.add(this.getSideVector().multiplyScalar(speedDelta));
|
|
106
|
+
}
|
|
107
|
+
if (this.playerOnFloor) {
|
|
108
|
+
if (this.keyStates['Space']) {
|
|
109
|
+
this.playerVelocity.y = 15;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
};
|
|
113
|
+
// 更新玩家的位置
|
|
114
|
+
updatePlayer = (deltaTime) => {
|
|
115
|
+
let damping = Math.exp(-4 * deltaTime) - 1;
|
|
116
|
+
if (!this.playerOnFloor) {
|
|
117
|
+
this.playerVelocity.y -= this.GRAVITY * deltaTime;
|
|
118
|
+
damping *= 0.1;
|
|
119
|
+
}
|
|
120
|
+
this.playerVelocity.addScaledVector(this.playerVelocity, damping);
|
|
121
|
+
const deltaPosition = this.playerVelocity.clone().multiplyScalar(deltaTime);
|
|
122
|
+
this.playerCollider.translate(deltaPosition);
|
|
123
|
+
this.playerCollisions();
|
|
124
|
+
this.camera.position.copy(this.playerCollider.end);
|
|
125
|
+
this.camera.position.y += 1;
|
|
126
|
+
this.camera.rotation.x = clamp(this.camera.rotation.x, degToRad(-20), degToRad(20));
|
|
127
|
+
};
|
|
128
|
+
// 玩家的碰撞检测
|
|
129
|
+
playerCollisions() {
|
|
130
|
+
const result = this.worldOctree.capsuleIntersect(this.playerCollider);
|
|
131
|
+
this.playerOnFloor = false;
|
|
132
|
+
if (result) {
|
|
133
|
+
this.playerOnFloor = result.normal.y > 0;
|
|
134
|
+
if (!this.playerOnFloor) {
|
|
135
|
+
this.playerVelocity.addScaledVector(result.normal, -result.normal.dot(this.playerVelocity));
|
|
136
|
+
}
|
|
137
|
+
this.playerCollider.translate(result.normal.multiplyScalar(result.depth));
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
// 更新控制器的位置
|
|
141
|
+
teleportPlayerIfOob = () => {
|
|
142
|
+
if (this.camera.position.y <= -10) {
|
|
143
|
+
this.playerCollider.start.set(0, 0.35, 0);
|
|
144
|
+
this.playerCollider.end.set(0, 1, 10);
|
|
145
|
+
this.playerCollider.radius = 0.35;
|
|
146
|
+
this.camera.position.copy(this.playerCollider.end);
|
|
147
|
+
// this.camera.position.set(0, 3, 0);
|
|
148
|
+
}
|
|
149
|
+
};
|
|
150
|
+
// 更新
|
|
151
|
+
update() {
|
|
152
|
+
if (this.enable) {
|
|
153
|
+
const deltaTime = Math.min(0.05, this.clock.getDelta()) / this.STEPS_PER_FRAME;
|
|
154
|
+
for (let i = 0; i < this.STEPS_PER_FRAME; i++) {
|
|
155
|
+
this.controls(deltaTime);
|
|
156
|
+
this.updatePlayer(deltaTime);
|
|
157
|
+
this.teleportPlayerIfOob();
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
// 销毁事件
|
|
162
|
+
disposer() {
|
|
163
|
+
this.enable = false;
|
|
164
|
+
document.removeEventListener('keydown', this.keydown);
|
|
165
|
+
document.removeEventListener('keyup', this.keyup);
|
|
166
|
+
this.canvas.removeEventListener('pointerdown', this.mousedown);
|
|
167
|
+
document.removeEventListener('pointerup', this.mouseup);
|
|
168
|
+
document.body.removeEventListener('pointermove', this.mousemove);
|
|
169
|
+
}
|
|
170
|
+
}
|
package/FPScontrol.ts
ADDED
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* @Author: xiaosihan
|
|
3
|
+
* @Date: 2022-05-04 23:01:36
|
|
4
|
+
* @Last Modified by: xiaosihan
|
|
5
|
+
* @Last Modified time: 2022-06-06 13:32:08
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { Camera, Clock, EventDispatcher, Object3D, Vector3 } from "three";
|
|
9
|
+
import { Capsule } from "three/examples/jsm/math/Capsule";
|
|
10
|
+
import { Octree } from "three/examples/jsm/math/Octree";
|
|
11
|
+
import { clamp, degToRad } from "three/src/math/MathUtils";
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* 第一人称控制器
|
|
16
|
+
*
|
|
17
|
+
* @export
|
|
18
|
+
* @class FPScontrol
|
|
19
|
+
* @extends {EventDispatcher}
|
|
20
|
+
*/
|
|
21
|
+
export default class FPScontrol extends EventDispatcher {
|
|
22
|
+
|
|
23
|
+
canvas!: HTMLCanvasElement
|
|
24
|
+
|
|
25
|
+
constructor(camera: Camera, canvas: HTMLCanvasElement) {
|
|
26
|
+
super();
|
|
27
|
+
|
|
28
|
+
// 相机对象
|
|
29
|
+
this.camera = camera;
|
|
30
|
+
|
|
31
|
+
this.camera.rotation.order = 'YXZ';
|
|
32
|
+
|
|
33
|
+
this.canvas = canvas;
|
|
34
|
+
|
|
35
|
+
this.init(canvas);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// 是否启用
|
|
39
|
+
enable = false;
|
|
40
|
+
|
|
41
|
+
GRAVITY = 30; // 重力
|
|
42
|
+
STEPS_PER_FRAME = 5; // 速度
|
|
43
|
+
|
|
44
|
+
camera!: Camera;
|
|
45
|
+
|
|
46
|
+
// 世界八叉树对象
|
|
47
|
+
worldOctree = new Octree();
|
|
48
|
+
|
|
49
|
+
// 用户自己的碰撞体积
|
|
50
|
+
playerCollider = new Capsule(new Vector3(0, 0.35, 0), new Vector3(0, 1, 0), 0.35);
|
|
51
|
+
|
|
52
|
+
// 时钟对象
|
|
53
|
+
clock = new Clock();
|
|
54
|
+
|
|
55
|
+
playerVelocity = new Vector3();
|
|
56
|
+
playerDirection = new Vector3();
|
|
57
|
+
|
|
58
|
+
playerOnFloor = false;
|
|
59
|
+
mouseTime = 0;
|
|
60
|
+
isMousedown = false;
|
|
61
|
+
keyStates: { [key: string]: boolean } = {};
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
init(canvas: HTMLCanvasElement) {
|
|
65
|
+
this.playerCollider.end.set(0, 1, 0);
|
|
66
|
+
document.addEventListener('keydown', this.keydown);
|
|
67
|
+
document.addEventListener('keyup', this.keyup);
|
|
68
|
+
canvas.addEventListener('pointerdown', this.mousedown);
|
|
69
|
+
document.addEventListener('pointerup', this.mouseup);
|
|
70
|
+
document.body.addEventListener('pointermove', this.mousemove);
|
|
71
|
+
this.enable = true;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
keydown = (event: KeyboardEvent) => {
|
|
76
|
+
this.keyStates[event.code] = true;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
keyup = (event: KeyboardEvent) => {
|
|
80
|
+
this.keyStates[event.code] = false;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
mousedown = () => {
|
|
84
|
+
this.isMousedown = true;
|
|
85
|
+
this.mouseTime = performance.now();
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
mouseup = () => {
|
|
89
|
+
this.isMousedown = false;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
mousemove = (event: MouseEvent) => {
|
|
93
|
+
if (this.enable && this.isMousedown) {
|
|
94
|
+
this.camera.rotation.y -= event.movementX / 500;
|
|
95
|
+
this.camera.rotation.x -= event.movementY / 500;
|
|
96
|
+
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
// 设置 八叉树 节点
|
|
101
|
+
fromGraphNode(object3d: Object3D) {
|
|
102
|
+
this.worldOctree.fromGraphNode(object3d);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
// 获取前进的向量
|
|
106
|
+
getForwardVector = () => {
|
|
107
|
+
this.camera.getWorldDirection(this.playerDirection);
|
|
108
|
+
this.playerDirection.y = 0;
|
|
109
|
+
this.playerDirection.normalize();
|
|
110
|
+
return this.playerDirection;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
// 获取 后退的向量
|
|
114
|
+
getSideVector = () => {
|
|
115
|
+
this.camera.getWorldDirection(this.playerDirection);
|
|
116
|
+
this.playerDirection.y = 0;
|
|
117
|
+
this.playerDirection.normalize();
|
|
118
|
+
this.playerDirection.cross(this.camera.up);
|
|
119
|
+
return this.playerDirection;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
// 玩家移动控制器
|
|
123
|
+
controls = (deltaTime: number) => {
|
|
124
|
+
const speedDelta = deltaTime * (this.playerOnFloor ? 25 : 8);
|
|
125
|
+
if (this.keyStates['KeyW']) {
|
|
126
|
+
this.playerVelocity.add(this.getForwardVector().multiplyScalar(speedDelta));
|
|
127
|
+
}
|
|
128
|
+
if (this.keyStates['KeyS']) {
|
|
129
|
+
this.playerVelocity.add(this.getForwardVector().multiplyScalar(-speedDelta));
|
|
130
|
+
}
|
|
131
|
+
if (this.keyStates['KeyA']) {
|
|
132
|
+
this.playerVelocity.add(this.getSideVector().multiplyScalar(-speedDelta));
|
|
133
|
+
}
|
|
134
|
+
if (this.keyStates['KeyD']) {
|
|
135
|
+
this.playerVelocity.add(this.getSideVector().multiplyScalar(speedDelta));
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
if (this.playerOnFloor) {
|
|
139
|
+
if (this.keyStates['Space']) {
|
|
140
|
+
this.playerVelocity.y = 15;
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
// 更新玩家的位置
|
|
147
|
+
updatePlayer = (deltaTime: number) => {
|
|
148
|
+
let damping = Math.exp(-4 * deltaTime) - 1;
|
|
149
|
+
if (!this.playerOnFloor) {
|
|
150
|
+
this.playerVelocity.y -= this.GRAVITY * deltaTime;
|
|
151
|
+
damping *= 0.1;
|
|
152
|
+
}
|
|
153
|
+
this.playerVelocity.addScaledVector(this.playerVelocity, damping);
|
|
154
|
+
const deltaPosition = this.playerVelocity.clone().multiplyScalar(deltaTime);
|
|
155
|
+
this.playerCollider.translate(deltaPosition);
|
|
156
|
+
this.playerCollisions();
|
|
157
|
+
this.camera.position.copy(this.playerCollider.end);
|
|
158
|
+
this.camera.position.y += 1;
|
|
159
|
+
this.camera.rotation.x = clamp(this.camera.rotation.x, degToRad(-20), degToRad(20));
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
// 玩家的碰撞检测
|
|
163
|
+
playerCollisions() {
|
|
164
|
+
const result = this.worldOctree.capsuleIntersect(this.playerCollider);
|
|
165
|
+
this.playerOnFloor = false;
|
|
166
|
+
if (result) {
|
|
167
|
+
this.playerOnFloor = result.normal.y > 0;
|
|
168
|
+
if (!this.playerOnFloor) {
|
|
169
|
+
this.playerVelocity.addScaledVector(result.normal, -result.normal.dot(this.playerVelocity));
|
|
170
|
+
|
|
171
|
+
}
|
|
172
|
+
this.playerCollider.translate(result.normal.multiplyScalar(result.depth));
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
// 更新控制器的位置
|
|
176
|
+
teleportPlayerIfOob = () => {
|
|
177
|
+
if (this.camera.position.y <= -10) {
|
|
178
|
+
this.playerCollider.start.set(0, 0.35, 0);
|
|
179
|
+
this.playerCollider.end.set(0, 1, 10);
|
|
180
|
+
this.playerCollider.radius = 0.35;
|
|
181
|
+
this.camera.position.copy(this.playerCollider.end);
|
|
182
|
+
// this.camera.position.set(0, 3, 0);
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
// 更新
|
|
187
|
+
update() {
|
|
188
|
+
if (this.enable) {
|
|
189
|
+
const deltaTime = Math.min(0.05, this.clock.getDelta()) / this.STEPS_PER_FRAME;
|
|
190
|
+
for (let i = 0; i < this.STEPS_PER_FRAME; i++) {
|
|
191
|
+
this.controls(deltaTime);
|
|
192
|
+
this.updatePlayer(deltaTime);
|
|
193
|
+
this.teleportPlayerIfOob();
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
// 销毁事件
|
|
199
|
+
disposer() {
|
|
200
|
+
this.enable = false;
|
|
201
|
+
document.removeEventListener('keydown', this.keydown);
|
|
202
|
+
document.removeEventListener('keyup', this.keyup);
|
|
203
|
+
this.canvas.removeEventListener('pointerdown', this.mousedown);
|
|
204
|
+
document.removeEventListener('pointerup', this.mouseup);
|
|
205
|
+
document.body.removeEventListener('pointermove', this.mousemove);
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
|
|
209
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import * as THREE from 'three';
|
|
2
|
+
export default class InstancedGroupMesh extends THREE.Mesh {
|
|
3
|
+
isInstancedGroupMesh: boolean;
|
|
4
|
+
count: number;
|
|
5
|
+
meshCollect: Record<string, THREE.Mesh[]>;
|
|
6
|
+
instanceCollect: Record<string, THREE.InstancedMesh>;
|
|
7
|
+
static matrix: THREE.Matrix4;
|
|
8
|
+
constructor(group: THREE.Group, count: number);
|
|
9
|
+
setMatrixAt(index: number, matrix: THREE.Matrix4): void;
|
|
10
|
+
}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* @Author: xiaosihan
|
|
3
|
+
* @Date: 2023-02-21 09:55:52
|
|
4
|
+
* @Last Modified by: xiaosihan
|
|
5
|
+
* @Last Modified time: 2023-02-26 14:42:21
|
|
6
|
+
*/
|
|
7
|
+
import * as THREE from 'three';
|
|
8
|
+
// 模型组转成 实例对象
|
|
9
|
+
export default class InstancedGroupMesh extends THREE.Mesh {
|
|
10
|
+
isInstancedGroupMesh = true;
|
|
11
|
+
count = 0;
|
|
12
|
+
meshCollect = {};
|
|
13
|
+
instanceCollect = {};
|
|
14
|
+
static matrix = new THREE.Matrix4();
|
|
15
|
+
constructor(group, count) {
|
|
16
|
+
super();
|
|
17
|
+
this.count = count;
|
|
18
|
+
const { meshCollect, instanceCollect } = this;
|
|
19
|
+
group.updateMatrixWorld(true);
|
|
20
|
+
// collect all mesh counts, in case there are more than one copy of the same mesh in this group
|
|
21
|
+
group.traverse((obj) => {
|
|
22
|
+
const mesh = obj;
|
|
23
|
+
if (mesh.isMesh) {
|
|
24
|
+
mesh.matrixWorld.decompose(mesh.position, mesh.quaternion, mesh.scale);
|
|
25
|
+
mesh.rotation.setFromQuaternion(mesh.quaternion);
|
|
26
|
+
mesh.updateMatrix();
|
|
27
|
+
// same geometry and same material consider as the same mesh
|
|
28
|
+
const uuid = mesh.geometry.uuid + '/' + mesh.material.uuid;
|
|
29
|
+
if (meshCollect[uuid]) {
|
|
30
|
+
meshCollect[uuid].push(mesh);
|
|
31
|
+
}
|
|
32
|
+
else {
|
|
33
|
+
meshCollect[uuid] = [mesh];
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
else {
|
|
37
|
+
obj.position.set(0, 0, 0);
|
|
38
|
+
obj.scale.set(1, 1, 1);
|
|
39
|
+
obj.rotation.set(0, 0, 0);
|
|
40
|
+
}
|
|
41
|
+
});
|
|
42
|
+
// create all instances
|
|
43
|
+
Object.keys(meshCollect).forEach(uuid => {
|
|
44
|
+
const meshes = meshCollect[uuid];
|
|
45
|
+
const mesh = meshes[0];
|
|
46
|
+
const instancedMesh = new THREE.InstancedMesh(mesh.geometry, mesh.material, meshes.length * count);
|
|
47
|
+
instanceCollect[uuid] = instancedMesh;
|
|
48
|
+
this.add(instancedMesh);
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
setMatrixAt(index, matrix) {
|
|
52
|
+
Object.keys(this.meshCollect).forEach(uuid => {
|
|
53
|
+
const instancedMesh = this.instanceCollect[uuid];
|
|
54
|
+
const collect = this.meshCollect[uuid];
|
|
55
|
+
collect.forEach((mesh, i) => {
|
|
56
|
+
InstancedGroupMesh.matrix.copy(mesh.matrix);
|
|
57
|
+
InstancedGroupMesh.matrix.premultiply(matrix);
|
|
58
|
+
instancedMesh.setMatrixAt(collect.length * index + i, InstancedGroupMesh.matrix);
|
|
59
|
+
instancedMesh.instanceMatrix.needsUpdate = true;
|
|
60
|
+
});
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* @Author: xiaosihan
|
|
3
|
+
* @Date: 2023-02-21 09:55:52
|
|
4
|
+
* @Last Modified by: xiaosihan
|
|
5
|
+
* @Last Modified time: 2023-02-26 14:42:21
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import * as THREE from 'three'
|
|
9
|
+
|
|
10
|
+
// 模型组转成 实例对象
|
|
11
|
+
export default class InstancedGroupMesh extends THREE.Mesh {
|
|
12
|
+
isInstancedGroupMesh = true
|
|
13
|
+
|
|
14
|
+
count: number = 0
|
|
15
|
+
|
|
16
|
+
meshCollect: Record<string, THREE.Mesh[]> = {}
|
|
17
|
+
|
|
18
|
+
instanceCollect: Record<string, THREE.InstancedMesh> = {}
|
|
19
|
+
|
|
20
|
+
static matrix = new THREE.Matrix4()
|
|
21
|
+
|
|
22
|
+
constructor(group: THREE.Group, count: number) {
|
|
23
|
+
super()
|
|
24
|
+
|
|
25
|
+
this.count = count
|
|
26
|
+
|
|
27
|
+
const { meshCollect, instanceCollect } = this
|
|
28
|
+
|
|
29
|
+
group.updateMatrixWorld(true);
|
|
30
|
+
|
|
31
|
+
// collect all mesh counts, in case there are more than one copy of the same mesh in this group
|
|
32
|
+
group.traverse((obj) => {
|
|
33
|
+
const mesh = obj as THREE.Mesh
|
|
34
|
+
if (mesh.isMesh) {
|
|
35
|
+
|
|
36
|
+
mesh.matrixWorld.decompose(mesh.position, mesh.quaternion, mesh.scale);
|
|
37
|
+
mesh.rotation.setFromQuaternion(mesh.quaternion);
|
|
38
|
+
mesh.updateMatrix();
|
|
39
|
+
|
|
40
|
+
// same geometry and same material consider as the same mesh
|
|
41
|
+
const uuid = mesh.geometry.uuid + '/' + (mesh.material as THREE.Material).uuid
|
|
42
|
+
|
|
43
|
+
if (meshCollect[uuid]) {
|
|
44
|
+
meshCollect[uuid].push(mesh)
|
|
45
|
+
} else {
|
|
46
|
+
meshCollect[uuid] = [mesh]
|
|
47
|
+
}
|
|
48
|
+
} else {
|
|
49
|
+
obj.position.set(0, 0, 0);
|
|
50
|
+
obj.scale.set(1, 1, 1);
|
|
51
|
+
obj.rotation.set(0, 0, 0);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
})
|
|
55
|
+
|
|
56
|
+
// create all instances
|
|
57
|
+
Object.keys(meshCollect).forEach(uuid => {
|
|
58
|
+
const meshes = meshCollect[uuid]
|
|
59
|
+
const mesh = meshes[0]
|
|
60
|
+
|
|
61
|
+
const instancedMesh = new THREE.InstancedMesh(mesh.geometry, mesh.material, meshes.length * count)
|
|
62
|
+
instanceCollect[uuid] = instancedMesh
|
|
63
|
+
this.add(instancedMesh)
|
|
64
|
+
})
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
setMatrixAt(index: number, matrix: THREE.Matrix4) {
|
|
68
|
+
Object.keys(this.meshCollect).forEach(uuid => {
|
|
69
|
+
const instancedMesh = this.instanceCollect[uuid]
|
|
70
|
+
const collect = this.meshCollect[uuid]
|
|
71
|
+
collect.forEach((mesh: THREE.Mesh, i: number) => {
|
|
72
|
+
InstancedGroupMesh.matrix.copy(mesh.matrix)
|
|
73
|
+
InstancedGroupMesh.matrix.premultiply(matrix)
|
|
74
|
+
|
|
75
|
+
instancedMesh.setMatrixAt(collect.length * index + i, InstancedGroupMesh.matrix);
|
|
76
|
+
instancedMesh.instanceMatrix.needsUpdate = true;
|
|
77
|
+
})
|
|
78
|
+
})
|
|
79
|
+
}
|
|
80
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { Euler, Line, LineBasicMaterial, Object3D, Vector3 } from "three";
|
|
2
|
+
export type Keyframe = {
|
|
3
|
+
position: Vector3;
|
|
4
|
+
scale: Vector3;
|
|
5
|
+
rotation: Euler;
|
|
6
|
+
timeTemp: number;
|
|
7
|
+
};
|
|
8
|
+
export type KeyframeAnimationProps = {
|
|
9
|
+
speedScale?: number;
|
|
10
|
+
object3d: Object3D;
|
|
11
|
+
keyframes: Array<Keyframe>;
|
|
12
|
+
};
|
|
13
|
+
export default class KeyframeAnimation extends Object3D {
|
|
14
|
+
constructor(props: KeyframeAnimationProps);
|
|
15
|
+
speedScale: number;
|
|
16
|
+
object3d: Object3D;
|
|
17
|
+
halperLine: Line<any, LineBasicMaterial>;
|
|
18
|
+
keyframes: Array<Keyframe>;
|
|
19
|
+
setObject3D(object3d: Object3D): void;
|
|
20
|
+
getKeyframe(i: number): Keyframe;
|
|
21
|
+
setKeyframe(i: number, keyframe: Keyframe): void;
|
|
22
|
+
setKeyframes(keyframes: Array<Keyframe>): void;
|
|
23
|
+
update(): void;
|
|
24
|
+
updateMatrix(): void;
|
|
25
|
+
}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* @Author: xiaosihan
|
|
3
|
+
* @Date: 2023-02-16 00:22:31
|
|
4
|
+
* @Last Modified by: xiaosihan
|
|
5
|
+
* @Last Modified time: 2023-02-16 19:08:55
|
|
6
|
+
*/
|
|
7
|
+
import { last } from "lodash";
|
|
8
|
+
import { BufferAttribute, Line, LineBasicMaterial, Object3D } from "three";
|
|
9
|
+
import threeUtils from "./threeUtils";
|
|
10
|
+
// 关键帧动画对象
|
|
11
|
+
export default class KeyframeAnimation extends Object3D {
|
|
12
|
+
constructor(props) {
|
|
13
|
+
super();
|
|
14
|
+
// 速度调整
|
|
15
|
+
this.speedScale = props.speedScale || 1;
|
|
16
|
+
// 设置关键帧对象数组
|
|
17
|
+
this.setKeyframes(props.keyframes);
|
|
18
|
+
// 设置对象
|
|
19
|
+
this.setObject3D(props.object3d);
|
|
20
|
+
}
|
|
21
|
+
// 速度调整
|
|
22
|
+
speedScale = 1;
|
|
23
|
+
// 需要需要移动的对象
|
|
24
|
+
object3d;
|
|
25
|
+
//路径辅助线
|
|
26
|
+
halperLine = new Line(undefined, new LineBasicMaterial({ color: "#f00" }));
|
|
27
|
+
// 关键帧数组
|
|
28
|
+
keyframes = [];
|
|
29
|
+
// 设置需要移动的对象
|
|
30
|
+
setObject3D(object3d) {
|
|
31
|
+
this.object3d = object3d;
|
|
32
|
+
if (threeUtils.isDev) {
|
|
33
|
+
this.children = [object3d, this.halperLine];
|
|
34
|
+
}
|
|
35
|
+
else {
|
|
36
|
+
this.children = [object3d];
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
// 获取单个关键帧
|
|
40
|
+
getKeyframe(i) {
|
|
41
|
+
return this.keyframes[i];
|
|
42
|
+
}
|
|
43
|
+
// 设置单个关键帧
|
|
44
|
+
setKeyframe(i, keyframe) {
|
|
45
|
+
this.keyframes[i] = keyframe;
|
|
46
|
+
this.setKeyframes(this.keyframes);
|
|
47
|
+
}
|
|
48
|
+
//设置全部关键帧
|
|
49
|
+
setKeyframes(keyframes) {
|
|
50
|
+
this.keyframes = keyframes;
|
|
51
|
+
const position = [];
|
|
52
|
+
keyframes.map(k => {
|
|
53
|
+
position.push(k.position.x);
|
|
54
|
+
position.push(k.position.y);
|
|
55
|
+
position.push(k.position.z);
|
|
56
|
+
});
|
|
57
|
+
this.halperLine.geometry.setAttribute("position", new BufferAttribute(new Float32Array(position), 3, false));
|
|
58
|
+
}
|
|
59
|
+
// 更具关键帧的信息更新 对象的位置
|
|
60
|
+
update() {
|
|
61
|
+
const { _timeTemp } = threeUtils;
|
|
62
|
+
const maxtimetemp = last(this.keyframes).timeTemp;
|
|
63
|
+
const currentTime = _timeTemp % maxtimetemp;
|
|
64
|
+
const currentKeyframeIndex = this.keyframes.findIndex(k => currentTime < k.timeTemp);
|
|
65
|
+
const startKeyframe = this.keyframes[currentKeyframeIndex - 1];
|
|
66
|
+
const endKeyframe = this.keyframes[currentKeyframeIndex];
|
|
67
|
+
const progress = (currentTime - startKeyframe.timeTemp) / (endKeyframe.timeTemp - startKeyframe.timeTemp);
|
|
68
|
+
this.object3d.position.copy(endKeyframe.position).sub(startKeyframe.position).multiplyScalar(progress).add(startKeyframe.position);
|
|
69
|
+
this.object3d.scale.copy(endKeyframe.scale).sub(startKeyframe.scale).multiplyScalar(progress).add(startKeyframe.scale);
|
|
70
|
+
this.object3d.rotation.set((endKeyframe.rotation.x - startKeyframe.rotation.x) * progress + startKeyframe.rotation.x, (endKeyframe.rotation.y - startKeyframe.rotation.y) * progress + startKeyframe.rotation.y, (endKeyframe.rotation.z - startKeyframe.rotation.z) * progress + startKeyframe.rotation.z);
|
|
71
|
+
this.dispatchEvent({ type: "update" });
|
|
72
|
+
}
|
|
73
|
+
//更新关键帧的实例矩阵
|
|
74
|
+
updateMatrix() {
|
|
75
|
+
this.update();
|
|
76
|
+
super.updateMatrix();
|
|
77
|
+
}
|
|
78
|
+
}
|