three-base 2.0.26 → 2.0.29
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/MeshBase.d.ts +26 -2
- package/MeshBase.js +170 -9
- package/MeshBase.ts +205 -10
- package/PlaneText.d.ts +3 -3
- package/ThreeBase.js +7 -4
- package/ThreeBase.ts +8 -5
- package/ThreeMouse.js +1 -1
- package/ThreeMouse.ts +1 -1
- package/package.json +1 -1
- package/threeLoader.js +7 -2
- package/threeLoader.ts +6 -2
- package/threeUtils.d.ts +1 -0
- package/threeUtils.js +13 -0
- package/threeUtils.ts +15 -1
package/MeshBase.d.ts
CHANGED
|
@@ -1,4 +1,28 @@
|
|
|
1
|
-
import { Group } from "three";
|
|
1
|
+
import { AnimationAction, AnimationMixer, Clock, Group, Mesh, Object3D, Vector3 } from "three";
|
|
2
2
|
export default class MeshBase extends Group {
|
|
3
|
-
constructor();
|
|
3
|
+
constructor(url?: string);
|
|
4
|
+
static models: Map<string, Object3D>;
|
|
5
|
+
static loadModeling: Map<string, boolean>;
|
|
6
|
+
loaded: boolean;
|
|
7
|
+
hasAnimation: boolean;
|
|
8
|
+
mixer?: AnimationMixer;
|
|
9
|
+
animationActions: {
|
|
10
|
+
[key: string]: AnimationAction;
|
|
11
|
+
};
|
|
12
|
+
loadModel(url: string): Promise<void>;
|
|
13
|
+
frustumCulled: boolean;
|
|
14
|
+
castShadow: boolean;
|
|
15
|
+
receiveShadow: boolean;
|
|
16
|
+
awaitLoaded(callback?: Function): Promise<void>;
|
|
17
|
+
traverseMesh(callback: (mesh: Mesh) => void): Promise<void>;
|
|
18
|
+
clock: Clock;
|
|
19
|
+
setClipActionWeight(weights?: {
|
|
20
|
+
[key: string]: number;
|
|
21
|
+
}): Promise<void>;
|
|
22
|
+
updateMatrix(): void;
|
|
23
|
+
getSize(): Promise<Vector3>;
|
|
24
|
+
center(): Promise<void>;
|
|
25
|
+
alignBottom(y?: number): Promise<void>;
|
|
26
|
+
scaleTo(size?: number, key?: Array<"x" | "y" | "z">): Promise<void>;
|
|
27
|
+
expandBynormal(length: number): void;
|
|
4
28
|
}
|
package/MeshBase.js
CHANGED
|
@@ -1,13 +1,174 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
*
|
|
5
|
-
|
|
6
|
-
*/
|
|
7
|
-
import { Group } from "three";
|
|
8
|
-
// 基础模型加载对象
|
|
1
|
+
import { AnimationMixer, Clock, Group, Object3D, Vector3 } from "three";
|
|
2
|
+
import threeUtils from "./threeUtils";
|
|
3
|
+
import threeLoader from "./threeLoader";
|
|
4
|
+
import * as SkeletonUtils from 'three/examples/jsm/utils/SkeletonUtils';
|
|
5
|
+
// 模型基类
|
|
9
6
|
export default class MeshBase extends Group {
|
|
10
|
-
constructor() {
|
|
7
|
+
constructor(url) {
|
|
11
8
|
super();
|
|
9
|
+
url && this.loadModel(url);
|
|
10
|
+
}
|
|
11
|
+
// 模型对象
|
|
12
|
+
static models = new Map();
|
|
13
|
+
// 模型是否在加载中
|
|
14
|
+
static loadModeling = new Map();
|
|
15
|
+
// 加载完成
|
|
16
|
+
loaded = false;
|
|
17
|
+
// 是否有动画
|
|
18
|
+
hasAnimation = false;
|
|
19
|
+
//动画混合器
|
|
20
|
+
mixer;
|
|
21
|
+
//动画剪辑对象数组
|
|
22
|
+
animationActions = {};
|
|
23
|
+
async loadModel(url) {
|
|
24
|
+
if (!url) {
|
|
25
|
+
this.clear();
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
this.loaded = false;
|
|
29
|
+
// 没有模型并且没有加载任务时就去加载模型
|
|
30
|
+
if (!MeshBase.models.get(url) && !MeshBase.loadModeling.get(url)) {
|
|
31
|
+
MeshBase.loadModeling.set(url, true);
|
|
32
|
+
let modal = new Object3D();
|
|
33
|
+
if (/\.fbx$/i.test(url)) {
|
|
34
|
+
await threeLoader.fbxLoader.loadAsync(url).then(res => {
|
|
35
|
+
modal = res;
|
|
36
|
+
}).catch(() => {
|
|
37
|
+
console.error(`${url},加载失败`);
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
else if (/\.(gltf|glb)$/i.test(url)) {
|
|
41
|
+
await threeLoader.gltfLoader.loadAsync(url).then(res => {
|
|
42
|
+
modal = res.scene;
|
|
43
|
+
modal.animations = res.animations;
|
|
44
|
+
}).catch(() => {
|
|
45
|
+
console.error(`${url},加载失败`);
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
else {
|
|
49
|
+
console.error(`${url},不支持的格式`);
|
|
50
|
+
}
|
|
51
|
+
threeUtils.center(modal);
|
|
52
|
+
threeUtils.alignBottom(modal);
|
|
53
|
+
modal.updateMatrixWorld(true);
|
|
54
|
+
MeshBase.models.set(url, modal);
|
|
55
|
+
MeshBase.loadModeling.set(url, false);
|
|
56
|
+
}
|
|
57
|
+
// 如果模型还在加载中, 就等待模型加载完成
|
|
58
|
+
do {
|
|
59
|
+
await new Promise(resolve => setTimeout(resolve, 50));
|
|
60
|
+
} while (MeshBase.loadModeling.get(url));
|
|
61
|
+
if (MeshBase.models.get(url)) {
|
|
62
|
+
this.clear();
|
|
63
|
+
const mesh = MeshBase.models.get(url);
|
|
64
|
+
// 判断是否有动画
|
|
65
|
+
this.hasAnimation = mesh.animations.length > 0;
|
|
66
|
+
if (this.hasAnimation) {
|
|
67
|
+
const model = SkeletonUtils.clone(mesh);
|
|
68
|
+
this.mixer = new AnimationMixer(model);
|
|
69
|
+
this.animationActions = {};
|
|
70
|
+
mesh.animations.map(animation => {
|
|
71
|
+
const animationAction = this.mixer.clipAction(animation).play();
|
|
72
|
+
animationAction.weight = 0;
|
|
73
|
+
this.animationActions[animation.name] = animationAction;
|
|
74
|
+
});
|
|
75
|
+
this.add(model);
|
|
76
|
+
}
|
|
77
|
+
else {
|
|
78
|
+
this.add(mesh);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
await new Promise(resolve => requestAnimationFrame(resolve));
|
|
82
|
+
// 加载完成事件
|
|
83
|
+
this.dispatchEvent({ type: "loaded" });
|
|
84
|
+
this.loaded = true;
|
|
85
|
+
}
|
|
86
|
+
// 超出绘制区域时不绘制
|
|
87
|
+
frustumCulled = false;
|
|
88
|
+
// 创建阴影
|
|
89
|
+
castShadow = false;
|
|
90
|
+
// 接受阴影
|
|
91
|
+
receiveShadow = false;
|
|
92
|
+
// 等待加载加载完成
|
|
93
|
+
async awaitLoaded(callback) {
|
|
94
|
+
while (!this.loaded) {
|
|
95
|
+
await new Promise(resolve => setTimeout(resolve, 50));
|
|
96
|
+
}
|
|
97
|
+
callback && callback();
|
|
98
|
+
}
|
|
99
|
+
//遍历模型
|
|
100
|
+
async traverseMesh(callback) {
|
|
101
|
+
// 等待加载完成
|
|
102
|
+
await this.awaitLoaded();
|
|
103
|
+
this.traverse(obj => {
|
|
104
|
+
const mesh = obj;
|
|
105
|
+
if (mesh.isMesh) {
|
|
106
|
+
callback(mesh);
|
|
107
|
+
}
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
clock = new Clock();
|
|
111
|
+
//设置动画的权重
|
|
112
|
+
async setClipActionWeight(weights = {}) {
|
|
113
|
+
// 等待加载完成
|
|
114
|
+
await this.awaitLoaded();
|
|
115
|
+
for (let key in this.animationActions) {
|
|
116
|
+
this.animationActions[key].weight = weights[key] || 0;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
updateMatrix() {
|
|
120
|
+
//播放动画
|
|
121
|
+
if (this.mixer) {
|
|
122
|
+
this.mixer.update(this.clock.getDelta());
|
|
123
|
+
}
|
|
124
|
+
// 深度应用属性
|
|
125
|
+
this.traverse(obj => {
|
|
126
|
+
const mesh = obj;
|
|
127
|
+
if (mesh.isMesh) {
|
|
128
|
+
mesh.frustumCulled = this.frustumCulled;
|
|
129
|
+
mesh.castShadow = this.castShadow;
|
|
130
|
+
mesh.receiveShadow = this.receiveShadow;
|
|
131
|
+
}
|
|
132
|
+
});
|
|
133
|
+
super.updateMatrix();
|
|
134
|
+
}
|
|
135
|
+
// 获取模型的尺寸
|
|
136
|
+
async getSize() {
|
|
137
|
+
await this.awaitLoaded();
|
|
138
|
+
return threeUtils.getSize(this);
|
|
139
|
+
}
|
|
140
|
+
// 居中
|
|
141
|
+
async center() {
|
|
142
|
+
await this.awaitLoaded();
|
|
143
|
+
threeUtils.center(this);
|
|
144
|
+
}
|
|
145
|
+
//底对齐
|
|
146
|
+
async alignBottom(y = 0) {
|
|
147
|
+
await this.awaitLoaded();
|
|
148
|
+
threeUtils.alignBottom(this, y);
|
|
149
|
+
}
|
|
150
|
+
// 放大到指定尺寸
|
|
151
|
+
async scaleTo(size = 1, key = ["x", "y", "z"]) {
|
|
152
|
+
await this.awaitLoaded();
|
|
153
|
+
threeUtils.scaleTo(this, size, key);
|
|
154
|
+
}
|
|
155
|
+
//按照法线拓展
|
|
156
|
+
expandBynormal(length) {
|
|
157
|
+
this.traverseMesh(mesh => {
|
|
158
|
+
// 没有法线就计算法线
|
|
159
|
+
mesh.geometry = mesh.geometry.clone();
|
|
160
|
+
if (!mesh.geometry.getAttribute("normal")) {
|
|
161
|
+
mesh.geometry.computeVertexNormals();
|
|
162
|
+
}
|
|
163
|
+
const normal = mesh.geometry.getAttribute("normal");
|
|
164
|
+
const position = mesh.geometry.getAttribute("position");
|
|
165
|
+
const v3 = new Vector3(0, 0, 0);
|
|
166
|
+
for (let i = 0; i < position.count; i++) {
|
|
167
|
+
v3.set(normal.getX(i), normal.getY(i), normal.getZ(i));
|
|
168
|
+
v3.setLength(length);
|
|
169
|
+
position.setXYZ(i, position.getX(i) + v3.x, position.getY(i) + v3.y, position.getZ(i) + v3.z);
|
|
170
|
+
}
|
|
171
|
+
position.needsUpdate = true;
|
|
172
|
+
});
|
|
12
173
|
}
|
|
13
174
|
}
|
package/MeshBase.ts
CHANGED
|
@@ -1,19 +1,214 @@
|
|
|
1
|
-
/*
|
|
2
|
-
* @Author: xiaosihan
|
|
3
|
-
* @Date: 2024-01-29 10:08:40
|
|
4
|
-
* @Last Modified by: xiaosihan
|
|
5
|
-
* @Last Modified time: 2024-02-05 09:40:17
|
|
6
|
-
*/
|
|
7
1
|
|
|
8
|
-
import { Group } from "three";
|
|
2
|
+
import { AnimationAction, AnimationMixer, Clock, DoubleSide, Group, Mesh, MeshStandardMaterial, Object3D, Vector3 } from "three";
|
|
3
|
+
import threeUtils from "./threeUtils";
|
|
4
|
+
import threeLoader from "./threeLoader";
|
|
5
|
+
import * as SkeletonUtils from 'three/examples/jsm/utils/SkeletonUtils';
|
|
9
6
|
|
|
10
|
-
//
|
|
7
|
+
// 模型基类
|
|
11
8
|
export default class MeshBase extends Group {
|
|
12
|
-
|
|
13
|
-
constructor() {
|
|
9
|
+
constructor(url?: string) {
|
|
14
10
|
super();
|
|
11
|
+
url && this.loadModel(url);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
// 模型对象
|
|
15
|
+
static models: Map<string, Object3D> = new Map();
|
|
16
|
+
|
|
17
|
+
// 模型是否在加载中
|
|
18
|
+
static loadModeling: Map<string, boolean> = new Map();
|
|
19
|
+
|
|
20
|
+
// 加载完成
|
|
21
|
+
loaded = false;
|
|
22
|
+
|
|
23
|
+
// 是否有动画
|
|
24
|
+
hasAnimation = false;
|
|
25
|
+
|
|
26
|
+
//动画混合器
|
|
27
|
+
mixer?: AnimationMixer;
|
|
28
|
+
|
|
29
|
+
//动画剪辑对象数组
|
|
30
|
+
animationActions: { [key: string]: AnimationAction } = {};
|
|
31
|
+
|
|
32
|
+
async loadModel(url: string) {
|
|
33
|
+
if (!url) {
|
|
34
|
+
this.clear();
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
this.loaded = false;
|
|
39
|
+
|
|
40
|
+
// 没有模型并且没有加载任务时就去加载模型
|
|
41
|
+
if (!MeshBase.models.get(url) && !MeshBase.loadModeling.get(url)) {
|
|
42
|
+
MeshBase.loadModeling.set(url, true);
|
|
43
|
+
|
|
44
|
+
let modal = new Object3D();
|
|
45
|
+
|
|
46
|
+
if (/\.fbx$/i.test(url)) {
|
|
47
|
+
await threeLoader.fbxLoader.loadAsync(url).then(res => {
|
|
48
|
+
modal = res;
|
|
49
|
+
}).catch(() => {
|
|
50
|
+
console.error(`${url},加载失败`);
|
|
51
|
+
})
|
|
52
|
+
} else if (/\.(gltf|glb)$/i.test(url)) {
|
|
53
|
+
await threeLoader.gltfLoader.loadAsync(url).then(res => {
|
|
54
|
+
modal = res.scene;
|
|
55
|
+
modal.animations = res.animations;
|
|
56
|
+
}).catch(() => {
|
|
57
|
+
console.error(`${url},加载失败`);
|
|
58
|
+
})
|
|
59
|
+
} else {
|
|
60
|
+
console.error(`${url},不支持的格式`);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
threeUtils.center(modal);
|
|
64
|
+
threeUtils.alignBottom(modal);
|
|
65
|
+
modal.updateMatrixWorld(true);
|
|
66
|
+
|
|
67
|
+
MeshBase.models.set(url, modal);
|
|
68
|
+
MeshBase.loadModeling.set(url, false);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// 如果模型还在加载中, 就等待模型加载完成
|
|
72
|
+
do {
|
|
73
|
+
await new Promise(resolve => setTimeout(resolve, 50));
|
|
74
|
+
} while (MeshBase.loadModeling.get(url));
|
|
75
|
+
|
|
76
|
+
if (MeshBase.models.get(url)) {
|
|
77
|
+
|
|
78
|
+
this.clear();
|
|
79
|
+
const mesh = MeshBase.models.get(url);
|
|
80
|
+
// 判断是否有动画
|
|
81
|
+
this.hasAnimation = mesh.animations.length > 0;
|
|
82
|
+
|
|
83
|
+
if (this.hasAnimation) {
|
|
84
|
+
const model = SkeletonUtils.clone(mesh);
|
|
85
|
+
this.mixer = new AnimationMixer(model);
|
|
86
|
+
|
|
87
|
+
this.animationActions = {};
|
|
88
|
+
mesh.animations.map(animation => {
|
|
89
|
+
const animationAction = this.mixer.clipAction(animation).play();
|
|
90
|
+
animationAction.weight = 0;
|
|
91
|
+
this.animationActions[animation.name] = animationAction;
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
this.add(model);
|
|
95
|
+
} else {
|
|
96
|
+
this.add(mesh);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
await new Promise(resolve => requestAnimationFrame(resolve));
|
|
102
|
+
|
|
103
|
+
// 加载完成事件
|
|
104
|
+
this.dispatchEvent({ type: "loaded" } as never);
|
|
105
|
+
|
|
106
|
+
this.loaded = true;
|
|
15
107
|
}
|
|
16
108
|
|
|
109
|
+
// 超出绘制区域时不绘制
|
|
110
|
+
frustumCulled = false;
|
|
17
111
|
|
|
112
|
+
// 创建阴影
|
|
113
|
+
castShadow: boolean = false;
|
|
114
|
+
|
|
115
|
+
// 接受阴影
|
|
116
|
+
receiveShadow: boolean = false;
|
|
117
|
+
|
|
118
|
+
// 等待加载加载完成
|
|
119
|
+
async awaitLoaded(callback?: Function) {
|
|
120
|
+
while (!this.loaded) {
|
|
121
|
+
await new Promise(resolve => setTimeout(resolve, 50));
|
|
122
|
+
}
|
|
123
|
+
callback && callback();
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
//遍历模型
|
|
127
|
+
async traverseMesh(callback: (mesh: Mesh) => void) {
|
|
128
|
+
// 等待加载完成
|
|
129
|
+
await this.awaitLoaded();
|
|
130
|
+
|
|
131
|
+
this.traverse(obj => {
|
|
132
|
+
const mesh = obj as Mesh;
|
|
133
|
+
if (mesh.isMesh) {
|
|
134
|
+
callback(mesh);
|
|
135
|
+
}
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
clock = new Clock();
|
|
140
|
+
|
|
141
|
+
//设置动画的权重
|
|
142
|
+
async setClipActionWeight(weights: { [key: string]: number } = {}) {
|
|
143
|
+
// 等待加载完成
|
|
144
|
+
await this.awaitLoaded();
|
|
145
|
+
for (let key in this.animationActions) {
|
|
146
|
+
this.animationActions[key].weight = weights[key] || 0;
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
updateMatrix(): void {
|
|
151
|
+
//播放动画
|
|
152
|
+
if (this.mixer) {
|
|
153
|
+
this.mixer.update(this.clock.getDelta());
|
|
154
|
+
}
|
|
155
|
+
// 深度应用属性
|
|
156
|
+
this.traverse(obj => {
|
|
157
|
+
const mesh = obj as Mesh;
|
|
158
|
+
if (mesh.isMesh) {
|
|
159
|
+
mesh.frustumCulled = this.frustumCulled;
|
|
160
|
+
mesh.castShadow = this.castShadow;
|
|
161
|
+
mesh.receiveShadow = this.receiveShadow;
|
|
162
|
+
}
|
|
163
|
+
});
|
|
164
|
+
|
|
165
|
+
super.updateMatrix();
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
// 获取模型的尺寸
|
|
169
|
+
async getSize() {
|
|
170
|
+
await this.awaitLoaded();
|
|
171
|
+
return threeUtils.getSize(this);
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
// 居中
|
|
175
|
+
async center() {
|
|
176
|
+
await this.awaitLoaded();
|
|
177
|
+
threeUtils.center(this);
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
//底对齐
|
|
181
|
+
async alignBottom(y: number = 0) {
|
|
182
|
+
await this.awaitLoaded();
|
|
183
|
+
threeUtils.alignBottom(this, y);
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
// 放大到指定尺寸
|
|
187
|
+
async scaleTo(size: number = 1, key: Array<"x" | "y" | "z"> = ["x", "y", "z"]) {
|
|
188
|
+
await this.awaitLoaded();
|
|
189
|
+
threeUtils.scaleTo(this, size, key);
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
//按照法线拓展
|
|
193
|
+
expandBynormal(length: number) {
|
|
194
|
+
this.traverseMesh(mesh => {
|
|
195
|
+
// 没有法线就计算法线
|
|
196
|
+
mesh.geometry = mesh.geometry.clone();
|
|
197
|
+
if (!mesh.geometry.getAttribute("normal")) {
|
|
198
|
+
mesh.geometry.computeVertexNormals();
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
const normal = mesh.geometry.getAttribute("normal");
|
|
202
|
+
const position = mesh.geometry.getAttribute("position");
|
|
203
|
+
const v3 = new Vector3(0, 0, 0);
|
|
204
|
+
for (let i = 0; i < position.count; i++) {
|
|
205
|
+
v3.set(normal.getX(i), normal.getY(i), normal.getZ(i));
|
|
206
|
+
v3.setLength(length);
|
|
207
|
+
position.setXYZ(i, position.getX(i) + v3.x, position.getY(i) + v3.y, position.getZ(i) + v3.z);
|
|
208
|
+
}
|
|
209
|
+
position.needsUpdate = true;
|
|
210
|
+
|
|
211
|
+
})
|
|
212
|
+
}
|
|
18
213
|
|
|
19
214
|
}
|
package/PlaneText.d.ts
CHANGED
|
@@ -22,15 +22,15 @@ export default class PlaneText extends Mesh {
|
|
|
22
22
|
spriteText: SpriteText;
|
|
23
23
|
material: MeshBasicMaterial;
|
|
24
24
|
set(parame: Props): void;
|
|
25
|
-
get(prop: keyof SpriteText): string | number | boolean | Vector3 | import("three").Object3D<import("three").Object3DEventMap> | import("three").BufferGeometry<import("three").NormalBufferAttributes> | ((force?: boolean) => void) | import("three").Object3D<import("three").Object3DEventMap>
|
|
25
|
+
get(prop: keyof SpriteText): string | number | boolean | Vector3 | import("three").Object3D<import("three").Object3DEventMap> | import("three").BufferGeometry<import("three").NormalBufferAttributes> | ((force?: boolean) => void) | ((callback: (object: import("three").Object3D<import("three").Object3DEventMap>) => any) => void) | import("three").Object3D<import("three").Object3DEventMap>[] | import("three").Euler | import("three").Material | import("three").Quaternion | import("three").Matrix4 | import("three").Matrix3 | import("three").Layers | import("three").AnimationClip[] | Record<string, any> | ((renderer: import("three").WebGLRenderer, scene: import("three").Scene, shadowCamera: import("three").Camera, geometry: import("three").BufferGeometry<import("three").NormalBufferAttributes>, depthMaterial: import("three").Material, group: import("three").Group<import("three").Object3DEventMap>) => void) | ((renderer: import("three").WebGLRenderer, scene: import("three").Scene, shadowCamera: import("three").Camera, geometry: import("three").BufferGeometry<import("three").NormalBufferAttributes>, depthMaterial: import("three").Material, group: import("three").Group<import("three").Object3DEventMap>) => void) | ((renderer: import("three").WebGLRenderer, scene: import("three").Scene, camera: import("three").Camera, geometry: import("three").BufferGeometry<import("three").NormalBufferAttributes>, material: import("three").Material, group: import("three").Group<import("three").Object3DEventMap>) => void) | ((renderer: import("three").WebGLRenderer, scene: import("three").Scene, camera: import("three").Camera, geometry: import("three").BufferGeometry<import("three").NormalBufferAttributes>, material: import("three").Material, group: import("three").Group<import("three").Object3DEventMap>) => void) | ((matrix: import("three").Matrix4) => void) | ((axis: Vector3, angle: number) => void) | ((euler: import("three").Euler) => void) | ((m: import("three").Matrix4) => void) | ((q: import("three").Quaternion) => void) | ((vector: Vector3) => Vector3) | ((vector: Vector3) => Vector3) | {
|
|
26
26
|
(vector: Vector3): void;
|
|
27
27
|
(x: number, y: number, z: number): void;
|
|
28
|
-
} | ((id: number) => import("three").Object3D<import("three").Object3DEventMap>) | ((name: string) => import("three").Object3D<import("three").Object3DEventMap>) | ((name: string, value: any) => import("three").Object3D<import("three").Object3DEventMap>) | ((name: string, value: any, optionalTarget?: import("three").Object3D<import("three").Object3DEventMap>[]) => import("three").Object3D<import("three").Object3DEventMap>[]) | ((target: Vector3) => Vector3) | ((target: import("three").Quaternion) => import("three").Quaternion) | ((target: Vector3) => Vector3) | ((target: Vector3) => Vector3) | ((raycaster: import("three").Raycaster, intersects: import("three").Intersection<import("three").Object3D<import("three").Object3DEventMap>>[]) => void) | ((callback: (object: import("three").Object3D<import("three").Object3DEventMap>) => any) => void) | ((callback: (object: import("three").Object3D<import("three").Object3DEventMap>) => any) => void) | ((
|
|
28
|
+
} | ((id: number) => import("three").Object3D<import("three").Object3DEventMap>) | ((name: string) => import("three").Object3D<import("three").Object3DEventMap>) | ((name: string, value: any) => import("three").Object3D<import("three").Object3DEventMap>) | ((name: string, value: any, optionalTarget?: import("three").Object3D<import("three").Object3DEventMap>[]) => import("three").Object3D<import("three").Object3DEventMap>[]) | ((target: Vector3) => Vector3) | ((target: import("three").Quaternion) => import("three").Quaternion) | ((target: Vector3) => Vector3) | ((target: Vector3) => Vector3) | ((raycaster: import("three").Raycaster, intersects: import("three").Intersection<import("three").Object3D<import("three").Object3DEventMap>>[]) => void) | ((callback: (object: import("three").Object3D<import("three").Object3DEventMap>) => any) => void) | ((callback: (object: import("three").Object3D<import("three").Object3DEventMap>) => any) => void) | (() => void) | ((updateParents: boolean, updateChildren: boolean) => void) | ((meta?: {
|
|
29
29
|
geometries: any;
|
|
30
30
|
materials: any;
|
|
31
31
|
textures: any;
|
|
32
32
|
images: any;
|
|
33
|
-
}) => any) | import("three").SpriteMaterial | ((source: SpriteText, recursive?: boolean) => SpriteText) | (() => void) | ((quaternion: import("three").Quaternion) => SpriteText) | ((axis: Vector3, angle: number) => SpriteText) | ((axis: Vector3, angle: number) => SpriteText) | ((angle: number) => SpriteText) | ((angle: number) => SpriteText) | ((angle: number) => SpriteText) | ((axis: Vector3, distance: number) => SpriteText) | ((distance: number) => SpriteText) | ((distance: number) => SpriteText) | ((distance: number) => SpriteText) | ((...object: import("three").Object3D<import("three").Object3DEventMap>[]) => SpriteText) | ((...object: import("three").Object3D<import("three").Object3DEventMap>[]) => SpriteText) | (() => SpriteText) | (() => SpriteText) | ((object: import("three").Object3D<import("three").Object3DEventMap>) => SpriteText) | ((recursive?: boolean) => SpriteText) | {
|
|
33
|
+
}) => any) | (<T extends keyof import("three").Object3DEventMap>(event: import("three").BaseEvent<T> & import("three").Object3DEventMap[T]) => void) | HTMLCanvasElement | import("three").Vector2 | import("three").SpriteMaterial | ((source: SpriteText, recursive?: boolean) => SpriteText) | (() => void) | ((quaternion: import("three").Quaternion) => SpriteText) | ((axis: Vector3, angle: number) => SpriteText) | ((axis: Vector3, angle: number) => SpriteText) | ((angle: number) => SpriteText) | ((angle: number) => SpriteText) | ((angle: number) => SpriteText) | ((axis: Vector3, distance: number) => SpriteText) | ((distance: number) => SpriteText) | ((distance: number) => SpriteText) | ((distance: number) => SpriteText) | ((...object: import("three").Object3D<import("three").Object3DEventMap>[]) => SpriteText) | ((...object: import("three").Object3D<import("three").Object3DEventMap>[]) => SpriteText) | (() => SpriteText) | (() => SpriteText) | ((object: import("three").Object3D<import("three").Object3DEventMap>) => SpriteText) | ((recursive?: boolean) => SpriteText) | {
|
|
34
34
|
<T_1 extends keyof import("three").Object3DEventMap>(type: T_1, listener: import("three").EventListener<import("three").Object3DEventMap[T_1], T_1, SpriteText>): void;
|
|
35
35
|
<T_2 extends string>(type: T_2, listener: import("three").EventListener<{}, T_2, SpriteText>): void;
|
|
36
36
|
} | {
|
package/ThreeBase.js
CHANGED
|
@@ -187,7 +187,12 @@ export default class ThreeBase extends EventDispatcher {
|
|
|
187
187
|
frame = 50;
|
|
188
188
|
init() {
|
|
189
189
|
// 资源加载进度有更新时, 需要渲染
|
|
190
|
-
threeLoader.addEventListener("
|
|
190
|
+
threeLoader.addEventListener("loadding", () => {
|
|
191
|
+
this.dispatchEvent({ type: "loadding" });
|
|
192
|
+
this.needRender = true;
|
|
193
|
+
});
|
|
194
|
+
threeLoader.addEventListener("onLoad", () => {
|
|
195
|
+
this.dispatchEvent({ type: "onLoad" });
|
|
191
196
|
this.needRender = true;
|
|
192
197
|
});
|
|
193
198
|
}
|
|
@@ -294,9 +299,7 @@ export default class ThreeBase extends EventDispatcher {
|
|
|
294
299
|
}
|
|
295
300
|
// 渲染场景
|
|
296
301
|
render() {
|
|
297
|
-
//
|
|
298
|
-
// this.renderer.domElement.style.pointerEvents = (!this.controlsPosition.isDone() || !this.controlsCenter.isDone()) ? "none" : "all";
|
|
299
|
-
// canvas 没有在页面上面的话 就跳过渲染
|
|
302
|
+
// canvas 没有在页面上面的话 就停止渲染
|
|
300
303
|
if (!threeUtils.inDocument(this.renderer.domElement)) {
|
|
301
304
|
this.stopRender();
|
|
302
305
|
return;
|
package/ThreeBase.ts
CHANGED
|
@@ -227,7 +227,13 @@ export default class ThreeBase extends EventDispatcher {
|
|
|
227
227
|
|
|
228
228
|
init() {
|
|
229
229
|
// 资源加载进度有更新时, 需要渲染
|
|
230
|
-
threeLoader.addEventListener("
|
|
230
|
+
threeLoader.addEventListener("loadding", () => {
|
|
231
|
+
this.dispatchEvent({ type: "loadding" } as never);
|
|
232
|
+
this.needRender = true;
|
|
233
|
+
});
|
|
234
|
+
|
|
235
|
+
threeLoader.addEventListener("onLoad", () => {
|
|
236
|
+
this.dispatchEvent({ type: "onLoad" } as never);
|
|
231
237
|
this.needRender = true;
|
|
232
238
|
});
|
|
233
239
|
|
|
@@ -363,10 +369,7 @@ export default class ThreeBase extends EventDispatcher {
|
|
|
363
369
|
|
|
364
370
|
// 渲染场景
|
|
365
371
|
render() {
|
|
366
|
-
//
|
|
367
|
-
// this.renderer.domElement.style.pointerEvents = (!this.controlsPosition.isDone() || !this.controlsCenter.isDone()) ? "none" : "all";
|
|
368
|
-
|
|
369
|
-
// canvas 没有在页面上面的话 就跳过渲染
|
|
372
|
+
// canvas 没有在页面上面的话 就停止渲染
|
|
370
373
|
if (!threeUtils.inDocument(this.renderer.domElement)) {
|
|
371
374
|
this.stopRender();
|
|
372
375
|
return;
|
package/ThreeMouse.js
CHANGED
|
@@ -232,7 +232,7 @@ export default class ThreeMouse {
|
|
|
232
232
|
return;
|
|
233
233
|
}
|
|
234
234
|
this._mesh_on = intersection.object;
|
|
235
|
-
if (this.hasEvent(this.
|
|
235
|
+
if (this.hasEvent(this._mesh_on, ["mouseup"])) {
|
|
236
236
|
this._mesh_on.dispatchEvent({
|
|
237
237
|
...intersection,
|
|
238
238
|
renderer: this._renderer,
|
package/ThreeMouse.ts
CHANGED
|
@@ -312,7 +312,7 @@ export default class ThreeMouse {
|
|
|
312
312
|
|
|
313
313
|
this._mesh_on = intersection.object as Object3D;
|
|
314
314
|
|
|
315
|
-
if (this.hasEvent(this.
|
|
315
|
+
if (this.hasEvent(this._mesh_on, ["mouseup"])) {
|
|
316
316
|
|
|
317
317
|
this._mesh_on.dispatchEvent({
|
|
318
318
|
...intersection,
|
package/package.json
CHANGED
package/threeLoader.js
CHANGED
|
@@ -26,8 +26,13 @@ class ThreeLoader extends EventDispatcher {
|
|
|
26
26
|
this.onload = false;
|
|
27
27
|
};
|
|
28
28
|
// 有资源加载完成时通知渲染器
|
|
29
|
-
DefaultLoadingManager.onProgress = () => {
|
|
30
|
-
|
|
29
|
+
DefaultLoadingManager.onProgress = (url, loaded, total) => {
|
|
30
|
+
if (loaded < total) {
|
|
31
|
+
this.dispatchEvent({ type: "loadding" });
|
|
32
|
+
}
|
|
33
|
+
else if (loaded === total) {
|
|
34
|
+
this.dispatchEvent({ type: "onLoad" });
|
|
35
|
+
}
|
|
31
36
|
};
|
|
32
37
|
DefaultLoadingManager.onLoad = () => {
|
|
33
38
|
this.onload = true;
|
package/threeLoader.ts
CHANGED
|
@@ -32,8 +32,12 @@ class ThreeLoader extends EventDispatcher {
|
|
|
32
32
|
}
|
|
33
33
|
|
|
34
34
|
// 有资源加载完成时通知渲染器
|
|
35
|
-
DefaultLoadingManager.onProgress = () => {
|
|
36
|
-
|
|
35
|
+
DefaultLoadingManager.onProgress = (url: string, loaded: number, total: number) => {
|
|
36
|
+
if (loaded < total) {
|
|
37
|
+
this.dispatchEvent({ type: "loadding" } as never);
|
|
38
|
+
} else if (loaded === total) {
|
|
39
|
+
this.dispatchEvent({ type: "onLoad" } as never);
|
|
40
|
+
}
|
|
37
41
|
}
|
|
38
42
|
|
|
39
43
|
DefaultLoadingManager.onLoad = () => {
|
package/threeUtils.d.ts
CHANGED
|
@@ -36,6 +36,7 @@ declare class ThreeUtils extends EventDispatcher {
|
|
|
36
36
|
centerObject3D(object3d: Object3D | BufferGeometry): void;
|
|
37
37
|
center(object3d: Object3D | BufferGeometry): void;
|
|
38
38
|
scaleTo(object3d: Object3D | BufferGeometry, size?: number, key?: Array<"x" | "y" | "z">): void;
|
|
39
|
+
applyAllTranstion(object3d: Object3D): void;
|
|
39
40
|
exportGLB(input: Object3D, fileName?: string): void;
|
|
40
41
|
getVolume(geometry: BufferGeometry): number;
|
|
41
42
|
signedVolumeOfTriangle(p1: Vector3, p2: Vector3, p3: Vector3): number;
|
package/threeUtils.js
CHANGED
|
@@ -173,6 +173,19 @@ class ThreeUtils extends EventDispatcher {
|
|
|
173
173
|
object3d.scale(scale, scale, scale);
|
|
174
174
|
}
|
|
175
175
|
}
|
|
176
|
+
// 应用全部变化
|
|
177
|
+
applyAllTranstion(object3d) {
|
|
178
|
+
object3d.updateMatrixWorld(true);
|
|
179
|
+
// 应用全部变换
|
|
180
|
+
object3d.traverse(obj => {
|
|
181
|
+
obj.position.set(0, 0, 0);
|
|
182
|
+
obj.rotation.set(0, 0, 0);
|
|
183
|
+
obj.scale.set(1, 1, 1);
|
|
184
|
+
if (obj.isMesh) {
|
|
185
|
+
obj.geometry.applyMatrix4(obj.matrixWorld);
|
|
186
|
+
}
|
|
187
|
+
});
|
|
188
|
+
}
|
|
176
189
|
// 导出 glb
|
|
177
190
|
exportGLB(input, fileName = "threeUtils.exportGLB") {
|
|
178
191
|
const gltfExporter = new GLTFExporter();
|
package/threeUtils.ts
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* @Last Modified time: 2023-05-03 00:36:18
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
-
import { Box3, BufferAttribute, BufferGeometry, Clock, EventDispatcher, Object3D, Vector3 } from "three";
|
|
8
|
+
import { Box3, BufferAttribute, BufferGeometry, Clock, EventDispatcher, Mesh, MeshStandardMaterial, Object3D, Vector3 } from "three";
|
|
9
9
|
import { GLTFExporter } from 'three/examples/jsm/exporters/GLTFExporter';
|
|
10
10
|
|
|
11
11
|
class ThreeUtils extends EventDispatcher {
|
|
@@ -200,6 +200,20 @@ class ThreeUtils extends EventDispatcher {
|
|
|
200
200
|
}
|
|
201
201
|
}
|
|
202
202
|
|
|
203
|
+
// 应用全部变化
|
|
204
|
+
applyAllTranstion(object3d: Object3D) {
|
|
205
|
+
object3d.updateMatrixWorld(true);
|
|
206
|
+
// 应用全部变换
|
|
207
|
+
object3d.traverse(obj => {
|
|
208
|
+
obj.position.set(0, 0, 0);
|
|
209
|
+
obj.rotation.set(0, 0, 0);
|
|
210
|
+
obj.scale.set(1, 1, 1);
|
|
211
|
+
if ((obj as Mesh).isMesh) {
|
|
212
|
+
(obj as Mesh).geometry.applyMatrix4(obj.matrixWorld);
|
|
213
|
+
}
|
|
214
|
+
});
|
|
215
|
+
}
|
|
216
|
+
|
|
203
217
|
// 导出 glb
|
|
204
218
|
exportGLB(input: Object3D, fileName: string = "threeUtils.exportGLB") {
|
|
205
219
|
const gltfExporter = new GLTFExporter();
|