Merged master

This commit is contained in:
Sachith Hasaranga Seneviratne 2014-07-11 07:04:25 +05:30
commit f4b357d03c
49 changed files with 1823 additions and 1111 deletions

View File

@ -35,6 +35,14 @@
<spacer width="10" height="10" />
<buttonbar id="menu_bottomrow" x="0" y="0" width="38%" height="100%" align="center">
<icon-button id="test_gpwin" width="64" height="64" icon="gui/main_options.png" extend_label="50"
text="TEST: GPWin" label_location="hover"/>
<icon-button id="test_gplose" width="64" height="64" icon="gui/main_options.png" extend_label="50"
text="TEST: GPLose" label_location="hover"/>
<icon-button id="test_unlocked" width="64" height="64" icon="gui/main_options.png" extend_label="50"
text="TEST: Unlocked" label_location="hover"/>
<icon-button id="test_unlocked2" width="64" height="64" icon="gui/main_options.png" extend_label="50"
text="TEST: Unlocked 2" label_location="hover"/>
<icon-button id="options" width="64" height="64" icon="gui/main_options.png" extend_label="50"
I18N="Main menu button" text="Options" label_location="hover"/>
<icon-button id="help" width="64" height="64" icon="gui/main_help.png" extend_label="50"

View File

@ -21,8 +21,13 @@
uniform mat4 ModelViewProjectionMatrix;
uniform float time;
#if __VERSION__ >= 330
layout(location = 0) in vec3 Position;
layout(location = 3) in vec2 Texcoord;
#else
in vec3 Position;
in vec2 Texcoord;
#endif
out vec2 uv;
void main()

View File

@ -1,6 +1,7 @@
uniform sampler2D displacement_tex;
uniform sampler2D mask_tex;
uniform sampler2D color_tex;
uniform sampler2D tex;
uniform vec2 dir;
uniform vec2 dir2;
@ -64,5 +65,8 @@ void main()
float mask = texture(mask_tex, tc + shift).x;
tc += (mask < 1.) ? vec2(0.) : shift;
FragColor = texture(color_tex, tc);
vec4 col = texture(color_tex, tc);
vec4 blend_tex = texture(tex, uv);
col.rgb = blend_tex.rgb * blend_tex.a + (1. - blend_tex.a) * col.rgb;
FragColor = vec4(col.rgb, 1.);
}

View File

@ -78,8 +78,8 @@ void main()
col += texture(tex, uv + (vec2(0.0, 0.4) * offset) * blur * 0.4);
col = vec4(col.rgb / 41.0, col.a);
depth = clamp((FragPos.z/280), 0., 1.);
depth = (1 - depth);
depth = clamp(max(1.1666 - (FragPos.z/240.0), FragPos.z - 2000.0), 0., 1.);
vec3 final = colOriginal.rgb * depth + col.rgb * (1 - depth);
FragColor = vec4(final, colOriginal.a);

View File

@ -80,7 +80,7 @@ void main()
blur_factor *= boost_amount;
// Scale the blur direction
blur_dir *= boost_amount;
blur_dir *= blur_factor;
// Compute the blur
vec2 inc_vec = blur_dir / vec2(NB_SAMPLES);

View File

@ -1,39 +0,0 @@
uniform sampler2D Albedo;
uniform sampler2D DiffuseMap;
uniform sampler2D SpecularMap;
uniform sampler2D SSAO;
uniform vec3 ambient;
layout (std140) uniform MatrixesData
{
mat4 ViewMatrix;
mat4 ProjectionMatrix;
mat4 InverseViewMatrix;
mat4 InverseProjectionMatrix;
mat4 ShadowViewProjMatrixes[4];
vec2 screen;
};
#if __VERSION__ >= 130
in vec3 nor;
in vec2 uv;
out vec4 FragColor;
#else
varying vec3 nor;
varying vec2 uv;
#define FragColor gl_FragColor
#endif
void main() {
float rim = 1.0 - dot(nor, vec3(0., 0., -1));
rim = smoothstep(0.5, 1.5, rim) * 0.15;
vec4 color = texture(Albedo, uv);
vec2 tc = gl_FragCoord.xy / screen;
vec3 DiffuseComponent = texture(DiffuseMap, tc).xyz;
vec3 SpecularComponent = texture(SpecularMap, tc).xyz;
float ao = texture(SSAO, tc).x;
vec3 LightFactor = ao * ambient + DiffuseComponent + SpecularComponent * (1. - color.a);
FragColor = vec4(color.xyz * LightFactor + rim, 1.);
}

View File

@ -1,18 +1,15 @@
uniform sampler2D tex;
#if __VERSION__ >= 130
in vec2 uv;
in vec4 color;
out vec4 FragColor;
#else
varying vec2 uv;
#define FragColor gl_FragColor
#endif
void main()
{
vec4 Color = texture(tex, uv) * pow(color, vec4(2.2));
vec4 Color = texture(tex, uv);
Color.xyz *= pow(color.xyz, vec3(2.2));
Color.a *= color.a;
// Premultiply alpha
FragColor = vec4(Color.rgb * Color.a, Color.a);
}

View File

@ -18,31 +18,28 @@ layout (std140) uniform MatrixesData
vec2 screen;
};
#if __VERSION__ >= 130
in vec2 uv;
in vec4 color;
out vec4 FragColor;
#else
varying vec2 uv;
#define FragColor gl_FragColor
#endif
void main()
{
vec4 diffusecolor = texture(tex, uv) * pow(color, vec4(2.2));
vec3 tmp = vec3(gl_FragCoord.xy / screen, gl_FragCoord.z);
tmp = 2. * tmp - 1.;
vec4 diffusecolor = texture(tex, uv);
diffusecolor.xyz *= pow(color.xyz, vec3(2.2));
diffusecolor.a *= color.a;
vec3 tmp = vec3(gl_FragCoord.xy / screen, gl_FragCoord.z);
tmp = 2. * tmp - 1.;
vec4 xpos = vec4(tmp, 1.0);
xpos = InverseProjectionMatrix * xpos;
xpos.xyz /= xpos.w;
vec4 xpos = vec4(tmp, 1.0);
xpos = InverseProjectionMatrix * xpos;
xpos.xyz /= xpos.w;
float dist = length(xpos.xyz);
float fog = smoothstep(start, end, dist);
float dist = length(xpos.xyz);
float fog = smoothstep(start, end, dist);
fog = min(fog, fogmax);
fog = min(fog, fogmax);
vec4 color = vec4(vec4(col, 0.) * fog + diffusecolor *(1. - fog));
FragColor = vec4(color.rgb * color.a, color.a);
vec4 finalcolor = vec4(col, 0.) * fog + diffusecolor *(1. - fog);
FragColor = vec4(finalcolor.rgb * finalcolor.a, finalcolor.a);
}

View File

@ -114,7 +114,7 @@ Achievement * AchievementsStatus::getAchievement(uint32_t id)
// ----------------------------------------------------------------------------
/** Synchronises the achievements between local and online usage. It takes
* the list of online achievements, and marks them all to be achieved
* the list of online achievements, and marks them all to be achieved
* locally. Then it issues 'achieved' requests to the server for all local
* achievements that are not set online.
*/

View File

