aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/src/others/mimesh/libg3d-0.0.8/plugins/import/imp_max/imp_max.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/others/mimesh/libg3d-0.0.8/plugins/import/imp_max/imp_max.c')
-rw-r--r--src/others/mimesh/libg3d-0.0.8/plugins/import/imp_max/imp_max.c358
1 files changed, 358 insertions, 0 deletions
diff --git a/src/others/mimesh/libg3d-0.0.8/plugins/import/imp_max/imp_max.c b/src/others/mimesh/libg3d-0.0.8/plugins/import/imp_max/imp_max.c
new file mode 100644
index 0000000..0dba25c
--- /dev/null
+++ b/src/others/mimesh/libg3d-0.0.8/plugins/import/imp_max/imp_max.c
@@ -0,0 +1,358 @@
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 <g3d/config.h>
24
25#include <string.h>
26
27#include <g3d/types.h>
28#include <g3d/context.h>
29#include <g3d/object.h>
30#include <g3d/material.h>
31#include <g3d/stream.h>
32#include <g3d/debug.h>
33
34#include "imp_max_chunks.h"
35
36
37
38static gboolean max_read_subfile(G3DContext *context, G3DModel *model,
39 G3DStream *stream, const gchar *subfile);
40static gboolean max_read_chunk(MaxGlobalData *global, gint32 *nb,
41 guint32 level, gint32 parentid, gpointer object, guint32 *l2cnt,
42 GNode *tree);
43static MaxChunk *max_get_chunk_desc(guint16 id, gint32 parentid,
44 gboolean container);
45
46static const gchar *max_subfiles[] = {
47#if 0
48 "Config",
49 "VideoPostQueue",
50 "ScriptedCustAttribDefs",
51 "DllDirectory",
52 "ClassDirectory",
53 "ClassDirectory2",
54 "ClassDirectory3",
55 "ClassData",
56#endif
57 "Scene",
58 NULL
59};
60
61typedef enum {
62 MAX_ROOT_NODE,
63 MAX_L2_NODE,
64 MAX_CNT_NODE,
65 MAX_DATA_NODE
66} MaxNodeType;
67
68typedef struct {
69 MaxNodeType type;
70 gchar *name;
71 guint32 cnt2034;
72 guint32 val2034;
73 gint32 data2034;
74 GSList *children;
75} MaxNode;
76
77typedef struct {
78 guint32 l2id;
79 guint32 id;
80 gchar *text;
81 G3DObject *object;
82} MaxTreeItem;
83
84EAPI
85gboolean plugin_load_model_from_stream(G3DContext *context, G3DStream *stream,
86 G3DModel *model)
87{
88 gboolean retval = FALSE;
89 G3DMaterial *material;
90 const gchar **subfile = max_subfiles;
91
92 /* create default material */
93 material = g3d_material_new();
94 material->name = g_strdup("default material");
95 model->materials = g_slist_append(model->materials, material);
96
97 /* debugging material */
98 material = g3d_material_new();
99 material->r = 1.0;
100 material->g = 0.2;
101 material->b = 0.1;
102 material->name = g_strdup("debugging material");
103 model->materials = g_slist_append(model->materials, material);
104
105 while(*subfile) {
106 retval = max_read_subfile(context, model, stream, *subfile);
107 subfile ++;
108 }
109
110 g3d_context_update_progress_bar(context, 0.0, FALSE);
111
112 return retval;
113}
114
115EAPI
116gchar *plugin_description(void)
117{
118 return g_strdup("3D Studio MAX models (EXPERIMENTAL).");
119}
120
121EAPI
122gchar **plugin_extensions(void)
123{
124 return g_strsplit("max:gmax", ":", 0);
125}
126
127/*****************************************************************************
128 * max specific
129 *****************************************************************************/
130
131static void max_walk_tree(GNode *tree, guint32 level)
132{
133 GNode *node;
134 MaxTreeItem *mtitem;
135
136 mtitem = (MaxTreeItem *)tree->data;
137
138#if DEBUG > 0
139 g_debug("\\%s(%u)[0x%04X][0x%04X] %s", debug_pad(level), level,
140 mtitem->l2id, mtitem->id, mtitem->text);
141#endif
142
143 for(node = tree->children; node != NULL; node = node->next) {
144 max_walk_tree(node, level + 1);
145 }
146}
147
148static gboolean max_read_subfile(G3DContext *context, G3DModel *model,
149 G3DStream *stream, const gchar *subfile)
150{
151 G3DStream *ssf;
152 MaxGlobalData *global;
153 gint32 fsize;
154 guint32 l2cnt = 0;
155 MaxTreeItem *rootitem;
156 GNode *tree;
157
158 rootitem = g_new0(MaxTreeItem, 1);
159 rootitem->text = g_strdup("ROOT");
160 tree = g_node_new(rootitem);
161
162 ssf = g3d_stream_open_structured_file_from_stream(stream, subfile);
163 if(ssf == NULL) {
164 g_warning("MAX: failed to open '%s' in structured file '%s'",
165 subfile, stream->uri);
166 return FALSE;
167 }
168
169 fsize = g3d_stream_size(ssf);
170
171 g_debug("\\%s (%d bytes)", subfile, fsize);
172
173 global = g_new0(MaxGlobalData, 1);
174 global->context = context;
175 global->model = model;
176 global->stream = ssf;
177 global->subfile = subfile;
178
179 while(max_read_chunk(global, &fsize, 1 /* level */, IDNONE, NULL, &l2cnt,
180 tree));
181
182 g_debug("MAX tree:");
183 max_walk_tree(tree, 0);
184
185 g_free(global);
186 g3d_stream_close(ssf);
187
188 return TRUE;
189}
190
191static GNode *max_find_node(GNode *tree, guint32 id)
192{
193 GNode *node, *found;
194 MaxTreeItem *mtitem;
195
196 mtitem = (MaxTreeItem *)tree->data;
197 if(mtitem->l2id == id)
198 return tree;
199
200 for(node = tree->children; node != NULL; node = node->next) {
201 found = max_find_node(node, id);
202 if(found != NULL)
203 return found;
204 }
205
206 return NULL;
207}
208
209static gboolean max_create_l2_tree_object(MaxGlobalData *global,
210 MaxLocalData *local, G3DObject *parent)
211{
212 G3DObject *object;
213
214 object = g_new0(G3DObject, 1);
215 object->name = g_strdup_printf("0x%04X object @ 0x%08x",
216 local->id, (guint32)g3d_stream_tell(global->stream));
217 local->object = object;
218 if(parent)
219 parent->objects = g_slist_append(parent->objects, object);
220 else
221 global->model->objects = g_slist_append(global->model->objects,
222 object);
223
224 global->object = object;
225 global->vertex_offset = 0;
226
227 return TRUE;
228}
229
230static gboolean max_read_chunk(MaxGlobalData *global, gint32 *nb,
231 guint32 level, gint32 parentid, gpointer object, guint32 *l2cnt,
232 GNode *tree)
233{
234 guint16 id;
235 guint32 length;
236 gboolean container;
237 MaxChunk *chunk;
238 MaxLocalData *local;
239 MaxTreeItem *mtitem;
240 GNode *pnode = NULL, *node;
241
242 if(nb && (*nb < 6))
243 return FALSE;
244
245 id = g3d_stream_read_int16_le(global->stream);
246 length = g3d_stream_read_int32_le(global->stream);
247 container = (length & 0x80000000);
248 length &= 0x7FFFFFFF;
249
250 if(nb && (length > *nb))
251 return FALSE;
252 if(nb)
253 *nb -= length;
254
255 if((level == 2) && l2cnt)
256 (*l2cnt) ++;
257
258 chunk = max_get_chunk_desc(id, parentid, container);
259
260#if DEBUG > 0
261 g_debug("\\%s(%d)[0x%04X][%c%c] %s -- %d (%d) bytes @ 0x%08x",
262 debug_pad(level), level,
263 id, (container ? 'c' : ' '),
264 (chunk && chunk->callback) ? 'f' : ' ',
265 chunk ? chunk->desc : (level == 2) ? "level 2 container" : "unknown",
266 length - 6, length,
267 (guint32)g3d_stream_tell(global->stream) - 6);
268#endif
269
270 node = tree;
271 if(level == 2) {
272 pnode = max_find_node(tree, id);
273 if(pnode != NULL) {
274 mtitem = g_new0(MaxTreeItem, 1);
275 mtitem->l2id = *l2cnt;
276 mtitem->id = id;
277 mtitem->text = g_strdup("L2ITEM");
278 node = g_node_append_data(pnode, mtitem);
279 } else {
280 mtitem = g_new0(MaxTreeItem, 1);
281 mtitem->l2id = 0xFFFF;
282 mtitem->id = id;
283 mtitem->text = g_strdup_printf("OUTOFTREE: 0x%04X", id);
284 node = g_node_append_data(tree, mtitem);
285 }
286 } else if(level > 2) {
287 mtitem = g_new0(MaxTreeItem, 1);
288 mtitem->l2id = 0xFFFF;
289 mtitem->id = id;
290 mtitem->text = g_strdup_printf("REGITEM: 0x%04X: %s",
291 id, chunk ? chunk->desc : "unknown");
292 node = g_node_append_data(tree, mtitem);
293 }
294
295 local = g_new0(MaxLocalData, 1);
296 local->id = (level > 2) ? id : 0x0000;
297 local->parentid = parentid;
298 local->nb = length - 6;
299 local->level = level + 1;
300 local->object = object;
301
302 if((level > 2) && chunk && chunk->callback)
303 chunk->callback(global, local);
304 if(level == 2) {
305 mtitem = pnode ? pnode->data : NULL;
306 max_create_l2_tree_object(global, local,
307 mtitem ? mtitem->object : NULL);
308 mtitem = node->data;
309 mtitem->object = local->object;
310 }
311
312 if(container)
313 while(local->nb > 0)
314 if(!max_read_chunk(global, &(local->nb), level + 1, id,
315 local->object, l2cnt, node))
316 return FALSE;
317
318 if(local->nb > 0)
319 g3d_stream_skip(global->stream, local->nb);
320
321 g_free(local);
322
323 g3d_context_update_interface(global->context);
324
325 if(level < 3)
326 g3d_context_update_progress_bar(global->context,
327 (G3DFloat)g3d_stream_tell(global->stream) /
328 (G3DFloat)g3d_stream_size(global->stream),
329 TRUE);
330
331 return TRUE;
332}
333
334static MaxChunk *max_get_chunk_desc(guint16 id, gint32 parentid,
335 gboolean container)
336{
337 MaxChunk *chunk, *chunks;
338 gint32 i;
339
340 if(container)
341 chunks = max_cnt_chunks;
342 else
343 chunks = max_chunks;
344
345 for(i = 0, chunk = &(chunks[i]); chunk->id != IDNONE;
346 i ++, chunk = &(chunks[i])) {
347 if((chunk->parentid == IDSOME) || (parentid == chunk->parentid) ||
348 (parentid == IDSOME) ||
349 ((chunk->parentid == IDROOT) && ID_IS_ROOT(parentid)) ||
350 ((chunk->parentid == IDGEOM) && ID_IS_GEOM(parentid)) ||
351 ((chunk->parentid == IDMATG) && ID_IS_MATG(parentid)) ||
352 ((chunk->parentid == IDFILE) && ID_IS_FILE(parentid))) {
353 if(chunk->id == id)
354 return chunk;
355 } /* parentid */
356 }
357 return NULL;
358}