Merge remote-tracking branch 'origin/master' into hq_mipmap_generator

This commit is contained in:
Benau 2017-03-16 11:23:27 +08:00
commit ce76abf4fe
17 changed files with 527 additions and 532 deletions

View File

@ -208,13 +208,6 @@ if(USE_FRIBIDI)
endif()
endif()
# OpenMP
find_package(OpenMP)
if (OPENMP_FOUND)
set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${OpenMP_C_FLAGS}")
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS}")
endif()
# OpenGL
if(NOT USE_GLES2 AND NOT SERVER_ONLY)
find_package(OpenGL REQUIRED)
@ -458,10 +451,6 @@ if(MINGW)
if(LIBSTDCPP)
file(COPY ${LIBSTDCPP} DESTINATION ${CMAKE_BINARY_DIR}/bin/)
endif()
find_library(LIBOPENMP NAMES "libgomp-1.dll" PATHS ${CMAKE_FIND_ROOT_PATH})
if(LIBOPENMP)
file(COPY ${LIBOPENMP} DESTINATION ${CMAKE_BINARY_DIR}/bin/)
endif()
find_library(LIBPTHREAD NAMES "winpthread-1.dll" "libwinpthread-1.dll" "pthreadGC2.dll" PATHS ${CMAKE_FIND_ROOT_PATH})
if(LIBPTHREAD)
file(COPY ${LIBPTHREAD} DESTINATION ${CMAKE_BINARY_DIR}/bin/)

View File

@ -534,18 +534,18 @@ void Ipo::update(float time, Vec3 *xyz, Vec3 *hpr,Vec3 *scale)
* the time.
* \param t Time for which m_next_n needs to be updated.
*/
void Ipo::updateNextN(float time) const
void Ipo::updateNextN(float *time) const
{
time = m_ipo_data->adjustTime(time);
*time = m_ipo_data->adjustTime(*time);
// Time was reset since the last cached value for n,
// reset n to start from the beginning again.
if (time < m_ipo_data->m_points[m_next_n - 1].getW())
if (*time < m_ipo_data->m_points[m_next_n - 1].getW())
m_next_n = 1;
// Search for the first point in the (sorted) array which is greater or equal
// to the current time.
while (m_next_n < m_ipo_data->m_points.size() - 1 &&
time >= m_ipo_data->m_points[m_next_n].getW())
*time >= m_ipo_data->m_points[m_next_n].getW())
{
m_next_n++;
} // while
@ -564,7 +564,7 @@ float Ipo::get(float time, unsigned int index) const
if(m_next_n==0)
return m_ipo_data->m_points[0][index];
updateNextN(time);
updateNextN(&time);
float rval = m_ipo_data->get(time, index, m_next_n-1);
assert(!std::isnan(rval));
@ -587,7 +587,7 @@ void Ipo::getDerivative(float time, Vec3 *xyz)
return;
}
updateNextN(time);
updateNextN(&time);
switch (m_ipo_data->m_channel)
{
case Ipo::IPO_LOCX: xyz->setX(m_ipo_data->getDerivative(time, m_next_n, 0)); break;

View File

@ -116,7 +116,7 @@ private:
* it is declared mutable). */
mutable unsigned int m_next_n;
void updateNextN(float time) const;
void updateNextN(float *time) const;
Ipo(const Ipo *ipo);
public:

View File

