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

Revision 692, 10.8 KB checked in by mattausch, 18 years ago (diff)

adding ogre 1.2 and dependencies

Line 
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#include "OgreMaterialManager.h"
37
38namespace Ogre {
39
40
41    //-----------------------------------------------------------------------
42    Quake3Shader::Quake3Shader(const String& name)
43    {
44        mName = name;
45        numPasses = 0;
46        deformFunc = DEFORM_FUNC_NONE;
47        farbox = false;
48        skyDome = false;
49        flags = 0;
50        fog = false;
51        cullMode = MANUAL_CULL_BACK;
52
53    }
54    //-----------------------------------------------------------------------
55    Quake3Shader::~Quake3Shader()
56    {
57    }
58    //-----------------------------------------------------------------------
59    MaterialPtr Quake3Shader::createAsMaterial(int lightmapNumber)
60    {
61                String matName;
62                StringUtil::StrStreamType str;
63        String resourceGroup = ResourceGroupManager::getSingleton().getWorldResourceGroupName();
64
65        str << mName << "#" << lightmapNumber;
66                matName = str.str();
67
68        MaterialPtr mat = MaterialManager::getSingleton().create(matName,
69            resourceGroup);
70                Ogre::Pass* ogrePass = mat->getTechnique(0)->getPass(0);
71
72        LogManager::getSingleton().logMessage("Using Q3 shader " + mName, LML_CRITICAL);
73        for (int p = 0; p < numPasses; ++p)
74        {
75            TextureUnitState* t;
76            // Create basic texture
77            if (pass[p].textureName == "$lightmap")
78            {
79                StringUtil::StrStreamType str2;
80                                str2 << "@lightmap" << lightmapNumber;
81                t = ogrePass->createTextureUnitState(str2.str());
82            }
83            // Animated texture support
84            else if (pass[p].animNumFrames > 0)
85            {
86                Real sequenceTime = pass[p].animNumFrames / pass[p].animFps;
87                /* Pre-load textures
88                   We need to know if each one was loaded OK since extensions may change for each
89                   Quake3 can still include alternate extension filenames e.g. jpg instead of tga
90                   Pain in the arse - have to check for each frame as letters<n>.tga for example
91                   is different per frame!
92                */
93                for (unsigned int alt = 0; alt < pass[p].animNumFrames; ++alt)
94                {
95                    if (!ResourceGroupManager::getSingleton().resourceExists(
96                        resourceGroup, pass[p].frames[alt]))
97                    {
98                        // Try alternate extension
99                        pass[p].frames[alt] = getAlternateName(pass[p].frames[alt]);
100                        if (!ResourceGroupManager::getSingleton().resourceExists(
101                            resourceGroup, pass[p].frames[alt]))
102                        {
103                            // stuffed - no texture
104                            continue;
105                        }
106                    }
107
108                }
109
110                t = ogrePass->createTextureUnitState("");
111                t->setAnimatedTextureName(pass[p].frames, pass[p].animNumFrames, sequenceTime);
112
113            }
114            else
115            {
116                // Quake3 can still include alternate extension filenames e.g. jpg instead of tga
117                // Pain in the arse - have to check for failure
118                if (!ResourceGroupManager::getSingleton().resourceExists(
119                    resourceGroup, pass[p].textureName))
120                {
121                    // Try alternate extension
122                    pass[p].textureName = getAlternateName(pass[p].textureName);
123                    if (!ResourceGroupManager::getSingleton().resourceExists(
124                        resourceGroup, pass[p].textureName))
125                    {
126                        // stuffed - no texture
127                        continue;
128                    }
129                }
130                t = ogrePass->createTextureUnitState(pass[p].textureName);
131            }
132            // Blending
133            if (p == 0)
134            {
135                // scene blend
136                mat->setSceneBlending(pass[p].blendSrc, pass[p].blendDest);
137                if (mat->isTransparent() &&
138                    pass[p].blendSrc != SBF_SOURCE_ALPHA)
139                    mat->setDepthWriteEnabled(false);
140
141                t->setColourOperation(LBO_REPLACE);
142                                // Alpha mode
143                                ogrePass->setAlphaRejectSettings(
144                                        pass[p].alphaFunc, pass[p].alphaVal);
145            }
146            else
147            {
148                if (pass[p].customBlend)
149                {
150                    // Fallback for now
151                    t->setColourOperation(LBO_MODULATE);
152                }
153                else
154                {
155                    // simple layer blend
156                    t->setColourOperation(pass[p].blend);
157                }
158                                // Alpha mode, prefer 'most alphary'
159                                CompareFunction currFunc = ogrePass->getAlphaRejectFunction();
160                                unsigned char currVal = ogrePass->getAlphaRejectValue();
161                                if (pass[p].alphaFunc > currFunc ||
162                                        (pass[p].alphaFunc == currFunc && pass[p].alphaVal < currVal))
163                                {
164                                        ogrePass->setAlphaRejectSettings(
165                                                pass[p].alphaFunc, pass[p].alphaVal);
166                                }
167            }
168            // Tex coords
169            if (pass[p].texGen == TEXGEN_BASE)
170            {
171                t->setTextureCoordSet(0);
172            }
173            else if (pass[p].texGen == TEXGEN_LIGHTMAP)
174            {
175                t->setTextureCoordSet(1);
176            }
177            else if (pass[p].texGen == TEXGEN_ENVIRONMENT)
178            {
179                t->setEnvironmentMap(true, TextureUnitState::ENV_PLANAR);
180            }
181            // Tex mod
182            // Scale
183            t->setTextureUScale(pass[p].tcModScale[0]);
184            t->setTextureVScale(pass[p].tcModScale[1]);
185            // Procedural mods
186            // Custom - don't use mod if generating environment
187            // Because I do env a different way it look horrible
188            if (pass[p].texGen != TEXGEN_ENVIRONMENT)
189            {
190                if (pass[p].tcModRotate)
191                {
192                    t->setRotateAnimation(pass[p].tcModRotate);
193                }
194                if (pass[p].tcModScroll[0] || pass[p].tcModScroll[1])
195                {
196                    if (pass[p].tcModTurbOn)
197                    {
198                        // Turbulent scroll
199                        if (pass[p].tcModScroll[0])
200                        {
201                            t->setTransformAnimation(TextureUnitState::TT_TRANSLATE_U, WFT_SINE,
202                                pass[p].tcModTurb[0], pass[p].tcModTurb[3], pass[p].tcModTurb[2], pass[p].tcModTurb[1]);
203                        }
204                        if (pass[p].tcModScroll[1])
205                        {
206                            t->setTransformAnimation(TextureUnitState::TT_TRANSLATE_V, WFT_SINE,
207                                pass[p].tcModTurb[0], pass[p].tcModTurb[3], pass[p].tcModTurb[2], pass[p].tcModTurb[1]);
208                        }
209                    }
210                    else
211                    {
212                        // Constant scroll
213                        t->setScrollAnimation(pass[p].tcModScroll[0], pass[p].tcModScroll[1]);
214                    }
215                }
216                if (pass[p].tcModStretchWave != SHADER_FUNC_NONE)
217                {
218                    WaveformType wft;
219                    switch(pass[p].tcModStretchWave)
220                    {
221                    case SHADER_FUNC_SIN:
222                        wft = WFT_SINE;
223                        break;
224                    case SHADER_FUNC_TRIANGLE:
225                        wft = WFT_TRIANGLE;
226                        break;
227                    case SHADER_FUNC_SQUARE:
228                        wft = WFT_SQUARE;
229                        break;
230                    case SHADER_FUNC_SAWTOOTH:
231                        wft = WFT_SAWTOOTH;
232                        break;
233                    case SHADER_FUNC_INVERSESAWTOOTH:
234                        wft = WFT_INVERSE_SAWTOOTH;
235                        break;
236                    default:
237                        break;
238                    }
239                    // Create wave-based stretcher
240                    t->setTransformAnimation(TextureUnitState::TT_SCALE_U, wft, pass[p].tcModStretchParams[3],
241                        pass[p].tcModStretchParams[0], pass[p].tcModStretchParams[2], pass[p].tcModStretchParams[1]);
242                    t->setTransformAnimation(TextureUnitState::TT_SCALE_V, wft, pass[p].tcModStretchParams[3],
243                        pass[p].tcModStretchParams[0], pass[p].tcModStretchParams[2], pass[p].tcModStretchParams[1]);
244                }
245            }
246            // Address mode
247            t->setTextureAddressingMode(pass[p].addressMode);
248
249            //assert(!t->isBlank());
250
251
252        }
253        // Do farbox (create new material)
254
255        // Set culling mode and lighting to defaults
256        mat->setCullingMode(CULL_NONE);
257        mat->setManualCullingMode(cullMode);
258        mat->setLightingEnabled(false);
259        mat->load();
260        return mat;
261    }
262    String Quake3Shader::getAlternateName(const String& texName)
263    {
264        // Get alternative JPG to TGA and vice versa
265        size_t pos;
266        String ext, base;
267
268        pos = texName.find_last_of(".");
269        ext = texName.substr(pos, 4);
270                StringUtil::toLowerCase(ext);
271        base = texName.substr(0,pos);
272        if (ext == ".jpg")
273        {
274            return base + ".tga";
275        }
276        else
277        {
278            return base + ".jpg";
279        }
280
281    }
282}
Note: See TracBrowser for help on using the repository browser.