238 lines
7.7 KiB
C++
Executable File
238 lines
7.7 KiB
C++
Executable File
#include "ProjectiveTextures.h"
|
|
#include <string>
|
|
|
|
/* CONSTRUCTOR */
|
|
CProjectiveTextures::CProjectiveTextures(irr::IrrlichtDevice* dev, irr::scene::ISceneNode* parent, irr::scene::ISceneManager* mgr, irr::s32 id,
|
|
const irr::core::vector3df& position, const irr::core::vector3df& lookat)
|
|
: irr::scene::ISceneNode(parent, mgr, id, position)
|
|
{
|
|
pDevice = dev;
|
|
pVideo = pDevice->getVideoDriver();
|
|
pScene = pDevice->getSceneManager();
|
|
pGUI = pDevice->getGUIEnvironment();
|
|
pGPU = pVideo->getGPUProgrammingServices();
|
|
pCollision = pScene->getSceneCollisionManager();
|
|
pLog = pDevice->getLogger();
|
|
|
|
// set default projection
|
|
Fovy = irr::core::PI / 2.5f; // Field of view, in radians.
|
|
|
|
Target = lookat;
|
|
|
|
recalculateProjectionMatrix();
|
|
recalculateViewArea();
|
|
|
|
std::string projector_vert =
|
|
"!!ARBvp1.0 \n"
|
|
"# cgc version 2.1.0016, build date Nov 20 2008 \n"
|
|
"# command line args: -oglsl -bestprecision -O3 -profile arbvp1 \n"
|
|
"# source file: projector.vert \n"
|
|
"#vendor NVIDIA Corporation \n"
|
|
"#version 2.1.0.16 \n"
|
|
"#profile arbvp1 \n"
|
|
"#program main \n"
|
|
"#semantic gl_ModelViewProjectionMatrixTranspose : state.matrix.mvp \n"
|
|
"#semantic TexGenMat \n"
|
|
"#var float4 gl_TexCoord[0] : $vout.TEX0 : TEX0 : -1 : 1 \n"
|
|
"#var float4 gl_TexCoord[1] : : : -1 : 0 \n"
|
|
"#var float4 gl_TexCoord[2] : : : -1 : 0 \n"
|
|
"#var float4 gl_TexCoord[3] : : : -1 : 0 \n"
|
|
"#var float4 gl_TexCoord[4] : : : -1 : 0 \n"
|
|
"#var float4 gl_TexCoord[5] : : : -1 : 0 \n"
|
|
"#var float4 gl_TexCoord[6] : : : -1 : 0 \n"
|
|
"#var float4 gl_TexCoord[7] : : : -1 : 0 \n"
|
|
"#var float4 gl_Vertex : $vin.POSITION : POSITION : -1 : 1 \n"
|
|
"#var float4 gl_Position : $vout.POSITION : HPOS : -1 : 1 \n"
|
|
"#var float4x4 gl_ModelViewProjectionMatrixTranspose : state.matrix.mvp : c[1], 4 : -1 : 1 \n"
|
|
"#var float4x4 TexGenMat : : c[5], 4 : -1 : 1 \n"
|
|
"PARAM c[9] = { program.local[0], \n"
|
|
" state.matrix.mvp, \n"
|
|
" program.local[5..8] }; \n"
|
|
"TEMP R0; \n"
|
|
"MUL R0, vertex.position.y, c[6]; \n"
|
|
"MAD R0, vertex.position.x, c[5], R0; \n"
|
|
"MAD R0, vertex.position.z, c[7], R0; \n"
|
|
"MAD result.texcoord[0], vertex.position.w, c[8], R0; \n"
|
|
"DP4 result.position.w, vertex.position, c[4]; \n"
|
|
"DP4 result.position.z, vertex.position, c[3]; \n"
|
|
"DP4 result.position.y, vertex.position, c[2]; \n"
|
|
"DP4 result.position.x, vertex.position, c[1]; \n"
|
|
"END \n"
|
|
"# 8 instructions, 1 R-regs \n"
|
|
;
|
|
|
|
|
|
std::string projector_frag =
|
|
"!!ARBfp1.0 \n"
|
|
"OPTION ARB_precision_hint_nicest; \n"
|
|
"# cgc version 2.1.0016, build date Nov 20 2008 \n"
|
|
"# command line args: -oglsl -bestprecision -O3 -profile arbfp1 \n"
|
|
"# source file: projector.frag \n"
|
|
"#vendor NVIDIA Corporation \n"
|
|
"#version 2.1.0.16 \n"
|
|
"#profile arbfp1 \n"
|
|
"#program main \n"
|
|
"#semantic projMap \n"
|
|
"#var float4 gl_TexCoord[0] : $vin.TEX0 : TEX0 : -1 : 1 \n"
|
|
"#var float4 gl_TexCoord[1] : : : -1 : 0 \n"
|
|
"#var float4 gl_TexCoord[2] : : : -1 : 0 \n"
|
|
"#var float4 gl_TexCoord[3] : : : -1 : 0 \n"
|
|
"#var float4 gl_TexCoord[4] : : : -1 : 0 \n"
|
|
"#var float4 gl_TexCoord[5] : : : -1 : 0 \n"
|
|
"#var float4 gl_TexCoord[6] : : : -1 : 0 \n"
|
|
"#var float4 gl_TexCoord[7] : : : -1 : 0 \n"
|
|
"#var float4 gl_FragColor : $vout.COLOR : COL : -1 : 1 \n"
|
|
"#var sampler2D projMap : : texunit 0 : -1 : 1 \n"
|
|
"#const c[0] = 0 \n"
|
|
"PARAM c[1] = { { 0 } }; \n"
|
|
"TEMP R0; \n"
|
|
"TXP R0, fragment.texcoord[0], texture[0], 2D; \n"
|
|
"CMP result.color, -fragment.texcoord[0].w, R0, c[0].x; \n"
|
|
"END \n"
|
|
"# 2 instructions, 1 R-regs \n"
|
|
;
|
|
|
|
// Load the shaders.
|
|
projTex = pGPU->addShaderMaterial(projector_vert.c_str(),
|
|
projector_frag.c_str(),
|
|
this,irr::video::EMT_TRANSPARENT_ADD_COLOR,0);
|
|
}
|
|
|
|
/* DESTRUCTOR */
|
|
CProjectiveTextures::~CProjectiveTextures()
|
|
{
|
|
// Remove the texture used.
|
|
pVideo->removeTexture(texture);
|
|
}
|
|
|
|
//! sets the look at target of the projector
|
|
void CProjectiveTextures::setTarget(const irr::core::vector3df& pos)
|
|
{
|
|
Target = pos;
|
|
const irr::core::vector3df toTarget = Target - getAbsolutePosition();
|
|
}
|
|
|
|
//! Gets the current look at target of the projector
|
|
const irr::core::vector3df& CProjectiveTextures::getTarget() const
|
|
{
|
|
return Target;
|
|
}
|
|
|
|
void CProjectiveTextures::setFOV(irr::f32 f)
|
|
{
|
|
Fovy = f;
|
|
recalculateProjectionMatrix();
|
|
}
|
|
|
|
irr::f32 CProjectiveTextures::getFOV()
|
|
{
|
|
return Fovy;
|
|
}
|
|
|
|
//! returns the axis aligned bounding box of this node
|
|
const irr::core::aabbox3d<irr::f32>& CProjectiveTextures::getBoundingBox() const
|
|
{
|
|
return ViewArea.getBoundingBox();
|
|
}
|
|
|
|
/* UPDATE */
|
|
void CProjectiveTextures::render()
|
|
{
|
|
irr::core::vector3df pos = getAbsolutePosition();
|
|
irr::core::vector3df tgtv = Target - pos;
|
|
tgtv.normalize();
|
|
|
|
// if upvector and vector to the target are the same, we have a
|
|
// problem. so solve this problem:
|
|
irr::core::vector3df up(0.0f,0.0f,1.0f);
|
|
|
|
ViewArea.getTransform(irr::video::ETS_VIEW).buildCameraLookAtMatrixLH(pos,Target,up);
|
|
|
|
recalculateViewArea();
|
|
|
|
irr::scene::IMesh* mesh = NULL;
|
|
|
|
for(irr::u32 i=0; i<nodeArray.size(); ++i)
|
|
{
|
|
projMat.MaterialType = (irr::video::E_MATERIAL_TYPE)projTex;
|
|
projMat.TextureLayer[0].Texture = texture;
|
|
projMat.TextureLayer[0].TextureWrapU = irr::video::ETC_CLAMP_TO_BORDER;
|
|
projMat.TextureLayer[0].TextureWrapV = irr::video::ETC_CLAMP_TO_BORDER;
|
|
|
|
pVideo->setTransform(irr::video::ETS_WORLD,nodeArray[i]->getAbsoluteTransformation());
|
|
pVideo->setMaterial(projMat);
|
|
|
|
mesh = NULL;
|
|
|
|
switch(nodeArray[i]->getType())
|
|
{
|
|
case irr::scene::ESNT_CUBE:
|
|
case irr::scene::ESNT_SPHERE:
|
|
case irr::scene::ESNT_MESH:
|
|
{
|
|
irr::scene::IMeshSceneNode* m_node = (irr::scene::IMeshSceneNode*)nodeArray[i];
|
|
mesh = m_node->getMesh();
|
|
}
|
|
break;
|
|
|
|
case irr::scene::ESNT_OCTREE:
|
|
{
|
|
irr::scene::IOctreeSceneNode* m_node = (irr::scene::IOctreeSceneNode*)nodeArray[i];
|
|
mesh = m_node->getMesh();
|
|
}
|
|
break;
|
|
|
|
case irr::scene::ESNT_ANIMATED_MESH:
|
|
{
|
|
irr::scene::IAnimatedMeshSceneNode* m_node = (irr::scene::IAnimatedMeshSceneNode*)nodeArray[i];
|
|
mesh = m_node->getMesh();
|
|
}
|
|
break;
|
|
|
|
case irr::scene::ESNT_TERRAIN:
|
|
{
|
|
irr::scene::ITerrainSceneNode* m_node = (irr::scene::ITerrainSceneNode*)nodeArray[i];
|
|
mesh = m_node->getMesh();
|
|
}
|
|
break;
|
|
}
|
|
|
|
if(mesh)
|
|
{
|
|
for(irr::u32 j=0; j<nodeArray[i]->getMaterialCount(); ++j)
|
|
pVideo->drawMeshBuffer(mesh->getMeshBuffer(j));
|
|
}
|
|
}
|
|
}
|
|
|
|
void CProjectiveTextures::recalculateProjectionMatrix()
|
|
{
|
|
ViewArea.getTransform(irr::video::ETS_PROJECTION ).buildProjectionMatrixPerspectiveFovLH(Fovy,1.0f,1.0f,3000.0f);
|
|
}
|
|
|
|
void CProjectiveTextures::recalculateViewArea()
|
|
{
|
|
ViewArea.cameraPosition = getAbsolutePosition();
|
|
|
|
irr::core::matrix4 m(irr::core::matrix4::EM4CONST_NOTHING);
|
|
m.setbyproduct_nocheck(ViewArea.getTransform(irr::video::ETS_PROJECTION),ViewArea.getTransform(irr::video::ETS_VIEW));
|
|
ViewArea.setFrom(m, true);
|
|
}
|
|
|
|
void CProjectiveTextures::OnSetConstants(irr::video::IMaterialRendererServices* services,irr::s32 userData)
|
|
{
|
|
if(userData == 0)
|
|
{
|
|
irr::core::matrix4 bias;
|
|
bias.makeIdentity();
|
|
bias.setTranslation(irr::core::vector3df(0.5f,0.5f,0));
|
|
bias.setScale(irr::core::vector3df(0.5f,-0.5f,1.0f));
|
|
|
|
irr::core::matrix4 worldViewProj;
|
|
worldViewProj = bias * ViewArea.getTransform(irr::video::ETS_PROJECTION);
|
|
worldViewProj *= ViewArea.getTransform(irr::video::ETS_VIEW);
|
|
worldViewProj *= pVideo->getTransform(irr::video::ETS_WORLD);
|
|
services->setVertexShaderConstant(reinterpret_cast<const irr::f32*>(worldViewProj.pointer()),5,4);
|
|
}
|
|
}
|