Skip to content

Commit 924ba9b

Browse files
committed
use the flat data API for CSG to convert to and from Manifold objects
1 parent 94b4508 commit 924ba9b

2 files changed

Lines changed: 38 additions & 132 deletions

File tree

src/main/java/com/neuronrobotics/manifold3d/CSGManifold3d.java

Lines changed: 6 additions & 108 deletions
Original file line numberDiff line numberDiff line change
@@ -49,95 +49,15 @@ public MemorySegment toManifold(CSG csg) throws Throwable {
4949
if (csg == null)
5050
throw new IllegalArgumentException("csg must not be null");
5151

52-
List<Polygon> polygons = csg.getPolygons();
53-
if (polygons == null || polygons.isEmpty())
54-
throw new IllegalArgumentException("CSG has no polygons");
55-
56-
// Build an indexed triangle mesh.
57-
// Use a tolerance-free exact key so we don't merge
58-
// numerically-close-but-distinct verts.
59-
Map<String, Integer> vertexIndex = new HashMap<>();
60-
List<double[]> vertexList = new ArrayList<>();
61-
List<Long> triList = new ArrayList<>();
62-
63-
for (Polygon incoming : polygons) {
64-
for (Polygon poly : PolygonUtil.triangulatePolygon(incoming)) {
65-
List<Vertex> pverts = poly.getVertices();
66-
if (pverts == null || pverts.size() < 3)
67-
continue;
68-
69-
// Fan triangulation: (0,1,2), (0,2,3), (0,3,4), ...
70-
int i0 = intern(pverts.get(0), vertexIndex, vertexList);
71-
for (int i = 1; i < pverts.size() - 1; i++) {
72-
int i1 = intern(pverts.get(i), vertexIndex, vertexList);
73-
int i2 = intern(pverts.get(i + 1), vertexIndex, vertexList);
74-
75-
// Skip degenerate triangles (two or more identical indices).
76-
if (i0 == i1 || i1 == i2 || i0 == i2)
77-
continue;
78-
79-
triList.add((long) i0);
80-
triList.add((long) i1);
81-
triList.add((long) i2);
82-
}
83-
}
84-
}
8552

86-
if (triList.isEmpty())
87-
throw new IllegalArgumentException("CSG produced no valid triangles after triangulation");
53+
double[] vertices = csg.getVertices();
8854

89-
long nVerts = vertexList.size();
90-
long nTris = triList.size() / 3;
91-
92-
// Flatten vertex list into a primitive array.
93-
double[] vertices = new double[(int) (nVerts * 3)];
94-
for (int i = 0; i < nVerts; i++) {
95-
double[] v = vertexList.get(i);
96-
vertices[i * 3] = v[0];
97-
vertices[i * 3 + 1] = v[1];
98-
vertices[i * 3 + 2] = v[2];
99-
}
100-
101-
// Flatten triangle index list.
102-
long[] triangles = new long[triList.size()];
103-
for (int i = 0; i < triList.size(); i++) {
104-
triangles[i] = triList.get(i);
105-
}
106-
107-
MemorySegment ms = manifold.importMeshGL64(vertices, triangles, nVerts, nTris);
55+
long[] triangles = csg.getTriangles();
56+
MemorySegment ms = manifold.importMeshGL64(vertices, triangles, vertices.length, triangles.length);
10857
checkResult(ms);
10958
return ms;
11059
}
11160

