Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members   Related Pages  

OgreQuake3Shader.cpp

Go to the documentation of this file.
00001 /*
00002 -----------------------------------------------------------------------------
00003 This source file is part of OGRE
00004     (Object-oriented Graphics Rendering Engine)
00005 For the latest info, see http://www.ogre3d.org/
00006 
00007 Copyright © 2000-2002 The OGRE Team
00008 Also see acknowledgements in Readme.html
00009 
00010 This program is free software; you can redistribute it and/or modify it under
00011 the terms of the GNU Lesser General Public License as published by the Free Software
00012 Foundation; either version 2 of the License, or (at your option) any later
00013 version.
00014 
00015 This program is distributed in the hope that it will be useful, but WITHOUT
00016 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
00017 FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
00018 
00019 You should have received a copy of the GNU Lesser General Public License along with
00020 this program; if not, write to the Free Software Foundation, Inc., 59 Temple
00021 Place - Suite 330, Boston, MA 02111-1307, USA, or go to
00022 http://www.gnu.org/copyleft/lesser.txt.
00023 -----------------------------------------------------------------------------
00024 */
00025 
00026 #include "OgreQuake3Shader.h"
00027 #include "OgreSceneManager.h"
00028 #include "OgreMaterial.h"
00029 #include "OgreTechnique.h"
00030 #include "OgrePass.h"
00031 #include "OgreTextureUnitState.h"
00032 #include "OgreMath.h"
00033 #include "OgreLogManager.h"
00034 #include "OgreTextureManager.h"
00035 
00036 namespace Ogre {
00037 
00038 
00039     //-----------------------------------------------------------------------
00040     Quake3Shader::Quake3Shader(const String& name)
00041     {
00042         mName = name;
00043         numPasses = 0;
00044         deformFunc = DEFORM_FUNC_NONE;
00045         farbox = false;
00046         skyDome = false;
00047         flags = 0;
00048         fog = false;
00049         cullMode = MANUAL_CULL_BACK;
00050 
00051     }
00052     //-----------------------------------------------------------------------
00053     Quake3Shader::~Quake3Shader()
00054     {
00055     }
00056     //-----------------------------------------------------------------------
00057     void Quake3Shader::load(void)
00058     {
00059         // Do nothing
00060     }
00061     //-----------------------------------------------------------------------
00062     void Quake3Shader::unload(void)
00063     {
00064         // Do nothing
00065     }
00066     //-----------------------------------------------------------------------
00067     Material* Quake3Shader::createAsMaterial(SceneManager* sm, int lightmapNumber)
00068     {
00069         char matName[72];
00070         sprintf(matName, "%s#%d", mName.c_str(), lightmapNumber);
00071         Material* mat = sm->createMaterial(matName);
00072 
00073         char msg[256];
00074         sprintf(msg, "Using Q3 shader %s", mName.c_str());
00075         LogManager::getSingleton().logMessage(msg, LML_CRITICAL);
00076         for (int p = 0; p < numPasses; ++p)
00077         {
00078             TextureUnitState* t;
00079             // Create basic texture
00080             if (pass[p].textureName == "$lightmap")
00081             {
00082                 char lightmapName[16];
00083                 sprintf(lightmapName, "@lightmap%d", lightmapNumber);
00084                 t = mat->getTechnique(0)->getPass(0)->createTextureUnitState(lightmapName);
00085             }
00086             // Animated texture support
00087             else if (pass[p].animNumFrames > 0)
00088             {
00089                 Real sequenceTime = pass[p].animNumFrames / pass[p].animFps;
00090                 /* Pre-load textures
00091                    We need to know if each one was loaded OK since extensions may change for each
00092                    Quake3 can still include alternate extension filenames e.g. jpg instead of tga
00093                    Pain in the arse - have to check for each frame as letters<n>.tga for example
00094                    is different per frame!
00095                 */
00096                 for (unsigned int alt = 0; alt < pass[p].animNumFrames; ++alt)
00097                 {
00098                     try {
00099                         TextureManager::getSingleton().load(pass[p].frames[alt]);
00100                     }
00101                     catch (...)
00102                     {
00103                         // Try alternate extension
00104                         pass[p].frames[alt] = getAlternateName(pass[p].frames[alt]);
00105                         try {
00106                             TextureManager::getSingleton().load(pass[p].frames[alt]);
00107                         }
00108                         catch (...)
00109                         { // stuffed - no texture
00110                         }
00111                     }
00112 
00113                 }
00114 
00115                 t = mat->getTechnique(0)->getPass(0)->createTextureUnitState("");
00116                 t->setAnimatedTextureName(pass[p].frames, pass[p].animNumFrames, sequenceTime);
00117 
00118             }
00119             else
00120             {
00121                 // Quake3 can still include alternate extension filenames e.g. jpg instead of tga
00122                 // Pain in the arse - have to check for failure
00123                 try {
00124                     TextureManager::getSingleton().load(pass[p].textureName);
00125                 }
00126                 catch (...)
00127                 {
00128                     // Try alternate extension
00129                     pass[p].textureName = getAlternateName(pass[p].textureName);
00130                     try {
00131                         TextureManager::getSingleton().load(pass[p].textureName);
00132                     }
00133                     catch (...)
00134                     { // stuffed - no texture
00135                     }
00136                 }
00137                 t = mat->getTechnique(0)->getPass(0)->createTextureUnitState(pass[p].textureName);
00138             }
00139             // Blending
00140             if (p == 0)
00141             {
00142                 // scene blend
00143                 mat->setSceneBlending(pass[p].blendSrc, pass[p].blendDest);
00144                 if (mat->isTransparent() && 
00145                     pass[p].blendSrc != SBF_SOURCE_ALPHA)
00146                     mat->setDepthWriteEnabled(false);
00147 
00148                 t->setColourOperation(LBO_REPLACE);
00149             }
00150             else
00151             {
00152                 if (pass[p].customBlend)
00153                 {
00154                     // Fallback for now
00155                     t->setColourOperation(LBO_MODULATE);
00156                 }
00157                 else
00158                 {
00159                     // simple layer blend
00160                     t->setColourOperation(pass[p].blend);
00161                 }
00162             }
00163             // Tex coords
00164             if (pass[p].texGen == TEXGEN_BASE)
00165             {
00166                 t->setTextureCoordSet(0);
00167             }
00168             else if (pass[p].texGen == TEXGEN_LIGHTMAP)
00169             {
00170                 t->setTextureCoordSet(1);
00171             }
00172             else if (pass[p].texGen == TEXGEN_ENVIRONMENT)
00173             {
00174                 t->setEnvironmentMap(true, TextureUnitState::ENV_PLANAR);
00175             }
00176             // Tex mod
00177             // Scale
00178             t->setTextureUScale(pass[p].tcModScale[0]);
00179             t->setTextureVScale(pass[p].tcModScale[1]);
00180             // Procedural mods
00181             // Custom - don't use mod if generating environment
00182             // Because I do env a different way it look horrible
00183             if (pass[p].texGen != TEXGEN_ENVIRONMENT)
00184             {
00185                 if (pass[p].tcModRotate)
00186                 {
00187                     t->setRotateAnimation(pass[p].tcModRotate);
00188                 }
00189                 if (pass[p].tcModScroll[0] || pass[p].tcModScroll[1])
00190                 {
00191                     if (pass[p].tcModTurbOn)
00192                     {
00193                         // Turbulent scroll
00194                         if (pass[p].tcModScroll[0])
00195                         {
00196                             t->setTransformAnimation(TextureUnitState::TT_TRANSLATE_U, WFT_SINE,
00197                                 pass[p].tcModTurb[0], pass[p].tcModTurb[3], pass[p].tcModTurb[2], pass[p].tcModTurb[1]);
00198                         }
00199                         if (pass[p].tcModScroll[1])
00200                         {
00201                             t->setTransformAnimation(TextureUnitState::TT_TRANSLATE_V, WFT_SINE,
00202                                 pass[p].tcModTurb[0], pass[p].tcModTurb[3], pass[p].tcModTurb[2], pass[p].tcModTurb[1]);
00203                         }
00204                     }
00205                     else
00206                     {
00207                         // Constant scroll
00208                         t->setScrollAnimation(pass[p].tcModScroll[0], pass[p].tcModScroll[1]);
00209                     }
00210                 }
00211                 if (pass[p].tcModStretchWave != SHADER_FUNC_NONE)
00212                 {
00213                     WaveformType wft;
00214                     switch(pass[p].tcModStretchWave)
00215                     {
00216                     case SHADER_FUNC_SIN:
00217                         wft = WFT_SINE;
00218                         break;
00219                     case SHADER_FUNC_TRIANGLE:
00220                         wft = WFT_TRIANGLE;
00221                         break;
00222                     case SHADER_FUNC_SQUARE:
00223                         wft = WFT_SQUARE;
00224                         break;
00225                     case SHADER_FUNC_SAWTOOTH:
00226                         wft = WFT_SAWTOOTH;
00227                         break;
00228                     case SHADER_FUNC_INVERSESAWTOOTH:
00229                         wft = WFT_INVERSE_SAWTOOTH;
00230                         break;
00231                     default:
00232                         break;
00233                     }
00234                     // Create wave-based stretcher
00235                     t->setTransformAnimation(TextureUnitState::TT_SCALE_U, wft, pass[p].tcModStretchParams[3],
00236                         pass[p].tcModStretchParams[0], pass[p].tcModStretchParams[2], pass[p].tcModStretchParams[1]);
00237                     t->setTransformAnimation(TextureUnitState::TT_SCALE_V, wft, pass[p].tcModStretchParams[3],
00238                         pass[p].tcModStretchParams[0], pass[p].tcModStretchParams[2], pass[p].tcModStretchParams[1]);
00239                 }
00240             }
00241             // Address mode
00242             t->setTextureAddressingMode(pass[p].addressMode);
00243             // Alpha mode
00244             t->setAlphaRejectSettings(pass[p].alphaFunc, pass[p].alphaVal);
00245 
00246             //assert(!t->isBlank());
00247 
00248 
00249         }
00250         // Do farbox (create new material)
00251 
00252         // Do skydome (use this material)
00253         if (skyDome)
00254         {
00255             // Quake3 is always aligned with Z upwards
00256             Quaternion q;
00257             q.FromAngleAxis(Radian(Math::HALF_PI), Vector3::UNIT_X);
00258             // Also draw last, and make close to camera (far clip plane is shorter)
00259             sm->setSkyDome(true, matName, 20 - (cloudHeight / 256 * 18), 12, 2000, false, q);
00260         }
00261 
00262 
00263         // Set culling mode and lighting to defaults
00264         mat->setCullingMode(CULL_NONE);
00265         mat->setManualCullingMode(cullMode);
00266         mat->setLightingEnabled(false);
00267         mat->load();
00268         return mat;
00269     }
00270     String Quake3Shader::getAlternateName(const String& texName)
00271     {
00272         // Get alternative JPG to TGA and vice versa
00273         size_t pos;
00274         String ext, base;
00275 
00276         pos = texName.find_last_of(".");
00277         ext = texName.substr(pos, 4);
00278         StringUtil::toLowerCase(ext);
00279         base = texName.substr(0,pos);
00280         if (ext == ".jpg")
00281         {
00282             return base + ".tga";
00283         }
00284         else
00285         {
00286             return base + ".jpg";
00287         }
00288 
00289     }
00290 }

Copyright © 2002-2003 by The OGRE Team
Last modified Sun Nov 28 19:48:40 2004