WoW Model Viewer
Your premiere tool for viewing, equipping and animating World of Warcraft models.
Loading...
Searching...
No Matches
ModelRenderPass.cpp
Go to the documentation of this file.
1#include "ModelRenderPass.h"
2#include "ModelColor.h"
3#include "ModelTransparency.h"
4#include "TextureAnim.h"
5#include "video.h"
6#include "wow_enums.h"
7#include "WoWModel.h"
8
9#include "Logger.h"
10
11#include <glad/gl.h>
12#include "glm/gtc/type_ptr.hpp"
13
15 useTex2(false), useEnvMap(false), cull(false), trans(false),
16 unlit(false), noZWrite(false), billboard(false),
17 texanim(-1), color(-1), opacity(-1), blendmode(-1), tex(INVALID_TEX),
18 swrap(false), twrap(false), ocol(0.0f, 0.0f, 0.0f, 0.0f), ecol(0.0f, 0.0f, 0.0f, 0.0f),
19 model(m), geoIndex(geo), specialTex(-1)
20{
21}
22
24{
25 glDisable(GL_BLEND);
26 glDisable(GL_ALPHA_TEST);
27 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
28
29 if (noZWrite)
30 glDepthMask(GL_TRUE);
31
32 if (texanim != -1)
33 {
34 glPopMatrix();
35 glMatrixMode(GL_MODELVIEW);
36 }
37
38 if (unlit)
39 glEnable(GL_LIGHTING);
40
41 //if (billboard)
42 // glPopMatrix();
43
44 if (cull)
45 glDisable(GL_CULL_FACE);
46
47 if (useEnvMap)
48 {
49 glDisable(GL_TEXTURE_GEN_S);
50 glDisable(GL_TEXTURE_GEN_T);
51 }
52
53 if (swrap)
54 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
55
56 if (twrap)
57 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
58
59 /*
60 if (useTex2)
61 {
62 glDisable(GL_TEXTURE_2D);
63 glActiveTextureARB(GL_TEXTURE0);
64 }
65 */
66
67 if (opacity != -1 || color != -1)
68 {
69 const GLfloat czero[4] = {0.0f, 0.0f, 0.0f, 1.0f};
70 glMaterialfv(GL_FRONT, GL_EMISSION, czero);
71
72 //glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
73 //glMaterialfv(GL_FRONT, GL_AMBIENT, ocol);
74 //ocol = glm::vec4(1.0f, 1.0f, 1.0f, 1.0f);
75 //glMaterialfv(GL_FRONT, GL_DIFFUSE, ocol);
76 }
77}
78
80{
81 // May as well check that we're going to render the geoset before doing all this crap.
82 if (!model || geoIndex == -1 || !model->geosets[geoIndex]->display)
83 return false;
84
85 // COLOUR
86 // Get the colour and transparency and check that we should even render
87 ocol = glm::vec4(1.0f, 1.0f, 1.0f, model->trans);
88 ecol = glm::vec4(0.0f, 0.0f, 0.0f, 0.0f);
89
90 // emissive colors
91 if (color != -1 && color < static_cast<int16>(model->colors.size()) && model->colors[color].color.uses(0))
92 {
93 /* Alfred 2008.10.02 buggy opacity make model invisible, TODO */
94 const glm::vec3 c = model->colors[color].color.getValue(0, model->animtime);
95 if (model->colors[color].opacity.uses(model->anim))
96 ocol.w = model->colors[color].opacity.getValue(model->anim, model->animtime);
97
98 if (unlit)
99 {
100 ocol.x = c.x;
101 ocol.y = c.y;
102 ocol.z = c.z;
103 }
104 else
105 ocol.x = ocol.y = ocol.z = 0;
106
107 ecol = glm::vec4(c, ocol.w);
108 glMaterialfv(GL_FRONT, GL_EMISSION, glm::value_ptr(ecol));
109 }
110
111 // opacity
112 if (opacity != -1 &&
113 opacity < static_cast<int16>(model->transparency.size()) &&
114 model->transparency[opacity].trans.uses(0))
115 {
116 // Alfred 2008.10.02 buggy opacity make model invisible, TODO
117 ocol.w *= model->transparency[opacity].trans.getValue(0, model->animtime);
118 }
119
120 // exit and return false before affecting the opengl render state
121 if (!((ocol.w > 0) && (color == -1 || ecol.w > 0)))
122 return false;
123
124 // TEXTURE
125 // bind to our texture
126 const GLuint texId = model->getGLTexture(tex);
127 if (texId != INVALID_TEX)
128 glBindTexture(GL_TEXTURE_2D, texId);
129
130 // ALPHA BLENDING
131 // blend mode
132
133 switch (blendmode)
134 {
135 case BM_OPAQUE: // 0
136 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
137 break;
138 case BM_TRANSPARENT: // 1
139 glEnable(GL_ALPHA_TEST);
140 glBlendFunc(GL_ONE, GL_ZERO);
141 break;
142 case BM_ALPHA_BLEND: // 2
143 glEnable(GL_BLEND);
144 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
145 break;
146 case BM_ADDITIVE: // 3
147 glEnable(GL_BLEND);
148 glBlendFunc(GL_SRC_COLOR, GL_ONE);
149 break;
150 case BM_ADDITIVE_ALPHA: // 4
151 glEnable(GL_BLEND);
152 glBlendFunc(GL_SRC_ALPHA, GL_ONE);
153 break;
154 case BM_MODULATE: // 5
155 glEnable(GL_BLEND);
156 glBlendFunc(GL_DST_COLOR, GL_ZERO);
157 break;
158 case BM_MODULATEX2: // 6
159 glEnable(GL_BLEND);
160 glBlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
161 break;
162 case BM_7: // 7, new in WoD
163 glEnable(GL_BLEND);
164 glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
165 break;
166 default:
167 LOG_ERROR << "Unknown blendmode:" << blendmode;
168 glEnable(GL_BLEND);
169 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
170 }
171
172 if (cull)
173 glEnable(GL_CULL_FACE);
174 else
175 glDisable(GL_CULL_FACE);
176 // no writing to the depth buffer.
177 if (noZWrite)
178 glDepthMask(GL_FALSE);
179 else
180 glDepthMask(GL_TRUE);
181
182 // Texture wrapping around the geometry
183 if (swrap)
184 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
185 if (twrap)
186 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
187
188 // Environmental mapping, material, and effects
189 if (useEnvMap)
190 {
191 // Turn on the 'reflection' shine, using 18.0f as that is what WoW uses based on the reverse engineering
192 // This is now set in InitGL(); - no need to call it every render.
193 glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 18.0f);
194
195 // env mapping
196 glEnable(GL_TEXTURE_GEN_S);
197 glEnable(GL_TEXTURE_GEN_T);
198
199 const GLint maptype = GL_SPHERE_MAP;
200 //const GLint maptype = GL_REFLECTION_MAP_ARB;
201
202 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, maptype);
203 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, maptype);
204 }
205
206 if (texanim != -1 &&
207 texanim < static_cast<int16>(model->texAnims.size()))
208 {
209 glMatrixMode(GL_TEXTURE);
210 glPushMatrix();
211
212 model->texAnims[texanim].setup(texanim);
213 }
214
215 // color
216 glColor4fv(glm::value_ptr(ocol));
217 //glMaterialfv(GL_FRONT, GL_SPECULAR, ocol);
218
219 // don't use lighting on the surface
220 if (unlit)
221 glDisable(GL_LIGHTING);
222
223 if (blendmode <= 1 && ocol.w < 1.0f)
224 glEnable(GL_BLEND);
225
226 return true;
227}
228
229void ModelRenderPass::render(bool animated)
230{
231 const ModelGeosetHD* geoset = model->geosets[geoIndex];
232 // we don't want to render completely transparent parts
233 // render
234 if (animated)
235 {
236 //glDrawElements(GL_TRIANGLES, p.indexCount, GL_UNSIGNED_SHORT, indices + p.indexStart);
237 // a GDC OpenGL Performace Tuning paper recommended glDrawRangeElements over glDrawElements
238 // I can't notice a difference but I guess it can't hurt
240 {
241 glDrawRangeElements(GL_TRIANGLES, geoset->vstart, geoset->vstart + geoset->vcount, geoset->icount,
242 GL_UNSIGNED_SHORT, &model->indices[geoset->istart]);
243 }
244 else
245 {
246 glBegin(GL_TRIANGLES);
247 for (size_t k = 0, b = geoset->istart; k < geoset->icount; k++, b++)
248 {
249 const uint32 a = model->indices[b];
250 glNormal3fv(glm::value_ptr(model->normals[a]));
251 glTexCoord2fv(glm::value_ptr(model->origVertices[a].texcoords));
252 glVertex3fv(glm::value_ptr(model->vertices[a]));
253 /*
254 if (geoset->id == 2401 && k < 10)
255 {
256 LOG_INFO << "b" << b;
257 LOG_INFO << "a" << model->indices[b] << a;
258 LOG_INFO << "model->normals[a]" << model->normals[a].x << model->normals[a].y << model->normals[a].z;
259 LOG_INFO << "model->vertices[a]" << model->vertices[a].x << model->vertices[a].y << model->vertices[a].z;
260 }
261 */
262 }
263 glEnd();
264 }
265 }
266 else
267 {
268 glBegin(GL_TRIANGLES);
269 for (size_t k = 0, b = geoset->istart; k < geoset->icount; k++, b++)
270 {
271 const uint16 a = model->indices[b];
272 glNormal3fv(glm::value_ptr(model->normals[a]));
273 glTexCoord2fv(glm::value_ptr(model->origVertices[a].texcoords));
274 glVertex3fv(glm::value_ptr(model->vertices[a]));
275 }
276 glEnd();
277 }
278}
#define LOG_ERROR
Definition Logger.h:11
Extended geoset with 32-bit index start to support HD models with > 65535 indices.
static const uint16 INVALID_TEX
Sentinel value for an unset texture.
void deinit()
Clean up render state after drawing.
WoWModel * model
Owning model.
bool twrap
Texture wrapping modes (S and T).
uint16 tex
Texture index.
void render(bool animated)
Execute the render pass.
bool init()
Initialise render state from the model's material data.
glm::vec4 ecol
Output and emissive colours.
int geoIndex
Geoset index this pass draws.
ModelRenderPass(WoWModel *, int geo)
bool supportVBO
Definition video.h:99
bool supportDrawRangeElements
Definition video.h:95
Core WoW .m2 model: geometry, animation, textures, and character data.
Definition WoWModel.h:50
GLuint getGLTexture(uint16 tex) const
size_t anim
Definition WoWModel.h:185
glm::vec3 * vertices
Definition WoWModel.h:138
std::vector< TextureAnim > texAnims
Definition WoWModel.h:98
std::vector< ModelColor > colors
Definition WoWModel.h:99
std::vector< uint32 > indices
Definition WoWModel.h:139
float trans
Definition WoWModel.h:176
glm::vec3 * normals
Definition WoWModel.h:136
size_t animtime
Definition WoWModel.h:185
std::vector< ModelGeosetHD * > geosets
Definition WoWModel.h:149
std::vector< ModelTransparency > transparency
Definition WoWModel.h:100
std::vector< ModelVertex > origVertices
Definition WoWModel.h:132
int16_t int16
Definition types.h:33
uint16_t uint16
Definition types.h:32
uint32_t uint32
Definition types.h:34
VideoSettings video
Definition video.cpp:38
@ BM_ADDITIVE
Definition wow_enums.h:289
@ BM_ADDITIVE_ALPHA
Definition wow_enums.h:290
@ BM_ALPHA_BLEND
Definition wow_enums.h:288
@ BM_OPAQUE
Definition wow_enums.h:286
@ BM_7
Definition wow_enums.h:293
@ BM_TRANSPARENT
Definition wow_enums.h:287
@ BM_MODULATEX2
Definition wow_enums.h:292
@ BM_MODULATE
Definition wow_enums.h:291