freeform-modeling-mcp 1.0.26
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 +61 -0
- package/index.cjs +21 -0
- package/package.json +48 -0
- package/src/cli.ts +47 -0
- package/src/commands/start.ts +88 -0
- package/src/commands/status.ts +81 -0
- package/src/dev.ts +24 -0
- package/src/lib/fileproxy/index.ts +505 -0
- package/src/lib/fileproxy/proxy-server.js +347 -0
- package/src/lib/gltf2obj/compress.js +33 -0
- package/src/lib/gltf2obj/engine/core/core.js +34 -0
- package/src/lib/gltf2obj/engine/core/eventnotifier.js +39 -0
- package/src/lib/gltf2obj/engine/core/taskrunner.js +88 -0
- package/src/lib/gltf2obj/engine/export/exporter.js +38 -0
- package/src/lib/gltf2obj/engine/export/exporterbase.js +86 -0
- package/src/lib/gltf2obj/engine/export/exportermodel.js +117 -0
- package/src/lib/gltf2obj/engine/export/exporterobj.js +147 -0
- package/src/lib/gltf2obj/engine/geometry/box3d.js +60 -0
- package/src/lib/gltf2obj/engine/geometry/coord2d.js +35 -0
- package/src/lib/gltf2obj/engine/geometry/coord3d.js +126 -0
- package/src/lib/gltf2obj/engine/geometry/coord4d.js +15 -0
- package/src/lib/gltf2obj/engine/geometry/geometry.js +56 -0
- package/src/lib/gltf2obj/engine/geometry/matrix.js +440 -0
- package/src/lib/gltf2obj/engine/geometry/octree.js +160 -0
- package/src/lib/gltf2obj/engine/geometry/quaternion.js +83 -0
- package/src/lib/gltf2obj/engine/geometry/transformation.js +63 -0
- package/src/lib/gltf2obj/engine/geometry/tween.js +31 -0
- package/src/lib/gltf2obj/engine/import/importer.js +270 -0
- package/src/lib/gltf2obj/engine/import/importerbase.js +115 -0
- package/src/lib/gltf2obj/engine/import/importerfiles.js +139 -0
- package/src/lib/gltf2obj/engine/import/importergltf.js +1045 -0
- package/src/lib/gltf2obj/engine/import/importerutils.js +102 -0
- package/src/lib/gltf2obj/engine/io/binaryreader.js +93 -0
- package/src/lib/gltf2obj/engine/io/binarywriter.js +92 -0
- package/src/lib/gltf2obj/engine/io/bufferutils.js +85 -0
- package/src/lib/gltf2obj/engine/io/externallibs.js +42 -0
- package/src/lib/gltf2obj/engine/io/fileutils.js +120 -0
- package/src/lib/gltf2obj/engine/io/textwriter.js +41 -0
- package/src/lib/gltf2obj/engine/main.js +19 -0
- package/src/lib/gltf2obj/engine/model/color.js +130 -0
- package/src/lib/gltf2obj/engine/model/generator.js +433 -0
- package/src/lib/gltf2obj/engine/model/material.js +243 -0
- package/src/lib/gltf2obj/engine/model/mesh.js +173 -0
- package/src/lib/gltf2obj/engine/model/meshbuffer.js +233 -0
- package/src/lib/gltf2obj/engine/model/meshinstance.js +128 -0
- package/src/lib/gltf2obj/engine/model/meshutils.js +64 -0
- package/src/lib/gltf2obj/engine/model/model.js +195 -0
- package/src/lib/gltf2obj/engine/model/modelfinalization.js +377 -0
- package/src/lib/gltf2obj/engine/model/modelutils.js +117 -0
- package/src/lib/gltf2obj/engine/model/node.js +178 -0
- package/src/lib/gltf2obj/engine/model/object.js +90 -0
- package/src/lib/gltf2obj/engine/model/property.js +86 -0
- package/src/lib/gltf2obj/engine/model/quantities.js +46 -0
- package/src/lib/gltf2obj/engine/model/topology.js +139 -0
- package/src/lib/gltf2obj/engine/model/triangle.js +99 -0
- package/src/lib/gltf2obj/engine/threejs/threemodelloader.js +85 -0
- package/src/lib/gltf2obj/handler.js +63 -0
- package/src/lib/gltf2obj/index.js +47 -0
- package/src/lib/logger.ts +304 -0
- package/src/lib/print.ts +37 -0
- package/src/lib/utils.ts +34 -0
- package/src/lib/wsbridge/bridge.ts +639 -0
- package/src/lib/wsbridge/lock.ts +258 -0
- package/src/llmClient.ts +245 -0
- package/src/prompt.ts +187 -0
- package/src/server.ts +125 -0
- package/src/tools/assets-tool.ts +314 -0
- package/src/tools/basic-tools.ts +531 -0
- package/src/tools/index.ts +2 -0
- package/src/tools/material-tools.ts +88 -0
- package/src/tools/modeling/auxiliary-curve-tool.ts +44 -0
- package/src/tools/modeling/find-face.ts +38 -0
- package/src/tools/modeling/sweep-tool.ts +60 -0
- package/src/tools/modeling/utils.ts +181 -0
- package/src/tools/modeling-tools.ts +135 -0
- package/src/tools/screenshot-tools.ts +107 -0
- package/src/tools/tools-info.ts +107 -0
- package/src/tools/tripo3d-tools.ts +496 -0
- package/src/types/index.ts +25 -0
- package/src/types/tripo3d.ts +38 -0
- package/tsconfig.json +22 -0
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import { CopyObjectAttributes } from '../core/core.js';
|
|
2
|
+
import { Transformation } from '../geometry/transformation.js';
|
|
3
|
+
import { CalculateTriangleNormal, TransformMesh } from '../model/meshutils.js';
|
|
4
|
+
|
|
5
|
+
export class ExporterSettings {
|
|
6
|
+
constructor(settings) {
|
|
7
|
+
this.transformation = new Transformation();
|
|
8
|
+
this.isMeshVisible = (meshInstanceId) => {
|
|
9
|
+
return true;
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
CopyObjectAttributes(settings, this);
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export class ExporterModel {
|
|
17
|
+
boundingBox = {
|
|
18
|
+
min: { x: Infinity, y: Infinity, z: Infinity },
|
|
19
|
+
max: { x: -Infinity, y: -Infinity, z: -Infinity }
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
constructor(model, settings) {
|
|
23
|
+
this.model = model;
|
|
24
|
+
this.settings = settings || new ExporterSettings();
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
GetModel() {
|
|
28
|
+
return this.model;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
MaterialCount() {
|
|
32
|
+
return this.model.MaterialCount();
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
GetMaterial(index) {
|
|
36
|
+
return this.model.GetMaterial(index);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
VertexCount() {
|
|
40
|
+
let vertexCount = 0;
|
|
41
|
+
this.EnumerateMeshInstances((meshInstance) => {
|
|
42
|
+
vertexCount += meshInstance.VertexCount();
|
|
43
|
+
});
|
|
44
|
+
return vertexCount;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
TriangleCount() {
|
|
48
|
+
let triangleCount = 0;
|
|
49
|
+
this.EnumerateMeshInstances((meshInstance) => {
|
|
50
|
+
triangleCount += meshInstance.TriangleCount();
|
|
51
|
+
});
|
|
52
|
+
return triangleCount;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
MeshInstanceCount() {
|
|
56
|
+
let meshInstanceCount = 0;
|
|
57
|
+
this.EnumerateMeshInstances((meshInstance) => {
|
|
58
|
+
meshInstanceCount += 1;
|
|
59
|
+
});
|
|
60
|
+
return meshInstanceCount;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
EnumerateMeshInstances(onMeshInstance) {
|
|
64
|
+
this.model.EnumerateMeshInstances((meshInstance) => {
|
|
65
|
+
if (this.settings.isMeshVisible(meshInstance.GetId())) {
|
|
66
|
+
onMeshInstance(meshInstance);
|
|
67
|
+
}
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
EnumerateTransformedMeshes(onMesh) {
|
|
72
|
+
this.EnumerateMeshInstances((meshInstance) => {
|
|
73
|
+
let transformation = meshInstance.GetTransformation();
|
|
74
|
+
if (!this.settings.transformation.IsIdentity()) {
|
|
75
|
+
transformation.Append(this.settings.transformation);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
let mesh = meshInstance.GetMesh();
|
|
79
|
+
let transformed = mesh.Clone();
|
|
80
|
+
if (!transformation.IsIdentity()) {
|
|
81
|
+
TransformMesh(transformed, transformation);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
onMesh(transformed);
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
EnumerateVerticesAndTriangles(callbacks) {
|
|
89
|
+
let transformedMeshes = [];
|
|
90
|
+
this.EnumerateTransformedMeshes((mesh) => {
|
|
91
|
+
transformedMeshes.push(mesh);
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
for (let mesh of transformedMeshes) {
|
|
95
|
+
mesh.EnumerateVertices((vertex) => {
|
|
96
|
+
callbacks.onVertex(vertex.x, vertex.y, vertex.z);
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
let vertexOffset = 0;
|
|
101
|
+
for (let mesh of transformedMeshes) {
|
|
102
|
+
mesh.EnumerateTriangleVertexIndices((v0, v1, v2) => {
|
|
103
|
+
callbacks.onTriangle(v0 + vertexOffset, v1 + vertexOffset, v2 + vertexOffset);
|
|
104
|
+
});
|
|
105
|
+
vertexOffset += mesh.VertexCount();
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
EnumerateTrianglesWithNormals(onTriangle) {
|
|
110
|
+
this.EnumerateTransformedMeshes((mesh) => {
|
|
111
|
+
mesh.EnumerateTriangleVertices((v0, v1, v2) => {
|
|
112
|
+
let normal = CalculateTriangleNormal(v0, v1, v2);
|
|
113
|
+
onTriangle(v0, v1, v2, normal);
|
|
114
|
+
});
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
}
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
import { FileFormat, GetFileName } from '../io/fileutils.js';
|
|
2
|
+
import { TextWriter } from '../io/textwriter.js';
|
|
3
|
+
import { MaterialType } from '../model/material.js';
|
|
4
|
+
import { ExportedFile, ExporterBase } from './exporterbase.js';
|
|
5
|
+
|
|
6
|
+
export class ExporterObj extends ExporterBase {
|
|
7
|
+
constructor() {
|
|
8
|
+
super();
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
CanExport(format, extension) {
|
|
12
|
+
return format === FileFormat.Text && extension === 'obj';
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
ExportContent(exporterModel, format, files, onFinish) {
|
|
16
|
+
function WriteTexture(mtlWriter, keyword, texture, files) {
|
|
17
|
+
if (texture === null || !texture.IsValid()) {
|
|
18
|
+
return;
|
|
19
|
+
}
|
|
20
|
+
let fileName = GetFileName(texture.name);
|
|
21
|
+
mtlWriter.WriteArrayLine([keyword, fileName]);
|
|
22
|
+
|
|
23
|
+
let fileIndex = files.findIndex((file) => {
|
|
24
|
+
return file.GetName() === fileName;
|
|
25
|
+
});
|
|
26
|
+
if (fileIndex === -1) {
|
|
27
|
+
let textureFile = new ExportedFile(fileName);
|
|
28
|
+
textureFile.SetBufferContent(texture.buffer);
|
|
29
|
+
files.push(textureFile);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
let mtlFile = new ExportedFile('model.mtl');
|
|
34
|
+
let objFile = new ExportedFile('model.obj');
|
|
35
|
+
|
|
36
|
+
files.push(mtlFile);
|
|
37
|
+
files.push(objFile);
|
|
38
|
+
|
|
39
|
+
let mtlWriter = new TextWriter();
|
|
40
|
+
mtlWriter.WriteLine(this.GetHeaderText());
|
|
41
|
+
for (let materialIndex = 0; materialIndex < exporterModel.MaterialCount(); materialIndex++) {
|
|
42
|
+
let material = exporterModel.GetMaterial(materialIndex);
|
|
43
|
+
mtlWriter.WriteArrayLine(['newmtl', this.GetExportedMaterialName(material.name)]);
|
|
44
|
+
mtlWriter.WriteArrayLine(['Kd', material.color.r / 255.0, material.color.g / 255.0, material.color.b / 255.0]);
|
|
45
|
+
mtlWriter.WriteArrayLine(['d', material.opacity]);
|
|
46
|
+
if (material.type === MaterialType.Phong) {
|
|
47
|
+
mtlWriter.WriteArrayLine(['Ka', material.ambient.r / 255.0, material.ambient.g / 255.0, material.ambient.b / 255.0]);
|
|
48
|
+
mtlWriter.WriteArrayLine(['Ks', material.specular.r / 255.0, material.specular.g / 255.0, material.specular.b / 255.0]);
|
|
49
|
+
mtlWriter.WriteArrayLine(['Ns', material.shininess * 1000.0]);
|
|
50
|
+
}
|
|
51
|
+
WriteTexture(mtlWriter, 'map_Kd', material.diffuseMap, files);
|
|
52
|
+
if (material.type === MaterialType.Phong) {
|
|
53
|
+
WriteTexture(mtlWriter, 'map_Ks', material.specularMap, files);
|
|
54
|
+
}
|
|
55
|
+
WriteTexture(mtlWriter, 'bump', material.bumpMap, files);
|
|
56
|
+
}
|
|
57
|
+
mtlFile.SetTextContent(mtlWriter.GetText());
|
|
58
|
+
|
|
59
|
+
// 初始化最小和最大坐标值
|
|
60
|
+
const boundingBox = {
|
|
61
|
+
min: { x: Infinity, y: Infinity, z: Infinity },
|
|
62
|
+
max: { x: -Infinity, y: -Infinity, z: -Infinity }
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
let objWriter = new TextWriter();
|
|
66
|
+
objWriter.WriteLine(this.GetHeaderText());
|
|
67
|
+
objWriter.WriteArrayLine(['mtllib', mtlFile.GetName()]);
|
|
68
|
+
let vertexOffset = 0;
|
|
69
|
+
let normalOffset = 0;
|
|
70
|
+
let uvOffset = 0;
|
|
71
|
+
let usedMaterialName = null;
|
|
72
|
+
exporterModel.EnumerateTransformedMeshes((mesh) => {
|
|
73
|
+
objWriter.WriteArrayLine(['g', this.GetExportedMeshName(mesh.GetName())]);
|
|
74
|
+
for (let vertexIndex = 0; vertexIndex < mesh.VertexCount(); vertexIndex++) {
|
|
75
|
+
let vertex = mesh.GetVertex(vertexIndex);
|
|
76
|
+
|
|
77
|
+
let z = vertex.z;
|
|
78
|
+
vertex.z = vertex.y;
|
|
79
|
+
vertex.y = z;
|
|
80
|
+
|
|
81
|
+
objWriter.WriteArrayLine(['v', vertex.x, vertex.y, vertex.z]);
|
|
82
|
+
// 更新包围盒
|
|
83
|
+
boundingBox.min.x = Math.min(boundingBox.min.x, vertex.x);
|
|
84
|
+
boundingBox.min.y = Math.min(boundingBox.min.y, vertex.y);
|
|
85
|
+
boundingBox.min.z = Math.min(boundingBox.min.z, vertex.z);
|
|
86
|
+
|
|
87
|
+
boundingBox.max.x = Math.max(boundingBox.max.x, vertex.x);
|
|
88
|
+
boundingBox.max.y = Math.max(boundingBox.max.y, vertex.y);
|
|
89
|
+
boundingBox.max.z = Math.max(boundingBox.max.z, vertex.z);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
for (let normalIndex = 0; normalIndex < mesh.NormalCount(); normalIndex++) {
|
|
93
|
+
let normal = mesh.GetNormal(normalIndex);
|
|
94
|
+
|
|
95
|
+
let z = normal.z;
|
|
96
|
+
normal.z = normal.y;
|
|
97
|
+
normal.y = z;
|
|
98
|
+
|
|
99
|
+
objWriter.WriteArrayLine(['vn', normal.x, normal.y, normal.z]);
|
|
100
|
+
}
|
|
101
|
+
for (let textureUVIndex = 0; textureUVIndex < mesh.TextureUVCount(); textureUVIndex++) {
|
|
102
|
+
let uv = mesh.GetTextureUV(textureUVIndex);
|
|
103
|
+
uv.y = 1 + uv.y;
|
|
104
|
+
objWriter.WriteArrayLine(['vt', uv.x, uv.y]);
|
|
105
|
+
}
|
|
106
|
+
for (let triangleIndex = 0; triangleIndex < mesh.TriangleCount(); triangleIndex++) {
|
|
107
|
+
let triangle = mesh.GetTriangle(triangleIndex);
|
|
108
|
+
let v0 = triangle.v0 + vertexOffset + 1;
|
|
109
|
+
let v1 = triangle.v1 + vertexOffset + 1;
|
|
110
|
+
let v2 = triangle.v2 + vertexOffset + 1;
|
|
111
|
+
let n0 = triangle.n0 + normalOffset + 1;
|
|
112
|
+
let n1 = triangle.n1 + normalOffset + 1;
|
|
113
|
+
let n2 = triangle.n2 + normalOffset + 1;
|
|
114
|
+
if (triangle.mat !== null) {
|
|
115
|
+
let material = exporterModel.GetMaterial(triangle.mat);
|
|
116
|
+
let materialName = this.GetExportedMaterialName(material.name);
|
|
117
|
+
if (materialName !== usedMaterialName) {
|
|
118
|
+
objWriter.WriteArrayLine(['usemtl', materialName]);
|
|
119
|
+
usedMaterialName = materialName;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
let u0 = '';
|
|
123
|
+
let u1 = '';
|
|
124
|
+
let u2 = '';
|
|
125
|
+
if (triangle.HasTextureUVs()) {
|
|
126
|
+
u0 = triangle.u0 + uvOffset + 1;
|
|
127
|
+
u1 = triangle.u1 + uvOffset + 1;
|
|
128
|
+
u2 = triangle.u2 + uvOffset + 1;
|
|
129
|
+
}
|
|
130
|
+
objWriter.WriteArrayLine(['f', [v0, u0, n0].join('/'), [v1, u1, n1].join('/'), [v2, u2, n2].join('/')]);
|
|
131
|
+
}
|
|
132
|
+
vertexOffset += mesh.VertexCount();
|
|
133
|
+
normalOffset += mesh.NormalCount();
|
|
134
|
+
uvOffset += mesh.TextureUVCount();
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
objFile.SetTextContent(objWriter.GetText());
|
|
138
|
+
|
|
139
|
+
exporterModel.boundingBox = boundingBox;
|
|
140
|
+
|
|
141
|
+
onFinish();
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
GetHeaderText() {
|
|
145
|
+
return '# exported by koomaster-mcp';
|
|
146
|
+
}
|
|
147
|
+
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { Coord3D } from './coord3d.js';
|
|
2
|
+
|
|
3
|
+
export class Box3D
|
|
4
|
+
{
|
|
5
|
+
constructor (min, max)
|
|
6
|
+
{
|
|
7
|
+
this.min = min;
|
|
8
|
+
this.max = max;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
GetMin ()
|
|
12
|
+
{
|
|
13
|
+
return this.min;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
GetMax ()
|
|
17
|
+
{
|
|
18
|
+
return this.max;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
GetCenter ()
|
|
22
|
+
{
|
|
23
|
+
return new Coord3D (
|
|
24
|
+
(this.min.x + this.max.x) / 2.0,
|
|
25
|
+
(this.min.y + this.max.y) / 2.0,
|
|
26
|
+
(this.min.z + this.max.z) / 2.0
|
|
27
|
+
);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export class BoundingBoxCalculator3D
|
|
32
|
+
{
|
|
33
|
+
constructor ()
|
|
34
|
+
{
|
|
35
|
+
this.box = new Box3D (
|
|
36
|
+
new Coord3D (Infinity, Infinity, Infinity),
|
|
37
|
+
new Coord3D (-Infinity, -Infinity, -Infinity)
|
|
38
|
+
);
|
|
39
|
+
this.isValid = false;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
GetBox ()
|
|
43
|
+
{
|
|
44
|
+
if (!this.isValid) {
|
|
45
|
+
return null;
|
|
46
|
+
}
|
|
47
|
+
return this.box;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
AddPoint (point)
|
|
51
|
+
{
|
|
52
|
+
this.box.min.x = Math.min (this.box.min.x, point.x);
|
|
53
|
+
this.box.min.y = Math.min (this.box.min.y, point.y);
|
|
54
|
+
this.box.min.z = Math.min (this.box.min.z, point.z);
|
|
55
|
+
this.box.max.x = Math.max (this.box.max.x, point.x);
|
|
56
|
+
this.box.max.y = Math.max (this.box.max.y, point.y);
|
|
57
|
+
this.box.max.z = Math.max (this.box.max.z, point.z);
|
|
58
|
+
this.isValid = true;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { IsEqual } from './geometry.js';
|
|
2
|
+
|
|
3
|
+
export class Coord2D
|
|
4
|
+
{
|
|
5
|
+
constructor (x, y)
|
|
6
|
+
{
|
|
7
|
+
this.x = x;
|
|
8
|
+
this.y = y;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
Clone ()
|
|
12
|
+
{
|
|
13
|
+
return new Coord2D (this.x, this.y);
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export function CoordIsEqual2D (a, b)
|
|
18
|
+
{
|
|
19
|
+
return IsEqual (a.x, b.x) && IsEqual (a.y, b.y);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export function AddCoord2D (a, b)
|
|
23
|
+
{
|
|
24
|
+
return new Coord2D (a.x + b.x, a.y + b.y);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export function SubCoord2D (a, b)
|
|
28
|
+
{
|
|
29
|
+
return new Coord2D (a.x - b.x, a.y - b.y);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export function CoordDistance2D (a, b)
|
|
33
|
+
{
|
|
34
|
+
return Math.sqrt ((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y));
|
|
35
|
+
}
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
import { IsEqual } from './geometry.js';
|
|
2
|
+
|
|
3
|
+
export class Coord3D
|
|
4
|
+
{
|
|
5
|
+
constructor (x, y, z)
|
|
6
|
+
{
|
|
7
|
+
this.x = x;
|
|
8
|
+
this.y = y;
|
|
9
|
+
this.z = z;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
Length ()
|
|
13
|
+
{
|
|
14
|
+
return Math.sqrt (this.x * this.x + this.y * this.y + this.z * this.z);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
MultiplyScalar (scalar)
|
|
18
|
+
{
|
|
19
|
+
this.x *= scalar;
|
|
20
|
+
this.y *= scalar;
|
|
21
|
+
this.z *= scalar;
|
|
22
|
+
return this;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
Normalize ()
|
|
26
|
+
{
|
|
27
|
+
let length = this.Length ();
|
|
28
|
+
if (length > 0.0) {
|
|
29
|
+
this.MultiplyScalar (1.0 / length);
|
|
30
|
+
}
|
|
31
|
+
return this;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
Offset (direction, distance)
|
|
35
|
+
{
|
|
36
|
+
let normal = direction.Clone ().Normalize ();
|
|
37
|
+
this.x += normal.x * distance;
|
|
38
|
+
this.y += normal.y * distance;
|
|
39
|
+
this.z += normal.z * distance;
|
|
40
|
+
return this;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
Rotate (axis, angle, origo)
|
|
44
|
+
{
|
|
45
|
+
let normal = axis.Clone ().Normalize ();
|
|
46
|
+
|
|
47
|
+
let u = normal.x;
|
|
48
|
+
let v = normal.y;
|
|
49
|
+
let w = normal.z;
|
|
50
|
+
|
|
51
|
+
let x = this.x - origo.x;
|
|
52
|
+
let y = this.y - origo.y;
|
|
53
|
+
let z = this.z - origo.z;
|
|
54
|
+
|
|
55
|
+
let si = Math.sin (angle);
|
|
56
|
+
let co = Math.cos (angle);
|
|
57
|
+
this.x = - u * (- u * x - v * y - w * z) * (1.0 - co) + x * co + (- w * y + v * z) * si;
|
|
58
|
+
this.y = - v * (- u * x - v * y - w * z) * (1.0 - co) + y * co + (w * x - u * z) * si;
|
|
59
|
+
this.z = - w * (- u * x - v * y - w * z) * (1.0 - co) + z * co + (- v * x + u * y) * si;
|
|
60
|
+
|
|
61
|
+
this.x += origo.x;
|
|
62
|
+
this.y += origo.y;
|
|
63
|
+
this.z += origo.z;
|
|
64
|
+
return this;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
Clone ()
|
|
68
|
+
{
|
|
69
|
+
return new Coord3D (this.x, this.y, this.z);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export function CoordIsEqual3D (a, b)
|
|
74
|
+
{
|
|
75
|
+
return IsEqual (a.x, b.x) && IsEqual (a.y, b.y) && IsEqual (a.z, b.z);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
export function AddCoord3D (a, b)
|
|
79
|
+
{
|
|
80
|
+
return new Coord3D (a.x + b.x, a.y + b.y, a.z + b.z);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
export function SubCoord3D (a, b)
|
|
84
|
+
{
|
|
85
|
+
return new Coord3D (a.x - b.x, a.y - b.y, a.z - b.z);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
export function CoordDistance3D (a, b)
|
|
89
|
+
{
|
|
90
|
+
return Math.sqrt ((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y) + (a.z - b.z) * (a.z - b.z));
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
export function DotVector3D (a, b)
|
|
94
|
+
{
|
|
95
|
+
return a.x * b.x + a.y * b.y + a.z * b.z;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
export function VectorAngle3D (a, b)
|
|
99
|
+
{
|
|
100
|
+
let aDirection = a.Clone ().Normalize ();
|
|
101
|
+
let bDirection = b.Clone ().Normalize ();
|
|
102
|
+
if (CoordIsEqual3D (aDirection, bDirection)) {
|
|
103
|
+
return 0.0;
|
|
104
|
+
}
|
|
105
|
+
let product = DotVector3D (aDirection, bDirection);
|
|
106
|
+
return Math.acos (product);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
export function CrossVector3D (a, b)
|
|
110
|
+
{
|
|
111
|
+
let result = new Coord3D (0.0, 0.0, 0.0);
|
|
112
|
+
result.x = a.y * b.z - a.z * b.y;
|
|
113
|
+
result.y = a.z * b.x - a.x * b.z;
|
|
114
|
+
result.z = a.x * b.y - a.y * b.x;
|
|
115
|
+
return result;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
export function VectorLength3D (x, y, z)
|
|
119
|
+
{
|
|
120
|
+
return Math.sqrt (x * x + y * y + z * z);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
export function ArrayToCoord3D (arr)
|
|
124
|
+
{
|
|
125
|
+
return new Coord3D (arr[0], arr[1], arr[2]);
|
|
126
|
+
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
export const Eps = 0.00000001;
|
|
2
|
+
export const BigEps = 0.0001;
|
|
3
|
+
export const RadDeg = 57.29577951308232;
|
|
4
|
+
export const DegRad = 0.017453292519943;
|
|
5
|
+
|
|
6
|
+
export function IsZero (a)
|
|
7
|
+
{
|
|
8
|
+
return Math.abs (a) < Eps;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export function IsLower (a, b)
|
|
12
|
+
{
|
|
13
|
+
return b - a > Eps;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export function IsGreater (a, b)
|
|
17
|
+
{
|
|
18
|
+
return a - b > Eps;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export function IsLowerOrEqual (a, b)
|
|
22
|
+
{
|
|
23
|
+
return b - a > -Eps;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export function IsGreaterOrEqual (a, b)
|
|
27
|
+
{
|
|
28
|
+
return a - b > -Eps;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export function IsEqual (a, b)
|
|
32
|
+
{
|
|
33
|
+
return Math.abs (b - a) < Eps;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export function IsEqualEps (a, b, eps)
|
|
37
|
+
{
|
|
38
|
+
return Math.abs (b - a) < eps;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export function IsPositive (a)
|
|
42
|
+
{
|
|
43
|
+
return a > Eps;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export function IsNegative (a)
|
|
47
|
+
{
|
|
48
|
+
return a < -Eps;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export const Direction =
|
|
52
|
+
{
|
|
53
|
+
X : 1,
|
|
54
|
+
Y : 2,
|
|
55
|
+
Z : 3
|
|
56
|
+
};
|