@ -47,7 +47,9 @@ PFNGLBINDATTRIBLOCATIONPROC glBindAttribLocation;
PFNGLBLENDEQUATIONPROC glBlendEquation;
PFNGLVERTEXATTRIBDIVISORPROC glVertexAttribDivisor;
PFNGLDRAWARRAYSINSTANCEDPROC glDrawArraysInstanced;
PFNGLDRAWELEMENTSBASEVERTEXPROC glDrawElementsBaseVertex;
PFNGLDRAWELEMENTSINSTANCEDPROC glDrawElementsInstanced;
PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXPROC glDrawElementsInstancedBaseVertex;
PFNGLDELETEBUFFERSPROC glDeleteBuffers;
PFNGLGENVERTEXARRAYSPROC glGenVertexArrays;
PFNGLBINDVERTEXARRAYPROC glBindVertexArray;
@ -201,7 +203,9 @@ void initGL()
glBlendEquation = (PFNGLBLENDEQUATIONPROC)IRR_OGL_LOAD_EXTENSION("glBlendEquation");
glVertexAttribDivisor = (PFNGLVERTEXATTRIBDIVISORPROC)IRR_OGL_LOAD_EXTENSION("glVertexAttribDivisor");
glDrawArraysInstanced = (PFNGLDRAWARRAYSINSTANCEDPROC)IRR_OGL_LOAD_EXTENSION("glDrawArraysInstanced");
glDrawElementsBaseVertex = (PFNGLDRAWELEMENTSBASEVERTEXPROC)IRR_OGL_LOAD_EXTENSION("glDrawElementsBaseVertex");
glDrawElementsInstanced = (PFNGLDRAWELEMENTSINSTANCEDPROC)IRR_OGL_LOAD_EXTENSION("glDrawElementsInstanced");
glDrawElementsInstancedBaseVertex = (PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXPROC)IRR_OGL_LOAD_EXTENSION("glDrawElementsInstancedBaseVertex");
glDeleteBuffers = (PFNGLDELETEBUFFERSPROC)IRR_OGL_LOAD_EXTENSION("glDeleteBuffers");
glGenVertexArrays = (PFNGLGENVERTEXARRAYSPROC)IRR_OGL_LOAD_EXTENSION("glGenVertexArrays");
glBindVertexArray = (PFNGLBINDVERTEXARRAYPROC)IRR_OGL_LOAD_EXTENSION("glBindVertexArray");
@ -504,6 +508,235 @@ void setTexture(unsigned TextureUnit, GLuint TextureId, GLenum MagFilter, GLenum
glGetError();
}
class VBOGatherer
{
enum VTXTYPE { VTXTYPE_STANDARD, VTXTYPE_TCOORD, VTXTYPE_TANGENT, VTXTYPE_COUNT };
GLuint vbo[VTXTYPE_COUNT], ibo[VTXTYPE_COUNT], vao[VTXTYPE_COUNT];
std::vector<scene::IMeshBuffer *> storedCPUBuffer[VTXTYPE_COUNT];
void *vtx_mirror[VTXTYPE_COUNT], *idx_mirror[VTXTYPE_COUNT];
size_t vtx_cnt[VTXTYPE_COUNT], idx_cnt[VTXTYPE_COUNT];
std::map<scene::IMeshBuffer*, unsigned> mappedBaseVertex[VTXTYPE_COUNT], mappedBaseIndex[VTXTYPE_COUNT];
void regenerateBuffer(enum VTXTYPE);
void regenerateVAO(enum VTXTYPE);
size_t getVertexPitch(enum VTXTYPE) const;
VTXTYPE getVTXTYPE(video::E_VERTEX_TYPE type);
void append(scene::IMeshBuffer *, VBOGatherer::VTXTYPE tp);
public:
VBOGatherer();
std::pair<unsigned, unsigned> getBase(scene::IMeshBuffer *);
unsigned getVBO(video::E_VERTEX_TYPE type) { return vbo[getVTXTYPE(type)]; }
unsigned getVAO(video::E_VERTEX_TYPE type) { return vao[getVTXTYPE(type)]; }
~VBOGatherer()
{
for (unsigned i = 0; i < VTXTYPE_COUNT; i++)
{
if (vbo[i])
glDeleteBuffers(1, &vbo[i]);
if (ibo[i])
glDeleteBuffers(1, &ibo[i]);
if (vao[i])
glDeleteVertexArrays(1, &vao[i]);
}
}
};
VBOGatherer::VBOGatherer()
{
vao[0] = vao[1] = vao[2] = 0;
vbo[0] = vbo[1] = vbo[2] = 0;
ibo[0] = ibo[1] = ibo[2] = 0;
vtx_cnt[0] = vtx_cnt[1] = vtx_cnt[2] = 0;
idx_cnt[0] = idx_cnt[1] = idx_cnt[2] = 0;
vtx_mirror[0] = vtx_mirror[1] = vtx_mirror[2] = NULL;
idx_mirror[0] = idx_mirror[1] = idx_mirror[2] = NULL;
}
void VBOGatherer::regenerateBuffer(enum VTXTYPE tp)
{
glBindVertexArray(0);
if (vbo[tp])
glDeleteBuffers(1, &vbo[tp]);
glGenBuffers(1, &vbo[tp]);
glBindBuffer(GL_ARRAY_BUFFER, vbo[tp]);
glBufferData(GL_ARRAY_BUFFER, vtx_cnt[tp] * getVertexPitch(tp), vtx_mirror[tp], GL_STATIC_DRAW);
if (ibo[tp])
glDeleteBuffers(1, &ibo[tp]);
glGenBuffers(1, &ibo[tp]);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo[tp]);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(u16)* idx_cnt[tp], idx_mirror[tp], GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
}
void VBOGatherer::regenerateVAO(enum VTXTYPE tp)
{
if (vao[tp])
glDeleteVertexArrays(1, &vao[tp]);
glGenVertexArrays(1, &vao[tp]);
glBindVertexArray(vao[tp]);
glBindBuffer(GL_ARRAY_BUFFER, vbo[tp]);
switch (tp)
{
case VTXTYPE_STANDARD:
// Position
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, getVertexPitch(tp), 0);
// Normal
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, getVertexPitch(tp), (GLvoid*)12);
// Color
glEnableVertexAttribArray(2);
glVertexAttribPointer(2, 4, GL_UNSIGNED_BYTE, GL_TRUE, getVertexPitch(tp), (GLvoid*)24);
// Texcoord
glEnableVertexAttribArray(3);
glVertexAttribPointer(3, 2, GL_FLOAT, GL_FALSE, getVertexPitch(tp), (GLvoid*)28);
break;
case VTXTYPE_TCOORD:
// Position
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, getVertexPitch(tp), 0);
// Normal
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, getVertexPitch(tp), (GLvoid*)12);
// Color
glEnableVertexAttribArray(2);
glVertexAttribPointer(2, 4, GL_UNSIGNED_BYTE, GL_TRUE, getVertexPitch(tp), (GLvoid*)24);
// Texcoord
glEnableVertexAttribArray(3);
glVertexAttribPointer(3, 2, GL_FLOAT, GL_FALSE, getVertexPitch(tp), (GLvoid*)28);
// SecondTexcoord
glEnableVertexAttribArray(4);
glVertexAttribPointer(4, 2, GL_FLOAT, GL_FALSE, getVertexPitch(tp), (GLvoid*)36);
break;
case VTXTYPE_TANGENT:
// Position
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, getVertexPitch(tp), 0);
// Normal
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, getVertexPitch(tp), (GLvoid*)12);
// Color
glEnableVertexAttribArray(2);
glVertexAttribPointer(2, 4, GL_UNSIGNED_BYTE, GL_TRUE, getVertexPitch(tp), (GLvoid*)24);
// Texcoord
glEnableVertexAttribArray(3);
glVertexAttribPointer(3, 2, GL_FLOAT, GL_FALSE, getVertexPitch(tp), (GLvoid*)28);
// Tangent
glEnableVertexAttribArray(5);
glVertexAttribPointer(5, 3, GL_FLOAT, GL_FALSE, getVertexPitch(tp), (GLvoid*)36);
// Bitangent
glEnableVertexAttribArray(6);
glVertexAttribPointer(6, 3, GL_FLOAT, GL_FALSE, getVertexPitch(tp), (GLvoid*)48);
break;
}
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo[tp]);
glBindVertexArray(0);
}
size_t VBOGatherer::getVertexPitch(enum VTXTYPE tp) const
{
switch (tp)
{
case VTXTYPE_STANDARD:
return getVertexPitchFromType(video::EVT_STANDARD);
case VTXTYPE_TCOORD:
return getVertexPitchFromType(video::EVT_2TCOORDS);
case VTXTYPE_TANGENT:
return getVertexPitchFromType(video::EVT_TANGENTS);
default:
assert(0 && "Wrong vtxtype");
return -1;
}
}
VBOGatherer::VTXTYPE VBOGatherer::getVTXTYPE(video::E_VERTEX_TYPE type)
{
switch (type)
{
case video::EVT_STANDARD:
return VTXTYPE_STANDARD;
case video::EVT_2TCOORDS:
return VTXTYPE_TCOORD;
case video::EVT_TANGENTS:
return VTXTYPE_TANGENT;
default:
assert(0 && "Wrong vtxtype");
}
};
void VBOGatherer::append(scene::IMeshBuffer *mb, VBOGatherer::VTXTYPE tp)
{
size_t old_vtx_cnt = vtx_cnt[tp];
vtx_cnt[tp] += mb->getVertexCount();
vtx_mirror[tp] = realloc(vtx_mirror[tp], vtx_cnt[tp] * getVertexPitch(tp));
intptr_t dstptr = (intptr_t)vtx_mirror[tp] + (old_vtx_cnt * getVertexPitch(tp));
memcpy((void *)dstptr, mb->getVertices(), mb->getVertexCount() * getVertexPitch(tp));
mappedBaseVertex[tp][mb] = old_vtx_cnt;
size_t old_idx_cnt = idx_cnt[tp];
idx_cnt[tp] += mb->getIndexCount();
idx_mirror[tp] = realloc(idx_mirror[tp], idx_cnt[tp] * sizeof(u16));
dstptr = (intptr_t)idx_mirror[tp] + (old_idx_cnt * sizeof(u16));
memcpy((void *)dstptr, mb->getIndices(), mb->getIndexCount() * sizeof(u16));
mappedBaseIndex[tp][mb] = old_idx_cnt * sizeof(u16);
}
std::pair<unsigned, unsigned> VBOGatherer::getBase(scene::IMeshBuffer *mb)
{
VTXTYPE tp = getVTXTYPE(mb->getVertexType());
if (mappedBaseVertex[tp].find(mb) == mappedBaseVertex[tp].end())
{
assert(mappedBaseIndex[tp].find(mb) == mappedBaseIndex[tp].end());
storedCPUBuffer[tp].push_back(mb);
append(mb, tp);
regenerateBuffer(tp);
regenerateVAO(tp);
}
std::map<scene::IMeshBuffer*, unsigned>::iterator It;
It = mappedBaseVertex[tp].find(mb);
assert(It != mappedBaseVertex[tp].end());
unsigned vtx = It->second;
It = mappedBaseIndex[tp].find(mb);
assert(It != mappedBaseIndex[tp].end());
return std::pair<unsigned, unsigned>(vtx, It->second);
}
static VBOGatherer *gatherersingleton = 0;
std::pair<unsigned, unsigned> getVAOOffsetAndBase(scene::IMeshBuffer *mb)
{
if (!gatherersingleton)
gatherersingleton = new VBOGatherer();
return gatherersingleton->getBase(mb);
}
unsigned getVBO(video::E_VERTEX_TYPE type)
{
if (gatherersingleton)
return gatherersingleton->getVBO(type);
return 0;
}
unsigned getVAO(video::E_VERTEX_TYPE type)
{
if (gatherersingleton)
return gatherersingleton->getVAO(type);
return 0;
}
void resetVAO()
{
if (gatherersingleton)
delete gatherersingleton;
gatherersingleton = 0;
}
ScopedGPUTimer::ScopedGPUTimer(GPUTimer &timer)
{
if (!UserConfigParams::m_profiler_enabled) return;

View File

@ -73,7 +73,9 @@ extern PFNGLBINDATTRIBLOCATIONPROC glBindAttribLocation;
extern PFNGLBLENDEQUATIONPROC glBlendEquation;
extern PFNGLVERTEXATTRIBDIVISORPROC glVertexAttribDivisor;
extern PFNGLDRAWARRAYSINSTANCEDPROC glDrawArraysInstanced;
extern PFNGLDRAWELEMENTSBASEVERTEXPROC glDrawElementsBaseVertex;
extern PFNGLDRAWELEMENTSINSTANCEDPROC glDrawElementsInstanced;
extern PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXPROC glDrawElementsInstancedBaseVertex;
extern PFNGLDELETEBUFFERSPROC glDeleteBuffers;
extern PFNGLGENVERTEXARRAYSPROC glGenVertexArrays;
extern PFNGLBINDVERTEXARRAYPROC glBindVertexArray;
@ -234,6 +236,11 @@ void compressTexture(irr::video::ITexture *tex, bool srgb, bool premul_alpha = f
bool loadCompressedTexture(const std::string& compressed_tex);
void saveCompressedTexture(const std::string& compressed_tex);
std::pair<unsigned, unsigned> getVAOOffsetAndBase(scene::IMeshBuffer *mb);
unsigned getVAO(video::E_VERTEX_TYPE type);
unsigned getVBO(video::E_VERTEX_TYPE type);
void resetVAO();
void draw3DLine(const core::vector3df& start,
const core::vector3df& end, irr::video::SColor color);

View File

@ -443,11 +443,11 @@ void IrrDriver::initDevice()
{
glGetIntegerv(GL_MAJOR_VERSION, &GLMajorVersion);
glGetIntegerv(GL_MINOR_VERSION, &GLMinorVersion);
Log::info("IrrDriver", "OpenGL version: %d.%d", GLMajorVersion, GLMinorVersion);
Log::info("IrrDriver", "OpenGL vendor: %s", glGetString(GL_VENDOR));
Log::info("IrrDriver", "OpenGL renderer: %s", glGetString(GL_RENDERER));
Log::info("IrrDriver", "OpenGL version string: %s", glGetString(GL_VERSION));
}
Log::info("IrrDriver", "OpenGL version: %d.%d", GLMajorVersion, GLMinorVersion);
Log::info("IrrDriver", "OpenGL vendor: %s", glGetString(GL_VENDOR));
Log::info("IrrDriver", "OpenGL renderer: %s", glGetString(GL_RENDERER));
Log::info("IrrDriver", "OpenGL version string: %s", glGetString(GL_VERSION));
m_glsl = (GLMajorVersion > 3 || (GLMajorVersion == 3 && GLMinorVersion >= 1));
// Parse extensions

View File

@ -17,9 +17,11 @@
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "graphics/mesh_tools.hpp"
#include <irrlicht.h>
#include <IMesh.h>
#include <IMeshBuffer.h>
#include "utils/log.hpp"
#include "graphics/irr_driver.hpp"
void MeshTools::minMax3D(scene::IMesh* mesh, Vec3 *min, Vec3 *max) {
@ -80,3 +82,359 @@ void MeshTools::minMax3D(scene::IMesh* mesh, Vec3 *min, Vec3 *max) {
} // for i<getMeshBufferCount
} // minMax3D
// Copied from irrlicht
void calculateTangents(
core::vector3df& normal,
core::vector3df& tangent,
core::vector3df& binormal,
const core::vector3df& vt1, const core::vector3df& vt2, const core::vector3df& vt3, // vertices
const core::vector2df& tc1, const core::vector2df& tc2, const core::vector2df& tc3) // texture coords
{
core::vector3df v1 = vt1 - vt2;
core::vector3df v2 = vt3 - vt1;
normal = v2.crossProduct(v1);
normal.normalize();
// binormal
f32 deltaX1 = tc1.X - tc2.X;
f32 deltaX2 = tc3.X - tc1.X;
binormal = (v1 * deltaX2) - (v2 * deltaX1);
binormal.normalize();
// tangent
f32 deltaY1 = tc1.Y - tc2.Y;
f32 deltaY2 = tc3.Y - tc1.Y;
tangent = (v1 * deltaY2) - (v2 * deltaY1);
tangent.normalize();
// adjust
core::vector3df txb = tangent.crossProduct(binormal);
if (txb.dotProduct(normal) < 0.0f)
{
tangent *= -1.0f;
binormal *= -1.0f;
}
}
// Copied from irrlicht
static inline core::vector3df getAngleWeight(const core::vector3df& v1,
const core::vector3df& v2,
const core::vector3df& v3)
{
// Calculate this triangle's weight for each of its three vertices
// start by calculating the lengths of its sides
const f32 a = v2.getDistanceFromSQ(v3);
const f32 asqrt = sqrtf(a);
const f32 b = v1.getDistanceFromSQ(v3);
const f32 bsqrt = sqrtf(b);
const f32 c = v1.getDistanceFromSQ(v2);
const f32 csqrt = sqrtf(c);
// use them to find the angle at each vertex
return core::vector3df(
acosf((b + c - a) / (2.f * bsqrt * csqrt)),
acosf((-b + c + a) / (2.f * asqrt * csqrt)),
acosf((b - c + a) / (2.f * bsqrt * asqrt)));
}
// Copied from irrlicht
template <typename T>
void recalculateTangentsT(scene::IMeshBuffer* buffer, bool recalculateNormals, bool smooth, bool angleWeighted)
{
if (!buffer || (buffer->getVertexType() != video::EVT_TANGENTS))
return;
const u32 vtxCnt = buffer->getVertexCount();
const u32 idxCnt = buffer->getIndexCount();
T* idx = reinterpret_cast<T*>(buffer->getIndices());
video::S3DVertexTangents* v =
(video::S3DVertexTangents*)buffer->getVertices();
if (smooth)
{
u32 i;
for (i = 0; i != vtxCnt; ++i)
{
if (recalculateNormals)
v[i].Normal.set(0.f, 0.f, 0.f);
v[i].Tangent.set(0.f, 0.f, 0.f);
v[i].Binormal.set(0.f, 0.f, 0.f);
}
//Each vertex gets the sum of the tangents and binormals from the faces around it
for (i = 0; i<idxCnt; i += 3)
{
// if this triangle is degenerate, skip it!
if (v[idx[i + 0]].Pos == v[idx[i + 1]].Pos ||
v[idx[i + 0]].Pos == v[idx[i + 2]].Pos ||
v[idx[i + 1]].Pos == v[idx[i + 2]].Pos
/*||
v[idx[i+0]].TCoords == v[idx[i+1]].TCoords ||
v[idx[i+0]].TCoords == v[idx[i+2]].TCoords ||
v[idx[i+1]].TCoords == v[idx[i+2]].TCoords */
)
continue;
//Angle-weighted normals look better, but are slightly more CPU intensive to calculate
core::vector3df weight(1.f, 1.f, 1.f);
if (angleWeighted)
weight = getAngleWeight(v[i + 0].Pos, v[i + 1].Pos, v[i + 2].Pos);
core::vector3df localNormal;
core::vector3df localTangent;
core::vector3df localBinormal;
calculateTangents(
localNormal,
localTangent,
localBinormal,
v[idx[i + 0]].Pos,
v[idx[i + 1]].Pos,
v[idx[i + 2]].Pos,
v[idx[i + 0]].TCoords,
v[idx[i + 1]].TCoords,
v[idx[i + 2]].TCoords);
if (recalculateNormals)
v[idx[i + 0]].Normal += localNormal * weight.X;
v[idx[i + 0]].Tangent += localTangent * weight.X;
v[idx[i + 0]].Binormal += localBinormal * weight.X;
calculateTangents(
localNormal,
localTangent,
localBinormal,
v[idx[i + 1]].Pos,
v[idx[i + 2]].Pos,
v[idx[i + 0]].Pos,
v[idx[i + 1]].TCoords,
v[idx[i + 2]].TCoords,
v[idx[i + 0]].TCoords);
if (recalculateNormals)
v[idx[i + 1]].Normal += localNormal * weight.Y;
v[idx[i + 1]].Tangent += localTangent * weight.Y;
v[idx[i + 1]].Binormal += localBinormal * weight.Y;
calculateTangents(
localNormal,
localTangent,
localBinormal,
v[idx[i + 2]].Pos,
v[idx[i + 0]].Pos,
v[idx[i + 1]].Pos,
v[idx[i + 2]].TCoords,
v[idx[i + 0]].TCoords,
v[idx[i + 1]].TCoords);
if (recalculateNormals)
v[idx[i + 2]].Normal += localNormal * weight.Z;
v[idx[i + 2]].Tangent += localTangent * weight.Z;
v[idx[i + 2]].Binormal += localBinormal * weight.Z;
}
// Normalize the tangents and binormals
if (recalculateNormals)
{
for (i = 0; i != vtxCnt; ++i)
v[i].Normal.normalize();
}
for (i = 0; i != vtxCnt; ++i)
{
v[i].Tangent.normalize();
v[i].Binormal.normalize();
}
}
else
{
core::vector3df localNormal;
for (u32 i = 0; i<idxCnt; i += 3)
{
calculateTangents(
localNormal,
v[idx[i + 0]].Tangent,
v[idx[i + 0]].Binormal,
v[idx[i + 0]].Pos,
v[idx[i + 1]].Pos,
v[idx[i + 2]].Pos,
v[idx[i + 0]].TCoords,
v[idx[i + 1]].TCoords,
v[idx[i + 2]].TCoords);
if (recalculateNormals)
v[idx[i + 0]].Normal = localNormal;
calculateTangents(
localNormal,
v[idx[i + 1]].Tangent,
v[idx[i + 1]].Binormal,
v[idx[i + 1]].Pos,
v[idx[i + 2]].Pos,
v[idx[i + 0]].Pos,
v[idx[i + 1]].TCoords,
v[idx[i + 2]].TCoords,
v[idx[i + 0]].TCoords);
if (recalculateNormals)
v[idx[i + 1]].Normal = localNormal;
calculateTangents(
localNormal,
v[idx[i + 2]].Tangent,
v[idx[i + 2]].Binormal,
v[idx[i + 2]].Pos,
v[idx[i + 0]].Pos,
v[idx[i + 1]].Pos,
v[idx[i + 2]].TCoords,
v[idx[i + 0]].TCoords,
v[idx[i + 1]].TCoords);
if (recalculateNormals)
v[idx[i + 2]].Normal = localNormal;
}
}
}
// Copied from irrlicht
void recalculateTangents(scene::IMeshBuffer* buffer, bool recalculateNormals, bool smooth, bool angleWeighted)
{
if (buffer && (buffer->getVertexType() == video::EVT_TANGENTS))
{
if (buffer->getIndexType() == video::EIT_16BIT)
recalculateTangentsT<u16>(buffer, recalculateNormals, smooth, angleWeighted);
else
recalculateTangentsT<u32>(buffer, recalculateNormals, smooth, angleWeighted);
}
}
// Copied from irrlicht
void recalculateTangents(scene::IMesh* mesh, bool recalculateNormals, bool smooth, bool angleWeighted)
{
if (!mesh)
return;
const u32 meshBufferCount = mesh->getMeshBufferCount();
for (u32 b = 0; b<meshBufferCount; ++b)
{
recalculateTangents(mesh->getMeshBuffer(b), recalculateNormals, smooth, angleWeighted);
}
}
bool MeshTools::isNormalMap(scene::IMeshBuffer* mb)
{
if (!irr_driver->isGLSL())
return false;
return (mb->getMaterial().MaterialType == irr_driver->getShader(ES_NORMAL_MAP));
}
// Copied from irrlicht
scene::IMesh* MeshTools::createMeshWithTangents(scene::IMesh* mesh, bool(*predicate)(scene::IMeshBuffer*),
bool recalculateNormals, bool smooth, bool angleWeighted, bool calculateTangents)
{
if (!mesh)
return 0;
// copy mesh and fill data into SMeshBufferTangents
scene::SMesh* clone = new scene::SMesh();
const u32 meshBufferCount = mesh->getMeshBufferCount();
bool needsNormalMap = false;
for (u32 b = 0; b < meshBufferCount; ++b)
{
scene::IMeshBuffer* original = mesh->getMeshBuffer(b);
if (predicate(original))
{
needsNormalMap = true;
break;
}
}
if (!needsNormalMap)
{
return mesh;
}
for (u32 b = 0; b<meshBufferCount; ++b)
{
scene::IMeshBuffer* original = mesh->getMeshBuffer(b);
const u32 idxCnt = original->getIndexCount();
const u16* idx = original->getIndices();
if (!predicate(original))
{
clone->addMeshBuffer(original);
continue;
}
scene::SMeshBufferTangents* buffer = new scene::SMeshBufferTangents();
buffer->Material = original->getMaterial();
buffer->Vertices.reallocate(idxCnt);
buffer->Indices.reallocate(idxCnt);
core::map<video::S3DVertexTangents, int> vertMap;
int vertLocation;
// copy vertices
const video::E_VERTEX_TYPE vType = original->getVertexType();
video::S3DVertexTangents vNew;
for (u32 i = 0; i<idxCnt; ++i)
{
switch (vType)
{
case video::EVT_STANDARD:
{
const video::S3DVertex* v =
(const video::S3DVertex*)original->getVertices();
vNew = video::S3DVertexTangents(
v[idx[i]].Pos, v[idx[i]].Normal, v[idx[i]].Color, v[idx[i]].TCoords);
}
break;
case video::EVT_2TCOORDS:
{
const video::S3DVertex2TCoords* v =
(const video::S3DVertex2TCoords*)original->getVertices();
vNew = video::S3DVertexTangents(
v[idx[i]].Pos, v[idx[i]].Normal, v[idx[i]].Color, v[idx[i]].TCoords);
}
break;
case video::EVT_TANGENTS:
{
const video::S3DVertexTangents* v =
(const video::S3DVertexTangents*)original->getVertices();
vNew = v[idx[i]];
}
break;
}
core::map<video::S3DVertexTangents, int>::Node* n = vertMap.find(vNew);
if (n)
{
vertLocation = n->getValue();
}
else
{
vertLocation = buffer->Vertices.size();
buffer->Vertices.push_back(vNew);
vertMap.insert(vNew, vertLocation);
}
// create new indices
buffer->Indices.push_back(vertLocation);
}
buffer->recalculateBoundingBox();
// add new buffer
clone->addMeshBuffer(buffer);
buffer->drop();
}
clone->recalculateBoundingBox();
if (calculateTangents)
recalculateTangents(clone, recalculateNormals, smooth, angleWeighted);
return clone;
}

View File

@ -21,7 +21,7 @@
namespace irr
{
namespace scene { class IMesh; }
namespace scene { class IMesh; class IMeshBuffer; }
}
using namespace irr;
@ -33,6 +33,12 @@ using namespace irr;
namespace MeshTools
{
void minMax3D(scene::IMesh* mesh, Vec3 *min, Vec3 *max);
bool isNormalMap(scene::IMeshBuffer* mb);
// Copied from irrlicht
scene::IMesh* createMeshWithTangents(scene::IMesh* mesh, bool(*predicate)(scene::IMeshBuffer*),
bool recalculateNormals = false, bool smooth = false, bool angleWeighted = false, bool calculateTangents = true);
} // MeshTools
#endif

View File

@ -612,7 +612,7 @@ void PostProcessing::renderMotionBlur(unsigned cam, FrameBuffer &in_fbo, FrameBu
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
setTexture(1, irr_driver->getDepthStencilTexture(), GL_NEAREST, GL_NEAREST);
FullScreenShader::MotionBlurShader
::setUniforms(.1, // Todo : should be framerate dependent
::setUniforms(cb->getBoostTime(0) * 10, // Todo : should be framerate dependent
// Todo : use a previousPVMatrix per cam, not global
irr_driver->getPreviousPVMatrix(),
cb->getCenter(cam),

View File

@ -185,12 +185,17 @@ void IrrDriver::renderGLSL(float dt)
// Render the post-processed scene
if (UserConfigParams::m_dynamic_lights)
{
FrameBuffer *fbo = m_post_processing->render(camnode, true);
bool isRace = StateManager::get()->getGameState() == GUIEngine::GAME;
FrameBuffer *fbo = m_post_processing->render(camnode, isRace);
if (irr_driver->getNormals())
irr_driver->getFBO(FBO_NORMAL_AND_DEPTHS).BlitToDefault(viewport.UpperLeftCorner.X, viewport.UpperLeftCorner.Y, viewport.LowerRightCorner.X, viewport.LowerRightCorner.Y);
else if (irr_driver->getSSAOViz())
irr_driver->getFBO(FBO_HALF1_R).BlitToDefault(viewport.UpperLeftCorner.X, viewport.UpperLeftCorner.Y, viewport.LowerRightCorner.X, viewport.LowerRightCorner.Y);
{
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glViewport(viewport.UpperLeftCorner.X, viewport.UpperLeftCorner.Y, viewport.LowerRightCorner.X, viewport.LowerRightCorner.Y);
m_post_processing->renderPassThrough(m_rtts->getFBO(FBO_HALF1_R).getRTT()[0]);
}
else if (irr_driver->getRSM())
{
glBindFramebuffer(GL_FRAMEBUFFER, 0);
@ -512,7 +517,8 @@ void IrrDriver::renderSolidFirstPass()
glDisable(GL_BLEND);
glEnable(GL_CULL_FACE);
irr_driver->setPhase(SOLID_NORMAL_AND_DEPTH_PASS);
GroupedFPSM<FPSM_DEFAULT>::reset();
GroupedFPSM<FPSM_DEFAULT_STANDARD>::reset();
GroupedFPSM<FPSM_DEFAULT_2TCOORD>::reset();
GroupedFPSM<FPSM_ALPHA_REF_TEXTURE>::reset();
GroupedFPSM<FPSM_NORMAL_MAP>::reset();
m_scene_manager->drawAll(scene::ESNRP_SOLID);
@ -523,38 +529,95 @@ void IrrDriver::renderSolidFirstPass()
{
ScopedGPUTimer Timer(getGPUTimer(Q_SOLID_PASS1));
glUseProgram(MeshShader::ObjectPass1Shader::Program);
for (unsigned i = 0; i < GroupedFPSM<FPSM_DEFAULT>::MeshSet.size(); ++i)
glBindVertexArray(getVAO(video::EVT_STANDARD));
for (unsigned i = 0; i < GroupedFPSM<FPSM_DEFAULT_STANDARD>::MeshSet.size(); ++i)
{
GLMesh &mesh = *GroupedFPSM<FPSM_DEFAULT>::MeshSet[i];
GLMesh &mesh = *GroupedFPSM<FPSM_DEFAULT_STANDARD>::MeshSet[i];
if (!mesh.textures[0])
mesh.textures[0] = getUnicolorTexture(video::SColor(255, 255, 255, 255));
compressTexture(mesh.textures[0], true);
setTexture(0, getTextureGLuint(mesh.textures[0]), GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, true);
draw<MeshShader::ObjectPass1Shader>(mesh, mesh.vao, GroupedFPSM<FPSM_DEFAULT>::MVPSet[i], GroupedFPSM<FPSM_DEFAULT>::TIMVSet[i], 0);
draw<MeshShader::ObjectPass1Shader>(mesh, GroupedFPSM<FPSM_DEFAULT_STANDARD>::MVPSet[i], GroupedFPSM<FPSM_DEFAULT_STANDARD>::TIMVSet[i], 0);
}
glBindVertexArray(getVAO(video::EVT_2TCOORDS));
for (unsigned i = 0; i < GroupedFPSM<FPSM_DEFAULT_2TCOORD>::MeshSet.size(); ++i)
{
GLMesh &mesh = *GroupedFPSM<FPSM_DEFAULT_2TCOORD>::MeshSet[i];
if (!mesh.textures[0])
mesh.textures[0] = getUnicolorTexture(video::SColor(255, 255, 255, 255));
compressTexture(mesh.textures[0], true);
setTexture(0, getTextureGLuint(mesh.textures[0]), GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, true);
draw<MeshShader::ObjectPass1Shader>(mesh, GroupedFPSM<FPSM_DEFAULT_2TCOORD>::MVPSet[i], GroupedFPSM<FPSM_DEFAULT_2TCOORD>::TIMVSet[i], 0);
}
glUseProgram(MeshShader::ObjectRefPass1Shader::Program);
glBindVertexArray(getVAO(EVT_STANDARD));
for (unsigned i = 0; i < GroupedFPSM<FPSM_ALPHA_REF_TEXTURE>::MeshSet.size(); ++i)
{
const GLMesh &mesh = *GroupedFPSM<FPSM_ALPHA_REF_TEXTURE>::MeshSet[i];
if (mesh.VAOType != video::EVT_STANDARD)
{
#ifdef DEBUG
Log::error("Materials", "Wrong vertex Type associed to alpha ref pass 1 (hint texture : %s)", mesh.textures[0]->getName().getPath().c_str());
#endif
continue;
}
compressTexture(mesh.textures[0], true);
setTexture(0, getTextureGLuint(mesh.textures[0]), GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, true);
draw<MeshShader::ObjectRefPass1Shader>(mesh, mesh.vao, GroupedFPSM<FPSM_ALPHA_REF_TEXTURE>::MVPSet[i], GroupedFPSM<FPSM_ALPHA_REF_TEXTURE>::TIMVSet[i], GroupedFPSM<FPSM_ALPHA_REF_TEXTURE>::MeshSet[i]->TextureMatrix, 0);
draw<MeshShader::ObjectRefPass1Shader>(mesh, GroupedFPSM<FPSM_ALPHA_REF_TEXTURE>::MVPSet[i], GroupedFPSM<FPSM_ALPHA_REF_TEXTURE>::TIMVSet[i], GroupedFPSM<FPSM_ALPHA_REF_TEXTURE>::MeshSet[i]->TextureMatrix, 0);
}
glUseProgram(MeshShader::NormalMapShader::Program);
glBindVertexArray(getVAO(EVT_TANGENTS));
for (unsigned i = 0; i < GroupedFPSM<FPSM_NORMAL_MAP>::MeshSet.size(); ++i)
{
const GLMesh &mesh = *GroupedFPSM<FPSM_NORMAL_MAP>::MeshSet[i];
assert(mesh.VAOType == video::EVT_TANGENTS);
assert(mesh.textures[1]);
compressTexture(mesh.textures[1], false);
setTexture(0, getTextureGLuint(mesh.textures[1]), GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, true);
compressTexture(mesh.textures[0], true);
setTexture(1, getTextureGLuint(mesh.textures[0]), GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, true);
draw<MeshShader::NormalMapShader>(mesh, mesh.vao, GroupedFPSM<FPSM_NORMAL_MAP>::MVPSet[i], GroupedFPSM<FPSM_NORMAL_MAP>::TIMVSet[i], 0, 1);
draw<MeshShader::NormalMapShader>(mesh, GroupedFPSM<FPSM_NORMAL_MAP>::MVPSet[i], GroupedFPSM<FPSM_NORMAL_MAP>::TIMVSet[i], 0, 1);
}
}
}
template<typename Shader, enum E_VERTEX_TYPE VertexType>
void renderMeshes2ndPass(std::vector<GLMesh *> &meshes, const std::vector<core::matrix4> &MVPMatrixes)
{
glUseProgram(Shader::Program);
glBindVertexArray(getVAO(VertexType));
for (unsigned i = 0; i < meshes.size(); i++)
{
GLMesh &mesh = *meshes[i];
if (!mesh.textures[0])
mesh.textures[0] = getUnicolorTexture(video::SColor(255, 255, 255, 255));
if (mesh.VAOType != VertexType)
{
#ifdef DEBUG
Log::error("Materials", "Wrong vertex Type associed to pass 2 (hint texture : %s)", mesh.textures[0]->getName().getPath().c_str());
#endif
continue;
}
compressTexture(mesh.textures[0], true);
setTexture(MeshShader::ObjectPass2Shader::TU_Albedo, getTextureGLuint(mesh.textures[0]), GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, true);
if (irr_driver->getLightViz())
{
GLint swizzleMask[] = { GL_ONE, GL_ONE, GL_ONE, GL_ALPHA };
glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask);
}
else
{
GLint swizzleMask[] = { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA };
glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask);
}
draw<Shader>(mesh, MVPMatrixes[i], mesh.TextureMatrix);
}
}
void IrrDriver::renderSolidSecondPass()
{
SColor clearColor(0, 150, 150, 150);
@ -577,9 +640,9 @@ void IrrDriver::renderSolidSecondPass()
glEnable(GL_DEPTH_TEST);
glDisable(GL_ALPHA_TEST);
glDisable(GL_BLEND);
GroupedSM<SM_DEFAULT>::reset();
GroupedSM<SM_DEFAULT_STANDARD>::reset();
GroupedSM<SM_DEFAULT_TANGENT>::reset();
GroupedSM<SM_ALPHA_REF_TEXTURE>::reset();
GroupedSM<SM_RIMLIT>::reset();
GroupedSM<SM_SPHEREMAP>::reset();
GroupedSM<SM_SPLATTING>::reset();
GroupedSM<SM_UNLIT>::reset();
@ -589,38 +652,90 @@ void IrrDriver::renderSolidSecondPass()
setTexture(2, m_rtts->getRenderTarget(RTT_HALF1_R), GL_LINEAR, GL_LINEAR);
{
ScopedGPUTimer Timer(getGPUTimer(Q_SOLID_PASS2));
m_scene_manager->drawAll(scene::ESNRP_SOLID);
glUseProgram(MeshShader::ObjectPass2Shader::Program);
for (unsigned i = 0; i < GroupedSM<SM_DEFAULT>::MeshSet.size(); i++)
drawObjectPass2(*GroupedSM<SM_DEFAULT>::MeshSet[i], GroupedSM<SM_DEFAULT>::MVPSet[i], GroupedSM<SM_DEFAULT>::MeshSet[i]->TextureMatrix);
glUseProgram(MeshShader::ObjectRefPass2Shader::Program);
for (unsigned i = 0; i < GroupedSM<SM_ALPHA_REF_TEXTURE>::MeshSet.size(); i++)
drawObjectRefPass2(*GroupedSM<SM_ALPHA_REF_TEXTURE>::MeshSet[i], GroupedSM<SM_ALPHA_REF_TEXTURE>::MVPSet[i], GroupedSM<SM_ALPHA_REF_TEXTURE>::MeshSet[i]->TextureMatrix);
glUseProgram(MeshShader::ObjectRimLimitShader::Program);
for (unsigned i = 0; i < GroupedSM<SM_RIMLIT>::MeshSet.size(); i++)
drawObjectRimLimit(*GroupedSM<SM_RIMLIT>::MeshSet[i], GroupedSM<SM_RIMLIT>::MVPSet[i], GroupedSM<SM_RIMLIT>::TIMVSet[i], GroupedSM<SM_RIMLIT>::MeshSet[i]->TextureMatrix);
renderMeshes2ndPass<MeshShader::ObjectPass2Shader, video::EVT_STANDARD>(GroupedSM<SM_DEFAULT_STANDARD>::MeshSet, GroupedSM<SM_DEFAULT_STANDARD>::MVPSet);
renderMeshes2ndPass<MeshShader::ObjectPass2Shader, video::EVT_TANGENTS>(GroupedSM<SM_DEFAULT_TANGENT>::MeshSet, GroupedSM<SM_DEFAULT_TANGENT>::MVPSet);
renderMeshes2ndPass<MeshShader::ObjectRefPass2Shader, video::EVT_STANDARD>(GroupedSM<SM_ALPHA_REF_TEXTURE>::MeshSet, GroupedSM<SM_ALPHA_REF_TEXTURE>::MVPSet);
glUseProgram(MeshShader::SphereMapShader::Program);
glBindVertexArray(getVAO(EVT_STANDARD));
for (unsigned i = 0; i < GroupedSM<SM_SPHEREMAP>::MeshSet.size(); i++)
drawSphereMap(*GroupedSM<SM_SPHEREMAP>::MeshSet[i], GroupedSM<SM_SPHEREMAP>::MVPSet[i], GroupedSM<SM_SPHEREMAP>::TIMVSet[i]);
{
const GLMesh &mesh = *GroupedSM<SM_SPHEREMAP>::MeshSet[i];
assert(mesh.VAOType == EVT_STANDARD);
compressTexture(mesh.textures[0], true);
if (irr_driver->getLightViz())
{
GLint swizzleMask[] = { GL_ONE, GL_ONE, GL_ONE, GL_ALPHA };
glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask);
}
else
{
GLint swizzleMask[] = { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA };
glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask);
}
setTexture(MeshShader::SphereMapShader::TU_tex, getTextureGLuint(mesh.textures[0]), GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, true);
draw<MeshShader::SphereMapShader>(mesh, GroupedSM<SM_SPHEREMAP>::MVPSet[i], GroupedSM<SM_SPHEREMAP>::TIMVSet[i], irr_driver->getSceneManager()->getAmbientLight());
}
glUseProgram(MeshShader::SplattingShader::Program);
glBindVertexArray(getVAO(EVT_2TCOORDS));
for (unsigned i = 0; i < GroupedSM<SM_SPLATTING>::MeshSet.size(); i++)
drawSplatting(*GroupedSM<SM_SPLATTING>::MeshSet[i], GroupedSM<SM_SPLATTING>::MVPSet[i]);
glUseProgram(MeshShader::ObjectUnlitShader::Program);
glBindVertexArray(getVAO(EVT_STANDARD));
for (unsigned i = 0; i < GroupedSM<SM_UNLIT>::MeshSet.size(); i++)
drawObjectUnlit(*GroupedSM<SM_UNLIT>::MeshSet[i], GroupedSM<SM_UNLIT>::MVPSet[i]);
{
const GLMesh &mesh = *GroupedSM<SM_UNLIT>::MeshSet[i];
assert(mesh.VAOType == EVT_STANDARD);
compressTexture(mesh.textures[0], true);
setTexture(MeshShader::ObjectUnlitShader::TU_tex, getTextureGLuint(mesh.textures[0]), GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, true);
if (irr_driver->getLightViz())
{
GLint swizzleMask[] = { GL_ONE, GL_ONE, GL_ONE, GL_ALPHA };
glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask);
}
else
{
GLint swizzleMask[] = { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA };
glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask);
}
draw<MeshShader::ObjectUnlitShader>(mesh, GroupedSM<SM_UNLIT>::MVPSet[i]);
}
glUseProgram(MeshShader::DetailledObjectPass2Shader::Program);
glBindVertexArray(getVAO(EVT_2TCOORDS));
for (unsigned i = 0; i < GroupedSM<SM_DETAILS>::MeshSet.size(); i++)
drawDetailledObjectPass2(*GroupedSM<SM_DETAILS>::MeshSet[i], GroupedSM<SM_DETAILS>::MVPSet[i]);
{
GLMesh &mesh = *GroupedSM<SM_DETAILS>::MeshSet[i];
assert(mesh.VAOType == EVT_2TCOORDS);
compressTexture(mesh.textures[0], true);
setTexture(MeshShader::DetailledObjectPass2Shader::TU_Albedo, getTextureGLuint(mesh.textures[0]), GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, true);
if (irr_driver->getLightViz())
{
GLint swizzleMask[] = { GL_ONE, GL_ONE, GL_ONE, GL_ALPHA };
glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask);
}
else
{
GLint swizzleMask[] = { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA };
glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask);
}
if (!mesh.textures[1])
{
#ifdef DEBUG
Log::error("Materials", "No detail/lightmap texture provided for detail/lightmap material.");
#endif
mesh.textures[1] = getUnicolorTexture(video::SColor(255, 255, 255, 255));
}
compressTexture(mesh.textures[1], true);
setTexture(MeshShader::DetailledObjectPass2Shader::TU_detail, getTextureGLuint(mesh.textures[1]), GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, true);
draw<MeshShader::DetailledObjectPass2Shader>(mesh, GroupedSM<SM_DETAILS>::MVPSet[i]);
}
}
}
@ -637,25 +752,112 @@ void IrrDriver::renderTransparent()
TransparentMeshes<TM_ADDITIVE>::reset();
m_scene_manager->drawAll(scene::ESNRP_TRANSPARENT);
glBindVertexArray(getVAO(EVT_STANDARD));
if (World::getWorld() && World::getWorld()->isFogEnabled())
{
const Track * const track = World::getWorld()->getTrack();
// This function is only called once per frame - thus no need for setters.
const float fogmax = track->getFogMax();
const float startH = track->getFogStartHeight();
const float endH = track->getFogEndHeight();
const float start = track->getFogStart();
const float end = track->getFogEnd();
const video::SColor tmpcol = track->getFogColor();
core::vector3df col(tmpcol.getRed() / 255.0f,
tmpcol.getGreen() / 255.0f,
tmpcol.getBlue() / 255.0f);
glUseProgram(MeshShader::TransparentFogShader::Program);
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
for (unsigned i = 0; i < TransparentMeshes<TM_DEFAULT>::MeshSet.size(); i++)
drawTransparentFogObject(*TransparentMeshes<TM_DEFAULT>::MeshSet[i], TransparentMeshes<TM_DEFAULT>::MVPSet[i], TransparentMeshes<TM_DEFAULT>::MeshSet[i]->TextureMatrix);
{
GLMesh &mesh = *TransparentMeshes<TM_DEFAULT>::MeshSet[i];
if (mesh.VAOType != EVT_STANDARD)
{
#ifdef DEBUG
Log::error("Materials", "Wrong vertex Type associed to fog + transparent blend (hint texture : %s)", mesh.textures[0]->getName().getPath().c_str());
#endif
glBindVertexArray(getVAO(mesh.VAOType));
}
if (!mesh.textures[0])
mesh.textures[0] = getUnicolorTexture(video::SColor(255, 255, 255, 255));
compressTexture(mesh.textures[0], true);
setTexture(0, getTextureGLuint(mesh.textures[0]), GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, true);
draw<MeshShader::TransparentFogShader>(mesh, TransparentMeshes<TM_DEFAULT>::MVPSet[i], TransparentMeshes<TM_DEFAULT>::MeshSet[i]->TextureMatrix, fogmax, startH, endH, start, end, col, Camera::getCamera(0)->getCameraSceneNode()->getAbsolutePosition(), 0);
if (mesh.VAOType != EVT_STANDARD)
glBindVertexArray(getVAO(EVT_STANDARD));
}
glBlendFunc(GL_ONE, GL_ONE);
for (unsigned i = 0; i < TransparentMeshes<TM_ADDITIVE>::MeshSet.size(); i++)
drawTransparentFogObject(*TransparentMeshes<TM_ADDITIVE>::MeshSet[i], TransparentMeshes<TM_ADDITIVE>::MVPSet[i], TransparentMeshes<TM_ADDITIVE>::MeshSet[i]->TextureMatrix);
{
GLMesh &mesh = *TransparentMeshes<TM_ADDITIVE>::MeshSet[i];
if (mesh.VAOType != EVT_STANDARD)
{
#ifdef DEBUG
Log::error("Materials", "Wrong vertex Type associed to fog + transparent additive (hint texture : %s)", mesh.textures[0]->getName().getPath().c_str());
#endif
glBindVertexArray(getVAO(mesh.VAOType));
}
glBindVertexArray(getVAO(mesh.VAOType));
if (!mesh.textures[0])
mesh.textures[0] = getUnicolorTexture(video::SColor(255, 255, 255, 255));
compressTexture(mesh.textures[0], true);
setTexture(0, getTextureGLuint(mesh.textures[0]), GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, true);
draw<MeshShader::TransparentFogShader>(mesh, TransparentMeshes<TM_ADDITIVE>::MVPSet[i], TransparentMeshes<TM_ADDITIVE>::MeshSet[i]->TextureMatrix, fogmax, startH, endH, start, end, col, Camera::getCamera(0)->getCameraSceneNode()->getAbsolutePosition(), 0);
if (mesh.VAOType != EVT_STANDARD)
glBindVertexArray(getVAO(EVT_STANDARD));
}
}
else
{
glUseProgram(MeshShader::TransparentShader::Program);
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
for (unsigned i = 0; i < TransparentMeshes<TM_DEFAULT>::MeshSet.size(); i++)
drawTransparentObject(*TransparentMeshes<TM_DEFAULT>::MeshSet[i], TransparentMeshes<TM_DEFAULT>::MVPSet[i], TransparentMeshes<TM_DEFAULT>::MeshSet[i]->TextureMatrix);
{
GLMesh &mesh = *TransparentMeshes<TM_DEFAULT>::MeshSet[i];
if (mesh.VAOType != EVT_STANDARD)
{
#ifdef DEBUG
Log::error("Materials", "Wrong vertex Type associed to fog + transparent additive (hint texture : %s)", mesh.textures[0]->getName().getPath().c_str());
#endif
glBindVertexArray(getVAO(mesh.VAOType));
}
glBindVertexArray(getVAO(mesh.VAOType));
if (!mesh.textures[0])
mesh.textures[0] = getUnicolorTexture(video::SColor(255, 255, 255, 255));
compressTexture(mesh.textures[0], true);
setTexture(0, getTextureGLuint(mesh.textures[0]), GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, true);
draw<MeshShader::TransparentShader>(mesh, TransparentMeshes<TM_DEFAULT>::MVPSet[i], TransparentMeshes<TM_DEFAULT>::MeshSet[i]->TextureMatrix, 0);
if (mesh.VAOType != EVT_STANDARD)
glBindVertexArray(getVAO(EVT_STANDARD));
}
glBlendFunc(GL_ONE, GL_ONE);
for (unsigned i = 0; i < TransparentMeshes<TM_ADDITIVE>::MeshSet.size(); i++)
drawTransparentObject(*TransparentMeshes<TM_ADDITIVE>::MeshSet[i], TransparentMeshes<TM_ADDITIVE>::MVPSet[i], TransparentMeshes<TM_ADDITIVE>::MeshSet[i]->TextureMatrix);
{
const GLMesh &mesh = *TransparentMeshes<TM_ADDITIVE>::MeshSet[i];
if (mesh.VAOType != EVT_STANDARD)
{
#ifdef DEBUG
Log::error("Materials", "Wrong vertex Type associed to fog + transparent additive (hint texture : %s)", mesh.textures[0]->getName().getPath().c_str());
#endif
glBindVertexArray(getVAO(mesh.VAOType));
}
glBindVertexArray(getVAO(mesh.VAOType));
compressTexture(mesh.textures[0], true);
setTexture(0, getTextureGLuint(mesh.textures[0]), GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, true);
draw<MeshShader::TransparentShader>(mesh, TransparentMeshes<TM_ADDITIVE>::MVPSet[i], TransparentMeshes<TM_ADDITIVE>::MeshSet[i]->TextureMatrix, 0);
if (mesh.VAOType != EVT_STANDARD)
glBindVertexArray(getVAO(EVT_STANDARD));
}
}
}
@ -668,6 +870,47 @@ void IrrDriver::renderParticles()
m_scene_manager->drawAll(scene::ESNRP_TRANSPARENT_EFFECT);
}
/** Given a matrix transform and a set of points returns an orthogonal projection matrix that maps coordinates of
transformed points between -1 and 1.
* \param transform a transform matrix.
* \param pointsInside a vector of point in 3d space.
*/
core::matrix4 getTighestFitOrthoProj(const core::matrix4 &transform, const std::vector<vector3df> &pointsInside)
{
float xmin = std::numeric_limits<float>::infinity();
float xmax = -std::numeric_limits<float>::infinity();
float ymin = std::numeric_limits<float>::infinity();
float ymax = -std::numeric_limits<float>::infinity();
float zmin = std::numeric_limits<float>::infinity();
float zmax = -std::numeric_limits<float>::infinity();
for (unsigned i = 0; i < pointsInside.size(); i++)
{
vector3df TransformedVector;
transform.transformVect(TransformedVector, pointsInside[i]);
xmin = MIN2(xmin, TransformedVector.X);
xmax = MAX2(xmax, TransformedVector.X);
ymin = MIN2(ymin, TransformedVector.Y);
ymax = MAX2(ymax, TransformedVector.Y);
zmin = MIN2(zmin, TransformedVector.Z);
zmax = MAX2(zmax, TransformedVector.Z);
}
float left = xmin;
float right = xmax;
float up = ymin;
float down = ymax;
core::matrix4 tmp_matrix;
// Prevent Matrix without extend
if (left == right || up == down)
return tmp_matrix;
tmp_matrix.buildProjectionMatrixOrthoLH(left, right,
down, up,
30, zmax);
return tmp_matrix;
}
void IrrDriver::computeCameraMatrix(scene::ICameraSceneNode * const camnode, size_t width, size_t height)
{
m_scene_manager->drawAll(scene::ESNRP_CAMERA);
@ -750,34 +993,17 @@ void IrrDriver::computeCameraMatrix(scene::ICameraSceneNode * const camnode, siz
core::aabbox3df box = smallcambox;
box = box.intersect(trackbox);
float xmin = std::numeric_limits<float>::infinity();
float xmax = -std::numeric_limits<float>::infinity();
float ymin = std::numeric_limits<float>::infinity();
float ymax = -std::numeric_limits<float>::infinity();
float zmin = std::numeric_limits<float>::infinity();
float zmax = -std::numeric_limits<float>::infinity();
const vector3df vectors[] =
{
frustrum->getFarLeftDown(),
frustrum->getFarLeftUp(),
frustrum->getFarRightDown(),
frustrum->getFarRightUp(),
frustrum->getNearLeftDown(),
frustrum->getNearLeftUp(),
frustrum->getNearRightDown(),
frustrum->getNearRightUp()
};
for (unsigned j = 0; j < 8; j++)
{
vector3df vector;
SunCamViewMatrix.transformVect(vector, vectors[j]);
xmin = MIN2(xmin, vector.X);
xmax = MAX2(xmax, vector.X);
ymin = MIN2(ymin, vector.Y);
ymax = MAX2(ymax, vector.Y);
zmin = MIN2(zmin, vector.Z);
zmax = MAX2(zmax, vector.Z);
}
std::vector<vector3df> vectors;
vectors.push_back(frustrum->getFarLeftDown());
vectors.push_back(frustrum->getFarLeftUp());
vectors.push_back(frustrum->getFarRightDown());
vectors.push_back(frustrum->getFarRightUp());
vectors.push_back(frustrum->getNearLeftDown());
vectors.push_back(frustrum->getNearLeftUp());
vectors.push_back(frustrum->getNearRightDown());
vectors.push_back(frustrum->getNearRightUp());
/* SunCamViewMatrix.transformBoxEx(trackbox);
SunCamViewMatrix.transformBoxEx(box);
@ -790,25 +1016,7 @@ void IrrDriver::computeCameraMatrix(scene::ICameraSceneNode * const camnode, siz
const float units_per_w = w / 1024;
const float units_per_h = h / 1024;*/
float left = xmin;
float right = xmax;
float up = ymin;
float down = ymax;
core::matrix4 tmp_matrix;
// Prevent Matrix without extend
if (left == right || up == down)
{
Log::error("Shadows", "Shadows Near/Far plane have a 0 area");
sun_ortho_matrix.push_back(tmp_matrix);
continue;
}
tmp_matrix.buildProjectionMatrixOrthoLH(left, right,
down, up,
30, zmax);
m_suncam->setProjectionMatrix(tmp_matrix, true);
m_suncam->setProjectionMatrix(getTighestFitOrthoProj(SunCamViewMatrix, vectors) , true);
m_suncam->render();
sun_ortho_matrix.push_back(getVideoDriver()->getTransform(video::ETS_PROJECTION) * getVideoDriver()->getTransform(video::ETS_VIEW));
@ -857,9 +1065,6 @@ void IrrDriver::computeCameraMatrix(scene::ICameraSceneNode * const camnode, siz
void IrrDriver::renderShadows()
{
GroupedFPSM<FPSM_DEFAULT>::reset();
GroupedFPSM<FPSM_ALPHA_REF_TEXTURE>::reset();
GroupedFPSM<FPSM_NORMAL_MAP>::reset();
irr_driver->setPhase(SHADOW_PASS);
glDisable(GL_BLEND);
glEnable(GL_POLYGON_OFFSET_FILL);
@ -873,12 +1078,18 @@ void IrrDriver::renderShadows()
m_scene_manager->drawAll(scene::ESNRP_SOLID);
glUseProgram(MeshShader::ShadowShader::Program);
for (unsigned i = 0; i < GroupedFPSM<FPSM_DEFAULT>::MeshSet.size(); ++i)
drawShadow(*GroupedFPSM<FPSM_DEFAULT>::MeshSet[i], GroupedFPSM<FPSM_DEFAULT>::MVPSet[i]);
glBindVertexArray(getVAO(EVT_STANDARD));
for (unsigned i = 0; i < GroupedFPSM<FPSM_DEFAULT_STANDARD>::MeshSet.size(); ++i)
drawShadow(*GroupedFPSM<FPSM_DEFAULT_STANDARD>::MeshSet[i], GroupedFPSM<FPSM_DEFAULT_STANDARD>::MVPSet[i]);
glBindVertexArray(getVAO(EVT_2TCOORDS));
for (unsigned i = 0; i < GroupedFPSM<FPSM_DEFAULT_2TCOORD>::MeshSet.size(); ++i)
drawShadow(*GroupedFPSM<FPSM_DEFAULT_2TCOORD>::MeshSet[i], GroupedFPSM<FPSM_DEFAULT_2TCOORD>::MVPSet[i]);
glBindVertexArray(getVAO(EVT_TANGENTS));
for (unsigned i = 0; i < GroupedFPSM<FPSM_NORMAL_MAP>::MeshSet.size(); ++i)
drawShadow(*GroupedFPSM<FPSM_NORMAL_MAP>::MeshSet[i], GroupedFPSM<FPSM_NORMAL_MAP>::MVPSet[i]);
glUseProgram(MeshShader::RefShadowShader::Program);
glBindVertexArray(getVAO(EVT_STANDARD));
for (unsigned i = 0; i < GroupedFPSM<FPSM_ALPHA_REF_TEXTURE>::MeshSet.size(); ++i)
drawShadowRef(*GroupedFPSM<FPSM_ALPHA_REF_TEXTURE>::MeshSet[i], GroupedFPSM<FPSM_ALPHA_REF_TEXTURE>::MVPSet[i]);
@ -891,14 +1102,25 @@ void IrrDriver::renderShadows()
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glUseProgram(MeshShader::RSMShader::Program);
for (unsigned i = 0; i < GroupedFPSM<FPSM_DEFAULT>::MeshSet.size(); ++i)
glBindVertexArray(getVAO(EVT_STANDARD));
for (unsigned i = 0; i < GroupedFPSM<FPSM_DEFAULT_STANDARD>::MeshSet.size(); ++i)
{
const GLMesh mesh = *GroupedFPSM<FPSM_DEFAULT>::MeshSet[i];
const GLMesh mesh = *GroupedFPSM<FPSM_DEFAULT_STANDARD>::MeshSet[i];
if (!mesh.textures[0])
continue;
compressTexture(mesh.textures[0], true);
setTexture(0, getTextureGLuint(mesh.textures[0]), GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, true);
draw<MeshShader::RSMShader>(mesh, mesh.vao, rsm_matrix, GroupedFPSM<FPSM_DEFAULT>::MVPSet[i], 0);
draw<MeshShader::RSMShader>(mesh, rsm_matrix, GroupedFPSM<FPSM_DEFAULT_STANDARD>::MVPSet[i], 0);
}
glBindVertexArray(getVAO(EVT_2TCOORDS));
for (unsigned i = 0; i < GroupedFPSM<FPSM_DEFAULT_2TCOORD>::MeshSet.size(); ++i)
{
const GLMesh mesh = *GroupedFPSM<FPSM_DEFAULT_2TCOORD>::MeshSet[i];
if (!mesh.textures[0])
continue;
compressTexture(mesh.textures[0], true);
setTexture(0, getTextureGLuint(mesh.textures[0]), GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, true);
draw<MeshShader::RSMShader>(mesh, rsm_matrix, GroupedFPSM<FPSM_DEFAULT_2TCOORD>::MVPSet[i], 0);
}
}
@ -954,6 +1176,7 @@ void IrrDriver::renderGlow(std::vector<GlowData>& glows)
glDepthMask(GL_FALSE);
glDisable(GL_BLEND);
glBindVertexArray(getVAO(EVT_STANDARD));
for (u32 i = 0; i < glowcount; i++)
{
const GlowData &dat = glows[i];
@ -1493,17 +1716,26 @@ static void testSH(unsigned char *color[6], size_t width, size_t height,
}
}
void IrrDriver::generateSkyboxCubemap()
/** Generate an opengl cubemap texture from 6 2d textures.
Out of legacy the sequence of textures maps to :
- 1st texture maps to GL_TEXTURE_CUBE_MAP_POSITIVE_Y
- 2nd texture maps to GL_TEXTURE_CUBE_MAP_NEGATIVE_Y
- 3rd texture maps to GL_TEXTURE_CUBE_MAP_POSITIVE_X
- 4th texture maps to GL_TEXTURE_CUBE_MAP_NEGATIVE_X
- 5th texture maps to GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
- 6th texture maps to GL_TEXTURE_CUBE_MAP_POSITIVE_Z
* \param textures sequence of 6 textures.
*/
GLuint generateCubeMapFromTextures(const std::vector<video::ITexture *> &textures)
{
glEnable(GL_TEXTURE_CUBE_MAP_SEAMLESS);
glGenTextures(1, &SkyboxCubeMap);
GLuint result;
glGenTextures(1, &result);
unsigned w = 0, h = 0;
for (unsigned i = 0; i < 6; i++)
{
w = MAX2(w, SkyboxTextures[i]->getOriginalSize().Width);
h = MAX2(h, SkyboxTextures[i]->getOriginalSize().Height);
w = MAX2(w, textures[i]->getOriginalSize().Width);
h = MAX2(h, textures[i]->getOriginalSize().Height);
}
const unsigned texture_permutation[] = { 2, 3, 0, 1, 5, 4 };
@ -1514,24 +1746,35 @@ void IrrDriver::generateSkyboxCubemap()
{
unsigned idx = texture_permutation[i];
video::IImage* image = getVideoDriver()->createImageFromData(
SkyboxTextures[idx]->getColorFormat(),
SkyboxTextures[idx]->getSize(),
SkyboxTextures[idx]->lock(),
video::IImage* image = irr_driver->getVideoDriver()->createImageFromData(
textures[idx]->getColorFormat(),
textures[idx]->getSize(),
textures[idx]->lock(),
false
);
SkyboxTextures[idx]->unlock();
textures[idx]->unlock();
image->copyToScaling(rgba[i], w, h);
image->drop();
glBindTexture(GL_TEXTURE_CUBE_MAP, SkyboxCubeMap);
glBindTexture(GL_TEXTURE_CUBE_MAP, result);
if (UserConfigParams::m_texture_compression)
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_COMPRESSED_SRGB_ALPHA, w, h, 0, GL_BGRA, GL_UNSIGNED_BYTE, (GLvoid*)rgba[i]);
else
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_SRGB_ALPHA, w, h, 0, GL_BGRA, GL_UNSIGNED_BYTE, (GLvoid*)rgba[i]);
}
for (unsigned i = 0; i < 6; i++)
delete[] rgba[i];
return result;
}
void IrrDriver::generateSkyboxCubemap()
{
glEnable(GL_TEXTURE_CUBE_MAP_SEAMLESS);
SkyboxCubeMap = generateCubeMapFromTextures(SkyboxTextures);
const unsigned texture_permutation[] = { 2, 3, 0, 1, 5, 4 };
if (SphericalHarmonicsTextures.size() == 6)
{
unsigned sh_w = 0, sh_h = 0;
@ -1593,9 +1836,6 @@ void IrrDriver::generateSkyboxCubemap()
delete[] sh_rgba[i];
}
for (unsigned i = 0; i < 6; i++)
delete[] rgba[i];
/*for (unsigned i = 0; i < 6; i++)
{
glBindTexture(GL_TEXTURE_CUBE_MAP, ConvolutedSkyboxCubeMap);
@ -1605,7 +1845,6 @@ void IrrDriver::generateSkyboxCubemap()
glBindTexture(GL_TEXTURE_CUBE_MAP, 0);*/
}
void IrrDriver::renderSkybox(const scene::ICameraSceneNode *camera)
{
if (!SkyboxCubeMap)
@ -1661,6 +1900,7 @@ void IrrDriver::renderDisplacement()
glStencilFunc(GL_ALWAYS, 1, 0xFF);
glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
glBindVertexArray(getVAO(EVT_2TCOORDS));
for (int i = 0; i < displacingcount; i++)
{
m_scene_manager->setCurrentRendertime(scene::ESNRP_TRANSPARENT);

View File

@ -336,7 +336,6 @@ void Shaders::loadShaders()
MeshShader::InstancedObjectRefPass2Shader::init();
MeshShader::InstancedGrassPass2Shader::init();
MeshShader::DetailledObjectPass2Shader::init();
MeshShader::ObjectRimLimitShader::init();
MeshShader::UntexturedObjectShader::init();
MeshShader::ObjectRefPass2Shader::init();
MeshShader::ObjectUnlitShader::init();
@ -856,54 +855,6 @@ namespace MeshShader
glUniformMatrix4fv(uniform_MM, 1, GL_FALSE, ModelMatrix.pointer());
}
GLuint ObjectRimLimitShader::Program;
GLuint ObjectRimLimitShader::uniform_MM;
GLuint ObjectRimLimitShader::uniform_IMM;
GLuint ObjectRimLimitShader::uniform_TM;
GLuint ObjectRimLimitShader::uniform_ambient;
GLuint ObjectRimLimitShader::TU_Albedo;
void ObjectRimLimitShader::init()
{
Program = LoadProgram(
GL_VERTEX_SHADER, file_manager->getAsset("shaders/object_pass.vert").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/objectpass_rimlit.frag").c_str());
uniform_MM = glGetUniformLocation(Program, "ModelMatrix");
uniform_IMM = glGetUniformLocation(Program, "InverseModelMatrix");
uniform_TM = glGetUniformLocation(Program, "TextureMatrix");
GLuint uniform_Albedo = glGetUniformLocation(Program, "Albedo");
GLuint uniform_DiffuseMap = glGetUniformLocation(Program, "DiffuseMap");
GLuint uniform_SpecularMap = glGetUniformLocation(Program, "SpecularMap");
GLuint uniform_SSAO = glGetUniformLocation(Program, "SSAO");
uniform_ambient = glGetUniformLocation(Program, "ambient");
if (!UserConfigParams::m_ubo_disabled)
{
GLuint uniform_ViewProjectionMatrixesUBO = glGetUniformBlockIndex(Program, "MatrixesData");
glUniformBlockBinding(Program, uniform_ViewProjectionMatrixesUBO, 0);
}
TU_Albedo = 3;
glUseProgram(Program);
glUniform1i(uniform_DiffuseMap, 0);
glUniform1i(uniform_SpecularMap, 1);
glUniform1i(uniform_SSAO, 2);
glUniform1i(uniform_Albedo, TU_Albedo);
glUseProgram(0);
}
void ObjectRimLimitShader::setUniforms(const core::matrix4 &ModelMatrix,
const core::matrix4 &InverseModelMatrix,
const core::matrix4 &TextureMatrix)
{
if (UserConfigParams::m_ubo_disabled)
bypassUBO(Program);
glUniformMatrix4fv(uniform_MM, 1, GL_FALSE, ModelMatrix.pointer());
glUniformMatrix4fv(uniform_IMM, 1, GL_FALSE, InverseModelMatrix.pointer());
glUniformMatrix4fv(uniform_TM, 1, GL_FALSE, TextureMatrix.pointer());
const video::SColorf s = irr_driver->getSceneManager()->getAmbientLight();
glUniform3f(uniform_ambient, s.r, s.g, s.b);
}
GLuint UntexturedObjectShader::Program;
GLuint UntexturedObjectShader::uniform_MM;
GLuint UntexturedObjectShader::uniform_ambient;
@ -1537,6 +1488,7 @@ namespace MeshShader
GLuint DisplaceShader::uniform_displacement_tex;
GLuint DisplaceShader::uniform_mask_tex;
GLuint DisplaceShader::uniform_color_tex;
GLuint DisplaceShader::uniform_tex;
GLuint DisplaceShader::uniform_dir;
GLuint DisplaceShader::uniform_dir2;
@ -1551,11 +1503,12 @@ namespace MeshShader
uniform_mask_tex = glGetUniformLocation(Program, "mask_tex");
uniform_dir = glGetUniformLocation(Program, "dir");
uniform_dir2 = glGetUniformLocation(Program, "dir2");
uniform_tex = glGetUniformLocation(Program, "tex");
GLuint uniform_ViewProjectionMatrixesUBO = glGetUniformBlockIndex(Program, "MatrixesData");
glUniformBlockBinding(Program, uniform_ViewProjectionMatrixesUBO, 0);
}
void DisplaceShader::setUniforms(const core::matrix4 &ModelMatrix, const core::vector2df &dir, const core::vector2df &dir2, const core::vector2df &screen, unsigned TU_displacement_tex, unsigned TU_mask_tex, unsigned TU_color_tex)
void DisplaceShader::setUniforms(const core::matrix4 &ModelMatrix, const core::vector2df &dir, const core::vector2df &dir2, const core::vector2df &screen, unsigned TU_displacement_tex, unsigned TU_mask_tex, unsigned TU_color_tex, unsigned TU_tex)
{
glUniformMatrix4fv(uniform_MVP, 1, GL_FALSE, ModelMatrix.pointer());
glUniform2f(uniform_dir, dir.X, dir.Y);
@ -1563,6 +1516,7 @@ namespace MeshShader
glUniform1i(uniform_displacement_tex, TU_displacement_tex);
glUniform1i(uniform_mask_tex, TU_mask_tex);
glUniform1i(uniform_color_tex, TU_color_tex);
glUniform1i(uniform_tex, TU_tex);
}
GLuint SkyboxShader::Program;

View File

@ -163,17 +163,6 @@ public:
static void setUniforms(const core::matrix4 &ModelMatrix);
};
class ObjectRimLimitShader
{
public:
static GLuint Program;
static GLuint uniform_MM, uniform_IMM, uniform_TM, uniform_ambient;
static GLuint TU_Albedo;
static void init();
static void setUniforms(const core::matrix4 &ModelMatrix, const core::matrix4 &InverseModelMatrix, const core::matrix4 &TextureMatrix);
};
class UntexturedObjectShader
{
public:
@ -375,10 +364,10 @@ class DisplaceShader
{
public:
static GLuint Program;
static GLuint uniform_MVP, uniform_displacement_tex, uniform_mask_tex, uniform_color_tex, uniform_dir, uniform_dir2;
static GLuint uniform_MVP, uniform_displacement_tex, uniform_mask_tex, uniform_color_tex, uniform_tex, uniform_dir, uniform_dir2;
static void init();
static void setUniforms(const core::matrix4 &ModelMatrix, const core::vector2df &dir, const core::vector2df &dir2, const core::vector2df &screen, unsigned TU_displacement_tex, unsigned TU_mask_tex, unsigned TU_color_tex);
static void setUniforms(const core::matrix4 &ModelMatrix, const core::vector2df &dir, const core::vector2df &dir2, const core::vector2df &screen, unsigned TU_displacement_tex, unsigned TU_mask_tex, unsigned TU_color_tex, unsigned TU_tex);
};
class SkyboxShader

View File

@ -93,17 +93,19 @@ void STKAnimatedMesh::render()
if (rnd->isTransparent())
{
TransparentMaterial TranspMat = MaterialTypeToTransparentMaterial(type, MaterialTypeParam);
initvaostate(mesh, TranspMat);
TransparentMesh[TranspMat].push_back(&mesh);
}
else
{
GeometricMaterial GeometricType = MaterialTypeToGeometricMaterial(type);
ShadedMaterial ShadedType = MaterialTypeToShadedMaterial(type, mesh.textures);
initvaostate(mesh, GeometricType, ShadedType);
GeometricMaterial GeometricType = MaterialTypeToGeometricMaterial(type, mb->getVertexType());
ShadedMaterial ShadedType = MaterialTypeToShadedMaterial(type, mesh.textures, mb->getVertexType());
GeometricMesh[GeometricType].push_back(&mesh);
ShadedMesh[ShadedType].push_back(&mesh);
}
std::pair<unsigned, unsigned> p = getVAOOffsetAndBase(mb);
mesh.vaoBaseVertex = p.first;
mesh.vaoOffset = p.second;
mesh.VAOType = mb->getVertexType();
}
}
firstTime = false;
@ -117,8 +119,9 @@ void STKAnimatedMesh::render()
if (irr_driver->getPhase() == SOLID_NORMAL_AND_DEPTH_PASS)
{
glBindVertexArray(0);
glBindBuffer(GL_ARRAY_BUFFER, GLmeshes[i].vertex_buffer);
glBufferSubData(GL_ARRAY_BUFFER, 0, mb->getVertexCount() * GLmeshes[i].Stride, mb->getVertices());
glBindBuffer(GL_ARRAY_BUFFER, getVBO(mb->getVertexType()));
glBufferSubData(GL_ARRAY_BUFFER, GLmeshes[i].vaoBaseVertex * GLmeshes[i].Stride, mb->getVertexCount() * GLmeshes[i].Stride, mb->getVertices());
glBindBuffer(GL_ARRAY_BUFFER, 0);
}
}
if (mb)
@ -133,7 +136,7 @@ void STKAnimatedMesh::render()
continue;
}
if (irr_driver->getPhase() == SOLID_NORMAL_AND_DEPTH_PASS || irr_driver->getPhase() == SHADOW_PASS)
if (irr_driver->getPhase() == SOLID_NORMAL_AND_DEPTH_PASS)
{
ModelViewProjectionMatrix = computeMVP(AbsoluteTransformation);
TransposeInverseModelView = computeTIMV(AbsoluteTransformation);
@ -141,11 +144,18 @@ void STKAnimatedMesh::render()
AbsoluteTransformation.getInverse(invmodel);
GLMesh* mesh;
for_in(mesh, GeometricMesh[FPSM_DEFAULT])
for_in(mesh, GeometricMesh[FPSM_DEFAULT_STANDARD])
{
GroupedFPSM<FPSM_DEFAULT>::MeshSet.push_back(mesh);
GroupedFPSM<FPSM_DEFAULT>::MVPSet.push_back(AbsoluteTransformation);
GroupedFPSM<FPSM_DEFAULT>::TIMVSet.push_back(invmodel);
GroupedFPSM<FPSM_DEFAULT_STANDARD>::MeshSet.push_back(mesh);
GroupedFPSM<FPSM_DEFAULT_STANDARD>::MVPSet.push_back(AbsoluteTransformation);
GroupedFPSM<FPSM_DEFAULT_STANDARD>::TIMVSet.push_back(invmodel);
}
for_in(mesh, GeometricMesh[FPSM_DEFAULT_2TCOORD])
{
GroupedFPSM<FPSM_DEFAULT_2TCOORD>::MeshSet.push_back(mesh);
GroupedFPSM<FPSM_DEFAULT_2TCOORD>::MVPSet.push_back(AbsoluteTransformation);
GroupedFPSM<FPSM_DEFAULT_2TCOORD>::TIMVSet.push_back(invmodel);
}
for_in(mesh, GeometricMesh[FPSM_ALPHA_REF_TEXTURE])
@ -164,11 +174,18 @@ void STKAnimatedMesh::render()
AbsoluteTransformation.getInverse(invmodel);
GLMesh* mesh;
for_in(mesh, ShadedMesh[SM_DEFAULT])
for_in(mesh, ShadedMesh[SM_DEFAULT_STANDARD])
{
GroupedSM<SM_DEFAULT>::MeshSet.push_back(mesh);
GroupedSM<SM_DEFAULT>::MVPSet.push_back(AbsoluteTransformation);
GroupedSM<SM_DEFAULT>::TIMVSet.push_back(invmodel);
GroupedSM<SM_DEFAULT_STANDARD>::MeshSet.push_back(mesh);
GroupedSM<SM_DEFAULT_STANDARD>::MVPSet.push_back(AbsoluteTransformation);
GroupedSM<SM_DEFAULT_STANDARD>::TIMVSet.push_back(invmodel);
}
for_in(mesh, ShadedMesh[SM_DEFAULT_TANGENT])
{
GroupedSM<SM_DEFAULT_TANGENT>::MeshSet.push_back(mesh);
GroupedSM<SM_DEFAULT_TANGENT>::MVPSet.push_back(AbsoluteTransformation);
GroupedSM<SM_DEFAULT_TANGENT>::TIMVSet.push_back(invmodel);
}
for_in(mesh, ShadedMesh[SM_ALPHA_REF_TEXTURE])
@ -178,13 +195,6 @@ void STKAnimatedMesh::render()
GroupedSM<SM_ALPHA_REF_TEXTURE>::TIMVSet.push_back(invmodel);
}
for_in(mesh, ShadedMesh[SM_RIMLIT])
{
GroupedSM<SM_RIMLIT>::MeshSet.push_back(mesh);
GroupedSM<SM_RIMLIT>::MVPSet.push_back(AbsoluteTransformation);
GroupedSM<SM_RIMLIT>::TIMVSet.push_back(invmodel);
}
for_in (mesh, ShadedMesh[SM_UNLIT])
{
GroupedSM<SM_UNLIT>::MeshSet.push_back(mesh);

View File

@ -50,6 +50,7 @@ void STKInstancedSceneNode::createGLMeshes()
{
scene::IMeshBuffer* mb = Mesh->getMeshBuffer(i);
GLmeshes.push_back(allocateMeshBuffer(mb));
fillLocalBuffer(GLmeshes.back(), mb);
}
isMaterialInitialized = false;
}
@ -98,8 +99,8 @@ void STKInstancedSceneNode::setFirstTimeMaterial()
video::E_MATERIAL_TYPE type = mb->getMaterial().MaterialType;
GLMesh &mesh = GLmeshes[i];
GeometricMaterial GeometricType = MaterialTypeToGeometricMaterial(type);
ShadedMaterial ShadedType = MaterialTypeToShadedMaterial(type, mesh.textures);
GeometricMaterial GeometricType = MaterialTypeToGeometricMaterial(type, mb->getVertexType());
ShadedMaterial ShadedType = MaterialTypeToShadedMaterial(type, mesh.textures, mb->getVertexType());
initinstancedvaostate(mesh, GeometricType, ShadedType);
GeometricMesh[GeometricType].push_back(&mesh);
ShadedMesh[ShadedType].push_back(&mesh);
@ -302,10 +303,10 @@ void STKInstancedSceneNode::render()
ModelViewProjectionMatrix = irr_driver->getProjMatrix();
ModelViewProjectionMatrix *= irr_driver->getViewMatrix();
if (!GeometricMesh[FPSM_DEFAULT].empty())
if (!GeometricMesh[FPSM_DEFAULT_STANDARD].empty())
glUseProgram(MeshShader::InstancedObjectPass1Shader::Program);
for (unsigned i = 0; i < GeometricMesh[FPSM_DEFAULT].size(); i++)
drawFSPMDefault(*GeometricMesh[FPSM_DEFAULT][i], instance_pos.size() / 9);
for (unsigned i = 0; i < GeometricMesh[FPSM_DEFAULT_STANDARD].size(); i++)
drawFSPMDefault(*GeometricMesh[FPSM_DEFAULT_STANDARD][i], instance_pos.size() / 9);
if (!GeometricMesh[FPSM_ALPHA_REF_TEXTURE].empty())
glUseProgram(MeshShader::InstancedObjectRefPass1Shader::Program);
@ -322,10 +323,10 @@ void STKInstancedSceneNode::render()
if (irr_driver->getPhase() == SOLID_LIT_PASS)
{
if (!ShadedMesh[SM_DEFAULT].empty())
if (!ShadedMesh[SM_DEFAULT_STANDARD].empty())
glUseProgram(MeshShader::InstancedObjectPass2Shader::Program);
for (unsigned i = 0; i < ShadedMesh[FPSM_DEFAULT].size(); i++)
drawSMDefault(*ShadedMesh[FPSM_DEFAULT][i], ModelViewProjectionMatrix, instance_pos.size() / 9);
for (unsigned i = 0; i < ShadedMesh[SM_DEFAULT_STANDARD].size(); i++)
drawSMDefault(*ShadedMesh[SM_DEFAULT_STANDARD][i], ModelViewProjectionMatrix, instance_pos.size() / 9);
if (!ShadedMesh[SM_ALPHA_REF_TEXTURE].empty())
glUseProgram(MeshShader::InstancedObjectRefPass2Shader::Program);
@ -341,10 +342,10 @@ void STKInstancedSceneNode::render()
if (irr_driver->getPhase() == SHADOW_PASS)
{
if (!GeometricMesh[FPSM_DEFAULT].empty())
if (!GeometricMesh[FPSM_DEFAULT_STANDARD].empty())
glUseProgram(MeshShader::InstancedShadowShader::Program);
for (unsigned i = 0; i < GeometricMesh[FPSM_DEFAULT].size(); i++)
drawShadowDefault(*GeometricMesh[FPSM_DEFAULT][i], instance_pos.size() / 9);
for (unsigned i = 0; i < GeometricMesh[FPSM_DEFAULT_STANDARD].size(); i++)
drawShadowDefault(*GeometricMesh[FPSM_DEFAULT_STANDARD][i], instance_pos.size() / 9);
if (!GeometricMesh[FPSM_ALPHA_REF_TEXTURE].empty())
glUseProgram(MeshShader::InstancedRefShadowShader::Program);

View File

@ -9,7 +9,7 @@
#include "graphics/camera.hpp"
#include "modes/world.hpp"
GeometricMaterial MaterialTypeToGeometricMaterial(video::E_MATERIAL_TYPE MaterialType)
GeometricMaterial MaterialTypeToGeometricMaterial(video::E_MATERIAL_TYPE MaterialType, video::E_VERTEX_TYPE tp)
{
if (MaterialType == irr_driver->getShader(ES_NORMAL_MAP))
return FPSM_NORMAL_MAP;
@ -17,11 +17,13 @@ GeometricMaterial MaterialTypeToGeometricMaterial(video::E_MATERIAL_TYPE Materia
return FPSM_ALPHA_REF_TEXTURE;
else if (MaterialType == irr_driver->getShader(ES_GRASS) || MaterialType == irr_driver->getShader(ES_GRASS_REF))
return FPSM_GRASS;
else
return FPSM_DEFAULT;
else if (tp == video::EVT_2TCOORDS)
return FPSM_DEFAULT_2TCOORD;
assert(tp == video::EVT_STANDARD);
return FPSM_DEFAULT_STANDARD;
}
ShadedMaterial MaterialTypeToShadedMaterial(video::E_MATERIAL_TYPE type, video::ITexture **textures)
ShadedMaterial MaterialTypeToShadedMaterial(video::E_MATERIAL_TYPE type, video::ITexture **textures, video::E_VERTEX_TYPE tp)
{
if (type == irr_driver->getShader(ES_SPHERE_MAP))
return SM_SPHEREMAP;
@ -29,16 +31,15 @@ ShadedMaterial MaterialTypeToShadedMaterial(video::E_MATERIAL_TYPE type, video::
return SM_SPLATTING;
else if (type == irr_driver->getShader(ES_OBJECTPASS_REF) || type == video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF)
return SM_ALPHA_REF_TEXTURE;
else if (type == irr_driver->getShader(ES_OBJECTPASS_RIMLIT) && textures[0])
return SM_RIMLIT;
else if (type == irr_driver->getShader(ES_GRASS) || type == irr_driver->getShader(ES_GRASS_REF))
return SM_GRASS;
else if (type == irr_driver->getShader(ES_OBJECT_UNLIT))
return SM_UNLIT;
else if (textures[1] && type != irr_driver->getShader(ES_NORMAL_MAP))
else if (tp == video::EVT_2TCOORDS)
return SM_DETAILS;
else
return SM_DEFAULT;
else if (tp == video::EVT_TANGENTS)
return SM_DEFAULT_TANGENT;
return SM_DEFAULT_STANDARD;
}
TransparentMaterial MaterialTypeToTransparentMaterial(video::E_MATERIAL_TYPE type, f32 MaterialTypeParam)
@ -49,7 +50,7 @@ TransparentMaterial MaterialTypeToTransparentMaterial(video::E_MATERIAL_TYPE typ
video::E_MODULATE_FUNC mod;
u32 alpha;
unpack_textureBlendFunc(srcFact, DstFact, mod, alpha, MaterialTypeParam);
if (DstFact == video::EBF_ONE)
if (DstFact == video::EBF_ONE || type == video::EMT_TRANSPARENT_ADD_COLOR)
return TM_ADDITIVE;
return TM_DEFAULT;
}
@ -137,46 +138,28 @@ GLMesh allocateMeshBuffer(scene::IMeshBuffer* mb)
GLMesh result = {};
if (!mb)
return result;
glBindVertexArray(0);
glGenBuffers(1, &(result.vertex_buffer));
glGenBuffers(1, &(result.index_buffer));
glBindBuffer(GL_ARRAY_BUFFER, result.vertex_buffer);
const void* vertices = mb->getVertices();
const u32 vertexCount = mb->getVertexCount();
const irr::video::E_VERTEX_TYPE vType = mb->getVertexType();
result.Stride = getVertexPitchFromType(vType);
const c8* vbuf = static_cast<const c8*>(vertices);
glBufferData(GL_ARRAY_BUFFER, vertexCount * result.Stride, vbuf, GL_STATIC_DRAW);
assert(vertexCount);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, result.index_buffer);
const void* indices = mb->getIndices();
u32 indexCount = mb->getIndexCount();
size_t indexSize = 0;
result.IndexCount = mb->getIndexCount();
switch (mb->getIndexType())
{
case irr::video::EIT_16BIT:
{
indexSize = sizeof(u16);
result.IndexType = GL_UNSIGNED_SHORT;
break;
}
case irr::video::EIT_32BIT:
{
indexSize = sizeof(u32);
result.IndexType = GL_UNSIGNED_INT;
break;
}
default:
{
assert(0 && "Wrong index size");
}
case irr::video::EIT_16BIT:
{
result.IndexType = GL_UNSIGNED_SHORT;
break;
}
glBufferData(GL_ELEMENT_ARRAY_BUFFER, indexCount * indexSize, indices, GL_STATIC_DRAW);
case irr::video::EIT_32BIT:
{
result.IndexType = GL_UNSIGNED_INT;
break;
}
default:
{
assert(0 && "Wrong index size");
}
}
result.VAOType = mb->getVertexType();
result.Stride = getVertexPitchFromType(result.VAOType);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
result.IndexCount = mb->getIndexCount();
switch (mb->getPrimitiveType())
@ -210,6 +193,44 @@ GLMesh allocateMeshBuffer(scene::IMeshBuffer* mb)
return result;
}
static
size_t getUnsignedSize(unsigned tp)
{
switch (tp)
{
case GL_UNSIGNED_SHORT:
return sizeof(u16);
case GL_UNSIGNED_INT:
return sizeof(u32);
default:
assert(0 && "Unsupported index type");
return 0;
}
}
void fillLocalBuffer(GLMesh &mesh, scene::IMeshBuffer* mb)
{
glBindVertexArray(0);
glGenBuffers(1, &(mesh.vertex_buffer));
glGenBuffers(1, &(mesh.index_buffer));
glBindBuffer(GL_ARRAY_BUFFER, mesh.vertex_buffer);
const void* vertices = mb->getVertices();
const u32 vertexCount = mb->getVertexCount();
const c8* vbuf = static_cast<const c8*>(vertices);
glBufferData(GL_ARRAY_BUFFER, vertexCount * mesh.Stride, vbuf, GL_STATIC_DRAW);
assert(vertexCount);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mesh.index_buffer);
const void* indices = mb->getIndices();
glBufferData(GL_ELEMENT_ARRAY_BUFFER, mesh.IndexCount * getUnsignedSize(mesh.IndexType), indices, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
}
core::matrix4 computeMVP(const core::matrix4 &ModelMatrix)
{
@ -243,149 +264,93 @@ void drawGrassPass1(const GLMesh &mesh, const core::matrix4 & ModelViewProjectio
GLenum ptype = mesh.PrimitiveType;
GLenum itype = mesh.IndexType;
size_t count = mesh.IndexCount;
assert(mesh.VAOType == video::EVT_STANDARD);
compressTexture(mesh.textures[0], true);
setTexture(0, getTextureGLuint(mesh.textures[0]), GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, true);
MeshShader::GrassPass1Shader::setUniforms(ModelViewProjectionMatrix, TransposeInverseModelView, windDir, 0);
assert(mesh.vao);
glBindVertexArray(mesh.vao);
glDrawElements(ptype, count, itype, 0);
glDrawElementsBaseVertex(ptype, count, itype, (GLvoid *)mesh.vaoOffset, mesh.vaoBaseVertex);
}
void drawSphereMap(const GLMesh &mesh, const core::matrix4 &ModelMatrix, const core::matrix4 &InverseModelMatrix)
{
irr_driver->IncreaseObjectCount();
GLenum ptype = mesh.PrimitiveType;
GLenum itype = mesh.IndexType;
size_t count = mesh.IndexCount;
compressTexture(mesh.textures[0], true);
if (irr_driver->getLightViz())
{
GLint swizzleMask[] = { GL_ONE, GL_ONE, GL_ONE, GL_ALPHA };
glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask);
}
else
{
GLint swizzleMask[] = { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA };
glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask);
}
setTexture(MeshShader::SphereMapShader::TU_tex, getTextureGLuint(mesh.textures[0]), GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, true);
MeshShader::SphereMapShader::setUniforms(ModelMatrix, InverseModelMatrix, irr_driver->getSceneManager()->getAmbientLight());
assert(mesh.vao);
glBindVertexArray(mesh.vao);
glDrawElements(ptype, count, itype, 0);
}
void drawSplatting(const GLMesh &mesh, const core::matrix4 &ModelViewProjectionMatrix)
{
irr_driver->IncreaseObjectCount();
GLenum ptype = mesh.PrimitiveType;
GLenum itype = mesh.IndexType;
size_t count = mesh.IndexCount;
GLenum ptype = mesh.PrimitiveType;
GLenum itype = mesh.IndexType;
size_t count = mesh.IndexCount;
// Texlayout
compressTexture(mesh.textures[1], true);
setTexture(MeshShader::SplattingShader::TU_tex_layout, getTextureGLuint(mesh.textures[1]), GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, true);
if (irr_driver->getLightViz())
{
GLint swizzleMask[] = {GL_ONE, GL_ONE, GL_ONE, GL_ALPHA};
glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask);
}
else
{
GLint swizzleMask[] = {GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA};
glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask);
}
//Tex detail0
compressTexture(mesh.textures[2], true);
setTexture(MeshShader::SplattingShader::TU_tex_detail0, getTextureGLuint(mesh.textures[2]), GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, true);
if (irr_driver->getLightViz())
{
GLint swizzleMask[] = {GL_ONE, GL_ONE, GL_ONE, GL_ALPHA};
glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask);
}
else
{
GLint swizzleMask[] = {GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA};
glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask);
}
//Tex detail1
compressTexture(mesh.textures[3], true);
setTexture(MeshShader::SplattingShader::TU_tex_detail1, getTextureGLuint(mesh.textures[3]), GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, true);
if (irr_driver->getLightViz())
{
GLint swizzleMask[] = {GL_ONE, GL_ONE, GL_ONE, GL_ALPHA};
glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask);
}
else
{
GLint swizzleMask[] = {GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA};
glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask);
}
compressTexture(mesh.textures[4], true);
//Tex detail2
setTexture(MeshShader::SplattingShader::TU_tex_detail2, getTextureGLuint(mesh.textures[4]), GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, true);
if (irr_driver->getLightViz())
{
GLint swizzleMask[] = {GL_ONE, GL_ONE, GL_ONE, GL_ALPHA};
glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask);
}
else
{
GLint swizzleMask[] = {GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA};
glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask);
}
//Tex detail3
compressTexture(mesh.textures[5], true);
setTexture(MeshShader::SplattingShader::TU_tex_detail3, getTextureGLuint(mesh.textures[5]), GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, true);
if (irr_driver->getLightViz())
{
GLint swizzleMask[] = {GL_ONE, GL_ONE, GL_ONE, GL_ALPHA};
glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask);
}
else
{
GLint swizzleMask[] = {GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA};
glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask);
}
// Texlayout
compressTexture(mesh.textures[1], true);
setTexture(MeshShader::SplattingShader::TU_tex_layout, getTextureGLuint(mesh.textures[1]), GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, true);
if (irr_driver->getLightViz())
{
GLint swizzleMask[] = {GL_ONE, GL_ONE, GL_ONE, GL_ALPHA};
glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask);
}
else
{
GLint swizzleMask[] = {GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA};
glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask);
}
//Tex detail0
compressTexture(mesh.textures[2], true);
setTexture(MeshShader::SplattingShader::TU_tex_detail0, getTextureGLuint(mesh.textures[2]), GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, true);
if (irr_driver->getLightViz())
{
GLint swizzleMask[] = {GL_ONE, GL_ONE, GL_ONE, GL_ALPHA};
glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask);
}
else
{
GLint swizzleMask[] = {GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA};
glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask);
}
//Tex detail1
compressTexture(mesh.textures[3], true);
setTexture(MeshShader::SplattingShader::TU_tex_detail1, getTextureGLuint(mesh.textures[3]), GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, true);
if (irr_driver->getLightViz())
{
GLint swizzleMask[] = { GL_ONE, GL_ONE, GL_ONE, GL_ALPHA };
glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask);
}
else
{
GLint swizzleMask[] = { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA };
glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask);
}
compressTexture(mesh.textures[4], true);
//Tex detail2
setTexture(MeshShader::SplattingShader::TU_tex_detail2, getTextureGLuint(mesh.textures[4]), GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, true);
if (irr_driver->getLightViz())
{
GLint swizzleMask[] = { GL_ONE, GL_ONE, GL_ONE, GL_ALPHA };
glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask);
}
else
{
GLint swizzleMask[] = { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA };
glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask);
}
//Tex detail3
compressTexture(mesh.textures[5], true);
setTexture(MeshShader::SplattingShader::TU_tex_detail3, getTextureGLuint(mesh.textures[5]), GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, true);
if (irr_driver->getLightViz())
{
GLint swizzleMask[] = { GL_ONE, GL_ONE, GL_ONE, GL_ALPHA };
glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask);
}
else
{
GLint swizzleMask[] = { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA };
glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask);
}
MeshShader::SplattingShader::setUniforms(ModelViewProjectionMatrix);
assert(mesh.vao);
glBindVertexArray(mesh.vao);
glDrawElements(ptype, count, itype, 0);
MeshShader::SplattingShader::setUniforms(ModelViewProjectionMatrix);
glDrawElementsBaseVertex(ptype, count, itype, (GLvoid *)mesh.vaoOffset, mesh.vaoBaseVertex);
}
void drawObjectRefPass2(const GLMesh &mesh, const core::matrix4 &ModelViewProjectionMatrix, const core::matrix4 &TextureMatrix)
{
irr_driver->IncreaseObjectCount();
GLenum ptype = mesh.PrimitiveType;
GLenum itype = mesh.IndexType;
size_t count = mesh.IndexCount;
compressTexture(mesh.textures[0], true);
setTexture(MeshShader::ObjectRefPass2Shader::TU_Albedo, getTextureGLuint(mesh.textures[0]), GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, true);
if (irr_driver->getLightViz())
{
GLint swizzleMask[] = {GL_ONE, GL_ONE, GL_ONE, GL_ALPHA};
glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask);
}
else
{
GLint swizzleMask[] = {GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA};
glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask);
}
MeshShader::ObjectRefPass2Shader::setUniforms(ModelViewProjectionMatrix, TextureMatrix);
assert(mesh.vao);
glBindVertexArray(mesh.vao);
glDrawElements(ptype, count, itype, 0);
}
void drawGrassPass2(const GLMesh &mesh, const core::matrix4 & ModelViewProjectionMatrix, core::vector3df windDir)
{
@ -393,7 +358,10 @@ void drawGrassPass2(const GLMesh &mesh, const core::matrix4 & ModelViewProjectio
GLenum ptype = mesh.PrimitiveType;
GLenum itype = mesh.IndexType;
size_t count = mesh.IndexCount;
assert(mesh.VAOType == video::EVT_STANDARD);
if (!mesh.textures[0])
const_cast<GLMesh &>(mesh).textures[0] = getUnicolorTexture(video::SColor(255, 255, 255, 255));
compressTexture(mesh.textures[0], true);
setTexture(MeshShader::GrassPass2Shader::TU_Albedo, getTextureGLuint(mesh.textures[0]), GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, true);
if (irr_driver->getLightViz())
@ -408,136 +376,7 @@ void drawGrassPass2(const GLMesh &mesh, const core::matrix4 & ModelViewProjectio
}
MeshShader::GrassPass2Shader::setUniforms(ModelViewProjectionMatrix, windDir);
assert(mesh.vao);
glBindVertexArray(mesh.vao);
glDrawElements(ptype, count, itype, 0);
}
void drawUntexturedObject(const GLMesh &mesh, const core::matrix4 &ModelMatrix)
{
irr_driver->IncreaseObjectCount();
GLenum ptype = mesh.PrimitiveType;
GLenum itype = mesh.IndexType;
size_t count = mesh.IndexCount;
MeshShader::UntexturedObjectShader::setUniforms(ModelMatrix);
assert(mesh.vao);
glBindVertexArray(mesh.vao);
glDrawElements(ptype, count, itype, 0);
}
void drawObjectRimLimit(const GLMesh &mesh, const core::matrix4 &ModelViewProjectionMatrix, const core::matrix4 &TransposeInverseModelView, const core::matrix4 &TextureMatrix)
{
irr_driver->IncreaseObjectCount();
GLenum ptype = mesh.PrimitiveType;
GLenum itype = mesh.IndexType;
size_t count = mesh.IndexCount;
compressTexture(mesh.textures[0], true);
setTexture(MeshShader::ObjectRimLimitShader::TU_Albedo, getTextureGLuint(mesh.textures[0]), GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, true);
if (irr_driver->getLightViz())
{
GLint swizzleMask[] = { GL_ONE, GL_ONE, GL_ONE, GL_ALPHA };
glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask);
}
else
{
GLint swizzleMask[] = { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA };
glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask);
}
MeshShader::ObjectRimLimitShader::setUniforms(ModelViewProjectionMatrix, TransposeInverseModelView, TextureMatrix);
assert(mesh.vao);
glBindVertexArray(mesh.vao);
glDrawElements(ptype, count, itype, 0);
}
void drawObjectUnlit(const GLMesh &mesh, const core::matrix4 &ModelViewProjectionMatrix)
{
irr_driver->IncreaseObjectCount();
GLenum ptype = mesh.PrimitiveType;
GLenum itype = mesh.IndexType;
size_t count = mesh.IndexCount;
compressTexture(mesh.textures[0], true);
setTexture(MeshShader::ObjectUnlitShader::TU_tex, getTextureGLuint(mesh.textures[0]), GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, true);
if (irr_driver->getLightViz())
{
GLint swizzleMask[] = { GL_ONE, GL_ONE, GL_ONE, GL_ALPHA };
glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask);
}
else
{
GLint swizzleMask[] = { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA };
glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask);
}
MeshShader::ObjectUnlitShader::setUniforms(ModelViewProjectionMatrix);
assert(mesh.vao);
glBindVertexArray(mesh.vao);
glDrawElements(ptype, count, itype, 0);
}
void drawDetailledObjectPass2(const GLMesh &mesh, const core::matrix4 &ModelViewProjectionMatrix)
{
irr_driver->IncreaseObjectCount();
GLenum ptype = mesh.PrimitiveType;
GLenum itype = mesh.IndexType;
size_t count = mesh.IndexCount;
compressTexture(mesh.textures[0], true);
setTexture(MeshShader::DetailledObjectPass2Shader::TU_Albedo, getTextureGLuint(mesh.textures[0]), GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, true);
if (irr_driver->getLightViz())
{
GLint swizzleMask[] = {GL_ONE, GL_ONE, GL_ONE, GL_ALPHA};
glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask);
}
else
{
GLint swizzleMask[] = {GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA};
glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask);
}
compressTexture(mesh.textures[1], true);
setTexture(MeshShader::DetailledObjectPass2Shader::TU_detail, getTextureGLuint(mesh.textures[1]), GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, true);
MeshShader::DetailledObjectPass2Shader::setUniforms(ModelViewProjectionMatrix);
assert(mesh.vao);
glBindVertexArray(mesh.vao);
glDrawElements(ptype, count, itype, 0);
}
void drawObjectPass2(const GLMesh &mesh, const core::matrix4 &ModelViewProjectionMatrix, const core::matrix4 &TextureMatrix)
{
irr_driver->IncreaseObjectCount();
GLenum ptype = mesh.PrimitiveType;
GLenum itype = mesh.IndexType;
size_t count = mesh.IndexCount;
if (!mesh.textures[0])
const_cast<GLMesh &>(mesh).textures[0] = getUnicolorTexture(video::SColor(255, 255, 255, 255));
compressTexture(mesh.textures[0], true);
setTexture(MeshShader::ObjectPass2Shader::TU_Albedo, getTextureGLuint(mesh.textures[0]), GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, true);
if (irr_driver->getLightViz())
{
GLint swizzleMask[] = { GL_ONE, GL_ONE, GL_ONE, GL_ALPHA };
glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask);
}
else
{
GLint swizzleMask[] = { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA };
glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask);
}
MeshShader::ObjectPass2Shader::setUniforms(ModelViewProjectionMatrix, TextureMatrix);
assert(mesh.vao);
glBindVertexArray(mesh.vao);
glDrawElements(ptype, count, itype, 0);
glDrawElementsBaseVertex(ptype, count, itype, (GLvoid *)mesh.vaoOffset, mesh.vaoBaseVertex);
}
void drawTransparentObject(const GLMesh &mesh, const core::matrix4 &ModelViewProjectionMatrix, const core::matrix4 &TextureMatrix)
@ -606,10 +445,7 @@ void drawBubble(const GLMesh &mesh, const core::matrix4 &ModelViewProjectionMatr
setTexture(0, getTextureGLuint(mesh.textures[0]), GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, true);
MeshShader::BubbleShader::setUniforms(ModelViewProjectionMatrix, 0, time, transparency);
assert(mesh.vao);
glBindVertexArray(mesh.vao);
glDrawElements(ptype, count, itype, 0);
glDrawElementsBaseVertex(ptype, count, itype, (GLvoid *)mesh.vaoOffset, mesh.vaoBaseVertex);
}
void drawShadowRef(const GLMesh &mesh, const core::matrix4 &ModelMatrix)
@ -622,10 +458,7 @@ void drawShadowRef(const GLMesh &mesh, const core::matrix4 &ModelMatrix)
compressTexture(mesh.textures[0], true);
setTexture(0, getTextureGLuint(mesh.textures[0]), GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, true);
MeshShader::RefShadowShader::setUniforms(ModelMatrix, 0);
assert(mesh.vao);
glBindVertexArray(mesh.vao);
glDrawElementsInstanced(ptype, count, itype, 0, 4);
glDrawElementsInstancedBaseVertex(ptype, count, itype, (GLvoid *)mesh.vaoOffset, 4, mesh.vaoBaseVertex);
}
void drawShadow(const GLMesh &mesh, const core::matrix4 &ModelMatrix)
@ -636,10 +469,7 @@ void drawShadow(const GLMesh &mesh, const core::matrix4 &ModelMatrix)
size_t count = mesh.IndexCount;
MeshShader::ShadowShader::setUniforms(ModelMatrix);
assert(mesh.vao);
glBindVertexArray(mesh.vao);
glDrawElementsInstanced(ptype, count, itype, 0, 4);
glDrawElementsInstancedBaseVertex(ptype, count, itype, (GLvoid *) mesh.vaoOffset, 4, mesh.vaoBaseVertex);
}
bool isObject(video::E_MATERIAL_TYPE type)

