diff options
Diffstat (limited to 'src/others/mimesh/libg3d-0.0.8/plugins/import/imp_blend/imp_blend.c')
-rw-r--r-- | src/others/mimesh/libg3d-0.0.8/plugins/import/imp_blend/imp_blend.c | 201 |
1 files changed, 201 insertions, 0 deletions
diff --git a/src/others/mimesh/libg3d-0.0.8/plugins/import/imp_blend/imp_blend.c b/src/others/mimesh/libg3d-0.0.8/plugins/import/imp_blend/imp_blend.c new file mode 100644 index 0000000..7893c1e --- /dev/null +++ b/src/others/mimesh/libg3d-0.0.8/plugins/import/imp_blend/imp_blend.c | |||
@@ -0,0 +1,201 @@ | |||
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 <stdlib.h> | ||
25 | |||
26 | #include <g3d/types.h> | ||
27 | #include <g3d/stream.h> | ||
28 | |||
29 | #include "imp_blend_def.h" | ||
30 | #include "imp_blend_types.h" | ||
31 | #include "imp_blend_sdna.h" | ||
32 | #include "imp_blend_read.h" | ||
33 | #include "imp_blend_chunks.h" | ||
34 | |||
35 | static gboolean blend_read_file(BlendGlobal *global); | ||
36 | |||
37 | EAPI | ||
38 | gboolean plugin_load_model_from_stream(G3DContext *context, G3DStream *stream, | ||
39 | G3DModel *model, gpointer user_data) | ||
40 | { | ||
41 | gchar buf[BLEND_HEADER_SIZE + 1]; | ||
42 | guint32 flags = 0, version; | ||
43 | BlendGlobal *global; | ||
44 | |||
45 | if(g3d_stream_read(stream, buf, BLEND_HEADER_SIZE) != BLEND_HEADER_SIZE) { | ||
46 | g_warning("Blend: %s: failed to read header", stream->uri); | ||
47 | return FALSE; | ||
48 | } | ||
49 | buf[BLEND_HEADER_SIZE] = '\0'; | ||
50 | if(strncmp(buf, "BLENDER", 7) != 0) { | ||
51 | g_warning("Blend: %s: not a blender file", stream->uri); | ||
52 | return FALSE; | ||
53 | } | ||
54 | if(buf[7] == '_') | ||
55 | flags |= FLAG_POINTERSIZE_4; | ||
56 | if(buf[8] == 'v') | ||
57 | flags |= FLAG_LITTLE_ENDIAN; | ||
58 | version = atoi(buf + 9); | ||
59 | |||
60 | g_debug("Blend: version %.2f, %s endian, pointer size is %d", | ||
61 | version / 100.0, | ||
62 | (flags & FLAG_LITTLE_ENDIAN) ? "little" : "big", | ||
63 | (flags & FLAG_POINTERSIZE_4) ? 4 : 8); | ||
64 | |||
65 | if(!(flags & FLAG_POINTERSIZE_4)) { | ||
66 | g_warning("Blend: 8-byte pointers are not implemented as I lack a " | ||
67 | "test file. Please send me one :)."); | ||
68 | return FALSE; | ||
69 | } | ||
70 | |||
71 | global = g_new0(BlendGlobal, 1); | ||
72 | global->context = context; | ||
73 | global->stream = stream; | ||
74 | global->model = model; | ||
75 | global->flags = flags; | ||
76 | |||
77 | blend_read_file(global); | ||
78 | |||
79 | g_free(global); | ||
80 | |||
81 | return TRUE; | ||
82 | } | ||
83 | |||
84 | EAPI | ||
85 | gchar *plugin_description(void) | ||
86 | { | ||
87 | return g_strdup("Blender models."); | ||
88 | } | ||
89 | |||
90 | EAPI | ||
91 | gchar **plugin_extensions(void) | ||
92 | { | ||
93 | return g_strsplit("blend", ":", 0); | ||
94 | } | ||
95 | |||
96 | /*****************************************************************************/ | ||
97 | |||
98 | static inline const BlendChunkInfo *blend_get_chunk_info(guint32 code, | ||
99 | guint32 oid) | ||
100 | { | ||
101 | gint32 i; | ||
102 | |||
103 | for(i = 0; blend_chunks[i].code != 0; i ++) | ||
104 | if((blend_chunks[i].code == code) && (blend_chunks[i].oid == oid)) | ||
105 | return &(blend_chunks[i]); | ||
106 | if(oid != 0) | ||
107 | return blend_get_chunk_info(code, 0); | ||
108 | return NULL; | ||
109 | } | ||
110 | |||
111 | static gboolean blend_read_file(BlendGlobal *global) | ||
112 | { | ||
113 | guint32 code, old, sdnanr, nr; | ||
114 | gsize len; | ||
115 | BlendLocal *local; | ||
116 | const BlendChunkInfo *cinfo; | ||
117 | const BlendSdnaStruct *sstruct; | ||
118 | gint i; | ||
119 | G3DObject *object = NULL; | ||
120 | G3DObject *grpobject = NULL; | ||
121 | guint32 object_id = 0; | ||
122 | |||
123 | while(TRUE) { | ||
124 | code = blend_read_uint(global->stream, global->flags); | ||
125 | len = blend_read_uint(global->stream, global->flags); | ||
126 | if(code == MKID('E','N','D','B')) | ||
127 | return TRUE; | ||
128 | |||
129 | old = blend_read_uint(global->stream, global->flags); | ||
130 | sdnanr = blend_read_uint(global->stream, global->flags); | ||
131 | nr = blend_read_uint(global->stream, global->flags); | ||
132 | |||
133 | if((global->sdna == NULL) && (code != MKID('D','N','A','1'))) { | ||
134 | g3d_stream_skip(global->stream, len); | ||
135 | continue; | ||
136 | } | ||
137 | |||
138 | cinfo = blend_get_chunk_info(code, (code == ID_DATA) ? object_id : 0); | ||
139 | if(cinfo == NULL) | ||
140 | g_warning("unknown chunk: %c%c%c%c", | ||
141 | blend_from_id(code, 0), blend_from_id(code, 1), | ||
142 | blend_from_id(code, 2), blend_from_id(code, 3)); | ||
143 | |||
144 | g_debug("\\%c%c%c%c: %-20s - %8d bytes (0x%08x, %d, %d)", | ||
145 | blend_from_id(code, 0), blend_from_id(code, 1), | ||
146 | blend_from_id(code, 2), blend_from_id(code, 3), | ||
147 | cinfo ? cinfo->description : "(unknown)", | ||
148 | (int) len, old, sdnanr, nr); | ||
149 | |||
150 | if(len == 0) | ||
151 | return FALSE; | ||
152 | |||
153 | /* on non-DATA nodes a new object starts */ | ||
154 | if(code != ID_DATA) { | ||
155 | object_id = code; | ||
156 | } | ||
157 | |||
158 | local = g_new0(BlendLocal, 1); | ||
159 | local->ndata = nr; | ||
160 | local->data = g_new0(BlendSdnaData *, nr); | ||
161 | |||
162 | if(global->sdna) { | ||
163 | for(i = 0; i < nr; i ++) { | ||
164 | sstruct = blend_sdna_get_struct_by_id(global->sdna, sdnanr); | ||
165 | if(sstruct) { | ||
166 | #if DEBUG > BLEND_DEBUG_STRUCT | ||
167 | g_debug("|struct %s /* %d */", | ||
168 | sstruct->name, sstruct->size); | ||
169 | #endif | ||
170 | local->data[i] = blend_sdna_data_read(global->sdna, | ||
171 | sstruct, global, &len, 0); | ||
172 | } | ||
173 | } | ||
174 | } | ||
175 | |||
176 | local->object = object; | ||
177 | local->grpobject = grpobject; | ||
178 | local->object_id = object_id; | ||
179 | local->len = len; | ||
180 | |||
181 | if(cinfo && cinfo->callback) | ||
182 | if(!cinfo->callback(global, local)) | ||
183 | return FALSE; | ||
184 | |||
185 | len = local->len; | ||
186 | object = local->object; | ||
187 | grpobject = local->grpobject; | ||
188 | |||
189 | for(i = 0; i < local->ndata; i ++) | ||
190 | if(local->data[i]) | ||
191 | blend_sdna_data_free(local->data[i]); | ||
192 | g_free(local->data); | ||
193 | g_free(local); | ||
194 | |||
195 | /* skip remaining data */ | ||
196 | g3d_stream_skip(global->stream, len); | ||
197 | } | ||
198 | |||
199 | blend_sdna_cleanup(global->sdna); | ||
200 | return TRUE; | ||
201 | } | ||