diff options
Diffstat (limited to 'src/others/mimesh/libg3d-0.0.8/plugins/import/imp_acf/imp_acf.c')
-rw-r--r-- | src/others/mimesh/libg3d-0.0.8/plugins/import/imp_acf/imp_acf.c | 338 |
1 files changed, 338 insertions, 0 deletions
diff --git a/src/others/mimesh/libg3d-0.0.8/plugins/import/imp_acf/imp_acf.c b/src/others/mimesh/libg3d-0.0.8/plugins/import/imp_acf/imp_acf.c new file mode 100644 index 0000000..5a73a1a --- /dev/null +++ b/src/others/mimesh/libg3d-0.0.8/plugins/import/imp_acf/imp_acf.c | |||
@@ -0,0 +1,338 @@ | |||
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/stream.h> | ||
28 | #include <g3d/object.h> | ||
29 | #include <g3d/face.h> | ||
30 | #include <g3d/material.h> | ||
31 | #include <g3d/matrix.h> | ||
32 | #include <g3d/vector.h> | ||
33 | |||
34 | #include "imp_acf.h" | ||
35 | #include "imp_acf_airfoil.h" | ||
36 | #include "imp_acf_wing.h" | ||
37 | #include "imp_acf_def.h" | ||
38 | #include "imp_acf_detect.h" | ||
39 | |||
40 | static gboolean acf_load_body(AcfGlobalData *global); | ||
41 | static gboolean acf_load_wings(AcfGlobalData *global); | ||
42 | |||
43 | EAPI | ||
44 | gpointer plugin_init(G3DContext *context) | ||
45 | { | ||
46 | return acf_airfoil_init(); | ||
47 | } | ||
48 | |||
49 | EAPI | ||
50 | void plugin_cleanup(gpointer user_data) | ||
51 | { | ||
52 | AcfAirfoilDb *db = user_data; | ||
53 | |||
54 | if(db) | ||
55 | acf_airfoil_cleanup(db); | ||
56 | } | ||
57 | |||
58 | EAPI | ||
59 | gboolean plugin_load_model_from_stream(G3DContext *context, G3DStream *stream, | ||
60 | G3DModel *model, gpointer user_data) | ||
61 | { | ||
62 | AcfGlobalData *global; | ||
63 | const AcfDef *def; | ||
64 | gboolean bigendian; | ||
65 | gchar magic; | ||
66 | |||
67 | magic = g3d_stream_read_int8(stream); | ||
68 | if(magic == 'i') { | ||
69 | bigendian = FALSE; | ||
70 | g_debug("ACF: intel file found"); | ||
71 | } else if(magic == 'a') { | ||
72 | bigendian = TRUE; | ||
73 | g_debug("ACF: apple file found"); | ||
74 | } else { | ||
75 | g_warning("ACF: not a valid .acf file"); | ||
76 | return FALSE; | ||
77 | } | ||
78 | |||
79 | g3d_stream_seek(stream, 0, G_SEEK_SET); | ||
80 | |||
81 | global = g_new0(AcfGlobalData, 1); | ||
82 | global->context = context; | ||
83 | global->model = model; | ||
84 | global->stream = stream; | ||
85 | global->afldb = user_data; | ||
86 | |||
87 | def = acf_detect_version(global); | ||
88 | if(def == NULL) { | ||
89 | g_free(global); | ||
90 | return FALSE; | ||
91 | } | ||
92 | |||
93 | global->acf = acf_def_read(stream, def, bigendian); | ||
94 | if(global->acf == NULL) { | ||
95 | g_free(global); | ||
96 | return FALSE; | ||
97 | } | ||
98 | |||
99 | if(!acf_load_body(global)) { | ||
100 | acf_def_free(global->acf); | ||
101 | g_free(global); | ||
102 | return FALSE; | ||
103 | } | ||
104 | if(!acf_load_wings(global)) { | ||
105 | acf_def_free(global->acf); | ||
106 | g_free(global); | ||
107 | return FALSE; | ||
108 | } | ||
109 | |||
110 | acf_def_free(global->acf); | ||
111 | g_free(global); | ||
112 | |||
113 | return TRUE; | ||
114 | } | ||
115 | |||
116 | EAPI | ||
117 | gchar *plugin_description(void) | ||
118 | { | ||
119 | return g_strdup("XPlane models."); | ||
120 | } | ||
121 | |||
122 | EAPI | ||
123 | gchar **plugin_extensions(void) | ||
124 | { | ||
125 | return g_strsplit("acf", ":", 0); | ||
126 | } | ||
127 | |||
128 | /*****************************************************************************/ | ||
129 | |||
130 | #define ACF_OBJECT_MIN 44 | ||
131 | #define ACF_OBJECT_MAX 66 | ||
132 | #define ACF_BODY_NUMSEC 20 | ||
133 | #define ACF_BODY_SECVER 18 | ||
134 | #define ACF_VERTS_PER_OBJECT (ACF_BODY_NUMSEC * ACF_BODY_SECVER) | ||
135 | |||
136 | #define ACF_REQUIRE_PART(var, name, t) do { \ | ||
137 | var = acf_def_lookup(global->acf, name); \ | ||
138 | if((var == NULL) || (var->type != t)) { \ | ||
139 | g_warning("ACF: %s is missing or has wrong type", name); \ | ||
140 | return FALSE; \ | ||
141 | } } while(0); | ||
142 | |||
143 | #define ACF_USE_PART(var, name, t) do { \ | ||
144 | var = acf_def_lookup(global->acf, name); \ | ||
145 | if((var != NULL) && (var->type != t)) { \ | ||
146 | g_warning("ACF: %s has wrong type", name); \ | ||
147 | var = NULL; \ | ||
148 | } } while(0); | ||
149 | |||
150 | static gboolean acf_load_body(AcfGlobalData *global) | ||
151 | { | ||
152 | AcfValue *vpart_eq, *vbody_x, *vbody_y, *vbody_z, *vbody_r; | ||
153 | AcfValue *vxarm, *vyarm, *vzarm, *vx_body, *vy_body, *vz_body; | ||
154 | G3DObject *object; | ||
155 | G3DMaterial *material; | ||
156 | G3DFace *face; | ||
157 | gint32 i, j; | ||
158 | guint32 min_obj, max_obj; | ||
159 | |||
160 | /* lookup some required data in library an return FALSE if one of | ||
161 | * them is missing */ | ||
162 | ACF_REQUIRE_PART(vpart_eq, "PARTS_part_eq", XINT); | ||
163 | ACF_REQUIRE_PART(vbody_x, "PARTS_body_X", XFLT); | ||
164 | ACF_REQUIRE_PART(vbody_y, "PARTS_body_Y", XFLT); | ||
165 | ACF_REQUIRE_PART(vbody_z, "PARTS_body_Z", XFLT); | ||
166 | ACF_REQUIRE_PART(vxarm, "PARTS_Xarm", XFLT); | ||
167 | ACF_REQUIRE_PART(vyarm, "PARTS_Yarm", XFLT); | ||
168 | ACF_REQUIRE_PART(vzarm, "PARTS_Zarm", XFLT); | ||
169 | ACF_REQUIRE_PART(vx_body, "PARTS_X_body_aero", XFLT); | ||
170 | ACF_REQUIRE_PART(vy_body, "PARTS_Y_body_aero", XFLT); | ||
171 | ACF_REQUIRE_PART(vz_body, "PARTS_Z_body_aero", XFLT); | ||
172 | ACF_REQUIRE_PART(vbody_r, "PARTS_body_r", XFLT); | ||
173 | |||
174 | material = g3d_material_new(); | ||
175 | material->name = g_strdup("(default material)"); | ||
176 | global->model->materials = g_slist_append(global->model->materials, | ||
177 | material); | ||
178 | |||
179 | min_obj = ACF_OBJECT_MIN; | ||
180 | max_obj = MIN(ACF_OBJECT_MAX, (vpart_eq->num - 1)); | ||
181 | if(vpart_eq->num <= 57) { | ||
182 | min_obj = 30; | ||
183 | max_obj = 49; | ||
184 | } | ||
185 | |||
186 | for(i = min_obj; i <= max_obj; i ++) { | ||
187 | if(!vpart_eq->xint[i]) | ||
188 | continue; | ||
189 | |||
190 | g_debug("ACF: part[%i]: (%.2f, %.2f, %.2f), %.2f", i, | ||
191 | vx_body->xflt[i], vy_body->xflt[i], vz_body->xflt[i], | ||
192 | vbody_r->xflt[i]); | ||
193 | |||
194 | object = g_new0(G3DObject, 1); | ||
195 | object->name = g_strdup_printf("object[%d]", i); | ||
196 | object->vertex_count = ACF_VERTS_PER_OBJECT; | ||
197 | object->vertex_data = g_new0(G3DFloat, object->vertex_count * 3); | ||
198 | for(j = 0; j < object->vertex_count; j ++) { | ||
199 | object->vertex_data[j * 3 + 0] = | ||
200 | vbody_x->xflt[i * ACF_VERTS_PER_OBJECT + j] + vxarm->xflt[i]; | ||
201 | object->vertex_data[j * 3 + 1] = | ||
202 | vbody_y->xflt[i * ACF_VERTS_PER_OBJECT + j] + vyarm->xflt[i]; | ||
203 | object->vertex_data[j * 3 + 2] = | ||
204 | vbody_z->xflt[i * ACF_VERTS_PER_OBJECT + j] + vzarm->xflt[i]; | ||
205 | #if DEBUG > 3 | ||
206 | g_debug("\tVERT: (%04d) %.3f, %.3f, %.3f", j, | ||
207 | object->vertex_data[j * 3 + 0], | ||
208 | object->vertex_data[j * 3 + 1], | ||
209 | object->vertex_data[j * 3 + 2]); | ||
210 | #endif | ||
211 | } | ||
212 | |||
213 | global->model->objects = g_slist_append(global->model->objects, | ||
214 | object); | ||
215 | |||
216 | for(j = 0; j < (ACF_VERTS_PER_OBJECT - ACF_BODY_SECVER - 1); j ++) { | ||
217 | face = g3d_face_new_tri(material, j + 1, j, j + ACF_BODY_SECVER); | ||
218 | object->faces = g_slist_prepend(object->faces, face); | ||
219 | |||
220 | face = g3d_face_new_tri(material, j + ACF_BODY_SECVER, | ||
221 | j + ACF_BODY_SECVER + 1, j + 1); | ||
222 | object->faces = g_slist_prepend(object->faces, face); | ||
223 | } | ||
224 | } | ||
225 | |||
226 | return TRUE; | ||
227 | } | ||
228 | |||
229 | static gboolean acf_load_wings(AcfGlobalData *global) | ||
230 | { | ||
231 | AcfValue *vpart_eq, *vrafl0, *vtafl0; | ||
232 | AcfValue *vctip, *vcroot, *vdihed, *vsweep, *vels; | ||
233 | AcfValue *vxarm, *vyarm, *vzarm, *visleft, *vlatsign; | ||
234 | AcfValue *vslseg, *vsljnd, *vpartss, *vpartse; | ||
235 | AcfAirfoil *afrt, *aftp; | ||
236 | G3DObject *object; | ||
237 | G3DMaterial *material; | ||
238 | gint32 i; | ||
239 | guint32 cnt; | ||
240 | G3DFloat m_dihed[16], m_sweep[16], m_trans[16]; | ||
241 | G3DFloat vecrt[3], vectp[3], lf, ls; | ||
242 | gchar *title; | ||
243 | |||
244 | ACF_REQUIRE_PART(vpart_eq, "PARTS_part_eq", XINT); | ||
245 | ACF_REQUIRE_PART(vrafl0, "PARTS_Rafl0", XCHR); | ||
246 | ACF_REQUIRE_PART(vtafl0, "PARTS_Tafl0", XCHR); | ||
247 | ACF_REQUIRE_PART(vcroot, "PARTS_Croot", XFLT); | ||
248 | ACF_REQUIRE_PART(vctip, "PARTS_Ctip", XFLT); | ||
249 | ACF_REQUIRE_PART(vels, "PARTS_els", XINT); | ||
250 | ACF_REQUIRE_PART(vxarm, "PARTS_Xarm", XFLT); | ||
251 | ACF_REQUIRE_PART(vyarm, "PARTS_Yarm", XFLT); | ||
252 | ACF_REQUIRE_PART(vzarm, "PARTS_Zarm", XFLT); | ||
253 | |||
254 | ACF_USE_PART(vdihed, "PARTS_dihed", XFLT); | ||
255 | if(vdihed == NULL) | ||
256 | ACF_REQUIRE_PART(vdihed, "PARTS_dihed1", XFLT); | ||
257 | ACF_USE_PART(vsweep, "PARTS_sweep", XFLT); | ||
258 | if(vsweep == NULL) | ||
259 | ACF_REQUIRE_PART(vsweep, "PARTS_sweep1", XFLT); | ||
260 | |||
261 | ACF_REQUIRE_PART(vpartss, "PARTS_s", XFLT); | ||
262 | ACF_REQUIRE_PART(vpartse, "PARTS_e", XFLT); | ||
263 | ACF_REQUIRE_PART(vlatsign, "OVERFLOW_lat_sign", XFLT); | ||
264 | ACF_REQUIRE_PART(vslseg, "PARTS_semilen_SEG", XFLT); | ||
265 | ACF_REQUIRE_PART(vsljnd, "PARTS_semilen_JND", XFLT); | ||
266 | |||
267 | ACF_USE_PART(visleft, "OVERFLOW_is_left", XINT); | ||
268 | |||
269 | |||
270 | material = g_slist_nth_data(global->model->materials, 0); | ||
271 | |||
272 | cnt = vrafl0->num / vpart_eq->num; | ||
273 | |||
274 | for(i = 8; i < vpart_eq->num; i ++) { | ||
275 | if(strlen(vrafl0->xchr + i * cnt) == 0) | ||
276 | continue; | ||
277 | if(vels->xint[i] == 0) | ||
278 | continue; | ||
279 | #if DEBUG > 0 | ||
280 | g_debug("PARTS_Rafl0[%d]: %s", i, vrafl0->xchr + i * cnt); | ||
281 | g_debug("PARTS_Tafl0[%d]: %s", i, vtafl0->xchr + i * cnt); | ||
282 | g_debug( | ||
283 | "[%i] lat_sign=%.2f, Croot=%.2f, Ctip=%.2f, dihed=%.2f, els=%i", i, | ||
284 | vlatsign->xflt[i], | ||
285 | vcroot->xflt[i], vctip->xflt[i], | ||
286 | vdihed ? vdihed->xflt[i] : -1337.0, | ||
287 | vels->xint[i]); | ||
288 | g_debug("[%i] semilen_SEG=%.2f, semilen_JND=%.2f, parts_e=%.2f", i, | ||
289 | vslseg->xflt[i], vsljnd->xflt[i], vpartse->xflt[i]); | ||
290 | g_debug("PARTS_s[%i]: %f, %f ... %f, %f", i, | ||
291 | vpartss->xflt[i * 10 + 0], vpartss->xflt[i * 10 + 1], | ||
292 | vpartss->xflt[i * 10 + 8], vpartss->xflt[i * 10 + 9]); | ||
293 | #endif | ||
294 | afrt = acf_airfoil_lookup(global->afldb, "naca16006.dat"); | ||
295 | aftp = acf_airfoil_lookup(global->afldb, "naca16006.dat"); | ||
296 | if((afrt == NULL) || (aftp == NULL)) | ||
297 | continue; | ||
298 | |||
299 | if(afrt->vertex_count != aftp->vertex_count) { | ||
300 | g_warning("ACF: airfoil vertex count mismatch: %s=%d, %s=%d", | ||
301 | afrt->filename, afrt->vertex_count, | ||
302 | aftp->filename, aftp->vertex_count); | ||
303 | continue; | ||
304 | } | ||
305 | |||
306 | lf = ((visleft && visleft->xint[i]) ? -1 : 1); | ||
307 | ls = (vlatsign ? vlatsign->xflt[i] : 1.0); | ||
308 | |||
309 | /* translation */ | ||
310 | g3d_matrix_identity(m_trans); | ||
311 | g3d_matrix_translate(vxarm->xflt[i], vyarm->xflt[i], vzarm->xflt[i], | ||
312 | m_trans); | ||
313 | |||
314 | /* rotation matrices */ | ||
315 | g3d_matrix_rotate(lf * vdihed->xflt[i] * G_PI / 180.0, | ||
316 | 0.0, 0.0, 1.0, m_dihed); | ||
317 | g3d_matrix_rotate(lf * -1.0 * vsweep->xflt[i] * G_PI / 180.0, | ||
318 | 0.0, 1.0, 0.0, m_sweep); | ||
319 | |||
320 | /* wing root & tip center */ | ||
321 | memset(vecrt, 0, sizeof(vecrt)); | ||
322 | memset(vectp, 0, sizeof(vectp)); | ||
323 | vectp[0] = vslseg->xflt[i]; | ||
324 | g3d_vector_transform(vectp, vectp + 1, vectp + 2, m_dihed); | ||
325 | g3d_vector_transform(vectp, vectp + 1, vectp + 2, m_sweep); | ||
326 | |||
327 | title = g_strdup_printf("Wing[%d]", i); | ||
328 | object = acf_wing(material, title, | ||
329 | m_sweep, m_dihed, m_trans, | ||
330 | vecrt, vectp, | ||
331 | afrt, aftp, | ||
332 | vcroot->xflt[i], vctip->xflt[i], lf); | ||
333 | g_free(title); | ||
334 | global->model->objects = g_slist_append(global->model->objects, | ||
335 | object); | ||
336 | } | ||
337 | return TRUE; | ||
338 | } | ||