794 lines
19 KiB
C++
794 lines
19 KiB
C++
// Copyright (C) 2002-2007 Nikolaus Gebhardt / Thomas Alten
|
|
// This file is part of the "Irrlicht Engine".
|
|
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
|
|
|
#include "CQuake3ShaderSceneNode.h"
|
|
#include "IVideoDriver.h"
|
|
#include "ICameraSceneNode.h"
|
|
#include "SViewFrustum.h"
|
|
#include "IMeshManipulator.h"
|
|
#include "SMesh.h"
|
|
#include "IMaterialRenderer.h"
|
|
|
|
namespace irr
|
|
{
|
|
namespace scene
|
|
{
|
|
|
|
|
|
CQuake3ShaderSceneNode::CQuake3ShaderSceneNode(
|
|
scene::ISceneNode* parent, scene::ISceneManager* mgr,s32 id,
|
|
io::IFileSystem *fileSystem, scene::IMeshBuffer *buffer,
|
|
const quake3::SShader * shader)
|
|
: scene::ISceneNode(parent, mgr, id), Shader ( shader ),TimeAbs ( 0.f )
|
|
{
|
|
#ifdef _DEBUG
|
|
core::stringc dName = "CQuake3ShaderSceneNode ";
|
|
dName += Shader->name;
|
|
|
|
setDebugName( dName.c_str() );
|
|
#endif
|
|
|
|
// name the Scene Node
|
|
this->Name = Shader->name;
|
|
|
|
// clone meshbuffer to modifiable buffer
|
|
cloneBuffer ( static_cast< scene::SMeshBufferLightMap *> ( buffer ) );
|
|
|
|
// load all Textures in all stages
|
|
loadTextures ( fileSystem );
|
|
|
|
setAutomaticCulling ( scene::EAC_BOX );
|
|
}
|
|
|
|
|
|
/*
|
|
*/
|
|
CQuake3ShaderSceneNode::~CQuake3ShaderSceneNode ()
|
|
{
|
|
}
|
|
|
|
/*
|
|
create single copies
|
|
*/
|
|
void CQuake3ShaderSceneNode::cloneBuffer ( scene::SMeshBufferLightMap * buffer )
|
|
{
|
|
Original.Material = buffer->Material;
|
|
MeshBuffer.Material = buffer->Material;
|
|
|
|
Original.Indices = buffer->Indices;
|
|
MeshBuffer.Indices = buffer->Indices;
|
|
|
|
const u32 vsize = buffer->Vertices.size ();
|
|
|
|
Original.Vertices.set_used ( vsize );
|
|
MeshBuffer.Vertices.set_used ( vsize );
|
|
for ( u32 i = 0; i!= vsize; ++i )
|
|
{
|
|
const video::S3DVertex2TCoords * src = &buffer->Vertices[i];
|
|
|
|
// Original has same Vertex Format
|
|
Original.Vertices[i] = *src;
|
|
|
|
// we have a different vertex format
|
|
MeshBuffer.Vertices[i].Pos = src->Pos;
|
|
MeshBuffer.Vertices[i].TCoords = src->TCoords;
|
|
MeshBuffer.Vertices[i].Color = 0xFFFFFFFF;
|
|
}
|
|
|
|
MeshBuffer.recalculateBoundingBox ();
|
|
|
|
#if 1
|
|
// move the (temp) Mesh
|
|
{
|
|
// original bounding box
|
|
core::aabbox3df b = MeshBuffer.getBoundingBox();
|
|
|
|
// set Scene Node Position
|
|
setPosition ( b.getCenter() );
|
|
|
|
scene::SMesh * mesh = new SMesh ();
|
|
mesh->addMeshBuffer ( &Original );
|
|
mesh->addMeshBuffer ( &MeshBuffer );
|
|
|
|
core::matrix4 m;
|
|
m.setTranslation ( -b.getCenter() );
|
|
SceneManager->getMeshManipulator()->transformMesh ( mesh, m );
|
|
mesh->drop ();
|
|
|
|
MeshBuffer.recalculateBoundingBox ();
|
|
}
|
|
#endif
|
|
// used for sorting
|
|
MeshBuffer.Material.setTexture(0, (video::ITexture*) Shader);
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
load the textures for all stages
|
|
*/
|
|
void CQuake3ShaderSceneNode::loadTextures ( io::IFileSystem * fileSystem )
|
|
{
|
|
const quake3::SVarGroup *group;
|
|
u32 i;
|
|
|
|
// clear all stages and prefill empty
|
|
Q3Texture.clear ();
|
|
for ( i = 0; i != Shader->VarGroup->VariableGroup.size (); ++i )
|
|
{
|
|
Q3Texture.push_back ( SQ3Texture() );
|
|
}
|
|
|
|
u32 pos;
|
|
|
|
// get texture map
|
|
for ( i = 0; i < Shader->VarGroup->VariableGroup.size (); ++i )
|
|
{
|
|
group = Shader->getGroup ( i );
|
|
|
|
const core::stringc &mapname = group->get ( "map" );
|
|
if ( 0 == mapname.size () )
|
|
continue;
|
|
|
|
// our lightmap is passed in material.Texture[2]
|
|
if ( mapname == "$lightmap" )
|
|
{
|
|
Q3Texture [i].Texture.push_back ( Original.getMaterial().getTexture(1) );
|
|
}
|
|
else
|
|
{
|
|
pos = 0;
|
|
quake3::getTextures ( Q3Texture [i].Texture, mapname, pos, fileSystem, SceneManager->getVideoDriver() );
|
|
}
|
|
}
|
|
|
|
// get anim map
|
|
for ( i = 0; i < Shader->VarGroup->VariableGroup.size (); ++i )
|
|
{
|
|
if ( Q3Texture [i].Texture.size() )
|
|
continue;
|
|
|
|
group = Shader->getGroup ( i );
|
|
|
|
const core::stringc &animmap = group->get ( "animmap" );
|
|
if ( 0 == animmap.size () )
|
|
continue;
|
|
|
|
// first parameter is frequency
|
|
pos = 0;
|
|
Q3Texture [i].TextureFrequency = core::max_ ( 0.0001f, quake3::getAsFloat ( animmap, pos ) );
|
|
|
|
quake3::getTextures ( Q3Texture [i].Texture, animmap, pos,fileSystem, SceneManager->getVideoDriver() );
|
|
}
|
|
|
|
// get clamp map
|
|
for ( i = 0; i < Shader->VarGroup->VariableGroup.size (); ++i )
|
|
{
|
|
if ( Q3Texture [i].Texture.size() )
|
|
continue;
|
|
|
|
group = Shader->getGroup ( i );
|
|
|
|
const core::stringc &clampmap = group->get ( "clampmap" );
|
|
if ( 0 == clampmap.size () )
|
|
continue;
|
|
|
|
Q3Texture [i].TextureAddressMode = video::ETC_CLAMP;
|
|
pos = 0;
|
|
quake3::getTextures ( Q3Texture [i].Texture, clampmap, pos,fileSystem, SceneManager->getVideoDriver() );
|
|
}
|
|
}
|
|
|
|
/*
|
|
Register each texture stage, if first is visible
|
|
*/
|
|
void CQuake3ShaderSceneNode::OnRegisterSceneNode()
|
|
{
|
|
if ( isVisible() )
|
|
{
|
|
SceneManager->registerNodeForRendering(this, isTransparent () ? ESNRP_TRANSPARENT: ESNRP_SOLID );
|
|
}
|
|
ISceneNode::OnRegisterSceneNode ();
|
|
}
|
|
|
|
/*
|
|
is this a transparent node ?
|
|
*/
|
|
bool CQuake3ShaderSceneNode::isTransparent ()
|
|
{
|
|
bool ret = false;
|
|
|
|
// generic stage
|
|
const quake3::SVarGroup *group;
|
|
|
|
group = Shader->getGroup ( 1 );
|
|
/*
|
|
if ( group->isDefined ( "surfaceparm", "nonsolid" ) )
|
|
{
|
|
ret = true;
|
|
}
|
|
*/
|
|
if ( group->isDefined ( "surfaceparm", "trans" ) )
|
|
{
|
|
ret = true;
|
|
}
|
|
else
|
|
{
|
|
for ( u32 stage = 0; stage < Shader->VarGroup->VariableGroup.size (); ++stage )
|
|
{
|
|
if ( 0 == Q3Texture [ stage].Texture.size() )
|
|
continue;
|
|
|
|
group = Shader->getGroup ( stage );
|
|
quake3::SBlendFunc blendfunc;
|
|
quake3::getBlendFunc ( group->get ( "blendfunc" ), blendfunc );
|
|
quake3::getBlendFunc ( group->get ( "alphafunc" ), blendfunc );
|
|
|
|
ret = blendfunc.isTransparent;
|
|
break;
|
|
}
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
|
|
/*
|
|
render in multipass technique
|
|
*/
|
|
void CQuake3ShaderSceneNode::render()
|
|
{
|
|
video::IVideoDriver* driver = SceneManager->getVideoDriver();
|
|
|
|
|
|
bool isTransparentPass =
|
|
SceneManager->getSceneNodeRenderPass() == scene::ESNRP_TRANSPARENT;
|
|
|
|
video::SMaterial material;
|
|
const quake3::SVarGroup *group;
|
|
|
|
material.Lighting = false;
|
|
material.setTexture(1, 0);
|
|
material.NormalizeNormals = false;
|
|
|
|
// generic stage
|
|
group = Shader->getGroup ( 1 );
|
|
material.BackfaceCulling = quake3::isDisabled ( group->get ( "cull" ) );
|
|
|
|
// u32 zEnable = group->getIndex ( "polygonoffset" ) >= 0;
|
|
|
|
driver->setTransform(video::ETS_WORLD, AbsoluteTransformation );
|
|
|
|
u32 drawCount = 0;
|
|
for ( u32 stage = 0; stage < Shader->VarGroup->VariableGroup.size (); ++stage )
|
|
//for ( u32 stage = 2; stage < 3; ++stage )
|
|
{
|
|
SQ3Texture &q = Q3Texture [ stage];
|
|
|
|
// advance current stage
|
|
core::matrix4 texture;
|
|
animate ( stage, texture );
|
|
|
|
// stage 1 finished, no drawing stage ( vertex transform only )
|
|
if ( 0 == q.Texture.size() )
|
|
continue;
|
|
|
|
// current stage
|
|
group = Shader->getGroup ( stage );
|
|
|
|
material.setTexture(0, q.Texture [ q.TextureIndex ]);
|
|
material.ZBuffer = quake3::getDepthFunction ( group->get ( "depthfunc" ) );
|
|
|
|
if ( group->getIndex ( "depthwrite" ) >= 0 )
|
|
{
|
|
material.ZWriteEnable = true;
|
|
}
|
|
else
|
|
{
|
|
material.ZWriteEnable = drawCount ? false: !isTransparentPass;
|
|
}
|
|
|
|
//resolve quake3 blendfunction to irrlicht Material Type
|
|
quake3::SBlendFunc blendfunc;
|
|
quake3::getBlendFunc ( group->get ( "blendfunc" ), blendfunc );
|
|
quake3::getBlendFunc ( group->get ( "alphafunc" ), blendfunc );
|
|
|
|
material.MaterialType = blendfunc.type;
|
|
material.MaterialTypeParam = blendfunc.param;
|
|
|
|
material.TextureLayer[0].TextureWrap = q.TextureAddressMode;
|
|
material.setTextureMatrix ( 0, texture );
|
|
|
|
driver->setMaterial( material );
|
|
driver->drawMeshBuffer( &MeshBuffer );
|
|
drawCount += 1;
|
|
}
|
|
|
|
if ( DebugDataVisible & scene::EDS_BBOX )
|
|
{
|
|
video::SMaterial deb_m;
|
|
deb_m.Lighting = false;
|
|
driver->setMaterial(deb_m);
|
|
driver->draw3DBox( getBoundingBox(), video::SColor(0,255,255,255));
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/*!
|
|
*/
|
|
void CQuake3ShaderSceneNode::vertextransform_wave ( f32 dt, quake3::SModifierFunction &function )
|
|
{
|
|
function.wave = core::reciprocal ( function.wave );
|
|
|
|
const f32 phase = function.phase;
|
|
|
|
const u32 vsize = MeshBuffer.Vertices.size();
|
|
for ( u32 i = 0; i != vsize; ++i )
|
|
{
|
|
const video::S3DVertex2TCoords &src = Original.Vertices[i];
|
|
video::S3DVertex &dst = MeshBuffer.Vertices[i];
|
|
|
|
f32 wavephase = (src.Pos.X + src.Pos.Y + src.Pos.Z) * function.wave;
|
|
function.phase = phase + wavephase;
|
|
|
|
const f32 f = function.evaluate ( dt );
|
|
|
|
dst.Pos.X = src.Pos.X + f * src.Normal.X;
|
|
dst.Pos.Y = src.Pos.Y + f * src.Normal.Y;
|
|
dst.Pos.Z = src.Pos.Z + f * src.Normal.Z;
|
|
}
|
|
}
|
|
|
|
/*!
|
|
*/
|
|
void CQuake3ShaderSceneNode::vertextransform_bulge ( f32 dt, quake3::SModifierFunction &function )
|
|
{
|
|
function.func = 0;
|
|
function.wave = core::reciprocal ( function.bulgewidth );
|
|
|
|
dt *= function.bulgespeed * 0.1f;
|
|
const f32 phase = function.phase;
|
|
|
|
const u32 vsize = MeshBuffer.Vertices.size();
|
|
for ( u32 i = 0; i != vsize; ++i )
|
|
{
|
|
const video::S3DVertex2TCoords &src = Original.Vertices[i];
|
|
video::S3DVertex &dst = MeshBuffer.Vertices[i];
|
|
|
|
f32 wavephase = (Original.Vertices[i].TCoords.X ) * function.wave;
|
|
function.phase = phase + wavephase;
|
|
|
|
const f32 f = function.evaluate ( dt );
|
|
|
|
dst.Pos.X = src.Pos.X + f * src.Normal.X;
|
|
dst.Pos.Y = src.Pos.Y + f * src.Normal.Y;
|
|
dst.Pos.Z = src.Pos.Z + f * src.Normal.Z;
|
|
}
|
|
}
|
|
|
|
/*!
|
|
*/
|
|
void CQuake3ShaderSceneNode::vertextransform_autosprite ( f32 dt, quake3::SModifierFunction &function )
|
|
{
|
|
const core::matrix4 &m = SceneManager->getActiveCamera()->getViewFrustum()->Matrices [ video::ETS_VIEW ];
|
|
const core::vector3df view ( -m[2], -m[6] , -m[10] );
|
|
|
|
const u32 vsize = MeshBuffer.Vertices.size();
|
|
|
|
core::aabbox3df box;
|
|
u32 g;
|
|
|
|
for ( u32 i = 0; i < vsize; i += 4 )
|
|
{
|
|
// in pairs of 4
|
|
box.reset ( Original.Vertices[i].Pos );
|
|
for ( g = 1; g != 4; ++g )
|
|
{
|
|
box.addInternalPoint ( Original.Vertices[i + g].Pos );
|
|
}
|
|
|
|
core::vector3df c = box.getCenter ();
|
|
f32 sh = 0.5f * ( box.MaxEdge.Z - box.MinEdge.Z );
|
|
f32 sv = 0.5f * ( box.MaxEdge.Y - box.MinEdge.Y );
|
|
|
|
const core::vector3df h ( m[0] * sh, m[4] * sh, m[8] * sh );
|
|
const core::vector3df v ( m[1] * sv, m[5] * sv, m[9] * sv );
|
|
|
|
MeshBuffer.Vertices[ i + 0 ].Pos = c + h + v;
|
|
MeshBuffer.Vertices[ i + 1 ].Pos = c - h - v;
|
|
MeshBuffer.Vertices[ i + 2 ].Pos = c + h - v;
|
|
MeshBuffer.Vertices[ i + 3 ].Pos = c - h + v;
|
|
|
|
MeshBuffer.Vertices[ i + 0 ].Normal = view;
|
|
MeshBuffer.Vertices[ i + 1 ].Normal = view;
|
|
MeshBuffer.Vertices[ i + 2 ].Normal = view;
|
|
MeshBuffer.Vertices[ i + 3 ].Normal = view;
|
|
}
|
|
}
|
|
|
|
/*
|
|
Generate Vertex Color
|
|
*/
|
|
void CQuake3ShaderSceneNode::vertextransform_rgbgen ( f32 dt, quake3::SModifierFunction &function )
|
|
{
|
|
u32 i;
|
|
const u32 vsize = MeshBuffer.Vertices.size();
|
|
|
|
switch ( function.masterfunc1 )
|
|
{
|
|
case 6:
|
|
//identity
|
|
for ( i = 0; i != vsize; ++i )
|
|
MeshBuffer.Vertices[i].Color = 0xFFFFFFFF;
|
|
break;
|
|
case 7:
|
|
// vertex
|
|
for ( i = 0; i != vsize; ++i )
|
|
MeshBuffer.Vertices[i].Color = Original.Vertices[i].Color;
|
|
break;
|
|
case 5:
|
|
{
|
|
// wave
|
|
f32 f = function.evaluate ( dt ) * 255.f;
|
|
s32 value = core::clamp ( core::floor32 ( f ), 0, 255 );
|
|
value |= value << 8;
|
|
value |= value << 16;
|
|
|
|
for ( i = 0; i != vsize; ++i )
|
|
MeshBuffer.Vertices[i].Color = value;
|
|
} break;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
Generate Texture Coordinates
|
|
*/
|
|
void CQuake3ShaderSceneNode::vertextransform_tcgen ( f32 dt, quake3::SModifierFunction &function )
|
|
{
|
|
u32 i;
|
|
const u32 vsize = MeshBuffer.Vertices.size();
|
|
|
|
switch ( function.tcgen )
|
|
{
|
|
case 12:
|
|
//tcgen turb
|
|
{
|
|
function.wave = core::reciprocal ( function.wave );
|
|
|
|
const f32 phase = function.phase;
|
|
|
|
for ( i = 0; i != vsize; ++i )
|
|
{
|
|
const video::S3DVertex2TCoords &src = Original.Vertices[i];
|
|
video::S3DVertex &dst = MeshBuffer.Vertices[i];
|
|
|
|
f32 wavephase = (src.Pos.X + src.Pos.Y + src.Pos.Z) * function.wave;
|
|
function.phase = phase + wavephase;
|
|
|
|
const f32 f = function.evaluate ( dt );
|
|
|
|
dst.TCoords.X = src.TCoords.X + f * src.Normal.X;
|
|
dst.TCoords.Y = src.TCoords.Y + f * src.Normal.Y;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case 8:
|
|
// tcgen texture
|
|
for ( i = 0; i != vsize; ++i )
|
|
MeshBuffer.Vertices[i].TCoords = Original.Vertices[i].TCoords;
|
|
break;
|
|
case 9:
|
|
// tcgen lightmap
|
|
for ( i = 0; i != vsize; ++i )
|
|
MeshBuffer.Vertices[i].TCoords = Original.Vertices[i].TCoords2;
|
|
break;
|
|
case 10:
|
|
{
|
|
// tcgen environment ( D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR )
|
|
|
|
// using eye linear, sphere map may be cooler;-)
|
|
// modelmatrix is identity
|
|
const core::matrix4 &view = SceneManager->getActiveCamera()->getViewFrustum()->Matrices [ video::ETS_VIEW ];
|
|
const core::matrix4 &viewinverse = SceneManager->getActiveCamera()->getViewFrustum()->Matrices [ SViewFrustum::ETS_VIEW_MODEL_INVERSE_3 ];
|
|
|
|
// eyePlane
|
|
core::vector3df eyePlaneS;
|
|
core::vector3df eyePlaneT;
|
|
|
|
viewinverse.transformVect ( eyePlaneS, core::vector3df ( 1.f, 0.f, 0.f ) );
|
|
viewinverse.transformVect ( eyePlaneT, core::vector3df ( 0.f, 1.f, 0.f ) );
|
|
|
|
eyePlaneS.normalize ();
|
|
eyePlaneT.normalize ();
|
|
|
|
core::vector3df v;
|
|
for ( i = 0; i != vsize; ++i )
|
|
{
|
|
// vertex in eye space
|
|
view.transformVect ( v, Original.Vertices[i].Pos );
|
|
v.normalize();
|
|
|
|
MeshBuffer.Vertices[i].TCoords.X = (1.f + eyePlaneS.dotProduct ( v ) ) * 0.5f;
|
|
MeshBuffer.Vertices[i].TCoords.Y = 1.f - ( (1.f + eyePlaneT.dotProduct ( v ) ) * 0.5f );
|
|
}
|
|
|
|
} break;
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
Transform Texture Coordinates
|
|
*/
|
|
void CQuake3ShaderSceneNode::transformtex ( const core::matrix4 &m, const u32 addressMode )
|
|
{
|
|
u32 i;
|
|
const u32 vsize = MeshBuffer.Vertices.size();
|
|
|
|
f32 tx1;
|
|
f32 ty1;
|
|
|
|
if ( addressMode )
|
|
{
|
|
for ( i = 0; i != vsize; ++i )
|
|
{
|
|
core::vector2df &tx = MeshBuffer.Vertices[i].TCoords;
|
|
|
|
tx1 = m[0] * tx.X + m[4] * tx.Y + m[8];
|
|
ty1 = m[1] * tx.X + m[5] * tx.Y + m[9];
|
|
|
|
tx.X = tx1;
|
|
tx.Y = ty1;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
|
|
for ( i = 0; i != vsize; ++i )
|
|
{
|
|
core::vector2df &tx = MeshBuffer.Vertices[i].TCoords;
|
|
|
|
tx1 = m[0] * tx.X + m[4] * tx.Y + m[8];
|
|
ty1 = m[1] * tx.X + m[5] * tx.Y + m[9];
|
|
|
|
tx.X = tx1 <= 0.f ? 0.f : tx1 >= 1.f ? 1.f : tx1;
|
|
tx.Y = ty1 <= 0.f ? 0.f : ty1 >= 1.f ? 1.f : ty1;
|
|
|
|
//tx.X = core::clamp ( tx1, 0.f, 1.f );
|
|
//tx.Y = core::clamp ( ty1, 0.f, 1.f );
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
Texture & Vertex Transform Animator
|
|
|
|
Return a Texture Transformation for this stage
|
|
Vertex transformation are called if found
|
|
|
|
*/
|
|
void CQuake3ShaderSceneNode::animate( u32 stage,core::matrix4 &texture )
|
|
{
|
|
const quake3::SVarGroup *group = Shader->getGroup ( stage );
|
|
|
|
// select current texture
|
|
if ( Q3Texture [ stage ].TextureFrequency != 0.f )
|
|
{
|
|
s32 v = core::floor32 ( TimeAbs * Q3Texture [ stage ].TextureFrequency );
|
|
Q3Texture [ stage ].TextureIndex = v % Q3Texture [ stage ].Texture.size();
|
|
}
|
|
|
|
core::matrix4 m2;
|
|
quake3::SModifierFunction function;
|
|
|
|
f32 f0;
|
|
f32 f1;
|
|
|
|
// walk group for all modifiers
|
|
for ( u32 g = 0; g != group->Variable.size (); ++g )
|
|
{
|
|
const quake3::SVariable &v = group->Variable[g];
|
|
|
|
// get the modifier
|
|
static const c8 * modifierList[] =
|
|
{
|
|
"tcmod","deformvertexes","rgbgen","tcgen","map"
|
|
};
|
|
|
|
u32 pos = 0;
|
|
function.masterfunc0 = quake3::isEqual ( v.name, pos, modifierList, 5 );
|
|
|
|
if ( -2 == function.masterfunc0 )
|
|
continue;
|
|
|
|
switch ( function.masterfunc0 )
|
|
{
|
|
//tcmod
|
|
case 0:
|
|
m2.makeIdentity ();
|
|
break;
|
|
}
|
|
|
|
// get the modifier function
|
|
static const c8 * funclist[] =
|
|
{
|
|
"scroll","scale","rotate","stretch","turb",
|
|
"wave","identity","vertex",
|
|
"texture","lightmap","environment","$lightmap",
|
|
"bulge","autosprite","autosprite2"
|
|
};
|
|
|
|
pos = 0;
|
|
function.masterfunc1 = quake3::isEqual ( v.content, pos, funclist, 14 );
|
|
|
|
switch ( function.masterfunc1 )
|
|
{
|
|
case 0:
|
|
// scroll
|
|
f0 = quake3::getAsFloat ( v.content, pos ) * TimeAbs;
|
|
f1 = quake3::getAsFloat ( v.content, pos ) * TimeAbs;
|
|
m2.setTextureTranslate ( -f0, f1 );
|
|
break;
|
|
case 1:
|
|
// scale
|
|
f0 = quake3::getAsFloat ( v.content, pos );
|
|
f1 = quake3::getAsFloat ( v.content, pos );
|
|
m2.setTextureScale ( f0, f1 );
|
|
break;
|
|
case 2:
|
|
//rotate
|
|
m2.setTextureRotationCenter ( quake3::getAsFloat ( v.content, pos ) * core::DEGTORAD * TimeAbs );
|
|
m2 = m2.getTransposed();
|
|
break;
|
|
case 3:
|
|
case 4:
|
|
case 5:
|
|
case 6:
|
|
case 7:
|
|
{
|
|
// turb == sin, default == sin
|
|
function.func = 0;
|
|
|
|
if ( function.masterfunc1 == 5 && function.masterfunc0 == 1)
|
|
{
|
|
// deformvertexes, wave
|
|
function.wave = quake3::getAsFloat ( v.content, pos );
|
|
}
|
|
|
|
if ( function.masterfunc1 == 3 ||
|
|
function.masterfunc1 == 4 ||
|
|
function.masterfunc1 == 5
|
|
)
|
|
{
|
|
// stretch, wave, tub
|
|
quake3::getModifierFunc ( function, v.content, pos );
|
|
}
|
|
|
|
switch ( function.masterfunc1 )
|
|
{
|
|
case 3:
|
|
// stretch
|
|
f0 = core::reciprocal ( function.evaluate ( TimeAbs ) );
|
|
m2.setTextureScaleCenter ( f0, f0 );
|
|
m2 = m2.getTransposed();
|
|
break;
|
|
case 4:
|
|
{
|
|
// turb
|
|
/*
|
|
quake3::SModifierFunction ampFunction;
|
|
ampFunction.func = 0;
|
|
ampFunction.freq = function.freq;
|
|
ampFunction.base = 1.f;
|
|
ampFunction.amp = 0.2f;
|
|
f2 = ampFunction.evaluate ( TimeAbs );
|
|
|
|
f0 = function.evaluate ( TimeAbs );
|
|
function.func = 1;
|
|
f1 = function.evaluate ( TimeAbs );
|
|
|
|
m2.setTextureTranslate ( f0, f1 );
|
|
m2.setTextureScaleCenter ( f2, f2 );
|
|
//m2.setTextureScale ( f2, f2 );
|
|
*/
|
|
}break;
|
|
case 5:
|
|
if ( function.masterfunc0 == 1 )
|
|
{
|
|
vertextransform_wave ( TimeAbs, function );
|
|
}
|
|
else
|
|
{
|
|
vertextransform_rgbgen ( TimeAbs, function );
|
|
}
|
|
break;
|
|
case 6:
|
|
case 7:
|
|
vertextransform_rgbgen ( TimeAbs, function );
|
|
break;
|
|
}
|
|
|
|
} break;
|
|
case 8:
|
|
case 9:
|
|
case 10:
|
|
// "texture","lightmap","environment"
|
|
function.tcgen = function.masterfunc1;
|
|
break;
|
|
case 11:
|
|
// map == lightmap, tcgen == lightmap
|
|
function.tcgen = 9;
|
|
break;
|
|
case 12:
|
|
// deformvertexes bulge
|
|
function.bulgewidth = quake3::getAsFloat ( v.content, pos );
|
|
function.bulgeheight = quake3::getAsFloat ( v.content, pos );
|
|
function.bulgespeed = quake3::getAsFloat ( v.content, pos );
|
|
|
|
vertextransform_bulge ( TimeAbs, function );
|
|
break;
|
|
|
|
case 13:
|
|
case 14:
|
|
// deformvertexes autosprite
|
|
vertextransform_autosprite ( TimeAbs, function);
|
|
break;
|
|
|
|
} // func
|
|
|
|
switch ( function.masterfunc0 )
|
|
{
|
|
case 0:
|
|
texture *= m2;
|
|
break;
|
|
}
|
|
|
|
} // group
|
|
|
|
// texture coordinate modifier
|
|
vertextransform_tcgen ( TimeAbs, function);
|
|
}
|
|
|
|
|
|
|
|
void CQuake3ShaderSceneNode::OnAnimate(u32 timeMs)
|
|
{
|
|
TimeAbs = f32( timeMs ) * ( 1.f/1000.f);
|
|
ISceneNode::OnAnimate ( timeMs );
|
|
}
|
|
|
|
const core::aabbox3d<f32>& CQuake3ShaderSceneNode::getBoundingBox() const
|
|
{
|
|
return MeshBuffer.getBoundingBox ();
|
|
}
|
|
|
|
|
|
u32 CQuake3ShaderSceneNode::getMaterialCount() const
|
|
{
|
|
return Q3Texture.size();
|
|
}
|
|
|
|
video::SMaterial& CQuake3ShaderSceneNode::getMaterial(u32 i)
|
|
{
|
|
video::SMaterial& m = MeshBuffer.getMaterial();
|
|
m.setTexture(0, 0);
|
|
if ( Q3Texture [ i ].TextureIndex )
|
|
m.setTexture(0, Q3Texture [ i ].Texture [ Q3Texture [ i ].TextureIndex ]);
|
|
return m;
|
|
}
|
|
|
|
|
|
} // end namespace scene
|
|
} // end namespace irr
|
|
|