112-
/**
113-
* Returns the index of {@code v} in {@code vertexList}, inserting it if not
114-
* already present. The key is an exact string representation of (x, y, z) using
115-
* {@link Double#toHexString} so that only bit-identical positions are merged,
116-
* matching the BSP's behavior.
117-
*/
118-
private static int intern(Vertex v, Map<String, Integer> index, List<double[]> list) {
119-
// 1. Lower the precision slightly. 1e9 is too high for 'double' stability
120-
// after multiple CSG operations. 1e7 (0.1 nanometer) is the "sweet spot".
121-
double precision = 1e7;
122-
123-
long x = Math.round(v.pos.x * precision);
124-
long y = Math.round(v.pos.y * precision);
125-
long z = Math.round(v.pos.z * precision);
126-
127-
String key = x + "," + y + "," + z;
128-
129-
return index.computeIfAbsent(key, k -> {
130-
int idx = list.size();
131-
// Use the RAW position for the first instance of this vertex.
132-
// This keeps the geometry as true to the BSP as possible.
133-
list.add(new double[] { v.pos.x, v.pos.y, v.pos.z });
134-
return idx;
135-
});
136-
}
137-
// -------------------------------------------------------------------------
138-
// helpers
139-
140-
14161
/**
14262
* Converts a native manifold {@link MemorySegment} to a JCSG {@link CSG}.
14363
*
@@ -168,31 +88,9 @@ public CSG fromManifold(MemorySegment ms) throws Throwable {
16888
if (triCount == 0)
16989
return new CSG();
17090

171-
ArrayList<Polygon> polygons = new ArrayList<>(triCount);
172-
173-
for (int t = 0; t < triCount; t++) {
174-
int base = t * 3;
175-
176-
Vector3d p0 = vertexAt(verts, (int) tris[base]);
177-
Vector3d p1 = vertexAt(verts, (int) tris[base + 1]);
178-
Vector3d p2 = vertexAt(verts, (int) tris[base + 2]);
179-
180-
List<Vertex> vertices = Arrays.asList(new Vertex(p0), new Vertex(p1), new Vertex(p2));
181-
182-
polygons.add(new Polygon(vertices));
183-
}
184-
185-
return CSG.fromPolygons(polygons);
91+
return new CSG(verts, tris, verts.length, triCount);
18692
}
18793

188-
// -------------------------------------------------------------------------
189-
// helpers
190-
191-
192-
private static Vector3d vertexAt(double[] verts, int index) {
193-
int base = index * 3;
194-
return new Vector3d(verts[base], verts[base + 1], verts[base + 2]);
195-
}
19694

19795
/**
19896
* Slices the given CSG at Z=0 and returns the resulting cross-section as a list
@@ -366,7 +264,7 @@ private void checkResult(MemorySegment... memorySegments) throws Throwable {
366264
System.out.println("Tris: " + manifold.numTri(ms));
367265
System.out.println("Genus: " + manifold.genus(ms));
368266
throw new NonManifoldShapeError("Error was " + err);
369-
}else {
267+
} else {
370268
System.out.println("Manifold check ok!");
371269
}
372270
}
@@ -387,7 +285,7 @@ public CSG hull(List<Vector3d> points) throws Throwable {
387285

388286
CSG fromManifold = fromManifold(mem);
389287
manifold.delete(mem);
390-
mem=null;
288+
mem = null;
391289
return fromManifold;
392290
} finally {
393291
manifold.delete(mem);

src/main/java/eu/mihosoft/vrl/v3d/CSG.java

Lines changed: 32 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -263,7 +263,7 @@ private static Vector3d vertexAt(double[] verts, long index) {
263263
}
264264

265265
public Vector3d vertexAt(long i) {
266-
return vertexAt(vertices, i);
266+
return vertexAt(getVertices(), i);
267267
}
268268

269269
public List<Vector3d> getPoints() {
@@ -275,9 +275,9 @@ public List<Vector3d> getPoints() {
275275

276276
public Polygon getPolygonByIndex(int faceIndex) throws ColinearPointsException {
277277
List<Vertex> points = new ArrayList<Vertex>();
278-
points.add(new Vertex(vertexAt(triangles[faceIndex * 3])));
279-
points.add(new Vertex(vertexAt(triangles[faceIndex * 3 + 1])));
280-
points.add(new Vertex(vertexAt(triangles[faceIndex * 3 + 2])));
278+
points.add(new Vertex(vertexAt(getTriangles()[faceIndex * 3])));
279+
points.add(new Vertex(vertexAt(getTriangles()[faceIndex * 3 + 1])));
280+
points.add(new Vertex(vertexAt(getTriangles()[faceIndex * 3 + 2])));
281281
return new Polygon(points);
282282
}
283283

@@ -323,15 +323,15 @@ public CSG processPolygonsToTriangles(ArrayList<Polygon> polygons) throws Coline
323323
vertices = new double[(int) (vertCount * 3)];
324324
for (int i = 0; i < vertCount; i++) {
325325
Vector3d v = vertexList.get(i);
326-
vertices[i * 3] = v.x;
327-
vertices[i * 3 + 1] = v.y;
328-
vertices[i * 3 + 2] = v.z;
326+
getVertices()[i * 3] = v.x;
327+
getVertices()[i * 3 + 1] = v.y;
328+
getVertices()[i * 3 + 2] = v.z;
329329
}
330330

331331
// Flatten triangle index list.
332332
triangles = new long[(int) triCount * 3];
333-
for (int i = 0; i < triangles.length; i++) {
334-
triangles[i] = triList.get(i);
333+
for (int i = 0; i < getTriangles().length; i++) {
334+
getTriangles()[i] = triList.get(i);
335335
}
336336
return this;
337337
}
@@ -995,7 +995,7 @@ public CSG clone() {
995995
}
996996

997997
public CSG cloneShallow() {
998-
return new CSG(vertices.clone(), triangles.clone(), vertCount, triCount);
998+
return new CSG(getVertices().clone(), getTriangles().clone(), vertCount, triCount);
999999
}
10001000

10011001
/**
@@ -1305,7 +1305,7 @@ public CSG hull(List<CSG> csgs) {
13051305

13061306
for (CSG c : csgs) {
13071307
for (int i = 0; i < c.vertCount; i++) {
1308-
points.add(vertexAt(c.vertices, i));
1308+
points.add(vertexAt(c.getVertices(), i));
13091309
}
13101310
}
13111311

@@ -2010,8 +2010,8 @@ public CSG makeManifold() throws ColinearPointsException {
20102010
}
20112011

20122012
private void setData(CSG csg) {
2013-
vertices = csg.vertices.clone();
2014-
triangles = csg.triangles.clone();
2013+
vertices = csg.getVertices().clone();
2014+
triangles = csg.getTriangles().clone();
20152015
vertCount = csg.vertCount;
20162016
triCount = csg.triCount;
20172017
}
@@ -2718,10 +2718,10 @@ public String toObjString() {
27182718
*/
27192719
private void flip() {
27202720
for (int i = 0; i < triCount; i++) {
2721-
long a = triangles[i * 3 + 1];
2722-
long b = triangles[i * 3 + 2];
2723-
triangles[i * 3 + 1] = b;
2724-
triangles[i * 3 + 2] = a;
2721+
long a = getTriangles()[i * 3 + 1];
2722+
long b = getTriangles()[i * 3 + 2];
2723+
getTriangles()[i * 3 + 1] = b;
2724+
getTriangles()[i * 3 + 2] = a;
27252725
}
27262726
}
27272727