View File

@ -12,7 +12,8 @@
enum GeometricMaterial
{
FPSM_DEFAULT,
FPSM_DEFAULT_STANDARD,
FPSM_DEFAULT_2TCOORD,
FPSM_ALPHA_REF_TEXTURE,
FPSM_NORMAL_MAP,
FPSM_GRASS,
@ -21,9 +22,9 @@ enum GeometricMaterial
enum ShadedMaterial
{
SM_DEFAULT,
SM_DEFAULT_STANDARD,
SM_DEFAULT_TANGENT,
SM_ALPHA_REF_TEXTURE,
SM_RIMLIT,
SM_SPHEREMAP,
SM_SPLATTING,
SM_GRASS,
@ -51,9 +52,13 @@ struct GLMesh {
size_t IndexCount;
size_t Stride;
core::matrix4 TextureMatrix;
size_t vaoBaseVertex;
size_t vaoOffset;
video::E_VERTEX_TYPE VAOType;
};
GLMesh allocateMeshBuffer(scene::IMeshBuffer* mb);
void fillLocalBuffer(GLMesh &, scene::IMeshBuffer* mb);
video::E_VERTEX_TYPE getVTXTYPEFromStride(size_t stride);
GLuint createVAO(GLuint vbo, GLuint idx, video::E_VERTEX_TYPE type);
void initvaostate(GLMesh &mesh, GeometricMaterial GeoMat, ShadedMaterial ShadedMat);
@ -89,7 +94,7 @@ std::vector<core::matrix4> GroupedFPSM<T>::TIMVSet;
template<typename Shader, typename...uniforms>
void draw(const GLMesh &mesh, GLuint vao, uniforms... Args)
void draw(const GLMesh &mesh, uniforms... Args)
{
irr_driver->IncreaseObjectCount();
GLenum ptype = mesh.PrimitiveType;
@ -97,10 +102,7 @@ void draw(const GLMesh &mesh, GLuint vao, uniforms... Args)
size_t count = mesh.IndexCount;
Shader::setUniforms(Args...);
assert(vao);
glBindVertexArray(vao);
glDrawElements(ptype, count, itype, 0);
glDrawElementsBaseVertex(ptype, count, itype, (GLvoid *)mesh.vaoOffset, mesh.vaoBaseVertex);
}
void drawGrassPass1(const GLMesh &mesh, const core::matrix4 & ModelViewProjectionMatrix, const core::matrix4 &TransposeInverseModelView, core::vector3df windDir);
@ -128,15 +130,8 @@ std::vector<core::matrix4> GroupedSM<T>::MVPSet;
template<enum ShadedMaterial T>
std::vector<core::matrix4> GroupedSM<T>::TIMVSet;
void drawDetailledObjectPass2(const GLMesh &mesh, const core::matrix4 &ModelViewProjectionMatrix);
void drawObjectPass2(const GLMesh &mesh, const core::matrix4 &ModelViewProjectionMatrix, const core::matrix4 &TextureMatrix);
void drawUntexturedObject(const GLMesh &mesh, const core::matrix4 &ModelViewProjectionMatrix);
void drawObjectRefPass2(const GLMesh &mesh, const core::matrix4 &ModelViewProjectionMatrix, const core::matrix4 &TextureMatrix);
void drawSphereMap(const GLMesh &mesh, const core::matrix4 &ModelViewProjectionMatrix, const core::matrix4 &TransposeInverseModelView);
void drawSplatting(const GLMesh &mesh, const core::matrix4 &ModelViewProjectionMatrix);
void drawGrassPass2(const GLMesh &mesh, const core::matrix4 & ModelViewProjectionMatrix, core::vector3df windDir);
void drawObjectRimLimit(const GLMesh &mesh, const core::matrix4 &ModelViewProjectionMatrix, const core::matrix4 &TransposeInverseModelView, const core::matrix4 &TextureMatrix);
void drawObjectUnlit(const GLMesh &mesh, const core::matrix4 &ModelViewProjectionMatrix);
// Shadow pass
void drawShadowRef(const GLMesh &mesh, const core::matrix4 &ModelMatrix);
@ -166,8 +161,8 @@ void drawTransparentObject(const GLMesh &mesh, const core::matrix4 &ModelViewPro
void drawTransparentFogObject(const GLMesh &mesh, const core::matrix4 &ModelViewProjectionMatrix, const core::matrix4 &TextureMatrix);
void drawBubble(const GLMesh &mesh, const core::matrix4 &ModelViewProjectionMatrix);
GeometricMaterial MaterialTypeToGeometricMaterial(video::E_MATERIAL_TYPE);
ShadedMaterial MaterialTypeToShadedMaterial(video::E_MATERIAL_TYPE, irr::video::ITexture **textures);
GeometricMaterial MaterialTypeToGeometricMaterial(video::E_MATERIAL_TYPE, video::E_VERTEX_TYPE);
ShadedMaterial MaterialTypeToShadedMaterial(video::E_MATERIAL_TYPE, irr::video::ITexture **textures, video::E_VERTEX_TYPE tp);
TransparentMaterial MaterialTypeToTransparentMaterial(video::E_MATERIAL_TYPE, f32 MaterialTypeParam);
#endif // STKMESH_H

View File

@ -16,13 +16,16 @@ STKMeshSceneNode::STKMeshSceneNode(irr::scene::IMesh* mesh, ISceneNode* parent,
const irr::core::vector3df& scale) :
CMeshSceneNode(mesh, parent, mgr, id, position, rotation, scale)
{
reload_each_frame = false;
immediate_draw = false;
update_each_frame = false;
createGLMeshes();
}
void STKMeshSceneNode::setReloadEachFrame(bool val)
{
reload_each_frame = val;
update_each_frame = val;
if (val)
immediate_draw = true;
}
void STKMeshSceneNode::createGLMeshes()
@ -60,16 +63,38 @@ void STKMeshSceneNode::setFirstTimeMaterial()
if (rnd->isTransparent())
{
TransparentMaterial TranspMat = MaterialTypeToTransparentMaterial(type, MaterialTypeParam);
initvaostate(mesh, TranspMat);
TransparentMesh[TranspMat].push_back(&mesh);
if (immediate_draw)
{
fillLocalBuffer(mesh, mb);
initvaostate(mesh, TranspMat);
glBindVertexArray(0);
}
else
TransparentMesh[TranspMat].push_back(&mesh);
}
else
{
GeometricMaterial GeometricType = MaterialTypeToGeometricMaterial(type);
ShadedMaterial ShadedType = MaterialTypeToShadedMaterial(type, mesh.textures);
initvaostate(mesh, GeometricType, ShadedType);
GeometricMesh[GeometricType].push_back(&mesh);
ShadedMesh[ShadedType].push_back(&mesh);
GeometricMaterial GeometricType = MaterialTypeToGeometricMaterial(type, mb->getVertexType());
ShadedMaterial ShadedType = MaterialTypeToShadedMaterial(type, mesh.textures, mb->getVertexType());
if (immediate_draw)
{
fillLocalBuffer(mesh, mb);
initvaostate(mesh, GeometricType, ShadedType);
glBindVertexArray(0);
}
else
{
GeometricMesh[GeometricType].push_back(&mesh);
ShadedMesh[ShadedType].push_back(&mesh);
}
}
if (!immediate_draw)
{
std::pair<unsigned, unsigned> p = getVAOOffsetAndBase(mb);
mesh.vaoBaseVertex = p.first;
mesh.vaoOffset = p.second;
mesh.VAOType = mb->getVertexType();
}
}
isMaterialInitialized = true;
@ -109,22 +134,26 @@ STKMeshSceneNode::~STKMeshSceneNode()
void STKMeshSceneNode::drawGlow(const GLMesh &mesh)
{
ColorizeProvider * const cb = (ColorizeProvider *)irr_driver->getCallback(ES_COLORIZE);
assert(mesh.VAOType == video::EVT_STANDARD);
GLenum ptype = mesh.PrimitiveType;
GLenum itype = mesh.IndexType;
size_t count = mesh.IndexCount;
MeshShader::ColorizeShader::setUniforms(AbsoluteTransformation, cb->getRed(), cb->getGreen(), cb->getBlue());
assert(mesh.vao);
glBindVertexArray(mesh.vao);
glDrawElements(ptype, count, itype, 0);
glDrawElementsBaseVertex(ptype, count, itype, (GLvoid *)mesh.vaoOffset, mesh.vaoBaseVertex);
}
static video::ITexture *displaceTex = 0;
void STKMeshSceneNode::drawDisplace(const GLMesh &mesh)
{
if (mesh.VAOType != video::EVT_2TCOORDS)
{
Log::error("Materials", "Displacement has wrong vertex type");
return;
}
glBindVertexArray(getVAO(video::EVT_2TCOORDS));
DisplaceProvider * const cb = (DisplaceProvider *)irr_driver->getCallback(ES_DISPLACE);
GLenum ptype = mesh.PrimitiveType;
@ -137,9 +166,7 @@ void STKMeshSceneNode::drawDisplace(const GLMesh &mesh)
glUseProgram(MeshShader::DisplaceMaskShader::Program);
MeshShader::DisplaceMaskShader::setUniforms(AbsoluteTransformation);
glBindVertexArray(mesh.vao);
glDrawElements(ptype, count, itype, 0);
glDrawElementsBaseVertex(ptype, count, itype, (GLvoid *)mesh.vaoOffset, mesh.vaoBaseVertex);
// Render the effect
if (!displaceTex)
@ -148,57 +175,16 @@ void STKMeshSceneNode::drawDisplace(const GLMesh &mesh)
setTexture(0, getTextureGLuint(displaceTex), GL_LINEAR, GL_LINEAR, true);
setTexture(1, irr_driver->getRenderTargetTexture(RTT_TMP1), GL_LINEAR, GL_LINEAR, true);
setTexture(2, irr_driver->getRenderTargetTexture(RTT_COLOR), GL_LINEAR, GL_LINEAR, true);
setTexture(3, getTextureGLuint(mesh.textures[0]), GL_LINEAR, GL_LINEAR, true);
glUseProgram(MeshShader::DisplaceShader::Program);
MeshShader::DisplaceShader::setUniforms(AbsoluteTransformation,
core::vector2df(cb->getDirX(), cb->getDirY()),
core::vector2df(cb->getDir2X(), cb->getDir2Y()),
core::vector2df(float(UserConfigParams::m_width),
float(UserConfigParams::m_height)),
0, 1, 2);
0, 1, 2, 3);
glDrawElements(ptype, count, itype, 0);
}
void STKMeshSceneNode::drawTransparent(const GLMesh &mesh, video::E_MATERIAL_TYPE type)
{
assert(irr_driver->getPhase() == TRANSPARENT_PASS);
ModelViewProjectionMatrix = computeMVP(AbsoluteTransformation);
if (type == irr_driver->getShader(ES_BUBBLES))
drawBubble(mesh, ModelViewProjectionMatrix);
// else if (World::getWorld()->getTrack()->isFogEnabled())
// drawTransparentFogObject(mesh, ModelViewProjectionMatrix, TextureMatrix);
else
drawTransparentObject(mesh, ModelViewProjectionMatrix, mesh.TextureMatrix);
return;
}
void STKMeshSceneNode::drawSolidPass1(const GLMesh &mesh, GeometricMaterial type)
{
irr_driver->IncreaseObjectCount();
windDir = getWind();
switch (type)
{
case FPSM_GRASS:
drawGrassPass1(mesh, ModelViewProjectionMatrix, TransposeInverseModelView, windDir);
break;
default:
assert(0 && "wrong geometric material");
}
}
void STKMeshSceneNode::drawSolidPass2(const GLMesh &mesh, ShadedMaterial type)
{
switch (type)
{
case SM_GRASS:
drawGrassPass2(mesh, ModelViewProjectionMatrix, windDir);
break;
default:
assert(0 && "Wrong shaded material");
break;
}
glDrawElementsBaseVertex(ptype, count, itype, (GLvoid *)mesh.vaoOffset, mesh.vaoBaseVertex);
}
void STKMeshSceneNode::updatevbo()
@ -243,8 +229,8 @@ void STKMeshSceneNode::render()
if (!Mesh || !driver)
return;
if (reload_each_frame)
updatevbo();
bool isTransparentPass =
SceneManager->getSceneNodeRenderPass() == scene::ESNRP_TRANSPARENT;
++PassCount;
@ -260,20 +246,52 @@ void STKMeshSceneNode::render()
GLmeshes[i].TextureMatrix = getMaterial(i).getTextureMatrix(0);
}
if (irr_driver->getPhase() == SOLID_NORMAL_AND_DEPTH_PASS || irr_driver->getPhase() == SHADOW_PASS)
if (irr_driver->getPhase() == SOLID_NORMAL_AND_DEPTH_PASS)
{
if (reload_each_frame)
glDisable(GL_CULL_FACE);
ModelViewProjectionMatrix = computeMVP(AbsoluteTransformation);
TransposeInverseModelView = computeTIMV(AbsoluteTransformation);
core::matrix4 invmodel;
AbsoluteTransformation.getInverse(invmodel);
GLMesh* mesh;
for_in(mesh, GeometricMesh[FPSM_DEFAULT])
if (immediate_draw)
{
GroupedFPSM<FPSM_DEFAULT>::MeshSet.push_back(mesh);
GroupedFPSM<FPSM_DEFAULT>::MVPSet.push_back(AbsoluteTransformation);
GroupedFPSM<FPSM_DEFAULT>::TIMVSet.push_back(invmodel);
glDisable(GL_CULL_FACE);
if (update_each_frame)
updatevbo();
glUseProgram(MeshShader::ObjectPass1Shader::Program);
// Only untextured
for (unsigned i = 0; i < GLmeshes.size(); i++)
{
irr_driver->IncreaseObjectCount();
GLMesh &mesh = GLmeshes[i];
GLenum ptype = mesh.PrimitiveType;
GLenum itype = mesh.IndexType;
size_t count = mesh.IndexCount;
MeshShader::ObjectPass1Shader::setUniforms(AbsoluteTransformation, invmodel, 0);
assert(mesh.vao);
glBindVertexArray(mesh.vao);
glDrawElements(ptype, count, itype, 0);
glBindVertexArray(0);
}
glEnable(GL_CULL_FACE);
return;
}
GLMesh* mesh;
for_in(mesh, GeometricMesh[FPSM_DEFAULT_STANDARD])
{
GroupedFPSM<FPSM_DEFAULT_STANDARD>::MeshSet.push_back(mesh);
GroupedFPSM<FPSM_DEFAULT_STANDARD>::MVPSet.push_back(AbsoluteTransformation);
GroupedFPSM<FPSM_DEFAULT_STANDARD>::TIMVSet.push_back(invmodel);
}
for_in(mesh, GeometricMesh[FPSM_DEFAULT_2TCOORD])
{
GroupedFPSM<FPSM_DEFAULT_2TCOORD>::MeshSet.push_back(mesh);
GroupedFPSM<FPSM_DEFAULT_2TCOORD>::MVPSet.push_back(AbsoluteTransformation);
GroupedFPSM<FPSM_DEFAULT_2TCOORD>::TIMVSet.push_back(invmodel);
}
for_in(mesh, GeometricMesh[FPSM_ALPHA_REF_TEXTURE])
@ -290,33 +308,57 @@ void STKMeshSceneNode::render()
GroupedFPSM<FPSM_NORMAL_MAP>::TIMVSet.push_back(invmodel);
}
if (irr_driver->getPhase() == SOLID_NORMAL_AND_DEPTH_PASS)
{
if (!GeometricMesh[FPSM_GRASS].empty())
glUseProgram(MeshShader::GrassPass1Shader::Program);
for_in(mesh, GeometricMesh[FPSM_GRASS])
drawSolidPass1(*mesh, FPSM_GRASS);
}
if (!GeometricMesh[FPSM_GRASS].empty())
glUseProgram(MeshShader::GrassPass1Shader::Program);
windDir = getWind();
glBindVertexArray(getVAO(video::EVT_STANDARD));
for_in(mesh, GeometricMesh[FPSM_GRASS])
drawGrassPass1(*mesh, ModelViewProjectionMatrix, TransposeInverseModelView, windDir);
if (reload_each_frame)
glEnable(GL_CULL_FACE);
return;
}
if (irr_driver->getPhase() == SOLID_LIT_PASS)
{
if (reload_each_frame)
glDisable(GL_CULL_FACE);
core::matrix4 invmodel;
AbsoluteTransformation.getInverse(invmodel);
GLMesh* mesh;
for_in(mesh, ShadedMesh[SM_DEFAULT])
if (immediate_draw)
{
GroupedSM<SM_DEFAULT>::MeshSet.push_back(mesh);
GroupedSM<SM_DEFAULT>::MVPSet.push_back(AbsoluteTransformation);
GroupedSM<SM_DEFAULT>::TIMVSet.push_back(invmodel);
glDisable(GL_CULL_FACE);
glUseProgram(MeshShader::UntexturedObjectShader::Program);
// Only untextured
for (unsigned i = 0; i < GLmeshes.size(); i++)
{
irr_driver->IncreaseObjectCount();
GLMesh &mesh = GLmeshes[i];
GLenum ptype = mesh.PrimitiveType;
GLenum itype = mesh.IndexType;
size_t count = mesh.IndexCount;
MeshShader::UntexturedObjectShader::setUniforms(AbsoluteTransformation);
assert(mesh.vao);
glBindVertexArray(mesh.vao);
glDrawElements(ptype, count, itype, 0);
glBindVertexArray(0);
}
glEnable(GL_CULL_FACE);
return;
}
GLMesh* mesh;
for_in(mesh, ShadedMesh[SM_DEFAULT_STANDARD])
{
GroupedSM<SM_DEFAULT_STANDARD>::MeshSet.push_back(mesh);
GroupedSM<SM_DEFAULT_STANDARD>::MVPSet.push_back(AbsoluteTransformation);
GroupedSM<SM_DEFAULT_STANDARD>::TIMVSet.push_back(invmodel);
}
for_in(mesh, ShadedMesh[SM_DEFAULT_TANGENT])
{
GroupedSM<SM_DEFAULT_TANGENT>::MeshSet.push_back(mesh);
GroupedSM<SM_DEFAULT_TANGENT>::MVPSet.push_back(AbsoluteTransformation);
GroupedSM<SM_DEFAULT_TANGENT>::TIMVSet.push_back(invmodel);
}
for_in(mesh, ShadedMesh[SM_ALPHA_REF_TEXTURE])
@ -326,14 +368,6 @@ void STKMeshSceneNode::render()
GroupedSM<SM_ALPHA_REF_TEXTURE>::TIMVSet.push_back(invmodel);
}
for_in(mesh, ShadedMesh[SM_RIMLIT])
{
GroupedSM<SM_RIMLIT>::MeshSet.push_back(mesh);
GroupedSM<SM_RIMLIT>::MVPSet.push_back(AbsoluteTransformation);
GroupedSM<SM_RIMLIT>::TIMVSet.push_back(invmodel);
}
for_in(mesh, ShadedMesh[SM_SPHEREMAP])
{
GroupedSM<SM_SPHEREMAP>::MeshSet.push_back(mesh);
@ -364,11 +398,10 @@ void STKMeshSceneNode::render()
if (!ShadedMesh[SM_GRASS].empty())
glUseProgram(MeshShader::GrassPass2Shader::Program);
glBindVertexArray(getVAO(video::EVT_STANDARD));
for_in(mesh, ShadedMesh[SM_GRASS])
drawSolidPass2(*mesh, SM_GRASS);
drawGrassPass2(*mesh, ModelViewProjectionMatrix, windDir);
if (reload_each_frame)
glEnable(GL_CULL_FACE);
return;
}
@ -380,6 +413,7 @@ void STKMeshSceneNode::render()
scene::IMeshBuffer* mb = Mesh->getMeshBuffer(i);
if (!mb)
continue;
glBindVertexArray(getVAO(video::EVT_STANDARD));
drawGlow(GLmeshes[i]);
}
}
@ -388,6 +422,71 @@ void STKMeshSceneNode::render()
{
ModelViewProjectionMatrix = computeMVP(AbsoluteTransformation);
if (immediate_draw)
{
if (update_each_frame)
updatevbo();
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
if (World::getWorld() && World::getWorld()->isFogEnabled())
{
glUseProgram(MeshShader::TransparentFogShader::Program);
for (unsigned i = 0; i < GLmeshes.size(); i++)
{
GLMesh &mesh = GLmeshes[i];
irr_driver->IncreaseObjectCount();
GLenum ptype = mesh.PrimitiveType;
GLenum itype = mesh.IndexType;
size_t count = mesh.IndexCount;
const Track * const track = World::getWorld()->getTrack();
// This function is only called once per frame - thus no need for setters.
const float fogmax = track->getFogMax();
const float startH = track->getFogStartHeight();
const float endH = track->getFogEndHeight();
const float start = track->getFogStart();
const float end = track->getFogEnd();
const video::SColor tmpcol = track->getFogColor();
core::vector3df col(tmpcol.getRed() / 255.0f,
tmpcol.getGreen() / 255.0f,
tmpcol.getBlue() / 255.0f);
compressTexture(mesh.textures[0], true);
setTexture(0, getTextureGLuint(mesh.textures[0]), GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, true);
MeshShader::TransparentFogShader::setUniforms(AbsoluteTransformation, mesh.TextureMatrix, fogmax, startH, endH, start, end, col, Camera::getCamera(0)->getCameraSceneNode()->getAbsolutePosition(), 0);
assert(mesh.vao);
glBindVertexArray(mesh.vao);
glDrawElements(ptype, count, itype, 0);
glBindVertexArray(0);
}
}
else
{
glUseProgram(MeshShader::TransparentShader::Program);
for (unsigned i = 0; i < GLmeshes.size(); i++)
{
irr_driver->IncreaseObjectCount();
GLMesh &mesh = GLmeshes[i];
GLenum ptype = mesh.PrimitiveType;
GLenum itype = mesh.IndexType;
size_t count = mesh.IndexCount;
compressTexture(mesh.textures[0], true);
setTexture(0, getTextureGLuint(mesh.textures[0]), GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, true);
MeshShader::TransparentShader::setUniforms(AbsoluteTransformation, mesh.TextureMatrix, 0);
assert(mesh.vao);
glBindVertexArray(mesh.vao);
glDrawElements(ptype, count, itype, 0);
glBindVertexArray(0);
}
}
return;
}
GLMesh* mesh;
for_in(mesh, TransparentMesh[TM_DEFAULT])
@ -404,6 +503,7 @@ void STKMeshSceneNode::render()
if (!TransparentMesh[TM_BUBBLE].empty())
glUseProgram(MeshShader::BubbleShader::Program);
glBindVertexArray(getVAO(video::EVT_STANDARD));
for_in(mesh, TransparentMesh[TM_BUBBLE])
drawBubble(*mesh, ModelViewProjectionMatrix);
return;

View File

@ -14,9 +14,6 @@ protected:
core::matrix4 ModelViewProjectionMatrix, TransposeInverseModelView;
core::vector3df windDir;
core::vector2df caustic_dir, caustic_dir2;
void drawSolidPass1(const GLMesh &mesh, GeometricMaterial type);
void drawSolidPass2(const GLMesh &mesh, ShadedMaterial type);
void drawTransparent(const GLMesh &mesh, video::E_MATERIAL_TYPE type);
// Misc passes shaders (glow, displace...)
void drawGlow(const GLMesh &mesh);
@ -26,7 +23,8 @@ protected:
void setFirstTimeMaterial();
void updatevbo();
bool isMaterialInitialized;
bool reload_each_frame;
bool immediate_draw;
bool update_each_frame;
public:
void setReloadEachFrame(bool);
STKMeshSceneNode(irr::scene::IMesh* mesh, ISceneNode* parent, irr::scene::ISceneManager* mgr, irr::s32 id,

View File

@ -87,7 +87,7 @@ public:
// ============================================================================
/** List of all messages. */
std::priority_queue<Message*, std::vector<Message*>,
std::priority_queue<Message*, std::vector<Message*>,
CompareMessages> g_all_messages;
/** How long the current message has been displayed. The special value
@ -139,7 +139,7 @@ void add(MessageType mt, const irr::core::stringw &message)
} // add
// ----------------------------------------------------------------------------
/** Update function called from the GUIEngine to handle displaying of the
/** Update function called from the GUIEngine to handle displaying of the
* messages. It will make sure that each message is shown for a certain
* amount of time, before it is discarded and the next message (if any)
* is displayed.
@ -166,7 +166,7 @@ void update(float dt)
}
Message *current = g_all_messages.top();
GUIEngine::getSkin()->drawMessage(g_container, g_area,
GUIEngine::getSkin()->drawMessage(g_container, g_area,
current->getRenderType());
gui::ScalableFont *font = GUIEngine::getFont();

View File

@ -149,12 +149,12 @@ void OverWorld::update(float dt)
if (m_return_to_garage)
{
m_return_to_garage = false;
delayedSelfDestruct();
race_manager->exitRace(false);
race_manager->exitRace();
KartSelectionScreen* s = OfflineKartSelectionScreen::getInstance();
s->setMultiplayer(false);
s->setFromOverworld(true);
StateManager::get()->resetAndGoToScreen(s);
throw AbortWorldUpdateException();
}
} // update

View File

@ -795,7 +795,14 @@ void World::updateWorld(float dt)
getPhase() == IN_GAME_MENU_PHASE )
return;
update(dt);
try
{
update(dt);
}
catch (AbortWorldUpdateException& e)
{
return;
}
#ifdef DEBUG
assert(m_magic_number == 0xB01D6543);

View File

@ -1,357 +1,363 @@
//
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2004-2013 SuperTuxKart-Team
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 3
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#ifndef HEADER_WORLD_HPP
#define HEADER_WORLD_HPP
/**
* \defgroup modes
* Contains the logic for the various game modes (race, follow the leader,
* battle, etc.)
*/
#include <vector>
#include "modes/world_status.hpp"
#include "race/highscores.hpp"
#include "states_screens/race_gui_base.hpp"
#include "states_screens/state_manager.hpp"
#include "utils/random_generator.hpp"
#include "LinearMath/btTransform.h"
class AbstractKart;
class btRigidBody;
class Controller;
class PhysicalObject;
class Physics;
class Track;
//
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2004-2013 SuperTuxKart-Team
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 3
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#ifndef HEADER_WORLD_HPP
#define HEADER_WORLD_HPP
/**
* \defgroup modes
* Contains the logic for the various game modes (race, follow the leader,
* battle, etc.)
*/
#include <vector>
#include <stdexcept>
#include "modes/world_status.hpp"
#include "race/highscores.hpp"
#include "states_screens/race_gui_base.hpp"
#include "states_screens/state_manager.hpp"
#include "utils/random_generator.hpp"
#include "LinearMath/btTransform.h"
class AbstractKart;
class btRigidBody;
class Controller;
class PhysicalObject;
class Physics;
class Track;
namespace Scripting
{
class ScriptEngine;
}
namespace irr
{
namespace scene { class ISceneNode; }
}
/**
* \brief base class for all game modes
* This class is responsible for running the actual race. A world is created
* by the race manager on the start of each race (so a new world is created
* for each race of a Grand Prix). It creates the
* physics, loads the track, creates all karts, and initialises the race
* specific managers (ItemManager, ProjectilManager, highscores, ...).
* It uses the information from the race manager to get information like
* what and how many karts, track to load etc. This class does not really
* know about Grand Prixs, a GP is created
* It maintains the race clock, and updates all karts, herings etc. during
* the race.
* Special game modes (e.g. follow the leader) are currently integrated in
* this world, see e.g. updateRaceStatus where the world clock behaviour
* is handled differently to create the count down.
* \ingroup modes
*/
class World : public WorldStatus
{
public:
typedef std::vector<AbstractKart*> KartList;
private:
/** A pointer to the global world object for a race. */
static World *m_world;
protected:
#ifdef DEBUG
unsigned int m_magic_number;
#endif
/** The list of all karts. */
KartList m_karts;
RandomGenerator m_random;
Physics* m_physics;
AbstractKart* m_fastest_kart;
/** Number of eliminated karts. */
int m_eliminated_karts;
/** Number of eliminated players. */
int m_eliminated_players;
/** OVerall number of players. */
int m_num_players;
bool m_faster_music_active; // true if faster music was activated
bool m_stop_music_when_dialog_open;
/** Whether highscores should be used for this kind of race.
* True by default, change to false in a child class to disable.
*/
bool m_use_highscores;
void updateHighscores (int* best_highscore_rank, int* best_finish_time,
std::string* highscore_who,
StateManager::ActivePlayer** best_player);
void resetAllKarts ();
void eliminateKart (int kart_number, bool notifyOfElimination=true);
Controller*
loadAIController (AbstractKart *kart);
virtual AbstractKart *createKart(const std::string &kart_ident, int index,
int local_player_id, int global_player_id,
RaceManager::KartType type);
/** Pointer to the track. The track is managed by world. */
Track* m_track;
/**Pointer to scripting engine */
Scripting::ScriptEngine* m_script_engine;
/** Pointer to the race GUI. The race GUI is handled by world. */
RaceGUIBase *m_race_gui;
/** The actual race gui needs to be saved when the race result gui is
displayed since it is still needed in case of a restart, and it
can't simply be created again (since it assumes that it can render
to texture without having any scene nodes, but in case of a restart
there are scene nodes). */
RaceGUIBase *m_saved_race_gui;
irr::video::SColor m_clear_color;
/** Pausing/unpausing are not done immediately, but at next udpdate. The
* use of this is when switching between screens : if we leave a screen
* that paused the game, only to go to another screen that pauses back
* the game, this mechanism prevents the game from moving on between
* the switch. */
bool m_schedule_pause;
/** Pausing/unpausing are not done immediately, but at next udpdate. The
* use of this is when switching between screens : if we leave a screen
* that paused the game, only to go to another screen that pauses back
* the game, this mechanism prevents the game from moving on between the
* switch. */
bool m_schedule_unpause;
bool m_schedule_exit_race;
bool m_schedule_tutorial;
Phase m_scheduled_pause_phase;
/** Set when the world needs to be deleted but you can't do it immediately
* because you are e.g. within World::update()
*/
bool m_self_destruct;
/** Set when the world is online and counts network players. */
bool m_is_network_world;
virtual void onGo();
/** Returns true if the race is over. Must be defined by all modes. */
virtual bool isRaceOver() = 0;
virtual void update(float dt);
virtual void createRaceGUI();
void updateTrack(float dt);
// ------------------------------------------------------------------------
/** Used for AI karts that are still racing when all player kart finished.
* Generally it should estimate the arrival time for those karts, but as
* a default (useful for battle mode and ftl races) we just use the
* current time for this (since this is a good value for karts still
* around at the end of a race, and other criteria (number of lives,
* race position) will be used to determine the final order.
*/
virtual float estimateFinishTimeForKart(AbstractKart* kart)
{return getTime(); }
public:
World();
virtual ~World();
// Static functions to access world:
// =================================
// ------------------------------------------------------------------------
/** Returns a pointer to the (singleton) world object. */
static World* getWorld() { return m_world; }
// ------------------------------------------------------------------------
/** Delete the )singleton) world object, if it exists, and sets the
* singleton pointer to NULL. It's harmless to call this if the world
* has been deleted already. */
static void deleteWorld() { delete m_world; m_world = NULL; }
// ------------------------------------------------------------------------
/** Sets the pointer to the world object. This is only used by
* the race_manager.*/
static void setWorld(World *world) {m_world = world; }
// ------------------------------------------------------------------------
// Pure virtual functions
// ======================
/** Each game mode should have a unique identifier. Override
* this method in child classes to provide it. */
virtual const std::string& getIdent() const = 0;
// ------------------------------------------------------------------------
/** Returns the number of rescue positions on a given track and game
* mode. */
virtual unsigned int getNumberOfRescuePositions() const = 0;
// ------------------------------------------------------------------------
/** Determines the rescue position index of the specified kart. */
virtual unsigned int getRescuePositionIndex(AbstractKart *kart) = 0;
// ------------------------------------------------------------------------
/** Returns the bullet transformation for the specified rescue index. */
virtual btTransform getRescueTransform(unsigned int index) const = 0;
// ------------------------------------------------------------------------
void moveKartAfterRescue(AbstractKart* kart);
// ------------------------------------------------------------------------
void moveKartTo(AbstractKart* kart, const btTransform &t);
// ------------------------------------------------------------------------
/** Called when it is needed to know whether this kind of race involves
* counting laps. */
virtual bool raceHasLaps() = 0;
// ------------------------------------------------------------------------
/** Returns the number of laps for a given kart. Only valid when
* raceHasLaps() - otherwise STK will abort. */
virtual int getKartLaps(unsigned int kart_index) const
{
assert(false); return -1; // remove compiler warning
} // getKartLaps
// ------------------------------------------------------------------------
/** Called by the code that draws the list of karts on the race GUI
* to know what needs to be drawn in the current mode. */
virtual void getKartsDisplayInfo(
std::vector<RaceGUIBase::KartIconDisplayInfo> *info)= 0;
// ------------------------------------------------------------------------
// Virtual functions
// =================
virtual void init();
virtual void terminateRace() OVERRIDE;
virtual void reset();
virtual void pause(Phase phase) OVERRIDE;
virtual void unpause() OVERRIDE;
virtual void getDefaultCollectibles(int *collectible_type,
int *amount );
virtual void endRaceEarly() { return; }
// ------------------------------------------------------------------------
/** Called to determine whether this race mode uses bonus boxes. */
virtual bool haveBonusBoxes() { return true; }
// ------------------------------------------------------------------------
/** Returns if this mode should use fast music (if available). */
virtual bool useFastMusicNearEnd() const { return true; }
// ------------------------------------------------------------------------
/** If you want to do something to karts or their graphics at the start
* of the race, override this. */
virtual void kartAdded(AbstractKart* kart, scene::ISceneNode* node) {}
// ------------------------------------------------------------------------
/** Called whenever a kart starts a new lap. Meaningless (and won't be
* called) in non-laped races.
*/
virtual void newLap(unsigned int kart_index) {}
// ------------------------------------------------------------------------
/** Called when a kart was hit by a projectile. */
virtual void kartHit(const unsigned int kart_id) {};
// ------------------------------------------------------------------------
virtual void onMouseClick(int x, int y) {};
// Other functions
// ===============
Highscores *getHighscores() const;
void schedulePause(Phase phase);
void scheduleUnpause();
void scheduleExitRace() { m_schedule_exit_race = true; }
void scheduleTutorial();
void updateWorld(float dt);
void handleExplosion(const Vec3 &xyz, AbstractKart *kart_hit,
PhysicalObject *object);
AbstractKart* getPlayerKart(unsigned int player) const;
AbstractKart* getLocalPlayerKart(unsigned int n) const;
// ------------------------------------------------------------------------
/** Returns a pointer to the race gui. */
RaceGUIBase *getRaceGUI() const { return m_race_gui;}
// ------------------------------------------------------------------------
/** Returns the number of karts in the race. */
unsigned int getNumKarts() const { return m_karts.size(); }
// ------------------------------------------------------------------------
/** Returns the kart with a given world id. */
AbstractKart *getKart(int kartId) const {
assert(kartId >= 0 && kartId < int(m_karts.size()));
return m_karts[kartId]; }
// ------------------------------------------------------------------------
/** Returns all karts. */
const KartList & getKarts() const { return m_karts; }
// ------------------------------------------------------------------------
/** Returns the number of currently active (i.e.non-elikminated) karts. */
unsigned int getCurrentNumKarts() const { return (int)m_karts.size() -
m_eliminated_karts; }
// ------------------------------------------------------------------------
/** Returns the number of currently active (i.e. non-eliminated) players.*/
unsigned int getCurrentNumPlayers() const { return m_num_players -
m_eliminated_players;}
// ------------------------------------------------------------------------
/** Returns a pointer to the physics. */
Physics *getPhysics() const { return m_physics; }
// ------------------------------------------------------------------------
/** Returns a pointer to the track. */
class ScriptEngine;
}
namespace irr
{
namespace scene { class ISceneNode; }
}
class AbortWorldUpdateException : public std::runtime_error
{
public:
AbortWorldUpdateException() : std::runtime_error("race abort") { };
};
/**
* \brief base class for all game modes
* This class is responsible for running the actual race. A world is created
* by the race manager on the start of each race (so a new world is created
* for each race of a Grand Prix). It creates the
* physics, loads the track, creates all karts, and initialises the race
* specific managers (ItemManager, ProjectilManager, highscores, ...).
* It uses the information from the race manager to get information like
* what and how many karts, track to load etc. This class does not really
* know about Grand Prixs, a GP is created
* It maintains the race clock, and updates all karts, herings etc. during
* the race.
* Special game modes (e.g. follow the leader) are currently integrated in
* this world, see e.g. updateRaceStatus where the world clock behaviour
* is handled differently to create the count down.
* \ingroup modes
*/
class World : public WorldStatus
{
public:
typedef std::vector<AbstractKart*> KartList;
private:
/** A pointer to the global world object for a race. */
static World *m_world;
protected:
#ifdef DEBUG
unsigned int m_magic_number;
#endif
/** The list of all karts. */
KartList m_karts;
RandomGenerator m_random;
Physics* m_physics;
AbstractKart* m_fastest_kart;
/** Number of eliminated karts. */
int m_eliminated_karts;
/** Number of eliminated players. */
int m_eliminated_players;
/** OVerall number of players. */
int m_num_players;
bool m_faster_music_active; // true if faster music was activated
bool m_stop_music_when_dialog_open;
/** Whether highscores should be used for this kind of race.
* True by default, change to false in a child class to disable.
*/
bool m_use_highscores;
void updateHighscores (int* best_highscore_rank, int* best_finish_time,
std::string* highscore_who,
StateManager::ActivePlayer** best_player);
void resetAllKarts ();
void eliminateKart (int kart_number, bool notifyOfElimination=true);
Controller*
loadAIController (AbstractKart *kart);
virtual AbstractKart *createKart(const std::string &kart_ident, int index,
int local_player_id, int global_player_id,
RaceManager::KartType type);
/** Pointer to the track. The track is managed by world. */
Track* m_track;
/**Pointer to scripting engine */
Scripting::ScriptEngine* m_script_engine;
/** Pointer to the race GUI. The race GUI is handled by world. */
RaceGUIBase *m_race_gui;
/** The actual race gui needs to be saved when the race result gui is
displayed since it is still needed in case of a restart, and it
can't simply be created again (since it assumes that it can render
to texture without having any scene nodes, but in case of a restart
there are scene nodes). */
RaceGUIBase *m_saved_race_gui;
irr::video::SColor m_clear_color;
/** Pausing/unpausing are not done immediately, but at next udpdate. The
* use of this is when switching between screens : if we leave a screen
* that paused the game, only to go to another screen that pauses back
* the game, this mechanism prevents the game from moving on between
* the switch. */
bool m_schedule_pause;
/** Pausing/unpausing are not done immediately, but at next udpdate. The
* use of this is when switching between screens : if we leave a screen
* that paused the game, only to go to another screen that pauses back
* the game, this mechanism prevents the game from moving on between the
* switch. */
bool m_schedule_unpause;
bool m_schedule_exit_race;
bool m_schedule_tutorial;
Phase m_scheduled_pause_phase;
/** Set when the world needs to be deleted but you can't do it immediately
* because you are e.g. within World::update()
*/
bool m_self_destruct;
/** Set when the world is online and counts network players. */
bool m_is_network_world;
virtual void onGo();
/** Returns true if the race is over. Must be defined by all modes. */
virtual bool isRaceOver() = 0;
virtual void update(float dt);
virtual void createRaceGUI();
void updateTrack(float dt);
// ------------------------------------------------------------------------
/** Used for AI karts that are still racing when all player kart finished.
* Generally it should estimate the arrival time for those karts, but as
* a default (useful for battle mode and ftl races) we just use the
* current time for this (since this is a good value for karts still
* around at the end of a race, and other criteria (number of lives,
* race position) will be used to determine the final order.
*/
virtual float estimateFinishTimeForKart(AbstractKart* kart)
{return getTime(); }
public:
World();
virtual ~World();
// Static functions to access world:
// =================================
// ------------------------------------------------------------------------
/** Returns a pointer to the (singleton) world object. */
static World* getWorld() { return m_world; }
// ------------------------------------------------------------------------
/** Delete the )singleton) world object, if it exists, and sets the
* singleton pointer to NULL. It's harmless to call this if the world
* has been deleted already. */
static void deleteWorld() { delete m_world; m_world = NULL; }
// ------------------------------------------------------------------------
/** Sets the pointer to the world object. This is only used by
* the race_manager.*/
static void setWorld(World *world) {m_world = world; }
// ------------------------------------------------------------------------
// Pure virtual functions
// ======================
/** Each game mode should have a unique identifier. Override
* this method in child classes to provide it. */
virtual const std::string& getIdent() const = 0;
// ------------------------------------------------------------------------
/** Returns the number of rescue positions on a given track and game
* mode. */
virtual unsigned int getNumberOfRescuePositions() const = 0;
// ------------------------------------------------------------------------
/** Determines the rescue position index of the specified kart. */
virtual unsigned int getRescuePositionIndex(AbstractKart *kart) = 0;
// ------------------------------------------------------------------------
/** Returns the bullet transformation for the specified rescue index. */
virtual btTransform getRescueTransform(unsigned int index) const = 0;
// ------------------------------------------------------------------------
void moveKartAfterRescue(AbstractKart* kart);
// ------------------------------------------------------------------------
/** Called when it is needed to know whether this kind of race involves
* counting laps. */
virtual bool raceHasLaps() = 0;
// ------------------------------------------------------------------------
/** Returns the number of laps for a given kart. Only valid when
* raceHasLaps() - otherwise STK will abort. */
virtual int getKartLaps(unsigned int kart_index) const
{
assert(false); return -1; // remove compiler warning
} // getKartLaps
// ------------------------------------------------------------------------
/** Called by the code that draws the list of karts on the race GUI
* to know what needs to be drawn in the current mode. */
virtual void getKartsDisplayInfo(
std::vector<RaceGUIBase::KartIconDisplayInfo> *info)= 0;
// ------------------------------------------------------------------------
// Virtual functions
// =================
virtual void init();
virtual void terminateRace() OVERRIDE;
virtual void reset();
virtual void pause(Phase phase) OVERRIDE;
virtual void unpause() OVERRIDE;
virtual void getDefaultCollectibles(int *collectible_type,
int *amount );
virtual void endRaceEarly() { return; }
// ------------------------------------------------------------------------
/** Called to determine whether this race mode uses bonus boxes. */
virtual bool haveBonusBoxes() { return true; }
// ------------------------------------------------------------------------
/** Returns if this mode should use fast music (if available). */
virtual bool useFastMusicNearEnd() const { return true; }
// ------------------------------------------------------------------------
/** If you want to do something to karts or their graphics at the start
* of the race, override this. */
virtual void kartAdded(AbstractKart* kart, scene::ISceneNode* node) {}
// ------------------------------------------------------------------------
/** Called whenever a kart starts a new lap. Meaningless (and won't be
* called) in non-laped races.
*/
virtual void newLap(unsigned int kart_index) {}
// ------------------------------------------------------------------------
/** Called when a kart was hit by a projectile. */
virtual void kartHit(const unsigned int kart_id) {};
// ------------------------------------------------------------------------
virtual void onMouseClick(int x, int y) {};
// Other functions
// ===============
Highscores *getHighscores() const;
void schedulePause(Phase phase);
void scheduleUnpause();
void scheduleExitRace() { m_schedule_exit_race = true; }
void scheduleTutorial();
void updateWorld(float dt);
void handleExplosion(const Vec3 &xyz, AbstractKart *kart_hit,
PhysicalObject *object);
AbstractKart* getPlayerKart(unsigned int player) const;
AbstractKart* getLocalPlayerKart(unsigned int n) const;
// ------------------------------------------------------------------------
/** Returns a pointer to the race gui. */
RaceGUIBase *getRaceGUI() const { return m_race_gui;}
// ------------------------------------------------------------------------
/** Returns the number of karts in the race. */
unsigned int getNumKarts() const { return m_karts.size(); }
// ------------------------------------------------------------------------
/** Returns the kart with a given world id. */
AbstractKart *getKart(int kartId) const {
assert(kartId >= 0 && kartId < int(m_karts.size()));
return m_karts[kartId]; }
// ------------------------------------------------------------------------
/** Returns all karts. */
const KartList & getKarts() const { return m_karts; }
// ------------------------------------------------------------------------
/** Returns the number of currently active (i.e.non-elikminated) karts. */
unsigned int getCurrentNumKarts() const { return (int)m_karts.size() -
m_eliminated_karts; }
// ------------------------------------------------------------------------
/** Returns the number of currently active (i.e. non-eliminated) players.*/
unsigned int getCurrentNumPlayers() const { return m_num_players -
m_eliminated_players;}
// ------------------------------------------------------------------------
/** Returns a pointer to the physics. */
Physics *getPhysics() const { return m_physics; }
// ------------------------------------------------------------------------
/** Returns a pointer to the track. */
Track *getTrack() const { return m_track; }
// ------------------------------------------------------------------------
// ------------------------------------------------------------------------
/** Returns a pointer to the Scripting Engine. */
Scripting::ScriptEngine *getScriptEngine() const { return m_script_engine; }
//------------------------------------------------------------------------
bool isFogEnabled() const;
// ------------------------------------------------------------------------
/** The code that draws the timer should call this first to know
* whether the game mode wants a timer drawn. */
virtual bool shouldDrawTimer() const
{ return isRacePhase() && getClockMode() != CLOCK_NONE; }
// ------------------------------------------------------------------------
/** \return whether this world can generate/have highscores */
bool useHighScores() const { return m_use_highscores; }
// ------------------------------------------------------------------------
/** Returns the color to clear the back buffer. */
const irr::video::SColor& getClearColor() const { return m_clear_color; }
// ------------------------------------------------------------------------
/** Sets the color to use when clearing the back buffer. */
void setClearbackBufferColor(irr::video::SColor color)
{
m_clear_color = color;
}
// ------------------------------------------------------------------------
/** Override if you want to know when a kart presses fire */
virtual void onFirePressed(Controller* who) {}
// ------------------------------------------------------------------------
/** Whether to compute checkline requirements for each world on the
* quadgraph. Override to change value. */
virtual bool useChecklineRequirements() const { return false; }
// ------------------------------------------------------------------------
void delayedSelfDestruct();
// ------------------------------------------------------------------------
virtual void escapePressed();
/** Set the network mode (true if networked) */
void setNetworkWorld(bool is_networked) { m_is_network_world = is_networked; }
bool isNetworkWorld() const { return m_is_network_world; }
}; // World
#endif
/* EOF */
Scripting::ScriptEngine *getScriptEngine()
const { return m_script_engine; }
//-------------------------------------------------------------------------
bool isFogEnabled() const;
// ------------------------------------------------------------------------
void moveKartTo(AbstractKart* kart, const btTransform &t);
// ------------------------------------------------------------------------
/** The code that draws the timer should call this first to know
* whether the game mode wants a timer drawn. */
virtual bool shouldDrawTimer() const
{ return isRacePhase() && getClockMode() != CLOCK_NONE; }
// ------------------------------------------------------------------------
/** \return whether this world can generate/have highscores */
bool useHighScores() const { return m_use_highscores; }
// ------------------------------------------------------------------------
/** Returns the color to clear the back buffer. */
const irr::video::SColor& getClearColor() const { return m_clear_color; }
// ------------------------------------------------------------------------
/** Sets the color to use when clearing the back buffer. */
void setClearbackBufferColor(irr::video::SColor color)
{
m_clear_color = color;
}
// ------------------------------------------------------------------------
/** Override if you want to know when a kart presses fire */
virtual void onFirePressed(Controller* who) {}
// ------------------------------------------------------------------------
/** Whether to compute checkline requirements for each world on the
* quadgraph. Override to change value. */
virtual bool useChecklineRequirements() const { return false; }
// ------------------------------------------------------------------------
void delayedSelfDestruct();
// ------------------------------------------------------------------------
virtual void escapePressed();
/** Set the network mode (true if networked) */
void setNetworkWorld(bool is_networked) { m_is_network_world = is_networked; }
bool isNetworkWorld() const { return m_is_network_world; }
}; // World
#endif
/* EOF */

View File

@ -322,7 +322,7 @@ namespace Online
// Check if we are asked to abort the download. If so, signal this
// back to libcurl by returning a non-zero status.
if( (request_manager->getAbort() || request->isCancelled()) &&
if( (request_manager->getAbort() || request->isCancelled()) &&
request->isAbortable() )
{
// Indicates to abort the current download, which means that this

View File

@ -196,7 +196,7 @@ namespace Online
// Even if no achievements were sent, we have to call sync
// in order to upload local achievements to the server
input->get("achieved", &achieved_string);
std::vector<uint32_t> achieved_ids =
std::vector<uint32_t> achieved_ids =
StringUtils::splitToUInt(achieved_string, ' ');
PlayerManager::getCurrentAchievementsStatus()->sync(achieved_ids);
m_profile->fetchFriends();

View File

@ -220,7 +220,7 @@ namespace Online
} // while
// Signal that the request manager can now be deleted.
// We signal this even before cleaning up memory, since there's no
// We signal this even before cleaning up memory, since there's no
// need to keep the user waiting for STK to exit.
me->setCanBeDeleted();

View File

@ -67,7 +67,7 @@ namespace Online
* manager which might be accessed if a download just finished before the
* abort). On executing the quit request, the request manager will set
* a flag that it is ready to be deleted (using the CanBeDeleted class).
* The main thread will wait for a certain amount of time for the
* The main thread will wait for a certain amount of time for the
* RequestManager to be ready to be deleted (i.e. the sign-out and quit
* request have been processes), before deleting the RequestManager.
* Typically the RequestManager will finish while the rest of stk is

View File

@ -85,7 +85,7 @@ Physics::~Physics()
// ----------------------------------------------------------------------------
/** Adds a kart to the physics engine.
* This adds the rigid body and the vehicle but only if the kart is not
* This adds the rigid body and the vehicle but only if the kart is not
* already in the physics world.
* \param kart The kart to add.
* \param vehicle The raycast vehicle object.

View File

@ -304,7 +304,7 @@ bool TriangleMesh::castRay(const btVector3 &from, const btVector3 &to,
btCollisionWorld::ClosestRayResultCallback result(from, to);
/** A special ray result class that stores the index of the triangle
/** A special ray result class that stores the index of the triangle
* that was hit. */
class MaterialRayResult : public btCollisionWorld::ClosestRayResultCallback
{
@ -351,7 +351,7 @@ bool TriangleMesh::castRay(const btVector3 &from, const btVector3 &to,
// the normal of the triangle interpolate the normal at the
// hit position based on the three normals of the triangle.
if(interpolate_normal)
*normal = getInterpolatedNormal(ray_callback.m_index,
*normal = getInterpolatedNormal(ray_callback.m_index,
ray_callback.m_hitPointWorld);
else
*normal = ray_callback.m_hitNormalWorld;

View File

@ -126,11 +126,11 @@ void GrandPrixData::changeReverse(const RandomGPInfoDialog::REVERSED use_reverse
m_reversed[i] = false;
else if (use_reverse == RandomGPInfoDialog::MIXED)
if (track_manager->getTrack(m_tracks[i])->reverseAvailable())
m_reversed[i] = (rand() % 2!=0);
m_reversed[i] = (rand() % 2 != 0);
else
m_reversed[i] = false;
else // all reversed
m_reversed[i] = true;
m_reversed[i] = track_manager->getTrack(m_tracks[i])->reverseAvailable();
}
}

View File

@ -452,7 +452,7 @@ bool UserInfoDialog::onEscapePressed()
void UserInfoDialog::onUpdate(float dt)
{
if(m_processing)
if(m_processing)
m_info_widget->setText(StringUtils::loadingDots(_("Processing")), false);
//If we want to open the registration dialog, we need to close this one first

View File

@ -80,6 +80,14 @@ void MainMenuScreen::loadedFromFile()
{
LabelWidget* w = getWidget<LabelWidget>("info_addons");
w->setScrollSpeed(15);
#if DEBUG_MENU_ITEM != 1
RibbonWidget* rw = getWidget<RibbonWidget>("menu_bottomrow");
rw->removeChildNamed("test_gpwin");
rw->removeChildNamed("test_gplose");
rw->removeChildNamed("test_unlocked");
rw->removeChildNamed("test_unlocked2");
#endif
} // loadedFromFile
// ----------------------------------------------------------------------------
@ -230,14 +238,12 @@ void MainMenuScreen::eventCallback(Widget* widget, const std::string& name,
*/
#if DEBUG_MENU_ITEM
if (selection == "gpEditor")
if (selection == "test_gpwin")
{
// The DEBUG item
StoryModeStatus* sms = PlayerManager::getCurrentPlayer()->getStoryModeStatus();
sms->unlockFeature(const_cast<ChallengeStatus*>(sms->getChallengeStatus("gp1")),
RaceManager::DIFFICULTY_HARD);
// GP WIN
StateManager::get()->enterGameState();
race_manager->setMinorMode(RaceManager::MINOR_MODE_CUTSCENE);
race_manager->setNumKarts(0);
@ -248,9 +254,9 @@ void MainMenuScreen::eventCallback(Widget* widget, const std::string& name,
StateManager::get()->pushScreen(scene);
const std::string winners[] = { "elephpant", "nolok", "pidgin" };
scene->setKarts(winners);
// GP Lose
/*
}
else if (selection == "test_gplose")
{
StateManager::get()->enterGameState();
race_manager->setMinorMode(RaceManager::MINOR_MODE_CUTSCENE);
race_manager->setNumKarts(0);
@ -265,10 +271,13 @@ void MainMenuScreen::eventCallback(Widget* widget, const std::string& name,
//losers.push_back("wilber");
//losers.push_back("tux");
scene->setKarts(losers);
*/
/*
// FEATURE UNLOCKED
}
else if (selection == "test_unlocked" || selection == "test_unlocked2")
{
StoryModeStatus* sms = PlayerManager::getCurrentPlayer()->getStoryModeStatus();
sms->unlockFeature(const_cast<ChallengeStatus*>(sms->getChallengeStatus("gp1")),
RaceManager::DIFFICULTY_HARD);
StateManager::get()->enterGameState();
race_manager->setMinorMode(RaceManager::MINOR_MODE_CUTSCENE);
race_manager->setNumKarts(0);
@ -284,12 +293,8 @@ void MainMenuScreen::eventCallback(Widget* widget, const std::string& name,
((CutsceneWorld*)World::getWorld())->setParts(parts);
scene->addTrophy(RaceManager::DIFFICULTY_EASY);
//StateManager::get()->pushScreen(scene);
static int i = 1;
i++;
if (i % 2 == 0)
if (selection == "test_unlocked")
{
// the passed kart will not be modified, that's why I allow myself
// to use const_cast
@ -299,9 +304,10 @@ void MainMenuScreen::eventCallback(Widget* widget, const std::string& name,
),
L"Unlocked"
);
scene->addUnlockedTrack(track_manager->getTrack("lighthouse"));
StateManager::get()->pushScreen(scene);
}
else if (i % 2 == 1)
else if (selection == "test_unlocked2")
{
std::vector<video::ITexture*> textures;
textures.push_back(irr_driver->getTexture(
@ -321,7 +327,6 @@ void MainMenuScreen::eventCallback(Widget* widget, const std::string& name,
StateManager::get()->pushScreen(scene);
}
*/
}
else
#endif

View File

@ -160,8 +160,8 @@ void OnlineProfileAchievements::onUpdate(float delta)
if (!m_visiting_profile->isReady())
{
// This will display an increasing number of dots while waiting.
m_achievements_list_widget->renameItem("loading",
StringUtils::loadingDots(_("Fetching achievements")));
m_achievements_list_widget->renameItem("loading",
StringUtils::loadingDots(_("Fetching achievements")));
return;
}

View File

@ -84,7 +84,7 @@ void OnlineProfileFriends::init()
m_visiting_profile->fetchFriends();
m_waiting_for_friends = true;
m_friends_list_widget->clear();
m_friends_list_widget->addItem("loading",
m_friends_list_widget->addItem("loading",
StringUtils::loadingDots(_("Fetching friends")));
} // init

View File

@ -275,7 +275,7 @@ void OnlineUserSearch::onUpdate(float dt)
}
else
{
m_user_list_widget->renameItem("loading",
m_user_list_widget->renameItem("loading",
StringUtils::loadingDots(_("Searching")) );
}
}

View File

@ -84,7 +84,7 @@ private:
/** Height of the digit font. */
int m_font_height;
/** Animation state: none, getting smaller (old value),
/** Animation state: none, getting smaller (old value),
* getting bigger (new number). */
enum AnimationState {AS_NONE, AS_SMALLER, AS_BIGGER};
std::vector<AnimationState> m_animation_states;

View File

@ -89,7 +89,7 @@ void RegisterScreen::init()
getWidget<CheckBoxWidget>("online")->setVisible(true);
getWidget<LabelWidget>("label_online")->setVisible(true);
onDialogClose();
bool online = UserConfigParams::m_internet_status
bool online = UserConfigParams::m_internet_status
!= Online::RequestManager::IPERM_NOT_ALLOWED;
getWidget<CheckBoxWidget>("online")->setState(online);
makeEntryFieldsVisible(online);
@ -108,7 +108,7 @@ void RegisterScreen::setRename(PlayerProfile *player)
*/
void RegisterScreen::onDialogClose()
{
bool online = UserConfigParams::m_internet_status
bool online = UserConfigParams::m_internet_status
!= Online::RequestManager::IPERM_NOT_ALLOWED;
getWidget<CheckBoxWidget>("online")->setState(online);
makeEntryFieldsVisible(online);

View File

@ -1005,6 +1005,7 @@ void QuadGraph::makeMiniMap(const core::dimension2du &dimension,
m_node->setName("minimap-mesh");
#endif
m_node->setAutomaticCulling(0);
m_node->setMaterialFlag(video::EMF_LIGHTING, false);
// Add the camera:

View File

@ -57,7 +57,7 @@ void TerrainInfo::update(const Vec3 &from)
to.setY(-10000.0f);
const TriangleMesh &tm = World::getWorld()->getTrack()->getTriangleMesh();
tm.castRay(from, to, &m_hit_point, &m_material, &m_normal,
tm.castRay(from, to, &m_hit_point, &m_material, &m_normal,
/*interpolate*/false);
} // update
//-----------------------------------------------------------------------------

View File

@ -269,6 +269,7 @@ void Track::cleanup()
{
QuadGraph::destroy();
ItemManager::destroy();
resetVAO();
ParticleKindManager::get()->cleanUpTrackSpecificGfx();
// Clear reminder of transformed textures
@ -707,6 +708,8 @@ void Track::createPhysicsModel(unsigned int main_track_count)
} // createPhysicsModel
// -----------------------------------------------------------------------------
/** Convert the graohics track into its physics equivalents.
* \param mesh The mesh to convert.
* \param node The scene node.
@ -954,9 +957,7 @@ bool Track::loadMainTrack(const XMLNode &root)
merged_mesh->addMesh(mesh);
merged_mesh->finalize();
scene::IMeshManipulator* manip = irr_driver->getVideoDriver()->getMeshManipulator();
// TODO: memory leak?
scene::IMesh* tangent_mesh = manip->createMeshWithTangents(merged_mesh);
scene::IMesh* tangent_mesh = MeshTools::createMeshWithTangents(merged_mesh, &MeshTools::isNormalMap);
adjustForFog(tangent_mesh, NULL);
@ -1165,8 +1166,6 @@ bool Track::loadMainTrack(const XMLNode &root)
if (tangent)
{
scene::IMeshManipulator* manip = irr_driver->getVideoDriver()->getMeshManipulator();
scene::IMesh* original_mesh = irr_driver->getMesh(full_path);
if (std::find(m_detached_cached_meshes.begin(),
@ -1188,7 +1187,7 @@ bool Track::loadMainTrack(const XMLNode &root)
scene_node->remove();
irr_driver->grabAllTextures(original_mesh);
scene::IMesh* mesh = manip->createMeshWithTangents(original_mesh);
scene::IMesh* mesh = MeshTools::createMeshWithTangents(original_mesh, &MeshTools::isNormalMap);
mesh->grab();
irr_driver->grabAllTextures(mesh);

View File

@ -224,6 +224,8 @@ void TrackObject::init(const XMLNode &xml_node, scene::ISceneNode* parent,
if (xml_node.get("displacing", &displacing) && displacing && glownode)
{
irr_driver->addDisplacingNode(glownode);
glownode->setVisible(false);
glownode->updateAbsolutePosition();
}
}

View File

@ -24,6 +24,7 @@
#include "config/user_config.hpp"
#include "graphics/irr_driver.hpp"
#include "graphics/material_manager.hpp"
#include "graphics/mesh_tools.hpp"
#include "graphics/particle_emitter.hpp"
#include "graphics/particle_kind_manager.hpp"
#include "graphics/stkinstancedscenenode.hpp"
@ -267,10 +268,8 @@ TrackObjectPresentationMesh::TrackObjectPresentationMesh(const XMLNode& xml_node
if (tangent)
{
scene::IMeshManipulator* manip = irr_driver->getVideoDriver()->getMeshManipulator();
// TODO: perhaps the original mesh leaks here?
m_mesh = manip->createMeshWithTangents(m_mesh);
}
m_mesh = MeshTools::createMeshWithTangents(m_mesh, &MeshTools::isNormalMap);
}
}
if (!m_mesh)

View File

@ -54,9 +54,9 @@ public:
Log::verbose("Thread", "Start waiting %lf", start);
while(1)
{
if(m_can_be_deleted.getAtomic())
if(m_can_be_deleted.getAtomic())
{
Log::verbose("Thread",
Log::verbose("Thread",
"Waited %lf seconds for thread to become deleteable.",
StkTime::getRealTime()-start);
Log::verbose("Thread", "Stop waiting %lf", StkTime::getRealTime());
@ -67,7 +67,7 @@ public:
{
Log::verbose("Thread", "Stop waiting %lf", StkTime::getRealTime());
Log::verbose("Thread", "Waited for more than %f seconds for "
"thread to become deleteable",
"thread to become deleteable",
waiting_time);
return false;
}
@ -76,4 +76,4 @@ public:
// ------------------------------------------------------------------------
}; // CanBeDeleted
#endif
#endif

View File

@ -531,9 +531,9 @@ namespace StringUtils
*/
irr::core::stringw loadingDots(float interval, int max_dots)
{
int nr_dots = int(floor(StkTime::getRealTime() / interval))
int nr_dots = int(floor(StkTime::getRealTime() / interval))
% (max_dots + 1);
return irr::core::stringw((std::string(nr_dots, '.') +
return irr::core::stringw((std::string(nr_dots, '.') +
std::string(max_dots - nr_dots, ' ')).c_str());
} // loadingDots