aboutsummaryrefslogtreecommitdiff
path: root/opengl/include/pdp_mesh.h
blob: 8fd6dffebb17af4199118eeaa28cd22405efd6a6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
/*
 *   Pure Data Packet module. mesh object specification
 *   Copyright (c) by Tom Schouten <pdp@zzz.kotnet.org>
 *
 *   This program is free software; you can redistribute it and/or modify
 *   it under the terms of the GNU General Public License as published by
 *   the Free Software Foundation; either version 2 of the License, or
 *   (at your option) any later version.
 *
 *   This program is distributed in the hope that it will be useful,
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *   GNU General Public License for more details.
 *
 *   You should have received a copy of the GNU General Public License
 *   along with this program; if not, write to the Free Software
 *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 */

/* a very naive approach to triangular meshes */

#ifndef PDP_MESH_H
#define PDP_MESH_H
#include "pdp_list.h"


/* VERTEX type 
   a vertex has a coordinate and normal vector
   a list of triangles it is connected to 
   and a list of vertexes it is connected to (these count as links) */

typedef struct _vertex
{
    float c[3]; // coordinates
    float n[3]; // normal (or force vector)
    t_pdp_list *trilist;
    t_pdp_list *vertlist;
} t_vertex;


/* TRIANGLE type:
   a triangle consist of 
   - 3 vertices
   - 3 optional median vertices (subdivision intermediates) */
typedef struct _triangle
{
    t_vertex *v[3]; // vertices
    t_vertex *m[3]; // median vertices
    float n[3]; //triangle normal
} t_triangle;


/* MESH type:
   a mesh is a list of vertices
   and a list of triangles (connections) */
typedef struct _mesh
{
    t_pdp_list *triangles;
    t_pdp_list *vertices;
    int normal_type;
    int refine_type;
} t_mesh;



/* object configuratie */
#define MESH_NORMAL_SPHERE  1  // normal = origin -> vertex
#define MESH_NORMAL_PRISM   2  // normal = center of gravity of prism base -> vertex
#define MESH_NORMAL_RANDOM  3  // normal = random vector
#define MESH_NORMAL_AVERAGE 4  // normal = average of surrounding triangles

/* refinement method */
#define MESH_REFINE_THREE 1   // triangle -> 3 triangles connecting center of gravity
#define MESH_REFINE_FOUR  2   // triangle -> 4 triangles connecting link medians

// vector utility stuff

// fixed size iterators for the lazy
#define I3(i) for(i=0; i<3; i++)
#define I4(i) for(i=0; i<4; i++)

static inline float _vector3_dot(float *v0, float *v1)
{
    float d;
    d =  v0[0] * v1[0];
    d += v0[1] * v1[1];
    d += v0[2] * v1[2];
    return d;
}

static inline void _vector3_scale(float *v, float s)
{
    int k;
    I3(k) v[k] *= s;
}

static inline float _vector3_normalize(float *v)
{
    float length = 0;
    float scale = 0;
    int k;
    length = sqrt(_vector3_dot(v,v));
    scale = 1.0f / length;
    _vector3_scale(v, scale);
    return length;
}

static inline void _vector3_cross(float *a, float *b, float *r)
{
    r[0] = a[1]*b[2] - a[2]*b[1];
    r[1] = a[2]*b[0] - a[0]*b[2];
    r[2] = a[0]*b[1] - a[1]*b[0];
}

static inline float _rand(void)
{
    long int r = random();
    float f;
    r -= (RAND_MAX >> 1);
    f = (float)r;
    f *= (2.0f / (float)RAND_MAX);
    return f;
}




/* VERTEX methods */
void vertex_add_triangle(t_vertex *v, t_triangle *t);
void vertex_remove_triangle(t_vertex *v, t_triangle *t);
void vertex_add_neighbour(t_vertex *v, t_vertex *neighbour);


/* constructor/destructors are "private"
   they may only be called by the mesh object to ensure
   the vector list stays sound (i.e. without duplicates) */
void _vertex_free(t_vertex *v);
t_vertex *_vertex_new(float *c, float *n);


void vertex_compute_normal_random(t_vertex *v);
void vertex_compute_normal_sphere(t_vertex *v);
void vertex_compute_normal_prism(t_vertex *v);
float vertex_normalize(t_vertex *v);


/* TRIANGLE methods */

/* create triangle (a connection between 3 vertices): 
   counterclockwize with facing front
   this method is "private"
   you can only create triangles as part of a mesh */
t_triangle *_triangle_new(t_vertex *v0, t_vertex *v1, t_vertex *v2);

/* delete a triangle, disconnecting the vertices */
void _triangle_free(t_triangle *t);

/* get triangle that shares the link between v0 and v1 */
t_triangle *triangle_neighbour(t_triangle *t, t_vertex *v0, t_vertex *v1);

/* add a median vector to a link in a triangle 
   note: vertices must be in triangle, or behaviour is undefined */
void triangle_add_median(t_triangle *t, t_vertex *v0, t_vertex *v1, t_vertex *median);

/* MESH methods */

/* add and remove methods for vertices and triangles */
t_vertex *mesh_vertex_add(t_mesh *m, float *c, float *n);
void mesh_vertex_remove(t_mesh *m, t_vertex *v);
t_triangle *mesh_triangle_add(t_mesh *m, t_vertex *v0, t_vertex *v1, t_vertex *v2);
void mesh_triangle_remove(t_mesh *m, t_triangle *t);

/* calculate normals */
void mesh_calculate_normals(t_mesh *m);

/* split a triangle in 4, using the intermedia median vertex storage */
void mesh_split_four(t_mesh *m, t_triangle *old_t);

/* split a triangle in 3 */
void mesh_split_three(t_mesh *m, t_triangle *old_t);

void mesh_split_all_four(t_mesh *m);

void mesh_split_all_three(t_mesh *m);

void mesh_split_random_three(t_mesh *m);

void mesh_free(t_mesh *m);

t_mesh *_mesh_new(void);

/* new tetra */
t_mesh *mesh_new_tetra(void);



void _mesh_relax_compute_resultant_spring(t_mesh *m, float *center, float d0, float r0);
void _mesh_relax_apply_force(t_mesh *m, float k);
void mesh_compute_center(t_mesh *m, float *c);
void mesh_translate(t_mesh *m, float *c);

/* relax a mesh (move toward equal link length) */
void mesh_relax(t_mesh *m, float step, float d0, float r0);

/* print some debug information */
void mesh_debug(t_mesh *m);


#endif