aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/libraries/irrlicht-1.8/source/Irrlicht/CQuake3ShaderSceneNode.cpp
diff options
context:
space:
mode:
authorDavid Walter Seikel2013-01-13 18:54:10 +1000
committerDavid Walter Seikel2013-01-13 18:54:10 +1000
commit959831f4ef5a3e797f576c3de08cd65032c997ad (patch)
treee7351908be5995f0b325b2ebeaa02d5a34b82583 /libraries/irrlicht-1.8/source/Irrlicht/CQuake3ShaderSceneNode.cpp
parentAdd info about changes to Irrlicht. (diff)
downloadSledjHamr-959831f4ef5a3e797f576c3de08cd65032c997ad.zip
SledjHamr-959831f4ef5a3e797f576c3de08cd65032c997ad.tar.gz
SledjHamr-959831f4ef5a3e797f576c3de08cd65032c997ad.tar.bz2
SledjHamr-959831f4ef5a3e797f576c3de08cd65032c997ad.tar.xz
Remove damned ancient DOS line endings from Irrlicht. Hopefully I did not go overboard.
Diffstat (limited to '')
-rw-r--r--libraries/irrlicht-1.8/source/Irrlicht/CQuake3ShaderSceneNode.cpp2752
1 files changed, 1376 insertions, 1376 deletions
diff --git a/libraries/irrlicht-1.8/source/Irrlicht/CQuake3ShaderSceneNode.cpp b/libraries/irrlicht-1.8/source/Irrlicht/CQuake3ShaderSceneNode.cpp
index 9219782..9f44a40 100644
--- a/libraries/irrlicht-1.8/source/Irrlicht/CQuake3ShaderSceneNode.cpp
+++ b/libraries/irrlicht-1.8/source/Irrlicht/CQuake3ShaderSceneNode.cpp
@@ -1,1376 +1,1376 @@
1// Copyright (C) 2002-2012 Thomas Alten / Nikolaus Gebhardt 1// Copyright (C) 2002-2012 Thomas Alten / Nikolaus Gebhardt
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#include "IrrCompileConfig.h" 5#include "IrrCompileConfig.h"
6 6
7#ifdef _IRR_COMPILE_WITH_BSP_LOADER_ 7#ifdef _IRR_COMPILE_WITH_BSP_LOADER_
8 8
9#include "CQuake3ShaderSceneNode.h" 9#include "CQuake3ShaderSceneNode.h"
10#include "ISceneManager.h" 10#include "ISceneManager.h"
11#include "IVideoDriver.h" 11#include "IVideoDriver.h"
12#include "ICameraSceneNode.h" 12#include "ICameraSceneNode.h"
13#include "SViewFrustum.h" 13#include "SViewFrustum.h"
14#include "IMeshManipulator.h" 14#include "IMeshManipulator.h"
15#include "SMesh.h" 15#include "SMesh.h"
16#include "IMaterialRenderer.h" 16#include "IMaterialRenderer.h"
17#include "CShadowVolumeSceneNode.h" 17#include "CShadowVolumeSceneNode.h"
18 18
19namespace irr 19namespace irr
20{ 20{
21namespace scene 21namespace scene
22{ 22{
23 23
24// who, if not you.. 24// who, if not you..
25using namespace quake3; 25using namespace quake3;
26 26
27/*! 27/*!
28*/ 28*/
29CQuake3ShaderSceneNode::CQuake3ShaderSceneNode( 29CQuake3ShaderSceneNode::CQuake3ShaderSceneNode(
30 scene::ISceneNode* parent, scene::ISceneManager* mgr,s32 id, 30 scene::ISceneNode* parent, scene::ISceneManager* mgr,s32 id,
31 io::IFileSystem *fileSystem, const scene::IMeshBuffer *original, 31 io::IFileSystem *fileSystem, const scene::IMeshBuffer *original,
32 const IShader * shader) 32 const IShader * shader)
33: scene::IMeshSceneNode(parent, mgr, id, 33: scene::IMeshSceneNode(parent, mgr, id,
34 core::vector3df(0.f, 0.f, 0.f), 34 core::vector3df(0.f, 0.f, 0.f),
35 core::vector3df(0.f, 0.f, 0.f), 35 core::vector3df(0.f, 0.f, 0.f),
36 core::vector3df(1.f, 1.f, 1.f)), 36 core::vector3df(1.f, 1.f, 1.f)),
37 Shader(shader), Mesh(0), Shadow(0), Original(0), MeshBuffer(0), TimeAbs(0.f) 37 Shader(shader), Mesh(0), Shadow(0), Original(0), MeshBuffer(0), TimeAbs(0.f)
38{ 38{
39 #ifdef _DEBUG 39 #ifdef _DEBUG
40 core::stringc dName = "CQuake3ShaderSceneNode "; 40 core::stringc dName = "CQuake3ShaderSceneNode ";
41 dName += Shader->name; 41 dName += Shader->name;
42 42
43 setDebugName( dName.c_str() ); 43 setDebugName( dName.c_str() );
44 #endif 44 #endif
45 45
46 // name the Scene Node 46 // name the Scene Node
47 this->Name = Shader->name; 47 this->Name = Shader->name;
48 48
49 // take lightmap vertex type 49 // take lightmap vertex type
50 MeshBuffer = new SMeshBuffer(); 50 MeshBuffer = new SMeshBuffer();
51 51
52 Mesh = new SMesh (); 52 Mesh = new SMesh ();
53 Mesh->addMeshBuffer ( MeshBuffer ); 53 Mesh->addMeshBuffer ( MeshBuffer );
54 MeshBuffer->drop (); 54 MeshBuffer->drop ();
55 55
56 //Original = new SMeshBufferLightMap(); 56 //Original = new SMeshBufferLightMap();
57 Original = (const scene::SMeshBufferLightMap*) original; 57 Original = (const scene::SMeshBufferLightMap*) original;
58 Original->grab(); 58 Original->grab();
59 59
60 // clone meshbuffer to modifiable buffer 60 // clone meshbuffer to modifiable buffer
61 cloneBuffer(MeshBuffer, Original, 61 cloneBuffer(MeshBuffer, Original,
62 Original->getMaterial().ColorMask != 0); 62 Original->getMaterial().ColorMask != 0);
63 63
64 // load all Textures in all stages 64 // load all Textures in all stages
65 loadTextures( fileSystem ); 65 loadTextures( fileSystem );
66 66
67 setAutomaticCulling( scene::EAC_OFF ); 67 setAutomaticCulling( scene::EAC_OFF );
68} 68}
69 69
70 70
71/*! 71/*!
72*/ 72*/
73CQuake3ShaderSceneNode::~CQuake3ShaderSceneNode() 73CQuake3ShaderSceneNode::~CQuake3ShaderSceneNode()
74{ 74{
75 if (Shadow) 75 if (Shadow)
76 Shadow->drop(); 76 Shadow->drop();
77 77
78 if (Mesh) 78 if (Mesh)
79 Mesh->drop(); 79 Mesh->drop();
80 80
81 if (Original) 81 if (Original)
82 Original->drop(); 82 Original->drop();
83} 83}
84 84
85 85
86 86
87/* 87/*
88 create single copies 88 create single copies
89*/ 89*/
90void CQuake3ShaderSceneNode::cloneBuffer( scene::SMeshBuffer *dest, const scene::SMeshBufferLightMap * buffer, bool translateCenter ) 90void CQuake3ShaderSceneNode::cloneBuffer( scene::SMeshBuffer *dest, const scene::SMeshBufferLightMap * buffer, bool translateCenter )
91{ 91{
92 dest->Material = buffer->Material; 92 dest->Material = buffer->Material;
93 dest->Indices = buffer->Indices; 93 dest->Indices = buffer->Indices;
94 94
95 const u32 vsize = buffer->Vertices.size(); 95 const u32 vsize = buffer->Vertices.size();
96 96
97 dest->Vertices.set_used( vsize ); 97 dest->Vertices.set_used( vsize );
98 for ( u32 i = 0; i!= vsize; ++i ) 98 for ( u32 i = 0; i!= vsize; ++i )
99 { 99 {
100 const video::S3DVertex2TCoords& src = buffer->Vertices[i]; 100 const video::S3DVertex2TCoords& src = buffer->Vertices[i];
101 video::S3DVertex &dst = dest->Vertices[i]; 101 video::S3DVertex &dst = dest->Vertices[i];
102 102
103 dst.Pos = src.Pos; 103 dst.Pos = src.Pos;
104 dst.Normal = src.Normal; 104 dst.Normal = src.Normal;
105 dst.Color = 0xFFFFFFFF; 105 dst.Color = 0xFFFFFFFF;
106 dst.TCoords = src.TCoords; 106 dst.TCoords = src.TCoords;
107 107
108 if ( i == 0 ) 108 if ( i == 0 )
109 dest->BoundingBox.reset ( src.Pos ); 109 dest->BoundingBox.reset ( src.Pos );
110 else 110 else
111 dest->BoundingBox.addInternalPoint ( src.Pos ); 111 dest->BoundingBox.addInternalPoint ( src.Pos );
112 } 112 }
113 113
114 // move the (temp) Mesh to a ScenePosititon 114 // move the (temp) Mesh to a ScenePosititon
115 // set Scene Node Position 115 // set Scene Node Position
116 116
117 if ( translateCenter ) 117 if ( translateCenter )
118 { 118 {
119 MeshOffset = dest->BoundingBox.getCenter(); 119 MeshOffset = dest->BoundingBox.getCenter();
120 setPosition( MeshOffset ); 120 setPosition( MeshOffset );
121 121
122 core::matrix4 m; 122 core::matrix4 m;
123 m.setTranslation( -MeshOffset ); 123 m.setTranslation( -MeshOffset );
124 SceneManager->getMeshManipulator()->transform( dest, m ); 124 SceneManager->getMeshManipulator()->transform( dest, m );
125 } 125 }
126 126
127 // No Texture!. Use Shader-Pointer for sorting 127 // No Texture!. Use Shader-Pointer for sorting
128 dest->Material.setTexture(0, (video::ITexture*) Shader); 128 dest->Material.setTexture(0, (video::ITexture*) Shader);
129} 129}
130 130
131 131
132/* 132/*
133 load the textures for all stages 133 load the textures for all stages
134*/ 134*/
135void CQuake3ShaderSceneNode::loadTextures( io::IFileSystem * fileSystem ) 135void CQuake3ShaderSceneNode::loadTextures( io::IFileSystem * fileSystem )
136{ 136{
137 const SVarGroup *group; 137 const SVarGroup *group;
138 u32 i; 138 u32 i;
139 139
140 video::IVideoDriver *driver = SceneManager->getVideoDriver(); 140 video::IVideoDriver *driver = SceneManager->getVideoDriver();
141 141
142 // generic stage 142 // generic stage
143 u32 mipmap = 0; 143 u32 mipmap = 0;
144 group = Shader->getGroup( 1 ); 144 group = Shader->getGroup( 1 );
145 if ( group->isDefined ( "nomipmaps" ) ) 145 if ( group->isDefined ( "nomipmaps" ) )
146 { 146 {
147 mipmap = 2 | (driver->getTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS)? 1: 0 ); 147 mipmap = 2 | (driver->getTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS)? 1: 0 );
148 driver->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, false); 148 driver->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, false);
149 } 149 }
150 150
151 // clear all stages and prefill empty 151 // clear all stages and prefill empty
152 Q3Texture.setAllocStrategy ( core::ALLOC_STRATEGY_SAFE ); 152 Q3Texture.setAllocStrategy ( core::ALLOC_STRATEGY_SAFE );
153 Q3Texture.clear(); 153 Q3Texture.clear();
154 for ( i = 0; i != Shader->VarGroup->VariableGroup.size(); ++i ) 154 for ( i = 0; i != Shader->VarGroup->VariableGroup.size(); ++i )
155 { 155 {
156 Q3Texture.push_back( SQ3Texture() ); 156 Q3Texture.push_back( SQ3Texture() );
157 } 157 }
158 158
159 u32 pos; 159 u32 pos;
160 160
161 // get texture map 161 // get texture map
162 for ( i = 0; i < Shader->VarGroup->VariableGroup.size(); ++i ) 162 for ( i = 0; i < Shader->VarGroup->VariableGroup.size(); ++i )
163 { 163 {
164 group = Shader->getGroup( i ); 164 group = Shader->getGroup( i );
165 165
166 const core::stringc &mapname = group->get( "map" ); 166 const core::stringc &mapname = group->get( "map" );
167 if ( 0 == mapname.size() ) 167 if ( 0 == mapname.size() )
168 continue; 168 continue;
169 169
170 // our lightmap is passed in material.Texture[2] 170 // our lightmap is passed in material.Texture[2]
171 if ( mapname == "$lightmap" ) 171 if ( mapname == "$lightmap" )
172 { 172 {
173 Q3Texture [i].Texture.push_back( Original->getMaterial().getTexture(1) ); 173 Q3Texture [i].Texture.push_back( Original->getMaterial().getTexture(1) );
174 } 174 }
175 else 175 else
176 { 176 {
177 pos = 0; 177 pos = 0;
178 getTextures( Q3Texture [i].Texture, mapname, pos, fileSystem, driver ); 178 getTextures( Q3Texture [i].Texture, mapname, pos, fileSystem, driver );
179 } 179 }
180 } 180 }
181 181
182 // get anim map 182 // get anim map
183 for ( i = 0; i < Shader->VarGroup->VariableGroup.size(); ++i ) 183 for ( i = 0; i < Shader->VarGroup->VariableGroup.size(); ++i )
184 { 184 {
185 if ( Q3Texture [i].Texture.size() ) 185 if ( Q3Texture [i].Texture.size() )
186 continue; 186 continue;
187 187
188 group = Shader->getGroup( i ); 188 group = Shader->getGroup( i );
189 189
190 const core::stringc &animmap = group->get( "animmap" ); 190 const core::stringc &animmap = group->get( "animmap" );
191 if ( 0 == animmap.size() ) 191 if ( 0 == animmap.size() )
192 continue; 192 continue;
193 193
194 // first parameter is frequency 194 // first parameter is frequency
195 pos = 0; 195 pos = 0;
196 Q3Texture [i].TextureFrequency = core::max_( 0.0001f, getAsFloat( animmap, pos ) ); 196 Q3Texture [i].TextureFrequency = core::max_( 0.0001f, getAsFloat( animmap, pos ) );
197 197
198 getTextures( Q3Texture [i].Texture, animmap, pos,fileSystem, driver ); 198 getTextures( Q3Texture [i].Texture, animmap, pos,fileSystem, driver );
199 } 199 }
200 200
201 // get clamp map 201 // get clamp map
202 for ( i = 0; i < Shader->VarGroup->VariableGroup.size(); ++i ) 202 for ( i = 0; i < Shader->VarGroup->VariableGroup.size(); ++i )
203 { 203 {
204 if ( Q3Texture [i].Texture.size() ) 204 if ( Q3Texture [i].Texture.size() )
205 continue; 205 continue;
206 206
207 group = Shader->getGroup( i ); 207 group = Shader->getGroup( i );
208 208
209 const core::stringc &clampmap = group->get( "clampmap" ); 209 const core::stringc &clampmap = group->get( "clampmap" );
210 if ( 0 == clampmap.size() ) 210 if ( 0 == clampmap.size() )
211 continue; 211 continue;
212 212
213 Q3Texture [i].TextureAddressMode = video::ETC_CLAMP_TO_EDGE; 213 Q3Texture [i].TextureAddressMode = video::ETC_CLAMP_TO_EDGE;
214 pos = 0; 214 pos = 0;
215 getTextures( Q3Texture [i].Texture, clampmap, pos,fileSystem, driver ); 215 getTextures( Q3Texture [i].Texture, clampmap, pos,fileSystem, driver );
216 } 216 }
217 217
218 if ( mipmap & 2 ) 218 if ( mipmap & 2 )
219 driver->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, mipmap & 1); 219 driver->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, mipmap & 1);
220} 220}
221 221
222/* 222/*
223 Register each texture stage, if first is visible 223 Register each texture stage, if first is visible
224*/ 224*/
225void CQuake3ShaderSceneNode::OnRegisterSceneNode() 225void CQuake3ShaderSceneNode::OnRegisterSceneNode()
226{ 226{
227 if ( isVisible() ) 227 if ( isVisible() )
228 { 228 {
229 SceneManager->registerNodeForRendering(this, getRenderStage() ); 229 SceneManager->registerNodeForRendering(this, getRenderStage() );
230 } 230 }
231 ISceneNode::OnRegisterSceneNode(); 231 ISceneNode::OnRegisterSceneNode();
232} 232}
233 233
234/* 234/*
235 is this a transparent node ? 235 is this a transparent node ?
236*/ 236*/
237E_SCENE_NODE_RENDER_PASS CQuake3ShaderSceneNode::getRenderStage() const 237E_SCENE_NODE_RENDER_PASS CQuake3ShaderSceneNode::getRenderStage() const
238{ 238{
239 E_SCENE_NODE_RENDER_PASS ret = ESNRP_SOLID; 239 E_SCENE_NODE_RENDER_PASS ret = ESNRP_SOLID;
240 240
241 // generic stage 241 // generic stage
242 const SVarGroup *group; 242 const SVarGroup *group;
243 243
244 group = Shader->getGroup( 1 ); 244 group = Shader->getGroup( 1 );
245/* 245/*
246 else 246 else
247 if ( group->getIndex( "portal" ) >= 0 ) 247 if ( group->getIndex( "portal" ) >= 0 )
248 { 248 {
249 ret = ESNRP_TRANSPARENT_EFFECT; 249 ret = ESNRP_TRANSPARENT_EFFECT;
250 } 250 }
251 else 251 else
252*/ 252*/
253 if ( group->isDefined( "sort", "opaque" ) ) 253 if ( group->isDefined( "sort", "opaque" ) )
254 { 254 {
255 ret = ESNRP_SOLID; 255 ret = ESNRP_SOLID;
256 } 256 }
257 else 257 else
258 if ( group->isDefined( "sort", "additive" ) ) 258 if ( group->isDefined( "sort", "additive" ) )
259 { 259 {
260 ret = ESNRP_TRANSPARENT; 260 ret = ESNRP_TRANSPARENT;
261 } 261 }
262 else 262 else
263 if ( strstr ( Shader->name.c_str(), "flame" ) || 263 if ( strstr ( Shader->name.c_str(), "flame" ) ||
264 group->isDefined( "surfaceparm", "water" ) || 264 group->isDefined( "surfaceparm", "water" ) ||
265 group->isDefined( "sort", "underwater" ) || 265 group->isDefined( "sort", "underwater" ) ||
266 group->isDefined( "sort", "underwater" ) 266 group->isDefined( "sort", "underwater" )
267 ) 267 )
268 { 268 {
269 ret = ESNRP_TRANSPARENT_EFFECT; 269 ret = ESNRP_TRANSPARENT_EFFECT;
270 } 270 }
271 else 271 else
272 { 272 {
273 // Look if first drawing stage needs graphical underlay 273 // Look if first drawing stage needs graphical underlay
274 for ( u32 stage = 2; stage < Shader->VarGroup->VariableGroup.size(); ++stage ) 274 for ( u32 stage = 2; stage < Shader->VarGroup->VariableGroup.size(); ++stage )
275 { 275 {
276 if ( 0 == Q3Texture [ stage ].Texture.size() ) 276 if ( 0 == Q3Texture [ stage ].Texture.size() )
277 continue; 277 continue;
278 278
279 group = Shader->getGroup( stage ); 279 group = Shader->getGroup( stage );
280 280
281 SBlendFunc blendfunc ( video::EMFN_MODULATE_1X ); 281 SBlendFunc blendfunc ( video::EMFN_MODULATE_1X );
282 getBlendFunc( group->get( "blendfunc" ), blendfunc ); 282 getBlendFunc( group->get( "blendfunc" ), blendfunc );
283 getBlendFunc( group->get( "alphafunc" ), blendfunc ); 283 getBlendFunc( group->get( "alphafunc" ), blendfunc );
284 284
285 //ret = blendfunc.isTransparent ? ESNRP_TRANSPARENT : ESNRP_SOLID; 285 //ret = blendfunc.isTransparent ? ESNRP_TRANSPARENT : ESNRP_SOLID;
286 if ( blendfunc.isTransparent ) 286 if ( blendfunc.isTransparent )
287 { 287 {
288 ret = ESNRP_TRANSPARENT; 288 ret = ESNRP_TRANSPARENT;
289 } 289 }
290 break; 290 break;
291 } 291 }
292 } 292 }
293 293
294 return ret; 294 return ret;
295} 295}
296 296
297 297
298/* 298/*
299 render in multipass technique 299 render in multipass technique
300*/ 300*/
301void CQuake3ShaderSceneNode::render() 301void CQuake3ShaderSceneNode::render()
302{ 302{
303 video::IVideoDriver* driver = SceneManager->getVideoDriver(); 303 video::IVideoDriver* driver = SceneManager->getVideoDriver();
304 E_SCENE_NODE_RENDER_PASS pass = SceneManager->getSceneNodeRenderPass(); 304 E_SCENE_NODE_RENDER_PASS pass = SceneManager->getSceneNodeRenderPass();
305 305
306 video::SMaterial material; 306 video::SMaterial material;
307 const SVarGroup *group; 307 const SVarGroup *group;
308 308
309 material.Lighting = false; 309 material.Lighting = false;
310 material.setTexture(1, 0); 310 material.setTexture(1, 0);
311 material.NormalizeNormals = false; 311 material.NormalizeNormals = false;
312 312
313 // generic stage 313 // generic stage
314 group = Shader->getGroup( 1 ); 314 group = Shader->getGroup( 1 );
315 material.BackfaceCulling = getCullingFunction( group->get( "cull" ) ); 315 material.BackfaceCulling = getCullingFunction( group->get( "cull" ) );
316 316
317 u32 pushProjection = 0; 317 u32 pushProjection = 0;
318 core::matrix4 projection ( core::matrix4::EM4CONST_NOTHING ); 318 core::matrix4 projection ( core::matrix4::EM4CONST_NOTHING );
319 319
320 // decal ( solve z-fighting ) 320 // decal ( solve z-fighting )
321 if ( group->isDefined( "polygonoffset" ) ) 321 if ( group->isDefined( "polygonoffset" ) )
322 { 322 {
323 projection = driver->getTransform( video::ETS_PROJECTION ); 323 projection = driver->getTransform( video::ETS_PROJECTION );
324 324
325 core::matrix4 decalProjection ( projection ); 325 core::matrix4 decalProjection ( projection );
326 326
327/* 327/*
328 f32 n = SceneManager->getActiveCamera()->getNearValue(); 328 f32 n = SceneManager->getActiveCamera()->getNearValue();
329 f32 f = SceneManager->getActiveCamera()->getFarValue (); 329 f32 f = SceneManager->getActiveCamera()->getFarValue ();
330 330
331 f32 delta = 0.01f; 331 f32 delta = 0.01f;
332 f32 pz = 0.2f; 332 f32 pz = 0.2f;
333 f32 epsilon = -2.f * f * n * delta / ( ( f + n ) * pz * ( pz + delta ) ); 333 f32 epsilon = -2.f * f * n * delta / ( ( f + n ) * pz * ( pz + delta ) );
334 decalProjection[10] *= 1.f + epsilon; 334 decalProjection[10] *= 1.f + epsilon;
335*/ 335*/
336 // TODO: involve camera 336 // TODO: involve camera
337 decalProjection[10] -= 0.0002f; 337 decalProjection[10] -= 0.0002f;
338 driver->setTransform( video::ETS_PROJECTION, decalProjection ); 338 driver->setTransform( video::ETS_PROJECTION, decalProjection );
339 pushProjection |= 1; 339 pushProjection |= 1;
340 } 340 }
341 341
342 driver->setTransform(video::ETS_WORLD, AbsoluteTransformation ); 342 driver->setTransform(video::ETS_WORLD, AbsoluteTransformation );
343 if (Shadow) 343 if (Shadow)
344 Shadow->updateShadowVolumes(); 344 Shadow->updateShadowVolumes();
345 345
346 //! render all stages 346 //! render all stages
347 u32 drawCount = (pass == ESNRP_TRANSPARENT_EFFECT) ? 1 : 0; 347 u32 drawCount = (pass == ESNRP_TRANSPARENT_EFFECT) ? 1 : 0;
348 core::matrix4 textureMatrix ( core::matrix4::EM4CONST_NOTHING ); 348 core::matrix4 textureMatrix ( core::matrix4::EM4CONST_NOTHING );
349 for ( u32 stage = 1; stage < Shader->VarGroup->VariableGroup.size(); ++stage ) 349 for ( u32 stage = 1; stage < Shader->VarGroup->VariableGroup.size(); ++stage )
350 { 350 {
351 SQ3Texture &q = Q3Texture[stage]; 351 SQ3Texture &q = Q3Texture[stage];
352 352
353 // advance current stage 353 // advance current stage
354 textureMatrix.makeIdentity(); 354 textureMatrix.makeIdentity();
355 animate( stage, textureMatrix ); 355 animate( stage, textureMatrix );
356 356
357 // stage finished, no drawing stage ( vertex transform only ) 357 // stage finished, no drawing stage ( vertex transform only )
358 video::ITexture * tex = q.Texture.size() ? q.Texture [ q.TextureIndex ] : 0; 358 video::ITexture * tex = q.Texture.size() ? q.Texture [ q.TextureIndex ] : 0;
359 if ( 0 == tex ) 359 if ( 0 == tex )
360 continue; 360 continue;
361 361
362 // current stage 362 // current stage
363 group = Shader->getGroup( stage ); 363 group = Shader->getGroup( stage );
364 364
365 material.setTexture(0, tex ); 365 material.setTexture(0, tex );
366 material.ZBuffer = getDepthFunction( group->get( "depthfunc" ) ); 366 material.ZBuffer = getDepthFunction( group->get( "depthfunc" ) );
367 367
368 if ( group->isDefined( "depthwrite" ) ) 368 if ( group->isDefined( "depthwrite" ) )
369 { 369 {
370 material.ZWriteEnable = true; 370 material.ZWriteEnable = true;
371 } 371 }
372 else 372 else
373 { 373 {
374 material.ZWriteEnable = drawCount == 0; 374 material.ZWriteEnable = drawCount == 0;
375 } 375 }
376 376
377 //resolve quake3 blendfunction to irrlicht Material Type 377 //resolve quake3 blendfunction to irrlicht Material Type
378 SBlendFunc blendfunc ( video::EMFN_MODULATE_1X ); 378 SBlendFunc blendfunc ( video::EMFN_MODULATE_1X );
379 getBlendFunc( group->get( "blendfunc" ), blendfunc ); 379 getBlendFunc( group->get( "blendfunc" ), blendfunc );
380 getBlendFunc( group->get( "alphafunc" ), blendfunc ); 380 getBlendFunc( group->get( "alphafunc" ), blendfunc );
381 381
382 material.MaterialType = blendfunc.type; 382 material.MaterialType = blendfunc.type;
383 material.MaterialTypeParam = blendfunc.param0; 383 material.MaterialTypeParam = blendfunc.param0;
384 384
385 material.TextureLayer[0].TextureWrapU = q.TextureAddressMode; 385 material.TextureLayer[0].TextureWrapU = q.TextureAddressMode;
386 material.TextureLayer[0].TextureWrapV = q.TextureAddressMode; 386 material.TextureLayer[0].TextureWrapV = q.TextureAddressMode;
387 //material.TextureLayer[0].TrilinearFilter = 1; 387 //material.TextureLayer[0].TrilinearFilter = 1;
388 //material.TextureLayer[0].AnisotropicFilter = 0xFF; 388 //material.TextureLayer[0].AnisotropicFilter = 0xFF;
389 material.setTextureMatrix( 0, textureMatrix ); 389 material.setTextureMatrix( 0, textureMatrix );
390 390
391 driver->setMaterial( material ); 391 driver->setMaterial( material );
392 driver->drawMeshBuffer( MeshBuffer ); 392 driver->drawMeshBuffer( MeshBuffer );
393 drawCount += 1; 393 drawCount += 1;
394 394
395 } 395 }
396 396
397 if ( DebugDataVisible & scene::EDS_MESH_WIRE_OVERLAY ) 397 if ( DebugDataVisible & scene::EDS_MESH_WIRE_OVERLAY )
398 { 398 {
399 video::SMaterial deb_m; 399 video::SMaterial deb_m;
400 deb_m.Wireframe = true; 400 deb_m.Wireframe = true;
401 deb_m.Lighting = false; 401 deb_m.Lighting = false;
402 deb_m.BackfaceCulling = material.BackfaceCulling; 402 deb_m.BackfaceCulling = material.BackfaceCulling;
403 driver->setMaterial( deb_m ); 403 driver->setMaterial( deb_m );
404 404
405 driver->drawMeshBuffer( MeshBuffer ); 405 driver->drawMeshBuffer( MeshBuffer );
406 } 406 }
407 407
408 // show normals 408 // show normals
409 if ( DebugDataVisible & scene::EDS_NORMALS ) 409 if ( DebugDataVisible & scene::EDS_NORMALS )
410 { 410 {
411 video::SMaterial deb_m; 411 video::SMaterial deb_m;
412 412
413 IAnimatedMesh * arrow = SceneManager->addArrowMesh ( 413 IAnimatedMesh * arrow = SceneManager->addArrowMesh (
414 "__debugnormalq3", 414 "__debugnormalq3",
415 0xFFECEC00,0xFF999900, 415 0xFFECEC00,0xFF999900,
416 4, 8, 416 4, 8,
417 8.f, 6.f, 417 8.f, 6.f,
418 0.5f,1.f 418 0.5f,1.f
419 ); 419 );
420 if ( 0 == arrow ) 420 if ( 0 == arrow )
421 { 421 {
422 arrow = SceneManager->getMesh ( "__debugnormalq3" ); 422 arrow = SceneManager->getMesh ( "__debugnormalq3" );
423 } 423 }
424 const IMesh *mesh = arrow->getMesh ( 0 ); 424 const IMesh *mesh = arrow->getMesh ( 0 );
425 425
426 // find a good scaling factor 426 // find a good scaling factor
427 427
428 core::matrix4 m2; 428 core::matrix4 m2;
429 429
430 // draw normals 430 // draw normals
431 const scene::IMeshBuffer* mb = MeshBuffer; 431 const scene::IMeshBuffer* mb = MeshBuffer;
432 const u32 vSize = video::getVertexPitchFromType(mb->getVertexType()); 432 const u32 vSize = video::getVertexPitchFromType(mb->getVertexType());
433 const video::S3DVertex* v = ( const video::S3DVertex*)mb->getVertices(); 433 const video::S3DVertex* v = ( const video::S3DVertex*)mb->getVertices();
434 434
435 //f32 colCycle = 270.f / (f32) core::s32_max ( mb->getVertexCount() - 1, 1 ); 435 //f32 colCycle = 270.f / (f32) core::s32_max ( mb->getVertexCount() - 1, 1 );
436 436
437 for ( u32 i=0; i != mb->getVertexCount(); ++i ) 437 for ( u32 i=0; i != mb->getVertexCount(); ++i )
438 { 438 {
439 // Align to v->normal 439 // Align to v->normal
440 m2.buildRotateFromTo ( core::vector3df ( 0.f, 1.f, 0 ), v->Normal ); 440 m2.buildRotateFromTo ( core::vector3df ( 0.f, 1.f, 0 ), v->Normal );
441 m2.setTranslation ( v->Pos + AbsoluteTransformation.getTranslation () ); 441 m2.setTranslation ( v->Pos + AbsoluteTransformation.getTranslation () );
442/* 442/*
443 core::quaternion quatRot( v->Normal.Z, 0.f, -v->Normal.X, 1 + v->Normal.Y ); 443 core::quaternion quatRot( v->Normal.Z, 0.f, -v->Normal.X, 1 + v->Normal.Y );
444 quatRot.normalize(); 444 quatRot.normalize();
445 quatRot.getMatrix ( m2, v->Pos ); 445 quatRot.getMatrix ( m2, v->Pos );
446 446
447 m2 [ 12 ] += AbsoluteTransformation [ 12 ]; 447 m2 [ 12 ] += AbsoluteTransformation [ 12 ];
448 m2 [ 13 ] += AbsoluteTransformation [ 13 ]; 448 m2 [ 13 ] += AbsoluteTransformation [ 13 ];
449 m2 [ 14 ] += AbsoluteTransformation [ 14 ]; 449 m2 [ 14 ] += AbsoluteTransformation [ 14 ];
450*/ 450*/
451 driver->setTransform(video::ETS_WORLD, m2 ); 451 driver->setTransform(video::ETS_WORLD, m2 );
452 452
453 deb_m.Lighting = true; 453 deb_m.Lighting = true;
454/* 454/*
455 irr::video::SColorHSL color; 455 irr::video::SColorHSL color;
456 irr::video::SColor rgb(0); 456 irr::video::SColor rgb(0);
457 color.Hue = i * colCycle * core::DEGTORAD; 457 color.Hue = i * colCycle * core::DEGTORAD;
458 color.Saturation = 1.f; 458 color.Saturation = 1.f;
459 color.Luminance = 0.5f; 459 color.Luminance = 0.5f;
460 color.toRGB( deb_m.EmissiveColor ); 460 color.toRGB( deb_m.EmissiveColor );
461*/ 461*/
462 switch ( i ) 462 switch ( i )
463 { 463 {
464 case 0: deb_m.EmissiveColor.set(0xFFFFFFFF); break; 464 case 0: deb_m.EmissiveColor.set(0xFFFFFFFF); break;
465 case 1: deb_m.EmissiveColor.set(0xFFFF0000); break; 465 case 1: deb_m.EmissiveColor.set(0xFFFF0000); break;
466 case 2: deb_m.EmissiveColor.set(0xFF00FF00); break; 466 case 2: deb_m.EmissiveColor.set(0xFF00FF00); break;
467 case 3: deb_m.EmissiveColor.set(0xFF0000FF); break; 467 case 3: deb_m.EmissiveColor.set(0xFF0000FF); break;
468 default: 468 default:
469 deb_m.EmissiveColor = v->Color; break; 469 deb_m.EmissiveColor = v->Color; break;
470 } 470 }
471 driver->setMaterial( deb_m ); 471 driver->setMaterial( deb_m );
472 472
473 for ( u32 a = 0; a != mesh->getMeshBufferCount(); ++a ) 473 for ( u32 a = 0; a != mesh->getMeshBufferCount(); ++a )
474 driver->drawMeshBuffer ( mesh->getMeshBuffer ( a ) ); 474 driver->drawMeshBuffer ( mesh->getMeshBuffer ( a ) );
475 475
476 v = (const video::S3DVertex*) ( (u8*) v + vSize ); 476 v = (const video::S3DVertex*) ( (u8*) v + vSize );
477 } 477 }
478 driver->setTransform(video::ETS_WORLD, AbsoluteTransformation); 478 driver->setTransform(video::ETS_WORLD, AbsoluteTransformation);
479 } 479 }
480 480
481 481
482 if ( pushProjection & 1 ) 482 if ( pushProjection & 1 )
483 { 483 {
484 driver->setTransform( video::ETS_PROJECTION, projection ); 484 driver->setTransform( video::ETS_PROJECTION, projection );
485 } 485 }
486 486
487 if ( DebugDataVisible & scene::EDS_BBOX ) 487 if ( DebugDataVisible & scene::EDS_BBOX )
488 { 488 {
489 video::SMaterial deb_m; 489 video::SMaterial deb_m;
490 deb_m.Lighting = false; 490 deb_m.Lighting = false;
491 driver->setMaterial(deb_m); 491 driver->setMaterial(deb_m);
492 driver->setTransform(video::ETS_WORLD, AbsoluteTransformation); 492 driver->setTransform(video::ETS_WORLD, AbsoluteTransformation);
493 driver->draw3DBox( getBoundingBox(), video::SColor(255,255,0,0)); 493 driver->draw3DBox( getBoundingBox(), video::SColor(255,255,0,0));
494 } 494 }
495 495
496} 496}
497 497
498 498
499//! Removes a child from this scene node. 499//! Removes a child from this scene node.
500//! Implemented here, to be able to remove the shadow properly, if there is one, 500//! Implemented here, to be able to remove the shadow properly, if there is one,
501//! or to remove attached childs. 501//! or to remove attached childs.
502bool CQuake3ShaderSceneNode::removeChild(ISceneNode* child) 502bool CQuake3ShaderSceneNode::removeChild(ISceneNode* child)
503{ 503{
504 if (child && Shadow == child) 504 if (child && Shadow == child)
505 { 505 {
506 Shadow->drop(); 506 Shadow->drop();
507 Shadow = 0; 507 Shadow = 0;
508 } 508 }
509 509
510 return ISceneNode::removeChild(child); 510 return ISceneNode::removeChild(child);
511} 511}
512 512
513 513
514//! Creates shadow volume scene node as child of this node 514//! Creates shadow volume scene node as child of this node
515//! and returns a pointer to it. 515//! and returns a pointer to it.
516IShadowVolumeSceneNode* CQuake3ShaderSceneNode::addShadowVolumeSceneNode( 516IShadowVolumeSceneNode* CQuake3ShaderSceneNode::addShadowVolumeSceneNode(
517 const IMesh* shadowMesh, s32 id, bool zfailmethod, f32 infinity) 517 const IMesh* shadowMesh, s32 id, bool zfailmethod, f32 infinity)
518{ 518{
519 if (!SceneManager->getVideoDriver()->queryFeature(video::EVDF_STENCIL_BUFFER)) 519 if (!SceneManager->getVideoDriver()->queryFeature(video::EVDF_STENCIL_BUFFER))
520 return 0; 520 return 0;
521 521
522 if (!shadowMesh) 522 if (!shadowMesh)
523 shadowMesh = Mesh; // if null is given, use the mesh of node 523 shadowMesh = Mesh; // if null is given, use the mesh of node
524 524
525 if (Shadow) 525 if (Shadow)
526 Shadow->drop(); 526 Shadow->drop();
527 527
528 Shadow = new CShadowVolumeSceneNode(shadowMesh, this, SceneManager, id, zfailmethod, infinity); 528 Shadow = new CShadowVolumeSceneNode(shadowMesh, this, SceneManager, id, zfailmethod, infinity);
529 return Shadow; 529 return Shadow;
530} 530}
531 531
532 532
533/*! 533/*!
5343.3.1 deformVertexes wave <div> <func> <base> <amplitude> <phase> <freq> 5343.3.1 deformVertexes wave <div> <func> <base> <amplitude> <phase> <freq>
535 Designed for water surfaces, modifying the values differently at each point. 535 Designed for water surfaces, modifying the values differently at each point.
536 It accepts the standard wave functions of the type sin, triangle, square, sawtooth 536 It accepts the standard wave functions of the type sin, triangle, square, sawtooth
537 or inversesawtooth. The "div" parameter is used to control the wave "spread" 537 or inversesawtooth. The "div" parameter is used to control the wave "spread"
538 - a value equal to the tessSize of the surface is a good default value 538 - a value equal to the tessSize of the surface is a good default value
539 (tessSize is subdivision size, in game units, used for the shader when seen in the game world) . 539 (tessSize is subdivision size, in game units, used for the shader when seen in the game world) .
540*/ 540*/
541void CQuake3ShaderSceneNode::deformvertexes_wave( f32 dt, SModifierFunction &function ) 541void CQuake3ShaderSceneNode::deformvertexes_wave( f32 dt, SModifierFunction &function )
542{ 542{
543 function.wave = core::reciprocal( function.wave ); 543 function.wave = core::reciprocal( function.wave );
544 544
545 const f32 phase = function.phase; 545 const f32 phase = function.phase;
546 546
547 const u32 vsize = Original->Vertices.size(); 547 const u32 vsize = Original->Vertices.size();
548 for ( u32 i = 0; i != vsize; ++i ) 548 for ( u32 i = 0; i != vsize; ++i )
549 { 549 {
550 const video::S3DVertex2TCoords &src = Original->Vertices[i]; 550 const video::S3DVertex2TCoords &src = Original->Vertices[i];
551 video::S3DVertex &dst = MeshBuffer->Vertices[i]; 551 video::S3DVertex &dst = MeshBuffer->Vertices[i];
552 552
553 if ( 0 == function.count ) 553 if ( 0 == function.count )
554 dst.Pos = src.Pos - MeshOffset; 554 dst.Pos = src.Pos - MeshOffset;
555 555
556 const f32 wavephase = (dst.Pos.X + dst.Pos.Y + dst.Pos.Z) * function.wave; 556 const f32 wavephase = (dst.Pos.X + dst.Pos.Y + dst.Pos.Z) * function.wave;
557 function.phase = phase + wavephase; 557 function.phase = phase + wavephase;
558 558
559 const f32 f = function.evaluate( dt ); 559 const f32 f = function.evaluate( dt );
560 560
561 dst.Pos.X += f * src.Normal.X; 561 dst.Pos.X += f * src.Normal.X;
562 dst.Pos.Y += f * src.Normal.Y; 562 dst.Pos.Y += f * src.Normal.Y;
563 dst.Pos.Z += f * src.Normal.Z; 563 dst.Pos.Z += f * src.Normal.Z;
564 564
565 if ( i == 0 ) 565 if ( i == 0 )
566 MeshBuffer->BoundingBox.reset ( dst.Pos ); 566 MeshBuffer->BoundingBox.reset ( dst.Pos );
567 else 567 else
568 MeshBuffer->BoundingBox.addInternalPoint ( dst.Pos ); 568 MeshBuffer->BoundingBox.addInternalPoint ( dst.Pos );
569 } 569 }
570 function.count = 1; 570 function.count = 1;
571} 571}
572 572
573/*! 573/*!
574 deformVertexes move x y z func base amplitude phase freq 574 deformVertexes move x y z func base amplitude phase freq
575 The move parameter is used to make a brush, curve patch or model 575 The move parameter is used to make a brush, curve patch or model
576 appear to move together as a unit. The x y z values are the distance 576 appear to move together as a unit. The x y z values are the distance
577 and direction in game units the object appears to move relative to 577 and direction in game units the object appears to move relative to
578 it's point of origin in the map. The func base amplitude phase freq values are 578 it's point of origin in the map. The func base amplitude phase freq values are
579 the same as found in other waveform manipulations. 579 the same as found in other waveform manipulations.
580 580
581 The product of the function modifies the values x, y, and z. 581 The product of the function modifies the values x, y, and z.
582 Therefore, if you have an amplitude of 5 and an x value of 2, 582 Therefore, if you have an amplitude of 5 and an x value of 2,
583 the object will travel 10 units from its point of origin along the x axis. 583 the object will travel 10 units from its point of origin along the x axis.
584 This results in a total of 20 units of motion along the x axis, since the 584 This results in a total of 20 units of motion along the x axis, since the
585 amplitude is the variation both above and below the base. 585 amplitude is the variation both above and below the base.
586 586
587 It must be noted that an object made with this shader does not actually 587 It must be noted that an object made with this shader does not actually
588 change position, it only appears to. 588 change position, it only appears to.
589 589
590 Design Notes: 590 Design Notes:
591 If an object is made up of surfaces with different shaders, all must have 591 If an object is made up of surfaces with different shaders, all must have
592 matching deformVertexes move values or the object will appear to tear itself apart. 592 matching deformVertexes move values or the object will appear to tear itself apart.
593*/ 593*/
594void CQuake3ShaderSceneNode::deformvertexes_move( f32 dt, SModifierFunction &function ) 594void CQuake3ShaderSceneNode::deformvertexes_move( f32 dt, SModifierFunction &function )
595{ 595{
596 function.wave = core::reciprocal( function.wave ); 596 function.wave = core::reciprocal( function.wave );
597 const f32 f = function.evaluate( dt ); 597 const f32 f = function.evaluate( dt );
598 598
599 const u32 vsize = Original->Vertices.size(); 599 const u32 vsize = Original->Vertices.size();
600 for ( u32 i = 0; i != vsize; ++i ) 600 for ( u32 i = 0; i != vsize; ++i )
601 { 601 {
602 const video::S3DVertex2TCoords &src = Original->Vertices[i]; 602 const video::S3DVertex2TCoords &src = Original->Vertices[i];
603 video::S3DVertex &dst = MeshBuffer->Vertices[i]; 603 video::S3DVertex &dst = MeshBuffer->Vertices[i];
604 604
605 if ( 0 == function.count ) 605 if ( 0 == function.count )
606 dst.Pos = src.Pos - MeshOffset; 606 dst.Pos = src.Pos - MeshOffset;
607 607
608 dst.Pos.X += f * function.x; 608 dst.Pos.X += f * function.x;
609 dst.Pos.Y += f * function.y; 609 dst.Pos.Y += f * function.y;
610 dst.Pos.Z += f * function.z; 610 dst.Pos.Z += f * function.z;
611 611
612 if ( i == 0 ) 612 if ( i == 0 )
613 MeshBuffer->BoundingBox.reset ( dst.Pos ); 613 MeshBuffer->BoundingBox.reset ( dst.Pos );
614 else 614 else
615 MeshBuffer->BoundingBox.addInternalPoint ( dst.Pos ); 615 MeshBuffer->BoundingBox.addInternalPoint ( dst.Pos );
616 } 616 }
617 function.count = 1; 617 function.count = 1;
618 618
619} 619}
620 620
621/*! 621/*!
622 3.3.2 deformVertexes normal <div> <func> <base> <amplitude ~0.1-~0.5> <frequency ~1.0-~4.0> 622 3.3.2 deformVertexes normal <div> <func> <base> <amplitude ~0.1-~0.5> <frequency ~1.0-~4.0>
623 This deformation affects the normals of a vertex without actually moving it, 623 This deformation affects the normals of a vertex without actually moving it,
624 which will effect later shader options like lighting and especially environment mapping. 624 which will effect later shader options like lighting and especially environment mapping.
625 If the shader stages don't use normals in any of their calculations, there will 625 If the shader stages don't use normals in any of their calculations, there will
626 be no visible effect. 626 be no visible effect.
627 627
628 Design Notes: Putting values of 0.1 t o 0.5 in Amplitude and 1.0 to 4.0 in the 628 Design Notes: Putting values of 0.1 t o 0.5 in Amplitude and 1.0 to 4.0 in the
629 Frequency can produce some satisfying results. Some things that have been 629 Frequency can produce some satisfying results. Some things that have been
630 done with it: A small fluttering bat, falling leaves, rain, flags. 630 done with it: A small fluttering bat, falling leaves, rain, flags.
631*/ 631*/
632void CQuake3ShaderSceneNode::deformvertexes_normal( f32 dt, SModifierFunction &function ) 632void CQuake3ShaderSceneNode::deformvertexes_normal( f32 dt, SModifierFunction &function )
633{ 633{
634 function.func = SINUS; 634 function.func = SINUS;
635 const u32 vsize = Original->Vertices.size(); 635 const u32 vsize = Original->Vertices.size();
636 for ( u32 i = 0; i != vsize; ++i ) 636 for ( u32 i = 0; i != vsize; ++i )
637 { 637 {
638 const video::S3DVertex2TCoords &src = Original->Vertices[i]; 638 const video::S3DVertex2TCoords &src = Original->Vertices[i];
639 video::S3DVertex &dst = MeshBuffer->Vertices[i]; 639 video::S3DVertex &dst = MeshBuffer->Vertices[i];
640 640
641 function.base = atan2f ( src.Pos.X, src.Pos.Y ); 641 function.base = atan2f ( src.Pos.X, src.Pos.Y );
642 function.phase = src.Pos.X + src.Pos.Z; 642 function.phase = src.Pos.X + src.Pos.Z;
643 643
644 const f32 lat = function.evaluate( dt ); 644 const f32 lat = function.evaluate( dt );
645 645
646 function.base = src.Normal.Y; 646 function.base = src.Normal.Y;
647 function.phase = src.Normal.Z + src.Normal.X; 647 function.phase = src.Normal.Z + src.Normal.X;
648 648
649 const f32 lng = function.evaluate( dt ); 649 const f32 lng = function.evaluate( dt );
650 650
651 dst.Normal.X = cosf ( lat ) * sinf ( lng ); 651 dst.Normal.X = cosf ( lat ) * sinf ( lng );
652 dst.Normal.Y = sinf ( lat ) * sinf ( lng ); 652 dst.Normal.Y = sinf ( lat ) * sinf ( lng );
653 dst.Normal.Z = cosf ( lng ); 653 dst.Normal.Z = cosf ( lng );
654 654
655 } 655 }
656} 656}
657 657
658 658
659/*! 659/*!
660 3.3.3 deformVertexes bulge <bulgeWidth> <bulgeHeight> <bulgeSpeed> 660 3.3.3 deformVertexes bulge <bulgeWidth> <bulgeHeight> <bulgeSpeed>
661 This forces a bulge to move along the given s and t directions. Designed for use 661 This forces a bulge to move along the given s and t directions. Designed for use
662 on curved pipes. 662 on curved pipes.
663 663
664 Specific parameter definitions for deform keywords: 664 Specific parameter definitions for deform keywords:
665 <div> This is roughly defined as the size of the waves that occur. 665 <div> This is roughly defined as the size of the waves that occur.
666 It is measured in game units. Smaller values create a greater 666 It is measured in game units. Smaller values create a greater
667 density of smaller wave forms occurring in a given area. 667 density of smaller wave forms occurring in a given area.
668 Larger values create a lesser density of waves, or otherwise put, 668 Larger values create a lesser density of waves, or otherwise put,
669 the appearance of larger waves. To look correct this value should 669 the appearance of larger waves. To look correct this value should
670 closely correspond to the value (in pixels) set for tessSize (tessellation size) 670 closely correspond to the value (in pixels) set for tessSize (tessellation size)
671 of the texture. A value of 100.0 is a good default value 671 of the texture. A value of 100.0 is a good default value
672 (which means your tessSize should be close to that for things to look "wavelike"). 672 (which means your tessSize should be close to that for things to look "wavelike").
673 673
674 <func> This is the type of wave form being created. Sin stands for sine wave, 674 <func> This is the type of wave form being created. Sin stands for sine wave,
675 a regular smoothly flowing wave. Triangle is a wave with a sharp ascent 675 a regular smoothly flowing wave. Triangle is a wave with a sharp ascent
676 and a sharp decay. It will make a choppy looking wave forms. 676 and a sharp decay. It will make a choppy looking wave forms.
677 A square wave is simply on or off for the period of the 677 A square wave is simply on or off for the period of the
678 frequency with no in between. The sawtooth wave has the ascent of a 678 frequency with no in between. The sawtooth wave has the ascent of a
679 triangle wave, but has the decay cut off sharply like a square wave. 679 triangle wave, but has the decay cut off sharply like a square wave.
680 An inversesawtooth wave reverses this. 680 An inversesawtooth wave reverses this.
681 681
682 <base> This is the distance, in game units that the apparent surface of the 682 <base> This is the distance, in game units that the apparent surface of the
683 texture is displaced from the actual surface of the brush as placed 683 texture is displaced from the actual surface of the brush as placed
684 in the editor. A positive value appears above the brush surface. 684 in the editor. A positive value appears above the brush surface.
685 A negative value appears below the brush surface. 685 A negative value appears below the brush surface.
686 An example of this is the Quad effect, which essentially is a 686 An example of this is the Quad effect, which essentially is a
687 shell with a positive base value to stand it away from the model 687 shell with a positive base value to stand it away from the model
688 surface and a 0 (zero) value for amplitude. 688 surface and a 0 (zero) value for amplitude.
689 689
690 <amplitude> The distance that the deformation moves away from the base value. 690 <amplitude> The distance that the deformation moves away from the base value.
691 See Wave Forms in the introduction for a description of amplitude. 691 See Wave Forms in the introduction for a description of amplitude.
692 692
693 <phase> See Wave Forms in the introduction for a description of phase) 693 <phase> See Wave Forms in the introduction for a description of phase)
694 694
695 <frequency> See Wave Forms in the introduction for a description of frequency) 695 <frequency> See Wave Forms in the introduction for a description of frequency)
696 696
697 Design Note: The div and amplitude parameters, when used in conjunction with 697 Design Note: The div and amplitude parameters, when used in conjunction with
698 liquid volumes like water should take into consideration how much the water 698 liquid volumes like water should take into consideration how much the water
699 will be moving. A large ocean area would have have massive swells (big div values) 699 will be moving. A large ocean area would have have massive swells (big div values)
700 that rose and fell dramatically (big amplitude values). While a small, quiet pool 700 that rose and fell dramatically (big amplitude values). While a small, quiet pool
701 may move very little. 701 may move very little.
702*/ 702*/
703void CQuake3ShaderSceneNode::deformvertexes_bulge( f32 dt, SModifierFunction &function ) 703void CQuake3ShaderSceneNode::deformvertexes_bulge( f32 dt, SModifierFunction &function )
704{ 704{
705 function.func = SINUS; 705 function.func = SINUS;
706 function.wave = core::reciprocal( function.bulgewidth ); 706 function.wave = core::reciprocal( function.bulgewidth );
707 707
708 dt *= function.bulgespeed * 0.1f; 708 dt *= function.bulgespeed * 0.1f;
709 const f32 phase = function.phase; 709 const f32 phase = function.phase;
710 710
711 const u32 vsize = Original->Vertices.size(); 711 const u32 vsize = Original->Vertices.size();
712 for ( u32 i = 0; i != vsize; ++i ) 712 for ( u32 i = 0; i != vsize; ++i )
713 { 713 {
714 const video::S3DVertex2TCoords &src = Original->Vertices[i]; 714 const video::S3DVertex2TCoords &src = Original->Vertices[i];
715 video::S3DVertex &dst = MeshBuffer->Vertices[i]; 715 video::S3DVertex &dst = MeshBuffer->Vertices[i];
716 716
717 const f32 wavephase = (Original->Vertices[i].TCoords.X ) * function.wave; 717 const f32 wavephase = (Original->Vertices[i].TCoords.X ) * function.wave;
718 function.phase = phase + wavephase; 718 function.phase = phase + wavephase;
719 719
720 const f32 f = function.evaluate( dt ); 720 const f32 f = function.evaluate( dt );
721 721
722 if ( 0 == function.count ) 722 if ( 0 == function.count )
723 dst.Pos = src.Pos - MeshOffset; 723 dst.Pos = src.Pos - MeshOffset;
724 724
725 dst.Pos.X += f * src.Normal.X; 725 dst.Pos.X += f * src.Normal.X;
726 dst.Pos.Y += f * src.Normal.Y; 726 dst.Pos.Y += f * src.Normal.Y;
727 dst.Pos.Z += f * src.Normal.Z; 727 dst.Pos.Z += f * src.Normal.Z;
728 728
729 if ( i == 0 ) 729 if ( i == 0 )
730 MeshBuffer->BoundingBox.reset ( dst.Pos ); 730 MeshBuffer->BoundingBox.reset ( dst.Pos );
731 else 731 else
732 MeshBuffer->BoundingBox.addInternalPoint ( dst.Pos ); 732 MeshBuffer->BoundingBox.addInternalPoint ( dst.Pos );
733 } 733 }
734 734
735 function.count = 1; 735 function.count = 1;
736} 736}
737 737
738 738
739/*! 739/*!
740 deformVertexes autosprite 740 deformVertexes autosprite
741 741
742 This function can be used to make any given triangle quad 742 This function can be used to make any given triangle quad
743 (pair of triangles that form a square rectangle) automatically behave 743 (pair of triangles that form a square rectangle) automatically behave
744 like a sprite without having to make it a separate entity. This means 744 like a sprite without having to make it a separate entity. This means
745 that the "sprite" on which the texture is placed will rotate to always 745 that the "sprite" on which the texture is placed will rotate to always
746 appear at right angles to the player's view as a sprite would. Any four-sided 746 appear at right angles to the player's view as a sprite would. Any four-sided
747 brush side, flat patch, or pair of triangles in a model can have the autosprite 747 brush side, flat patch, or pair of triangles in a model can have the autosprite
748 effect on it. The brush face containing a texture with this shader keyword must 748 effect on it. The brush face containing a texture with this shader keyword must
749 be square. 749 be square.
750*/ 750*/
751void CQuake3ShaderSceneNode::deformvertexes_autosprite( f32 dt, SModifierFunction &function ) 751void CQuake3ShaderSceneNode::deformvertexes_autosprite( f32 dt, SModifierFunction &function )
752{ 752{
753 u32 vsize = Original->Vertices.size(); 753 u32 vsize = Original->Vertices.size();
754 u32 g; 754 u32 g;
755 u32 i; 755 u32 i;
756 756
757 const core::vector3df& camPos = SceneManager->getActiveCamera()->getPosition(); 757 const core::vector3df& camPos = SceneManager->getActiveCamera()->getPosition();
758 758
759 video::S3DVertex * dv = MeshBuffer->Vertices.pointer(); 759 video::S3DVertex * dv = MeshBuffer->Vertices.pointer();
760 const video::S3DVertex2TCoords * vin = Original->Vertices.const_pointer(); 760 const video::S3DVertex2TCoords * vin = Original->Vertices.const_pointer();
761 761
762 core::matrix4 lookat ( core::matrix4::EM4CONST_NOTHING ); 762 core::matrix4 lookat ( core::matrix4::EM4CONST_NOTHING );
763 core::quaternion q; 763 core::quaternion q;
764 for ( i = 0; i < vsize; i += 4 ) 764 for ( i = 0; i < vsize; i += 4 )
765 { 765 {
766 // quad-plane 766 // quad-plane
767 core::vector3df center = 0.25f * ( vin[i+0].Pos + vin[i+1].Pos + vin[i+2].Pos + vin[i+3].Pos ); 767 core::vector3df center = 0.25f * ( vin[i+0].Pos + vin[i+1].Pos + vin[i+2].Pos + vin[i+3].Pos );
768 core::vector3df forward = camPos - center; 768 core::vector3df forward = camPos - center;
769 769
770 q.rotationFromTo ( vin[i].Normal, forward ); 770 q.rotationFromTo ( vin[i].Normal, forward );
771 q.getMatrixCenter ( lookat, center, MeshOffset ); 771 q.getMatrixCenter ( lookat, center, MeshOffset );
772 772
773 for ( g = 0; g < 4; ++g ) 773 for ( g = 0; g < 4; ++g )
774 { 774 {
775 lookat.transformVect ( dv[i+g].Pos, vin[i+g].Pos ); 775 lookat.transformVect ( dv[i+g].Pos, vin[i+g].Pos );
776 lookat.rotateVect ( dv[i+g].Normal, vin[i+g].Normal ); 776 lookat.rotateVect ( dv[i+g].Normal, vin[i+g].Normal );
777 } 777 }
778 778
779 } 779 }
780 function.count = 1; 780 function.count = 1;
781} 781}
782 782
783 783
784/*! 784/*!
785 deformVertexes autosprite2 785 deformVertexes autosprite2
786 Is a slightly modified "sprite" that only rotates around the middle of its longest axis. 786 Is a slightly modified "sprite" that only rotates around the middle of its longest axis.
787 This allows you to make a pillar of fire that you can walk around, or an energy beam 787 This allows you to make a pillar of fire that you can walk around, or an energy beam
788 stretched across the room. 788 stretched across the room.
789*/ 789*/
790 790
791struct sortaxis 791struct sortaxis
792{ 792{
793 core::vector3df v; 793 core::vector3df v;
794 bool operator < ( const sortaxis &other ) const 794 bool operator < ( const sortaxis &other ) const
795 { 795 {
796 return v.getLengthSQ () < other.v.getLengthSQ (); 796 return v.getLengthSQ () < other.v.getLengthSQ ();
797 } 797 }
798}; 798};
799/*! 799/*!
800*/ 800*/
801void CQuake3ShaderSceneNode::deformvertexes_autosprite2( f32 dt, SModifierFunction &function ) 801void CQuake3ShaderSceneNode::deformvertexes_autosprite2( f32 dt, SModifierFunction &function )
802{ 802{
803 u32 vsize = Original->Vertices.size(); 803 u32 vsize = Original->Vertices.size();
804 u32 g; 804 u32 g;
805 u32 i; 805 u32 i;
806 806
807 const core::vector3df camPos = SceneManager->getActiveCamera()->getAbsolutePosition(); 807 const core::vector3df camPos = SceneManager->getActiveCamera()->getAbsolutePosition();
808 808
809 video::S3DVertex * dv = MeshBuffer->Vertices.pointer(); 809 video::S3DVertex * dv = MeshBuffer->Vertices.pointer();
810 const video::S3DVertex2TCoords * vin = Original->Vertices.const_pointer(); 810 const video::S3DVertex2TCoords * vin = Original->Vertices.const_pointer();
811 811
812 core::matrix4 lookat ( core::matrix4::EM4CONST_NOTHING ); 812 core::matrix4 lookat ( core::matrix4::EM4CONST_NOTHING );
813 813
814 core::array < sortaxis > axis; 814 core::array < sortaxis > axis;
815 axis.set_used ( 3 ); 815 axis.set_used ( 3 );
816 816
817 for ( i = 0; i < vsize; i += 4 ) 817 for ( i = 0; i < vsize; i += 4 )
818 { 818 {
819 // quad-plane 819 // quad-plane
820 core::vector3df center = 0.25f * ( vin[i+0].Pos + vin[i+1].Pos + vin[i+2].Pos + vin[i+3].Pos ); 820 core::vector3df center = 0.25f * ( vin[i+0].Pos + vin[i+1].Pos + vin[i+2].Pos + vin[i+3].Pos );
821 821
822 // longes axe 822 // longes axe
823 axis[0].v = vin[i+1].Pos - vin[i+0].Pos; 823 axis[0].v = vin[i+1].Pos - vin[i+0].Pos;
824 axis[1].v = vin[i+2].Pos - vin[i+0].Pos; 824 axis[1].v = vin[i+2].Pos - vin[i+0].Pos;
825 axis[2].v = vin[i+3].Pos - vin[i+0].Pos; 825 axis[2].v = vin[i+3].Pos - vin[i+0].Pos;
826 axis.set_sorted ( false ); 826 axis.set_sorted ( false );
827 axis.sort (); 827 axis.sort ();
828 828
829 lookat.buildAxisAlignedBillboard ( camPos, center, MeshOffset, axis[1].v, vin[i+0].Normal ); 829 lookat.buildAxisAlignedBillboard ( camPos, center, MeshOffset, axis[1].v, vin[i+0].Normal );
830 830
831 for ( g = 0; g < 4; ++g ) 831 for ( g = 0; g < 4; ++g )
832 { 832 {
833 lookat.transformVect ( dv[i+g].Pos, vin[i+g].Pos ); 833 lookat.transformVect ( dv[i+g].Pos, vin[i+g].Pos );
834 lookat.rotateVect ( dv[i+g].Normal, vin[i+g].Normal ); 834 lookat.rotateVect ( dv[i+g].Normal, vin[i+g].Normal );
835 } 835 }
836 } 836 }
837 function.count = 1; 837 function.count = 1;
838} 838}
839 839
840/* 840/*
841 Generate Vertex Color 841 Generate Vertex Color
842*/ 842*/
843void CQuake3ShaderSceneNode::vertextransform_rgbgen( f32 dt, SModifierFunction &function ) 843void CQuake3ShaderSceneNode::vertextransform_rgbgen( f32 dt, SModifierFunction &function )
844{ 844{
845 u32 i; 845 u32 i;
846 const u32 vsize = Original->Vertices.size(); 846 const u32 vsize = Original->Vertices.size();
847 847
848 switch ( function.rgbgen ) 848 switch ( function.rgbgen )
849 { 849 {
850 case IDENTITY: 850 case IDENTITY:
851 //rgbgen identity 851 //rgbgen identity
852 for ( i = 0; i != vsize; ++i ) 852 for ( i = 0; i != vsize; ++i )
853 MeshBuffer->Vertices[i].Color.set(0xFFFFFFFF); 853 MeshBuffer->Vertices[i].Color.set(0xFFFFFFFF);
854 break; 854 break;
855 855
856 case IDENTITYLIGHTING: 856 case IDENTITYLIGHTING:
857 // rgbgen identitylighting TODO: overbright 857 // rgbgen identitylighting TODO: overbright
858 for ( i = 0; i != vsize; ++i ) 858 for ( i = 0; i != vsize; ++i )
859 MeshBuffer->Vertices[i].Color.set(0xFF7F7F7F); 859 MeshBuffer->Vertices[i].Color.set(0xFF7F7F7F);
860 break; 860 break;
861 861
862 case EXACTVERTEX: 862 case EXACTVERTEX:
863 // alphagen exactvertex TODO lighting 863 // alphagen exactvertex TODO lighting
864 case VERTEX: 864 case VERTEX:
865 // rgbgen vertex 865 // rgbgen vertex
866 for ( i = 0; i != vsize; ++i ) 866 for ( i = 0; i != vsize; ++i )
867 MeshBuffer->Vertices[i].Color=Original->Vertices[i].Color; 867 MeshBuffer->Vertices[i].Color=Original->Vertices[i].Color;
868 break; 868 break;
869 case WAVE: 869 case WAVE:
870 { 870 {
871 // rgbGen wave <func> <base> <amp> <phase> <freq> 871 // rgbGen wave <func> <base> <amp> <phase> <freq>
872 f32 f = function.evaluate( dt ) * 255.f; 872 f32 f = function.evaluate( dt ) * 255.f;
873 s32 value = core::clamp( core::floor32(f), 0, 255 ); 873 s32 value = core::clamp( core::floor32(f), 0, 255 );
874 value = 0xFF000000 | value << 16 | value << 8 | value; 874 value = 0xFF000000 | value << 16 | value << 8 | value;
875 875
876 for ( i = 0; i != vsize; ++i ) 876 for ( i = 0; i != vsize; ++i )
877 MeshBuffer->Vertices[i].Color.set(value); 877 MeshBuffer->Vertices[i].Color.set(value);
878 } break; 878 } break;
879 case CONSTANT: 879 case CONSTANT:
880 { 880 {
881 //rgbgen const ( x y z ) 881 //rgbgen const ( x y z )
882 video::SColorf cf( function.x, function.y, function.z ); 882 video::SColorf cf( function.x, function.y, function.z );
883 video::SColor col = cf.toSColor(); 883 video::SColor col = cf.toSColor();
884 for ( i = 0; i != vsize; ++i ) 884 for ( i = 0; i != vsize; ++i )
885 MeshBuffer->Vertices[i].Color=col; 885 MeshBuffer->Vertices[i].Color=col;
886 } break; 886 } break;
887 default: 887 default:
888 break; 888 break;
889 } 889 }
890} 890}
891 891
892/* 892/*
893 Generate Vertex Color, Alpha 893 Generate Vertex Color, Alpha
894*/ 894*/
895void CQuake3ShaderSceneNode::vertextransform_alphagen( f32 dt, SModifierFunction &function ) 895void CQuake3ShaderSceneNode::vertextransform_alphagen( f32 dt, SModifierFunction &function )
896{ 896{
897 u32 i; 897 u32 i;
898 const u32 vsize = Original->Vertices.size(); 898 const u32 vsize = Original->Vertices.size();
899 899
900 switch ( function.alphagen ) 900 switch ( function.alphagen )
901 { 901 {
902 case IDENTITY: 902 case IDENTITY:
903 //alphagen identity 903 //alphagen identity
904 for ( i = 0; i != vsize; ++i ) 904 for ( i = 0; i != vsize; ++i )
905 MeshBuffer->Vertices[i].Color.setAlpha ( 0xFF ); 905 MeshBuffer->Vertices[i].Color.setAlpha ( 0xFF );
906 break; 906 break;
907 907
908 case EXACTVERTEX: 908 case EXACTVERTEX:
909 // alphagen exactvertex TODO lighting 909 // alphagen exactvertex TODO lighting
910 case VERTEX: 910 case VERTEX:
911 // alphagen vertex 911 // alphagen vertex
912 for ( i = 0; i != vsize; ++i ) 912 for ( i = 0; i != vsize; ++i )
913 MeshBuffer->Vertices[i].Color.setAlpha ( Original->Vertices[i].Color.getAlpha() ); 913 MeshBuffer->Vertices[i].Color.setAlpha ( Original->Vertices[i].Color.getAlpha() );
914 break; 914 break;
915 case CONSTANT: 915 case CONSTANT:
916 { 916 {
917 // alphagen const 917 // alphagen const
918 u32 a = (u32) ( function.x * 255.f ); 918 u32 a = (u32) ( function.x * 255.f );
919 for ( i = 0; i != vsize; ++i ) 919 for ( i = 0; i != vsize; ++i )
920 MeshBuffer->Vertices[i].Color.setAlpha ( a ); 920 MeshBuffer->Vertices[i].Color.setAlpha ( a );
921 } break; 921 } break;
922 922
923 case LIGHTINGSPECULAR: 923 case LIGHTINGSPECULAR:
924 { 924 {
925 // alphagen lightingspecular TODO!!! 925 // alphagen lightingspecular TODO!!!
926 const SViewFrustum *frustum = SceneManager->getActiveCamera()->getViewFrustum(); 926 const SViewFrustum *frustum = SceneManager->getActiveCamera()->getViewFrustum();
927 const core::matrix4 &view = frustum->getTransform ( video::ETS_VIEW ); 927 const core::matrix4 &view = frustum->getTransform ( video::ETS_VIEW );
928 928
929 const f32 *m = view.pointer(); 929 const f32 *m = view.pointer();
930 930
931 for ( i = 0; i != vsize; ++i ) 931 for ( i = 0; i != vsize; ++i )
932 { 932 {
933 const core::vector3df &n = Original->Vertices[i].Normal; 933 const core::vector3df &n = Original->Vertices[i].Normal;
934 MeshBuffer->Vertices[i].Color.setAlpha ((u32)( 128.f *(1.f+(n.X*m[0]+n.Y*m[1]+n.Z*m[2])))); 934 MeshBuffer->Vertices[i].Color.setAlpha ((u32)( 128.f *(1.f+(n.X*m[0]+n.Y*m[1]+n.Z*m[2]))));
935 } 935 }
936 936
937 } break; 937 } break;
938 938
939 939
940 case WAVE: 940 case WAVE:
941 { 941 {
942 // alphagen wave 942 // alphagen wave
943 f32 f = function.evaluate( dt ) * 255.f; 943 f32 f = function.evaluate( dt ) * 255.f;
944 s32 value = core::clamp( core::floor32(f), 0, 255 ); 944 s32 value = core::clamp( core::floor32(f), 0, 255 );
945 945
946 for ( i = 0; i != vsize; ++i ) 946 for ( i = 0; i != vsize; ++i )
947 MeshBuffer->Vertices[i].Color.setAlpha ( value ); 947 MeshBuffer->Vertices[i].Color.setAlpha ( value );
948 } break; 948 } break;
949 default: 949 default:
950 break; 950 break;
951 } 951 }
952} 952}
953 953
954 954
955 955
956/* 956/*
957 Generate Texture Coordinates 957 Generate Texture Coordinates
958*/ 958*/
959void CQuake3ShaderSceneNode::vertextransform_tcgen( f32 dt, SModifierFunction &function ) 959void CQuake3ShaderSceneNode::vertextransform_tcgen( f32 dt, SModifierFunction &function )
960{ 960{
961 u32 i; 961 u32 i;
962 const u32 vsize = Original->Vertices.size(); 962 const u32 vsize = Original->Vertices.size();
963 963
964 switch ( function.tcgen ) 964 switch ( function.tcgen )
965 { 965 {
966 case TURBULENCE: 966 case TURBULENCE:
967 //tcgen turb 967 //tcgen turb
968 { 968 {
969 function.wave = core::reciprocal( function.phase ); 969 function.wave = core::reciprocal( function.phase );
970 970
971 const f32 phase = function.phase; 971 const f32 phase = function.phase;
972 972
973 for ( i = 0; i != vsize; ++i ) 973 for ( i = 0; i != vsize; ++i )
974 { 974 {
975 const video::S3DVertex2TCoords &src = Original->Vertices[i]; 975 const video::S3DVertex2TCoords &src = Original->Vertices[i];
976 video::S3DVertex &dst = MeshBuffer->Vertices[i]; 976 video::S3DVertex &dst = MeshBuffer->Vertices[i];
977 977
978 const f32 wavephase = (src.Pos.X + src.Pos.Y + src.Pos.Z) * function.wave; 978 const f32 wavephase = (src.Pos.X + src.Pos.Y + src.Pos.Z) * function.wave;
979 function.phase = phase + wavephase; 979 function.phase = phase + wavephase;
980 980
981 const f32 f = function.evaluate( dt ); 981 const f32 f = function.evaluate( dt );
982 982
983 dst.TCoords.X = src.TCoords.X + f * src.Normal.X; 983 dst.TCoords.X = src.TCoords.X + f * src.Normal.X;
984 dst.TCoords.Y = src.TCoords.Y + f * src.Normal.Y; 984 dst.TCoords.Y = src.TCoords.Y + f * src.Normal.Y;
985 } 985 }
986 } 986 }
987 break; 987 break;
988 988
989 case TEXTURE: 989 case TEXTURE:
990 // tcgen texture 990 // tcgen texture
991 for ( i = 0; i != vsize; ++i ) 991 for ( i = 0; i != vsize; ++i )
992 MeshBuffer->Vertices[i].TCoords = Original->Vertices[i].TCoords; 992 MeshBuffer->Vertices[i].TCoords = Original->Vertices[i].TCoords;
993 break; 993 break;
994 case LIGHTMAP: 994 case LIGHTMAP:
995 // tcgen lightmap 995 // tcgen lightmap
996 for ( i = 0; i != vsize; ++i ) 996 for ( i = 0; i != vsize; ++i )
997 MeshBuffer->Vertices[i].TCoords = Original->Vertices[i].TCoords2; 997 MeshBuffer->Vertices[i].TCoords = Original->Vertices[i].TCoords2;
998 break; 998 break;
999 case ENVIRONMENT: 999 case ENVIRONMENT:
1000 { 1000 {
1001 // tcgen environment 1001 // tcgen environment
1002 const SViewFrustum *frustum = SceneManager->getActiveCamera()->getViewFrustum(); 1002 const SViewFrustum *frustum = SceneManager->getActiveCamera()->getViewFrustum();
1003 const core::matrix4 &view = frustum->getTransform ( video::ETS_VIEW ); 1003 const core::matrix4 &view = frustum->getTransform ( video::ETS_VIEW );
1004 1004
1005 const f32 *m = view.pointer(); 1005 const f32 *m = view.pointer();
1006 1006
1007 core::vector3df n; 1007 core::vector3df n;
1008 for ( i = 0; i != vsize; ++i ) 1008 for ( i = 0; i != vsize; ++i )
1009 { 1009 {
1010 //const core::vector3df &n = Original->Vertices[i].Normal; 1010 //const core::vector3df &n = Original->Vertices[i].Normal;
1011 1011
1012 n = frustum->cameraPosition - Original->Vertices[i].Pos; 1012 n = frustum->cameraPosition - Original->Vertices[i].Pos;
1013 n.normalize(); 1013 n.normalize();
1014 n += Original->Vertices[i].Normal; 1014 n += Original->Vertices[i].Normal;
1015 n.normalize(); 1015 n.normalize();
1016 1016
1017 MeshBuffer->Vertices[i].TCoords.X = 0.5f*(1.f+(n.X*m[0]+n.Y*m[1]+n.Z*m[2])); 1017 MeshBuffer->Vertices[i].TCoords.X = 0.5f*(1.f+(n.X*m[0]+n.Y*m[1]+n.Z*m[2]));
1018 MeshBuffer->Vertices[i].TCoords.Y = 0.5f*(1.f+(n.X*m[4]+n.Y*m[5]+n.Z*m[6])); 1018 MeshBuffer->Vertices[i].TCoords.Y = 0.5f*(1.f+(n.X*m[4]+n.Y*m[5]+n.Z*m[6]));
1019 } 1019 }
1020 1020
1021 } break; 1021 } break;
1022 default: 1022 default:
1023 break; 1023 break;
1024 } 1024 }
1025} 1025}
1026 1026
1027 1027
1028#if 0 1028#if 0
1029/* 1029/*
1030 Transform Texture Coordinates 1030 Transform Texture Coordinates
1031*/ 1031*/
1032void CQuake3ShaderSceneNode::transformtex( const core::matrix4 &m, const u32 addressMode ) 1032void CQuake3ShaderSceneNode::transformtex( const core::matrix4 &m, const u32 addressMode )
1033{ 1033{
1034 u32 i; 1034 u32 i;
1035 const u32 vsize = MeshBuffer->Vertices.size(); 1035 const u32 vsize = MeshBuffer->Vertices.size();
1036 1036
1037 f32 tx1; 1037 f32 tx1;
1038 f32 ty1; 1038 f32 ty1;
1039 1039
1040 if ( addressMode ) 1040 if ( addressMode )
1041 { 1041 {
1042 for ( i = 0; i != vsize; ++i ) 1042 for ( i = 0; i != vsize; ++i )
1043 { 1043 {
1044 core::vector2df &tx = MeshBuffer->Vertices[i].TCoords; 1044 core::vector2df &tx = MeshBuffer->Vertices[i].TCoords;
1045 1045
1046 tx1 = m[0] * tx.X + m[4] * tx.Y + m[8]; 1046 tx1 = m[0] * tx.X + m[4] * tx.Y + m[8];
1047 ty1 = m[1] * tx.X + m[5] * tx.Y + m[9]; 1047 ty1 = m[1] * tx.X + m[5] * tx.Y + m[9];
1048 1048
1049 tx.X = tx1; 1049 tx.X = tx1;
1050 tx.Y = ty1; 1050 tx.Y = ty1;
1051 } 1051 }
1052 } 1052 }
1053 else 1053 else
1054 { 1054 {
1055 1055
1056 for ( i = 0; i != vsize; ++i ) 1056 for ( i = 0; i != vsize; ++i )
1057 { 1057 {
1058 core::vector2df &tx = MeshBuffer->Vertices[i].TCoords; 1058 core::vector2df &tx = MeshBuffer->Vertices[i].TCoords;
1059 1059
1060 tx1 = m[0] * tx.X + m[4] * tx.Y + m[8]; 1060 tx1 = m[0] * tx.X + m[4] * tx.Y + m[8];
1061 ty1 = m[1] * tx.X + m[5] * tx.Y + m[9]; 1061 ty1 = m[1] * tx.X + m[5] * tx.Y + m[9];
1062 1062
1063 tx.X = tx1 <= 0.f ? 0.f : tx1 >= 1.f ? 1.f : tx1; 1063 tx.X = tx1 <= 0.f ? 0.f : tx1 >= 1.f ? 1.f : tx1;
1064 tx.Y = ty1 <= 0.f ? 0.f : ty1 >= 1.f ? 1.f : ty1; 1064 tx.Y = ty1 <= 0.f ? 0.f : ty1 >= 1.f ? 1.f : ty1;
1065 1065
1066 //tx.X = core::clamp( tx1, 0.f, 1.f ); 1066 //tx.X = core::clamp( tx1, 0.f, 1.f );
1067 //tx.Y = core::clamp( ty1, 0.f, 1.f ); 1067 //tx.Y = core::clamp( ty1, 0.f, 1.f );
1068 } 1068 }
1069 } 1069 }
1070} 1070}
1071 1071
1072#endif 1072#endif
1073 1073
1074 1074
1075/* 1075/*
1076 Texture & Vertex Transform Animator 1076 Texture & Vertex Transform Animator
1077 1077
1078 Return a Texture Transformation for this stage 1078 Return a Texture Transformation for this stage
1079 Vertex transformation are called if found 1079 Vertex transformation are called if found
1080 1080
1081*/ 1081*/
1082void CQuake3ShaderSceneNode::animate( u32 stage,core::matrix4 &texture ) 1082void CQuake3ShaderSceneNode::animate( u32 stage,core::matrix4 &texture )
1083{ 1083{
1084 const SVarGroup *group = Shader->getGroup( stage ); 1084 const SVarGroup *group = Shader->getGroup( stage );
1085 1085
1086 // select current texture 1086 // select current texture
1087 SQ3Texture &q3Tex = Q3Texture [ stage ]; 1087 SQ3Texture &q3Tex = Q3Texture [ stage ];
1088 if ( q3Tex.TextureFrequency != 0.f ) 1088 if ( q3Tex.TextureFrequency != 0.f )
1089 { 1089 {
1090 s32 v = core::floor32( TimeAbs * q3Tex.TextureFrequency ); 1090 s32 v = core::floor32( TimeAbs * q3Tex.TextureFrequency );
1091 q3Tex.TextureIndex = v % q3Tex.Texture.size(); 1091 q3Tex.TextureIndex = v % q3Tex.Texture.size();
1092 } 1092 }
1093 1093
1094 core::matrix4 m2; 1094 core::matrix4 m2;
1095 SModifierFunction function; 1095 SModifierFunction function;
1096 1096
1097 f32 f[16]; 1097 f32 f[16];
1098 1098
1099 // walk group for all modifiers 1099 // walk group for all modifiers
1100 for ( u32 g = 0; g != group->Variable.size(); ++g ) 1100 for ( u32 g = 0; g != group->Variable.size(); ++g )
1101 { 1101 {
1102 const SVariable &v = group->Variable[g]; 1102 const SVariable &v = group->Variable[g];
1103 1103
1104 // get the modifier 1104 // get the modifier
1105 static const c8 * modifierList[] = 1105 static const c8 * modifierList[] =
1106 { 1106 {
1107 "tcmod","deformvertexes","rgbgen","tcgen","map","alphagen" 1107 "tcmod","deformvertexes","rgbgen","tcgen","map","alphagen"
1108 }; 1108 };
1109 1109
1110 u32 pos = 0; 1110 u32 pos = 0;
1111 function.masterfunc0 = (eQ3ModifierFunction) isEqual( v.name, pos, modifierList, 6 ); 1111 function.masterfunc0 = (eQ3ModifierFunction) isEqual( v.name, pos, modifierList, 6 );
1112 1112
1113 if ( UNKNOWN == function.masterfunc0 ) 1113 if ( UNKNOWN == function.masterfunc0 )
1114 continue; 1114 continue;
1115 1115
1116 switch ( function.masterfunc0 ) 1116 switch ( function.masterfunc0 )
1117 { 1117 {
1118 //tcmod 1118 //tcmod
1119 case TCMOD: 1119 case TCMOD:
1120 m2.makeIdentity(); 1120 m2.makeIdentity();
1121 break; 1121 break;
1122 default: 1122 default:
1123 break; 1123 break;
1124 } 1124 }
1125 1125
1126 // get the modifier function 1126 // get the modifier function
1127 static const c8 * funclist[] = 1127 static const c8 * funclist[] =
1128 { 1128 {
1129 "scroll","scale","rotate","stretch","turb", 1129 "scroll","scale","rotate","stretch","turb",
1130 "wave","identity","vertex", 1130 "wave","identity","vertex",
1131 "texture","lightmap","environment","$lightmap", 1131 "texture","lightmap","environment","$lightmap",
1132 "bulge","autosprite","autosprite2","transform", 1132 "bulge","autosprite","autosprite2","transform",
1133 "exactvertex","const","lightingspecular","move","normal", 1133 "exactvertex","const","lightingspecular","move","normal",
1134 "identitylighting" 1134 "identitylighting"
1135 }; 1135 };
1136 static const c8 * groupToken[] = { "(", ")" }; 1136 static const c8 * groupToken[] = { "(", ")" };
1137 1137
1138 pos = 0; 1138 pos = 0;
1139 function.masterfunc1 = (eQ3ModifierFunction) isEqual( v.content, pos, funclist, 22 ); 1139 function.masterfunc1 = (eQ3ModifierFunction) isEqual( v.content, pos, funclist, 22 );
1140 if ( function.masterfunc1 != UNKNOWN ) 1140 if ( function.masterfunc1 != UNKNOWN )
1141 function.masterfunc1 = (eQ3ModifierFunction) ((u32) function.masterfunc1 + FUNCTION2 + 1); 1141 function.masterfunc1 = (eQ3ModifierFunction) ((u32) function.masterfunc1 + FUNCTION2 + 1);
1142 1142
1143 switch ( function.masterfunc1 ) 1143 switch ( function.masterfunc1 )
1144 { 1144 {
1145 case SCROLL: 1145 case SCROLL:
1146 // tcMod scroll <sSpeed> <tSpeed> 1146 // tcMod scroll <sSpeed> <tSpeed>
1147 f[0] = getAsFloat( v.content, pos ) * TimeAbs; 1147 f[0] = getAsFloat( v.content, pos ) * TimeAbs;
1148 f[1] = getAsFloat( v.content, pos ) * TimeAbs; 1148 f[1] = getAsFloat( v.content, pos ) * TimeAbs;
1149 m2.setTextureTranslate( f[0], f[1] ); 1149 m2.setTextureTranslate( f[0], f[1] );
1150 break; 1150 break;
1151 case SCALE: 1151 case SCALE:
1152 // tcmod scale <sScale> <tScale> 1152 // tcmod scale <sScale> <tScale>
1153 f[0] = getAsFloat( v.content, pos ); 1153 f[0] = getAsFloat( v.content, pos );
1154 f[1] = getAsFloat( v.content, pos ); 1154 f[1] = getAsFloat( v.content, pos );
1155 m2.setTextureScale( f[0], f[1] ); 1155 m2.setTextureScale( f[0], f[1] );
1156 break; 1156 break;
1157 case ROTATE: 1157 case ROTATE:
1158 // tcmod rotate <degress per second> 1158 // tcmod rotate <degress per second>
1159 m2.setTextureRotationCenter( getAsFloat( v.content, pos ) * 1159 m2.setTextureRotationCenter( getAsFloat( v.content, pos ) *
1160 core::DEGTORAD * 1160 core::DEGTORAD *
1161 TimeAbs 1161 TimeAbs
1162 ); 1162 );
1163 break; 1163 break;
1164 case TRANSFORM: 1164 case TRANSFORM:
1165 // tcMod <transform> <m00> <m01> <m10> <m11> <t0> <t1> 1165 // tcMod <transform> <m00> <m01> <m10> <m11> <t0> <t1>
1166 memset(f, 0, sizeof ( f )); 1166 memset(f, 0, sizeof ( f ));
1167 f[10] = f[15] = 1.f; 1167 f[10] = f[15] = 1.f;
1168 1168
1169 f[0] = getAsFloat( v.content, pos ); 1169 f[0] = getAsFloat( v.content, pos );
1170 f[1] = getAsFloat( v.content, pos ); 1170 f[1] = getAsFloat( v.content, pos );
1171 f[4] = getAsFloat( v.content, pos ); 1171 f[4] = getAsFloat( v.content, pos );
1172 f[5] = getAsFloat( v.content, pos ); 1172 f[5] = getAsFloat( v.content, pos );
1173 f[8] = getAsFloat( v.content, pos ); 1173 f[8] = getAsFloat( v.content, pos );
1174 f[9] = getAsFloat( v.content, pos ); 1174 f[9] = getAsFloat( v.content, pos );
1175 m2.setM ( f ); 1175 m2.setM ( f );
1176 break; 1176 break;
1177 1177
1178 case STRETCH: // stretch 1178 case STRETCH: // stretch
1179 case TURBULENCE: // turb 1179 case TURBULENCE: // turb
1180 case WAVE: // wave 1180 case WAVE: // wave
1181 case IDENTITY: // identity 1181 case IDENTITY: // identity
1182 case IDENTITYLIGHTING: 1182 case IDENTITYLIGHTING:
1183 case VERTEX: // vertex 1183 case VERTEX: // vertex
1184 case MOVE: 1184 case MOVE:
1185 case CONSTANT: 1185 case CONSTANT:
1186 { 1186 {
1187 // turb == sin, default == sin 1187 // turb == sin, default == sin
1188 function.func = SINUS; 1188 function.func = SINUS;
1189 1189
1190 if ( function.masterfunc0 == DEFORMVERTEXES ) 1190 if ( function.masterfunc0 == DEFORMVERTEXES )
1191 { 1191 {
1192 switch ( function.masterfunc1 ) 1192 switch ( function.masterfunc1 )
1193 { 1193 {
1194 case WAVE: 1194 case WAVE:
1195 // deformvertexes wave 1195 // deformvertexes wave
1196 function.wave = getAsFloat( v.content, pos ); 1196 function.wave = getAsFloat( v.content, pos );
1197 break; 1197 break;
1198 case MOVE: 1198 case MOVE:
1199 //deformvertexes move 1199 //deformvertexes move
1200 function.x = getAsFloat( v.content, pos ); 1200 function.x = getAsFloat( v.content, pos );
1201 function.z = getAsFloat( v.content, pos ); 1201 function.z = getAsFloat( v.content, pos );
1202 function.y = getAsFloat( v.content, pos ); 1202 function.y = getAsFloat( v.content, pos );
1203 break; 1203 break;
1204 default: 1204 default:
1205 break; 1205 break;
1206 } 1206 }
1207 } 1207 }
1208 1208
1209 switch ( function.masterfunc1 ) 1209 switch ( function.masterfunc1 )
1210 { 1210 {
1211 case STRETCH: 1211 case STRETCH:
1212 case TURBULENCE: 1212 case TURBULENCE:
1213 case WAVE: 1213 case WAVE:
1214 case MOVE: 1214 case MOVE:
1215 getModifierFunc( function, v.content, pos ); 1215 getModifierFunc( function, v.content, pos );
1216 break; 1216 break;
1217 default: 1217 default:
1218 break; 1218 break;
1219 } 1219 }
1220 1220
1221 switch ( function.masterfunc1 ) 1221 switch ( function.masterfunc1 )
1222 { 1222 {
1223 case STRETCH: 1223 case STRETCH:
1224 //tcMod stretch <func> <base> <amplitude> <phase> <frequency> 1224 //tcMod stretch <func> <base> <amplitude> <phase> <frequency>
1225 f[0] = core::reciprocal( function.evaluate(TimeAbs) ); 1225 f[0] = core::reciprocal( function.evaluate(TimeAbs) );
1226 m2.setTextureScaleCenter( f[0], f[0] ); 1226 m2.setTextureScaleCenter( f[0], f[0] );
1227 break; 1227 break;
1228 case TURBULENCE: 1228 case TURBULENCE:
1229 //tcMod turb <base> <amplitude> <phase> <freq> 1229 //tcMod turb <base> <amplitude> <phase> <freq>
1230 //function.tcgen = TURBULENCE; 1230 //function.tcgen = TURBULENCE;
1231 m2.setTextureRotationCenter( function.frequency * 1231 m2.setTextureRotationCenter( function.frequency *
1232 core::DEGTORAD * 1232 core::DEGTORAD *
1233 TimeAbs 1233 TimeAbs
1234 ); 1234 );
1235 break; 1235 break;
1236 case WAVE: 1236 case WAVE:
1237 case IDENTITY: 1237 case IDENTITY:
1238 case IDENTITYLIGHTING: 1238 case IDENTITYLIGHTING:
1239 case VERTEX: 1239 case VERTEX:
1240 case EXACTVERTEX: 1240 case EXACTVERTEX:
1241 case CONSTANT: 1241 case CONSTANT:
1242 case LIGHTINGSPECULAR: 1242 case LIGHTINGSPECULAR:
1243 case MOVE: 1243 case MOVE:
1244 switch ( function.masterfunc0 ) 1244 switch ( function.masterfunc0 )
1245 { 1245 {
1246 case DEFORMVERTEXES: 1246 case DEFORMVERTEXES:
1247 switch ( function.masterfunc1 ) 1247 switch ( function.masterfunc1 )
1248 { 1248 {
1249 case WAVE: 1249 case WAVE:
1250 deformvertexes_wave( TimeAbs, function ); 1250 deformvertexes_wave( TimeAbs, function );
1251 break; 1251 break;
1252 case MOVE: 1252 case MOVE:
1253 deformvertexes_move( TimeAbs, function ); 1253 deformvertexes_move( TimeAbs, function );
1254 break; 1254 break;
1255 default: 1255 default:
1256 break; 1256 break;
1257 } 1257 }
1258 break; 1258 break;
1259 case RGBGEN: 1259 case RGBGEN:
1260 function.rgbgen = function.masterfunc1; 1260 function.rgbgen = function.masterfunc1;
1261 if ( function.rgbgen == CONSTANT ) 1261 if ( function.rgbgen == CONSTANT )
1262 { 1262 {
1263 isEqual ( v.content, pos, groupToken, 2 ); 1263 isEqual ( v.content, pos, groupToken, 2 );
1264 function.x = getAsFloat( v.content, pos ); 1264 function.x = getAsFloat( v.content, pos );
1265 function.y = getAsFloat( v.content, pos ); 1265 function.y = getAsFloat( v.content, pos );
1266 function.z = getAsFloat( v.content, pos ); 1266 function.z = getAsFloat( v.content, pos );
1267 } 1267 }
1268 //vertextransform_rgbgen( TimeAbs, function ); 1268 //vertextransform_rgbgen( TimeAbs, function );
1269 break; 1269 break;
1270 case ALPHAGEN: 1270 case ALPHAGEN:
1271 function.alphagen = function.masterfunc1; 1271 function.alphagen = function.masterfunc1;
1272 if ( function.alphagen == CONSTANT ) 1272 if ( function.alphagen == CONSTANT )
1273 { 1273 {
1274 function.x = getAsFloat( v.content, pos ); 1274 function.x = getAsFloat( v.content, pos );
1275 } 1275 }
1276 1276
1277 //vertextransform_alphagen( TimeAbs, function ); 1277 //vertextransform_alphagen( TimeAbs, function );
1278 break; 1278 break;
1279 default: 1279 default:
1280 break; 1280 break;
1281 } 1281 }
1282 break; 1282 break;
1283 default: 1283 default:
1284 break; 1284 break;
1285 } 1285 }
1286 1286
1287 } break; 1287 } break;
1288 case TEXTURE: 1288 case TEXTURE:
1289 case LIGHTMAP: 1289 case LIGHTMAP:
1290 case ENVIRONMENT: 1290 case ENVIRONMENT:
1291 // "texture","lightmap","environment" 1291 // "texture","lightmap","environment"
1292 function.tcgen = function.masterfunc1; 1292 function.tcgen = function.masterfunc1;
1293 break; 1293 break;
1294 case DOLLAR_LIGHTMAP: 1294 case DOLLAR_LIGHTMAP:
1295 // map == lightmap, tcgen == lightmap 1295 // map == lightmap, tcgen == lightmap
1296 function.tcgen = LIGHTMAP; 1296 function.tcgen = LIGHTMAP;
1297 break; 1297 break;
1298 case BULGE: 1298 case BULGE:
1299 // deformvertexes bulge 1299 // deformvertexes bulge
1300 function.bulgewidth = getAsFloat( v.content, pos ); 1300 function.bulgewidth = getAsFloat( v.content, pos );
1301 function.bulgeheight = getAsFloat( v.content, pos ); 1301 function.bulgeheight = getAsFloat( v.content, pos );
1302 function.bulgespeed = getAsFloat( v.content, pos ); 1302 function.bulgespeed = getAsFloat( v.content, pos );
1303 1303
1304 deformvertexes_bulge(TimeAbs, function); 1304 deformvertexes_bulge(TimeAbs, function);
1305 break; 1305 break;
1306 1306
1307 case NORMAL: 1307 case NORMAL:
1308 // deformvertexes normal 1308 // deformvertexes normal
1309 function.amp = getAsFloat( v.content, pos ); 1309 function.amp = getAsFloat( v.content, pos );
1310 function.frequency = getAsFloat( v.content, pos ); 1310 function.frequency = getAsFloat( v.content, pos );
1311 1311
1312 deformvertexes_normal(TimeAbs, function); 1312 deformvertexes_normal(TimeAbs, function);
1313 break; 1313 break;
1314 1314
1315 case AUTOSPRITE: 1315 case AUTOSPRITE:
1316 // deformvertexes autosprite 1316 // deformvertexes autosprite
1317 deformvertexes_autosprite(TimeAbs, function); 1317 deformvertexes_autosprite(TimeAbs, function);
1318 break; 1318 break;
1319 1319
1320 case AUTOSPRITE2: 1320 case AUTOSPRITE2:
1321 // deformvertexes autosprite2 1321 // deformvertexes autosprite2
1322 deformvertexes_autosprite2(TimeAbs, function); 1322 deformvertexes_autosprite2(TimeAbs, function);
1323 break; 1323 break;
1324 default: 1324 default:
1325 break; 1325 break;
1326 } // func 1326 } // func
1327 1327
1328 switch ( function.masterfunc0 ) 1328 switch ( function.masterfunc0 )
1329 { 1329 {
1330 case TCMOD: 1330 case TCMOD:
1331 texture *= m2; 1331 texture *= m2;
1332 break; 1332 break;
1333 default: 1333 default:
1334 break; 1334 break;
1335 } 1335 }
1336 1336
1337 } // group 1337 } // group
1338 1338
1339 vertextransform_rgbgen( TimeAbs, function ); 1339 vertextransform_rgbgen( TimeAbs, function );
1340 vertextransform_alphagen( TimeAbs, function ); 1340 vertextransform_alphagen( TimeAbs, function );
1341 vertextransform_tcgen( TimeAbs, function ); 1341 vertextransform_tcgen( TimeAbs, function );
1342} 1342}
1343 1343
1344 1344
1345void CQuake3ShaderSceneNode::OnAnimate(u32 timeMs) 1345void CQuake3ShaderSceneNode::OnAnimate(u32 timeMs)
1346{ 1346{
1347 TimeAbs = f32( timeMs ) * (1.f/1000.f); 1347 TimeAbs = f32( timeMs ) * (1.f/1000.f);
1348 ISceneNode::OnAnimate( timeMs ); 1348 ISceneNode::OnAnimate( timeMs );
1349} 1349}
1350 1350
1351const core::aabbox3d<f32>& CQuake3ShaderSceneNode::getBoundingBox() const 1351const core::aabbox3d<f32>& CQuake3ShaderSceneNode::getBoundingBox() const
1352{ 1352{
1353 return MeshBuffer->getBoundingBox(); 1353 return MeshBuffer->getBoundingBox();
1354} 1354}
1355 1355
1356 1356
1357u32 CQuake3ShaderSceneNode::getMaterialCount() const 1357u32 CQuake3ShaderSceneNode::getMaterialCount() const
1358{ 1358{
1359 return Q3Texture.size(); 1359 return Q3Texture.size();
1360} 1360}
1361 1361
1362video::SMaterial& CQuake3ShaderSceneNode::getMaterial(u32 i) 1362video::SMaterial& CQuake3ShaderSceneNode::getMaterial(u32 i)
1363{ 1363{
1364 video::SMaterial& m = MeshBuffer->Material; 1364 video::SMaterial& m = MeshBuffer->Material;
1365 m.setTexture(0, 0); 1365 m.setTexture(0, 0);
1366 if ( Q3Texture [ i ].TextureIndex ) 1366 if ( Q3Texture [ i ].TextureIndex )
1367 m.setTexture(0, Q3Texture [ i ].Texture [ Q3Texture [ i ].TextureIndex ]); 1367 m.setTexture(0, Q3Texture [ i ].Texture [ Q3Texture [ i ].TextureIndex ]);
1368 return m; 1368 return m;
1369} 1369}
1370 1370
1371 1371
1372} // end namespace scene 1372} // end namespace scene
1373} // end namespace irr 1373} // end namespace irr
1374 1374
1375#endif 1375#endif
1376 1376