diff options
Diffstat (limited to '')
-rw-r--r-- | libraries/irrlicht-1.8/include/IQ3Shader.h | 1768 |
1 files changed, 884 insertions, 884 deletions
diff --git a/libraries/irrlicht-1.8/include/IQ3Shader.h b/libraries/irrlicht-1.8/include/IQ3Shader.h index 080471a..3163651 100644 --- a/libraries/irrlicht-1.8/include/IQ3Shader.h +++ b/libraries/irrlicht-1.8/include/IQ3Shader.h | |||
@@ -1,884 +1,884 @@ | |||
1 | // Copyright (C) 2006-2012 Nikolaus Gebhardt / Thomas Alten | 1 | // Copyright (C) 2006-2012 Nikolaus Gebhardt / Thomas Alten |
2 | // This file is part of the "Irrlicht Engine". | 2 | // This file is part of the "Irrlicht Engine". |
3 | // For conditions of distribution and use, see copyright notice in irrlicht.h | 3 | // For conditions of distribution and use, see copyright notice in irrlicht.h |
4 | 4 | ||
5 | #ifndef __I_Q3_LEVEL_SHADER_H_INCLUDED__ | 5 | #ifndef __I_Q3_LEVEL_SHADER_H_INCLUDED__ |
6 | #define __I_Q3_LEVEL_SHADER_H_INCLUDED__ | 6 | #define __I_Q3_LEVEL_SHADER_H_INCLUDED__ |
7 | 7 | ||
8 | #include "irrArray.h" | 8 | #include "irrArray.h" |
9 | #include "fast_atof.h" | 9 | #include "fast_atof.h" |
10 | #include "IFileSystem.h" | 10 | #include "IFileSystem.h" |
11 | #include "IVideoDriver.h" | 11 | #include "IVideoDriver.h" |
12 | #include "coreutil.h" | 12 | #include "coreutil.h" |
13 | 13 | ||
14 | namespace irr | 14 | namespace irr |
15 | { | 15 | { |
16 | namespace scene | 16 | namespace scene |
17 | { | 17 | { |
18 | namespace quake3 | 18 | namespace quake3 |
19 | { | 19 | { |
20 | 20 | ||
21 | static core::stringc irrEmptyStringc(""); | 21 | static core::stringc irrEmptyStringc(""); |
22 | 22 | ||
23 | //! Hold the different Mesh Types used for getMesh | 23 | //! Hold the different Mesh Types used for getMesh |
24 | enum eQ3MeshIndex | 24 | enum eQ3MeshIndex |
25 | { | 25 | { |
26 | E_Q3_MESH_GEOMETRY = 0, | 26 | E_Q3_MESH_GEOMETRY = 0, |
27 | E_Q3_MESH_ITEMS, | 27 | E_Q3_MESH_ITEMS, |
28 | E_Q3_MESH_BILLBOARD, | 28 | E_Q3_MESH_BILLBOARD, |
29 | E_Q3_MESH_FOG, | 29 | E_Q3_MESH_FOG, |
30 | E_Q3_MESH_UNRESOLVED, | 30 | E_Q3_MESH_UNRESOLVED, |
31 | E_Q3_MESH_SIZE | 31 | E_Q3_MESH_SIZE |
32 | }; | 32 | }; |
33 | 33 | ||
34 | /*! used to customize Quake3 BSP Loader | 34 | /*! used to customize Quake3 BSP Loader |
35 | */ | 35 | */ |
36 | 36 | ||
37 | struct Q3LevelLoadParameter | 37 | struct Q3LevelLoadParameter |
38 | { | 38 | { |
39 | Q3LevelLoadParameter () | 39 | Q3LevelLoadParameter () |
40 | :defaultLightMapMaterial ( video::EMT_LIGHTMAP_M4 ), | 40 | :defaultLightMapMaterial ( video::EMT_LIGHTMAP_M4 ), |
41 | defaultModulate ( video::EMFN_MODULATE_4X ), | 41 | defaultModulate ( video::EMFN_MODULATE_4X ), |
42 | defaultFilter ( video::EMF_BILINEAR_FILTER ), | 42 | defaultFilter ( video::EMF_BILINEAR_FILTER ), |
43 | patchTesselation ( 8 ), | 43 | patchTesselation ( 8 ), |
44 | verbose ( 0 ), | 44 | verbose ( 0 ), |
45 | startTime ( 0 ), endTime ( 0 ), | 45 | startTime ( 0 ), endTime ( 0 ), |
46 | mergeShaderBuffer ( 1 ), | 46 | mergeShaderBuffer ( 1 ), |
47 | cleanUnResolvedMeshes ( 1 ), | 47 | cleanUnResolvedMeshes ( 1 ), |
48 | loadAllShaders ( 0 ), | 48 | loadAllShaders ( 0 ), |
49 | loadSkyShader ( 0 ), | 49 | loadSkyShader ( 0 ), |
50 | alpharef ( 1 ), | 50 | alpharef ( 1 ), |
51 | swapLump ( 0 ), | 51 | swapLump ( 0 ), |
52 | #ifdef __BIG_ENDIAN__ | 52 | #ifdef __BIG_ENDIAN__ |
53 | swapHeader ( 1 ) | 53 | swapHeader ( 1 ) |
54 | #else | 54 | #else |
55 | swapHeader ( 0 ) | 55 | swapHeader ( 0 ) |
56 | #endif | 56 | #endif |
57 | { | 57 | { |
58 | memcpy ( scriptDir, "scripts\x0", 8 ); | 58 | memcpy ( scriptDir, "scripts\x0", 8 ); |
59 | } | 59 | } |
60 | 60 | ||
61 | video::E_MATERIAL_TYPE defaultLightMapMaterial; | 61 | video::E_MATERIAL_TYPE defaultLightMapMaterial; |
62 | video::E_MODULATE_FUNC defaultModulate; | 62 | video::E_MODULATE_FUNC defaultModulate; |
63 | video::E_MATERIAL_FLAG defaultFilter; | 63 | video::E_MATERIAL_FLAG defaultFilter; |
64 | s32 patchTesselation; | 64 | s32 patchTesselation; |
65 | s32 verbose; | 65 | s32 verbose; |
66 | u32 startTime; | 66 | u32 startTime; |
67 | u32 endTime; | 67 | u32 endTime; |
68 | s32 mergeShaderBuffer; | 68 | s32 mergeShaderBuffer; |
69 | s32 cleanUnResolvedMeshes; | 69 | s32 cleanUnResolvedMeshes; |
70 | s32 loadAllShaders; | 70 | s32 loadAllShaders; |
71 | s32 loadSkyShader; | 71 | s32 loadSkyShader; |
72 | s32 alpharef; | 72 | s32 alpharef; |
73 | s32 swapLump; | 73 | s32 swapLump; |
74 | s32 swapHeader; | 74 | s32 swapHeader; |
75 | c8 scriptDir [ 64 ]; | 75 | c8 scriptDir [ 64 ]; |
76 | }; | 76 | }; |
77 | 77 | ||
78 | // some useful typedefs | 78 | // some useful typedefs |
79 | typedef core::array< core::stringc > tStringList; | 79 | typedef core::array< core::stringc > tStringList; |
80 | typedef core::array< video::ITexture* > tTexArray; | 80 | typedef core::array< video::ITexture* > tTexArray; |
81 | 81 | ||
82 | // string helper.. TODO: move to generic files | 82 | // string helper.. TODO: move to generic files |
83 | inline s16 isEqual ( const core::stringc &string, u32 &pos, const c8 *list[], u16 listSize ) | 83 | inline s16 isEqual ( const core::stringc &string, u32 &pos, const c8 *list[], u16 listSize ) |
84 | { | 84 | { |
85 | const char * in = string.c_str () + pos; | 85 | const char * in = string.c_str () + pos; |
86 | 86 | ||
87 | for ( u16 i = 0; i != listSize; ++i ) | 87 | for ( u16 i = 0; i != listSize; ++i ) |
88 | { | 88 | { |
89 | if (string.size() < pos) | 89 | if (string.size() < pos) |
90 | return -2; | 90 | return -2; |
91 | u32 len = (u32) strlen ( list[i] ); | 91 | u32 len = (u32) strlen ( list[i] ); |
92 | if (string.size() < pos+len) | 92 | if (string.size() < pos+len) |
93 | continue; | 93 | continue; |
94 | if ( in [len] != 0 && in [len] != ' ' ) | 94 | if ( in [len] != 0 && in [len] != ' ' ) |
95 | continue; | 95 | continue; |
96 | if ( strncmp ( in, list[i], len ) ) | 96 | if ( strncmp ( in, list[i], len ) ) |
97 | continue; | 97 | continue; |
98 | 98 | ||
99 | pos += len + 1; | 99 | pos += len + 1; |
100 | return (s16) i; | 100 | return (s16) i; |
101 | } | 101 | } |
102 | return -2; | 102 | return -2; |
103 | } | 103 | } |
104 | 104 | ||
105 | inline f32 getAsFloat ( const core::stringc &string, u32 &pos ) | 105 | inline f32 getAsFloat ( const core::stringc &string, u32 &pos ) |
106 | { | 106 | { |
107 | const char * in = string.c_str () + pos; | 107 | const char * in = string.c_str () + pos; |
108 | 108 | ||
109 | f32 value = 0.f; | 109 | f32 value = 0.f; |
110 | pos += (u32) ( core::fast_atof_move ( in, value ) - in ) + 1; | 110 | pos += (u32) ( core::fast_atof_move ( in, value ) - in ) + 1; |
111 | return value; | 111 | return value; |
112 | } | 112 | } |
113 | 113 | ||
114 | //! get a quake3 vector translated to irrlicht position (x,-z,y ) | 114 | //! get a quake3 vector translated to irrlicht position (x,-z,y ) |
115 | inline core::vector3df getAsVector3df ( const core::stringc &string, u32 &pos ) | 115 | inline core::vector3df getAsVector3df ( const core::stringc &string, u32 &pos ) |
116 | { | 116 | { |
117 | core::vector3df v; | 117 | core::vector3df v; |
118 | 118 | ||
119 | v.X = getAsFloat ( string, pos ); | 119 | v.X = getAsFloat ( string, pos ); |
120 | v.Z = getAsFloat ( string, pos ); | 120 | v.Z = getAsFloat ( string, pos ); |
121 | v.Y = getAsFloat ( string, pos ); | 121 | v.Y = getAsFloat ( string, pos ); |
122 | 122 | ||
123 | return v; | 123 | return v; |
124 | } | 124 | } |
125 | 125 | ||
126 | 126 | ||
127 | /* | 127 | /* |
128 | extract substrings | 128 | extract substrings |
129 | */ | 129 | */ |
130 | inline void getAsStringList ( tStringList &list, s32 max, const core::stringc &string, u32 &startPos ) | 130 | inline void getAsStringList ( tStringList &list, s32 max, const core::stringc &string, u32 &startPos ) |
131 | { | 131 | { |
132 | list.clear (); | 132 | list.clear (); |
133 | 133 | ||
134 | s32 finish = 0; | 134 | s32 finish = 0; |
135 | s32 endPos; | 135 | s32 endPos; |
136 | do | 136 | do |
137 | { | 137 | { |
138 | endPos = string.findNext ( ' ', startPos ); | 138 | endPos = string.findNext ( ' ', startPos ); |
139 | if ( endPos == -1 ) | 139 | if ( endPos == -1 ) |
140 | { | 140 | { |
141 | finish = 1; | 141 | finish = 1; |
142 | endPos = string.size(); | 142 | endPos = string.size(); |
143 | } | 143 | } |
144 | 144 | ||
145 | list.push_back ( string.subString ( startPos, endPos - startPos ) ); | 145 | list.push_back ( string.subString ( startPos, endPos - startPos ) ); |
146 | startPos = endPos + 1; | 146 | startPos = endPos + 1; |
147 | 147 | ||
148 | if ( list.size() >= (u32) max ) | 148 | if ( list.size() >= (u32) max ) |
149 | finish = 1; | 149 | finish = 1; |
150 | 150 | ||
151 | } while ( !finish ); | 151 | } while ( !finish ); |
152 | 152 | ||
153 | } | 153 | } |
154 | 154 | ||
155 | //! A blend function for a q3 shader. | 155 | //! A blend function for a q3 shader. |
156 | struct SBlendFunc | 156 | struct SBlendFunc |
157 | { | 157 | { |
158 | SBlendFunc ( video::E_MODULATE_FUNC mod ) | 158 | SBlendFunc ( video::E_MODULATE_FUNC mod ) |
159 | : type ( video::EMT_SOLID ), modulate ( mod ), | 159 | : type ( video::EMT_SOLID ), modulate ( mod ), |
160 | param0( 0.f ), | 160 | param0( 0.f ), |
161 | isTransparent ( 0 ) {} | 161 | isTransparent ( 0 ) {} |
162 | 162 | ||
163 | video::E_MATERIAL_TYPE type; | 163 | video::E_MATERIAL_TYPE type; |
164 | video::E_MODULATE_FUNC modulate; | 164 | video::E_MODULATE_FUNC modulate; |
165 | 165 | ||
166 | f32 param0; | 166 | f32 param0; |
167 | u32 isTransparent; | 167 | u32 isTransparent; |
168 | }; | 168 | }; |
169 | 169 | ||
170 | // parses the content of Variable cull | 170 | // parses the content of Variable cull |
171 | inline bool getCullingFunction ( const core::stringc &cull ) | 171 | inline bool getCullingFunction ( const core::stringc &cull ) |
172 | { | 172 | { |
173 | if ( cull.size() == 0 ) | 173 | if ( cull.size() == 0 ) |
174 | return true; | 174 | return true; |
175 | 175 | ||
176 | bool ret = true; | 176 | bool ret = true; |
177 | static const c8 * funclist[] = { "none", "disable", "twosided" }; | 177 | static const c8 * funclist[] = { "none", "disable", "twosided" }; |
178 | 178 | ||
179 | u32 pos = 0; | 179 | u32 pos = 0; |
180 | switch ( isEqual ( cull, pos, funclist, 3 ) ) | 180 | switch ( isEqual ( cull, pos, funclist, 3 ) ) |
181 | { | 181 | { |
182 | case 0: | 182 | case 0: |
183 | case 1: | 183 | case 1: |
184 | case 2: | 184 | case 2: |
185 | ret = false; | 185 | ret = false; |
186 | break; | 186 | break; |
187 | } | 187 | } |
188 | return ret; | 188 | return ret; |
189 | } | 189 | } |
190 | 190 | ||
191 | // parses the content of Variable depthfunc | 191 | // parses the content of Variable depthfunc |
192 | // return a z-test | 192 | // return a z-test |
193 | inline u8 getDepthFunction ( const core::stringc &string ) | 193 | inline u8 getDepthFunction ( const core::stringc &string ) |
194 | { | 194 | { |
195 | u8 ret = video::ECFN_LESSEQUAL; | 195 | u8 ret = video::ECFN_LESSEQUAL; |
196 | 196 | ||
197 | if ( string.size() == 0 ) | 197 | if ( string.size() == 0 ) |
198 | return ret; | 198 | return ret; |
199 | 199 | ||
200 | static const c8 * funclist[] = { "lequal","equal" }; | 200 | static const c8 * funclist[] = { "lequal","equal" }; |
201 | 201 | ||
202 | u32 pos = 0; | 202 | u32 pos = 0; |
203 | switch ( isEqual ( string, pos, funclist, 2 ) ) | 203 | switch ( isEqual ( string, pos, funclist, 2 ) ) |
204 | { | 204 | { |
205 | case 0: | 205 | case 0: |
206 | ret = video::ECFN_LESSEQUAL; | 206 | ret = video::ECFN_LESSEQUAL; |
207 | case 1: | 207 | case 1: |
208 | ret = video::ECFN_EQUAL; | 208 | ret = video::ECFN_EQUAL; |
209 | break; | 209 | break; |
210 | } | 210 | } |
211 | return ret; | 211 | return ret; |
212 | } | 212 | } |
213 | 213 | ||
214 | 214 | ||
215 | /*! | 215 | /*! |
216 | parses the content of Variable blendfunc,alphafunc | 216 | parses the content of Variable blendfunc,alphafunc |
217 | it also make a hint for rendering as transparent or solid node. | 217 | it also make a hint for rendering as transparent or solid node. |
218 | 218 | ||
219 | we assume a typical quake scene would look like this.. | 219 | we assume a typical quake scene would look like this.. |
220 | 1) Big Static Mesh ( solid ) | 220 | 1) Big Static Mesh ( solid ) |
221 | 2) static scene item ( may use transparency ) but rendered in the solid pass | 221 | 2) static scene item ( may use transparency ) but rendered in the solid pass |
222 | 3) additional transparency item in the transparent pass | 222 | 3) additional transparency item in the transparent pass |
223 | 223 | ||
224 | it's not 100% accurate! it just empirical.. | 224 | it's not 100% accurate! it just empirical.. |
225 | */ | 225 | */ |
226 | inline static void getBlendFunc ( const core::stringc &string, SBlendFunc &blendfunc ) | 226 | inline static void getBlendFunc ( const core::stringc &string, SBlendFunc &blendfunc ) |
227 | { | 227 | { |
228 | if ( string.size() == 0 ) | 228 | if ( string.size() == 0 ) |
229 | return; | 229 | return; |
230 | 230 | ||
231 | // maps to E_BLEND_FACTOR | 231 | // maps to E_BLEND_FACTOR |
232 | static const c8 * funclist[] = | 232 | static const c8 * funclist[] = |
233 | { | 233 | { |
234 | "gl_zero", | 234 | "gl_zero", |
235 | "gl_one", | 235 | "gl_one", |
236 | "gl_dst_color", | 236 | "gl_dst_color", |
237 | "gl_one_minus_dst_color", | 237 | "gl_one_minus_dst_color", |
238 | "gl_src_color", | 238 | "gl_src_color", |
239 | "gl_one_minus_src_color", | 239 | "gl_one_minus_src_color", |
240 | "gl_src_alpha", | 240 | "gl_src_alpha", |
241 | "gl_one_minus_src_alpha", | 241 | "gl_one_minus_src_alpha", |
242 | "gl_dst_alpha", | 242 | "gl_dst_alpha", |
243 | "gl_one_minus_dst_alpha", | 243 | "gl_one_minus_dst_alpha", |
244 | "gl_src_alpha_sat", | 244 | "gl_src_alpha_sat", |
245 | 245 | ||
246 | "add", | 246 | "add", |
247 | "filter", | 247 | "filter", |
248 | "blend", | 248 | "blend", |
249 | 249 | ||
250 | "ge128", | 250 | "ge128", |
251 | "gt0", | 251 | "gt0", |
252 | }; | 252 | }; |
253 | 253 | ||
254 | 254 | ||
255 | u32 pos = 0; | 255 | u32 pos = 0; |
256 | s32 srcFact = isEqual ( string, pos, funclist, 16 ); | 256 | s32 srcFact = isEqual ( string, pos, funclist, 16 ); |
257 | 257 | ||
258 | if ( srcFact < 0 ) | 258 | if ( srcFact < 0 ) |
259 | return; | 259 | return; |
260 | 260 | ||
261 | u32 resolved = 0; | 261 | u32 resolved = 0; |
262 | s32 dstFact = isEqual ( string, pos, funclist, 16 ); | 262 | s32 dstFact = isEqual ( string, pos, funclist, 16 ); |
263 | 263 | ||
264 | switch ( srcFact ) | 264 | switch ( srcFact ) |
265 | { | 265 | { |
266 | case video::EBF_ZERO: | 266 | case video::EBF_ZERO: |
267 | switch ( dstFact ) | 267 | switch ( dstFact ) |
268 | { | 268 | { |
269 | // gl_zero gl_src_color == gl_dst_color gl_zero | 269 | // gl_zero gl_src_color == gl_dst_color gl_zero |
270 | case video::EBF_SRC_COLOR: | 270 | case video::EBF_SRC_COLOR: |
271 | blendfunc.type = video::EMT_ONETEXTURE_BLEND; | 271 | blendfunc.type = video::EMT_ONETEXTURE_BLEND; |
272 | blendfunc.param0 = video::pack_textureBlendFunc ( video::EBF_DST_COLOR, video::EBF_ZERO, blendfunc.modulate ); | 272 | blendfunc.param0 = video::pack_textureBlendFunc ( video::EBF_DST_COLOR, video::EBF_ZERO, blendfunc.modulate ); |
273 | blendfunc.isTransparent = 1; | 273 | blendfunc.isTransparent = 1; |
274 | resolved = 1; | 274 | resolved = 1; |
275 | break; | 275 | break; |
276 | } break; | 276 | } break; |
277 | 277 | ||
278 | case video::EBF_ONE: | 278 | case video::EBF_ONE: |
279 | switch ( dstFact ) | 279 | switch ( dstFact ) |
280 | { | 280 | { |
281 | // gl_one gl_zero | 281 | // gl_one gl_zero |
282 | case video::EBF_ZERO: | 282 | case video::EBF_ZERO: |
283 | blendfunc.type = video::EMT_SOLID; | 283 | blendfunc.type = video::EMT_SOLID; |
284 | blendfunc.isTransparent = 0; | 284 | blendfunc.isTransparent = 0; |
285 | resolved = 1; | 285 | resolved = 1; |
286 | break; | 286 | break; |
287 | 287 | ||
288 | // gl_one gl_one | 288 | // gl_one gl_one |
289 | case video::EBF_ONE: | 289 | case video::EBF_ONE: |
290 | blendfunc.type = video::EMT_TRANSPARENT_ADD_COLOR; | 290 | blendfunc.type = video::EMT_TRANSPARENT_ADD_COLOR; |
291 | blendfunc.isTransparent = 1; | 291 | blendfunc.isTransparent = 1; |
292 | resolved = 1; | 292 | resolved = 1; |
293 | break; | 293 | break; |
294 | } break; | 294 | } break; |
295 | 295 | ||
296 | case video::EBF_SRC_ALPHA: | 296 | case video::EBF_SRC_ALPHA: |
297 | switch ( dstFact ) | 297 | switch ( dstFact ) |
298 | { | 298 | { |
299 | // gl_src_alpha gl_one_minus_src_alpha | 299 | // gl_src_alpha gl_one_minus_src_alpha |
300 | case video::EBF_ONE_MINUS_SRC_ALPHA: | 300 | case video::EBF_ONE_MINUS_SRC_ALPHA: |
301 | blendfunc.type = video::EMT_TRANSPARENT_ALPHA_CHANNEL; | 301 | blendfunc.type = video::EMT_TRANSPARENT_ALPHA_CHANNEL; |
302 | blendfunc.param0 = 1.f/255.f; | 302 | blendfunc.param0 = 1.f/255.f; |
303 | blendfunc.isTransparent = 1; | 303 | blendfunc.isTransparent = 1; |
304 | resolved = 1; | 304 | resolved = 1; |
305 | break; | 305 | break; |
306 | } break; | 306 | } break; |
307 | 307 | ||
308 | case 11: | 308 | case 11: |
309 | // add | 309 | // add |
310 | blendfunc.type = video::EMT_TRANSPARENT_ADD_COLOR; | 310 | blendfunc.type = video::EMT_TRANSPARENT_ADD_COLOR; |
311 | blendfunc.isTransparent = 1; | 311 | blendfunc.isTransparent = 1; |
312 | resolved = 1; | 312 | resolved = 1; |
313 | break; | 313 | break; |
314 | case 12: | 314 | case 12: |
315 | // filter = gl_dst_color gl_zero or gl_zero gl_src_color | 315 | // filter = gl_dst_color gl_zero or gl_zero gl_src_color |
316 | blendfunc.type = video::EMT_ONETEXTURE_BLEND; | 316 | blendfunc.type = video::EMT_ONETEXTURE_BLEND; |
317 | blendfunc.param0 = video::pack_textureBlendFunc ( video::EBF_DST_COLOR, video::EBF_ZERO, blendfunc.modulate ); | 317 | blendfunc.param0 = video::pack_textureBlendFunc ( video::EBF_DST_COLOR, video::EBF_ZERO, blendfunc.modulate ); |
318 | blendfunc.isTransparent = 1; | 318 | blendfunc.isTransparent = 1; |
319 | resolved = 1; | 319 | resolved = 1; |
320 | break; | 320 | break; |
321 | case 13: | 321 | case 13: |
322 | // blend = gl_src_alpha gl_one_minus_src_alpha | 322 | // blend = gl_src_alpha gl_one_minus_src_alpha |
323 | blendfunc.type = video::EMT_TRANSPARENT_ALPHA_CHANNEL; | 323 | blendfunc.type = video::EMT_TRANSPARENT_ALPHA_CHANNEL; |
324 | blendfunc.param0 = 1.f/255.f; | 324 | blendfunc.param0 = 1.f/255.f; |
325 | blendfunc.isTransparent = 1; | 325 | blendfunc.isTransparent = 1; |
326 | resolved = 1; | 326 | resolved = 1; |
327 | break; | 327 | break; |
328 | case 14: | 328 | case 14: |
329 | // alphafunc ge128 | 329 | // alphafunc ge128 |
330 | blendfunc.type = video::EMT_TRANSPARENT_ALPHA_CHANNEL; | 330 | blendfunc.type = video::EMT_TRANSPARENT_ALPHA_CHANNEL; |
331 | blendfunc.param0 = 0.5f; | 331 | blendfunc.param0 = 0.5f; |
332 | blendfunc.isTransparent = 1; | 332 | blendfunc.isTransparent = 1; |
333 | resolved = 1; | 333 | resolved = 1; |
334 | break; | 334 | break; |
335 | case 15: | 335 | case 15: |
336 | // alphafunc gt0 | 336 | // alphafunc gt0 |
337 | blendfunc.type = video::EMT_TRANSPARENT_ALPHA_CHANNEL; | 337 | blendfunc.type = video::EMT_TRANSPARENT_ALPHA_CHANNEL; |
338 | blendfunc.param0 = 1.f / 255.f; | 338 | blendfunc.param0 = 1.f / 255.f; |
339 | blendfunc.isTransparent = 1; | 339 | blendfunc.isTransparent = 1; |
340 | resolved = 1; | 340 | resolved = 1; |
341 | break; | 341 | break; |
342 | 342 | ||
343 | } | 343 | } |
344 | 344 | ||
345 | // use the generic blender | 345 | // use the generic blender |
346 | if ( 0 == resolved ) | 346 | if ( 0 == resolved ) |
347 | { | 347 | { |
348 | blendfunc.type = video::EMT_ONETEXTURE_BLEND; | 348 | blendfunc.type = video::EMT_ONETEXTURE_BLEND; |
349 | blendfunc.param0 = video::pack_textureBlendFunc ( | 349 | blendfunc.param0 = video::pack_textureBlendFunc ( |
350 | (video::E_BLEND_FACTOR) srcFact, | 350 | (video::E_BLEND_FACTOR) srcFact, |
351 | (video::E_BLEND_FACTOR) dstFact, | 351 | (video::E_BLEND_FACTOR) dstFact, |
352 | blendfunc.modulate); | 352 | blendfunc.modulate); |
353 | 353 | ||
354 | blendfunc.isTransparent = 1; | 354 | blendfunc.isTransparent = 1; |
355 | } | 355 | } |
356 | } | 356 | } |
357 | 357 | ||
358 | // random noise [-1;1] | 358 | // random noise [-1;1] |
359 | struct Noiser | 359 | struct Noiser |
360 | { | 360 | { |
361 | static f32 get () | 361 | static f32 get () |
362 | { | 362 | { |
363 | static u32 RandomSeed = 0x69666966; | 363 | static u32 RandomSeed = 0x69666966; |
364 | RandomSeed = (RandomSeed * 3631 + 1); | 364 | RandomSeed = (RandomSeed * 3631 + 1); |
365 | 365 | ||
366 | f32 value = ( (f32) (RandomSeed & 0x7FFF ) * (1.0f / (f32)(0x7FFF >> 1) ) ) - 1.f; | 366 | f32 value = ( (f32) (RandomSeed & 0x7FFF ) * (1.0f / (f32)(0x7FFF >> 1) ) ) - 1.f; |
367 | return value; | 367 | return value; |
368 | } | 368 | } |
369 | }; | 369 | }; |
370 | 370 | ||
371 | enum eQ3ModifierFunction | 371 | enum eQ3ModifierFunction |
372 | { | 372 | { |
373 | TCMOD = 0, | 373 | TCMOD = 0, |
374 | DEFORMVERTEXES = 1, | 374 | DEFORMVERTEXES = 1, |
375 | RGBGEN = 2, | 375 | RGBGEN = 2, |
376 | TCGEN = 3, | 376 | TCGEN = 3, |
377 | MAP = 4, | 377 | MAP = 4, |
378 | ALPHAGEN = 5, | 378 | ALPHAGEN = 5, |
379 | 379 | ||
380 | FUNCTION2 = 0x10, | 380 | FUNCTION2 = 0x10, |
381 | SCROLL = FUNCTION2 + 1, | 381 | SCROLL = FUNCTION2 + 1, |
382 | SCALE = FUNCTION2 + 2, | 382 | SCALE = FUNCTION2 + 2, |
383 | ROTATE = FUNCTION2 + 3, | 383 | ROTATE = FUNCTION2 + 3, |
384 | STRETCH = FUNCTION2 + 4, | 384 | STRETCH = FUNCTION2 + 4, |
385 | TURBULENCE = FUNCTION2 + 5, | 385 | TURBULENCE = FUNCTION2 + 5, |
386 | WAVE = FUNCTION2 + 6, | 386 | WAVE = FUNCTION2 + 6, |
387 | 387 | ||
388 | IDENTITY = FUNCTION2 + 7, | 388 | IDENTITY = FUNCTION2 + 7, |
389 | VERTEX = FUNCTION2 + 8, | 389 | VERTEX = FUNCTION2 + 8, |
390 | TEXTURE = FUNCTION2 + 9, | 390 | TEXTURE = FUNCTION2 + 9, |
391 | LIGHTMAP = FUNCTION2 + 10, | 391 | LIGHTMAP = FUNCTION2 + 10, |
392 | ENVIRONMENT = FUNCTION2 + 11, | 392 | ENVIRONMENT = FUNCTION2 + 11, |
393 | DOLLAR_LIGHTMAP = FUNCTION2 + 12, | 393 | DOLLAR_LIGHTMAP = FUNCTION2 + 12, |
394 | BULGE = FUNCTION2 + 13, | 394 | BULGE = FUNCTION2 + 13, |
395 | AUTOSPRITE = FUNCTION2 + 14, | 395 | AUTOSPRITE = FUNCTION2 + 14, |
396 | AUTOSPRITE2 = FUNCTION2 + 15, | 396 | AUTOSPRITE2 = FUNCTION2 + 15, |
397 | TRANSFORM = FUNCTION2 + 16, | 397 | TRANSFORM = FUNCTION2 + 16, |
398 | EXACTVERTEX = FUNCTION2 + 17, | 398 | EXACTVERTEX = FUNCTION2 + 17, |
399 | CONSTANT = FUNCTION2 + 18, | 399 | CONSTANT = FUNCTION2 + 18, |
400 | LIGHTINGSPECULAR = FUNCTION2 + 19, | 400 | LIGHTINGSPECULAR = FUNCTION2 + 19, |
401 | MOVE = FUNCTION2 + 20, | 401 | MOVE = FUNCTION2 + 20, |
402 | NORMAL = FUNCTION2 + 21, | 402 | NORMAL = FUNCTION2 + 21, |
403 | IDENTITYLIGHTING = FUNCTION2 + 22, | 403 | IDENTITYLIGHTING = FUNCTION2 + 22, |
404 | 404 | ||
405 | WAVE_MODIFIER_FUNCTION = 0x30, | 405 | WAVE_MODIFIER_FUNCTION = 0x30, |
406 | SINUS = WAVE_MODIFIER_FUNCTION + 1, | 406 | SINUS = WAVE_MODIFIER_FUNCTION + 1, |
407 | COSINUS = WAVE_MODIFIER_FUNCTION + 2, | 407 | COSINUS = WAVE_MODIFIER_FUNCTION + 2, |
408 | SQUARE = WAVE_MODIFIER_FUNCTION + 3, | 408 | SQUARE = WAVE_MODIFIER_FUNCTION + 3, |
409 | TRIANGLE = WAVE_MODIFIER_FUNCTION + 4, | 409 | TRIANGLE = WAVE_MODIFIER_FUNCTION + 4, |
410 | SAWTOOTH = WAVE_MODIFIER_FUNCTION + 5, | 410 | SAWTOOTH = WAVE_MODIFIER_FUNCTION + 5, |
411 | SAWTOOTH_INVERSE = WAVE_MODIFIER_FUNCTION + 6, | 411 | SAWTOOTH_INVERSE = WAVE_MODIFIER_FUNCTION + 6, |
412 | NOISE = WAVE_MODIFIER_FUNCTION + 7, | 412 | NOISE = WAVE_MODIFIER_FUNCTION + 7, |
413 | 413 | ||
414 | 414 | ||
415 | UNKNOWN = -2 | 415 | UNKNOWN = -2 |
416 | 416 | ||
417 | }; | 417 | }; |
418 | 418 | ||
419 | struct SModifierFunction | 419 | struct SModifierFunction |
420 | { | 420 | { |
421 | SModifierFunction () | 421 | SModifierFunction () |
422 | : masterfunc0 ( UNKNOWN ), masterfunc1( UNKNOWN ), func ( SINUS ), | 422 | : masterfunc0 ( UNKNOWN ), masterfunc1( UNKNOWN ), func ( SINUS ), |
423 | tcgen( TEXTURE ), rgbgen ( IDENTITY ), alphagen ( UNKNOWN ), | 423 | tcgen( TEXTURE ), rgbgen ( IDENTITY ), alphagen ( UNKNOWN ), |
424 | base ( 0 ), amp ( 1 ), phase ( 0 ), frequency ( 1 ), | 424 | base ( 0 ), amp ( 1 ), phase ( 0 ), frequency ( 1 ), |
425 | wave ( 1 ), | 425 | wave ( 1 ), |
426 | x ( 0 ), y ( 0 ), z( 0 ), count( 0 ) {} | 426 | x ( 0 ), y ( 0 ), z( 0 ), count( 0 ) {} |
427 | 427 | ||
428 | // "tcmod","deformvertexes","rgbgen", "tcgen" | 428 | // "tcmod","deformvertexes","rgbgen", "tcgen" |
429 | eQ3ModifierFunction masterfunc0; | 429 | eQ3ModifierFunction masterfunc0; |
430 | // depends | 430 | // depends |
431 | eQ3ModifierFunction masterfunc1; | 431 | eQ3ModifierFunction masterfunc1; |
432 | // depends | 432 | // depends |
433 | eQ3ModifierFunction func; | 433 | eQ3ModifierFunction func; |
434 | 434 | ||
435 | eQ3ModifierFunction tcgen; | 435 | eQ3ModifierFunction tcgen; |
436 | eQ3ModifierFunction rgbgen; | 436 | eQ3ModifierFunction rgbgen; |
437 | eQ3ModifierFunction alphagen; | 437 | eQ3ModifierFunction alphagen; |
438 | 438 | ||
439 | union | 439 | union |
440 | { | 440 | { |
441 | f32 base; | 441 | f32 base; |
442 | f32 bulgewidth; | 442 | f32 bulgewidth; |
443 | }; | 443 | }; |
444 | 444 | ||
445 | union | 445 | union |
446 | { | 446 | { |
447 | f32 amp; | 447 | f32 amp; |
448 | f32 bulgeheight; | 448 | f32 bulgeheight; |
449 | }; | 449 | }; |
450 | 450 | ||
451 | f32 phase; | 451 | f32 phase; |
452 | 452 | ||
453 | union | 453 | union |
454 | { | 454 | { |
455 | f32 frequency; | 455 | f32 frequency; |
456 | f32 bulgespeed; | 456 | f32 bulgespeed; |
457 | }; | 457 | }; |
458 | 458 | ||
459 | union | 459 | union |
460 | { | 460 | { |
461 | f32 wave; | 461 | f32 wave; |
462 | f32 div; | 462 | f32 div; |
463 | }; | 463 | }; |
464 | 464 | ||
465 | f32 x; | 465 | f32 x; |
466 | f32 y; | 466 | f32 y; |
467 | f32 z; | 467 | f32 z; |
468 | u32 count; | 468 | u32 count; |
469 | 469 | ||
470 | f32 evaluate ( f32 dt ) const | 470 | f32 evaluate ( f32 dt ) const |
471 | { | 471 | { |
472 | // phase in 0 and 1.. | 472 | // phase in 0 and 1.. |
473 | f32 x = core::fract( (dt + phase ) * frequency ); | 473 | f32 x = core::fract( (dt + phase ) * frequency ); |
474 | f32 y = 0.f; | 474 | f32 y = 0.f; |
475 | 475 | ||
476 | switch ( func ) | 476 | switch ( func ) |
477 | { | 477 | { |
478 | case SINUS: | 478 | case SINUS: |
479 | y = sinf ( x * core::PI * 2.f ); | 479 | y = sinf ( x * core::PI * 2.f ); |
480 | break; | 480 | break; |
481 | case COSINUS: | 481 | case COSINUS: |
482 | y = cosf ( x * core::PI * 2.f ); | 482 | y = cosf ( x * core::PI * 2.f ); |
483 | break; | 483 | break; |
484 | case SQUARE: | 484 | case SQUARE: |
485 | y = x < 0.5f ? 1.f : -1.f; | 485 | y = x < 0.5f ? 1.f : -1.f; |
486 | break; | 486 | break; |
487 | case TRIANGLE: | 487 | case TRIANGLE: |
488 | y = x < 0.5f ? ( 4.f * x ) - 1.f : ( -4.f * x ) + 3.f; | 488 | y = x < 0.5f ? ( 4.f * x ) - 1.f : ( -4.f * x ) + 3.f; |
489 | break; | 489 | break; |
490 | case SAWTOOTH: | 490 | case SAWTOOTH: |
491 | y = x; | 491 | y = x; |
492 | break; | 492 | break; |
493 | case SAWTOOTH_INVERSE: | 493 | case SAWTOOTH_INVERSE: |
494 | y = 1.f - x; | 494 | y = 1.f - x; |
495 | break; | 495 | break; |
496 | case NOISE: | 496 | case NOISE: |
497 | y = Noiser::get(); | 497 | y = Noiser::get(); |
498 | break; | 498 | break; |
499 | default: | 499 | default: |
500 | break; | 500 | break; |
501 | } | 501 | } |
502 | 502 | ||
503 | return base + ( y * amp ); | 503 | return base + ( y * amp ); |
504 | } | 504 | } |
505 | 505 | ||
506 | 506 | ||
507 | }; | 507 | }; |
508 | 508 | ||
509 | inline core::vector3df getMD3Normal ( u32 i, u32 j ) | 509 | inline core::vector3df getMD3Normal ( u32 i, u32 j ) |
510 | { | 510 | { |
511 | const f32 lng = i * 2.0f * core::PI / 255.0f; | 511 | const f32 lng = i * 2.0f * core::PI / 255.0f; |
512 | const f32 lat = j * 2.0f * core::PI / 255.0f; | 512 | const f32 lat = j * 2.0f * core::PI / 255.0f; |
513 | return core::vector3df(cosf ( lat ) * sinf ( lng ), | 513 | return core::vector3df(cosf ( lat ) * sinf ( lng ), |
514 | sinf ( lat ) * sinf ( lng ), | 514 | sinf ( lat ) * sinf ( lng ), |
515 | cosf ( lng )); | 515 | cosf ( lng )); |
516 | } | 516 | } |
517 | 517 | ||
518 | // | 518 | // |
519 | inline void getModifierFunc ( SModifierFunction& fill, const core::stringc &string, u32 &pos ) | 519 | inline void getModifierFunc ( SModifierFunction& fill, const core::stringc &string, u32 &pos ) |
520 | { | 520 | { |
521 | if ( string.size() == 0 ) | 521 | if ( string.size() == 0 ) |
522 | return; | 522 | return; |
523 | 523 | ||
524 | static const c8 * funclist[] = | 524 | static const c8 * funclist[] = |
525 | { | 525 | { |
526 | "sin","cos","square", | 526 | "sin","cos","square", |
527 | "triangle", "sawtooth","inversesawtooth", "noise" | 527 | "triangle", "sawtooth","inversesawtooth", "noise" |
528 | }; | 528 | }; |
529 | 529 | ||
530 | fill.func = (eQ3ModifierFunction) isEqual ( string,pos, funclist,7 ); | 530 | fill.func = (eQ3ModifierFunction) isEqual ( string,pos, funclist,7 ); |
531 | fill.func = fill.func == UNKNOWN ? SINUS : (eQ3ModifierFunction) ((u32) fill.func + WAVE_MODIFIER_FUNCTION + 1); | 531 | fill.func = fill.func == UNKNOWN ? SINUS : (eQ3ModifierFunction) ((u32) fill.func + WAVE_MODIFIER_FUNCTION + 1); |
532 | 532 | ||
533 | fill.base = getAsFloat ( string, pos ); | 533 | fill.base = getAsFloat ( string, pos ); |
534 | fill.amp = getAsFloat ( string, pos ); | 534 | fill.amp = getAsFloat ( string, pos ); |
535 | fill.phase = getAsFloat ( string, pos ); | 535 | fill.phase = getAsFloat ( string, pos ); |
536 | fill.frequency = getAsFloat ( string, pos ); | 536 | fill.frequency = getAsFloat ( string, pos ); |
537 | } | 537 | } |
538 | 538 | ||
539 | 539 | ||
540 | // name = "a b c .." | 540 | // name = "a b c .." |
541 | struct SVariable | 541 | struct SVariable |
542 | { | 542 | { |
543 | core::stringc name; | 543 | core::stringc name; |
544 | core::stringc content; | 544 | core::stringc content; |
545 | 545 | ||
546 | SVariable ( const c8 * n, const c8 *c = 0 ) : name ( n ), content (c) {} | 546 | SVariable ( const c8 * n, const c8 *c = 0 ) : name ( n ), content (c) {} |
547 | virtual ~SVariable () {} | 547 | virtual ~SVariable () {} |
548 | 548 | ||
549 | void clear () | 549 | void clear () |
550 | { | 550 | { |
551 | name = ""; | 551 | name = ""; |
552 | content = ""; | 552 | content = ""; |
553 | } | 553 | } |
554 | 554 | ||
555 | s32 isValid () const | 555 | s32 isValid () const |
556 | { | 556 | { |
557 | return name.size(); | 557 | return name.size(); |
558 | } | 558 | } |
559 | 559 | ||
560 | bool operator == ( const SVariable &other ) const | 560 | bool operator == ( const SVariable &other ) const |
561 | { | 561 | { |
562 | return 0 == strcmp ( name.c_str(), other.name.c_str () ); | 562 | return 0 == strcmp ( name.c_str(), other.name.c_str () ); |
563 | } | 563 | } |
564 | 564 | ||
565 | bool operator < ( const SVariable &other ) const | 565 | bool operator < ( const SVariable &other ) const |
566 | { | 566 | { |
567 | return 0 > strcmp ( name.c_str(), other.name.c_str () ); | 567 | return 0 > strcmp ( name.c_str(), other.name.c_str () ); |
568 | } | 568 | } |
569 | 569 | ||
570 | }; | 570 | }; |
571 | 571 | ||
572 | 572 | ||
573 | // string database. "a" = "Hello", "b" = "1234.6" | 573 | // string database. "a" = "Hello", "b" = "1234.6" |
574 | struct SVarGroup | 574 | struct SVarGroup |
575 | { | 575 | { |
576 | SVarGroup () { Variable.setAllocStrategy ( core::ALLOC_STRATEGY_SAFE ); } | 576 | SVarGroup () { Variable.setAllocStrategy ( core::ALLOC_STRATEGY_SAFE ); } |
577 | virtual ~SVarGroup () {} | 577 | virtual ~SVarGroup () {} |
578 | 578 | ||
579 | u32 isDefined ( const c8 * name, const c8 * content = 0 ) const | 579 | u32 isDefined ( const c8 * name, const c8 * content = 0 ) const |
580 | { | 580 | { |
581 | for ( u32 i = 0; i != Variable.size (); ++i ) | 581 | for ( u32 i = 0; i != Variable.size (); ++i ) |
582 | { | 582 | { |
583 | if ( 0 == strcmp ( Variable[i].name.c_str(), name ) && | 583 | if ( 0 == strcmp ( Variable[i].name.c_str(), name ) && |
584 | ( 0 == content || strstr ( Variable[i].content.c_str(), content ) ) | 584 | ( 0 == content || strstr ( Variable[i].content.c_str(), content ) ) |
585 | ) | 585 | ) |
586 | { | 586 | { |
587 | return i + 1; | 587 | return i + 1; |
588 | } | 588 | } |
589 | } | 589 | } |
590 | return 0; | 590 | return 0; |
591 | } | 591 | } |
592 | 592 | ||
593 | // searches for Variable name and returns is content | 593 | // searches for Variable name and returns is content |
594 | // if Variable is not found a reference to an Empty String is returned | 594 | // if Variable is not found a reference to an Empty String is returned |
595 | const core::stringc &get( const c8 * name ) const | 595 | const core::stringc &get( const c8 * name ) const |
596 | { | 596 | { |
597 | SVariable search ( name ); | 597 | SVariable search ( name ); |
598 | s32 index = Variable.linear_search ( search ); | 598 | s32 index = Variable.linear_search ( search ); |
599 | if ( index < 0 ) | 599 | if ( index < 0 ) |
600 | return irrEmptyStringc; | 600 | return irrEmptyStringc; |
601 | 601 | ||
602 | return Variable [ index ].content; | 602 | return Variable [ index ].content; |
603 | } | 603 | } |
604 | 604 | ||
605 | // set the Variable name | 605 | // set the Variable name |
606 | void set ( const c8 * name, const c8 * content = 0 ) | 606 | void set ( const c8 * name, const c8 * content = 0 ) |
607 | { | 607 | { |
608 | u32 index = isDefined ( name, 0 ); | 608 | u32 index = isDefined ( name, 0 ); |
609 | if ( 0 == index ) | 609 | if ( 0 == index ) |
610 | { | 610 | { |
611 | Variable.push_back ( SVariable ( name, content ) ); | 611 | Variable.push_back ( SVariable ( name, content ) ); |
612 | } | 612 | } |
613 | else | 613 | else |
614 | { | 614 | { |
615 | Variable [ index ].content = content; | 615 | Variable [ index ].content = content; |
616 | } | 616 | } |
617 | } | 617 | } |
618 | 618 | ||
619 | 619 | ||
620 | core::array < SVariable > Variable; | 620 | core::array < SVariable > Variable; |
621 | }; | 621 | }; |
622 | 622 | ||
623 | //! holding a group a variable | 623 | //! holding a group a variable |
624 | struct SVarGroupList: public IReferenceCounted | 624 | struct SVarGroupList: public IReferenceCounted |
625 | { | 625 | { |
626 | SVarGroupList () | 626 | SVarGroupList () |
627 | { | 627 | { |
628 | VariableGroup.setAllocStrategy ( core::ALLOC_STRATEGY_SAFE ); | 628 | VariableGroup.setAllocStrategy ( core::ALLOC_STRATEGY_SAFE ); |
629 | } | 629 | } |
630 | virtual ~SVarGroupList () {} | 630 | virtual ~SVarGroupList () {} |
631 | 631 | ||
632 | core::array < SVarGroup > VariableGroup; | 632 | core::array < SVarGroup > VariableGroup; |
633 | }; | 633 | }; |
634 | 634 | ||
635 | 635 | ||
636 | //! A Parsed Shader Holding Variables ordered in Groups | 636 | //! A Parsed Shader Holding Variables ordered in Groups |
637 | struct IShader | 637 | struct IShader |
638 | { | 638 | { |
639 | IShader () | 639 | IShader () |
640 | : ID ( 0 ), VarGroup ( 0 ) {} | 640 | : ID ( 0 ), VarGroup ( 0 ) {} |
641 | virtual ~IShader () {} | 641 | virtual ~IShader () {} |
642 | 642 | ||
643 | void operator = (const IShader &other ) | 643 | void operator = (const IShader &other ) |
644 | { | 644 | { |
645 | ID = other.ID; | 645 | ID = other.ID; |
646 | VarGroup = other.VarGroup; | 646 | VarGroup = other.VarGroup; |
647 | name = other.name; | 647 | name = other.name; |
648 | } | 648 | } |
649 | 649 | ||
650 | bool operator == (const IShader &other ) const | 650 | bool operator == (const IShader &other ) const |
651 | { | 651 | { |
652 | return 0 == strcmp ( name.c_str(), other.name.c_str () ); | 652 | return 0 == strcmp ( name.c_str(), other.name.c_str () ); |
653 | //return name == other.name; | 653 | //return name == other.name; |
654 | } | 654 | } |
655 | 655 | ||
656 | bool operator < (const IShader &other ) const | 656 | bool operator < (const IShader &other ) const |
657 | { | 657 | { |
658 | return strcmp ( name.c_str(), other.name.c_str () ) < 0; | 658 | return strcmp ( name.c_str(), other.name.c_str () ) < 0; |
659 | //return name < other.name; | 659 | //return name < other.name; |
660 | } | 660 | } |
661 | 661 | ||
662 | u32 getGroupSize () const | 662 | u32 getGroupSize () const |
663 | { | 663 | { |
664 | if ( 0 == VarGroup ) | 664 | if ( 0 == VarGroup ) |
665 | return 0; | 665 | return 0; |
666 | return VarGroup->VariableGroup.size (); | 666 | return VarGroup->VariableGroup.size (); |
667 | } | 667 | } |
668 | 668 | ||
669 | const SVarGroup * getGroup ( u32 stage ) const | 669 | const SVarGroup * getGroup ( u32 stage ) const |
670 | { | 670 | { |
671 | if ( 0 == VarGroup || stage >= VarGroup->VariableGroup.size () ) | 671 | if ( 0 == VarGroup || stage >= VarGroup->VariableGroup.size () ) |
672 | return 0; | 672 | return 0; |
673 | 673 | ||
674 | return &VarGroup->VariableGroup [ stage ]; | 674 | return &VarGroup->VariableGroup [ stage ]; |
675 | } | 675 | } |
676 | 676 | ||
677 | // id | 677 | // id |
678 | s32 ID; | 678 | s32 ID; |
679 | SVarGroupList *VarGroup; // reference | 679 | SVarGroupList *VarGroup; // reference |
680 | 680 | ||
681 | // Shader: shader name ( also first variable in first Vargroup ) | 681 | // Shader: shader name ( also first variable in first Vargroup ) |
682 | // Entity: classname ( variable in Group(1) ) | 682 | // Entity: classname ( variable in Group(1) ) |
683 | core::stringc name; | 683 | core::stringc name; |
684 | }; | 684 | }; |
685 | 685 | ||
686 | typedef IShader IEntity; | 686 | typedef IShader IEntity; |
687 | 687 | ||
688 | typedef core::array < IEntity > tQ3EntityList; | 688 | typedef core::array < IEntity > tQ3EntityList; |
689 | 689 | ||
690 | /* | 690 | /* |
691 | dump shader like original layout, regardless of internal data holding | 691 | dump shader like original layout, regardless of internal data holding |
692 | no recursive folding.. | 692 | no recursive folding.. |
693 | */ | 693 | */ |
694 | inline void dumpVarGroup ( core::stringc &dest, const SVarGroup * group, s32 stack ) | 694 | inline void dumpVarGroup ( core::stringc &dest, const SVarGroup * group, s32 stack ) |
695 | { | 695 | { |
696 | core::stringc buf; | 696 | core::stringc buf; |
697 | s32 i; | 697 | s32 i; |
698 | 698 | ||
699 | 699 | ||
700 | if ( stack > 0 ) | 700 | if ( stack > 0 ) |
701 | { | 701 | { |
702 | buf = ""; | 702 | buf = ""; |
703 | for ( i = 0; i < stack - 1; ++i ) | 703 | for ( i = 0; i < stack - 1; ++i ) |
704 | buf += '\t'; | 704 | buf += '\t'; |
705 | 705 | ||
706 | buf += "{\n"; | 706 | buf += "{\n"; |
707 | dest.append ( buf ); | 707 | dest.append ( buf ); |
708 | } | 708 | } |
709 | 709 | ||
710 | for ( u32 g = 0; g != group->Variable.size(); ++g ) | 710 | for ( u32 g = 0; g != group->Variable.size(); ++g ) |
711 | { | 711 | { |
712 | buf = ""; | 712 | buf = ""; |
713 | for ( i = 0; i < stack; ++i ) | 713 | for ( i = 0; i < stack; ++i ) |
714 | buf += '\t'; | 714 | buf += '\t'; |
715 | 715 | ||
716 | buf += group->Variable[g].name; | 716 | buf += group->Variable[g].name; |
717 | buf += " "; | 717 | buf += " "; |
718 | buf += group->Variable[g].content; | 718 | buf += group->Variable[g].content; |
719 | buf += "\n"; | 719 | buf += "\n"; |
720 | dest.append ( buf ); | 720 | dest.append ( buf ); |
721 | } | 721 | } |
722 | 722 | ||
723 | if ( stack > 1 ) | 723 | if ( stack > 1 ) |
724 | { | 724 | { |
725 | buf = ""; | 725 | buf = ""; |
726 | for ( i = 0; i < stack - 1; ++i ) | 726 | for ( i = 0; i < stack - 1; ++i ) |
727 | buf += '\t'; | 727 | buf += '\t'; |
728 | 728 | ||
729 | buf += "}\n"; | 729 | buf += "}\n"; |
730 | dest.append ( buf ); | 730 | dest.append ( buf ); |
731 | } | 731 | } |
732 | 732 | ||
733 | } | 733 | } |
734 | 734 | ||
735 | /*! | 735 | /*! |
736 | dump a Shader or an Entity | 736 | dump a Shader or an Entity |
737 | */ | 737 | */ |
738 | inline core::stringc & dumpShader ( core::stringc &dest, const IShader * shader, bool entity = false ) | 738 | inline core::stringc & dumpShader ( core::stringc &dest, const IShader * shader, bool entity = false ) |
739 | { | 739 | { |
740 | if ( 0 == shader ) | 740 | if ( 0 == shader ) |
741 | return dest; | 741 | return dest; |
742 | 742 | ||
743 | const SVarGroup * group; | 743 | const SVarGroup * group; |
744 | 744 | ||
745 | const u32 size = shader->VarGroup->VariableGroup.size (); | 745 | const u32 size = shader->VarGroup->VariableGroup.size (); |
746 | for ( u32 i = 0; i != size; ++i ) | 746 | for ( u32 i = 0; i != size; ++i ) |
747 | { | 747 | { |
748 | group = &shader->VarGroup->VariableGroup[ i ]; | 748 | group = &shader->VarGroup->VariableGroup[ i ]; |
749 | dumpVarGroup ( dest, group, core::clamp( (int)i, 0, 2 ) ); | 749 | dumpVarGroup ( dest, group, core::clamp( (int)i, 0, 2 ) ); |
750 | } | 750 | } |
751 | 751 | ||
752 | if ( !entity ) | 752 | if ( !entity ) |
753 | { | 753 | { |
754 | if ( size <= 1 ) | 754 | if ( size <= 1 ) |
755 | { | 755 | { |
756 | dest.append ( "{\n" ); | 756 | dest.append ( "{\n" ); |
757 | } | 757 | } |
758 | dest.append ( "}\n" ); | 758 | dest.append ( "}\n" ); |
759 | } | 759 | } |
760 | return dest; | 760 | return dest; |
761 | } | 761 | } |
762 | 762 | ||
763 | 763 | ||
764 | /* | 764 | /* |
765 | quake3 doesn't care much about tga & jpg | 765 | quake3 doesn't care much about tga & jpg |
766 | load one or multiple files stored in name started at startPos to the texture array textures | 766 | load one or multiple files stored in name started at startPos to the texture array textures |
767 | if texture is not loaded 0 will be added ( to find missing textures easier) | 767 | if texture is not loaded 0 will be added ( to find missing textures easier) |
768 | */ | 768 | */ |
769 | inline void getTextures(tTexArray &textures, | 769 | inline void getTextures(tTexArray &textures, |
770 | const core::stringc &name, u32 &startPos, | 770 | const core::stringc &name, u32 &startPos, |
771 | io::IFileSystem *fileSystem, | 771 | io::IFileSystem *fileSystem, |
772 | video::IVideoDriver* driver) | 772 | video::IVideoDriver* driver) |
773 | { | 773 | { |
774 | static const char* extension[] = | 774 | static const char* extension[] = |
775 | { | 775 | { |
776 | ".jpg", | 776 | ".jpg", |
777 | ".jpeg", | 777 | ".jpeg", |
778 | ".png", | 778 | ".png", |
779 | ".dds", | 779 | ".dds", |
780 | ".tga", | 780 | ".tga", |
781 | ".bmp", | 781 | ".bmp", |
782 | ".pcx" | 782 | ".pcx" |
783 | }; | 783 | }; |
784 | 784 | ||
785 | tStringList stringList; | 785 | tStringList stringList; |
786 | getAsStringList(stringList, -1, name, startPos); | 786 | getAsStringList(stringList, -1, name, startPos); |
787 | 787 | ||
788 | textures.clear(); | 788 | textures.clear(); |
789 | 789 | ||
790 | io::path loadFile; | 790 | io::path loadFile; |
791 | for ( u32 i = 0; i!= stringList.size (); ++i ) | 791 | for ( u32 i = 0; i!= stringList.size (); ++i ) |
792 | { | 792 | { |
793 | video::ITexture* texture = 0; | 793 | video::ITexture* texture = 0; |
794 | for (u32 g = 0; g != 7 ; ++g) | 794 | for (u32 g = 0; g != 7 ; ++g) |
795 | { | 795 | { |
796 | core::cutFilenameExtension ( loadFile, stringList[i] ); | 796 | core::cutFilenameExtension ( loadFile, stringList[i] ); |
797 | 797 | ||
798 | if ( loadFile == "$whiteimage" ) | 798 | if ( loadFile == "$whiteimage" ) |
799 | { | 799 | { |
800 | texture = driver->getTexture( "$whiteimage" ); | 800 | texture = driver->getTexture( "$whiteimage" ); |
801 | if ( 0 == texture ) | 801 | if ( 0 == texture ) |
802 | { | 802 | { |
803 | core::dimension2du s ( 2, 2 ); | 803 | core::dimension2du s ( 2, 2 ); |
804 | u32 image[4] = { 0xFFFFFFFF, 0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF }; | 804 | u32 image[4] = { 0xFFFFFFFF, 0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF }; |
805 | video::IImage* w = driver->createImageFromData ( video::ECF_A8R8G8B8, s,&image ); | 805 | video::IImage* w = driver->createImageFromData ( video::ECF_A8R8G8B8, s,&image ); |
806 | texture = driver->addTexture( "$whiteimage", w ); | 806 | texture = driver->addTexture( "$whiteimage", w ); |
807 | w->drop (); | 807 | w->drop (); |
808 | } | 808 | } |
809 | 809 | ||
810 | } | 810 | } |
811 | else | 811 | else |
812 | if ( loadFile == "$redimage" ) | 812 | if ( loadFile == "$redimage" ) |
813 | { | 813 | { |
814 | texture = driver->getTexture( "$redimage" ); | 814 | texture = driver->getTexture( "$redimage" ); |
815 | if ( 0 == texture ) | 815 | if ( 0 == texture ) |
816 | { | 816 | { |
817 | core::dimension2du s ( 2, 2 ); | 817 | core::dimension2du s ( 2, 2 ); |
818 | u32 image[4] = { 0xFFFF0000, 0xFFFF0000,0xFFFF0000,0xFFFF0000 }; | 818 | u32 image[4] = { 0xFFFF0000, 0xFFFF0000,0xFFFF0000,0xFFFF0000 }; |
819 | video::IImage* w = driver->createImageFromData ( video::ECF_A8R8G8B8, s,&image ); | 819 | video::IImage* w = driver->createImageFromData ( video::ECF_A8R8G8B8, s,&image ); |
820 | texture = driver->addTexture( "$redimage", w ); | 820 | texture = driver->addTexture( "$redimage", w ); |
821 | w->drop (); | 821 | w->drop (); |
822 | } | 822 | } |
823 | } | 823 | } |
824 | else | 824 | else |
825 | if ( loadFile == "$blueimage" ) | 825 | if ( loadFile == "$blueimage" ) |
826 | { | 826 | { |
827 | texture = driver->getTexture( "$blueimage" ); | 827 | texture = driver->getTexture( "$blueimage" ); |
828 | if ( 0 == texture ) | 828 | if ( 0 == texture ) |
829 | { | 829 | { |
830 | core::dimension2du s ( 2, 2 ); | 830 | core::dimension2du s ( 2, 2 ); |
831 | u32 image[4] = { 0xFF0000FF, 0xFF0000FF,0xFF0000FF,0xFF0000FF }; | 831 | u32 image[4] = { 0xFF0000FF, 0xFF0000FF,0xFF0000FF,0xFF0000FF }; |
832 | video::IImage* w = driver->createImageFromData ( video::ECF_A8R8G8B8, s,&image ); | 832 | video::IImage* w = driver->createImageFromData ( video::ECF_A8R8G8B8, s,&image ); |
833 | texture = driver->addTexture( "$blueimage", w ); | 833 | texture = driver->addTexture( "$blueimage", w ); |
834 | w->drop (); | 834 | w->drop (); |
835 | } | 835 | } |
836 | } | 836 | } |
837 | else | 837 | else |
838 | if ( loadFile == "$checkerimage" ) | 838 | if ( loadFile == "$checkerimage" ) |
839 | { | 839 | { |
840 | texture = driver->getTexture( "$checkerimage" ); | 840 | texture = driver->getTexture( "$checkerimage" ); |
841 | if ( 0 == texture ) | 841 | if ( 0 == texture ) |
842 | { | 842 | { |
843 | core::dimension2du s ( 2, 2 ); | 843 | core::dimension2du s ( 2, 2 ); |
844 | u32 image[4] = { 0xFFFFFFFF, 0xFF000000,0xFF000000,0xFFFFFFFF }; | 844 | u32 image[4] = { 0xFFFFFFFF, 0xFF000000,0xFF000000,0xFFFFFFFF }; |
845 | video::IImage* w = driver->createImageFromData ( video::ECF_A8R8G8B8, s,&image ); | 845 | video::IImage* w = driver->createImageFromData ( video::ECF_A8R8G8B8, s,&image ); |
846 | texture = driver->addTexture( "$checkerimage", w ); | 846 | texture = driver->addTexture( "$checkerimage", w ); |
847 | w->drop (); | 847 | w->drop (); |
848 | } | 848 | } |
849 | } | 849 | } |
850 | else | 850 | else |
851 | if ( loadFile == "$lightmap" ) | 851 | if ( loadFile == "$lightmap" ) |
852 | { | 852 | { |
853 | texture = 0; | 853 | texture = 0; |
854 | } | 854 | } |
855 | else | 855 | else |
856 | { | 856 | { |
857 | loadFile.append ( extension[g] ); | 857 | loadFile.append ( extension[g] ); |
858 | } | 858 | } |
859 | 859 | ||
860 | if ( fileSystem->existFile ( loadFile ) ) | 860 | if ( fileSystem->existFile ( loadFile ) ) |
861 | { | 861 | { |
862 | texture = driver->getTexture( loadFile ); | 862 | texture = driver->getTexture( loadFile ); |
863 | if ( texture ) | 863 | if ( texture ) |
864 | break; | 864 | break; |
865 | texture = 0; | 865 | texture = 0; |
866 | } | 866 | } |
867 | } | 867 | } |
868 | // take 0 Texture | 868 | // take 0 Texture |
869 | textures.push_back(texture); | 869 | textures.push_back(texture); |
870 | } | 870 | } |
871 | } | 871 | } |
872 | 872 | ||
873 | 873 | ||
874 | //! Manages various Quake3 Shader Styles | 874 | //! Manages various Quake3 Shader Styles |
875 | class IShaderManager : public IReferenceCounted | 875 | class IShaderManager : public IReferenceCounted |
876 | { | 876 | { |
877 | }; | 877 | }; |
878 | 878 | ||
879 | } // end namespace quake3 | 879 | } // end namespace quake3 |
880 | } // end namespace scene | 880 | } // end namespace scene |
881 | } // end namespace irr | 881 | } // end namespace irr |
882 | 882 | ||
883 | #endif | 883 | #endif |
884 | 884 | ||