mirror of
https://github.com/minetest/irrlicht.git
synced 2025-07-06 02:00:25 +02:00
Avoid warning and make local variable lower-case.
git-svn-id: svn://svn.code.sf.net/p/irrlicht/code/trunk@6000 dfc29bdd-3216-0410-991c-e03cc46cb475
This commit is contained in:
882
include/IQ3Shader.h
Normal file
882
include/IQ3Shader.h
Normal file
@ -0,0 +1,882 @@
|
||||
// Copyright (C) 2006-2012 Nikolaus Gebhardt / Thomas Alten
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#ifndef __I_Q3_LEVEL_SHADER_H_INCLUDED__
|
||||
#define __I_Q3_LEVEL_SHADER_H_INCLUDED__
|
||||
|
||||
#include "irrArray.h"
|
||||
#include "fast_atof.h"
|
||||
#include "IFileSystem.h"
|
||||
#include "IVideoDriver.h"
|
||||
#include "coreutil.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace scene
|
||||
{
|
||||
namespace quake3
|
||||
{
|
||||
|
||||
static core::stringc irrEmptyStringc("");
|
||||
|
||||
//! Hold the different Mesh Types used for getMesh
|
||||
enum eQ3MeshIndex
|
||||
{
|
||||
E_Q3_MESH_GEOMETRY = 0,
|
||||
E_Q3_MESH_ITEMS,
|
||||
E_Q3_MESH_BILLBOARD,
|
||||
E_Q3_MESH_FOG,
|
||||
E_Q3_MESH_UNRESOLVED,
|
||||
E_Q3_MESH_SIZE
|
||||
};
|
||||
|
||||
/*! used to customize Quake3 BSP Loader
|
||||
*/
|
||||
|
||||
struct Q3LevelLoadParameter
|
||||
{
|
||||
Q3LevelLoadParameter ()
|
||||
:defaultLightMapMaterial ( video::EMT_LIGHTMAP_M4 ),
|
||||
defaultModulate ( video::EMFN_MODULATE_4X ),
|
||||
defaultFilter ( video::EMF_BILINEAR_FILTER ),
|
||||
patchTesselation ( 8 ),
|
||||
verbose ( 0 ),
|
||||
startTime ( 0 ), endTime ( 0 ),
|
||||
mergeShaderBuffer ( 1 ),
|
||||
cleanUnResolvedMeshes ( 1 ),
|
||||
loadAllShaders ( 0 ),
|
||||
loadSkyShader ( 0 ),
|
||||
alpharef ( 1 ),
|
||||
swapLump ( 0 ),
|
||||
#ifdef __BIG_ENDIAN__
|
||||
swapHeader ( 1 )
|
||||
#else
|
||||
swapHeader ( 0 )
|
||||
#endif
|
||||
{
|
||||
memcpy ( scriptDir, "scripts\x0", 8 );
|
||||
}
|
||||
|
||||
video::E_MATERIAL_TYPE defaultLightMapMaterial;
|
||||
video::E_MODULATE_FUNC defaultModulate;
|
||||
video::E_MATERIAL_FLAG defaultFilter;
|
||||
s32 patchTesselation;
|
||||
s32 verbose;
|
||||
u32 startTime;
|
||||
u32 endTime;
|
||||
s32 mergeShaderBuffer;
|
||||
s32 cleanUnResolvedMeshes;
|
||||
s32 loadAllShaders;
|
||||
s32 loadSkyShader;
|
||||
s32 alpharef;
|
||||
s32 swapLump;
|
||||
s32 swapHeader;
|
||||
c8 scriptDir [ 64 ];
|
||||
};
|
||||
|
||||
// some useful typedefs
|
||||
typedef core::array< core::stringc > tStringList;
|
||||
typedef core::array< video::ITexture* > tTexArray;
|
||||
|
||||
// string helper.. TODO: move to generic files
|
||||
inline s16 isEqual ( const core::stringc &string, u32 &pos, const c8 * const list[], u16 listSize )
|
||||
{
|
||||
const char * in = string.c_str () + pos;
|
||||
|
||||
for ( u16 i = 0; i != listSize; ++i )
|
||||
{
|
||||
if (string.size() < pos)
|
||||
return -2;
|
||||
u32 len = (u32) strlen ( list[i] );
|
||||
if (string.size() < pos+len)
|
||||
continue;
|
||||
if ( in [len] != 0 && in [len] != ' ' )
|
||||
continue;
|
||||
if ( strncmp ( in, list[i], len ) )
|
||||
continue;
|
||||
|
||||
pos += len + 1;
|
||||
return (s16) i;
|
||||
}
|
||||
return -2;
|
||||
}
|
||||
|
||||
inline f32 getAsFloat ( const core::stringc &string, u32 &pos )
|
||||
{
|
||||
const char * in = string.c_str () + pos;
|
||||
|
||||
f32 value = 0.f;
|
||||
pos += (u32) ( core::fast_atof_move ( in, value ) - in ) + 1;
|
||||
return value;
|
||||
}
|
||||
|
||||
//! get a quake3 vector translated to irrlicht position (x,-z,y )
|
||||
inline core::vector3df getAsVector3df ( const core::stringc &string, u32 &pos )
|
||||
{
|
||||
core::vector3df v;
|
||||
|
||||
v.X = getAsFloat ( string, pos );
|
||||
v.Z = getAsFloat ( string, pos );
|
||||
v.Y = getAsFloat ( string, pos );
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
extract substrings
|
||||
*/
|
||||
inline void getAsStringList ( tStringList &list, s32 max, const core::stringc &string, u32 &startPos )
|
||||
{
|
||||
list.clear ();
|
||||
|
||||
s32 finish = 0;
|
||||
s32 endPos;
|
||||
do
|
||||
{
|
||||
endPos = string.findNext ( ' ', startPos );
|
||||
if ( endPos == -1 )
|
||||
{
|
||||
finish = 1;
|
||||
endPos = string.size();
|
||||
}
|
||||
|
||||
list.push_back ( string.subString ( startPos, endPos - startPos ) );
|
||||
startPos = endPos + 1;
|
||||
|
||||
if ( list.size() >= (u32) max )
|
||||
finish = 1;
|
||||
|
||||
} while ( !finish );
|
||||
|
||||
}
|
||||
|
||||
//! A blend function for a q3 shader.
|
||||
struct SBlendFunc
|
||||
{
|
||||
SBlendFunc ( video::E_MODULATE_FUNC mod )
|
||||
: type ( video::EMT_SOLID ), modulate ( mod ),
|
||||
param0( 0.f ),
|
||||
isTransparent ( 0 ) {}
|
||||
|
||||
video::E_MATERIAL_TYPE type;
|
||||
video::E_MODULATE_FUNC modulate;
|
||||
|
||||
f32 param0;
|
||||
u32 isTransparent;
|
||||
};
|
||||
|
||||
// parses the content of Variable cull
|
||||
inline bool getCullingFunction ( const core::stringc &cull )
|
||||
{
|
||||
if ( cull.size() == 0 )
|
||||
return true;
|
||||
|
||||
bool ret = true;
|
||||
static const c8 * funclist[] = { "none", "disable", "twosided" };
|
||||
|
||||
u32 pos = 0;
|
||||
switch ( isEqual ( cull, pos, funclist, 3 ) )
|
||||
{
|
||||
case 0:
|
||||
case 1:
|
||||
case 2:
|
||||
ret = false;
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
// parses the content of Variable depthfunc
|
||||
// return a z-test
|
||||
inline u8 getDepthFunction ( const core::stringc &string )
|
||||
{
|
||||
u8 ret = video::ECFN_LESSEQUAL;
|
||||
|
||||
if ( string.size() == 0 )
|
||||
return ret;
|
||||
|
||||
static const c8 * funclist[] = { "lequal","equal" };
|
||||
|
||||
u32 pos = 0;
|
||||
switch ( isEqual ( string, pos, funclist, 2 ) )
|
||||
{
|
||||
case 0:
|
||||
ret = video::ECFN_LESSEQUAL;
|
||||
break;
|
||||
case 1:
|
||||
ret = video::ECFN_EQUAL;
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
parses the content of Variable blendfunc,alphafunc
|
||||
it also make a hint for rendering as transparent or solid node.
|
||||
|
||||
we assume a typical quake scene would look like this..
|
||||
1) Big Static Mesh ( solid )
|
||||
2) static scene item ( may use transparency ) but rendered in the solid pass
|
||||
3) additional transparency item in the transparent pass
|
||||
|
||||
it's not 100% accurate! it just empirical..
|
||||
*/
|
||||
inline static void getBlendFunc ( const core::stringc &string, SBlendFunc &blendfunc )
|
||||
{
|
||||
if ( string.size() == 0 )
|
||||
return;
|
||||
|
||||
// maps to E_BLEND_FACTOR
|
||||
static const c8 * funclist[] =
|
||||
{
|
||||
"gl_zero",
|
||||
"gl_one",
|
||||
"gl_dst_color",
|
||||
"gl_one_minus_dst_color",
|
||||
"gl_src_color",
|
||||
"gl_one_minus_src_color",
|
||||
"gl_src_alpha",
|
||||
"gl_one_minus_src_alpha",
|
||||
"gl_dst_alpha",
|
||||
"gl_one_minus_dst_alpha",
|
||||
"gl_src_alpha_sat",
|
||||
|
||||
"add",
|
||||
"filter",
|
||||
"blend",
|
||||
|
||||
"ge128",
|
||||
"gt0",
|
||||
};
|
||||
|
||||
|
||||
u32 pos = 0;
|
||||
s32 srcFact = isEqual ( string, pos, funclist, 16 );
|
||||
|
||||
if ( srcFact < 0 )
|
||||
return;
|
||||
|
||||
u32 resolved = 0;
|
||||
s32 dstFact = isEqual ( string, pos, funclist, 16 );
|
||||
|
||||
switch ( srcFact )
|
||||
{
|
||||
case video::EBF_ZERO:
|
||||
switch ( dstFact )
|
||||
{
|
||||
// gl_zero gl_src_color == gl_dst_color gl_zero
|
||||
case video::EBF_SRC_COLOR:
|
||||
blendfunc.type = video::EMT_ONETEXTURE_BLEND;
|
||||
blendfunc.param0 = video::pack_textureBlendFunc ( video::EBF_DST_COLOR, video::EBF_ZERO, blendfunc.modulate );
|
||||
blendfunc.isTransparent = 1;
|
||||
resolved = 1;
|
||||
break;
|
||||
} break;
|
||||
|
||||
case video::EBF_ONE:
|
||||
switch ( dstFact )
|
||||
{
|
||||
// gl_one gl_zero
|
||||
case video::EBF_ZERO:
|
||||
blendfunc.type = video::EMT_SOLID;
|
||||
blendfunc.isTransparent = 0;
|
||||
resolved = 1;
|
||||
break;
|
||||
|
||||
// gl_one gl_one
|
||||
case video::EBF_ONE:
|
||||
blendfunc.type = video::EMT_TRANSPARENT_ADD_COLOR;
|
||||
blendfunc.isTransparent = 1;
|
||||
resolved = 1;
|
||||
break;
|
||||
} break;
|
||||
|
||||
case video::EBF_SRC_ALPHA:
|
||||
switch ( dstFact )
|
||||
{
|
||||
// gl_src_alpha gl_one_minus_src_alpha
|
||||
case video::EBF_ONE_MINUS_SRC_ALPHA:
|
||||
blendfunc.type = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
|
||||
blendfunc.param0 = 1.f/255.f;
|
||||
blendfunc.isTransparent = 1;
|
||||
resolved = 1;
|
||||
break;
|
||||
} break;
|
||||
|
||||
case 11:
|
||||
// add
|
||||
blendfunc.type = video::EMT_TRANSPARENT_ADD_COLOR;
|
||||
blendfunc.isTransparent = 1;
|
||||
resolved = 1;
|
||||
break;
|
||||
case 12:
|
||||
// filter = gl_dst_color gl_zero or gl_zero gl_src_color
|
||||
blendfunc.type = video::EMT_ONETEXTURE_BLEND;
|
||||
blendfunc.param0 = video::pack_textureBlendFunc ( video::EBF_DST_COLOR, video::EBF_ZERO, blendfunc.modulate );
|
||||
blendfunc.isTransparent = 1;
|
||||
resolved = 1;
|
||||
break;
|
||||
case 13:
|
||||
// blend = gl_src_alpha gl_one_minus_src_alpha
|
||||
blendfunc.type = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
|
||||
blendfunc.param0 = 1.f/255.f;
|
||||
blendfunc.isTransparent = 1;
|
||||
resolved = 1;
|
||||
break;
|
||||
case 14:
|
||||
// alphafunc ge128
|
||||
blendfunc.type = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
|
||||
blendfunc.param0 = 0.5f;
|
||||
blendfunc.isTransparent = 1;
|
||||
resolved = 1;
|
||||
break;
|
||||
case 15:
|
||||
// alphafunc gt0
|
||||
blendfunc.type = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
|
||||
blendfunc.param0 = 1.f / 255.f;
|
||||
blendfunc.isTransparent = 1;
|
||||
resolved = 1;
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
// use the generic blender
|
||||
if ( 0 == resolved )
|
||||
{
|
||||
blendfunc.type = video::EMT_ONETEXTURE_BLEND;
|
||||
blendfunc.param0 = video::pack_textureBlendFunc (
|
||||
(video::E_BLEND_FACTOR) srcFact,
|
||||
(video::E_BLEND_FACTOR) dstFact,
|
||||
blendfunc.modulate);
|
||||
|
||||
blendfunc.isTransparent = 1;
|
||||
}
|
||||
}
|
||||
|
||||
// random noise [-1;1]
|
||||
struct Noiser
|
||||
{
|
||||
static f32 get ()
|
||||
{
|
||||
static u32 RandomSeed = 0x69666966;
|
||||
RandomSeed = (RandomSeed * 3631 + 1);
|
||||
|
||||
f32 value = ( (f32) (RandomSeed & 0x7FFF ) * (1.0f / (f32)(0x7FFF >> 1) ) ) - 1.f;
|
||||
return value;
|
||||
}
|
||||
};
|
||||
|
||||
enum eQ3ModifierFunction
|
||||
{
|
||||
TCMOD = 0,
|
||||
DEFORMVERTEXES = 1,
|
||||
RGBGEN = 2,
|
||||
TCGEN = 3,
|
||||
MAP = 4,
|
||||
ALPHAGEN = 5,
|
||||
|
||||
FUNCTION2 = 0x10,
|
||||
SCROLL = FUNCTION2 + 1,
|
||||
SCALE = FUNCTION2 + 2,
|
||||
ROTATE = FUNCTION2 + 3,
|
||||
STRETCH = FUNCTION2 + 4,
|
||||
TURBULENCE = FUNCTION2 + 5,
|
||||
WAVE = FUNCTION2 + 6,
|
||||
|
||||
IDENTITY = FUNCTION2 + 7,
|
||||
VERTEX = FUNCTION2 + 8,
|
||||
TEXTURE = FUNCTION2 + 9,
|
||||
LIGHTMAP = FUNCTION2 + 10,
|
||||
ENVIRONMENT = FUNCTION2 + 11,
|
||||
DOLLAR_LIGHTMAP = FUNCTION2 + 12,
|
||||
BULGE = FUNCTION2 + 13,
|
||||
AUTOSPRITE = FUNCTION2 + 14,
|
||||
AUTOSPRITE2 = FUNCTION2 + 15,
|
||||
TRANSFORM = FUNCTION2 + 16,
|
||||
EXACTVERTEX = FUNCTION2 + 17,
|
||||
CONSTANT = FUNCTION2 + 18,
|
||||
LIGHTINGSPECULAR = FUNCTION2 + 19,
|
||||
MOVE = FUNCTION2 + 20,
|
||||
NORMAL = FUNCTION2 + 21,
|
||||
IDENTITYLIGHTING = FUNCTION2 + 22,
|
||||
|
||||
WAVE_MODIFIER_FUNCTION = 0x30,
|
||||
SINUS = WAVE_MODIFIER_FUNCTION + 1,
|
||||
COSINUS = WAVE_MODIFIER_FUNCTION + 2,
|
||||
SQUARE = WAVE_MODIFIER_FUNCTION + 3,
|
||||
TRIANGLE = WAVE_MODIFIER_FUNCTION + 4,
|
||||
SAWTOOTH = WAVE_MODIFIER_FUNCTION + 5,
|
||||
SAWTOOTH_INVERSE = WAVE_MODIFIER_FUNCTION + 6,
|
||||
NOISE = WAVE_MODIFIER_FUNCTION + 7,
|
||||
|
||||
UNKNOWN = -2
|
||||
};
|
||||
|
||||
struct SModifierFunction
|
||||
{
|
||||
SModifierFunction ()
|
||||
: masterfunc0 ( UNKNOWN ), masterfunc1( UNKNOWN ), func ( SINUS ),
|
||||
tcgen( TEXTURE ), rgbgen ( IDENTITY ), alphagen ( UNKNOWN ),
|
||||
base ( 0 ), amp ( 1 ), phase ( 0 ), frequency ( 1 ),
|
||||
wave ( 1 ),
|
||||
x ( 0 ), y ( 0 ), z( 0 ), count( 0 ) {}
|
||||
|
||||
// "tcmod","deformvertexes","rgbgen", "tcgen"
|
||||
eQ3ModifierFunction masterfunc0;
|
||||
// depends
|
||||
eQ3ModifierFunction masterfunc1;
|
||||
// depends
|
||||
eQ3ModifierFunction func;
|
||||
|
||||
eQ3ModifierFunction tcgen;
|
||||
eQ3ModifierFunction rgbgen;
|
||||
eQ3ModifierFunction alphagen;
|
||||
|
||||
union
|
||||
{
|
||||
f32 base;
|
||||
f32 bulgewidth;
|
||||
};
|
||||
|
||||
union
|
||||
{
|
||||
f32 amp;
|
||||
f32 bulgeheight;
|
||||
};
|
||||
|
||||
f32 phase;
|
||||
|
||||
union
|
||||
{
|
||||
f32 frequency;
|
||||
f32 bulgespeed;
|
||||
};
|
||||
|
||||
union
|
||||
{
|
||||
f32 wave;
|
||||
f32 div;
|
||||
};
|
||||
|
||||
f32 x;
|
||||
f32 y;
|
||||
f32 z;
|
||||
u32 count;
|
||||
|
||||
f32 evaluate ( f32 dt ) const
|
||||
{
|
||||
// phase in 0 and 1..
|
||||
f32 x = core::fract( (dt + phase ) * frequency );
|
||||
f32 y = 0.f;
|
||||
|
||||
switch ( func )
|
||||
{
|
||||
case SINUS:
|
||||
y = sinf ( x * core::PI * 2.f );
|
||||
break;
|
||||
case COSINUS:
|
||||
y = cosf ( x * core::PI * 2.f );
|
||||
break;
|
||||
case SQUARE:
|
||||
y = x < 0.5f ? 1.f : -1.f;
|
||||
break;
|
||||
case TRIANGLE:
|
||||
y = x < 0.5f ? ( 4.f * x ) - 1.f : ( -4.f * x ) + 3.f;
|
||||
break;
|
||||
case SAWTOOTH:
|
||||
y = x;
|
||||
break;
|
||||
case SAWTOOTH_INVERSE:
|
||||
y = 1.f - x;
|
||||
break;
|
||||
case NOISE:
|
||||
y = Noiser::get();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return base + ( y * amp );
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
|
||||
inline core::vector3df getMD3Normal ( u32 i, u32 j )
|
||||
{
|
||||
const f32 lng = i * 2.0f * core::PI / 255.0f;
|
||||
const f32 lat = j * 2.0f * core::PI / 255.0f;
|
||||
return core::vector3df(cosf ( lat ) * sinf ( lng ),
|
||||
sinf ( lat ) * sinf ( lng ),
|
||||
cosf ( lng ));
|
||||
}
|
||||
|
||||
//
|
||||
inline void getModifierFunc ( SModifierFunction& fill, const core::stringc &string, u32 &pos )
|
||||
{
|
||||
if ( string.size() == 0 )
|
||||
return;
|
||||
|
||||
static const c8 * funclist[] =
|
||||
{
|
||||
"sin","cos","square",
|
||||
"triangle", "sawtooth","inversesawtooth", "noise"
|
||||
};
|
||||
|
||||
fill.func = (eQ3ModifierFunction) isEqual ( string,pos, funclist,7 );
|
||||
fill.func = fill.func == UNKNOWN ? SINUS : (eQ3ModifierFunction) ((u32) fill.func + WAVE_MODIFIER_FUNCTION + 1);
|
||||
|
||||
fill.base = getAsFloat ( string, pos );
|
||||
fill.amp = getAsFloat ( string, pos );
|
||||
fill.phase = getAsFloat ( string, pos );
|
||||
fill.frequency = getAsFloat ( string, pos );
|
||||
}
|
||||
|
||||
|
||||
// name = "a b c .."
|
||||
struct SVariable
|
||||
{
|
||||
core::stringc name;
|
||||
core::stringc content;
|
||||
|
||||
SVariable ( const c8 * n, const c8 *c = 0 ) : name ( n ), content (c) {}
|
||||
virtual ~SVariable () {}
|
||||
|
||||
void clear ()
|
||||
{
|
||||
name = "";
|
||||
content = "";
|
||||
}
|
||||
|
||||
s32 isValid () const
|
||||
{
|
||||
return name.size();
|
||||
}
|
||||
|
||||
bool operator == ( const SVariable &other ) const
|
||||
{
|
||||
return 0 == strcmp ( name.c_str(), other.name.c_str () );
|
||||
}
|
||||
|
||||
bool operator < ( const SVariable &other ) const
|
||||
{
|
||||
return 0 > strcmp ( name.c_str(), other.name.c_str () );
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
// string database. "a" = "Hello", "b" = "1234.6"
|
||||
struct SVarGroup
|
||||
{
|
||||
SVarGroup () { Variable.setAllocStrategy ( core::ALLOC_STRATEGY_SAFE ); }
|
||||
virtual ~SVarGroup () {}
|
||||
|
||||
u32 isDefined ( const c8 * name, const c8 * content = 0 ) const
|
||||
{
|
||||
for ( u32 i = 0; i != Variable.size (); ++i )
|
||||
{
|
||||
if ( 0 == strcmp ( Variable[i].name.c_str(), name ) &&
|
||||
( 0 == content || strstr ( Variable[i].content.c_str(), content ) )
|
||||
)
|
||||
{
|
||||
return i + 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// searches for Variable name and returns is content
|
||||
// if Variable is not found a reference to an Empty String is returned
|
||||
const core::stringc &get( const c8 * name ) const
|
||||
{
|
||||
SVariable search ( name );
|
||||
s32 index = Variable.linear_search ( search );
|
||||
if ( index < 0 )
|
||||
return irrEmptyStringc;
|
||||
|
||||
return Variable [ index ].content;
|
||||
}
|
||||
|
||||
// set the Variable name
|
||||
void set ( const c8 * name, const c8 * content = 0 )
|
||||
{
|
||||
u32 index = isDefined ( name, 0 );
|
||||
if ( 0 == index )
|
||||
{
|
||||
Variable.push_back ( SVariable ( name, content ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
Variable [ index ].content = content;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
core::array < SVariable > Variable;
|
||||
};
|
||||
|
||||
//! holding a group a variable
|
||||
struct SVarGroupList: public IReferenceCounted
|
||||
{
|
||||
SVarGroupList ()
|
||||
{
|
||||
VariableGroup.setAllocStrategy ( core::ALLOC_STRATEGY_SAFE );
|
||||
}
|
||||
virtual ~SVarGroupList () {}
|
||||
|
||||
core::array < SVarGroup > VariableGroup;
|
||||
};
|
||||
|
||||
|
||||
//! A Parsed Shader Holding Variables ordered in Groups
|
||||
struct IShader
|
||||
{
|
||||
IShader ()
|
||||
: ID ( 0 ), VarGroup ( 0 ) {}
|
||||
virtual ~IShader () {}
|
||||
|
||||
void operator = (const IShader &other )
|
||||
{
|
||||
ID = other.ID;
|
||||
VarGroup = other.VarGroup;
|
||||
name = other.name;
|
||||
}
|
||||
|
||||
bool operator == (const IShader &other ) const
|
||||
{
|
||||
return 0 == strcmp ( name.c_str(), other.name.c_str () );
|
||||
//return name == other.name;
|
||||
}
|
||||
|
||||
bool operator < (const IShader &other ) const
|
||||
{
|
||||
return strcmp ( name.c_str(), other.name.c_str () ) < 0;
|
||||
//return name < other.name;
|
||||
}
|
||||
|
||||
u32 getGroupSize () const
|
||||
{
|
||||
if ( 0 == VarGroup )
|
||||
return 0;
|
||||
return VarGroup->VariableGroup.size ();
|
||||
}
|
||||
|
||||
const SVarGroup * getGroup ( u32 stage ) const
|
||||
{
|
||||
if ( 0 == VarGroup || stage >= VarGroup->VariableGroup.size () )
|
||||
return 0;
|
||||
|
||||
return &VarGroup->VariableGroup [ stage ];
|
||||
}
|
||||
|
||||
// id
|
||||
s32 ID;
|
||||
SVarGroupList *VarGroup; // reference
|
||||
|
||||
// Shader: shader name ( also first variable in first Vargroup )
|
||||
// Entity: classname ( variable in Group(1) )
|
||||
core::stringc name;
|
||||
};
|
||||
|
||||
typedef IShader IEntity;
|
||||
|
||||
typedef core::array < IEntity > tQ3EntityList;
|
||||
|
||||
/*
|
||||
dump shader like original layout, regardless of internal data holding
|
||||
no recursive folding..
|
||||
*/
|
||||
inline void dumpVarGroup ( core::stringc &dest, const SVarGroup * group, s32 stack )
|
||||
{
|
||||
core::stringc buf;
|
||||
|
||||
if ( stack > 0 )
|
||||
{
|
||||
buf = "";
|
||||
for (s32 i = 0; i < stack - 1; ++i )
|
||||
buf += '\t';
|
||||
|
||||
buf += "{\n";
|
||||
dest.append ( buf );
|
||||
}
|
||||
|
||||
for ( u32 g = 0; g != group->Variable.size(); ++g )
|
||||
{
|
||||
buf = "";
|
||||
for (s32 i = 0; i < stack; ++i )
|
||||
buf += '\t';
|
||||
|
||||
buf += group->Variable[g].name;
|
||||
buf += " ";
|
||||
buf += group->Variable[g].content;
|
||||
buf += "\n";
|
||||
dest.append ( buf );
|
||||
}
|
||||
|
||||
if ( stack > 1 )
|
||||
{
|
||||
buf = "";
|
||||
for (s32 i = 0; i < stack - 1; ++i )
|
||||
buf += '\t';
|
||||
|
||||
buf += "}\n";
|
||||
dest.append ( buf );
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
dump a Shader or an Entity
|
||||
*/
|
||||
inline core::stringc & dumpShader ( core::stringc &dest, const IShader * shader, bool entity = false )
|
||||
{
|
||||
if ( 0 == shader )
|
||||
return dest;
|
||||
|
||||
const u32 size = shader->VarGroup->VariableGroup.size ();
|
||||
for ( u32 i = 0; i != size; ++i )
|
||||
{
|
||||
const SVarGroup * group = &shader->VarGroup->VariableGroup[ i ];
|
||||
dumpVarGroup ( dest, group, core::clamp( (int)i, 0, 2 ) );
|
||||
}
|
||||
|
||||
if ( !entity )
|
||||
{
|
||||
if ( size <= 1 )
|
||||
{
|
||||
dest.append ( "{\n" );
|
||||
}
|
||||
dest.append ( "}\n" );
|
||||
}
|
||||
return dest;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
quake3 doesn't care much about tga & jpg
|
||||
load one or multiple files stored in name started at startPos to the texture array textures
|
||||
if texture is not loaded 0 will be added ( to find missing textures easier)
|
||||
*/
|
||||
inline void getTextures(tTexArray &textures,
|
||||
const core::stringc &name, u32 &startPos,
|
||||
const io::IFileSystem *fileSystem,
|
||||
video::IVideoDriver* driver)
|
||||
{
|
||||
static const char * const extension[] =
|
||||
{
|
||||
".jpg",
|
||||
".jpeg",
|
||||
".png",
|
||||
".dds",
|
||||
".tga",
|
||||
".bmp",
|
||||
".pcx"
|
||||
};
|
||||
|
||||
tStringList stringList;
|
||||
getAsStringList(stringList, -1, name, startPos);
|
||||
|
||||
textures.clear();
|
||||
|
||||
io::path loadFile;
|
||||
for ( u32 i = 0; i!= stringList.size (); ++i )
|
||||
{
|
||||
video::ITexture* texture = 0;
|
||||
for (u32 g = 0; g != 7; ++g)
|
||||
{
|
||||
core::cutFilenameExtension ( loadFile, stringList[i] );
|
||||
|
||||
if ( loadFile == "$whiteimage" )
|
||||
{
|
||||
texture = driver->getTexture( "$whiteimage" );
|
||||
if ( 0 == texture )
|
||||
{
|
||||
core::dimension2du s ( 2, 2 );
|
||||
u32 image[4] = { 0xFFFFFFFF, 0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF };
|
||||
video::IImage* w = driver->createImageFromData ( video::ECF_A8R8G8B8, s,&image );
|
||||
texture = driver->addTexture( "$whiteimage", w );
|
||||
w->drop ();
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
if ( loadFile == "$redimage" )
|
||||
{
|
||||
texture = driver->getTexture( "$redimage" );
|
||||
if ( 0 == texture )
|
||||
{
|
||||
core::dimension2du s ( 2, 2 );
|
||||
u32 image[4] = { 0xFFFF0000, 0xFFFF0000,0xFFFF0000,0xFFFF0000 };
|
||||
video::IImage* w = driver->createImageFromData ( video::ECF_A8R8G8B8, s,&image );
|
||||
texture = driver->addTexture( "$redimage", w );
|
||||
w->drop ();
|
||||
}
|
||||
}
|
||||
else
|
||||
if ( loadFile == "$blueimage" )
|
||||
{
|
||||
texture = driver->getTexture( "$blueimage" );
|
||||
if ( 0 == texture )
|
||||
{
|
||||
core::dimension2du s ( 2, 2 );
|
||||
u32 image[4] = { 0xFF0000FF, 0xFF0000FF,0xFF0000FF,0xFF0000FF };
|
||||
video::IImage* w = driver->createImageFromData ( video::ECF_A8R8G8B8, s,&image );
|
||||
texture = driver->addTexture( "$blueimage", w );
|
||||
w->drop ();
|
||||
}
|
||||
}
|
||||
else
|
||||
if ( loadFile == "$checkerimage" )
|
||||
{
|
||||
texture = driver->getTexture( "$checkerimage" );
|
||||
if ( 0 == texture )
|
||||
{
|
||||
core::dimension2du s ( 2, 2 );
|
||||
u32 image[4] = { 0xFFFFFFFF, 0xFF000000,0xFF000000,0xFFFFFFFF };
|
||||
video::IImage* w = driver->createImageFromData ( video::ECF_A8R8G8B8, s,&image );
|
||||
texture = driver->addTexture( "$checkerimage", w );
|
||||
w->drop ();
|
||||
}
|
||||
}
|
||||
else
|
||||
if ( loadFile == "$lightmap" )
|
||||
{
|
||||
texture = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
loadFile.append ( extension[g] );
|
||||
}
|
||||
|
||||
texture = driver->findTexture( loadFile );
|
||||
if ( texture )
|
||||
break;
|
||||
|
||||
if ( fileSystem->existFile ( loadFile ) )
|
||||
{
|
||||
texture = driver->getTexture( loadFile );
|
||||
if ( texture )
|
||||
break;
|
||||
texture = 0;
|
||||
}
|
||||
}
|
||||
// take 0 Texture
|
||||
textures.push_back(texture);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//! Manages various Quake3 Shader Styles
|
||||
class IShaderManager : public IReferenceCounted
|
||||
{
|
||||
};
|
||||
|
||||
} // end namespace quake3
|
||||
} // end namespace scene
|
||||
} // end namespace irr
|
||||
|
||||
#endif
|
||||
|
Reference in New Issue
Block a user