diff options
Diffstat (limited to 'src/others/mimesh/libg3d-0.0.8/plugins/import/imp_glb/imp_glb.c')
-rw-r--r-- | src/others/mimesh/libg3d-0.0.8/plugins/import/imp_glb/imp_glb.c | 258 |
1 files changed, 258 insertions, 0 deletions
diff --git a/src/others/mimesh/libg3d-0.0.8/plugins/import/imp_glb/imp_glb.c b/src/others/mimesh/libg3d-0.0.8/plugins/import/imp_glb/imp_glb.c new file mode 100644 index 0000000..d9bea0b --- /dev/null +++ b/src/others/mimesh/libg3d-0.0.8/plugins/import/imp_glb/imp_glb.c | |||
@@ -0,0 +1,258 @@ | |||
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 <stdio.h> | ||
24 | #include <stdlib.h> | ||
25 | #include <string.h> | ||
26 | |||
27 | #include <g3d/types.h> | ||
28 | #include <g3d/stream.h> | ||
29 | #include <g3d/material.h> | ||
30 | #include <g3d/texture.h> | ||
31 | #include <g3d/iff.h> | ||
32 | #include <g3d/vector.h> | ||
33 | |||
34 | static G3DObject *glb_load_object(G3DContext *context, G3DStream *stream, | ||
35 | G3DModel *model); | ||
36 | |||
37 | EAPI | ||
38 | gboolean plugin_load_model_from_stream(G3DContext *context, G3DStream *stream, | ||
39 | G3DModel *model, gpointer user_data) | ||
40 | { | ||
41 | return (glb_load_object(context, stream, model) != NULL); | ||
42 | } | ||
43 | |||
44 | EAPI | ||
45 | gchar *plugin_description(G3DContext *context) | ||
46 | { | ||
47 | return g_strdup("UltimateStunts models."); | ||
48 | } | ||
49 | |||
50 | EAPI | ||
51 | gchar **plugin_extensions(G3DContext *context) | ||
52 | { | ||
53 | return g_strsplit("glb", ":", 0); | ||
54 | } | ||
55 | |||
56 | /*****************************************************************************/ | ||
57 | /* GLB specific */ | ||
58 | |||
59 | static G3DFloat glb_get_float(G3DStream *stream) | ||
60 | { | ||
61 | return 0.001 * ( | ||
62 | (float)((guint32)g3d_stream_read_int32_be(stream)) - (float)(0x7FFFFFFF)); | ||
63 | } | ||
64 | |||
65 | static G3DObject *glb_load_object(G3DContext *context, G3DStream *stream, | ||
66 | G3DModel *model) | ||
67 | { | ||
68 | G3DObject *pobject, *object; | ||
69 | G3DMaterial *material; | ||
70 | G3DFace *face; | ||
71 | guint32 magic, otype, index; | ||
72 | gint32 i, j, msize, namelen, datalen, nvertices, nindices; | ||
73 | gchar *name; | ||
74 | G3DFloat *normals = NULL, *texcoords = NULL; | ||
75 | |||
76 | magic = g3d_stream_read_int32_be(stream); | ||
77 | if(magic != G3D_IFF_MKID('\0', 'G', 'L', 'B')) { | ||
78 | g_warning("%s is not a correct GLB file (wrong magic)\n", | ||
79 | stream->uri); | ||
80 | return NULL; | ||
81 | } | ||
82 | |||
83 | pobject = g_new0(G3DObject, 1); | ||
84 | pobject->name = g_strdup(stream->uri); | ||
85 | model->objects = g_slist_append(model->objects, pobject); | ||
86 | |||
87 | while(!g3d_stream_eof(stream)) { | ||
88 | otype = g3d_stream_read_int32_be(stream); | ||
89 | namelen = g3d_stream_read_int32_be(stream); | ||
90 | |||
91 | if(namelen == 0) | ||
92 | break; | ||
93 | |||
94 | name = g_new0(gchar, namelen + 1); | ||
95 | g3d_stream_read(stream, name, namelen); | ||
96 | #if DEBUG > 0 | ||
97 | printf("GLB: object named '%s'\n", name); | ||
98 | #endif | ||
99 | |||
100 | object = g_new0(G3DObject, 1); | ||
101 | object->name = g_strdup(name); | ||
102 | g_free(name); | ||
103 | pobject->objects = g_slist_append(pobject->objects, object); | ||
104 | |||
105 | /* hide collision planes by default */ | ||
106 | if(strncmp(object->name, "Collision plane", 15) == 0) | ||
107 | object->hide = TRUE; | ||
108 | |||
109 | datalen = g3d_stream_read_int32_be(stream); | ||
110 | |||
111 | if(otype != 0) { | ||
112 | /* skip */ | ||
113 | g3d_stream_skip(stream, datalen); | ||
114 | continue; | ||
115 | } | ||
116 | |||
117 | /* object type 0 */ | ||
118 | msize = g3d_stream_read_int32_be(stream); | ||
119 | nvertices = g3d_stream_read_int32_be(stream); | ||
120 | nindices = g3d_stream_read_int32_be(stream); | ||
121 | |||
122 | #if DEBUG > 0 | ||
123 | printf("GLB: material size: %d bytes, %d vertices, %d indices\n", | ||
124 | msize, nvertices, nindices); | ||
125 | #endif | ||
126 | if(msize > 0) { | ||
127 | /* material */ | ||
128 | material = g3d_material_new(); | ||
129 | material->name = g_strdup("default material"); | ||
130 | object->materials = g_slist_append(object->materials, material); | ||
131 | |||
132 | material->r = (G3DFloat)g3d_stream_read_int8(stream) / 255.0; | ||
133 | material->g = (G3DFloat)g3d_stream_read_int8(stream) / 255.0; | ||
134 | material->b = (G3DFloat)g3d_stream_read_int8(stream) / 255.0; | ||
135 | material->a = (G3DFloat)g3d_stream_read_int8(stream) / 255.0; | ||
136 | |||
137 | if(material->a == 0.0) | ||
138 | material->a = 1.0; | ||
139 | |||
140 | /* replacement color */ | ||
141 | g3d_stream_read_int8(stream); | ||
142 | g3d_stream_read_int8(stream); | ||
143 | g3d_stream_read_int8(stream); | ||
144 | g3d_stream_read_int8(stream); /* unused */ | ||
145 | |||
146 | g3d_stream_read_int8(stream); /* LODs */ | ||
147 | g3d_stream_read_int8(stream); /* reflectance */ | ||
148 | /* emissivity */ | ||
149 | material->shininess = (G3DFloat)g3d_stream_read_int8(stream) / 255.0; | ||
150 | g3d_stream_read_int8(stream); /* static friction */ | ||
151 | g3d_stream_read_int8(stream); /* dynamic friction */ | ||
152 | g3d_stream_read_int8(stream); /* unused */ | ||
153 | g3d_stream_read_int8(stream); /* unused */ | ||
154 | g3d_stream_read_int8(stream); /* unused */ | ||
155 | |||
156 | /* texture name */ | ||
157 | namelen = msize - 16; | ||
158 | if(namelen > 0) { | ||
159 | name = g_new0(gchar, namelen + 1); | ||
160 | g3d_stream_read(stream, name, namelen); | ||
161 | #if DEBUG > 1 | ||
162 | printf("GLB: texture name: %s\n", name); | ||
163 | #endif | ||
164 | |||
165 | /* texture name is something like "0", the real name is in | ||
166 | * "../$carname.conf"; try to load default texture */ | ||
167 | if(name[0] == '0') { | ||
168 | if(g_file_test("textures.jpg", G_FILE_TEST_EXISTS)) { | ||
169 | material->tex_image = g3d_texture_load_cached( | ||
170 | context, model, "textures.jpg"); | ||
171 | if(material->tex_image != NULL) | ||
172 | material->tex_image->tex_id = 1; | ||
173 | } | ||
174 | } | ||
175 | |||
176 | g_free(name); | ||
177 | } | ||
178 | } | ||
179 | |||
180 | /* vertices */ | ||
181 | if(nvertices > 0) { | ||
182 | object->vertex_count = nvertices; | ||
183 | object->vertex_data = g_new0(G3DFloat, nvertices * 3); | ||
184 | normals = g_new0(G3DFloat, nvertices * 3); | ||
185 | texcoords = g_new0(G3DFloat, nvertices * 2); | ||
186 | |||
187 | for(i = 0; i < nvertices; i ++) { | ||
188 | object->vertex_data[i * 3 + 0] = glb_get_float(stream); | ||
189 | object->vertex_data[i * 3 + 1] = glb_get_float(stream); | ||
190 | object->vertex_data[i * 3 + 2] = glb_get_float(stream); | ||
191 | |||
192 | #if DEBUG > 3 | ||
193 | printf("D: %f, %f, %f\n", | ||
194 | object->vertex_data[i * 3 + 0], | ||
195 | object->vertex_data[i * 3 + 1], | ||
196 | object->vertex_data[i * 3 + 2]); | ||
197 | #endif | ||
198 | |||
199 | /* normal */ | ||
200 | normals[i * 3 + 0] = glb_get_float(stream); | ||
201 | normals[i * 3 + 1] = glb_get_float(stream); | ||
202 | normals[i * 3 + 2] = glb_get_float(stream); | ||
203 | g3d_vector_unify( | ||
204 | normals + i * 3 + 0, | ||
205 | normals + i * 3 + 1, | ||
206 | normals + i * 3 + 2); | ||
207 | |||
208 | /* texture coordinates */ | ||
209 | texcoords[i * 2 + 0] = glb_get_float(stream) / 64; | ||
210 | texcoords[i * 2 + 1] = 1.0 - glb_get_float(stream) / 64; | ||
211 | } | ||
212 | } | ||
213 | |||
214 | if(nindices > 0) { | ||
215 | for(i = 0; i < nindices; i += 3) { | ||
216 | face = g_new0(G3DFace, 1); | ||
217 | face->vertex_count = 3; | ||
218 | face->vertex_indices = g_new0(guint32, 3); | ||
219 | face->normals = g_new0(G3DFloat, 3 * 3); | ||
220 | face->flags |= G3D_FLAG_FAC_NORMALS; | ||
221 | for(j = 0; j < 3; j ++) { | ||
222 | face->vertex_indices[j] = g3d_stream_read_int32_be(stream); | ||
223 | |||
224 | /* set normals */ | ||
225 | index = face->vertex_indices[j]; | ||
226 | face->normals[j * 3 + 0] = normals[index * 3 + 0]; | ||
227 | face->normals[j * 3 + 1] = normals[index * 3 + 1]; | ||
228 | face->normals[j * 3 + 2] = normals[index * 3 + 2]; | ||
229 | } | ||
230 | face->material = g_slist_nth_data(object->materials, 0); | ||
231 | |||
232 | if(face->material->tex_image != NULL) { | ||
233 | face->tex_vertex_count = 3; | ||
234 | face->tex_vertex_data = g_new0(G3DFloat, 3 * 2); | ||
235 | face->tex_image = face->material->tex_image; | ||
236 | for(j = 0; j < 3; j ++) { | ||
237 | index = face->vertex_indices[j]; | ||
238 | |||
239 | face->tex_vertex_data[j * 2 + 0] = | ||
240 | texcoords[index * 2 + 0]; | ||
241 | face->tex_vertex_data[j * 2 + 1] = | ||
242 | texcoords[index * 2 + 1]; | ||
243 | face->flags |= G3D_FLAG_FAC_TEXMAP; | ||
244 | } | ||
245 | } | ||
246 | |||
247 | object->faces = g_slist_append(object->faces, face); | ||
248 | } | ||
249 | } | ||
250 | |||
251 | if(normals != NULL) | ||
252 | g_free(normals); | ||
253 | if(texcoords != NULL) | ||
254 | g_free(texcoords); | ||
255 | } | ||
256 | |||
257 | return pobject; | ||
258 | } | ||