source: OGRE/trunk/ogrenew/PlugIns/BSPSceneManager/src/OgreQuake3Shader.cpp @ 657

Revision 657, 11.3 KB checked in by mattausch, 19 years ago (diff)

added ogre dependencies and patched ogre sources

RevLine 
[657]1/*
2-----------------------------------------------------------------------------
3This source file is part of OGRE
4    (Object-oriented Graphics Rendering Engine)
5For the latest info, see http://www.ogre3d.org/
6
7Copyright (c) 2000-2005 The OGRE Team
8Also see acknowledgements in Readme.html
9
10This program is free software; you can redistribute it and/or modify it under
11the terms of the GNU Lesser General Public License as published by the Free Software
12Foundation; either version 2 of the License, or (at your option) any later
13version.
14
15This program is distributed in the hope that it will be useful, but WITHOUT
16ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
17FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
18
19You should have received a copy of the GNU Lesser General Public License along with
20this program; if not, write to the Free Software Foundation, Inc., 59 Temple
21Place - Suite 330, Boston, MA 02111-1307, USA, or go to
22http://www.gnu.org/copyleft/lesser.txt.
23-----------------------------------------------------------------------------
24*/
25
26#include "OgreQuake3Shader.h"
27#include "OgreSceneManager.h"
28#include "OgreMaterial.h"
29#include "OgreTechnique.h"
30#include "OgrePass.h"
31#include "OgreTextureUnitState.h"
32#include "OgreMath.h"
33#include "OgreLogManager.h"
34#include "OgreTextureManager.h"
35#include "OgreRoot.h"
36
37namespace Ogre {
38
39
40    //-----------------------------------------------------------------------
41    Quake3Shader::Quake3Shader(const String& name)
42    {
43        mName = name;
44        numPasses = 0;
45        deformFunc = DEFORM_FUNC_NONE;
46        farbox = false;
47        skyDome = false;
48        flags = 0;
49        fog = false;
50        cullMode = MANUAL_CULL_BACK;
51
52    }
53    //-----------------------------------------------------------------------
54    Quake3Shader::~Quake3Shader()
55    {
56    }
57    //-----------------------------------------------------------------------
58    MaterialPtr Quake3Shader::createAsMaterial(int lightmapNumber)
59    {
60                String matName;
61                StringUtil::StrStreamType str;
62        String resourceGroup = ResourceGroupManager::getSingleton().getWorldResourceGroupName();
63
64        str << mName << "#" << lightmapNumber;
65                matName = str.str();
66
67        MaterialPtr mat = MaterialManager::getSingleton().create(matName,
68            resourceGroup);
69                Ogre::Pass* ogrePass = mat->getTechnique(0)->getPass(0);
70
71        LogManager::getSingleton().logMessage("Using Q3 shader " + mName, LML_CRITICAL);
72        for (int p = 0; p < numPasses; ++p)
73        {
74            TextureUnitState* t;
75            // Create basic texture
76            if (pass[p].textureName == "$lightmap")
77            {
78                StringUtil::StrStreamType str2;
79                                str2 << "@lightmap" << lightmapNumber;
80                t = ogrePass->createTextureUnitState(str2.str());
81            }
82            // Animated texture support
83            else if (pass[p].animNumFrames > 0)
84            {
85                Real sequenceTime = pass[p].animNumFrames / pass[p].animFps;
86                /* Pre-load textures
87                   We need to know if each one was loaded OK since extensions may change for each
88                   Quake3 can still include alternate extension filenames e.g. jpg instead of tga
89                   Pain in the arse - have to check for each frame as letters<n>.tga for example
90                   is different per frame!
91                */
92                for (unsigned int alt = 0; alt < pass[p].animNumFrames; ++alt)
93                {
94                    if (!ResourceGroupManager::getSingleton().resourceExists(
95                        resourceGroup, pass[p].frames[alt]))
96                    {
97                        // Try alternate extension
98                        pass[p].frames[alt] = getAlternateName(pass[p].frames[alt]);
99                        if (!ResourceGroupManager::getSingleton().resourceExists(
100                            resourceGroup, pass[p].frames[alt]))
101                        {
102                            // stuffed - no texture
103                            continue;
104                        }
105                    }
106
107                }
108
109                t = ogrePass->createTextureUnitState("");
110                t->setAnimatedTextureName(pass[p].frames, pass[p].animNumFrames, sequenceTime);
111
112            }
113            else
114            {
115                // Quake3 can still include alternate extension filenames e.g. jpg instead of tga
116                // Pain in the arse - have to check for failure
117                if (!ResourceGroupManager::getSingleton().resourceExists(
118                    resourceGroup, pass[p].textureName))
119                {
120                    // Try alternate extension
121                    pass[p].textureName = getAlternateName(pass[p].textureName);
122                    if (!ResourceGroupManager::getSingleton().resourceExists(
123                        resourceGroup, pass[p].textureName))
124                    {
125                        // stuffed - no texture
126                        continue;
127                    }
128                }
129                t = ogrePass->createTextureUnitState(pass[p].textureName);
130            }
131            // Blending
132            if (p == 0)
133            {
134                // scene blend
135                mat->setSceneBlending(pass[p].blendSrc, pass[p].blendDest);
136                if (mat->isTransparent() &&
137                    pass[p].blendSrc != SBF_SOURCE_ALPHA)
138                    mat->setDepthWriteEnabled(false);
139
140                t->setColourOperation(LBO_REPLACE);
141                                // Alpha mode
142                                ogrePass->setAlphaRejectSettings(
143                                        pass[p].alphaFunc, pass[p].alphaVal);
144            }
145            else
146            {
147                if (pass[p].customBlend)
148                {
149                    // Fallback for now
150                    t->setColourOperation(LBO_MODULATE);
151                }
152                else
153                {
154                    // simple layer blend
155                    t->setColourOperation(pass[p].blend);
156                }
157                                // Alpha mode, prefer 'most alphary'
158                                CompareFunction currFunc = ogrePass->getAlphaRejectFunction();
159                                unsigned char currVal = ogrePass->getAlphaRejectValue();
160                                if (pass[p].alphaFunc > currFunc ||
161                                        (pass[p].alphaFunc == currFunc && pass[p].alphaVal < currVal))
162                                {
163                                        ogrePass->setAlphaRejectSettings(
164                                                pass[p].alphaFunc, pass[p].alphaVal);
165                                }
166            }
167            // Tex coords
168            if (pass[p].texGen == TEXGEN_BASE)
169            {
170                t->setTextureCoordSet(0);
171            }
172            else if (pass[p].texGen == TEXGEN_LIGHTMAP)
173            {
174                t->setTextureCoordSet(1);
175            }
176            else if (pass[p].texGen == TEXGEN_ENVIRONMENT)
177            {
178                t->setEnvironmentMap(true, TextureUnitState::ENV_PLANAR);
179            }
180            // Tex mod
181            // Scale
182            t->setTextureUScale(pass[p].tcModScale[0]);
183            t->setTextureVScale(pass[p].tcModScale[1]);
184            // Procedural mods
185            // Custom - don't use mod if generating environment
186            // Because I do env a different way it look horrible
187            if (pass[p].texGen != TEXGEN_ENVIRONMENT)
188            {
189                if (pass[p].tcModRotate)
190                {
191                    t->setRotateAnimation(pass[p].tcModRotate);
192                }
193                if (pass[p].tcModScroll[0] || pass[p].tcModScroll[1])
194                {
195                    if (pass[p].tcModTurbOn)
196                    {
197                        // Turbulent scroll
198                        if (pass[p].tcModScroll[0])
199                        {
200                            t->setTransformAnimation(TextureUnitState::TT_TRANSLATE_U, WFT_SINE,
201                                pass[p].tcModTurb[0], pass[p].tcModTurb[3], pass[p].tcModTurb[2], pass[p].tcModTurb[1]);
202                        }
203                        if (pass[p].tcModScroll[1])
204                        {
205                            t->setTransformAnimation(TextureUnitState::TT_TRANSLATE_V, WFT_SINE,
206                                pass[p].tcModTurb[0], pass[p].tcModTurb[3], pass[p].tcModTurb[2], pass[p].tcModTurb[1]);
207                        }
208                    }
209                    else
210                    {
211                        // Constant scroll
212                        t->setScrollAnimation(pass[p].tcModScroll[0], pass[p].tcModScroll[1]);
213                    }
214                }
215                if (pass[p].tcModStretchWave != SHADER_FUNC_NONE)
216                {
217                    WaveformType wft;
218                    switch(pass[p].tcModStretchWave)
219                    {
220                    case SHADER_FUNC_SIN:
221                        wft = WFT_SINE;
222                        break;
223                    case SHADER_FUNC_TRIANGLE:
224                        wft = WFT_TRIANGLE;
225                        break;
226                    case SHADER_FUNC_SQUARE:
227                        wft = WFT_SQUARE;
228                        break;
229                    case SHADER_FUNC_SAWTOOTH:
230                        wft = WFT_SAWTOOTH;
231                        break;
232                    case SHADER_FUNC_INVERSESAWTOOTH:
233                        wft = WFT_INVERSE_SAWTOOTH;
234                        break;
235                    default:
236                        break;
237                    }
238                    // Create wave-based stretcher
239                    t->setTransformAnimation(TextureUnitState::TT_SCALE_U, wft, pass[p].tcModStretchParams[3],
240                        pass[p].tcModStretchParams[0], pass[p].tcModStretchParams[2], pass[p].tcModStretchParams[1]);
241                    t->setTransformAnimation(TextureUnitState::TT_SCALE_V, wft, pass[p].tcModStretchParams[3],
242                        pass[p].tcModStretchParams[0], pass[p].tcModStretchParams[2], pass[p].tcModStretchParams[1]);
243                }
244            }
245            // Address mode
246            t->setTextureAddressingMode(pass[p].addressMode);
247
248            //assert(!t->isBlank());
249
250
251        }
252        // Do farbox (create new material)
253
254        // Do skydome (use this material)
255        if (skyDome)
256        {
257            // Quake3 is always aligned with Z upwards
258            Quaternion q;
259            q.FromAngleAxis(Radian(Math::HALF_PI), Vector3::UNIT_X);
260            // Also draw last, and make close to camera (far clip plane is shorter)
261            Root::getSingleton().getSceneManager(ST_INTERIOR)
262                ->setSkyDome(true, matName, 20 - (cloudHeight / 256 * 18), 12, 2000, false, q);
263        }
264
265
266        // Set culling mode and lighting to defaults
267        mat->setCullingMode(CULL_NONE);
268        mat->setManualCullingMode(cullMode);
269        mat->setLightingEnabled(false);
270        mat->load();
271        return mat;
272    }
273    String Quake3Shader::getAlternateName(const String& texName)
274    {
275        // Get alternative JPG to TGA and vice versa
276        size_t pos;
277        String ext, base;
278
279        pos = texName.find_last_of(".");
280        ext = texName.substr(pos, 4);
281                StringUtil::toLowerCase(ext);
282        base = texName.substr(0,pos);
283        if (ext == ".jpg")
284        {
285            return base + ".tga";
286        }
287        else
288        {
289            return base + ".jpg";
290        }
291
292    }
293}
Note: See TracBrowser for help on using the repository browser.