Skip to content

Commit 4db1d3c

Browse files
author
Eric Sartre
committed
first commit
1 parent 6398753 commit 4db1d3c

File tree

4 files changed

+451
-0
lines changed

4 files changed

+451
-0
lines changed

geometry.c

+203
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,203 @@
1+
#include <stdio.h>
2+
#include <stdlib.h>
3+
#include <math.h>
4+
#include "geometry.h"
5+
6+
static vertex_t *vertices = NULL;
7+
static face_t *faces = NULL;
8+
static unsigned capacity_vertices;
9+
static unsigned capacity_faces;
10+
static unsigned num_vertices;
11+
static unsigned num_faces;
12+
13+
void init_geometry()
14+
{
15+
num_vertices = num_faces = 0;
16+
capacity_vertices = INIT_BUFSIZE_VERTICES;
17+
capacity_faces = INIT_BUFSIZE_FACES;
18+
if((vertices = malloc(capacity_vertices * sizeof(vertex_t))) == NULL) {
19+
error_printf("out of memory(faces)\n");
20+
exit(EXIT_FAILURE);
21+
}
22+
if((faces = malloc(capacity_faces * sizeof(face_t))) == NULL) {
23+
error_printf("out of memory(vertices)\n");
24+
FREE(vertices);
25+
exit(EXIT_FAILURE);
26+
}
27+
}
28+
29+
void finalize_geometry()
30+
{
31+
FREE(vertices);
32+
FREE(faces);
33+
}
34+
35+
bool is_valid_id(const vertex_id id)
36+
{
37+
if(id > num_vertices) {
38+
error_printf("invalid vertex_id %d\n", id);
39+
return false;
40+
} else {
41+
return true;
42+
}
43+
}
44+
45+
vertex_id new_vertex(const double x, const double y, const double z)
46+
{
47+
// initialized check
48+
if(vertices == NULL) {
49+
error_printf("not initialized\n");
50+
exit(EXIT_FAILURE);
51+
}
52+
// expand vertices buffer
53+
if(num_vertices >= capacity_vertices) {
54+
capacity_vertices *= 2;
55+
vertices = realloc(vertices, capacity_vertices * sizeof(vertex_t));
56+
if(vertices == NULL) {
57+
error_printf("failed to expand buffer(vertices)\n");
58+
FREE(faces);
59+
exit(EXIT_FAILURE);
60+
}
61+
}
62+
// put on record
63+
vertices[num_vertices].x = x;
64+
vertices[num_vertices].y = y;
65+
vertices[num_vertices].z = z;
66+
num_vertices++;
67+
return num_vertices - 1;
68+
}
69+
70+
vertex_id copy_vertex(const vertex_id v)
71+
{
72+
if(!is_valid_id(v)) return ERROR_VERTEX;
73+
return new_vertex(vertices[v].x, vertices[v].y, vertices[v].z);
74+
}
75+
76+
void new_face(const vertex_id v1, const vertex_id v2, const vertex_id v3)
77+
{
78+
// initialized check
79+
if(faces == NULL) {
80+
error_printf("not initialized\n");
81+
exit(EXIT_FAILURE);
82+
}
83+
// expand faces buffer
84+
if(num_faces >= capacity_faces) {
85+
capacity_faces *= 2;
86+
faces = realloc(faces, capacity_faces * sizeof(face_t));
87+
if(faces == NULL) {
88+
error_printf("failed to expand buffer(faces)\n");
89+
FREE(vertices);
90+
exit(EXIT_FAILURE);
91+
}
92+
}
93+
// put on record
94+
faces[num_faces].v1 = v1;
95+
faces[num_faces].v2 = v2;
96+
faces[num_faces].v3 = v3;
97+
num_faces++;
98+
}
99+
100+
double get_x(const vertex_id v)
101+
{
102+
return vertices[v].x;
103+
}
104+
double get_y(const vertex_id v)
105+
{
106+
return vertices[v].y;
107+
}
108+
double get_z(const vertex_id v)
109+
{
110+
return vertices[v].z;
111+
}
112+
vertex_t get_point(const vertex_id v)
113+
{
114+
return vertices[v];
115+
}
116+
117+
bool flushOBJ(FILE *fp)
118+
{
119+
// initialized check
120+
if(vertices == NULL || faces == NULL) {
121+
error_printf("not initialized\n");
122+
exit(EXIT_FAILURE);
123+
}
124+
// flush vertices
125+
for(unsigned i = 0; i < num_vertices; ++i) {
126+
vertex_t *v = &vertices[i];
127+
if(fprintf(fp, "v %f %f %f\n", v->x, v->y, v->z) < 0) {
128+
error_printf("failed to write file\n");
129+
goto ON_ERROR;
130+
}
131+
}
132+
// flush faces
133+
for(unsigned i = 0; i < num_faces; ++i) {
134+
face_t *f = &faces[i];
135+
if(fprintf(fp, "f %d %d %d\n", f->v1 + 1, f->v2 + 1, f->v3 + 1) < 0) {
136+
error_printf("failed to write file\n");
137+
goto ON_ERROR;
138+
}
139+
}
140+
return true;
141+
ON_ERROR:
142+
FREE(vertices);
143+
FREE(faces);
144+
fclose(fp);
145+
return false;
146+
}
147+
148+
static inline vertex_t *vp(const vertex_id id)
149+
{
150+
return &vertices[id];
151+
}
152+
153+
bool vertex_translate(const vertex_id *vs, const unsigned len,
154+
const double x, const double y, const double z)
155+
{
156+
for(unsigned i = 0; i < len; ++i) {
157+
if(!is_valid_id(vs[i])) return false;
158+
vertex_t *v = vp(vs[i]);
159+
v->x += x;
160+
v->y += y;
161+
v->z += z;
162+
}
163+
return true;
164+
}
165+
166+
bool vertex_scale(const vertex_id *vs, const unsigned len,
167+
const double x, const double y, const double z)
168+
{
169+
for(unsigned i = 0; i < len; ++i) {
170+
if(!is_valid_id(vs[i])) return false;
171+
vertex_t *v = vp(vs[i]);
172+
v->x *= x;
173+
v->y *= y;
174+
v->z *= z;
175+
}
176+
return true;
177+
}
178+
179+
bool vertex_rotate(const vertex_id *vs,
180+
const unsigned len, const double degree,
181+
const double nx, const double ny, const double nz)
182+
{
183+
const double rad = M_PI * degree / 180.0 / 2.0;
184+
const double x = nx * sin(rad);
185+
const double y = ny * sin(rad);
186+
const double z = nz * sin(rad);
187+
const double w = cos(rad / 2.0);
188+
const double m[3][3] = {
189+
{1-2*(y*y+z*z), 2*(x*y-z*w) , 2*(x*z+y*w) },
190+
{2*(x*y+z*w) , 1-2*(z*z+x*x), 2*(y*z-x*w) },
191+
{2*(x*y-y*w) , 2*(y*z+x*w) , 1-2*(x*x+y*y)},
192+
};
193+
for(unsigned i = 0; i < len; ++i) {
194+
if(!is_valid_id(vs[i])) return false;
195+
vertex_t *v = vp(vs[i]);
196+
const vertex_t t = {v->x, v->y, v->z};
197+
v->x = t.x * m[0][0] + t.y * m[0][1] + t.z * m[0][2];
198+
v->y = t.x * m[1][0] + t.y * m[1][1] + t.z * m[1][2];
199+
v->z = t.x * m[2][0] + t.y * m[2][1] + t.z * m[2][2];
200+
}
201+
return true;
202+
}
203+

