diff options
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.c | 400 |
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 | |||
33 | EAPI | ||
34 | void 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 | |||
75 | EAPI | ||
76 | gdouble 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 | |||
93 | EAPI | ||
94 | gboolean 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 | |||
119 | EAPI | ||
120 | gboolean 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 | |||
154 | EAPI | ||
155 | gboolean 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 | |||
181 | EAPI | ||
182 | G3DObject *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 | |||
242 | EAPI | ||
243 | gboolean 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 | |||
285 | EAPI | ||
286 | gboolean g3d_object_smooth(G3DObject *object) | ||
287 | { | ||
288 | /* FIXME: implement */ | ||
289 | return FALSE; | ||
290 | } | ||
291 | |||
292 | EAPI | ||
293 | gboolean 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 | |||