1 /** @file modeldef.h  3D model resource definition.
2  *
3  * @authors Copyright © 2003-2017 Jaakko Keränen <jaakko.keranen@iki.fi>
4  * @authors Copyright © 2006-2013 Daniel Swanson <danij@dengine.net>
5  *
6  * @par License
7  * GPL: http://www.gnu.org/licenses/gpl.html
8  *
9  * <small>This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by the
11  * Free Software Foundation; either version 2 of the License, or (at your
12  * option) any later version. This program is distributed in the hope that it
13  * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
14  * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
15  * Public License for more details. You should have received a copy of the GNU
16  * General Public License along with this program; if not, write to the Free
17  * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
18  * 02110-1301 USA</small>
19  */
20 
21 #ifndef DENG_RESOURCE_FRAMEMODELDEF_H
22 #define DENG_RESOURCE_FRAMEMODELDEF_H
23 
24 #include <vector>
25 #include <de/Vector>
26 #include <doomsday/defs/ded.h>
27 #include <doomsday/defs/model.h>
28 
29 #include "framemodel.h"
30 
31 /**
32  * @defgroup modelFrameFlags Model frame flags
33  * @ingroup flags
34  */
35 ///@{
36 #define MFF_FULLBRIGHT          0x00000001
37 #define MFF_SHADOW1             0x00000002
38 #define MFF_SHADOW2             0x00000004
39 #define MFF_BRIGHTSHADOW        0x00000008
40 #define MFF_MOVEMENT_PITCH      0x00000010 ///< Pitch aligned to movement.
41 #define MFF_SPIN                0x00000020 ///< Spin around (for bonus items).
42 #define MFF_SKINTRANS           0x00000040 ///< Color translation -> skins.
43 #define MFF_AUTOSCALE           0x00000080 ///< Scale to match sprite height.
44 #define MFF_MOVEMENT_YAW        0x00000100
45 #define MFF_DONT_INTERPOLATE    0x00000200 ///< Don't interpolate from the frame.
46 #define MFF_BRIGHTSHADOW2       0x00000400
47 #define MFF_ALIGN_YAW           0x00000800
48 #define MFF_ALIGN_PITCH         0x00001000
49 #define MFF_DARKSHADOW          0x00002000
50 #define MFF_IDSKIN              0x00004000 ///< Mobj id -> skin in skin range
51 #define MFF_DISABLE_Z_WRITE     0x00008000
52 #define MFF_NO_DISTANCE_CHECK   0x00010000
53 #define MFF_SELSKIN             0x00020000
54 #define MFF_PARTICLE_SUB1       0x00040000 ///< Sub1 center is particle origin.
55 #define MFF_NO_PARTICLES        0x00080000 ///< No particles for this object.
56 #define MFF_SHINY_SPECULAR      0x00100000 ///< Shiny skin rendered as additive.
57 #define MFF_SHINY_LIT           0x00200000 ///< Shiny skin is not fullbright.
58 #define MFF_IDFRAME             0x00400000 ///< Mobj id -> frame in frame range
59 #define MFF_IDANGLE             0x00800000 ///< Mobj id -> static angle offset
60 #define MFF_DIM                 0x01000000 ///< Never fullbright.
61 #define MFF_SUBTRACT            0x02000000 ///< Subtract blending.
62 #define MFF_REVERSE_SUBTRACT    0x04000000 ///< Reverse subtract blending.
63 #define MFF_TWO_SIDED           0x08000000 ///< Disable culling.
64 #define MFF_NO_TEXCOMP          0x10000000 ///< Never compress skins.
65 #define MFF_WORLD_TIME_ANIM     0x20000000
66 ///@}
67 
68 struct SubmodelDef
69 {
70     modelid_t modelId;
71     short frame;
72     char frameRange;
73     int _flags;
74     short skin;
75     char skinRange;
76     de::Vector3f offset;
77     byte alpha;
78     res::Texture *shinySkin;
79     blendmode_t blendMode;
80 
SubmodelDefSubmodelDef81     SubmodelDef()
82         : modelId(0)
83         , frame(0)
84         , frameRange(0)
85         , _flags(0)
86         , skin(0)
87         , skinRange(0)
88         , alpha(0)
89         , shinySkin(0)
90         , blendMode(BM_NORMAL)
91     {}
92 
setFlagsSubmodelDef93     void setFlags(int newFlags)
94     {
95         _flags = newFlags;
96     }
97 
98     /**
99      * Tests if the flags in @a flag are all set for the submodel.
100      *
101      * @param flag  One or more flags.
102      *
103      * @return @c true, if all the flags were set; otherwise @c false.
104      */
testFlagSubmodelDef105     bool testFlag(int flag) const
106     {
107         return (_flags & flag) == flag;
108     }
109 };
110 
111 #define MODELDEF_ID_MAXLEN      32
112 
113 struct FrameModelDef
114 {
115     char id[MODELDEF_ID_MAXLEN + 1];
116 
117     /// Pointer to the states list.
118     state_t *state      = nullptr;
119 
120     int flags           = 0;
121     uint group          = 0;
122     int select          = 0;
123     short skinTics      = 0;
124 
125     /// [0,1) When is this frame in effect?
126     float interMark     = 0;
127     float interRange[2];
128     de::Vector3f offset;
129     float resize        = 0;
130     de::Vector3f scale;
131 
132     typedef std::vector<de::Vector3f> PtcOffsets;
133     PtcOffsets _ptcOffset;
134 
135     float visualRadius  = 0;
136     float shadowRadius  = 0; // if zero, visual radius used instead
137 
138     defn::Model def;
139 
140     /// Points to next inter-frame, or NULL.
141     FrameModelDef *interNext = nullptr;
142 
143     /// Points to next selector, or NULL (only for "base" modeldefs).
144     FrameModelDef *selectNext = nullptr;
145 
146     /// Submodels.
147     typedef std::vector<SubmodelDef> Subs;
148     Subs _sub;
149 
150     FrameModelDef(char const *modelDefId = "")
151     {
152         de::zap(id);
153         de::zap(interRange);
154         strncpy(id, modelDefId, MODELDEF_ID_MAXLEN);
155     }
156 
addSubFrameModelDef157     SubmodelDef *addSub()
158     {
159         _sub.push_back(SubmodelDef());
160         _ptcOffset.push_back(de::Vector3f());
161         return &_sub.back();
162     }
163 
clearSubsFrameModelDef164     void clearSubs()
165     {
166         _sub.clear();
167         _ptcOffset.clear();
168     }
169 
subCountFrameModelDef170     uint subCount() const
171     {
172         return uint(_sub.size());
173     }
174 
testSubFlagFrameModelDef175     bool testSubFlag(unsigned int subnum, int flag) const
176     {
177         if(!hasSub(subnum)) return false;
178         return _sub[subnum].testFlag(flag);
179     }
180 
subModelIdFrameModelDef181     modelid_t subModelId(unsigned int subnum) const
182     {
183         if(!hasSub(subnum)) return NOMODELID;
184         return _sub[subnum].modelId;
185     }
186 
subModelDefFrameModelDef187     SubmodelDef &subModelDef(unsigned int subnum)
188     {
189         DENG2_ASSERT(hasSub(subnum));
190         return _sub[subnum];
191     }
192 
subModelDefFrameModelDef193     SubmodelDef const &subModelDef(unsigned int subnum) const
194     {
195         DENG2_ASSERT(hasSub(subnum));
196         return _sub[subnum];
197     }
198 
hasSubFrameModelDef199     bool hasSub(unsigned int subnum) const
200     {
201         return subnum < _sub.size();
202     }
203 
particleOffsetFrameModelDef204     de::Vector3f particleOffset(unsigned int subnum) const
205     {
206         if(hasSub(subnum))
207         {
208             DENG2_ASSERT(subnum < _ptcOffset.size());
209             return _ptcOffset[subnum];
210         }
211         return de::Vector3f();
212     }
213 
setParticleOffsetFrameModelDef214     void setParticleOffset(unsigned int subnum, de::Vector3f const &off)
215     {
216         DENG2_ASSERT(hasSub(subnum));
217         _ptcOffset[subnum] = off;
218     }
219 };
220 
221 #endif // DENG_RESOURCE_FRAMEMODELDEF_H
222