aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/src/others/mimesh/libg3d-0.0.8/src/object.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/others/mimesh/libg3d-0.0.8/src/object.c')
-rw-r--r--src/others/mimesh/libg3d-0.0.8/src/object.c400
1 files changed, 400 insertions, 0 deletions
diff --git a/src/others/mimesh/libg3d-0.0.8/src/object.c b/src/others/mimesh/libg3d-0.0.8/src/object.c
new file mode 100644
index 0000000..7fc3df1
--- /dev/null
+++ b/src/others/mimesh/libg3d-0.0.8/src/object.c
@@ -0,0 +1,400 @@
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 <string.h>
24#include <math.h>
25
26#include <g3d/types.h>
27#include <g3d/vector.h>
28#include <g3d/matrix.h>
29#include <g3d/face.h>
30#include <g3d/texture.h>
31#include <g3d/object.h>
32
33EAPI
34void g3d_object_free(G3DObject *object)
35{
36 GSList *slist, *snext;
37 G3DMaterial *mat;
38 G3DFace *face;
39
40 if(object->name != NULL)
41 g_free(object->name);
42
43 /* materials */
44 slist = object->materials;
45 while(slist != NULL)
46 {
47 mat = (G3DMaterial*)slist->data;
48 snext = slist->next;
49 g_slist_free_1(slist);
50 slist = snext;
51 }
52
53 /* faces */
54 slist = object->faces;
55 while(slist != NULL)
56 {
57 face = (G3DFace*)slist->data;
58 g3d_face_free(face);
59 snext = slist->next;
60 g_slist_free_1(slist);
61 slist = snext;
62 }
63
64 /* vertices */
65 if(object->vertex_data != NULL) g_free(object->vertex_data);
66 if(object->tex_vertex_data != NULL) g_free(object->tex_vertex_data);
67 if(object->_normals != NULL) g_free(object->_normals);
68 if(object->_indices != NULL) g_free(object->_indices);
69 if(object->_materials != NULL) g_free(object->_materials);
70 if(object->_flags != NULL) g_free(object->_flags);
71
72 g_free(object);
73}
74
75EAPI
76gdouble g3d_object_radius(G3DObject *object)
77{
78 guint32 i;
79 gdouble max_radius = 0.0, r;
80 G3DVector *v;
81
82 for(i = 0; i < object->vertex_count; i ++)
83 {
84 v = &object->vertex_data[i * 3];
85 r = v[0] * v[0] + v[1] * v[1] + v[2] * v[2];
86 if(r > max_radius)
87 max_radius = r;
88 }
89
90 return sqrt(max_radius);
91}
92
93EAPI
94gboolean g3d_object_scale(G3DObject *object, G3DFloat scale)
95{
96 guint32 i;
97 G3DMatrix *matrix;
98
99 for(i = 0; i < object->vertex_count; i ++)
100 {
101 object->vertex_data[i * 3 + 0] *= scale;
102 object->vertex_data[i * 3 + 1] *= scale;
103 object->vertex_data[i * 3 + 2] *= scale;
104 }
105
106 if(object->transformation)
107 {
108 matrix = object->transformation->matrix;
109 g3d_matrix_translate(
110 - (matrix[12] - (matrix[12] * scale)),
111 - (matrix[13] - (matrix[13] * scale)),
112 - (matrix[14] - (matrix[14] * scale)),
113 matrix);
114 }
115
116 return TRUE;
117}
118
119EAPI
120gboolean g3d_object_transform_normals(G3DObject *object, G3DMatrix *matrix)
121{
122 gint32 i;
123 G3DFace *face;
124 GSList *fitem;
125
126 fitem = object->faces;
127 while(fitem)
128 {
129 face = (G3DFace *)fitem->data;
130
131 if(face->flags & G3D_FLAG_FAC_NORMALS)
132 {
133 for(i = 0; i < face->vertex_count; i ++)
134 {
135 g3d_vector_transform(
136 &(face->normals[i * 3 + 0]),
137 &(face->normals[i * 3 + 1]),
138 &(face->normals[i * 3 + 2]),
139 matrix);
140 g3d_vector_unify(
141 &(face->normals[i * 3 + 0]),
142 &(face->normals[i * 3 + 1]),
143 &(face->normals[i * 3 + 2]));
144 }
145 }
146
147 fitem = fitem->next;
148 }
149 return TRUE;
150}
151
152#define G3D_OBJECT_TRANSFORM_NORMALS 0
153
154EAPI
155gboolean g3d_object_transform(G3DObject *object, G3DMatrix *matrix)
156{
157 guint32 i;
158 GSList *oitem;
159
160 /* transform vertices */
161 for(i = 0; i < object->vertex_count; i ++)
162 {
163 g3d_vector_transform(
164 &(object->vertex_data[i * 3 + 0]),
165 &(object->vertex_data[i * 3 + 1]),
166 &(object->vertex_data[i * 3 + 2]),
167 matrix);
168 }
169
170#if G3D_OBJECT_TRANSFORM_NORMALS
171 g3d_object_transform_normals(object, matrix);
172#endif
173
174 /* transform sub-objects */
175 for(oitem = object->objects; oitem != NULL; oitem = oitem->next)
176 g3d_object_transform((G3DObject *)oitem->data, matrix);
177
178 return TRUE;
179}
180
181EAPI
182G3DObject *g3d_object_duplicate(G3DObject *object)
183{
184 G3DObject *new, *sub, *newsub;
185 G3DFace *face, *oface;
186 GSList *litem;
187
188 new = g_new0(G3DObject, 1);
189
190 /* name */
191 if(object->name)
192 new->name = g_strdup(object->name);
193
194 /* vertices */
195 new->vertex_count = object->vertex_count;
196 new->vertex_data = g3d_vector_new(3, new->vertex_count);
197 memcpy(new->vertex_data, object->vertex_data,
198 new->vertex_count * 3 * sizeof(G3DVector));
199
200 /* texture stuff */
201 /* TODO: implement? */
202
203 /* faces */
204 for(litem = object->faces; litem != NULL; litem = litem->next) {
205 oface = litem->data;
206
207 face = g_new0(G3DFace, 1);
208 face->material = oface->material;
209 face->vertex_count = oface->vertex_count;
210 face->vertex_indices = g_new0(guint32, face->vertex_count);
211 memcpy(face->vertex_indices, oface->vertex_indices,
212 face->vertex_count * sizeof(guint32));
213 face->flags = oface->flags;
214 if(face->flags & G3D_FLAG_FAC_NORMALS)
215 {
216 face->normals = g3d_vector_new(3, face->vertex_count);
217 memcpy(face->normals, oface->normals,
218 face->vertex_count * 3 * sizeof(G3DVector));
219 }
220 if(face->flags & G3D_FLAG_FAC_TEXMAP)
221 {
222 face->tex_image = oface->tex_image;
223 face->tex_vertex_count = oface->tex_vertex_count;
224 face->tex_vertex_data = g3d_vector_new(2, face->tex_vertex_count);
225 memcpy(face->tex_vertex_data, oface->tex_vertex_data,
226 face->tex_vertex_count * 2 * sizeof(G3DVector));
227 }
228
229 new->faces = g_slist_prepend(new->faces, face);
230 }
231
232 /* sub-objects */
233 for(litem = object->objects; litem != NULL; litem = litem->next) {
234 sub = litem->data;
235 newsub = g3d_object_duplicate(sub);
236 new->objects = g_slist_append(new->objects, newsub);
237 }
238
239 return new;
240}
241
242EAPI
243gboolean g3d_object_merge(G3DObject *o1, G3DObject *o2)
244{
245 G3DFace *face;
246 GSList *fitem;
247 guint32 i, voff, foff = 0;
248
249 /* copy vertices */
250 voff = o1->vertex_count;
251 o1->vertex_count += o2->vertex_count;
252
253 o1->vertex_data = g_realloc(o1->vertex_data,
254 o1->vertex_count * 3 * sizeof(G3DVector));
255
256 memcpy(o1->vertex_data + voff * 3, o2->vertex_data,
257 o2->vertex_count * 3 * sizeof(G3DVector));
258
259 /* attach faces to first object */
260 fitem = o2->faces;
261 while(fitem)
262 {
263 face = (G3DFace *)fitem->data;
264 foff ++;
265
266 if(face->vertex_count > 100)
267 {
268 g_warning("face->vertex_count > 100: %d (%dth)",
269 face->vertex_count, foff);
270 }
271
272 for(i = 0; i < face->vertex_count; i ++)
273 face->vertex_indices[i] += voff;
274
275 o1->faces = g_slist_prepend(o1->faces, face);
276
277 fitem = fitem->next;
278 }
279
280 /* FIXME: clean up o2 or copy faces */
281
282 return TRUE;
283}
284
285EAPI
286gboolean g3d_object_smooth(G3DObject *object)
287{
288 /* FIXME: implement */
289 return FALSE;
290}
291
292EAPI
293gboolean g3d_object_optimize(G3DObject *object)
294{
295 G3DFace *face;
296 guint32 index = 0, i, j;
297 GSList *fitem;
298 G3DVector nx, ny, nz, su = 1.0, sv = 1.0;
299
300 /* count number of faces (optimized) */
301 object->_num_faces = 0;
302 fitem = object->faces;
303 while(fitem)
304 {
305 face = (G3DFace *)fitem->data;
306 object->_num_faces += face->vertex_count - 2;
307
308 fitem = fitem->next;
309 }
310
311 object->_normals = g3d_vector_new(3, 3 * object->_num_faces);
312 object->_materials = g_new0(G3DMaterial *, object->_num_faces);
313 object->_flags = g_new0(guint32, object->_num_faces);
314 object->_indices = g_new0(guint32, object->_num_faces * 3);
315 object->_tex_images = g_new0(guint32, object->_num_faces);
316 object->_tex_coords = g3d_vector_new(2, object->_num_faces * 3);
317
318 /* copy faces */
319 fitem = object->faces;
320 while(fitem)
321 {
322 face = (G3DFace *)fitem->data;
323
324 /* generate default normal for face */
325 if(!(face->flags & G3D_FLAG_FAC_NORMALS))
326 {
327 if(!g3d_face_get_normal(face, object, &nx, &ny, &nz))
328 {
329 fitem = fitem->next;
330 object->_num_faces -= face->vertex_count - 2;
331 }
332
333 g3d_vector_unify(&nx, &ny, &nz);
334 }
335
336 for(i = 0; i < (face->vertex_count - 2); i ++)
337 {
338 object->_materials[index] = face->material;
339 object->_flags[index] = face->flags;
340
341 if(face->flags & G3D_FLAG_FAC_TEXMAP)
342 {
343#if 0
344 g3d_texture_prepare(face->tex_image);
345#endif
346 object->_tex_images[index] = face->tex_image->tex_id;
347 su = face->tex_image->tex_scale_u;
348 sv = face->tex_image->tex_scale_v;
349 }
350
351 for(j = 0; j < 3; j ++)
352 {
353 /* vertex stuff */
354 if(j == 0)
355 object->_indices[index * 3] = face->vertex_indices[0];
356 else
357 object->_indices[index * 3+j] = face->vertex_indices[i+j];
358
359 /* normal stuff */
360 if(face->flags & G3D_FLAG_FAC_NORMALS)
361 {
362 object->_normals[(index * 3 + j) * 3 + 0] =
363 face->normals[(i + j) * 3 + 0];
364 object->_normals[(index * 3 + j) * 3 + 1] =
365 face->normals[(i + j) * 3 + 1];
366 object->_normals[(index * 3 + j) * 3 + 2] =
367 face->normals[(i + j) * 3 + 2];
368 }
369 else
370 {
371 object->_normals[(index * 3 + j) * 3 + 0] = nx;
372 object->_normals[(index * 3 + j) * 3 + 1] = ny;
373 object->_normals[(index * 3 + j) * 3 + 2] = nz;
374 }
375
376 /* texture stuff */
377 if(face->flags & G3D_FLAG_FAC_TEXMAP)
378 {
379 /* u */
380 object->_tex_coords[(index * 3 + j) * 2 + 0] = su *
381 ((j == 0) ?
382 face->tex_vertex_data[0] :
383 face->tex_vertex_data[(i + j) * 2 + 0]);
384 /* v */
385 object->_tex_coords[(index * 3 + j) * 2 + 1] = sv *
386 ((j == 0) ?
387 face->tex_vertex_data[1] :
388 face->tex_vertex_data[(i + j) * 2 + 1]);
389 }
390 } /* j: 0 < 3 */
391
392 index ++;
393 } /* i: 0 < vertex_count - 2 */
394
395 fitem = fitem->next;
396 } /* while(fitem) */
397
398 return TRUE;
399}
400