diff options
author | David Walter Seikel | 2013-01-13 18:54:10 +1000 |
---|---|---|
committer | David Walter Seikel | 2013-01-13 18:54:10 +1000 |
commit | 959831f4ef5a3e797f576c3de08cd65032c997ad (patch) | |
tree | e7351908be5995f0b325b2ebeaa02d5a34b82583 /libraries/irrlicht-1.8/source/Irrlicht/CQuake3ShaderSceneNode.cpp | |
parent | Add info about changes to Irrlicht. (diff) | |
download | SledjHamr-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.cpp | 2752 |
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 | ||
19 | namespace irr | 19 | namespace irr |
20 | { | 20 | { |
21 | namespace scene | 21 | namespace scene |
22 | { | 22 | { |
23 | 23 | ||
24 | // who, if not you.. | 24 | // who, if not you.. |
25 | using namespace quake3; | 25 | using namespace quake3; |
26 | 26 | ||
27 | /*! | 27 | /*! |
28 | */ | 28 | */ |
29 | CQuake3ShaderSceneNode::CQuake3ShaderSceneNode( | 29 | CQuake3ShaderSceneNode::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 | */ |
73 | CQuake3ShaderSceneNode::~CQuake3ShaderSceneNode() | 73 | CQuake3ShaderSceneNode::~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 | */ |
90 | void CQuake3ShaderSceneNode::cloneBuffer( scene::SMeshBuffer *dest, const scene::SMeshBufferLightMap * buffer, bool translateCenter ) | 90 | void 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 | */ |
135 | void CQuake3ShaderSceneNode::loadTextures( io::IFileSystem * fileSystem ) | 135 | void 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 | */ |
225 | void CQuake3ShaderSceneNode::OnRegisterSceneNode() | 225 | void 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 | */ |
237 | E_SCENE_NODE_RENDER_PASS CQuake3ShaderSceneNode::getRenderStage() const | 237 | E_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 | */ |
301 | void CQuake3ShaderSceneNode::render() | 301 | void 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. |
502 | bool CQuake3ShaderSceneNode::removeChild(ISceneNode* child) | 502 | bool 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. |
516 | IShadowVolumeSceneNode* CQuake3ShaderSceneNode::addShadowVolumeSceneNode( | 516 | IShadowVolumeSceneNode* 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 | /*! |
534 | 3.3.1 deformVertexes wave <div> <func> <base> <amplitude> <phase> <freq> | 534 | 3.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 | */ |
541 | void CQuake3ShaderSceneNode::deformvertexes_wave( f32 dt, SModifierFunction &function ) | 541 | void 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 | */ |
594 | void CQuake3ShaderSceneNode::deformvertexes_move( f32 dt, SModifierFunction &function ) | 594 | void 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 | */ |
632 | void CQuake3ShaderSceneNode::deformvertexes_normal( f32 dt, SModifierFunction &function ) | 632 | void 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 | */ |
703 | void CQuake3ShaderSceneNode::deformvertexes_bulge( f32 dt, SModifierFunction &function ) | 703 | void 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 | */ |
751 | void CQuake3ShaderSceneNode::deformvertexes_autosprite( f32 dt, SModifierFunction &function ) | 751 | void 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 | ||
791 | struct sortaxis | 791 | struct 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 | */ |
801 | void CQuake3ShaderSceneNode::deformvertexes_autosprite2( f32 dt, SModifierFunction &function ) | 801 | void 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 | */ |
843 | void CQuake3ShaderSceneNode::vertextransform_rgbgen( f32 dt, SModifierFunction &function ) | 843 | void 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 | */ |
895 | void CQuake3ShaderSceneNode::vertextransform_alphagen( f32 dt, SModifierFunction &function ) | 895 | void 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 | */ |
959 | void CQuake3ShaderSceneNode::vertextransform_tcgen( f32 dt, SModifierFunction &function ) | 959 | void 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 | */ |
1032 | void CQuake3ShaderSceneNode::transformtex( const core::matrix4 &m, const u32 addressMode ) | 1032 | void 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 | */ |
1082 | void CQuake3ShaderSceneNode::animate( u32 stage,core::matrix4 &texture ) | 1082 | void 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 | ||
1345 | void CQuake3ShaderSceneNode::OnAnimate(u32 timeMs) | 1345 | void 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 | ||
1351 | const core::aabbox3d<f32>& CQuake3ShaderSceneNode::getBoundingBox() const | 1351 | const core::aabbox3d<f32>& CQuake3ShaderSceneNode::getBoundingBox() const |
1352 | { | 1352 | { |
1353 | return MeshBuffer->getBoundingBox(); | 1353 | return MeshBuffer->getBoundingBox(); |
1354 | } | 1354 | } |
1355 | 1355 | ||
1356 | 1356 | ||
1357 | u32 CQuake3ShaderSceneNode::getMaterialCount() const | 1357 | u32 CQuake3ShaderSceneNode::getMaterialCount() const |
1358 | { | 1358 | { |
1359 | return Q3Texture.size(); | 1359 | return Q3Texture.size(); |
1360 | } | 1360 | } |
1361 | 1361 | ||
1362 | video::SMaterial& CQuake3ShaderSceneNode::getMaterial(u32 i) | 1362 | video::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 | ||