Merge branch 'Instancing'

This commit is contained in:
vlj
2014-03-29 01:22:57 +01:00
24 changed files with 767 additions and 84 deletions

View File

@@ -0,0 +1,26 @@
uniform vec3 windDir;
uniform mat4 ViewProjectionMatrix;
uniform mat4 InverseViewMatrix;
in vec3 Origin;
in vec3 Orientation;
in vec3 Position;
in vec3 Normal;
in vec2 Texcoord;
in vec4 Color;
out vec3 nor;
out vec2 uv;
mat4 getWorldMatrix(vec3 translation, vec3 rotation);
mat4 getInverseWorldMatrix(vec3 translation, vec3 rotation);
void main()
{
mat4 ModelMatrix = getWorldMatrix(Origin + windDir * Color.r, Orientation);
mat4 TransposeInverseModelView = transpose(getInverseWorldMatrix(Origin + windDir * Color.r, Orientation) * InverseViewMatrix);
gl_Position = ViewProjectionMatrix * ModelMatrix * vec4(Position, 1.);
nor = (TransposeInverseModelView * vec4(Normal, 0.)).xyz;
uv = Texcoord;
}

View File

@@ -0,0 +1,24 @@
uniform mat4 ViewProjectionMatrix;
uniform mat4 InverseViewMatrix;
in vec3 Origin;
in vec3 Orientation;
in vec3 Position;
in vec3 Normal;
in vec2 Texcoord;
out vec3 nor;
out vec2 uv;
mat4 getWorldMatrix(vec3 translation, vec3 rotation);
mat4 getInverseWorldMatrix(vec3 translation, vec3 rotation);
void main(void)
{
mat4 ModelMatrix = getWorldMatrix(Origin, Orientation);
mat4 TransposeInverseModelView = transpose(getInverseWorldMatrix(Origin, Orientation) * InverseViewMatrix);
gl_Position = ViewProjectionMatrix * ModelMatrix * vec4(Position, 1.);
nor = (TransposeInverseModelView * vec4(Normal, 0.)).xyz;
uv = Texcoord;
}

View File

@@ -0,0 +1,36 @@
mat4 getMatrixFromRotation(vec3 rotation)
{
// from irrlicht
float cr = cos( rotation.z );
float sr = sin( rotation.z );
float cp = cos( rotation.x );
float sp = sin( rotation.x );
float cy = cos( rotation.y );
float sy = sin( rotation.y );
float srsp = sr*sp;
float crsp = cr*sp;
return mat4(
vec4(cp * cy, srsp * cy - cr * sy, crsp * cy + sr * sy, 0.),
vec4(cp * sy, srsp * sy + cr * cy, crsp * sy - sr * cy, 0.),
vec4(-sp, sr * cp, cr * cp, 0.),
vec4(0., 0., 0., 1.));
}
mat4 getWorldMatrix(vec3 translation, vec3 rotation)
{
mat4 result = getMatrixFromRotation(rotation);
// translation
result[3].xyz += translation;
return result;
}
mat4 getInverseWorldMatrix(vec3 translation, vec3 rotation)
{
mat4 result = transpose(getMatrixFromRotation(rotation));
// FIXME: it's wrong but the fourth column is not used
result[3].xyz -= translation;
return result;
}

View File

@@ -63,6 +63,7 @@ src/graphics/slip_stream.cpp
src/graphics/stars.cpp
src/graphics/stkanimatedmesh.cpp
src/graphics/stkbillboard.cpp
src/graphics/stkinstancedscenenode.cpp
src/graphics/stkmesh.cpp
src/graphics/stkmeshscenenode.cpp
src/graphics/sun.cpp
@@ -304,7 +305,7 @@ src/tracks/check_manager.cpp
src/tracks/check_sphere.cpp
src/tracks/check_structure.cpp
src/tracks/graph_node.cpp
src/tracks/lod_node_loader.cpp
src/tracks/model_definition_loader.cpp
src/tracks/quad.cpp
src/tracks/quad_graph.cpp
src/tracks/quad_set.cpp
@@ -399,6 +400,7 @@ src/graphics/slip_stream.hpp
src/graphics/stars.hpp
src/graphics/stkanimatedmesh.hpp
src/graphics/stkbillboard.hpp
src/graphics/stkinstancedscenenode.hpp
src/graphics/stkmesh.hpp
src/graphics/stkmeshscenenode.hpp
src/graphics/sun.hpp
@@ -646,7 +648,7 @@ src/tracks/check_manager.hpp
src/tracks/check_sphere.hpp
src/tracks/check_structure.hpp
src/tracks/graph_node.hpp
src/tracks/lod_node_loader.hpp
src/tracks/model_definition_loader.hpp
src/tracks/quad.hpp
src/tracks/quad_graph.hpp
src/tracks/quad_set.hpp

View File

@@ -46,6 +46,7 @@ PFNGLGETATTRIBLOCATIONPROC glGetAttribLocation;
PFNGLBLENDEQUATIONPROC glBlendEquation;
PFNGLVERTEXATTRIBDIVISORPROC glVertexAttribDivisor;
PFNGLDRAWARRAYSINSTANCEDPROC glDrawArraysInstanced;
PFNGLDRAWELEMENTSINSTANCEDPROC glDrawElementsInstanced;
PFNGLDELETEBUFFERSPROC glDeleteBuffers;
PFNGLGENVERTEXARRAYSPROC glGenVertexArrays;
PFNGLBINDVERTEXARRAYPROC glBindVertexArray;
@@ -183,6 +184,7 @@ void initGL()
glBlendEquation = (PFNGLBLENDEQUATIONPROC)IRR_OGL_LOAD_EXTENSION("glBlendEquation");
glVertexAttribDivisor = (PFNGLVERTEXATTRIBDIVISORPROC)IRR_OGL_LOAD_EXTENSION("glVertexAttribDivisor");
glDrawArraysInstanced = (PFNGLDRAWARRAYSINSTANCEDPROC)IRR_OGL_LOAD_EXTENSION("glDrawArraysInstanced");
glDrawElementsInstanced = (PFNGLDRAWELEMENTSINSTANCEDPROC)IRR_OGL_LOAD_EXTENSION("glDrawElementsInstanced");
glDeleteBuffers = (PFNGLDELETEBUFFERSPROC)IRR_OGL_LOAD_EXTENSION("glDeleteBuffers");
glGenVertexArrays = (PFNGLGENVERTEXARRAYSPROC)IRR_OGL_LOAD_EXTENSION("glGenVertexArrays");
glBindVertexArray = (PFNGLBINDVERTEXARRAYPROC)IRR_OGL_LOAD_EXTENSION("glBindVertexArray");

View File

@@ -64,6 +64,7 @@ extern PFNGLGETATTRIBLOCATIONPROC glGetAttribLocation;
extern PFNGLBLENDEQUATIONPROC glBlendEquation;
extern PFNGLVERTEXATTRIBDIVISORPROC glVertexAttribDivisor;
extern PFNGLDRAWARRAYSINSTANCEDPROC glDrawArraysInstanced;
extern PFNGLDRAWELEMENTSINSTANCEDPROC glDrawElementsInstanced;
extern PFNGLDELETEBUFFERSPROC glDeleteBuffers;
extern PFNGLGENVERTEXARRAYSPROC glGenVertexArrays;
extern PFNGLBINDVERTEXARRAYPROC glBindVertexArray;

View File