geometry.h

+60
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
#ifndef GEOMETRY_H_
2+
#define GEOMETRY_H_
3+
4+
#include <stdio.h>
5+
#include <stdbool.h>
6+
#include <limits.h>
7+
#define INIT_BUFSIZE_VERTICES 1024
8+
#define INIT_BUFSIZE_FACES 1024
9+
#define ERROR_VERTEX UINT_MAX
10+
11+
// Utility
12+
#define FREE(P) do { if(P) free(P); P = NULL; } while(0)
13+
#define error_printf(...) do {\
14+
fprintf(stderr, "ERROR(%s) : ", __func__);\
15+
fprintf(stderr, __VA_ARGS__);\
16+
} while(0)
17+
18+
typedef struct {
19+
double x;
20+
double y;
21+
double z;
22+
} vertex_t;
23+
24+
typedef unsigned vertex_id;
25+
26+
typedef struct {
27+
vertex_id v1;
28+
vertex_id v2;
29+
vertex_id v3;
30+
} face_t;
31+
32+
void init_geometry();
33+
void finalize_geometry();
34+
bool is_valid_id(const vertex_id id);
35+
36+
// Constructors
37+
vertex_id new_vertex(const double x, const double y, const double z);
38+
vertex_id copy_vertex(const vertex_id v);
39+
void new_face(const vertex_id v1, const vertex_id v2, const vertex_id v3);
40+
41+
// Accessor
42+
double get_x(const vertex_id v);
43+
double get_y(const vertex_id v);
44+
double get_z(const vertex_id v);
45+
vertex_t get_point(const vertex_id v);
46+
47+
// Affine transformations
48+
bool vertex_translate(const vertex_id *vs, const unsigned len,
49+
const double x, const double y, const double z);
50+
bool vertex_scale(const vertex_id *vs, const unsigned len,
51+
const double x, const double y, const double z);
52+
bool vertex_rotate(const vertex_id *vs,
53+
const unsigned len, const double degree,
54+
const double nx, const double ny, const double nz);
55+
56+
// Flush as Wavefront OBJ file format
57+
bool flushOBJ(FILE *fp);
58+
59+
#endif
60+

0 commit comments

Comments
 (0)