Merged master
This commit is contained in:
commit
10e2634f22
@ -78,17 +78,17 @@ include_directories("${PROJECT_SOURCE_DIR}/lib/angelscript/include")
|
|||||||
include_directories(${STK_SOURCE_DIR})
|
include_directories(${STK_SOURCE_DIR})
|
||||||
|
|
||||||
# These variables enable MSVC to find libraries located in "dependencies"
|
# These variables enable MSVC to find libraries located in "dependencies"
|
||||||
if(MSVC)
|
if(WIN32)
|
||||||
set(ENV{PATH} ${PROJECT_SOURCE_DIR}/dependencies/include)
|
set(ENV{PATH} "$ENV{PATH};${PROJECT_SOURCE_DIR}/dependencies/include")
|
||||||
set(ENV{LIB} ${PROJECT_SOURCE_DIR}/dependencies/lib)
|
set(ENV{LIB} ${PROJECT_SOURCE_DIR}/dependencies/lib)
|
||||||
set(ENV{OPENALDIR} ${PROJECT_SOURCE_DIR}/dependencies)
|
set(ENV{OPENALDIR} ${PROJECT_SOURCE_DIR}/dependencies)
|
||||||
add_definitions(/D_IRR_STATIC_LIB_)
|
if(MSVC)
|
||||||
|
add_definitions(/D_IRR_STATIC_LIB_)
|
||||||
|
elseif(MINGW)
|
||||||
|
add_definitions(-D_IRR_STATIC_LIB_)
|
||||||
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(MINGW)
|
|
||||||
set(ENV{OPENALDIR} ${PROJECT_SOURCE_DIR}/dependencies)
|
|
||||||
add_definitions(-D_IRR_STATIC_LIB_)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(APPLE)
|
if(APPLE)
|
||||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -arch i386")
|
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -arch i386")
|
||||||
|
@ -7,7 +7,7 @@ void sheep_dance()
|
|||||||
//displayMessage("moo");
|
//displayMessage("moo");
|
||||||
sheepMesh.setLoop(1,3); //rapid-nod sheep
|
sheepMesh.setLoop(1,3); //rapid-nod sheep
|
||||||
Vec3 newloc = Vec3(2,3,4);
|
Vec3 newloc = Vec3(2,3,4);
|
||||||
sheepMesh.move(newloc);
|
//sheepMesh.move(newloc);
|
||||||
//runScript("sheep_approach");
|
//runScript("sheep_approach");
|
||||||
TrackObject @t_obj2 = getTrackObject("waterfall");
|
TrackObject @t_obj2 = getTrackObject("waterfall");
|
||||||
ParticleEmitter @waterfallemitter = t_obj2.getParticleEmitter();
|
ParticleEmitter @waterfallemitter = t_obj2.getParticleEmitter();
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
void onUpdate()
|
void onUpdate()
|
||||||
{
|
{
|
||||||
|
/*
|
||||||
TrackObject @t_obj = getTrackObject("anim_sheep2.b3d");
|
TrackObject @t_obj = getTrackObject("anim_sheep2.b3d");
|
||||||
Mesh @sheepMesh = t_obj.getMesh();
|
Mesh @sheepMesh = t_obj.getMesh();
|
||||||
Vec3 newloc = Vec3(2,-2,-2);
|
Vec3 newloc = Vec3(2,-2,-2);
|
||||||
@ -14,4 +14,5 @@ void onUpdate()
|
|||||||
Vec3 kartLoc = getKartLocation(0);
|
Vec3 kartLoc = getKartLocation(0);
|
||||||
sheepMesh.move(kartLoc);
|
sheepMesh.move(kartLoc);
|
||||||
printVec3(kartLoc);
|
printVec3(kartLoc);
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
#if __VERSION__ >= 330
|
||||||
layout(location=0) in vec3 Position;
|
layout(location=0) in vec3 Position;
|
||||||
layout(location = 1) in float lifetime;
|
layout(location = 1) in float lifetime;
|
||||||
layout(location = 2) in float size;
|
layout(location = 2) in float size;
|
||||||
@ -7,6 +8,17 @@ layout(location = 4) in vec2 quadcorner;
|
|||||||
|
|
||||||
layout(location = 5) in vec3 rotationvec;
|
layout(location = 5) in vec3 rotationvec;
|
||||||
layout(location = 6) in float anglespeed;
|
layout(location = 6) in float anglespeed;
|
||||||
|
#else
|
||||||
|
in vec3 Position;
|
||||||
|
in float lifetime;
|
||||||
|
in float size;
|
||||||
|
|
||||||
|
in vec2 Texcoord;
|
||||||
|
in vec2 quadcorner;
|
||||||
|
|
||||||
|
in vec3 rotationvec;
|
||||||
|
float anglespeed;
|
||||||
|
#endif
|
||||||
|
|
||||||
out float lf;
|
out float lf;
|
||||||
out vec2 tc;
|
out vec2 tc;
|
||||||
|
@ -12,8 +12,8 @@
|
|||||||
#include "aabbox3d.h"
|
#include "aabbox3d.h"
|
||||||
#include "rect.h"
|
#include "rect.h"
|
||||||
#include "irrString.h"
|
#include "irrString.h"
|
||||||
#if defined(WIN32) && (defined(__x86_64__) || defined(_M_X64) || defined(__i386) || defined(_M_IX86))
|
#if defined(WIN32) && !defined(__MINGW32__) && (defined(__x86_64__) || defined(_M_X64) || defined(__i386) || defined(_M_IX86))
|
||||||
#include <intrin.h>
|
#include <intrin.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// enable this to keep track of changes to the matrix
|
// enable this to keep track of changes to the matrix
|
||||||
@ -48,7 +48,7 @@ namespace core
|
|||||||
class CMatrix4
|
class CMatrix4
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
#if defined(WIN32) && (defined(__x86_64__) || defined(_M_X64) || defined(__i386) || defined(_M_IX86))
|
#if defined(WIN32) && !defined(__MINGW32__) && (defined(__x86_64__) || defined(_M_X64) || defined(__i386) || defined(_M_IX86))
|
||||||
float M_raw[24];
|
float M_raw[24];
|
||||||
#endif
|
#endif
|
||||||
public:
|
public:
|
||||||
@ -409,7 +409,7 @@ namespace core
|
|||||||
bool equals(const core::CMatrix4<T>& other, const T tolerance=(T)ROUNDING_ERROR_f64) const;
|
bool equals(const core::CMatrix4<T>& other, const T tolerance=(T)ROUNDING_ERROR_f64) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
#if defined(WIN32) && (defined(__x86_64__) || defined(_M_X64) || defined(__i386) || defined(_M_IX86))
|
#if defined(WIN32) && !defined(__MINGW32__) && (defined(__x86_64__) || defined(_M_X64) || defined(__i386) || defined(_M_IX86))
|
||||||
//! Matrix data, stored in row-major order
|
//! Matrix data, stored in row-major order
|
||||||
T* M = (T*)((uintptr_t)&M_raw[4] & ~0xF);
|
T* M = (T*)((uintptr_t)&M_raw[4] & ~0xF);
|
||||||
#else
|
#else
|
||||||
@ -669,7 +669,7 @@ namespace core
|
|||||||
const T *m1 = other_a.M;
|
const T *m1 = other_a.M;
|
||||||
const T *m2 = other_b.M;
|
const T *m2 = other_b.M;
|
||||||
|
|
||||||
#if defined(WIN32) && (defined(__x86_64__) || defined(_M_X64) || defined(__i386) || defined(_M_IX86))
|
#if defined(WIN32) && !defined(__MINGW32__) && (defined(__x86_64__) || defined(_M_X64) || defined(__i386) || defined(_M_IX86))
|
||||||
// From http://drrobsjournal.blogspot.fr/2012/10/fast-simd-4x4-matrix-multiplication.html
|
// From http://drrobsjournal.blogspot.fr/2012/10/fast-simd-4x4-matrix-multiplication.html
|
||||||
// Use unaligned load/store
|
// Use unaligned load/store
|
||||||
|
|
||||||
@ -1019,13 +1019,13 @@ namespace core
|
|||||||
const f64 t = 1.0 - c;
|
const f64 t = 1.0 - c;
|
||||||
|
|
||||||
const f64 tx = t * axis.X;
|
const f64 tx = t * axis.X;
|
||||||
const f64 ty = t * axis.Y;
|
const f64 ty = t * axis.Y;
|
||||||
const f64 tz = t * axis.Z;
|
const f64 tz = t * axis.Z;
|
||||||
|
|
||||||
const f64 sx = s * axis.X;
|
const f64 sx = s * axis.X;
|
||||||
const f64 sy = s * axis.Y;
|
const f64 sy = s * axis.Y;
|
||||||
const f64 sz = s * axis.Z;
|
const f64 sz = s * axis.Z;
|
||||||
|
|
||||||
M[0] = (T)(tx * axis.X + c);
|
M[0] = (T)(tx * axis.X + c);
|
||||||
M[1] = (T)(tx * axis.Y + sz);
|
M[1] = (T)(tx * axis.Y + sz);
|
||||||
M[2] = (T)(tx * axis.Z - sy);
|
M[2] = (T)(tx * axis.Z - sy);
|
||||||
@ -1385,7 +1385,7 @@ namespace core
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
const CMatrix4<T> &m = *this;
|
const CMatrix4<T> &m = *this;
|
||||||
#if defined(WIN32) && (defined(__x86_64__) || defined(_M_X64) || defined(__i386) || defined(_M_IX86))
|
#if defined(WIN32) && !defined(__MINGW32__) && (defined(__x86_64__) || defined(_M_X64) || defined(__i386) || defined(_M_IX86))
|
||||||
float *src = (float*)m.pointer();
|
float *src = (float*)m.pointer();
|
||||||
float *dst = (float*)out.pointer();
|
float *dst = (float*)out.pointer();
|
||||||
// from http://www.intel.com/design/pentiumiii/sml/245043.htm
|
// from http://www.intel.com/design/pentiumiii/sml/245043.htm
|
||||||
|
@ -104,7 +104,10 @@ void initGL()
|
|||||||
if (is_gl_init)
|
if (is_gl_init)
|
||||||
return;
|
return;
|
||||||
is_gl_init = true;
|
is_gl_init = true;
|
||||||
|
// For Mesa extension reporting
|
||||||
|
#ifdef UNIX
|
||||||
glewExperimental = GL_TRUE;
|
glewExperimental = GL_TRUE;
|
||||||
|
#endif
|
||||||
GLenum err = glewInit();
|
GLenum err = glewInit();
|
||||||
if (GLEW_OK != err)
|
if (GLEW_OK != err)
|
||||||
Log::fatal("GLEW", "Glew initialisation failed with error %s", glewGetErrorString(err));
|
Log::fatal("GLEW", "Glew initialisation failed with error %s", glewGetErrorString(err));
|
||||||
@ -217,6 +220,8 @@ void setAttribute(AttributeType Tp, GLuint ProgramID)
|
|||||||
glBindAttribLocation(ProgramID, 1, "lifetime");
|
glBindAttribLocation(ProgramID, 1, "lifetime");
|
||||||
glBindAttribLocation(ProgramID, 2, "size");
|
glBindAttribLocation(ProgramID, 2, "size");
|
||||||
glBindAttribLocation(ProgramID, 4, "quadcorner");
|
glBindAttribLocation(ProgramID, 4, "quadcorner");
|
||||||
|
glBindAttribLocation(ProgramID, 5, "rotationvec");
|
||||||
|
glBindAttribLocation(ProgramID, 6, "anglespeed");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -247,182 +252,6 @@ GLuint LoadTFBProgram(const char * vertex_file_path, const char **varyings, unsi
|
|||||||
return Program;
|
return Program;
|
||||||
}
|
}
|
||||||
|
|
||||||
GLuint getTextureGLuint(irr::video::ITexture *tex)
|
|
||||||
{
|
|
||||||
return static_cast<irr::video::COpenGLTexture*>(tex)->getOpenGLTextureName();
|
|
||||||
}
|
|
||||||
|
|
||||||
GLuint getDepthTexture(irr::video::ITexture *tex)
|
|
||||||
{
|
|
||||||
assert(tex->isRenderTarget());
|
|
||||||
return static_cast<irr::video::COpenGLFBOTexture*>(tex)->DepthBufferTexture;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::set<irr::video::ITexture *> AlreadyTransformedTexture;
|
|
||||||
void resetTextureTable()
|
|
||||||
{
|
|
||||||
AlreadyTransformedTexture.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
void compressTexture(irr::video::ITexture *tex, bool srgb, bool premul_alpha)
|
|
||||||
{
|
|
||||||
if (AlreadyTransformedTexture.find(tex) != AlreadyTransformedTexture.end())
|
|
||||||
return;
|
|
||||||
AlreadyTransformedTexture.insert(tex);
|
|
||||||
|
|
||||||
glBindTexture(GL_TEXTURE_2D, getTextureGLuint(tex));
|
|
||||||
|
|
||||||
std::string cached_file;
|
|
||||||
if (UserConfigParams::m_texture_compression)
|
|
||||||
{
|
|
||||||
// Try to retrieve the compressed texture in cache
|
|
||||||
std::string tex_name = irr_driver->getTextureName(tex);
|
|
||||||
if (!tex_name.empty()) {
|
|
||||||
cached_file = file_manager->getTextureCacheLocation(tex_name) + ".gltz";
|
|
||||||
if (!file_manager->fileIsNewer(tex_name, cached_file)) {
|
|
||||||
if (loadCompressedTexture(cached_file))
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t w = tex->getSize().Width, h = tex->getSize().Height;
|
|
||||||
unsigned char *data = new unsigned char[w * h * 4];
|
|
||||||
memcpy(data, tex->lock(), w * h * 4);
|
|
||||||
tex->unlock();
|
|
||||||
unsigned internalFormat, Format;
|
|
||||||
if (tex->hasAlpha())
|
|
||||||
Format = GL_BGRA;
|
|
||||||
else
|
|
||||||
Format = GL_BGR;
|
|
||||||
|
|
||||||
if (premul_alpha)
|
|
||||||
{
|
|
||||||
for (unsigned i = 0; i < w * h; i++)
|
|
||||||
{
|
|
||||||
float alpha = data[4 * i + 3];
|
|
||||||
if (alpha > 0.)
|
|
||||||
alpha = pow(alpha / 255.f, 1.f / 2.2f);
|
|
||||||
data[4 * i ] = (unsigned char)(data[4 * i ] * alpha);
|
|
||||||
data[4 * i + 1] = (unsigned char)(data[4 * i + 1] * alpha);
|
|
||||||
data[4 * i + 2] = (unsigned char)(data[4 * i + 2] * alpha);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!UserConfigParams::m_texture_compression)
|
|
||||||
{
|
|
||||||
if (srgb)
|
|
||||||
internalFormat = (tex->hasAlpha()) ? GL_SRGB_ALPHA : GL_SRGB;
|
|
||||||
else
|
|
||||||
internalFormat = (tex->hasAlpha()) ? GL_RGBA : GL_RGB;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (srgb)
|
|
||||||
internalFormat = (tex->hasAlpha()) ? GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT : GL_COMPRESSED_SRGB_S3TC_DXT1_EXT;
|
|
||||||
else
|
|
||||||
internalFormat = (tex->hasAlpha()) ? GL_COMPRESSED_RGBA_S3TC_DXT5_EXT : GL_COMPRESSED_RGB_S3TC_DXT1_EXT;
|
|
||||||
}
|
|
||||||
glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, w, h, 0, Format, GL_UNSIGNED_BYTE, (GLvoid *)data);
|
|
||||||
glGenerateMipmap(GL_TEXTURE_2D);
|
|
||||||
delete[] data;
|
|
||||||
|
|
||||||
if (UserConfigParams::m_texture_compression && !cached_file.empty())
|
|
||||||
{
|
|
||||||
// Save the compressed texture in the cache for later use.
|
|
||||||
saveCompressedTexture(cached_file);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
/** Try to load a compressed texture from the given file name.
|
|
||||||
* Data in the specified file need to have a specific format. See the
|
|
||||||
* saveCompressedTexture() function for a description of the format.
|
|
||||||
* \return true if the loading succeeded, false otherwise.
|
|
||||||
* \see saveCompressedTexture
|
|
||||||
*/
|
|
||||||
bool loadCompressedTexture(const std::string& compressed_tex)
|
|
||||||
{
|
|
||||||
std::ifstream ifs(compressed_tex.c_str(), std::ios::in | std::ios::binary);
|
|
||||||
if (!ifs.is_open())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
int internal_format;
|
|
||||||
int w, h;
|
|
||||||
int size = -1;
|
|
||||||
ifs.read((char*)&internal_format, sizeof(int));
|
|
||||||
ifs.read((char*)&w, sizeof(int));
|
|
||||||
ifs.read((char*)&h, sizeof(int));
|
|
||||||
ifs.read((char*)&size, sizeof(int));
|
|
||||||
|
|
||||||
if (ifs.fail() || size == -1)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
char *data = new char[size];
|
|
||||||
ifs.read(data, size);
|
|
||||||
if (!ifs.fail())
|
|
||||||
{
|
|
||||||
glCompressedTexImage2D(GL_TEXTURE_2D, 0, internal_format,
|
|
||||||
w, h, 0, size, (GLvoid*)data);
|
|
||||||
glGenerateMipmap(GL_TEXTURE_2D);
|
|
||||||
delete[] data;
|
|
||||||
ifs.close();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
delete[] data;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
/** Try to save the last texture sent to glTexImage2D in a file of the given
|
|
||||||
* file name. This function should only be used for textures sent to
|
|
||||||
* glTexImage2D with a compressed internal format as argument.<br>
|
|
||||||
* \note The following format is used to save the compressed texture:<br>
|
|
||||||
* <internal-format><width><height><size><data> <br>
|
|
||||||
* The first four elements are integers and the last one is stored
|
|
||||||
* on \c size bytes.
|
|
||||||
* \see loadCompressedTexture
|
|
||||||
*/
|
|
||||||
void saveCompressedTexture(const std::string& compressed_tex)
|
|
||||||
{
|
|
||||||
int internal_format, width, height, size, compressionSuccessful;
|
|
||||||
glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_INTERNAL_FORMAT, (GLint *)&internal_format);
|
|
||||||
glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, (GLint *)&width);
|
|
||||||
glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, (GLint *)&height);
|
|
||||||
glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_COMPRESSED, (GLint *)&compressionSuccessful);
|
|
||||||
if (!compressionSuccessful)
|
|
||||||
return;
|
|
||||||
glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_COMPRESSED_IMAGE_SIZE, (GLint *)&size);
|
|
||||||
|
|
||||||
char *data = new char[size];
|
|
||||||
glGetCompressedTexImage(GL_TEXTURE_2D, 0, (GLvoid*)data);
|
|
||||||
std::ofstream ofs(compressed_tex.c_str(), std::ios::out | std::ios::binary);
|
|
||||||
if (ofs.is_open())
|
|
||||||
{
|
|
||||||
ofs.write((char*)&internal_format, sizeof(int));
|
|
||||||
ofs.write((char*)&width, sizeof(int));
|
|
||||||
ofs.write((char*)&height, sizeof(int));
|
|
||||||
ofs.write((char*)&size, sizeof(int));
|
|
||||||
ofs.write(data, size);
|
|
||||||
ofs.close();
|
|
||||||
}
|
|
||||||
delete[] data;
|
|
||||||
}
|
|
||||||
|
|
||||||
static unsigned colorcount = 0;
|
|
||||||
|
|
||||||
video::ITexture* getUnicolorTexture(video::SColor c)
|
|
||||||
{
|
|
||||||
video::SColor tmp[4] = {
|
|
||||||
c, c, c, c
|
|
||||||
};
|
|
||||||
video::IImage *img = irr_driver->getVideoDriver()->createImageFromData(video::ECF_A8R8G8B8, core::dimension2d<u32>(2, 2), tmp);
|
|
||||||
img->grab();
|
|
||||||
std::string name("color");
|
|
||||||
name += colorcount++;
|
|
||||||
return irr_driver->getVideoDriver()->addTexture(name.c_str(), img);
|
|
||||||
}
|
|
||||||
|
|
||||||
void setTexture(unsigned TextureUnit, GLuint TextureId, GLenum MagFilter, GLenum MinFilter, bool allowAF)
|
void setTexture(unsigned TextureUnit, GLuint TextureId, GLenum MagFilter, GLenum MinFilter, bool allowAF)
|
||||||
{
|
{
|
||||||
glActiveTexture(GL_TEXTURE0 + TextureUnit);
|
glActiveTexture(GL_TEXTURE0 + TextureUnit);
|
||||||
|
@ -129,13 +129,7 @@ public:
|
|||||||
// core::rect<s32> needs these includes
|
// core::rect<s32> needs these includes
|
||||||
#include <rect.h>
|
#include <rect.h>
|
||||||
#include "utils/vec3.hpp"
|
#include "utils/vec3.hpp"
|
||||||
|
#include "texturemanager.hpp"
|
||||||
GLuint getTextureGLuint(irr::video::ITexture *tex);
|
|
||||||
GLuint getDepthTexture(irr::video::ITexture *tex);
|
|
||||||
void resetTextureTable();
|
|
||||||
void compressTexture(irr::video::ITexture *tex, bool srgb, bool premul_alpha = false);
|
|
||||||
bool loadCompressedTexture(const std::string& compressed_tex);
|
|
||||||
void saveCompressedTexture(const std::string& compressed_tex);
|
|
||||||
|
|
||||||
void draw3DLine(const core::vector3df& start,
|
void draw3DLine(const core::vector3df& start,
|
||||||
const core::vector3df& end, irr::video::SColor color);
|
const core::vector3df& end, irr::video::SColor color);
|
||||||
|
@ -608,7 +608,7 @@ FrameBuffer *PostProcessing::render(scene::ICameraSceneNode * const camnode, boo
|
|||||||
// Grab the sky
|
// Grab the sky
|
||||||
out_fbo->Bind();
|
out_fbo->Bind();
|
||||||
glClear(GL_COLOR_BUFFER_BIT);
|
glClear(GL_COLOR_BUFFER_BIT);
|
||||||
irr_driver->renderSkybox(camnode);
|
// irr_driver->renderSkybox(camnode);
|
||||||
|
|
||||||
// Set the sun's color
|
// Set the sun's color
|
||||||
const SColor col = track->getGodRaysColor();
|
const SColor col = track->getGodRaysColor();
|
||||||
@ -617,9 +617,9 @@ FrameBuffer *PostProcessing::render(scene::ICameraSceneNode * const camnode, boo
|
|||||||
|
|
||||||
// The sun interposer
|
// The sun interposer
|
||||||
STKMeshSceneNode *sun = irr_driver->getSunInterposer();
|
STKMeshSceneNode *sun = irr_driver->getSunInterposer();
|
||||||
|
sun->setGlowColors(col);
|
||||||
sun->setPosition(track->getGodRaysPosition());
|
sun->setPosition(track->getGodRaysPosition());
|
||||||
sun->updateAbsolutePosition();
|
sun->updateAbsolutePosition();
|
||||||
irr_driver->getSceneManager()->drawAll(ESNRP_CAMERA);
|
|
||||||
irr_driver->setPhase(GLOW_PASS);
|
irr_driver->setPhase(GLOW_PASS);
|
||||||
sun->render();
|
sun->render();
|
||||||
glDisable(GL_DEPTH_TEST);
|
glDisable(GL_DEPTH_TEST);
|
||||||
|
@ -628,6 +628,9 @@ void IrrDriver::renderTransparent()
|
|||||||
TexUnit(0, true)), ListAdditiveTransparent::getInstance());
|
TexUnit(0, true)), ListAdditiveTransparent::getInstance());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (unsigned i = 0; i < BillBoardList::getInstance()->size(); i++)
|
||||||
|
BillBoardList::getInstance()->at(i)->render();
|
||||||
|
|
||||||
if (!UserConfigParams::m_dynamic_lights)
|
if (!UserConfigParams::m_dynamic_lights)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -280,6 +280,8 @@ void STKMeshSceneNode::render()
|
|||||||
AbsoluteTransformation.getInverse(invmodel);
|
AbsoluteTransformation.getInverse(invmodel);
|
||||||
|
|
||||||
glDisable(GL_CULL_FACE);
|
glDisable(GL_CULL_FACE);
|
||||||
|
if (update_each_frame && !UserConfigParams::m_dynamic_lights)
|
||||||
|
updatevbo();
|
||||||
if (!spareWhiteTex)
|
if (!spareWhiteTex)
|
||||||
spareWhiteTex = getUnicolorTexture(video::SColor(255, 255, 255, 255));
|
spareWhiteTex = getUnicolorTexture(video::SColor(255, 255, 255, 255));
|
||||||
glUseProgram(MeshShader::ObjectPass2Shader::getInstance()->Program);
|
glUseProgram(MeshShader::ObjectPass2Shader::getInstance()->Program);
|
||||||
@ -294,51 +296,30 @@ void STKMeshSceneNode::render()
|
|||||||
|
|
||||||
if (UserConfigParams::m_azdo)
|
if (UserConfigParams::m_azdo)
|
||||||
{
|
{
|
||||||
irr_driver->IncreaseObjectCount();
|
GLuint64 DiffuseHandle = glGetTextureSamplerHandleARB(irr_driver->getRenderTargetTexture(RTT_DIFFUSE), MeshShader::ObjectPass2Shader::getInstance()->SamplersId[0]);
|
||||||
GLMesh &mesh = GLmeshes[i];
|
if (!glIsTextureHandleResidentARB(DiffuseHandle))
|
||||||
GLenum ptype = mesh.PrimitiveType;
|
glMakeTextureHandleResidentARB(DiffuseHandle);
|
||||||
GLenum itype = mesh.IndexType;
|
|
||||||
size_t count = mesh.IndexCount;
|
|
||||||
|
|
||||||
if (UserConfigParams::m_azdo)
|
GLuint64 SpecularHandle = glGetTextureSamplerHandleARB(irr_driver->getRenderTargetTexture(RTT_SPECULAR), MeshShader::ObjectPass2Shader::getInstance()->SamplersId[1]);
|
||||||
{
|
if (!glIsTextureHandleResidentARB(SpecularHandle))
|
||||||
GLuint64 DiffuseHandle = glGetTextureSamplerHandleARB(irr_driver->getRenderTargetTexture(RTT_DIFFUSE), MeshShader::ObjectPass2Shader::getInstance()->SamplersId[0]);
|
glMakeTextureHandleResidentARB(SpecularHandle);
|
||||||
if (!glIsTextureHandleResidentARB(DiffuseHandle))
|
|
||||||
glMakeTextureHandleResidentARB(DiffuseHandle);
|
|
||||||
|
|
||||||
GLuint64 SpecularHandle = glGetTextureSamplerHandleARB(irr_driver->getRenderTargetTexture(RTT_SPECULAR), MeshShader::ObjectPass2Shader::getInstance()->SamplersId[1]);
|
GLuint64 SSAOHandle = glGetTextureSamplerHandleARB(irr_driver->getRenderTargetTexture(RTT_HALF1_R), MeshShader::ObjectPass2Shader::getInstance()->SamplersId[2]);
|
||||||
if (!glIsTextureHandleResidentARB(SpecularHandle))
|
if (!glIsTextureHandleResidentARB(SSAOHandle))
|
||||||
glMakeTextureHandleResidentARB(SpecularHandle);
|
glMakeTextureHandleResidentARB(SSAOHandle);
|
||||||
|
|
||||||
GLuint64 SSAOHandle = glGetTextureSamplerHandleARB(irr_driver->getRenderTargetTexture(RTT_HALF1_R), MeshShader::ObjectPass2Shader::getInstance()->SamplersId[2]);
|
if (!mesh.TextureHandles[0])
|
||||||
if (!glIsTextureHandleResidentARB(SSAOHandle))
|
mesh.TextureHandles[0] = glGetTextureSamplerHandleARB(getTextureGLuint(spareWhiteTex), MeshShader::TransparentFogShader::getInstance()->SamplersId[0]);
|
||||||
glMakeTextureHandleResidentARB(SSAOHandle);
|
if (!glIsTextureHandleResidentARB(mesh.TextureHandles[0]))
|
||||||
|
glMakeTextureHandleResidentARB(mesh.TextureHandles[0]);
|
||||||
if (!mesh.TextureHandles[0])
|
MeshShader::ObjectPass2Shader::getInstance()->SetTextureHandles(createVector<uint64_t>(DiffuseHandle, SpecularHandle, SSAOHandle, mesh.TextureHandles[0]));
|
||||||
mesh.TextureHandles[0] = glGetTextureSamplerHandleARB(getTextureGLuint(spareWhiteTex), MeshShader::TransparentFogShader::getInstance()->SamplersId[0]);
|
|
||||||
if (!glIsTextureHandleResidentARB(mesh.TextureHandles[0]))
|
|
||||||
glMakeTextureHandleResidentARB(mesh.TextureHandles[0]);
|
|
||||||
MeshShader::ObjectPass2Shader::getInstance()->SetTextureHandles(createVector<uint64_t>(DiffuseHandle, SpecularHandle, SSAOHandle, mesh.TextureHandles[0]));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
MeshShader::ObjectPass2Shader::getInstance()->SetTextureUnits(createVector<GLuint>(
|
|
||||||
irr_driver->getRenderTargetTexture(RTT_DIFFUSE),
|
|
||||||
irr_driver->getRenderTargetTexture(RTT_SPECULAR),
|
|
||||||
irr_driver->getRenderTargetTexture(RTT_HALF1_R),
|
|
||||||
getTextureGLuint(spareWhiteTex)));
|
|
||||||
|
|
||||||
MeshShader::ObjectPass2Shader::getInstance()->setUniforms(AbsoluteTransformation, mesh.TextureMatrix);
|
|
||||||
assert(mesh.vao);
|
|
||||||
glBindVertexArray(mesh.vao);
|
|
||||||
glDrawElements(ptype, count, itype, 0);
|
|
||||||
glBindVertexArray(0);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
MeshShader::ObjectPass2Shader::getInstance()->SetTextureUnits(createVector<GLuint>(
|
MeshShader::ObjectPass2Shader::getInstance()->SetTextureUnits(createVector<GLuint>(
|
||||||
irr_driver->getRenderTargetTexture(RTT_DIFFUSE),
|
irr_driver->getRenderTargetTexture(RTT_DIFFUSE),
|
||||||
irr_driver->getRenderTargetTexture(RTT_SPECULAR),
|
irr_driver->getRenderTargetTexture(RTT_SPECULAR),
|
||||||
irr_driver->getRenderTargetTexture(RTT_HALF1_R),
|
irr_driver->getRenderTargetTexture(RTT_HALF1_R),
|
||||||
getTextureGLuint(mesh.textures[0])));
|
getTextureGLuint(spareWhiteTex)));
|
||||||
MeshShader::ObjectPass2Shader::getInstance()->setUniforms(AbsoluteTransformation, mesh.TextureMatrix);
|
MeshShader::ObjectPass2Shader::getInstance()->setUniforms(AbsoluteTransformation, mesh.TextureMatrix);
|
||||||
assert(mesh.vao);
|
assert(mesh.vao);
|
||||||
glBindVertexArray(mesh.vao);
|
glBindVertexArray(mesh.vao);
|
||||||
|
@ -117,24 +117,7 @@ void FillInstances(const std::unordered_map<scene::IMeshBuffer *, std::vector<st
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static
|
|
||||||
void FillInstancesGrass(const std::unordered_map<scene::IMeshBuffer *, std::vector<std::pair<GLMesh *, scene::ISceneNode*> > > &GatheredGLMesh, std::vector<GLMesh *> &InstancedList,
|
|
||||||
InstanceData *InstanceBuffer, DrawElementsIndirectCommand *CommandBuffer, size_t &InstanceBufferOffset, size_t &CommandBufferOffset, const core::vector3df &dir, size_t &PolyCount,
|
|
||||||
std::function<bool (const scene::ISceneNode *)> cull_func)
|
|
||||||
{
|
|
||||||
auto It = GatheredGLMesh.begin(), E = GatheredGLMesh.end();
|
|
||||||
SunLightProvider * const cb = (SunLightProvider *)irr_driver->getCallback(ES_SUNLIGHT);
|
|
||||||
for (; It != E; ++It)
|
|
||||||
{
|
|
||||||
FillInstances_impl(It->second, InstanceBuffer, CommandBuffer, InstanceBufferOffset, CommandBufferOffset, PolyCount, cull_func);
|
|
||||||
if (!UserConfigParams::m_azdo)
|
|
||||||
InstancedList.push_back(It->second.front().first);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static std::unordered_map <scene::IMeshBuffer *, std::vector<std::pair<GLMesh *, scene::ISceneNode*> > > MeshForSolidPass[MAT_COUNT];
|
static std::unordered_map <scene::IMeshBuffer *, std::vector<std::pair<GLMesh *, scene::ISceneNode*> > > MeshForSolidPass[MAT_COUNT];
|
||||||
static std::unordered_map <scene::IMeshBuffer *, std::vector<std::pair<GLMesh *, scene::ISceneNode*> > > MeshForShadowPass[4][MAT_COUNT];
|
|
||||||
static std::unordered_map <scene::IMeshBuffer *, std::vector<std::pair<GLMesh *, scene::ISceneNode*> > > MeshForRSMPass[MAT_COUNT];
|
|
||||||
static std::unordered_map <scene::IMeshBuffer *, std::vector<std::pair<GLMesh *, STKMeshCommon *> > > MeshForGlowPass;
|
static std::unordered_map <scene::IMeshBuffer *, std::vector<std::pair<GLMesh *, STKMeshCommon *> > > MeshForGlowPass;
|
||||||
static std::vector <STKMeshCommon *> DeferredUpdate;
|
static std::vector <STKMeshCommon *> DeferredUpdate;
|
||||||
|
|
||||||
@ -151,7 +134,7 @@ bool isBoxInFrontOfPlane(const core::plane3df &plane, const core::vector3df edge
|
|||||||
}
|
}
|
||||||
|
|
||||||
static
|
static
|
||||||
bool isCulled(const scene::ICameraSceneNode *cam, const scene::ISceneNode *node)
|
bool isCulledPrecise(const scene::ICameraSceneNode *cam, const scene::ISceneNode *node)
|
||||||
{
|
{
|
||||||
if (!node->getAutomaticCulling())
|
if (!node->getAutomaticCulling())
|
||||||
return false;
|
return false;
|
||||||
@ -172,8 +155,20 @@ bool isCulled(const scene::ICameraSceneNode *cam, const scene::ISceneNode *node)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
bool isCulledFast(const scene::ICameraSceneNode *cam, const scene::ISceneNode *node)
|
||||||
|
{
|
||||||
|
if (!node->getAutomaticCulling())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
core::aabbox3d<f32> tbox = node->getBoundingBox();
|
||||||
|
node->getAbsoluteTransformation().transformBoxEx(tbox);
|
||||||
|
return !(tbox.intersectsWithBox(cam->getViewFrustum()->getBoundingBox()));
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
handleSTKCommon(scene::ISceneNode *Node, std::vector<scene::ISceneNode *> *ImmediateDraw)
|
handleSTKCommon(scene::ISceneNode *Node, std::vector<scene::ISceneNode *> *ImmediateDraw,
|
||||||
|
const scene::ICameraSceneNode *cam, scene::ICameraSceneNode *shadowcam[4], const scene::ICameraSceneNode *rsmcam)
|
||||||
{
|
{
|
||||||
STKMeshCommon *node = dynamic_cast<STKMeshCommon*>(Node);
|
STKMeshCommon *node = dynamic_cast<STKMeshCommon*>(Node);
|
||||||
if (!node)
|
if (!node)
|
||||||
@ -187,7 +182,6 @@ handleSTKCommon(scene::ISceneNode *Node, std::vector<scene::ISceneNode *> *Immed
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Transparent
|
// Transparent
|
||||||
GLMesh *mesh;
|
GLMesh *mesh;
|
||||||
if (World::getWorld() && World::getWorld()->isFogEnabled())
|
if (World::getWorld() && World::getWorld()->isFogEnabled())
|
||||||
@ -258,6 +252,8 @@ handleSTKCommon(scene::ISceneNode *Node, std::vector<scene::ISceneNode *> *Immed
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
if (isCulledFast(cam, Node))
|
||||||
|
continue;
|
||||||
core::matrix4 ModelMatrix = Node->getAbsoluteTransformation(), InvModelMatrix;
|
core::matrix4 ModelMatrix = Node->getAbsoluteTransformation(), InvModelMatrix;
|
||||||
ModelMatrix.getInverse(InvModelMatrix);
|
ModelMatrix.getInverse(InvModelMatrix);
|
||||||
|
|
||||||
@ -299,13 +295,10 @@ handleSTKCommon(scene::ISceneNode *Node, std::vector<scene::ISceneNode *> *Immed
|
|||||||
{
|
{
|
||||||
for (unsigned cascade = 0; cascade < 4; ++cascade)
|
for (unsigned cascade = 0; cascade < 4; ++cascade)
|
||||||
{
|
{
|
||||||
if (irr_driver->hasARB_draw_indirect())
|
if (!irr_driver->hasARB_draw_indirect())
|
||||||
{
|
|
||||||
for_in(mesh, node->MeshSolidMaterial[Mat])
|
|
||||||
MeshForShadowPass[cascade][Mat][mesh->mb].emplace_back(mesh, Node);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
|
if (isCulledFast(shadowcam[cascade], Node))
|
||||||
|
continue;
|
||||||
core::matrix4 ModelMatrix = Node->getAbsoluteTransformation(), InvModelMatrix;
|
core::matrix4 ModelMatrix = Node->getAbsoluteTransformation(), InvModelMatrix;
|
||||||
ModelMatrix.getInverse(InvModelMatrix);
|
ModelMatrix.getInverse(InvModelMatrix);
|
||||||
|
|
||||||
@ -347,10 +340,8 @@ handleSTKCommon(scene::ISceneNode *Node, std::vector<scene::ISceneNode *> *Immed
|
|||||||
{
|
{
|
||||||
if (irr_driver->hasARB_draw_indirect())
|
if (irr_driver->hasARB_draw_indirect())
|
||||||
{
|
{
|
||||||
for_in(mesh, node->MeshSolidMaterial[Mat])
|
if (Mat == MAT_SPLATTING)
|
||||||
if (Mat != MAT_SPLATTING)
|
for_in(mesh, node->MeshSolidMaterial[Mat])
|
||||||
MeshForRSMPass[Mat][mesh->mb].emplace_back(mesh, Node);
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
core::matrix4 ModelMatrix = Node->getAbsoluteTransformation(), InvModelMatrix;
|
core::matrix4 ModelMatrix = Node->getAbsoluteTransformation(), InvModelMatrix;
|
||||||
ModelMatrix.getInverse(InvModelMatrix);
|
ModelMatrix.getInverse(InvModelMatrix);
|
||||||
@ -359,6 +350,8 @@ handleSTKCommon(scene::ISceneNode *Node, std::vector<scene::ISceneNode *> *Immed
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
if (isCulledFast(rsmcam, Node))
|
||||||
|
continue;
|
||||||
core::matrix4 ModelMatrix = Node->getAbsoluteTransformation(), InvModelMatrix;
|
core::matrix4 ModelMatrix = Node->getAbsoluteTransformation(), InvModelMatrix;
|
||||||
ModelMatrix.getInverse(InvModelMatrix);
|
ModelMatrix.getInverse(InvModelMatrix);
|
||||||
|
|
||||||
@ -398,27 +391,34 @@ handleSTKCommon(scene::ISceneNode *Node, std::vector<scene::ISceneNode *> *Immed
|
|||||||
|
|
||||||
static void
|
static void
|
||||||
parseSceneManager(core::list<scene::ISceneNode*> List, std::vector<scene::ISceneNode *> *ImmediateDraw,
|
parseSceneManager(core::list<scene::ISceneNode*> List, std::vector<scene::ISceneNode *> *ImmediateDraw,
|
||||||
scene::ICameraSceneNode* cam)
|
const scene::ICameraSceneNode* cam, scene::ICameraSceneNode *shadow_cam[4], const scene::ICameraSceneNode *rsmcam)
|
||||||
{
|
{
|
||||||
core::list<scene::ISceneNode*>::Iterator I = List.begin(), E = List.end();
|
core::list<scene::ISceneNode*>::Iterator I = List.begin(), E = List.end();
|
||||||
for (; I != E; ++I)
|
for (; I != E; ++I)
|
||||||
{
|
{
|
||||||
if (LODNode *node = dynamic_cast<LODNode *>(*I))
|
if (LODNode *node = dynamic_cast<LODNode *>(*I))
|
||||||
node->updateVisibility();
|
node->updateVisibility();
|
||||||
|
(*I)->updateAbsolutePosition();
|
||||||
if (!(*I)->isVisible())
|
if (!(*I)->isVisible())
|
||||||
continue;
|
continue;
|
||||||
(*I)->updateAbsolutePosition();
|
|
||||||
|
|
||||||
if (ParticleSystemProxy *node = dynamic_cast<ParticleSystemProxy *>(*I))
|
if (ParticleSystemProxy *node = dynamic_cast<ParticleSystemProxy *>(*I))
|
||||||
{
|
{
|
||||||
if (!isCulled(cam, *I) && node->update())
|
if (!isCulledPrecise(cam, *I) && node->update())
|
||||||
ParticlesList::getInstance()->push_back(node);
|
ParticlesList::getInstance()->push_back(node);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
handleSTKCommon(*I, ImmediateDraw);
|
if (STKBillboard *node = dynamic_cast<STKBillboard *>(*I))
|
||||||
|
{
|
||||||
|
if (!isCulledPrecise(cam, *I))
|
||||||
|
BillBoardList::getInstance()->push_back(node);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
parseSceneManager((*I)->getChildren(), ImmediateDraw, cam);
|
handleSTKCommon(*I, ImmediateDraw, cam, shadow_cam, rsmcam);
|
||||||
|
|
||||||
|
parseSceneManager((*I)->getChildren(), ImmediateDraw, cam, shadow_cam, rsmcam);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -429,22 +429,12 @@ GenDrawCalls(unsigned cascade, std::vector<GLMesh *> &InstancedList,
|
|||||||
std::function<bool(const scene::ISceneNode *)> shadowculling = [&](const scene::ISceneNode *nd) {return dynamic_cast<const STKMeshCommon*>(nd)->isCulledForShadowCam(cascade); };
|
std::function<bool(const scene::ISceneNode *)> shadowculling = [&](const scene::ISceneNode *nd) {return dynamic_cast<const STKMeshCommon*>(nd)->isCulledForShadowCam(cascade); };
|
||||||
if (irr_driver->hasARB_draw_indirect())
|
if (irr_driver->hasARB_draw_indirect())
|
||||||
ShadowPassCmd::getInstance()->Offset[cascade][Mat] = CommandBufferOffset; // Store command buffer offset
|
ShadowPassCmd::getInstance()->Offset[cascade][Mat] = CommandBufferOffset; // Store command buffer offset
|
||||||
FillInstances(MeshForShadowPass[cascade][Mat], InstancedList, InstanceBuffer, CommandBuffer, InstanceBufferOffset, CommandBufferOffset, PolyCount, shadowculling);
|
FillInstances(MeshForSolidPass[Mat], InstancedList, InstanceBuffer, CommandBuffer, InstanceBufferOffset, CommandBufferOffset, PolyCount, shadowculling);
|
||||||
if (UserConfigParams::m_azdo)
|
if (UserConfigParams::m_azdo)
|
||||||
ShadowPassCmd::getInstance()->Size[cascade][Mat] = CommandBufferOffset - ShadowPassCmd::getInstance()->Offset[cascade][Mat];
|
ShadowPassCmd::getInstance()->Size[cascade][Mat] = CommandBufferOffset - ShadowPassCmd::getInstance()->Offset[cascade][Mat];
|
||||||
}
|
}
|
||||||
|
|
||||||
template<MeshMaterial Mat> static void
|
int enableOpenMP;
|
||||||
GenDrawCallsGrass(unsigned cascade, std::vector<GLMesh *> &InstancedList,
|
|
||||||
InstanceData *InstanceBuffer, DrawElementsIndirectCommand *CommandBuffer, size_t &InstanceBufferOffset, size_t &CommandBufferOffset, const core::vector3df &dir, size_t &PolyCount)
|
|
||||||
{
|
|
||||||
std::function<bool(const scene::ISceneNode *)> shadowculling = [&](const scene::ISceneNode *nd) {return dynamic_cast<const STKMeshCommon*>(nd)->isCulledForShadowCam(cascade); };
|
|
||||||
if (irr_driver->hasARB_draw_indirect())
|
|
||||||
ShadowPassCmd::getInstance()->Offset[cascade][Mat] = CommandBufferOffset; // Store command buffer offset
|
|
||||||
FillInstancesGrass(MeshForShadowPass[cascade][Mat], InstancedList, InstanceBuffer, CommandBuffer, InstanceBufferOffset, CommandBufferOffset, dir, PolyCount, shadowculling);
|
|
||||||
if (UserConfigParams::m_azdo)
|
|
||||||
ShadowPassCmd::getInstance()->Size[cascade][Mat] = CommandBufferOffset - ShadowPassCmd::getInstance()->Offset[cascade][Mat];
|
|
||||||
}
|
|
||||||
|
|
||||||
void IrrDriver::PrepareDrawCalls(scene::ICameraSceneNode *camnode)
|
void IrrDriver::PrepareDrawCalls(scene::ICameraSceneNode *camnode)
|
||||||
{
|
{
|
||||||
@ -465,32 +455,28 @@ void IrrDriver::PrepareDrawCalls(scene::ICameraSceneNode *camnode)
|
|||||||
ListMatSplatting::getInstance()->clear();
|
ListMatSplatting::getInstance()->clear();
|
||||||
|
|
||||||
ImmediateDrawList::getInstance()->clear();
|
ImmediateDrawList::getInstance()->clear();
|
||||||
|
BillBoardList::getInstance()->clear();
|
||||||
ParticlesList::getInstance()->clear();
|
ParticlesList::getInstance()->clear();
|
||||||
ListInstancedGlow::getInstance()->clear();
|
ListInstancedGlow::getInstance()->clear();
|
||||||
|
|
||||||
for (unsigned Mat = 0; Mat < MAT_COUNT; ++Mat)
|
for (unsigned Mat = 0; Mat < MAT_COUNT; ++Mat)
|
||||||
{
|
|
||||||
MeshForSolidPass[Mat].clear();
|
MeshForSolidPass[Mat].clear();
|
||||||
MeshForRSMPass[Mat].clear();
|
|
||||||
for (unsigned cascade = 0; cascade < 4; ++cascade)
|
|
||||||
MeshForShadowPass[cascade][Mat].clear();
|
|
||||||
}
|
|
||||||
MeshForGlowPass.clear();
|
MeshForGlowPass.clear();
|
||||||
DeferredUpdate.clear();
|
DeferredUpdate.clear();
|
||||||
core::list<scene::ISceneNode*> List = m_scene_manager->getRootSceneNode()->getChildren();
|
core::list<scene::ISceneNode*> List = m_scene_manager->getRootSceneNode()->getChildren();
|
||||||
|
|
||||||
parseSceneManager(List, ImmediateDrawList::getInstance(), camnode);
|
parseSceneManager(List, ImmediateDrawList::getInstance(), camnode, m_shadow_camnodes, m_suncam);
|
||||||
|
|
||||||
#pragma omp parallel for
|
#pragma omp parallel for
|
||||||
for (int i = 0; i < (int)DeferredUpdate.size(); i++)
|
for (int i = 0; i < (int)DeferredUpdate.size(); i++)
|
||||||
{
|
{
|
||||||
scene::ISceneNode *node = dynamic_cast<scene::ISceneNode *>(DeferredUpdate[i]);
|
scene::ISceneNode *node = dynamic_cast<scene::ISceneNode *>(DeferredUpdate[i]);
|
||||||
DeferredUpdate[i]->setCulledForPlayerCam(isCulled(camnode, node));
|
DeferredUpdate[i]->setCulledForPlayerCam(isCulledPrecise(camnode, node));
|
||||||
DeferredUpdate[i]->setCulledForRSMCam(isCulled(m_suncam, node));
|
DeferredUpdate[i]->setCulledForRSMCam(isCulledPrecise(m_suncam, node));
|
||||||
DeferredUpdate[i]->setCulledForShadowCam(0, isCulled(m_shadow_camnodes[0], node));
|
DeferredUpdate[i]->setCulledForShadowCam(0, isCulledPrecise(m_shadow_camnodes[0], node));
|
||||||
DeferredUpdate[i]->setCulledForShadowCam(1, isCulled(m_shadow_camnodes[1], node));
|
DeferredUpdate[i]->setCulledForShadowCam(1, isCulledPrecise(m_shadow_camnodes[1], node));
|
||||||
DeferredUpdate[i]->setCulledForShadowCam(2, isCulled(m_shadow_camnodes[2], node));
|
DeferredUpdate[i]->setCulledForShadowCam(2, isCulledPrecise(m_shadow_camnodes[2], node));
|
||||||
DeferredUpdate[i]->setCulledForShadowCam(3, isCulled(m_shadow_camnodes[3], node));
|
DeferredUpdate[i]->setCulledForShadowCam(3, isCulledPrecise(m_shadow_camnodes[3], node));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add a 1 s timeout
|
// Add a 1 s timeout
|
||||||
@ -541,7 +527,10 @@ void IrrDriver::PrepareDrawCalls(scene::ICameraSceneNode *camnode)
|
|||||||
ShadowCmdBuffer = ShadowPassCmd::getInstance()->Ptr;
|
ShadowCmdBuffer = ShadowPassCmd::getInstance()->Ptr;
|
||||||
GlowCmdBuffer = GlowPassCmd::getInstance()->Ptr;
|
GlowCmdBuffer = GlowPassCmd::getInstance()->Ptr;
|
||||||
RSMCmdBuffer = RSMPassCmd::getInstance()->Ptr;
|
RSMCmdBuffer = RSMPassCmd::getInstance()->Ptr;
|
||||||
|
enableOpenMP = 1;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
enableOpenMP = 0;
|
||||||
|
|
||||||
ListInstancedMatDefault::getInstance()->clear();
|
ListInstancedMatDefault::getInstance()->clear();
|
||||||
ListInstancedMatAlphaRef::getInstance()->clear();
|
ListInstancedMatAlphaRef::getInstance()->clear();
|
||||||
@ -556,7 +545,7 @@ void IrrDriver::PrepareDrawCalls(scene::ICameraSceneNode *camnode)
|
|||||||
PROFILER_PUSH_CPU_MARKER("- Draw Command upload", 0xFF, 0x0, 0xFF);
|
PROFILER_PUSH_CPU_MARKER("- Draw Command upload", 0xFF, 0x0, 0xFF);
|
||||||
|
|
||||||
auto playercamculling = [](const scene::ISceneNode *nd) {return dynamic_cast<const STKMeshCommon*>(nd)->isCulledForPlayerCam(); };
|
auto playercamculling = [](const scene::ISceneNode *nd) {return dynamic_cast<const STKMeshCommon*>(nd)->isCulledForPlayerCam(); };
|
||||||
#pragma omp parallel sections
|
#pragma omp parallel sections if(enableOpenMP)
|
||||||
{
|
{
|
||||||
#pragma omp section
|
#pragma omp section
|
||||||
{
|
{
|
||||||
@ -597,7 +586,7 @@ void IrrDriver::PrepareDrawCalls(scene::ICameraSceneNode *camnode)
|
|||||||
|
|
||||||
// Grass
|
// Grass
|
||||||
SolidPassCmd::getInstance()->Offset[MAT_GRASS] = current_cmd;
|
SolidPassCmd::getInstance()->Offset[MAT_GRASS] = current_cmd;
|
||||||
FillInstancesGrass(MeshForSolidPass[MAT_GRASS], ListInstancedMatGrass::getInstance()->SolidPass, InstanceBuffer, CmdBuffer, offset, current_cmd, windDir, SolidPoly, playercamculling);
|
FillInstances(MeshForSolidPass[MAT_GRASS], ListInstancedMatGrass::getInstance()->SolidPass, InstanceBuffer, CmdBuffer, offset, current_cmd, SolidPoly, playercamculling);
|
||||||
SolidPassCmd::getInstance()->Size[MAT_GRASS] = current_cmd - SolidPassCmd::getInstance()->Offset[MAT_GRASS];
|
SolidPassCmd::getInstance()->Size[MAT_GRASS] = current_cmd - SolidPassCmd::getInstance()->Offset[MAT_GRASS];
|
||||||
|
|
||||||
if (!irr_driver->hasBufferStorageExtension())
|
if (!irr_driver->hasBufferStorageExtension())
|
||||||
@ -667,7 +656,7 @@ void IrrDriver::PrepareDrawCalls(scene::ICameraSceneNode *camnode)
|
|||||||
// Mat Detail
|
// Mat Detail
|
||||||
GenDrawCalls<MAT_DETAIL>(i, ListInstancedMatDetails::getInstance()->Shadows[i], ShadowInstanceBuffer, ShadowCmdBuffer, offset, current_cmd, ShadowPoly);
|
GenDrawCalls<MAT_DETAIL>(i, ListInstancedMatDetails::getInstance()->Shadows[i], ShadowInstanceBuffer, ShadowCmdBuffer, offset, current_cmd, ShadowPoly);
|
||||||
// Mat Grass
|
// Mat Grass
|
||||||
GenDrawCallsGrass<MAT_GRASS>(i, ListInstancedMatGrass::getInstance()->Shadows[i], ShadowInstanceBuffer, ShadowCmdBuffer, offset, current_cmd, windDir, ShadowPoly);
|
GenDrawCalls<MAT_GRASS>(i, ListInstancedMatGrass::getInstance()->Shadows[i], ShadowInstanceBuffer, ShadowCmdBuffer, offset, current_cmd, ShadowPoly);
|
||||||
}
|
}
|
||||||
if (!irr_driver->hasBufferStorageExtension())
|
if (!irr_driver->hasBufferStorageExtension())
|
||||||
{
|
{
|
||||||
@ -689,23 +678,23 @@ void IrrDriver::PrepareDrawCalls(scene::ICameraSceneNode *camnode)
|
|||||||
|
|
||||||
// Default Material
|
// Default Material
|
||||||
RSMPassCmd::getInstance()->Offset[MAT_DEFAULT] = current_cmd;
|
RSMPassCmd::getInstance()->Offset[MAT_DEFAULT] = current_cmd;
|
||||||
FillInstances(MeshForRSMPass[MAT_DEFAULT], ListInstancedMatDefault::getInstance()->RSM, RSMInstanceBuffer, RSMCmdBuffer, offset, current_cmd, MiscPoly, rsmcamculling);
|
FillInstances(MeshForSolidPass[MAT_DEFAULT], ListInstancedMatDefault::getInstance()->RSM, RSMInstanceBuffer, RSMCmdBuffer, offset, current_cmd, MiscPoly, rsmcamculling);
|
||||||
RSMPassCmd::getInstance()->Size[MAT_DEFAULT] = current_cmd - RSMPassCmd::getInstance()->Offset[MAT_DEFAULT];
|
RSMPassCmd::getInstance()->Size[MAT_DEFAULT] = current_cmd - RSMPassCmd::getInstance()->Offset[MAT_DEFAULT];
|
||||||
// Alpha Ref
|
// Alpha Ref
|
||||||
RSMPassCmd::getInstance()->Offset[MAT_ALPHA_REF] = current_cmd;
|
RSMPassCmd::getInstance()->Offset[MAT_ALPHA_REF] = current_cmd;
|
||||||
FillInstances(MeshForRSMPass[MAT_ALPHA_REF], ListInstancedMatAlphaRef::getInstance()->RSM, RSMInstanceBuffer, RSMCmdBuffer, offset, current_cmd, MiscPoly, rsmcamculling);
|
FillInstances(MeshForSolidPass[MAT_ALPHA_REF], ListInstancedMatAlphaRef::getInstance()->RSM, RSMInstanceBuffer, RSMCmdBuffer, offset, current_cmd, MiscPoly, rsmcamculling);
|
||||||
RSMPassCmd::getInstance()->Size[MAT_ALPHA_REF] = current_cmd - RSMPassCmd::getInstance()->Offset[MAT_ALPHA_REF];
|
RSMPassCmd::getInstance()->Size[MAT_ALPHA_REF] = current_cmd - RSMPassCmd::getInstance()->Offset[MAT_ALPHA_REF];
|
||||||
// Unlit
|
// Unlit
|
||||||
RSMPassCmd::getInstance()->Offset[MAT_UNLIT] = current_cmd;
|
RSMPassCmd::getInstance()->Offset[MAT_UNLIT] = current_cmd;
|
||||||
FillInstances(MeshForRSMPass[MAT_UNLIT], ListInstancedMatUnlit::getInstance()->RSM, RSMInstanceBuffer, RSMCmdBuffer, offset, current_cmd, MiscPoly, rsmcamculling);
|
FillInstances(MeshForSolidPass[MAT_UNLIT], ListInstancedMatUnlit::getInstance()->RSM, RSMInstanceBuffer, RSMCmdBuffer, offset, current_cmd, MiscPoly, rsmcamculling);
|
||||||
RSMPassCmd::getInstance()->Size[MAT_UNLIT] = current_cmd - RSMPassCmd::getInstance()->Offset[MAT_UNLIT];
|
RSMPassCmd::getInstance()->Size[MAT_UNLIT] = current_cmd - RSMPassCmd::getInstance()->Offset[MAT_UNLIT];
|
||||||
// Detail
|
// Detail
|
||||||
RSMPassCmd::getInstance()->Offset[MAT_DETAIL] = current_cmd;
|
RSMPassCmd::getInstance()->Offset[MAT_DETAIL] = current_cmd;
|
||||||
FillInstances(MeshForRSMPass[MAT_DETAIL], ListInstancedMatDetails::getInstance()->RSM, RSMInstanceBuffer, RSMCmdBuffer, offset, current_cmd, MiscPoly, rsmcamculling);
|
FillInstances(MeshForSolidPass[MAT_DETAIL], ListInstancedMatDetails::getInstance()->RSM, RSMInstanceBuffer, RSMCmdBuffer, offset, current_cmd, MiscPoly, rsmcamculling);
|
||||||
RSMPassCmd::getInstance()->Size[MAT_DETAIL] = current_cmd - RSMPassCmd::getInstance()->Offset[MAT_DETAIL];
|
RSMPassCmd::getInstance()->Size[MAT_DETAIL] = current_cmd - RSMPassCmd::getInstance()->Offset[MAT_DETAIL];
|
||||||
// Normal Map
|
// Normal Map
|
||||||
RSMPassCmd::getInstance()->Offset[MAT_NORMAL_MAP] = current_cmd;
|
RSMPassCmd::getInstance()->Offset[MAT_NORMAL_MAP] = current_cmd;
|
||||||
FillInstances(MeshForRSMPass[MAT_NORMAL_MAP], ListInstancedMatNormalMap::getInstance()->RSM, RSMInstanceBuffer, RSMCmdBuffer, offset, current_cmd, MiscPoly, rsmcamculling);
|
FillInstances(MeshForSolidPass[MAT_NORMAL_MAP], ListInstancedMatNormalMap::getInstance()->RSM, RSMInstanceBuffer, RSMCmdBuffer, offset, current_cmd, MiscPoly, rsmcamculling);
|
||||||
RSMPassCmd::getInstance()->Size[MAT_NORMAL_MAP] = current_cmd - RSMPassCmd::getInstance()->Offset[MAT_NORMAL_MAP];
|
RSMPassCmd::getInstance()->Size[MAT_NORMAL_MAP] = current_cmd - RSMPassCmd::getInstance()->Offset[MAT_NORMAL_MAP];
|
||||||
|
|
||||||
if (!irr_driver->hasBufferStorageExtension())
|
if (!irr_driver->hasBufferStorageExtension())
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
#include "gl_headers.hpp"
|
#include "gl_headers.hpp"
|
||||||
#include "stkmesh.hpp"
|
#include "stkmesh.hpp"
|
||||||
#include "gpuparticles.hpp"
|
#include "gpuparticles.hpp"
|
||||||
|
#include "stkbillboard.hpp"
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
class CommandBuffer : public Singleton<T>
|
class CommandBuffer : public Singleton<T>
|
||||||
@ -34,6 +35,9 @@ public:
|
|||||||
class ImmediateDrawList : public Singleton<ImmediateDrawList>, public std::vector<scene::ISceneNode *>
|
class ImmediateDrawList : public Singleton<ImmediateDrawList>, public std::vector<scene::ISceneNode *>
|
||||||
{};
|
{};
|
||||||
|
|
||||||
|
class BillBoardList : public Singleton<BillBoardList>, public std::vector<STKBillboard *>
|
||||||
|
{};
|
||||||
|
|
||||||
class ParticlesList : public Singleton<ParticlesList>, public std::vector<ParticleSystemProxy *>
|
class ParticlesList : public Singleton<ParticlesList>, public std::vector<ParticleSystemProxy *>
|
||||||
{};
|
{};
|
||||||
|
|
||||||
|
182
src/graphics/texturemanager.cpp
Normal file
182
src/graphics/texturemanager.cpp
Normal file
@ -0,0 +1,182 @@
|
|||||||
|
#include "texturemanager.hpp"
|
||||||
|
#include <fstream>
|
||||||
|
#include <string>
|
||||||
|
#include "../../lib/irrlicht/source/Irrlicht/COpenGLTexture.h"
|
||||||
|
#include "irr_driver.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
GLuint getTextureGLuint(irr::video::ITexture *tex)
|
||||||
|
{
|
||||||
|
return static_cast<irr::video::COpenGLTexture*>(tex)->getOpenGLTextureName();
|
||||||
|
}
|
||||||
|
|
||||||
|
GLuint getDepthTexture(irr::video::ITexture *tex)
|
||||||
|
{
|
||||||
|
assert(tex->isRenderTarget());
|
||||||
|
return static_cast<irr::video::COpenGLFBOTexture*>(tex)->DepthBufferTexture;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::set<irr::video::ITexture *> AlreadyTransformedTexture;
|
||||||
|
void resetTextureTable()
|
||||||
|
{
|
||||||
|
AlreadyTransformedTexture.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
void compressTexture(irr::video::ITexture *tex, bool srgb, bool premul_alpha)
|
||||||
|
{
|
||||||
|
if (AlreadyTransformedTexture.find(tex) != AlreadyTransformedTexture.end())
|
||||||
|
return;
|
||||||
|
AlreadyTransformedTexture.insert(tex);
|
||||||
|
|
||||||
|
glBindTexture(GL_TEXTURE_2D, getTextureGLuint(tex));
|
||||||
|
|
||||||
|
std::string cached_file;
|
||||||
|
if (UserConfigParams::m_texture_compression)
|
||||||
|
{
|
||||||
|
// Try to retrieve the compressed texture in cache
|
||||||
|
std::string tex_name = irr_driver->getTextureName(tex);
|
||||||
|
if (!tex_name.empty()) {
|
||||||
|
cached_file = file_manager->getTextureCacheLocation(tex_name) + ".gltz";
|
||||||
|
if (!file_manager->fileIsNewer(tex_name, cached_file)) {
|
||||||
|
if (loadCompressedTexture(cached_file))
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t w = tex->getSize().Width, h = tex->getSize().Height;
|
||||||
|
unsigned char *data = new unsigned char[w * h * 4];
|
||||||
|
memcpy(data, tex->lock(), w * h * 4);
|
||||||
|
tex->unlock();
|
||||||
|
unsigned internalFormat, Format;
|
||||||
|
if (tex->hasAlpha())
|
||||||
|
Format = GL_BGRA;
|
||||||
|
else
|
||||||
|
Format = GL_BGR;
|
||||||
|
|
||||||
|
if (premul_alpha)
|
||||||
|
{
|
||||||
|
for (unsigned i = 0; i < w * h; i++)
|
||||||
|
{
|
||||||
|
float alpha = data[4 * i + 3];
|
||||||
|
if (alpha > 0.)
|
||||||
|
alpha = pow(alpha / 255.f, 1.f / 2.2f);
|
||||||
|
data[4 * i] = (unsigned char)(data[4 * i] * alpha);
|
||||||
|
data[4 * i + 1] = (unsigned char)(data[4 * i + 1] * alpha);
|
||||||
|
data[4 * i + 2] = (unsigned char)(data[4 * i + 2] * alpha);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!UserConfigParams::m_texture_compression)
|
||||||
|
{
|
||||||
|
if (srgb)
|
||||||
|
internalFormat = (tex->hasAlpha()) ? GL_SRGB_ALPHA : GL_SRGB;
|
||||||
|
else
|
||||||
|
internalFormat = (tex->hasAlpha()) ? GL_RGBA : GL_RGB;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (srgb)
|
||||||
|
internalFormat = (tex->hasAlpha()) ? GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT : GL_COMPRESSED_SRGB_S3TC_DXT1_EXT;
|
||||||
|
else
|
||||||
|
internalFormat = (tex->hasAlpha()) ? GL_COMPRESSED_RGBA_S3TC_DXT5_EXT : GL_COMPRESSED_RGB_S3TC_DXT1_EXT;
|
||||||
|
}
|
||||||
|
glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, w, h, 0, Format, GL_UNSIGNED_BYTE, (GLvoid *)data);
|
||||||
|
glGenerateMipmap(GL_TEXTURE_2D);
|
||||||
|
delete[] data;
|
||||||
|
|
||||||
|
if (UserConfigParams::m_texture_compression && !cached_file.empty())
|
||||||
|
{
|
||||||
|
// Save the compressed texture in the cache for later use.
|
||||||
|
saveCompressedTexture(cached_file);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
/** Try to load a compressed texture from the given file name.
|
||||||
|
* Data in the specified file need to have a specific format. See the
|
||||||
|
* saveCompressedTexture() function for a description of the format.
|
||||||
|
* \return true if the loading succeeded, false otherwise.
|
||||||
|
* \see saveCompressedTexture
|
||||||
|
*/
|
||||||
|
bool loadCompressedTexture(const std::string& compressed_tex)
|
||||||
|
{
|
||||||
|
std::ifstream ifs(compressed_tex.c_str(), std::ios::in | std::ios::binary);
|
||||||
|
if (!ifs.is_open())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
int internal_format;
|
||||||
|
int w, h;
|
||||||
|
int size = -1;
|
||||||
|
ifs.read((char*)&internal_format, sizeof(int));
|
||||||
|
ifs.read((char*)&w, sizeof(int));
|
||||||
|
ifs.read((char*)&h, sizeof(int));
|
||||||
|
ifs.read((char*)&size, sizeof(int));
|
||||||
|
|
||||||
|
if (ifs.fail() || size == -1)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
char *data = new char[size];
|
||||||
|
ifs.read(data, size);
|
||||||
|
if (!ifs.fail())
|
||||||
|
{
|
||||||
|
glCompressedTexImage2D(GL_TEXTURE_2D, 0, internal_format,
|
||||||
|
w, h, 0, size, (GLvoid*)data);
|
||||||
|
glGenerateMipmap(GL_TEXTURE_2D);
|
||||||
|
delete[] data;
|
||||||
|
ifs.close();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
delete[] data;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
/** Try to save the last texture sent to glTexImage2D in a file of the given
|
||||||
|
* file name. This function should only be used for textures sent to
|
||||||
|
* glTexImage2D with a compressed internal format as argument.<br>
|
||||||
|
* \note The following format is used to save the compressed texture:<br>
|
||||||
|
* <internal-format><width><height><size><data> <br>
|
||||||
|
* The first four elements are integers and the last one is stored
|
||||||
|
* on \c size bytes.
|
||||||
|
* \see loadCompressedTexture
|
||||||
|
*/
|
||||||
|
void saveCompressedTexture(const std::string& compressed_tex)
|
||||||
|
{
|
||||||
|
int internal_format, width, height, size, compressionSuccessful;
|
||||||
|
glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_INTERNAL_FORMAT, (GLint *)&internal_format);
|
||||||
|
glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, (GLint *)&width);
|
||||||
|
glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, (GLint *)&height);
|
||||||
|
glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_COMPRESSED, (GLint *)&compressionSuccessful);
|
||||||
|
if (!compressionSuccessful)
|
||||||
|
return;
|
||||||
|
glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_COMPRESSED_IMAGE_SIZE, (GLint *)&size);
|
||||||
|
|
||||||
|
char *data = new char[size];
|
||||||
|
glGetCompressedTexImage(GL_TEXTURE_2D, 0, (GLvoid*)data);
|
||||||
|
std::ofstream ofs(compressed_tex.c_str(), std::ios::out | std::ios::binary);
|
||||||
|
if (ofs.is_open())
|
||||||
|
{
|
||||||
|
ofs.write((char*)&internal_format, sizeof(int));
|
||||||
|
ofs.write((char*)&width, sizeof(int));
|
||||||
|
ofs.write((char*)&height, sizeof(int));
|
||||||
|
ofs.write((char*)&size, sizeof(int));
|
||||||
|
ofs.write(data, size);
|
||||||
|
ofs.close();
|
||||||
|
}
|
||||||
|
delete[] data;
|
||||||
|
}
|
||||||
|
|
||||||
|
static unsigned colorcount = 0;
|
||||||
|
|
||||||
|
video::ITexture* getUnicolorTexture(video::SColor c)
|
||||||
|
{
|
||||||
|
video::SColor tmp[4] = {
|
||||||
|
c, c, c, c
|
||||||
|
};
|
||||||
|
video::IImage *img = irr_driver->getVideoDriver()->createImageFromData(video::ECF_A8R8G8B8, core::dimension2d<u32>(2, 2), tmp);
|
||||||
|
img->grab();
|
||||||
|
std::string name("color");
|
||||||
|
name += colorcount++;
|
||||||
|
return irr_driver->getVideoDriver()->addTexture(name.c_str(), img);
|
||||||
|
}
|
15
src/graphics/texturemanager.hpp
Normal file
15
src/graphics/texturemanager.hpp
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
#ifndef MEMORYMANAGER_HPP
|
||||||
|
#define MEMORYMANAGER_HPP
|
||||||
|
|
||||||
|
#include "gl_headers.hpp"
|
||||||
|
#include <ITexture.h>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
GLuint getTextureGLuint(irr::video::ITexture *tex);
|
||||||
|
GLuint getDepthTexture(irr::video::ITexture *tex);
|
||||||
|
void resetTextureTable();
|
||||||
|
void compressTexture(irr::video::ITexture *tex, bool srgb, bool premul_alpha = false);
|
||||||
|
bool loadCompressedTexture(const std::string& compressed_tex);
|
||||||
|
void saveCompressedTexture(const std::string& compressed_tex);
|
||||||
|
|
||||||
|
#endif
|
@ -308,6 +308,8 @@ void PhysicalObject::init()
|
|||||||
}
|
}
|
||||||
case MP_EXACT:
|
case MP_EXACT:
|
||||||
{
|
{
|
||||||
|
m_graphical_offset = Vec3(0,0,0);
|
||||||
|
extend.setY(0);
|
||||||
TriangleMesh* triangle_mesh = new TriangleMesh();
|
TriangleMesh* triangle_mesh = new TriangleMesh();
|
||||||
|
|
||||||
// In case of readonly materials we have to get the material from
|
// In case of readonly materials we have to get the material from
|
||||||
@ -472,7 +474,8 @@ void PhysicalObject::init()
|
|||||||
}
|
}
|
||||||
|
|
||||||
World::getWorld()->getPhysics()->addBody(m_body);
|
World::getWorld()->getPhysics()->addBody(m_body);
|
||||||
|
if(m_triangle_mesh)
|
||||||
|
m_triangle_mesh->setBody(m_body);
|
||||||
} // init
|
} // init
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
@ -505,6 +508,36 @@ void PhysicalObject::update(float dt)
|
|||||||
return;
|
return;
|
||||||
} // update
|
} // update
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
/** Does a raycast against this physical object. The physical object must
|
||||||
|
* have an 'exact' shape, i.e. be a triangle mesh (for other physical objects
|
||||||
|
* no material information would be available).
|
||||||
|
* \param from/to The from and to position for the raycast.
|
||||||
|
* \param xyz The position in world where the ray hit.
|
||||||
|
* \param material The material of the mesh that was hit.
|
||||||
|
* \param normal The intrapolated normal at that position.
|
||||||
|
* \param interpolate_normal If true, the returned normal is the interpolated
|
||||||
|
* based on the three normals of the triangle and the location of the
|
||||||
|
* hit point (which is more compute intensive, but results in much
|
||||||
|
* smoother results).
|
||||||
|
* \return True if a triangle was hit, false otherwise (and no output
|
||||||
|
* variable will be set.
|
||||||
|
*/
|
||||||
|
bool PhysicalObject::castRay(const btVector3 &from, const btVector3 &to,
|
||||||
|
btVector3 *hit_point, const Material **material,
|
||||||
|
btVector3 *normal, bool interpolate_normal) const
|
||||||
|
{
|
||||||
|
if(m_body_type!=MP_EXACT)
|
||||||
|
{
|
||||||
|
Log::warn("PhysicalObject", "Can only raycast against 'exact' meshes.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
bool result = m_triangle_mesh->castRay(from, to, hit_point,
|
||||||
|
material, normal,
|
||||||
|
interpolate_normal);
|
||||||
|
return result;
|
||||||
|
} // castRay
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
void PhysicalObject::reset()
|
void PhysicalObject::reset()
|
||||||
{
|
{
|
||||||
|
@ -164,6 +164,11 @@ public:
|
|||||||
void move (const Vec3& xyz, const core::vector3df& hpr);
|
void move (const Vec3& xyz, const core::vector3df& hpr);
|
||||||
void hit (const Material *m, const Vec3 &normal);
|
void hit (const Material *m, const Vec3 &normal);
|
||||||
bool isSoccerBall () const;
|
bool isSoccerBall () const;
|
||||||
|
bool castRay(const btVector3 &from,
|
||||||
|
const btVector3 &to, btVector3 *hit_point,
|
||||||
|
const Material **material, btVector3 *normal,
|
||||||
|
bool interpolate_normal) const;
|
||||||
|
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
/** Returns the ID of this physical object. */
|
/** Returns the ID of this physical object. */
|
||||||
std::string getID() { return m_id; }
|
std::string getID() { return m_id; }
|
||||||
|
@ -33,6 +33,7 @@
|
|||||||
TriangleMesh::TriangleMesh() : m_mesh()
|
TriangleMesh::TriangleMesh() : m_mesh()
|
||||||
{
|
{
|
||||||
m_body = NULL;
|
m_body = NULL;
|
||||||
|
m_free_body = true;
|
||||||
m_motion_state = NULL;
|
m_motion_state = NULL;
|
||||||
// FIXME: on VS in release mode this statement actually overwrites
|
// FIXME: on VS in release mode this statement actually overwrites
|
||||||
// part of the data of m_mesh, causing a crash later. Debugging
|
// part of the data of m_mesh, causing a crash later. Debugging
|
||||||
@ -200,7 +201,8 @@ void TriangleMesh::createPhysicalBody(btCollisionObject::CollisionFlags flags,
|
|||||||
*/
|
*/
|
||||||
void TriangleMesh::removeAll()
|
void TriangleMesh::removeAll()
|
||||||
{
|
{
|
||||||
if(m_body)
|
// Don't free the physical body if it was created outside this object.
|
||||||
|
if(m_body && m_free_body)
|
||||||
{
|
{
|
||||||
World::getWorld()->getPhysics()->removeBody(m_body);
|
World::getWorld()->getPhysics()->removeBody(m_body);
|
||||||
delete m_body;
|
delete m_body;
|
||||||
@ -270,7 +272,7 @@ btVector3 TriangleMesh::getInterpolatedNormal(unsigned int index,
|
|||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
/** Casts a ray from 'from' to 'to'. If a triangle of this mesh was hit,
|
/** Casts a ray from 'from' to 'to'. If a triangle of this mesh was hit,
|
||||||
* xyz and material will be set.
|
* xyz and material will be set.
|
||||||
* \param from/to The from and to position for the raycast/
|
* \param from/to The from and to position for the raycast.
|
||||||
* \param xyz The position in world where the ray hit.
|
* \param xyz The position in world where the ray hit.
|
||||||
* \param material The material of the mesh that was hit.
|
* \param material The material of the mesh that was hit.
|
||||||
* \param normal The intrapolated normal at that position.
|
* \param normal The intrapolated normal at that position.
|
||||||
@ -300,7 +302,11 @@ bool TriangleMesh::castRay(const btVector3 &from, const btVector3 &to,
|
|||||||
trans_to.setOrigin(to);
|
trans_to.setOrigin(to);
|
||||||
|
|
||||||
btTransform world_trans;
|
btTransform world_trans;
|
||||||
world_trans.setIdentity();
|
// If there is a body, take the current transform from the body.
|
||||||
|
if(m_body)
|
||||||
|
world_trans = m_body->getWorldTransform();
|
||||||
|
else
|
||||||
|
world_trans.setIdentity();
|
||||||
|
|
||||||
btCollisionWorld::ClosestRayResultCallback result(from, to);
|
btCollisionWorld::ClosestRayResultCallback result(from, to);
|
||||||
|
|
||||||
@ -334,8 +340,7 @@ bool TriangleMesh::castRay(const btVector3 &from, const btVector3 &to,
|
|||||||
// If this is a rigid body, m_collision_object is NULL, and the
|
// If this is a rigid body, m_collision_object is NULL, and the
|
||||||
// rigid body is the actual collision object.
|
// rigid body is the actual collision object.
|
||||||
btCollisionWorld::rayTestSingle(trans_from, trans_to,
|
btCollisionWorld::rayTestSingle(trans_from, trans_to,
|
||||||
m_collision_object ? m_collision_object
|
m_collision_object ? m_collision_object : m_body,
|
||||||
: m_body,
|
|
||||||
m_collision_shape, world_trans,
|
m_collision_shape, world_trans,
|
||||||
ray_callback);
|
ray_callback);
|
||||||
// Get the index of the triangle hit
|
// Get the index of the triangle hit
|
||||||
|
@ -37,6 +37,9 @@ private:
|
|||||||
UserPointer m_user_pointer;
|
UserPointer m_user_pointer;
|
||||||
std::vector<const Material*> m_triangleIndex2Material;
|
std::vector<const Material*> m_triangleIndex2Material;
|
||||||
btRigidBody *m_body;
|
btRigidBody *m_body;
|
||||||
|
/** Keep track if the physical body was created here or not. */
|
||||||
|
bool m_free_body;
|
||||||
|
|
||||||
btCollisionObject *m_collision_object;
|
btCollisionObject *m_collision_object;
|
||||||
btTriangleMesh m_mesh;
|
btTriangleMesh m_mesh;
|
||||||
btVector3 dummy1, dummy2;
|
btVector3 dummy1, dummy2;
|
||||||
@ -60,6 +63,20 @@ public:
|
|||||||
btVector3 getInterpolatedNormal(unsigned int index,
|
btVector3 getInterpolatedNormal(unsigned int index,
|
||||||
const btVector3 &position) const;
|
const btVector3 &position) const;
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
|
/** In case of physical objects of shape 'exact', the physical body is
|
||||||
|
* created outside of the mesh. Since raycasts need the body's world
|
||||||
|
* transform, the body can be set using this function. This will also
|
||||||
|
* cause the body not to be freed (since it will be freed as part of
|
||||||
|
* the physical object). */
|
||||||
|
void setBody(btRigidBody *body)
|
||||||
|
{
|
||||||
|
assert(!m_body);
|
||||||
|
// Mark that the body should not be deleted when this object is
|
||||||
|
// deleted, since the body is managed elsewhere.
|
||||||
|
m_free_body = false;
|
||||||
|
m_body = body;
|
||||||
|
}
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
const Material* getMaterial(int n) const
|
const Material* getMaterial(int n) const
|
||||||
{return m_triangleIndex2Material[n];}
|
{return m_triangleIndex2Material[n];}
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
|
@ -216,6 +216,9 @@ void GPInfoScreen::init()
|
|||||||
|
|
||||||
addTracks();
|
addTracks();
|
||||||
addScreenshot();
|
addScreenshot();
|
||||||
|
|
||||||
|
RibbonWidget* bt_start = getWidget<GUIEngine::RibbonWidget>("buttons");
|
||||||
|
bt_start->setFocusForPlayer(PLAYER_ID_GAME_MASTER);
|
||||||
} // init
|
} // init
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
@ -18,14 +18,16 @@
|
|||||||
|
|
||||||
#include "tracks/terrain_info.hpp"
|
#include "tracks/terrain_info.hpp"
|
||||||
|
|
||||||
#include <math.h>
|
|
||||||
|
|
||||||
#include "modes/world.hpp"
|
#include "modes/world.hpp"
|
||||||
#include "physics/triangle_mesh.hpp"
|
#include "physics/triangle_mesh.hpp"
|
||||||
#include "race/race_manager.hpp"
|
#include "race/race_manager.hpp"
|
||||||
#include "tracks/track.hpp"
|
#include "tracks/track.hpp"
|
||||||
|
#include "tracks/track_manager.hpp"
|
||||||
|
#include "tracks/track_object_manager.hpp"
|
||||||
#include "utils/constants.hpp"
|
#include "utils/constants.hpp"
|
||||||
|
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
/** Constructor to initialise terrain data.
|
/** Constructor to initialise terrain data.
|
||||||
*/
|
*/
|
||||||
TerrainInfo::TerrainInfo()
|
TerrainInfo::TerrainInfo()
|
||||||
@ -59,6 +61,10 @@ void TerrainInfo::update(const Vec3 &from)
|
|||||||
const TriangleMesh &tm = World::getWorld()->getTrack()->getTriangleMesh();
|
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);
|
/*interpolate*/false);
|
||||||
|
// Now also raycast against all track objects (that are driveable).
|
||||||
|
World::getWorld()->getTrack()->getTrackObjectManager()
|
||||||
|
->castRay(from, to, &m_hit_point, &m_material,
|
||||||
|
&m_normal, /*interpolate*/false);
|
||||||
} // update
|
} // update
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
/** Update the terrain information based on the latest position.
|
/** Update the terrain information based on the latest position.
|
||||||
@ -74,6 +80,13 @@ void TerrainInfo::update(const btTransform &trans, const Vec3 &offset)
|
|||||||
const TriangleMesh &tm = World::getWorld()->getTrack()->getTriangleMesh();
|
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*/true);
|
/*interpolate*/true);
|
||||||
|
|
||||||
|
// Now also raycast against all track objects (that are driveable). If
|
||||||
|
// there should be a closer result (than the one against the main track
|
||||||
|
// mesh), its data will be returned.
|
||||||
|
World::getWorld()->getTrack()->getTrackObjectManager()
|
||||||
|
->castRay(from, to, &m_hit_point, &m_material,
|
||||||
|
&m_normal, /*interpolate*/true);
|
||||||
} // update
|
} // update
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
@ -2398,7 +2398,7 @@ std::vector< std::vector<float> > Track::buildHeightMap()
|
|||||||
}
|
}
|
||||||
|
|
||||||
return out;
|
return out;
|
||||||
}
|
} // buildHeightMap
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
/** Returns the rotation of the sun. */
|
/** Returns the rotation of the sun. */
|
||||||
|
@ -42,7 +42,7 @@ TrackObject::TrackObject(const XMLNode &xml_node, scene::ISceneNode* parent,
|
|||||||
ModelDefinitionLoader& model_def_loader)
|
ModelDefinitionLoader& model_def_loader)
|
||||||
{
|
{
|
||||||
init(xml_node, parent, model_def_loader);
|
init(xml_node, parent, model_def_loader);
|
||||||
}
|
} // TrackObject
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
/**
|
/**
|
||||||
@ -56,29 +56,33 @@ TrackObject::TrackObject(const core::vector3df& xyz, const core::vector3df& hpr,
|
|||||||
bool is_dynamic,
|
bool is_dynamic,
|
||||||
const PhysicalObject::Settings* physics_settings)
|
const PhysicalObject::Settings* physics_settings)
|
||||||
{
|
{
|
||||||
m_init_xyz = xyz;
|
m_init_xyz = xyz;
|
||||||
m_init_hpr = hpr;
|
m_init_hpr = hpr;
|
||||||
m_init_scale = scale;
|
m_init_scale = scale;
|
||||||
m_enabled = true;
|
m_enabled = true;
|
||||||
m_presentation = NULL;
|
m_presentation = NULL;
|
||||||
m_animator = NULL;
|
m_animator = NULL;
|
||||||
m_physical_object = NULL;
|
m_physical_object = NULL;
|
||||||
m_interaction = interaction;
|
m_interaction = interaction;
|
||||||
|
m_presentation = presentation;
|
||||||
m_presentation = presentation;
|
|
||||||
|
|
||||||
if (m_interaction != "ghost" && m_interaction != "none" &&
|
if (m_interaction != "ghost" && m_interaction != "none" &&
|
||||||
physics_settings )
|
physics_settings )
|
||||||
{
|
{
|
||||||
m_physical_object = new PhysicalObject(is_dynamic,
|
m_physical_object = new PhysicalObject(is_dynamic,
|
||||||
*physics_settings,
|
*physics_settings,
|
||||||
this);
|
this);
|
||||||
}
|
}
|
||||||
|
|
||||||
reset();
|
reset();
|
||||||
} // TrackObject
|
} // TrackObject
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
/** Initialises the track object based on the specified XML data.
|
||||||
|
* \param xml_node The XML data.
|
||||||
|
* \param parent The parent scene node.
|
||||||
|
* \param model_def_loader Used to load level-of-detail nodes.
|
||||||
|
*/
|
||||||
void TrackObject::init(const XMLNode &xml_node, scene::ISceneNode* parent,
|
void TrackObject::init(const XMLNode &xml_node, scene::ISceneNode* parent,
|
||||||
ModelDefinitionLoader& model_def_loader)
|
ModelDefinitionLoader& model_def_loader)
|
||||||
{
|
{
|
||||||
@ -102,6 +106,9 @@ void TrackObject::init(const XMLNode &xml_node, scene::ISceneNode* parent,
|
|||||||
xml_node.get("interaction", &m_interaction);
|
xml_node.get("interaction", &m_interaction);
|
||||||
xml_node.get("lod_group", &m_lod_group);
|
xml_node.get("lod_group", &m_lod_group);
|
||||||
|
|
||||||
|
m_is_driveable = false;
|
||||||
|
xml_node.get("driveable", &m_is_driveable);
|
||||||
|
|
||||||
bool lod_instance = false;
|
bool lod_instance = false;
|
||||||
xml_node.get("lod_instance", &lod_instance);
|
xml_node.get("lod_instance", &lod_instance);
|
||||||
|
|
||||||
@ -256,14 +263,42 @@ void TrackObject::setEnable(bool mode)
|
|||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
void TrackObject::update(float dt)
|
void TrackObject::update(float dt)
|
||||||
{
|
{
|
||||||
if (m_presentation != NULL) m_presentation->update(dt);
|
if (m_presentation) m_presentation->update(dt);
|
||||||
|
|
||||||
if (m_physical_object != NULL) m_physical_object->update(dt);
|
if (m_physical_object) m_physical_object->update(dt);
|
||||||
|
|
||||||
if (m_animator != NULL) m_animator->update(dt);
|
if (m_animator) m_animator->update(dt);
|
||||||
} // update
|
} // update
|
||||||
|
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
/** Does a raycast against the track object. The object must have a physical
|
||||||
|
* object.
|
||||||
|
* \param from/to The from and to position for the raycast.
|
||||||
|
* \param xyz The position in world where the ray hit.
|
||||||
|
* \param material The material of the mesh that was hit.
|
||||||
|
* \param normal The intrapolated normal at that position.
|
||||||
|
* \param interpolate_normal If true, the returned normal is the interpolated
|
||||||
|
* based on the three normals of the triangle and the location of the
|
||||||
|
* hit point (which is more compute intensive, but results in much
|
||||||
|
* smoother results).
|
||||||
|
* \return True if a triangle was hit, false otherwise (and no output
|
||||||
|
* variable will be set.
|
||||||
|
*/
|
||||||
|
bool TrackObject::castRay(const btVector3 &from,
|
||||||
|
const btVector3 &to, btVector3 *hit_point,
|
||||||
|
const Material **material, btVector3 *normal,
|
||||||
|
bool interpolate_normal) const
|
||||||
|
{
|
||||||
|
if(!m_physical_object)
|
||||||
|
{
|
||||||
|
Log::warn("TrackObject", "Can't raycast on non-physical object.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return m_physical_object->castRay(from, to, hit_point, material, normal,
|
||||||
|
interpolate_normal);
|
||||||
|
} // castRay
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
void TrackObject::move(const core::vector3df& xyz, const core::vector3df& hpr,
|
void TrackObject::move(const core::vector3df& xyz, const core::vector3df& hpr,
|
||||||
|
@ -80,7 +80,10 @@ protected:
|
|||||||
bool m_soccer_ball;
|
bool m_soccer_ball;
|
||||||
|
|
||||||
bool m_garage;
|
bool m_garage;
|
||||||
|
|
||||||
|
/** True if a kart can drive on this object. This will */
|
||||||
|
bool m_is_driveable;
|
||||||
|
|
||||||
float m_distance;
|
float m_distance;
|
||||||
|
|
||||||
PhysicalObject* m_physical_object;
|
PhysicalObject* m_physical_object;
|
||||||
@ -101,46 +104,64 @@ public:
|
|||||||
const PhysicalObject::Settings* physicsSettings);
|
const PhysicalObject::Settings* physicsSettings);
|
||||||
virtual ~TrackObject();
|
virtual ~TrackObject();
|
||||||
virtual void update(float dt);
|
virtual void update(float dt);
|
||||||
virtual void reset();
|
|
||||||
/** To finish object constructions. Called after the track model
|
|
||||||
* is ready. */
|
|
||||||
virtual void init() {};
|
|
||||||
/** Called when an explosion happens. As a default does nothing, will
|
|
||||||
* e.g. be overwritten by physical objects etc. */
|
|
||||||
virtual void handleExplosion(const Vec3& pos, bool directHit) {};
|
|
||||||
void setEnable(bool mode);
|
|
||||||
void setID(std::string obj_id) { m_id = obj_id; }
|
|
||||||
|
|
||||||
const std::string& getLodGroup() const { return m_lod_group; }
|
|
||||||
|
|
||||||
const std::string& getType() const { return m_type; }
|
|
||||||
|
|
||||||
const std::string getName() const { return m_name; }
|
|
||||||
|
|
||||||
const std::string getID() const { return m_id; }
|
|
||||||
|
|
||||||
const std::string getInteraction() const { return m_interaction; }
|
|
||||||
|
|
||||||
bool isEnabled() const { return m_enabled; }
|
|
||||||
bool isSoccerBall() const { return m_soccer_ball; }
|
|
||||||
bool isGarage() const { return m_garage; }
|
|
||||||
float getDistance() const { return m_distance; }
|
|
||||||
|
|
||||||
const PhysicalObject* getPhysicalObject() const { return m_physical_object; }
|
|
||||||
PhysicalObject* getPhysicalObject() { return m_physical_object; }
|
|
||||||
//Due to above overload AngelScript cannot decide which function to bind
|
|
||||||
PhysicalObject* getPhysicalObjectForScript() { return m_physical_object; }
|
|
||||||
|
|
||||||
const core::vector3df getInitXYZ() const { return m_init_xyz; }
|
|
||||||
const core::vector3df getInitRotation() const { return m_init_hpr; }
|
|
||||||
const core::vector3df getInitScale() const { return m_init_scale; }
|
|
||||||
|
|
||||||
void move(const core::vector3df& xyz, const core::vector3df& hpr,
|
void move(const core::vector3df& xyz, const core::vector3df& hpr,
|
||||||
const core::vector3df& scale, bool updateRigidBody);
|
const core::vector3df& scale, bool updateRigidBody);
|
||||||
|
|
||||||
|
virtual void reset();
|
||||||
|
void setEnable(bool mode);
|
||||||
|
const core::vector3df& getPosition() const;
|
||||||
|
const core::vector3df getAbsolutePosition() const;
|
||||||
|
const core::vector3df& getRotation() const;
|
||||||
|
const core::vector3df& getScale() const;
|
||||||
|
bool castRay(const btVector3 &from,
|
||||||
|
const btVector3 &to, btVector3 *hit_point,
|
||||||
|
const Material **material, btVector3 *normal,
|
||||||
|
bool interpolate_normal) const;
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
/** To finish object constructions. Called after the track model
|
||||||
|
* is ready. */
|
||||||
|
virtual void init() {};
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
/** Called when an explosion happens. As a default does nothing, will
|
||||||
|
* e.g. be overwritten by physical objects etc. */
|
||||||
|
virtual void handleExplosion(const Vec3& pos, bool directHit) {};
|
||||||
|
void setID(std::string obj_id) { m_id = obj_id; }
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
const std::string& getLodGroup() const { return m_lod_group; }
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
const std::string& getType() const { return m_type; }
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
const std::string getName() const { return m_name; }
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
const std::string getID() const { return m_id; }
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
const std::string getInteraction() const { return m_interaction; }
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
bool isEnabled() const { return m_enabled; }
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
bool isSoccerBall() const { return m_soccer_ball; }
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
bool isGarage() const { return m_garage; }
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
float getDistance() const { return m_distance; }
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
const PhysicalObject* getPhysicalObject() const { return m_physical_object; }
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
PhysicalObject* getPhysicalObject() { return m_physical_object; }
|
||||||
|
//Due to above overload AngelScript cannot decide which function to bind
|
||||||
|
PhysicalObject* getPhysicalObjectForScript() { return m_physical_object; }
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
const core::vector3df getInitXYZ() const { return m_init_xyz; }
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
const core::vector3df getInitRotation() const { return m_init_hpr; }
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
const core::vector3df getInitScale() const { return m_init_scale; }
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
template<typename T>
|
template<typename T>
|
||||||
T* getPresentation() { return dynamic_cast<T*>(m_presentation); }
|
T* getPresentation() { return dynamic_cast<T*>(m_presentation); }
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
template<typename T>
|
template<typename T>
|
||||||
const T* getPresentation() const { return dynamic_cast<T*>(m_presentation); }
|
const T* getPresentation() const { return dynamic_cast<T*>(m_presentation); }
|
||||||
|
|
||||||
@ -151,17 +172,17 @@ public:
|
|||||||
|
|
||||||
TrackObjectPresentationSound* getSound(){ return getPresentation<TrackObjectPresentationSound>(); }
|
TrackObjectPresentationSound* getSound(){ return getPresentation<TrackObjectPresentationSound>(); }
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
ThreeDAnimation* getAnimator() { return m_animator; }
|
ThreeDAnimation* getAnimator() { return m_animator; }
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
const ThreeDAnimation* getAnimator() const { return m_animator; }
|
const ThreeDAnimation* getAnimator() const { return m_animator; }
|
||||||
//Due to above overload AngelScript cannot decide which function to bind
|
//Due to above overload AngelScript cannot decide which function to bind
|
||||||
ThreeDAnimation* getAnimatorForScript() { return m_animator; }
|
ThreeDAnimation* getAnimatorForScript() { return m_animator; }
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
void setPaused(bool mode){ m_animator->setPaused(mode); }
|
void setPaused(bool mode){ m_animator->setPaused(mode); }
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
const core::vector3df& getPosition() const;
|
/** Returns if a kart can drive on this object. */
|
||||||
const core::vector3df getAbsolutePosition() const;
|
bool isDriveable() const { return m_is_driveable; }
|
||||||
const core::vector3df& getRotation() const;
|
|
||||||
const core::vector3df& getScale() const;
|
|
||||||
|
|
||||||
LEAK_CHECK()
|
LEAK_CHECK()
|
||||||
}; // TrackObject
|
}; // TrackObject
|
||||||
|
@ -50,11 +50,15 @@ TrackObjectManager::~TrackObjectManager()
|
|||||||
* in a separate section that's read before everything and remove all this
|
* in a separate section that's read before everything and remove all this
|
||||||
* crap
|
* crap
|
||||||
*/
|
*/
|
||||||
void TrackObjectManager::add(const XMLNode &xml_node, scene::ISceneNode* parent, ModelDefinitionLoader& model_def_loader)
|
void TrackObjectManager::add(const XMLNode &xml_node, scene::ISceneNode* parent,
|
||||||
|
ModelDefinitionLoader& model_def_loader)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
m_all_objects.push_back(new TrackObject(xml_node, parent, model_def_loader));
|
TrackObject *obj = new TrackObject(xml_node, parent, model_def_loader);
|
||||||
|
m_all_objects.push_back(obj);
|
||||||
|
if(obj->isDriveable())
|
||||||
|
m_driveable_objects.push_back(obj);
|
||||||
}
|
}
|
||||||
catch (std::exception& e)
|
catch (std::exception& e)
|
||||||
{
|
{
|
||||||
@ -213,6 +217,61 @@ void TrackObjectManager::update(float dt)
|
|||||||
}
|
}
|
||||||
} // update
|
} // update
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
/** Does a raycast against all driveable objects. This way part of the track
|
||||||
|
* can be a physical object, and can e.g. be animated. A separate list of all
|
||||||
|
* driveable objects is maintained (in one case there were over 2000 bodies,
|
||||||
|
* but only one is driveable). The result of the raycast against the track
|
||||||
|
* mesh are the input parameter. It is then tested if the raycast against
|
||||||
|
* a track object gives a 'closer' result. If so, the parameters hit_point,
|
||||||
|
* normal, and material will be updated.
|
||||||
|
* \param from/to The from and to position for the raycast.
|
||||||
|
* \param xyz The position in world where the ray hit.
|
||||||
|
* \param material The material of the mesh that was hit.
|
||||||
|
* \param normal The intrapolated normal at that position.
|
||||||
|
* \param interpolate_normal If true, the returned normal is the interpolated
|
||||||
|
* based on the three normals of the triangle and the location of the
|
||||||
|
* hit point (which is more compute intensive, but results in much
|
||||||
|
* smoother results).
|
||||||
|
* \return True if a triangle was hit, false otherwise (and no output
|
||||||
|
* variable will be set.
|
||||||
|
|
||||||
|
*/
|
||||||
|
void TrackObjectManager::castRay(const btVector3 &from,
|
||||||
|
const btVector3 &to, btVector3 *hit_point,
|
||||||
|
const Material **material,
|
||||||
|
btVector3 *normal,
|
||||||
|
bool interpolate_normal) const
|
||||||
|
{
|
||||||
|
float distance = 9999.9f;
|
||||||
|
// If there was a hit already, compute the current distance
|
||||||
|
if(*material)
|
||||||
|
{
|
||||||
|
distance = hit_point->distance(from);
|
||||||
|
}
|
||||||
|
const TrackObject* curr;
|
||||||
|
for_in (curr, m_driveable_objects)
|
||||||
|
{
|
||||||
|
btVector3 new_hit_point;
|
||||||
|
const Material *new_material;
|
||||||
|
btVector3 new_normal;
|
||||||
|
if(curr->castRay(from, to, &new_hit_point, &new_material, &new_normal,
|
||||||
|
interpolate_normal))
|
||||||
|
{
|
||||||
|
float new_distance = new_hit_point.distance(from);
|
||||||
|
// If the new hit is closer than the current hit, save
|
||||||
|
// the data.
|
||||||
|
if (new_distance < distance)
|
||||||
|
{
|
||||||
|
*material = new_material;
|
||||||
|
*hit_point = new_hit_point;
|
||||||
|
*normal = new_normal;
|
||||||
|
distance = new_distance;
|
||||||
|
} // if new_distance < distance
|
||||||
|
} // if hit
|
||||||
|
} // for all track objects.
|
||||||
|
} // castRay
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
/** Enables or disables fog for a given scene node.
|
/** Enables or disables fog for a given scene node.
|
||||||
* \param node The node to adjust.
|
* \param node The node to adjust.
|
||||||
|
@ -44,20 +44,30 @@ protected:
|
|||||||
* eye candy (to reduce work for physics), ...
|
* eye candy (to reduce work for physics), ...
|
||||||
*/
|
*/
|
||||||
enum TrackObjectType {TO_PHYSICAL, TO_GRAPHICAL};
|
enum TrackObjectType {TO_PHYSICAL, TO_GRAPHICAL};
|
||||||
|
|
||||||
|
/** The list of all track objects. */
|
||||||
PtrVector<TrackObject> m_all_objects;
|
PtrVector<TrackObject> m_all_objects;
|
||||||
|
|
||||||
|
/** A second list which holds all objects that karts can drive on. */
|
||||||
|
PtrVector<TrackObject, REF> m_driveable_objects;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
TrackObjectManager();
|
TrackObjectManager();
|
||||||
~TrackObjectManager();
|
~TrackObjectManager();
|
||||||
void add(const XMLNode &xml_node, scene::ISceneNode* parent, ModelDefinitionLoader& model_def_loader);
|
void reset();
|
||||||
|
void init();
|
||||||
|
void add(const XMLNode &xml_node, scene::ISceneNode* parent,
|
||||||
|
ModelDefinitionLoader& model_def_loader);
|
||||||
void update(float dt);
|
void update(float dt);
|
||||||
void handleExplosion(const Vec3 &pos, const PhysicalObject *mp,
|
void handleExplosion(const Vec3 &pos, const PhysicalObject *mp,
|
||||||
bool secondary_hits=true);
|
bool secondary_hits=true);
|
||||||
void reset();
|
|
||||||
void init();
|
|
||||||
void disable(std::string name);
|
void disable(std::string name);
|
||||||
void enable (std::string name);
|
void enable (std::string name);
|
||||||
bool getStatus(std::string name);
|
bool getStatus(std::string name);
|
||||||
|
void castRay(const btVector3 &from,
|
||||||
|
const btVector3 &to, btVector3 *hit_point,
|
||||||
|
const Material **material, btVector3 *normal = NULL,
|
||||||
|
bool interpolate_normal = false) const;
|
||||||
|
|
||||||
/** Enable or disable fog on objects */
|
/** Enable or disable fog on objects */
|
||||||
void enableFog(bool enable);
|
void enableFog(bool enable);
|
||||||
|
Loading…
Reference in New Issue
Block a user