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,90 @@
|
|
|
1
|
+
export class Object3D
|
|
2
|
+
{
|
|
3
|
+
constructor ()
|
|
4
|
+
{
|
|
5
|
+
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
VertexCount ()
|
|
9
|
+
{
|
|
10
|
+
return 0;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
VertexColorCount ()
|
|
14
|
+
{
|
|
15
|
+
return 0;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
NormalCount ()
|
|
19
|
+
{
|
|
20
|
+
return 0;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
TextureUVCount ()
|
|
24
|
+
{
|
|
25
|
+
return 0;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
TriangleCount ()
|
|
29
|
+
{
|
|
30
|
+
return 0;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
EnumerateVertices (onVertex)
|
|
34
|
+
{
|
|
35
|
+
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
EnumerateTriangleVertexIndices (onTriangleVertexIndices)
|
|
39
|
+
{
|
|
40
|
+
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
EnumerateTriangleVertices (onTriangleVertices)
|
|
44
|
+
{
|
|
45
|
+
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export class ModelObject3D extends Object3D
|
|
50
|
+
{
|
|
51
|
+
constructor ()
|
|
52
|
+
{
|
|
53
|
+
super ();
|
|
54
|
+
this.name = '';
|
|
55
|
+
this.propertyGroups = [];
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
GetName ()
|
|
59
|
+
{
|
|
60
|
+
return this.name;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
SetName (name)
|
|
64
|
+
{
|
|
65
|
+
this.name = name;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
PropertyGroupCount ()
|
|
69
|
+
{
|
|
70
|
+
return this.propertyGroups.length;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
AddPropertyGroup (propertyGroup)
|
|
74
|
+
{
|
|
75
|
+
this.propertyGroups.push (propertyGroup);
|
|
76
|
+
return this.propertyGroups.length - 1;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
GetPropertyGroup (index)
|
|
80
|
+
{
|
|
81
|
+
return this.propertyGroups[index];
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
CloneProperties (target)
|
|
85
|
+
{
|
|
86
|
+
for (let propertyGroup of this.propertyGroups) {
|
|
87
|
+
target.AddPropertyGroup (propertyGroup.Clone ());
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { EscapeHtmlChars } from '../core/core.js';
|
|
2
|
+
import { RGBColorToHexString } from './color.js';
|
|
3
|
+
|
|
4
|
+
export const PropertyType =
|
|
5
|
+
{
|
|
6
|
+
Text : 1,
|
|
7
|
+
Integer : 2,
|
|
8
|
+
Number : 3,
|
|
9
|
+
Boolean : 4,
|
|
10
|
+
Percent : 5,
|
|
11
|
+
Color : 6
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
export class Property
|
|
15
|
+
{
|
|
16
|
+
constructor (type, name, value)
|
|
17
|
+
{
|
|
18
|
+
this.type = type;
|
|
19
|
+
this.name = name;
|
|
20
|
+
this.value = value;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
Clone ()
|
|
24
|
+
{
|
|
25
|
+
const clonable = (this.type === PropertyType.Color);
|
|
26
|
+
if (clonable) {
|
|
27
|
+
return new Property (this.type, this.name, this.value.Clone ());
|
|
28
|
+
} else {
|
|
29
|
+
return new Property (this.type, this.name, this.value);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export class PropertyGroup
|
|
35
|
+
{
|
|
36
|
+
constructor (name)
|
|
37
|
+
{
|
|
38
|
+
this.name = name;
|
|
39
|
+
this.properties = [];
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
PropertyCount ()
|
|
43
|
+
{
|
|
44
|
+
return this.properties.length;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
AddProperty (property)
|
|
48
|
+
{
|
|
49
|
+
this.properties.push (property);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
GetProperty (index)
|
|
53
|
+
{
|
|
54
|
+
return this.properties[index];
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
Clone ()
|
|
58
|
+
{
|
|
59
|
+
let cloned = new PropertyGroup (this.name);
|
|
60
|
+
for (let property of this.properties) {
|
|
61
|
+
cloned.AddProperty (property.Clone ());
|
|
62
|
+
}
|
|
63
|
+
return cloned;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
export function PropertyToString (property)
|
|
68
|
+
{
|
|
69
|
+
if (property.type === PropertyType.Text) {
|
|
70
|
+
return EscapeHtmlChars (property.value);
|
|
71
|
+
} else if (property.type === PropertyType.Integer) {
|
|
72
|
+
return property.value.toLocaleString ();
|
|
73
|
+
} else if (property.type === PropertyType.Number) {
|
|
74
|
+
return property.value.toLocaleString (undefined, {
|
|
75
|
+
minimumFractionDigits: 2,
|
|
76
|
+
maximumFractionDigits: 2
|
|
77
|
+
});
|
|
78
|
+
} else if (property.type === PropertyType.Boolean) {
|
|
79
|
+
return property.value ? 'True' : 'False';
|
|
80
|
+
} else if (property.type === PropertyType.Percent) {
|
|
81
|
+
return parseInt (property.value * 100, 10).toString () + '%';
|
|
82
|
+
} else if (property.type === PropertyType.Color) {
|
|
83
|
+
return '#' + RGBColorToHexString (property.value);
|
|
84
|
+
}
|
|
85
|
+
return null;
|
|
86
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { CoordDistance3D, CrossVector3D, DotVector3D } from '../geometry/coord3d.js';
|
|
2
|
+
import { Model } from './model.js';
|
|
3
|
+
|
|
4
|
+
export function GetTriangleArea (v0, v1, v2)
|
|
5
|
+
{
|
|
6
|
+
const a = CoordDistance3D (v0, v1);
|
|
7
|
+
const b = CoordDistance3D (v1, v2);
|
|
8
|
+
const c = CoordDistance3D (v0, v2);
|
|
9
|
+
const s = (a + b + c) / 2.0;
|
|
10
|
+
const areaSquare = s * (s - a) * (s - b) * (s - c);
|
|
11
|
+
if (areaSquare < 0.0) {
|
|
12
|
+
return 0.0;
|
|
13
|
+
}
|
|
14
|
+
return Math.sqrt (areaSquare);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export function GetTetrahedronSignedVolume (v0, v1, v2)
|
|
18
|
+
{
|
|
19
|
+
return DotVector3D (v0, CrossVector3D (v1, v2)) / 6.0;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export function CalculateVolume (object3D)
|
|
23
|
+
{
|
|
24
|
+
if (object3D instanceof Model) {
|
|
25
|
+
let volume = 0.0;
|
|
26
|
+
object3D.EnumerateMeshInstances ((meshInstance) => {
|
|
27
|
+
volume += CalculateVolume (meshInstance);
|
|
28
|
+
});
|
|
29
|
+
return volume;
|
|
30
|
+
} else {
|
|
31
|
+
let volume = 0.0;
|
|
32
|
+
object3D.EnumerateTriangleVertices ((v0, v1, v2) => {
|
|
33
|
+
volume += GetTetrahedronSignedVolume (v0, v1, v2);
|
|
34
|
+
});
|
|
35
|
+
return volume;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export function CalculateSurfaceArea (object3D)
|
|
40
|
+
{
|
|
41
|
+
let surface = 0.0;
|
|
42
|
+
object3D.EnumerateTriangleVertices ((v0, v1, v2) => {
|
|
43
|
+
surface += GetTriangleArea (v0, v1, v2);
|
|
44
|
+
});
|
|
45
|
+
return surface;
|
|
46
|
+
}
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
export class TopologyVertex
|
|
2
|
+
{
|
|
3
|
+
constructor ()
|
|
4
|
+
{
|
|
5
|
+
this.edges = [];
|
|
6
|
+
this.triangles = [];
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export class TopologyEdge
|
|
11
|
+
{
|
|
12
|
+
constructor (vertex1, vertex2)
|
|
13
|
+
{
|
|
14
|
+
this.vertex1 = vertex1;
|
|
15
|
+
this.vertex2 = vertex2;
|
|
16
|
+
this.triangles = [];
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export class TopologyTriangleEdge
|
|
21
|
+
{
|
|
22
|
+
constructor (edge, reversed)
|
|
23
|
+
{
|
|
24
|
+
this.edge = edge;
|
|
25
|
+
this.reversed = reversed;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export class TopologyTriangle
|
|
30
|
+
{
|
|
31
|
+
constructor ()
|
|
32
|
+
{
|
|
33
|
+
this.triEdge1 = null;
|
|
34
|
+
this.triEdge2 = null;
|
|
35
|
+
this.triEdge3 = null;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export class Topology
|
|
40
|
+
{
|
|
41
|
+
constructor ()
|
|
42
|
+
{
|
|
43
|
+
this.vertices = [];
|
|
44
|
+
this.edges = [];
|
|
45
|
+
this.triangleEdges = [];
|
|
46
|
+
this.triangles = [];
|
|
47
|
+
this.edgeStartToEndVertexMap = new Map ();
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
AddVertex ()
|
|
51
|
+
{
|
|
52
|
+
this.vertices.push (new TopologyVertex ());
|
|
53
|
+
return this.vertices.length - 1;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
AddTriangle (vertex1, vertex2, vertex3)
|
|
57
|
+
{
|
|
58
|
+
function AddTriangleToVertex (vertices, vertexIndex, triangleIndex)
|
|
59
|
+
{
|
|
60
|
+
let vertex = vertices[vertexIndex];
|
|
61
|
+
vertex.triangles.push (triangleIndex);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function AddEdgeToVertex (vertices, triangleEdges, vertexIndex, triangleEdgeIndex)
|
|
65
|
+
{
|
|
66
|
+
let vertex = vertices[vertexIndex];
|
|
67
|
+
let triangleEdge = triangleEdges[triangleEdgeIndex];
|
|
68
|
+
vertex.edges.push (triangleEdge.edge);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
function AddTriangleToEdge (edges, triangleEdges, triangleEdgeIndex, triangleIndex)
|
|
72
|
+
{
|
|
73
|
+
let triangleEdge = triangleEdges[triangleEdgeIndex];
|
|
74
|
+
let edge = edges[triangleEdge.edge];
|
|
75
|
+
edge.triangles.push (triangleIndex);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
let triangleIndex = this.triangles.length;
|
|
79
|
+
|
|
80
|
+
let triangle = new TopologyTriangle ();
|
|
81
|
+
triangle.triEdge1 = this.AddTriangleEdge (vertex1, vertex2);
|
|
82
|
+
triangle.triEdge2 = this.AddTriangleEdge (vertex2, vertex3);
|
|
83
|
+
triangle.triEdge3 = this.AddTriangleEdge (vertex3, vertex1);
|
|
84
|
+
|
|
85
|
+
AddTriangleToVertex (this.vertices, vertex1, triangleIndex);
|
|
86
|
+
AddTriangleToVertex (this.vertices, vertex2, triangleIndex);
|
|
87
|
+
AddTriangleToVertex (this.vertices, vertex3, triangleIndex);
|
|
88
|
+
|
|
89
|
+
AddEdgeToVertex (this.vertices, this.triangleEdges, vertex1, triangle.triEdge1);
|
|
90
|
+
AddEdgeToVertex (this.vertices, this.triangleEdges, vertex2, triangle.triEdge2);
|
|
91
|
+
AddEdgeToVertex (this.vertices, this.triangleEdges, vertex3, triangle.triEdge3);
|
|
92
|
+
|
|
93
|
+
AddTriangleToEdge (this.edges, this.triangleEdges, triangle.triEdge1, triangleIndex);
|
|
94
|
+
AddTriangleToEdge (this.edges, this.triangleEdges, triangle.triEdge2, triangleIndex);
|
|
95
|
+
AddTriangleToEdge (this.edges, this.triangleEdges, triangle.triEdge3, triangleIndex);
|
|
96
|
+
|
|
97
|
+
this.triangles.push (triangle);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
AddTriangleEdge (vertex1, vertex2)
|
|
101
|
+
{
|
|
102
|
+
let startVertex = vertex1;
|
|
103
|
+
let endVertex = vertex2;
|
|
104
|
+
let reversed = false;
|
|
105
|
+
if (vertex2 < vertex1) {
|
|
106
|
+
startVertex = vertex2;
|
|
107
|
+
endVertex = vertex1;
|
|
108
|
+
reversed = true;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
let edgeIndex = this.AddEdge (startVertex, endVertex);
|
|
112
|
+
this.triangleEdges.push (new TopologyTriangleEdge (edgeIndex, reversed));
|
|
113
|
+
return this.triangleEdges.length - 1;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
AddEdge (startVertex, endVertex)
|
|
117
|
+
{
|
|
118
|
+
if (!this.edgeStartToEndVertexMap.has (startVertex)) {
|
|
119
|
+
this.edgeStartToEndVertexMap.set (startVertex, []);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
let endVertices = this.edgeStartToEndVertexMap.get (startVertex);
|
|
123
|
+
for (let i = 0; i < endVertices.length; i++) {
|
|
124
|
+
let endVertexItem = endVertices[i];
|
|
125
|
+
if (endVertexItem.endVertex === endVertex) {
|
|
126
|
+
return endVertexItem.edgeIndex;
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
let edgeIndex = this.edges.length;
|
|
131
|
+
endVertices.push ({
|
|
132
|
+
endVertex : endVertex,
|
|
133
|
+
edgeIndex : edgeIndex
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
this.edges.push (new TopologyEdge (startVertex, endVertex));
|
|
137
|
+
return edgeIndex;
|
|
138
|
+
}
|
|
139
|
+
}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
export class Triangle
|
|
2
|
+
{
|
|
3
|
+
constructor (v0, v1, v2)
|
|
4
|
+
{
|
|
5
|
+
this.v0 = v0;
|
|
6
|
+
this.v1 = v1;
|
|
7
|
+
this.v2 = v2;
|
|
8
|
+
|
|
9
|
+
this.c0 = null;
|
|
10
|
+
this.c1 = null;
|
|
11
|
+
this.c2 = null;
|
|
12
|
+
|
|
13
|
+
this.n0 = null;
|
|
14
|
+
this.n1 = null;
|
|
15
|
+
this.n2 = null;
|
|
16
|
+
|
|
17
|
+
this.u0 = null;
|
|
18
|
+
this.u1 = null;
|
|
19
|
+
this.u2 = null;
|
|
20
|
+
|
|
21
|
+
this.mat = null;
|
|
22
|
+
this.curve = null;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
HasVertices ()
|
|
26
|
+
{
|
|
27
|
+
return this.v0 !== null && this.v1 !== null && this.v2 !== null;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
HasVertexColors ()
|
|
31
|
+
{
|
|
32
|
+
return this.c0 !== null && this.c1 !== null && this.c2 !== null;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
HasNormals ()
|
|
36
|
+
{
|
|
37
|
+
return this.n0 !== null && this.n1 !== null && this.n2 !== null;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
HasTextureUVs ()
|
|
41
|
+
{
|
|
42
|
+
return this.u0 !== null && this.u1 !== null && this.u2 !== null;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
SetVertices (v0, v1, v2)
|
|
46
|
+
{
|
|
47
|
+
this.v0 = v0;
|
|
48
|
+
this.v1 = v1;
|
|
49
|
+
this.v2 = v2;
|
|
50
|
+
return this;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
SetVertexColors (c0, c1, c2)
|
|
54
|
+
{
|
|
55
|
+
this.c0 = c0;
|
|
56
|
+
this.c1 = c1;
|
|
57
|
+
this.c2 = c2;
|
|
58
|
+
return this;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
SetNormals (n0, n1, n2)
|
|
62
|
+
{
|
|
63
|
+
this.n0 = n0;
|
|
64
|
+
this.n1 = n1;
|
|
65
|
+
this.n2 = n2;
|
|
66
|
+
return this;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
SetTextureUVs (u0, u1, u2)
|
|
70
|
+
{
|
|
71
|
+
this.u0 = u0;
|
|
72
|
+
this.u1 = u1;
|
|
73
|
+
this.u2 = u2;
|
|
74
|
+
return this;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
SetMaterial (mat)
|
|
78
|
+
{
|
|
79
|
+
this.mat = mat;
|
|
80
|
+
return this;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
SetCurve (curve)
|
|
84
|
+
{
|
|
85
|
+
this.curve = curve;
|
|
86
|
+
return this;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
Clone ()
|
|
90
|
+
{
|
|
91
|
+
let cloned = new Triangle (this.v0, this.v1, this.v2);
|
|
92
|
+
cloned.SetVertexColors (this.c0, this.c1, this.c2);
|
|
93
|
+
cloned.SetNormals (this.n0, this.n1, this.n2);
|
|
94
|
+
cloned.SetTextureUVs (this.u0, this.u1, this.u2);
|
|
95
|
+
cloned.SetMaterial (this.mat);
|
|
96
|
+
cloned.SetCurve (this.curve);
|
|
97
|
+
return cloned;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
|
|
2
|
+
import { Importer } from '../import/importer.js';
|
|
3
|
+
import { RevokeObjectUrl } from '../io/bufferutils.js';
|
|
4
|
+
|
|
5
|
+
export class ThreeModelLoader {
|
|
6
|
+
constructor() {
|
|
7
|
+
this.importer = new Importer();
|
|
8
|
+
this.inProgress = false;
|
|
9
|
+
this.defaultMaterial = null;
|
|
10
|
+
this.objectUrls = null;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
InProgress() {
|
|
14
|
+
return this.inProgress;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
LoadModel(inputFiles, settings, callbacks) {
|
|
18
|
+
if (this.inProgress) {
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
this.inProgress = true;
|
|
23
|
+
this.RevokeObjectUrls();
|
|
24
|
+
this.importer.ImportFiles(inputFiles, settings, {
|
|
25
|
+
onLoadStart: () => {
|
|
26
|
+
callbacks.onLoadStart();
|
|
27
|
+
},
|
|
28
|
+
onFileListProgress: (current, total) => {
|
|
29
|
+
callbacks.onFileListProgress(current, total);
|
|
30
|
+
},
|
|
31
|
+
onFileLoadProgress: (current, total) => {
|
|
32
|
+
callbacks.onFileLoadProgress(current, total);
|
|
33
|
+
},
|
|
34
|
+
onImportStart: () => {
|
|
35
|
+
callbacks.onImportStart();
|
|
36
|
+
},
|
|
37
|
+
onSelectMainFile: (fileNames, selectFile) => {
|
|
38
|
+
if (!callbacks.onSelectMainFile) {
|
|
39
|
+
selectFile(0);
|
|
40
|
+
} else {
|
|
41
|
+
callbacks.onSelectMainFile(fileNames, selectFile);
|
|
42
|
+
}
|
|
43
|
+
},
|
|
44
|
+
onImportSuccess: (importResult) => {
|
|
45
|
+
callbacks.onVisualizationStart();
|
|
46
|
+
// let params = new ModelToThreeConversionParams();
|
|
47
|
+
// let output = new ModelToThreeConversionOutput();
|
|
48
|
+
|
|
49
|
+
callbacks.onModelFinished(importResult, undefined);
|
|
50
|
+
|
|
51
|
+
// ConvertModelToThreeObject(importResult.model, params, output, {
|
|
52
|
+
// onTextureLoaded: () => {
|
|
53
|
+
// callbacks.onTextureLoaded();
|
|
54
|
+
// },
|
|
55
|
+
// onModelLoaded: (threeObject) => {
|
|
56
|
+
// callbacks.onModelFinished(importResult, threeObject);
|
|
57
|
+
// this.inProgress = false;
|
|
58
|
+
// }
|
|
59
|
+
// });
|
|
60
|
+
},
|
|
61
|
+
onImportError: (importError) => {
|
|
62
|
+
callbacks.onLoadError(importError);
|
|
63
|
+
this.inProgress = false;
|
|
64
|
+
}
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
GetImporter() {
|
|
69
|
+
return this.importer;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
GetDefaultMaterial() {
|
|
73
|
+
return this.defaultMaterial;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
RevokeObjectUrls() {
|
|
77
|
+
if (this.objectUrls === null) {
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
for (let objectUrl of this.objectUrls) {
|
|
81
|
+
RevokeObjectUrl(objectUrl);
|
|
82
|
+
}
|
|
83
|
+
this.objectUrls = null;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import * as OV from './engine/main.js';
|
|
2
|
+
export class ExporterWorker {
|
|
3
|
+
constructor() {
|
|
4
|
+
this.settings = new OV.ImportSettings()
|
|
5
|
+
this.loader = new OV.ThreeModelLoader()
|
|
6
|
+
this.exporterSettings = new OV.ExporterSettings()
|
|
7
|
+
this.exporter = new OV.Exporter();
|
|
8
|
+
}
|
|
9
|
+
export(req, listeners) {
|
|
10
|
+
let file_name = req.file_name
|
|
11
|
+
// this.storage.startExport(req.gid, req.request_id, req.convert_type)
|
|
12
|
+
let inputFiles = []
|
|
13
|
+
if (req.urlType == 2) {
|
|
14
|
+
inputFiles = [new OV.InputFile(file_name, OV.FileSource.File, req.url)]
|
|
15
|
+
} else {
|
|
16
|
+
inputFiles = [new OV.InputFile(file_name, OV.FileSource.Url, req.url)]
|
|
17
|
+
}
|
|
18
|
+
this.loader.LoadModel(inputFiles, this.settings, {
|
|
19
|
+
onLoadStart: () => { },
|
|
20
|
+
onFileListProgress: (current, total) => {
|
|
21
|
+
// let msg = current + "," + total
|
|
22
|
+
// this.storage.exportStage(req.gid, "FileListProgress", msg)
|
|
23
|
+
},
|
|
24
|
+
onFileLoadProgress: (current, total) => {
|
|
25
|
+
// let msg = current + "," + total
|
|
26
|
+
// this.storage.exportStage(req.gid, "FileLoadProgress", msg)
|
|
27
|
+
if (listeners.onProgress) listeners.onProgress(Math.ceil(current * 100 / total))
|
|
28
|
+
},
|
|
29
|
+
onImportStart: () => {
|
|
30
|
+
// let msg = "Importing model..."
|
|
31
|
+
// this.storage.exportStage(req.gid, "ImportStart", msg)
|
|
32
|
+
},
|
|
33
|
+
onSelectMainFile: (fileNames, selectFile) => {
|
|
34
|
+
|
|
35
|
+
},
|
|
36
|
+
onImportSuccess: (importResult) => {
|
|
37
|
+
},
|
|
38
|
+
onModelFinished: (importResult, threeObject) => {
|
|
39
|
+
// let msg = "Exporting model..."
|
|
40
|
+
// this.storage.exportStage(req.gid, "ExportStart", msg)
|
|
41
|
+
let model = importResult.model;
|
|
42
|
+
this.exporter.Export(model, this.exporterSettings, OV.FileFormat.Text, req.convert_type, {
|
|
43
|
+
onError: () => {
|
|
44
|
+
// this.storage.executionErr(req.gid, "ExportStart", "")
|
|
45
|
+
if (listeners.onError) listeners.onError(new Error("ExportStart"));
|
|
46
|
+
},
|
|
47
|
+
onSuccess: (files, boundingBox) => {
|
|
48
|
+
if (files.length < 1) {
|
|
49
|
+
return
|
|
50
|
+
}
|
|
51
|
+
if (listeners.onSuccess) listeners.onSuccess(files, boundingBox);
|
|
52
|
+
// this.storage.executionSuccess(req.gid, req.save_path, Buffer.from(file.GetBufferContent()))
|
|
53
|
+
}
|
|
54
|
+
})
|
|
55
|
+
},
|
|
56
|
+
onLoadError: (importError) => {
|
|
57
|
+
// this.storage.executionErr(req.gid, "importError", importError)
|
|
58
|
+
if (listeners.onError) listeners.onError(importError);
|
|
59
|
+
},
|
|
60
|
+
onVisualizationStart: () => { }
|
|
61
|
+
})
|
|
62
|
+
}
|
|
63
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { randomUUID } from 'crypto';
|
|
2
|
+
import { ExporterWorker } from "./handler.js";
|
|
3
|
+
import { compressArrayBufferFiles } from './compress.js';
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* 将 GLB 文件转换为 OBJ 格式并压缩
|
|
8
|
+
* @param {string} glbUrl - GLB 文件的 URL
|
|
9
|
+
* @returns {Promise<{zipBuffer:any,boundingBox:any}>} - 压缩后的文件内容
|
|
10
|
+
*/
|
|
11
|
+
export async function gltf2obj(glbUrl, onProgress) {
|
|
12
|
+
const data = {};
|
|
13
|
+
data.file_name = "test.glb";
|
|
14
|
+
data.convert_type = "obj";
|
|
15
|
+
data.url = glbUrl;
|
|
16
|
+
data.gid = randomUUID();
|
|
17
|
+
data.urlType = 1;
|
|
18
|
+
|
|
19
|
+
const {
|
|
20
|
+
files,
|
|
21
|
+
boundingBox
|
|
22
|
+
} = await new Promise((res, rej) => {
|
|
23
|
+
const exporterWorker = new ExporterWorker();
|
|
24
|
+
exporterWorker.export(data, {
|
|
25
|
+
onProgress,
|
|
26
|
+
onError(error) {
|
|
27
|
+
rej(error);
|
|
28
|
+
},
|
|
29
|
+
onSuccess(files, boundingBox) {
|
|
30
|
+
res({
|
|
31
|
+
files,
|
|
32
|
+
boundingBox
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
});
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
// 将导出的文件映射为压缩需要的格式
|
|
39
|
+
const buffer = await compressArrayBufferFiles(
|
|
40
|
+
files.map(f => ({ name: f.name, content: f.content }))
|
|
41
|
+
);
|
|
42
|
+
|
|
43
|
+
return {
|
|
44
|
+
zipBuffer: buffer,
|
|
45
|
+
boundingBox
|
|
46
|
+
};
|
|
47
|
+
}
|