@@ -36,6 +36,7 @@
#include "graphics/shaders.hpp"
#include "graphics/shadow_importance.hpp"
#include "graphics/stkmeshscenenode.hpp"
#include "graphics/stkinstancedscenenode.hpp"
#include "graphics/wind.hpp"
#include "io/file_manager.hpp"
#include "items/item.hpp"
@@ -50,6 +51,8 @@
#include <algorithm>
STKInstancedSceneNode *InstancedBox = 0;
void IrrDriver::renderGLSL(float dt)
{
World *world = World::getWorld(); // Never NULL.
@@ -203,7 +206,6 @@ void IrrDriver::renderGLSL(float dt)
irr_driver->setProjMatrix(irr_driver->getVideoDriver()->getTransform(video::ETS_PROJECTION));
irr_driver->setViewMatrix(irr_driver->getVideoDriver()->getTransform(video::ETS_VIEW));
irr_driver->genProjViewMatrix();
PROFILER_POP_CPU_MARKER();
// Todo : reenable glow and shadows
@@ -245,7 +247,6 @@ void IrrDriver::renderGLSL(float dt)
glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask);
}
m_scene_manager->drawAll(m_renderpass);
PROFILER_POP_CPU_MARKER();
if (World::getWorld()->getTrack()->isFogEnabled())

View File

@@ -318,7 +318,11 @@ void Shaders::loadShaders()
MeshShader::NormalMapShader::init();
MeshShader::ObjectPass1Shader::init();
MeshShader::ObjectRefPass1Shader::init();
MeshShader::InstancedObjectPass1Shader::init();
MeshShader::InstancedGrassPass1Shader::init();
MeshShader::ObjectPass2Shader::init();
MeshShader::InstancedObjectPass2Shader::init();
MeshShader::InstancedGrassPass2Shader::init();
MeshShader::DetailledObjectPass2Shader::init();
MeshShader::ObjectRimLimitShader::init();
MeshShader::UntexturedObjectShader::init();
@@ -501,6 +505,72 @@ namespace MeshShader
glUniform1i(uniform_normalMap, TU_normalMap);
}
GLuint InstancedObjectPass1Shader::Program;
GLuint InstancedObjectPass1Shader::attrib_position;
GLuint InstancedObjectPass1Shader::attrib_normal;
GLuint InstancedObjectPass1Shader::attrib_origin;
GLuint InstancedObjectPass1Shader::uniform_MP;
GLuint InstancedObjectPass1Shader::uniform_VM;
void InstancedObjectPass1Shader::init()
{
Program = LoadProgram(
GL_VERTEX_SHADER, file_manager->getAsset("shaders/utils/getworldmatrix.vert").c_str(),
GL_VERTEX_SHADER, file_manager->getAsset("shaders/instanced_object_pass.vert").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/utils/encode_normal.frag").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/object_pass1.frag").c_str());
attrib_origin = glGetAttribLocation(Program, "Origin");
attrib_position = glGetAttribLocation(Program, "Position");
attrib_normal = glGetAttribLocation(Program, "Normal");
uniform_MP = glGetUniformLocation(Program, "ViewProjectionMatrix");
uniform_VM = glGetUniformLocation(Program, "InverseViewMatrix");
}
void InstancedObjectPass1Shader::setUniforms(const core::matrix4 &ModelViewProjectionMatrix, const core::matrix4 &ViewMatrix)
{
glUniformMatrix4fv(uniform_MP, 1, GL_FALSE, ModelViewProjectionMatrix.pointer());
glUniformMatrix4fv(uniform_VM, 1, GL_FALSE, ViewMatrix.pointer());
}
GLuint InstancedGrassPass1Shader::Program;
GLuint InstancedGrassPass1Shader::attrib_position;
GLuint InstancedGrassPass1Shader::attrib_normal;
GLuint InstancedGrassPass1Shader::attrib_origin;
GLuint InstancedGrassPass1Shader::attrib_orientation;
GLuint InstancedGrassPass1Shader::attrib_texcoord;
GLuint InstancedGrassPass1Shader::attrib_color;
GLuint InstancedGrassPass1Shader::uniform_MP;
GLuint InstancedGrassPass1Shader::uniform_IVM;
GLuint InstancedGrassPass1Shader::uniform_windDir;
GLuint InstancedGrassPass1Shader::uniform_tex;
void InstancedGrassPass1Shader::init()
{
Program = LoadProgram(
GL_VERTEX_SHADER, file_manager->getAsset("shaders/utils/getworldmatrix.vert").c_str(),
GL_VERTEX_SHADER, file_manager->getAsset("shaders/instanced_grass.vert").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/utils/encode_normal.frag").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/objectref_pass1.frag").c_str());
attrib_origin = glGetAttribLocation(Program, "Origin");
attrib_orientation = glGetAttribLocation(Program, "Orientation");
attrib_position = glGetAttribLocation(Program, "Position");
attrib_normal = glGetAttribLocation(Program, "Normal");
attrib_color = glGetAttribLocation(Program, "Color");
attrib_texcoord = glGetAttribLocation(Program, "Texcoord");
uniform_MP = glGetUniformLocation(Program, "ViewProjectionMatrix");
uniform_IVM = glGetUniformLocation(Program, "InverseViewMatrix");
uniform_windDir = glGetUniformLocation(Program, "windDir");
uniform_tex = glGetUniformLocation(Program, "tex");
}
void InstancedGrassPass1Shader::setUniforms(const core::matrix4 &ModelViewProjectionMatrix, const core::matrix4 &InverseViewMatrix, const core::vector3df &windDir, unsigned TU_tex)
{
glUniformMatrix4fv(uniform_MP, 1, GL_FALSE, ModelViewProjectionMatrix.pointer());
glUniformMatrix4fv(uniform_IVM, 1, GL_FALSE, InverseViewMatrix.pointer());
glUniform3f(uniform_windDir, windDir.X, windDir.Y, windDir.Z);
glUniform1i(uniform_tex, TU_tex);
}
// Solid Lit pass shaders
GLuint ObjectPass2Shader::Program;
@@ -547,6 +617,53 @@ namespace MeshShader
glUniform3f(uniform_ambient, s.r, s.g, s.b);
}
GLuint InstancedObjectPass2Shader::Program;
GLuint InstancedObjectPass2Shader::attrib_position;
GLuint InstancedObjectPass2Shader::attrib_texcoord;
GLuint InstancedObjectPass2Shader::attrib_origin;
GLuint InstancedObjectPass2Shader::uniform_VP;
GLuint InstancedObjectPass2Shader::uniform_TM;
GLuint InstancedObjectPass2Shader::uniform_screen;
GLuint InstancedObjectPass2Shader::uniform_ambient;
GLuint InstancedObjectPass2Shader::TU_Albedo;
void InstancedObjectPass2Shader::init()
{
Program = LoadProgram(
GL_VERTEX_SHADER, file_manager->getAsset("shaders/utils/getworldmatrix.vert").c_str(),
GL_VERTEX_SHADER, file_manager->getAsset("shaders/instanced_object_pass.vert").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/utils/getLightFactor.frag").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/object_pass2.frag").c_str());
attrib_position = glGetAttribLocation(Program, "Position");
attrib_texcoord = glGetAttribLocation(Program, "Texcoord");
attrib_origin = glGetAttribLocation(Program, "Origin");
uniform_VP = glGetUniformLocation(Program, "ViewProjectionMatrix");
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_screen = glGetUniformLocation(Program, "screen");
uniform_ambient = glGetUniformLocation(Program, "ambient");
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 InstancedObjectPass2Shader::setUniforms(const core::matrix4 &ViewProjectionMatrix, const core::matrix4 &TextureMatrix)
{
glUniformMatrix4fv(uniform_VP, 1, GL_FALSE, ViewProjectionMatrix.pointer());
glUniformMatrix4fv(uniform_TM, 1, GL_FALSE, TextureMatrix.pointer());
glUniform2f(uniform_screen, UserConfigParams::m_width, UserConfigParams::m_height);
const video::SColorf s = irr_driver->getSceneManager()->getAmbientLight();
glUniform3f(uniform_ambient, s.r, s.g, s.b);
}
GLuint DetailledObjectPass2Shader::Program;
GLuint DetailledObjectPass2Shader::attrib_position;
GLuint DetailledObjectPass2Shader::attrib_texcoord;
@@ -798,6 +915,57 @@ namespace MeshShader
glUniform3f(uniform_windDir, windDirection.X, windDirection.Y, windDirection.Z);
}
GLuint InstancedGrassPass2Shader::Program;
GLuint InstancedGrassPass2Shader::attrib_position;
GLuint InstancedGrassPass2Shader::attrib_texcoord;
GLuint InstancedGrassPass2Shader::attrib_color;
GLuint InstancedGrassPass2Shader::attrib_origin;
GLuint InstancedGrassPass2Shader::attrib_orientation;
GLuint InstancedGrassPass2Shader::uniform_VP;
GLuint InstancedGrassPass2Shader::uniform_screen;
GLuint InstancedGrassPass2Shader::uniform_ambient;
GLuint InstancedGrassPass2Shader::uniform_windDir;
GLuint InstancedGrassPass2Shader::TU_Albedo;
void InstancedGrassPass2Shader::init()
{
Program = LoadProgram(
GL_VERTEX_SHADER, file_manager->getAsset("shaders/utils/getworldmatrix.vert").c_str(),
GL_VERTEX_SHADER, file_manager->getAsset("shaders/instanced_grass.vert").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/utils/getLightFactor.frag").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/objectref_pass2.frag").c_str());
attrib_position = glGetAttribLocation(Program, "Position");
attrib_texcoord = glGetAttribLocation(Program, "Texcoord");
attrib_color = glGetAttribLocation(Program, "Color");
attrib_origin = glGetAttribLocation(Program, "Origin");
attrib_orientation = glGetAttribLocation(Program, "Orientation");
uniform_VP = glGetUniformLocation(Program, "ViewProjectionMatrix");
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_screen = glGetUniformLocation(Program, "screen");
uniform_ambient = glGetUniformLocation(Program, "ambient");
uniform_windDir = glGetUniformLocation(Program, "windDir");
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 InstancedGrassPass2Shader::setUniforms(const core::matrix4 &ModelViewProjectionMatrix, const core::vector3df &windDirection)
{
glUniformMatrix4fv(uniform_VP, 1, GL_FALSE, ModelViewProjectionMatrix.pointer());
glUniform2f(uniform_screen, UserConfigParams::m_width, UserConfigParams::m_height);
const video::SColorf s = irr_driver->getSceneManager()->getAmbientLight();
glUniform3f(uniform_ambient, s.r, s.g, s.b);
glUniform3f(uniform_windDir, windDirection.X, windDirection.Y, windDirection.Z);
}
GLuint SphereMapShader::Program;
GLuint SphereMapShader::attrib_position;
GLuint SphereMapShader::attrib_normal;

