-
Notifications
You must be signed in to change notification settings - Fork 30
/
Copy pathhelpers.ts
145 lines (124 loc) · 4.08 KB
/
helpers.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
/**
* FF Typescript Foundation Library
* Copyright 2020 Ralph Wiedemeier, Frame Factory GmbH
*
* License: MIT
*/
import {
Object3D,
Mesh,
Texture,
Material,
BufferGeometry,
Vector3,
Matrix4,
Box3,
Euler,
Quaternion,
MathUtils,
EulerOrder,
} from "three";
////////////////////////////////////////////////////////////////////////////////
const _vec3 = new Vector3();
const _mat4 = new Matrix4();
const _euler = new Euler();
const _quat = new Quaternion();
export type RotationOrder = "XYZ" | "XZY" | "YXZ" | "YZX" | "ZXY" | "ZYX";
export function degreesToQuaternion(rotation: number[], order: RotationOrder, quaternion?: Quaternion): Quaternion
{
const result = quaternion || new Quaternion();
_vec3.fromArray(rotation).multiplyScalar(MathUtils.DEG2RAD);
_euler.setFromVector3(_vec3, order);
result.setFromEuler(_euler);
return result;
}
export function quaternionToDegrees(quaternion: Quaternion, order: string, rotation?: number[]): number[]
{
const result = rotation || [ 0, 0, 0 ];
_euler.setFromQuaternion(quaternion, order as EulerOrder);
_vec3.setFromEuler(_euler);
_vec3.multiplyScalar(MathUtils.RAD2DEG).toArray(result);
return result;
}
export function disposeObject(object: Object3D)
{
const geometries = new Map<string, BufferGeometry>();
const materials = new Map<string, Material>();
const textures = new Map<string, Texture>();
object.traverse(object => {
const mesh = object as Mesh;
if (mesh.isMesh) {
const geometry = mesh.geometry as BufferGeometry;
if (geometry) {
geometries.set(geometry.uuid, geometry);
}
const material = mesh.material as Material;
if (material) {
materials.set(material.uuid, material);
for (let key in material) {
const texture = material[key] as any; // Texture;
if (texture && texture.isTexture) {
textures.set(texture.uuid, texture);
}
}
}
}
});
if (ENV_DEVELOPMENT) {
console.log("disposeObject - %s geometries, %s materials, %s textures",
geometries.size, materials.size, textures.size);
}
for (let entry of textures) {
entry[1].dispose();
}
for (let entry of materials) {
entry[1].dispose();
}
for (let entry of geometries) {
entry[1].dispose();
}
}
/**
* Computes the bounding box of the given object, relative to the given root (same as object if
* not specified explicitly). Accounts for the transforms of all children relative to the root.
* Caller is responsible for emptying the given bounding box, and for updating the matrices of
* all child objects.
* @param object
* @param box The box to be updated.
* @param root
*/
export function computeLocalBoundingBox(object: Object3D, box: Box3, root?: Object3D)
{
if (!root) {
root = object;
}
const geometry = (object as any).geometry;
if (geometry && object.visible) {
let current = object;
_mat4.identity();
while(current && current !== root) {
_mat4.premultiply(current.matrix);
current = current.parent;
}
if (geometry.isGeometry) {
const vertices = geometry.vertices;
for (let i = 0, n = vertices.length; i < n; ++i) {
_vec3.copy(vertices[i]).applyMatrix4(_mat4);
box.expandByPoint(_vec3);
}
}
else if (geometry.isBufferGeometry) {
const attribute = geometry.attributes.position;
if (attribute !== undefined) {
for (let i = 0, n = attribute.count; i < n; ++i) {
_vec3.fromBufferAttribute(attribute, i).applyMatrix4(_mat4);
box.expandByPoint(_vec3);
}
}
}
}
const children = object.children;
for (let i = 0, n = children.length; i < n; ++i) {
computeLocalBoundingBox(children[i], box, root);
}
}