Files
RCBASIC4/rcbasic_runtime/ProjectiveTextures.cpp
2026-02-22 23:07:53 -06:00

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);
}
}