View File

@@ -77,6 +77,28 @@ public:
static void setUniforms(const core::matrix4 &ModelViewProjectionMatrix, const core::matrix4 &TransposeInverseModelView, unsigned TU_normalMap);
};
class InstancedObjectPass1Shader
{
public:
static GLuint Program;
static GLuint attrib_position, attrib_normal, attrib_origin;
static GLuint uniform_MP, uniform_VM;
static void init();
static void setUniforms(const core::matrix4 &ViewProjectionMatrix, const core::matrix4 &ViewMatrix);
};
class InstancedGrassPass1Shader
{
public:
static GLuint Program;
static GLuint attrib_position, attrib_normal, attrib_origin, attrib_orientation, attrib_color, attrib_texcoord;
static GLuint uniform_MP, uniform_IVM, uniform_windDir, uniform_tex;
static void init();
static void setUniforms(const core::matrix4 &ViewProjectionMatrix, const core::matrix4 &InverseViewMatrix, const core::vector3df &windDir, unsigned TU_tex);
};
class ObjectPass2Shader
{
public:
@@ -89,6 +111,18 @@ public:
static void setUniforms(const core::matrix4 &ModelViewProjectionMatrix, const core::matrix4 &TextureMatrix);
};
class InstancedObjectPass2Shader
{
public:
static GLuint Program;
static GLuint attrib_position, attrib_texcoord, attrib_origin;
static GLuint uniform_VP, uniform_TM, uniform_screen, uniform_ambient;
static GLuint TU_Albedo;
static void init();
static void setUniforms(const core::matrix4 &ViewProjectionMatrix, const core::matrix4 &TextureMatrix);
};
class DetailledObjectPass2Shader
{
public:
@@ -160,6 +194,18 @@ public:
static void setUniforms(const core::matrix4 &ModelViewProjectionMatrix, const core::vector3df &windDirection);
};
class InstancedGrassPass2Shader
{
public:
static GLuint Program;
static GLuint attrib_position, attrib_texcoord, attrib_color, attrib_origin, attrib_orientation;
static GLuint uniform_VP, uniform_TM, uniform_screen, uniform_ambient, uniform_windDir;
static GLuint TU_Albedo;
static void init();
static void setUniforms(const core::matrix4 &ViewProjectionMatrix, const core::vector3df &windDirection);
};
class SphereMapShader
{
public:

View File

@@ -0,0 +1,244 @@
#include "stkinstancedscenenode.hpp"
#include "graphics/irr_driver.hpp"
STKInstancedSceneNode::STKInstancedSceneNode(irr::scene::IMesh* mesh, ISceneNode* parent, irr::scene::ISceneManager* mgr, irr::s32 id,
const irr::core::vector3df& position,
const irr::core::vector3df& rotation,
const irr::core::vector3df& scale) :
CMeshSceneNode(mesh, parent, mgr, id, position, rotation, scale)
{
createGLMeshes();
setAutomaticCulling(0);
}
void STKInstancedSceneNode::cleanGL()
{
for (u32 i = 0; i < GLmeshes.size(); ++i)
{
GLMesh mesh = GLmeshes[i];
if (!mesh.vertex_buffer)
continue;
if (mesh.vao_first_pass)
glDeleteVertexArrays(1, &(mesh.vao_first_pass));
if (mesh.vao_second_pass)
glDeleteVertexArrays(1, &(mesh.vao_second_pass));
if (mesh.vao_glow_pass)
glDeleteVertexArrays(1, &(mesh.vao_glow_pass));
if (mesh.vao_displace_pass)
glDeleteVertexArrays(1, &(mesh.vao_displace_pass));
if (mesh.vao_displace_mask_pass)
glDeleteVertexArrays(1, &(mesh.vao_displace_mask_pass));
if (mesh.vao_shadow_pass)
glDeleteVertexArrays(1, &(mesh.vao_shadow_pass));
glDeleteBuffers(1, &(mesh.vertex_buffer));
glDeleteBuffers(1, &(mesh.index_buffer));
}
glDeleteBuffers(1, &instances_vbo);
}
STKInstancedSceneNode::~STKInstancedSceneNode()
{
cleanGL();
}
void STKInstancedSceneNode::createGLMeshes()
{
for (u32 i = 0; i<Mesh->getMeshBufferCount(); ++i)
{
scene::IMeshBuffer* mb = Mesh->getMeshBuffer(i);
GLmeshes.push_back(allocateMeshBuffer(mb));
}
isMaterialInitialized = false;
}
void STKInstancedSceneNode::initinstancedvaostate(GLMesh &mesh, GeometricMaterial GeoMat, ShadedMaterial ShadedMat)
{
switch (GeoMat)
{
case FPSM_DEFAULT:
mesh.vao_first_pass = createVAO(mesh.vertex_buffer, mesh.index_buffer,
MeshShader::InstancedObjectPass1Shader::attrib_position, -1, -1, MeshShader::InstancedObjectPass1Shader::attrib_normal, -1, -1, -1, mesh.Stride);
glGenBuffers(1, &instances_vbo);
glBindBuffer(GL_ARRAY_BUFFER, instances_vbo);
glBufferData(GL_ARRAY_BUFFER, instance_pos.size() * sizeof(float), instance_pos.data(), GL_STATIC_DRAW);
glEnableVertexAttribArray(MeshShader::InstancedObjectPass1Shader::attrib_origin);
glVertexAttribPointer(MeshShader::InstancedObjectPass1Shader::attrib_origin, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), 0);
glVertexAttribDivisor(MeshShader::InstancedObjectPass1Shader::attrib_origin, 1);
break;
case FPSM_GRASS:
mesh.vao_first_pass = createVAO(mesh.vertex_buffer, mesh.index_buffer,
MeshShader::InstancedGrassPass1Shader::attrib_position, MeshShader::InstancedGrassPass1Shader::attrib_texcoord, -1, MeshShader::InstancedGrassPass1Shader::attrib_normal, -1, -1, MeshShader::InstancedGrassPass1Shader::attrib_color, mesh.Stride);
glGenBuffers(1, &instances_vbo);
glBindBuffer(GL_ARRAY_BUFFER, instances_vbo);
glBufferData(GL_ARRAY_BUFFER, instance_pos.size() * sizeof(float), instance_pos.data(), GL_STATIC_DRAW);
glEnableVertexAttribArray(MeshShader::InstancedGrassPass1Shader::attrib_origin);
glVertexAttribPointer(MeshShader::InstancedGrassPass1Shader::attrib_origin, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), 0);
glVertexAttribDivisor(MeshShader::InstancedGrassPass1Shader::attrib_origin, 1);
glVertexAttribPointer(MeshShader::InstancedGrassPass1Shader::attrib_orientation, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (GLvoid*)(3 * sizeof(float)));
glVertexAttribDivisor(MeshShader::InstancedGrassPass1Shader::attrib_orientation, 1);
break;
default:
return;
}
switch (ShadedMat)
{
case SM_DEFAULT:
mesh.vao_second_pass = createVAO(mesh.vertex_buffer, mesh.index_buffer,
MeshShader::InstancedObjectPass2Shader::attrib_position, MeshShader::InstancedObjectPass2Shader::attrib_texcoord, -1, -1, -1, -1, -1, mesh.Stride);
glBindBuffer(GL_ARRAY_BUFFER, instances_vbo);
glEnableVertexAttribArray(MeshShader::InstancedObjectPass2Shader::attrib_origin);
glVertexAttribPointer(MeshShader::InstancedObjectPass2Shader::attrib_origin, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), 0);
glVertexAttribDivisor(MeshShader::InstancedObjectPass2Shader::attrib_origin, 1);
break;
case SM_GRASS:
mesh.vao_second_pass = createVAO(mesh.vertex_buffer, mesh.index_buffer,
MeshShader::InstancedGrassPass2Shader::attrib_position, MeshShader::InstancedGrassPass2Shader::attrib_texcoord, -1, -1, -1, -1, MeshShader::InstancedGrassPass2Shader::attrib_color, mesh.Stride);
glBindBuffer(GL_ARRAY_BUFFER, instances_vbo);
glEnableVertexAttribArray(MeshShader::InstancedGrassPass2Shader::attrib_origin);
glVertexAttribPointer(MeshShader::InstancedGrassPass2Shader::attrib_origin, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), 0);
glVertexAttribDivisor(MeshShader::InstancedGrassPass2Shader::attrib_origin, 1);
glVertexAttribPointer(MeshShader::InstancedGrassPass2Shader::attrib_orientation, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (GLvoid*) (3 * sizeof(float)));
glVertexAttribDivisor(MeshShader::InstancedGrassPass2Shader::attrib_orientation, 1);
break;
default:
return;
}
glBindVertexArray(0);
}
void STKInstancedSceneNode::setFirstTimeMaterial()
{
if (isMaterialInitialized)
return;
for (u32 i = 0; i<Mesh->getMeshBufferCount(); ++i)
{
scene::IMeshBuffer* mb = Mesh->getMeshBuffer(i);
if (!mb)
continue;
video::E_MATERIAL_TYPE type = mb->getMaterial().MaterialType;
GLMesh &mesh = GLmeshes[i];
GeometricMaterial GeometricType = MaterialTypeToGeometricMaterial(type);
ShadedMaterial ShadedType = MaterialTypeToShadedMaterial(type, mesh.textures);
initinstancedvaostate(mesh, GeometricType, ShadedType);
if (mesh.vao_first_pass)
GeometricMesh[GeometricType].push_back(&mesh);
if (mesh.vao_second_pass)
ShadedMesh[ShadedType].push_back(&mesh);
}
isMaterialInitialized = true;
}
void STKInstancedSceneNode::addInstance(const core::vector3df &origin, const core::vector3df &orientation)
{
instance_pos.push_back(origin.X);
instance_pos.push_back(origin.Y);
instance_pos.push_back(origin.Z);
instance_pos.push_back(orientation.X);
instance_pos.push_back(orientation.Y);
instance_pos.push_back(orientation.Z);
}
static void drawFSPMDefault(GLMesh &mesh, const core::matrix4 &ModelViewProjectionMatrix, size_t instance_count)
{
irr_driver->IncreaseObjectCount();
GLenum ptype = mesh.PrimitiveType;
GLenum itype = mesh.IndexType;
size_t count = mesh.IndexCount;
core::matrix4 InverseViewMatrix;
irr_driver->getVideoDriver()->getTransform(video::ETS_VIEW).getInverse(InverseViewMatrix);
MeshShader::InstancedObjectPass1Shader::setUniforms(ModelViewProjectionMatrix, InverseViewMatrix);
glBindVertexArray(mesh.vao_first_pass);
glDrawElementsInstanced(ptype, count, itype, 0, instance_count);
}
static void drawFSPMGrass(GLMesh &mesh, const core::matrix4 &ModelViewProjectionMatrix, const core::vector3df &windDir, size_t instance_count)
{
irr_driver->IncreaseObjectCount();
GLenum ptype = mesh.PrimitiveType;
GLenum itype = mesh.IndexType;
size_t count = mesh.IndexCount;
core::matrix4 InverseViewMatrix;
irr_driver->getVideoDriver()->getTransform(video::ETS_VIEW).getInverse(InverseViewMatrix);
setTexture(0, mesh.textures[0], GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, true);
MeshShader::InstancedGrassPass1Shader::setUniforms(ModelViewProjectionMatrix, InverseViewMatrix, windDir, 0);
glBindVertexArray(mesh.vao_first_pass);
glDrawElementsInstanced(ptype, count, itype, 0, instance_count);
}
static void drawSMDefault(GLMesh &mesh, const core::matrix4 &ModelViewProjectionMatrix, size_t instance_count)
{
irr_driver->IncreaseObjectCount();
GLenum ptype = mesh.PrimitiveType;
GLenum itype = mesh.IndexType;
size_t count = mesh.IndexCount;
setTexture(MeshShader::InstancedObjectPass2Shader::TU_Albedo, mesh.textures[0], GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, true);
MeshShader::InstancedObjectPass2Shader::setUniforms(ModelViewProjectionMatrix, core::matrix4::EM4CONST_IDENTITY);
glBindVertexArray(mesh.vao_second_pass);
glDrawElementsInstanced(ptype, count, itype, 0, instance_count);
}
static void drawSMGrass(GLMesh &mesh, const core::matrix4 &ModelViewProjectionMatrix, const core::vector3df &windDir, size_t instance_count)
{
irr_driver->IncreaseObjectCount();
GLenum ptype = mesh.PrimitiveType;
GLenum itype = mesh.IndexType;
size_t count = mesh.IndexCount;
setTexture(MeshShader::InstancedGrassPass2Shader::TU_Albedo, mesh.textures[0], GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, true);
MeshShader::InstancedGrassPass2Shader::setUniforms(ModelViewProjectionMatrix, windDir);
glBindVertexArray(mesh.vao_second_pass);
glDrawElementsInstanced(ptype, count, itype, 0, instance_count);
}
void STKInstancedSceneNode::render()
{
setFirstTimeMaterial();
if (irr_driver->getPhase() == SOLID_NORMAL_AND_DEPTH_PASS)
{
ModelViewProjectionMatrix = irr_driver->getVideoDriver()->getTransform(video::ETS_PROJECTION);
ModelViewProjectionMatrix *= irr_driver->getVideoDriver()->getTransform(video::ETS_VIEW);
if (!GeometricMesh[FPSM_DEFAULT].empty())
glUseProgram(MeshShader::InstancedObjectPass1Shader::Program);
for (unsigned i = 0; i < GeometricMesh[FPSM_DEFAULT].size(); i++)
drawFSPMDefault(*GeometricMesh[FPSM_DEFAULT][i], ModelViewProjectionMatrix, instance_pos.size() / 3);
windDir = getWind();
if (!GeometricMesh[FPSM_GRASS].empty())
glUseProgram(MeshShader::InstancedGrassPass1Shader::Program);
for (unsigned i = 0; i < GeometricMesh[FPSM_GRASS].size(); i++)
drawFSPMGrass(*GeometricMesh[FPSM_GRASS][i], ModelViewProjectionMatrix, windDir, instance_pos.size() / 3);
return;
}
if (irr_driver->getPhase() == SOLID_LIT_PASS)
{
if (!ShadedMesh[SM_DEFAULT].empty())
glUseProgram(MeshShader::InstancedObjectPass2Shader::Program);
for (unsigned i = 0; i < ShadedMesh[FPSM_DEFAULT].size(); i++)
drawSMDefault(*ShadedMesh[FPSM_DEFAULT][i], ModelViewProjectionMatrix, instance_pos.size() / 3);
if (!ShadedMesh[SM_GRASS].empty())
glUseProgram(MeshShader::InstancedGrassPass2Shader::Program);
for (unsigned i = 0; i < ShadedMesh[SM_GRASS].size(); i++)
drawSMGrass(*ShadedMesh[SM_GRASS][i], ModelViewProjectionMatrix, windDir, instance_pos.size() / 3);
return;
}
}

