diff options
Diffstat (limited to 'src/others/mimesh/libg3d-0.0.8/src/primitive.c')
-rw-r--r-- | src/others/mimesh/libg3d-0.0.8/src/primitive.c | 743 |
1 files changed, 743 insertions, 0 deletions
diff --git a/src/others/mimesh/libg3d-0.0.8/src/primitive.c b/src/others/mimesh/libg3d-0.0.8/src/primitive.c new file mode 100644 index 0000000..53b9c5b --- /dev/null +++ b/src/others/mimesh/libg3d-0.0.8/src/primitive.c | |||
@@ -0,0 +1,743 @@ | |||
1 | /* $Id$ */ | ||
2 | |||
3 | /* | ||
4 | libg3d - 3D object loading library | ||
5 | |||
6 | Copyright (C) 2005-2009 Markus Dahms <mad@automagically.de> | ||
7 | |||
8 | This library is free software; you can redistribute it and/or | ||
9 | modify it under the terms of the GNU Lesser General Public | ||
10 | License as published by the Free Software Foundation; either | ||
11 | version 2.1 of the License, or (at your option) any later version. | ||
12 | |||
13 | This library is distributed in the hope that it will be useful, | ||
14 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
16 | Lesser General Public License for more details. | ||
17 | |||
18 | You should have received a copy of the GNU Lesser General Public | ||
19 | License along with this library; if not, write to the Free Software | ||
20 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
21 | */ | ||
22 | |||
23 | #include <math.h> | ||
24 | #include <string.h> | ||
25 | |||
26 | #ifndef M_PI | ||
27 | # define M_PI 3.14159265358979323846 | ||
28 | #endif | ||
29 | |||
30 | #include <g3d/types.h> | ||
31 | #include <g3d/vector.h> | ||
32 | #include <g3d/primitive.h> | ||
33 | #include <g3d/face.h> | ||
34 | |||
35 | EAPI | ||
36 | G3DObject *g3d_primitive_cube(G3DFloat width, G3DFloat height, G3DFloat depth, | ||
37 | G3DMaterial *material) | ||
38 | { | ||
39 | g_warning("g3d_primitive_cube is deprecated - please update your " | ||
40 | "sources to use g3d_primitive_box instead"); | ||
41 | return g3d_primitive_box(width, height, depth, material); | ||
42 | } | ||
43 | |||
44 | EAPI | ||
45 | G3DObject *g3d_primitive_box(G3DFloat width, G3DFloat height, G3DFloat depth, | ||
46 | G3DMaterial *material) | ||
47 | { | ||
48 | G3DObject *object; | ||
49 | G3DFace *face; | ||
50 | G3DVector nx, ny, nz; | ||
51 | gint32 faces[6][4] = { | ||
52 | { 0, 1, 2, 3 }, | ||
53 | { 4, 5, 6, 7 }, | ||
54 | { 0, 1, 5, 4 }, | ||
55 | { 2, 3, 7, 6 }, | ||
56 | { 1, 2, 6, 5 }, | ||
57 | { 0, 4, 7, 3 }}; | ||
58 | gint32 i, j; | ||
59 | |||
60 | object = g_new0(G3DObject, 1); | ||
61 | |||
62 | object->vertex_count = 8; | ||
63 | object->vertex_data = g3d_vector_new(3, object->vertex_count); | ||
64 | |||
65 | object->vertex_data[0 * 3 + 0] = -(width / 2); | ||
66 | object->vertex_data[0 * 3 + 1] = -(height / 2); | ||
67 | object->vertex_data[0 * 3 + 2] = -(depth / 2); | ||
68 | |||
69 | object->vertex_data[1 * 3 + 0] = -(width / 2); | ||
70 | object->vertex_data[1 * 3 + 1] = -(height / 2); | ||
71 | object->vertex_data[1 * 3 + 2] = (depth / 2); | ||
72 | |||
73 | object->vertex_data[2 * 3 + 0] = (width / 2); | ||
74 | object->vertex_data[2 * 3 + 1] = -(height / 2); | ||
75 | object->vertex_data[2 * 3 + 2] = (depth / 2); | ||
76 | |||
77 | object->vertex_data[3 * 3 + 0] = (width / 2); | ||
78 | object->vertex_data[3 * 3 + 1] = -(height / 2); | ||
79 | object->vertex_data[3 * 3 + 2] = -(depth / 2); | ||
80 | |||
81 | object->vertex_data[4 * 3 + 0] = -(width / 2); | ||
82 | object->vertex_data[4 * 3 + 1] = (height / 2); | ||
83 | object->vertex_data[4 * 3 + 2] = -(depth / 2); | ||
84 | |||
85 | object->vertex_data[5 * 3 + 0] = -(width / 2); | ||
86 | object->vertex_data[5 * 3 + 1] = (height / 2); | ||
87 | object->vertex_data[5 * 3 + 2] = (depth / 2); | ||
88 | |||
89 | object->vertex_data[6 * 3 + 0] = (width / 2); | ||
90 | object->vertex_data[6 * 3 + 1] = (height / 2); | ||
91 | object->vertex_data[6 * 3 + 2] = (depth / 2); | ||
92 | |||
93 | object->vertex_data[7 * 3 + 0] = (width / 2); | ||
94 | object->vertex_data[7 * 3 + 1] = (height / 2); | ||
95 | object->vertex_data[7 * 3 + 2] = -(depth / 2); | ||
96 | |||
97 | for(i = 0; i < 6; i ++) { | ||
98 | face = g_new0(G3DFace, 1); | ||
99 | face->vertex_count = 4; | ||
100 | face->vertex_indices = g_new0(guint32, 4); | ||
101 | face->normals = g3d_vector_new(3, 4); | ||
102 | face->tex_vertex_count = 4; | ||
103 | face->tex_vertex_data = g3d_vector_new(2, 4); | ||
104 | for(j = 0; j < 4; j ++) { | ||
105 | face->vertex_indices[j] = faces[i][j]; | ||
106 | } | ||
107 | |||
108 | /* add normals */ | ||
109 | g3d_face_get_normal(face, object, &nx, &ny, &nz); | ||
110 | for(j = 0; j < 4; j ++) { | ||
111 | face->normals[j * 3 + 0] = nx; | ||
112 | face->normals[j * 3 + 1] = ny; | ||
113 | face->normals[j * 3 + 2] = nz; | ||
114 | } | ||
115 | |||
116 | face->flags |= G3D_FLAG_FAC_NORMALS; | ||
117 | |||
118 | /* add default texture coordinates */ | ||
119 | face->tex_vertex_data[0 * 2 + 0] = 0; | ||
120 | face->tex_vertex_data[0 * 2 + 1] = 0; | ||
121 | face->tex_vertex_data[1 * 2 + 0] = 1; | ||
122 | face->tex_vertex_data[1 * 2 + 1] = 0; | ||
123 | face->tex_vertex_data[2 * 2 + 0] = 1; | ||
124 | face->tex_vertex_data[2 * 2 + 1] = 1; | ||
125 | face->tex_vertex_data[3 * 2 + 0] = 0; | ||
126 | face->tex_vertex_data[3 * 2 + 1] = 1; | ||
127 | |||
128 | face->material = material; | ||
129 | object->faces = g_slist_append(object->faces, face); | ||
130 | } | ||
131 | |||
132 | return object; | ||
133 | } | ||
134 | |||
135 | EAPI | ||
136 | G3DObject *g3d_primitive_cylinder(G3DFloat radius, G3DFloat height, | ||
137 | guint32 sides, gboolean top, gboolean bottom, G3DMaterial *material) | ||
138 | { | ||
139 | G3DObject *object; | ||
140 | G3DFace *face; | ||
141 | guint32 i; | ||
142 | |||
143 | if(sides < 3) | ||
144 | return NULL; | ||
145 | |||
146 | object = g_new0(G3DObject, 1); | ||
147 | |||
148 | /* vertices */ | ||
149 | object->vertex_count = sides * 2 + 2; | ||
150 | object->vertex_data = g3d_vector_new(3, object->vertex_count); | ||
151 | |||
152 | /* 2 rings */ | ||
153 | for(i = 0; i < sides; i ++) | ||
154 | { | ||
155 | object->vertex_data[i * 3 + 0] = | ||
156 | object->vertex_data[(sides + i) * 3 + 0] = | ||
157 | radius * cos(M_PI * 2 * i / sides); | ||
158 | object->vertex_data[i * 3 + 1] = | ||
159 | object->vertex_data[(sides + i) * 3 + 1] = | ||
160 | radius * sin(M_PI * 2 * i / sides); | ||
161 | |||
162 | object->vertex_data[i * 3 + 2] = 0.0; | ||
163 | object->vertex_data[(sides + i) * 3 + 2] = height; | ||
164 | } | ||
165 | |||
166 | /* center top & bottom */ | ||
167 | object->vertex_data[sides * 2 * 3 + 0] = 0.0; | ||
168 | object->vertex_data[sides * 2 * 3 + 1] = 0.0; | ||
169 | object->vertex_data[sides * 2 * 3 + 2] = 0.0; | ||
170 | |||
171 | object->vertex_data[sides * 2 * 3 + 3] = 0.0; | ||
172 | object->vertex_data[sides * 2 * 3 + 4] = 0.0; | ||
173 | object->vertex_data[sides * 2 * 3 + 5] = height; | ||
174 | |||
175 | /* ring faces */ | ||
176 | for(i = 0; i < sides; i ++) | ||
177 | { | ||
178 | face = g_new0(G3DFace, 1); | ||
179 | face->material = material; | ||
180 | face->vertex_count = 4; | ||
181 | face->vertex_indices = g_new0(guint32, 4); | ||
182 | |||
183 | face->vertex_indices[0] = i; | ||
184 | face->vertex_indices[1] = i + sides; | ||
185 | |||
186 | if(i == (sides - 1)) | ||
187 | { | ||
188 | face->vertex_indices[2] = sides; | ||
189 | face->vertex_indices[3] = 0; | ||
190 | } | ||
191 | else | ||
192 | { | ||
193 | face->vertex_indices[2] = i + sides + 1; | ||
194 | face->vertex_indices[3] = i + 1; | ||
195 | } | ||
196 | |||
197 | /* normals */ | ||
198 | face->flags |= G3D_FLAG_FAC_NORMALS; | ||
199 | face->normals = g3d_vector_new(3, 4); | ||
200 | |||
201 | face->normals[0 * 3 + 0] = | ||
202 | face->normals[1 * 3 + 0] = | ||
203 | object->vertex_data[i * 3 + 0]; | ||
204 | face->normals[0 * 3 + 1] = | ||
205 | face->normals[1 * 3 + 1] = | ||
206 | object->vertex_data[i * 3 + 1]; | ||
207 | face->normals[0 * 3 + 2] = 0.0; | ||
208 | face->normals[1 * 3 + 2] = 0.0; | ||
209 | |||
210 | g3d_vector_unify( | ||
211 | &(face->normals[0 * 3 + 0]), | ||
212 | &(face->normals[0 * 3 + 1]), | ||
213 | &(face->normals[0 * 3 + 2])); | ||
214 | g3d_vector_unify( | ||
215 | &(face->normals[1 * 3 + 0]), | ||
216 | &(face->normals[1 * 3 + 1]), | ||
217 | &(face->normals[1 * 3 + 2])); | ||
218 | |||
219 | face->normals[2 * 3 + 0] = | ||
220 | face->normals[3 * 3 + 0] = | ||
221 | object->vertex_data[face->vertex_indices[2] * 3 + 0]; | ||
222 | face->normals[2 * 3 + 1] = | ||
223 | face->normals[3 * 3 + 1] = | ||
224 | object->vertex_data[face->vertex_indices[2] * 3 + 1]; | ||
225 | face->normals[2 * 3 + 2] = 0.0; | ||
226 | face->normals[3 * 3 + 2] = 0.0; | ||
227 | |||
228 | g3d_vector_unify( | ||
229 | &(face->normals[2 * 3 + 0]), | ||
230 | &(face->normals[2 * 3 + 1]), | ||
231 | &(face->normals[2 * 3 + 2])); | ||
232 | g3d_vector_unify( | ||
233 | &(face->normals[3 * 3 + 0]), | ||
234 | &(face->normals[3 * 3 + 1]), | ||
235 | &(face->normals[3 * 3 + 2])); | ||
236 | |||
237 | object->faces = g_slist_append(object->faces, face); | ||
238 | } | ||
239 | |||
240 | if(top) | ||
241 | { | ||
242 | for(i = 0; i < sides; i ++) | ||
243 | { | ||
244 | face = g_new0(G3DFace, 1); | ||
245 | face->material = material; | ||
246 | face->vertex_count = 3; | ||
247 | face->vertex_indices = g_new0(guint32, 3); | ||
248 | |||
249 | face->vertex_indices[0] = sides + i; | ||
250 | face->vertex_indices[1] = sides * 2 + 1; /* top center */ | ||
251 | if(i == (sides - 1)) | ||
252 | face->vertex_indices[2] = sides; | ||
253 | else | ||
254 | face->vertex_indices[2] = sides + i + 1; | ||
255 | |||
256 | object->faces = g_slist_append(object->faces, face); | ||
257 | } | ||
258 | } | ||
259 | |||
260 | if(bottom) | ||
261 | { | ||
262 | for(i = 0; i < sides; i ++) | ||
263 | { | ||
264 | face = g_new0(G3DFace, 1); | ||
265 | face->material = material; | ||
266 | face->vertex_count = 3; | ||
267 | face->vertex_indices = g_new0(guint32, 3); | ||
268 | |||
269 | face->vertex_indices[0] = i; | ||
270 | face->vertex_indices[1] = sides * 2; /* bottom center */ | ||
271 | if(i == (sides - 1)) | ||
272 | face->vertex_indices[2] = 0; | ||
273 | else | ||
274 | face->vertex_indices[2] = i + 1; | ||
275 | |||
276 | object->faces = g_slist_append(object->faces, face); | ||
277 | } | ||
278 | } | ||
279 | |||
280 | return object; | ||
281 | } | ||
282 | |||
283 | EAPI | ||
284 | G3DObject *g3d_primitive_tube(G3DFloat r_in, G3DFloat r_out, G3DFloat height, | ||
285 | guint32 sides, gboolean top, gboolean bottom, G3DMaterial *material) | ||
286 | { | ||
287 | G3DObject *object; | ||
288 | G3DFace *face; | ||
289 | guint32 i, j; | ||
290 | |||
291 | if(sides < 3) | ||
292 | return NULL; | ||
293 | |||
294 | object = g_new0(G3DObject, 1); | ||
295 | |||
296 | /* vertices */ | ||
297 | object->vertex_count = sides * 4; | ||
298 | object->vertex_data = g3d_vector_new(3, object->vertex_count); | ||
299 | |||
300 | /* | ||
301 | * outer lower 0 | ||
302 | * outer upper sides | ||
303 | * inner lower sides * 2 | ||
304 | * inner upper sides * 3 | ||
305 | */ | ||
306 | |||
307 | /* 4 rings */ | ||
308 | for(i = 0; i < sides; i ++) | ||
309 | { | ||
310 | /* outer rings */ | ||
311 | object->vertex_data[i * 3 + 0] = | ||
312 | object->vertex_data[(sides + i) * 3 + 0] = | ||
313 | r_out * cos(M_PI * 2 * i / sides); | ||
314 | object->vertex_data[i * 3 + 1] = | ||
315 | object->vertex_data[(sides + i) * 3 + 1] = | ||
316 | r_out * sin(M_PI * 2 * i / sides); | ||
317 | |||
318 | object->vertex_data[i * 3 + 2] = 0.0; | ||
319 | object->vertex_data[(sides + i) * 3 + 2] = height; | ||
320 | |||
321 | /* inner rings */ | ||
322 | object->vertex_data[(sides * 2 + i) * 3 + 0] = | ||
323 | object->vertex_data[(sides * 3 + i) * 3 + 0] = | ||
324 | r_in * cos(M_PI * 2 * i / sides); | ||
325 | object->vertex_data[(sides * 2 + i) * 3 + 1] = | ||
326 | object->vertex_data[(sides * 3 + i) * 3 + 1] = | ||
327 | r_in * sin(M_PI * 2 * i / sides); | ||
328 | |||
329 | object->vertex_data[(sides * 2 + i) * 3 + 2] = 0.0; | ||
330 | object->vertex_data[(sides * 3 + i) * 3 + 2] = height; | ||
331 | } | ||
332 | |||
333 | /* ring faces */ | ||
334 | for(i = 0; i < sides; i ++) | ||
335 | { | ||
336 | /* outer and inner faces */ | ||
337 | for(j = 0; j < 2; j ++) | ||
338 | { | ||
339 | face = g_new0(G3DFace, 1); | ||
340 | face->material = material; | ||
341 | face->vertex_count = 4; | ||
342 | face->vertex_indices = g_new0(guint32, 4); | ||
343 | |||
344 | face->vertex_indices[0] = i + sides * (j * 2 + 0); | ||
345 | face->vertex_indices[1] = i + sides * (j * 2 + 1); | ||
346 | |||
347 | if(i == (sides - 1)) | ||
348 | { | ||
349 | face->vertex_indices[2] = sides * (j * 2 + 1); | ||
350 | face->vertex_indices[3] = sides * (j * 2 + 0); | ||
351 | } | ||
352 | else | ||
353 | { | ||
354 | face->vertex_indices[2] = i + sides * (j * 2 + 1) + 1; | ||
355 | face->vertex_indices[3] = i + sides * (j * 2 + 0) + 1; | ||
356 | } | ||
357 | |||
358 | /* normals */ | ||
359 | face->flags |= G3D_FLAG_FAC_NORMALS; | ||
360 | face->normals = g3d_vector_new(3, 4); | ||
361 | |||
362 | face->normals[0 * 3 + 0] = | ||
363 | face->normals[1 * 3 + 0] = | ||
364 | object->vertex_data[face->vertex_indices[0] * 3 + 0] * | ||
365 | (j ? -1 : 1); | ||
366 | face->normals[0 * 3 + 1] = | ||
367 | face->normals[1 * 3 + 1] = | ||
368 | object->vertex_data[face->vertex_indices[0] * 3 + 1] * | ||
369 | (j ? -1 : 1); | ||
370 | face->normals[0 * 3 + 2] = 0.0; | ||
371 | face->normals[1 * 3 + 2] = 0.0; | ||
372 | |||
373 | g3d_vector_unify( | ||
374 | &(face->normals[0 * 3 + 0]), | ||
375 | &(face->normals[0 * 3 + 1]), | ||
376 | &(face->normals[0 * 3 + 2])); | ||
377 | g3d_vector_unify( | ||
378 | &(face->normals[1 * 3 + 0]), | ||
379 | &(face->normals[1 * 3 + 1]), | ||
380 | &(face->normals[1 * 3 + 2])); | ||
381 | |||
382 | face->normals[2 * 3 + 0] = | ||
383 | face->normals[3 * 3 + 0] = | ||
384 | object->vertex_data[face->vertex_indices[2] * 3 + 0] * | ||
385 | (j ? -1 : 1); | ||
386 | face->normals[2 * 3 + 1] = | ||
387 | face->normals[3 * 3 + 1] = | ||
388 | object->vertex_data[face->vertex_indices[2] * 3 + 1] * | ||
389 | (j ? -1 : 1); | ||
390 | face->normals[2 * 3 + 2] = 0.0; | ||
391 | face->normals[3 * 3 + 2] = 0.0; | ||
392 | |||
393 | g3d_vector_unify( | ||
394 | &(face->normals[2 * 3 + 0]), | ||
395 | &(face->normals[2 * 3 + 1]), | ||
396 | &(face->normals[2 * 3 + 2])); | ||
397 | g3d_vector_unify( | ||
398 | &(face->normals[3 * 3 + 0]), | ||
399 | &(face->normals[3 * 3 + 1]), | ||
400 | &(face->normals[3 * 3 + 2])); | ||
401 | |||
402 | object->faces = g_slist_append(object->faces, face); | ||
403 | } | ||
404 | } | ||
405 | |||
406 | /* top/bottom faces if requested */ | ||
407 | for(i = 0; i < sides; i ++) | ||
408 | { | ||
409 | for(j = (bottom ? 0 : 1); j < (top ? 2 : 1); j ++) | ||
410 | { | ||
411 | face = g_new0(G3DFace, 1); | ||
412 | face->material = material; | ||
413 | face->vertex_count = 4; | ||
414 | face->vertex_indices = g_new0(guint32, 4); | ||
415 | |||
416 | face->vertex_indices[0] = sides * (2 + j) + i; /* inner */ | ||
417 | face->vertex_indices[1] = sides * (0 + j) + i; /* outer */ | ||
418 | |||
419 | if(i == (sides - 1)) | ||
420 | { | ||
421 | face->vertex_indices[2] = sides * (0 + j); /* outer first */ | ||
422 | face->vertex_indices[3] = sides * (2 + j); /* inner first */ | ||
423 | } | ||
424 | else | ||
425 | { | ||
426 | face->vertex_indices[2] = sides * (0 + j) + i + 1; | ||
427 | face->vertex_indices[3] = sides * (2 + j) + i + 1; | ||
428 | } | ||
429 | |||
430 | object->faces = g_slist_append(object->faces, face); | ||
431 | } | ||
432 | } | ||
433 | |||
434 | return object; | ||
435 | } | ||
436 | |||
437 | EAPI | ||
438 | G3DObject *g3d_primitive_sphere(G3DFloat radius, guint32 vseg, guint32 hseg, | ||
439 | G3DMaterial *material) | ||
440 | { | ||
441 | G3DObject *object; | ||
442 | G3DFace *face; | ||
443 | GSList *flist; | ||
444 | gint32 sh, sv, i; | ||
445 | gdouble x, y, z, u; | ||
446 | |||
447 | g_return_val_if_fail(vseg >= 2, NULL); | ||
448 | g_return_val_if_fail(hseg >= 3, NULL); | ||
449 | |||
450 | object = g_new0(G3DObject, 1); | ||
451 | object->vertex_count = (vseg - 1) * hseg + 2; | ||
452 | object->vertex_data = g3d_vector_new(3, object->vertex_count); | ||
453 | |||
454 | for(sv = 1; sv < vseg; sv ++) | ||
455 | { | ||
456 | y = radius * cos(M_PI * sv / vseg); | ||
457 | u = radius * sin(M_PI * sv / vseg); | ||
458 | for(sh = 0; sh < hseg; sh ++) | ||
459 | { | ||
460 | x = radius * cos(M_PI * 2 * sh / hseg) * u; | ||
461 | z = radius * sin(M_PI * 2 * sh / hseg) * u; | ||
462 | |||
463 | object->vertex_data[((sv - 1) * hseg + sh) * 3 + 0] = x; | ||
464 | object->vertex_data[((sv - 1) * hseg + sh) * 3 + 1] = y; | ||
465 | object->vertex_data[((sv - 1) * hseg + sh) * 3 + 2] = z; | ||
466 | |||
467 | if(sv > 1) | ||
468 | { | ||
469 | /* first triangle */ | ||
470 | face = g_new0(G3DFace, 1); | ||
471 | face->material = material; | ||
472 | face->vertex_count = 3; | ||
473 | face->vertex_indices = g_new0(guint32, 3); | ||
474 | face->vertex_indices[0] = (sv - 1) * hseg + sh; | ||
475 | face->vertex_indices[1] = (sh == (hseg - 1)) ? | ||
476 | (sv - 1) * hseg : | ||
477 | (sv - 1) * hseg + sh + 1; | ||
478 | face->vertex_indices[2] = (sv - 2) * hseg + sh; | ||
479 | object->faces = g_slist_append(object->faces, face); | ||
480 | |||
481 | /* second triangle */ | ||
482 | face = g_new0(G3DFace, 1); | ||
483 | face->material = material; | ||
484 | face->vertex_count = 3; | ||
485 | face->vertex_indices = g_new0(guint32, 3); | ||
486 | face->vertex_indices[0] = (sv - 2) * hseg + sh; | ||
487 | face->vertex_indices[1] = (sh == (hseg - 1)) ? | ||
488 | (sv - 1) * hseg : | ||
489 | (sv - 1) * hseg + sh + 1; | ||
490 | face->vertex_indices[2] = (sh == (hseg - 1)) ? | ||
491 | (sv - 2) * hseg : | ||
492 | (sv - 2) * hseg + sh + 1; | ||
493 | object->faces = g_slist_append(object->faces, face); | ||
494 | } /* sv > 1 */ | ||
495 | } /* hseg */ | ||
496 | } /* vseg */ | ||
497 | |||
498 | object->vertex_data[(object->vertex_count - 1) * 3 + 0] = 0; | ||
499 | object->vertex_data[(object->vertex_count - 1) * 3 + 1] = radius; | ||
500 | object->vertex_data[(object->vertex_count - 1) * 3 + 2] = 0; | ||
501 | |||
502 | object->vertex_data[(object->vertex_count - 2) * 3 + 0] = 0; | ||
503 | object->vertex_data[(object->vertex_count - 2) * 3 + 1] = -radius; | ||
504 | object->vertex_data[(object->vertex_count - 2) * 3 + 2] = 0; | ||
505 | |||
506 | for(sh = 0; sh < hseg; sh ++) | ||
507 | { | ||
508 | /* top */ | ||
509 | face = g_new0(G3DFace, 1); | ||
510 | face->material = material; | ||
511 | face->vertex_count = 3; | ||
512 | face->vertex_indices = g_new0(guint32, 3); | ||
513 | |||
514 | face->vertex_indices[0] = object->vertex_count - 1; | ||
515 | face->vertex_indices[1] = sh; | ||
516 | face->vertex_indices[2] = (sh == (hseg - 1)) ? 0 : sh + 1; | ||
517 | |||
518 | object->faces = g_slist_append(object->faces, face); | ||
519 | |||
520 | /* bottom */ | ||
521 | face = g_new0(G3DFace, 1); | ||
522 | face->material = material; | ||
523 | face->vertex_count = 3; | ||
524 | face->vertex_indices = g_new0(guint32, 3); | ||
525 | |||
526 | face->vertex_indices[2] = object->vertex_count - 2; | ||
527 | face->vertex_indices[1] = (vseg - 2) * hseg + sh; | ||
528 | face->vertex_indices[0] = (sh == (hseg - 1)) ? | ||
529 | (vseg - 2) * hseg : | ||
530 | (vseg - 2) * hseg + sh + 1; | ||
531 | |||
532 | object->faces = g_slist_append(object->faces, face); | ||
533 | } | ||
534 | |||
535 | /* generate normals */ | ||
536 | flist = object->faces; | ||
537 | while(flist) | ||
538 | { | ||
539 | face = (G3DFace *)flist->data; | ||
540 | face->flags |= G3D_FLAG_FAC_NORMALS; | ||
541 | face->normals = g3d_vector_new(3, face->vertex_count); | ||
542 | for(i = 0; i < face->vertex_count; i ++) | ||
543 | { | ||
544 | face->normals[i * 3 + 0] = | ||
545 | - object->vertex_data[face->vertex_indices[i] * 3 + 0]; | ||
546 | face->normals[i * 3 + 1] = | ||
547 | - object->vertex_data[face->vertex_indices[i] * 3 + 1]; | ||
548 | face->normals[i * 3 + 2] = | ||
549 | - object->vertex_data[face->vertex_indices[i] * 3 + 2]; | ||
550 | |||
551 | g3d_vector_unify( | ||
552 | &(face->normals[i * 3 + 0]), | ||
553 | &(face->normals[i * 3 + 1]), | ||
554 | &(face->normals[i * 3 + 2])); | ||
555 | } | ||
556 | |||
557 | flist = flist->next; | ||
558 | } | ||
559 | |||
560 | return object; | ||
561 | } | ||
562 | |||
563 | /* vdata: 2-dimensional coordinates: vcnt * 2 * gdouble */ | ||
564 | EAPI | ||
565 | G3DObject *g3d_primitive_box_strip_2d(guint32 vcnt, gdouble *vdata, | ||
566 | gdouble height, gdouble width, G3DMaterial *material) | ||
567 | { | ||
568 | G3DObject *object; | ||
569 | G3DFace *face; | ||
570 | gint32 i, index; | ||
571 | G3DVector *normals, normal[3]; | ||
572 | G3DFloat r; | ||
573 | |||
574 | /* create object & helpers */ | ||
575 | object = g_new0(G3DObject, 1); | ||
576 | normals = g3d_vector_new(3, vcnt); | ||
577 | object->vertex_count = vcnt * 4; | ||
578 | object->vertex_data = g3d_vector_new(3, object->vertex_count); | ||
579 | |||
580 | /* generate normals */ | ||
581 | for(i = 0; i < vcnt; i ++) { | ||
582 | /* normal data */ | ||
583 | g3d_vector_normal( | ||
584 | /* vector 1 */ | ||
585 | vdata[(i + 1) * 2 + 0] - vdata[i * 2 + 0], | ||
586 | 0.0, | ||
587 | vdata[(i + 1) * 2 + 1] - vdata[i * 2 + 1], | ||
588 | /* vector 2 */ | ||
589 | 0.0, 1.0, 0.0, | ||
590 | /* resulting vector */ | ||
591 | &(normals[i * 3 + 0]), | ||
592 | &(normals[i * 3 + 1]), | ||
593 | &(normals[i * 3 + 2])); | ||
594 | g3d_vector_unify( | ||
595 | &(normals[i * 3 + 0]), | ||
596 | &(normals[i * 3 + 1]), | ||
597 | &(normals[i * 3 + 2])); | ||
598 | } | ||
599 | |||
600 | /* radius */ | ||
601 | r = width / 2.0; | ||
602 | |||
603 | /* generate vertices */ | ||
604 | for(i = 0; i < vcnt; i ++) { | ||
605 | /* average normal for vertex */ | ||
606 | if(i == 0) { | ||
607 | normal[0] = normals[i * 3 + 0]; | ||
608 | normal[1] = normals[i * 3 + 1]; | ||
609 | normal[2] = normals[i * 3 + 2]; | ||
610 | } else { | ||
611 | normal[0] = (normals[i * 3 + 0] + normals[(i - 1) * 3 + 0]) / 2.0; | ||
612 | normal[1] = (normals[i * 3 + 1] + normals[(i - 1) * 3 + 1]) / 2.0; | ||
613 | normal[2] = (normals[i * 3 + 2] + normals[(i - 1) * 3 + 2]) / 2.0; | ||
614 | g3d_vector_unify(&(normals[0]), &(normals[1]), &(normals[2])); | ||
615 | } | ||
616 | |||
617 | /* vertex data */ | ||
618 | /* v0 */ | ||
619 | index = i * 4; | ||
620 | object->vertex_data[index * 3 + 0] = vdata[i * 2 + 0] + normals[0] * r; | ||
621 | object->vertex_data[index * 3 + 1] = height; | ||
622 | object->vertex_data[index * 3 + 2] = vdata[i * 2 + 1] + normals[2] * r; | ||
623 | /* v1 */ | ||
624 | index ++; | ||
625 | object->vertex_data[index * 3 + 0] = vdata[i * 2 + 0] - normals[0] * r; | ||
626 | object->vertex_data[index * 3 + 1] = height; | ||
627 | object->vertex_data[index * 3 + 2] = vdata[i * 2 + 1] - normals[2] * r; | ||
628 | /* v2 */ | ||
629 | index ++; | ||
630 | object->vertex_data[index * 3 + 0] = vdata[i * 2 + 0] - normals[0] * r; | ||
631 | object->vertex_data[index * 3 + 1] = 0.0; | ||
632 | object->vertex_data[index * 3 + 2] = vdata[i * 2 + 1] - normals[2] * r; | ||
633 | /* v3 */ | ||
634 | index ++; | ||
635 | object->vertex_data[index * 3 + 0] = vdata[i * 2 + 0] + normals[0] * r; | ||
636 | object->vertex_data[index * 3 + 1] = 0.0; | ||
637 | object->vertex_data[index * 3 + 2] = vdata[i * 2 + 1] + normals[2] * r; | ||
638 | |||
639 | if(i > 0) { | ||
640 | /* generate faces */ | ||
641 | /* upper face */ | ||
642 | face = g_new0(G3DFace, 1); | ||
643 | face->material = material; | ||
644 | face->vertex_count = 4; | ||
645 | face->vertex_indices = g_new0(guint32, 4); | ||
646 | face->vertex_indices[0] = (i * 4) + 0; | ||
647 | face->vertex_indices[1] = (i * 4) + 1; | ||
648 | face->vertex_indices[2] = (i * 4) - 3; | ||
649 | face->vertex_indices[3] = (i * 4) - 4; | ||
650 | object->faces = g_slist_prepend(object->faces, face); | ||
651 | /* lower face */ | ||
652 | face = g_new0(G3DFace, 1); | ||
653 | face->material = material; | ||
654 | face->vertex_count = 4; | ||
655 | face->vertex_indices = g_new0(guint32, 4); | ||
656 | face->vertex_indices[0] = (i * 4) + 3; | ||
657 | face->vertex_indices[1] = (i * 4) - 1; | ||
658 | face->vertex_indices[2] = (i * 4) - 2; | ||
659 | face->vertex_indices[3] = (i * 4) + 2; | ||
660 | object->faces = g_slist_prepend(object->faces, face); | ||
661 | /* "front" face */ | ||
662 | face = g_new0(G3DFace, 1); | ||
663 | face->material = material; | ||
664 | face->vertex_count = 4; | ||
665 | face->vertex_indices = g_new0(guint32, 4); | ||
666 | face->vertex_indices[0] = (i * 4) + 1; | ||
667 | face->vertex_indices[1] = (i * 4) + 2; | ||
668 | face->vertex_indices[2] = (i * 4) - 2; | ||
669 | face->vertex_indices[3] = (i * 4) - 3; | ||
670 | object->faces = g_slist_prepend(object->faces, face); | ||
671 | /* "back" face */ | ||
672 | face = g_new0(G3DFace, 1); | ||
673 | face->material = material; | ||
674 | face->vertex_count = 4; | ||
675 | face->vertex_indices = g_new0(guint32, 4); | ||
676 | face->vertex_indices[0] = (i * 4) - 4; | ||
677 | face->vertex_indices[1] = (i * 4) - 1; | ||
678 | face->vertex_indices[2] = (i * 4) + 3; | ||
679 | face->vertex_indices[3] = (i * 4) + 0; | ||
680 | object->faces = g_slist_prepend(object->faces, face); | ||
681 | } | ||
682 | } | ||
683 | /* clean up */ | ||
684 | g_free(normals); | ||
685 | |||
686 | return object; | ||
687 | } | ||
688 | |||
689 | EAPI | ||
690 | G3DObject *g3d_primitive_mesh(guint32 m, guint32 n, gboolean wrap_m, | ||
691 | gboolean wrap_n, G3DMaterial *material) | ||
692 | { | ||
693 | G3DObject *object; | ||
694 | G3DFace *face; | ||
695 | gint32 x, y; | ||
696 | |||
697 | object = g_new0(G3DObject, 1); | ||
698 | object->vertex_count = m * n; | ||
699 | object->vertex_data = g3d_vector_new(3, object->vertex_count); | ||
700 | |||
701 | for(y = 0; y < (n - 1); y ++) { | ||
702 | for(x = 0; x < (m - 1); x ++) { | ||
703 | face = g3d_face_new_tri(material, | ||
704 | y * m + x, y * m + x + 1, (y + 1) * m + x); | ||
705 | object->faces = g_slist_prepend(object->faces, face); | ||
706 | |||
707 | face = g3d_face_new_tri(material, | ||
708 | (y + 1) * m + x, y * m + x + 1, (y + 1) * m + x + 1); | ||
709 | object->faces = g_slist_prepend(object->faces, face); | ||
710 | } | ||
711 | if(wrap_n) { | ||
712 | face = g3d_face_new_tri(material, | ||
713 | (y + 1) * m - 1, y * m, (y + 2) * m - 1); | ||
714 | object->faces = g_slist_prepend(object->faces, face); | ||
715 | |||
716 | face = g3d_face_new_tri(material, | ||
717 | (y + 2) * m - 1, y * m, (y + 1) * m); | ||
718 | object->faces = g_slist_prepend(object->faces, face); | ||
719 | } | ||
720 | } | ||
721 | if(wrap_m) { | ||
722 | for(x = 0; x < (m - 1); x ++) { | ||
723 | face = g3d_face_new_tri(material, | ||
724 | (n - 1) * m + x, (n - 1) * m + x + 1, x); | ||
725 | object->faces = g_slist_prepend(object->faces, face); | ||
726 | |||
727 | face = g3d_face_new_tri(material, | ||
728 | x, (n - 1) * m + x + 1, x + 1); | ||
729 | object->faces = g_slist_prepend(object->faces, face); | ||
730 | } | ||
731 | if(wrap_n) { | ||
732 | face = g3d_face_new_tri(material, | ||
733 | n * m - 1, (n - 1) * m, m - 1); | ||
734 | object->faces = g_slist_prepend(object->faces, face); | ||
735 | |||
736 | face = g3d_face_new_tri(material, | ||
737 | m - 1, (n - 1) * m, 0); | ||
738 | object->faces = g_slist_prepend(object->faces, face); | ||
739 | } | ||
740 | } | ||
741 | return object; | ||
742 | } | ||
743 | |||