OpenMW
components/nif/property.hpp
Go to the documentation of this file.
00001 /*
00002   OpenMW - The completely unofficial reimplementation of Morrowind
00003   Copyright (C) 2008-2010  Nicolay Korslund
00004   Email: < korslund@gmail.com >
00005   WWW: http://openmw.sourceforge.net/
00006 
00007   This file (property.h) is part of the OpenMW package.
00008 
00009   OpenMW is distributed as free software: you can redistribute it
00010   and/or modify it under the terms of the GNU General Public License
00011   version 3, as published by the Free Software Foundation.
00012 
00013   This program is distributed in the hope that it will be useful, but
00014   WITHOUT ANY WARRANTY; without even the implied warranty of
00015   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00016   General Public License for more details.
00017 
00018   You should have received a copy of the GNU General Public License
00019   version 3 along with this program. If not, see
00020   http://www.gnu.org/licenses/ .
00021 
00022  */
00023 
00024 #ifndef OPENMW_COMPONENTS_NIF_PROPERTY_HPP
00025 #define OPENMW_COMPONENTS_NIF_PROPERTY_HPP
00026 
00027 #include "controlled.hpp"
00028 
00029 namespace Nif
00030 {
00031 
00032 class Property : public Named
00033 {
00034 public:
00035     // The meaning of these depends on the actual property type.
00036     int flags;
00037 
00038     void read(NIFStream *nif)
00039     {
00040         Named::read(nif);
00041         flags = nif->getUShort();
00042     }
00043 };
00044 
00045 class NiTexturingProperty : public Property
00046 {
00047 public:
00048     // A sub-texture
00049     struct Texture
00050     {
00051         /* Clamp mode
00052         0 - clampS clampT
00053         1 - clampS wrapT
00054         2 - wrapS clampT
00055         3 - wrapS wrapT
00056         */
00057 
00058         /* Filter:
00059         0 - nearest
00060         1 - bilinear
00061         2 - trilinear
00062         3, 4, 5 - who knows
00063         */
00064         bool inUse;
00065         NiSourceTexturePtr texture;
00066 
00067         int clamp, uvSet, filter;
00068         short unknown2;
00069 
00070         void read(NIFStream *nif)
00071         {
00072             inUse = !!nif->getInt();
00073             if(!inUse) return;
00074 
00075             texture.read(nif);
00076             clamp = nif->getInt();
00077             filter = nif->getInt();
00078             uvSet = nif->getInt();
00079 
00080             // I have no idea, but I think these are actually two
00081             // PS2-specific shorts (ps2L and ps2K), followed by an unknown
00082             // short.
00083             nif->skip(6);
00084         }
00085 
00086         void post(NIFFile *nif)
00087         {
00088             texture.post(nif);
00089         }
00090     };
00091 
00092     /* Apply mode:
00093         0 - replace
00094         1 - decal
00095         2 - modulate
00096         3 - hilight  // These two are for PS2 only?
00097         4 - hilight2
00098     */
00099     int apply;
00100 
00101     /*
00102      * The textures in this list are as follows:
00103      *
00104      * 0 - Base texture
00105      * 1 - Dark texture
00106      * 2 - Detail texture
00107      * 3 - Gloss texture (never used?)
00108      * 4 - Glow texture
00109      * 5 - Bump map texture
00110      * 6 - Decal texture
00111      */
00112     enum TextureType
00113     {
00114         BaseTexture = 0,
00115         DarkTexture = 1,
00116         DetailTexture = 2,
00117         GlossTexture = 3,
00118         GlowTexture = 4,
00119         BumpTexture = 5,
00120         DecalTexture = 6
00121     };
00122 
00123     Texture textures[7];
00124 
00125     void read(NIFStream *nif)
00126     {
00127         Property::read(nif);
00128         apply = nif->getInt();
00129 
00130         // Unknown, always 7. Probably the number of textures to read
00131         // below
00132         nif->getInt();
00133 
00134         textures[0].read(nif); // Base
00135         textures[1].read(nif); // Dark
00136         textures[2].read(nif); // Detail
00137         textures[3].read(nif); // Gloss (never present)
00138         textures[4].read(nif); // Glow
00139         textures[5].read(nif); // Bump map
00140         if(textures[5].inUse)
00141         {
00142             // Ignore these at the moment
00143             /*float lumaScale =*/ nif->getFloat();
00144             /*float lumaOffset =*/ nif->getFloat();
00145             /*const Vector4 *lumaMatrix =*/ nif->getVector4();
00146         }
00147         textures[6].read(nif); // Decal
00148     }
00149 
00150     void post(NIFFile *nif)
00151     {
00152         Property::post(nif);
00153         for(int i = 0;i < 7;i++)
00154             textures[i].post(nif);
00155     }
00156 };
00157 
00158 // These contain no other data than the 'flags' field in Property
00159 class NiShadeProperty : public Property { };
00160 class NiDitherProperty : public Property { };
00161 class NiZBufferProperty : public Property { };
00162 class NiSpecularProperty : public Property { };
00163 class NiWireframeProperty : public Property { };
00164 
00165 // The rest are all struct-based
00166 template <typename T>
00167 struct StructPropT : Property
00168 {
00169     T data;
00170 
00171     void read(NIFStream *nif)
00172     {
00173         Property::read(nif);
00174         data.read(nif);
00175     }
00176 };
00177 
00178 struct S_MaterialProperty
00179 {
00180     // The vector components are R,G,B
00181     Ogre::Vector3 ambient, diffuse, specular, emissive;
00182     float glossiness, alpha;
00183 
00184     void read(NIFStream *nif)
00185     {
00186         ambient = nif->getVector3();
00187         diffuse = nif->getVector3();
00188         specular = nif->getVector3();
00189         emissive = nif->getVector3();
00190         glossiness = nif->getFloat();
00191         alpha = nif->getFloat();
00192     }
00193 };
00194 
00195 struct S_VertexColorProperty
00196 {
00197     /* Vertex mode:
00198         0 - source ignore
00199         1 - source emmisive
00200         2 - source amb diff
00201 
00202         Lighting mode
00203         0 - lighting emmisive
00204         1 - lighting emmisive ambient/diffuse
00205     */
00206     int vertmode, lightmode;
00207 
00208     void read(NIFStream *nif)
00209     {
00210         vertmode = nif->getInt();
00211         lightmode = nif->getInt();
00212     }
00213 };
00214 
00215 struct S_AlphaProperty
00216 {
00217     /*
00218         In NiAlphaProperty, the flags have the following meaning:
00219 
00220         Bit 0 : alpha blending enable
00221         Bits 1-4 : source blend mode
00222         Bits 5-8 : destination blend mode
00223         Bit 9 : alpha test enable
00224         Bit 10-12 : alpha test mode
00225         Bit 13 : no sorter flag ( disables triangle sorting )
00226 
00227         blend modes (glBlendFunc):
00228         0000 GL_ONE
00229         0001 GL_ZERO
00230         0010 GL_SRC_COLOR
00231         0011 GL_ONE_MINUS_SRC_COLOR
00232         0100 GL_DST_COLOR
00233         0101 GL_ONE_MINUS_DST_COLOR
00234         0110 GL_SRC_ALPHA
00235         0111 GL_ONE_MINUS_SRC_ALPHA
00236         1000 GL_DST_ALPHA
00237         1001 GL_ONE_MINUS_DST_ALPHA
00238         1010 GL_SRC_ALPHA_SATURATE
00239 
00240         test modes (glAlphaFunc):
00241         000 GL_ALWAYS
00242         001 GL_LESS
00243         010 GL_EQUAL
00244         011 GL_LEQUAL
00245         100 GL_GREATER
00246         101 GL_NOTEQUAL
00247         110 GL_GEQUAL
00248         111 GL_NEVER
00249 
00250         Taken from:
00251         http://niftools.sourceforge.net/doc/nif/NiAlphaProperty.html
00252 
00253         Right now we only use standard alpha blending (see the Ogre code
00254         that sets it up) and it appears that this is the only blending
00255         used in the original game. Bloodmoon (along with several mods) do
00256         however use other settings, such as discarding pixel values with
00257         alpha < 1.0. This is faster because we don't have to mess with the
00258         depth stuff like we did for blending. And OGRE has settings for
00259         this too.
00260     */
00261 
00262     // Tested against when certain flags are set (see above.)
00263     unsigned char threshold;
00264 
00265     void read(NIFStream *nif)
00266     {
00267         threshold = nif->getChar();
00268     }
00269 };
00270 
00271 /*
00272     Docs taken from:
00273     http://niftools.sourceforge.net/doc/nif/NiStencilProperty.html
00274  */
00275 struct S_StencilProperty
00276 {
00277     // Is stencil test enabled?
00278     unsigned char enabled;
00279 
00280     /*
00281         0   TEST_NEVER
00282         1   TEST_LESS
00283         2   TEST_EQUAL
00284         3   TEST_LESS_EQUAL
00285         4   TEST_GREATER
00286         5   TEST_NOT_EQUAL
00287         6   TEST_GREATER_EQUAL
00288         7   TEST_ALWAYS
00289      */
00290     int compareFunc;
00291     unsigned stencilRef;
00292     unsigned stencilMask;
00293     /*
00294         Stencil test fail action, depth test fail action and depth test pass action:
00295         0   ACTION_KEEP
00296         1   ACTION_ZERO
00297         2   ACTION_REPLACE
00298         3   ACTION_INCREMENT
00299         4   ACTION_DECREMENT
00300         5   ACTION_INVERT
00301      */
00302     int failAction;
00303     int zFailAction;
00304     int zPassAction;
00305     /*
00306         Face draw mode:
00307         0   DRAW_CCW_OR_BOTH
00308         1   DRAW_CCW        [default]
00309         2   DRAW_CW
00310         3   DRAW_BOTH
00311      */
00312     int drawMode;
00313 
00314     void read(NIFStream *nif)
00315     {
00316         enabled = nif->getChar();
00317         compareFunc = nif->getInt();
00318         stencilRef = nif->getUInt();
00319         stencilMask = nif->getUInt();
00320         failAction = nif->getInt();
00321         zFailAction = nif->getInt();
00322         zPassAction = nif->getInt();
00323         drawMode = nif->getInt();
00324     }
00325 };
00326 
00327 class NiAlphaProperty : public StructPropT<S_AlphaProperty> { };
00328 class NiMaterialProperty : public StructPropT<S_MaterialProperty> { };
00329 class NiVertexColorProperty : public StructPropT<S_VertexColorProperty> { };
00330 class NiStencilProperty : public StructPropT<S_StencilProperty> { };
00331 
00332 } // Namespace
00333 #endif