View File

@@ -0,0 +1,31 @@
#ifndef STKINSTANCEDSCENENODE_HPP
#define STKINSTANCEDSCENENODE_HPP
#include "stkmesh.hpp"
class STKInstancedSceneNode : public irr::scene::CMeshSceneNode
{
protected:
std::vector<GLMesh *> GeometricMesh[FPSM_COUNT];
std::vector<GLMesh *> ShadedMesh[SM_COUNT];
std::vector<GLMesh> GLmeshes;
std::vector<float> instance_pos;
core::matrix4 ModelViewProjectionMatrix, TransposeInverseModelView;
GLuint instances_vbo;
void createGLMeshes();
bool isMaterialInitialized;
void setFirstTimeMaterial();
void initinstancedvaostate(GLMesh &mesh, GeometricMaterial GeoMat, ShadedMaterial ShadedMat);
void cleanGL();
core::vector3df windDir;
public:
STKInstancedSceneNode(irr::scene::IMesh* mesh, ISceneNode* parent, irr::scene::ISceneManager* mgr, irr::s32 id,
const irr::core::vector3df& position = irr::core::vector3df(0, 0, 0),
const irr::core::vector3df& rotation = irr::core::vector3df(0, 0, 0),
const irr::core::vector3df& scale = irr::core::vector3df(1.0f, 1.0f, 1.0f));
~STKInstancedSceneNode();
virtual void render();
void addInstance(const core::vector3df &origin, const core::vector3df &orientation);
};
#endif