@ -83,8 +83,6 @@ SFXManager::SFXManager()
m_listener_front = Vec3(0, 0, 1);
m_listener_up = Vec3(0, 1, 0);
loadSfx();
pthread_cond_init(&m_cond_request, NULL);
pthread_attr_t attr;
@ -296,6 +294,7 @@ void* SFXManager::mainLoop(void *obj)
VS::setThreadName("SFXManager");
SFXManager *me = (SFXManager*)obj;
me->loadSfx();
me->m_sfx_commands.lock();
// Wait till we have an empty sfx in the queue
@ -514,7 +513,6 @@ void SFXManager::loadSfx()
array[i++] = buffer;
}
#pragma omp parallel for private(i)
for (i = 0; i < max; i++)
{
array[i]->load();

View File

@ -28,9 +28,9 @@ void InstanceFiller<InstanceDataSingleTex>::add(GLMesh* mesh,
const InstanceSettings& is,
InstanceDataSingleTex& instance)
{
fillOriginOrientationScale<InstanceDataSingleTex>(STK::tuple_get<0>(is), instance);
fillOriginOrientationScale<InstanceDataSingleTex>(std::get<0>(is), instance);
instance.Texture = mesh->TextureHandles[0];
instance.skinning_offset = STK::tuple_get<3>(is);
instance.skinning_offset = std::get<3>(is);
}
// ----------------------------------------------------------------------------
@ -39,15 +39,15 @@ void InstanceFiller<InstanceDataThreeTex>::add(GLMesh* mesh,
const InstanceSettings& is,
InstanceDataThreeTex& instance)
{
fillOriginOrientationScale<InstanceDataThreeTex>(STK::tuple_get<0>(is), instance);
instance.MiscData.X = STK::tuple_get<1>(is).X;
instance.MiscData.Y = STK::tuple_get<1>(is).Y;
instance.MiscData.Z = STK::tuple_get<2>(is).X;
instance.MiscData.W = STK::tuple_get<2>(is).Y;
fillOriginOrientationScale<InstanceDataThreeTex>(std::get<0>(is), instance);
instance.MiscData.X = std::get<1>(is).X;
instance.MiscData.Y = std::get<1>(is).Y;
instance.MiscData.Z = std::get<2>(is).X;
instance.MiscData.W = std::get<2>(is).Y;
instance.Texture = mesh->TextureHandles[0];
instance.SecondTexture = mesh->TextureHandles[1];
instance.ThirdTexture = mesh->TextureHandles[2];
instance.skinning_offset = STK::tuple_get<3>(is);
instance.skinning_offset = std::get<3>(is);
}
// ----------------------------------------------------------------------------
@ -56,16 +56,16 @@ void InstanceFiller<InstanceDataFourTex>::add(GLMesh* mesh,
const InstanceSettings& is,
InstanceDataFourTex& instance)
{
fillOriginOrientationScale<InstanceDataFourTex>(STK::tuple_get<0>(is), instance);
instance.MiscData.X = STK::tuple_get<1>(is).X;
instance.MiscData.Y = STK::tuple_get<1>(is).Y;
instance.MiscData.Z = STK::tuple_get<2>(is).X;
instance.MiscData.W = STK::tuple_get<2>(is).Y;
fillOriginOrientationScale<InstanceDataFourTex>(std::get<0>(is), instance);
instance.MiscData.X = std::get<1>(is).X;
instance.MiscData.Y = std::get<1>(is).Y;
instance.MiscData.Z = std::get<2>(is).X;
instance.MiscData.W = std::get<2>(is).Y;
instance.Texture = mesh->TextureHandles[0];
instance.SecondTexture = mesh->TextureHandles[1];
instance.ThirdTexture = mesh->TextureHandles[2];
instance.FourthTexture = mesh->TextureHandles[3];
instance.skinning_offset = STK::tuple_get<3>(is);
instance.skinning_offset = std::get<3>(is);
}
// ----------------------------------------------------------------------------
@ -74,7 +74,7 @@ void InstanceFiller<GlowInstanceData>::add(GLMesh* mesh,
const InstanceSettings& is,
GlowInstanceData& instance)
{
scene::ISceneNode* node = STK::tuple_get<0>(is);
scene::ISceneNode* node = std::get<0>(is);
fillOriginOrientationScale<GlowInstanceData>(node, instance);
STKMeshSceneNode *nd = dynamic_cast<STKMeshSceneNode*>(node);
instance.Color = nd->getGlowColor().color;

View File

@ -688,34 +688,16 @@ void DrawCalls::prepareDrawCalls( ShadowMatrices& shadow_matrices,
return;
#if !defined(USE_GLES2)
int enableOpenMP = 0;
if (CVS->supportsAsyncInstanceUpload())
enableOpenMP = 1;
PROFILER_PUSH_CPU_MARKER("- Draw Command upload", 0xFF, 0x0, 0xFF);
#pragma omp parallel sections if(enableOpenMP)
{
#pragma omp section
{
m_solid_cmd_buffer->fill(m_solid_pass_mesh);
}
#pragma omp section
{
m_glow_cmd_buffer->fill(&m_glow_pass_mesh);
}
#pragma omp section
{
irr_driver->setPhase(SHADOW_PASS);
m_shadow_cmd_buffer->fill(m_shadow_pass_mesh);
}
#pragma omp section
if (!shadow_matrices.isRSMMapAvail())
{
m_reflective_shadow_map_cmd_buffer->fill(m_reflective_shadow_map_mesh);
}
}
PROFILER_POP_CPU_MARKER();
solid_poly_count = m_solid_cmd_buffer->getPolyCount();
shadow_poly_count = m_shadow_cmd_buffer->getPolyCount();

View File

@ -32,7 +32,7 @@ void renderMeshes1stPass()
glBindVertexArray(VAOManager::getInstance()->getVAO(T::VertexType));
for (unsigned i = 0; i < meshes.size(); i++)
{
GLMesh &mesh = *(STK::tuple_get<0>(meshes.at(i)));
GLMesh &mesh = *(std::get<0>(meshes.at(i)));
if (!CVS->isARBBaseInstanceUsable())
glBindVertexArray(mesh.vao);
if (mesh.VAOType != T::VertexType)
@ -62,7 +62,7 @@ void renderMeshes2ndPass( const std::vector<uint64_t> &Prefilled_Handle,
glBindVertexArray(VAOManager::getInstance()->getVAO(T::VertexType));
for (unsigned i = 0; i < meshes.size(); i++)
{
GLMesh &mesh = *(STK::tuple_get<0>(meshes.at(i)));
GLMesh &mesh = *(std::get<0>(meshes.at(i)));
if (!CVS->isARBBaseInstanceUsable())
glBindVertexArray(mesh.vao);
@ -101,7 +101,7 @@ void renderMeshes2ndPass<GrassMat, 4, 3, 1>
glBindVertexArray(VAOManager::getInstance()->getVAO(GrassMat::VertexType));
for (unsigned i = 0; i < meshes.size(); i++)
{
GLMesh &mesh = *(STK::tuple_get<0>(meshes.at(i)));
GLMesh &mesh = *(std::get<0>(meshes.at(i)));
if (!CVS->isARBBaseInstanceUsable())
glBindVertexArray(mesh.vao);
@ -142,7 +142,7 @@ void renderShadow(unsigned cascade)
glBindVertexArray(VAOManager::getInstance()->getVAO(T::VertexType));
for (unsigned i = 0; i < t.size(); i++)
{
GLMesh *mesh = STK::tuple_get<0>(t.at(i));
GLMesh *mesh = std::get<0>(t.at(i));
if (!CVS->isARBBaseInstanceUsable())
glBindVertexArray(mesh->vao);
if (CVS->isAZDOEnabled())
@ -164,7 +164,7 @@ void drawRSM(const core::matrix4 & rsm_matrix)
for (unsigned i = 0; i < t.size(); i++)
{
std::vector<GLuint> Textures;
GLMesh *mesh = STK::tuple_get<0>(t.at(i));
GLMesh *mesh = std::get<0>(t.at(i));
if (!CVS->isARBBaseInstanceUsable())
glBindVertexArray(mesh->vao);
if (CVS->isAZDOEnabled())

View File

@ -40,10 +40,10 @@ struct CustomUnrollArgs<n, list...>
template<typename S,
typename ...TupleTypes,
typename ...Args>
static void drawMesh(const STK::Tuple<TupleTypes...> &t,
static void drawMesh(const std::tuple<TupleTypes...> &t,
Args... args)
{
CustomUnrollArgs<list...>::template drawMesh<S>(t, STK::tuple_get<n>(t), args...);
CustomUnrollArgs<list...>::template drawMesh<S>(t, std::get<n>(t), args...);
} // drawMesh
}; // CustomUnrollArgs
@ -56,11 +56,11 @@ struct CustomUnrollArgs<>
template<typename S,
typename ...TupleTypes,
typename ...Args>
static void drawMesh(const STK::Tuple<TupleTypes...> &t,
static void drawMesh(const std::tuple<TupleTypes...> &t,
Args... args)
{
irr_driver->increaseObjectCount(); //TODO: move somewhere else
GLMesh *mesh = STK::tuple_get<0>(t);
GLMesh *mesh = std::get<0>(t);
if (!mesh->mb->getMaterial().BackfaceCulling)
glDisable(GL_CULL_FACE);
S::getInstance()->setUniforms(args...);
@ -82,10 +82,10 @@ struct TexExpanderImpl
template<typename...TupleArgs,
typename... Args>
static void expandTex(const GLMesh &mesh,
const STK::Tuple<TupleArgs...> &tex_swizzle,
const std::tuple<TupleArgs...> &tex_swizzle,
Args... args)
{
size_t idx = STK::tuple_get<sizeof...(TupleArgs) - N>(tex_swizzle);
size_t idx = std::get<sizeof...(TupleArgs) - N>(tex_swizzle);
TexExpanderImpl<T, N - 1>::template expandTex(mesh, tex_swizzle,
args..., mesh.textures[idx]->getOpenGLTextureName());
} // ExpandTex
@ -98,7 +98,7 @@ struct TexExpanderImpl<T, 0>
{
template<typename...TupleArgs, typename... Args>
static void expandTex(const GLMesh &mesh,
const STK::Tuple<TupleArgs...> &tex_swizzle,
const std::tuple<TupleArgs...> &tex_swizzle,
Args... args)
{
T::getInstance()->setTextureUnits(args...);
@ -117,7 +117,7 @@ struct TexExpander
template<typename...TupleArgs,
typename... Args>
static void expandTex(const GLMesh &mesh,
const STK::Tuple<TupleArgs...> &tex_swizzle,
const std::tuple<TupleArgs...> &tex_swizzle,
Args... args)
{
TexExpanderImpl<T, sizeof...(TupleArgs)>::expandTex(mesh,
@ -134,10 +134,10 @@ struct HandleExpanderImpl
{
template<typename...TupleArgs, typename... Args>
static void expand(uint64_t *texture_handles,
const STK::Tuple<TupleArgs...> &tex_swizzle,
const std::tuple<TupleArgs...> &tex_swizzle,
Args... args)
{
size_t idx = STK::tuple_get<sizeof...(TupleArgs)-N>(tex_swizzle);
size_t idx = std::get<sizeof...(TupleArgs)-N>(tex_swizzle);
HandleExpanderImpl<T, N - 1>::template expand(texture_handles,
tex_swizzle,
args...,
@ -152,7 +152,7 @@ struct HandleExpanderImpl<T, 0>
{
template<typename...TupleArgs, typename... Args>
static void expand(uint64_t *texture_handles,
const STK::Tuple<TupleArgs...> &tex_swizzle,
const std::tuple<TupleArgs...> &tex_swizzle,
Args... args)
{
T::getInstance()->setTextureHandles(args...);
@ -174,7 +174,7 @@ struct HandleExpander
template<typename...TupleArgs,
typename... Args>
static void expand(uint64_t *texture_handles,
const STK::Tuple<TupleArgs...> &tex_swizzle,
const std::tuple<TupleArgs...> &tex_swizzle,
Args... args)
{
HandleExpanderImpl<T, sizeof...(TupleArgs)>::expand(texture_handles,

View File

@ -26,7 +26,7 @@
#include "graphics/shaders.hpp"
#include "modes/world.hpp"
#include "tracks/track.hpp"
#include "utils/tuple.hpp"
#include <tuple>
#include <SColor.h>
#include <S3DVertex.h>
@ -199,14 +199,14 @@ void AbstractGeometryPasses::setFirstPassRenderTargets(const std::vector<GLuint>
template<typename Shader, enum video::E_VERTEX_TYPE VertexType, int...List,
typename... TupleType>
void renderTransparenPass(const std::vector<RenderGeometry::TexUnit> &TexUnits,
std::vector<STK::Tuple<TupleType...> > *meshes)
std::vector<std::tuple<TupleType...> > *meshes)
{
Shader::getInstance()->use();
if (CVS->isARBBaseInstanceUsable())
glBindVertexArray(VAOManager::getInstance()->getVAO(VertexType));
for (unsigned i = 0; i < meshes->size(); i++)
{
GLMesh &mesh = *(STK::tuple_get<0>(meshes->at(i)));
GLMesh &mesh = *(std::get<0>(meshes->at(i)));
if (!CVS->isARBBaseInstanceUsable())
glBindVertexArray(mesh.vao);
if (mesh.VAOType != VertexType)
@ -329,11 +329,11 @@ void AbstractGeometryPasses::renderTransparent(const DrawCalls& draw_calls,
for (unsigned i = 0; i < ListDisplacement::getInstance()->size(); i++)
{
const GLMesh &mesh =
*(STK::tuple_get<0>(ListDisplacement::getInstance()->at(i)));
*(std::get<0>(ListDisplacement::getInstance()->at(i)));
if (!CVS->isARBBaseInstanceUsable())
glBindVertexArray(mesh.vao);
const core::matrix4 &AbsoluteTransformation
= STK::tuple_get<1>(ListDisplacement::getInstance()->at(i));
= std::get<1>(ListDisplacement::getInstance()->at(i));
if (mesh.VAOType != video::EVT_2TCOORDS)
{
#ifdef DEBUG
@ -360,11 +360,11 @@ void AbstractGeometryPasses::renderTransparent(const DrawCalls& draw_calls,
for (unsigned i = 0; i < ListDisplacement::getInstance()->size(); i++)
{
const GLMesh &mesh =
*(STK::tuple_get<0>(ListDisplacement::getInstance()->at(i)));
*(std::get<0>(ListDisplacement::getInstance()->at(i)));
if (!CVS->isARBBaseInstanceUsable())
glBindVertexArray(mesh.vao);
const core::matrix4 &AbsoluteTransformation =
STK::tuple_get<1>(ListDisplacement::getInstance()->at(i));
std::get<1>(ListDisplacement::getInstance()->at(i));
if (mesh.VAOType != video::EVT_2TCOORDS)
continue;

View File

@ -742,111 +742,111 @@ InstancedSkinnedRefShadowShader::InstancedSkinnedRefShadowShader()
// ============================================================================
const InstanceType SkinnedSolid::Instance = InstanceTypeThreeTex;
const STK::Tuple<size_t> SkinnedSolid::FirstPassTextures
= STK::Tuple<size_t>(1);
const STK::Tuple<size_t, size_t, size_t> SkinnedSolid::SecondPassTextures
= STK::Tuple<size_t, size_t, size_t>(0, 1, 2);
const STK::Tuple<> SkinnedSolid::ShadowTextures;
const STK::Tuple<size_t> SkinnedSolid::RSMTextures = STK::Tuple<size_t>(0);
const std::tuple<size_t> SkinnedSolid::FirstPassTextures
= std::tuple<size_t>(1);
const std::tuple<size_t, size_t, size_t> SkinnedSolid::SecondPassTextures
= std::tuple<size_t, size_t, size_t>(0, 1, 2);
std::tuple<> SkinnedSolid::ShadowTextures;
const std::tuple<size_t> SkinnedSolid::RSMTextures = std::tuple<size_t>(0);
// ----------------------------------------------------------------------------
const InstanceType SkinnedAlphaRef::Instance = InstanceTypeThreeTex;
const STK::Tuple<size_t, size_t> SkinnedAlphaRef::FirstPassTextures
= STK::Tuple<size_t, size_t>(0, 1);
const STK::Tuple<size_t, size_t, size_t> SkinnedAlphaRef::SecondPassTextures
= STK::Tuple<size_t, size_t, size_t>(0, 1, 2);
const STK::Tuple<size_t> SkinnedAlphaRef::ShadowTextures
= STK::Tuple<size_t>(0);
const STK::Tuple<size_t> SkinnedAlphaRef::RSMTextures = STK::Tuple<size_t>(0);
const std::tuple<size_t, size_t> SkinnedAlphaRef::FirstPassTextures
= std::tuple<size_t, size_t>(0, 1);
const std::tuple<size_t, size_t, size_t> SkinnedAlphaRef::SecondPassTextures
= std::tuple<size_t, size_t, size_t>(0, 1, 2);
const std::tuple<size_t> SkinnedAlphaRef::ShadowTextures
= std::tuple<size_t>(0);
const std::tuple<size_t> SkinnedAlphaRef::RSMTextures = std::tuple<size_t>(0);
// ----------------------------------------------------------------------------
const InstanceType SkinnedUnlitMat::Instance = InstanceTypeThreeTex;
const STK::Tuple<size_t, size_t> SkinnedUnlitMat::FirstPassTextures
= STK::Tuple<size_t, size_t>(0, 1);
const STK::Tuple<size_t> SkinnedUnlitMat::SecondPassTextures
= STK::Tuple<size_t>(0);
const STK::Tuple<size_t> SkinnedUnlitMat::ShadowTextures
= STK::Tuple<size_t>(0);
const STK::Tuple<size_t> SkinnedUnlitMat::RSMTextures = STK::Tuple<size_t>(0);
const std::tuple<size_t, size_t> SkinnedUnlitMat::FirstPassTextures
= std::tuple<size_t, size_t>(0, 1);
const std::tuple<size_t> SkinnedUnlitMat::SecondPassTextures
= std::tuple<size_t>(0);
const std::tuple<size_t> SkinnedUnlitMat::ShadowTextures
= std::tuple<size_t>(0);
const std::tuple<size_t> SkinnedUnlitMat::RSMTextures = std::tuple<size_t>(0);
// ----------------------------------------------------------------------------
const InstanceType SkinnedNormalMat::Instance = InstanceTypeFourTex;
const STK::Tuple<size_t, size_t> SkinnedNormalMat::FirstPassTextures
= STK::Tuple<size_t, size_t>(3, 1);
const STK::Tuple<size_t, size_t, size_t> SkinnedNormalMat::SecondPassTextures
= STK::Tuple<size_t, size_t, size_t>(0, 1, 2);
const STK::Tuple<> SkinnedNormalMat::ShadowTextures;
const STK::Tuple<size_t> SkinnedNormalMat::RSMTextures = STK::Tuple<size_t>(0);
const std::tuple<size_t, size_t> SkinnedNormalMat::FirstPassTextures
= std::tuple<size_t, size_t>(3, 1);
const std::tuple<size_t, size_t, size_t> SkinnedNormalMat::SecondPassTextures
= std::tuple<size_t, size_t, size_t>(0, 1, 2);
std::tuple<> SkinnedNormalMat::ShadowTextures;
const std::tuple<size_t> SkinnedNormalMat::RSMTextures = std::tuple<size_t>(0);
// ----------------------------------------------------------------------------
const InstanceType DefaultMaterial::Instance = InstanceTypeThreeTex;
const STK::Tuple<size_t> DefaultMaterial::FirstPassTextures
= STK::Tuple<size_t>(1);
const STK::Tuple<size_t, size_t, size_t> DefaultMaterial::SecondPassTextures
= STK::Tuple<size_t, size_t, size_t>(0, 1, 2);
const STK::Tuple<> DefaultMaterial::ShadowTextures;
const STK::Tuple<size_t> DefaultMaterial::RSMTextures = STK::Tuple<size_t>(0);
const std::tuple<size_t> DefaultMaterial::FirstPassTextures
= std::tuple<size_t>(1);
const std::tuple<size_t, size_t, size_t> DefaultMaterial::SecondPassTextures
= std::tuple<size_t, size_t, size_t>(0, 1, 2);
std::tuple<> DefaultMaterial::ShadowTextures;
const std::tuple<size_t> DefaultMaterial::RSMTextures = std::tuple<size_t>(0);
// ----------------------------------------------------------------------------
const InstanceType AlphaRef::Instance = InstanceTypeThreeTex;
const STK::Tuple<size_t, size_t> AlphaRef::FirstPassTextures
= STK::Tuple<size_t, size_t>(0, 1);
const STK::Tuple<size_t, size_t, size_t> AlphaRef::SecondPassTextures
= STK::Tuple<size_t, size_t, size_t>(0, 1, 2);
const STK::Tuple<size_t> AlphaRef::ShadowTextures = STK::Tuple<size_t>(0);
const STK::Tuple<size_t> AlphaRef::RSMTextures = STK::Tuple<size_t>(0);
const std::tuple<size_t, size_t> AlphaRef::FirstPassTextures
= std::tuple<size_t, size_t>(0, 1);
const std::tuple<size_t, size_t, size_t> AlphaRef::SecondPassTextures
= std::tuple<size_t, size_t, size_t>(0, 1, 2);
const std::tuple<size_t> AlphaRef::ShadowTextures = std::tuple<size_t>(0);
const std::tuple<size_t> AlphaRef::RSMTextures = std::tuple<size_t>(0);
// ----------------------------------------------------------------------------
const InstanceType SphereMap::Instance = InstanceTypeThreeTex;
const STK::Tuple<size_t> SphereMap::FirstPassTextures = STK::Tuple<size_t>(1);
const STK::Tuple<size_t> SphereMap::SecondPassTextures = STK::Tuple<size_t>(0);
const STK::Tuple<> SphereMap::ShadowTextures;
const STK::Tuple<size_t> SphereMap::RSMTextures = STK::Tuple<size_t>(0);
const std::tuple<size_t> SphereMap::FirstPassTextures = std::tuple<size_t>(1);
const std::tuple<size_t> SphereMap::SecondPassTextures = std::tuple<size_t>(0);
std::tuple<> SphereMap::ShadowTextures;
const std::tuple<size_t> SphereMap::RSMTextures = std::tuple<size_t>(0);
// ----------------------------------------------------------------------------
const InstanceType UnlitMat::Instance = InstanceTypeThreeTex;
const STK::Tuple<size_t, size_t> UnlitMat::FirstPassTextures
= STK::Tuple<size_t, size_t>(0, 1);
const STK::Tuple<size_t> UnlitMat::SecondPassTextures = STK::Tuple<size_t>(0);
const STK::Tuple<size_t> UnlitMat::ShadowTextures = STK::Tuple<size_t>(0);
const STK::Tuple<size_t> UnlitMat::RSMTextures = STK::Tuple<size_t>(0);
const std::tuple<size_t, size_t> UnlitMat::FirstPassTextures
= std::tuple<size_t, size_t>(0, 1);
const std::tuple<size_t> UnlitMat::SecondPassTextures = std::tuple<size_t>(0);
const std::tuple<size_t> UnlitMat::ShadowTextures = std::tuple<size_t>(0);
const std::tuple<size_t> UnlitMat::RSMTextures = std::tuple<size_t>(0);
// ----------------------------------------------------------------------------
const InstanceType GrassMat::Instance = InstanceTypeThreeTex;
const STK::Tuple<size_t, size_t> GrassMat::FirstPassTextures
= STK::Tuple<size_t, size_t>(0, 1);
const STK::Tuple<size_t, size_t, size_t> GrassMat::SecondPassTextures
= STK::Tuple<size_t, size_t, size_t>(0, 1, 2);
const STK::Tuple<size_t> GrassMat::ShadowTextures = STK::Tuple<size_t>(0);
const STK::Tuple<size_t> GrassMat::RSMTextures = STK::Tuple<size_t>(0);
const std::tuple<size_t, size_t> GrassMat::FirstPassTextures
= std::tuple<size_t, size_t>(0, 1);
const std::tuple<size_t, size_t, size_t> GrassMat::SecondPassTextures
= std::tuple<size_t, size_t, size_t>(0, 1, 2);
const std::tuple<size_t> GrassMat::ShadowTextures = std::tuple<size_t>(0);
const std::tuple<size_t> GrassMat::RSMTextures = std::tuple<size_t>(0);
// ----------------------------------------------------------------------------
const InstanceType NormalMat::Instance = InstanceTypeFourTex;
const STK::Tuple<size_t, size_t> NormalMat::FirstPassTextures
= STK::Tuple<size_t, size_t>(3, 1);
const STK::Tuple<size_t, size_t, size_t> NormalMat::SecondPassTextures
= STK::Tuple<size_t, size_t, size_t>(0, 1, 2);
const STK::Tuple<> NormalMat::ShadowTextures;
const STK::Tuple<size_t> NormalMat::RSMTextures = STK::Tuple<size_t>(0);
const std::tuple<size_t, size_t> NormalMat::FirstPassTextures
= std::tuple<size_t, size_t>(3, 1);
const std::tuple<size_t, size_t, size_t> NormalMat::SecondPassTextures
= std::tuple<size_t, size_t, size_t>(0, 1, 2);
std::tuple<> NormalMat::ShadowTextures;
const std::tuple<size_t> NormalMat::RSMTextures = std::tuple<size_t>(0);
// ----------------------------------------------------------------------------
const InstanceType DetailMat::Instance = InstanceTypeFourTex;
const STK::Tuple<size_t> DetailMat::FirstPassTextures = STK::Tuple<size_t>(1);
const STK::Tuple<size_t, size_t, size_t> DetailMat::SecondPassTextures
= STK::Tuple<size_t, size_t, size_t>(0, 3, 1);
const STK::Tuple<> DetailMat::ShadowTextures;
const STK::Tuple<size_t> DetailMat::RSMTextures = STK::Tuple<size_t>(0);
const std::tuple<size_t> DetailMat::FirstPassTextures = std::tuple<size_t>(1);
const std::tuple<size_t, size_t, size_t> DetailMat::SecondPassTextures
= std::tuple<size_t, size_t, size_t>(0, 3, 1);
std::tuple<> DetailMat::ShadowTextures;
const std::tuple<size_t> DetailMat::RSMTextures = std::tuple<size_t>(0);
// ----------------------------------------------------------------------------
const STK::Tuple<size_t> SplattingMat::FirstPassTextures
= STK::Tuple<size_t>(7);
const STK::Tuple<size_t, size_t, size_t, size_t, size_t>
const std::tuple<size_t> SplattingMat::FirstPassTextures
= std::tuple<size_t>(7);
const std::tuple<size_t, size_t, size_t, size_t, size_t>
SplattingMat::SecondPassTextures
= STK::Tuple<size_t, size_t, size_t, size_t, size_t>(1, 3, 4, 5, 6);
const STK::Tuple<> SplattingMat::ShadowTextures;
const STK::Tuple<size_t, size_t, size_t, size_t, size_t>
= std::tuple<size_t, size_t, size_t, size_t, size_t>(1, 3, 4, 5, 6);
std::tuple<> SplattingMat::ShadowTextures;
const std::tuple<size_t, size_t, size_t, size_t, size_t>
SplattingMat::RSMTextures
= STK::Tuple<size_t, size_t, size_t, size_t, size_t>(1, 3, 4, 5, 6);
= std::tuple<size_t, size_t, size_t, size_t, size_t>(1, 3, 4, 5, 6);
// ----------------------------------------------------------------------------
#endif

View File

@ -443,10 +443,10 @@ struct SkinnedSolid
static const enum Material::ShaderType MaterialType
= Material::SHADERTYPE_SOLID_SKINNED_MESH;
static const enum InstanceType Instance;
static const STK::Tuple<size_t> FirstPassTextures;
static const STK::Tuple<size_t, size_t, size_t> SecondPassTextures;
static const STK::Tuple<> ShadowTextures;
static const STK::Tuple<size_t> RSMTextures;
static const std::tuple<size_t> FirstPassTextures;
static const std::tuple<size_t, size_t, size_t> SecondPassTextures;
static std::tuple<> ShadowTextures;
static const std::tuple<size_t> RSMTextures;
}; // SkinnedSolid
// ----------------------------------------------------------------------------
@ -464,10 +464,10 @@ struct SkinnedAlphaRef
static const enum Material::ShaderType MaterialType =
Material::SHADERTYPE_ALPHA_TEST_SKINNED_MESH;
static const enum InstanceType Instance;
static const STK::Tuple<size_t, size_t> FirstPassTextures;
static const STK::Tuple<size_t, size_t, size_t> SecondPassTextures;
static const STK::Tuple<size_t> ShadowTextures;
static const STK::Tuple<size_t> RSMTextures;
static const std::tuple<size_t, size_t> FirstPassTextures;
static const std::tuple<size_t, size_t, size_t> SecondPassTextures;
static const std::tuple<size_t> ShadowTextures;
static const std::tuple<size_t> RSMTextures;
}; // SkinnedAlphaRef
// ----------------------------------------------------------------------------
@ -485,10 +485,10 @@ struct SkinnedNormalMat
static const enum Material::ShaderType MaterialType =
Material::SHADERTYPE_NORMAL_MAP_SKINNED_MESH;
static const enum InstanceType Instance;
static const STK::Tuple<size_t, size_t> FirstPassTextures;
static const STK::Tuple<size_t, size_t, size_t> SecondPassTextures;
static const STK::Tuple<> ShadowTextures;
static const STK::Tuple<size_t> RSMTextures;
static const std::tuple<size_t, size_t> FirstPassTextures;
static const std::tuple<size_t, size_t, size_t> SecondPassTextures;
static std::tuple<> ShadowTextures;
static const std::tuple<size_t> RSMTextures;
}; // SkinnedNormalMat
// ----------------------------------------------------------------------------
@ -506,10 +506,10 @@ struct SkinnedUnlitMat
static const enum Material::ShaderType MaterialType =
Material::SHADERTYPE_SOLID_UNLIT_SKINNED_MESH;
static const enum InstanceType Instance;
static const STK::Tuple<size_t, size_t> FirstPassTextures;
static const STK::Tuple<size_t> SecondPassTextures;
static const STK::Tuple<size_t> ShadowTextures;
static const STK::Tuple<size_t> RSMTextures;
static const std::tuple<size_t, size_t> FirstPassTextures;
static const std::tuple<size_t> SecondPassTextures;
static const std::tuple<size_t> ShadowTextures;
static const std::tuple<size_t> RSMTextures;
}; // SkinnedUnlitMat
// ----------------------------------------------------------------------------
@ -528,10 +528,10 @@ struct DefaultMaterial
static const enum Material::ShaderType MaterialType
= Material::SHADERTYPE_SOLID;
static const enum InstanceType Instance;
static const STK::Tuple<size_t> FirstPassTextures;
static const STK::Tuple<size_t, size_t, size_t> SecondPassTextures;
static const STK::Tuple<> ShadowTextures;
static const STK::Tuple<size_t> RSMTextures;
static const std::tuple<size_t> FirstPassTextures;
static const std::tuple<size_t, size_t, size_t> SecondPassTextures;
static std::tuple<> ShadowTextures;
static const std::tuple<size_t> RSMTextures;
}; // DefaultMaterial
// ----------------------------------------------------------------------------
@ -549,10 +549,10 @@ struct AlphaRef
static const enum video::E_VERTEX_TYPE VertexType = video::EVT_STANDARD;
static const enum Material::ShaderType MaterialType = Material::SHADERTYPE_ALPHA_TEST;
static const enum InstanceType Instance;
static const STK::Tuple<size_t, size_t> FirstPassTextures;
static const STK::Tuple<size_t, size_t, size_t> SecondPassTextures;
static const STK::Tuple<size_t> ShadowTextures;
static const STK::Tuple<size_t> RSMTextures;
static const std::tuple<size_t, size_t> FirstPassTextures;
static const std::tuple<size_t, size_t, size_t> SecondPassTextures;
static const std::tuple<size_t> ShadowTextures;
static const std::tuple<size_t> RSMTextures;
}; // AlphaRef
// ----------------------------------------------------------------------------
@ -571,10 +571,10 @@ struct SphereMap
static const enum Material::ShaderType MaterialType
= Material::SHADERTYPE_SPHERE_MAP;
static const enum InstanceType Instance;
static const STK::Tuple<size_t> FirstPassTextures;
static const STK::Tuple<size_t> SecondPassTextures;
static const STK::Tuple<> ShadowTextures;
static const STK::Tuple<size_t> RSMTextures;
static const std::tuple<size_t> FirstPassTextures;
static const std::tuple<size_t> SecondPassTextures;
static std::tuple<> ShadowTextures;
static const std::tuple<size_t> RSMTextures;
}; // SphereMap
// ----------------------------------------------------------------------------
@ -593,10 +593,10 @@ struct UnlitMat
static const enum Material::ShaderType MaterialType =
Material::SHADERTYPE_SOLID_UNLIT;
static const enum InstanceType Instance;
static const STK::Tuple<size_t, size_t> FirstPassTextures;
static const STK::Tuple<size_t> SecondPassTextures;
static const STK::Tuple<size_t> ShadowTextures;
static const STK::Tuple<size_t> RSMTextures;
static const std::tuple<size_t, size_t> FirstPassTextures;
static const std::tuple<size_t> SecondPassTextures;
static const std::tuple<size_t> ShadowTextures;
static const std::tuple<size_t> RSMTextures;
}; // UnlitMat
// ----------------------------------------------------------------------------
@ -615,10 +615,10 @@ struct GrassMat
static const enum Material::ShaderType MaterialType
= Material::SHADERTYPE_VEGETATION;
static const enum InstanceType Instance;
static const STK::Tuple<size_t, size_t> FirstPassTextures;
static const STK::Tuple<size_t, size_t, size_t> SecondPassTextures;
static const STK::Tuple<size_t> ShadowTextures;
static const STK::Tuple<size_t> RSMTextures;
static const std::tuple<size_t, size_t> FirstPassTextures;
static const std::tuple<size_t, size_t, size_t> SecondPassTextures;
static const std::tuple<size_t> ShadowTextures;
static const std::tuple<size_t> RSMTextures;
}; // GrassMat
// ----------------------------------------------------------------------------
@ -637,10 +637,10 @@ struct NormalMat
static const enum Material::ShaderType MaterialType
= Material::SHADERTYPE_NORMAL_MAP;
static const enum InstanceType Instance;
static const STK::Tuple<size_t, size_t> FirstPassTextures;
static const STK::Tuple<size_t, size_t, size_t> SecondPassTextures;
static const STK::Tuple<> ShadowTextures;
static const STK::Tuple<size_t> RSMTextures;
static const std::tuple<size_t, size_t> FirstPassTextures;
static const std::tuple<size_t, size_t, size_t> SecondPassTextures;
static std::tuple<> ShadowTextures;
static const std::tuple<size_t> RSMTextures;
}; // NormalMat
// ----------------------------------------------------------------------------
@ -659,10 +659,10 @@ struct DetailMat
static const enum Material::ShaderType MaterialType
= Material::SHADERTYPE_DETAIL_MAP;
static const enum InstanceType Instance;
static const STK::Tuple<size_t> FirstPassTextures;
static const STK::Tuple<size_t, size_t, size_t> SecondPassTextures;
static const STK::Tuple<> ShadowTextures;
static const STK::Tuple<size_t> RSMTextures;
static const std::tuple<size_t> FirstPassTextures;
static const std::tuple<size_t, size_t, size_t> SecondPassTextures;
static std::tuple<> ShadowTextures;
static const std::tuple<size_t> RSMTextures;
}; // DetailMat
// ----------------------------------------------------------------------------
@ -678,11 +678,11 @@ struct SplattingMat
static const enum video::E_VERTEX_TYPE VertexType = video::EVT_2TCOORDS;
static const enum Material::ShaderType MaterialType
= Material::SHADERTYPE_SPLATTING;
static const STK::Tuple<size_t> FirstPassTextures;
static const STK::Tuple<size_t, size_t, size_t, size_t, size_t>
static const std::tuple<size_t> FirstPassTextures;
static const std::tuple<size_t, size_t, size_t, size_t, size_t>
SecondPassTextures;
static const STK::Tuple<> ShadowTextures;
static const STK::Tuple<size_t, size_t, size_t, size_t, size_t>
static std::tuple<> ShadowTextures;
static const std::tuple<size_t, size_t, size_t, size_t, size_t>
RSMTextures;
}; // SplattingMat

View File

@ -29,29 +29,107 @@
#include <cassert>
#include <irrlicht.h>
#if __SSE2__ || _M_X64 || _M_IX86_FP >= 2
#include <emmintrin.h>
#define SIMD_SSE2_SUPPORT (1)
#endif
#if __SSE4_1__ || __AVX__
#include <smmintrin.h>
#define SIMD_SSE4_1_SUPPORT (1)
#endif
#if SIMD_SSE4_1_SUPPORT
#include <smmintrin.h>
#define SIMD_BLENDV_PS(x,y,mask) _mm_blendv_ps(x,y,mask)
#elif SIMD_SSE2_SUPPORT
#define SIMD_BLENDV_PS(x,y,mask) _mm_or_ps(_mm_andnot_ps(mask,x),_mm_and_ps(y,mask))
#endif
#if defined(__GNUC__) || defined(__INTEL_COMPILER) || defined(__clang__)
#define ALWAYSINLINE __attribute__((always_inline))
#define SIMD_ALIGN16 __attribute__((aligned(16)))
#elif defined(_MSC_VER)
#define SIMD_ALIGN16 __declspec(align(16))
#define ALWAYSINLINE __forceinline
#else
#define ALWAYSINLINE
#endif
using namespace irr;
namespace
{
/** Convert an unsigned char cubemap texture to a float texture
* \param sh_rgba The 6 faces of the cubemap texture
* \param sh_w Texture width
* \param sh_h Texture height
* \param[out] float_tex_cube The converted float cubemap texture
*/
void convertToFloatTexture(unsigned char *sh_rgba[6], unsigned sh_w, unsigned sh_h, Color *float_tex_cube[6])
#if defined(__x86_64__) || defined(__x86_64) || defined(__amd64__) || defined(__amd64) || defined(__i386__) || defined(__i386) || defined(i386)
/* Input is 0.0,255.0, output is 0.0,1.0 */
static inline ALWAYSINLINE float srgb2linear( float v )
{
for (unsigned i = 0; i < 6; i++)
float v2, vpow, vpwsqrt;
union
{
float_tex_cube[i] = new Color[sh_w * sh_h];
for (unsigned j = 0; j < sh_w * sh_h; j++)
int32_t i;
float f;
} u;
if( v <= (0.04045f*255.0f) )
v = v * ( (1.0f/12.92f)*(1.0f/255.0f) );
else
{
float_tex_cube[i][j].Blue = powf(float(0xFF & sh_rgba[i][4 * j]) / 255.f, 2.2f);
float_tex_cube[i][j].Green = powf(float(0xFF & sh_rgba[i][4 * j + 1]) / 255.f, 2.2f);
float_tex_cube[i][j].Red = powf(float(0xFF & sh_rgba[i][4 * j + 2]) / 255.f, 2.2f);
v = ( v + (0.055f*255.0f) ) * ( (1.0f/1.055f)*(1.0f/255.0f) );
v2 = v * v;
u.f = v * 5417434112.0f;
u.i = (int32_t)( ( (float)u.i * 0.8f ) + 0.5f );
vpow = u.f;
vpwsqrt = sqrtf( vpow );
v = ( ( v2 * vpwsqrt ) + ( ( ( v2 * v ) / vpwsqrt ) / sqrtf( vpwsqrt ) ) ) * 0.51011878327f;
}
return v;
}
} //convertToFloatTexture
#else
/* Input is 0.0,255.0, output is 0.0,1.0 */
/* Only for reference, this is waayyy too slow and should never be used */
static inline ALWAYSINLINE float srgb2linear( float v )
{
v *= (1.0f/255.0f);
if( v <= 0.04045f )
v = v * (1.0f/12.92);
else
v = pow( ( v + 0.055f ) * (1.0f/1.055f), 2.4f );
return v;
}
#endif
#if SIMD_SSE2_SUPPORT
static const float SIMD_ALIGN16 srgbLinearConst00[4] = { 0.04045f*255.0f, 0.04045f*255.0f, 0.04045f*255.0f, 0.04045f*255.0f };
static const float SIMD_ALIGN16 srgbLinearConst01[4] = { (1.0f/12.92f)*(1.0f/255.0f), (1.0f/12.92f)*(1.0f/255.0f), (1.0f/12.92f)*(1.0f/255.0f), (1.0f/12.92f)*(1.0f/255.0f) };
static const float SIMD_ALIGN16 srgbLinearConst02[4] = { 0.055f*255.0f, 0.055f*255.0f, 0.055f*255.0f, 0.055f*255.0f };
static const float SIMD_ALIGN16 srgbLinearConst03[4] = { (1.0f/1.055f)*(1.0f/255.0f), (1.0f/1.055f)*(1.0f/255.0f), (1.0f/1.055f)*(1.0f/255.0f), (1.0f/1.055f)*(1.0f/255.0f) };
static const float SIMD_ALIGN16 srgbLinearConst04[4] = { 5417434112.0f, 5417434112.0f, 5417434112.0f, 5417434112.0f };
static const float SIMD_ALIGN16 srgbLinearConst05[4] = { 0.8f, 0.8f, 0.8f, 0.8f };
static const float SIMD_ALIGN16 srgbLinearConst06[4] = { 0.51011878327f, 0.51011878327f, 0.51011878327f, 0.51011878327f };
/* Input is 0.0,255.0 ~ output is 0.0,1.0 */
static inline ALWAYSINLINE __m128 srgb2linear4( __m128 vx )
{
__m128 vmask, vbase;
__m128 vpow, vpwsqrtinv, vpwsqrt, vx2;
vmask = _mm_cmple_ps( vx, *(__m128*)srgbLinearConst00 );
vbase = _mm_mul_ps( vx, *(__m128*)srgbLinearConst01 );
vx = _mm_mul_ps( _mm_add_ps( vx, *(__m128*)srgbLinearConst02 ), *(__m128*)srgbLinearConst03 );
vx2 = _mm_mul_ps( vx, vx );
vpow = _mm_castsi128_ps( _mm_cvtps_epi32( _mm_mul_ps( _mm_cvtepi32_ps( _mm_castps_si128( _mm_mul_ps( vx, *(__m128*)srgbLinearConst04 ) ) ), *(__m128*)srgbLinearConst05 ) ) );
vpwsqrtinv = _mm_rsqrt_ps( vpow );
vpwsqrt = _mm_mul_ps( vpow, vpwsqrtinv );
vx = _mm_mul_ps( _mm_add_ps( _mm_mul_ps( vx2, vpwsqrt ), _mm_mul_ps( _mm_mul_ps( _mm_mul_ps( vx2, vx ), vpwsqrtinv ), _mm_rsqrt_ps( vpwsqrt ) ) ), *(__m128*)srgbLinearConst06 );
return SIMD_BLENDV_PS( vx, vbase, vmask );
}
#endif
// ------------------------------------------------------------------------
/** Print the nine first spherical harmonics coefficients
@ -106,174 +184,292 @@ namespace
*/
void getXYZ(GLenum face, float i, float j, float &x, float &y, float &z)
{
float norminv;
switch (face)
{
case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
x = 1.;
case 0: // PosX
x = 1.0f;
y = -i;
z = -j;
break;
case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
x = -1.;
case 1: // NegX
x = -1.0f;
y = -i;
z = j;
break;
case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
case 2: // PosY
x = j;
y = 1.;
y = 1.0f;
z = i;
break;
case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
case 3: // NegY
x = j;
y = -1;
y = -1.0f;
z = -i;
break;
case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
case 4: // PosZ
x = j;
y = -i;
z = 1;
z = 1.0f;
break;
case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
case 5: // NegZ
x = -j;
y = -i;
z = -1;
z = -1.0f;
break;
}
float norm = sqrt(x * x + y * y + z * z);
x /= norm, y /= norm, z /= norm;
norminv = 1.0f / sqrtf(x * x + y * y + z * z);
x *= norminv, y *= norminv, z *= norminv;
return;
} // getXYZ
// ------------------------------------------------------------------------
/** Compute the value of the spherical harmonics basis functions (Yml)
* on each texel of a cubemap face
* \param face Face of the cubemap
* \param edge_size Size of the cubemap face
* \param[out] Yml The sphericals harmonics functions values on each texel of the cubemap
*/
void getYml(GLenum face, size_t edge_size,
float *Y00,
float *Y1minus1, float *Y10, float *Y11,
float *Y2minus2, float *Y2minus1, float *Y20, float *Y21, float *Y22)
{
#pragma omp parallel for
for (int i = 0; i < int(edge_size); i++)
{
for (unsigned j = 0; j < edge_size; j++)
{
float x, y, z;
float fi = float(i), fj = float(j);
fi /= edge_size, fj /= edge_size;
fi = 2 * fi - 1, fj = 2 * fj - 1;
getXYZ(face, fi, fj, x, y, z);
// constant part of Ylm
float c00 = 0.282095f;
float c1minus1 = 0.488603f;
float c10 = 0.488603f;
float c11 = 0.488603f;
float c2minus2 = 1.092548f;
float c2minus1 = 1.092548f;
float c21 = 1.092548f;
float c20 = 0.315392f;
float c22 = 0.546274f;
size_t idx = i * edge_size + j;
Y00[idx] = c00;
Y1minus1[idx] = c1minus1 * y;
Y10[idx] = c10 * z;
Y11[idx] = c11 * x;
Y2minus2[idx] = c2minus2 * x * y;
Y2minus1[idx] = c2minus1 * y * z;
Y21[idx] = c21 * x * z;
Y20[idx] = c20 * (3 * z * z - 1);
Y22[idx] = c22 * (x * x - y * y);
}
}
}
} //namespace
// ----------------------------------------------------------------------------
/** Compute m_SH_coeff->red_SH_coeff, m_SH_coeff->green_SH_coeff
* and m_SH_coeff->blue_SH_coeff from Yml values
* \param cubemap_face The 6 cubemap faces (float textures)
* \param sh_rgba The 6 cubemap faces (sRGB byte textures)
* \param edge_size Size of the cubemap face
* \param Yml The sphericals harmonics functions values on each texel of the cubemap
*/
void SphericalHarmonics::projectSH(Color *cubemap_face[6], size_t edge_size,
float *Y00[],
float *Y1minus1[], float *Y10[], float *Y11[],
float *Y2minus2[], float *Y2minus1[], float * Y20[],
float *Y21[], float *Y22[])
void SphericalHarmonics::generateSphericalHarmonics(unsigned char *sh_rgba[6], size_t edge_size)
{
for (unsigned i = 0; i < 9; i++)
#if SIMD_SSE2_SUPPORT
float wh = float(edge_size * edge_size);
float edge_size_inv;
float fi, fj, fi2p1;
unsigned char *shface;
__m128 sh0, sh1, sh2, sh3, sh4, sh5, sh6, sh7, sh8;
// constant part of Ylm
const float c00 = 0.282095f;
const float c1minus1 = 0.488603f;
const float c10 = 0.488603f;
const float c11 = 0.488603f;
const float c2minus2 = 1.092548f;
const float c2minus1 = 1.092548f;
const float c21 = 1.092548f;
const float c20 = 0.315392f;
const float c22 = 0.546274f;
sh0 = _mm_setzero_ps();
sh1 = _mm_setzero_ps();
sh2 = _mm_setzero_ps();
sh3 = _mm_setzero_ps();
sh4 = _mm_setzero_ps();
sh5 = _mm_setzero_ps();
sh6 = _mm_setzero_ps();
sh7 = _mm_setzero_ps();
sh8 = _mm_setzero_ps();
edge_size_inv = 2.0f / edge_size;
for (unsigned face = 0; face < 6; face++)
{
m_SH_coeff->blue_SH_coeff[i] = 0;
m_SH_coeff->green_SH_coeff[i] = 0;
m_SH_coeff->red_SH_coeff[i] = 0;
shface = sh_rgba[face];
for (int i = 0; i < int(edge_size); i++)
{
int shidx = ( i * edge_size ) * 4;
fi = (float(i) * edge_size_inv) - 1.0f;
fi2p1 = (fi * fi) + 1.0f;
for (unsigned j = 0; j < edge_size; j++, shidx += 4)
{
float d, solidangle, dinv;
float shx, shy, shz;
__m128 vrgb;
fj = (float(j) * edge_size_inv) - 1.0f;
d = sqrtf(fi2p1 + (fj * fj));
dinv = 1.0f / d;
// Constant obtained by projecting unprojected ref values
solidangle = 2.75f / (wh * sqrtf(d*d*d));
#if SIMD_SSE4_1_SUPPORT
vrgb = _mm_cvtepi32_ps( _mm_cvtepu8_epi32( _mm_castps_si128( _mm_load_ss( (float *)&shface[shidx+0] ) ) ) );
#else
vrgb = _mm_cvtepi32_ps( _mm_unpacklo_epi16( _mm_unpacklo_epi8( _mm_castps_si128( _mm_load_ss( (float *)&shface[shidx+0] ) ), _mm_setzero_si128() ), _mm_setzero_si128() ) );
#endif
vrgb = _mm_mul_ps( srgb2linear4( vrgb ), _mm_set1_ps( solidangle ) );
// TODO: This is very suboptimal, and a pity to break such a streamlined loop
// I think people will disapprove if I unroll the 'face' loop 6 times...
// What about some branchless vblendps masking?
switch (face)
{
case 0: // PosX
shx = 1.0f;
shy = -fi;
shz = -fj;
break;
case 1: // NegX
shx = -1.0f;
shy = -fi;
shz = fj;
break;
case 2: // PosY
shx = fj;
shy = 1.0f;
shz = fi;
break;
case 3: // NegY
shx = fj;
shy = -1.0f;
shz = -fi;
break;
case 4: // PosZ
shx = fj;
shy = -fi;
shz = 1.0f;
break;
case 5: // NegZ
shx = -fj;
shy = -fi;
shz = -1.0f;
break;
}
shx *= dinv;
shy *= dinv;
shz *= dinv;
sh0 = _mm_add_ps( sh0, vrgb );
sh1 = _mm_add_ps( sh1, _mm_mul_ps( vrgb, _mm_set1_ps( shy ) ) );
sh2 = _mm_add_ps( sh2, _mm_mul_ps( vrgb, _mm_set1_ps( shz ) ) );
sh3 = _mm_add_ps( sh3, _mm_mul_ps( vrgb, _mm_set1_ps( shx ) ) );
sh4 = _mm_add_ps( sh4, _mm_mul_ps( vrgb, _mm_set1_ps( shx * shy ) ) );
sh5 = _mm_add_ps( sh5, _mm_mul_ps( vrgb, _mm_set1_ps( shy * shz ) ) );
sh6 = _mm_add_ps( sh6, _mm_mul_ps( vrgb, _mm_set1_ps( shx * shz ) ) );
sh7 = _mm_add_ps( sh7, _mm_mul_ps( vrgb, _mm_set1_ps( ((3.0f * shz * shz) - 1.0f) ) ) );
sh8 = _mm_add_ps( sh8, _mm_mul_ps( vrgb, _mm_set1_ps( ((shx * shx) - (shy * shy)) ) ) );
}
}
}
sh0 = _mm_mul_ps( sh0, _mm_set1_ps( c00 ) );
sh1 = _mm_mul_ps( sh1, _mm_set1_ps( c1minus1 ) );
sh2 = _mm_mul_ps( sh2, _mm_set1_ps( c10 ) );
sh3 = _mm_mul_ps( sh3, _mm_set1_ps( c11 ) );
sh4 = _mm_mul_ps( sh4, _mm_set1_ps( c2minus2 ) );
sh5 = _mm_mul_ps( sh5, _mm_set1_ps( c2minus1 ) );
sh6 = _mm_mul_ps( sh6, _mm_set1_ps( c21 ) );
sh7 = _mm_mul_ps( sh7, _mm_set1_ps( c20 ) );
sh8 = _mm_mul_ps( sh8, _mm_set1_ps( c22 ) );
m_SH_coeff->blue_SH_coeff[0] = _mm_cvtss_f32( sh0 );
m_SH_coeff->blue_SH_coeff[1] = _mm_cvtss_f32( sh1 );
m_SH_coeff->blue_SH_coeff[2] = _mm_cvtss_f32( sh2 );
m_SH_coeff->blue_SH_coeff[3] = _mm_cvtss_f32( sh3 );
m_SH_coeff->blue_SH_coeff[4] = _mm_cvtss_f32( sh4 );
m_SH_coeff->blue_SH_coeff[5] = _mm_cvtss_f32( sh5 );
m_SH_coeff->blue_SH_coeff[6] = _mm_cvtss_f32( sh6 );
m_SH_coeff->blue_SH_coeff[7] = _mm_cvtss_f32( sh7 );
m_SH_coeff->blue_SH_coeff[8] = _mm_cvtss_f32( sh8 );
m_SH_coeff->green_SH_coeff[0] = _mm_cvtss_f32( _mm_shuffle_ps( sh0, sh0, 0x55 ) );
m_SH_coeff->green_SH_coeff[1] = _mm_cvtss_f32( _mm_shuffle_ps( sh1, sh1, 0x55 ) );
m_SH_coeff->green_SH_coeff[2] = _mm_cvtss_f32( _mm_shuffle_ps( sh2, sh2, 0x55 ) );
m_SH_coeff->green_SH_coeff[3] = _mm_cvtss_f32( _mm_shuffle_ps( sh3, sh3, 0x55 ) );
m_SH_coeff->green_SH_coeff[4] = _mm_cvtss_f32( _mm_shuffle_ps( sh4, sh4, 0x55 ) );
m_SH_coeff->green_SH_coeff[5] = _mm_cvtss_f32( _mm_shuffle_ps( sh5, sh5, 0x55 ) );
m_SH_coeff->green_SH_coeff[6] = _mm_cvtss_f32( _mm_shuffle_ps( sh6, sh6, 0x55 ) );
m_SH_coeff->green_SH_coeff[7] = _mm_cvtss_f32( _mm_shuffle_ps( sh7, sh7, 0x55 ) );
m_SH_coeff->green_SH_coeff[8] = _mm_cvtss_f32( _mm_shuffle_ps( sh8, sh8, 0x55 ) );
m_SH_coeff->red_SH_coeff[0] = _mm_cvtss_f32( _mm_movehl_ps( sh0, sh0 ) );
m_SH_coeff->red_SH_coeff[1] = _mm_cvtss_f32( _mm_movehl_ps( sh1, sh1 ) );
m_SH_coeff->red_SH_coeff[2] = _mm_cvtss_f32( _mm_movehl_ps( sh2, sh2 ) );
m_SH_coeff->red_SH_coeff[3] = _mm_cvtss_f32( _mm_movehl_ps( sh3, sh3 ) );
m_SH_coeff->red_SH_coeff[4] = _mm_cvtss_f32( _mm_movehl_ps( sh4, sh4 ) );
m_SH_coeff->red_SH_coeff[5] = _mm_cvtss_f32( _mm_movehl_ps( sh5, sh5 ) );
m_SH_coeff->red_SH_coeff[6] = _mm_cvtss_f32( _mm_movehl_ps( sh6, sh6 ) );
m_SH_coeff->red_SH_coeff[7] = _mm_cvtss_f32( _mm_movehl_ps( sh7, sh7 ) );
m_SH_coeff->red_SH_coeff[8] = _mm_cvtss_f32( _mm_movehl_ps( sh8, sh8 ) );
#else
float wh = float(edge_size * edge_size);
float b0 = 0., b1 = 0., b2 = 0., b3 = 0., b4 = 0., b5 = 0., b6 = 0., b7 = 0., b8 = 0.;
float r0 = 0., r1 = 0., r2 = 0., r3 = 0., r4 = 0., r5 = 0., r6 = 0., r7 = 0., r8 = 0.;
float g0 = 0., g1 = 0., g2 = 0., g3 = 0., g4 = 0., g5 = 0., g6 = 0., g7 = 0., g8 = 0.;
float r0 = 0., r1 = 0., r2 = 0., r3 = 0., r4 = 0., r5 = 0., r6 = 0., r7 = 0., r8 = 0.;
float edge_size_inv;
float fi, fj, fi2p1;
unsigned char *shface;
// constant part of Ylm
const float c00 = 0.282095f;
const float c1minus1 = 0.488603f;
const float c10 = 0.488603f;
const float c11 = 0.488603f;
const float c2minus2 = 1.092548f;
const float c2minus1 = 1.092548f;
const float c21 = 1.092548f;
const float c20 = 0.315392f;
const float c22 = 0.546274f;
edge_size_inv = 2.0f / edge_size;
for (unsigned face = 0; face < 6; face++)
{
#pragma omp parallel for reduction(+ : b0, b1, b2, b3, b4, b5, b6, b7, b8, \
r0, r1, r2, r3, r4, r5, r6, r7, r8, \
g0, g1, g2, g3, g4, g5, g6, g7, g8)
shface = sh_rgba[face];
for (int i = 0; i < int(edge_size); i++)
{
for (unsigned j = 0; j < edge_size; j++)
int shidx = ( i * edge_size ) * 4;
fi = (float(i) * edge_size_inv) - 1.0f;
fi2p1 = (fi * fi) + 1.0f;
for (unsigned j = 0; j < edge_size; j++, shidx += 4)
{
int idx = i * edge_size + j;
float fi = float(i), fj = float(j);
fi /= edge_size, fj /= edge_size;
fi = 2 * fi - 1, fj = 2 * fj - 1;
float d = sqrt(fi * fi + fj * fj + 1);
fj = (float(j) * edge_size_inv) - 1.0f;
float d = sqrtf(fi2p1 + (fj * fj));
// Constant obtained by projecting unprojected ref values
float solidangle = 2.75f / (wh * pow(d, 1.5f));
// pow(., 2.2) to convert from srgb
float b = cubemap_face[face][edge_size * i + j].Blue;
float g = cubemap_face[face][edge_size * i + j].Green;
float r = cubemap_face[face][edge_size * i + j].Red;
float solidangle = 2.75f / (wh * sqrtf(d*d*d));
float r, g, b;
float y00, y1m1, y10, y11, y2m2, y2m1, y21, y20, y22;
float shx, shy, shz;
b0 += b * Y00[face][idx] * solidangle;
b1 += b * Y1minus1[face][idx] * solidangle;
b2 += b * Y10[face][idx] * solidangle;
b3 += b * Y11[face][idx] * solidangle;
b4 += b * Y2minus2[face][idx] * solidangle;
b5 += b * Y2minus1[face][idx] * solidangle;
b6 += b * Y20[face][idx] * solidangle;
b7 += b * Y21[face][idx] * solidangle;
b8 += b * Y22[face][idx] * solidangle;
b = srgb2linear( float(shface[shidx+0]) ) * solidangle;
g = srgb2linear( float(shface[shidx+1]) ) * solidangle;
r = srgb2linear( float(shface[shidx+2]) ) * solidangle;
g0 += g * Y00[face][idx] * solidangle;
g1 += g * Y1minus1[face][idx] * solidangle;
g2 += g * Y10[face][idx] * solidangle;
g3 += g * Y11[face][idx] * solidangle;
g4 += g * Y2minus2[face][idx] * solidangle;
g5 += g * Y2minus1[face][idx] * solidangle;
g6 += g * Y20[face][idx] * solidangle;
g7 += g * Y21[face][idx] * solidangle;
g8 += g * Y22[face][idx] * solidangle;
getXYZ(face, fi, fj, shx, shy, shz);
y00 = c00;
y1m1 = c1minus1 * shy;
y10 = c10 * shz;
y11 = c11 * shx;
y2m2 = c2minus2 * shx * shy;
y2m1 = c2minus1 * shy * shz;
y21 = c21 * shx * shz;
y20 = c20 * ((3.0f * shz * shz) - 1.0f);
y22 = c22 * ((shx * shx) - (shy * shy));
b0 += b * y00;
b1 += b * y1m1;
b2 += b * y10;
b3 += b * y11;
b4 += b * y2m2;
b5 += b * y2m1;
b6 += b * y20;
b7 += b * y21;
b8 += b * y22;
r0 += r * Y00[face][idx] * solidangle;
r1 += r * Y1minus1[face][idx] * solidangle;
r2 += r * Y10[face][idx] * solidangle;
r3 += r * Y11[face][idx] * solidangle;
r4 += r * Y2minus2[face][idx] * solidangle;
r5 += r * Y2minus1[face][idx] * solidangle;
r6 += r * Y20[face][idx] * solidangle;
r7 += r * Y21[face][idx] * solidangle;
r8 += r * Y22[face][idx] * solidangle;
g0 += g * y00;
g1 += g * y1m1;
g2 += g * y10;
g3 += g * y11;
g4 += g * y2m2;
g5 += g * y2m1;
g6 += g * y20;
g7 += g * y21;
g8 += g * y22;
r0 += r * y00;
r1 += r * y1m1;
r2 += r * y10;
r3 += r * y11;
r4 += r * y2m2;
r5 += r * y2m1;
r6 += r * y20;
r7 += r * y21;
r8 += r * y22;
}
}
}
@ -307,59 +503,14 @@ void SphericalHarmonics::projectSH(Color *cubemap_face[6], size_t edge_size,
m_SH_coeff->green_SH_coeff[6] = g6;
m_SH_coeff->green_SH_coeff[7] = g7;
m_SH_coeff->green_SH_coeff[8] = g8;
} // projectSH
// ----------------------------------------------------------------------------
/** Generate the 9 first SH coefficients for each color channel
* using the cubemap provided by CubemapFace.
* \param cubemap_face The 6 cubemap faces (float textures)
* \param edge_size Size of the cubemap face
#endif
/*
printf( "#### SH ; Coeffs R ; %f %f %f %f %f %f %f %f\n", m_SH_coeff->red_SH_coeff[0], m_SH_coeff->red_SH_coeff[1], m_SH_coeff->red_SH_coeff[2], m_SH_coeff->red_SH_coeff[3], m_SH_coeff->red_SH_coeff[4], m_SH_coeff->red_SH_coeff[5], m_SH_coeff->red_SH_coeff[6], m_SH_coeff->red_SH_coeff[7] );
printf( "#### SH ; Coeffs G ; %f %f %f %f %f %f %f %f\n", m_SH_coeff->green_SH_coeff[0], m_SH_coeff->green_SH_coeff[1], m_SH_coeff->green_SH_coeff[2], m_SH_coeff->green_SH_coeff[3], m_SH_coeff->green_SH_coeff[4], m_SH_coeff->green_SH_coeff[5], m_SH_coeff->green_SH_coeff[6], m_SH_coeff->green_SH_coeff[7] );
printf( "#### SH ; Coeffs B ; %f %f %f %f %f %f %f %f\n", m_SH_coeff->blue_SH_coeff[0], m_SH_coeff->blue_SH_coeff[1], m_SH_coeff->blue_SH_coeff[2], m_SH_coeff->blue_SH_coeff[3], m_SH_coeff->blue_SH_coeff[4], m_SH_coeff->blue_SH_coeff[5], m_SH_coeff->blue_SH_coeff[6], m_SH_coeff->blue_SH_coeff[7] );
*/
void SphericalHarmonics::generateSphericalHarmonics(Color *cubemap_face[6], size_t edge_size)
{
float *Y00[6];
float *Y1minus1[6];
float *Y10[6];
float *Y11[6];
float *Y2minus2[6];
float *Y2minus1[6];
float *Y20[6];
float *Y21[6];
float *Y22[6];
for (unsigned face = 0; face < 6; face++)
{
Y00[face] = new float[edge_size * edge_size];
Y1minus1[face] = new float[edge_size * edge_size];
Y10[face] = new float[edge_size * edge_size];
Y11[face] = new float[edge_size * edge_size];
Y2minus2[face] = new float[edge_size * edge_size];
Y2minus1[face] = new float[edge_size * edge_size];
Y20[face] = new float[edge_size * edge_size];
Y21[face] = new float[edge_size * edge_size];
Y22[face] = new float[edge_size * edge_size];
getYml(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, edge_size, Y00[face],
Y1minus1[face], Y10[face], Y11[face], Y2minus2[face],
Y2minus1[face], Y20[face], Y21[face], Y22[face]);
}
projectSH(cubemap_face, edge_size, Y00, Y1minus1, Y10, Y11, Y2minus2,
Y2minus1, Y20, Y21, Y22);
for (unsigned face = 0; face < 6; face++)
{
delete[] Y00[face];
delete[] Y1minus1[face];
delete[] Y10[face];
delete[] Y11[face];
delete[] Y2minus2[face];
delete[] Y2minus1[face];
delete[] Y20[face];
delete[] Y21[face];
delete[] Y22[face];
}
} // generateSphericalHarmonics
} // projectSH
// ----------------------------------------------------------------------------
SphericalHarmonics::SphericalHarmonics(const std::vector<video::ITexture *> &spherical_harmonics_textures)
@ -427,15 +578,10 @@ void SphericalHarmonics::setTextures(const std::vector<video::ITexture *> &spher
#endif
} //for (unsigned i = 0; i < 6; i++)
Color *float_tex_cube[6];
convertToFloatTexture(sh_rgba, sh_w, sh_h, float_tex_cube);
generateSphericalHarmonics(float_tex_cube, sh_w);
generateSphericalHarmonics(sh_rgba, sh_w);
for (unsigned i = 0; i < 6; i++)
{
delete[] sh_rgba[i];
delete[] float_tex_cube[i];
}
} //setSphericalHarmonicsTextures
/** Compute spherical harmonics coefficients from ambient light */
@ -451,29 +597,28 @@ void SphericalHarmonics::setAmbientLight(const video::SColor &ambient)
unsigned char *sh_rgba[6];
unsigned sh_w = 16;
unsigned sh_h = 16;
unsigned ambr, ambg, ambb;
ambr = ambient.getBlue();
ambg = ambient.getGreen();
ambb = ambient.getBlue();
for (unsigned i = 0; i < 6; i++)
{
sh_rgba[i] = new unsigned char[sh_w * sh_h * 4];
for (unsigned j = 0; j < sh_w * sh_h * 4; j += 4)
{
sh_rgba[i][j] = ambient.getBlue();
sh_rgba[i][j + 1] = ambient.getGreen();
sh_rgba[i][j + 2] = ambient.getRed();
sh_rgba[i][j] = ambb;
sh_rgba[i][j + 1] = ambg;
sh_rgba[i][j + 2] = ambr;
sh_rgba[i][j + 3] = 255;
}
}
Color *float_tex_cube[6];
convertToFloatTexture(sh_rgba, sh_w, sh_h, float_tex_cube);
generateSphericalHarmonics(float_tex_cube, sh_w);
generateSphericalHarmonics(sh_rgba, sh_w);
for (unsigned i = 0; i < 6; i++)
{
delete[] sh_rgba[i];
delete[] float_tex_cube[i];
}
// Diffuse env map is x 0.25, compensate
for (unsigned i = 0; i < 9; i++)

View File

@ -49,12 +49,7 @@ private:
/** The spherical harmonics coefficients */
SHCoefficients *m_SH_coeff;
void projectSH(Color *cubemap_face[6], size_t edge_size, float *Y00[],
float *Y1minus1[], float *Y10[], float *Y11[],
float *Y2minus2[], float *Y2minus1[], float * Y20[],
float *Y21[], float *Y22[]);
void generateSphericalHarmonics(Color *cubemap_face[6], size_t edge_size);
void generateSphericalHarmonics(unsigned char *sh_rgba[6], size_t edge_size);
public:
SphericalHarmonics(const std::vector<irr::video::ITexture *> &spherical_harmonics_textures);

View File

@ -22,7 +22,7 @@
#include "graphics/irr_driver.hpp"
#include "graphics/material.hpp"
#include "utils/singleton.hpp"
#include "utils/tuple.hpp"
#include <tuple>
#include <IMeshSceneNode.h>
#include <IMesh.h>
@ -101,7 +101,7 @@ template<typename T, typename... Args>
class MeshList : public Singleton<T>
{
public:
std::vector<STK::Tuple<Args...> > SolidPass, Shadows[4], RSM;
std::vector<std::tuple<Args...> > SolidPass, Shadows[4], RSM;
void clear()
{
SolidPass.clear();
@ -183,7 +183,7 @@ class ListMatDetails : public MeshList<ListMatDetails, GLMesh *, core::matrix4,
// ----------------------------------------------------------------------------
// Transparent
template <typename T, typename ...Args>
class MiscList : public Singleton<T>, public std::vector<STK::Tuple<Args...> >
class MiscList : public Singleton<T>, public std::vector<std::tuple<Args...> >
{};
// ----------------------------------------------------------------------------

View File

@ -20,7 +20,7 @@
#include "graphics/gl_headers.hpp"
#include "utils/singleton.hpp"
#include "utils/tuple.hpp"
#include <tuple>
#include <S3DVertex.h>
#include <IMeshBuffer.h>
#include <ISceneNode.h>
@ -40,7 +40,7 @@ enum InstanceType : unsigned int
InstanceTypeCount,
};
typedef STK::Tuple<scene::ISceneNode*, core::vector2df, core::vector2df,
typedef std::tuple<scene::ISceneNode*, core::vector2df, core::vector2df,
int32_t> InstanceSettings;
struct GLMesh;

View File

@ -1256,7 +1256,7 @@ bool CGUIEditBox::processMouse(const SEvent& event)
if (GUIEngine::ScreenKeyboard::getCurrent() == NULL)
{
new GUIEngine::ScreenKeyboard(0.98, 0.30, this);
new GUIEngine::ScreenKeyboard(0.98f, 0.30f, this);
}
return true;

View File

@ -1,114 +0,0 @@
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2014-2015 SuperTuxKart-Team
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 3
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#ifndef __STK_TUPLE_HPP__
#define __STK_TUPLE_HPP__
namespace STK {
// tuple
template<typename... _Types> class Tuple;
// empty tuple
template<> class Tuple<> {
public:
Tuple()
{
}
};
// recursive tuple definition
template<typename _This, typename... _Rest>
class Tuple<_This, _Rest...> : private Tuple<_Rest...>
{
public:
_This _Elem;
Tuple()
{
}
Tuple(_This val, _Rest... rest) : Tuple<_Rest...>(rest...)
{
_Elem = val;
}
};
// tuple_element
template<size_t _Index, typename _Tuple> struct tuple_element;
// select first element
template<typename _This, typename... _Rest>
struct tuple_element<0, Tuple<_This, _Rest...>>
{
typedef _This& type;
typedef Tuple<_This, _Rest...> _Ttype;
};
// recursive tuple_element definition
template <size_t _Index, typename _This, typename... _Rest>
struct tuple_element<_Index, Tuple<_This, _Rest...>>
: public tuple_element<_Index - 1, Tuple<_Rest...> >
{
};
template<size_t _Index, class... _Types> inline
typename tuple_element<_Index, Tuple<_Types...>>::type
tuple_get(Tuple<_Types...>& _Tuple)
{
typedef typename tuple_element<_Index, Tuple<_Types...>>::_Ttype _Ttype;
return (((_Ttype&)_Tuple)._Elem);
}
template<size_t _Index, class... _Types> inline
typename tuple_element<_Index, Tuple<_Types...>>::type tuple_get(const Tuple<_Types...>& _Tuple)
{
typedef typename tuple_element<_Index, Tuple<_Types...>>::_Ttype _Ttype;
return (((_Ttype&)_Tuple)._Elem);
}
template<size_t Index, typename... T> inline
Tuple<T...> make_tuple(T... values)
{
return Tuple<T...>(values...);
}
template<typename... T> inline
Tuple<T...> make_tuple(T... values)
{
return Tuple<T...>(values...);
}
//template<typename... T>
//int tuple_size(Tuple<T...> tuple)
//{
// return sizeof...(T);
//}
template<typename... T>
struct TupleSize
{
const int value;
TupleSize()
{
value = sizeof...(T);
}
};
}
#endif