Skip to content

Commit 23a65a8

Browse files
committed
Merge pull request #49 from sshirokov/mesh-type
Generic Mesh Type
2 parents 9885b4b + 1686f57 commit 23a65a8

File tree

14 files changed

+598
-25
lines changed

14 files changed

+598
-25
lines changed

src/bsp.c

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
#include "bsp.h"
44
#include "dbg.h"
5+
#include "export.h"
56

67
bsp_node_t *alloc_bsp_node(void) {
78
bsp_node_t *node = NULL;
@@ -627,3 +628,49 @@ bsp_node_t *bsp_intersect(bsp_node_t *tree_a, bsp_node_t *tree_b) {
627628
if(result != NULL) free_bsp_tree(result);
628629
return NULL;
629630
}
631+
632+
int bsp_count_polygons(bsp_node_t *tree) {
633+
if(tree == NULL) return 0;
634+
635+
return (tree->polygons == NULL) ? 0 : tree->polygons->size +
636+
bsp_count_polygons(tree->front) +
637+
bsp_count_polygons(tree->back);
638+
}
639+
640+
// bsp_node_t tree backed mesh methods and mesh prototype
641+
int bsp_mesh_init(void *self, void *data) {
642+
bsp_mesh_t *mesh = (bsp_mesh_t*)self;
643+
if(data == NULL) {
644+
check_mem(mesh->bsp = alloc_bsp_node());
645+
}
646+
else {
647+
mesh->bsp = (bsp_node_t*)data;
648+
}
649+
return 0;
650+
error:
651+
return -1;
652+
}
653+
654+
void bsp_mesh_destroy(void *self) {
655+
bsp_mesh_t *mesh = (bsp_mesh_t*)self;
656+
free_bsp_tree(mesh->bsp);
657+
free(self);
658+
}
659+
660+
int bsp_mesh_poly_count(void *self) {
661+
bsp_mesh_t *mesh = (bsp_mesh_t*)self;
662+
return bsp_count_polygons(mesh->bsp);
663+
}
664+
665+
klist_t(poly)* bsp_mesh_to_polygons(void *self) {
666+
bsp_mesh_t *mesh = (bsp_mesh_t*)self;
667+
return bsp_to_polygons(mesh->bsp, 0, NULL);
668+
}
669+
670+
// bsp_mesh_t prototype definition
671+
mesh_t bsp_mesh_t_Proto = {
672+
.init = bsp_mesh_init,
673+
.destroy = bsp_mesh_destroy,
674+
.poly_count = bsp_mesh_poly_count,
675+
.to_polygons = bsp_mesh_to_polygons,
676+
};

src/bsp.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
#include "klist.h"
22
#include "poly.h"
3+
#include "mesh.h"
34

45
#ifndef __BSP_H
56
#define __BSP_H
@@ -23,6 +24,14 @@ typedef struct s_bsp_node {
2324
struct s_bsp_node *back;
2425
} bsp_node_t;
2526

27+
extern mesh_t bsp_mesh_t_Proto;
28+
29+
typedef struct s_bsp_mesh_t {
30+
mesh_t proto;
31+
bsp_node_t *bsp;
32+
} bsp_mesh_t;
33+
34+
2635
bsp_node_t *alloc_bsp_node(void);
2736
bsp_node_t *clone_bsp_tree(bsp_node_t *tree);
2837

src/commands.c

Lines changed: 23 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
#include "dbg.h"
33

44
#include "commands.h"
5-
#include "stl.h"
5+
#include "mesh.h"
66
#include "bsp.h"
77
#include "export.h"
88

@@ -12,39 +12,39 @@ typedef bsp_node_t* (*bsp_binary_op)(bsp_node_t *, bsp_node_t *);
1212
// in `path1` and `path1` defined by an operation `op` from` bsp.h
1313
// Result is freshly allocated, and needs to be freed with `free_bsp_tree()`
1414
bsp_node_t* bsp_binary_operation(char *path1, char *path2, bsp_binary_op op) {
15-
stl_object *file1 = NULL;
15+
mesh_t *file1 = NULL;
1616
bsp_node_t *bsp1 = NULL;
1717

18-
stl_object *file2 = NULL;
18+
mesh_t *file2 = NULL;
1919
bsp_node_t *bsp2 = NULL;
2020

2121
bsp_node_t *result = NULL;
2222

2323
// Read 1
24-
file1 = stl_read_file(path1, 1);
25-
check(file1 != NULL, "Failed to read .stl from '%s'", path1);
26-
log_info("Loaded file: %s %d facets", path1, file1->facet_count);
27-
bsp1 = stl_to_bsp(file1);
24+
file1 = mesh_read_file(path1);
25+
check(file1 != NULL, "Failed to read mesh from '%s'", path1);
26+
log_info("Loaded file: %s %d facets", path1, file1->poly_count(file1));
27+
bsp1 = mesh_to_bsp(file1);
2828
check_mem(bsp1);
2929

3030
// Read 2
31-
file2 = stl_read_file(path2, 1);
32-
check(file2 != NULL, "Failed to read .stl from '%s'", path2);
33-
log_info("Loaded file: %s %d facets", path2, file2->facet_count);
34-
bsp2 = stl_to_bsp(file2);
31+
file2 = mesh_read_file(path2);
32+
check(file2 != NULL, "Failed to read mesh from '%s'", path2);
33+
log_info("Loaded file: %s %d facets", path2, file2->poly_count(file2));
34+
bsp2 = mesh_to_bsp(file2);
3535
check_mem(bsp2);
3636

3737
// Operate
3838
result = op(bsp1, bsp2);
3939

40-
if(file1 != NULL) stl_free(file1);
41-
if(file2 != NULL) stl_free(file2);
40+
if(file1 != NULL) file1->destroy(file1);
41+
if(file2 != NULL) file2->destroy(file2);
4242
if(bsp1 != NULL) free_bsp_tree(bsp1);
4343
if(bsp2 != NULL) free_bsp_tree(bsp2);
4444
return result;
4545
error:
46-
if(file1 != NULL) stl_free(file1);
47-
if(file2 != NULL) stl_free(file2);
46+
if(file1 != NULL) file1->destroy(file1);
47+
if(file2 != NULL) file2->destroy(file2);
4848
if(bsp1 != NULL) free_bsp_tree(bsp1);
4949
if(bsp2 != NULL) free_bsp_tree(bsp2);
5050
if(result != NULL) free_bsp_tree(result);
@@ -61,23 +61,23 @@ bsp_node_t* bsp_binary_operation(char *path1, char *path2, bsp_binary_op op) {
6161
#define MAKE_CSG_COMMAND(name) \
6262
int cmd_##name(int argc, char **argv) { \
6363
bsp_node_t *result = NULL; \
64-
stl_object *out = NULL; \
64+
mesh_t *out = NULL; \
6565
char *out_path = "./out.stl"; \
6666
\
6767
check(argc >= 2, "At least two input files required."); \
6868
if(argc > 2) out_path = argv[2]; \
6969
\
70-
result = bsp_binary_operation(argv[0], argv[1], bsp_##name); \
71-
out = bsp_to_stl(result); \
70+
result = bsp_binary_operation(argv[0], argv[1], bsp_##name); \
71+
check(result != NULL, "Binary operation" #name "failed."); \
72+
out = NEW(bsp_mesh_t, "BSP", result); \
7273
log_info("Writing output to %s", out_path); \
73-
check(stl_write_file(out, out_path) == 0, "Failed to write STL to %s", out_path); \
74+
check(out->write(out, out_path) == 0, "Failed to write STL to %s", out_path); \
7475
\
75-
if(result != NULL) free_bsp_tree(result); \
76-
if(out != NULL) stl_free(out); \
76+
out->destroy(out); \
7777
return 0; \
7878
error: \
79-
if(result != NULL) free_bsp_tree(result); \
80-
if(out != NULL) stl_free(out); \
79+
if(out != NULL) out->destroy(out); \
80+
else if(result != NULL) free_bsp_tree(result); \
8181
return -1; \
8282
}
8383

src/export.c

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,3 +65,56 @@ bsp_node_t *stl_to_bsp(stl_object *stl) {
6565
}
6666
return NULL;
6767
}
68+
69+
bsp_node_t *mesh_to_bsp(mesh_t *mesh) {
70+
bsp_node_t *tree = NULL;
71+
klist_t(poly) *polys = NULL;
72+
73+
check((polys = mesh->to_polygons(mesh)) != NULL,
74+
"Failed to convert mesh %p to polgon list", mesh);
75+
76+
check((tree = bsp_build(NULL, polys, 1)) != NULL,
77+
"Failed to build BSP tree from %zd polys", polys->size);
78+
79+
kl_destroy(poly, polys);
80+
return tree;
81+
error:
82+
if(tree != NULL) free_bsp_tree(tree);
83+
if(polys != NULL) kl_destroy(poly, polys);
84+
return NULL;
85+
}
86+
87+
klist_t(poly)* polys_to_tris(klist_t(poly) *dst, klist_t(poly) *src) {
88+
klist_t(poly) *result = dst;
89+
if(result == NULL) result = kl_init(poly);
90+
91+
kliter_t(poly) *iter = NULL;
92+
for(iter = kl_begin(src); iter != kl_end(src); iter = kl_next(iter)) {
93+
poly_t *poly = kl_val(iter);
94+
int vertex_count = poly_vertex_count(poly);
95+
96+
// Copy triangles, split higher-vertex polygons into triangle fans.
97+
if(vertex_count == 3) {
98+
poly_t *copy = clone_poly(poly);
99+
check_mem(copy);
100+
*kl_pushp(poly, result) = copy;
101+
}
102+
else if(vertex_count > 3) {
103+
float3 *v_cur, *v_prev;
104+
for(int i = 2; i < vertex_count; i++) {
105+
v_cur = &poly->vertices[i];
106+
v_prev = &poly->vertices[i - 1];
107+
poly_t *tri = poly_make_triangle(poly->vertices[0], *v_prev, *v_cur);
108+
check_mem(tri);
109+
*kl_pushp(poly, result) = tri;
110+
}
111+
} else {
112+
sentinel("polygon(%p) has less than three(%d) vertices.", poly, poly_vertex_count(poly));
113+
}
114+
}
115+
116+
return result;
117+
error:
118+
if(result != dst) if(result != NULL) kl_destroy(poly, result);
119+
return NULL;
120+
}

src/export.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,15 @@
55
#include "stl.h"
66
#include "poly.h"
77
#include "bsp.h"
8+
#include "mesh.h"
89

910
#ifndef __EXPORT_H
1011
#define __EXPORT_H
1112

1213
stl_object *stl_from_polys(klist_t(poly) *polygons);
1314
stl_object *bsp_to_stl(bsp_node_t *tree);
1415
bsp_node_t *stl_to_bsp(stl_object *stl);
16+
bsp_node_t *mesh_to_bsp(mesh_t *mesh);
17+
klist_t(poly)* polys_to_tris(klist_t(poly)* dst, klist_t(poly)* src);
1518

1619
#endif

src/mesh.c

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
#include "dbg.h"
2+
3+
#include "stl.h"
4+
#include "export.h"
5+
#include "mesh.h"
6+
#include "reader.h"
7+
8+
int mesh_init(void *self, void *unused) {
9+
if(self == NULL) return -1;
10+
return 0;
11+
}
12+
13+
char* mesh_describe(void *self) {
14+
mesh_t *mesh = (mesh_t*)self;
15+
return mesh->type;
16+
}
17+
18+
void free_mesh(void *self) {
19+
if(self != NULL) free(self);
20+
return;
21+
}
22+
23+
int _default_poly_count(void *self) {
24+
return 0;
25+
}
26+
27+
klist_t(poly)* _default_to_polygons(void *self) {
28+
return NULL;
29+
}
30+
31+
int _default_write(void *self, char *path) {
32+
int rc = -1;
33+
mesh_t *mesh = (mesh_t*)self;
34+
stl_object *stl = NULL;
35+
klist_t(poly) *polys = mesh->to_polygons(mesh);
36+
klist_t(poly) *triangles = NULL;
37+
check(polys != NULL, "Failed to get polygons from mesh %p", mesh);
38+
39+
triangles = polys_to_tris(NULL, polys);
40+
check(triangles != NULL, "Failed to convert polygons to trianges.");
41+
42+
// The default output format is STL
43+
stl = stl_from_polys(triangles);
44+
check(stl != NULL, "Failed to generate STL object for write.");
45+
rc = stl_write_file(stl, path);
46+
47+
if(stl != NULL) stl_free(stl);
48+
if(polys != NULL) kl_destroy(poly, polys);
49+
if(triangles != NULL) kl_destroy(poly, triangles);
50+
return rc;
51+
error:
52+
if(stl != NULL) stl_free(stl);
53+
if(polys != NULL) kl_destroy(poly, polys);
54+
if(triangles != NULL) kl_destroy(poly, triangles);
55+
return -1;
56+
}
57+
58+
void *alloc_mesh(size_t size, mesh_t proto, char type[4], void *data) {
59+
if(proto.init == NULL) proto.init = mesh_init;
60+
if(proto.destroy == NULL) proto.destroy = free_mesh;
61+
if(proto.poly_count == NULL) proto.poly_count = _default_poly_count;
62+
if(proto.to_polygons == NULL) proto.to_polygons = _default_to_polygons;
63+
if(proto.write == NULL) proto.write = _default_write;
64+
65+
mesh_t *m = calloc(1, size);
66+
*m = proto;
67+
strncpy(m->type, type, 3);
68+
69+
check(m->init(m, data) != -1, "Failed to initialize %p(%s, %p)", m, m->type, data);
70+
return m;
71+
error:
72+
if(m != NULL) m->destroy(m);
73+
return NULL;
74+
}
75+
76+
mesh_t *mesh_read_file(char *path) {
77+
return reader_load(path);
78+
}

src/mesh.h

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
#include <stdlib.h>
2+
3+
#include "poly.h"
4+
5+
#ifndef __MESH_H
6+
#define __MESH_H
7+
8+
typedef struct s_mesh_t {
9+
char type[4];
10+
11+
int (*init)(void *self, void *data);
12+
void (*destroy)(void *self);
13+
14+
int (*poly_count)(void *self);
15+
klist_t(poly)* (*to_polygons)(void *self);
16+
17+
int (*write)(void *self, char *path);
18+
} mesh_t;
19+
20+
int mesh_init(void *self, void *data);
21+
void free_mesh(void *self);
22+
23+
void *alloc_mesh(size_t size, mesh_t proto, char type[4], void *data);
24+
25+
#define NEW(T, N, D) alloc_mesh(sizeof(T), T##_Proto, N, D)
26+
#define _(M) proto.M
27+
28+
// Load wrapper to read better
29+
mesh_t *mesh_read_file(char *path);
30+
31+
#endif

0 commit comments

Comments
 (0)