View File

@@ -102,7 +102,6 @@ GLuint createVAO(GLuint vbo, GLuint idx, GLuint attrib_position, GLuint attrib_t
glVertexAttribPointer(attrib_color, 4, GL_UNSIGNED_BYTE, GL_TRUE, stride, (GLvoid*)24);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, idx);
glBindVertexArray(0);
return vao;
}
@@ -206,6 +205,16 @@ void computeTIMV(core::matrix4 &TransposeInverseModelView)
TransposeInverseModelView = TransposeInverseModelView.getTransposed();
}
core::vector3df getWind()
{
const core::vector3df pos = irr_driver->getVideoDriver()->getTransform(video::ETS_WORLD).getTranslation();
const float time = irr_driver->getDevice()->getTimer()->getTime() / 1000.0f;
GrassShaderProvider *gsp = (GrassShaderProvider *)irr_driver->getCallback(ES_GRASS);
float m_speed = gsp->getSpeed(), m_amplitude = gsp->getAmplitude();
return m_speed * vector3df(1., 0., 0.) * cos(time);
}
void drawObjectPass1(const GLMesh &mesh, const core::matrix4 & ModelViewProjectionMatrix, const core::matrix4 &TransposeInverseModelView)
{
irr_driver->IncreaseObjectCount();

View File

@@ -64,6 +64,8 @@ void computeMVP(core::matrix4 &ModelViewProjectionMatrix);
void computeTIMV(core::matrix4 &TransposeInverseModelView);
bool isObject(video::E_MATERIAL_TYPE type);
core::vector3df getWind();
// Pass 1 shader (ie shaders that outputs normals and depth)
void drawObjectPass1(const GLMesh &mesh, const core::matrix4 & ModelViewProjectionMatrix, const core::matrix4 &TransposeInverseModelView);
void drawNormalPass(const GLMesh &mesh, const core::matrix4 & ModelViewProjectionMatrix, const core::matrix4 &TransposeInverseModelView);

View File

@@ -10,22 +10,6 @@
#include "graphics/camera.hpp"
#include "modes/world.hpp"
static
core::vector3df getWind()
{
const core::vector3df pos = irr_driver->getVideoDriver()->getTransform(video::ETS_WORLD).getTranslation();
const float time = irr_driver->getDevice()->getTimer()->getTime() / 1000.0f;
GrassShaderProvider *gsp = (GrassShaderProvider *)irr_driver->getCallback(ES_GRASS);
float m_speed = gsp->getSpeed(), m_amplitude = gsp->getAmplitude();
float strength = (pos.X + pos.Y + pos.Z) * 1.2f + time * m_speed;
strength = noise2d(strength / 10.0f) * m_amplitude * 5;
// * 5 is to work with the existing amplitude values.
// Pre-multiply on the cpu
return irr_driver->getWind() * strength;
}
STKMeshSceneNode::STKMeshSceneNode(irr::scene::IMesh* mesh, ISceneNode* parent, irr::scene::ISceneManager* mgr, irr::s32 id,
const irr::core::vector3df& position,
const irr::core::vector3df& rotation,

View File

@@ -16,11 +16,12 @@
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "tracks/lod_node_loader.hpp"
#include "tracks/model_definition_loader.hpp"
using namespace irr;
#include "graphics/irr_driver.hpp"
#include "graphics/lod_node.hpp"
#include "graphics/stkinstancedscenenode.hpp"
#include "io/xml_node.hpp"
#include "tracks/track.hpp"
@@ -29,14 +30,14 @@ using namespace irr;
#include <IMeshManipulator.h>
#include <algorithm>
LodNodeLoader::LodNodeLoader(Track* track)
ModelDefinitionLoader::ModelDefinitionLoader(Track* track)
{
m_track = track;
}
// ----------------------------------------------------------------------------
void LodNodeLoader::addLODModelDefinition(const XMLNode* xml)
void ModelDefinitionLoader::addModelDefinition(const XMLNode* xml)
{
float lod_distance = -1.0f;
xml->get("lod_distance", &lod_distance);
@@ -50,35 +51,24 @@ void LodNodeLoader::addLODModelDefinition(const XMLNode* xml)
std::string model_name;
xml->get("model", &model_name);
m_lod_groups[lodgroup].push_back(LodModel(xml, (int)lod_distance, model_name, tangent));
m_lod_groups[lodgroup].push_back(ModelDefinition(xml, (int)lod_distance, model_name, tangent));
}
// ----------------------------------------------------------------------------
LODNode* LodNodeLoader::instanciate(const XMLNode* node, scene::ISceneNode* parent)
//Track* track, std::vector<irr::scene::IMesh*>& cache)
LODNode* ModelDefinitionLoader::instanciateAsLOD(const XMLNode* node, scene::ISceneNode* parent)
{
scene::ISceneManager* sm = irr_driver->getSceneManager();
std::string groupname = "";
node->get("lod_group", &groupname);
std::vector< LodModel >& group = m_lod_groups[groupname];
//core::vector3df xyz(0,0,0);
//node->get("xyz", &xyz);
//core::vector3df hpr(0,0,0);
//node->get("hpr", &hpr);
//core::vector3df scale(1.0f, 1.0f, 1.0f);
//node->get("scale", &scale);
std::vector< ModelDefinition >& group = m_lod_groups[groupname];
if (group.size() > 0)
{
scene::ISceneNode* actual_parent = (parent == NULL ? sm->getRootSceneNode() : parent);
LODNode* lod_node = new LODNode(groupname, actual_parent, sm);
//lod_node->setPosition(xyz);
//lod_node->setRotation(hpr);
//lod_node->setScale(scale);
lod_node->updateAbsolutePosition();
for (unsigned int m=0; m<group.size(); m++)
{
@@ -119,14 +109,37 @@ LODNode* LodNodeLoader::instanciate(const XMLNode* node, scene::ISceneNode* pare
}
else
{
Log::warn("LodNodeLoader", "LOD group '%s' is empty", groupname.c_str());
Log::warn("ModelDefinitionLoader", "LOD group '%s' is empty", groupname.c_str());
return NULL;
}
}
// ----------------------------------------------------------------------------
void LodNodeLoader::clear()
void ModelDefinitionLoader::instanciate(const irr::core::vector3df& position,
const irr::core::vector3df& rotation,
const std::string& name)
{
if (m_instancing_nodes.find(name) == m_instancing_nodes.end())
{
if (m_lod_groups.find(name) == m_lod_groups.end())
{
Log::warn("Instancing", "Cannot find instancing model <%s>", name.c_str());
return;
}
scene::IMesh* mesh = irr_driver->getMesh(m_lod_groups[name][0].m_model_file);
m_instancing_nodes[name] = new STKInstancedSceneNode(mesh,
irr_driver->getSceneManager()->getRootSceneNode(), irr_driver->getSceneManager(), -1);
m_track->addNode(m_instancing_nodes[name]);
}
m_instancing_nodes[name]->addInstance(position, rotation);
}
// ----------------------------------------------------------------------------
void ModelDefinitionLoader::clear()
{
m_lod_groups.clear();
}

View File

@@ -21,10 +21,12 @@
class LODNode;
class Track;
class STKInstancedSceneNode;
#include <map>
#include <vector>
#include <string>
#include <irrlicht.h>
#include "io/xml_node.hpp"
namespace irr
@@ -36,23 +38,24 @@ namespace irr
}
}
struct LodModel
struct ModelDefinition
{
std::string m_model_file;
bool m_tangent;
const XMLNode* m_xml;
/** For LOD */
int m_distance;
/** Constructor to allow storing this in STL containers */
LodModel()
ModelDefinition()
{
m_tangent = false;
m_distance = 0;
m_xml = NULL;
}
LodModel(const XMLNode* xml, int distance, std::string& model, bool tangent)
ModelDefinition(const XMLNode* xml, int distance, std::string& model, bool tangent)
{
m_model_file = model;
m_tangent = tangent;
@@ -60,29 +63,32 @@ struct LodModel
m_distance = distance;
}
~LodModel()
~ModelDefinition()
{
}
};
/** Utility class to load level-of-detail nodes
/** Utility class to load level-of-detail nodes and instaincing nodes
* \ingroup tracks
*/
class LodNodeLoader
class ModelDefinitionLoader
{
private:
std::map< std::string, std::vector< LodModel > > m_lod_groups;
std::map< std::string, std::vector< ModelDefinition > > m_lod_groups;
std::map< std::string, STKInstancedSceneNode* > m_instancing_nodes;
Track* m_track;
public:
LodNodeLoader(Track* track);
ModelDefinitionLoader(Track* track);
void addLODModelDefinition(const XMLNode* xml);
LODNode* instanciate(const XMLNode* xml_node, scene::ISceneNode* parent);
//Track* track, std::vector<irr::scene::IMesh*>& cache);
void addModelDefinition(const XMLNode* xml);
LODNode* instanciateAsLOD(const XMLNode* xml_node, scene::ISceneNode* parent);
void instanciate(const core::vector3df& position,
const irr::core::vector3df& rotation,
const std::string& name);
void clear();
}; // LodNodeLoader
}; // ModelDefinitionLoader
#endif // HEADER_LOD_NODE_LOADER_HPP

View File

@@ -52,7 +52,7 @@
#include "race/race_manager.hpp"
#include "tracks/bezier_curve.hpp"
#include "tracks/check_manager.hpp"
#include "tracks/lod_node_loader.hpp"
#include "tracks/model_definition_loader.hpp"
#include "tracks/track_manager.hpp"
#include "tracks/quad_graph.hpp"
#include "tracks/quad_set.hpp"
@@ -880,7 +880,7 @@ bool Track::loadMainTrack(const XMLNode &root)
m_aabb_max.setY(m_aabb_max.getY()+30.0f);
World::getWorld()->getPhysics()->init(m_aabb_min, m_aabb_max);
LodNodeLoader lodLoader(this);
ModelDefinitionLoader lodLoader(this);
// Load LOD groups
const XMLNode *lod_xml_node = root.getNode("lod");
@@ -891,7 +891,21 @@ bool Track::loadMainTrack(const XMLNode &root)
const XMLNode* lod_group_xml = lod_xml_node->getNode(i);
for (unsigned int j = 0; j < lod_group_xml->getNumNodes(); j++)
{
lodLoader.addLODModelDefinition(lod_group_xml->getNode(j));
lodLoader.addModelDefinition(lod_group_xml->getNode(j));
}
}
}
// Load instancing models (for the moment they are loaded the same way as LOD to simplify implementation)
const XMLNode *instancing_xml_node = root.getNode("instancing");
if (instancing_xml_node != NULL)
{
for (unsigned int i = 0; i < instancing_xml_node->getNumNodes(); i++)
{
const XMLNode* lod_group_xml = instancing_xml_node->getNode(i);
for (unsigned int j = 0; j < lod_group_xml->getNumNodes(); j++)
{
lodLoader.addModelDefinition(lod_group_xml->getNode(j));
}
}
}
@@ -1075,7 +1089,7 @@ bool Track::loadMainTrack(const XMLNode &root)
}
else if (lod_instance)
{
LODNode* node = lodLoader.instanciate(n, NULL);
LODNode* node = lodLoader.instanciateAsLOD(n, NULL);
if (node != NULL)
{
node->setPosition(xyz);
@@ -1524,7 +1538,7 @@ void Track::loadTrackModel(bool reverse_track, unsigned int mode_id)
loadMainTrack(*root);
unsigned int main_track_count = m_all_nodes.size();
LodNodeLoader lod_loader(this);
ModelDefinitionLoader model_def_loader(this);
// Load LOD groups
const XMLNode *lod_xml_node = root->getNode("lod");
@@ -1535,13 +1549,27 @@ void Track::loadTrackModel(bool reverse_track, unsigned int mode_id)
const XMLNode* lod_group_xml = lod_xml_node->getNode(i);
for (unsigned int j = 0; j < lod_group_xml->getNumNodes(); j++)
{
lod_loader.addLODModelDefinition(lod_group_xml->getNode(j));
model_def_loader.addModelDefinition(lod_group_xml->getNode(j));
}
}
}
// Load instancing models (for the moment they are loaded the same way as LOD to simplify implementation)
const XMLNode *instancing_xml_node = root->getNode("instancing");
if (instancing_xml_node != NULL)
{
for (unsigned int i = 0; i < instancing_xml_node->getNumNodes(); i++)
{
const XMLNode* lod_group_xml = instancing_xml_node->getNode(i);
for (unsigned int j = 0; j < lod_group_xml->getNumNodes(); j++)
{
model_def_loader.addModelDefinition(lod_group_xml->getNode(j));
}
}
}
std::map<std::string, XMLNode*> library_nodes;
loadObjects(root, path, lod_loader, true, NULL, library_nodes);
loadObjects(root, path, model_def_loader, true, NULL, library_nodes);
// Cleanup library nodes
for (std::map<std::string, XMLNode*>::iterator it = library_nodes.begin();
@@ -1709,7 +1737,7 @@ void Track::loadTrackModel(bool reverse_track, unsigned int mode_id)
//-----------------------------------------------------------------------------
void Track::loadObjects(const XMLNode* root, const std::string& path, LodNodeLoader& lod_loader,
void Track::loadObjects(const XMLNode* root, const std::string& path, ModelDefinitionLoader& model_def_loader,
bool create_lod_definitions, scene::ISceneNode* parent,
std::map<std::string, XMLNode*>& library_nodes)
{
@@ -1725,7 +1753,7 @@ void Track::loadObjects(const XMLNode* root, const std::string& path, LodNodeLoa
if (name == "track" || name == "default-start") continue;
if (name == "object")
{
m_track_object_manager->add(*node, parent, lod_loader);
m_track_object_manager->add(*node, parent, model_def_loader);
}
else if (name == "library")
{
@@ -1770,7 +1798,21 @@ void Track::loadObjects(const XMLNode* root, const std::string& path, LodNodeLoa
const XMLNode* lod_group_xml = lod_xml_node->getNode(i);
for (unsigned int j = 0; j < lod_group_xml->getNumNodes(); j++)
{
lod_loader.addLODModelDefinition(lod_group_xml->getNode(j));
model_def_loader.addModelDefinition(lod_group_xml->getNode(j));
}
}
}
// Load instancing definitions
const XMLNode *instancing_xml_node = libroot->getNode("instancing");
if (instancing_xml_node != NULL)
{
for (unsigned int i = 0; i < instancing_xml_node->getNumNodes(); i++)
{
const XMLNode* instancing_group_xml = instancing_xml_node->getNode(i);
for (unsigned int j = 0; j < instancing_group_xml->getNumNodes(); j++)
{
model_def_loader.addModelDefinition(instancing_group_xml->getNode(j));
}
}
}
@@ -1786,7 +1828,7 @@ void Track::loadObjects(const XMLNode* root, const std::string& path, LodNodeLoa
parent->setRotation(hpr);
parent->setScale(scale);
parent->updateAbsolutePosition();
loadObjects(libroot, lib_path, lod_loader, create_lod_definitions, parent, library_nodes);
loadObjects(libroot, lib_path, model_def_loader, create_lod_definitions, parent, library_nodes);
}
else if (name == "water")
{
@@ -1830,7 +1872,7 @@ void Track::loadObjects(const XMLNode* root, const std::string& path, LodNodeLoa
{
if (UserConfigParams::m_graphical_effects)
{
m_track_object_manager->add(*node, parent, lod_loader);
m_track_object_manager->add(*node, parent, model_def_loader);
}
}
else if (name == "sky-dome" || name == "sky-box" || name == "sky-color")
@@ -1843,7 +1885,7 @@ void Track::loadObjects(const XMLNode* root, const std::string& path, LodNodeLoa
}
else if (name == "light")
{
m_track_object_manager->add(*node, parent, lod_loader);
m_track_object_manager->add(*node, parent, model_def_loader);
}
else if (name == "weather")
{
@@ -1883,6 +1925,10 @@ void Track::loadObjects(const XMLNode* root, const std::string& path, LodNodeLoa
{
// handled above
}
else if (name == "instancing")
{
// handled above
}
else if (name == "subtitles")
{
std::vector<XMLNode*> subtitles;

View File

@@ -35,7 +35,7 @@ namespace irr
namespace scene { class IMesh; class ILightSceneNode; }
}
using namespace irr;
class LodNodeLoader;
class ModelDefinitionLoader;
#include "LinearMath/btTransform.h"
@@ -401,7 +401,7 @@ private:
std::vector<MusicInformation*>& m_music );
void loadCurves(const XMLNode &node);
void handleSky(const XMLNode &root, const std::string &filename);
void loadObjects(const XMLNode* root, const std::string& path, LodNodeLoader& lod_loader,
void loadObjects(const XMLNode* root, const std::string& path, ModelDefinitionLoader& lod_loader,
bool create_lod_definitions, scene::ISceneNode* parent,
std::map<std::string, XMLNode*>& library_nodes);
@@ -606,6 +606,7 @@ public:
bool hasGodRays() const { return m_godrays; }
bool hasShadows() const { return m_shadows; }
void addNode(scene::ISceneNode* node) { m_all_nodes.push_back(node); }
float getDisplacementSpeed() const { return m_displacement_speed; }
float getCausticsSpeed() const { return m_caustics_speed; }

View File

@@ -39,9 +39,9 @@
* \param lod_node Lod node (defaults to NULL).
*/
TrackObject::TrackObject(const XMLNode &xml_node, scene::ISceneNode* parent,
LodNodeLoader& lod_loader)
ModelDefinitionLoader& model_def_loader)
{
init(xml_node, parent, lod_loader);
init(xml_node, parent, model_def_loader);
}
// ----------------------------------------------------------------------------
@@ -80,7 +80,7 @@ TrackObject::TrackObject(const core::vector3df& xyz, const core::vector3df& hpr,
// ----------------------------------------------------------------------------
void TrackObject::init(const XMLNode &xml_node, scene::ISceneNode* parent,
LodNodeLoader& lod_loader)
ModelDefinitionLoader& model_def_loader)
{
m_init_xyz = core::vector3df(0,0,0);
m_init_hpr = core::vector3df(0,0,0);
@@ -103,6 +103,9 @@ void TrackObject::init(const XMLNode &xml_node, scene::ISceneNode* parent,
bool lod_instance = false;
xml_node.get("lod_instance", &lod_instance);
bool instancing = false;
xml_node.get("instancing", &instancing);
m_soccer_ball = false;
xml_node.get("soccer_ball", &m_soccer_ball);
@@ -156,11 +159,18 @@ void TrackObject::init(const XMLNode &xml_node, scene::ISceneNode* parent,
{
scene::ISceneNode *glownode = NULL;
if (lod_instance)
if (instancing)
{
m_type = "lod";
TrackObjectPresentationInstancing* instancing_node =
new TrackObjectPresentationInstancing(xml_node, parent, model_def_loader);
m_presentation = instancing_node;
}
else if (lod_instance)
{
m_type = "lod";
TrackObjectPresentationLOD* lod_node =
new TrackObjectPresentationLOD(xml_node, parent, lod_loader);
new TrackObjectPresentationLOD(xml_node, parent, model_def_loader);
m_presentation = lod_node;
glownode = ((LODNode*)lod_node->getNode())->getAllNodes()[0];

View File

@@ -31,7 +31,7 @@
class XMLNode;
class ThreeDAnimation;
class LodNodeLoader;
class ModelDefinitionLoader;
/**
* \ingroup tracks
@@ -82,10 +82,10 @@ protected:
ThreeDAnimation* m_animator;
void init(const XMLNode &xml_node, scene::ISceneNode* parent, LodNodeLoader& lod_loader);
void init(const XMLNode &xml_node, scene::ISceneNode* parent, ModelDefinitionLoader& model_def_loader);
public:
TrackObject(const XMLNode &xml_node, scene::ISceneNode* parent, LodNodeLoader& lod_loader);
TrackObject(const XMLNode &xml_node, scene::ISceneNode* parent, ModelDefinitionLoader& model_def_loader);
TrackObject(const core::vector3df& xyz,
const core::vector3df& hpr,

View File

@@ -49,11 +49,11 @@ TrackObjectManager::~TrackObjectManager()
* in a separate section that's read before everything and remove all this
* crap
*/
void TrackObjectManager::add(const XMLNode &xml_node, scene::ISceneNode* parent, LodNodeLoader& lod_loader)
void TrackObjectManager::add(const XMLNode &xml_node, scene::ISceneNode* parent, ModelDefinitionLoader& model_def_loader)
{
try
{
m_all_objects.push_back(new TrackObject(xml_node, parent, lod_loader));
m_all_objects.push_back(new TrackObject(xml_node, parent, model_def_loader));
}
catch (std::exception& e)
{

View File

@@ -49,7 +49,7 @@ protected:
public:
TrackObjectManager();
~TrackObjectManager();
void add(const XMLNode &xml_node, scene::ISceneNode* parent, LodNodeLoader& lod_loader);
void add(const XMLNode &xml_node, scene::ISceneNode* parent, ModelDefinitionLoader& model_def_loader);
void update(float dt);
void handleExplosion(const Vec3 &pos, const PhysicalObject *mp,
bool secondary_hits=true);

View File

@@ -34,7 +34,7 @@
#include "modes/world.hpp"
#include "states_screens/dialogs/race_paused_dialog.hpp"
#include "states_screens/dialogs/tutorial_message_dialog.hpp"
#include "tracks/lod_node_loader.hpp"
#include "tracks/model_definition_loader.hpp"
#include "tracks/track.hpp"
#include <ISceneManager.h>
@@ -138,10 +138,10 @@ TrackObjectPresentationEmpty::~TrackObjectPresentationEmpty()
// ----------------------------------------------------------------------------
TrackObjectPresentationLOD::TrackObjectPresentationLOD(const XMLNode& xml_node,
scene::ISceneNode* parent, LodNodeLoader& lod_loader) :
scene::ISceneNode* parent, ModelDefinitionLoader& model_def_loader) :
TrackObjectPresentationSceneNode(xml_node)
{
m_node = lod_loader.instanciate(&xml_node, parent);
m_node = model_def_loader.instanciateAsLOD(&xml_node, parent);
if (m_node == NULL) throw std::runtime_error("Cannot load LOD node");
m_node->setPosition(m_init_xyz);
m_node->setRotation(m_init_hpr);
@@ -156,6 +156,27 @@ TrackObjectPresentationLOD::~TrackObjectPresentationLOD()
// ----------------------------------------------------------------------------
TrackObjectPresentationInstancing::TrackObjectPresentationInstancing(const XMLNode& xml_node,
scene::ISceneNode* parent,
ModelDefinitionLoader& model_def_loader) : TrackObjectPresentationSceneNode(xml_node)
{
std::string instancing_model;
xml_node.get("instancing_model", &instancing_model);
m_node = irr_driver->getSceneManager()->addEmptySceneNode(parent);
m_node->setPosition(m_init_xyz);
m_node->setRotation(m_init_hpr);
m_node->setScale(m_init_scale);
m_node->updateAbsolutePosition();
model_def_loader.instanciate(m_node->getAbsolutePosition(), m_init_hpr, instancing_model);
}
TrackObjectPresentationInstancing::~TrackObjectPresentationInstancing()
{
}
// ----------------------------------------------------------------------------
TrackObjectPresentationMesh::TrackObjectPresentationMesh(const XMLNode& xml_node,
bool enabled, scene::ISceneNode* parent) :
TrackObjectPresentationSceneNode(xml_node)

View File

@@ -40,7 +40,7 @@ class SFXBase;
class ParticleEmitter;
class PhysicalObject;
class ThreeDAnimation;
class LodNodeLoader;
class ModelDefinitionLoader;
/**
* \ingroup tracks
@@ -152,10 +152,20 @@ public:
TrackObjectPresentationLOD(const XMLNode& xml_node,
scene::ISceneNode* parent,
LodNodeLoader& lod_loader);
ModelDefinitionLoader& model_def_loader);
virtual ~TrackObjectPresentationLOD();
};
class TrackObjectPresentationInstancing : public TrackObjectPresentationSceneNode
{
public:
TrackObjectPresentationInstancing(const XMLNode& xml_node,
scene::ISceneNode* parent,
ModelDefinitionLoader& model_def_loader);
virtual ~TrackObjectPresentationInstancing();
};
/**
* \ingroup tracks
* A track object representation that consists of a mesh scene node.