1 /*
2   OpenMW - The completely unofficial reimplementation of Morrowind
3   Copyright (C) 2008-2010  Nicolay Korslund
4   Email: < korslund@gmail.com >
5   WWW: https://openmw.org/
6 
7   This file (property.h) is part of the OpenMW package.
8 
9   OpenMW is distributed as free software: you can redistribute it
10   and/or modify it under the terms of the GNU General Public License
11   version 3, as published by the Free Software Foundation.
12 
13   This program is distributed in the hope that it will be useful, but
14   WITHOUT ANY WARRANTY; without even the implied warranty of
15   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16   General Public License for more details.
17 
18   You should have received a copy of the GNU General Public License
19   version 3 along with this program. If not, see
20   https://www.gnu.org/licenses/ .
21 
22  */
23 
24 #ifndef OPENMW_COMPONENTS_NIF_PROPERTY_HPP
25 #define OPENMW_COMPONENTS_NIF_PROPERTY_HPP
26 
27 #include "base.hpp"
28 
29 namespace Nif
30 {
31 
32 struct Property : public Named { };
33 
34 struct NiTexturingProperty : public Property
35 {
36     unsigned short flags{0u};
37 
38     // A sub-texture
39     struct Texture
40     {
41         /* Clamp mode
42         0 - clampS clampT
43         1 - clampS wrapT
44         2 - wrapS clampT
45         3 - wrapS wrapT
46         */
47 
48         bool inUse;
49         NiSourceTexturePtr texture;
50 
51         unsigned int clamp, uvSet;
52 
53         void read(NIFStream *nif);
54         void post(NIFFile *nif);
55     };
56 
57     /* Apply mode:
58         0 - replace
59         1 - decal
60         2 - modulate
61         3 - hilight  // These two are for PS2 only?
62         4 - hilight2
63     */
64     unsigned int apply{0};
65 
66     /*
67      * The textures in this list are as follows:
68      *
69      * 0 - Base texture
70      * 1 - Dark texture
71      * 2 - Detail texture
72      * 3 - Gloss texture
73      * 4 - Glow texture
74      * 5 - Bump map texture
75      * 6 - Decal texture
76      */
77     enum TextureType
78     {
79         BaseTexture = 0,
80         DarkTexture = 1,
81         DetailTexture = 2,
82         GlossTexture = 3,
83         GlowTexture = 4,
84         BumpTexture = 5,
85         DecalTexture = 6,
86     };
87 
88     std::vector<Texture> textures;
89     std::vector<Texture> shaderTextures;
90 
91     osg::Vec2f envMapLumaBias;
92     osg::Vec4f bumpMapMatrix;
93 
94     void read(NIFStream *nif) override;
95     void post(NIFFile *nif) override;
96 };
97 
98 struct NiFogProperty : public Property
99 {
100     unsigned short mFlags;
101     float mFogDepth;
102     osg::Vec3f mColour;
103 
104     void read(NIFStream *nif) override;
105 };
106 
107 // These contain no other data than the 'flags' field
108 struct NiShadeProperty : public Property
109 {
110     unsigned short flags{0u};
readNif::NiShadeProperty111     void read(NIFStream *nif) override
112     {
113         Property::read(nif);
114         if (nif->getBethVersion() <= NIFFile::BethVersion::BETHVER_FO3)
115             flags = nif->getUShort();
116     }
117 };
118 
119 struct BSShaderProperty : public NiShadeProperty
120 {
121     enum BSShaderType
122     {
123         SHADER_TALL_GRASS = 0,
124         SHADER_DEFAULT = 1,
125         SHADER_SKY = 10,
126         SHADER_SKIN = 14,
127         SHADER_WATER = 17,
128         SHADER_LIGHTING30 = 29,
129         SHADER_TILE = 32,
130         SHADER_NOLIGHTING = 33
131     };
132 
133     unsigned int type{0u}, flags1{0u}, flags2{0u};
134     float envMapIntensity{0.f};
135     void read(NIFStream *nif) override;
136 };
137 
138 struct BSShaderLightingProperty : public BSShaderProperty
139 {
140     unsigned int clamp{0u};
141     void read(NIFStream *nif) override;
142 };
143 
144 struct BSShaderPPLightingProperty : public BSShaderLightingProperty
145 {
146     BSShaderTextureSetPtr textureSet;
147     struct RefractionSettings
148     {
149         float strength{0.f};
150         int period{0};
151     };
152     struct ParallaxSettings
153     {
154         float passes{0.f};
155         float scale{0.f};
156     };
157     RefractionSettings refraction;
158     ParallaxSettings parallax;
159 
160     void read(NIFStream *nif) override;
161     void post(NIFFile *nif) override;
162 };
163 
164 struct BSShaderNoLightingProperty : public BSShaderLightingProperty
165 {
166     std::string filename;
167     osg::Vec4f falloffParams;
168 
169     void read(NIFStream *nif) override;
170 };
171 
172 struct NiDitherProperty : public Property
173 {
174     unsigned short flags;
readNif::NiDitherProperty175     void read(NIFStream* nif) override
176     {
177         Property::read(nif);
178         flags = nif->getUShort();
179     }
180 };
181 
182 struct NiZBufferProperty : public Property
183 {
184     unsigned short flags;
185     unsigned int testFunction;
readNif::NiZBufferProperty186     void read(NIFStream *nif) override
187     {
188         Property::read(nif);
189         flags = nif->getUShort();
190         testFunction = (flags >> 2) & 0x7;
191         if (nif->getVersion() >= NIFStream::generateVersion(4,1,0,12) && nif->getVersion() <= NIFFile::NIFVersion::VER_OB)
192             testFunction = nif->getUInt();
193     }
194 };
195 
196 struct NiSpecularProperty : public Property
197 {
198     unsigned short flags;
readNif::NiSpecularProperty199     void read(NIFStream* nif) override
200     {
201         Property::read(nif);
202         flags = nif->getUShort();
203     }
204 };
205 
206 struct NiWireframeProperty : public Property
207 {
208     unsigned short flags;
readNif::NiWireframeProperty209     void read(NIFStream* nif) override
210     {
211         Property::read(nif);
212         flags = nif->getUShort();
213     }
214 };
215 
216 // The rest are all struct-based
217 template <typename T>
218 struct StructPropT : Property
219 {
220     T data;
221     unsigned short flags;
222 
readNif::StructPropT223     void read(NIFStream *nif) override
224     {
225         Property::read(nif);
226         flags = nif->getUShort();
227         data.read(nif);
228     }
229 };
230 
231 struct S_MaterialProperty
232 {
233     // The vector components are R,G,B
234     osg::Vec3f ambient{1.f,1.f,1.f}, diffuse{1.f,1.f,1.f};
235     osg::Vec3f specular, emissive;
236     float glossiness{0.f}, alpha{0.f}, emissiveMult{1.f};
237 
238     void read(NIFStream *nif);
239 };
240 
241 struct S_VertexColorProperty
242 {
243     /* Vertex mode:
244         0 - source ignore
245         1 - source emmisive
246         2 - source amb diff
247 
248         Lighting mode
249         0 - lighting emmisive
250         1 - lighting emmisive ambient/diffuse
251     */
252     int vertmode, lightmode;
253 
254     void read(NIFStream *nif);
255 };
256 
257 struct S_AlphaProperty
258 {
259     /*
260         In NiAlphaProperty, the flags have the following meaning:
261 
262         Bit 0 : alpha blending enable
263         Bits 1-4 : source blend mode
264         Bits 5-8 : destination blend mode
265         Bit 9 : alpha test enable
266         Bit 10-12 : alpha test mode
267         Bit 13 : no sorter flag ( disables triangle sorting )
268 
269         blend modes (glBlendFunc):
270         0000 GL_ONE
271         0001 GL_ZERO
272         0010 GL_SRC_COLOR
273         0011 GL_ONE_MINUS_SRC_COLOR
274         0100 GL_DST_COLOR
275         0101 GL_ONE_MINUS_DST_COLOR
276         0110 GL_SRC_ALPHA
277         0111 GL_ONE_MINUS_SRC_ALPHA
278         1000 GL_DST_ALPHA
279         1001 GL_ONE_MINUS_DST_ALPHA
280         1010 GL_SRC_ALPHA_SATURATE
281 
282         test modes (glAlphaFunc):
283         000 GL_ALWAYS
284         001 GL_LESS
285         010 GL_EQUAL
286         011 GL_LEQUAL
287         100 GL_GREATER
288         101 GL_NOTEQUAL
289         110 GL_GEQUAL
290         111 GL_NEVER
291 
292         Taken from:
293         http://niftools.sourceforge.net/doc/nif/NiAlphaProperty.html
294     */
295 
296     // Tested against when certain flags are set (see above.)
297     unsigned char threshold;
298 
299     void read(NIFStream *nif);
300 };
301 
302 /*
303     Docs taken from:
304     http://niftools.sourceforge.net/doc/nif/NiStencilProperty.html
305  */
306 struct S_StencilProperty
307 {
308     // Is stencil test enabled?
309     unsigned char enabled;
310 
311     /*
312         0   TEST_NEVER
313         1   TEST_LESS
314         2   TEST_EQUAL
315         3   TEST_LESS_EQUAL
316         4   TEST_GREATER
317         5   TEST_NOT_EQUAL
318         6   TEST_GREATER_EQUAL
319         7   TEST_NEVER (though nifskope comment says TEST_ALWAYS, but ingame it is TEST_NEVER)
320      */
321     int compareFunc;
322     unsigned stencilRef;
323     unsigned stencilMask;
324     /*
325         Stencil test fail action, depth test fail action and depth test pass action:
326         0   ACTION_KEEP
327         1   ACTION_ZERO
328         2   ACTION_REPLACE
329         3   ACTION_INCREMENT
330         4   ACTION_DECREMENT
331         5   ACTION_INVERT
332      */
333     int failAction;
334     int zFailAction;
335     int zPassAction;
336     /*
337         Face draw mode:
338         0   DRAW_CCW_OR_BOTH
339         1   DRAW_CCW        [default]
340         2   DRAW_CW
341         3   DRAW_BOTH
342      */
343     int drawMode;
344 
345     void read(NIFStream *nif);
346 };
347 
348 struct NiAlphaProperty : public StructPropT<S_AlphaProperty> { };
349 struct NiVertexColorProperty : public StructPropT<S_VertexColorProperty> { };
350 struct NiStencilProperty : public Property
351 {
352     S_StencilProperty data;
353     unsigned short flags{0u};
354 
readNif::NiStencilProperty355     void read(NIFStream *nif) override
356     {
357         Property::read(nif);
358         if (nif->getVersion() <= NIFFile::NIFVersion::VER_OB_OLD)
359             flags = nif->getUShort();
360         data.read(nif);
361     }
362 };
363 
364 struct NiMaterialProperty : public Property
365 {
366     S_MaterialProperty data;
367     unsigned short flags{0u};
368 
readNif::NiMaterialProperty369     void read(NIFStream *nif) override
370     {
371         Property::read(nif);
372         if (nif->getVersion() >= NIFStream::generateVersion(3,0,0,0)
373          && nif->getVersion() <= NIFFile::NIFVersion::VER_OB_OLD)
374             flags = nif->getUShort();
375         data.read(nif);
376     }
377 };
378 
379 } // Namespace
380 #endif
381