@@ -2742,9 +2742,9 @@ public CSG transformed(Transform transform) {
27422742
CSG csg = clone();
27432743

27442744
for (int i = 0; i < vertCount; i++) {
2745-
double vectx = csg.vertices[i * 3];
2746-
double vecty = csg.vertices[i * 3 + 1];
2747-
double vectz = csg.vertices[i * 3 + 2];
2745+
double vectx = csg.getVertices()[i * 3];
2746+
double vecty = csg.getVertices()[i * 3 + 1];
2747+
double vectz = csg.getVertices()[i * 3 + 2];
27482748
double prevX = vectx;
27492749
double prevY = vecty;
27502750
double prevZ = vectz;
@@ -2763,9 +2763,9 @@ public CSG transformed(Transform transform) {
27632763
double diffY = vecty - prevY;
27642764
double diffZ = vectz - prevZ;
27652765

2766-
csg.vertices[i * 3] = prevX + (diffX);
2767-
csg.vertices[i * 3 + 1] = prevY + (diffY);
2768-
csg.vertices[i * 3 + 2] = prevZ + (diffZ);
2766+
csg.getVertices()[i * 3] = prevX + (diffX);
2767+
csg.getVertices()[i * 3 + 1] = prevY + (diffY);
2768+
csg.getVertices()[i * 3 + 2] = prevZ + (diffZ);
27692769
}
27702770
if (transform.isMirror()) {
27712771
flip();
@@ -2846,7 +2846,7 @@ public Bounds getBounds() {
28462846

28472847
for (int i = 0; i < vertCount; i++) {
28482848

2849-
Vector3d vert = vertexAt(vertices, i);
2849+
Vector3d vert = vertexAt(getVertices(), i);
28502850

28512851
if (vert.x < minX) {
28522852
minX = vert.x;
@@ -4534,4 +4534,12 @@ public static CSGManifold3d getManifold() {
45344534
return manifold;
45354535
}
45364536

4537+
public double[] getVertices() {
4538+
return vertices;
4539+
}
4540+
4541+
public long[] getTriangles() {
4542+
return triangles;
4543+
}
4544+
45374545
}

0 commit comments

Comments
 (0)