diff options
Diffstat (limited to '')
-rw-r--r-- | src/others/mimesh/libg3d-0.0.8/src/texture.c | 270 |
1 files changed, 270 insertions, 0 deletions
diff --git a/src/others/mimesh/libg3d-0.0.8/src/texture.c b/src/others/mimesh/libg3d-0.0.8/src/texture.c new file mode 100644 index 0000000..8d9f471 --- /dev/null +++ b/src/others/mimesh/libg3d-0.0.8/src/texture.c | |||
@@ -0,0 +1,270 @@ | |||
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 <string.h> | ||
25 | #include <g3d/config.h> | ||
26 | #include <g3d/types.h> | ||
27 | #include <g3d/plugins.h> | ||
28 | #include <g3d/stream.h> | ||
29 | #include <g3d/texture.h> | ||
30 | |||
31 | #ifdef G3D_DEBUG_DUMP_IMAGE | ||
32 | static gboolean dump_ppm(G3DImage *image, const gchar *filename); | ||
33 | #endif | ||
34 | |||
35 | |||
36 | EAPI | ||
37 | G3DImage *g3d_texture_load_from_stream(G3DContext *context, G3DModel *model, | ||
38 | G3DStream *stream) | ||
39 | { | ||
40 | G3DImage *image; | ||
41 | |||
42 | if(model != NULL) { | ||
43 | if(model->tex_images == NULL) | ||
44 | model->tex_images = g_hash_table_new(g_str_hash, g_str_equal); | ||
45 | |||
46 | image = g_hash_table_lookup(model->tex_images, stream->uri); | ||
47 | if(image != NULL) | ||
48 | return image; | ||
49 | } | ||
50 | |||
51 | image = g_new0(G3DImage, 1); | ||
52 | image->tex_scale_u = 1.0; | ||
53 | image->tex_scale_v = 1.0; | ||
54 | |||
55 | if(g3d_plugins_load_image_from_stream(context, stream, image)) { | ||
56 | image->tex_id = g_str_hash(stream->uri); | ||
57 | if(model != NULL) | ||
58 | g_hash_table_insert(model->tex_images, g_strdup(stream->uri), | ||
59 | image); | ||
60 | return image; | ||
61 | } | ||
62 | g_free(image); | ||
63 | return NULL; | ||
64 | } | ||
65 | |||
66 | EAPI | ||
67 | G3DImage *g3d_texture_load_cached(G3DContext *context, G3DModel *model, | ||
68 | const gchar *filename) | ||
69 | { | ||
70 | G3DImage *image = NULL; | ||
71 | G3DStream *imgstream; | ||
72 | #ifdef G3D_DEBUG_DUMP_IMAGE | ||
73 | gchar *basename, *ppmname; | ||
74 | #endif | ||
75 | |||
76 | /* create hash table if it does not exist yet */ | ||
77 | if(model->tex_images == NULL) | ||
78 | model->tex_images = g_hash_table_new(g_str_hash, g_str_equal); | ||
79 | |||
80 | /* if already loaded, return cached image */ | ||
81 | image = g_hash_table_lookup(model->tex_images, filename); | ||
82 | if(image != NULL) | ||
83 | return image; | ||
84 | |||
85 | if (model->stream) | ||
86 | { | ||
87 | g_debug("texture: loading '%s' from: '%s'", filename, model->stream->uri); | ||
88 | imgstream = g3d_stream_open_zip_from_stream(model->stream->zip_container, filename); | ||
89 | image = g3d_texture_load_from_stream(context, model, imgstream); | ||
90 | } | ||
91 | if(image != NULL) | ||
92 | { | ||
93 | image->tex_id = g_str_hash(filename); | ||
94 | #if 0 | ||
95 | g3d_texture_prepare(image); | ||
96 | #endif | ||
97 | g_hash_table_insert(model->tex_images, (gpointer)g_strdup(filename), | ||
98 | image); | ||
99 | } | ||
100 | |||
101 | #ifdef G3D_DEBUG_DUMP_IMAGE | ||
102 | if(image) | ||
103 | { | ||
104 | basename = g_path_get_basename(filename); | ||
105 | ppmname = g_strdup_printf("/tmp/%s.ppm", basename); | ||
106 | dump_ppm(image, ppmname); | ||
107 | g_free(ppmname); | ||
108 | g_free(basename); | ||
109 | } | ||
110 | #endif | ||
111 | |||
112 | return image; | ||
113 | } | ||
114 | |||
115 | EAPI | ||
116 | void g3d_texture_free(G3DImage *texture) | ||
117 | { | ||
118 | if(texture->name) g_free(texture->name); | ||
119 | if(texture->pixeldata) g_free(texture->pixeldata); | ||
120 | g_free(texture); | ||
121 | } | ||
122 | |||
123 | EAPI | ||
124 | gboolean g3d_texture_prepare(G3DImage *texture) | ||
125 | { | ||
126 | guint32 nw = 1, nh = 1, y; | ||
127 | guint8 *np; | ||
128 | |||
129 | while(nw < texture->width) nw *= 2; | ||
130 | while(nh < texture->height) nh *= 2; | ||
131 | |||
132 | if((nw != texture->width) || (nh != texture->height)) | ||
133 | { | ||
134 | /* blow up texture image to dimensions with a power of two */ | ||
135 | np = g_malloc(nw * nh * 4); | ||
136 | memset(np, 0xFF, nw * nh * 4); | ||
137 | |||
138 | /* copy image data */ | ||
139 | for(y = 0; y < nh; y ++) | ||
140 | memcpy(np + ((nh - y - 1) * nw * 4), | ||
141 | texture->pixeldata + | ||
142 | (((texture->height - y - 1) % texture->height) * | ||
143 | texture->width * 4), | ||
144 | texture->width * 4); | ||
145 | |||
146 | /* calculate scaling factor */ | ||
147 | texture->tex_scale_u = ((G3DFloat)texture->width / (G3DFloat)nw); | ||
148 | texture->tex_scale_v = ((G3DFloat)texture->height / (G3DFloat)nh); | ||
149 | |||
150 | #if DEBUG > 0 | ||
151 | g_debug("texture scaling factor for '%s' set to %.2f,%.2f", | ||
152 | texture->name, texture->tex_scale_u, texture->tex_scale_v); | ||
153 | #endif | ||
154 | |||
155 | /* update image */ | ||
156 | g_free(texture->pixeldata); | ||
157 | texture->pixeldata = np; | ||
158 | texture->width = nw; | ||
159 | texture->height = nh; | ||
160 | |||
161 | return TRUE; | ||
162 | } | ||
163 | return FALSE; | ||
164 | } | ||
165 | |||
166 | EAPI | ||
167 | gboolean g3d_texture_flip_y(G3DImage *texture) | ||
168 | { | ||
169 | guint8 *newpixel; | ||
170 | gint32 y; | ||
171 | |||
172 | g_return_val_if_fail(texture != NULL, FALSE); | ||
173 | |||
174 | newpixel = g_new0(guint8, texture->width * texture->height * 4); | ||
175 | |||
176 | for(y = 0; y < texture->height; y ++) | ||
177 | { | ||
178 | memcpy( | ||
179 | newpixel + (y * texture->width * 4), | ||
180 | texture->pixeldata + ( | ||
181 | (texture->height - y - 1) * texture->width * 4), | ||
182 | texture->width * 4); | ||
183 | } | ||
184 | |||
185 | g_free(texture->pixeldata); | ||
186 | texture->pixeldata = newpixel; | ||
187 | |||
188 | return TRUE; | ||
189 | } | ||
190 | |||
191 | #ifdef G3D_DEBUG_DUMP_IMAGE | ||
192 | static gboolean dump_ppm(G3DImage *image, const gchar *filename) | ||
193 | { | ||
194 | FILE *f; | ||
195 | guint32 x, y; | ||
196 | |||
197 | f = fopen(filename, "w"); | ||
198 | if(f == NULL) | ||
199 | { | ||
200 | g_warning("image: failed to write to '%s'", filename); | ||
201 | return FALSE; | ||
202 | } | ||
203 | |||
204 | fprintf(f, "P3\n# CREATOR: g3dviewer\n%d %d\n%d\n", | ||
205 | image->width, image->height, 255); | ||
206 | |||
207 | for(y = 0; y < image->height; y ++) | ||
208 | for(x = 0; x < image->width; x ++) | ||
209 | fprintf(f, "%d\n%d\n%d\n", | ||
210 | image->pixeldata[(y * image->width + x) * 4 + 0], | ||
211 | image->pixeldata[(y * image->width + x) * 4 + 1], | ||
212 | image->pixeldata[(y * image->width + x) * 4 + 2]); | ||
213 | |||
214 | fclose(f); | ||
215 | return TRUE; | ||
216 | } | ||
217 | #endif | ||
218 | |||
219 | EAPI | ||
220 | G3DImage *g3d_texture_merge_alpha(G3DImage *image, G3DImage *aimage) | ||
221 | { | ||
222 | G3DImage *texture; | ||
223 | gint32 x, y; | ||
224 | gboolean negative; | ||
225 | |||
226 | g_return_val_if_fail(aimage != NULL, NULL); | ||
227 | |||
228 | if(image && ( | ||
229 | (image->width != aimage->width) || | ||
230 | (image->height != aimage->height))) | ||
231 | { | ||
232 | /* size doesn't match, don't do something */ | ||
233 | return image; | ||
234 | } | ||
235 | |||
236 | if(image) | ||
237 | { | ||
238 | texture = image; | ||
239 | } | ||
240 | else | ||
241 | { | ||
242 | texture = g_new0(G3DImage, 1); | ||
243 | texture->tex_scale_u = 1.0; | ||
244 | texture->tex_scale_v = 1.0; | ||
245 | texture->width = aimage->width; | ||
246 | texture->height = aimage->height; | ||
247 | texture->depth = 4; | ||
248 | texture->pixeldata = g_malloc(texture->width * texture->height * 4); | ||
249 | } | ||
250 | |||
251 | /* negative map? */ | ||
252 | /* FIXME: better solution? */ | ||
253 | if(aimage->pixeldata[0] == 0) | ||
254 | negative = TRUE; | ||
255 | else | ||
256 | negative = FALSE; | ||
257 | |||
258 | for(y = 0; y < texture->height; y ++) | ||
259 | { | ||
260 | for(x = 0; x < texture->width; x ++) | ||
261 | { | ||
262 | texture->pixeldata[(y * image->width + x) * 4 + 3] = (negative ? | ||
263 | 255 - aimage->pixeldata[(y * image->width + x) * 4 + 0] : | ||
264 | aimage->pixeldata[(y * image->width + x) * 4 + 0]); | ||
265 | } | ||
266 | } | ||
267 | |||
268 | return texture; | ||
269 | } | ||
270 | |||