mirror of
https://github.com/minetest/irrlicht.git
synced 2025-07-01 07:40:26 +02:00
Import irrlicht 1.8.4 release
This commit is contained in:
1075
source/Irrlicht/BuiltInFont.h
Normal file
1075
source/Irrlicht/BuiltInFont.h
Normal file
File diff suppressed because it is too large
Load Diff
1396
source/Irrlicht/C3DSMeshFileLoader.cpp
Normal file
1396
source/Irrlicht/C3DSMeshFileLoader.cpp
Normal file
File diff suppressed because it is too large
Load Diff
166
source/Irrlicht/C3DSMeshFileLoader.h
Normal file
166
source/Irrlicht/C3DSMeshFileLoader.h
Normal file
@ -0,0 +1,166 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#ifndef __C_3DS_MESH_FILE_LOADER_H_INCLUDED__
|
||||
#define __C_3DS_MESH_FILE_LOADER_H_INCLUDED__
|
||||
|
||||
#include "IMeshLoader.h"
|
||||
#include "IFileSystem.h"
|
||||
#include "ISceneManager.h"
|
||||
#include "irrString.h"
|
||||
#include "SMesh.h"
|
||||
#include "matrix4.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace scene
|
||||
{
|
||||
|
||||
//! Meshloader capable of loading 3ds meshes.
|
||||
class C3DSMeshFileLoader : public IMeshLoader
|
||||
{
|
||||
public:
|
||||
|
||||
//! Constructor
|
||||
C3DSMeshFileLoader(ISceneManager* smgr, io::IFileSystem* fs);
|
||||
|
||||
//! destructor
|
||||
virtual ~C3DSMeshFileLoader();
|
||||
|
||||
//! returns true if the file maybe is able to be loaded by this class
|
||||
//! based on the file extension (e.g. ".cob")
|
||||
virtual bool isALoadableFileExtension(const io::path& filename) const;
|
||||
|
||||
//! creates/loads an animated mesh from the file.
|
||||
//! \return Pointer to the created mesh. Returns 0 if loading failed.
|
||||
//! If you no longer need the mesh, you should call IAnimatedMesh::drop().
|
||||
//! See IReferenceCounted::drop() for more information.
|
||||
virtual IAnimatedMesh* createMesh(io::IReadFile* file);
|
||||
|
||||
private:
|
||||
|
||||
// byte-align structures
|
||||
#include "irrpack.h"
|
||||
|
||||
struct ChunkHeader
|
||||
{
|
||||
u16 id;
|
||||
s32 length;
|
||||
} PACK_STRUCT;
|
||||
|
||||
// Default alignment
|
||||
#include "irrunpack.h"
|
||||
|
||||
struct ChunkData
|
||||
{
|
||||
ChunkData() : read(0) {}
|
||||
|
||||
ChunkHeader header;
|
||||
s32 read;
|
||||
};
|
||||
|
||||
struct SCurrentMaterial
|
||||
{
|
||||
void clear() {
|
||||
Material=video::SMaterial();
|
||||
Name="";
|
||||
Filename[0]="";
|
||||
Filename[1]="";
|
||||
Filename[2]="";
|
||||
Filename[3]="";
|
||||
Filename[4]="";
|
||||
Strength[0]=0.f;
|
||||
Strength[1]=0.f;
|
||||
Strength[2]=0.f;
|
||||
Strength[3]=0.f;
|
||||
Strength[4]=0.f;
|
||||
}
|
||||
|
||||
video::SMaterial Material;
|
||||
core::stringc Name;
|
||||
core::stringc Filename[5];
|
||||
f32 Strength[5];
|
||||
};
|
||||
|
||||
struct SMaterialGroup
|
||||
{
|
||||
SMaterialGroup() : faceCount(0), faces(0) {};
|
||||
|
||||
SMaterialGroup(const SMaterialGroup& o)
|
||||
{
|
||||
*this = o;
|
||||
}
|
||||
|
||||
~SMaterialGroup()
|
||||
{
|
||||
clear();
|
||||
}
|
||||
|
||||
void clear()
|
||||
{
|
||||
delete [] faces;
|
||||
faces = 0;
|
||||
faceCount = 0;
|
||||
}
|
||||
|
||||
void operator =(const SMaterialGroup& o)
|
||||
{
|
||||
MaterialName = o.MaterialName;
|
||||
faceCount = o.faceCount;
|
||||
faces = new u16[faceCount];
|
||||
for (u16 i=0; i<faceCount; ++i)
|
||||
faces[i] = o.faces[i];
|
||||
}
|
||||
|
||||
core::stringc MaterialName;
|
||||
u16 faceCount;
|
||||
u16* faces;
|
||||
};
|
||||
|
||||
bool readChunk(io::IReadFile* file, ChunkData* parent);
|
||||
bool readMaterialChunk(io::IReadFile* file, ChunkData* parent);
|
||||
bool readFrameChunk(io::IReadFile* file, ChunkData* parent);
|
||||
bool readTrackChunk(io::IReadFile* file, ChunkData& data,
|
||||
IMeshBuffer* mb, const core::vector3df& pivot);
|
||||
bool readObjectChunk(io::IReadFile* file, ChunkData* parent);
|
||||
bool readPercentageChunk(io::IReadFile* file, ChunkData* chunk, f32& percentage);
|
||||
bool readColorChunk(io::IReadFile* file, ChunkData* chunk, video::SColor& out);
|
||||
|
||||
void readChunkData(io::IReadFile* file, ChunkData& data);
|
||||
void readString(io::IReadFile* file, ChunkData& data, core::stringc& out);
|
||||
void readVertices(io::IReadFile* file, ChunkData& data);
|
||||
void readIndices(io::IReadFile* file, ChunkData& data);
|
||||
void readMaterialGroup(io::IReadFile* file, ChunkData& data);
|
||||
void readTextureCoords(io::IReadFile* file, ChunkData& data);
|
||||
|
||||
void composeObject(io::IReadFile* file, const core::stringc& name);
|
||||
void loadMaterials(io::IReadFile* file);
|
||||
void cleanUp();
|
||||
|
||||
scene::ISceneManager* SceneManager;
|
||||
io::IFileSystem* FileSystem;
|
||||
|
||||
f32* Vertices;
|
||||
u16* Indices;
|
||||
u32* SmoothingGroups;
|
||||
core::array<u16> TempIndices;
|
||||
f32* TCoords;
|
||||
u16 CountVertices;
|
||||
u16 CountFaces; // = CountIndices/4
|
||||
u16 CountTCoords;
|
||||
core::array<SMaterialGroup> MaterialGroups;
|
||||
|
||||
SCurrentMaterial CurrentMaterial;
|
||||
core::array<SCurrentMaterial> Materials;
|
||||
core::array<core::stringc> MeshBufferNames;
|
||||
core::matrix4 TransformationMatrix;
|
||||
|
||||
SMesh* Mesh;
|
||||
};
|
||||
|
||||
} // end namespace scene
|
||||
} // end namespace irr
|
||||
|
||||
#endif
|
||||
|
1695
source/Irrlicht/CAnimatedMeshHalfLife.cpp
Normal file
1695
source/Irrlicht/CAnimatedMeshHalfLife.cpp
Normal file
File diff suppressed because it is too large
Load Diff
630
source/Irrlicht/CAnimatedMeshHalfLife.h
Normal file
630
source/Irrlicht/CAnimatedMeshHalfLife.h
Normal file
@ -0,0 +1,630 @@
|
||||
// Copyright (C) 2002-2012 Thomas Alten
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#ifndef __C_ANIMATED_MESH_HALFLIFE_H_INCLUDED__
|
||||
#define __C_ANIMATED_MESH_HALFLIFE_H_INCLUDED__
|
||||
|
||||
#include "IAnimatedMesh.h"
|
||||
#include "ISceneManager.h"
|
||||
#include "irrArray.h"
|
||||
#include "irrString.h"
|
||||
#include "IMeshLoader.h"
|
||||
#include "SMesh.h"
|
||||
#include "IReadFile.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace scene
|
||||
{
|
||||
|
||||
|
||||
// STUDIO MODELS, Copyright (c) 1998, Valve LLC. All rights reserved.
|
||||
#define MAXSTUDIOTRIANGLES 20000 // TODO: tune this
|
||||
#define MAXSTUDIOVERTS 2048 // TODO: tune this
|
||||
#define MAXSTUDIOSEQUENCES 256 // total animation sequences
|
||||
#define MAXSTUDIOSKINS 100 // total textures
|
||||
#define MAXSTUDIOSRCBONES 512 // bones allowed at source movement
|
||||
#define MAXSTUDIOBONES 128 // total bones actually used
|
||||
#define MAXSTUDIOMODELS 32 // sub-models per model
|
||||
#define MAXSTUDIOBODYPARTS 32
|
||||
#define MAXSTUDIOGROUPS 4
|
||||
#define MAXSTUDIOANIMATIONS 512 // per sequence
|
||||
#define MAXSTUDIOMESHES 256
|
||||
#define MAXSTUDIOEVENTS 1024
|
||||
#define MAXSTUDIOPIVOTS 256
|
||||
#define MAXSTUDIOCONTROLLERS 8
|
||||
|
||||
typedef f32 vec3_hl[3]; // x,y,z
|
||||
typedef f32 vec4_hl[4]; // x,y,z,w
|
||||
|
||||
// byte-align structures
|
||||
#include "irrpack.h"
|
||||
|
||||
struct SHalflifeHeader
|
||||
{
|
||||
c8 id[4];
|
||||
s32 version;
|
||||
|
||||
c8 name[64];
|
||||
s32 length;
|
||||
|
||||
vec3_hl eyeposition; // ideal eye position
|
||||
vec3_hl min; // ideal movement hull size
|
||||
vec3_hl max;
|
||||
|
||||
vec3_hl bbmin; // clipping bounding box
|
||||
vec3_hl bbmax;
|
||||
|
||||
s32 flags;
|
||||
|
||||
u32 numbones; // bones
|
||||
u32 boneindex;
|
||||
|
||||
u32 numbonecontrollers; // bone controllers
|
||||
u32 bonecontrollerindex;
|
||||
|
||||
u32 numhitboxes; // complex bounding boxes
|
||||
u32 hitboxindex;
|
||||
|
||||
u32 numseq; // animation sequences
|
||||
u32 seqindex;
|
||||
|
||||
u32 numseqgroups; // demand loaded sequences
|
||||
u32 seqgroupindex;
|
||||
|
||||
u32 numtextures; // raw textures
|
||||
u32 textureindex;
|
||||
u32 texturedataindex;
|
||||
|
||||
u32 numskinref; // replaceable textures
|
||||
u32 numskinfamilies;
|
||||
u32 skinindex;
|
||||
|
||||
u32 numbodyparts;
|
||||
u32 bodypartindex;
|
||||
|
||||
u32 numattachments; // queryable attachable points
|
||||
u32 attachmentindex;
|
||||
|
||||
s32 soundtable;
|
||||
s32 soundindex;
|
||||
s32 soundgroups;
|
||||
s32 soundgroupindex;
|
||||
|
||||
s32 numtransitions; // animation node to animation node transition graph
|
||||
s32 transitionindex;
|
||||
} PACK_STRUCT;
|
||||
|
||||
// header for demand loaded sequence group data
|
||||
struct studioseqhdr_t
|
||||
{
|
||||
s32 id;
|
||||
s32 version;
|
||||
|
||||
c8 name[64];
|
||||
s32 length;
|
||||
} PACK_STRUCT;
|
||||
|
||||
// bones
|
||||
struct SHalflifeBone
|
||||
{
|
||||
c8 name[32]; // bone name for symbolic links
|
||||
s32 parent; // parent bone
|
||||
s32 flags; // ??
|
||||
s32 bonecontroller[6]; // bone controller index, -1 == none
|
||||
f32 value[6]; // default DoF values
|
||||
f32 scale[6]; // scale for delta DoF values
|
||||
} PACK_STRUCT;
|
||||
|
||||
|
||||
// bone controllers
|
||||
struct SHalflifeBoneController
|
||||
{
|
||||
s32 bone; // -1 == 0
|
||||
s32 type; // X, Y, Z, XR, YR, ZR, M
|
||||
f32 start;
|
||||
f32 end;
|
||||
s32 rest; // byte index value at rest
|
||||
s32 index; // 0-3 user set controller, 4 mouth
|
||||
} PACK_STRUCT;
|
||||
|
||||
// intersection boxes
|
||||
struct SHalflifeBBox
|
||||
{
|
||||
s32 bone;
|
||||
s32 group; // intersection group
|
||||
vec3_hl bbmin; // bounding box
|
||||
vec3_hl bbmax;
|
||||
} PACK_STRUCT;
|
||||
|
||||
#ifndef ZONE_H
|
||||
// NOTE: this was a void*, but that crashes on 64bit.
|
||||
// I have found no mdl format desc, so not sure what it's meant to be, but s32 at least works.
|
||||
typedef s32 cache_user_t;
|
||||
#endif
|
||||
|
||||
// demand loaded sequence groups
|
||||
struct SHalflifeSequenceGroup
|
||||
{
|
||||
c8 label[32]; // textual name
|
||||
c8 name[64]; // file name
|
||||
cache_user_t cache; // cache index pointer
|
||||
s32 data; // hack for group 0
|
||||
} PACK_STRUCT;
|
||||
|
||||
// sequence descriptions
|
||||
struct SHalflifeSequence
|
||||
{
|
||||
c8 label[32]; // sequence label
|
||||
|
||||
f32 fps; // frames per second
|
||||
s32 flags; // looping/non-looping flags
|
||||
|
||||
s32 activity;
|
||||
s32 actweight;
|
||||
|
||||
s32 numevents;
|
||||
s32 eventindex;
|
||||
|
||||
s32 numframes; // number of frames per sequence
|
||||
|
||||
u32 numpivots; // number of foot pivots
|
||||
u32 pivotindex;
|
||||
|
||||
s32 motiontype;
|
||||
s32 motionbone;
|
||||
vec3_hl linearmovement;
|
||||
s32 automoveposindex;
|
||||
s32 automoveangleindex;
|
||||
|
||||
vec3_hl bbmin; // per sequence bounding box
|
||||
vec3_hl bbmax;
|
||||
|
||||
s32 numblends;
|
||||
s32 animindex; // SHalflifeAnimOffset pointer relative to start of sequence group data
|
||||
// [blend][bone][X, Y, Z, XR, YR, ZR]
|
||||
|
||||
s32 blendtype[2]; // X, Y, Z, XR, YR, ZR
|
||||
f32 blendstart[2]; // starting value
|
||||
f32 blendend[2]; // ending value
|
||||
s32 blendparent;
|
||||
|
||||
s32 seqgroup; // sequence group for demand loading
|
||||
|
||||
s32 entrynode; // transition node at entry
|
||||
s32 exitnode; // transition node at exit
|
||||
s32 nodeflags; // transition rules
|
||||
|
||||
s32 nextseq; // auto advancing sequences
|
||||
} PACK_STRUCT;
|
||||
|
||||
// events
|
||||
struct mstudioevent_t
|
||||
{
|
||||
s32 frame;
|
||||
s32 event;
|
||||
s32 type;
|
||||
c8 options[64];
|
||||
} PACK_STRUCT;
|
||||
|
||||
|
||||
// pivots
|
||||
struct mstudiopivot_t
|
||||
{
|
||||
vec3_hl org; // pivot point
|
||||
s32 start;
|
||||
s32 end;
|
||||
} PACK_STRUCT;
|
||||
|
||||
// attachment
|
||||
struct SHalflifeAttachment
|
||||
{
|
||||
c8 name[32];
|
||||
s32 type;
|
||||
s32 bone;
|
||||
vec3_hl org; // attachment point
|
||||
vec3_hl vectors[3];
|
||||
} PACK_STRUCT;
|
||||
|
||||
struct SHalflifeAnimOffset
|
||||
{
|
||||
u16 offset[6];
|
||||
} PACK_STRUCT;
|
||||
|
||||
// animation frames
|
||||
union SHalflifeAnimationFrame
|
||||
{
|
||||
struct {
|
||||
u8 valid;
|
||||
u8 total;
|
||||
} PACK_STRUCT num;
|
||||
s16 value;
|
||||
} PACK_STRUCT;
|
||||
|
||||
|
||||
// body part index
|
||||
struct SHalflifeBody
|
||||
{
|
||||
c8 name[64];
|
||||
u32 nummodels;
|
||||
u32 base;
|
||||
u32 modelindex; // index into models array
|
||||
} PACK_STRUCT;
|
||||
|
||||
|
||||
// skin info
|
||||
struct SHalflifeTexture
|
||||
{
|
||||
c8 name[64];
|
||||
s32 flags;
|
||||
s32 width;
|
||||
s32 height;
|
||||
s32 index;
|
||||
} PACK_STRUCT;
|
||||
|
||||
|
||||
// skin families
|
||||
// short index[skinfamilies][skinref]
|
||||
|
||||
// studio models
|
||||
struct SHalflifeModel
|
||||
{
|
||||
c8 name[64];
|
||||
s32 type;
|
||||
|
||||
f32 boundingradius;
|
||||
|
||||
u32 nummesh;
|
||||
u32 meshindex;
|
||||
|
||||
u32 numverts; // number of unique vertices
|
||||
u32 vertinfoindex; // vertex bone info
|
||||
u32 vertindex; // vertex vec3_hl
|
||||
u32 numnorms; // number of unique surface normals
|
||||
u32 norminfoindex; // normal bone info
|
||||
u32 normindex; // normal vec3_hl
|
||||
|
||||
u32 numgroups; // deformation groups
|
||||
u32 groupindex;
|
||||
} PACK_STRUCT;
|
||||
|
||||
|
||||
// meshes
|
||||
struct SHalflifeMesh
|
||||
{
|
||||
u32 numtris;
|
||||
u32 triindex;
|
||||
u32 skinref;
|
||||
u32 numnorms; // per mesh normals
|
||||
u32 normindex; // normal vec3_hl
|
||||
} PACK_STRUCT;
|
||||
|
||||
// Default alignment
|
||||
#include "irrunpack.h"
|
||||
|
||||
// lighting options
|
||||
#define STUDIO_NF_FLATSHADE 0x0001
|
||||
#define STUDIO_NF_CHROME 0x0002
|
||||
#define STUDIO_NF_FULLBRIGHT 0x0004
|
||||
|
||||
// motion flags
|
||||
#define STUDIO_X 0x0001
|
||||
#define STUDIO_Y 0x0002
|
||||
#define STUDIO_Z 0x0004
|
||||
#define STUDIO_XR 0x0008
|
||||
#define STUDIO_YR 0x0010
|
||||
#define STUDIO_ZR 0x0020
|
||||
#define STUDIO_LX 0x0040
|
||||
#define STUDIO_LY 0x0080
|
||||
#define STUDIO_LZ 0x0100
|
||||
#define STUDIO_AX 0x0200
|
||||
#define STUDIO_AY 0x0400
|
||||
#define STUDIO_AZ 0x0800
|
||||
#define STUDIO_AXR 0x1000
|
||||
#define STUDIO_AYR 0x2000
|
||||
#define STUDIO_AZR 0x4000
|
||||
#define STUDIO_TYPES 0x7FFF
|
||||
#define STUDIO_RLOOP 0x8000 // controller that wraps shortest distance
|
||||
|
||||
// sequence flags
|
||||
#define STUDIO_LOOPING 0x0001
|
||||
|
||||
// bone flags
|
||||
#define STUDIO_HAS_NORMALS 0x0001
|
||||
#define STUDIO_HAS_VERTICES 0x0002
|
||||
#define STUDIO_HAS_BBOX 0x0004
|
||||
#define STUDIO_HAS_CHROME 0x0008 // if any of the textures have chrome on them
|
||||
|
||||
#define RAD_TO_STUDIO (32768.0/M_PI)
|
||||
#define STUDIO_TO_RAD (M_PI/32768.0)
|
||||
|
||||
/*!
|
||||
Textureatlas
|
||||
Combine Source Images with arbitrary size and bithdepth to an Image with 2^n size
|
||||
borders from the source images are copied around for allowing filtering ( bilinear, mipmap )
|
||||
*/
|
||||
struct STextureAtlas
|
||||
{
|
||||
STextureAtlas ()
|
||||
{
|
||||
release();
|
||||
}
|
||||
|
||||
virtual ~STextureAtlas ()
|
||||
{
|
||||
release ();
|
||||
}
|
||||
|
||||
void release ();
|
||||
void addSource ( const c8 * name, video::IImage * image );
|
||||
void create ( u32 pixelborder, video::E_TEXTURE_CLAMP texmode );
|
||||
void getScale ( core::vector2df &scale );
|
||||
void getTranslation ( const c8 * name, core::vector2di &pos );
|
||||
|
||||
struct TextureAtlasEntry
|
||||
{
|
||||
io::path name;
|
||||
u32 width;
|
||||
u32 height;
|
||||
|
||||
core::vector2di pos;
|
||||
|
||||
video::IImage * image;
|
||||
|
||||
bool operator < ( const TextureAtlasEntry & other )
|
||||
{
|
||||
return height > other.height;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
core::array < TextureAtlasEntry > atlas;
|
||||
video::IImage * Master;
|
||||
};
|
||||
|
||||
|
||||
//! Possible types of Animation Type
|
||||
enum E_ANIMATION_TYPE
|
||||
{
|
||||
//! No Animation
|
||||
EAMT_STILL,
|
||||
//! From Start to End, then Stop ( Limited Line )
|
||||
EAMT_WAYPOINT,
|
||||
//! Linear Cycling Animation ( Sawtooth )
|
||||
EAMT_LOOPING,
|
||||
//! Linear bobbing ( Triangle )
|
||||
EAMT_PINGPONG
|
||||
};
|
||||
|
||||
//! Names for Animation Type
|
||||
const c8* const MeshAnimationTypeNames[] =
|
||||
{
|
||||
"still",
|
||||
"waypoint",
|
||||
"looping",
|
||||
"pingpong",
|
||||
0
|
||||
};
|
||||
|
||||
|
||||
//! Data for holding named Animation Info
|
||||
struct KeyFrameInterpolation
|
||||
{
|
||||
core::stringc Name; // Name of the current Animation/Bone
|
||||
E_ANIMATION_TYPE AnimationType; // Type of Animation ( looping, usw..)
|
||||
|
||||
f32 CurrentFrame; // Current Frame
|
||||
s32 NextFrame; // Frame which will be used next. For blending
|
||||
|
||||
s32 StartFrame; // Absolute Frame where the current animation start
|
||||
s32 Frames; // Relative Frames how much Frames this animation have
|
||||
s32 LoopingFrames; // How much of Frames sould be looped
|
||||
s32 EndFrame; // Absolute Frame where the current animation ends End = start + frames - 1
|
||||
|
||||
f32 FramesPerSecond; // Speed in Frames/Seconds the animation is played
|
||||
f32 RelativeSpeed; // Factor Original fps is modified
|
||||
|
||||
u32 BeginTime; // Animation started at this thime
|
||||
u32 EndTime; // Animation end at this time
|
||||
u32 LastTime; // Last Keyframe was done at this time
|
||||
|
||||
KeyFrameInterpolation ( const c8 * name = "", s32 start = 0, s32 frames = 0, s32 loopingframes = 0,
|
||||
f32 fps = 0.f, f32 relativefps = 1.f )
|
||||
: Name ( name ), AnimationType ( loopingframes ? EAMT_LOOPING : EAMT_WAYPOINT),
|
||||
CurrentFrame ( (f32) start ), NextFrame ( start ), StartFrame ( start ),
|
||||
Frames ( frames ), LoopingFrames ( loopingframes ), EndFrame ( start + frames - 1 ),
|
||||
FramesPerSecond ( fps ), RelativeSpeed ( relativefps ),
|
||||
BeginTime ( 0 ), EndTime ( 0 ), LastTime ( 0 )
|
||||
{
|
||||
}
|
||||
|
||||
// linear search
|
||||
bool operator == ( const KeyFrameInterpolation & other ) const
|
||||
{
|
||||
return Name.equals_ignore_case ( other.Name );
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
//! a List holding named Animations
|
||||
typedef core::array < KeyFrameInterpolation > IAnimationList;
|
||||
|
||||
//! a List holding named Skins
|
||||
typedef core::array < core::stringc > ISkinList;
|
||||
|
||||
|
||||
// Current Model per Body
|
||||
struct SubModel
|
||||
{
|
||||
core::stringc name;
|
||||
u32 startBuffer;
|
||||
u32 endBuffer;
|
||||
u32 state;
|
||||
};
|
||||
|
||||
struct BodyPart
|
||||
{
|
||||
core::stringc name;
|
||||
u32 defaultModel;
|
||||
core::array < SubModel > model;
|
||||
};
|
||||
//! a List holding named Models and SubModels
|
||||
typedef core::array < BodyPart > IBodyList;
|
||||
|
||||
|
||||
class CAnimatedMeshHalfLife : public IAnimatedMesh
|
||||
{
|
||||
public:
|
||||
|
||||
//! constructor
|
||||
CAnimatedMeshHalfLife();
|
||||
|
||||
//! destructor
|
||||
virtual ~CAnimatedMeshHalfLife();
|
||||
|
||||
//! loads a Halflife mdl file
|
||||
virtual bool loadModelFile( io::IReadFile* file, ISceneManager * smgr );
|
||||
|
||||
//IAnimatedMesh
|
||||
virtual u32 getFrameCount() const;
|
||||
virtual IMesh* getMesh(s32 frame, s32 detailLevel, s32 startFrameLoop, s32 endFrameLoop);
|
||||
virtual const core::aabbox3d<f32>& getBoundingBox() const;
|
||||
virtual E_ANIMATED_MESH_TYPE getMeshType() const;
|
||||
virtual void renderModel ( u32 param, video::IVideoDriver * driver, const core::matrix4 &absoluteTransformation);
|
||||
|
||||
//! returns amount of mesh buffers.
|
||||
virtual u32 getMeshBufferCount() const;
|
||||
//! returns pointer to a mesh buffer
|
||||
virtual IMeshBuffer* getMeshBuffer(u32 nr) const;
|
||||
//! Returns pointer to a mesh buffer which fits a material
|
||||
virtual IMeshBuffer* getMeshBuffer( const video::SMaterial &material) const;
|
||||
|
||||
virtual void setMaterialFlag(video::E_MATERIAL_FLAG flag, bool newvalue);
|
||||
|
||||
//! set the hardware mapping hint, for driver
|
||||
virtual void setHardwareMappingHint(E_HARDWARE_MAPPING newMappingHint, E_BUFFER_TYPE buffer=EBT_VERTEX_AND_INDEX);
|
||||
|
||||
//! flags the meshbuffer as changed, reloads hardware buffers
|
||||
virtual void setDirty(E_BUFFER_TYPE buffer=EBT_VERTEX_AND_INDEX);
|
||||
|
||||
//! set user axis aligned bounding box
|
||||
virtual void setBoundingBox(const core::aabbox3df& box);
|
||||
|
||||
//! Gets the default animation speed of the animated mesh.
|
||||
/** \return Amount of frames per second. If the amount is 0, it is a static, non animated mesh. */
|
||||
virtual f32 getAnimationSpeed() const
|
||||
{
|
||||
return FramesPerSecond;
|
||||
}
|
||||
|
||||
//! Gets the frame count of the animated mesh.
|
||||
/** \param fps Frames per second to play the animation with. If the amount is 0, it is not animated.
|
||||
The actual speed is set in the scene node the mesh is instantiated in.*/
|
||||
virtual void setAnimationSpeed(f32 fps)
|
||||
{
|
||||
FramesPerSecond=fps;
|
||||
}
|
||||
|
||||
//! Get the Animation List
|
||||
virtual IAnimationList* getAnimList () { return &AnimList; }
|
||||
|
||||
//! Return the named Body List of this Animated Mesh
|
||||
virtual IBodyList *getBodyList() { return &BodyList; }
|
||||
|
||||
private:
|
||||
|
||||
// KeyFrame Animation List
|
||||
IAnimationList AnimList;
|
||||
// Sum of all sequences
|
||||
u32 FrameCount;
|
||||
|
||||
// Named meshes of the Body
|
||||
IBodyList BodyList;
|
||||
|
||||
//! return a Mesh per frame
|
||||
SMesh* MeshIPol;
|
||||
|
||||
ISceneManager *SceneManager;
|
||||
|
||||
SHalflifeHeader *Header;
|
||||
SHalflifeHeader *TextureHeader;
|
||||
bool OwnTexModel; // do we have a modelT.mdl ?
|
||||
SHalflifeHeader *AnimationHeader[32]; // sequences named model01.mdl, model02.mdl
|
||||
|
||||
void initData ();
|
||||
SHalflifeHeader * loadModel( io::IReadFile* file, const io::path &filename );
|
||||
bool postLoadModel( const io::path &filename );
|
||||
|
||||
u32 SequenceIndex; // sequence index
|
||||
f32 CurrentFrame; // Current Frame
|
||||
f32 FramesPerSecond;
|
||||
|
||||
#define MOUTH_CONTROLLER 4
|
||||
u8 BoneController[4 + 1 ]; // bone controllers + mouth position
|
||||
u8 Blending[2]; // animation blending
|
||||
|
||||
vec4_hl BoneAdj;
|
||||
f32 SetController( s32 controllerIndex, f32 value );
|
||||
|
||||
u32 SkinGroupSelection; // skin group selection
|
||||
u32 SetSkin( u32 value );
|
||||
|
||||
void initModel();
|
||||
void dumpModelInfo(u32 level) const;
|
||||
|
||||
void ExtractBbox(s32 sequence, core::aabbox3df &box) const;
|
||||
|
||||
void setUpBones ();
|
||||
SHalflifeAnimOffset * getAnim( SHalflifeSequence *seq );
|
||||
void slerpBones( vec4_hl q1[], vec3_hl pos1[], vec4_hl q2[], vec3_hl pos2[], f32 s );
|
||||
void calcRotations ( vec3_hl *pos, vec4_hl *q, SHalflifeSequence *seq, SHalflifeAnimOffset *anim, f32 f );
|
||||
|
||||
void calcBoneAdj();
|
||||
void calcBoneQuaternion(const s32 frame, const SHalflifeBone *bone, SHalflifeAnimOffset *anim, const u32 j, f32& angle1, f32& angle2) const;
|
||||
void calcBonePosition(const s32 frame, f32 s, const SHalflifeBone *bone, SHalflifeAnimOffset *anim, f32 *pos ) const;
|
||||
|
||||
void buildVertices ();
|
||||
|
||||
io::path TextureBaseName;
|
||||
|
||||
#define HL_TEXTURE_ATLAS
|
||||
|
||||
#ifdef HL_TEXTURE_ATLAS
|
||||
STextureAtlas TextureAtlas;
|
||||
video::ITexture *TextureMaster;
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
|
||||
//! Meshloader capable of loading HalfLife Model files
|
||||
class CHalflifeMDLMeshFileLoader : public IMeshLoader
|
||||
{
|
||||
public:
|
||||
|
||||
//! Constructor
|
||||
CHalflifeMDLMeshFileLoader( scene::ISceneManager* smgr );
|
||||
|
||||
//! returns true if the file maybe is able to be loaded by this class
|
||||
/** based on the file extension (e.g. ".bsp") */
|
||||
virtual bool isALoadableFileExtension(const io::path& filename) const;
|
||||
|
||||
//! creates/loads an animated mesh from the file.
|
||||
/** \return Pointer to the created mesh. Returns 0 if loading failed.
|
||||
If you no longer need the mesh, you should call IAnimatedMesh::drop().
|
||||
See IReferenceCounted::drop() for more information.
|
||||
*/
|
||||
virtual IAnimatedMesh* createMesh(io::IReadFile* file);
|
||||
|
||||
private:
|
||||
scene::ISceneManager* SceneManager;
|
||||
};
|
||||
|
||||
|
||||
} // end namespace scene
|
||||
} // end namespace irr
|
||||
|
||||
#endif
|
||||
|
457
source/Irrlicht/CAnimatedMeshMD2.cpp
Normal file
457
source/Irrlicht/CAnimatedMeshMD2.cpp
Normal file
@ -0,0 +1,457 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#include "IrrCompileConfig.h"
|
||||
#ifdef _IRR_COMPILE_WITH_MD2_LOADER_
|
||||
|
||||
#include "CAnimatedMeshMD2.h"
|
||||
#include "SColor.h"
|
||||
#include "irrMath.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace scene
|
||||
{
|
||||
|
||||
const s32 MD2_FRAME_SHIFT = 2;
|
||||
const f32 MD2_FRAME_SHIFT_RECIPROCAL = 1.f / (1 << MD2_FRAME_SHIFT);
|
||||
|
||||
const s32 Q2_VERTEX_NORMAL_TABLE_SIZE = 162;
|
||||
|
||||
static const f32 Q2_VERTEX_NORMAL_TABLE[Q2_VERTEX_NORMAL_TABLE_SIZE][3] = {
|
||||
{-0.525731f, 0.000000f, 0.850651f},
|
||||
{-0.442863f, 0.238856f, 0.864188f},
|
||||
{-0.295242f, 0.000000f, 0.955423f},
|
||||
{-0.309017f, 0.500000f, 0.809017f},
|
||||
{-0.162460f, 0.262866f, 0.951056f},
|
||||
{0.000000f, 0.000000f, 1.000000f},
|
||||
{0.000000f, 0.850651f, 0.525731f},
|
||||
{-0.147621f, 0.716567f, 0.681718f},
|
||||
{0.147621f, 0.716567f, 0.681718f},
|
||||
{0.000000f, 0.525731f, 0.850651f},
|
||||
{0.309017f, 0.500000f, 0.809017f},
|
||||
{0.525731f, 0.000000f, 0.850651f},
|
||||
{0.295242f, 0.000000f, 0.955423f},
|
||||
{0.442863f, 0.238856f, 0.864188f},
|
||||
{0.162460f, 0.262866f, 0.951056f},
|
||||
{-0.681718f, 0.147621f, 0.716567f},
|
||||
{-0.809017f, 0.309017f, 0.500000f},
|
||||
{-0.587785f, 0.425325f, 0.688191f},
|
||||
{-0.850651f, 0.525731f, 0.000000f},
|
||||
{-0.864188f, 0.442863f, 0.238856f},
|
||||
{-0.716567f, 0.681718f, 0.147621f},
|
||||
{-0.688191f, 0.587785f, 0.425325f},
|
||||
{-0.500000f, 0.809017f, 0.309017f},
|
||||
{-0.238856f, 0.864188f, 0.442863f},
|
||||
{-0.425325f, 0.688191f, 0.587785f},
|
||||
{-0.716567f, 0.681718f, -0.147621f},
|
||||
{-0.500000f, 0.809017f, -0.309017f},
|
||||
{-0.525731f, 0.850651f, 0.000000f},
|
||||
{0.000000f, 0.850651f, -0.525731f},
|
||||
{-0.238856f, 0.864188f, -0.442863f},
|
||||
{0.000000f, 0.955423f, -0.295242f},
|
||||
{-0.262866f, 0.951056f, -0.162460f},
|
||||
{0.000000f, 1.000000f, 0.000000f},
|
||||
{0.000000f, 0.955423f, 0.295242f},
|
||||
{-0.262866f, 0.951056f, 0.162460f},
|
||||
{0.238856f, 0.864188f, 0.442863f},
|
||||
{0.262866f, 0.951056f, 0.162460f},
|
||||
{0.500000f, 0.809017f, 0.309017f},
|
||||
{0.238856f, 0.864188f, -0.442863f},
|
||||
{0.262866f, 0.951056f, -0.162460f},
|
||||
{0.500000f, 0.809017f, -0.309017f},
|
||||
{0.850651f, 0.525731f, 0.000000f},
|
||||
{0.716567f, 0.681718f, 0.147621f},
|
||||
{0.716567f, 0.681718f, -0.147621f},
|
||||
{0.525731f, 0.850651f, 0.000000f},
|
||||
{0.425325f, 0.688191f, 0.587785f},
|
||||
{0.864188f, 0.442863f, 0.238856f},
|
||||
{0.688191f, 0.587785f, 0.425325f},
|
||||
{0.809017f, 0.309017f, 0.500000f},
|
||||
{0.681718f, 0.147621f, 0.716567f},
|
||||
{0.587785f, 0.425325f, 0.688191f},
|
||||
{0.955423f, 0.295242f, 0.000000f},
|
||||
{1.000000f, 0.000000f, 0.000000f},
|
||||
{0.951056f, 0.162460f, 0.262866f},
|
||||
{0.850651f, -0.525731f, 0.000000f},
|
||||
{0.955423f, -0.295242f, 0.000000f},
|
||||
{0.864188f, -0.442863f, 0.238856f},
|
||||
{0.951056f, -0.162460f, 0.262866f},
|
||||
{0.809017f, -0.309017f, 0.500000f},
|
||||
{0.681718f, -0.147621f, 0.716567f},
|
||||
{0.850651f, 0.000000f, 0.525731f},
|
||||
{0.864188f, 0.442863f, -0.238856f},
|
||||
{0.809017f, 0.309017f, -0.500000f},
|
||||
{0.951056f, 0.162460f, -0.262866f},
|
||||
{0.525731f, 0.000000f, -0.850651f},
|
||||
{0.681718f, 0.147621f, -0.716567f},
|
||||
{0.681718f, -0.147621f, -0.716567f},
|
||||
{0.850651f, 0.000000f, -0.525731f},
|
||||
{0.809017f, -0.309017f, -0.500000f},
|
||||
{0.864188f, -0.442863f, -0.238856f},
|
||||
{0.951056f, -0.162460f, -0.262866f},
|
||||
{0.147621f, 0.716567f, -0.681718f},
|
||||
{0.309017f, 0.500000f, -0.809017f},
|
||||
{0.425325f, 0.688191f, -0.587785f},
|
||||
{0.442863f, 0.238856f, -0.864188f},
|
||||
{0.587785f, 0.425325f, -0.688191f},
|
||||
{0.688191f, 0.587785f, -0.425325f},
|
||||
{-0.147621f, 0.716567f, -0.681718f},
|
||||
{-0.309017f, 0.500000f, -0.809017f},
|
||||
{0.000000f, 0.525731f, -0.850651f},
|
||||
{-0.525731f, 0.000000f, -0.850651f},
|
||||
{-0.442863f, 0.238856f, -0.864188f},
|
||||
{-0.295242f, 0.000000f, -0.955423f},
|
||||
{-0.162460f, 0.262866f, -0.951056f},
|
||||
{0.000000f, 0.000000f, -1.000000f},
|
||||
{0.295242f, 0.000000f, -0.955423f},
|
||||
{0.162460f, 0.262866f, -0.951056f},
|
||||
{-0.442863f, -0.238856f, -0.864188f},
|
||||
{-0.309017f, -0.500000f, -0.809017f},
|
||||
{-0.162460f, -0.262866f, -0.951056f},
|
||||
{0.000000f, -0.850651f, -0.525731f},
|
||||
{-0.147621f, -0.716567f, -0.681718f},
|
||||
{0.147621f, -0.716567f, -0.681718f},
|
||||
{0.000000f, -0.525731f, -0.850651f},
|
||||
{0.309017f, -0.500000f, -0.809017f},
|
||||
{0.442863f, -0.238856f, -0.864188f},
|
||||
{0.162460f, -0.262866f, -0.951056f},
|
||||
{0.238856f, -0.864188f, -0.442863f},
|
||||
{0.500000f, -0.809017f, -0.309017f},
|
||||
{0.425325f, -0.688191f, -0.587785f},
|
||||
{0.716567f, -0.681718f, -0.147621f},
|
||||
{0.688191f, -0.587785f, -0.425325f},
|
||||
{0.587785f, -0.425325f, -0.688191f},
|
||||
{0.000000f, -0.955423f, -0.295242f},
|
||||
{0.000000f, -1.000000f, 0.000000f},
|
||||
{0.262866f, -0.951056f, -0.162460f},
|
||||
{0.000000f, -0.850651f, 0.525731f},
|
||||
{0.000000f, -0.955423f, 0.295242f},
|
||||
{0.238856f, -0.864188f, 0.442863f},
|
||||
{0.262866f, -0.951056f, 0.162460f},
|
||||
{0.500000f, -0.809017f, 0.309017f},
|
||||
{0.716567f, -0.681718f, 0.147621f},
|
||||
{0.525731f, -0.850651f, 0.000000f},
|
||||
{-0.238856f, -0.864188f, -0.442863f},
|
||||
{-0.500000f, -0.809017f, -0.309017f},
|
||||
{-0.262866f, -0.951056f, -0.162460f},
|
||||
{-0.850651f, -0.525731f, 0.000000f},
|
||||
{-0.716567f, -0.681718f, -0.147621f},
|
||||
{-0.716567f, -0.681718f, 0.147621f},
|
||||
{-0.525731f, -0.850651f, 0.000000f},
|
||||
{-0.500000f, -0.809017f, 0.309017f},
|
||||
{-0.238856f, -0.864188f, 0.442863f},
|
||||
{-0.262866f, -0.951056f, 0.162460f},
|
||||
{-0.864188f, -0.442863f, 0.238856f},
|
||||
{-0.809017f, -0.309017f, 0.500000f},
|
||||
{-0.688191f, -0.587785f, 0.425325f},
|
||||
{-0.681718f, -0.147621f, 0.716567f},
|
||||
{-0.442863f, -0.238856f, 0.864188f},
|
||||
{-0.587785f, -0.425325f, 0.688191f},
|
||||
{-0.309017f, -0.500000f, 0.809017f},
|
||||
{-0.147621f, -0.716567f, 0.681718f},
|
||||
{-0.425325f, -0.688191f, 0.587785f},
|
||||
{-0.162460f, -0.262866f, 0.951056f},
|
||||
{0.442863f, -0.238856f, 0.864188f},
|
||||
{0.162460f, -0.262866f, 0.951056f},
|
||||
{0.309017f, -0.500000f, 0.809017f},
|
||||
{0.147621f, -0.716567f, 0.681718f},
|
||||
{0.000000f, -0.525731f, 0.850651f},
|
||||
{0.425325f, -0.688191f, 0.587785f},
|
||||
{0.587785f, -0.425325f, 0.688191f},
|
||||
{0.688191f, -0.587785f, 0.425325f},
|
||||
{-0.955423f, 0.295242f, 0.000000f},
|
||||
{-0.951056f, 0.162460f, 0.262866f},
|
||||
{-1.000000f, 0.000000f, 0.000000f},
|
||||
{-0.850651f, 0.000000f, 0.525731f},
|
||||
{-0.955423f, -0.295242f, 0.000000f},
|
||||
{-0.951056f, -0.162460f, 0.262866f},
|
||||
{-0.864188f, 0.442863f, -0.238856f},
|
||||
{-0.951056f, 0.162460f, -0.262866f},
|
||||
{-0.809017f, 0.309017f, -0.500000f},
|
||||
{-0.864188f, -0.442863f, -0.238856f},
|
||||
{-0.951056f, -0.162460f, -0.262866f},
|
||||
{-0.809017f, -0.309017f, -0.500000f},
|
||||
{-0.681718f, 0.147621f, -0.716567f},
|
||||
{-0.681718f, -0.147621f, -0.716567f},
|
||||
{-0.850651f, 0.000000f, -0.525731f},
|
||||
{-0.688191f, 0.587785f, -0.425325f},
|
||||
{-0.587785f, 0.425325f, -0.688191f},
|
||||
{-0.425325f, 0.688191f, -0.587785f},
|
||||
{-0.425325f, -0.688191f, -0.587785f},
|
||||
{-0.587785f, -0.425325f, -0.688191f},
|
||||
{-0.688191f, -0.587785f, -0.425325f},
|
||||
};
|
||||
|
||||
struct SMD2AnimationType
|
||||
{
|
||||
s32 begin;
|
||||
s32 end;
|
||||
s32 fps;
|
||||
};
|
||||
|
||||
static const SMD2AnimationType MD2AnimationTypeList[21] =
|
||||
{
|
||||
{ 0, 39, 9}, // STAND
|
||||
{ 40, 45, 10}, // RUN
|
||||
{ 46, 53, 10}, // ATTACK
|
||||
{ 54, 57, 7}, // PAIN_A
|
||||
{ 58, 61, 7}, // PAIN_B
|
||||
{ 62, 65, 7}, // PAIN_C
|
||||
{ 66, 71, 7}, // JUMP
|
||||
{ 72, 83, 7}, // FLIP
|
||||
{ 84, 94, 7}, // SALUTE
|
||||
{ 95, 111, 10}, // FALLBACK
|
||||
{112, 122, 7}, // WAVE
|
||||
{123, 134, 6}, // POINT
|
||||
{135, 153, 10}, // CROUCH_STAND
|
||||
{154, 159, 7}, // CROUCH_WALK
|
||||
{160, 168, 10}, // CROUCH_ATTACK
|
||||
{169, 172, 7}, // CROUCH_PAIN
|
||||
{173, 177, 5}, // CROUCH_DEATH
|
||||
{178, 183, 7}, // DEATH_FALLBACK
|
||||
{184, 189, 7}, // DEATH_FALLFORWARD
|
||||
{190, 197, 7}, // DEATH_FALLBACKSLOW
|
||||
{198, 198, 5}, // BOOM
|
||||
};
|
||||
|
||||
|
||||
//! constructor
|
||||
CAnimatedMeshMD2::CAnimatedMeshMD2()
|
||||
: InterpolationBuffer(0), FrameList(0), FrameCount(0), FramesPerSecond((f32)(MD2AnimationTypeList[0].fps << MD2_FRAME_SHIFT))
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
IAnimatedMesh::setDebugName("CAnimatedMeshMD2 IAnimatedMesh");
|
||||
IMesh::setDebugName("CAnimatedMeshMD2 IMesh");
|
||||
#endif
|
||||
InterpolationBuffer = new SMeshBuffer;
|
||||
}
|
||||
|
||||
|
||||
//! destructor
|
||||
CAnimatedMeshMD2::~CAnimatedMeshMD2()
|
||||
{
|
||||
delete [] FrameList;
|
||||
if (InterpolationBuffer)
|
||||
InterpolationBuffer->drop();
|
||||
}
|
||||
|
||||
|
||||
//! returns the amount of frames in milliseconds. If the amount is 1, it is a static (=non animated) mesh.
|
||||
u32 CAnimatedMeshMD2::getFrameCount() const
|
||||
{
|
||||
return FrameCount<<MD2_FRAME_SHIFT;
|
||||
}
|
||||
|
||||
|
||||
//! returns the animated mesh based on a detail level. 0 is the lowest, 255 the highest detail. Note, that some Meshes will ignore the detail level.
|
||||
IMesh* CAnimatedMeshMD2::getMesh(s32 frame, s32 detailLevel, s32 startFrameLoop, s32 endFrameLoop)
|
||||
{
|
||||
if ((u32)frame > getFrameCount())
|
||||
frame = (frame % getFrameCount());
|
||||
|
||||
if (startFrameLoop == -1 && endFrameLoop == -1)
|
||||
{
|
||||
startFrameLoop = 0;
|
||||
endFrameLoop = getFrameCount();
|
||||
}
|
||||
|
||||
updateInterpolationBuffer(frame, startFrameLoop, endFrameLoop);
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
//! returns amount of mesh buffers. MD2 meshes only have one buffer
|
||||
u32 CAnimatedMeshMD2::getMeshBufferCount() const
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
//! returns pointer to a mesh buffer
|
||||
IMeshBuffer* CAnimatedMeshMD2::getMeshBuffer(u32 nr) const
|
||||
{
|
||||
if (nr == 0)
|
||||
return InterpolationBuffer;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
//! Returns pointer to a mesh buffer which fits a material
|
||||
IMeshBuffer* CAnimatedMeshMD2::getMeshBuffer(const video::SMaterial &material) const
|
||||
{
|
||||
if (InterpolationBuffer->Material == material)
|
||||
return InterpolationBuffer;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// updates the interpolation buffer
|
||||
void CAnimatedMeshMD2::updateInterpolationBuffer(s32 frame, s32 startFrameLoop, s32 endFrameLoop)
|
||||
{
|
||||
u32 firstFrame, secondFrame;
|
||||
f32 div;
|
||||
|
||||
// TA: resolve missing ipol in loop between end-start
|
||||
|
||||
if (endFrameLoop - startFrameLoop == 0)
|
||||
{
|
||||
firstFrame = frame>>MD2_FRAME_SHIFT;
|
||||
secondFrame = frame>>MD2_FRAME_SHIFT;
|
||||
div = 1.0f;
|
||||
}
|
||||
else
|
||||
{
|
||||
// key frames
|
||||
u32 s = startFrameLoop >> MD2_FRAME_SHIFT;
|
||||
u32 e = endFrameLoop >> MD2_FRAME_SHIFT;
|
||||
|
||||
firstFrame = frame >> MD2_FRAME_SHIFT;
|
||||
secondFrame = core::if_c_a_else_b(firstFrame + 1 > e, s, firstFrame + 1);
|
||||
|
||||
firstFrame = core::s32_min(FrameCount - 1, firstFrame);
|
||||
secondFrame = core::s32_min(FrameCount - 1, secondFrame);
|
||||
|
||||
//div = (frame % (1<<MD2_FRAME_SHIFT)) / (f32)(1<<MD2_FRAME_SHIFT);
|
||||
frame &= (1<<MD2_FRAME_SHIFT) - 1;
|
||||
div = frame * MD2_FRAME_SHIFT_RECIPROCAL;
|
||||
}
|
||||
|
||||
video::S3DVertex* target = static_cast<video::S3DVertex*>(InterpolationBuffer->getVertices());
|
||||
SMD2Vert* first = FrameList[firstFrame].pointer();
|
||||
SMD2Vert* second = FrameList[secondFrame].pointer();
|
||||
|
||||
// interpolate both frames
|
||||
const u32 count = FrameList[firstFrame].size();
|
||||
for (u32 i=0; i<count; ++i)
|
||||
{
|
||||
const core::vector3df one = core::vector3df(f32(first->Pos.X) * FrameTransforms[firstFrame].scale.X + FrameTransforms[firstFrame].translate.X,
|
||||
f32(first->Pos.Y) * FrameTransforms[firstFrame].scale.Y + FrameTransforms[firstFrame].translate.Y,
|
||||
f32(first->Pos.Z) * FrameTransforms[firstFrame].scale.Z + FrameTransforms[firstFrame].translate.Z);
|
||||
const core::vector3df two = core::vector3df(f32(second->Pos.X) * FrameTransforms[secondFrame].scale.X + FrameTransforms[secondFrame].translate.X,
|
||||
f32(second->Pos.Y) * FrameTransforms[secondFrame].scale.Y + FrameTransforms[secondFrame].translate.Y,
|
||||
f32(second->Pos.Z) * FrameTransforms[secondFrame].scale.Z + FrameTransforms[secondFrame].translate.Z);
|
||||
target->Pos = two.getInterpolated(one, div);
|
||||
const core::vector3df n1(
|
||||
Q2_VERTEX_NORMAL_TABLE[first->NormalIdx][0],
|
||||
Q2_VERTEX_NORMAL_TABLE[first->NormalIdx][2],
|
||||
Q2_VERTEX_NORMAL_TABLE[first->NormalIdx][1]);
|
||||
const core::vector3df n2(
|
||||
Q2_VERTEX_NORMAL_TABLE[second->NormalIdx][0],
|
||||
Q2_VERTEX_NORMAL_TABLE[second->NormalIdx][2],
|
||||
Q2_VERTEX_NORMAL_TABLE[second->NormalIdx][1]);
|
||||
target->Normal = n2.getInterpolated(n1, div);
|
||||
++target;
|
||||
++first;
|
||||
++second;
|
||||
}
|
||||
|
||||
//update bounding box
|
||||
InterpolationBuffer->setBoundingBox(BoxList[secondFrame].getInterpolated(BoxList[firstFrame], div));
|
||||
InterpolationBuffer->setDirty();
|
||||
}
|
||||
|
||||
|
||||
//! sets a flag of all contained materials to a new value
|
||||
void CAnimatedMeshMD2::setMaterialFlag(video::E_MATERIAL_FLAG flag, bool newvalue)
|
||||
{
|
||||
InterpolationBuffer->Material.setFlag(flag, newvalue);
|
||||
}
|
||||
|
||||
|
||||
//! set the hardware mapping hint, for driver
|
||||
void CAnimatedMeshMD2::setHardwareMappingHint(E_HARDWARE_MAPPING newMappingHint,
|
||||
E_BUFFER_TYPE buffer)
|
||||
{
|
||||
InterpolationBuffer->setHardwareMappingHint(newMappingHint, buffer);
|
||||
}
|
||||
|
||||
|
||||
//! flags the meshbuffer as changed, reloads hardware buffers
|
||||
void CAnimatedMeshMD2::setDirty(E_BUFFER_TYPE buffer)
|
||||
{
|
||||
InterpolationBuffer->setDirty(buffer);
|
||||
}
|
||||
|
||||
|
||||
//! returns an axis aligned bounding box
|
||||
const core::aabbox3d<f32>& CAnimatedMeshMD2::getBoundingBox() const
|
||||
{
|
||||
return InterpolationBuffer->BoundingBox;
|
||||
}
|
||||
|
||||
|
||||
//! set user axis aligned bounding box
|
||||
void CAnimatedMeshMD2::setBoundingBox(const core::aabbox3df& box)
|
||||
{
|
||||
InterpolationBuffer->BoundingBox = box;
|
||||
}
|
||||
|
||||
|
||||
//! Returns the type of the animated mesh.
|
||||
E_ANIMATED_MESH_TYPE CAnimatedMeshMD2::getMeshType() const
|
||||
{
|
||||
return EAMT_MD2;
|
||||
}
|
||||
|
||||
|
||||
//! Returns frame loop data for a special MD2 animation type.
|
||||
void CAnimatedMeshMD2::getFrameLoop(EMD2_ANIMATION_TYPE l,
|
||||
s32& outBegin, s32& outEnd, s32& outFPS) const
|
||||
{
|
||||
if (l < 0 || l >= EMAT_COUNT)
|
||||
return;
|
||||
|
||||
outBegin = MD2AnimationTypeList[l].begin << MD2_FRAME_SHIFT;
|
||||
outEnd = MD2AnimationTypeList[l].end << MD2_FRAME_SHIFT;
|
||||
|
||||
// correct to anim between last->first frame
|
||||
outEnd += MD2_FRAME_SHIFT == 0 ? 1 : (1 << MD2_FRAME_SHIFT) - 1;
|
||||
outFPS = MD2AnimationTypeList[l].fps << MD2_FRAME_SHIFT;
|
||||
}
|
||||
|
||||
|
||||
//! Returns frame loop data for a special MD2 animation type.
|
||||
bool CAnimatedMeshMD2::getFrameLoop(const c8* name,
|
||||
s32& outBegin, s32&outEnd, s32& outFPS) const
|
||||
{
|
||||
for (u32 i=0; i < AnimationData.size(); ++i)
|
||||
{
|
||||
if (AnimationData[i].name == name)
|
||||
{
|
||||
outBegin = AnimationData[i].begin << MD2_FRAME_SHIFT;
|
||||
outEnd = AnimationData[i].end << MD2_FRAME_SHIFT;
|
||||
outEnd += MD2_FRAME_SHIFT == 0 ? 1 : (1 << MD2_FRAME_SHIFT) - 1;
|
||||
outFPS = AnimationData[i].fps << MD2_FRAME_SHIFT;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
//! Returns amount of md2 animations in this file.
|
||||
s32 CAnimatedMeshMD2::getAnimationCount() const
|
||||
{
|
||||
return AnimationData.size();
|
||||
}
|
||||
|
||||
|
||||
//! Returns name of md2 animation.
|
||||
const c8* CAnimatedMeshMD2::getAnimationName(s32 nr) const
|
||||
{
|
||||
if ((u32)nr >= AnimationData.size())
|
||||
return 0;
|
||||
|
||||
return AnimationData[nr].name.c_str();
|
||||
}
|
||||
|
||||
|
||||
} // end namespace scene
|
||||
} // end namespace irr
|
||||
|
||||
#endif // _IRR_COMPILE_WITH_MD2_LOADER_
|
154
source/Irrlicht/CAnimatedMeshMD2.h
Normal file
154
source/Irrlicht/CAnimatedMeshMD2.h
Normal file
@ -0,0 +1,154 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#ifndef __C_ANIMATED_MESH_MD2_H_INCLUDED__
|
||||
#define __C_ANIMATED_MESH_MD2_H_INCLUDED__
|
||||
|
||||
#include "IAnimatedMeshMD2.h"
|
||||
#include "IMesh.h"
|
||||
#include "CMeshBuffer.h"
|
||||
#include "IReadFile.h"
|
||||
#include "S3DVertex.h"
|
||||
#include "irrArray.h"
|
||||
#include "irrString.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace scene
|
||||
{
|
||||
|
||||
class CAnimatedMeshMD2 : public IAnimatedMeshMD2
|
||||
{
|
||||
public:
|
||||
|
||||
//! constructor
|
||||
CAnimatedMeshMD2();
|
||||
|
||||
//! destructor
|
||||
virtual ~CAnimatedMeshMD2();
|
||||
|
||||
//! returns the amount of frames. If the amount is 1, it is a static (=non animated) mesh.
|
||||
virtual u32 getFrameCount() const;
|
||||
|
||||
//! Gets the default animation speed of the animated mesh.
|
||||
/** \return Amount of frames per second. If the amount is 0, it is a static, non animated mesh. */
|
||||
virtual f32 getAnimationSpeed() const
|
||||
{
|
||||
return FramesPerSecond;
|
||||
}
|
||||
|
||||
//! Gets the frame count of the animated mesh.
|
||||
/** \param fps Frames per second to play the animation with. If the amount is 0, it is not animated.
|
||||
The actual speed is set in the scene node the mesh is instantiated in.*/
|
||||
virtual void setAnimationSpeed(f32 fps)
|
||||
{
|
||||
FramesPerSecond=fps;
|
||||
}
|
||||
|
||||
//! returns the animated mesh based on a detail level. 0 is the lowest, 255 the highest detail. Note, that some Meshes will ignore the detail level.
|
||||
virtual IMesh* getMesh(s32 frame, s32 detailLevel=255, s32 startFrameLoop=-1, s32 endFrameLoop=-1);
|
||||
|
||||
//! returns amount of mesh buffers.
|
||||
virtual u32 getMeshBufferCount() const;
|
||||
|
||||
//! returns pointer to a mesh buffer
|
||||
virtual IMeshBuffer* getMeshBuffer(u32 nr) const;
|
||||
|
||||
//! Returns pointer to a mesh buffer which fits a material
|
||||
/** \param material: material to search for
|
||||
\return Returns the pointer to the mesh buffer or
|
||||
NULL if there is no such mesh buffer. */
|
||||
virtual IMeshBuffer* getMeshBuffer( const video::SMaterial &material) const;
|
||||
|
||||
//! returns an axis aligned bounding box
|
||||
virtual const core::aabbox3d<f32>& getBoundingBox() const;
|
||||
|
||||
//! set user axis aligned bounding box
|
||||
virtual void setBoundingBox( const core::aabbox3df& box);
|
||||
|
||||
//! sets a flag of all contained materials to a new value
|
||||
virtual void setMaterialFlag(video::E_MATERIAL_FLAG flag, bool newvalue);
|
||||
|
||||
//! set the hardware mapping hint, for driver
|
||||
virtual void setHardwareMappingHint(E_HARDWARE_MAPPING newMappingHint, E_BUFFER_TYPE buffer=EBT_VERTEX_AND_INDEX);
|
||||
|
||||
//! flags the meshbuffer as changed, reloads hardware buffers
|
||||
virtual void setDirty(E_BUFFER_TYPE buffer=EBT_VERTEX_AND_INDEX);
|
||||
|
||||
//! Returns the type of the animated mesh.
|
||||
virtual E_ANIMATED_MESH_TYPE getMeshType() const;
|
||||
|
||||
//! Returns frame loop data for a special MD2 animation type.
|
||||
virtual void getFrameLoop(EMD2_ANIMATION_TYPE,
|
||||
s32& outBegin, s32& outEnd, s32& outFps) const;
|
||||
|
||||
//! Returns frame loop data for a special MD2 animation type.
|
||||
virtual bool getFrameLoop(const c8* name,
|
||||
s32& outBegin, s32& outEnd, s32& outFps) const;
|
||||
|
||||
//! Returns amount of md2 animations in this file.
|
||||
virtual s32 getAnimationCount() const;
|
||||
|
||||
//! Returns name of md2 animation.
|
||||
//! \param nr: Zero based index of animation.
|
||||
virtual const c8* getAnimationName(s32 nr) const;
|
||||
|
||||
|
||||
//
|
||||
// exposed for loader
|
||||
//
|
||||
|
||||
//! the buffer that contains the most recent animation
|
||||
SMeshBuffer* InterpolationBuffer;
|
||||
|
||||
//! named animations
|
||||
struct SAnimationData
|
||||
{
|
||||
core::stringc name;
|
||||
s32 begin;
|
||||
s32 end;
|
||||
s32 fps;
|
||||
};
|
||||
|
||||
//! scale and translations for keyframes
|
||||
struct SKeyFrameTransform
|
||||
{
|
||||
core::vector3df scale;
|
||||
core::vector3df translate;
|
||||
};
|
||||
|
||||
//! md2 vertex data
|
||||
struct SMD2Vert
|
||||
{
|
||||
core::vector3d<u8> Pos;
|
||||
u8 NormalIdx;
|
||||
};
|
||||
|
||||
//! keyframe transformations
|
||||
core::array<SKeyFrameTransform> FrameTransforms;
|
||||
|
||||
//! keyframe vertex data
|
||||
core::array<SMD2Vert> *FrameList;
|
||||
|
||||
//! bounding boxes for each keyframe
|
||||
core::array<core::aabbox3d<f32> > BoxList;
|
||||
|
||||
//! named animations
|
||||
core::array< SAnimationData > AnimationData;
|
||||
|
||||
u32 FrameCount;
|
||||
|
||||
private:
|
||||
|
||||
//! updates the interpolation buffer
|
||||
void updateInterpolationBuffer(s32 frame, s32 startFrame, s32 endFrame);
|
||||
|
||||
f32 FramesPerSecond;
|
||||
};
|
||||
|
||||
} // end namespace scene
|
||||
} // end namespace irr
|
||||
|
||||
#endif
|
||||
|
468
source/Irrlicht/CAnimatedMeshMD3.cpp
Normal file
468
source/Irrlicht/CAnimatedMeshMD3.cpp
Normal file
@ -0,0 +1,468 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt / Fabio Concas / Thomas Alten
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#include "IrrCompileConfig.h"
|
||||
#ifdef _IRR_COMPILE_WITH_MD3_LOADER_
|
||||
|
||||
#include "CAnimatedMeshMD3.h"
|
||||
#include "os.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace scene
|
||||
{
|
||||
|
||||
|
||||
// byte-align structures
|
||||
#include "irrpack.h"
|
||||
|
||||
//! General properties of a single animation frame.
|
||||
struct SMD3Frame
|
||||
{
|
||||
f32 mins[3]; // bounding box per frame
|
||||
f32 maxs[3];
|
||||
f32 position[3]; // position of bounding box
|
||||
f32 radius; // radius of bounding sphere
|
||||
c8 creator[16]; // name of frame
|
||||
} PACK_STRUCT;
|
||||
|
||||
|
||||
//! An attachment point for another MD3 model.
|
||||
struct SMD3Tag
|
||||
{
|
||||
c8 Name[64]; //name of 'tag' as it's usually called in the md3 files try to see it as a sub-mesh/seperate mesh-part.
|
||||
f32 position[3]; //relative position of tag
|
||||
f32 rotationMatrix[9]; //3x3 rotation direction of tag
|
||||
} PACK_STRUCT;
|
||||
|
||||
//!Shader
|
||||
struct SMD3Shader
|
||||
{
|
||||
c8 name[64]; // name of shader
|
||||
s32 shaderIndex;
|
||||
} PACK_STRUCT;
|
||||
|
||||
// Default alignment
|
||||
#include "irrunpack.h"
|
||||
|
||||
|
||||
//! Constructor
|
||||
CAnimatedMeshMD3::CAnimatedMeshMD3()
|
||||
:Mesh(0), IPolShift(0), LoopMode(0), Scaling(1.f)//, FramesPerSecond(25.f)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
setDebugName("CAnimatedMeshMD3");
|
||||
#endif
|
||||
|
||||
Mesh = new SMD3Mesh();
|
||||
MeshIPol = new SMesh();
|
||||
setInterpolationShift(0, 0);
|
||||
}
|
||||
|
||||
|
||||
//! Destructor
|
||||
CAnimatedMeshMD3::~CAnimatedMeshMD3()
|
||||
{
|
||||
if (Mesh)
|
||||
Mesh->drop();
|
||||
if (MeshIPol)
|
||||
MeshIPol->drop();
|
||||
}
|
||||
|
||||
|
||||
//! Returns the amount of frames in milliseconds. If the amount is 1, it is a static (=non animated) mesh.
|
||||
u32 CAnimatedMeshMD3::getFrameCount() const
|
||||
{
|
||||
return Mesh->MD3Header.numFrames << IPolShift;
|
||||
}
|
||||
|
||||
|
||||
//! Rendering Hint
|
||||
void CAnimatedMeshMD3::setInterpolationShift(u32 shift, u32 loopMode)
|
||||
{
|
||||
IPolShift = shift;
|
||||
LoopMode = loopMode;
|
||||
}
|
||||
|
||||
|
||||
//! returns amount of mesh buffers.
|
||||
u32 CAnimatedMeshMD3::getMeshBufferCount() const
|
||||
{
|
||||
return MeshIPol->getMeshBufferCount();
|
||||
}
|
||||
|
||||
|
||||
//! returns pointer to a mesh buffer
|
||||
IMeshBuffer* CAnimatedMeshMD3::getMeshBuffer(u32 nr) const
|
||||
{
|
||||
return MeshIPol->getMeshBuffer(nr);
|
||||
}
|
||||
|
||||
|
||||
//! Returns pointer to a mesh buffer which fits a material
|
||||
IMeshBuffer* CAnimatedMeshMD3::getMeshBuffer(const video::SMaterial &material) const
|
||||
{
|
||||
return MeshIPol->getMeshBuffer(material);
|
||||
}
|
||||
|
||||
|
||||
void CAnimatedMeshMD3::setMaterialFlag(video::E_MATERIAL_FLAG flag, bool newvalue)
|
||||
{
|
||||
MeshIPol->setMaterialFlag(flag, newvalue);
|
||||
}
|
||||
|
||||
|
||||
//! set the hardware mapping hint, for driver
|
||||
void CAnimatedMeshMD3::setHardwareMappingHint(E_HARDWARE_MAPPING newMappingHint,
|
||||
E_BUFFER_TYPE buffer)
|
||||
{
|
||||
MeshIPol->setHardwareMappingHint(newMappingHint, buffer);
|
||||
}
|
||||
|
||||
|
||||
//! flags the meshbuffer as changed, reloads hardware buffers
|
||||
void CAnimatedMeshMD3::setDirty(E_BUFFER_TYPE buffer)
|
||||
{
|
||||
MeshIPol->setDirty(buffer);
|
||||
}
|
||||
|
||||
|
||||
//! set user axis aligned bounding box
|
||||
void CAnimatedMeshMD3::setBoundingBox(const core::aabbox3df& box)
|
||||
{
|
||||
MeshIPol->setBoundingBox(box);
|
||||
}
|
||||
|
||||
|
||||
//! Returns the animated tag list based on a detail level. 0 is the lowest, 255 the highest detail.
|
||||
SMD3QuaternionTagList *CAnimatedMeshMD3::getTagList(s32 frame, s32 detailLevel, s32 startFrameLoop, s32 endFrameLoop)
|
||||
{
|
||||
if (0 == Mesh)
|
||||
return 0;
|
||||
|
||||
getMesh(frame, detailLevel, startFrameLoop, endFrameLoop);
|
||||
return &TagListIPol;
|
||||
}
|
||||
|
||||
|
||||
//! Returns the animated mesh based on a detail level. 0 is the lowest, 255 the highest detail.
|
||||
IMesh* CAnimatedMeshMD3::getMesh(s32 frame, s32 detailLevel, s32 startFrameLoop, s32 endFrameLoop)
|
||||
{
|
||||
if (0 == Mesh)
|
||||
return 0;
|
||||
|
||||
//! check if we have the mesh in our private cache
|
||||
SCacheInfo candidate(frame, startFrameLoop, endFrameLoop);
|
||||
if (candidate == Current)
|
||||
return MeshIPol;
|
||||
|
||||
startFrameLoop = core::s32_max(0, startFrameLoop >> IPolShift);
|
||||
endFrameLoop = core::if_c_a_else_b(endFrameLoop < 0, Mesh->MD3Header.numFrames - 1, endFrameLoop >> IPolShift);
|
||||
|
||||
const u32 mask = 1 << IPolShift;
|
||||
|
||||
s32 frameA;
|
||||
s32 frameB;
|
||||
f32 iPol;
|
||||
|
||||
if (LoopMode)
|
||||
{
|
||||
// correct frame to "pixel center"
|
||||
frame -= mask >> 1;
|
||||
|
||||
// interpolation
|
||||
iPol = f32(frame & (mask - 1)) * core::reciprocal(f32(mask));
|
||||
|
||||
// wrap anim
|
||||
frame >>= IPolShift;
|
||||
frameA = core::if_c_a_else_b(frame < startFrameLoop, endFrameLoop, frame);
|
||||
frameB = core::if_c_a_else_b(frameA + 1 > endFrameLoop, startFrameLoop, frameA + 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
// correct frame to "pixel center"
|
||||
frame -= mask >> 1;
|
||||
|
||||
iPol = f32(frame & (mask - 1)) * core::reciprocal(f32(mask));
|
||||
|
||||
// clamp anim
|
||||
frame >>= IPolShift;
|
||||
frameA = core::s32_clamp(frame, startFrameLoop, endFrameLoop);
|
||||
frameB = core::s32_min(frameA + 1, endFrameLoop);
|
||||
}
|
||||
|
||||
// build current vertex
|
||||
for (u32 i = 0; i!= Mesh->Buffer.size(); ++i)
|
||||
{
|
||||
buildVertexArray(frameA, frameB, iPol,
|
||||
Mesh->Buffer[i],
|
||||
(SMeshBufferLightMap*) MeshIPol->getMeshBuffer(i));
|
||||
}
|
||||
MeshIPol->recalculateBoundingBox();
|
||||
|
||||
// build current tags
|
||||
buildTagArray(frameA, frameB, iPol);
|
||||
|
||||
Current = candidate;
|
||||
return MeshIPol;
|
||||
}
|
||||
|
||||
|
||||
//! create a Irrlicht MeshBuffer for a MD3 MeshBuffer
|
||||
IMeshBuffer * CAnimatedMeshMD3::createMeshBuffer(const SMD3MeshBuffer* source,
|
||||
io::IFileSystem* fs, video::IVideoDriver * driver)
|
||||
{
|
||||
SMeshBufferLightMap * dest = new SMeshBufferLightMap();
|
||||
dest->Vertices.set_used(source->MeshHeader.numVertices);
|
||||
dest->Indices.set_used(source->Indices.size());
|
||||
|
||||
u32 i;
|
||||
|
||||
// fill in static face info
|
||||
for (i = 0; i < source->Indices.size(); i += 3)
|
||||
{
|
||||
dest->Indices[i + 0] = (u16) source->Indices[i + 0];
|
||||
dest->Indices[i + 1] = (u16) source->Indices[i + 1];
|
||||
dest->Indices[i + 2] = (u16) source->Indices[i + 2];
|
||||
}
|
||||
|
||||
// fill in static vertex info
|
||||
for (i = 0; i!= (u32)source->MeshHeader.numVertices; ++i)
|
||||
{
|
||||
video::S3DVertex2TCoords &v = dest->Vertices[i];
|
||||
v.Color = 0xFFFFFFFF;
|
||||
v.TCoords.X = source->Tex[i].u;
|
||||
v.TCoords.Y = source->Tex[i].v;
|
||||
v.TCoords2.X = 0.f;
|
||||
v.TCoords2.Y = 0.f;
|
||||
}
|
||||
|
||||
// load static texture
|
||||
u32 pos = 0;
|
||||
quake3::tTexArray textureArray;
|
||||
quake3::getTextures(textureArray, source->Shader, pos, fs, driver);
|
||||
dest->Material.MaterialType = video::EMT_SOLID;
|
||||
dest->Material.setTexture(0, textureArray[0]);
|
||||
dest->Material.Lighting = false;
|
||||
|
||||
return dest;
|
||||
}
|
||||
|
||||
|
||||
//! build final mesh's vertices from frames frameA and frameB with linear interpolation.
|
||||
void CAnimatedMeshMD3::buildVertexArray(u32 frameA, u32 frameB, f32 interpolate,
|
||||
const SMD3MeshBuffer* source,
|
||||
SMeshBufferLightMap* dest)
|
||||
{
|
||||
const u32 frameOffsetA = frameA * source->MeshHeader.numVertices;
|
||||
const u32 frameOffsetB = frameB * source->MeshHeader.numVertices;
|
||||
const f32 scale = (1.f/ 64.f);
|
||||
|
||||
for (s32 i = 0; i != source->MeshHeader.numVertices; ++i)
|
||||
{
|
||||
video::S3DVertex2TCoords &v = dest->Vertices [ i ];
|
||||
|
||||
const SMD3Vertex &vA = source->Vertices [ frameOffsetA + i ];
|
||||
const SMD3Vertex &vB = source->Vertices [ frameOffsetB + i ];
|
||||
|
||||
// position
|
||||
v.Pos.X = scale * (vA.position[0] + interpolate * (vB.position[0] - vA.position[0]));
|
||||
v.Pos.Y = scale * (vA.position[2] + interpolate * (vB.position[2] - vA.position[2]));
|
||||
v.Pos.Z = scale * (vA.position[1] + interpolate * (vB.position[1] - vA.position[1]));
|
||||
|
||||
// normal
|
||||
const core::vector3df nA(quake3::getMD3Normal(vA.normal[0], vA.normal[1]));
|
||||
const core::vector3df nB(quake3::getMD3Normal(vB.normal[0], vB.normal[1]));
|
||||
|
||||
v.Normal.X = nA.X + interpolate * (nB.X - nA.X);
|
||||
v.Normal.Y = nA.Z + interpolate * (nB.Z - nA.Z);
|
||||
v.Normal.Z = nA.Y + interpolate * (nB.Y - nA.Y);
|
||||
}
|
||||
|
||||
dest->recalculateBoundingBox();
|
||||
}
|
||||
|
||||
|
||||
//! build final mesh's tag from frames frameA and frameB with linear interpolation.
|
||||
void CAnimatedMeshMD3::buildTagArray(u32 frameA, u32 frameB, f32 interpolate)
|
||||
{
|
||||
const u32 frameOffsetA = frameA * Mesh->MD3Header.numTags;
|
||||
const u32 frameOffsetB = frameB * Mesh->MD3Header.numTags;
|
||||
|
||||
for (s32 i = 0; i != Mesh->MD3Header.numTags; ++i)
|
||||
{
|
||||
SMD3QuaternionTag &d = TagListIPol [ i ];
|
||||
|
||||
const SMD3QuaternionTag &qA = Mesh->TagList[ frameOffsetA + i];
|
||||
const SMD3QuaternionTag &qB = Mesh->TagList[ frameOffsetB + i];
|
||||
|
||||
// rotation
|
||||
d.rotation.slerp(qA.rotation, qB.rotation, interpolate);
|
||||
|
||||
// position
|
||||
d.position.X = qA.position.X + interpolate * (qB.position.X - qA.position.X);
|
||||
d.position.Y = qA.position.Y + interpolate * (qB.position.Y - qA.position.Y);
|
||||
d.position.Z = qA.position.Z + interpolate * (qB.position.Z - qA.position.Z);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
loads a model
|
||||
*/
|
||||
bool CAnimatedMeshMD3::loadModelFile(u32 modelIndex, io::IReadFile* file,
|
||||
io::IFileSystem* fs, video::IVideoDriver* driver)
|
||||
{
|
||||
if (!file)
|
||||
return false;
|
||||
|
||||
//! Check MD3Header
|
||||
{
|
||||
file->read(&Mesh->MD3Header, sizeof(SMD3Header));
|
||||
|
||||
if (strncmp("IDP3", Mesh->MD3Header.headerID, 4))
|
||||
{
|
||||
os::Printer::log("MD3 Loader: invalid header");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
//! store model name
|
||||
Mesh->Name = file->getFileName();
|
||||
|
||||
u32 i;
|
||||
|
||||
//! Frame Data (ignore)
|
||||
#if 0
|
||||
SMD3Frame frameImport;
|
||||
file->seek(Mesh->MD3Header.frameStart);
|
||||
for (i = 0; i != Mesh->MD3Header.numFrames; ++i)
|
||||
{
|
||||
file->read(&frameImport, sizeof(frameImport));
|
||||
}
|
||||
#endif
|
||||
|
||||
//! Tag Data
|
||||
const u32 totalTags = Mesh->MD3Header.numTags * Mesh->MD3Header.numFrames;
|
||||
|
||||
SMD3Tag import;
|
||||
|
||||
file->seek(Mesh->MD3Header.tagStart);
|
||||
Mesh->TagList.set_used(totalTags);
|
||||
for (i = 0; i != totalTags; ++i)
|
||||
{
|
||||
file->read(&import, sizeof(import));
|
||||
|
||||
SMD3QuaternionTag &exp = Mesh->TagList[i];
|
||||
|
||||
//! tag name
|
||||
exp.Name = import.Name;
|
||||
|
||||
//! position
|
||||
exp.position.X = import.position[0];
|
||||
exp.position.Y = import.position[2];
|
||||
exp.position.Z = import.position[1];
|
||||
|
||||
//! construct quaternion from a RH 3x3 Matrix
|
||||
exp.rotation.set(import.rotationMatrix[7],
|
||||
0.f,
|
||||
-import.rotationMatrix[6],
|
||||
1 + import.rotationMatrix[8]);
|
||||
exp.rotation.normalize();
|
||||
}
|
||||
|
||||
//! Meshes
|
||||
u32 offset = Mesh->MD3Header.tagEnd;
|
||||
|
||||
for (i = 0; i != (u32)Mesh->MD3Header.numMeshes; ++i)
|
||||
{
|
||||
//! construct a new mesh buffer
|
||||
SMD3MeshBuffer * buf = new SMD3MeshBuffer();
|
||||
|
||||
// !read mesh header info
|
||||
SMD3MeshHeader &meshHeader = buf->MeshHeader;
|
||||
|
||||
//! read mesh info
|
||||
file->seek(offset);
|
||||
file->read(&meshHeader, sizeof(SMD3MeshHeader));
|
||||
|
||||
//! prepare memory
|
||||
buf->Vertices.set_used(meshHeader.numVertices * Mesh->MD3Header.numFrames);
|
||||
buf->Indices.set_used(meshHeader.numTriangles * 3);
|
||||
buf->Tex.set_used(meshHeader.numVertices);
|
||||
|
||||
//! read skins (shaders). should be 1 per meshbuffer
|
||||
SMD3Shader skin;
|
||||
file->seek(offset + buf->MeshHeader.offset_shaders);
|
||||
for (s32 g = 0; g != buf->MeshHeader.numShader; ++g)
|
||||
{
|
||||
file->read(&skin, sizeof(skin));
|
||||
|
||||
io::path name;
|
||||
cutFilenameExtension(name, skin.name);
|
||||
name.replace('\\', '/');
|
||||
buf->Shader = name;
|
||||
}
|
||||
|
||||
//! read texture coordinates
|
||||
file->seek(offset + buf->MeshHeader.offset_st);
|
||||
file->read(buf->Tex.pointer(), buf->MeshHeader.numVertices * sizeof(SMD3TexCoord));
|
||||
|
||||
//! read vertices
|
||||
file->seek(offset + meshHeader.vertexStart);
|
||||
file->read(buf->Vertices.pointer(), Mesh->MD3Header.numFrames * meshHeader.numVertices * sizeof(SMD3Vertex));
|
||||
|
||||
//! read indices
|
||||
file->seek(offset + meshHeader.offset_triangles);
|
||||
file->read(buf->Indices.pointer(), meshHeader.numTriangles * sizeof(SMD3Face));
|
||||
|
||||
//! store meshBuffer
|
||||
Mesh->Buffer.push_back(buf);
|
||||
|
||||
offset += meshHeader.offset_end;
|
||||
}
|
||||
|
||||
// Init Mesh Interpolation
|
||||
for (i = 0; i != Mesh->Buffer.size(); ++i)
|
||||
{
|
||||
IMeshBuffer * buffer = createMeshBuffer(Mesh->Buffer[i], fs, driver);
|
||||
MeshIPol->addMeshBuffer(buffer);
|
||||
buffer->drop();
|
||||
}
|
||||
MeshIPol->recalculateBoundingBox();
|
||||
|
||||
// Init Tag Interpolation
|
||||
for (i = 0; i != (u32)Mesh->MD3Header.numTags; ++i)
|
||||
{
|
||||
TagListIPol.push_back(Mesh->TagList[i]);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
SMD3Mesh * CAnimatedMeshMD3::getOriginalMesh()
|
||||
{
|
||||
return Mesh;
|
||||
}
|
||||
|
||||
|
||||
//! Returns an axis aligned bounding box
|
||||
const core::aabbox3d<f32>& CAnimatedMeshMD3::getBoundingBox() const
|
||||
{
|
||||
return MeshIPol->BoundingBox;
|
||||
}
|
||||
|
||||
|
||||
//! Returns the type of the animated mesh.
|
||||
E_ANIMATED_MESH_TYPE CAnimatedMeshMD3::getMeshType() const
|
||||
{
|
||||
return EAMT_MD3;
|
||||
}
|
||||
|
||||
|
||||
} // end namespace scene
|
||||
} // end namespace irr
|
||||
|
||||
#endif // _IRR_COMPILE_WITH_MD3_LOADER_
|
135
source/Irrlicht/CAnimatedMeshMD3.h
Normal file
135
source/Irrlicht/CAnimatedMeshMD3.h
Normal file
@ -0,0 +1,135 @@
|
||||
// Copyright (C) 2002-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 __C_ANIMATED_MESH_MD3_H_INCLUDED__
|
||||
#define __C_ANIMATED_MESH_MD3_H_INCLUDED__
|
||||
|
||||
#include "IAnimatedMeshMD3.h"
|
||||
#include "IReadFile.h"
|
||||
#include "IFileSystem.h"
|
||||
#include "irrArray.h"
|
||||
#include "irrString.h"
|
||||
#include "SMesh.h"
|
||||
#include "SMeshBuffer.h"
|
||||
#include "IQ3Shader.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace scene
|
||||
{
|
||||
|
||||
class CAnimatedMeshMD3 : public IAnimatedMeshMD3
|
||||
{
|
||||
public:
|
||||
|
||||
//! constructor
|
||||
CAnimatedMeshMD3();
|
||||
|
||||
//! destructor
|
||||
virtual ~CAnimatedMeshMD3();
|
||||
|
||||
//! loads a quake3 md3 file
|
||||
virtual bool loadModelFile(u32 modelIndex, io::IReadFile* file,
|
||||
io::IFileSystem* fs, video::IVideoDriver* driver);
|
||||
|
||||
// IAnimatedMeshMD3
|
||||
virtual void setInterpolationShift(u32 shift, u32 loopMode);
|
||||
virtual SMD3Mesh* getOriginalMesh();
|
||||
virtual SMD3QuaternionTagList* getTagList(s32 frame, s32 detailLevel, s32 startFrameLoop, s32 endFrameLoop);
|
||||
|
||||
//IAnimatedMesh
|
||||
virtual u32 getFrameCount() const;
|
||||
|
||||
//! Gets the default animation speed of the animated mesh.
|
||||
/** \return Amount of frames per second. If the amount is 0, it is a static, non animated mesh. */
|
||||
virtual f32 getAnimationSpeed() const
|
||||
{
|
||||
return FramesPerSecond;
|
||||
}
|
||||
|
||||
//! Gets the frame count of the animated mesh.
|
||||
/** \param fps Frames per second to play the animation with. If the amount is 0, it is not animated.
|
||||
The actual speed is set in the scene node the mesh is instantiated in.*/
|
||||
virtual void setAnimationSpeed(f32 fps)
|
||||
{
|
||||
FramesPerSecond=fps;
|
||||
}
|
||||
|
||||
virtual IMesh* getMesh(s32 frame, s32 detailLevel,
|
||||
s32 startFrameLoop, s32 endFrameLoop);
|
||||
virtual const core::aabbox3d<f32>& getBoundingBox() const;
|
||||
virtual E_ANIMATED_MESH_TYPE getMeshType() const;
|
||||
|
||||
//! returns amount of mesh buffers.
|
||||
virtual u32 getMeshBufferCount() const;
|
||||
|
||||
//! returns pointer to a mesh buffer
|
||||
virtual IMeshBuffer* getMeshBuffer(u32 nr) const;
|
||||
|
||||
//! Returns pointer to a mesh buffer which fits a material
|
||||
virtual IMeshBuffer* getMeshBuffer(const video::SMaterial &material) const;
|
||||
|
||||
virtual void setMaterialFlag(video::E_MATERIAL_FLAG flag, bool newvalue);
|
||||
|
||||
//! set user axis aligned bounding box
|
||||
virtual void setBoundingBox(const core::aabbox3df& box);
|
||||
|
||||
//! set the hardware mapping hint, for driver
|
||||
virtual void setHardwareMappingHint(E_HARDWARE_MAPPING newMappingHint, E_BUFFER_TYPE buffer=EBT_VERTEX_AND_INDEX);
|
||||
|
||||
//! flags the meshbuffer as changed, reloads hardware buffers
|
||||
virtual void setDirty(E_BUFFER_TYPE buffer=EBT_VERTEX_AND_INDEX);
|
||||
|
||||
private:
|
||||
//! animates one frame
|
||||
inline void Animate(u32 frame);
|
||||
|
||||
video::SMaterial Material;
|
||||
|
||||
//! hold original compressed MD3 Info
|
||||
SMD3Mesh *Mesh;
|
||||
|
||||
u32 IPolShift;
|
||||
u32 LoopMode;
|
||||
f32 Scaling;
|
||||
|
||||
//! Cache Info
|
||||
struct SCacheInfo
|
||||
{
|
||||
SCacheInfo(s32 frame=-1, s32 start=-1, s32 end=-1 ) :
|
||||
Frame(frame), startFrameLoop(start),
|
||||
endFrameLoop(end)
|
||||
{}
|
||||
|
||||
bool operator == ( const SCacheInfo &other ) const
|
||||
{
|
||||
return 0 == memcmp ( this, &other, sizeof ( SCacheInfo ) );
|
||||
}
|
||||
s32 Frame;
|
||||
s32 startFrameLoop;
|
||||
s32 endFrameLoop;
|
||||
};
|
||||
SCacheInfo Current;
|
||||
|
||||
//! return a Mesh per frame
|
||||
SMesh* MeshIPol;
|
||||
SMD3QuaternionTagList TagListIPol;
|
||||
|
||||
IMeshBuffer* createMeshBuffer(const SMD3MeshBuffer* source,
|
||||
io::IFileSystem* fs, video::IVideoDriver* driver);
|
||||
|
||||
void buildVertexArray(u32 frameA, u32 frameB, f32 interpolate,
|
||||
const SMD3MeshBuffer* source,
|
||||
SMeshBufferLightMap* dest);
|
||||
|
||||
void buildTagArray(u32 frameA, u32 frameB, f32 interpolate);
|
||||
f32 FramesPerSecond;
|
||||
};
|
||||
|
||||
|
||||
} // end namespace scene
|
||||
} // end namespace irr
|
||||
|
||||
#endif
|
||||
|
1132
source/Irrlicht/CAnimatedMeshSceneNode.cpp
Normal file
1132
source/Irrlicht/CAnimatedMeshSceneNode.cpp
Normal file
File diff suppressed because it is too large
Load Diff
227
source/Irrlicht/CAnimatedMeshSceneNode.h
Normal file
227
source/Irrlicht/CAnimatedMeshSceneNode.h
Normal file
@ -0,0 +1,227 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#ifndef __C_ANIMATED_MESH_SCENE_NODE_H_INCLUDED__
|
||||
#define __C_ANIMATED_MESH_SCENE_NODE_H_INCLUDED__
|
||||
|
||||
#include "IAnimatedMeshSceneNode.h"
|
||||
#include "IAnimatedMesh.h"
|
||||
|
||||
#include "matrix4.h"
|
||||
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace scene
|
||||
{
|
||||
class IDummyTransformationSceneNode;
|
||||
|
||||
class CAnimatedMeshSceneNode : public IAnimatedMeshSceneNode
|
||||
{
|
||||
public:
|
||||
|
||||
//! constructor
|
||||
CAnimatedMeshSceneNode(IAnimatedMesh* mesh, ISceneNode* parent, ISceneManager* mgr, s32 id,
|
||||
const core::vector3df& position = core::vector3df(0,0,0),
|
||||
const core::vector3df& rotation = core::vector3df(0,0,0),
|
||||
const core::vector3df& scale = core::vector3df(1.0f, 1.0f, 1.0f));
|
||||
|
||||
//! destructor
|
||||
virtual ~CAnimatedMeshSceneNode();
|
||||
|
||||
//! sets the current frame. from now on the animation is played from this frame.
|
||||
virtual void setCurrentFrame(f32 frame);
|
||||
|
||||
//! frame
|
||||
virtual void OnRegisterSceneNode();
|
||||
|
||||
//! OnAnimate() is called just before rendering the whole scene.
|
||||
virtual void OnAnimate(u32 timeMs);
|
||||
|
||||
//! renders the node.
|
||||
virtual void render();
|
||||
|
||||
//! returns the axis aligned bounding box of this node
|
||||
virtual const core::aabbox3d<f32>& getBoundingBox() const;
|
||||
|
||||
//! sets the frames between the animation is looped.
|
||||
//! the default is 0 - MaximalFrameCount of the mesh.
|
||||
virtual bool setFrameLoop(s32 begin, s32 end);
|
||||
|
||||
//! Sets looping mode which is on by default. If set to false,
|
||||
//! animations will not be looped.
|
||||
virtual void setLoopMode(bool playAnimationLooped);
|
||||
|
||||
//! returns the current loop mode
|
||||
virtual bool getLoopMode() const;
|
||||
|
||||
//! Sets a callback interface which will be called if an animation
|
||||
//! playback has ended. Set this to 0 to disable the callback again.
|
||||
virtual void setAnimationEndCallback(IAnimationEndCallBack* callback=0);
|
||||
|
||||
//! sets the speed with which the animation is played
|
||||
virtual void setAnimationSpeed(f32 framesPerSecond);
|
||||
|
||||
//! gets the speed with which the animation is played
|
||||
virtual f32 getAnimationSpeed() const;
|
||||
|
||||
//! returns the material based on the zero based index i. To get the amount
|
||||
//! of materials used by this scene node, use getMaterialCount().
|
||||
//! This function is needed for inserting the node into the scene hirachy on a
|
||||
//! optimal position for minimizing renderstate changes, but can also be used
|
||||
//! to directly modify the material of a scene node.
|
||||
virtual video::SMaterial& getMaterial(u32 i);
|
||||
|
||||
//! returns amount of materials used by this scene node.
|
||||
virtual u32 getMaterialCount() const;
|
||||
|
||||
//! Creates shadow volume scene node as child of this node
|
||||
//! and returns a pointer to it.
|
||||
virtual IShadowVolumeSceneNode* addShadowVolumeSceneNode(const IMesh* shadowMesh,
|
||||
s32 id, bool zfailmethod=true, f32 infinity=1000.0f);
|
||||
|
||||
//! Returns a pointer to a child node, which has the same transformation as
|
||||
//! the corrsesponding joint, if the mesh in this scene node is a skinned mesh.
|
||||
virtual IBoneSceneNode* getJointNode(const c8* jointName);
|
||||
|
||||
//! same as getJointNode(const c8* jointName), but based on id
|
||||
virtual IBoneSceneNode* getJointNode(u32 jointID);
|
||||
|
||||
//! Gets joint count.
|
||||
virtual u32 getJointCount() const;
|
||||
|
||||
//! Deprecated command, please use getJointNode.
|
||||
virtual ISceneNode* getMS3DJointNode(const c8* jointName);
|
||||
|
||||
//! Deprecated command, please use getJointNode.
|
||||
virtual ISceneNode* getXJointNode(const c8* jointName);
|
||||
|
||||
//! Removes a child from this scene node.
|
||||
//! Implemented here, to be able to remove the shadow properly, if there is one,
|
||||
//! or to remove attached childs.
|
||||
virtual bool removeChild(ISceneNode* child);
|
||||
|
||||
//! Starts a MD2 animation.
|
||||
virtual bool setMD2Animation(EMD2_ANIMATION_TYPE anim);
|
||||
|
||||
//! Starts a special MD2 animation.
|
||||
virtual bool setMD2Animation(const c8* animationName);
|
||||
|
||||
//! Returns the current displayed frame number.
|
||||
virtual f32 getFrameNr() const;
|
||||
//! Returns the current start frame number.
|
||||
virtual s32 getStartFrame() const;
|
||||
//! Returns the current end frame number.
|
||||
virtual s32 getEndFrame() const;
|
||||
|
||||
//! Sets if the scene node should not copy the materials of the mesh but use them in a read only style.
|
||||
/* In this way it is possible to change the materials a mesh causing all mesh scene nodes
|
||||
referencing this mesh to change too. */
|
||||
virtual void setReadOnlyMaterials(bool readonly);
|
||||
|
||||
//! Returns if the scene node should not copy the materials of the mesh but use them in a read only style
|
||||
virtual bool isReadOnlyMaterials() const;
|
||||
|
||||
//! Sets a new mesh
|
||||
virtual void setMesh(IAnimatedMesh* mesh);
|
||||
|
||||
//! Returns the current mesh
|
||||
virtual IAnimatedMesh* getMesh(void) { return Mesh; }
|
||||
|
||||
//! Writes attributes of the scene node.
|
||||
virtual void serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options=0) const;
|
||||
|
||||
//! Reads attributes of the scene node.
|
||||
virtual void deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options=0);
|
||||
|
||||
//! Returns type of the scene node
|
||||
virtual ESCENE_NODE_TYPE getType() const { return ESNT_ANIMATED_MESH; }
|
||||
|
||||
// returns the absolute transformation for a special MD3 Tag if the mesh is a md3 mesh,
|
||||
// or the absolutetransformation if it's a normal scenenode
|
||||
const SMD3QuaternionTag* getMD3TagTransformation( const core::stringc & tagname);
|
||||
|
||||
//! updates the absolute position based on the relative and the parents position
|
||||
virtual void updateAbsolutePosition();
|
||||
|
||||
|
||||
//! Set the joint update mode (0-unused, 1-get joints only, 2-set joints only, 3-move and set)
|
||||
virtual void setJointMode(E_JOINT_UPDATE_ON_RENDER mode);
|
||||
|
||||
//! Sets the transition time in seconds (note: This needs to enable joints, and setJointmode maybe set to 2)
|
||||
//! you must call animateJoints(), or the mesh will not animate
|
||||
virtual void setTransitionTime(f32 Time);
|
||||
|
||||
//! updates the joint positions of this mesh
|
||||
virtual void animateJoints(bool CalculateAbsolutePositions=true);
|
||||
|
||||
//! render mesh ignoring its transformation. Used with ragdolls. (culling is unaffected)
|
||||
virtual void setRenderFromIdentity( bool On );
|
||||
|
||||
//! Creates a clone of this scene node and its children.
|
||||
/** \param newParent An optional new parent.
|
||||
\param newManager An optional new scene manager.
|
||||
\return The newly created clone of this node. */
|
||||
virtual ISceneNode* clone(ISceneNode* newParent=0, ISceneManager* newManager=0);
|
||||
|
||||
private:
|
||||
|
||||
//! Get a static mesh for the current frame of this animated mesh
|
||||
IMesh* getMeshForCurrentFrame();
|
||||
|
||||
void buildFrameNr(u32 timeMs);
|
||||
void checkJoints();
|
||||
void beginTransition();
|
||||
|
||||
core::array<video::SMaterial> Materials;
|
||||
core::aabbox3d<f32> Box;
|
||||
IAnimatedMesh* Mesh;
|
||||
|
||||
s32 StartFrame;
|
||||
s32 EndFrame;
|
||||
f32 FramesPerSecond;
|
||||
f32 CurrentFrameNr;
|
||||
|
||||
u32 LastTimeMs;
|
||||
u32 TransitionTime; //Transition time in millisecs
|
||||
f32 Transiting; //is mesh transiting (plus cache of TransitionTime)
|
||||
f32 TransitingBlend; //0-1, calculated on buildFrameNr
|
||||
|
||||
//0-unused, 1-get joints only, 2-set joints only, 3-move and set
|
||||
E_JOINT_UPDATE_ON_RENDER JointMode;
|
||||
bool JointsUsed;
|
||||
|
||||
bool Looping;
|
||||
bool ReadOnlyMaterials;
|
||||
bool RenderFromIdentity;
|
||||
|
||||
IAnimationEndCallBack* LoopCallBack;
|
||||
s32 PassCount;
|
||||
|
||||
IShadowVolumeSceneNode* Shadow;
|
||||
|
||||
core::array<IBoneSceneNode* > JointChildSceneNodes;
|
||||
core::array<core::matrix4> PretransitingSave;
|
||||
|
||||
// Quake3 Model
|
||||
struct SMD3Special : public virtual IReferenceCounted
|
||||
{
|
||||
core::stringc Tagname;
|
||||
SMD3QuaternionTagList AbsoluteTagList;
|
||||
|
||||
SMD3Special & operator = (const SMD3Special & copyMe)
|
||||
{
|
||||
Tagname = copyMe.Tagname;
|
||||
AbsoluteTagList = copyMe.AbsoluteTagList;
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
SMD3Special *MD3Special;
|
||||
};
|
||||
|
||||
} // end namespace scene
|
||||
} // end namespace irr
|
||||
|
||||
#endif
|
||||
|
2071
source/Irrlicht/CAttributeImpl.h
Normal file
2071
source/Irrlicht/CAttributeImpl.h
Normal file
File diff suppressed because it is too large
Load Diff
1665
source/Irrlicht/CAttributes.cpp
Normal file
1665
source/Irrlicht/CAttributes.cpp
Normal file
File diff suppressed because it is too large
Load Diff
712
source/Irrlicht/CAttributes.h
Normal file
712
source/Irrlicht/CAttributes.h
Normal file
@ -0,0 +1,712 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#ifndef __C_ATTRIBUTES_H_INCLUDED__
|
||||
#define __C_ATTRIBUTES_H_INCLUDED__
|
||||
|
||||
#include "IAttributes.h"
|
||||
#include "IAttribute.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace video
|
||||
{
|
||||
class ITexture;
|
||||
class IVideoDriver;
|
||||
}
|
||||
namespace io
|
||||
{
|
||||
|
||||
|
||||
//! Implementation of the IAttributes interface
|
||||
class CAttributes : public IAttributes
|
||||
{
|
||||
public:
|
||||
|
||||
CAttributes(video::IVideoDriver* driver=0);
|
||||
~CAttributes();
|
||||
|
||||
//! Returns amount of attributes in this collection of attributes.
|
||||
virtual u32 getAttributeCount() const;
|
||||
|
||||
//! Returns attribute name by index.
|
||||
//! \param index: Index value, must be between 0 and getAttributeCount()-1.
|
||||
virtual const c8* getAttributeName(s32 index);
|
||||
|
||||
//! Returns the type of an attribute
|
||||
//! \param attributeName: Name for the attribute
|
||||
virtual E_ATTRIBUTE_TYPE getAttributeType(const c8* attributeName);
|
||||
|
||||
//! Returns attribute type by index.
|
||||
//! \param index: Index value, must be between 0 and getAttributeCount()-1.
|
||||
virtual E_ATTRIBUTE_TYPE getAttributeType(s32 index);
|
||||
|
||||
//! Returns the type string of the attribute
|
||||
//! \param attributeName: String for the attribute type
|
||||
virtual const wchar_t* getAttributeTypeString(const c8* attributeName);
|
||||
|
||||
//! Returns the type string of the attribute by index.
|
||||
//! \param index: Index value, must be between 0 and getAttributeCount()-1.
|
||||
virtual const wchar_t* getAttributeTypeString(s32 index);
|
||||
|
||||
//! Returns if an attribute with a name exists
|
||||
virtual bool existsAttribute(const c8* attributeName);
|
||||
|
||||
//! Returns attribute index from name, -1 if not found
|
||||
virtual s32 findAttribute(const c8* attributeName) const;
|
||||
|
||||
//! Removes all attributes
|
||||
virtual void clear();
|
||||
|
||||
//! Reads attributes from a xml file.
|
||||
//! \param readCurrentElementOnly: If set to true, reading only works if current element has the name 'attributes'.
|
||||
//! IF set to false, the first appearing list attributes are read.
|
||||
virtual bool read(io::IXMLReader* reader, bool readCurrentElementOnly=false,
|
||||
const wchar_t* nonDefaultElementName = 0);
|
||||
|
||||
//! Write these attributes into a xml file
|
||||
virtual bool write(io::IXMLWriter* writer, bool writeXMLHeader=false, const wchar_t* nonDefaultElementName=0);
|
||||
|
||||
|
||||
/*
|
||||
|
||||
Integer Attribute
|
||||
|
||||
*/
|
||||
|
||||
//! Adds an attribute as integer
|
||||
virtual void addInt(const c8* attributeName, s32 value);
|
||||
|
||||
//! Sets an attribute as integer value
|
||||
virtual void setAttribute(const c8* attributeName, s32 value);
|
||||
|
||||
//! Gets an attribute as integer value
|
||||
//! \param attributeName: Name of the attribute to get.
|
||||
//! \return Returns value of the attribute previously set by setAttribute()
|
||||
virtual s32 getAttributeAsInt(const c8* attributeName) const;
|
||||
|
||||
//! Gets an attribute as integer value
|
||||
//! \param index: Index value, must be between 0 and getAttributeCount()-1.
|
||||
virtual s32 getAttributeAsInt(s32 index) const;
|
||||
|
||||
//! Sets an attribute as integer value
|
||||
virtual void setAttribute(s32 index, s32 value);
|
||||
|
||||
/*
|
||||
|
||||
Float Attribute
|
||||
|
||||
*/
|
||||
|
||||
//! Adds an attribute as float
|
||||
virtual void addFloat(const c8* attributeName, f32 value);
|
||||
|
||||
//! Sets a attribute as float value
|
||||
virtual void setAttribute(const c8* attributeName, f32 value);
|
||||
|
||||
//! Gets an attribute as float value
|
||||
//! \param attributeName: Name of the attribute to get.
|
||||
//! \return Returns value of the attribute previously set by setAttribute()
|
||||
virtual f32 getAttributeAsFloat(const c8* attributeName);
|
||||
|
||||
//! Gets an attribute as float value
|
||||
//! \param index: Index value, must be between 0 and getAttributeCount()-1.
|
||||
virtual f32 getAttributeAsFloat(s32 index);
|
||||
|
||||
//! Sets an attribute as float value
|
||||
virtual void setAttribute(s32 index, f32 value);
|
||||
|
||||
/*
|
||||
|
||||
String Attribute
|
||||
|
||||
*/
|
||||
|
||||
//! Adds an attribute as string
|
||||
virtual void addString(const c8* attributeName, const c8* value);
|
||||
|
||||
//! Sets an attribute value as string.
|
||||
//! \param attributeName: Name for the attribute
|
||||
//! \param value: Value for the attribute. Set this to 0 to delete the attribute
|
||||
virtual void setAttribute(const c8* attributeName, const c8* value);
|
||||
|
||||
//! Gets an attribute as string.
|
||||
//! \param attributeName: Name of the attribute to get.
|
||||
//! \return Returns value of the attribute previously set by setAttribute()
|
||||
//! or 0 if attribute is not set.
|
||||
virtual core::stringc getAttributeAsString(const c8* attributeName);
|
||||
|
||||
//! Gets an attribute as string.
|
||||
//! \param attributeName: Name of the attribute to get.
|
||||
//! \param target: Buffer where the string is copied to.
|
||||
virtual void getAttributeAsString(const c8* attributeName, c8* target);
|
||||
|
||||
//! Returns attribute value as string by index.
|
||||
//! \param index: Index value, must be between 0 and getAttributeCount()-1.
|
||||
virtual core::stringc getAttributeAsString(s32 index);
|
||||
|
||||
//! Sets an attribute value as string.
|
||||
//! \param attributeName: Name for the attribute
|
||||
virtual void setAttribute(s32 index, const c8* value);
|
||||
|
||||
// wide strings
|
||||
|
||||
//! Adds an attribute as string
|
||||
virtual void addString(const c8* attributeName, const wchar_t* value);
|
||||
|
||||
//! Sets an attribute value as string.
|
||||
//! \param attributeName: Name for the attribute
|
||||
//! \param value: Value for the attribute. Set this to 0 to delete the attribute
|
||||
virtual void setAttribute(const c8* attributeName, const wchar_t* value);
|
||||
|
||||
//! Gets an attribute as string.
|
||||
//! \param attributeName: Name of the attribute to get.
|
||||
//! \return Returns value of the attribute previously set by setAttribute()
|
||||
//! or 0 if attribute is not set.
|
||||
virtual core::stringw getAttributeAsStringW(const c8* attributeName);
|
||||
|
||||
//! Gets an attribute as string.
|
||||
//! \param attributeName: Name of the attribute to get.
|
||||
//! \param target: Buffer where the string is copied to.
|
||||
virtual void getAttributeAsStringW(const c8* attributeName, wchar_t* target);
|
||||
|
||||
//! Returns attribute value as string by index.
|
||||
//! \param index: Index value, must be between 0 and getAttributeCount()-1.
|
||||
virtual core::stringw getAttributeAsStringW(s32 index);
|
||||
|
||||
//! Sets an attribute value as string.
|
||||
//! \param attributeName: Name for the attribute
|
||||
virtual void setAttribute(s32 index, const wchar_t* value);
|
||||
|
||||
/*
|
||||
|
||||
Binary Data Attribute
|
||||
|
||||
*/
|
||||
|
||||
//! Adds an attribute as binary data
|
||||
virtual void addBinary(const c8* attributeName, void* data, s32 dataSizeInBytes);
|
||||
|
||||
//! Sets an attribute as binary data
|
||||
virtual void setAttribute(const c8* attributeName, void* data, s32 dataSizeInBytes);
|
||||
|
||||
//! Gets an attribute as binary data
|
||||
//! \param attributeName: Name of the attribute to get.
|
||||
virtual void getAttributeAsBinaryData(const c8* attributeName, void* outData, s32 maxSizeInBytes);
|
||||
|
||||
//! Gets an attribute as binary data
|
||||
//! \param index: Index value, must be between 0 and getAttributeCount()-1.
|
||||
virtual void getAttributeAsBinaryData(s32 index, void* outData, s32 maxSizeInBytes);
|
||||
|
||||
//! Sets an attribute as binary data
|
||||
virtual void setAttribute(s32 index, void* data, s32 dataSizeInBytes);
|
||||
|
||||
|
||||
/*
|
||||
|
||||
Array Attribute
|
||||
|
||||
*/
|
||||
|
||||
//! Adds an attribute as wide string array
|
||||
virtual void addArray(const c8* attributeName, const core::array<core::stringw>& value);
|
||||
|
||||
//! Sets an attribute value as a wide string array.
|
||||
//! \param attributeName: Name for the attribute
|
||||
//! \param value: Value for the attribute. Set this to 0 to delete the attribute
|
||||
virtual void setAttribute(const c8* attributeName, const core::array<core::stringw>& value);
|
||||
|
||||
//! Gets an attribute as an array of wide strings.
|
||||
//! \param attributeName: Name of the attribute to get.
|
||||
//! \return Returns value of the attribute previously set by setAttribute()
|
||||
//! or 0 if attribute is not set.
|
||||
virtual core::array<core::stringw> getAttributeAsArray(const c8* attributeName);
|
||||
|
||||
//! Returns attribute value as an array of wide strings by index.
|
||||
//! \param index: Index value, must be between 0 and getAttributeCount()-1.
|
||||
virtual core::array<core::stringw> getAttributeAsArray(s32 index);
|
||||
|
||||
//! Sets an attribute as an array of wide strings
|
||||
virtual void setAttribute(s32 index, const core::array<core::stringw>& value);
|
||||
|
||||
/*
|
||||
|
||||
Bool Attribute
|
||||
|
||||
*/
|
||||
|
||||
//! Adds an attribute as bool
|
||||
virtual void addBool(const c8* attributeName, bool value);
|
||||
|
||||
//! Sets an attribute as boolean value
|
||||
virtual void setAttribute(const c8* attributeName, bool value);
|
||||
|
||||
//! Gets an attribute as boolean value
|
||||
//! \param attributeName: Name of the attribute to get.
|
||||
//! \return Returns value of the attribute previously set by setAttribute()
|
||||
virtual bool getAttributeAsBool(const c8* attributeName);
|
||||
|
||||
//! Gets an attribute as boolean value
|
||||
//! \param index: Index value, must be between 0 and getAttributeCount()-1.
|
||||
virtual bool getAttributeAsBool(s32 index);
|
||||
|
||||
//! Sets an attribute as boolean value
|
||||
virtual void setAttribute(s32 index, bool value);
|
||||
|
||||
/*
|
||||
|
||||
Enumeration Attribute
|
||||
|
||||
*/
|
||||
|
||||
//! Adds an attribute as enum
|
||||
virtual void addEnum(const c8* attributeName, const c8* enumValue, const c8* const* enumerationLiterals);
|
||||
|
||||
//! Adds an attribute as enum
|
||||
virtual void addEnum(const c8* attributeName, s32 enumValue, const c8* const* enumerationLiterals);
|
||||
|
||||
//! Sets an attribute as enumeration
|
||||
virtual void setAttribute(const c8* attributeName, const c8* enumValue, const c8* const* enumerationLiterals);
|
||||
|
||||
//! Gets an attribute as enumeration
|
||||
//! \param attributeName: Name of the attribute to get.
|
||||
//! \return Returns value of the attribute previously set by setAttribute()
|
||||
virtual const c8* getAttributeAsEnumeration(const c8* attributeName);
|
||||
|
||||
//! Gets an attribute as enumeration
|
||||
//! \param attributeName: Name of the attribute to get.
|
||||
//! \param enumerationLiteralsToUse: Use these enumeration literals to get the index value instead of the set ones.
|
||||
//! This is useful when the attribute list maybe was read from an xml file, and only contains the enumeration string, but
|
||||
//! no information about its index.
|
||||
//! \return Returns value of the attribute previously set by setAttribute()
|
||||
virtual s32 getAttributeAsEnumeration(const c8* attributeName, const c8* const* enumerationLiteralsToUse);
|
||||
|
||||
//! Gets an attribute as enumeration
|
||||
//! \param index: Index value, must be between 0 and getAttributeCount()-1.
|
||||
virtual s32 getAttributeAsEnumeration(s32 index, const c8* const* enumerationLiteralsToUse);
|
||||
|
||||
//! Gets an attribute as enumeration
|
||||
//! \param index: Index value, must be between 0 and getAttributeCount()-1.
|
||||
virtual const c8* getAttributeAsEnumeration(s32 index);
|
||||
|
||||
//! Gets the list of enumeration literals of an enumeration attribute
|
||||
//! \param attributeName: Name of the attribute to get.
|
||||
virtual void getAttributeEnumerationLiteralsOfEnumeration(const c8* attributeName, core::array<core::stringc>& outLiterals);
|
||||
|
||||
//! Gets the list of enumeration literals of an enumeration attribute
|
||||
//! \param index: Index value, must be between 0 and getAttributeCount()-1.
|
||||
virtual void getAttributeEnumerationLiteralsOfEnumeration(s32 index, core::array<core::stringc>& outLiterals);
|
||||
|
||||
//! Sets an attribute as enumeration
|
||||
virtual void setAttribute(s32 index, const c8* enumValue, const c8* const* enumerationLiterals);
|
||||
|
||||
|
||||
/*
|
||||
|
||||
SColor Attribute
|
||||
|
||||
*/
|
||||
|
||||
//! Adds an attribute as color
|
||||
virtual void addColor(const c8* attributeName, video::SColor value);
|
||||
|
||||
//! Sets a attribute as color
|
||||
virtual void setAttribute(const c8* attributeName, video::SColor color);
|
||||
|
||||
//! Gets an attribute as color
|
||||
//! \param attributeName: Name of the attribute to get.
|
||||
//! \return Returns value of the attribute previously set by setAttribute()
|
||||
virtual video::SColor getAttributeAsColor(const c8* attributeName);
|
||||
|
||||
//! Gets an attribute as color
|
||||
//! \param index: Index value, must be between 0 and getAttributeCount()-1.
|
||||
virtual video::SColor getAttributeAsColor(s32 index);
|
||||
|
||||
//! Sets an attribute as color
|
||||
virtual void setAttribute(s32 index, video::SColor color);
|
||||
|
||||
/*
|
||||
|
||||
SColorf Attribute
|
||||
|
||||
*/
|
||||
|
||||
//! Adds an attribute as floating point color
|
||||
virtual void addColorf(const c8* attributeName, video::SColorf value);
|
||||
|
||||
//! Sets a attribute as floating point color
|
||||
virtual void setAttribute(const c8* attributeName, video::SColorf color);
|
||||
|
||||
//! Gets an attribute as floating point color
|
||||
//! \param attributeName: Name of the attribute to get.
|
||||
//! \return Returns value of the attribute previously set by setAttribute()
|
||||
virtual video::SColorf getAttributeAsColorf(const c8* attributeName);
|
||||
|
||||
//! Gets an attribute as floating point color
|
||||
//! \param index: Index value, must be between 0 and getAttributeCount()-1.
|
||||
virtual video::SColorf getAttributeAsColorf(s32 index);
|
||||
|
||||
//! Sets an attribute as floating point color
|
||||
virtual void setAttribute(s32 index, video::SColorf color);
|
||||
|
||||
|
||||
/*
|
||||
|
||||
Vector3d Attribute
|
||||
|
||||
*/
|
||||
|
||||
//! Adds an attribute as 3d vector
|
||||
virtual void addVector3d(const c8* attributeName, core::vector3df value);
|
||||
|
||||
//! Sets a attribute as 3d vector
|
||||
virtual void setAttribute(const c8* attributeName, core::vector3df v);
|
||||
|
||||
//! Gets an attribute as 3d vector
|
||||
//! \param attributeName: Name of the attribute to get.
|
||||
//! \return Returns value of the attribute previously set by setAttribute()
|
||||
virtual core::vector3df getAttributeAsVector3d(const c8* attributeName);
|
||||
|
||||
//! Gets an attribute as 3d vector
|
||||
//! \param index: Index value, must be between 0 and getAttributeCount()-1.
|
||||
virtual core::vector3df getAttributeAsVector3d(s32 index);
|
||||
|
||||
//! Sets an attribute as vector
|
||||
virtual void setAttribute(s32 index, core::vector3df v);
|
||||
|
||||
|
||||
/*
|
||||
|
||||
Vector2d Attribute
|
||||
|
||||
*/
|
||||
|
||||
//! Adds an attribute as 2d vector
|
||||
virtual void addVector2d(const c8* attributeName, core::vector2df value);
|
||||
|
||||
//! Sets a attribute as 2d vector
|
||||
virtual void setAttribute(const c8* attributeName, core::vector2df v);
|
||||
|
||||
//! Gets an attribute as 2d vector
|
||||
//! \param attributeName: Name of the attribute to get.
|
||||
//! \return Returns value of the attribute previously set by setAttribute()
|
||||
virtual core::vector2df getAttributeAsVector2d(const c8* attributeName);
|
||||
|
||||
//! Gets an attribute as 3d vector
|
||||
//! \param index: Index value, must be between 0 and getAttributeCount()-1.
|
||||
virtual core::vector2df getAttributeAsVector2d(s32 index);
|
||||
|
||||
//! Sets an attribute as vector
|
||||
virtual void setAttribute(s32 index, core::vector2df v);
|
||||
|
||||
|
||||
/*
|
||||
|
||||
Position2d Attribute
|
||||
|
||||
*/
|
||||
|
||||
//! Adds an attribute as 2d position
|
||||
virtual void addPosition2d(const c8* attributeName, core::position2di value);
|
||||
|
||||
//! Sets a attribute as 2d position
|
||||
virtual void setAttribute(const c8* attributeName, core::position2di v);
|
||||
|
||||
//! Gets an attribute as position
|
||||
//! \param attributeName: Name of the attribute to get.
|
||||
//! \return Returns value of the attribute previously set by setAttribute()
|
||||
virtual core::position2di getAttributeAsPosition2d(const c8* attributeName);
|
||||
|
||||
//! Gets an attribute as position
|
||||
//! \param index: Index value, must be between 0 and getAttributeCount()-1.
|
||||
virtual core::position2di getAttributeAsPosition2d(s32 index);
|
||||
|
||||
//! Sets an attribute as 2d position
|
||||
virtual void setAttribute(s32 index, core::position2di v);
|
||||
|
||||
/*
|
||||
|
||||
Rectangle Attribute
|
||||
|
||||
*/
|
||||
|
||||
//! Adds an attribute as rectangle
|
||||
virtual void addRect(const c8* attributeName, core::rect<s32> value);
|
||||
|
||||
//! Sets an attribute as rectangle
|
||||
virtual void setAttribute(const c8* attributeName, core::rect<s32> v);
|
||||
|
||||
//! Gets an attribute as rectangle
|
||||
//! \param attributeName: Name of the attribute to get.
|
||||
//! \return Returns value of the attribute previously set by setAttribute()
|
||||
virtual core::rect<s32> getAttributeAsRect(const c8* attributeName);
|
||||
|
||||
//! Gets an attribute as rectangle
|
||||
//! \param index: Index value, must be between 0 and getAttributeCount()-1.
|
||||
virtual core::rect<s32> getAttributeAsRect(s32 index);
|
||||
|
||||
//! Sets an attribute as rectangle
|
||||
virtual void setAttribute(s32 index, core::rect<s32> v);
|
||||
|
||||
|
||||
/*
|
||||
|
||||
Dimension2d Attribute
|
||||
|
||||
*/
|
||||
|
||||
//! Adds an attribute as dimension2d
|
||||
virtual void addDimension2d(const c8* attributeName, core::dimension2d<u32> value);
|
||||
|
||||
//! Sets an attribute as dimension2d
|
||||
virtual void setAttribute(const c8* attributeName, core::dimension2d<u32> v);
|
||||
|
||||
//! Gets an attribute as dimension2d
|
||||
//! \param attributeName: Name of the attribute to get.
|
||||
//! \return Returns value of the attribute previously set by setAttribute()
|
||||
virtual core::dimension2d<u32> getAttributeAsDimension2d(const c8* attributeName);
|
||||
|
||||
//! Gets an attribute as dimension2d
|
||||
//! \param index: Index value, must be between 0 and getAttributeCount()-1.
|
||||
virtual core::dimension2d<u32> getAttributeAsDimension2d(s32 index);
|
||||
|
||||
//! Sets an attribute as dimension2d
|
||||
virtual void setAttribute(s32 index, core::dimension2d<u32> v);
|
||||
|
||||
|
||||
/*
|
||||
|
||||
matrix attribute
|
||||
|
||||
*/
|
||||
|
||||
//! Adds an attribute as matrix
|
||||
virtual void addMatrix(const c8* attributeName, const core::matrix4& v);
|
||||
|
||||
//! Sets an attribute as matrix
|
||||
virtual void setAttribute(const c8* attributeName, const core::matrix4& v);
|
||||
|
||||
//! Gets an attribute as a matrix4
|
||||
//! \param attributeName: Name of the attribute to get.
|
||||
//! \return Returns value of the attribute previously set by setAttribute()
|
||||
virtual core::matrix4 getAttributeAsMatrix(const c8* attributeName);
|
||||
|
||||
//! Gets an attribute as matrix
|
||||
//! \param index: Index value, must be between 0 and getAttributeCount()-1.
|
||||
virtual core::matrix4 getAttributeAsMatrix(s32 index);
|
||||
|
||||
//! Sets an attribute as matrix
|
||||
virtual void setAttribute(s32 index, const core::matrix4& v);
|
||||
|
||||
/*
|
||||
quaternion attribute
|
||||
|
||||
*/
|
||||
|
||||
//! Adds an attribute as quaternion
|
||||
virtual void addQuaternion(const c8* attributeName, core::quaternion v);
|
||||
|
||||
//! Sets an attribute as quaternion
|
||||
virtual void setAttribute(const c8* attributeName, core::quaternion v);
|
||||
|
||||
//! Gets an attribute as a quaternion
|
||||
//! \param attributeName: Name of the attribute to get.
|
||||
//! \return Returns value of the attribute previously set by setAttribute()
|
||||
virtual core::quaternion getAttributeAsQuaternion(const c8* attributeName);
|
||||
|
||||
//! Gets an attribute as quaternion
|
||||
//! \param index: Index value, must be between 0 and getAttributeCount()-1.
|
||||
virtual core::quaternion getAttributeAsQuaternion(s32 index);
|
||||
|
||||
//! Sets an attribute as quaternion
|
||||
virtual void setAttribute(s32 index, core::quaternion v);
|
||||
|
||||
/*
|
||||
|
||||
3d bounding box
|
||||
|
||||
*/
|
||||
|
||||
//! Adds an attribute as axis aligned bounding box
|
||||
virtual void addBox3d(const c8* attributeName, core::aabbox3df v);
|
||||
|
||||
//! Sets an attribute as axis aligned bounding box
|
||||
virtual void setAttribute(const c8* attributeName, core::aabbox3df v);
|
||||
|
||||
//! Gets an attribute as a axis aligned bounding box
|
||||
//! \param attributeName: Name of the attribute to get.
|
||||
//! \return Returns value of the attribute previously set by setAttribute()
|
||||
virtual core::aabbox3df getAttributeAsBox3d(const c8* attributeName);
|
||||
|
||||
//! Gets an attribute as axis aligned bounding box
|
||||
//! \param index: Index value, must be between 0 and getAttributeCount()-1.
|
||||
virtual core::aabbox3df getAttributeAsBox3d(s32 index);
|
||||
|
||||
//! Sets an attribute as axis aligned bounding box
|
||||
virtual void setAttribute(s32 index, core::aabbox3df v);
|
||||
|
||||
/*
|
||||
|
||||
plane
|
||||
|
||||
*/
|
||||
|
||||
//! Adds an attribute as 3d plane
|
||||
virtual void addPlane3d(const c8* attributeName, core::plane3df v);
|
||||
|
||||
//! Sets an attribute as 3d plane
|
||||
virtual void setAttribute(const c8* attributeName, core::plane3df v);
|
||||
|
||||
//! Gets an attribute as a 3d plane
|
||||
//! \param attributeName: Name of the attribute to get.
|
||||
//! \return Returns value of the attribute previously set by setAttribute()
|
||||
virtual core::plane3df getAttributeAsPlane3d(const c8* attributeName);
|
||||
|
||||
//! Gets an attribute as 3d plane
|
||||
//! \param index: Index value, must be between 0 and getAttributeCount()-1.
|
||||
virtual core::plane3df getAttributeAsPlane3d(s32 index);
|
||||
|
||||
//! Sets an attribute as 3d plane
|
||||
virtual void setAttribute(s32 index, core::plane3df v);
|
||||
|
||||
|
||||
/*
|
||||
|
||||
3d triangle
|
||||
|
||||
*/
|
||||
|
||||
//! Adds an attribute as 3d triangle
|
||||
virtual void addTriangle3d(const c8* attributeName, core::triangle3df v);
|
||||
|
||||
//! Sets an attribute as 3d trianle
|
||||
virtual void setAttribute(const c8* attributeName, core::triangle3df v);
|
||||
|
||||
//! Gets an attribute as a 3d triangle
|
||||
//! \param attributeName: Name of the attribute to get.
|
||||
//! \return Returns value of the attribute previously set by setAttribute()
|
||||
virtual core::triangle3df getAttributeAsTriangle3d(const c8* attributeName);
|
||||
|
||||
//! Gets an attribute as 3d triangle
|
||||
//! \param index: Index value, must be between 0 and getAttributeCount()-1.
|
||||
virtual core::triangle3df getAttributeAsTriangle3d(s32 index);
|
||||
|
||||
//! Sets an attribute as 3d triangle
|
||||
virtual void setAttribute(s32 index, core::triangle3df v);
|
||||
|
||||
|
||||
/*
|
||||
|
||||
line 2d
|
||||
|
||||
*/
|
||||
|
||||
//! Adds an attribute as a 2d line
|
||||
virtual void addLine2d(const c8* attributeName, core::line2df v);
|
||||
|
||||
//! Sets an attribute as a 2d line
|
||||
virtual void setAttribute(const c8* attributeName, core::line2df v);
|
||||
|
||||
//! Gets an attribute as a 2d line
|
||||
//! \param attributeName: Name of the attribute to get.
|
||||
//! \return Returns value of the attribute previously set by setAttribute()
|
||||
virtual core::line2df getAttributeAsLine2d(const c8* attributeName);
|
||||
|
||||
//! Gets an attribute as a 2d line
|
||||
//! \param index: Index value, must be between 0 and getAttributeCount()-1.
|
||||
virtual core::line2df getAttributeAsLine2d(s32 index);
|
||||
|
||||
//! Sets an attribute as a 2d line
|
||||
virtual void setAttribute(s32 index, core::line2df v);
|
||||
|
||||
|
||||
/*
|
||||
|
||||
line 3d
|
||||
|
||||
*/
|
||||
|
||||
//! Adds an attribute as a 3d line
|
||||
virtual void addLine3d(const c8* attributeName, core::line3df v);
|
||||
|
||||
//! Sets an attribute as a 3d line
|
||||
virtual void setAttribute(const c8* attributeName, core::line3df v);
|
||||
|
||||
//! Gets an attribute as a 3d line
|
||||
//! \param attributeName: Name of the attribute to get.
|
||||
//! \return Returns value of the attribute previously set by setAttribute()
|
||||
virtual core::line3df getAttributeAsLine3d(const c8* attributeName);
|
||||
|
||||
//! Gets an attribute as a 3d line
|
||||
//! \param index: Index value, must be between 0 and getAttributeCount()-1.
|
||||
virtual core::line3df getAttributeAsLine3d(s32 index);
|
||||
|
||||
//! Sets an attribute as a 3d line
|
||||
virtual void setAttribute(s32 index, core::line3df v);
|
||||
|
||||
|
||||
/*
|
||||
|
||||
Texture Attribute
|
||||
|
||||
*/
|
||||
|
||||
//! Adds an attribute as texture reference
|
||||
virtual void addTexture(const c8* attributeName, video::ITexture* texture, const io::path& filename = "");
|
||||
|
||||
//! Sets an attribute as texture reference
|
||||
virtual void setAttribute(const c8* attributeName, video::ITexture* texture, const io::path& filename = "");
|
||||
|
||||
//! Gets an attribute as texture reference
|
||||
//! \param attributeName: Name of the attribute to get.
|
||||
virtual video::ITexture* getAttributeAsTexture(const c8* attributeName);
|
||||
|
||||
//! Gets an attribute as texture reference
|
||||
//! \param index: Index value, must be between 0 and getAttributeCount()-1.
|
||||
virtual video::ITexture* getAttributeAsTexture(s32 index);
|
||||
|
||||
//! Sets an attribute as texture reference
|
||||
virtual void setAttribute(s32 index, video::ITexture* texture, const io::path& filename = "");
|
||||
|
||||
|
||||
|
||||
/*
|
||||
|
||||
User Pointer Attribute
|
||||
|
||||
*/
|
||||
|
||||
//! Adds an attribute as user pointner
|
||||
virtual void addUserPointer(const c8* attributeName, void* userPointer);
|
||||
|
||||
//! Sets an attribute as user pointer
|
||||
virtual void setAttribute(const c8* attributeName, void* userPointer);
|
||||
|
||||
//! Gets an attribute as user pointer
|
||||
//! \param attributeName: Name of the attribute to get.
|
||||
virtual void* getAttributeAsUserPointer(const c8* attributeName);
|
||||
|
||||
//! Gets an attribute as user pointer
|
||||
//! \param index: Index value, must be between 0 and getAttributeCount()-1.
|
||||
virtual void* getAttributeAsUserPointer(s32 index);
|
||||
|
||||
//! Sets an attribute as user pointer
|
||||
virtual void setAttribute(s32 index, void* userPointer);
|
||||
|
||||
protected:
|
||||
|
||||
void readAttributeFromXML(io::IXMLReader* reader);
|
||||
|
||||
core::array<IAttribute*> Attributes;
|
||||
|
||||
IAttribute* getAttributeP(const c8* attributeName) const;
|
||||
|
||||
video::IVideoDriver* Driver;
|
||||
};
|
||||
|
||||
} // end namespace io
|
||||
} // end namespace irr
|
||||
|
||||
#endif
|
||||
|
1108
source/Irrlicht/CB3DMeshFileLoader.cpp
Normal file
1108
source/Irrlicht/CB3DMeshFileLoader.cpp
Normal file
File diff suppressed because it is too large
Load Diff
140
source/Irrlicht/CB3DMeshFileLoader.h
Normal file
140
source/Irrlicht/CB3DMeshFileLoader.h
Normal file
@ -0,0 +1,140 @@
|
||||
// Copyright (C) 2006-2012 Luke Hoschke
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
// B3D Mesh loader
|
||||
// File format designed by Mark Sibly for the Blitz3D engine and has been
|
||||
// declared public domain
|
||||
|
||||
#include "IrrCompileConfig.h"
|
||||
|
||||
#ifndef __C_B3D_MESH_LOADER_H_INCLUDED__
|
||||
#define __C_B3D_MESH_LOADER_H_INCLUDED__
|
||||
|
||||
#include "IMeshLoader.h"
|
||||
#include "ISceneManager.h"
|
||||
#include "CSkinnedMesh.h"
|
||||
#include "IReadFile.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
|
||||
namespace scene
|
||||
{
|
||||
|
||||
//! Meshloader for B3D format
|
||||
class CB3DMeshFileLoader : public IMeshLoader
|
||||
{
|
||||
public:
|
||||
|
||||
//! Constructor
|
||||
CB3DMeshFileLoader(scene::ISceneManager* smgr);
|
||||
|
||||
//! returns true if the file maybe is able to be loaded by this class
|
||||
//! based on the file extension (e.g. ".bsp")
|
||||
virtual bool isALoadableFileExtension(const io::path& filename) const;
|
||||
|
||||
//! creates/loads an animated mesh from the file.
|
||||
//! \return Pointer to the created mesh. Returns 0 if loading failed.
|
||||
//! If you no longer need the mesh, you should call IAnimatedMesh::drop().
|
||||
//! See IReferenceCounted::drop() for more information.
|
||||
virtual IAnimatedMesh* createMesh(io::IReadFile* file);
|
||||
|
||||
private:
|
||||
|
||||
struct SB3dChunkHeader
|
||||
{
|
||||
c8 name[4];
|
||||
s32 size;
|
||||
};
|
||||
|
||||
struct SB3dChunk
|
||||
{
|
||||
SB3dChunk(const SB3dChunkHeader& header, long sp)
|
||||
: length(header.size+8), startposition(sp)
|
||||
{
|
||||
name[0]=header.name[0];
|
||||
name[1]=header.name[1];
|
||||
name[2]=header.name[2];
|
||||
name[3]=header.name[3];
|
||||
}
|
||||
|
||||
c8 name[4];
|
||||
s32 length;
|
||||
long startposition;
|
||||
};
|
||||
|
||||
struct SB3dTexture
|
||||
{
|
||||
core::stringc TextureName;
|
||||
s32 Flags;
|
||||
s32 Blend;
|
||||
f32 Xpos;
|
||||
f32 Ypos;
|
||||
f32 Xscale;
|
||||
f32 Yscale;
|
||||
f32 Angle;
|
||||
};
|
||||
|
||||
struct SB3dMaterial
|
||||
{
|
||||
SB3dMaterial() : red(1.0f), green(1.0f),
|
||||
blue(1.0f), alpha(1.0f), shininess(0.0f), blend(1),
|
||||
fx(0)
|
||||
{
|
||||
for (u32 i=0; i<video::MATERIAL_MAX_TEXTURES; ++i)
|
||||
Textures[i]=0;
|
||||
}
|
||||
video::SMaterial Material;
|
||||
f32 red, green, blue, alpha;
|
||||
f32 shininess;
|
||||
s32 blend,fx;
|
||||
SB3dTexture *Textures[video::MATERIAL_MAX_TEXTURES];
|
||||
};
|
||||
|
||||
bool load();
|
||||
bool readChunkNODE(CSkinnedMesh::SJoint* InJoint);
|
||||
bool readChunkMESH(CSkinnedMesh::SJoint* InJoint);
|
||||
bool readChunkVRTS(CSkinnedMesh::SJoint* InJoint);
|
||||
bool readChunkTRIS(scene::SSkinMeshBuffer *MeshBuffer, u32 MeshBufferID, s32 Vertices_Start);
|
||||
bool readChunkBONE(CSkinnedMesh::SJoint* InJoint);
|
||||
bool readChunkKEYS(CSkinnedMesh::SJoint* InJoint);
|
||||
bool readChunkANIM();
|
||||
bool readChunkTEXS();
|
||||
bool readChunkBRUS();
|
||||
|
||||
void loadTextures(SB3dMaterial& material) const;
|
||||
|
||||
void readString(core::stringc& newstring);
|
||||
void readFloats(f32* vec, u32 count);
|
||||
|
||||
core::array<SB3dChunk> B3dStack;
|
||||
|
||||
core::array<SB3dMaterial> Materials;
|
||||
core::array<SB3dTexture> Textures;
|
||||
|
||||
core::array<s32> AnimatedVertices_VertexID;
|
||||
|
||||
core::array<s32> AnimatedVertices_BufferID;
|
||||
|
||||
core::array<video::S3DVertex2TCoords> BaseVertices;
|
||||
|
||||
ISceneManager* SceneManager;
|
||||
CSkinnedMesh* AnimatedMesh;
|
||||
io::IReadFile* B3DFile;
|
||||
|
||||
//B3Ds have Vertex ID's local within the mesh I don't want this
|
||||
// Variable needs to be class member due to recursion in calls
|
||||
u32 VerticesStart;
|
||||
|
||||
bool NormalsInFile;
|
||||
bool HasVertexColors;
|
||||
bool ShowWarning;
|
||||
};
|
||||
|
||||
|
||||
} // end namespace scene
|
||||
} // end namespace irr
|
||||
|
||||
#endif // __C_B3D_MESH_LOADER_H_INCLUDED__
|
||||
|
107
source/Irrlicht/CBSPMeshFileLoader.cpp
Normal file
107
source/Irrlicht/CBSPMeshFileLoader.cpp
Normal file
@ -0,0 +1,107 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#include "IrrCompileConfig.h"
|
||||
#ifdef _IRR_COMPILE_WITH_BSP_LOADER_
|
||||
|
||||
#include "CBSPMeshFileLoader.h"
|
||||
#include "CQ3LevelMesh.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace scene
|
||||
{
|
||||
|
||||
//! Constructor
|
||||
CBSPMeshFileLoader::CBSPMeshFileLoader(scene::ISceneManager* smgr,
|
||||
io::IFileSystem* fs)
|
||||
: FileSystem(fs), SceneManager(smgr)
|
||||
{
|
||||
|
||||
#ifdef _DEBUG
|
||||
setDebugName("CBSPMeshFileLoader");
|
||||
#endif
|
||||
|
||||
if (FileSystem)
|
||||
FileSystem->grab();
|
||||
}
|
||||
|
||||
|
||||
//! destructor
|
||||
CBSPMeshFileLoader::~CBSPMeshFileLoader()
|
||||
{
|
||||
if (FileSystem)
|
||||
FileSystem->drop();
|
||||
}
|
||||
|
||||
|
||||
//! returns true if the file maybe is able to be loaded by this class
|
||||
//! based on the file extension (e.g. ".bsp")
|
||||
bool CBSPMeshFileLoader::isALoadableFileExtension(const io::path& filename) const
|
||||
{
|
||||
return core::hasFileExtension ( filename, "bsp", "shader", "cfg" );
|
||||
}
|
||||
|
||||
|
||||
//! creates/loads an animated mesh from the file.
|
||||
//! \return Pointer to the created mesh. Returns 0 if loading failed.
|
||||
//! If you no longer need the mesh, you should call IAnimatedMesh::drop().
|
||||
//! See IReferenceCounted::drop() for more information.
|
||||
IAnimatedMesh* CBSPMeshFileLoader::createMesh(io::IReadFile* file)
|
||||
{
|
||||
s32 type = core::isFileExtension ( file->getFileName(), "bsp", "shader", "cfg" );
|
||||
CQ3LevelMesh* q = 0;
|
||||
|
||||
switch ( type )
|
||||
{
|
||||
case 1:
|
||||
q = new CQ3LevelMesh(FileSystem, SceneManager, LoadParam);
|
||||
|
||||
// determine real shaders in LoadParam
|
||||
if ( 0 == LoadParam.loadAllShaders )
|
||||
{
|
||||
q->getShader("scripts/common.shader");
|
||||
q->getShader("scripts/sfx.shader");
|
||||
q->getShader("scripts/gfx.shader");
|
||||
q->getShader("scripts/liquid.shader");
|
||||
q->getShader("scripts/models.shader");
|
||||
q->getShader("scripts/walls.shader");
|
||||
//q->getShader("scripts/sky.shader");
|
||||
}
|
||||
|
||||
if ( q->loadFile(file) )
|
||||
return q;
|
||||
|
||||
q->drop();
|
||||
break;
|
||||
|
||||
case 2:
|
||||
q = new CQ3LevelMesh(FileSystem, SceneManager,LoadParam);
|
||||
q->getShader( file );
|
||||
return q;
|
||||
break;
|
||||
|
||||
case 3:
|
||||
// load quake 3 loading parameter
|
||||
if ( file->getFileName() == "levelparameter.cfg" )
|
||||
{
|
||||
file->read ( &LoadParam, sizeof ( LoadParam ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
q = new CQ3LevelMesh(FileSystem, SceneManager,LoadParam);
|
||||
q->getConfiguration( file );
|
||||
return q;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
} // end namespace scene
|
||||
} // end namespace irr
|
||||
|
||||
#endif // _IRR_COMPILE_WITH_BSP_LOADER_
|
||||
|
52
source/Irrlicht/CBSPMeshFileLoader.h
Normal file
52
source/Irrlicht/CBSPMeshFileLoader.h
Normal file
@ -0,0 +1,52 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#ifndef __C_BSP_MESH_FILE_LOADER_H_INCLUDED__
|
||||
#define __C_BSP_MESH_FILE_LOADER_H_INCLUDED__
|
||||
|
||||
#include "IMeshLoader.h"
|
||||
#include "IFileSystem.h"
|
||||
#include "IVideoDriver.h"
|
||||
#include "ISceneManager.h"
|
||||
#include "IQ3Shader.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace scene
|
||||
{
|
||||
|
||||
//! Meshloader capable of loading Quake 3 BSP files and shaders
|
||||
class CBSPMeshFileLoader : public IMeshLoader
|
||||
{
|
||||
public:
|
||||
|
||||
//! Constructor
|
||||
CBSPMeshFileLoader(scene::ISceneManager* smgr, io::IFileSystem* fs);
|
||||
|
||||
//! destructor
|
||||
virtual ~CBSPMeshFileLoader();
|
||||
|
||||
//! returns true if the file maybe is able to be loaded by this class
|
||||
//! based on the file extension (e.g. ".bsp")
|
||||
virtual bool isALoadableFileExtension(const io::path& filename) const;
|
||||
|
||||
//! creates/loads an animated mesh from the file.
|
||||
//! \return Pointer to the created mesh. Returns 0 if loading failed.
|
||||
//! If you no longer need the mesh, you should call IAnimatedMesh::drop().
|
||||
//! See IReferenceCounted::drop() for more information.
|
||||
virtual IAnimatedMesh* createMesh(io::IReadFile* file);
|
||||
|
||||
private:
|
||||
|
||||
io::IFileSystem* FileSystem;
|
||||
scene::ISceneManager* SceneManager;
|
||||
|
||||
quake3::Q3LevelLoadParameter LoadParam;
|
||||
};
|
||||
|
||||
} // end namespace scene
|
||||
} // end namespace irr
|
||||
|
||||
#endif
|
||||
|
294
source/Irrlicht/CBillboardSceneNode.cpp
Normal file
294
source/Irrlicht/CBillboardSceneNode.cpp
Normal file
@ -0,0 +1,294 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#include "CBillboardSceneNode.h"
|
||||
#include "IVideoDriver.h"
|
||||
#include "ISceneManager.h"
|
||||
#include "ICameraSceneNode.h"
|
||||
#include "os.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace scene
|
||||
{
|
||||
|
||||
//! constructor
|
||||
CBillboardSceneNode::CBillboardSceneNode(ISceneNode* parent, ISceneManager* mgr, s32 id,
|
||||
const core::vector3df& position, const core::dimension2d<f32>& size,
|
||||
video::SColor colorTop, video::SColor colorBottom)
|
||||
: IBillboardSceneNode(parent, mgr, id, position)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
setDebugName("CBillboardSceneNode");
|
||||
#endif
|
||||
|
||||
setSize(size);
|
||||
|
||||
indices[0] = 0;
|
||||
indices[1] = 2;
|
||||
indices[2] = 1;
|
||||
indices[3] = 0;
|
||||
indices[4] = 3;
|
||||
indices[5] = 2;
|
||||
|
||||
vertices[0].TCoords.set(1.0f, 1.0f);
|
||||
vertices[0].Color = colorBottom;
|
||||
|
||||
vertices[1].TCoords.set(1.0f, 0.0f);
|
||||
vertices[1].Color = colorTop;
|
||||
|
||||
vertices[2].TCoords.set(0.0f, 0.0f);
|
||||
vertices[2].Color = colorTop;
|
||||
|
||||
vertices[3].TCoords.set(0.0f, 1.0f);
|
||||
vertices[3].Color = colorBottom;
|
||||
}
|
||||
|
||||
|
||||
//! pre render event
|
||||
void CBillboardSceneNode::OnRegisterSceneNode()
|
||||
{
|
||||
if (IsVisible)
|
||||
SceneManager->registerNodeForRendering(this);
|
||||
|
||||
ISceneNode::OnRegisterSceneNode();
|
||||
}
|
||||
|
||||
|
||||
//! render
|
||||
void CBillboardSceneNode::render()
|
||||
{
|
||||
video::IVideoDriver* driver = SceneManager->getVideoDriver();
|
||||
ICameraSceneNode* camera = SceneManager->getActiveCamera();
|
||||
|
||||
if (!camera || !driver)
|
||||
return;
|
||||
|
||||
// make billboard look to camera
|
||||
|
||||
core::vector3df pos = getAbsolutePosition();
|
||||
|
||||
core::vector3df campos = camera->getAbsolutePosition();
|
||||
core::vector3df target = camera->getTarget();
|
||||
core::vector3df up = camera->getUpVector();
|
||||
core::vector3df view = target - campos;
|
||||
view.normalize();
|
||||
|
||||
core::vector3df horizontal = up.crossProduct(view);
|
||||
if ( horizontal.getLength() == 0 )
|
||||
{
|
||||
horizontal.set(up.Y,up.X,up.Z);
|
||||
}
|
||||
horizontal.normalize();
|
||||
core::vector3df topHorizontal = horizontal * 0.5f * TopEdgeWidth;
|
||||
horizontal *= 0.5f * Size.Width;
|
||||
|
||||
// pointing down!
|
||||
core::vector3df vertical = horizontal.crossProduct(view);
|
||||
vertical.normalize();
|
||||
vertical *= 0.5f * Size.Height;
|
||||
|
||||
view *= -1.0f;
|
||||
|
||||
for (s32 i=0; i<4; ++i)
|
||||
vertices[i].Normal = view;
|
||||
|
||||
/* Vertices are:
|
||||
2--1
|
||||
|\ |
|
||||
| \|
|
||||
3--0
|
||||
*/
|
||||
vertices[0].Pos = pos + horizontal + vertical;
|
||||
vertices[1].Pos = pos + topHorizontal - vertical;
|
||||
vertices[2].Pos = pos - topHorizontal - vertical;
|
||||
vertices[3].Pos = pos - horizontal + vertical;
|
||||
|
||||
// draw
|
||||
|
||||
if (DebugDataVisible & scene::EDS_BBOX)
|
||||
{
|
||||
driver->setTransform(video::ETS_WORLD, AbsoluteTransformation);
|
||||
video::SMaterial m;
|
||||
m.Lighting = false;
|
||||
driver->setMaterial(m);
|
||||
driver->draw3DBox(BBox, video::SColor(0,208,195,152));
|
||||
}
|
||||
|
||||
driver->setTransform(video::ETS_WORLD, core::IdentityMatrix);
|
||||
|
||||
driver->setMaterial(Material);
|
||||
|
||||
driver->drawIndexedTriangleList(vertices, 4, indices, 2);
|
||||
}
|
||||
|
||||
|
||||
//! returns the axis aligned bounding box of this node
|
||||
const core::aabbox3d<f32>& CBillboardSceneNode::getBoundingBox() const
|
||||
{
|
||||
return BBox;
|
||||
}
|
||||
|
||||
|
||||
//! sets the size of the billboard
|
||||
void CBillboardSceneNode::setSize(const core::dimension2d<f32>& size)
|
||||
{
|
||||
Size = size;
|
||||
|
||||
if (core::equals(Size.Width, 0.0f))
|
||||
Size.Width = 1.0f;
|
||||
TopEdgeWidth = Size.Width;
|
||||
|
||||
if (core::equals(Size.Height, 0.0f))
|
||||
Size.Height = 1.0f;
|
||||
|
||||
const f32 avg = (Size.Width + Size.Height)/6;
|
||||
BBox.MinEdge.set(-avg,-avg,-avg);
|
||||
BBox.MaxEdge.set(avg,avg,avg);
|
||||
}
|
||||
|
||||
|
||||
void CBillboardSceneNode::setSize(f32 height, f32 bottomEdgeWidth, f32 topEdgeWidth)
|
||||
{
|
||||
Size.set(bottomEdgeWidth, height);
|
||||
TopEdgeWidth = topEdgeWidth;
|
||||
|
||||
if (core::equals(Size.Height, 0.0f))
|
||||
Size.Height = 1.0f;
|
||||
|
||||
if (core::equals(Size.Width, 0.f) && core::equals(TopEdgeWidth, 0.f))
|
||||
{
|
||||
Size.Width = 1.0f;
|
||||
TopEdgeWidth = 1.0f;
|
||||
}
|
||||
|
||||
const f32 avg = (core::max_(Size.Width,TopEdgeWidth) + Size.Height)/6;
|
||||
BBox.MinEdge.set(-avg,-avg,-avg);
|
||||
BBox.MaxEdge.set(avg,avg,avg);
|
||||
}
|
||||
|
||||
|
||||
video::SMaterial& CBillboardSceneNode::getMaterial(u32 i)
|
||||
{
|
||||
return Material;
|
||||
}
|
||||
|
||||
|
||||
//! returns amount of materials used by this scene node.
|
||||
u32 CBillboardSceneNode::getMaterialCount() const
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
//! gets the size of the billboard
|
||||
const core::dimension2d<f32>& CBillboardSceneNode::getSize() const
|
||||
{
|
||||
return Size;
|
||||
}
|
||||
|
||||
|
||||
//! Gets the widths of the top and bottom edges of the billboard.
|
||||
void CBillboardSceneNode::getSize(f32& height, f32& bottomEdgeWidth,
|
||||
f32& topEdgeWidth) const
|
||||
{
|
||||
height = Size.Height;
|
||||
bottomEdgeWidth = Size.Width;
|
||||
topEdgeWidth = TopEdgeWidth;
|
||||
}
|
||||
|
||||
|
||||
//! Writes attributes of the scene node.
|
||||
void CBillboardSceneNode::serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options) const
|
||||
{
|
||||
IBillboardSceneNode::serializeAttributes(out, options);
|
||||
|
||||
out->addFloat("Width", Size.Width);
|
||||
out->addFloat("TopEdgeWidth", TopEdgeWidth);
|
||||
out->addFloat("Height", Size.Height);
|
||||
out->addColor("Shade_Top", vertices[1].Color);
|
||||
out->addColor("Shade_Down", vertices[0].Color);
|
||||
}
|
||||
|
||||
|
||||
//! Reads attributes of the scene node.
|
||||
void CBillboardSceneNode::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options)
|
||||
{
|
||||
IBillboardSceneNode::deserializeAttributes(in, options);
|
||||
|
||||
Size.Width = in->getAttributeAsFloat("Width");
|
||||
Size.Height = in->getAttributeAsFloat("Height");
|
||||
|
||||
if (in->existsAttribute("TopEdgeWidth"))
|
||||
{
|
||||
TopEdgeWidth = in->getAttributeAsFloat("TopEdgeWidth");
|
||||
if (Size.Width != TopEdgeWidth)
|
||||
setSize(Size.Height, Size.Width, TopEdgeWidth);
|
||||
}
|
||||
else
|
||||
setSize(Size);
|
||||
vertices[1].Color = in->getAttributeAsColor("Shade_Top");
|
||||
vertices[0].Color = in->getAttributeAsColor("Shade_Down");
|
||||
vertices[2].Color = vertices[1].Color;
|
||||
vertices[3].Color = vertices[0].Color;
|
||||
}
|
||||
|
||||
|
||||
//! Set the color of all vertices of the billboard
|
||||
//! \param overallColor: the color to set
|
||||
void CBillboardSceneNode::setColor(const video::SColor& overallColor)
|
||||
{
|
||||
for(u32 vertex = 0; vertex < 4; ++vertex)
|
||||
vertices[vertex].Color = overallColor;
|
||||
}
|
||||
|
||||
|
||||
//! Set the color of the top and bottom vertices of the billboard
|
||||
//! \param topColor: the color to set the top vertices
|
||||
//! \param bottomColor: the color to set the bottom vertices
|
||||
void CBillboardSceneNode::setColor(const video::SColor& topColor,
|
||||
const video::SColor& bottomColor)
|
||||
{
|
||||
vertices[0].Color = bottomColor;
|
||||
vertices[1].Color = topColor;
|
||||
vertices[2].Color = topColor;
|
||||
vertices[3].Color = bottomColor;
|
||||
}
|
||||
|
||||
|
||||
//! Gets the color of the top and bottom vertices of the billboard
|
||||
//! \param[out] topColor: stores the color of the top vertices
|
||||
//! \param[out] bottomColor: stores the color of the bottom vertices
|
||||
void CBillboardSceneNode::getColor(video::SColor& topColor,
|
||||
video::SColor& bottomColor) const
|
||||
{
|
||||
bottomColor = vertices[0].Color;
|
||||
topColor = vertices[1].Color;
|
||||
}
|
||||
|
||||
|
||||
//! Creates a clone of this scene node and its children.
|
||||
ISceneNode* CBillboardSceneNode::clone(ISceneNode* newParent, ISceneManager* newManager)
|
||||
{
|
||||
if (!newParent)
|
||||
newParent = Parent;
|
||||
if (!newManager)
|
||||
newManager = SceneManager;
|
||||
|
||||
CBillboardSceneNode* nb = new CBillboardSceneNode(newParent,
|
||||
newManager, ID, RelativeTranslation, Size);
|
||||
|
||||
nb->cloneMembers(this, newManager);
|
||||
nb->Material = Material;
|
||||
nb->TopEdgeWidth = this->TopEdgeWidth;
|
||||
|
||||
if ( newParent )
|
||||
nb->drop();
|
||||
return nb;
|
||||
}
|
||||
|
||||
|
||||
} // end namespace scene
|
||||
} // end namespace irr
|
||||
|
99
source/Irrlicht/CBillboardSceneNode.h
Normal file
99
source/Irrlicht/CBillboardSceneNode.h
Normal file
@ -0,0 +1,99 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#ifndef __C_BILLBOARD_SCENE_NODE_H_INCLUDED__
|
||||
#define __C_BILLBOARD_SCENE_NODE_H_INCLUDED__
|
||||
|
||||
#include "IBillboardSceneNode.h"
|
||||
#include "S3DVertex.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace scene
|
||||
{
|
||||
|
||||
//! Scene node which is a billboard. A billboard is like a 3d sprite: A 2d element,
|
||||
//! which always looks to the camera.
|
||||
class CBillboardSceneNode : virtual public IBillboardSceneNode
|
||||
{
|
||||
public:
|
||||
|
||||
//! constructor
|
||||
CBillboardSceneNode(ISceneNode* parent, ISceneManager* mgr, s32 id,
|
||||
const core::vector3df& position, const core::dimension2d<f32>& size,
|
||||
video::SColor colorTop=video::SColor(0xFFFFFFFF),
|
||||
video::SColor colorBottom=video::SColor(0xFFFFFFFF));
|
||||
|
||||
//! pre render event
|
||||
virtual void OnRegisterSceneNode();
|
||||
|
||||
//! render
|
||||
virtual void render();
|
||||
|
||||
//! returns the axis aligned bounding box of this node
|
||||
virtual const core::aabbox3d<f32>& getBoundingBox() const;
|
||||
|
||||
//! sets the size of the billboard
|
||||
virtual void setSize(const core::dimension2d<f32>& size);
|
||||
|
||||
//! Sets the widths of the top and bottom edges of the billboard independently.
|
||||
virtual void setSize(f32 height, f32 bottomEdgeWidth, f32 topEdgeWidth);
|
||||
|
||||
//! gets the size of the billboard
|
||||
virtual const core::dimension2d<f32>& getSize() const;
|
||||
|
||||
//! Gets the widths of the top and bottom edges of the billboard.
|
||||
virtual void getSize(f32& height, f32& bottomEdgeWidth, f32& topEdgeWidth) const;
|
||||
|
||||
virtual video::SMaterial& getMaterial(u32 i);
|
||||
|
||||
//! returns amount of materials used by this scene node.
|
||||
virtual u32 getMaterialCount() const;
|
||||
|
||||
//! Set the color of all vertices of the billboard
|
||||
//! \param overallColor: the color to set
|
||||
virtual void setColor(const video::SColor& overallColor);
|
||||
|
||||
//! Set the color of the top and bottom vertices of the billboard
|
||||
//! \param topColor: the color to set the top vertices
|
||||
//! \param bottomColor: the color to set the bottom vertices
|
||||
virtual void setColor(const video::SColor& topColor,
|
||||
const video::SColor& bottomColor);
|
||||
|
||||
//! Gets the color of the top and bottom vertices of the billboard
|
||||
//! \param[out] topColor: stores the color of the top vertices
|
||||
//! \param[out] bottomColor: stores the color of the bottom vertices
|
||||
virtual void getColor(video::SColor& topColor,
|
||||
video::SColor& bottomColor) const;
|
||||
|
||||
//! Writes attributes of the scene node.
|
||||
virtual void serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options=0) const;
|
||||
|
||||
//! Reads attributes of the scene node.
|
||||
virtual void deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options=0);
|
||||
|
||||
//! Returns type of the scene node
|
||||
virtual ESCENE_NODE_TYPE getType() const { return ESNT_BILLBOARD; }
|
||||
|
||||
//! Creates a clone of this scene node and its children.
|
||||
virtual ISceneNode* clone(ISceneNode* newParent=0, ISceneManager* newManager=0);
|
||||
|
||||
private:
|
||||
|
||||
//! Size.Width is the bottom edge width
|
||||
core::dimension2d<f32> Size;
|
||||
f32 TopEdgeWidth;
|
||||
core::aabbox3d<f32> BBox;
|
||||
video::SMaterial Material;
|
||||
|
||||
video::S3DVertex vertices[4];
|
||||
u16 indices[6];
|
||||
};
|
||||
|
||||
|
||||
} // end namespace scene
|
||||
} // end namespace irr
|
||||
|
||||
#endif
|
||||
|
1273
source/Irrlicht/CBlit.h
Normal file
1273
source/Irrlicht/CBlit.h
Normal file
File diff suppressed because it is too large
Load Diff
129
source/Irrlicht/CBoneSceneNode.cpp
Normal file
129
source/Irrlicht/CBoneSceneNode.cpp
Normal file
@ -0,0 +1,129 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#include "IrrCompileConfig.h"
|
||||
#ifdef _IRR_COMPILE_WITH_SKINNED_MESH_SUPPORT_
|
||||
|
||||
#include "CBoneSceneNode.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace scene
|
||||
{
|
||||
|
||||
//! constructor
|
||||
CBoneSceneNode::CBoneSceneNode(ISceneNode* parent, ISceneManager* mgr, s32 id,
|
||||
u32 boneIndex, const c8* boneName)
|
||||
: IBoneSceneNode(parent, mgr, id), BoneIndex(boneIndex),
|
||||
AnimationMode(EBAM_AUTOMATIC), SkinningSpace(EBSS_LOCAL)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
setDebugName("CBoneSceneNode");
|
||||
#endif
|
||||
setName(boneName);
|
||||
}
|
||||
|
||||
|
||||
//! Returns the index of the bone
|
||||
u32 CBoneSceneNode::getBoneIndex() const
|
||||
{
|
||||
return BoneIndex;
|
||||
}
|
||||
|
||||
|
||||
//! Sets the animation mode of the bone. Returns true if successful.
|
||||
bool CBoneSceneNode::setAnimationMode(E_BONE_ANIMATION_MODE mode)
|
||||
{
|
||||
AnimationMode = mode;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
//! Gets the current animation mode of the bone
|
||||
E_BONE_ANIMATION_MODE CBoneSceneNode::getAnimationMode() const
|
||||
{
|
||||
return AnimationMode;
|
||||
}
|
||||
|
||||
|
||||
//! returns the axis aligned bounding box of this node
|
||||
const core::aabbox3d<f32>& CBoneSceneNode::getBoundingBox() const
|
||||
{
|
||||
return Box;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
//! Returns the relative transformation of the scene node.
|
||||
core::matrix4 CBoneSceneNode::getRelativeTransformation() const
|
||||
{
|
||||
return core::matrix4(); // RelativeTransformation;
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
void CBoneSceneNode::OnAnimate(u32 timeMs)
|
||||
{
|
||||
if (IsVisible)
|
||||
{
|
||||
// animate this node with all animators
|
||||
|
||||
ISceneNodeAnimatorList::Iterator ait = Animators.begin();
|
||||
for (; ait != Animators.end(); ++ait)
|
||||
(*ait)->animateNode(this, timeMs);
|
||||
|
||||
// update absolute position
|
||||
//updateAbsolutePosition();
|
||||
|
||||
// perform the post render process on all children
|
||||
ISceneNodeList::Iterator it = Children.begin();
|
||||
for (; it != Children.end(); ++it)
|
||||
(*it)->OnAnimate(timeMs);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CBoneSceneNode::helper_updateAbsolutePositionOfAllChildren(ISceneNode *Node)
|
||||
{
|
||||
Node->updateAbsolutePosition();
|
||||
|
||||
ISceneNodeList::ConstIterator it = Node->getChildren().begin();
|
||||
for (; it != Node->getChildren().end(); ++it)
|
||||
{
|
||||
helper_updateAbsolutePositionOfAllChildren( (*it) );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CBoneSceneNode::updateAbsolutePositionOfAllChildren()
|
||||
{
|
||||
helper_updateAbsolutePositionOfAllChildren( this );
|
||||
}
|
||||
|
||||
|
||||
void CBoneSceneNode::serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options) const
|
||||
{
|
||||
IBoneSceneNode::serializeAttributes(out, options);
|
||||
out->addInt("BoneIndex", BoneIndex);
|
||||
out->addEnum("AnimationMode", AnimationMode, BoneAnimationModeNames);
|
||||
}
|
||||
|
||||
|
||||
void CBoneSceneNode::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options)
|
||||
{
|
||||
BoneIndex = in->getAttributeAsInt("BoneIndex");
|
||||
AnimationMode = (E_BONE_ANIMATION_MODE)in->getAttributeAsEnumeration("AnimationMode", BoneAnimationModeNames);
|
||||
// for legacy files (before 1.5)
|
||||
const core::stringc boneName = in->getAttributeAsString("BoneName");
|
||||
setName(boneName);
|
||||
IBoneSceneNode::deserializeAttributes(in, options);
|
||||
// TODO: add/replace bone in parent with bone from mesh
|
||||
}
|
||||
|
||||
|
||||
} // namespace scene
|
||||
} // namespace irr
|
||||
|
||||
#endif
|
||||
|
79
source/Irrlicht/CBoneSceneNode.h
Normal file
79
source/Irrlicht/CBoneSceneNode.h
Normal file
@ -0,0 +1,79 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#ifndef __C_BONE_SCENE_NODE_H_INCLUDED__
|
||||
#define __C_BONE_SCENE_NODE_H_INCLUDED__
|
||||
|
||||
// Used with SkinnedMesh and IAnimatedMeshSceneNode, for boned meshes
|
||||
|
||||
#include "IBoneSceneNode.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace scene
|
||||
{
|
||||
|
||||
class CBoneSceneNode : public IBoneSceneNode
|
||||
{
|
||||
public:
|
||||
|
||||
//! constructor
|
||||
CBoneSceneNode(ISceneNode* parent, ISceneManager* mgr,
|
||||
s32 id=-1, u32 boneIndex=0, const c8* boneName=0);
|
||||
|
||||
//! Returns the index of the bone
|
||||
virtual u32 getBoneIndex() const;
|
||||
|
||||
//! Sets the animation mode of the bone. Returns true if successful.
|
||||
virtual bool setAnimationMode(E_BONE_ANIMATION_MODE mode);
|
||||
|
||||
//! Gets the current animation mode of the bone
|
||||
virtual E_BONE_ANIMATION_MODE getAnimationMode() const;
|
||||
|
||||
//! returns the axis aligned bounding box of this node
|
||||
virtual const core::aabbox3d<f32>& getBoundingBox() const;
|
||||
|
||||
/*
|
||||
//! Returns the relative transformation of the scene node.
|
||||
//virtual core::matrix4 getRelativeTransformation() const;
|
||||
*/
|
||||
|
||||
virtual void OnAnimate(u32 timeMs);
|
||||
|
||||
virtual void updateAbsolutePositionOfAllChildren();
|
||||
|
||||
//! Writes attributes of the scene node.
|
||||
virtual void serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options=0) const;
|
||||
|
||||
//! Reads attributes of the scene node.
|
||||
virtual void deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options=0);
|
||||
|
||||
//! How the relative transformation of the bone is used
|
||||
virtual void setSkinningSpace( E_BONE_SKINNING_SPACE space )
|
||||
{
|
||||
SkinningSpace=space;
|
||||
}
|
||||
|
||||
virtual E_BONE_SKINNING_SPACE getSkinningSpace() const
|
||||
{
|
||||
return SkinningSpace;
|
||||
}
|
||||
|
||||
private:
|
||||
void helper_updateAbsolutePositionOfAllChildren(ISceneNode *Node);
|
||||
|
||||
u32 BoneIndex;
|
||||
|
||||
core::aabbox3d<f32> Box;
|
||||
|
||||
E_BONE_ANIMATION_MODE AnimationMode;
|
||||
E_BONE_SKINNING_SPACE SkinningSpace;
|
||||
};
|
||||
|
||||
|
||||
} // end namespace scene
|
||||
} // end namespace irr
|
||||
|
||||
#endif
|
||||
|
1143
source/Irrlicht/CBurningShader_Raster_Reference.cpp
Normal file
1143
source/Irrlicht/CBurningShader_Raster_Reference.cpp
Normal file
File diff suppressed because it is too large
Load Diff
872
source/Irrlicht/CCSMLoader.cpp
Normal file
872
source/Irrlicht/CCSMLoader.cpp
Normal file
@ -0,0 +1,872 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
//
|
||||
// This file was written by Saurav Mohapatra and modified by Nikolaus Gebhardt.
|
||||
// See CCSMLoader.h for details.
|
||||
|
||||
#include "IrrCompileConfig.h"
|
||||
#ifdef _IRR_COMPILE_WITH_CSM_LOADER_
|
||||
|
||||
#include "CCSMLoader.h"
|
||||
#include "os.h"
|
||||
#include "IFileSystem.h"
|
||||
#include "IReadFile.h"
|
||||
#include "ISceneManager.h"
|
||||
#include "IAttributes.h"
|
||||
#include "SMesh.h"
|
||||
#include "IVideoDriver.h"
|
||||
#include "SAnimatedMesh.h"
|
||||
#include "SMeshBufferLightMap.h"
|
||||
|
||||
#ifdef _DEBUG
|
||||
#define _IRR_DEBUG_CSM_LOADER_
|
||||
#endif
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace scene
|
||||
{
|
||||
//
|
||||
// the CSM data types
|
||||
//
|
||||
struct color_rgb_t
|
||||
{
|
||||
s32 red;
|
||||
s32 green;
|
||||
s32 blue;
|
||||
|
||||
color_rgb_t() : red(0), green(0), blue(0) {}
|
||||
void clear() { red=0; green=0; blue=0; }
|
||||
video::SColor toSColor() const { return video::SColor(255, red, green, blue); }
|
||||
};
|
||||
|
||||
|
||||
//
|
||||
// A Binary File Reader
|
||||
//
|
||||
struct BinaryFileReader
|
||||
{
|
||||
BinaryFileReader(io::IReadFile* pFile) : file(pFile) { }
|
||||
|
||||
s32 readBuffer(void* buffer, s32 len)
|
||||
{
|
||||
return file->read(buffer,len);
|
||||
}
|
||||
|
||||
s32 readLong();
|
||||
f32 readFloat();
|
||||
|
||||
void readString(core::stringc &str);
|
||||
void readVec3f(core::vector3df* v);
|
||||
void readVec2f(core::vector2df* v);
|
||||
void readColorRGB(color_rgb_t* color);
|
||||
|
||||
io::IReadFile *file;
|
||||
};
|
||||
|
||||
//
|
||||
// The file header
|
||||
//
|
||||
class Header
|
||||
{
|
||||
public:
|
||||
|
||||
enum E_CSM_VERSION
|
||||
{
|
||||
VERSION_4 = 4,
|
||||
VERSION_4_1 = 5
|
||||
};
|
||||
|
||||
Header(){ clear(); }
|
||||
|
||||
s32 getVersion() const { return version; }
|
||||
void clear(){ version = 0; }
|
||||
void load(BinaryFileReader* pReader)
|
||||
{
|
||||
version = pReader->readLong();
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
s32 version;
|
||||
};
|
||||
|
||||
|
||||
//
|
||||
// The groups
|
||||
//
|
||||
class Group
|
||||
{
|
||||
public:
|
||||
|
||||
Group(){ clear(); }
|
||||
~Group(){ clear(); }
|
||||
|
||||
void clear();
|
||||
void load(BinaryFileReader* pReader);
|
||||
|
||||
s32 getFlags() const { return flags; }
|
||||
s32 getParentGroupID() const { return parentGroup; }
|
||||
const core::stringc& getProperties() const { return props; }
|
||||
video::SColor getColor() const { return color.toSColor(); }
|
||||
|
||||
private:
|
||||
|
||||
s32 flags;
|
||||
s32 parentGroup;
|
||||
core::stringc props;
|
||||
color_rgb_t color;
|
||||
};
|
||||
|
||||
|
||||
//
|
||||
// The visgroups
|
||||
//
|
||||
class VisGroup
|
||||
{
|
||||
public:
|
||||
|
||||
VisGroup(){ clear(); }
|
||||
~VisGroup(){ clear(); }
|
||||
void clear();
|
||||
void load(BinaryFileReader* pReader);
|
||||
|
||||
s32 getFlags() const{ return flags; }
|
||||
const core::stringc& getName() const{ return name; }
|
||||
video::SColor getColor() const{ return color.toSColor(); }
|
||||
|
||||
private:
|
||||
|
||||
core::stringc name;
|
||||
s32 flags;
|
||||
color_rgb_t color;
|
||||
};
|
||||
|
||||
|
||||
//
|
||||
// Lightmaps
|
||||
//
|
||||
class LightMap
|
||||
{
|
||||
public:
|
||||
|
||||
LightMap() : pixelData(0){ clear(); }
|
||||
~LightMap(){ clear(); }
|
||||
void clear();
|
||||
void load(BinaryFileReader* pReader);
|
||||
s32 getWidth() const{ return width; }
|
||||
s32 getHeight() const{ return height; }
|
||||
s32* getPixelData() const{ return pixelData; }
|
||||
|
||||
private:
|
||||
|
||||
s32 width;
|
||||
s32 height;
|
||||
s32* pixelData;
|
||||
};
|
||||
|
||||
struct Triangle
|
||||
{
|
||||
s32 a,b,c;
|
||||
};
|
||||
|
||||
|
||||
struct Line
|
||||
{
|
||||
s32 a,b;
|
||||
};
|
||||
|
||||
|
||||
class Vertex
|
||||
{
|
||||
public:
|
||||
|
||||
Vertex(){ clear(); }
|
||||
~Vertex(){ clear(); }
|
||||
void clear();
|
||||
void load(BinaryFileReader* pReader);
|
||||
|
||||
const core::vector3df& getPosition() const { return position; }
|
||||
const core::vector3df& getNormal() const { return normal; }
|
||||
video::SColor getColor() const { return color.toSColor(); }
|
||||
const core::vector3df& getTextureCoordinates() const { return texCoords; }
|
||||
const core::vector3df& getLightMapCoordinates() const { return lmapCoords; }
|
||||
|
||||
private:
|
||||
|
||||
core::vector3df position;
|
||||
core::vector3df normal;
|
||||
color_rgb_t color;
|
||||
core::vector3df texCoords;
|
||||
core::vector3df lmapCoords;
|
||||
};
|
||||
|
||||
|
||||
class Surface
|
||||
{
|
||||
public:
|
||||
|
||||
Surface() { clear(); }
|
||||
~Surface(){ clear(); }
|
||||
|
||||
void clear();
|
||||
void load(BinaryFileReader *pReader);
|
||||
|
||||
s32 getFlags() const{ return flags; }
|
||||
const core::stringc& getTextureName() const{ return textureName; }
|
||||
s32 getLightMapId() const{ return lightMapId; }
|
||||
const core::vector2df* getUVOffset() const{ return &uvOffset; }
|
||||
const core::vector2df* getUVScale() const{ return &uvScale; }
|
||||
f32 getUVRotation() const{ return uvRotation; }
|
||||
|
||||
u32 getVertexCount() const{ return vertices.size(); }
|
||||
const Vertex& getVertexAt(const s32 index) const{ return vertices[index]; }
|
||||
|
||||
u32 getTriangleCount() const{ return triangles.size(); }
|
||||
const Triangle& getTriangleAt(const s32 index) const{ return triangles[index]; }
|
||||
|
||||
private:
|
||||
|
||||
s32 flags;
|
||||
core::stringc textureName;
|
||||
s32 lightMapId;
|
||||
core::vector2df uvOffset;
|
||||
core::vector2df uvScale;
|
||||
f32 uvRotation;
|
||||
core::array<Vertex> vertices;
|
||||
core::array<Triangle> triangles;
|
||||
core::array<Line> lines;
|
||||
};
|
||||
|
||||
class Mesh
|
||||
{
|
||||
public:
|
||||
|
||||
Mesh(){ clear(); }
|
||||
~Mesh(){ clear(); }
|
||||
|
||||
void clear();
|
||||
void load(BinaryFileReader* pReader, bool bReadVisGroups);
|
||||
|
||||
s32 getFlags() const { return flags; }
|
||||
s32 getGroupID() const { return groupId; }
|
||||
const core::stringc& getProperties() const { return props; }
|
||||
video::SColor getColor() const { return color.toSColor(); }
|
||||
const core::vector3df* getPosition() const { return &position; }
|
||||
s32 getVisgroupID() const { return visgroupId; }
|
||||
s32 getSurfaceCount() const { return surfaces.size(); }
|
||||
const Surface* getSurfaceAt(const s32 index) const { return surfaces[index]; }
|
||||
|
||||
private:
|
||||
|
||||
s32 flags;
|
||||
s32 groupId;
|
||||
core::stringc props;
|
||||
color_rgb_t color;
|
||||
core::vector3df position;
|
||||
s32 visgroupId;
|
||||
|
||||
core::array<Surface*> surfaces;
|
||||
};
|
||||
|
||||
class Entity
|
||||
{
|
||||
public:
|
||||
|
||||
Entity() { clear(); }
|
||||
~Entity() { clear(); }
|
||||
|
||||
void clear();
|
||||
void load(BinaryFileReader* pReader);
|
||||
s32 getVisgroupID() const { return visgroupId; }
|
||||
s32 getGroupID() const { return groupId; }
|
||||
const core::stringc& getProperties() const { return props; }
|
||||
const core::vector3df* getPosition() const { return &position; }
|
||||
|
||||
private:
|
||||
|
||||
s32 visgroupId;
|
||||
s32 groupId;
|
||||
core::stringc props;
|
||||
core::vector3df position;
|
||||
};
|
||||
|
||||
|
||||
class CameraData
|
||||
{
|
||||
public:
|
||||
|
||||
CameraData(){ clear(); }
|
||||
~CameraData(){ clear(); }
|
||||
|
||||
void clear();
|
||||
void load(BinaryFileReader* pReader);
|
||||
|
||||
const core::vector3df* getPosition(){ return &position; }
|
||||
f32 getPitch(){ return pitch; }
|
||||
f32 getYaw(){ return yaw; }
|
||||
|
||||
private:
|
||||
|
||||
core::vector3df position;
|
||||
f32 pitch;
|
||||
f32 yaw;
|
||||
};
|
||||
|
||||
//
|
||||
// A CSM File
|
||||
//
|
||||
class CSMFile
|
||||
{
|
||||
public:
|
||||
|
||||
CSMFile(){ clear(); }
|
||||
~CSMFile(){ clear(); }
|
||||
void clear();
|
||||
void load(BinaryFileReader* pReader);
|
||||
|
||||
const Header* getHeader() const{ return &header; }
|
||||
|
||||
u32 getGroupCount() const{ return groups.size(); }
|
||||
const Group* getGroupAt(const s32 index) const{ return groups[index]; }
|
||||
|
||||
u32 getVisGroupCount() const{ return visgroups.size(); }
|
||||
const VisGroup* getVisGroupAt(const s32 index) const{ return visgroups[index]; }
|
||||
|
||||
u32 getLightMapCount() const{ return lightmaps.size(); }
|
||||
const LightMap* getLightMapAt(const s32 index) const { return lightmaps[index]; }
|
||||
|
||||
u32 getMeshCount() const{ return meshes.size(); }
|
||||
const Mesh* getMeshAt(const s32 index) const{ return meshes[index]; }
|
||||
|
||||
u32 getEntityCount() const{ return entities.size(); }
|
||||
const Entity* getEntityAt(const s32 index) const{ return entities[index]; }
|
||||
|
||||
const CameraData* getCameraData() const{ return &cameraData; }
|
||||
|
||||
private:
|
||||
|
||||
Header header;
|
||||
core::array<Group*> groups;
|
||||
core::array<VisGroup*> visgroups;
|
||||
core::array<LightMap*> lightmaps;
|
||||
core::array<Mesh*> meshes;
|
||||
core::array<Entity*> entities;
|
||||
CameraData cameraData;
|
||||
};
|
||||
|
||||
CCSMLoader::CCSMLoader(scene::ISceneManager* manager, io::IFileSystem* fs)
|
||||
: FileSystem(fs), SceneManager(manager)
|
||||
{
|
||||
|
||||
#ifdef _DEBUG
|
||||
setDebugName("CCSMLoader");
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
//! returns true if the file maybe is able to be loaded by this class
|
||||
//! based on the file extension (e.g. ".bsp")
|
||||
bool CCSMLoader::isALoadableFileExtension(const io::path& filename) const
|
||||
{
|
||||
return core::hasFileExtension ( filename, "csm" );
|
||||
}
|
||||
|
||||
|
||||
//! creates/loads an animated mesh from the file.
|
||||
IAnimatedMesh* CCSMLoader::createMesh(io::IReadFile* file)
|
||||
{
|
||||
scene::IMesh* m = createCSMMesh(file);
|
||||
|
||||
if (!m)
|
||||
return 0;
|
||||
|
||||
SAnimatedMesh* am = new SAnimatedMesh();
|
||||
am->Type = EAMT_CSM;
|
||||
am->addMesh(m);
|
||||
m->drop();
|
||||
|
||||
am->recalculateBoundingBox();
|
||||
return am;
|
||||
}
|
||||
|
||||
scene::IMesh* CCSMLoader::createCSMMesh(io::IReadFile* file)
|
||||
{
|
||||
if (!file)
|
||||
return 0;
|
||||
|
||||
BinaryFileReader reader(file);
|
||||
CSMFile csmFile;
|
||||
csmFile.load(&reader);
|
||||
|
||||
return createIrrlichtMesh(&csmFile,
|
||||
SceneManager->getParameters()->getAttributeAsString(CSM_TEXTURE_PATH),
|
||||
file->getFileName());
|
||||
}
|
||||
|
||||
|
||||
scene::IMesh* CCSMLoader::createIrrlichtMesh(const CSMFile* csmFile,
|
||||
const core::stringc& textureRoot, const io::path& lmprefix)
|
||||
{
|
||||
scene::SMesh *pMesh = new scene::SMesh();
|
||||
video::IVideoDriver* driver = SceneManager->getVideoDriver();
|
||||
|
||||
for(u32 l = 0; l<csmFile->getLightMapCount(); l++)
|
||||
{
|
||||
const LightMap* lmap = csmFile->getLightMapAt(l);
|
||||
|
||||
io::path lmapName = lmprefix;
|
||||
lmapName += "LMAP_";
|
||||
lmapName += io::path(l+1);
|
||||
os::Printer::log("CCSMLoader loading light map", lmapName.c_str());
|
||||
|
||||
video::IImage* lmapImg = driver->createImageFromData(
|
||||
video::ECF_A8R8G8B8,
|
||||
core::dimension2d<u32>(lmap->getWidth(),lmap->getHeight()),
|
||||
lmap->getPixelData());
|
||||
|
||||
driver->addTexture(lmapName.c_str(), lmapImg);
|
||||
lmapImg->drop();
|
||||
}
|
||||
|
||||
for(u32 m = 0; m<csmFile->getMeshCount(); m++)
|
||||
{
|
||||
const Mesh* mshPtr = csmFile->getMeshAt(m);
|
||||
|
||||
for(s32 s = 0; s < mshPtr->getSurfaceCount(); s++)
|
||||
{
|
||||
const Surface* surface = mshPtr->getSurfaceAt(s);
|
||||
|
||||
core::stringc texName;
|
||||
if (textureRoot.size())
|
||||
{
|
||||
texName += textureRoot;
|
||||
texName += "/";
|
||||
}
|
||||
texName+= surface->getTextureName();
|
||||
|
||||
video::ITexture* texture = 0;
|
||||
if (texName.size())
|
||||
{
|
||||
if (FileSystem->existFile(texName))
|
||||
texture = driver->getTexture(texName);
|
||||
else if (FileSystem->existFile(surface->getTextureName()))
|
||||
texture = driver->getTexture(surface->getTextureName());
|
||||
else if (FileSystem->existFile(FileSystem->getFileBasename(surface->getTextureName())))
|
||||
texture = driver->getTexture(FileSystem->getFileBasename(surface->getTextureName()));
|
||||
else if (FileSystem->existFile(FileSystem->getFileDir(lmprefix)+"/"+surface->getTextureName()))
|
||||
texture = driver->getTexture(FileSystem->getFileDir(lmprefix)+"/"+surface->getTextureName());
|
||||
else
|
||||
texture = driver->getTexture(FileSystem->getFileDir(lmprefix)+"/"+FileSystem->getFileBasename(surface->getTextureName()));
|
||||
}
|
||||
|
||||
//material
|
||||
io::path lmapName = lmprefix;
|
||||
lmapName += "LMAP_";
|
||||
lmapName += io::path(surface->getLightMapId());
|
||||
|
||||
scene::SMeshBufferLightMap *buffer = new scene::SMeshBufferLightMap();
|
||||
buffer->Material.setTexture(0, texture);
|
||||
if (surface->getLightMapId())
|
||||
{
|
||||
buffer->Material.setTexture(1, driver->getTexture(lmapName));
|
||||
buffer->Material.Lighting = false;
|
||||
buffer->Material.MaterialType = video::EMT_LIGHTMAP_ADD;
|
||||
}
|
||||
|
||||
buffer->Vertices.reallocate(surface->getVertexCount());
|
||||
for(u32 v = 0; v < surface->getVertexCount(); ++v)
|
||||
{
|
||||
const Vertex& vtxPtr = surface->getVertexAt(v);
|
||||
video::S3DVertex2TCoords vtx;
|
||||
vtx.Pos = vtxPtr.getPosition();
|
||||
vtx.Normal = vtxPtr.getPosition();
|
||||
vtx.Color=vtxPtr.getColor();
|
||||
vtx.TCoords.set(vtxPtr.getTextureCoordinates().X, 1.f-vtxPtr.getTextureCoordinates().Y);
|
||||
vtx.TCoords2.set(vtxPtr.getLightMapCoordinates().X, 1.f-vtxPtr.getLightMapCoordinates().Y);
|
||||
|
||||
buffer->Vertices.push_back(vtx);
|
||||
}
|
||||
|
||||
buffer->Indices.reallocate(surface->getTriangleCount()*3);
|
||||
for(u32 t = 0; t < surface->getTriangleCount(); ++t)
|
||||
{
|
||||
const Triangle& tri = surface->getTriangleAt(t);
|
||||
buffer->Indices.push_back(tri.c);
|
||||
buffer->Indices.push_back(tri.b);
|
||||
buffer->Indices.push_back(tri.a);
|
||||
}
|
||||
|
||||
buffer->recalculateBoundingBox();
|
||||
pMesh->addMeshBuffer(buffer);
|
||||
buffer->drop();
|
||||
}
|
||||
}
|
||||
|
||||
pMesh->recalculateBoundingBox();
|
||||
return pMesh;
|
||||
}
|
||||
|
||||
void Group::clear()
|
||||
{
|
||||
color.clear();
|
||||
flags = 0;
|
||||
parentGroup = 0;
|
||||
props = "";
|
||||
}
|
||||
|
||||
void Group::load(BinaryFileReader* pReader)
|
||||
{
|
||||
flags = pReader->readLong();
|
||||
parentGroup = pReader->readLong();
|
||||
pReader->readString(props);
|
||||
pReader->readColorRGB(&color);
|
||||
}
|
||||
|
||||
void VisGroup::clear()
|
||||
{
|
||||
color.clear();
|
||||
flags = 0;
|
||||
name = "";
|
||||
}
|
||||
|
||||
void VisGroup::load(BinaryFileReader* pReader)
|
||||
{
|
||||
pReader->readString(name);
|
||||
flags = pReader->readLong();
|
||||
pReader->readColorRGB(&color);
|
||||
}
|
||||
|
||||
void LightMap::clear()
|
||||
{
|
||||
delete[] pixelData;
|
||||
pixelData = 0;
|
||||
width = height = 0;
|
||||
}
|
||||
|
||||
void LightMap::load(BinaryFileReader* pReader)
|
||||
{
|
||||
width = pReader->readLong();
|
||||
height = pReader->readLong();
|
||||
pixelData = new s32[width * height];
|
||||
pReader->readBuffer(pixelData, width * height * sizeof(s32));
|
||||
}
|
||||
|
||||
void Mesh::clear()
|
||||
{
|
||||
flags = 0;
|
||||
groupId = 0;
|
||||
visgroupId = 0;
|
||||
props = "";
|
||||
color.clear();
|
||||
position.set(0,0,0);
|
||||
|
||||
for(u32 s = 0; s < surfaces.size(); s++)
|
||||
{
|
||||
delete surfaces[s];
|
||||
}
|
||||
surfaces.clear();
|
||||
}
|
||||
|
||||
void Mesh::load(BinaryFileReader* pReader, bool bReadVisGroups)
|
||||
{
|
||||
flags = pReader->readLong();
|
||||
groupId = pReader->readLong();
|
||||
pReader->readString(props);
|
||||
pReader->readColorRGB(&color);
|
||||
pReader->readVec3f(&position);
|
||||
if(bReadVisGroups)
|
||||
visgroupId = pReader->readLong();
|
||||
else
|
||||
visgroupId = 0;
|
||||
|
||||
s32 count = pReader->readLong();
|
||||
|
||||
for(s32 i = 0; i < count; i++)
|
||||
{
|
||||
Surface* surf = new Surface();
|
||||
surf->load(pReader);
|
||||
surfaces.push_back(surf);
|
||||
}
|
||||
}
|
||||
|
||||
void Surface::clear()
|
||||
{
|
||||
flags = 0;
|
||||
lightMapId = 0;
|
||||
textureName = "";
|
||||
uvOffset.set(0.0f,0.0f);
|
||||
uvScale.set(0.0f,0.0f);
|
||||
uvRotation = 0.0f;
|
||||
triangles.clear();
|
||||
lines.clear();
|
||||
vertices.clear();
|
||||
}
|
||||
|
||||
void Surface::load(BinaryFileReader* pReader)
|
||||
{
|
||||
flags = pReader->readLong();
|
||||
pReader->readString(textureName);
|
||||
textureName.replace('\\', '/');
|
||||
|
||||
lightMapId = pReader->readLong();
|
||||
pReader->readVec2f(&uvOffset);
|
||||
pReader->readVec2f(&uvScale);
|
||||
uvRotation = pReader->readFloat();
|
||||
s32 vtxCount = pReader->readLong();
|
||||
s32 triCount = pReader->readLong();
|
||||
s32 lineCount = pReader->readLong();
|
||||
|
||||
for(s32 v = 0; v < vtxCount; v++)
|
||||
{
|
||||
vertices.push_back(Vertex());
|
||||
vertices.getLast().load(pReader);
|
||||
}
|
||||
|
||||
for(s32 t = 0; t < triCount; t++)
|
||||
{
|
||||
Triangle tri;
|
||||
pReader->readBuffer(&tri, sizeof(tri));
|
||||
triangles.push_back(tri);
|
||||
}
|
||||
|
||||
for(s32 l = 0; l < lineCount; l++)
|
||||
{
|
||||
Line line;
|
||||
pReader->readBuffer(&line,sizeof(line));
|
||||
lines.push_back(line);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void Vertex::clear()
|
||||
{
|
||||
position.set(0,0,0);
|
||||
normal.set(0,0,0);
|
||||
color.clear();
|
||||
texCoords.set(0,0,0);
|
||||
lmapCoords.set(0,0,0);
|
||||
}
|
||||
|
||||
void Vertex::load(BinaryFileReader* pReader)
|
||||
{
|
||||
pReader->readVec3f(&position);
|
||||
pReader->readVec3f(&normal);
|
||||
pReader->readColorRGB(&color);
|
||||
pReader->readVec3f(&texCoords);
|
||||
pReader->readVec3f(&lmapCoords);
|
||||
}
|
||||
|
||||
void Entity::clear()
|
||||
{
|
||||
visgroupId = groupId = 0;
|
||||
props = "";
|
||||
position.set(0,0,0);
|
||||
}
|
||||
|
||||
void Entity::load(BinaryFileReader* pReader)
|
||||
{
|
||||
visgroupId = pReader->readLong();
|
||||
groupId = pReader->readLong();
|
||||
pReader->readString(props);
|
||||
pReader->readVec3f(&position);
|
||||
}
|
||||
|
||||
void CameraData::clear()
|
||||
{
|
||||
position.set(0,0,0);
|
||||
pitch = 0;
|
||||
yaw = 0;
|
||||
}
|
||||
|
||||
void CameraData::load(BinaryFileReader* pReader)
|
||||
{
|
||||
pReader->readVec3f(&position);
|
||||
pitch = pReader->readFloat();
|
||||
yaw = pReader->readFloat();
|
||||
}
|
||||
|
||||
void CSMFile::clear()
|
||||
{
|
||||
header.clear();
|
||||
cameraData.clear();
|
||||
|
||||
u32 x =0;
|
||||
for( x= 0; x < groups.size(); x++)
|
||||
delete groups[x];
|
||||
|
||||
groups.clear();
|
||||
|
||||
for(x= 0; x < visgroups.size(); x++)
|
||||
delete visgroups[x];
|
||||
|
||||
visgroups.clear();
|
||||
|
||||
for(x= 0; x < lightmaps.size(); x++)
|
||||
delete lightmaps[x];
|
||||
|
||||
lightmaps.clear();
|
||||
|
||||
for(x= 0; x < meshes.size(); x++)
|
||||
delete meshes[x];
|
||||
|
||||
meshes.clear();
|
||||
|
||||
for(x= 0; x < entities.size(); x++)
|
||||
delete entities[x];
|
||||
|
||||
entities.clear();
|
||||
}
|
||||
|
||||
void CSMFile::load(BinaryFileReader* pReader)
|
||||
{
|
||||
clear();
|
||||
|
||||
header.load(pReader);
|
||||
|
||||
//groups
|
||||
{
|
||||
const s32 count = pReader->readLong();
|
||||
#ifdef _IRR_DEBUG_CSM_LOADER_
|
||||
os::Printer::log("CSM Version", core::stringc(header.getVersion()).c_str());
|
||||
os::Printer::log("Loading groups. Count", core::stringc(count));
|
||||
#endif
|
||||
|
||||
groups.reallocate(count);
|
||||
for (s32 i = 0; i < count; i++)
|
||||
{
|
||||
Group* grp = new Group();
|
||||
grp->load(pReader);
|
||||
groups.push_back(grp);
|
||||
}
|
||||
}
|
||||
const bool bHasVGroups = (header.getVersion() == Header::VERSION_4_1);
|
||||
|
||||
if (bHasVGroups)
|
||||
{
|
||||
//visgroups
|
||||
const s32 count = pReader->readLong();
|
||||
#ifdef _IRR_DEBUG_CSM_LOADER_
|
||||
os::Printer::log("Loading visgroups. Count", core::stringc(count));
|
||||
#endif
|
||||
|
||||
visgroups.reallocate(count);
|
||||
for (s32 i = 0; i < count; i++)
|
||||
{
|
||||
VisGroup* grp = new VisGroup();
|
||||
grp->load(pReader);
|
||||
visgroups.push_back(grp);
|
||||
}
|
||||
}
|
||||
|
||||
//lightmaps
|
||||
{
|
||||
const s32 count = pReader->readLong();
|
||||
#ifdef _IRR_DEBUG_CSM_LOADER_
|
||||
os::Printer::log("Loading lightmaps. Count", core::stringc(count));
|
||||
#endif
|
||||
|
||||
lightmaps.reallocate(count);
|
||||
for(s32 i = 0; i < count; i++)
|
||||
{
|
||||
LightMap* lm = new LightMap();
|
||||
lm->load(pReader);
|
||||
lightmaps.push_back(lm);
|
||||
}
|
||||
}
|
||||
|
||||
//meshes
|
||||
{
|
||||
const s32 count = pReader->readLong();
|
||||
#ifdef _IRR_DEBUG_CSM_LOADER_
|
||||
os::Printer::log("Loading meshes. Count", core::stringc(count));
|
||||
#endif
|
||||
|
||||
meshes.reallocate(count);
|
||||
for(s32 i = 0; i < count; i++)
|
||||
{
|
||||
Mesh* mesh = new Mesh();
|
||||
mesh->load(pReader,bHasVGroups);
|
||||
meshes.push_back(mesh);
|
||||
}
|
||||
}
|
||||
|
||||
//entities
|
||||
{
|
||||
const s32 count = pReader->readLong();
|
||||
#ifdef _IRR_DEBUG_CSM_LOADER_
|
||||
os::Printer::log("Loading entitites. Count", core::stringc(count));
|
||||
#endif
|
||||
|
||||
entities.reallocate(count);
|
||||
for(s32 i = 0; i < count; i++)
|
||||
{
|
||||
Entity* ent = new Entity();
|
||||
ent->load(pReader);
|
||||
entities.push_back(ent);
|
||||
}
|
||||
}
|
||||
|
||||
//camera data
|
||||
#ifdef _IRR_DEBUG_CSM_LOADER_
|
||||
os::Printer::log("Loading camera data.");
|
||||
#endif
|
||||
cameraData.load(pReader);
|
||||
}
|
||||
|
||||
s32 BinaryFileReader::readLong()
|
||||
{
|
||||
int ret = 0;
|
||||
readBuffer(&ret,sizeof(int));
|
||||
#ifdef __BIG_ENDIAN__
|
||||
ret = os::Byteswap::byteswap(ret);
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
|
||||
f32 BinaryFileReader::readFloat()
|
||||
{
|
||||
float ret = 0;
|
||||
readBuffer(&ret,sizeof(float));
|
||||
#ifdef __BIG_ENDIAN__
|
||||
ret = os::Byteswap::byteswap(ret);
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
|
||||
void BinaryFileReader::readString(core::stringc &str)
|
||||
{
|
||||
str = "";
|
||||
c8 c;
|
||||
readBuffer(&c,sizeof(char));
|
||||
while(c != 0)
|
||||
{
|
||||
str += c;
|
||||
readBuffer(&c,sizeof(char));
|
||||
}
|
||||
}
|
||||
|
||||
void BinaryFileReader::readVec3f(core::vector3df* v)
|
||||
{
|
||||
v->X = readFloat();
|
||||
v->Y = readFloat();
|
||||
v->Z = readFloat();
|
||||
}
|
||||
|
||||
void BinaryFileReader::readVec2f(core::vector2df* v)
|
||||
{
|
||||
v->X = readFloat();
|
||||
v->Y = readFloat();
|
||||
}
|
||||
|
||||
void BinaryFileReader::readColorRGB(color_rgb_t* color)
|
||||
{
|
||||
readBuffer(color,sizeof(color_rgb_t));
|
||||
}
|
||||
|
||||
} // end namespace
|
||||
} // end namespace
|
||||
|
||||
#endif // _IRR_COMPILE_WITH_CSM_LOADER_
|
82
source/Irrlicht/CCSMLoader.h
Normal file
82
source/Irrlicht/CCSMLoader.h
Normal file
@ -0,0 +1,82 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
//
|
||||
// This Loader has been originally written by Saurav Mohapatra. I (Nikolaus Gebhardt)
|
||||
// modified some minor things and integrated it into Irrlicht 0.9. Thanks a lot
|
||||
// to Saurav Mohapatra for his work on this and that he gave me his permission to
|
||||
// add it into Irrlicht.
|
||||
// I did some changes to Saurav Mohapatra's loader, so I'm writing this down here:
|
||||
// - Replaced all dependencies to STL and stdio with irr:: methods/constructs.
|
||||
// - Moved everything into namespace irr::scene
|
||||
// - Replaced logging with Irrlicht's internal logger.
|
||||
// - Removed dependency to IrrlichtDevice
|
||||
// - Moved all internal structures into CCSMLoader.cpp
|
||||
// - Made the texture root parameter dependent on a ISceneManager string parameter
|
||||
// - removed exceptions
|
||||
// - Implemented CCCSMLoader as IMeshLoader
|
||||
// - Fixed some problems with memory leaks
|
||||
// - Fixed bounding box calculation
|
||||
//
|
||||
// The original readme of this file looks like this:
|
||||
//
|
||||
// This component provides a loader for the Cartography shop 4.x .csm maps for Irrlicht Engine.
|
||||
// This is a part of the M_TRIX Project.
|
||||
// This is licensed under the ZLib/LibPNG license
|
||||
// The IrrCSM library is written by Saurav Mohapatra.
|
||||
//
|
||||
// Features
|
||||
//
|
||||
// The IrrCSM library features the following capabilities
|
||||
//
|
||||
// * Loads the .csm 4.0 and 4.1 files transparently
|
||||
// * Presents the loaded file as irr::scene::IAnimatedMesh for easy creation of IOctreeSceneNode
|
||||
// * Loads the textures given the correct texture root. hence map and textures can be in separate directories
|
||||
//
|
||||
// For more informations go to http://www.geocities.com/standard_template/irrcsm/downloads.html
|
||||
|
||||
#ifndef __CSM_LOADER_H_INCLUDED__
|
||||
#define __CSM_LOADER_H_INCLUDED__
|
||||
|
||||
#include "irrArray.h"
|
||||
#include "IMesh.h"
|
||||
#include "irrString.h"
|
||||
#include "IFileSystem.h"
|
||||
#include "IMeshLoader.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace scene
|
||||
{
|
||||
class CSMFile;
|
||||
class ISceneManager;
|
||||
|
||||
class CCSMLoader : public scene::IMeshLoader
|
||||
{
|
||||
public:
|
||||
|
||||
CCSMLoader(ISceneManager* manager, io::IFileSystem* fs);
|
||||
|
||||
//! returns true if the file maybe is able to be loaded by this class
|
||||
//! based on the file extension (e.g. ".bsp")
|
||||
virtual bool isALoadableFileExtension(const io::path& filename) const;
|
||||
|
||||
//! creates/loads an animated mesh from the file.
|
||||
virtual IAnimatedMesh* createMesh(io::IReadFile* file);
|
||||
|
||||
private:
|
||||
|
||||
scene::IMesh* createCSMMesh(io::IReadFile* file);
|
||||
|
||||
scene::IMesh* createIrrlichtMesh(const CSMFile* csmFile,
|
||||
const core::stringc& textureRoot, const io::path& lmprefix);
|
||||
|
||||
io::IFileSystem* FileSystem;
|
||||
scene::ISceneManager* SceneManager;
|
||||
};
|
||||
|
||||
} // end namespace
|
||||
} // end namespace
|
||||
|
||||
#endif
|
||||
|
385
source/Irrlicht/CCameraSceneNode.cpp
Normal file
385
source/Irrlicht/CCameraSceneNode.cpp
Normal file
@ -0,0 +1,385 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#include "CCameraSceneNode.h"
|
||||
#include "ISceneManager.h"
|
||||
#include "IVideoDriver.h"
|
||||
#include "os.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace scene
|
||||
{
|
||||
|
||||
|
||||
//! constructor
|
||||
CCameraSceneNode::CCameraSceneNode(ISceneNode* parent, ISceneManager* mgr, s32 id,
|
||||
const core::vector3df& position, const core::vector3df& lookat)
|
||||
: ICameraSceneNode(parent, mgr, id, position),
|
||||
Target(lookat), UpVector(0.0f, 1.0f, 0.0f), ZNear(1.0f), ZFar(3000.0f),
|
||||
InputReceiverEnabled(true), TargetAndRotationAreBound(false)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
setDebugName("CCameraSceneNode");
|
||||
#endif
|
||||
|
||||
// set default projection
|
||||
Fovy = core::PI / 2.5f; // Field of view, in radians.
|
||||
|
||||
const video::IVideoDriver* const d = mgr?mgr->getVideoDriver():0;
|
||||
if (d)
|
||||
Aspect = (f32)d->getCurrentRenderTargetSize().Width /
|
||||
(f32)d->getCurrentRenderTargetSize().Height;
|
||||
else
|
||||
Aspect = 4.0f / 3.0f; // Aspect ratio.
|
||||
|
||||
recalculateProjectionMatrix();
|
||||
recalculateViewArea();
|
||||
}
|
||||
|
||||
|
||||
//! Disables or enables the camera to get key or mouse inputs.
|
||||
void CCameraSceneNode::setInputReceiverEnabled(bool enabled)
|
||||
{
|
||||
InputReceiverEnabled = enabled;
|
||||
}
|
||||
|
||||
|
||||
//! Returns if the input receiver of the camera is currently enabled.
|
||||
bool CCameraSceneNode::isInputReceiverEnabled() const
|
||||
{
|
||||
_IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX;
|
||||
return InputReceiverEnabled;
|
||||
}
|
||||
|
||||
|
||||
//! Sets the projection matrix of the camera.
|
||||
/** The core::matrix4 class has some methods
|
||||
to build a projection matrix. e.g: core::matrix4::buildProjectionMatrixPerspectiveFovLH
|
||||
\param projection: The new projection matrix of the camera. */
|
||||
void CCameraSceneNode::setProjectionMatrix(const core::matrix4& projection, bool isOrthogonal)
|
||||
{
|
||||
IsOrthogonal = isOrthogonal;
|
||||
ViewArea.getTransform ( video::ETS_PROJECTION ) = projection;
|
||||
}
|
||||
|
||||
|
||||
//! Gets the current projection matrix of the camera
|
||||
//! \return Returns the current projection matrix of the camera.
|
||||
const core::matrix4& CCameraSceneNode::getProjectionMatrix() const
|
||||
{
|
||||
return ViewArea.getTransform ( video::ETS_PROJECTION );
|
||||
}
|
||||
|
||||
|
||||
//! Gets the current view matrix of the camera
|
||||
//! \return Returns the current view matrix of the camera.
|
||||
const core::matrix4& CCameraSceneNode::getViewMatrix() const
|
||||
{
|
||||
return ViewArea.getTransform ( video::ETS_VIEW );
|
||||
}
|
||||
|
||||
|
||||
//! Sets a custom view matrix affector. The matrix passed here, will be
|
||||
//! multiplied with the view matrix when it gets updated.
|
||||
//! This allows for custom camera setups like, for example, a reflection camera.
|
||||
/** \param affector: The affector matrix. */
|
||||
void CCameraSceneNode::setViewMatrixAffector(const core::matrix4& affector)
|
||||
{
|
||||
Affector = affector;
|
||||
}
|
||||
|
||||
|
||||
//! Gets the custom view matrix affector.
|
||||
const core::matrix4& CCameraSceneNode::getViewMatrixAffector() const
|
||||
{
|
||||
return Affector;
|
||||
}
|
||||
|
||||
|
||||
//! It is possible to send mouse and key events to the camera. Most cameras
|
||||
//! may ignore this input, but camera scene nodes which are created for
|
||||
//! example with scene::ISceneManager::addMayaCameraSceneNode or
|
||||
//! scene::ISceneManager::addFPSCameraSceneNode, may want to get this input
|
||||
//! for changing their position, look at target or whatever.
|
||||
bool CCameraSceneNode::OnEvent(const SEvent& event)
|
||||
{
|
||||
if (!InputReceiverEnabled)
|
||||
return false;
|
||||
|
||||
// send events to event receiving animators
|
||||
|
||||
ISceneNodeAnimatorList::Iterator ait = Animators.begin();
|
||||
|
||||
for (; ait != Animators.end(); ++ait)
|
||||
if ((*ait)->isEventReceiverEnabled() && (*ait)->OnEvent(event))
|
||||
return true;
|
||||
|
||||
// if nobody processed the event, return false
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
//! sets the look at target of the camera
|
||||
//! \param pos: Look at target of the camera.
|
||||
void CCameraSceneNode::setTarget(const core::vector3df& pos)
|
||||
{
|
||||
Target = pos;
|
||||
|
||||
if(TargetAndRotationAreBound)
|
||||
{
|
||||
const core::vector3df toTarget = Target - getAbsolutePosition();
|
||||
ISceneNode::setRotation(toTarget.getHorizontalAngle());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//! Sets the rotation of the node.
|
||||
/** This only modifies the relative rotation of the node.
|
||||
If the camera's target and rotation are bound ( @see bindTargetAndRotation() )
|
||||
then calling this will also change the camera's target to match the rotation.
|
||||
\param rotation New rotation of the node in degrees. */
|
||||
void CCameraSceneNode::setRotation(const core::vector3df& rotation)
|
||||
{
|
||||
if(TargetAndRotationAreBound)
|
||||
Target = getAbsolutePosition() + rotation.rotationToDirection();
|
||||
|
||||
ISceneNode::setRotation(rotation);
|
||||
}
|
||||
|
||||
|
||||
//! Gets the current look at target of the camera
|
||||
//! \return Returns the current look at target of the camera
|
||||
const core::vector3df& CCameraSceneNode::getTarget() const
|
||||
{
|
||||
return Target;
|
||||
}
|
||||
|
||||
|
||||
//! sets the up vector of the camera
|
||||
//! \param pos: New upvector of the camera.
|
||||
void CCameraSceneNode::setUpVector(const core::vector3df& pos)
|
||||
{
|
||||
UpVector = pos;
|
||||
}
|
||||
|
||||
|
||||
//! Gets the up vector of the camera.
|
||||
//! \return Returns the up vector of the camera.
|
||||
const core::vector3df& CCameraSceneNode::getUpVector() const
|
||||
{
|
||||
return UpVector;
|
||||
}
|
||||
|
||||
|
||||
f32 CCameraSceneNode::getNearValue() const
|
||||
{
|
||||
return ZNear;
|
||||
}
|
||||
|
||||
|
||||
f32 CCameraSceneNode::getFarValue() const
|
||||
{
|
||||
return ZFar;
|
||||
}
|
||||
|
||||
|
||||
f32 CCameraSceneNode::getAspectRatio() const
|
||||
{
|
||||
return Aspect;
|
||||
}
|
||||
|
||||
|
||||
f32 CCameraSceneNode::getFOV() const
|
||||
{
|
||||
return Fovy;
|
||||
}
|
||||
|
||||
|
||||
void CCameraSceneNode::setNearValue(f32 f)
|
||||
{
|
||||
ZNear = f;
|
||||
recalculateProjectionMatrix();
|
||||
}
|
||||
|
||||
|
||||
void CCameraSceneNode::setFarValue(f32 f)
|
||||
{
|
||||
ZFar = f;
|
||||
recalculateProjectionMatrix();
|
||||
}
|
||||
|
||||
|
||||
void CCameraSceneNode::setAspectRatio(f32 f)
|
||||
{
|
||||
Aspect = f;
|
||||
recalculateProjectionMatrix();
|
||||
}
|
||||
|
||||
|
||||
void CCameraSceneNode::setFOV(f32 f)
|
||||
{
|
||||
Fovy = f;
|
||||
recalculateProjectionMatrix();
|
||||
}
|
||||
|
||||
|
||||
void CCameraSceneNode::recalculateProjectionMatrix()
|
||||
{
|
||||
ViewArea.getTransform ( video::ETS_PROJECTION ).buildProjectionMatrixPerspectiveFovLH(Fovy, Aspect, ZNear, ZFar);
|
||||
}
|
||||
|
||||
|
||||
//! prerender
|
||||
void CCameraSceneNode::OnRegisterSceneNode()
|
||||
{
|
||||
if ( SceneManager->getActiveCamera () == this )
|
||||
SceneManager->registerNodeForRendering(this, ESNRP_CAMERA);
|
||||
|
||||
ISceneNode::OnRegisterSceneNode();
|
||||
}
|
||||
|
||||
|
||||
//! render
|
||||
void CCameraSceneNode::render()
|
||||
{
|
||||
core::vector3df pos = getAbsolutePosition();
|
||||
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:
|
||||
core::vector3df up = UpVector;
|
||||
up.normalize();
|
||||
|
||||
f32 dp = tgtv.dotProduct(up);
|
||||
|
||||
if ( core::equals(core::abs_<f32>(dp), 1.f) )
|
||||
{
|
||||
up.X += 0.5f;
|
||||
}
|
||||
|
||||
ViewArea.getTransform(video::ETS_VIEW).buildCameraLookAtMatrixLH(pos, Target, up);
|
||||
ViewArea.getTransform(video::ETS_VIEW) *= Affector;
|
||||
recalculateViewArea();
|
||||
|
||||
video::IVideoDriver* driver = SceneManager->getVideoDriver();
|
||||
if ( driver)
|
||||
{
|
||||
driver->setTransform(video::ETS_PROJECTION, ViewArea.getTransform ( video::ETS_PROJECTION) );
|
||||
driver->setTransform(video::ETS_VIEW, ViewArea.getTransform ( video::ETS_VIEW) );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//! returns the axis aligned bounding box of this node
|
||||
const core::aabbox3d<f32>& CCameraSceneNode::getBoundingBox() const
|
||||
{
|
||||
return ViewArea.getBoundingBox();
|
||||
}
|
||||
|
||||
|
||||
//! returns the view frustum. needed sometimes by bsp or lod render nodes.
|
||||
const SViewFrustum* CCameraSceneNode::getViewFrustum() const
|
||||
{
|
||||
return &ViewArea;
|
||||
}
|
||||
|
||||
|
||||
void CCameraSceneNode::recalculateViewArea()
|
||||
{
|
||||
ViewArea.cameraPosition = getAbsolutePosition();
|
||||
|
||||
core::matrix4 m(core::matrix4::EM4CONST_NOTHING);
|
||||
m.setbyproduct_nocheck(ViewArea.getTransform(video::ETS_PROJECTION),
|
||||
ViewArea.getTransform(video::ETS_VIEW));
|
||||
ViewArea.setFrom(m);
|
||||
}
|
||||
|
||||
|
||||
//! Writes attributes of the scene node.
|
||||
void CCameraSceneNode::serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options) const
|
||||
{
|
||||
ICameraSceneNode::serializeAttributes(out, options);
|
||||
|
||||
out->addVector3d("Target", Target);
|
||||
out->addVector3d("UpVector", UpVector);
|
||||
out->addFloat("Fovy", Fovy);
|
||||
out->addFloat("Aspect", Aspect);
|
||||
out->addFloat("ZNear", ZNear);
|
||||
out->addFloat("ZFar", ZFar);
|
||||
out->addBool("Binding", TargetAndRotationAreBound);
|
||||
out->addBool("ReceiveInput", InputReceiverEnabled);
|
||||
}
|
||||
|
||||
//! Reads attributes of the scene node.
|
||||
void CCameraSceneNode::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options)
|
||||
{
|
||||
ICameraSceneNode::deserializeAttributes(in, options);
|
||||
|
||||
Target = in->getAttributeAsVector3d("Target");
|
||||
UpVector = in->getAttributeAsVector3d("UpVector");
|
||||
Fovy = in->getAttributeAsFloat("Fovy");
|
||||
Aspect = in->getAttributeAsFloat("Aspect");
|
||||
ZNear = in->getAttributeAsFloat("ZNear");
|
||||
ZFar = in->getAttributeAsFloat("ZFar");
|
||||
TargetAndRotationAreBound = in->getAttributeAsBool("Binding");
|
||||
if ( in->findAttribute("ReceiveInput") )
|
||||
InputReceiverEnabled = in->getAttributeAsBool("ReceiveInput");
|
||||
|
||||
recalculateProjectionMatrix();
|
||||
recalculateViewArea();
|
||||
}
|
||||
|
||||
|
||||
//! Set the binding between the camera's rotation adn target.
|
||||
void CCameraSceneNode::bindTargetAndRotation(bool bound)
|
||||
{
|
||||
TargetAndRotationAreBound = bound;
|
||||
}
|
||||
|
||||
|
||||
//! Gets the binding between the camera's rotation and target.
|
||||
bool CCameraSceneNode::getTargetAndRotationBinding(void) const
|
||||
{
|
||||
return TargetAndRotationAreBound;
|
||||
}
|
||||
|
||||
|
||||
//! Creates a clone of this scene node and its children.
|
||||
ISceneNode* CCameraSceneNode::clone(ISceneNode* newParent, ISceneManager* newManager)
|
||||
{
|
||||
ICameraSceneNode::clone(newParent, newManager);
|
||||
|
||||
if (!newParent)
|
||||
newParent = Parent;
|
||||
if (!newManager)
|
||||
newManager = SceneManager;
|
||||
|
||||
CCameraSceneNode* nb = new CCameraSceneNode(newParent,
|
||||
newManager, ID, RelativeTranslation, Target);
|
||||
|
||||
nb->ISceneNode::cloneMembers(this, newManager);
|
||||
nb->ICameraSceneNode::cloneMembers(this);
|
||||
|
||||
nb->Target = Target;
|
||||
nb->UpVector = UpVector;
|
||||
nb->Fovy = Fovy;
|
||||
nb->Aspect = Aspect;
|
||||
nb->ZNear = ZNear;
|
||||
nb->ZFar = ZFar;
|
||||
nb->ViewArea = ViewArea;
|
||||
nb->Affector = Affector;
|
||||
nb->InputReceiverEnabled = InputReceiverEnabled;
|
||||
nb->TargetAndRotationAreBound = TargetAndRotationAreBound;
|
||||
|
||||
if ( newParent )
|
||||
nb->drop();
|
||||
return nb;
|
||||
}
|
||||
|
||||
|
||||
} // end namespace
|
||||
} // end namespace
|
||||
|
172
source/Irrlicht/CCameraSceneNode.h
Normal file
172
source/Irrlicht/CCameraSceneNode.h
Normal file
@ -0,0 +1,172 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#ifndef __C_CAMERA_SCENE_NODE_H_INCLUDED__
|
||||
#define __C_CAMERA_SCENE_NODE_H_INCLUDED__
|
||||
|
||||
#include "ICameraSceneNode.h"
|
||||
#include "SViewFrustum.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace scene
|
||||
{
|
||||
|
||||
class CCameraSceneNode : public ICameraSceneNode
|
||||
{
|
||||
public:
|
||||
|
||||
//! constructor
|
||||
CCameraSceneNode(ISceneNode* parent, ISceneManager* mgr, s32 id,
|
||||
const core::vector3df& position = core::vector3df(0,0,0),
|
||||
const core::vector3df& lookat = core::vector3df(0,0,100));
|
||||
|
||||
//! Sets the projection matrix of the camera.
|
||||
/** The core::matrix4 class has some methods
|
||||
to build a projection matrix. e.g: core::matrix4::buildProjectionMatrixPerspectiveFovLH.
|
||||
Note that the matrix will only stay as set by this method until one of
|
||||
the following Methods are called: setNearValue, setFarValue, setAspectRatio, setFOV.
|
||||
\param projection The new projection matrix of the camera.
|
||||
\param isOrthogonal Set this to true if the matrix is an orthogonal one (e.g.
|
||||
from matrix4::buildProjectionMatrixOrthoLH(). */
|
||||
virtual void setProjectionMatrix(const core::matrix4& projection, bool isOrthogonal = false);
|
||||
|
||||
//! Gets the current projection matrix of the camera
|
||||
//! \return Returns the current projection matrix of the camera.
|
||||
virtual const core::matrix4& getProjectionMatrix() const;
|
||||
|
||||
//! Gets the current view matrix of the camera
|
||||
//! \return Returns the current view matrix of the camera.
|
||||
virtual const core::matrix4& getViewMatrix() const;
|
||||
|
||||
//! Sets a custom view matrix affector.
|
||||
/** \param affector: The affector matrix. */
|
||||
virtual void setViewMatrixAffector(const core::matrix4& affector);
|
||||
|
||||
//! Gets the custom view matrix affector.
|
||||
virtual const core::matrix4& getViewMatrixAffector() const;
|
||||
|
||||
//! It is possible to send mouse and key events to the camera. Most cameras
|
||||
//! may ignore this input, but camera scene nodes which are created for
|
||||
//! example with scene::ISceneManager::addMayaCameraSceneNode or
|
||||
//! scene::ISceneManager::addMeshViewerCameraSceneNode, may want to get this input
|
||||
//! for changing their position, look at target or whatever.
|
||||
virtual bool OnEvent(const SEvent& event);
|
||||
|
||||
//! Sets the look at target of the camera
|
||||
/** If the camera's target and rotation are bound ( @see bindTargetAndRotation() )
|
||||
then calling this will also change the camera's scene node rotation to match the target.
|
||||
\param pos: Look at target of the camera. */
|
||||
virtual void setTarget(const core::vector3df& pos);
|
||||
|
||||
//! Sets the rotation of the node.
|
||||
/** This only modifies the relative rotation of the node.
|
||||
If the camera's target and rotation are bound ( @see bindTargetAndRotation() )
|
||||
then calling this will also change the camera's target to match the rotation.
|
||||
\param rotation New rotation of the node in degrees. */
|
||||
virtual void setRotation(const core::vector3df& rotation);
|
||||
|
||||
//! Gets the current look at target of the camera
|
||||
/** \return The current look at target of the camera */
|
||||
virtual const core::vector3df& getTarget() const;
|
||||
|
||||
//! Sets the up vector of the camera.
|
||||
//! \param pos: New upvector of the camera.
|
||||
virtual void setUpVector(const core::vector3df& pos);
|
||||
|
||||
//! Gets the up vector of the camera.
|
||||
//! \return Returns the up vector of the camera.
|
||||
virtual const core::vector3df& getUpVector() const;
|
||||
|
||||
//! Gets distance from the camera to the near plane.
|
||||
//! \return Value of the near plane of the camera.
|
||||
virtual f32 getNearValue() const;
|
||||
|
||||
//! Gets the distance from the camera to the far plane.
|
||||
//! \return Value of the far plane of the camera.
|
||||
virtual f32 getFarValue() const;
|
||||
|
||||
//! Get the aspect ratio of the camera.
|
||||
//! \return The aspect ratio of the camera.
|
||||
virtual f32 getAspectRatio() const;
|
||||
|
||||
//! Gets the field of view of the camera.
|
||||
//! \return Field of view of the camera
|
||||
virtual f32 getFOV() const;
|
||||
|
||||
//! Sets the value of the near clipping plane. (default: 1.0f)
|
||||
virtual void setNearValue(f32 zn);
|
||||
|
||||
//! Sets the value of the far clipping plane (default: 2000.0f)
|
||||
virtual void setFarValue(f32 zf);
|
||||
|
||||
//! Sets the aspect ratio (default: 4.0f / 3.0f)
|
||||
virtual void setAspectRatio(f32 aspect);
|
||||
|
||||
//! Sets the field of view (Default: PI / 3.5f)
|
||||
virtual void setFOV(f32 fovy);
|
||||
|
||||
//! PreRender event
|
||||
virtual void OnRegisterSceneNode();
|
||||
|
||||
//! Render
|
||||
virtual void render();
|
||||
|
||||
//! Returns the axis aligned bounding box of this node
|
||||
virtual const core::aabbox3d<f32>& getBoundingBox() const;
|
||||
|
||||
//! Returns the view area. Sometimes needed by bsp or lod render nodes.
|
||||
virtual const SViewFrustum* getViewFrustum() const;
|
||||
|
||||
//! Disables or enables the camera to get key or mouse inputs.
|
||||
//! If this is set to true, the camera will respond to key inputs
|
||||
//! otherwise not.
|
||||
virtual void setInputReceiverEnabled(bool enabled);
|
||||
|
||||
//! Returns if the input receiver of the camera is currently enabled.
|
||||
virtual bool isInputReceiverEnabled() const;
|
||||
|
||||
//! Writes attributes of the scene node.
|
||||
virtual void serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options=0) const;
|
||||
|
||||
//! Reads attributes of the scene node.
|
||||
virtual void deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options=0);
|
||||
|
||||
//! Returns type of the scene node
|
||||
virtual ESCENE_NODE_TYPE getType() const { return ESNT_CAMERA; }
|
||||
|
||||
//! Binds the camera scene node's rotation to its target position and vice vera, or unbinds them.
|
||||
virtual void bindTargetAndRotation(bool bound);
|
||||
|
||||
//! Queries if the camera scene node's rotation and its target position are bound together.
|
||||
virtual bool getTargetAndRotationBinding(void) const;
|
||||
|
||||
//! Creates a clone of this scene node and its children.
|
||||
virtual ISceneNode* clone(ISceneNode* newParent=0, ISceneManager* newManager=0);
|
||||
|
||||
protected:
|
||||
|
||||
void recalculateProjectionMatrix();
|
||||
void recalculateViewArea();
|
||||
|
||||
core::vector3df Target;
|
||||
core::vector3df UpVector;
|
||||
|
||||
f32 Fovy; // Field of view, in radians.
|
||||
f32 Aspect; // Aspect ratio.
|
||||
f32 ZNear; // value of the near view-plane.
|
||||
f32 ZFar; // Z-value of the far view-plane.
|
||||
|
||||
SViewFrustum ViewArea;
|
||||
core::matrix4 Affector;
|
||||
|
||||
bool InputReceiverEnabled;
|
||||
bool TargetAndRotationAreBound;
|
||||
};
|
||||
|
||||
} // end namespace
|
||||
} // end namespace
|
||||
|
||||
#endif
|
||||
|
361
source/Irrlicht/CCgMaterialRenderer.cpp
Normal file
361
source/Irrlicht/CCgMaterialRenderer.cpp
Normal file
@ -0,0 +1,361 @@
|
||||
// Copyright (C) 2012 Patryk Nadrowski
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#include "IrrCompileConfig.h"
|
||||
#ifdef _IRR_COMPILE_WITH_CG_
|
||||
|
||||
#include "CCgMaterialRenderer.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace video
|
||||
{
|
||||
|
||||
CCgUniform::CCgUniform(const CGparameter& parameter, bool global) : Parameter(parameter), Type(CG_UNKNOWN_TYPE)
|
||||
{
|
||||
Name = cgGetParameterName(Parameter);
|
||||
|
||||
if(global)
|
||||
Space = CG_GLOBAL;
|
||||
else
|
||||
Space = CG_PROGRAM;
|
||||
}
|
||||
|
||||
const core::stringc& CCgUniform::getName() const
|
||||
{
|
||||
return Name;
|
||||
}
|
||||
|
||||
const CGparameter& CCgUniform::getParameter() const
|
||||
{
|
||||
return Parameter;
|
||||
}
|
||||
|
||||
CGenum CCgUniform::getSpace() const
|
||||
{
|
||||
return Space;
|
||||
}
|
||||
|
||||
CGtype CCgUniform::getType() const
|
||||
{
|
||||
return Type;
|
||||
}
|
||||
|
||||
CCgUniform1f::CCgUniform1f(const CGparameter& parameter, bool global) : CCgUniform(parameter, global)
|
||||
{
|
||||
Type = CG_FLOAT;
|
||||
}
|
||||
|
||||
void CCgUniform1f::update(const void* data, const SMaterial& material) const
|
||||
{
|
||||
f32* Data = (f32*)data;
|
||||
cgSetParameter1f(Parameter, *Data);
|
||||
}
|
||||
|
||||
CCgUniform2f::CCgUniform2f(const CGparameter& parameter, bool global) : CCgUniform(parameter, global)
|
||||
{
|
||||
Type = CG_FLOAT2;
|
||||
}
|
||||
|
||||
void CCgUniform2f::update(const void* data, const SMaterial& material) const
|
||||
{
|
||||
f32* Data = (f32*)data;
|
||||
cgSetParameter2f(Parameter, *Data, *(Data+1));
|
||||
}
|
||||
|
||||
CCgUniform3f::CCgUniform3f(const CGparameter& parameter, bool global) : CCgUniform(parameter, global)
|
||||
{
|
||||
Type = CG_FLOAT3;
|
||||
}
|
||||
|
||||
void CCgUniform3f::update(const void* data, const SMaterial& material) const
|
||||
{
|
||||
f32* Data = (f32*)data;
|
||||
cgSetParameter3f(Parameter, *Data, *(Data+1), *(Data+2));
|
||||
}
|
||||
|
||||
CCgUniform4f::CCgUniform4f(const CGparameter& parameter, bool global) : CCgUniform(parameter, global)
|
||||
{
|
||||
Type = CG_FLOAT4;
|
||||
}
|
||||
|
||||
void CCgUniform4f::update(const void* data, const SMaterial& material) const
|
||||
{
|
||||
f32* Data = (f32*)data;
|
||||
cgSetParameter4f(Parameter, *Data, *(Data+1), *(Data+2), *(Data+3));
|
||||
}
|
||||
|
||||
CCgUniform1i::CCgUniform1i(const CGparameter& parameter, bool global) : CCgUniform(parameter, global)
|
||||
{
|
||||
Type = CG_INT;
|
||||
}
|
||||
|
||||
void CCgUniform1i::update(const void* data, const SMaterial& material) const
|
||||
{
|
||||
s32* Data = (s32*)data;
|
||||
cgSetParameter1i(Parameter, *Data);
|
||||
}
|
||||
|
||||
CCgUniform2i::CCgUniform2i(const CGparameter& parameter, bool global) : CCgUniform(parameter, global)
|
||||
{
|
||||
Type = CG_INT2;
|
||||
}
|
||||
|
||||
void CCgUniform2i::update(const void* data, const SMaterial& material) const
|
||||
{
|
||||
s32* Data = (s32*)data;
|
||||
cgSetParameter2i(Parameter, *Data, *(Data+1));
|
||||
}
|
||||
|
||||
CCgUniform3i::CCgUniform3i(const CGparameter& parameter, bool global) : CCgUniform(parameter, global)
|
||||
{
|
||||
Type = CG_INT3;
|
||||
}
|
||||
|
||||
void CCgUniform3i::update(const void* data, const SMaterial& material) const
|
||||
{
|
||||
s32* Data = (s32*)data;
|
||||
cgSetParameter3i(Parameter, *Data, *(Data+1), *(Data+2));
|
||||
}
|
||||
|
||||
CCgUniform4i::CCgUniform4i(const CGparameter& parameter, bool global) : CCgUniform(parameter, global)
|
||||
{
|
||||
Type = CG_INT4;
|
||||
}
|
||||
|
||||
void CCgUniform4i::update(const void* data, const SMaterial& material) const
|
||||
{
|
||||
s32* Data = (s32*)data;
|
||||
cgSetParameter4i(Parameter, *Data, *(Data+1), *(Data+2), *(Data+3));
|
||||
}
|
||||
|
||||
CCgUniform4x4f::CCgUniform4x4f(const CGparameter& parameter, bool global) : CCgUniform(parameter, global)
|
||||
{
|
||||
Type = CG_FLOAT4x4;
|
||||
}
|
||||
|
||||
void CCgUniform4x4f::update(const void* data, const SMaterial& material) const
|
||||
{
|
||||
f32* Data = (f32*)data;
|
||||
cgSetMatrixParameterfr(Parameter, Data);
|
||||
}
|
||||
|
||||
CCgUniformSampler2D::CCgUniformSampler2D(const CGparameter& parameter, bool global) : CCgUniform(parameter, global)
|
||||
{
|
||||
Type = CG_SAMPLER2D;
|
||||
}
|
||||
|
||||
void CCgUniformSampler2D::update(const void* data, const SMaterial& material) const
|
||||
{
|
||||
}
|
||||
|
||||
CCgMaterialRenderer::CCgMaterialRenderer(IShaderConstantSetCallBack* callback, IMaterialRenderer* baseMaterial, s32 userData) :
|
||||
CallBack(callback), BaseMaterial(baseMaterial), UserData(userData),
|
||||
VertexProgram(0), FragmentProgram(0), GeometryProgram(0), VertexProfile(CG_PROFILE_UNKNOWN), FragmentProfile(CG_PROFILE_UNKNOWN), GeometryProfile(CG_PROFILE_UNKNOWN),
|
||||
Material(IdentityMaterial), Error(CG_NO_ERROR)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
setDebugName("CCgMaterialRenderer");
|
||||
#endif
|
||||
|
||||
if(BaseMaterial)
|
||||
BaseMaterial->grab();
|
||||
|
||||
if(CallBack)
|
||||
CallBack->grab();
|
||||
}
|
||||
|
||||
CCgMaterialRenderer::~CCgMaterialRenderer()
|
||||
{
|
||||
if(CallBack)
|
||||
CallBack->drop();
|
||||
|
||||
if(BaseMaterial)
|
||||
BaseMaterial->drop();
|
||||
|
||||
for(unsigned int i = 0; i < UniformInfo.size(); ++i)
|
||||
delete UniformInfo[i];
|
||||
|
||||
UniformInfo.clear();
|
||||
}
|
||||
|
||||
bool CCgMaterialRenderer::isTransparent() const
|
||||
{
|
||||
return BaseMaterial ? BaseMaterial->isTransparent() : false;
|
||||
}
|
||||
|
||||
void CCgMaterialRenderer::setVertexShaderConstant(const f32* data, s32 startRegister, s32 constantAmount)
|
||||
{
|
||||
os::Printer::log("Cannot set constant, please use high level shader call instead.", ELL_WARNING);
|
||||
}
|
||||
|
||||
bool CCgMaterialRenderer::setVertexShaderConstant(const c8* name, const f32* floats, int count)
|
||||
{
|
||||
return setPixelShaderConstant(name, floats, count);
|
||||
}
|
||||
|
||||
bool CCgMaterialRenderer::setVertexShaderConstant(const c8* name, const bool* bools, int count)
|
||||
{
|
||||
return setPixelShaderConstant(name, bools, count);
|
||||
}
|
||||
|
||||
bool CCgMaterialRenderer::setVertexShaderConstant(const c8* name, const s32* ints, int count)
|
||||
{
|
||||
return setPixelShaderConstant(name, ints, count);
|
||||
}
|
||||
|
||||
void CCgMaterialRenderer::setPixelShaderConstant(const f32* data, s32 startRegister, s32 constantAmount)
|
||||
{
|
||||
os::Printer::log("Cannot set constant, please use high level shader call instead.", ELL_WARNING);
|
||||
}
|
||||
|
||||
bool CCgMaterialRenderer::setPixelShaderConstant(const c8* name, const f32* floats, int count)
|
||||
{
|
||||
bool Status = false;
|
||||
|
||||
for(unsigned int i = 0; i < UniformInfo.size(); ++i)
|
||||
{
|
||||
if(UniformInfo[i]->getName() == name)
|
||||
{
|
||||
UniformInfo[i]->update(floats, Material);
|
||||
|
||||
Status = true;
|
||||
}
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
bool CCgMaterialRenderer::setPixelShaderConstant(const c8* name, const s32* ints, int count)
|
||||
{
|
||||
bool Status = false;
|
||||
|
||||
for(unsigned int i = 0; i < UniformInfo.size(); ++i)
|
||||
{
|
||||
if(UniformInfo[i]->getName() == name)
|
||||
{
|
||||
UniformInfo[i]->update(ints, Material);
|
||||
|
||||
Status = true;
|
||||
}
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
bool CCgMaterialRenderer::setPixelShaderConstant(const c8* name, const bool* bools, int count)
|
||||
{
|
||||
bool Status = false;
|
||||
|
||||
for(unsigned int i = 0; i < UniformInfo.size(); ++i)
|
||||
{
|
||||
if(UniformInfo[i]->getName() == name)
|
||||
{
|
||||
UniformInfo[i]->update(bools, Material);
|
||||
|
||||
Status = true;
|
||||
}
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
void CCgMaterialRenderer::getUniformList()
|
||||
{
|
||||
for(unsigned int i = 0; i < UniformInfo.size(); ++i)
|
||||
delete UniformInfo[i];
|
||||
|
||||
UniformInfo.clear();
|
||||
|
||||
for(unsigned int i = 0; i < 2; ++i)
|
||||
{
|
||||
CGenum Space = CG_GLOBAL;
|
||||
bool IsGlobal = 1;
|
||||
|
||||
if(i == 1)
|
||||
{
|
||||
Space = CG_PROGRAM;
|
||||
IsGlobal = 0;
|
||||
}
|
||||
|
||||
for(unsigned int j = 0; j < 3; ++j)
|
||||
{
|
||||
CGprogram* Program = 0;
|
||||
|
||||
switch(j)
|
||||
{
|
||||
case 0:
|
||||
Program = &VertexProgram;
|
||||
break;
|
||||
case 1:
|
||||
Program = &FragmentProgram;
|
||||
break;
|
||||
case 2:
|
||||
Program = &GeometryProgram;
|
||||
break;
|
||||
}
|
||||
|
||||
if(*Program)
|
||||
{
|
||||
CGparameter Parameter = cgGetFirstParameter(*Program, Space);
|
||||
|
||||
while(Parameter)
|
||||
{
|
||||
if(cgGetParameterVariability(Parameter) == CG_UNIFORM && cgGetParameterDirection(Parameter) == CG_IN)
|
||||
{
|
||||
CCgUniform* Uniform = 0;
|
||||
|
||||
CGtype Type = cgGetParameterType(Parameter);
|
||||
|
||||
switch(Type)
|
||||
{
|
||||
case CG_FLOAT:
|
||||
case CG_FLOAT1:
|
||||
Uniform = new CCgUniform1f(Parameter, IsGlobal);
|
||||
break;
|
||||
case CG_FLOAT2:
|
||||
Uniform = new CCgUniform2f(Parameter, IsGlobal);
|
||||
break;
|
||||
case CG_FLOAT3:
|
||||
Uniform = new CCgUniform3f(Parameter, IsGlobal);
|
||||
break;
|
||||
case CG_FLOAT4:
|
||||
Uniform = new CCgUniform4f(Parameter, IsGlobal);
|
||||
break;
|
||||
case CG_INT:
|
||||
case CG_INT1:
|
||||
Uniform = new CCgUniform1i(Parameter, IsGlobal);
|
||||
break;
|
||||
case CG_INT2:
|
||||
Uniform = new CCgUniform2i(Parameter, IsGlobal);
|
||||
break;
|
||||
case CG_INT3:
|
||||
Uniform = new CCgUniform3i(Parameter, IsGlobal);
|
||||
break;
|
||||
case CG_INT4:
|
||||
Uniform = new CCgUniform4i(Parameter, IsGlobal);
|
||||
break;
|
||||
case CG_FLOAT4x4:
|
||||
Uniform = new CCgUniform4x4f(Parameter, IsGlobal);
|
||||
break;
|
||||
case CG_SAMPLER2D:
|
||||
Uniform = new CCgUniformSampler2D(Parameter, IsGlobal);
|
||||
break;
|
||||
}
|
||||
|
||||
if(Uniform)
|
||||
UniformInfo.push_back(Uniform);
|
||||
}
|
||||
|
||||
Parameter = cgGetNextParameter(Parameter);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
176
source/Irrlicht/CCgMaterialRenderer.h
Normal file
176
source/Irrlicht/CCgMaterialRenderer.h
Normal file
@ -0,0 +1,176 @@
|
||||
// Copyright (C) 2012 Patryk Nadrowski
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#ifndef __C_CG_MATERIAL_RENDERER_H_INCLUDED__
|
||||
#define __C_CG_MATERIAL_RENDERER_H_INCLUDED__
|
||||
|
||||
#include "IrrCompileConfig.h"
|
||||
#ifdef _IRR_COMPILE_WITH_CG_
|
||||
|
||||
#include "IMaterialRenderer.h"
|
||||
#include "IMaterialRendererServices.h"
|
||||
#include "IShaderConstantSetCallBack.h"
|
||||
#include "IGPUProgrammingServices.h"
|
||||
#include "irrArray.h"
|
||||
#include "irrString.h"
|
||||
#include "IVideoDriver.h"
|
||||
#include "os.h"
|
||||
#include "Cg/cg.h"
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma comment(lib, "cg.lib")
|
||||
#endif
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace video
|
||||
{
|
||||
|
||||
class CCgUniform
|
||||
{
|
||||
public:
|
||||
CCgUniform(const CGparameter& parameter, bool global);
|
||||
|
||||
const core::stringc& getName() const;
|
||||
const CGparameter& getParameter() const;
|
||||
CGenum getSpace() const;
|
||||
CGtype getType() const;
|
||||
|
||||
virtual void update(const void* data, const SMaterial& material) const = 0;
|
||||
|
||||
protected:
|
||||
core::stringc Name;
|
||||
CGparameter Parameter;
|
||||
CGenum Space;
|
||||
CGtype Type;
|
||||
};
|
||||
|
||||
class CCgUniform1f : public CCgUniform
|
||||
{
|
||||
public:
|
||||
CCgUniform1f(const CGparameter& parameter, bool global);
|
||||
|
||||
void update(const void* data, const SMaterial& material) const;
|
||||
};
|
||||
|
||||
class CCgUniform2f : public CCgUniform
|
||||
{
|
||||
public:
|
||||
CCgUniform2f(const CGparameter& parameter, bool global);
|
||||
|
||||
void update(const void* data, const SMaterial& material) const;
|
||||
};
|
||||
|
||||
class CCgUniform3f : public CCgUniform
|
||||
{
|
||||
public:
|
||||
CCgUniform3f(const CGparameter& parameter, bool global);
|
||||
|
||||
void update(const void* data, const SMaterial& material) const;
|
||||
};
|
||||
|
||||
class CCgUniform4f : public CCgUniform
|
||||
{
|
||||
public:
|
||||
CCgUniform4f(const CGparameter& parameter, bool global);
|
||||
|
||||
void update(const void* data, const SMaterial& material) const;
|
||||
};
|
||||
|
||||
class CCgUniform1i : public CCgUniform
|
||||
{
|
||||
public:
|
||||
CCgUniform1i(const CGparameter& parameter, bool global);
|
||||
|
||||
void update(const void* data, const SMaterial& material) const;
|
||||
};
|
||||
|
||||
class CCgUniform2i : public CCgUniform
|
||||
{
|
||||
public:
|
||||
CCgUniform2i(const CGparameter& parameter, bool global);
|
||||
|
||||
void update(const void* data, const SMaterial& material) const;
|
||||
};
|
||||
|
||||
class CCgUniform3i : public CCgUniform
|
||||
{
|
||||
public:
|
||||
CCgUniform3i(const CGparameter& parameter, bool global);
|
||||
|
||||
void update(const void* data, const SMaterial& material) const;
|
||||
};
|
||||
|
||||
class CCgUniform4i : public CCgUniform
|
||||
{
|
||||
public:
|
||||
CCgUniform4i(const CGparameter& parameter, bool global);
|
||||
|
||||
void update(const void* data, const SMaterial& material) const;
|
||||
};
|
||||
|
||||
class CCgUniform4x4f : public CCgUniform
|
||||
{
|
||||
public:
|
||||
CCgUniform4x4f(const CGparameter& parameter, bool global);
|
||||
|
||||
void update(const void* data, const SMaterial& material) const;
|
||||
};
|
||||
|
||||
class CCgUniformSampler2D : public CCgUniform
|
||||
{
|
||||
public:
|
||||
CCgUniformSampler2D(const CGparameter& parameter, bool global);
|
||||
|
||||
void update(const void* data, const SMaterial& material) const;
|
||||
};
|
||||
|
||||
class CCgMaterialRenderer : public IMaterialRenderer, public IMaterialRendererServices
|
||||
{
|
||||
public:
|
||||
CCgMaterialRenderer(IShaderConstantSetCallBack* callback = 0, IMaterialRenderer* baseMaterial = 0, s32 userData = 0);
|
||||
virtual ~CCgMaterialRenderer();
|
||||
|
||||
virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial, bool resetAllRenderstates, IMaterialRendererServices* services) = 0;
|
||||
virtual bool OnRender(IMaterialRendererServices* service, E_VERTEX_TYPE vtxtype) = 0;
|
||||
virtual void OnUnsetMaterial() = 0;
|
||||
|
||||
virtual bool isTransparent() const;
|
||||
|
||||
virtual void setBasicRenderStates(const SMaterial& material, const SMaterial& lastMaterial, bool resetAllRenderstates) = 0;
|
||||
virtual bool setVertexShaderConstant(const c8* name, const f32* floats, int count);
|
||||
virtual bool setVertexShaderConstant(const c8* name, const bool* bools, int count);
|
||||
virtual bool setVertexShaderConstant(const c8* name, const s32* ints, int count);
|
||||
virtual void setVertexShaderConstant(const f32* data, s32 startRegister, s32 constantAmount=1);
|
||||
virtual bool setPixelShaderConstant(const c8* name, const f32* floats, int count);
|
||||
virtual bool setPixelShaderConstant(const c8* name, const bool* bools, int count);
|
||||
virtual bool setPixelShaderConstant(const c8* name, const s32* ints, int count);
|
||||
virtual void setPixelShaderConstant(const f32* data, s32 startRegister, s32 constantAmount=1);
|
||||
virtual IVideoDriver* getVideoDriver() = 0;
|
||||
|
||||
protected:
|
||||
void getUniformList();
|
||||
|
||||
IShaderConstantSetCallBack* CallBack;
|
||||
IMaterialRenderer* BaseMaterial;
|
||||
s32 UserData;
|
||||
|
||||
core::array<CCgUniform*> UniformInfo;
|
||||
|
||||
CGprogram VertexProgram;
|
||||
CGprogram FragmentProgram;
|
||||
CGprogram GeometryProgram;
|
||||
CGprofile VertexProfile;
|
||||
CGprofile FragmentProfile;
|
||||
CGprofile GeometryProfile;
|
||||
|
||||
SMaterial Material;
|
||||
CGerror Error;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
2957
source/Irrlicht/CColladaFileLoader.cpp
Normal file
2957
source/Irrlicht/CColladaFileLoader.cpp
Normal file
File diff suppressed because it is too large
Load Diff
389
source/Irrlicht/CColladaFileLoader.h
Normal file
389
source/Irrlicht/CColladaFileLoader.h
Normal file
@ -0,0 +1,389 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#ifndef __C_COLLADA_MESH_FILE_LOADER_H_INCLUDED__
|
||||
#define __C_COLLADA_MESH_FILE_LOADER_H_INCLUDED__
|
||||
|
||||
#include "IMeshLoader.h"
|
||||
#include "IFileSystem.h"
|
||||
#include "IVideoDriver.h"
|
||||
#include "irrString.h"
|
||||
#include "SMesh.h"
|
||||
#include "SMeshBuffer.h"
|
||||
#include "ISceneManager.h"
|
||||
#include "irrMap.h"
|
||||
#include "CAttributes.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace scene
|
||||
{
|
||||
|
||||
#ifdef _DEBUG
|
||||
//#define COLLADA_READER_DEBUG
|
||||
#endif
|
||||
|
||||
class IColladaPrefab;
|
||||
|
||||
enum ECOLLADA_PARAM_NAME
|
||||
{
|
||||
ECPN_COLOR = 0,
|
||||
ECPN_AMBIENT,
|
||||
ECPN_DIFFUSE,
|
||||
ECPN_SPECULAR,
|
||||
ECPN_SHININESS,
|
||||
ECPN_TRANSPARENCY,
|
||||
ECPN_YFOV,
|
||||
ECPN_ZNEAR,
|
||||
ECPN_ZFAR,
|
||||
|
||||
ECPN_COUNT
|
||||
};
|
||||
|
||||
enum ECOLLADA_PARAM_TYPE
|
||||
{
|
||||
ECPT_FLOAT = 0,
|
||||
ECPT_FLOAT2,
|
||||
ECPT_FLOAT3,
|
||||
ECPT_FLOAT4,
|
||||
|
||||
ECPT_COUNT
|
||||
};
|
||||
|
||||
//! Collada Parameter
|
||||
struct SColladaParam
|
||||
{
|
||||
SColladaParam()
|
||||
: Name(ECPN_COUNT), Type(ECPT_COUNT)
|
||||
{
|
||||
for (int i=0; i<4; ++i) Floats[i] = 0;
|
||||
}
|
||||
|
||||
ECOLLADA_PARAM_NAME Name;
|
||||
ECOLLADA_PARAM_TYPE Type;
|
||||
|
||||
f32 Floats[4];
|
||||
};
|
||||
|
||||
enum ECOLLADA_INPUT_SEMANTIC
|
||||
{
|
||||
ECIS_POSITION = 0,
|
||||
ECIS_VERTEX,
|
||||
ECIS_NORMAL,
|
||||
ECIS_TEXCOORD,
|
||||
ECIS_UV,
|
||||
ECIS_TANGENT,
|
||||
ECIS_IMAGE,
|
||||
ECIS_TEXTURE,
|
||||
|
||||
ECIS_COUNT
|
||||
};
|
||||
|
||||
//! Collada Input
|
||||
struct SColladaInput
|
||||
{
|
||||
SColladaInput()
|
||||
: Semantic(ECIS_COUNT), Data(0), Offset(0), Set(0), Stride(1)
|
||||
{
|
||||
}
|
||||
|
||||
ECOLLADA_INPUT_SEMANTIC Semantic;
|
||||
core::stringc Source;
|
||||
f32* Data;
|
||||
u32 Offset;
|
||||
u32 Set;
|
||||
u32 Stride;
|
||||
};
|
||||
|
||||
//! Collada images
|
||||
struct SColladaImage
|
||||
{
|
||||
core::stringc Id;
|
||||
core::stringc Source;
|
||||
core::dimension2du Dimension;
|
||||
bool SourceIsFilename;
|
||||
};
|
||||
|
||||
|
||||
//! Collada texture
|
||||
struct SColladaTexture
|
||||
{
|
||||
video::ITexture* Texture;
|
||||
core::stringc Id;
|
||||
};
|
||||
|
||||
|
||||
//! Collada material
|
||||
struct SColladaMaterial
|
||||
{
|
||||
video::SMaterial Mat;
|
||||
core::stringc Id;
|
||||
core::stringc InstanceEffectId;
|
||||
f32 Transparency;
|
||||
|
||||
inline bool operator< (const SColladaMaterial & other) const
|
||||
{
|
||||
return Id < other.Id;
|
||||
}
|
||||
};
|
||||
|
||||
//! Collada effect (materials, shaders, and programs)
|
||||
struct SColladaEffect
|
||||
{
|
||||
core::stringc Id;
|
||||
f32 Transparency;
|
||||
core::array<core::stringc> Textures;
|
||||
video::SMaterial Mat;
|
||||
// TODO: Parameters looks somewhat lazy workaround, I think we should really read all parameters correct.
|
||||
io::IAttributes * Parameters;
|
||||
|
||||
inline bool operator< (const SColladaEffect & other) const
|
||||
{
|
||||
return Id < other.Id;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
struct SNumberArray // for storing float and int arrays
|
||||
{
|
||||
core::stringc Name;
|
||||
core::array<f32> Data;
|
||||
};
|
||||
|
||||
struct SAccessor
|
||||
{
|
||||
SAccessor()
|
||||
: Count(0), Offset(0), Stride(1) {}
|
||||
// I don't store the source of the accessor here because I assume
|
||||
// it to use the array of the source this accessor is located in.
|
||||
|
||||
int Count;
|
||||
int Offset;
|
||||
int Stride;
|
||||
|
||||
core::array<SColladaParam> Parameters; // parameters defining the accessor
|
||||
};
|
||||
|
||||
struct SSource
|
||||
{
|
||||
core::stringc Id;
|
||||
SNumberArray Array;
|
||||
core::array<SAccessor> Accessors;
|
||||
};
|
||||
|
||||
class CScenePrefab;
|
||||
|
||||
//! Meshloader capable of loading COLLADA meshes and scene descriptions into Irrlicht.
|
||||
class CColladaFileLoader : public IMeshLoader
|
||||
{
|
||||
public:
|
||||
|
||||
//! Constructor
|
||||
CColladaFileLoader(scene::ISceneManager* smgr, io::IFileSystem* fs);
|
||||
|
||||
//! destructor
|
||||
virtual ~CColladaFileLoader();
|
||||
|
||||
//! returns true if the file maybe is able to be loaded by this class
|
||||
//! based on the file extension (e.g. ".cob")
|
||||
virtual bool isALoadableFileExtension(const io::path& filename) const;
|
||||
|
||||
//! creates/loads an animated mesh from the file.
|
||||
//! \return Pointer to the created mesh. Returns 0 if loading failed.
|
||||
//! If you no longer need the mesh, you should call IAnimatedMesh::drop().
|
||||
//! See IReferenceCounted::drop() for more information.
|
||||
virtual IAnimatedMesh* createMesh(io::IReadFile* file);
|
||||
|
||||
private:
|
||||
|
||||
//! skips an (unknown) section in the collada document
|
||||
void skipSection(io::IXMLReaderUTF8* reader, bool reportSkipping);
|
||||
|
||||
//! reads the <COLLADA> section and its content
|
||||
void readColladaSection(io::IXMLReaderUTF8* reader);
|
||||
|
||||
//! reads a <library> section and its content
|
||||
void readLibrarySection(io::IXMLReaderUTF8* reader);
|
||||
|
||||
//! reads a <visual_scene> element and stores it as a prefab
|
||||
void readVisualScene(io::IXMLReaderUTF8* reader);
|
||||
|
||||
//! reads a <scene> section and its content
|
||||
void readSceneSection(io::IXMLReaderUTF8* reader);
|
||||
|
||||
//! reads a <asset> section and its content
|
||||
void readAssetSection(io::IXMLReaderUTF8* reader);
|
||||
|
||||
//! reads a <node> section and its content
|
||||
//! if a prefab pointer is passed the nodes are created as scene prefabs children of that prefab
|
||||
void readNodeSection(io::IXMLReaderUTF8* reader, scene::ISceneNode* parent, CScenePrefab* p=0);
|
||||
|
||||
//! reads a <lookat> element and its content and creates a matrix from it
|
||||
core::matrix4 readLookAtNode(io::IXMLReaderUTF8* reader);
|
||||
|
||||
//! reads a <matrix> element and its content and creates a matrix from it
|
||||
core::matrix4 readMatrixNode(io::IXMLReaderUTF8* reader);
|
||||
|
||||
//! reads a <perspective> element and its content and creates a matrix from it
|
||||
core::matrix4 readPerspectiveNode(io::IXMLReaderUTF8* reader);
|
||||
|
||||
//! reads a <rotate> element and its content and creates a matrix from it
|
||||
core::matrix4 readRotateNode(io::IXMLReaderUTF8* reader);
|
||||
|
||||
//! reads a <skew> element and its content and creates a matrix from it
|
||||
core::matrix4 readSkewNode(io::IXMLReaderUTF8* reader);
|
||||
|
||||
//! reads a <boundingbox> element and its content and stores it in bbox
|
||||
void readBboxNode(io::IXMLReaderUTF8* reader, core::aabbox3df& bbox);
|
||||
|
||||
//! reads a <scale> element and its content and creates a matrix from it
|
||||
core::matrix4 readScaleNode(io::IXMLReaderUTF8* reader);
|
||||
|
||||
//! reads a <translate> element and its content and creates a matrix from it
|
||||
core::matrix4 readTranslateNode(io::IXMLReaderUTF8* reader);
|
||||
|
||||
//! reads a <color> element
|
||||
video::SColorf readColorNode(io::IXMLReaderUTF8* reader);
|
||||
|
||||
//! reads a <float> element
|
||||
f32 readFloatNode(io::IXMLReaderUTF8* reader);
|
||||
|
||||
//! reads a <instance> node
|
||||
void readInstanceNode(io::IXMLReaderUTF8* reader,
|
||||
scene::ISceneNode* parent, scene::ISceneNode** outNode,
|
||||
CScenePrefab* p=0, const core::stringc& type=core::stringc());
|
||||
|
||||
//! creates a scene node from Prefabs (with name given in 'url')
|
||||
void instantiateNode(scene::ISceneNode* parent, scene::ISceneNode** outNode=0,
|
||||
CScenePrefab* p=0, const core::stringc& url="",
|
||||
const core::stringc& type=core::stringc());
|
||||
|
||||
//! reads a <light> element and stores it as prefab
|
||||
void readLightPrefab(io::IXMLReaderUTF8* reader);
|
||||
|
||||
//! reads a <camera> element and stores it as prefab
|
||||
void readCameraPrefab(io::IXMLReaderUTF8* reader);
|
||||
|
||||
//! reads a <image> element and stores it in the image section
|
||||
void readImage(io::IXMLReaderUTF8* reader);
|
||||
|
||||
//! reads a <texture> element and stores it in the texture section
|
||||
void readTexture(io::IXMLReaderUTF8* reader);
|
||||
|
||||
//! reads a <material> element and stores it in the material section
|
||||
void readMaterial(io::IXMLReaderUTF8* reader);
|
||||
|
||||
//! reads a <effect> element and stores it in the effects section
|
||||
void readEffect(io::IXMLReaderUTF8* reader, SColladaEffect * effect = 0);
|
||||
|
||||
//! reads a <geometry> element and stores it as mesh if possible
|
||||
void readGeometry(io::IXMLReaderUTF8* reader);
|
||||
|
||||
//! parses a float from a char pointer and moves the pointer to
|
||||
//! the end of the parsed float
|
||||
inline f32 readFloat(const c8** p);
|
||||
|
||||
//! parses an int from a char pointer and moves the pointer to
|
||||
//! the end of the parsed float
|
||||
inline s32 readInt(const c8** p);
|
||||
|
||||
//! places pointer to next begin of a token
|
||||
void findNextNoneWhiteSpace(const c8** p);
|
||||
|
||||
//! reads floats from inside of xml element until end of xml element
|
||||
void readFloatsInsideElement(io::IXMLReaderUTF8* reader, f32* floats, u32 count);
|
||||
|
||||
//! reads ints from inside of xml element until end of xml element
|
||||
void readIntsInsideElement(io::IXMLReaderUTF8* reader, s32* ints, u32 count);
|
||||
|
||||
//! clears all loaded data
|
||||
void clearData();
|
||||
|
||||
//! parses all collada parameters inside an element and stores them in ColladaParameters
|
||||
void readColladaParameters(io::IXMLReaderUTF8* reader, const core::stringc& parentName);
|
||||
|
||||
//! returns a collada parameter or none if not found
|
||||
SColladaParam* getColladaParameter(ECOLLADA_PARAM_NAME name);
|
||||
|
||||
//! parses all collada inputs inside an element and stores them in Inputs. Reads
|
||||
//! until first tag which is not an input tag or the end of the parent is reached
|
||||
void readColladaInputs(io::IXMLReaderUTF8* reader, const core::stringc& parentName);
|
||||
|
||||
//! reads a collada input tag and adds it to the input parameter
|
||||
void readColladaInput(io::IXMLReaderUTF8* reader, core::array<SColladaInput>& inputs);
|
||||
|
||||
//! returns a collada input or none if not found
|
||||
SColladaInput* getColladaInput(ECOLLADA_INPUT_SEMANTIC input);
|
||||
|
||||
//! read Collada Id, uses id or name if id is missing
|
||||
core::stringc readId(io::IXMLReaderUTF8* reader);
|
||||
|
||||
//! changes the XML URI into an internal id
|
||||
void uriToId(core::stringc& str);
|
||||
|
||||
//! reads a polygons section and creates a mesh from it
|
||||
void readPolygonSection(io::IXMLReaderUTF8* reader,
|
||||
core::array<SSource>& sources, scene::SMesh* mesh,
|
||||
const core::stringc& geometryId);
|
||||
|
||||
//! finds a material, possible instancing it
|
||||
const SColladaMaterial * findMaterial(const core::stringc & materialName);
|
||||
|
||||
//! reads and bind materials as given by the symbol->target bind mapping
|
||||
void readBindMaterialSection(io::IXMLReaderUTF8* reader, const core::stringc & id);
|
||||
|
||||
//! create an Irrlicht texture from the SColladaImage
|
||||
video::ITexture* getTextureFromImage(core::stringc uri, SColladaEffect * effect);
|
||||
|
||||
//! read a parameter and value
|
||||
void readParameter(io::IXMLReaderUTF8* reader, io::IAttributes* parameters);
|
||||
|
||||
scene::ISceneManager* SceneManager;
|
||||
io::IFileSystem* FileSystem;
|
||||
|
||||
scene::IAnimatedMesh* DummyMesh;
|
||||
core::stringc CurrentlyLoadingMesh;
|
||||
|
||||
scene::IAnimatedMesh* FirstLoadedMesh;
|
||||
io::path FirstLoadedMeshName;
|
||||
s32 LoadedMeshCount;
|
||||
u32 Version;
|
||||
bool FlipAxis;
|
||||
|
||||
core::array<IColladaPrefab*> Prefabs;
|
||||
core::array<SColladaParam> ColladaParameters;
|
||||
core::array<SColladaImage> Images;
|
||||
core::array<SColladaTexture> Textures;
|
||||
core::array<SColladaMaterial> Materials;
|
||||
core::array<SColladaInput> Inputs;
|
||||
core::array<SColladaEffect> Effects;
|
||||
//! meshbuffer reference ("geomid/matname") -> index into MeshesToBind
|
||||
core::map<core::stringc,u32> MaterialsToBind;
|
||||
//! Array of buffers for each material binding
|
||||
core::array< core::array<irr::scene::IMeshBuffer*> > MeshesToBind;
|
||||
|
||||
bool CreateInstances;
|
||||
};
|
||||
|
||||
|
||||
|
||||
//! following class is for holding and createing instances of library objects,
|
||||
//! named prefabs in this loader.
|
||||
class IColladaPrefab : public virtual IReferenceCounted
|
||||
{
|
||||
public:
|
||||
//! creates an instance of this prefab
|
||||
virtual scene::ISceneNode* addInstance(scene::ISceneNode* parent,
|
||||
scene::ISceneManager* mgr) = 0;
|
||||
|
||||
//! returns id of this prefab
|
||||
virtual const core::stringc& getId() = 0;
|
||||
};
|
||||
|
||||
|
||||
} // end namespace scene
|
||||
} // end namespace irr
|
||||
|
||||
#endif
|
||||
|
2245
source/Irrlicht/CColladaMeshWriter.cpp
Normal file
2245
source/Irrlicht/CColladaMeshWriter.cpp
Normal file
File diff suppressed because it is too large
Load Diff
271
source/Irrlicht/CColladaMeshWriter.h
Normal file
271
source/Irrlicht/CColladaMeshWriter.h
Normal file
@ -0,0 +1,271 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#ifndef __IRR_C_COLLADA_MESH_WRITER_H_INCLUDED__
|
||||
#define __IRR_C_COLLADA_MESH_WRITER_H_INCLUDED__
|
||||
|
||||
#include "IColladaMeshWriter.h"
|
||||
#include "S3DVertex.h"
|
||||
#include "irrMap.h"
|
||||
#include "IVideoDriver.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace io
|
||||
{
|
||||
class IXMLWriter;
|
||||
class IFileSystem;
|
||||
}
|
||||
|
||||
namespace scene
|
||||
{
|
||||
//! Callback interface for properties which can be used to influence collada writing
|
||||
// (Implementer note: keep namespace labels here to make it easier for users copying this one)
|
||||
class CColladaMeshWriterProperties : public virtual IColladaMeshWriterProperties
|
||||
{
|
||||
public:
|
||||
//! Which lighting model should be used in the technique (FX) section when exporting effects (materials)
|
||||
virtual irr::scene::E_COLLADA_TECHNIQUE_FX getTechniqueFx(const irr::video::SMaterial& material) const;
|
||||
|
||||
//! Which texture index should be used when writing the texture of the given sampler color.
|
||||
virtual irr::s32 getTextureIdx(const irr::video::SMaterial & material, irr::scene::E_COLLADA_COLOR_SAMPLER cs) const;
|
||||
|
||||
//! Return which color from Irrlicht should be used for the color requested by collada
|
||||
virtual irr::scene::E_COLLADA_IRR_COLOR getColorMapping(const irr::video::SMaterial & material, irr::scene::E_COLLADA_COLOR_SAMPLER cs) const;
|
||||
|
||||
//! Return custom colors for certain color types requested by collada.
|
||||
virtual irr::video::SColor getCustomColor(const irr::video::SMaterial & material, irr::scene::E_COLLADA_COLOR_SAMPLER cs) const;
|
||||
|
||||
//! Return the settings for transparence
|
||||
virtual irr::scene::E_COLLADA_TRANSPARENT_FX getTransparentFx(const irr::video::SMaterial& material) const;
|
||||
|
||||
//! Transparency value for that material.
|
||||
virtual irr::f32 getTransparency(const irr::video::SMaterial& material) const;
|
||||
|
||||
//! Reflectivity value for that material
|
||||
virtual irr::f32 getReflectivity(const irr::video::SMaterial& material) const;
|
||||
|
||||
//! Return index of refraction for that material
|
||||
virtual irr::f32 getIndexOfRefraction(const irr::video::SMaterial& material) const;
|
||||
|
||||
//! Should node be used in scene export? By default all visible nodes are exported.
|
||||
virtual bool isExportable(const irr::scene::ISceneNode * node) const;
|
||||
|
||||
//! Return the mesh for the given nod. If it has no mesh or shouldn't export it's mesh return 0.
|
||||
virtual irr::scene::IMesh* getMesh(irr::scene::ISceneNode * node);
|
||||
|
||||
//! Return if the node has it's own material overwriting the mesh-materials
|
||||
virtual bool useNodeMaterial(const scene::ISceneNode* node) const;
|
||||
};
|
||||
|
||||
class CColladaMeshWriterNames : public virtual IColladaMeshWriterNames
|
||||
{
|
||||
public:
|
||||
CColladaMeshWriterNames(IColladaMeshWriter * writer);
|
||||
virtual irr::core::stringw nameForMesh(const scene::IMesh* mesh, int instance);
|
||||
virtual irr::core::stringw nameForNode(const scene::ISceneNode* node);
|
||||
virtual irr::core::stringw nameForMaterial(const video::SMaterial & material, int materialId, const scene::IMesh* mesh, const scene::ISceneNode* node);
|
||||
protected:
|
||||
irr::core::stringw nameForPtr(const void* ptr) const;
|
||||
private:
|
||||
IColladaMeshWriter * ColladaMeshWriter;
|
||||
};
|
||||
|
||||
|
||||
|
||||
//! class to write meshes, implementing a COLLADA (.dae, .xml) writer
|
||||
/** This writer implementation has been originally developed for irrEdit and then
|
||||
merged out to the Irrlicht Engine */
|
||||
class CColladaMeshWriter : public IColladaMeshWriter
|
||||
{
|
||||
public:
|
||||
|
||||
CColladaMeshWriter(ISceneManager * smgr, video::IVideoDriver* driver, io::IFileSystem* fs);
|
||||
virtual ~CColladaMeshWriter();
|
||||
|
||||
//! Returns the type of the mesh writer
|
||||
virtual EMESH_WRITER_TYPE getType() const;
|
||||
|
||||
//! writes a scene starting with the given node
|
||||
virtual bool writeScene(io::IWriteFile* file, scene::ISceneNode* root);
|
||||
|
||||
//! writes a mesh
|
||||
virtual bool writeMesh(io::IWriteFile* file, scene::IMesh* mesh, s32 flags=EMWF_NONE);
|
||||
|
||||
// Restrict the characters of oldString a set of allowed characters in xs::NCName and add the prefix.
|
||||
virtual irr::core::stringw toNCName(const irr::core::stringw& oldString, const irr::core::stringw& prefix=irr::core::stringw(L"_NC_")) const;
|
||||
|
||||
protected:
|
||||
|
||||
void reset();
|
||||
bool hasSecondTextureCoordinates(video::E_VERTEX_TYPE type) const;
|
||||
void writeUv(const irr::core::vector2df& vec);
|
||||
void writeVector(const irr::core::vector2df& vec);
|
||||
void writeVector(const irr::core::vector3df& vec);
|
||||
void writeColor(const irr::video::SColorf& colorf, bool writeAlpha=true);
|
||||
inline irr::core::stringw toString(const irr::video::ECOLOR_FORMAT format) const;
|
||||
inline irr::core::stringw toString(const irr::video::E_TEXTURE_CLAMP clamp) const;
|
||||
inline irr::core::stringw toString(const irr::scene::E_COLLADA_TRANSPARENT_FX opaque) const;
|
||||
inline irr::core::stringw toRef(const irr::core::stringw& source) const;
|
||||
bool isCamera(const scene::ISceneNode* node) const;
|
||||
irr::core::stringw nameForMesh(const scene::IMesh* mesh, int instance) const;
|
||||
irr::core::stringw nameForNode(const scene::ISceneNode* node) const;
|
||||
irr::core::stringw nameForMaterial(const video::SMaterial & material, int materialId, const scene::IMesh* mesh, const scene::ISceneNode* node);
|
||||
irr::core::stringw nameForMaterialSymbol(const scene::IMesh* mesh, int materialId) const;
|
||||
irr::core::stringw findCachedMaterialName(const irr::video::SMaterial& material) const;
|
||||
irr::core::stringw minTexfilterToString(bool bilinear, bool trilinear) const;
|
||||
irr::core::stringw magTexfilterToString(bool bilinear, bool trilinear) const;
|
||||
irr::core::stringw pathToURI(const irr::io::path& path) const;
|
||||
inline bool isXmlNameStartChar(wchar_t c) const;
|
||||
inline bool isXmlNameChar(wchar_t c) const;
|
||||
s32 getCheckedTextureIdx(const video::SMaterial & material, E_COLLADA_COLOR_SAMPLER cs);
|
||||
video::SColor getColorMapping(const video::SMaterial & material, E_COLLADA_COLOR_SAMPLER cs, E_COLLADA_IRR_COLOR colType);
|
||||
void writeAsset();
|
||||
void makeMeshNames(irr::scene::ISceneNode * node);
|
||||
void writeNodeMaterials(irr::scene::ISceneNode * node);
|
||||
void writeNodeEffects(irr::scene::ISceneNode * node);
|
||||
void writeNodeLights(irr::scene::ISceneNode * node);
|
||||
void writeNodeCameras(irr::scene::ISceneNode * node);
|
||||
void writeAllMeshGeometries();
|
||||
void writeSceneNode(irr::scene::ISceneNode * node);
|
||||
void writeMeshMaterials(scene::IMesh* mesh, irr::core::array<irr::core::stringw> * materialNamesOut=0);
|
||||
void writeMeshEffects(scene::IMesh* mesh);
|
||||
void writeMaterialEffect(const irr::core::stringw& materialname, const video::SMaterial & material);
|
||||
void writeMeshGeometry(const irr::core::stringw& meshname, scene::IMesh* mesh);
|
||||
void writeMeshInstanceGeometry(const irr::core::stringw& meshname, scene::IMesh* mesh, scene::ISceneNode* node=0);
|
||||
void writeMaterial(const irr::core::stringw& materialname);
|
||||
void writeLightInstance(const irr::core::stringw& lightName);
|
||||
void writeCameraInstance(const irr::core::stringw& cameraName);
|
||||
void writeLibraryImages();
|
||||
void writeColorFx(const video::SMaterial & material, const wchar_t * colorname, E_COLLADA_COLOR_SAMPLER cs, const wchar_t* attr1Name=0, const wchar_t* attr1Value=0);
|
||||
void writeAmbientLightElement(const video::SColorf & col);
|
||||
void writeColorElement(const video::SColor & col, bool writeAlpha=true);
|
||||
void writeColorElement(const video::SColorf & col, bool writeAlpha=true);
|
||||
void writeTextureSampler(s32 textureIdx);
|
||||
void writeFxElement(const video::SMaterial & material, E_COLLADA_TECHNIQUE_FX techFx);
|
||||
void writeNode(const wchar_t * nodeName, const wchar_t * content);
|
||||
void writeFloatElement(irr::f32 value);
|
||||
void writeRotateElement(const irr::core::vector3df& axis, irr::f32 angle);
|
||||
void writeScaleElement(const irr::core::vector3df& scale);
|
||||
void writeTranslateElement(const irr::core::vector3df& translate);
|
||||
void writeMatrixElement(const irr::core::matrix4& matrix);
|
||||
|
||||
struct SComponentGlobalStartPos
|
||||
{
|
||||
SComponentGlobalStartPos() : PosStartIndex(-1), PosLastIndex(-1),
|
||||
NormalStartIndex(-1), NormalLastIndex(-1),
|
||||
TCoord0StartIndex(-1), TCoord0LastIndex(-1),
|
||||
TCoord1StartIndex(-1), TCoord1LastIndex(-1)
|
||||
{ }
|
||||
|
||||
s32 PosStartIndex;
|
||||
s32 PosLastIndex;
|
||||
|
||||
s32 NormalStartIndex;
|
||||
s32 NormalLastIndex;
|
||||
|
||||
s32 TCoord0StartIndex;
|
||||
s32 TCoord0LastIndex;
|
||||
|
||||
s32 TCoord1StartIndex;
|
||||
s32 TCoord1LastIndex;
|
||||
};
|
||||
|
||||
io::IFileSystem* FileSystem;
|
||||
video::IVideoDriver* VideoDriver;
|
||||
io::IXMLWriter* Writer;
|
||||
core::array<video::ITexture*> LibraryImages;
|
||||
io::path Directory;
|
||||
|
||||
// Helper struct for creating geometry copies for the ECGI_PER_MESH_AND_MATERIAL settings.
|
||||
struct SGeometryMeshMaterials
|
||||
{
|
||||
bool equals(const core::array<irr::core::stringw>& names) const
|
||||
{
|
||||
if ( names.size() != MaterialNames.size() )
|
||||
return false;
|
||||
for ( irr::u32 i=0; i<MaterialNames.size(); ++i )
|
||||
if ( names[i] != MaterialNames[i] )
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
irr::core::stringw GeometryName; // replacing the usual ColladaMesh::Name
|
||||
core::array<irr::core::stringw> MaterialNames; // Material names exported for this instance
|
||||
core::array<const ISceneNode*> MaterialOwners; // Nodes using this specific mesh-material combination
|
||||
};
|
||||
|
||||
// Check per mesh-ptr if stuff has been written for this mesh already
|
||||
struct SColladaMesh
|
||||
{
|
||||
SColladaMesh() : MaterialsWritten(false), EffectsWritten(false)
|
||||
{
|
||||
}
|
||||
|
||||
SGeometryMeshMaterials * findGeometryMeshMaterials(const irr::core::array<irr::core::stringw> materialNames)
|
||||
{
|
||||
for ( irr::u32 i=0; i<GeometryMeshMaterials.size(); ++i )
|
||||
{
|
||||
if ( GeometryMeshMaterials[i].equals(materialNames) )
|
||||
return &(GeometryMeshMaterials[i]);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const irr::core::stringw& findGeometryNameForNode(const ISceneNode* node) const
|
||||
{
|
||||
if ( GeometryMeshMaterials.size() < 2 )
|
||||
return Name;
|
||||
for ( irr::u32 i=0; i<GeometryMeshMaterials.size(); ++i )
|
||||
{
|
||||
if ( GeometryMeshMaterials[i].MaterialOwners.linear_search(node) >= 0 )
|
||||
return GeometryMeshMaterials[i].GeometryName;
|
||||
}
|
||||
return Name; // (shouldn't get here usually)
|
||||
}
|
||||
|
||||
irr::core::stringw Name;
|
||||
bool MaterialsWritten; // just an optimization doing that here in addition to the MaterialsWritten map
|
||||
bool EffectsWritten; // just an optimization doing that here in addition to the EffectsWritten map
|
||||
|
||||
core::array<SGeometryMeshMaterials> GeometryMeshMaterials;
|
||||
};
|
||||
typedef core::map<IMesh*, SColladaMesh>::Node MeshNode;
|
||||
core::map<IMesh*, SColladaMesh> Meshes;
|
||||
|
||||
// structure for the lights library
|
||||
struct SColladaLight
|
||||
{
|
||||
SColladaLight() {}
|
||||
irr::core::stringw Name;
|
||||
};
|
||||
typedef core::map<ISceneNode*, SColladaLight>::Node LightNode;
|
||||
core::map<ISceneNode*, SColladaLight> LightNodes;
|
||||
|
||||
// structure for the camera library
|
||||
typedef core::map<ISceneNode*, irr::core::stringw>::Node CameraNode;
|
||||
core::map<ISceneNode*, irr::core::stringw> CameraNodes;
|
||||
|
||||
// Check per name if stuff has been written already
|
||||
// TODO: second parameter not needed, we just don't have a core::set class yet in Irrlicht
|
||||
core::map<irr::core::stringw, bool> MaterialsWritten;
|
||||
core::map<irr::core::stringw, bool> EffectsWritten;
|
||||
|
||||
// Cache material names
|
||||
struct MaterialName
|
||||
{
|
||||
MaterialName(const irr::video::SMaterial & material, const irr::core::stringw& name)
|
||||
: Material(material), Name(name)
|
||||
{}
|
||||
irr::video::SMaterial Material;
|
||||
irr::core::stringw Name;
|
||||
};
|
||||
irr::core::array< MaterialName > MaterialNameCache;
|
||||
};
|
||||
|
||||
|
||||
} // end namespace
|
||||
} // end namespace
|
||||
|
||||
#endif
|
705
source/Irrlicht/CColorConverter.cpp
Normal file
705
source/Irrlicht/CColorConverter.cpp
Normal file
@ -0,0 +1,705 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#include "CColorConverter.h"
|
||||
#include "SColor.h"
|
||||
#include "os.h"
|
||||
#include "irrString.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace video
|
||||
{
|
||||
|
||||
//! converts a monochrome bitmap to A1R5G5B5 data
|
||||
void CColorConverter::convert1BitTo16Bit(const u8* in, s16* out, s32 width, s32 height, s32 linepad, bool flip)
|
||||
{
|
||||
if (!in || !out)
|
||||
return;
|
||||
|
||||
if (flip)
|
||||
out += width * height;
|
||||
|
||||
for (s32 y=0; y<height; ++y)
|
||||
{
|
||||
s32 shift = 7;
|
||||
if (flip)
|
||||
out -= width;
|
||||
|
||||
for (s32 x=0; x<width; ++x)
|
||||
{
|
||||
out[x] = *in>>shift & 0x01 ? (s16)0xffff : (s16)0x8000;
|
||||
|
||||
if ((--shift)<0) // 8 pixel done
|
||||
{
|
||||
shift=7;
|
||||
++in;
|
||||
}
|
||||
}
|
||||
|
||||
if (shift != 7) // width did not fill last byte
|
||||
++in;
|
||||
|
||||
if (!flip)
|
||||
out += width;
|
||||
in += linepad;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
//! converts a 4 bit palettized image to A1R5G5B5
|
||||
void CColorConverter::convert4BitTo16Bit(const u8* in, s16* out, s32 width, s32 height, const s32* palette, s32 linepad, bool flip)
|
||||
{
|
||||
if (!in || !out || !palette)
|
||||
return;
|
||||
|
||||
if (flip)
|
||||
out += width*height;
|
||||
|
||||
for (s32 y=0; y<height; ++y)
|
||||
{
|
||||
s32 shift = 4;
|
||||
if (flip)
|
||||
out -= width;
|
||||
|
||||
for (s32 x=0; x<width; ++x)
|
||||
{
|
||||
out[x] = X8R8G8B8toA1R5G5B5(palette[(u8)((*in >> shift) & 0xf)]);
|
||||
|
||||
if (shift==0)
|
||||
{
|
||||
shift = 4;
|
||||
++in;
|
||||
}
|
||||
else
|
||||
shift = 0;
|
||||
}
|
||||
|
||||
if (shift == 0) // odd width
|
||||
++in;
|
||||
|
||||
if (!flip)
|
||||
out += width;
|
||||
in += linepad;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
//! converts a 8 bit palettized image into A1R5G5B5
|
||||
void CColorConverter::convert8BitTo16Bit(const u8* in, s16* out, s32 width, s32 height, const s32* palette, s32 linepad, bool flip)
|
||||
{
|
||||
if (!in || !out || !palette)
|
||||
return;
|
||||
|
||||
if (flip)
|
||||
out += width * height;
|
||||
|
||||
for (s32 y=0; y<height; ++y)
|
||||
{
|
||||
if (flip)
|
||||
out -= width; // one line back
|
||||
for (s32 x=0; x<width; ++x)
|
||||
{
|
||||
out[x] = X8R8G8B8toA1R5G5B5(palette[(u8)(*in)]);
|
||||
++in;
|
||||
}
|
||||
if (!flip)
|
||||
out += width;
|
||||
in += linepad;
|
||||
}
|
||||
}
|
||||
|
||||
//! converts a 8 bit palettized or non palettized image (A8) into R8G8B8
|
||||
void CColorConverter::convert8BitTo24Bit(const u8* in, u8* out, s32 width, s32 height, const u8* palette, s32 linepad, bool flip)
|
||||
{
|
||||
if (!in || !out )
|
||||
return;
|
||||
|
||||
const s32 lineWidth = 3 * width;
|
||||
if (flip)
|
||||
out += lineWidth * height;
|
||||
|
||||
for (s32 y=0; y<height; ++y)
|
||||
{
|
||||
if (flip)
|
||||
out -= lineWidth; // one line back
|
||||
for (s32 x=0; x< lineWidth; x += 3)
|
||||
{
|
||||
if ( palette )
|
||||
{
|
||||
#ifdef __BIG_ENDIAN__
|
||||
out[x+0] = palette[ (in[0] << 2 ) + 0];
|
||||
out[x+1] = palette[ (in[0] << 2 ) + 1];
|
||||
out[x+2] = palette[ (in[0] << 2 ) + 2];
|
||||
#else
|
||||
out[x+0] = palette[ (in[0] << 2 ) + 2];
|
||||
out[x+1] = palette[ (in[0] << 2 ) + 1];
|
||||
out[x+2] = palette[ (in[0] << 2 ) + 0];
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
out[x+0] = in[0];
|
||||
out[x+1] = in[0];
|
||||
out[x+2] = in[0];
|
||||
}
|
||||
++in;
|
||||
}
|
||||
if (!flip)
|
||||
out += lineWidth;
|
||||
in += linepad;
|
||||
}
|
||||
}
|
||||
|
||||
//! converts a 8 bit palettized or non palettized image (A8) into R8G8B8
|
||||
void CColorConverter::convert8BitTo32Bit(const u8* in, u8* out, s32 width, s32 height, const u8* palette, s32 linepad, bool flip)
|
||||
{
|
||||
if (!in || !out )
|
||||
return;
|
||||
|
||||
const u32 lineWidth = 4 * width;
|
||||
if (flip)
|
||||
out += lineWidth * height;
|
||||
|
||||
u32 x;
|
||||
register u32 c;
|
||||
for (u32 y=0; y < (u32) height; ++y)
|
||||
{
|
||||
if (flip)
|
||||
out -= lineWidth; // one line back
|
||||
|
||||
if ( palette )
|
||||
{
|
||||
for (x=0; x < (u32) width; x += 1)
|
||||
{
|
||||
c = in[x];
|
||||
((u32*)out)[x] = ((u32*)palette)[ c ];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (x=0; x < (u32) width; x += 1)
|
||||
{
|
||||
c = in[x];
|
||||
#ifdef __BIG_ENDIAN__
|
||||
((u32*)out)[x] = c << 24 | c << 16 | c << 8 | 0x000000FF;
|
||||
#else
|
||||
((u32*)out)[x] = 0xFF000000 | c << 16 | c << 8 | c;
|
||||
#endif
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (!flip)
|
||||
out += lineWidth;
|
||||
in += width + linepad;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
//! converts 16bit data to 16bit data
|
||||
void CColorConverter::convert16BitTo16Bit(const s16* in, s16* out, s32 width, s32 height, s32 linepad, bool flip)
|
||||
{
|
||||
if (!in || !out)
|
||||
return;
|
||||
|
||||
if (flip)
|
||||
out += width * height;
|
||||
|
||||
for (s32 y=0; y<height; ++y)
|
||||
{
|
||||
if (flip)
|
||||
out -= width;
|
||||
#ifdef __BIG_ENDIAN__
|
||||
for (s32 x=0; x<width; ++x)
|
||||
out[x]=os::Byteswap::byteswap(in[x]);
|
||||
#else
|
||||
memcpy(out, in, width*sizeof(s16));
|
||||
#endif
|
||||
if (!flip)
|
||||
out += width;
|
||||
in += width;
|
||||
in += linepad;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
//! copies R8G8B8 24bit data to 24bit data
|
||||
void CColorConverter::convert24BitTo24Bit(const u8* in, u8* out, s32 width, s32 height, s32 linepad, bool flip, bool bgr)
|
||||
{
|
||||
if (!in || !out)
|
||||
return;
|
||||
|
||||
const s32 lineWidth = 3 * width;
|
||||
if (flip)
|
||||
out += lineWidth * height;
|
||||
|
||||
for (s32 y=0; y<height; ++y)
|
||||
{
|
||||
if (flip)
|
||||
out -= lineWidth;
|
||||
if (bgr)
|
||||
{
|
||||
for (s32 x=0; x<lineWidth; x+=3)
|
||||
{
|
||||
out[x+0] = in[x+2];
|
||||
out[x+1] = in[x+1];
|
||||
out[x+2] = in[x+0];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy(out,in,lineWidth);
|
||||
}
|
||||
if (!flip)
|
||||
out += lineWidth;
|
||||
in += lineWidth;
|
||||
in += linepad;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
//! Resizes the surface to a new size and converts it at the same time
|
||||
//! to an A8R8G8B8 format, returning the pointer to the new buffer.
|
||||
void CColorConverter::convert16bitToA8R8G8B8andResize(const s16* in, s32* out, s32 newWidth, s32 newHeight, s32 currentWidth, s32 currentHeight)
|
||||
{
|
||||
if (!newWidth || !newHeight)
|
||||
return;
|
||||
|
||||
// note: this is very very slow. (i didn't want to write a fast version.
|
||||
// but hopefully, nobody wants to convert surfaces every frame.
|
||||
|
||||
f32 sourceXStep = (f32)currentWidth / (f32)newWidth;
|
||||
f32 sourceYStep = (f32)currentHeight / (f32)newHeight;
|
||||
f32 sy;
|
||||
s32 t;
|
||||
|
||||
for (s32 x=0; x<newWidth; ++x)
|
||||
{
|
||||
sy = 0.0f;
|
||||
|
||||
for (s32 y=0; y<newHeight; ++y)
|
||||
{
|
||||
t = in[(s32)(((s32)sy)*currentWidth + x*sourceXStep)];
|
||||
t = (((t >> 15)&0x1)<<31) | (((t >> 10)&0x1F)<<19) |
|
||||
(((t >> 5)&0x1F)<<11) | (t&0x1F)<<3;
|
||||
out[(s32)(y*newWidth + x)] = t;
|
||||
|
||||
sy+=sourceYStep;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
//! copies X8R8G8B8 32 bit data
|
||||
void CColorConverter::convert32BitTo32Bit(const s32* in, s32* out, s32 width, s32 height, s32 linepad, bool flip)
|
||||
{
|
||||
if (!in || !out)
|
||||
return;
|
||||
|
||||
if (flip)
|
||||
out += width * height;
|
||||
|
||||
for (s32 y=0; y<height; ++y)
|
||||
{
|
||||
if (flip)
|
||||
out -= width;
|
||||
#ifdef __BIG_ENDIAN__
|
||||
for (s32 x=0; x<width; ++x)
|
||||
out[x]=os::Byteswap::byteswap(in[x]);
|
||||
#else
|
||||
memcpy(out, in, width*sizeof(s32));
|
||||
#endif
|
||||
if (!flip)
|
||||
out += width;
|
||||
in += width;
|
||||
in += linepad;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void CColorConverter::convert_A1R5G5B5toR8G8B8(const void* sP, s32 sN, void* dP)
|
||||
{
|
||||
u16* sB = (u16*)sP;
|
||||
u8 * dB = (u8 *)dP;
|
||||
|
||||
for (s32 x = 0; x < sN; ++x)
|
||||
{
|
||||
dB[2] = (*sB & 0x7c00) >> 7;
|
||||
dB[1] = (*sB & 0x03e0) >> 2;
|
||||
dB[0] = (*sB & 0x1f) << 3;
|
||||
|
||||
sB += 1;
|
||||
dB += 3;
|
||||
}
|
||||
}
|
||||
|
||||
void CColorConverter::convert_A1R5G5B5toB8G8R8(const void* sP, s32 sN, void* dP)
|
||||
{
|
||||
u16* sB = (u16*)sP;
|
||||
u8 * dB = (u8 *)dP;
|
||||
|
||||
for (s32 x = 0; x < sN; ++x)
|
||||
{
|
||||
dB[0] = (*sB & 0x7c00) >> 7;
|
||||
dB[1] = (*sB & 0x03e0) >> 2;
|
||||
dB[2] = (*sB & 0x1f) << 3;
|
||||
|
||||
sB += 1;
|
||||
dB += 3;
|
||||
}
|
||||
}
|
||||
|
||||
void CColorConverter::convert_A1R5G5B5toA8R8G8B8(const void* sP, s32 sN, void* dP)
|
||||
{
|
||||
u16* sB = (u16*)sP;
|
||||
u32* dB = (u32*)dP;
|
||||
|
||||
for (s32 x = 0; x < sN; ++x)
|
||||
*dB++ = A1R5G5B5toA8R8G8B8(*sB++);
|
||||
}
|
||||
|
||||
void CColorConverter::convert_A1R5G5B5toA1R5G5B5(const void* sP, s32 sN, void* dP)
|
||||
{
|
||||
memcpy(dP, sP, sN * 2);
|
||||
}
|
||||
|
||||
void CColorConverter::convert_A1R5G5B5toR5G6B5(const void* sP, s32 sN, void* dP)
|
||||
{
|
||||
u16* sB = (u16*)sP;
|
||||
u16* dB = (u16*)dP;
|
||||
|
||||
for (s32 x = 0; x < sN; ++x)
|
||||
*dB++ = A1R5G5B5toR5G6B5(*sB++);
|
||||
}
|
||||
|
||||
void CColorConverter::convert_A8R8G8B8toR8G8B8(const void* sP, s32 sN, void* dP)
|
||||
{
|
||||
u8* sB = (u8*)sP;
|
||||
u8* dB = (u8*)dP;
|
||||
|
||||
for (s32 x = 0; x < sN; ++x)
|
||||
{
|
||||
// sB[3] is alpha
|
||||
dB[0] = sB[2];
|
||||
dB[1] = sB[1];
|
||||
dB[2] = sB[0];
|
||||
|
||||
sB += 4;
|
||||
dB += 3;
|
||||
}
|
||||
}
|
||||
|
||||
void CColorConverter::convert_A8R8G8B8toB8G8R8(const void* sP, s32 sN, void* dP)
|
||||
{
|
||||
u8* sB = (u8*)sP;
|
||||
u8* dB = (u8*)dP;
|
||||
|
||||
for (s32 x = 0; x < sN; ++x)
|
||||
{
|
||||
// sB[3] is alpha
|
||||
dB[0] = sB[0];
|
||||
dB[1] = sB[1];
|
||||
dB[2] = sB[2];
|
||||
|
||||
sB += 4;
|
||||
dB += 3;
|
||||
}
|
||||
}
|
||||
|
||||
void CColorConverter::convert_A8R8G8B8toA8R8G8B8(const void* sP, s32 sN, void* dP)
|
||||
{
|
||||
memcpy(dP, sP, sN * 4);
|
||||
}
|
||||
|
||||
void CColorConverter::convert_A8R8G8B8toA1R5G5B5(const void* sP, s32 sN, void* dP)
|
||||
{
|
||||
u32* sB = (u32*)sP;
|
||||
u16* dB = (u16*)dP;
|
||||
|
||||
for (s32 x = 0; x < sN; ++x)
|
||||
*dB++ = A8R8G8B8toA1R5G5B5(*sB++);
|
||||
}
|
||||
|
||||
void CColorConverter::convert_A8R8G8B8toR5G6B5(const void* sP, s32 sN, void* dP)
|
||||
{
|
||||
u8 * sB = (u8 *)sP;
|
||||
u16* dB = (u16*)dP;
|
||||
|
||||
for (s32 x = 0; x < sN; ++x)
|
||||
{
|
||||
s32 r = sB[2] >> 3;
|
||||
s32 g = sB[1] >> 2;
|
||||
s32 b = sB[0] >> 3;
|
||||
|
||||
dB[0] = (r << 11) | (g << 5) | (b);
|
||||
|
||||
sB += 4;
|
||||
dB += 1;
|
||||
}
|
||||
}
|
||||
|
||||
void CColorConverter::convert_A8R8G8B8toR3G3B2(const void* sP, s32 sN, void* dP)
|
||||
{
|
||||
u8* sB = (u8*)sP;
|
||||
u8* dB = (u8*)dP;
|
||||
|
||||
for (s32 x = 0; x < sN; ++x)
|
||||
{
|
||||
u8 r = sB[2] & 0xe0;
|
||||
u8 g = (sB[1] & 0xe0) >> 3;
|
||||
u8 b = (sB[0] & 0xc0) >> 6;
|
||||
|
||||
dB[0] = (r | g | b);
|
||||
|
||||
sB += 4;
|
||||
dB += 1;
|
||||
}
|
||||
}
|
||||
|
||||
void CColorConverter::convert_R8G8B8toR8G8B8(const void* sP, s32 sN, void* dP)
|
||||
{
|
||||
memcpy(dP, sP, sN * 3);
|
||||
}
|
||||
|
||||
void CColorConverter::convert_R8G8B8toA8R8G8B8(const void* sP, s32 sN, void* dP)
|
||||
{
|
||||
u8* sB = (u8* )sP;
|
||||
u32* dB = (u32*)dP;
|
||||
|
||||
for (s32 x = 0; x < sN; ++x)
|
||||
{
|
||||
*dB = 0xff000000 | (sB[0]<<16) | (sB[1]<<8) | sB[2];
|
||||
|
||||
sB += 3;
|
||||
++dB;
|
||||
}
|
||||
}
|
||||
|
||||
void CColorConverter::convert_R8G8B8toA1R5G5B5(const void* sP, s32 sN, void* dP)
|
||||
{
|
||||
u8 * sB = (u8 *)sP;
|
||||
u16* dB = (u16*)dP;
|
||||
|
||||
for (s32 x = 0; x < sN; ++x)
|
||||
{
|
||||
s32 r = sB[0] >> 3;
|
||||
s32 g = sB[1] >> 3;
|
||||
s32 b = sB[2] >> 3;
|
||||
|
||||
dB[0] = (0x8000) | (r << 10) | (g << 5) | (b);
|
||||
|
||||
sB += 3;
|
||||
dB += 1;
|
||||
}
|
||||
}
|
||||
|
||||
void CColorConverter::convert_B8G8R8toA8R8G8B8(const void* sP, s32 sN, void* dP)
|
||||
{
|
||||
u8* sB = (u8* )sP;
|
||||
u32* dB = (u32*)dP;
|
||||
|
||||
for (s32 x = 0; x < sN; ++x)
|
||||
{
|
||||
*dB = 0xff000000 | (sB[2]<<16) | (sB[1]<<8) | sB[0];
|
||||
|
||||
sB += 3;
|
||||
++dB;
|
||||
}
|
||||
}
|
||||
|
||||
void CColorConverter::convert_B8G8R8A8toA8R8G8B8(const void* sP, s32 sN, void* dP)
|
||||
{
|
||||
u8* sB = (u8*)sP;
|
||||
u8* dB = (u8*)dP;
|
||||
|
||||
for (s32 x = 0; x < sN; ++x)
|
||||
{
|
||||
dB[0] = sB[3];
|
||||
dB[1] = sB[2];
|
||||
dB[2] = sB[1];
|
||||
dB[3] = sB[0];
|
||||
|
||||
sB += 4;
|
||||
dB += 4;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void CColorConverter::convert_R8G8B8toR5G6B5(const void* sP, s32 sN, void* dP)
|
||||
{
|
||||
u8 * sB = (u8 *)sP;
|
||||
u16* dB = (u16*)dP;
|
||||
|
||||
for (s32 x = 0; x < sN; ++x)
|
||||
{
|
||||
s32 r = sB[0] >> 3;
|
||||
s32 g = sB[1] >> 2;
|
||||
s32 b = sB[2] >> 3;
|
||||
|
||||
dB[0] = (r << 11) | (g << 5) | (b);
|
||||
|
||||
sB += 3;
|
||||
dB += 1;
|
||||
}
|
||||
}
|
||||
|
||||
void CColorConverter::convert_R5G6B5toR5G6B5(const void* sP, s32 sN, void* dP)
|
||||
{
|
||||
memcpy(dP, sP, sN * 2);
|
||||
}
|
||||
|
||||
void CColorConverter::convert_R5G6B5toR8G8B8(const void* sP, s32 sN, void* dP)
|
||||
{
|
||||
u16* sB = (u16*)sP;
|
||||
u8 * dB = (u8 *)dP;
|
||||
|
||||
for (s32 x = 0; x < sN; ++x)
|
||||
{
|
||||
dB[0] = (*sB & 0xf800) >> 8;
|
||||
dB[1] = (*sB & 0x07e0) >> 3;
|
||||
dB[2] = (*sB & 0x001f) << 3;
|
||||
|
||||
sB += 1;
|
||||
dB += 3;
|
||||
}
|
||||
}
|
||||
|
||||
void CColorConverter::convert_R5G6B5toB8G8R8(const void* sP, s32 sN, void* dP)
|
||||
{
|
||||
u16* sB = (u16*)sP;
|
||||
u8 * dB = (u8 *)dP;
|
||||
|
||||
for (s32 x = 0; x < sN; ++x)
|
||||
{
|
||||
dB[2] = (*sB & 0xf800) >> 8;
|
||||
dB[1] = (*sB & 0x07e0) >> 3;
|
||||
dB[0] = (*sB & 0x001f) << 3;
|
||||
|
||||
sB += 1;
|
||||
dB += 3;
|
||||
}
|
||||
}
|
||||
|
||||
void CColorConverter::convert_R5G6B5toA8R8G8B8(const void* sP, s32 sN, void* dP)
|
||||
{
|
||||
u16* sB = (u16*)sP;
|
||||
u32* dB = (u32*)dP;
|
||||
|
||||
for (s32 x = 0; x < sN; ++x)
|
||||
*dB++ = R5G6B5toA8R8G8B8(*sB++);
|
||||
}
|
||||
|
||||
void CColorConverter::convert_R5G6B5toA1R5G5B5(const void* sP, s32 sN, void* dP)
|
||||
{
|
||||
u16* sB = (u16*)sP;
|
||||
u16* dB = (u16*)dP;
|
||||
|
||||
for (s32 x = 0; x < sN; ++x)
|
||||
*dB++ = R5G6B5toA1R5G5B5(*sB++);
|
||||
}
|
||||
|
||||
|
||||
void CColorConverter::convert_viaFormat(const void* sP, ECOLOR_FORMAT sF, s32 sN,
|
||||
void* dP, ECOLOR_FORMAT dF)
|
||||
{
|
||||
switch (sF)
|
||||
{
|
||||
case ECF_A1R5G5B5:
|
||||
switch (dF)
|
||||
{
|
||||
case ECF_A1R5G5B5:
|
||||
convert_A1R5G5B5toA1R5G5B5(sP, sN, dP);
|
||||
break;
|
||||
case ECF_R5G6B5:
|
||||
convert_A1R5G5B5toR5G6B5(sP, sN, dP);
|
||||
break;
|
||||
case ECF_A8R8G8B8:
|
||||
convert_A1R5G5B5toA8R8G8B8(sP, sN, dP);
|
||||
break;
|
||||
case ECF_R8G8B8:
|
||||
convert_A1R5G5B5toR8G8B8(sP, sN, dP);
|
||||
break;
|
||||
#ifndef _DEBUG
|
||||
default:
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
case ECF_R5G6B5:
|
||||
switch (dF)
|
||||
{
|
||||
case ECF_A1R5G5B5:
|
||||
convert_R5G6B5toA1R5G5B5(sP, sN, dP);
|
||||
break;
|
||||
case ECF_R5G6B5:
|
||||
convert_R5G6B5toR5G6B5(sP, sN, dP);
|
||||
break;
|
||||
case ECF_A8R8G8B8:
|
||||
convert_R5G6B5toA8R8G8B8(sP, sN, dP);
|
||||
break;
|
||||
case ECF_R8G8B8:
|
||||
convert_R5G6B5toR8G8B8(sP, sN, dP);
|
||||
break;
|
||||
#ifndef _DEBUG
|
||||
default:
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
case ECF_A8R8G8B8:
|
||||
switch (dF)
|
||||
{
|
||||
case ECF_A1R5G5B5:
|
||||
convert_A8R8G8B8toA1R5G5B5(sP, sN, dP);
|
||||
break;
|
||||
case ECF_R5G6B5:
|
||||
convert_A8R8G8B8toR5G6B5(sP, sN, dP);
|
||||
break;
|
||||
case ECF_A8R8G8B8:
|
||||
convert_A8R8G8B8toA8R8G8B8(sP, sN, dP);
|
||||
break;
|
||||
case ECF_R8G8B8:
|
||||
convert_A8R8G8B8toR8G8B8(sP, sN, dP);
|
||||
break;
|
||||
#ifndef _DEBUG
|
||||
default:
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
case ECF_R8G8B8:
|
||||
switch (dF)
|
||||
{
|
||||
case ECF_A1R5G5B5:
|
||||
convert_R8G8B8toA1R5G5B5(sP, sN, dP);
|
||||
break;
|
||||
case ECF_R5G6B5:
|
||||
convert_R8G8B8toR5G6B5(sP, sN, dP);
|
||||
break;
|
||||
case ECF_A8R8G8B8:
|
||||
convert_R8G8B8toA8R8G8B8(sP, sN, dP);
|
||||
break;
|
||||
case ECF_R8G8B8:
|
||||
convert_R8G8B8toR8G8B8(sP, sN, dP);
|
||||
break;
|
||||
#ifndef _DEBUG
|
||||
default:
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
} // end namespace video
|
||||
} // end namespace irr
|
92
source/Irrlicht/CColorConverter.h
Normal file
92
source/Irrlicht/CColorConverter.h
Normal file
@ -0,0 +1,92 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#ifndef __C_COLOR_CONVERTER_H_INCLUDED__
|
||||
#define __C_COLOR_CONVERTER_H_INCLUDED__
|
||||
|
||||
#include "irrTypes.h"
|
||||
#include "IImage.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace video
|
||||
{
|
||||
|
||||
class CColorConverter
|
||||
{
|
||||
public:
|
||||
|
||||
//! converts a monochrome bitmap to A1R5G5B5
|
||||
static void convert1BitTo16Bit(const u8* in, s16* out, s32 width, s32 height, s32 linepad=0, bool flip=false);
|
||||
|
||||
//! converts a 4 bit palettized image to A1R5G5B5
|
||||
static void convert4BitTo16Bit(const u8* in, s16* out, s32 width, s32 height, const s32* palette, s32 linepad=0, bool flip=false);
|
||||
|
||||
//! converts a 8 bit palettized image to A1R5G5B5
|
||||
static void convert8BitTo16Bit(const u8* in, s16* out, s32 width, s32 height, const s32* palette, s32 linepad=0, bool flip=false);
|
||||
|
||||
//! converts a 8 bit palettized or non palettized image (A8) into R8G8B8
|
||||
static void convert8BitTo24Bit(const u8* in, u8* out, s32 width, s32 height, const u8* palette, s32 linepad = 0, bool flip=false);
|
||||
|
||||
//! converts a 8 bit palettized or non palettized image (A8) into A8R8G8B8
|
||||
static void convert8BitTo32Bit(const u8* in, u8* out, s32 width, s32 height, const u8* palette, s32 linepad = 0, bool flip=false);
|
||||
|
||||
//! converts R8G8B8 16 bit data to A1R5G5B5 data
|
||||
static void convert16BitTo16Bit(const s16* in, s16* out, s32 width, s32 height, s32 linepad=0, bool flip=false);
|
||||
|
||||
//! copies R8G8B8 24 bit data to 24 data, and flips and
|
||||
//! mirrors the image during the process.
|
||||
static void convert24BitTo24Bit(const u8* in, u8* out, s32 width, s32 height, s32 linepad=0, bool flip=false, bool bgr=false);
|
||||
|
||||
//! Resizes the surface to a new size and converts it at the same time
|
||||
//! to an A8R8G8B8 format, returning the pointer to the new buffer.
|
||||
static void convert16bitToA8R8G8B8andResize(const s16* in, s32* out, s32 newWidth, s32 newHeight, s32 currentWidth, s32 currentHeight);
|
||||
|
||||
//! copies X8R8G8B8 32 bit data, and flips and
|
||||
//! mirrors the image during the process.
|
||||
static void convert32BitTo32Bit(const s32* in, s32* out, s32 width, s32 height, s32 linepad, bool flip=false);
|
||||
|
||||
|
||||
//! functions for converting one image format to another efficiently
|
||||
//! and hopefully correctly.
|
||||
//!
|
||||
//! \param sP pointer to source pixel data
|
||||
//! \param sN number of source pixels to copy
|
||||
//! \param dP pointer to destination data buffer. must be big enough
|
||||
//! to hold sN pixels in the output format.
|
||||
static void convert_A1R5G5B5toR8G8B8(const void* sP, s32 sN, void* dP);
|
||||
static void convert_A1R5G5B5toB8G8R8(const void* sP, s32 sN, void* dP);
|
||||
static void convert_A1R5G5B5toA8R8G8B8(const void* sP, s32 sN, void* dP);
|
||||
static void convert_A1R5G5B5toA1R5G5B5(const void* sP, s32 sN, void* dP);
|
||||
static void convert_A1R5G5B5toR5G6B5(const void* sP, s32 sN, void* dP);
|
||||
|
||||
static void convert_A8R8G8B8toR8G8B8(const void* sP, s32 sN, void* dP);
|
||||
static void convert_A8R8G8B8toB8G8R8(const void* sP, s32 sN, void* dP);
|
||||
static void convert_A8R8G8B8toA8R8G8B8(const void* sP, s32 sN, void* dP);
|
||||
static void convert_A8R8G8B8toA1R5G5B5(const void* sP, s32 sN, void* dP);
|
||||
static void convert_A8R8G8B8toR5G6B5(const void* sP, s32 sN, void* dP);
|
||||
|
||||
static void convert_A8R8G8B8toR3G3B2(const void* sP, s32 sN, void* dP);
|
||||
static void convert_R8G8B8toR8G8B8(const void* sP, s32 sN, void* dP);
|
||||
static void convert_R8G8B8toA8R8G8B8(const void* sP, s32 sN, void* dP);
|
||||
static void convert_R8G8B8toA1R5G5B5(const void* sP, s32 sN, void* dP);
|
||||
static void convert_R8G8B8toR5G6B5(const void* sP, s32 sN, void* dP);
|
||||
static void convert_B8G8R8toA8R8G8B8(const void* sP, s32 sN, void* dP);
|
||||
static void convert_B8G8R8A8toA8R8G8B8(const void* sP, s32 sN, void* dP);
|
||||
|
||||
static void convert_R5G6B5toR5G6B5(const void* sP, s32 sN, void* dP);
|
||||
static void convert_R5G6B5toR8G8B8(const void* sP, s32 sN, void* dP);
|
||||
static void convert_R5G6B5toB8G8R8(const void* sP, s32 sN, void* dP);
|
||||
static void convert_R5G6B5toA8R8G8B8(const void* sP, s32 sN, void* dP);
|
||||
static void convert_R5G6B5toA1R5G5B5(const void* sP, s32 sN, void* dP);
|
||||
static void convert_viaFormat(const void* sP, ECOLOR_FORMAT sF, s32 sN,
|
||||
void* dP, ECOLOR_FORMAT dF);
|
||||
};
|
||||
|
||||
|
||||
} // end namespace video
|
||||
} // end namespace irr
|
||||
|
||||
#endif
|
||||
|
235
source/Irrlicht/CCubeSceneNode.cpp
Normal file
235
source/Irrlicht/CCubeSceneNode.cpp
Normal file
@ -0,0 +1,235 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#include "CCubeSceneNode.h"
|
||||
#include "IVideoDriver.h"
|
||||
#include "ISceneManager.h"
|
||||
#include "S3DVertex.h"
|
||||
#include "SMeshBuffer.h"
|
||||
#include "os.h"
|
||||
#include "CShadowVolumeSceneNode.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace scene
|
||||
{
|
||||
|
||||
/*
|
||||
011 111
|
||||
/6,8------/5 y
|
||||
/ | / | ^ z
|
||||
/ | / | | /
|
||||
010 3,9-------2 | |/
|
||||
| 7- - -10,4 101 *---->x
|
||||
| / | /
|
||||
|/ | /
|
||||
0------11,1/
|
||||
000 100
|
||||
*/
|
||||
|
||||
//! constructor
|
||||
CCubeSceneNode::CCubeSceneNode(f32 size, ISceneNode* parent, ISceneManager* mgr,
|
||||
s32 id, const core::vector3df& position,
|
||||
const core::vector3df& rotation, const core::vector3df& scale)
|
||||
: IMeshSceneNode(parent, mgr, id, position, rotation, scale),
|
||||
Mesh(0), Shadow(0), Size(size)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
setDebugName("CCubeSceneNode");
|
||||
#endif
|
||||
|
||||
setSize();
|
||||
}
|
||||
|
||||
|
||||
CCubeSceneNode::~CCubeSceneNode()
|
||||
{
|
||||
if (Shadow)
|
||||
Shadow->drop();
|
||||
if (Mesh)
|
||||
Mesh->drop();
|
||||
}
|
||||
|
||||
|
||||
void CCubeSceneNode::setSize()
|
||||
{
|
||||
if (Mesh)
|
||||
Mesh->drop();
|
||||
Mesh = SceneManager->getGeometryCreator()->createCubeMesh(core::vector3df(Size));
|
||||
}
|
||||
|
||||
|
||||
//! renders the node.
|
||||
void CCubeSceneNode::render()
|
||||
{
|
||||
video::IVideoDriver* driver = SceneManager->getVideoDriver();
|
||||
driver->setTransform(video::ETS_WORLD, AbsoluteTransformation);
|
||||
|
||||
if (Shadow)
|
||||
Shadow->updateShadowVolumes();
|
||||
|
||||
// for debug purposes only:
|
||||
video::SMaterial mat = Mesh->getMeshBuffer(0)->getMaterial();
|
||||
|
||||
// overwrite half transparency
|
||||
if (DebugDataVisible & scene::EDS_HALF_TRANSPARENCY)
|
||||
mat.MaterialType = video::EMT_TRANSPARENT_ADD_COLOR;
|
||||
driver->setMaterial(mat);
|
||||
driver->drawMeshBuffer(Mesh->getMeshBuffer(0));
|
||||
|
||||
// for debug purposes only:
|
||||
if (DebugDataVisible)
|
||||
{
|
||||
video::SMaterial m;
|
||||
m.Lighting = false;
|
||||
m.AntiAliasing=0;
|
||||
driver->setMaterial(m);
|
||||
|
||||
if (DebugDataVisible & scene::EDS_BBOX)
|
||||
{
|
||||
driver->draw3DBox(Mesh->getMeshBuffer(0)->getBoundingBox(), video::SColor(255,255,255,255));
|
||||
}
|
||||
if (DebugDataVisible & scene::EDS_BBOX_BUFFERS)
|
||||
{
|
||||
driver->draw3DBox(Mesh->getMeshBuffer(0)->getBoundingBox(),
|
||||
video::SColor(255,190,128,128));
|
||||
}
|
||||
if (DebugDataVisible & scene::EDS_NORMALS)
|
||||
{
|
||||
// draw normals
|
||||
const f32 debugNormalLength = SceneManager->getParameters()->getAttributeAsFloat(DEBUG_NORMAL_LENGTH);
|
||||
const video::SColor debugNormalColor = SceneManager->getParameters()->getAttributeAsColor(DEBUG_NORMAL_COLOR);
|
||||
const u32 count = Mesh->getMeshBufferCount();
|
||||
|
||||
for (u32 i=0; i != count; ++i)
|
||||
{
|
||||
driver->drawMeshBufferNormals(Mesh->getMeshBuffer(i), debugNormalLength, debugNormalColor);
|
||||
}
|
||||
}
|
||||
|
||||
// show mesh
|
||||
if (DebugDataVisible & scene::EDS_MESH_WIRE_OVERLAY)
|
||||
{
|
||||
m.Wireframe = true;
|
||||
driver->setMaterial(m);
|
||||
|
||||
driver->drawMeshBuffer(Mesh->getMeshBuffer(0));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//! returns the axis aligned bounding box of this node
|
||||
const core::aabbox3d<f32>& CCubeSceneNode::getBoundingBox() const
|
||||
{
|
||||
return Mesh->getMeshBuffer(0)->getBoundingBox();
|
||||
}
|
||||
|
||||
|
||||
//! Removes a child from this scene node.
|
||||
//! Implemented here, to be able to remove the shadow properly, if there is one,
|
||||
//! or to remove attached childs.
|
||||
bool CCubeSceneNode::removeChild(ISceneNode* child)
|
||||
{
|
||||
if (child && Shadow == child)
|
||||
{
|
||||
Shadow->drop();
|
||||
Shadow = 0;
|
||||
}
|
||||
|
||||
return ISceneNode::removeChild(child);
|
||||
}
|
||||
|
||||
|
||||
//! Creates shadow volume scene node as child of this node
|
||||
//! and returns a pointer to it.
|
||||
IShadowVolumeSceneNode* CCubeSceneNode::addShadowVolumeSceneNode(
|
||||
const IMesh* shadowMesh, s32 id, bool zfailmethod, f32 infinity)
|
||||
{
|
||||
if (!SceneManager->getVideoDriver()->queryFeature(video::EVDF_STENCIL_BUFFER))
|
||||
return 0;
|
||||
|
||||
if (!shadowMesh)
|
||||
shadowMesh = Mesh; // if null is given, use the mesh of node
|
||||
|
||||
if (Shadow)
|
||||
Shadow->drop();
|
||||
|
||||
Shadow = new CShadowVolumeSceneNode(shadowMesh, this, SceneManager, id, zfailmethod, infinity);
|
||||
return Shadow;
|
||||
}
|
||||
|
||||
|
||||
void CCubeSceneNode::OnRegisterSceneNode()
|
||||
{
|
||||
if (IsVisible)
|
||||
SceneManager->registerNodeForRendering(this);
|
||||
ISceneNode::OnRegisterSceneNode();
|
||||
}
|
||||
|
||||
|
||||
//! returns the material based on the zero based index i.
|
||||
video::SMaterial& CCubeSceneNode::getMaterial(u32 i)
|
||||
{
|
||||
return Mesh->getMeshBuffer(0)->getMaterial();
|
||||
}
|
||||
|
||||
|
||||
//! returns amount of materials used by this scene node.
|
||||
u32 CCubeSceneNode::getMaterialCount() const
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
//! Writes attributes of the scene node.
|
||||
void CCubeSceneNode::serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options) const
|
||||
{
|
||||
ISceneNode::serializeAttributes(out, options);
|
||||
|
||||
out->addFloat("Size", Size);
|
||||
}
|
||||
|
||||
|
||||
//! Reads attributes of the scene node.
|
||||
void CCubeSceneNode::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options)
|
||||
{
|
||||
f32 newSize = in->getAttributeAsFloat("Size");
|
||||
newSize = core::max_(newSize, 0.0001f);
|
||||
if (newSize != Size)
|
||||
{
|
||||
Size = newSize;
|
||||
setSize();
|
||||
}
|
||||
|
||||
ISceneNode::deserializeAttributes(in, options);
|
||||
}
|
||||
|
||||
|
||||
//! Creates a clone of this scene node and its children.
|
||||
ISceneNode* CCubeSceneNode::clone(ISceneNode* newParent, ISceneManager* newManager)
|
||||
{
|
||||
if (!newParent)
|
||||
newParent = Parent;
|
||||
if (!newManager)
|
||||
newManager = SceneManager;
|
||||
|
||||
CCubeSceneNode* nb = new CCubeSceneNode(Size, newParent,
|
||||
newManager, ID, RelativeTranslation);
|
||||
|
||||
nb->cloneMembers(this, newManager);
|
||||
nb->getMaterial(0) = getMaterial(0);
|
||||
nb->Shadow = Shadow;
|
||||
if ( nb->Shadow )
|
||||
nb->Shadow->grab();
|
||||
|
||||
if ( newParent )
|
||||
nb->drop();
|
||||
return nb;
|
||||
}
|
||||
|
||||
|
||||
} // end namespace scene
|
||||
} // end namespace irr
|
||||
|
93
source/Irrlicht/CCubeSceneNode.h
Normal file
93
source/Irrlicht/CCubeSceneNode.h
Normal file
@ -0,0 +1,93 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#ifndef __C_CUBE_SCENE_NODE_H_INCLUDED__
|
||||
#define __C_CUBE_SCENE_NODE_H_INCLUDED__
|
||||
|
||||
#include "IMeshSceneNode.h"
|
||||
#include "SMesh.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace scene
|
||||
{
|
||||
class CCubeSceneNode : public IMeshSceneNode
|
||||
{
|
||||
public:
|
||||
|
||||
//! constructor
|
||||
CCubeSceneNode(f32 size, ISceneNode* parent, ISceneManager* mgr, s32 id,
|
||||
const core::vector3df& position = core::vector3df(0,0,0),
|
||||
const core::vector3df& rotation = core::vector3df(0,0,0),
|
||||
const core::vector3df& scale = core::vector3df(1.0f, 1.0f, 1.0f));
|
||||
|
||||
virtual ~CCubeSceneNode();
|
||||
|
||||
virtual void OnRegisterSceneNode();
|
||||
|
||||
//! renders the node.
|
||||
virtual void render();
|
||||
|
||||
//! returns the axis aligned bounding box of this node
|
||||
virtual const core::aabbox3d<f32>& getBoundingBox() const;
|
||||
|
||||
//! returns the material based on the zero based index i. To get the amount
|
||||
//! of materials used by this scene node, use getMaterialCount().
|
||||
//! This function is needed for inserting the node into the scene hirachy on a
|
||||
//! optimal position for minimizing renderstate changes, but can also be used
|
||||
//! to directly modify the material of a scene node.
|
||||
virtual video::SMaterial& getMaterial(u32 i);
|
||||
|
||||
//! returns amount of materials used by this scene node.
|
||||
virtual u32 getMaterialCount() const;
|
||||
|
||||
//! Returns type of the scene node
|
||||
virtual ESCENE_NODE_TYPE getType() const { return ESNT_CUBE; }
|
||||
|
||||
//! Creates shadow volume scene node as child of this node
|
||||
//! and returns a pointer to it.
|
||||
virtual IShadowVolumeSceneNode* addShadowVolumeSceneNode(const IMesh* shadowMesh,
|
||||
s32 id, bool zfailmethod=true, f32 infinity=10000.0f);
|
||||
|
||||
//! Writes attributes of the scene node.
|
||||
virtual void serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options=0) const;
|
||||
|
||||
//! Reads attributes of the scene node.
|
||||
virtual void deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options=0);
|
||||
|
||||
//! Creates a clone of this scene node and its children.
|
||||
virtual ISceneNode* clone(ISceneNode* newParent=0, ISceneManager* newManager=0);
|
||||
|
||||
//! Sets a new mesh to display
|
||||
virtual void setMesh(IMesh* mesh) {}
|
||||
|
||||
//! Returns the current mesh
|
||||
virtual IMesh* getMesh(void) { return Mesh; }
|
||||
|
||||
//! Sets if the scene node should not copy the materials of the mesh but use them in a read only style.
|
||||
/* In this way it is possible to change the materials a mesh causing all mesh scene nodes
|
||||
referencing this mesh to change too. */
|
||||
virtual void setReadOnlyMaterials(bool readonly) {}
|
||||
|
||||
//! Returns if the scene node should not copy the materials of the mesh but use them in a read only style
|
||||
virtual bool isReadOnlyMaterials() const { return false; }
|
||||
|
||||
//! Removes a child from this scene node.
|
||||
//! Implemented here, to be able to remove the shadow properly, if there is one,
|
||||
//! or to remove attached childs.
|
||||
virtual bool removeChild(ISceneNode* child);
|
||||
|
||||
private:
|
||||
void setSize();
|
||||
|
||||
IMesh* Mesh;
|
||||
IShadowVolumeSceneNode* Shadow;
|
||||
f32 Size;
|
||||
};
|
||||
|
||||
} // end namespace scene
|
||||
} // end namespace irr
|
||||
|
||||
#endif
|
||||
|
2455
source/Irrlicht/CD3D8Driver.cpp
Normal file
2455
source/Irrlicht/CD3D8Driver.cpp
Normal file
File diff suppressed because it is too large
Load Diff
341
source/Irrlicht/CD3D8Driver.h
Normal file
341
source/Irrlicht/CD3D8Driver.h
Normal file
@ -0,0 +1,341 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#ifndef __C_VIDEO_DIRECTX_8_H_INCLUDED__
|
||||
#define __C_VIDEO_DIRECTX_8_H_INCLUDED__
|
||||
|
||||
#include "IrrCompileConfig.h"
|
||||
|
||||
#ifdef _IRR_COMPILE_WITH_DIRECT3D_8_
|
||||
|
||||
#ifdef _IRR_WINDOWS_
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
#include "SIrrCreationParameters.h"
|
||||
// always included for static createDriver function
|
||||
#include "CNullDriver.h"
|
||||
#include "IMaterialRendererServices.h"
|
||||
|
||||
#include <d3d8.h>
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace video
|
||||
{
|
||||
class CD3D8Driver : public CNullDriver, IMaterialRendererServices
|
||||
{
|
||||
friend class CD3D8Texture;
|
||||
|
||||
public:
|
||||
|
||||
//! constructor
|
||||
CD3D8Driver(const SIrrlichtCreationParameters& params, io::IFileSystem* io);
|
||||
|
||||
//! destructor
|
||||
virtual ~CD3D8Driver();
|
||||
|
||||
//! applications must call this method before performing any rendering. returns false if failed.
|
||||
virtual bool beginScene(bool backBuffer=true, bool zBuffer=true,
|
||||
SColor color=SColor(255,0,0,0),
|
||||
const SExposedVideoData& videoData=SExposedVideoData(),
|
||||
core::rect<s32>* sourceRect=0);
|
||||
|
||||
//! applications must call this method after performing any rendering. returns false if failed.
|
||||
virtual bool endScene();
|
||||
|
||||
//! queries the features of the driver, returns true if feature is available
|
||||
virtual bool queryFeature(E_VIDEO_DRIVER_FEATURE feature) const;
|
||||
|
||||
//! sets transformation
|
||||
virtual void setTransform(E_TRANSFORMATION_STATE state, const core::matrix4& mat);
|
||||
|
||||
//! sets a material
|
||||
virtual void setMaterial(const SMaterial& material);
|
||||
|
||||
//! sets a render target
|
||||
virtual bool setRenderTarget(video::ITexture* texture,
|
||||
bool clearBackBuffer=true, bool clearZBuffer=true,
|
||||
SColor color=video::SColor(0,0,0,0));
|
||||
|
||||
//! sets a viewport
|
||||
virtual void setViewPort(const core::rect<s32>& area);
|
||||
|
||||
//! gets the area of the current viewport
|
||||
virtual const core::rect<s32>& getViewPort() const;
|
||||
|
||||
//! draws a vertex primitive list
|
||||
virtual void drawVertexPrimitiveList(const void* vertices, u32 vertexCount,
|
||||
const void* indexList, u32 primitiveCount,
|
||||
E_VERTEX_TYPE vType, scene::E_PRIMITIVE_TYPE pType,
|
||||
E_INDEX_TYPE iType);
|
||||
|
||||
//! draws a vertex primitive list in 2d
|
||||
virtual void draw2DVertexPrimitiveList(const void* vertices, u32 vertexCount,
|
||||
const void* indexList, u32 primitiveCount,
|
||||
E_VERTEX_TYPE vType, scene::E_PRIMITIVE_TYPE pType,
|
||||
E_INDEX_TYPE iType);
|
||||
|
||||
//! draws an 2d image, using a color (if color is other then Color(255,255,255,255)) and the alpha channel of the texture if wanted.
|
||||
virtual void draw2DImage(const video::ITexture* texture, const core::position2d<s32>& destPos,
|
||||
const core::rect<s32>& sourceRect, const core::rect<s32>* clipRect = 0,
|
||||
SColor color=SColor(255,255,255,255), bool useAlphaChannelOfTexture=false);
|
||||
|
||||
//! Draws a part of the texture into the rectangle.
|
||||
virtual void draw2DImage(const video::ITexture* texture, const core::rect<s32>& destRect,
|
||||
const core::rect<s32>& sourceRect, const core::rect<s32>* clipRect = 0,
|
||||
const video::SColor* const colors=0, bool useAlphaChannelOfTexture=false);
|
||||
|
||||
//!Draws an 2d rectangle with a gradient.
|
||||
virtual void draw2DRectangle(const core::rect<s32>& pos,
|
||||
SColor colorLeftUp, SColor colorRightUp, SColor colorLeftDown, SColor colorRightDown,
|
||||
const core::rect<s32>* clip = 0);
|
||||
|
||||
//! Draws a 2d line.
|
||||
virtual void draw2DLine(const core::position2d<s32>& start,
|
||||
const core::position2d<s32>& end,
|
||||
SColor color=SColor(255,255,255,255));
|
||||
|
||||
//! Draws a pixel.
|
||||
virtual void drawPixel(u32 x, u32 y, const SColor & color);
|
||||
|
||||
//! Draws a 3d line.
|
||||
virtual void draw3DLine(const core::vector3df& start,
|
||||
const core::vector3df& end, SColor color = SColor(255,255,255,255));
|
||||
|
||||
//! initialises the Direct3D API
|
||||
bool initDriver(HWND hwnd, bool pureSoftware);
|
||||
|
||||
//! \return Returns the name of the video driver. Example: In case of the DIRECT3D8
|
||||
//! driver, it would return "Direct3D8.1".
|
||||
virtual const wchar_t* getName() const;
|
||||
|
||||
//! deletes all dynamic lights there are
|
||||
virtual void deleteAllDynamicLights();
|
||||
|
||||
//! adds a dynamic light, returning an index to the light
|
||||
//! \param light: the light data to use to create the light
|
||||
//! \return An index to the light, or -1 if an error occurs
|
||||
virtual s32 addDynamicLight(const SLight& light);
|
||||
|
||||
//! Turns a dynamic light on or off
|
||||
//! \param lightIndex: the index returned by addDynamicLight
|
||||
//! \param turnOn: true to turn the light on, false to turn it off
|
||||
virtual void turnLightOn(s32 lightIndex, bool turnOn);
|
||||
|
||||
//! returns the maximal amount of dynamic lights the device can handle
|
||||
virtual u32 getMaximalDynamicLightAmount() const;
|
||||
|
||||
//! Sets the dynamic ambient light color. The default color is
|
||||
//! (0,0,0,0) which means it is dark.
|
||||
//! \param color: New color of the ambient light.
|
||||
virtual void setAmbientLight(const SColorf& color);
|
||||
|
||||
//! Draws a shadow volume into the stencil buffer. To draw a stencil shadow, do
|
||||
//! this: Frist, draw all geometry. Then use this method, to draw the shadow
|
||||
//! volume. Then, use IVideoDriver::drawStencilShadow() to visualize the shadow.
|
||||
virtual void drawStencilShadowVolume(const core::array<core::vector3df>& triangles, bool zfail=true, u32 debugDataVisible=0);
|
||||
|
||||
//! Fills the stencil shadow with color. After the shadow volume has been drawn
|
||||
//! into the stencil buffer using IVideoDriver::drawStencilShadowVolume(), use this
|
||||
//! to draw the color of the shadow.
|
||||
virtual void drawStencilShadow(bool clearStencilBuffer=false,
|
||||
video::SColor leftUpEdge = video::SColor(0,0,0,0),
|
||||
video::SColor rightUpEdge = video::SColor(0,0,0,0),
|
||||
video::SColor leftDownEdge = video::SColor(0,0,0,0),
|
||||
video::SColor rightDownEdge = video::SColor(0,0,0,0));
|
||||
|
||||
//! Returns the maximum amount of primitives (mostly vertices) which
|
||||
//! the device is able to render with one drawIndexedTriangleList
|
||||
//! call.
|
||||
virtual u32 getMaximalPrimitiveCount() const;
|
||||
|
||||
//! Enables or disables a texture creation flag.
|
||||
virtual void setTextureCreationFlag(E_TEXTURE_CREATION_FLAG flag, bool enabled);
|
||||
|
||||
//! Sets the fog mode.
|
||||
virtual void setFog(SColor color, E_FOG_TYPE fogType, f32 start,
|
||||
f32 end, f32 density, bool pixelFog, bool rangeFog);
|
||||
|
||||
//! Only used by the internal engine. Used to notify the driver that
|
||||
//! the window was resized.
|
||||
virtual void OnResize(const core::dimension2d<u32>& size);
|
||||
|
||||
//! Returns type of video driver
|
||||
virtual E_DRIVER_TYPE getDriverType() const;
|
||||
|
||||
//! Returns the transformation set by setTransform
|
||||
virtual const core::matrix4& getTransform(E_TRANSFORMATION_STATE state) const;
|
||||
|
||||
//! Can be called by an IMaterialRenderer to make its work easier.
|
||||
virtual void setBasicRenderStates(const SMaterial& material, const SMaterial& lastMaterial,
|
||||
bool resetAllRenderstates);
|
||||
|
||||
//! Sets a vertex shader constant.
|
||||
virtual void setVertexShaderConstant(const f32* data, s32 startRegister, s32 constantAmount=1);
|
||||
|
||||
//! Sets a pixel shader constant.
|
||||
virtual void setPixelShaderConstant(const f32* data, s32 startRegister, s32 constantAmount=1);
|
||||
|
||||
//! Sets a constant for the vertex shader based on a name.
|
||||
virtual bool setVertexShaderConstant(const c8* name, const f32* floats, int count);
|
||||
|
||||
//! Bool interface for the above.
|
||||
virtual bool setVertexShaderConstant(const c8* name, const bool* bools, int count);
|
||||
|
||||
//! Int interface for the above.
|
||||
virtual bool setVertexShaderConstant(const c8* name, const s32* ints, int count);
|
||||
|
||||
//! Sets a constant for the pixel shader based on a name.
|
||||
virtual bool setPixelShaderConstant(const c8* name, const f32* floats, int count);
|
||||
|
||||
//! Bool interface for the above.
|
||||
virtual bool setPixelShaderConstant(const c8* name, const bool* bools, int count);
|
||||
|
||||
//! Int interface for the above.
|
||||
virtual bool setPixelShaderConstant(const c8* name, const s32* ints, int count);
|
||||
|
||||
//! Returns a pointer to the IVideoDriver interface. (Implementation for
|
||||
//! IMaterialRendererServices)
|
||||
virtual IVideoDriver* getVideoDriver();
|
||||
|
||||
//! Creates a render target texture.
|
||||
virtual ITexture* addRenderTargetTexture(const core::dimension2d<u32>& size,
|
||||
const io::path& name, const ECOLOR_FORMAT format = ECF_UNKNOWN);
|
||||
|
||||
//! Clears the ZBuffer.
|
||||
virtual void clearZBuffer();
|
||||
|
||||
//! Returns an image created from the last rendered frame.
|
||||
virtual IImage* createScreenShot(video::ECOLOR_FORMAT format=video::ECF_UNKNOWN, video::E_RENDER_TARGET target=video::ERT_FRAME_BUFFER);
|
||||
|
||||
//! Set/unset a clipping plane.
|
||||
//! There are at least 6 clipping planes available for the user to set at will.
|
||||
//! \param index: The plane index. Must be between 0 and MaxUserClipPlanes.
|
||||
//! \param plane: The plane itself.
|
||||
//! \param enable: If true, enable the clipping plane else disable it.
|
||||
virtual bool setClipPlane(u32 index, const core::plane3df& plane, bool enable=false);
|
||||
|
||||
//! Enable/disable a clipping plane.
|
||||
//! There are at least 6 clipping planes available for the user to set at will.
|
||||
//! \param index: The plane index. Must be between 0 and MaxUserClipPlanes.
|
||||
//! \param enable: If true, enable the clipping plane else disable it.
|
||||
virtual void enableClipPlane(u32 index, bool enable);
|
||||
|
||||
//! Returns the maximum texture size supported.
|
||||
virtual core::dimension2du getMaxTextureSize() const;
|
||||
|
||||
virtual bool checkDriverReset() {return DriverWasReset;}
|
||||
private:
|
||||
|
||||
// enumeration for rendering modes such as 2d and 3d for minizing the switching of renderStates.
|
||||
enum E_RENDER_MODE
|
||||
{
|
||||
ERM_NONE = 0, // no render state has been set yet.
|
||||
ERM_2D, // 2d drawing rendermode
|
||||
ERM_3D, // 3d rendering mode
|
||||
ERM_STENCIL_FILL, // stencil fill mode
|
||||
ERM_SHADOW_VOLUME_ZFAIL, // stencil volume draw mode
|
||||
ERM_SHADOW_VOLUME_ZPASS // stencil volume draw mode
|
||||
};
|
||||
|
||||
//! sets right vertex shader
|
||||
void setVertexShader(video::E_VERTEX_TYPE newType);
|
||||
|
||||
//! sets the needed renderstates
|
||||
bool setRenderStates3DMode();
|
||||
|
||||
//! sets the needed renderstates
|
||||
void setRenderStates2DMode(bool alpha, bool texture, bool alphaChannel);
|
||||
|
||||
//! sets the needed renderstates
|
||||
void setRenderStatesStencilFillMode(bool alpha);
|
||||
|
||||
//! sets the needed renderstates
|
||||
void setRenderStatesStencilShadowMode(bool zfail, u32 debugDataVisible);
|
||||
|
||||
//! sets the current Texture
|
||||
bool setActiveTexture(u32 stage, const video::ITexture* texture);
|
||||
|
||||
//! resets the device
|
||||
bool reset();
|
||||
|
||||
//! returns a device dependent texture from a software surface (IImage)
|
||||
//! THIS METHOD HAS TO BE OVERRIDDEN BY DERIVED DRIVERS WITH OWN TEXTURES
|
||||
virtual video::ITexture* createDeviceDependentTexture(IImage* surface, const io::path& name, void* mipmapData=0);
|
||||
|
||||
// returns the current size of the screen or rendertarget
|
||||
virtual const core::dimension2d<u32>& getCurrentRenderTargetSize() const;
|
||||
|
||||
//! Adds a new material renderer to the VideoDriver, using pixel and/or
|
||||
//! vertex shaders to render geometry.
|
||||
s32 addShaderMaterial(const c8* vertexShaderProgram, const c8* pixelShaderProgram,
|
||||
IShaderConstantSetCallBack* callback,
|
||||
E_MATERIAL_TYPE baseMaterial, s32 userData);
|
||||
|
||||
void createMaterialRenderers();
|
||||
|
||||
void draw2D3DVertexPrimitiveList(const void* vertices,
|
||||
u32 vertexCount, const void* indexList, u32 primitiveCount,
|
||||
E_VERTEX_TYPE vType, scene::E_PRIMITIVE_TYPE pType,
|
||||
E_INDEX_TYPE iType, bool is3D);
|
||||
|
||||
D3DTEXTUREADDRESS getTextureWrapMode(const u8 clamp);
|
||||
|
||||
inline D3DCOLORVALUE colorToD3D(const SColor& col)
|
||||
{
|
||||
const f32 f = 1.0f / 255.0f;
|
||||
D3DCOLORVALUE v;
|
||||
v.r = col.getRed() * f;
|
||||
v.g = col.getGreen() * f;
|
||||
v.b = col.getBlue() * f;
|
||||
v.a = col.getAlpha() * f;
|
||||
return v;
|
||||
}
|
||||
|
||||
E_RENDER_MODE CurrentRenderMode;
|
||||
D3DPRESENT_PARAMETERS present;
|
||||
|
||||
SMaterial Material, LastMaterial;
|
||||
bool ResetRenderStates; // bool to make all renderstates be reseted if set.
|
||||
bool Transformation3DChanged;
|
||||
const ITexture* CurrentTexture[MATERIAL_MAX_TEXTURES];
|
||||
core::matrix4 Matrices[ETS_COUNT]; // matrices of the 3d mode we need to restore when we switch back from the 2d mode.
|
||||
|
||||
HINSTANCE D3DLibrary;
|
||||
IDirect3D8* pID3D;
|
||||
IDirect3DDevice8* pID3DDevice;
|
||||
|
||||
IDirect3DSurface8* PrevRenderTarget;
|
||||
core::dimension2d<u32> CurrentRendertargetSize;
|
||||
|
||||
HWND WindowId;
|
||||
core::rect<s32>* SceneSourceRect;
|
||||
|
||||
D3DCAPS8 Caps;
|
||||
|
||||
E_VERTEX_TYPE LastVertexType;
|
||||
|
||||
D3DMATRIX UnitMatrix;
|
||||
|
||||
u32 MaxTextureUnits;
|
||||
u32 MaxUserClipPlanes;
|
||||
f32 MaxLightDistance;
|
||||
s32 LastSetLight;
|
||||
bool DeviceLost;
|
||||
bool DriverWasReset;
|
||||
|
||||
SColorf AmbientLight;
|
||||
|
||||
SIrrlichtCreationParameters Params;
|
||||
};
|
||||
|
||||
} // end namespace video
|
||||
} // end namespace irr
|
||||
|
||||
#endif // _IRR_COMPILE_WITH_DIRECT3D_8_
|
||||
|
||||
#endif // __C_VIDEO_DIRECTX_8_H_INCLUDED__
|
||||
|
581
source/Irrlicht/CD3D8MaterialRenderer.h
Normal file
581
source/Irrlicht/CD3D8MaterialRenderer.h
Normal file
@ -0,0 +1,581 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#ifndef __C_D3D8_MATERIAL_RENDERER_H_INCLUDED__
|
||||
#define __C_D3D8_MATERIAL_RENDERER_H_INCLUDED__
|
||||
|
||||
#include "IrrCompileConfig.h"
|
||||
#ifdef _IRR_WINDOWS_API_
|
||||
|
||||
#ifdef _IRR_COMPILE_WITH_DIRECT3D_8_
|
||||
#include <d3d8.h>
|
||||
|
||||
#include "IMaterialRenderer.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace video
|
||||
{
|
||||
|
||||
namespace
|
||||
{
|
||||
D3DMATRIX UnitMatrixD3D8;
|
||||
D3DMATRIX SphereMapMatrixD3D8;
|
||||
inline void setTextureColorStage(IDirect3DDevice8* dev, DWORD i,
|
||||
DWORD arg1, DWORD op, DWORD arg2)
|
||||
{
|
||||
dev->SetTextureStageState(i, D3DTSS_COLOROP, op);
|
||||
dev->SetTextureStageState(i, D3DTSS_COLORARG1, arg1);
|
||||
dev->SetTextureStageState(i, D3DTSS_COLORARG2, arg2);
|
||||
}
|
||||
inline void setTextureColorStage(IDirect3DDevice8* dev, DWORD i, DWORD arg1)
|
||||
{
|
||||
dev->SetTextureStageState(i, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
|
||||
dev->SetTextureStageState(i, D3DTSS_COLORARG1, arg1);
|
||||
}
|
||||
|
||||
inline void setTextureAlphaStage(IDirect3DDevice8* dev, DWORD i,
|
||||
DWORD arg1, DWORD op, DWORD arg2)
|
||||
{
|
||||
dev->SetTextureStageState(i, D3DTSS_ALPHAOP, op);
|
||||
dev->SetTextureStageState(i, D3DTSS_ALPHAARG1, arg1);
|
||||
dev->SetTextureStageState(i, D3DTSS_ALPHAARG2, arg2);
|
||||
}
|
||||
inline void setTextureAlphaStage(IDirect3DDevice8* dev, DWORD i, DWORD arg1)
|
||||
{
|
||||
dev->SetTextureStageState(i, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
|
||||
dev->SetTextureStageState(i, D3DTSS_ALPHAARG1, arg1);
|
||||
}
|
||||
} // anonymous namespace
|
||||
|
||||
//! Base class for all internal D3D8 material renderers
|
||||
class CD3D8MaterialRenderer : public IMaterialRenderer
|
||||
{
|
||||
public:
|
||||
|
||||
//! Constructor
|
||||
CD3D8MaterialRenderer(IDirect3DDevice8* d3ddev, video::IVideoDriver* driver)
|
||||
: pID3DDevice(d3ddev), Driver(driver)
|
||||
{
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
IDirect3DDevice8* pID3DDevice;
|
||||
video::IVideoDriver* Driver;
|
||||
};
|
||||
|
||||
|
||||
//! Solid material renderer
|
||||
class CD3D8MaterialRenderer_SOLID : public CD3D8MaterialRenderer
|
||||
{
|
||||
public:
|
||||
|
||||
CD3D8MaterialRenderer_SOLID(IDirect3DDevice8* p, video::IVideoDriver* d)
|
||||
: CD3D8MaterialRenderer(p, d) {}
|
||||
|
||||
virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial,
|
||||
bool resetAllRenderstates, IMaterialRendererServices* services)
|
||||
{
|
||||
services->setBasicRenderStates(material, lastMaterial, resetAllRenderstates);
|
||||
|
||||
if (material.MaterialType != lastMaterial.MaterialType || resetAllRenderstates)
|
||||
{
|
||||
setTextureColorStage(pID3DDevice, 0,
|
||||
D3DTA_TEXTURE, D3DTOP_MODULATE, D3DTA_DIFFUSE);
|
||||
}
|
||||
|
||||
pID3DDevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE);
|
||||
pID3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
|
||||
}
|
||||
};
|
||||
|
||||
//! Generic Texture Blend
|
||||
class CD3D8MaterialRenderer_ONETEXTURE_BLEND : public CD3D8MaterialRenderer
|
||||
{
|
||||
public:
|
||||
|
||||
CD3D8MaterialRenderer_ONETEXTURE_BLEND(IDirect3DDevice8* p, video::IVideoDriver* d)
|
||||
: CD3D8MaterialRenderer(p, d) {}
|
||||
|
||||
virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial,
|
||||
bool resetAllRenderstates, IMaterialRendererServices* services)
|
||||
{
|
||||
services->setBasicRenderStates(material, lastMaterial, resetAllRenderstates);
|
||||
|
||||
if (material.MaterialType != lastMaterial.MaterialType ||
|
||||
material.MaterialTypeParam != lastMaterial.MaterialTypeParam ||
|
||||
resetAllRenderstates)
|
||||
{
|
||||
|
||||
E_BLEND_FACTOR srcFact,dstFact;
|
||||
E_MODULATE_FUNC modulate;
|
||||
u32 alphaSource;
|
||||
unpack_textureBlendFunc ( srcFact, dstFact, modulate, alphaSource, material.MaterialTypeParam );
|
||||
|
||||
if (srcFact == EBF_SRC_COLOR && dstFact == EBF_ZERO)
|
||||
{
|
||||
pID3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
|
||||
}
|
||||
else
|
||||
{
|
||||
pID3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
|
||||
pID3DDevice->SetRenderState(D3DRS_SRCBLEND, getD3DBlend ( srcFact ) );
|
||||
pID3DDevice->SetRenderState(D3DRS_DESTBLEND, getD3DBlend ( dstFact ) );
|
||||
}
|
||||
|
||||
setTextureColorStage(pID3DDevice, 0,
|
||||
D3DTA_TEXTURE, getD3DModulate(modulate), D3DTA_DIFFUSE);
|
||||
|
||||
if ( alphaSource && (textureBlendFunc_hasAlpha ( srcFact ) || textureBlendFunc_hasAlpha ( dstFact ) ))
|
||||
{
|
||||
if (alphaSource==EAS_VERTEX_COLOR)
|
||||
{
|
||||
setTextureAlphaStage(pID3DDevice, 0, D3DTA_DIFFUSE);
|
||||
}
|
||||
else if (alphaSource==EAS_TEXTURE)
|
||||
{
|
||||
setTextureAlphaStage(pID3DDevice, 0, D3DTA_TEXTURE);
|
||||
}
|
||||
else
|
||||
{
|
||||
setTextureAlphaStage(pID3DDevice, 0,
|
||||
D3DTA_TEXTURE, D3DTOP_MODULATE, D3DTA_DIFFUSE);
|
||||
}
|
||||
}
|
||||
|
||||
pID3DDevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
//! Returns if the material is transparent.
|
||||
/** The scene management needs to know this for being able to sort the
|
||||
materials by opaque and transparent.
|
||||
The return value could be optimized, but we'd need to know the
|
||||
MaterialTypeParam for it. */
|
||||
virtual bool isTransparent() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
u32 getD3DBlend ( E_BLEND_FACTOR factor ) const
|
||||
{
|
||||
u32 r = 0;
|
||||
switch ( factor )
|
||||
{
|
||||
case EBF_ZERO: r = D3DBLEND_ZERO; break;
|
||||
case EBF_ONE: r = D3DBLEND_ONE; break;
|
||||
case EBF_DST_COLOR: r = D3DBLEND_DESTCOLOR; break;
|
||||
case EBF_ONE_MINUS_DST_COLOR: r = D3DBLEND_INVDESTCOLOR; break;
|
||||
case EBF_SRC_COLOR: r = D3DBLEND_SRCCOLOR; break;
|
||||
case EBF_ONE_MINUS_SRC_COLOR: r = D3DBLEND_INVSRCCOLOR; break;
|
||||
case EBF_SRC_ALPHA: r = D3DBLEND_SRCALPHA; break;
|
||||
case EBF_ONE_MINUS_SRC_ALPHA: r = D3DBLEND_INVSRCALPHA; break;
|
||||
case EBF_DST_ALPHA: r = D3DBLEND_DESTALPHA; break;
|
||||
case EBF_ONE_MINUS_DST_ALPHA: r = D3DBLEND_INVDESTALPHA; break;
|
||||
case EBF_SRC_ALPHA_SATURATE: r = D3DBLEND_SRCALPHASAT; break;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
u32 getD3DModulate ( E_MODULATE_FUNC func ) const
|
||||
{
|
||||
u32 r = D3DTOP_MODULATE;
|
||||
switch ( func )
|
||||
{
|
||||
case EMFN_MODULATE_1X: r = D3DTOP_MODULATE; break;
|
||||
case EMFN_MODULATE_2X: r = D3DTOP_MODULATE2X; break;
|
||||
case EMFN_MODULATE_4X: r = D3DTOP_MODULATE4X; break;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
//! Solid 2 layer material renderer
|
||||
class CD3D8MaterialRenderer_SOLID_2_LAYER : public CD3D8MaterialRenderer
|
||||
{
|
||||
public:
|
||||
|
||||
CD3D8MaterialRenderer_SOLID_2_LAYER(IDirect3DDevice8* p, video::IVideoDriver* d)
|
||||
: CD3D8MaterialRenderer(p, d) {}
|
||||
|
||||
virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial,
|
||||
bool resetAllRenderstates, IMaterialRendererServices* services)
|
||||
{
|
||||
services->setBasicRenderStates(material, lastMaterial, resetAllRenderstates);
|
||||
|
||||
if (material.MaterialType != lastMaterial.MaterialType || resetAllRenderstates)
|
||||
{
|
||||
setTextureColorStage(pID3DDevice, 0, D3DTA_TEXTURE);
|
||||
|
||||
pID3DDevice->SetTextureStageState(1, D3DTSS_TEXCOORDINDEX, 0);
|
||||
pID3DDevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_BLENDDIFFUSEALPHA);
|
||||
|
||||
pID3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//! Transparent add color material renderer
|
||||
class CD3D8MaterialRenderer_TRANSPARENT_ADD_COLOR : public CD3D8MaterialRenderer
|
||||
{
|
||||
public:
|
||||
|
||||
CD3D8MaterialRenderer_TRANSPARENT_ADD_COLOR(IDirect3DDevice8* p, video::IVideoDriver* d)
|
||||
: CD3D8MaterialRenderer(p, d) {}
|
||||
|
||||
virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial,
|
||||
bool resetAllRenderstates, IMaterialRendererServices* services)
|
||||
{
|
||||
services->setBasicRenderStates(material, lastMaterial, resetAllRenderstates);
|
||||
|
||||
if (material.MaterialType != lastMaterial.MaterialType || resetAllRenderstates)
|
||||
{
|
||||
setTextureColorStage(pID3DDevice, 0,
|
||||
D3DTA_TEXTURE, D3DTOP_MODULATE, D3DTA_DIFFUSE);
|
||||
|
||||
pID3DDevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE);
|
||||
pID3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
|
||||
pID3DDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ONE);
|
||||
pID3DDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCCOLOR);
|
||||
}
|
||||
}
|
||||
|
||||
//! Returns if the material is transparent. The scene management needs to know this
|
||||
//! for being able to sort the materials by opaque and transparent.
|
||||
virtual bool isTransparent() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//! Transparent vertex alpha material renderer
|
||||
class CD3D8MaterialRenderer_TRANSPARENT_VERTEX_ALPHA : public CD3D8MaterialRenderer
|
||||
{
|
||||
public:
|
||||
|
||||
CD3D8MaterialRenderer_TRANSPARENT_VERTEX_ALPHA(IDirect3DDevice8* p, video::IVideoDriver* d)
|
||||
: CD3D8MaterialRenderer(p, d) {}
|
||||
|
||||
virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial,
|
||||
bool resetAllRenderstates, IMaterialRendererServices* services)
|
||||
{
|
||||
services->setBasicRenderStates(material, lastMaterial, resetAllRenderstates);
|
||||
|
||||
if (material.MaterialType != lastMaterial.MaterialType || resetAllRenderstates)
|
||||
{
|
||||
setTextureColorStage(pID3DDevice, 0,
|
||||
D3DTA_TEXTURE, D3DTOP_MODULATE, D3DTA_DIFFUSE);
|
||||
setTextureAlphaStage(pID3DDevice, 0, D3DTA_DIFFUSE);
|
||||
|
||||
pID3DDevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE);
|
||||
pID3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
|
||||
pID3DDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
|
||||
pID3DDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
|
||||
}
|
||||
}
|
||||
|
||||
//! Returns if the material is transparent. The scene managment needs to know this
|
||||
//! for being able to sort the materials by opaque and transparent.
|
||||
virtual bool isTransparent() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//! Transparent alpha channel material renderer
|
||||
class CD3D8MaterialRenderer_TRANSPARENT_ALPHA_CHANNEL : public CD3D8MaterialRenderer
|
||||
{
|
||||
public:
|
||||
|
||||
CD3D8MaterialRenderer_TRANSPARENT_ALPHA_CHANNEL(IDirect3DDevice8* p, video::IVideoDriver* d)
|
||||
: CD3D8MaterialRenderer(p, d) {}
|
||||
|
||||
virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial,
|
||||
bool resetAllRenderstates, IMaterialRendererServices* services)
|
||||
{
|
||||
services->setBasicRenderStates(material, lastMaterial, resetAllRenderstates);
|
||||
|
||||
if (material.MaterialType != lastMaterial.MaterialType || resetAllRenderstates
|
||||
|| material.MaterialTypeParam != lastMaterial.MaterialTypeParam )
|
||||
{
|
||||
setTextureColorStage(pID3DDevice, 0,
|
||||
D3DTA_TEXTURE, D3DTOP_MODULATE, D3DTA_CURRENT);
|
||||
setTextureAlphaStage(pID3DDevice, 0, D3DTA_TEXTURE);
|
||||
|
||||
pID3DDevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE);
|
||||
pID3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
|
||||
pID3DDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
|
||||
pID3DDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA );
|
||||
|
||||
pID3DDevice->SetRenderState(D3DRS_ALPHAREF, core::floor32(material.MaterialTypeParam * 255.f));
|
||||
pID3DDevice->SetRenderState(D3DRS_ALPHAFUNC, D3DCMP_GREATEREQUAL);
|
||||
pID3DDevice->SetRenderState(D3DRS_ALPHATESTENABLE, TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
virtual void OnUnsetMaterial()
|
||||
{
|
||||
pID3DDevice->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE);
|
||||
}
|
||||
|
||||
//! Returns if the material is transparent. The scene managment needs to know this
|
||||
//! for being able to sort the materials by opaque and transparent.
|
||||
virtual bool isTransparent() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//! Transparent alpha channel material renderer
|
||||
class CD3D8MaterialRenderer_TRANSPARENT_ALPHA_CHANNEL_REF : public CD3D8MaterialRenderer
|
||||
{
|
||||
public:
|
||||
|
||||
CD3D8MaterialRenderer_TRANSPARENT_ALPHA_CHANNEL_REF(IDirect3DDevice8* p, video::IVideoDriver* d)
|
||||
: CD3D8MaterialRenderer(p, d) {}
|
||||
|
||||
virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial,
|
||||
bool resetAllRenderstates, IMaterialRendererServices* services)
|
||||
{
|
||||
services->setBasicRenderStates(material, lastMaterial, resetAllRenderstates);
|
||||
|
||||
if (material.MaterialType != lastMaterial.MaterialType || resetAllRenderstates)
|
||||
{
|
||||
setTextureColorStage(pID3DDevice, 0,
|
||||
D3DTA_TEXTURE, D3DTOP_MODULATE, D3DTA_CURRENT);
|
||||
setTextureAlphaStage(pID3DDevice, 0, D3DTA_TEXTURE);
|
||||
|
||||
pID3DDevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE);
|
||||
|
||||
pID3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
|
||||
|
||||
// 127 is required by EMT_TRANSPARENT_ALPHA_CHANNEL_REF
|
||||
pID3DDevice->SetRenderState(D3DRS_ALPHAREF, 127);
|
||||
pID3DDevice->SetRenderState(D3DRS_ALPHAFUNC, D3DCMP_GREATEREQUAL);
|
||||
pID3DDevice->SetRenderState(D3DRS_ALPHATESTENABLE, TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
virtual void OnUnsetMaterial()
|
||||
{
|
||||
pID3DDevice->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE);
|
||||
}
|
||||
|
||||
//! Returns if the material is transparent. The scene managment needs to know this
|
||||
//! for being able to sort the materials by opaque and transparent.
|
||||
virtual bool isTransparent() const
|
||||
{
|
||||
return false; // this material is not really transparent because it does no blending.
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//! material renderer for all kinds of lightmaps
|
||||
class CD3D8MaterialRenderer_LIGHTMAP : public CD3D8MaterialRenderer
|
||||
{
|
||||
public:
|
||||
|
||||
CD3D8MaterialRenderer_LIGHTMAP(IDirect3DDevice8* p, video::IVideoDriver* d)
|
||||
: CD3D8MaterialRenderer(p, d) {}
|
||||
|
||||
virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial,
|
||||
bool resetAllRenderstates, IMaterialRendererServices* services)
|
||||
{
|
||||
services->setBasicRenderStates(material, lastMaterial, resetAllRenderstates);
|
||||
|
||||
if (material.MaterialType != lastMaterial.MaterialType || resetAllRenderstates)
|
||||
{
|
||||
if (material.MaterialType >= EMT_LIGHTMAP_LIGHTING)
|
||||
{
|
||||
// with lighting
|
||||
setTextureColorStage(pID3DDevice, 0,
|
||||
D3DTA_TEXTURE, D3DTOP_MODULATE, D3DTA_DIFFUSE);
|
||||
}
|
||||
else
|
||||
{
|
||||
setTextureColorStage(pID3DDevice, 0, D3DTA_TEXTURE);
|
||||
}
|
||||
|
||||
pID3DDevice->SetTextureStageState(1, D3DTSS_TEXCOORDINDEX, 1);
|
||||
|
||||
setTextureColorStage(pID3DDevice, 1,
|
||||
D3DTA_TEXTURE,
|
||||
(material.MaterialType == EMT_LIGHTMAP_ADD)?
|
||||
D3DTOP_ADD:
|
||||
(material.MaterialType == EMT_LIGHTMAP_M4 || material.MaterialType == EMT_LIGHTMAP_LIGHTING_M4)?
|
||||
D3DTOP_MODULATE4X:
|
||||
(material.MaterialType == EMT_LIGHTMAP_M2 || material.MaterialType == EMT_LIGHTMAP_LIGHTING_M2)?
|
||||
D3DTOP_MODULATE2X:
|
||||
D3DTOP_MODULATE,
|
||||
D3DTA_CURRENT);
|
||||
|
||||
pID3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//! material renderer for detail maps
|
||||
class CD3D8MaterialRenderer_DETAIL_MAP : public CD3D8MaterialRenderer
|
||||
{
|
||||
public:
|
||||
|
||||
CD3D8MaterialRenderer_DETAIL_MAP(IDirect3DDevice8* p, video::IVideoDriver* d)
|
||||
: CD3D8MaterialRenderer(p, d) {}
|
||||
|
||||
virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial,
|
||||
bool resetAllRenderstates, IMaterialRendererServices* services)
|
||||
{
|
||||
services->setBasicRenderStates(material, lastMaterial, resetAllRenderstates);
|
||||
|
||||
if (material.MaterialType != lastMaterial.MaterialType || resetAllRenderstates)
|
||||
{
|
||||
setTextureColorStage(pID3DDevice, 0,
|
||||
D3DTA_TEXTURE, D3DTOP_MODULATE, D3DTA_DIFFUSE);
|
||||
setTextureColorStage(pID3DDevice, 1,
|
||||
D3DTA_TEXTURE, D3DTOP_ADDSIGNED, D3DTA_CURRENT);
|
||||
pID3DDevice->SetTextureStageState(1, D3DTSS_TEXCOORDINDEX, 1);
|
||||
pID3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//! sphere map material renderer
|
||||
class CD3D8MaterialRenderer_SPHERE_MAP : public CD3D8MaterialRenderer
|
||||
{
|
||||
public:
|
||||
|
||||
CD3D8MaterialRenderer_SPHERE_MAP(IDirect3DDevice8* p, video::IVideoDriver* d)
|
||||
: CD3D8MaterialRenderer(p, d) {}
|
||||
|
||||
virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial,
|
||||
bool resetAllRenderstates, IMaterialRendererServices* services)
|
||||
{
|
||||
services->setBasicRenderStates(material, lastMaterial, resetAllRenderstates);
|
||||
|
||||
if (material.MaterialType != lastMaterial.MaterialType || resetAllRenderstates)
|
||||
{
|
||||
setTextureColorStage(pID3DDevice, 0,
|
||||
D3DTA_TEXTURE, D3DTOP_MODULATE, D3DTA_DIFFUSE);
|
||||
|
||||
pID3DDevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE);
|
||||
pID3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
|
||||
|
||||
pID3DDevice->SetTransform( D3DTS_TEXTURE0, &SphereMapMatrixD3D8 );
|
||||
pID3DDevice->SetTextureStageState( 0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT2 );
|
||||
pID3DDevice->SetTextureStageState( 0, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_CAMERASPACENORMAL );
|
||||
}
|
||||
}
|
||||
|
||||
virtual void OnUnsetMaterial()
|
||||
{
|
||||
pID3DDevice->SetTextureStageState( 0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_DISABLE );
|
||||
pID3DDevice->SetTextureStageState( 0, D3DTSS_TEXCOORDINDEX, 0);
|
||||
pID3DDevice->SetTransform( D3DTS_TEXTURE0, &UnitMatrixD3D8 );
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//! reflection 2 layer material renderer
|
||||
class CD3D8MaterialRenderer_REFLECTION_2_LAYER : public CD3D8MaterialRenderer
|
||||
{
|
||||
public:
|
||||
|
||||
CD3D8MaterialRenderer_REFLECTION_2_LAYER(IDirect3DDevice8* p, video::IVideoDriver* d)
|
||||
: CD3D8MaterialRenderer(p, d) {}
|
||||
|
||||
virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial,
|
||||
bool resetAllRenderstates, IMaterialRendererServices* services)
|
||||
{
|
||||
services->setBasicRenderStates(material, lastMaterial, resetAllRenderstates);
|
||||
|
||||
if (material.MaterialType != lastMaterial.MaterialType || resetAllRenderstates)
|
||||
{
|
||||
setTextureColorStage(pID3DDevice, 0,
|
||||
D3DTA_TEXTURE, D3DTOP_MODULATE, D3DTA_DIFFUSE);
|
||||
|
||||
setTextureColorStage(pID3DDevice, 1,
|
||||
D3DTA_TEXTURE, D3DTOP_MODULATE, D3DTA_CURRENT);
|
||||
|
||||
pID3DDevice->SetTransform( D3DTS_TEXTURE1, &SphereMapMatrixD3D8 );
|
||||
pID3DDevice->SetTextureStageState( 1, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT2 );
|
||||
pID3DDevice->SetTextureStageState( 1, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR);
|
||||
pID3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
virtual void OnUnsetMaterial()
|
||||
{
|
||||
pID3DDevice->SetTextureStageState( 1, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_DISABLE );
|
||||
pID3DDevice->SetTextureStageState( 1, D3DTSS_TEXCOORDINDEX, 1);
|
||||
pID3DDevice->SetTransform( D3DTS_TEXTURE1, &UnitMatrixD3D8 );
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//! reflection 2 layer material renderer
|
||||
class CD3D8MaterialRenderer_TRANSPARENT_REFLECTION_2_LAYER : public CD3D8MaterialRenderer
|
||||
{
|
||||
public:
|
||||
|
||||
CD3D8MaterialRenderer_TRANSPARENT_REFLECTION_2_LAYER(IDirect3DDevice8* p, video::IVideoDriver* d)
|
||||
: CD3D8MaterialRenderer(p, d) {}
|
||||
|
||||
virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial,
|
||||
bool resetAllRenderstates, IMaterialRendererServices* services)
|
||||
{
|
||||
services->setBasicRenderStates(material, lastMaterial, resetAllRenderstates);
|
||||
|
||||
if (material.MaterialType != lastMaterial.MaterialType || resetAllRenderstates)
|
||||
{
|
||||
setTextureColorStage(pID3DDevice, 0,
|
||||
D3DTA_TEXTURE, D3DTOP_MODULATE, D3DTA_DIFFUSE);
|
||||
setTextureAlphaStage(pID3DDevice, 0, D3DTA_DIFFUSE);
|
||||
setTextureColorStage(pID3DDevice, 1,
|
||||
D3DTA_TEXTURE, D3DTOP_MODULATE, D3DTA_CURRENT);
|
||||
setTextureAlphaStage(pID3DDevice, 1, D3DTA_CURRENT);
|
||||
|
||||
pID3DDevice->SetTransform(D3DTS_TEXTURE1, &SphereMapMatrixD3D8 );
|
||||
pID3DDevice->SetTextureStageState(1, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT2 );
|
||||
pID3DDevice->SetTextureStageState(1, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR);
|
||||
|
||||
pID3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
|
||||
pID3DDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
|
||||
pID3DDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
|
||||
}
|
||||
}
|
||||
|
||||
virtual void OnUnsetMaterial()
|
||||
{
|
||||
pID3DDevice->SetTextureStageState(1, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_DISABLE);
|
||||
pID3DDevice->SetTextureStageState(1, D3DTSS_TEXCOORDINDEX, 1);
|
||||
pID3DDevice->SetTransform(D3DTS_TEXTURE1, &UnitMatrixD3D8);
|
||||
}
|
||||
|
||||
//! Returns if the material is transparent. The scene managment needs to know this
|
||||
//! for being able to sort the materials by opaque and transparent.
|
||||
virtual bool isTransparent() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
} // end namespace video
|
||||
} // end namespace irr
|
||||
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
248
source/Irrlicht/CD3D8NormalMapRenderer.cpp
Normal file
248
source/Irrlicht/CD3D8NormalMapRenderer.cpp
Normal file
@ -0,0 +1,248 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#include "IrrCompileConfig.h"
|
||||
#ifdef _IRR_COMPILE_WITH_DIRECT3D_8_
|
||||
|
||||
#include "CD3D8NormalMapRenderer.h"
|
||||
#include "IMaterialRendererServices.h"
|
||||
#include "IVideoDriver.h"
|
||||
#include "os.h"
|
||||
#include "SLight.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace video
|
||||
{
|
||||
|
||||
// 1.1 Shaders with two lights and vertex based attenuation
|
||||
|
||||
// Irrlicht Engine D3D8 render path normal map vertex shader
|
||||
const char D3D8_NORMAL_MAP_VSH[] =
|
||||
";Irrlicht Engine 0.8 D3D8 render path normal map vertex shader\n"\
|
||||
"; c0-3: Transposed world matrix \n"\
|
||||
"; c8-11: Transposed worldViewProj matrix (Projection * View * World) \n"\
|
||||
"; c12: Light01 position \n"\
|
||||
"; c13: x,y,z: Light01 color; .w: 1/LightRadius<75> \n"\
|
||||
"; c14: Light02 position \n"\
|
||||
"; c15: x,y,z: Light02 color; .w: 1/LightRadius<75> \n"\
|
||||
"\n"\
|
||||
"; v0 - position \n"\
|
||||
"; v1 - normal \n"\
|
||||
"; v2 - color \n"\
|
||||
"; v3 - texture coord \n"\
|
||||
"; v4 - tangent \n"\
|
||||
"; v5 - binormal \n"\
|
||||
"\n"\
|
||||
"vs.1.1\n"\
|
||||
"\n"\
|
||||
"m4x4 oPos, v0, c8 ; transform position to clip space with worldViewProj matrix\n"\
|
||||
"\n"\
|
||||
"m3x3 r5, v4, c0 ; transform tangent U\n"\
|
||||
"m3x3 r7, v1, c0 ; transform normal W\n"\
|
||||
"m3x3 r6, v5, c0 ; transform binormal V\n"\
|
||||
"\n"\
|
||||
"m4x4 r4, v0, c0 ; vertex into world position\n"\
|
||||
"add r2, c12, -r4 ; vtxpos - lightpos1\n"\
|
||||
"add r3, c14, -r4 ; vtxpos - lightpos2\n"\
|
||||
"\n"\
|
||||
"dp3 r8.x, r5, r2 ; transform the light vector 1 with U, V, W\n"\
|
||||
"dp3 r8.y, r6, r2 \n"\
|
||||
"dp3 r8.z, r7, r2 \n"\
|
||||
"dp3 r9.x, r5, r3 ; transform the light vector 2 with U, V, W\n"\
|
||||
"dp3 r9.y, r6, r3 \n"\
|
||||
"dp3 r9.z, r7, r3 \n"\
|
||||
"\n"\
|
||||
"dp3 r8.w, r8, r8 ; normalize light vector 1 (r8)\n"\
|
||||
"rsq r8.w, r8.w \n"\
|
||||
"mul r8, r8, r8.w \n"\
|
||||
"dp3 r9.w, r9, r9 ; normalize light vector 2 (r9)\n"\
|
||||
"rsq r9.w, r9.w \n"\
|
||||
"mul r9, r9, r9.w \n"\
|
||||
"\n"\
|
||||
"mad oT2.xyz, r8.xyz, c95, c95 ; move light vector 1 from -1..1 into 0..1 \n"\
|
||||
"mad oT3.xyz, r9.xyz, c95, c95 ; move light vector 2 from -1..1 into 0..1 \n"\
|
||||
"\n"\
|
||||
" ; calculate attenuation of light 1 \n"\
|
||||
"dp3 r2.x, r2.xyz, r2.xyz ; r2.x = r2.x<> + r2.y<> + r2.z<> \n"\
|
||||
"mul r2.x, r2.x, c13.w ; r2.x * attenutation \n"\
|
||||
"rsq r2, r2.x ; r2.xyzw = 1/sqrt(r2.x * attenutation)\n"\
|
||||
"mul oD0, r2, c13 ; resulting light color = lightcolor * attenuation \n"\
|
||||
"\n"\
|
||||
" ; calculate attenuation of light 2 \n"\
|
||||
"dp3 r3.x, r3.xyz, r3.xyz ; r3.x = r3.x<> + r3.y<> + r3.z<> \n"\
|
||||
"mul r3.x, r3.x, c15.w ; r2.x * attenutation \n"\
|
||||
"rsq r3, r3.x ; r2.xyzw = 1/sqrt(r2.x * attenutation)\n"\
|
||||
"mul oD1, r3, c15 ; resulting light color = lightcolor * attenuation \n"\
|
||||
"\n"\
|
||||
"mov oT0.xy, v3.xy ; move out texture coordinates 1\n"\
|
||||
"mov oT1.xy, v3.xy ; move out texture coordinates 2\n"\
|
||||
"mov oD0.a, v2.a ; move out original alpha value \n"\
|
||||
"\n";
|
||||
|
||||
// Irrlicht Engine D3D8 render path normal map pixel shader
|
||||
const char D3D8_NORMAL_MAP_PSH[] =
|
||||
";Irrlicht Engine 0.8 D3D8 render path normal map pixel shader\n"\
|
||||
";Input: \n"\
|
||||
";t0: color map texture coord \n"\
|
||||
";t1: normal map texture coords \n"\
|
||||
";t2: light 1 vector in tangent space \n"\
|
||||
";v0: light 1 color \n"\
|
||||
";t3: light 2 vector in tangent space \n"\
|
||||
";v1: light 2 color \n"\
|
||||
";v0.a: vertex alpha value \n"\
|
||||
"ps.1.1 \n"\
|
||||
"tex t0 ; sample color map \n"\
|
||||
"tex t1 ; sample normal map\n"\
|
||||
"texcoord t2 ; fetch light vector 1\n"\
|
||||
"texcoord t3 ; fetch light vector 2\n"\
|
||||
"\n"\
|
||||
"dp3_sat r0, t1_bx2, t2_bx2 ; normal dot light 1 (_bx2 because moved into 0..1)\n"\
|
||||
"mul r0, r0, v0 ; luminance1 * light color 1 \n"\
|
||||
"\n"\
|
||||
"dp3_sat r1, t1_bx2, t3_bx2 ; normal dot light 2 (_bx2 because moved into 0..1)\n"\
|
||||
"mad r0, r1, v1, r0 ; (luminance2 * light color 2) + luminance 1 \n"\
|
||||
"\n"\
|
||||
"mul r0, t0, r0 ; total luminance * base color\n"\
|
||||
"mov r0.a, v0.a ; write interpolated vertex alpha value \n"\
|
||||
"\n"\
|
||||
"";
|
||||
|
||||
CD3D8NormalMapRenderer::CD3D8NormalMapRenderer(
|
||||
IDirect3DDevice8* d3ddev, video::IVideoDriver* driver,
|
||||
s32& outMaterialTypeNr, IMaterialRenderer* baseMaterial)
|
||||
: CD3D8ShaderMaterialRenderer(d3ddev, driver, 0, baseMaterial),
|
||||
CompiledShaders(true)
|
||||
{
|
||||
|
||||
#ifdef _DEBUG
|
||||
setDebugName("CD3D8NormalMapRenderer");
|
||||
#endif
|
||||
|
||||
// set this as callback. We could have done this in
|
||||
// the initialization list, but some compilers don't like it.
|
||||
|
||||
CallBack = this;
|
||||
|
||||
// basicly, this thing simply compiles these hardcoded shaders if the
|
||||
// hardware is able to do them, otherwise it maps to the base material
|
||||
|
||||
if (!driver->queryFeature(video::EVDF_PIXEL_SHADER_1_1) ||
|
||||
!driver->queryFeature(video::EVDF_VERTEX_SHADER_1_1))
|
||||
{
|
||||
// this hardware is not able to do shaders. Fall back to
|
||||
// base material.
|
||||
outMaterialTypeNr = driver->addMaterialRenderer(this);
|
||||
return;
|
||||
}
|
||||
|
||||
// check if already compiled normal map shaders are there.
|
||||
|
||||
video::IMaterialRenderer* renderer = driver->getMaterialRenderer(EMT_NORMAL_MAP_SOLID);
|
||||
if (renderer)
|
||||
{
|
||||
// use the already compiled shaders
|
||||
video::CD3D8NormalMapRenderer* nmr = (video::CD3D8NormalMapRenderer*)renderer;
|
||||
CompiledShaders = false;
|
||||
|
||||
VertexShader = nmr->VertexShader;
|
||||
PixelShader = nmr->PixelShader;
|
||||
|
||||
outMaterialTypeNr = driver->addMaterialRenderer(this);
|
||||
}
|
||||
else
|
||||
{
|
||||
// compile shaders on our own
|
||||
init(outMaterialTypeNr, D3D8_NORMAL_MAP_VSH, D3D8_NORMAL_MAP_PSH, EVT_TANGENTS);
|
||||
}
|
||||
// something failed, use base material
|
||||
if (-1==outMaterialTypeNr)
|
||||
driver->addMaterialRenderer(this);
|
||||
}
|
||||
|
||||
|
||||
CD3D8NormalMapRenderer::~CD3D8NormalMapRenderer()
|
||||
{
|
||||
if (CallBack == this)
|
||||
CallBack = 0;
|
||||
|
||||
if (!CompiledShaders)
|
||||
{
|
||||
// prevent this from deleting shaders we did not create
|
||||
VertexShader = 0;
|
||||
PixelShader = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool CD3D8NormalMapRenderer::OnRender(IMaterialRendererServices* service, E_VERTEX_TYPE vtxtype)
|
||||
{
|
||||
if (vtxtype != video::EVT_TANGENTS)
|
||||
{
|
||||
os::Printer::log("Error: Normal map renderer only supports vertices of type EVT_TANGENTS", ELL_ERROR);
|
||||
return false;
|
||||
}
|
||||
|
||||
return CD3D8ShaderMaterialRenderer::OnRender(service, vtxtype);
|
||||
}
|
||||
|
||||
//! Returns the render capability of the material.
|
||||
s32 CD3D8NormalMapRenderer::getRenderCapability() const
|
||||
{
|
||||
if (Driver->queryFeature(video::EVDF_PIXEL_SHADER_1_1) &&
|
||||
Driver->queryFeature(video::EVDF_VERTEX_SHADER_1_1))
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
//! Called by the engine when the vertex and/or pixel shader constants for an
|
||||
//! material renderer should be set.
|
||||
void CD3D8NormalMapRenderer::OnSetConstants(IMaterialRendererServices* services, s32 userData)
|
||||
{
|
||||
video::IVideoDriver* driver = services->getVideoDriver();
|
||||
|
||||
// set transposed world matrix
|
||||
services->setVertexShaderConstant(driver->getTransform(video::ETS_WORLD).getTransposed().pointer(), 0, 4);
|
||||
|
||||
// set transposed worldViewProj matrix
|
||||
core::matrix4 worldViewProj(driver->getTransform(video::ETS_PROJECTION));
|
||||
worldViewProj *= driver->getTransform(video::ETS_VIEW);
|
||||
worldViewProj *= driver->getTransform(video::ETS_WORLD);
|
||||
services->setVertexShaderConstant(worldViewProj.getTransposed().pointer(), 8, 4);
|
||||
|
||||
// here we've got to fetch the fixed function lights from the
|
||||
// driver and set them as constants
|
||||
|
||||
u32 cnt = driver->getDynamicLightCount();
|
||||
|
||||
for (u32 i=0; i<2; ++i)
|
||||
{
|
||||
SLight light;
|
||||
|
||||
if (i<cnt)
|
||||
light = driver->getDynamicLight(i);
|
||||
else
|
||||
{
|
||||
light.DiffuseColor.set(0,0,0); // make light dark
|
||||
light.Radius = 1.0f;
|
||||
}
|
||||
|
||||
light.DiffuseColor.a = 1.0f/(light.Radius*light.Radius); // set attenuation
|
||||
|
||||
services->setVertexShaderConstant(reinterpret_cast<const f32*>(&light.Position), 12+(i*2), 1);
|
||||
services->setVertexShaderConstant(reinterpret_cast<const f32*>(&light.DiffuseColor), 13+(i*2), 1);
|
||||
}
|
||||
|
||||
f32 c95[] = {0.5f, 0.5f, 0.5f, 0.5f};
|
||||
services->setVertexShaderConstant(c95, 95, 1);
|
||||
}
|
||||
|
||||
|
||||
} // end namespace video
|
||||
} // end namespace irr
|
||||
|
||||
#endif // _IRR_COMPILE_WITH_DIRECT3D_8_
|
||||
|
56
source/Irrlicht/CD3D8NormalMapRenderer.h
Normal file
56
source/Irrlicht/CD3D8NormalMapRenderer.h
Normal file
@ -0,0 +1,56 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#ifndef __C_D3D8_NORMAL_MAPMATERIAL_RENDERER_H_INCLUDED__
|
||||
#define __C_D3D8_NORMAL_MAPMATERIAL_RENDERER_H_INCLUDED__
|
||||
|
||||
#include "IrrCompileConfig.h"
|
||||
#ifdef _IRR_WINDOWS_API_
|
||||
|
||||
#ifdef _IRR_COMPILE_WITH_DIRECT3D_8_
|
||||
#include <d3d8.h>
|
||||
|
||||
#include "CD3D8ShaderMaterialRenderer.h"
|
||||
#include "IShaderConstantSetCallBack.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace video
|
||||
{
|
||||
|
||||
//! Renderer for normal maps
|
||||
class CD3D8NormalMapRenderer : public CD3D8ShaderMaterialRenderer, IShaderConstantSetCallBack
|
||||
{
|
||||
public:
|
||||
|
||||
CD3D8NormalMapRenderer(
|
||||
IDirect3DDevice8* d3ddev, video::IVideoDriver* driver,
|
||||
s32& outMaterialTypeNr, IMaterialRenderer* baseMaterial);
|
||||
~CD3D8NormalMapRenderer();
|
||||
|
||||
//! Called by the engine when the vertex and/or pixel shader constants for an
|
||||
//! material renderer should be set.
|
||||
virtual void OnSetConstants(IMaterialRendererServices* services, s32 userData);
|
||||
|
||||
bool OnRender(IMaterialRendererServices* service, E_VERTEX_TYPE vtxtype);
|
||||
|
||||
//! Returns the render capability of the material.
|
||||
virtual s32 getRenderCapability() const;
|
||||
|
||||
private:
|
||||
|
||||
//! stores if this shader compiled the shaders and is
|
||||
//! allowed to delete them again. D3D8 lacks reference counting
|
||||
//! support for shaders.
|
||||
bool CompiledShaders;
|
||||
|
||||
};
|
||||
|
||||
} // end namespace video
|
||||
} // end namespace irr
|
||||
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
318
source/Irrlicht/CD3D8ParallaxMapRenderer.cpp
Normal file
318
source/Irrlicht/CD3D8ParallaxMapRenderer.cpp
Normal file
@ -0,0 +1,318 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#include "IrrCompileConfig.h"
|
||||
#ifdef _IRR_COMPILE_WITH_DIRECT3D_8_
|
||||
|
||||
#include "CD3D8ParallaxMapRenderer.h"
|
||||
#include "IMaterialRendererServices.h"
|
||||
#include "IVideoDriver.h"
|
||||
#include "os.h"
|
||||
#include "SLight.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace video
|
||||
{
|
||||
// 1.1/1.4 Shaders with two lights and vertex based attenuation
|
||||
|
||||
// Irrlicht Engine D3D8 render path normal map vertex shader
|
||||
const char D3D8_PARALLAX_MAP_VSH[] =
|
||||
";Irrlicht Engine 0.10 D3D8 render path parallax mapping vertex shader\n"\
|
||||
"; c0-3: Transposed world matrix \n"\
|
||||
"; c4: Eye position \n"\
|
||||
"; c8-11: Transposed worldViewProj matrix (Projection * View * World) \n"\
|
||||
"; c12: Light01 position \n"\
|
||||
"; c13: x,y,z: Light01 color; .w: 1/LightRadius<75> \n"\
|
||||
"; c14: Light02 position \n"\
|
||||
"; c15: x,y,z: Light02 color; .w: 1/LightRadius<75> \n"\
|
||||
"vs.1.1\n"\
|
||||
"; v0 ; position \n"\
|
||||
"; v1 ; normal \n"\
|
||||
"; v2 ; color \n"\
|
||||
"; v3 ; texture coord \n"\
|
||||
"; v4 ; tangent \n"\
|
||||
"; v5 ; binormal \n"\
|
||||
"\n"\
|
||||
"def c95, 0.5, 0.5, 0.5, 0.5 ; used for moving light vector to ps \n"\
|
||||
"def c96, -1, 1, 1, 1 ; somewhere I've got a bug. flipping the vectors with this fixes it. \n"\
|
||||
"\n"\
|
||||
"m4x4 oPos, v0, c8 ; transform position to clip space with worldViewProj matrix\n"\
|
||||
"\n"\
|
||||
"m3x3 r5, v4, c0 ; transform tangent U\n"\
|
||||
"m3x3 r7, v1, c0 ; transform normal W\n"\
|
||||
"m3x3 r6, v5, c0 ; transform binormal V\n"\
|
||||
"\n"\
|
||||
"m4x4 r4, v0, c0 ; vertex into world position\n"\
|
||||
"add r2, c12, -r4 ; vtxpos - light1 pos\n"\
|
||||
"add r3, c14, -r4 ; vtxpos - light2 pos\n"\
|
||||
"add r1, -c4, r4 ; eye - vtxpos \n"\
|
||||
"\n"\
|
||||
"dp3 r8.x, r5, r2 ; transform the light1 vector with U, V, W\n"\
|
||||
"dp3 r8.y, r6, r2 \n"\
|
||||
"dp3 r8.z, r7, r2 \n"\
|
||||
"dp3 r9.x, r5, r3 ; transform the light2 vector with U, V, W\n"\
|
||||
"dp3 r9.y, r6, r3 \n"\
|
||||
"dp3 r9.z, r7, r3 \n"\
|
||||
"dp3 r10.x, r5, r1 ; transform the eye vector with U, V, W\n"\
|
||||
"dp3 r10.y, r6, r1 \n"\
|
||||
"dp3 r10.z, r7, r1 \n"\
|
||||
"\n"\
|
||||
"dp3 r8.w, r8, r8 ; normalize light vector 1 (r8)\n"\
|
||||
"rsq r8.w, r8.w \n"\
|
||||
"mul r8, r8, r8.w \n"\
|
||||
";mul r8, r8, c96 \n"\
|
||||
"dp3 r9.w, r9, r9 ; normalize light vector 2 (r9)\n"\
|
||||
"rsq r9.w, r9.w \n"\
|
||||
"mul r9, r9, r9.w \n"\
|
||||
";mul r9, r9, c96 \n"\
|
||||
"dp3 r10.w, r10, r10 ; normalize eye vector (r10)\n"\
|
||||
"rsq r10.w, r10.w \n"\
|
||||
"mul r10, r10, r10.w \n"\
|
||||
"mul r10, r10, c96 \n"\
|
||||
"\n"\
|
||||
"\n"\
|
||||
"mad oT2.xyz, r8.xyz, c95, c95 ; move light vector 1 from -1..1 into 0..1 \n"\
|
||||
"mad oT3.xyz, r9.xyz, c95, c95 ; move light vector 2 from -1..1 into 0..1 \n"\
|
||||
"mad oT4.xyz, r10.xyz, c95, c95 ; move eye vector from -1..1 into 0..1 \n"\
|
||||
"\n"\
|
||||
" ; calculate attenuation of light 1 \n"\
|
||||
"dp3 r2.x, r2.xyz, r2.xyz ; r2.x = r2.x<> + r2.y<> + r2.z<> \n"\
|
||||
"mul r2.x, r2.x, c13.w ; r2.x * attenutation \n"\
|
||||
"rsq r2, r2.x ; r2.xyzw = 1/sqrt(r2.x * attenutation)\n"\
|
||||
"mul oD0, r2, c13 ; resulting light color = lightcolor * attenuation \n"\
|
||||
"\n"\
|
||||
" ; calculate attenuation of light 2 \n"\
|
||||
"dp3 r3.x, r3.xyz, r3.xyz ; r3.x = r3.x<> + r3.y<> + r3.z<> \n"\
|
||||
"mul r3.x, r3.x, c15.w ; r2.x * attenutation \n"\
|
||||
"rsq r3, r3.x ; r2.xyzw = 1/sqrt(r2.x * attenutation)\n"\
|
||||
"mul oD1, r3, c15 ; resulting light color = lightcolor * attenuation \n"\
|
||||
"\n"\
|
||||
"mov oT0.xy, v3.xy ; move out texture coordinates 1\n"\
|
||||
"mov oT1.xy, v3.xy ; move out texture coordinates 2\n"\
|
||||
"mov oD0.a, v2.a ; move out original alpha value \n"\
|
||||
"\n";
|
||||
|
||||
|
||||
// Irrlicht Engine D3D8 render path normal map pixel shader version 1.4
|
||||
const char D3D8_PARALLAX_MAP_PSH[] =
|
||||
";Irrlicht Engine 0.10 D3D8 render path parallax mapping pixel shader \n"\
|
||||
";Input: \n"\
|
||||
";t0: color map texture coord \n"\
|
||||
";t1: normal map texture coords \n"\
|
||||
";t2: light 1 vector in tangent space \n"\
|
||||
";t4: eye vector in tangent space \n"\
|
||||
";v0: light 1 color \n"\
|
||||
";t3: light 2 vector in tangent space \n"\
|
||||
";v1: light 2 color \n"\
|
||||
";v0.a: vertex alpha value \n"\
|
||||
" \n"\
|
||||
"ps.1.4 \n"\
|
||||
" \n"\
|
||||
";def c6, 0.02f, 0.02f, 0.02f, 0.0f ; scale factor, now set in callback \n"\
|
||||
" \n"\
|
||||
"texld r1, t1 ; sample (normal.x, normal.y, normal.z, height) \n"\
|
||||
"texcrd r4.xyz, t4 ; fetch eye vector \n"\
|
||||
"texcrd r0.xyz, t0 ; color map \n"\
|
||||
" \n"\
|
||||
"; original parallax mapping: \n"\
|
||||
";mul r3, r1_bx2.wwww, c6; ; r3 = (height, height, height) * scale \n"\
|
||||
";mad r2.xyz, r3, r4_bx2, r0 ; newTexCoord = height * eye + oldTexCoord \n"\
|
||||
" \n"\
|
||||
"; modified parallax mapping to reduce swimming effect: \n"\
|
||||
"mul r3, r1_bx2.wwww, r1_bx2.zzzz ; (nh,nh,nh,nh) = (h,h,h,h) * (n.z,n.z,n.z,n.z,) \n"\
|
||||
"mul r3, r3, c6; ; r3 = (nh, nh, nh) * scale \n"\
|
||||
"mad r2.xyz, r3, r4_bx2, r0 ; newTexCoord = height * eye + oldTexCoord \n"\
|
||||
" \n"\
|
||||
"phase \n"\
|
||||
" \n"\
|
||||
"texld r0, r2 ; load diffuse texture with new tex coord \n"\
|
||||
"texld r1, r2 ; sample normal map \n"\
|
||||
"texcrd r2.xyz, t2 ; fetch light vector 1 \n"\
|
||||
"texcrd r3.xyz, t3 ; fetch light vector 2 \n"\
|
||||
" \n"\
|
||||
"dp3_sat r2, r1_bx2, r2_bx2 ; normal dot light 1 (_bx2 because moved into 0..1) \n"\
|
||||
"mul r2, r2, v0 ; luminance1 * light color 1 \n"\
|
||||
" \n"\
|
||||
"dp3_sat r3, r1_bx2, r3_bx2 ; normal dot light 2 (_bx2 because moved into 0..1) \n"\
|
||||
"mad r3, r3, v1, r2 ; (luminance2 * light color 2) + luminance1 \n"\
|
||||
" \n"\
|
||||
"mul r0.xyz, r0, r3 ; total luminance * base color \n"\
|
||||
"+mov r0.a, v0.a ; write original alpha value \n"\
|
||||
"\n";
|
||||
|
||||
|
||||
CD3D8ParallaxMapRenderer::CD3D8ParallaxMapRenderer(
|
||||
IDirect3DDevice8* d3ddev, video::IVideoDriver* driver,
|
||||
s32& outMaterialTypeNr, IMaterialRenderer* baseMaterial)
|
||||
: CD3D8ShaderMaterialRenderer(d3ddev, driver, 0, baseMaterial),
|
||||
CompiledShaders(true), CurrentScale(0.0f)
|
||||
{
|
||||
|
||||
#ifdef _DEBUG
|
||||
setDebugName("CD3D8ParallaxMapRenderer");
|
||||
#endif
|
||||
|
||||
// set this as callback. We could have done this in
|
||||
// the initialization list, but some compilers don't like it.
|
||||
|
||||
CallBack = this;
|
||||
|
||||
// basicly, this thing simply compiles these hardcoded shaders if the
|
||||
// hardware is able to do them, otherwise it maps to the base material
|
||||
|
||||
if (!driver->queryFeature(video::EVDF_PIXEL_SHADER_1_4) ||
|
||||
!driver->queryFeature(video::EVDF_VERTEX_SHADER_1_1))
|
||||
{
|
||||
// this hardware is not able to do shaders. Fall back to
|
||||
// base material.
|
||||
outMaterialTypeNr = driver->addMaterialRenderer(this);
|
||||
return;
|
||||
}
|
||||
|
||||
// check if already compiled parallax map shaders are there.
|
||||
|
||||
video::IMaterialRenderer* renderer = driver->getMaterialRenderer(EMT_PARALLAX_MAP_SOLID);
|
||||
if (renderer)
|
||||
{
|
||||
// use the already compiled shaders
|
||||
video::CD3D8ParallaxMapRenderer* nmr = (video::CD3D8ParallaxMapRenderer*)renderer;
|
||||
CompiledShaders = false;
|
||||
|
||||
VertexShader = nmr->VertexShader;
|
||||
PixelShader = nmr->PixelShader;
|
||||
|
||||
outMaterialTypeNr = driver->addMaterialRenderer(this);
|
||||
}
|
||||
else
|
||||
{
|
||||
// compile shaders on our own
|
||||
init(outMaterialTypeNr, D3D8_PARALLAX_MAP_VSH, D3D8_PARALLAX_MAP_PSH, EVT_TANGENTS);
|
||||
}
|
||||
// something failed, use base material
|
||||
if (-1==outMaterialTypeNr)
|
||||
driver->addMaterialRenderer(this);
|
||||
}
|
||||
|
||||
|
||||
CD3D8ParallaxMapRenderer::~CD3D8ParallaxMapRenderer()
|
||||
{
|
||||
if (CallBack == this)
|
||||
CallBack = 0;
|
||||
|
||||
if (!CompiledShaders)
|
||||
{
|
||||
// prevent this from deleting shaders we did not create
|
||||
VertexShader = 0;
|
||||
PixelShader = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool CD3D8ParallaxMapRenderer::OnRender(IMaterialRendererServices* service, E_VERTEX_TYPE vtxtype)
|
||||
{
|
||||
if (vtxtype != video::EVT_TANGENTS)
|
||||
{
|
||||
os::Printer::log("Error: Normal map renderer only supports vertices of type EVT_TANGENTS", ELL_ERROR);
|
||||
return false;
|
||||
}
|
||||
|
||||
return CD3D8ShaderMaterialRenderer::OnRender(service, vtxtype);
|
||||
}
|
||||
|
||||
|
||||
void CD3D8ParallaxMapRenderer::OnSetMaterial(const video::SMaterial& material,
|
||||
const video::SMaterial& lastMaterial,
|
||||
bool resetAllRenderstates, video::IMaterialRendererServices* services)
|
||||
{
|
||||
CD3D8ShaderMaterialRenderer::OnSetMaterial(material, lastMaterial,
|
||||
resetAllRenderstates, services);
|
||||
|
||||
CurrentScale = material.MaterialTypeParam;
|
||||
}
|
||||
|
||||
|
||||
//! Returns the render capability of the material.
|
||||
s32 CD3D8ParallaxMapRenderer::getRenderCapability() const
|
||||
{
|
||||
if (Driver->queryFeature(video::EVDF_PIXEL_SHADER_1_4) &&
|
||||
Driver->queryFeature(video::EVDF_VERTEX_SHADER_1_1))
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
//! Called by the engine when the vertex and/or pixel shader constants
|
||||
//! for an material renderer should be set.
|
||||
void CD3D8ParallaxMapRenderer::OnSetConstants(IMaterialRendererServices* services, s32 userData)
|
||||
{
|
||||
video::IVideoDriver* driver = services->getVideoDriver();
|
||||
|
||||
// set transposed world matrix
|
||||
services->setVertexShaderConstant(driver->getTransform(video::ETS_WORLD).getTransposed().pointer(), 0, 4);
|
||||
|
||||
// set eye position
|
||||
|
||||
// The viewpoint is at (0., 0., 0.) in eye space.
|
||||
// Turning this into a vector [0 0 0 1] and multiply it by
|
||||
// the inverse of the view matrix, the resulting vector is the
|
||||
// object space location of the camera.
|
||||
|
||||
f32 floats[4] = {0,0,0,1};
|
||||
core::matrix4 minv(driver->getTransform(video::ETS_VIEW));
|
||||
minv.makeInverse();
|
||||
minv.multiplyWith1x4Matrix(floats);
|
||||
services->setVertexShaderConstant(floats, 4, 1);
|
||||
|
||||
// set transposed worldViewProj matrix
|
||||
core::matrix4 worldViewProj(driver->getTransform(video::ETS_PROJECTION));
|
||||
worldViewProj *= driver->getTransform(video::ETS_VIEW);
|
||||
worldViewProj *= driver->getTransform(video::ETS_WORLD);
|
||||
services->setVertexShaderConstant(worldViewProj.getTransposed().pointer(), 8, 4);
|
||||
|
||||
// here we've got to fetch the fixed function lights from the driver
|
||||
// and set them as constants
|
||||
|
||||
const u32 cnt = driver->getDynamicLightCount();
|
||||
|
||||
for (u32 i=0; i<2; ++i)
|
||||
{
|
||||
SLight light;
|
||||
|
||||
if (i<cnt)
|
||||
light = driver->getDynamicLight(i);
|
||||
else
|
||||
{
|
||||
light.DiffuseColor.set(0,0,0); // make light dark
|
||||
light.Radius = 1.0f;
|
||||
}
|
||||
|
||||
light.DiffuseColor.a = 1.0f/(light.Radius*light.Radius); // set attenuation
|
||||
|
||||
services->setVertexShaderConstant(reinterpret_cast<const f32*>(&light.Position), 12+(i*2), 1);
|
||||
services->setVertexShaderConstant(reinterpret_cast<const f32*>(&light.DiffuseColor), 13+(i*2), 1);
|
||||
}
|
||||
|
||||
// this is not really necessary in d3d9 (used a def instruction), but to be sure:
|
||||
f32 c95[] = {0.5f, 0.5f, 0.5f, 0.5f};
|
||||
services->setVertexShaderConstant(c95, 95, 1);
|
||||
f32 c96[] = {-1, 1, 1, 1};
|
||||
services->setVertexShaderConstant(c96, 96, 1);
|
||||
|
||||
// set scale factor
|
||||
f32 factor = 0.02f; // default value
|
||||
if (CurrentScale != 0)
|
||||
factor = CurrentScale;
|
||||
|
||||
f32 c6[] = {factor, factor, factor, 0};
|
||||
services->setPixelShaderConstant(c6, 6, 1);
|
||||
}
|
||||
|
||||
|
||||
} // end namespace video
|
||||
} // end namespace irr
|
||||
|
||||
#endif // _IRR_COMPILE_WITH_DIRECT3D_8_
|
||||
|
62
source/Irrlicht/CD3D8ParallaxMapRenderer.h
Normal file
62
source/Irrlicht/CD3D8ParallaxMapRenderer.h
Normal file
@ -0,0 +1,62 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#ifndef __C_D3D8_PARALLAX_MAPMATERIAL_RENDERER_H_INCLUDED__
|
||||
#define __C_D3D8_PARALLAX_MAPMATERIAL_RENDERER_H_INCLUDED__
|
||||
|
||||
#include "IrrCompileConfig.h"
|
||||
#ifdef _IRR_WINDOWS_API_
|
||||
|
||||
#ifdef _IRR_COMPILE_WITH_DIRECT3D_8_
|
||||
#include <d3d8.h>
|
||||
|
||||
#include "CD3D8ShaderMaterialRenderer.h"
|
||||
#include "IShaderConstantSetCallBack.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace video
|
||||
{
|
||||
|
||||
//! Renderer for parallax maps
|
||||
class CD3D8ParallaxMapRenderer : public CD3D8ShaderMaterialRenderer, IShaderConstantSetCallBack
|
||||
{
|
||||
public:
|
||||
|
||||
CD3D8ParallaxMapRenderer(
|
||||
IDirect3DDevice8* d3ddev, video::IVideoDriver* driver,
|
||||
s32& outMaterialTypeNr, IMaterialRenderer* baseMaterial);
|
||||
~CD3D8ParallaxMapRenderer();
|
||||
|
||||
//! Called by the engine when the vertex and/or pixel shader constants for an
|
||||
//! material renderer should be set.
|
||||
virtual void OnSetConstants(IMaterialRendererServices* services, s32 userData);
|
||||
|
||||
virtual bool OnRender(IMaterialRendererServices* service, E_VERTEX_TYPE vtxtype);
|
||||
|
||||
virtual void OnSetMaterial(const SMaterial& material) { }
|
||||
virtual void OnSetMaterial(const video::SMaterial& material,
|
||||
const video::SMaterial& lastMaterial,
|
||||
bool resetAllRenderstates, video::IMaterialRendererServices* services);
|
||||
|
||||
//! Returns the render capability of the material.
|
||||
virtual s32 getRenderCapability() const;
|
||||
|
||||
private:
|
||||
|
||||
//! stores if this shader compiled the shaders and is
|
||||
//! allowed to delete them again. D3D8 lacks reference counting
|
||||
//! support for shaders.
|
||||
bool CompiledShaders;
|
||||
|
||||
f32 CurrentScale;
|
||||
};
|
||||
|
||||
} // end namespace video
|
||||
} // end namespace irr
|
||||
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
332
source/Irrlicht/CD3D8ShaderMaterialRenderer.cpp
Normal file
332
source/Irrlicht/CD3D8ShaderMaterialRenderer.cpp
Normal file
@ -0,0 +1,332 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#include "CD3D8ShaderMaterialRenderer.h"
|
||||
|
||||
#include "IrrCompileConfig.h"
|
||||
#ifdef _IRR_COMPILE_WITH_DIRECT3D_8_
|
||||
#include <d3d8.h>
|
||||
#include <d3dx8core.h>
|
||||
#pragma comment (lib, "d3dx8.lib")
|
||||
|
||||
#include "IShaderConstantSetCallBack.h"
|
||||
#include "IMaterialRendererServices.h"
|
||||
#include "IVideoDriver.h"
|
||||
#include "os.h"
|
||||
|
||||
#ifndef _IRR_D3D_NO_SHADER_DEBUGGING
|
||||
#include <stdio.h>
|
||||
#endif
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace video
|
||||
{
|
||||
|
||||
//! Public constructor
|
||||
CD3D8ShaderMaterialRenderer::CD3D8ShaderMaterialRenderer(IDirect3DDevice8* d3ddev, video::IVideoDriver* driver,
|
||||
s32& outMaterialTypeNr, const c8* vertexShaderProgram, const c8* pixelShaderProgram,
|
||||
IShaderConstantSetCallBack* callback, IMaterialRenderer* baseMaterial, s32 userData)
|
||||
: pID3DDevice(d3ddev), Driver(driver), CallBack(callback), BaseMaterial(baseMaterial),
|
||||
VertexShader(0), OldVertexShader(0), PixelShader(0), UserData(userData)
|
||||
{
|
||||
|
||||
#ifdef _DEBUG
|
||||
setDebugName("CD3D8ShaderMaterialRenderer");
|
||||
#endif
|
||||
|
||||
if (BaseMaterial)
|
||||
BaseMaterial->grab();
|
||||
|
||||
if (CallBack)
|
||||
CallBack->grab();
|
||||
|
||||
init(outMaterialTypeNr, vertexShaderProgram, pixelShaderProgram, EVT_STANDARD);
|
||||
}
|
||||
|
||||
//! constructor only for use by derived classes who want to
|
||||
//! create a fall back material for example.
|
||||
CD3D8ShaderMaterialRenderer::CD3D8ShaderMaterialRenderer(IDirect3DDevice8* d3ddev,
|
||||
video::IVideoDriver* driver,
|
||||
IShaderConstantSetCallBack* callback,
|
||||
IMaterialRenderer* baseMaterial,
|
||||
s32 userData)
|
||||
: pID3DDevice(d3ddev), Driver(driver), BaseMaterial(baseMaterial), CallBack(callback),
|
||||
VertexShader(0), PixelShader(0), UserData(userData)
|
||||
{
|
||||
if (BaseMaterial)
|
||||
BaseMaterial->grab();
|
||||
|
||||
if (CallBack)
|
||||
CallBack->grab();
|
||||
}
|
||||
|
||||
|
||||
|
||||
//! Destructor
|
||||
CD3D8ShaderMaterialRenderer::~CD3D8ShaderMaterialRenderer()
|
||||
{
|
||||
if (CallBack)
|
||||
CallBack->drop();
|
||||
|
||||
if (VertexShader)
|
||||
pID3DDevice->DeleteVertexShader(VertexShader);
|
||||
|
||||
if (PixelShader)
|
||||
pID3DDevice->DeletePixelShader(PixelShader);
|
||||
|
||||
if (BaseMaterial)
|
||||
BaseMaterial->drop ();
|
||||
}
|
||||
|
||||
|
||||
void CD3D8ShaderMaterialRenderer::init(s32& outMaterialTypeNr, const c8* vertexShaderProgram,
|
||||
const c8* pixelShaderProgram, E_VERTEX_TYPE type)
|
||||
{
|
||||
outMaterialTypeNr = -1;
|
||||
|
||||
// create vertex shader
|
||||
if (!createVertexShader(vertexShaderProgram, type))
|
||||
return;
|
||||
|
||||
// create pixel shader
|
||||
if (!createPixelShader(pixelShaderProgram))
|
||||
return;
|
||||
|
||||
// register myself as new material
|
||||
outMaterialTypeNr = Driver->addMaterialRenderer(this);
|
||||
}
|
||||
|
||||
|
||||
bool CD3D8ShaderMaterialRenderer::OnRender(IMaterialRendererServices* service, E_VERTEX_TYPE vtxtype)
|
||||
{
|
||||
// call callback to set shader constants
|
||||
if (CallBack && (VertexShader || PixelShader))
|
||||
CallBack->OnSetConstants(service, UserData);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void CD3D8ShaderMaterialRenderer::OnSetMaterial(const video::SMaterial& material, const video::SMaterial& lastMaterial,
|
||||
bool resetAllRenderstates, video::IMaterialRendererServices* services)
|
||||
{
|
||||
if (material.MaterialType != lastMaterial.MaterialType || resetAllRenderstates)
|
||||
{
|
||||
if (VertexShader)
|
||||
{
|
||||
// We do not need to save and reset the old vertex shader, because
|
||||
// in D3D8, this is mixed up with the fvf, and this is set by the driver
|
||||
// every time.
|
||||
//pID3DDevice->GetVertexShader(&OldVertexShader);
|
||||
|
||||
// set new vertex shader
|
||||
if (FAILED(pID3DDevice->SetVertexShader(VertexShader)))
|
||||
os::Printer::log("Could not set vertex shader.", ELL_ERROR);
|
||||
}
|
||||
|
||||
// set new pixel shader
|
||||
if (PixelShader)
|
||||
{
|
||||
if (FAILED(pID3DDevice->SetPixelShader(PixelShader)))
|
||||
os::Printer::log("Could not set pixel shader.", ELL_ERROR);
|
||||
}
|
||||
|
||||
if (BaseMaterial)
|
||||
BaseMaterial->OnSetMaterial(material, material, true, services);
|
||||
}
|
||||
|
||||
//let callback know used material
|
||||
if (CallBack)
|
||||
CallBack->OnSetMaterial(material);
|
||||
|
||||
services->setBasicRenderStates(material, lastMaterial, resetAllRenderstates);
|
||||
}
|
||||
|
||||
void CD3D8ShaderMaterialRenderer::OnUnsetMaterial()
|
||||
{
|
||||
// We do not need to save and reset the old vertex shader, because
|
||||
// in D3D8, this is mixed up with the fvf, and this is set by the driver
|
||||
// every time.
|
||||
// if (VertexShader)
|
||||
// pID3DDevice->SetVertexShader(OldVertexShader);
|
||||
|
||||
if (PixelShader)
|
||||
pID3DDevice->SetPixelShader(0);
|
||||
|
||||
if (BaseMaterial)
|
||||
BaseMaterial->OnUnsetMaterial();
|
||||
}
|
||||
|
||||
|
||||
//! Returns if the material is transparent. The scene managment needs to know this
|
||||
//! for being able to sort the materials by opaque and transparent.
|
||||
bool CD3D8ShaderMaterialRenderer::isTransparent() const
|
||||
{
|
||||
return BaseMaterial ? BaseMaterial->isTransparent() : false;
|
||||
}
|
||||
|
||||
bool CD3D8ShaderMaterialRenderer::createPixelShader(const c8* pxsh)
|
||||
{
|
||||
if (!pxsh)
|
||||
return true;
|
||||
|
||||
#if defined( _IRR_XBOX_PLATFORM_)
|
||||
return false;
|
||||
#else
|
||||
// compile shader
|
||||
|
||||
LPD3DXBUFFER code = 0;
|
||||
LPD3DXBUFFER errors = 0;
|
||||
|
||||
#ifdef _IRR_D3D_NO_SHADER_DEBUGGING
|
||||
|
||||
// compile shader without debug info
|
||||
D3DXAssembleShader(pxsh, (UINT)strlen(pxsh), 0, 0, &code, &errors);
|
||||
|
||||
#else
|
||||
|
||||
// compile shader and emitt some debug informations to
|
||||
// make it possible to debug the shader in visual studio
|
||||
|
||||
static int irr_dbg_file_nr = 0;
|
||||
++irr_dbg_file_nr;
|
||||
char tmp[32];
|
||||
sprintf(tmp, "irr_d3d8_dbg_shader_%d.psh", irr_dbg_file_nr);
|
||||
|
||||
FILE* f = fopen(tmp, "wb");
|
||||
fwrite(pxsh, strlen(pxsh), 1, f);
|
||||
fflush(f);
|
||||
fclose(f);
|
||||
|
||||
D3DXAssembleShaderFromFile(tmp, D3DXASM_DEBUG, 0, &code, &errors);
|
||||
#endif
|
||||
if (errors)
|
||||
{
|
||||
// print out compilation errors.
|
||||
os::Printer::log("Pixel shader compilation failed:", ELL_ERROR);
|
||||
os::Printer::log((c8*)errors->GetBufferPointer(), ELL_ERROR);
|
||||
|
||||
if (code)
|
||||
code->Release();
|
||||
|
||||
errors->Release();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (FAILED(pID3DDevice->CreatePixelShader((DWORD*)code->GetBufferPointer(), &PixelShader)))
|
||||
{
|
||||
os::Printer::log("Could not create pixel shader.", ELL_ERROR);
|
||||
code->Release();
|
||||
return false;
|
||||
}
|
||||
|
||||
code->Release();
|
||||
return true;
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool CD3D8ShaderMaterialRenderer::createVertexShader(const char* vtxsh, E_VERTEX_TYPE type)
|
||||
{
|
||||
if (!vtxsh)
|
||||
return true;
|
||||
|
||||
// compile shader
|
||||
#if defined( _IRR_XBOX_PLATFORM_)
|
||||
return false;
|
||||
#else
|
||||
|
||||
LPD3DXBUFFER code = 0;
|
||||
LPD3DXBUFFER errors = 0;
|
||||
|
||||
#ifdef _IRR_D3D_NO_SHADER_DEBUGGING
|
||||
|
||||
// compile shader without debug info
|
||||
D3DXAssembleShader(vtxsh, (UINT)strlen(vtxsh), 0, 0, &code, &errors);
|
||||
|
||||
#else
|
||||
|
||||
// compile shader and emitt some debug informations to
|
||||
// make it possible to debug the shader in visual studio
|
||||
static int irr_dbg_file_nr = 0;
|
||||
++irr_dbg_file_nr;
|
||||
char tmp[32];
|
||||
sprintf(tmp, "irr_d3d8_dbg_shader_%d.vsh", irr_dbg_file_nr);
|
||||
|
||||
FILE* f = fopen(tmp, "wb");
|
||||
fwrite(vtxsh, strlen(vtxsh), 1, f);
|
||||
fflush(f);
|
||||
fclose(f);
|
||||
|
||||
D3DXAssembleShaderFromFile(tmp, D3DXASM_DEBUG, 0, &code, &errors);
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
if (errors)
|
||||
{
|
||||
// print out compilation errors.
|
||||
os::Printer::log("Vertex shader compilation failed:", ELL_ERROR);
|
||||
os::Printer::log((c8*)errors->GetBufferPointer(), ELL_ERROR);
|
||||
|
||||
if (code)
|
||||
code->Release();
|
||||
|
||||
errors->Release();
|
||||
return false;
|
||||
}
|
||||
|
||||
DWORD* decl = 0;
|
||||
|
||||
DWORD dwStdDecl[] =
|
||||
{
|
||||
D3DVSD_STREAM(0),
|
||||
D3DVSD_REG(0, D3DVSDT_FLOAT3), // position 0
|
||||
D3DVSD_REG(1, D3DVSDT_FLOAT3), // normal 1
|
||||
D3DVSD_REG(2, D3DVSDT_D3DCOLOR ),// color 2
|
||||
D3DVSD_REG(3, D3DVSDT_FLOAT2 ), // tex1 3
|
||||
D3DVSD_REG(4, D3DVSDT_FLOAT2 ), // tex2 4
|
||||
D3DVSD_END()
|
||||
};
|
||||
|
||||
DWORD dwTngtDecl[] =
|
||||
{
|
||||
D3DVSD_STREAM(0),
|
||||
D3DVSD_REG(0 , D3DVSDT_FLOAT3), // position 0
|
||||
D3DVSD_REG(1 , D3DVSDT_FLOAT3), // normal 1
|
||||
D3DVSD_REG(2 , D3DVSDT_D3DCOLOR ),// color 2
|
||||
D3DVSD_REG(3 , D3DVSDT_FLOAT2 ), // tex1 3
|
||||
D3DVSD_REG(4, D3DVSDT_FLOAT3 ), // tangent 4
|
||||
D3DVSD_REG(5, D3DVSDT_FLOAT3 ), // binormal 5
|
||||
D3DVSD_END()
|
||||
};
|
||||
|
||||
if (type == EVT_TANGENTS)
|
||||
decl = dwTngtDecl;
|
||||
else
|
||||
decl = dwStdDecl;
|
||||
|
||||
if (FAILED(pID3DDevice->CreateVertexShader(decl,
|
||||
(DWORD*)code->GetBufferPointer(), &VertexShader, 0)))
|
||||
{
|
||||
os::Printer::log("Could not create vertex shader.", ELL_ERROR);
|
||||
code->Release();
|
||||
return false;
|
||||
}
|
||||
|
||||
code->Release();
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
} // end namespace video
|
||||
} // end namespace irr
|
||||
|
||||
#endif // _IRR_COMPILE_WITH_DIRECT3D_8_
|
||||
|
82
source/Irrlicht/CD3D8ShaderMaterialRenderer.h
Normal file
82
source/Irrlicht/CD3D8ShaderMaterialRenderer.h
Normal file
@ -0,0 +1,82 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#ifndef __C_D3D8_SHADER_MATERIAL_RENDERER_H_INCLUDED__
|
||||
#define __C_D3D8_SHADER_MATERIAL_RENDERER_H_INCLUDED__
|
||||
|
||||
#include "IrrCompileConfig.h"
|
||||
#ifdef _IRR_WINDOWS_API_
|
||||
|
||||
#ifdef _IRR_COMPILE_WITH_DIRECT3D_8_
|
||||
#include <d3d8.h>
|
||||
#include <d3dx8core.h>
|
||||
|
||||
#include "IMaterialRenderer.h"
|
||||
#include "S3DVertex.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace video
|
||||
{
|
||||
|
||||
class IVideoDriver;
|
||||
class IShaderConstantSetCallBack;
|
||||
class IMaterialRenderer;
|
||||
|
||||
//! Class for using vertex and pixel shaders with D3D8
|
||||
class CD3D8ShaderMaterialRenderer : public IMaterialRenderer
|
||||
{
|
||||
public:
|
||||
|
||||
//! Public constructor
|
||||
CD3D8ShaderMaterialRenderer(IDirect3DDevice8* d3ddev, video::IVideoDriver* driver,
|
||||
s32& outMaterialTypeNr, const c8* vertexShaderProgram, const c8* pixelShaderProgram,
|
||||
IShaderConstantSetCallBack* callback, IMaterialRenderer* baseMaterial, s32 userData);
|
||||
|
||||
//! Destructor
|
||||
~CD3D8ShaderMaterialRenderer();
|
||||
|
||||
virtual void OnSetMaterial(const video::SMaterial& material, const video::SMaterial& lastMaterial,
|
||||
bool resetAllRenderstates, video::IMaterialRendererServices* services);
|
||||
|
||||
virtual void OnUnsetMaterial();
|
||||
|
||||
virtual bool OnRender(IMaterialRendererServices* service, E_VERTEX_TYPE vtxtype);
|
||||
|
||||
//! Returns if the material is transparent.
|
||||
virtual bool isTransparent() const;
|
||||
|
||||
protected:
|
||||
|
||||
//! constructor only for use by derived classes who want to
|
||||
//! create a fall back material for example.
|
||||
CD3D8ShaderMaterialRenderer(IDirect3DDevice8* d3ddev,
|
||||
video::IVideoDriver* driver,
|
||||
IShaderConstantSetCallBack* callback,
|
||||
IMaterialRenderer* baseMaterial, s32 userData=0);
|
||||
|
||||
void init(s32& outMaterialTypeNr, const c8* vertexShaderProgram, const c8* pixelShaderProgram,
|
||||
E_VERTEX_TYPE type);
|
||||
bool createPixelShader(const c8* pxsh);
|
||||
bool createVertexShader(const char* vtxsh, E_VERTEX_TYPE type);
|
||||
|
||||
IDirect3DDevice8* pID3DDevice;
|
||||
video::IVideoDriver* Driver;
|
||||
IShaderConstantSetCallBack* CallBack;
|
||||
IMaterialRenderer* BaseMaterial;
|
||||
|
||||
DWORD VertexShader;
|
||||
DWORD OldVertexShader;
|
||||
DWORD PixelShader;
|
||||
s32 UserData;
|
||||
};
|
||||
|
||||
|
||||
} // end namespace video
|
||||
} // end namespace irr
|
||||
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
659
source/Irrlicht/CD3D8Texture.cpp
Normal file
659
source/Irrlicht/CD3D8Texture.cpp
Normal file
@ -0,0 +1,659 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#include "IrrCompileConfig.h"
|
||||
#ifdef _IRR_COMPILE_WITH_DIRECT3D_8_
|
||||
|
||||
#define _IRR_DONT_DO_MEMORY_DEBUGGING_HERE
|
||||
#include "CD3D8Texture.h"
|
||||
#include "CD3D8Driver.h"
|
||||
#include "os.h"
|
||||
|
||||
|
||||
#ifndef _IRR_COMPILE_WITH_DIRECT3D_9_
|
||||
// The D3DXFilterTexture function seems to get linked wrong when
|
||||
// compiling with both D3D8 and 9, causing it not to work in the D3D9 device.
|
||||
// So mipmapgeneration is replaced with my own bad generation in d3d 8 when
|
||||
// compiling with both D3D 8 and 9.
|
||||
//#define _IRR_USE_D3DXFilterTexture_
|
||||
#endif // _IRR_COMPILE_WITH_DIRECT3D_9_
|
||||
|
||||
#include <d3dx8tex.h>
|
||||
|
||||
#ifdef _IRR_USE_D3DXFilterTexture_
|
||||
#pragma comment (lib, "d3dx8.lib")
|
||||
#endif // _IRR_USE_D3DXFilterTexture_
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace video
|
||||
{
|
||||
|
||||
//! rendertarget constructor
|
||||
CD3D8Texture::CD3D8Texture(CD3D8Driver* driver, const core::dimension2d<u32>& size, const io::path& name)
|
||||
: ITexture(name), Texture(0), RTTSurface(0), Driver(driver),
|
||||
TextureSize(size), ImageSize(size), Pitch(0),
|
||||
HasMipMaps(false), IsRenderTarget(true)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
setDebugName("CD3D8Texture");
|
||||
#endif
|
||||
|
||||
Device=driver->getExposedVideoData().D3D8.D3DDev8;
|
||||
if (Device)
|
||||
Device->AddRef();
|
||||
|
||||
createRenderTarget();
|
||||
}
|
||||
|
||||
|
||||
//! constructor
|
||||
CD3D8Texture::CD3D8Texture(IImage* image, CD3D8Driver* driver,
|
||||
u32 flags, const io::path& name, void* mipmapData)
|
||||
: ITexture(name), Texture(0), RTTSurface(0), Driver(driver),
|
||||
TextureSize(0,0), ImageSize(0,0), Pitch(0),
|
||||
HasMipMaps(false), IsRenderTarget(false)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
setDebugName("CD3D8Texture");
|
||||
#endif
|
||||
|
||||
HasMipMaps = Driver->getTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS);
|
||||
|
||||
Device=driver->getExposedVideoData().D3D8.D3DDev8;
|
||||
if (Device)
|
||||
Device->AddRef();
|
||||
|
||||
if (image)
|
||||
{
|
||||
if (createTexture(flags, image))
|
||||
{
|
||||
if (copyTexture(image))
|
||||
{
|
||||
regenerateMipMapLevels(mipmapData);
|
||||
}
|
||||
}
|
||||
else
|
||||
os::Printer::log("Could not create DIRECT3D8 Texture.", ELL_WARNING);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//! destructor
|
||||
CD3D8Texture::~CD3D8Texture()
|
||||
{
|
||||
if (Texture)
|
||||
Texture->Release();
|
||||
|
||||
if (RTTSurface)
|
||||
RTTSurface->Release();
|
||||
|
||||
if (Device)
|
||||
Device->Release();
|
||||
}
|
||||
|
||||
|
||||
//! creates the hardware texture
|
||||
bool CD3D8Texture::createTexture(u32 flags, video::IImage* image)
|
||||
{
|
||||
ImageSize = image->getDimension();
|
||||
|
||||
core::dimension2d<u32> optSize = ImageSize.getOptimalSize(!Driver->queryFeature(EVDF_TEXTURE_NPOT), !Driver->queryFeature(EVDF_TEXTURE_NSQUARE), true, Driver->Caps.MaxTextureWidth);
|
||||
|
||||
D3DFORMAT format = D3DFMT_A1R5G5B5;
|
||||
switch(getTextureFormatFromFlags(flags))
|
||||
{
|
||||
case ETCF_ALWAYS_16_BIT:
|
||||
format = D3DFMT_A1R5G5B5; break;
|
||||
case ETCF_ALWAYS_32_BIT:
|
||||
format = D3DFMT_A8R8G8B8; break;
|
||||
case ETCF_OPTIMIZED_FOR_QUALITY:
|
||||
{
|
||||
switch(image->getColorFormat())
|
||||
{
|
||||
case ECF_R8G8B8:
|
||||
case ECF_A8R8G8B8:
|
||||
format = D3DFMT_A8R8G8B8; break;
|
||||
case ECF_A1R5G5B5:
|
||||
case ECF_R5G6B5:
|
||||
format = D3DFMT_A1R5G5B5; break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case ETCF_OPTIMIZED_FOR_SPEED:
|
||||
format = D3DFMT_A1R5G5B5; break;
|
||||
}
|
||||
|
||||
if (Driver->getTextureCreationFlag(video::ETCF_NO_ALPHA_CHANNEL))
|
||||
{
|
||||
if (format == D3DFMT_A8R8G8B8)
|
||||
|
||||
#ifdef _IRR_XBOX_PLATFORM_
|
||||
format = D3DFMT_X8R8G8B8;
|
||||
#else
|
||||
format = D3DFMT_R8G8B8;
|
||||
#endif
|
||||
|
||||
else if (format == D3DFMT_A1R5G5B5)
|
||||
format = D3DFMT_R5G6B5;
|
||||
}
|
||||
|
||||
const bool mipmaps = Driver->getTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS);
|
||||
|
||||
HRESULT hr = Device->CreateTexture(optSize.Width, optSize.Height,
|
||||
mipmaps ? 0 : 1, // number of mipmaplevels (0 = automatic all)
|
||||
0, format, D3DPOOL_MANAGED, &Texture);
|
||||
|
||||
if (FAILED(hr))
|
||||
{
|
||||
// try brute force 16 bit
|
||||
if (format == D3DFMT_A8R8G8B8)
|
||||
format = D3DFMT_A1R5G5B5;
|
||||
#ifdef _IRR_XBOX_PLATFORM_
|
||||
else if (format == D3DFMT_X8R8G8B8)
|
||||
format = D3DFMT_R5G6B5;
|
||||
#else
|
||||
else if (format == D3DFMT_R8G8B8)
|
||||
format = D3DFMT_R5G6B5;
|
||||
#endif
|
||||
else
|
||||
return false;
|
||||
|
||||
hr = Device->CreateTexture(optSize.Width, optSize.Height,
|
||||
mipmaps ? 0 : 1, // number of mipmaplevels (0 = automatic all)
|
||||
0, format, D3DPOOL_MANAGED, &Texture);
|
||||
}
|
||||
|
||||
ColorFormat = getColorFormatFromD3DFormat(format);
|
||||
return (SUCCEEDED(hr));
|
||||
}
|
||||
|
||||
|
||||
//! copies the image to the texture
|
||||
bool CD3D8Texture::copyTexture(video::IImage* image)
|
||||
{
|
||||
if (Texture && image)
|
||||
{
|
||||
D3DSURFACE_DESC desc;
|
||||
Texture->GetLevelDesc(0, &desc);
|
||||
|
||||
TextureSize.Width = desc.Width;
|
||||
TextureSize.Height = desc.Height;
|
||||
|
||||
D3DLOCKED_RECT rect;
|
||||
HRESULT hr = Texture->LockRect(0, &rect, 0, 0);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
os::Printer::log("Could not lock D3D8 Texture.", ELL_ERROR);
|
||||
return false;
|
||||
}
|
||||
|
||||
Pitch = rect.Pitch;
|
||||
image->copyToScaling(rect.pBits, TextureSize.Width, TextureSize.Height, ColorFormat, Pitch);
|
||||
|
||||
hr = Texture->UnlockRect(0);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
os::Printer::log("Could not unlock D3D8 Texture.", ELL_ERROR);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
//! lock function
|
||||
void* CD3D8Texture::lock(E_TEXTURE_LOCK_MODE mode, u32 mipmapLevel)
|
||||
{
|
||||
if (!Texture)
|
||||
return 0;
|
||||
|
||||
MipLevelLocked=mipmapLevel;
|
||||
HRESULT hr;
|
||||
D3DLOCKED_RECT rect;
|
||||
if(!IsRenderTarget)
|
||||
{
|
||||
hr = Texture->LockRect(mipmapLevel, &rect, 0, (mode==ETLM_READ_ONLY)?D3DLOCK_READONLY:0);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
os::Printer::log("Could not lock DIRECT3D9 Texture.", ELL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!RTTSurface)
|
||||
{
|
||||
// Make RTT surface large enough for all miplevels (including 0)
|
||||
D3DSURFACE_DESC desc;
|
||||
Texture->GetLevelDesc(0, &desc);
|
||||
hr = Device->CreateImageSurface(desc.Width, desc.Height, desc.Format, &RTTSurface);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
os::Printer::log("Could not lock DIRECT3D8 Texture.", ELL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
IDirect3DSurface8 *surface = 0;
|
||||
hr = Texture->GetSurfaceLevel(mipmapLevel, &surface);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
os::Printer::log("Could not lock DIRECT3D8 Texture.", "Could not get surface.", ELL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
hr = Device->CopyRects(surface, 0, 0, RTTSurface, 0);
|
||||
surface->Release();
|
||||
if(FAILED(hr))
|
||||
{
|
||||
os::Printer::log("Could not lock DIRECT3D8 Texture.", "Data copy failed.", ELL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
hr = RTTSurface->LockRect(&rect, 0, (mode==ETLM_READ_ONLY)?D3DLOCK_READONLY:0);
|
||||
if(FAILED(hr))
|
||||
{
|
||||
os::Printer::log("Could not lock DIRECT3D8 Texture.", "LockRect failed.", ELL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return rect.pBits;
|
||||
}
|
||||
|
||||
|
||||
//! unlock function
|
||||
void CD3D8Texture::unlock()
|
||||
{
|
||||
if (!Texture)
|
||||
return;
|
||||
|
||||
if (!IsRenderTarget)
|
||||
Texture->UnlockRect(MipLevelLocked);
|
||||
else if (RTTSurface)
|
||||
RTTSurface->UnlockRect();
|
||||
}
|
||||
|
||||
|
||||
//! Returns original size of the texture.
|
||||
const core::dimension2d<u32>& CD3D8Texture::getOriginalSize() const
|
||||
{
|
||||
return ImageSize;
|
||||
}
|
||||
|
||||
|
||||
//! Returns (=size) of the texture.
|
||||
const core::dimension2d<u32>& CD3D8Texture::getSize() const
|
||||
{
|
||||
return TextureSize;
|
||||
}
|
||||
|
||||
|
||||
//! returns driver type of texture (=the driver, who created the texture)
|
||||
E_DRIVER_TYPE CD3D8Texture::getDriverType() const
|
||||
{
|
||||
return EDT_DIRECT3D8;
|
||||
}
|
||||
|
||||
|
||||
//! returns color format of texture
|
||||
ECOLOR_FORMAT CD3D8Texture::getColorFormat() const
|
||||
{
|
||||
return ColorFormat;
|
||||
}
|
||||
|
||||
|
||||
//! returns pitch of texture (in bytes)
|
||||
u32 CD3D8Texture::getPitch() const
|
||||
{
|
||||
return Pitch;
|
||||
}
|
||||
|
||||
|
||||
//! returns the DIRECT3D8 Texture
|
||||
IDirect3DTexture8* CD3D8Texture::getDX8Texture() const
|
||||
{
|
||||
return Texture;
|
||||
}
|
||||
|
||||
|
||||
//! returns if texture has mipmap levels
|
||||
bool CD3D8Texture::hasMipMaps() const
|
||||
{
|
||||
return HasMipMaps;
|
||||
}
|
||||
|
||||
|
||||
// The D3DXFilterTexture function seems to get linked wrong when
|
||||
// compiling with both D3D8 and 9, causing it not to work in the D3D9 device.
|
||||
// So mipmapgeneration is replaced with my own bad generation in d3d 8 when
|
||||
// compiling with both D3D 8 and 9.
|
||||
bool CD3D8Texture::createMipMaps(u32 level)
|
||||
{
|
||||
if (level==0)
|
||||
return true;
|
||||
|
||||
IDirect3DSurface8* upperSurface = 0;
|
||||
IDirect3DSurface8* lowerSurface = 0;
|
||||
|
||||
// get upper level
|
||||
HRESULT hr = Texture->GetSurfaceLevel(level-1, &upperSurface);
|
||||
if (FAILED(hr) || !upperSurface)
|
||||
{
|
||||
os::Printer::log("Could not get upper surface level for mip map generation", ELL_WARNING);
|
||||
return false;
|
||||
}
|
||||
|
||||
// get lower level
|
||||
hr = Texture->GetSurfaceLevel(level, &lowerSurface);
|
||||
if (FAILED(hr) || !lowerSurface)
|
||||
{
|
||||
os::Printer::log("Could not get lower surface level for mip map generation", ELL_WARNING);
|
||||
upperSurface->Release();
|
||||
return false;
|
||||
}
|
||||
|
||||
D3DSURFACE_DESC upperDesc, lowerDesc;
|
||||
upperSurface->GetDesc(&upperDesc);
|
||||
lowerSurface->GetDesc(&lowerDesc);
|
||||
|
||||
D3DLOCKED_RECT upperlr;
|
||||
D3DLOCKED_RECT lowerlr;
|
||||
|
||||
// lock upper surface
|
||||
if (FAILED(upperSurface->LockRect(&upperlr, NULL, 0)))
|
||||
{
|
||||
os::Printer::log("Could not lock upper texture for mip map generation", ELL_WARNING);
|
||||
upperSurface->Release();
|
||||
lowerSurface->Release();
|
||||
return false;
|
||||
}
|
||||
|
||||
// lock lower surface
|
||||
if (FAILED(lowerSurface->LockRect(&lowerlr, NULL, 0)))
|
||||
{
|
||||
os::Printer::log("Could not lock lower texture for mip map generation", ELL_WARNING);
|
||||
upperSurface->UnlockRect();
|
||||
upperSurface->Release();
|
||||
lowerSurface->Release();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (upperDesc.Format != lowerDesc.Format)
|
||||
{
|
||||
os::Printer::log("Cannot copy mip maps with different formats.", ELL_WARNING);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (upperDesc.Format == D3DFMT_A1R5G5B5)
|
||||
copy16BitMipMap((char*)upperlr.pBits, (char*)lowerlr.pBits,
|
||||
lowerDesc.Width, lowerDesc.Height,
|
||||
upperlr.Pitch, lowerlr.Pitch);
|
||||
else
|
||||
if (upperDesc.Format == D3DFMT_A8R8G8B8)
|
||||
copy32BitMipMap((char*)upperlr.pBits, (char*)lowerlr.pBits,
|
||||
lowerDesc.Width, lowerDesc.Height,
|
||||
upperlr.Pitch, lowerlr.Pitch);
|
||||
else
|
||||
os::Printer::log("Unsupported mipmap format, cannot copy.", ELL_WARNING);
|
||||
}
|
||||
|
||||
bool result=true;
|
||||
// unlock
|
||||
if (FAILED(upperSurface->UnlockRect()))
|
||||
result=false;
|
||||
if (FAILED(lowerSurface->UnlockRect()))
|
||||
result=false;
|
||||
|
||||
// release
|
||||
upperSurface->Release();
|
||||
lowerSurface->Release();
|
||||
|
||||
if (!result || upperDesc.Width < 3 || upperDesc.Height < 3)
|
||||
return result; // stop generating levels
|
||||
|
||||
// generate next level
|
||||
return createMipMaps(level+1);
|
||||
}
|
||||
|
||||
|
||||
ECOLOR_FORMAT CD3D8Texture::getColorFormatFromD3DFormat(D3DFORMAT format)
|
||||
{
|
||||
switch(format)
|
||||
{
|
||||
case D3DFMT_X1R5G5B5:
|
||||
case D3DFMT_A1R5G5B5:
|
||||
Pitch = TextureSize.Width * 2;
|
||||
return ECF_A1R5G5B5;
|
||||
break;
|
||||
case D3DFMT_A8R8G8B8:
|
||||
case D3DFMT_X8R8G8B8:
|
||||
Pitch = TextureSize.Width * 4;
|
||||
return ECF_A8R8G8B8;
|
||||
break;
|
||||
case D3DFMT_R5G6B5:
|
||||
Pitch = TextureSize.Width * 2;
|
||||
return ECF_R5G6B5;
|
||||
break;
|
||||
default:
|
||||
return (ECOLOR_FORMAT)0;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
|
||||
void CD3D8Texture::copy16BitMipMap(char* src, char* tgt,
|
||||
s32 width, s32 height,
|
||||
s32 pitchsrc, s32 pitchtgt) const
|
||||
{
|
||||
u16 c;
|
||||
|
||||
for (int x=0; x<width; ++x)
|
||||
{
|
||||
for (int y=0; y<height; ++y)
|
||||
{
|
||||
s32 a=0, r=0, g=0, b=0;
|
||||
|
||||
for (int dx=0; dx<2; ++dx)
|
||||
{
|
||||
for (int dy=0; dy<2; ++dy)
|
||||
{
|
||||
int tgx = (x*2)+dx;
|
||||
int tgy = (y*2)+dy;
|
||||
|
||||
c = *(u16*)((void*)&src[(tgx*2)+(tgy*pitchsrc)]);
|
||||
|
||||
a += getAlpha(c);
|
||||
r += getRed(c);
|
||||
g += getGreen(c);
|
||||
b += getBlue(c);
|
||||
}
|
||||
}
|
||||
|
||||
a /= 4;
|
||||
r /= 4;
|
||||
g /= 4;
|
||||
b /= 4;
|
||||
|
||||
c = ((a & 0x1) <<15) | ((r & 0x1F)<<10) | ((g & 0x1F)<<5) | (b & 0x1F);
|
||||
*(u16*)((void*)&tgt[(x*2)+(y*pitchtgt)]) = c;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CD3D8Texture::copy32BitMipMap(char* src, char* tgt,
|
||||
s32 width, s32 height,
|
||||
s32 pitchsrc, s32 pitchtgt) const
|
||||
{
|
||||
SColor c;
|
||||
|
||||
for (int x=0; x<width; ++x)
|
||||
{
|
||||
for (int y=0; y<height; ++y)
|
||||
{
|
||||
s32 a=0, r=0, g=0, b=0;
|
||||
|
||||
for (int dx=0; dx<2; ++dx)
|
||||
{
|
||||
for (int dy=0; dy<2; ++dy)
|
||||
{
|
||||
int tgx = (x*2)+dx;
|
||||
int tgy = (y*2)+dy;
|
||||
|
||||
c = *(u32*)((void*)&src[(tgx<<2)+(tgy*pitchsrc)]);
|
||||
|
||||
a += c.getAlpha();
|
||||
r += c.getRed();
|
||||
g += c.getGreen();
|
||||
b += c.getBlue();
|
||||
}
|
||||
}
|
||||
|
||||
a >>= 2;
|
||||
r >>= 2;
|
||||
g >>= 2;
|
||||
b >>= 2;
|
||||
|
||||
c = ((a & 0xff)<<24) | ((r & 0xff)<<16) | ((g & 0xff)<<8) | (b & 0xff);
|
||||
*(u32*)((void*)&tgt[(x*4)+(y*pitchtgt)]) = c.color;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CD3D8Texture::createRenderTarget()
|
||||
{
|
||||
TextureSize = TextureSize.getOptimalSize(!Driver->queryFeature(EVDF_TEXTURE_NPOT), !Driver->queryFeature(EVDF_TEXTURE_NSQUARE), true, Driver->Caps.MaxTextureWidth);
|
||||
|
||||
// get backbuffer format to create the render target in the
|
||||
// same format
|
||||
|
||||
IDirect3DSurface8* bb;
|
||||
D3DFORMAT d3DFormat = D3DFMT_A8R8G8B8;
|
||||
|
||||
if (!FAILED(Device->GetBackBuffer(0, D3DBACKBUFFER_TYPE_MONO, &bb)))
|
||||
{
|
||||
D3DSURFACE_DESC desc;
|
||||
bb->GetDesc(&desc);
|
||||
d3DFormat = desc.Format;
|
||||
|
||||
if (d3DFormat == D3DFMT_X8R8G8B8)
|
||||
d3DFormat = D3DFMT_A8R8G8B8;
|
||||
|
||||
bb->Release();
|
||||
}
|
||||
else
|
||||
{
|
||||
os::Printer::log("Could not create RenderTarget texture: could not get BackBuffer.",
|
||||
ELL_WARNING);
|
||||
return;
|
||||
}
|
||||
|
||||
// create texture
|
||||
HRESULT hr;
|
||||
|
||||
hr = Device->CreateTexture(
|
||||
TextureSize.Width,
|
||||
TextureSize.Height,
|
||||
1, // mip map level count, we don't want mipmaps here
|
||||
D3DUSAGE_RENDERTARGET,
|
||||
d3DFormat,
|
||||
D3DPOOL_DEFAULT,
|
||||
&Texture);
|
||||
|
||||
// get irrlicht format from D3D format
|
||||
ColorFormat = getColorFormatFromD3DFormat(d3DFormat);
|
||||
|
||||
if (FAILED(hr))
|
||||
os::Printer::log("Could not create render target texture");
|
||||
}
|
||||
|
||||
|
||||
//! Regenerates the mip map levels of the texture. Useful after locking and
|
||||
//! modifying the texture
|
||||
void CD3D8Texture::regenerateMipMapLevels(void* mipmapData)
|
||||
{
|
||||
if (mipmapData)
|
||||
{
|
||||
core::dimension2du size = TextureSize;
|
||||
u32 level=0;
|
||||
do
|
||||
{
|
||||
if (size.Width>1)
|
||||
size.Width /=2;
|
||||
if (size.Height>1)
|
||||
size.Height /=2;
|
||||
++level;
|
||||
IDirect3DSurface8* mipSurface = 0;
|
||||
HRESULT hr = Texture->GetSurfaceLevel(level, &mipSurface);
|
||||
if (FAILED(hr) || !mipSurface)
|
||||
{
|
||||
os::Printer::log("Could not get mipmap level", ELL_WARNING);
|
||||
return;
|
||||
}
|
||||
D3DSURFACE_DESC mipDesc;
|
||||
mipSurface->GetDesc(&mipDesc);
|
||||
D3DLOCKED_RECT miplr;
|
||||
|
||||
// lock mipmap surface
|
||||
if (FAILED(mipSurface->LockRect(&miplr, NULL, 0)))
|
||||
{
|
||||
mipSurface->Release();
|
||||
os::Printer::log("Could not lock texture", ELL_WARNING);
|
||||
return;
|
||||
}
|
||||
|
||||
memcpy(miplr.pBits, mipmapData, size.getArea()*getPitch()/TextureSize.Width);
|
||||
mipmapData = (u8*)mipmapData+size.getArea()*getPitch()/TextureSize.Width;
|
||||
// unlock
|
||||
mipSurface->UnlockRect();
|
||||
// release
|
||||
mipSurface->Release();
|
||||
} while (size.Width != 1 || size.Height != 1);
|
||||
}
|
||||
else if (HasMipMaps)
|
||||
{
|
||||
// create mip maps.
|
||||
#ifndef _IRR_USE_D3DXFilterTexture_
|
||||
// The D3DXFilterTexture function seems to get linked wrong when
|
||||
// compiling with both D3D8 and 9, causing it not to work in the D3D9 device.
|
||||
// So mipmapgeneration is replaced with my own bad generation in d3d 8 when
|
||||
// compiling with both D3D 8 and 9.
|
||||
HRESULT hr = D3DXFilterTexture(Texture, NULL, D3DX_DEFAULT , D3DX_DEFAULT );
|
||||
if (FAILED(hr))
|
||||
#endif
|
||||
createMipMaps();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//! returns if it is a render target
|
||||
bool CD3D8Texture::isRenderTarget() const
|
||||
{
|
||||
return IsRenderTarget;
|
||||
}
|
||||
|
||||
|
||||
//! Returns pointer to the render target surface
|
||||
IDirect3DSurface8* CD3D8Texture::getRenderTargetSurface()
|
||||
{
|
||||
if (!IsRenderTarget)
|
||||
return 0;
|
||||
|
||||
IDirect3DSurface8 *pRTTSurface = 0;
|
||||
if (Texture)
|
||||
Texture->GetSurfaceLevel(0, &pRTTSurface);
|
||||
|
||||
if (pRTTSurface)
|
||||
pRTTSurface->Release();
|
||||
|
||||
return pRTTSurface;
|
||||
}
|
||||
|
||||
|
||||
} // end namespace video
|
||||
} // end namespace irr
|
||||
|
||||
#endif // _IRR_COMPILE_WITH_DIRECT3D_8_
|
||||
|
120
source/Irrlicht/CD3D8Texture.h
Normal file
120
source/Irrlicht/CD3D8Texture.h
Normal file
@ -0,0 +1,120 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#ifndef __C_DIRECTX8_TEXTURE_H_INCLUDED__
|
||||
#define __C_DIRECTX8_TEXTURE_H_INCLUDED__
|
||||
|
||||
#include "IrrCompileConfig.h"
|
||||
#ifdef _IRR_COMPILE_WITH_DIRECT3D_8_
|
||||
|
||||
#include "ITexture.h"
|
||||
#include "IImage.h"
|
||||
|
||||
#include <d3d8.h>
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace video
|
||||
{
|
||||
|
||||
class CD3D8Driver;
|
||||
|
||||
/*!
|
||||
interface for a Video Driver dependent Texture.
|
||||
*/
|
||||
class CD3D8Texture : public ITexture
|
||||
{
|
||||
public:
|
||||
|
||||
//! constructor
|
||||
CD3D8Texture(IImage* image, CD3D8Driver* driver,
|
||||
u32 flags, const io::path& name, void* mipmapData=0);
|
||||
|
||||
//! rendertarget constructor
|
||||
CD3D8Texture(CD3D8Driver* driver, const core::dimension2d<u32>& size, const io::path& name);
|
||||
|
||||
//! destructor
|
||||
virtual ~CD3D8Texture();
|
||||
|
||||
//! lock function
|
||||
virtual void* lock(E_TEXTURE_LOCK_MODE mode=ETLM_READ_WRITE, u32 mipmapLevel=0);
|
||||
|
||||
//! unlock function
|
||||
virtual void unlock();
|
||||
|
||||
//! Returns original size of the texture.
|
||||
virtual const core::dimension2d<u32>& getOriginalSize() const;
|
||||
|
||||
//! Returns (=size) of the texture.
|
||||
virtual const core::dimension2d<u32>& getSize() const;
|
||||
|
||||
//! returns driver type of texture (=the driver, who created the texture)
|
||||
virtual E_DRIVER_TYPE getDriverType() const;
|
||||
|
||||
//! returns color format of texture
|
||||
virtual ECOLOR_FORMAT getColorFormat() const;
|
||||
|
||||
//! returns pitch of texture (in bytes)
|
||||
virtual u32 getPitch() const;
|
||||
|
||||
//! returns the DIRECT3D8 Texture
|
||||
IDirect3DTexture8* getDX8Texture() const;
|
||||
|
||||
//! returns if texture has mipmap levels
|
||||
bool hasMipMaps() const;
|
||||
|
||||
//! Regenerates the mip map levels of the texture. Useful after locking and
|
||||
//! modifying the texture
|
||||
virtual void regenerateMipMapLevels(void* mipmapData=0);
|
||||
|
||||
//! returns if it is a render target
|
||||
virtual bool isRenderTarget() const;
|
||||
|
||||
//! Returns pointer to the render target surface
|
||||
IDirect3DSurface8* getRenderTargetSurface();
|
||||
|
||||
private:
|
||||
friend class CD3D8Driver;
|
||||
|
||||
void createRenderTarget();
|
||||
|
||||
//! creates the hardware texture
|
||||
bool createTexture(u32 flags, IImage* Image);
|
||||
|
||||
//! copies the image to the texture
|
||||
bool copyTexture(IImage* Image);
|
||||
|
||||
//! convert color formats
|
||||
ECOLOR_FORMAT getColorFormatFromD3DFormat(D3DFORMAT format);
|
||||
|
||||
bool createMipMaps(u32 level=1);
|
||||
|
||||
void copy16BitMipMap(char* src, char* tgt,
|
||||
s32 width, s32 height, s32 pitchsrc, s32 pitchtgt) const;
|
||||
|
||||
void copy32BitMipMap(char* src, char* tgt,
|
||||
s32 width, s32 height, s32 pitchsrc, s32 pitchtgt) const;
|
||||
|
||||
IDirect3DDevice8* Device;
|
||||
IDirect3DTexture8* Texture;
|
||||
IDirect3DSurface8* RTTSurface;
|
||||
CD3D8Driver* Driver;
|
||||
core::dimension2d<u32> TextureSize;
|
||||
core::dimension2d<u32> ImageSize;
|
||||
s32 Pitch;
|
||||
u32 MipLevelLocked;
|
||||
ECOLOR_FORMAT ColorFormat;
|
||||
|
||||
bool HasMipMaps;
|
||||
bool IsRenderTarget;
|
||||
};
|
||||
|
||||
|
||||
} // end namespace video
|
||||
} // end namespace irr
|
||||
|
||||
#endif // _IRR_COMPILE_WITH_DIRECT3D_8_
|
||||
|
||||
#endif // __C_DIRECTX8_TEXTURE_H_INCLUDED__
|
||||
|
222
source/Irrlicht/CD3D9CgMaterialRenderer.cpp
Normal file
222
source/Irrlicht/CD3D9CgMaterialRenderer.cpp
Normal file
@ -0,0 +1,222 @@
|
||||
// Copyright (C) 2012-2012 Patryk Nadrowski
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#include "IrrCompileConfig.h"
|
||||
#if defined(_IRR_COMPILE_WITH_DIRECT3D_9_) && defined(_IRR_COMPILE_WITH_CG_)
|
||||
|
||||
#include "CD3D9CgMaterialRenderer.h"
|
||||
#include "CD3D9Driver.h"
|
||||
#include "CD3D9Texture.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace video
|
||||
{
|
||||
|
||||
CD3D9CgUniformSampler2D::CD3D9CgUniformSampler2D(const CGparameter& parameter, bool global) : CCgUniform(parameter, global)
|
||||
{
|
||||
Type = CG_SAMPLER2D;
|
||||
}
|
||||
|
||||
void CD3D9CgUniformSampler2D::update(const void* data, const SMaterial& material) const
|
||||
{
|
||||
s32* Data = (s32*)data;
|
||||
s32 LayerID = *Data;
|
||||
|
||||
if (material.TextureLayer[LayerID].Texture)
|
||||
{
|
||||
IDirect3DBaseTexture9* Texture = reinterpret_cast<irr::video::CD3D9Texture*>(material.TextureLayer[LayerID].Texture)->getDX9Texture();
|
||||
|
||||
cgD3D9SetTextureParameter(Parameter, Texture);
|
||||
}
|
||||
}
|
||||
|
||||
CD3D9CgMaterialRenderer::CD3D9CgMaterialRenderer(CD3D9Driver* driver, s32& materialType,
|
||||
const c8* vertexProgram, const c8* vertexEntry, E_VERTEX_SHADER_TYPE vertexProfile,
|
||||
const c8* fragmentProgram, const c8* fragmentEntry, E_PIXEL_SHADER_TYPE fragmentProfile,
|
||||
const c8* geometryProgram, const c8* geometryEntry, E_GEOMETRY_SHADER_TYPE geometryProfile,
|
||||
scene::E_PRIMITIVE_TYPE inType, scene::E_PRIMITIVE_TYPE outType, u32 vertices,
|
||||
IShaderConstantSetCallBack* callback, IMaterialRenderer* baseMaterial, s32 userData) :
|
||||
Driver(driver), CCgMaterialRenderer(callback, baseMaterial, userData)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
setDebugName("CD3D9CgMaterialRenderer");
|
||||
#endif
|
||||
|
||||
init(materialType, vertexProgram, vertexEntry, vertexProfile, fragmentProgram, fragmentEntry, fragmentProfile,
|
||||
geometryProgram, geometryEntry, geometryProfile, inType, outType, vertices);
|
||||
}
|
||||
|
||||
CD3D9CgMaterialRenderer::~CD3D9CgMaterialRenderer()
|
||||
{
|
||||
if (VertexProgram)
|
||||
{
|
||||
cgD3D9UnloadProgram(VertexProgram);
|
||||
cgDestroyProgram(VertexProgram);
|
||||
}
|
||||
if (FragmentProgram)
|
||||
{
|
||||
cgD3D9UnloadProgram(FragmentProgram);
|
||||
cgDestroyProgram(FragmentProgram);
|
||||
}
|
||||
/*if (GeometryProgram)
|
||||
{
|
||||
cgD3D9UnloadProgram(GeometryProgram);
|
||||
cgDestroyProgram(GeometryProgram);
|
||||
}*/
|
||||
}
|
||||
|
||||
void CD3D9CgMaterialRenderer::OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial, bool resetAllRenderstates, IMaterialRendererServices* services)
|
||||
{
|
||||
Material = material;
|
||||
|
||||
if (material.MaterialType != lastMaterial.MaterialType || resetAllRenderstates)
|
||||
{
|
||||
if (VertexProgram)
|
||||
cgD3D9BindProgram(VertexProgram);
|
||||
|
||||
if (FragmentProgram)
|
||||
cgD3D9BindProgram(FragmentProgram);
|
||||
|
||||
/*if (GeometryProgram)
|
||||
cgD3D9BindProgram(GeometryProgram);*/
|
||||
|
||||
if (BaseMaterial)
|
||||
BaseMaterial->OnSetMaterial(material, material, true, this);
|
||||
}
|
||||
|
||||
if (CallBack)
|
||||
CallBack->OnSetMaterial(material);
|
||||
|
||||
Driver->setBasicRenderStates(material, lastMaterial, resetAllRenderstates);
|
||||
}
|
||||
|
||||
bool CD3D9CgMaterialRenderer::OnRender(IMaterialRendererServices* services, E_VERTEX_TYPE vtxtype)
|
||||
{
|
||||
if (CallBack && (VertexProgram || FragmentProgram || GeometryProgram))
|
||||
CallBack->OnSetConstants(this, UserData);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CD3D9CgMaterialRenderer::OnUnsetMaterial()
|
||||
{
|
||||
if (VertexProgram)
|
||||
cgD3D9UnbindProgram(VertexProgram);
|
||||
if (FragmentProgram)
|
||||
cgD3D9UnbindProgram(FragmentProgram);
|
||||
/*if (GeometryProgram)
|
||||
cgD3D9UnbindProgram(GeometryProgram);*/
|
||||
|
||||
if (BaseMaterial)
|
||||
BaseMaterial->OnUnsetMaterial();
|
||||
|
||||
Material = IdentityMaterial;;
|
||||
}
|
||||
|
||||
void CD3D9CgMaterialRenderer::setBasicRenderStates(const SMaterial& material, const SMaterial& lastMaterial, bool resetAllRenderstates)
|
||||
{
|
||||
Driver->setBasicRenderStates(material, lastMaterial, resetAllRenderstates);
|
||||
}
|
||||
|
||||
IVideoDriver* CD3D9CgMaterialRenderer::getVideoDriver()
|
||||
{
|
||||
return Driver;
|
||||
}
|
||||
|
||||
void CD3D9CgMaterialRenderer::init(s32& materialType,
|
||||
const c8* vertexProgram, const c8* vertexEntry, E_VERTEX_SHADER_TYPE vertexProfile,
|
||||
const c8* fragmentProgram, const c8* fragmentEntry, E_PIXEL_SHADER_TYPE fragmentProfile,
|
||||
const c8* geometryProgram, const c8* geometryEntry, E_GEOMETRY_SHADER_TYPE geometryProfile,
|
||||
scene::E_PRIMITIVE_TYPE inType, scene::E_PRIMITIVE_TYPE outType, u32 vertices)
|
||||
{
|
||||
bool Status = true;
|
||||
CGerror Error = CG_NO_ERROR;
|
||||
materialType = -1;
|
||||
|
||||
// TODO: add profile selection
|
||||
|
||||
if (vertexProgram)
|
||||
{
|
||||
VertexProfile = cgD3D9GetLatestVertexProfile();
|
||||
|
||||
if (VertexProfile)
|
||||
VertexProgram = cgCreateProgram(Driver->getCgContext(), CG_SOURCE, vertexProgram, VertexProfile, vertexEntry, 0);
|
||||
|
||||
if (!VertexProgram)
|
||||
{
|
||||
Error = cgGetError();
|
||||
os::Printer::log("Cg vertex program failed to compile:", ELL_ERROR);
|
||||
os::Printer::log(cgGetLastListing(Driver->getCgContext()), ELL_ERROR);
|
||||
|
||||
Status = false;
|
||||
}
|
||||
else
|
||||
cgD3D9LoadProgram(VertexProgram, 0, 0);
|
||||
}
|
||||
|
||||
if (fragmentProgram)
|
||||
{
|
||||
FragmentProfile = cgD3D9GetLatestPixelProfile();
|
||||
|
||||
if (FragmentProfile)
|
||||
FragmentProgram = cgCreateProgram(Driver->getCgContext(), CG_SOURCE, fragmentProgram, FragmentProfile, fragmentEntry, 0);
|
||||
|
||||
if (!FragmentProgram)
|
||||
{
|
||||
Error = cgGetError();
|
||||
os::Printer::log("Cg fragment program failed to compile:", ELL_ERROR);
|
||||
os::Printer::log(cgGetLastListing(Driver->getCgContext()), ELL_ERROR);
|
||||
|
||||
Status = false;
|
||||
}
|
||||
else
|
||||
cgD3D9LoadProgram(FragmentProgram, 0, 0);
|
||||
}
|
||||
|
||||
/*if (geometryProgram)
|
||||
{
|
||||
GeometryProfile = cgD3D9GetLatestGeometryProfile();
|
||||
|
||||
if (GeometryProfile)
|
||||
GeometryProgram = cgCreateProgram(Driver->getCgContext(), CG_SOURCE, geometryProgram, GeometryProfile, geometryEntry, 0);
|
||||
|
||||
if (!GeometryProgram)
|
||||
{
|
||||
Error = cgGetError();
|
||||
os::Printer::log("Cg geometry program failed to compile:", ELL_ERROR);
|
||||
os::Printer::log(cgGetLastListing(Driver->getCgContext()), ELL_ERROR);
|
||||
|
||||
Status = false;
|
||||
}
|
||||
else
|
||||
cgD3D9LoadProgram(GeometryProgram, 0, 0);
|
||||
}*/
|
||||
|
||||
getUniformList();
|
||||
|
||||
// create D3D9 specifics sampler uniforms.
|
||||
for(unsigned int i = 0; i < UniformInfo.size(); ++i)
|
||||
{
|
||||
if (UniformInfo[i]->getType() == CG_SAMPLER2D)
|
||||
{
|
||||
bool IsGlobal = true;
|
||||
|
||||
if (UniformInfo[i]->getSpace() == CG_PROGRAM)
|
||||
IsGlobal = false;
|
||||
|
||||
CCgUniform* Uniform = new CD3D9CgUniformSampler2D(UniformInfo[i]->getParameter(), IsGlobal);
|
||||
delete UniformInfo[i];
|
||||
UniformInfo[i] = Uniform;
|
||||
}
|
||||
}
|
||||
|
||||
if (Status)
|
||||
materialType = Driver->addMaterialRenderer(this);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
83
source/Irrlicht/CD3D9CgMaterialRenderer.h
Normal file
83
source/Irrlicht/CD3D9CgMaterialRenderer.h
Normal file
@ -0,0 +1,83 @@
|
||||
// Copyright (C) 2012-2012 Patryk Nadrowski
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#ifndef __C_DIRECT3D_9_CG_MATERIAL_RENDERER_H_INCLUDED__
|
||||
#define __C_DIRECT3D_9_CG_MATERIAL_RENDERER_H_INCLUDED__
|
||||
|
||||
#include "IrrCompileConfig.h"
|
||||
#if defined(_IRR_COMPILE_WITH_DIRECT3D_9_) && defined(_IRR_COMPILE_WITH_CG_)
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
|
||||
#include <windows.h>
|
||||
#include <d3d9.h>
|
||||
#include <d3dx9.h>
|
||||
#include "CCgMaterialRenderer.h"
|
||||
#include "Cg/cgD3D9.h"
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma comment(lib, "cgD3D9.lib")
|
||||
#endif
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace video
|
||||
{
|
||||
|
||||
class CD3D9Driver;
|
||||
class IShaderConstantSetCallBack;
|
||||
|
||||
class CD3D9CgUniformSampler2D : public CCgUniform
|
||||
{
|
||||
public:
|
||||
CD3D9CgUniformSampler2D(const CGparameter& parameter, bool global);
|
||||
|
||||
void update(const void* data, const SMaterial& material) const;
|
||||
};
|
||||
|
||||
class CD3D9CgMaterialRenderer : public CCgMaterialRenderer
|
||||
{
|
||||
public:
|
||||
CD3D9CgMaterialRenderer(CD3D9Driver* driver, s32& materialType,
|
||||
const c8* vertexProgram = 0, const c8* vertexEntry = "main",
|
||||
E_VERTEX_SHADER_TYPE vertexProfile = video::EVST_VS_1_1,
|
||||
const c8* fragmentProgram = 0, const c8* fragmentEntry = "main",
|
||||
E_PIXEL_SHADER_TYPE fragmentProfile = video::EPST_PS_1_1,
|
||||
const c8* geometryProgram = 0, const c8* geometryEntry = "main",
|
||||
E_GEOMETRY_SHADER_TYPE geometryProfile = video::EGST_GS_4_0,
|
||||
scene::E_PRIMITIVE_TYPE inType = scene::EPT_TRIANGLES,
|
||||
scene::E_PRIMITIVE_TYPE outType = scene::EPT_TRIANGLE_STRIP,
|
||||
u32 vertices = 0, IShaderConstantSetCallBack* callback = 0,
|
||||
IMaterialRenderer* baseMaterial = 0, s32 userData = 0);
|
||||
|
||||
virtual ~CD3D9CgMaterialRenderer();
|
||||
|
||||
virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial, bool resetAllRenderstates, IMaterialRendererServices* services);
|
||||
virtual bool OnRender(IMaterialRendererServices* services, E_VERTEX_TYPE vtxtype);
|
||||
virtual void OnUnsetMaterial();
|
||||
|
||||
virtual void setBasicRenderStates(const SMaterial& material, const SMaterial& lastMaterial, bool resetAllRenderstates);
|
||||
virtual IVideoDriver* getVideoDriver();
|
||||
|
||||
protected:
|
||||
void init(s32& materialType,
|
||||
const c8* vertexProgram = 0, const c8* vertexEntry = "main",
|
||||
E_VERTEX_SHADER_TYPE vertexProfile = video::EVST_VS_1_1,
|
||||
const c8* fragmentProgram = 0, const c8* fragmentEntry = "main",
|
||||
E_PIXEL_SHADER_TYPE fragmentProfile = video::EPST_PS_1_1,
|
||||
const c8* geometryProgram = 0, const c8* geometryEntry = "main",
|
||||
E_GEOMETRY_SHADER_TYPE geometryProfile = video::EGST_GS_4_0,
|
||||
scene::E_PRIMITIVE_TYPE inType = scene::EPT_TRIANGLES,
|
||||
scene::E_PRIMITIVE_TYPE outType = scene::EPT_TRIANGLE_STRIP,
|
||||
u32 vertices = 0);
|
||||
|
||||
CD3D9Driver* Driver;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
3633
source/Irrlicht/CD3D9Driver.cpp
Normal file
3633
source/Irrlicht/CD3D9Driver.cpp
Normal file
File diff suppressed because it is too large
Load Diff
496
source/Irrlicht/CD3D9Driver.h
Normal file
496
source/Irrlicht/CD3D9Driver.h
Normal file
@ -0,0 +1,496 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#ifndef __C_VIDEO_DIRECTX_9_H_INCLUDED__
|
||||
#define __C_VIDEO_DIRECTX_9_H_INCLUDED__
|
||||
|
||||
#include "IrrCompileConfig.h"
|
||||
|
||||
#ifdef _IRR_COMPILE_WITH_DIRECT3D_9_
|
||||
|
||||
#ifdef _IRR_WINDOWS_
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
#include "CNullDriver.h"
|
||||
#include "SIrrCreationParameters.h"
|
||||
#include "IMaterialRendererServices.h"
|
||||
#if defined(__BORLANDC__) || defined (__BCPLUSPLUS__)
|
||||
#include "irrMath.h" // needed by borland for sqrtf define
|
||||
#endif
|
||||
#include <d3d9.h>
|
||||
|
||||
#ifdef _IRR_COMPILE_WITH_CG_
|
||||
#include "Cg/cg.h"
|
||||
#include "Cg/cgD3D9.h"
|
||||
#endif
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace video
|
||||
{
|
||||
struct SDepthSurface : public IReferenceCounted
|
||||
{
|
||||
SDepthSurface() : Surface(0)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
setDebugName("SDepthSurface");
|
||||
#endif
|
||||
}
|
||||
virtual ~SDepthSurface()
|
||||
{
|
||||
if (Surface)
|
||||
Surface->Release();
|
||||
}
|
||||
|
||||
IDirect3DSurface9* Surface;
|
||||
core::dimension2du Size;
|
||||
};
|
||||
|
||||
class CD3D9Driver : public CNullDriver, IMaterialRendererServices
|
||||
{
|
||||
public:
|
||||
|
||||
friend class CD3D9Texture;
|
||||
|
||||
//! constructor
|
||||
CD3D9Driver(const SIrrlichtCreationParameters& params, io::IFileSystem* io);
|
||||
|
||||
//! destructor
|
||||
virtual ~CD3D9Driver();
|
||||
|
||||
//! applications must call this method before performing any rendering. returns false if failed.
|
||||
virtual bool beginScene(bool backBuffer=true, bool zBuffer=true,
|
||||
SColor color=SColor(255,0,0,0),
|
||||
const SExposedVideoData& videoData=SExposedVideoData(),
|
||||
core::rect<s32>* sourceRect=0);
|
||||
|
||||
//! applications must call this method after performing any rendering. returns false if failed.
|
||||
virtual bool endScene();
|
||||
|
||||
//! queries the features of the driver, returns true if feature is available
|
||||
virtual bool queryFeature(E_VIDEO_DRIVER_FEATURE feature) const;
|
||||
|
||||
//! sets transformation
|
||||
virtual void setTransform(E_TRANSFORMATION_STATE state, const core::matrix4& mat);
|
||||
|
||||
//! sets a material
|
||||
virtual void setMaterial(const SMaterial& material);
|
||||
|
||||
//! sets a render target
|
||||
virtual bool setRenderTarget(video::ITexture* texture,
|
||||
bool clearBackBuffer=true, bool clearZBuffer=true,
|
||||
SColor color=video::SColor(0,0,0,0));
|
||||
|
||||
//! Sets multiple render targets
|
||||
virtual bool setRenderTarget(const core::array<video::IRenderTarget>& texture,
|
||||
bool clearBackBuffer=true, bool clearZBuffer=true,
|
||||
SColor color=video::SColor(0,0,0,0));
|
||||
|
||||
//! sets a viewport
|
||||
virtual void setViewPort(const core::rect<s32>& area);
|
||||
|
||||
//! gets the area of the current viewport
|
||||
virtual const core::rect<s32>& getViewPort() const;
|
||||
|
||||
struct SHWBufferLink_d3d9 : public SHWBufferLink
|
||||
{
|
||||
SHWBufferLink_d3d9(const scene::IMeshBuffer *_MeshBuffer):
|
||||
SHWBufferLink(_MeshBuffer),
|
||||
vertexBuffer(0), indexBuffer(0),
|
||||
vertexBufferSize(0), indexBufferSize(0) {}
|
||||
|
||||
IDirect3DVertexBuffer9* vertexBuffer;
|
||||
IDirect3DIndexBuffer9* indexBuffer;
|
||||
|
||||
u32 vertexBufferSize;
|
||||
u32 indexBufferSize;
|
||||
};
|
||||
|
||||
bool updateVertexHardwareBuffer(SHWBufferLink_d3d9 *HWBuffer);
|
||||
bool updateIndexHardwareBuffer(SHWBufferLink_d3d9 *HWBuffer);
|
||||
|
||||
//! updates hardware buffer if needed
|
||||
virtual bool updateHardwareBuffer(SHWBufferLink *HWBuffer);
|
||||
|
||||
//! Create hardware buffer from mesh
|
||||
virtual SHWBufferLink *createHardwareBuffer(const scene::IMeshBuffer* mb);
|
||||
|
||||
//! Delete hardware buffer (only some drivers can)
|
||||
virtual void deleteHardwareBuffer(SHWBufferLink *HWBuffer);
|
||||
|
||||
//! Draw hardware buffer
|
||||
virtual void drawHardwareBuffer(SHWBufferLink *HWBuffer);
|
||||
|
||||
//! Create occlusion query.
|
||||
/** Use node for identification and mesh for occlusion test. */
|
||||
virtual void addOcclusionQuery(scene::ISceneNode* node,
|
||||
const scene::IMesh* mesh=0);
|
||||
|
||||
//! Remove occlusion query.
|
||||
virtual void removeOcclusionQuery(scene::ISceneNode* node);
|
||||
|
||||
//! Run occlusion query. Draws mesh stored in query.
|
||||
/** If the mesh shall not be rendered visible, use
|
||||
overrideMaterial to disable the color and depth buffer. */
|
||||
virtual void runOcclusionQuery(scene::ISceneNode* node, bool visible=false);
|
||||
|
||||
//! Update occlusion query. Retrieves results from GPU.
|
||||
/** If the query shall not block, set the flag to false.
|
||||
Update might not occur in this case, though */
|
||||
virtual void updateOcclusionQuery(scene::ISceneNode* node, bool block=true);
|
||||
|
||||
//! Return query result.
|
||||
/** Return value is the number of visible pixels/fragments.
|
||||
The value is a safe approximation, i.e. can be larger then the
|
||||
actual value of pixels. */
|
||||
virtual u32 getOcclusionQueryResult(scene::ISceneNode* node) const;
|
||||
|
||||
//! draws a vertex primitive list
|
||||
virtual void drawVertexPrimitiveList(const void* vertices, u32 vertexCount,
|
||||
const void* indexList, u32 primitiveCount,
|
||||
E_VERTEX_TYPE vType, scene::E_PRIMITIVE_TYPE pType,
|
||||
E_INDEX_TYPE iType);
|
||||
|
||||
//! draws a vertex primitive list in 2d
|
||||
virtual void draw2DVertexPrimitiveList(const void* vertices, u32 vertexCount,
|
||||
const void* indexList, u32 primitiveCount,
|
||||
E_VERTEX_TYPE vType, scene::E_PRIMITIVE_TYPE pType,
|
||||
E_INDEX_TYPE iType);
|
||||
|
||||
//! draws an 2d image, using a color (if color is other then Color(255,255,255,255)) and the alpha channel of the texture if wanted.
|
||||
virtual void draw2DImage(const video::ITexture* texture, const core::position2d<s32>& destPos,
|
||||
const core::rect<s32>& sourceRect, const core::rect<s32>* clipRect = 0,
|
||||
SColor color=SColor(255,255,255,255), bool useAlphaChannelOfTexture=false);
|
||||
|
||||
//! Draws a part of the texture into the rectangle.
|
||||
virtual void draw2DImage(const video::ITexture* texture, const core::rect<s32>& destRect,
|
||||
const core::rect<s32>& sourceRect, const core::rect<s32>* clipRect = 0,
|
||||
const video::SColor* const colors=0, bool useAlphaChannelOfTexture=false);
|
||||
|
||||
//! Draws a set of 2d images, using a color and the alpha channel of the texture.
|
||||
virtual void draw2DImageBatch(const video::ITexture* texture,
|
||||
const core::array<core::position2d<s32> >& positions,
|
||||
const core::array<core::rect<s32> >& sourceRects,
|
||||
const core::rect<s32>* clipRect=0,
|
||||
SColor color=SColor(255,255,255,255),
|
||||
bool useAlphaChannelOfTexture=false);
|
||||
|
||||
//!Draws an 2d rectangle with a gradient.
|
||||
virtual void draw2DRectangle(const core::rect<s32>& pos,
|
||||
SColor colorLeftUp, SColor colorRightUp, SColor colorLeftDown, SColor colorRightDown,
|
||||
const core::rect<s32>* clip);
|
||||
|
||||
//! Draws a 2d line.
|
||||
virtual void draw2DLine(const core::position2d<s32>& start,
|
||||
const core::position2d<s32>& end,
|
||||
SColor color=SColor(255,255,255,255));
|
||||
|
||||
//! Draws a pixel.
|
||||
virtual void drawPixel(u32 x, u32 y, const SColor & color);
|
||||
|
||||
//! Draws a 3d line.
|
||||
virtual void draw3DLine(const core::vector3df& start,
|
||||
const core::vector3df& end, SColor color = SColor(255,255,255,255));
|
||||
|
||||
//! initialises the Direct3D API
|
||||
bool initDriver(HWND hwnd, bool pureSoftware);
|
||||
|
||||
//! \return Returns the name of the video driver. Example: In case of the DIRECT3D8
|
||||
//! driver, it would return "Direct3D8.1".
|
||||
virtual const wchar_t* getName() const;
|
||||
|
||||
//! deletes all dynamic lights there are
|
||||
virtual void deleteAllDynamicLights();
|
||||
|
||||
//! adds a dynamic light, returning an index to the light
|
||||
//! \param light: the light data to use to create the light
|
||||
//! \return An index to the light, or -1 if an error occurs
|
||||
virtual s32 addDynamicLight(const SLight& light);
|
||||
|
||||
//! Turns a dynamic light on or off
|
||||
//! \param lightIndex: the index returned by addDynamicLight
|
||||
//! \param turnOn: true to turn the light on, false to turn it off
|
||||
virtual void turnLightOn(s32 lightIndex, bool turnOn);
|
||||
|
||||
//! returns the maximal amount of dynamic lights the device can handle
|
||||
virtual u32 getMaximalDynamicLightAmount() const;
|
||||
|
||||
//! Sets the dynamic ambient light color. The default color is
|
||||
//! (0,0,0,0) which means it is dark.
|
||||
//! \param color: New color of the ambient light.
|
||||
virtual void setAmbientLight(const SColorf& color);
|
||||
|
||||
//! Draws a shadow volume into the stencil buffer.
|
||||
virtual void drawStencilShadowVolume(const core::array<core::vector3df>& triangles, bool zfail=true, u32 debugDataVisible=0);
|
||||
|
||||
//! Fills the stencil shadow with color.
|
||||
virtual void drawStencilShadow(bool clearStencilBuffer=false,
|
||||
video::SColor leftUpEdge = video::SColor(0,0,0,0),
|
||||
video::SColor rightUpEdge = video::SColor(0,0,0,0),
|
||||
video::SColor leftDownEdge = video::SColor(0,0,0,0),
|
||||
video::SColor rightDownEdge = video::SColor(0,0,0,0));
|
||||
|
||||
//! Returns the maximum amount of primitives (mostly vertices) which
|
||||
//! the device is able to render with one drawIndexedTriangleList
|
||||
//! call.
|
||||
virtual u32 getMaximalPrimitiveCount() const;
|
||||
|
||||
//! Enables or disables a texture creation flag.
|
||||
virtual void setTextureCreationFlag(E_TEXTURE_CREATION_FLAG flag, bool enabled);
|
||||
|
||||
//! Sets the fog mode.
|
||||
virtual void setFog(SColor color, E_FOG_TYPE fogType, f32 start,
|
||||
f32 end, f32 density, bool pixelFog, bool rangeFog);
|
||||
|
||||
//! Only used by the internal engine. Used to notify the driver that
|
||||
//! the window was resized.
|
||||
virtual void OnResize(const core::dimension2d<u32>& size);
|
||||
|
||||
//! Can be called by an IMaterialRenderer to make its work easier.
|
||||
virtual void setBasicRenderStates(const SMaterial& material, const SMaterial& lastMaterial,
|
||||
bool resetAllRenderstates);
|
||||
|
||||
//! Returns type of video driver
|
||||
virtual E_DRIVER_TYPE getDriverType() const;
|
||||
|
||||
//! Returns the transformation set by setTransform
|
||||
virtual const core::matrix4& getTransform(E_TRANSFORMATION_STATE state) const;
|
||||
|
||||
//! Sets a vertex shader constant.
|
||||
virtual void setVertexShaderConstant(const f32* data, s32 startRegister, s32 constantAmount=1);
|
||||
|
||||
//! Sets a pixel shader constant.
|
||||
virtual void setPixelShaderConstant(const f32* data, s32 startRegister, s32 constantAmount=1);
|
||||
|
||||
//! Sets a constant for the vertex shader based on a name.
|
||||
virtual bool setVertexShaderConstant(const c8* name, const f32* floats, int count);
|
||||
|
||||
//! Bool interface for the above.
|
||||
virtual bool setVertexShaderConstant(const c8* name, const bool* bools, int count);
|
||||
|
||||
//! Int interface for the above.
|
||||
virtual bool setVertexShaderConstant(const c8* name, const s32* ints, int count);
|
||||
|
||||
//! Sets a constant for the pixel shader based on a name.
|
||||
virtual bool setPixelShaderConstant(const c8* name, const f32* floats, int count);
|
||||
|
||||
//! Bool interface for the above.
|
||||
virtual bool setPixelShaderConstant(const c8* name, const bool* bools, int count);
|
||||
|
||||
//! Int interface for the above.
|
||||
virtual bool setPixelShaderConstant(const c8* name, const s32* ints, int count);
|
||||
|
||||
//! Returns a pointer to the IVideoDriver interface. (Implementation for
|
||||
//! IMaterialRendererServices)
|
||||
virtual IVideoDriver* getVideoDriver();
|
||||
|
||||
//! Creates a render target texture.
|
||||
virtual ITexture* addRenderTargetTexture(const core::dimension2d<u32>& size,
|
||||
const io::path& name, const ECOLOR_FORMAT format = ECF_UNKNOWN);
|
||||
|
||||
//! Clears the ZBuffer.
|
||||
virtual void clearZBuffer();
|
||||
|
||||
//! Returns an image created from the last rendered frame.
|
||||
virtual IImage* createScreenShot(video::ECOLOR_FORMAT format=video::ECF_UNKNOWN, video::E_RENDER_TARGET target=video::ERT_FRAME_BUFFER);
|
||||
|
||||
//! Set/unset a clipping plane.
|
||||
virtual bool setClipPlane(u32 index, const core::plane3df& plane, bool enable=false);
|
||||
|
||||
//! Enable/disable a clipping plane.
|
||||
virtual void enableClipPlane(u32 index, bool enable);
|
||||
|
||||
//! Returns the graphics card vendor name.
|
||||
virtual core::stringc getVendorInfo() {return VendorName;}
|
||||
|
||||
//! Enable the 2d override material
|
||||
virtual void enableMaterial2D(bool enable=true);
|
||||
|
||||
//! Check if the driver was recently reset.
|
||||
virtual bool checkDriverReset() {return DriverWasReset;}
|
||||
|
||||
// removes the depth struct from the DepthSurface array
|
||||
void removeDepthSurface(SDepthSurface* depth);
|
||||
|
||||
//! Get the current color format of the color buffer
|
||||
/** \return Color format of the color buffer. */
|
||||
virtual ECOLOR_FORMAT getColorFormat() const;
|
||||
|
||||
//! Returns the maximum texture size supported.
|
||||
virtual core::dimension2du getMaxTextureSize() const;
|
||||
|
||||
//! Get the current color format of the color buffer
|
||||
/** \return Color format of the color buffer as D3D color value. */
|
||||
D3DFORMAT getD3DColorFormat() const;
|
||||
|
||||
//! Get D3D color format from Irrlicht color format.
|
||||
D3DFORMAT getD3DFormatFromColorFormat(ECOLOR_FORMAT format) const;
|
||||
|
||||
//! Get Irrlicht color format from D3D color format.
|
||||
ECOLOR_FORMAT getColorFormatFromD3DFormat(D3DFORMAT format) const;
|
||||
|
||||
//! Get Cg context
|
||||
#ifdef _IRR_COMPILE_WITH_CG_
|
||||
const CGcontext& getCgContext();
|
||||
#endif
|
||||
|
||||
private:
|
||||
|
||||
//! enumeration for rendering modes such as 2d and 3d for minizing the switching of renderStates.
|
||||
enum E_RENDER_MODE
|
||||
{
|
||||
ERM_NONE = 0, // no render state has been set yet.
|
||||
ERM_2D, // 2d drawing rendermode
|
||||
ERM_3D, // 3d rendering mode
|
||||
ERM_STENCIL_FILL, // stencil fill mode
|
||||
ERM_SHADOW_VOLUME_ZFAIL, // stencil volume draw mode
|
||||
ERM_SHADOW_VOLUME_ZPASS // stencil volume draw mode
|
||||
};
|
||||
|
||||
//! sets right vertex shader
|
||||
void setVertexShader(video::E_VERTEX_TYPE newType);
|
||||
|
||||
//! sets the needed renderstates
|
||||
bool setRenderStates3DMode();
|
||||
|
||||
//! sets the needed renderstates
|
||||
void setRenderStates2DMode(bool alpha, bool texture, bool alphaChannel);
|
||||
|
||||
//! sets the needed renderstates
|
||||
void setRenderStatesStencilFillMode(bool alpha);
|
||||
|
||||
//! sets the needed renderstates
|
||||
void setRenderStatesStencilShadowMode(bool zfail, u32 debugDataVisible);
|
||||
|
||||
//! sets the current Texture
|
||||
bool setActiveTexture(u32 stage, const video::ITexture* texture);
|
||||
|
||||
//! resets the device
|
||||
bool reset();
|
||||
|
||||
//! returns a device dependent texture from a software surface (IImage)
|
||||
//! THIS METHOD HAS TO BE OVERRIDDEN BY DERIVED DRIVERS WITH OWN TEXTURES
|
||||
virtual video::ITexture* createDeviceDependentTexture(IImage* surface, const io::path& name, void* mipmapData=0);
|
||||
|
||||
//! returns the current size of the screen or rendertarget
|
||||
virtual const core::dimension2d<u32>& getCurrentRenderTargetSize() const;
|
||||
|
||||
//! Check if a proper depth buffer for the RTT is available, otherwise create it.
|
||||
void checkDepthBuffer(ITexture* tex);
|
||||
|
||||
//! Adds a new material renderer to the VideoDriver, using pixel and/or
|
||||
//! vertex shaders to render geometry.
|
||||
s32 addShaderMaterial(const c8* vertexShaderProgram, const c8* pixelShaderProgram,
|
||||
IShaderConstantSetCallBack* callback,
|
||||
E_MATERIAL_TYPE baseMaterial, s32 userData);
|
||||
|
||||
//! Adds a new material renderer to the VideoDriver, based on a high level shading
|
||||
//! language.
|
||||
virtual s32 addHighLevelShaderMaterial(
|
||||
const c8* vertexShaderProgram,
|
||||
const c8* vertexShaderEntryPointName,
|
||||
E_VERTEX_SHADER_TYPE vsCompileTarget,
|
||||
const c8* pixelShaderProgram,
|
||||
const c8* pixelShaderEntryPointName,
|
||||
E_PIXEL_SHADER_TYPE psCompileTarget,
|
||||
const c8* geometryShaderProgram,
|
||||
const c8* geometryShaderEntryPointName = "main",
|
||||
E_GEOMETRY_SHADER_TYPE gsCompileTarget = EGST_GS_4_0,
|
||||
scene::E_PRIMITIVE_TYPE inType = scene::EPT_TRIANGLES,
|
||||
scene::E_PRIMITIVE_TYPE outType = scene::EPT_TRIANGLE_STRIP,
|
||||
u32 verticesOut = 0,
|
||||
IShaderConstantSetCallBack* callback = 0,
|
||||
E_MATERIAL_TYPE baseMaterial = video::EMT_SOLID,
|
||||
s32 userData = 0,
|
||||
E_GPU_SHADING_LANGUAGE shadingLang = EGSL_DEFAULT);
|
||||
|
||||
void createMaterialRenderers();
|
||||
|
||||
void draw2D3DVertexPrimitiveList(const void* vertices,
|
||||
u32 vertexCount, const void* indexList, u32 primitiveCount,
|
||||
E_VERTEX_TYPE vType, scene::E_PRIMITIVE_TYPE pType,
|
||||
E_INDEX_TYPE iType, bool is3D);
|
||||
|
||||
D3DTEXTUREADDRESS getTextureWrapMode(const u8 clamp);
|
||||
|
||||
inline D3DCOLORVALUE colorToD3D(const SColor& col)
|
||||
{
|
||||
const f32 f = 1.0f / 255.0f;
|
||||
D3DCOLORVALUE v;
|
||||
v.r = col.getRed() * f;
|
||||
v.g = col.getGreen() * f;
|
||||
v.b = col.getBlue() * f;
|
||||
v.a = col.getAlpha() * f;
|
||||
return v;
|
||||
}
|
||||
|
||||
E_RENDER_MODE CurrentRenderMode;
|
||||
D3DPRESENT_PARAMETERS present;
|
||||
|
||||
SMaterial Material, LastMaterial;
|
||||
bool ResetRenderStates; // bool to make all renderstates be reseted if set.
|
||||
bool Transformation3DChanged;
|
||||
const ITexture* CurrentTexture[MATERIAL_MAX_TEXTURES];
|
||||
bool LastTextureMipMapsAvailable[MATERIAL_MAX_TEXTURES];
|
||||
core::matrix4 Matrices[ETS_COUNT]; // matrizes of the 3d mode we need to restore when we switch back from the 2d mode.
|
||||
|
||||
HINSTANCE D3DLibrary;
|
||||
IDirect3D9* pID3D;
|
||||
IDirect3DDevice9* pID3DDevice;
|
||||
|
||||
IDirect3DSurface9* PrevRenderTarget;
|
||||
core::dimension2d<u32> CurrentRendertargetSize;
|
||||
|
||||
HWND WindowId;
|
||||
core::rect<s32>* SceneSourceRect;
|
||||
|
||||
D3DCAPS9 Caps;
|
||||
|
||||
SIrrlichtCreationParameters Params;
|
||||
|
||||
E_VERTEX_TYPE LastVertexType;
|
||||
|
||||
SColorf AmbientLight;
|
||||
|
||||
core::stringc VendorName;
|
||||
u16 VendorID;
|
||||
|
||||
core::array<SDepthSurface*> DepthBuffers;
|
||||
|
||||
u32 MaxTextureUnits;
|
||||
u32 MaxUserClipPlanes;
|
||||
u32 MaxMRTs;
|
||||
u32 NumSetMRTs;
|
||||
f32 MaxLightDistance;
|
||||
s32 LastSetLight;
|
||||
|
||||
enum E_CACHE_2D_ATTRIBUTES
|
||||
{
|
||||
EC2D_ALPHA = 0x1,
|
||||
EC2D_TEXTURE = 0x2,
|
||||
EC2D_ALPHA_CHANNEL = 0x4
|
||||
};
|
||||
|
||||
ECOLOR_FORMAT ColorFormat;
|
||||
D3DFORMAT D3DColorFormat;
|
||||
bool DeviceLost;
|
||||
bool DriverWasReset;
|
||||
bool OcclusionQuerySupport;
|
||||
bool AlphaToCoverageSupport;
|
||||
|
||||
#ifdef _IRR_COMPILE_WITH_CG_
|
||||
CGcontext CgContext;
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
} // end namespace video
|
||||
} // end namespace irr
|
||||
|
||||
|
||||
#endif // _IRR_COMPILE_WITH_DIRECT3D_9_
|
||||
#endif // __C_VIDEO_DIRECTX_9_H_INCLUDED__
|
||||
|
428
source/Irrlicht/CD3D9HLSLMaterialRenderer.cpp
Normal file
428
source/Irrlicht/CD3D9HLSLMaterialRenderer.cpp
Normal file
@ -0,0 +1,428 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#include "IrrCompileConfig.h"
|
||||
#ifdef _IRR_COMPILE_WITH_DIRECT3D_9_
|
||||
|
||||
#include "CD3D9HLSLMaterialRenderer.h"
|
||||
#include "IShaderConstantSetCallBack.h"
|
||||
#include "IVideoDriver.h"
|
||||
#include "os.h"
|
||||
#include "irrString.h"
|
||||
|
||||
#ifndef _IRR_D3D_NO_SHADER_DEBUGGING
|
||||
#include <stdio.h>
|
||||
#endif
|
||||
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace video
|
||||
{
|
||||
|
||||
|
||||
//! Public constructor
|
||||
CD3D9HLSLMaterialRenderer::CD3D9HLSLMaterialRenderer(IDirect3DDevice9* d3ddev,
|
||||
video::IVideoDriver* driver, s32& outMaterialTypeNr,
|
||||
const c8* vertexShaderProgram,
|
||||
const c8* vertexShaderEntryPointName,
|
||||
E_VERTEX_SHADER_TYPE vsCompileTarget,
|
||||
const c8* pixelShaderProgram,
|
||||
const c8* pixelShaderEntryPointName,
|
||||
E_PIXEL_SHADER_TYPE psCompileTarget,
|
||||
IShaderConstantSetCallBack* callback,
|
||||
IMaterialRenderer* baseMaterial,
|
||||
s32 userData)
|
||||
: CD3D9ShaderMaterialRenderer(d3ddev, driver, callback, baseMaterial, userData),
|
||||
VSConstantsTable(0), PSConstantsTable(0)
|
||||
{
|
||||
|
||||
#ifdef _DEBUG
|
||||
setDebugName("CD3D9HLSLMaterialRenderer");
|
||||
#endif
|
||||
|
||||
outMaterialTypeNr = -1;
|
||||
|
||||
// now create shaders
|
||||
|
||||
if (vsCompileTarget < 0 || vsCompileTarget > EVST_COUNT)
|
||||
{
|
||||
os::Printer::log("Invalid HLSL vertex shader compilation target", ELL_ERROR);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!createHLSLVertexShader(vertexShaderProgram,
|
||||
vertexShaderEntryPointName, VERTEX_SHADER_TYPE_NAMES[vsCompileTarget]))
|
||||
return;
|
||||
|
||||
if (!createHLSLPixelShader(pixelShaderProgram,
|
||||
pixelShaderEntryPointName, PIXEL_SHADER_TYPE_NAMES[psCompileTarget]))
|
||||
return;
|
||||
|
||||
// register myself as new material
|
||||
outMaterialTypeNr = Driver->addMaterialRenderer(this);
|
||||
}
|
||||
|
||||
|
||||
//! Destructor
|
||||
CD3D9HLSLMaterialRenderer::~CD3D9HLSLMaterialRenderer()
|
||||
{
|
||||
if (VSConstantsTable)
|
||||
VSConstantsTable->Release();
|
||||
|
||||
if (PSConstantsTable)
|
||||
PSConstantsTable->Release();
|
||||
}
|
||||
|
||||
|
||||
bool CD3D9HLSLMaterialRenderer::createHLSLVertexShader(const char* vertexShaderProgram,
|
||||
const char* shaderEntryPointName,
|
||||
const char* shaderTargetName)
|
||||
{
|
||||
if (!vertexShaderProgram)
|
||||
return true;
|
||||
|
||||
LPD3DXBUFFER buffer = 0;
|
||||
LPD3DXBUFFER errors = 0;
|
||||
|
||||
#ifdef _IRR_D3D_NO_SHADER_DEBUGGING
|
||||
|
||||
// compile without debug info
|
||||
HRESULT h = stubD3DXCompileShader(
|
||||
vertexShaderProgram,
|
||||
strlen(vertexShaderProgram),
|
||||
0, // macros
|
||||
0, // no includes
|
||||
shaderEntryPointName,
|
||||
shaderTargetName,
|
||||
0, // no flags
|
||||
&buffer,
|
||||
&errors,
|
||||
&VSConstantsTable);
|
||||
|
||||
#else
|
||||
|
||||
// compile shader and emitt some debug informations to
|
||||
// make it possible to debug the shader in visual studio
|
||||
|
||||
static int irr_dbg_hlsl_file_nr = 0;
|
||||
++irr_dbg_hlsl_file_nr;
|
||||
char tmp[32];
|
||||
sprintf(tmp, "irr_d3d9_dbg_hlsl_%d.vsh", irr_dbg_hlsl_file_nr);
|
||||
|
||||
FILE* f = fopen(tmp, "wb");
|
||||
fwrite(vertexShaderProgram, strlen(vertexShaderProgram), 1, f);
|
||||
fflush(f);
|
||||
fclose(f);
|
||||
|
||||
HRESULT h = stubD3DXCompileShaderFromFile(
|
||||
tmp,
|
||||
0, // macros
|
||||
0, // no includes
|
||||
shaderEntryPointName,
|
||||
shaderTargetName,
|
||||
D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION,
|
||||
&buffer,
|
||||
&errors,
|
||||
&VSConstantsTable);
|
||||
|
||||
#endif
|
||||
|
||||
if (FAILED(h))
|
||||
{
|
||||
os::Printer::log("HLSL vertex shader compilation failed:", ELL_ERROR);
|
||||
if (errors)
|
||||
{
|
||||
os::Printer::log((c8*)errors->GetBufferPointer(), ELL_ERROR);
|
||||
errors->Release();
|
||||
if (buffer)
|
||||
buffer->Release();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
if (errors)
|
||||
errors->Release();
|
||||
|
||||
if (buffer)
|
||||
{
|
||||
if (FAILED(pID3DDevice->CreateVertexShader((DWORD*)buffer->GetBufferPointer(),
|
||||
&VertexShader)))
|
||||
{
|
||||
os::Printer::log("Could not create hlsl vertex shader.", ELL_ERROR);
|
||||
buffer->Release();
|
||||
return false;
|
||||
}
|
||||
|
||||
buffer->Release();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool CD3D9HLSLMaterialRenderer::createHLSLPixelShader(const char* pixelShaderProgram,
|
||||
const char* shaderEntryPointName,
|
||||
const char* shaderTargetName)
|
||||
{
|
||||
if (!pixelShaderProgram)
|
||||
return true;
|
||||
|
||||
LPD3DXBUFFER buffer = 0;
|
||||
LPD3DXBUFFER errors = 0;
|
||||
|
||||
DWORD flags = 0;
|
||||
|
||||
#ifdef D3DXSHADER_ENABLE_BACKWARDS_COMPATIBILITY
|
||||
if (Driver->queryFeature(video::EVDF_VERTEX_SHADER_2_0) || Driver->queryFeature(video::EVDF_VERTEX_SHADER_3_0))
|
||||
// this one's for newer DX SDKs which don't support ps_1_x anymore
|
||||
// instead they'll silently compile 1_x as 2_x when using this flag
|
||||
flags |= D3DXSHADER_ENABLE_BACKWARDS_COMPATIBILITY;
|
||||
#endif
|
||||
#if defined(_IRR_D3D_USE_LEGACY_HLSL_COMPILER) && defined(D3DXSHADER_USE_LEGACY_D3DX9_31_DLL)
|
||||
#ifdef D3DXSHADER_ENABLE_BACKWARDS_COMPATIBILITY
|
||||
else
|
||||
#endif
|
||||
flags |= D3DXSHADER_USE_LEGACY_D3DX9_31_DLL;
|
||||
#endif
|
||||
|
||||
#ifdef _IRR_D3D_NO_SHADER_DEBUGGING
|
||||
|
||||
// compile without debug info
|
||||
HRESULT h = stubD3DXCompileShader(
|
||||
pixelShaderProgram,
|
||||
strlen(pixelShaderProgram),
|
||||
0, // macros
|
||||
0, // no includes
|
||||
shaderEntryPointName,
|
||||
shaderTargetName,
|
||||
flags,
|
||||
&buffer,
|
||||
&errors,
|
||||
&PSConstantsTable);
|
||||
|
||||
#else
|
||||
|
||||
// compile shader and emitt some debug informations to
|
||||
// make it possible to debug the shader in visual studio
|
||||
|
||||
static int irr_dbg_hlsl_file_nr = 0;
|
||||
++irr_dbg_hlsl_file_nr;
|
||||
char tmp[32];
|
||||
sprintf(tmp, "irr_d3d9_dbg_hlsl_%d.psh", irr_dbg_hlsl_file_nr);
|
||||
|
||||
FILE* f = fopen(tmp, "wb");
|
||||
fwrite(pixelShaderProgram, strlen(pixelShaderProgram), 1, f);
|
||||
fflush(f);
|
||||
fclose(f);
|
||||
|
||||
HRESULT h = stubD3DXCompileShaderFromFile(
|
||||
tmp,
|
||||
0, // macros
|
||||
0, // no includes
|
||||
shaderEntryPointName,
|
||||
shaderTargetName,
|
||||
flags | D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION,
|
||||
&buffer,
|
||||
&errors,
|
||||
&PSConstantsTable);
|
||||
|
||||
#endif
|
||||
|
||||
if (FAILED(h))
|
||||
{
|
||||
os::Printer::log("HLSL pixel shader compilation failed:", ELL_ERROR);
|
||||
if (errors)
|
||||
{
|
||||
os::Printer::log((c8*)errors->GetBufferPointer(), ELL_ERROR);
|
||||
errors->Release();
|
||||
if (buffer)
|
||||
buffer->Release();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
if (errors)
|
||||
errors->Release();
|
||||
|
||||
if (buffer)
|
||||
{
|
||||
if (FAILED(pID3DDevice->CreatePixelShader((DWORD*)buffer->GetBufferPointer(),
|
||||
&PixelShader)))
|
||||
{
|
||||
os::Printer::log("Could not create hlsl pixel shader.", ELL_ERROR);
|
||||
buffer->Release();
|
||||
return false;
|
||||
}
|
||||
|
||||
buffer->Release();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool CD3D9HLSLMaterialRenderer::setVariable(bool vertexShader, const c8* name,
|
||||
const f32* floats, int count)
|
||||
{
|
||||
LPD3DXCONSTANTTABLE tbl = vertexShader ? VSConstantsTable : PSConstantsTable;
|
||||
if (!tbl)
|
||||
return false;
|
||||
|
||||
// currently we only support top level parameters.
|
||||
// Should be enough for the beginning. (TODO)
|
||||
|
||||
D3DXHANDLE hndl = tbl->GetConstantByName(NULL, name);
|
||||
if (!hndl)
|
||||
{
|
||||
core::stringc s = "HLSL Variable to set not found: '";
|
||||
s += name;
|
||||
s += "'. Available variables are:";
|
||||
os::Printer::log(s.c_str(), ELL_WARNING);
|
||||
printHLSLVariables(tbl);
|
||||
return false;
|
||||
}
|
||||
|
||||
D3DXCONSTANT_DESC Description;
|
||||
UINT ucount = 1;
|
||||
tbl->GetConstantDesc(hndl, &Description, &ucount);
|
||||
|
||||
if(Description.RegisterSet != D3DXRS_SAMPLER)
|
||||
{
|
||||
HRESULT hr = tbl->SetFloatArray(pID3DDevice, hndl, floats, count);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
os::Printer::log("Error setting float array for HLSL variable", ELL_WARNING);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool CD3D9HLSLMaterialRenderer::setVariable(bool vertexShader, const c8* name,
|
||||
const bool* bools, int count)
|
||||
{
|
||||
LPD3DXCONSTANTTABLE tbl = vertexShader ? VSConstantsTable : PSConstantsTable;
|
||||
if (!tbl)
|
||||
return false;
|
||||
|
||||
// currently we only support top level parameters.
|
||||
// Should be enough for the beginning. (TODO)
|
||||
|
||||
D3DXHANDLE hndl = tbl->GetConstantByName(NULL, name);
|
||||
if (!hndl)
|
||||
{
|
||||
core::stringc s = "HLSL Variable to set not found: '";
|
||||
s += name;
|
||||
s += "'. Available variables are:";
|
||||
os::Printer::log(s.c_str(), ELL_WARNING);
|
||||
printHLSLVariables(tbl);
|
||||
return false;
|
||||
}
|
||||
|
||||
D3DXCONSTANT_DESC Description;
|
||||
UINT ucount = 1;
|
||||
tbl->GetConstantDesc(hndl, &Description, &ucount);
|
||||
|
||||
if(Description.RegisterSet != D3DXRS_SAMPLER)
|
||||
{
|
||||
HRESULT hr = tbl->SetBoolArray(pID3DDevice, hndl, (BOOL*)bools, count);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
os::Printer::log("Error setting bool array for HLSL variable", ELL_WARNING);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool CD3D9HLSLMaterialRenderer::setVariable(bool vertexShader, const c8* name,
|
||||
const s32* ints, int count)
|
||||
{
|
||||
LPD3DXCONSTANTTABLE tbl = vertexShader ? VSConstantsTable : PSConstantsTable;
|
||||
if (!tbl)
|
||||
return false;
|
||||
|
||||
// currently we only support top level parameters.
|
||||
// Should be enough for the beginning. (TODO)
|
||||
|
||||
D3DXHANDLE hndl = tbl->GetConstantByName(NULL, name);
|
||||
if (!hndl)
|
||||
{
|
||||
core::stringc s = "HLSL Variable to set not found: '";
|
||||
s += name;
|
||||
s += "'. Available variables are:";
|
||||
os::Printer::log(s.c_str(), ELL_WARNING);
|
||||
printHLSLVariables(tbl);
|
||||
return false;
|
||||
}
|
||||
|
||||
D3DXCONSTANT_DESC Description;
|
||||
UINT ucount = 1;
|
||||
tbl->GetConstantDesc(hndl, &Description, &ucount);
|
||||
|
||||
if(Description.RegisterSet != D3DXRS_SAMPLER)
|
||||
{
|
||||
HRESULT hr = tbl->SetIntArray(pID3DDevice, hndl, ints, count);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
os::Printer::log("Error setting int array for HLSL variable", ELL_WARNING);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool CD3D9HLSLMaterialRenderer::OnRender(IMaterialRendererServices* service, E_VERTEX_TYPE vtxtype)
|
||||
{
|
||||
if (VSConstantsTable)
|
||||
VSConstantsTable->SetDefaults(pID3DDevice);
|
||||
|
||||
return CD3D9ShaderMaterialRenderer::OnRender(service, vtxtype);
|
||||
}
|
||||
|
||||
|
||||
void CD3D9HLSLMaterialRenderer::printHLSLVariables(LPD3DXCONSTANTTABLE table)
|
||||
{
|
||||
// currently we only support top level parameters.
|
||||
// Should be enough for the beginning. (TODO)
|
||||
|
||||
// print out constant names
|
||||
D3DXCONSTANTTABLE_DESC tblDesc;
|
||||
HRESULT hr = table->GetDesc(&tblDesc);
|
||||
if (!FAILED(hr))
|
||||
{
|
||||
for (int i=0; i<(int)tblDesc.Constants; ++i)
|
||||
{
|
||||
D3DXCONSTANT_DESC d;
|
||||
UINT n = 1;
|
||||
D3DXHANDLE cHndl = table->GetConstant(NULL, i);
|
||||
if (!FAILED(table->GetConstantDesc(cHndl, &d, &n)))
|
||||
{
|
||||
core::stringc s = " '";
|
||||
s += d.Name;
|
||||
s += "' Registers:[begin:";
|
||||
s += (int)d.RegisterIndex;
|
||||
s += ", count:";
|
||||
s += (int)d.RegisterCount;
|
||||
s += "]";
|
||||
os::Printer::log(s.c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
} // end namespace video
|
||||
} // end namespace irr
|
||||
|
||||
#endif // _IRR_COMPILE_WITH_DIRECT3D_9_
|
85
source/Irrlicht/CD3D9HLSLMaterialRenderer.h
Normal file
85
source/Irrlicht/CD3D9HLSLMaterialRenderer.h
Normal file
@ -0,0 +1,85 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#ifndef __C_D3D9_HLSL_MATERIAL_RENDERER_H_INCLUDED__
|
||||
#define __C_D3D9_HLSL_MATERIAL_RENDERER_H_INCLUDED__
|
||||
|
||||
#include "IrrCompileConfig.h"
|
||||
#ifdef _IRR_WINDOWS_
|
||||
|
||||
#ifdef _IRR_COMPILE_WITH_DIRECT3D_9_
|
||||
|
||||
#include "CD3D9ShaderMaterialRenderer.h"
|
||||
#include "IGPUProgrammingServices.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace video
|
||||
{
|
||||
|
||||
class IVideoDriver;
|
||||
class IShaderConstantSetCallBack;
|
||||
class IMaterialRenderer;
|
||||
|
||||
//! Class for using vertex and pixel shaders via HLSL with D3D9
|
||||
class CD3D9HLSLMaterialRenderer : public CD3D9ShaderMaterialRenderer
|
||||
{
|
||||
public:
|
||||
|
||||
//! Public constructor
|
||||
CD3D9HLSLMaterialRenderer(IDirect3DDevice9* d3ddev, video::IVideoDriver* driver,
|
||||
s32& outMaterialTypeNr,
|
||||
const c8* vertexShaderProgram,
|
||||
const c8* vertexShaderEntryPointName,
|
||||
E_VERTEX_SHADER_TYPE vsCompileTarget,
|
||||
const c8* pixelShaderProgram,
|
||||
const c8* pixelShaderEntryPointName,
|
||||
E_PIXEL_SHADER_TYPE psCompileTarget,
|
||||
IShaderConstantSetCallBack* callback,
|
||||
IMaterialRenderer* baseMaterial,
|
||||
s32 userData);
|
||||
|
||||
//! Destructor
|
||||
~CD3D9HLSLMaterialRenderer();
|
||||
|
||||
//! sets a variable in the shader.
|
||||
//! \param vertexShader: True if this should be set in the vertex shader, false if
|
||||
//! in the pixel shader.
|
||||
//! \param name: Name of the variable
|
||||
//! \param floats: Pointer to array of floats
|
||||
//! \param count: Amount of floats in array.
|
||||
virtual bool setVariable(bool vertexShader, const c8* name, const f32* floats, int count);
|
||||
|
||||
//! Bool interface for the above.
|
||||
virtual bool setVariable(bool vertexShader, const c8* name, const bool* bools, int count);
|
||||
|
||||
//! Int interface for the above.
|
||||
virtual bool setVariable(bool vertexShader, const c8* name, const s32* ints, int count);
|
||||
|
||||
bool OnRender(IMaterialRendererServices* service, E_VERTEX_TYPE vtxtype);
|
||||
|
||||
protected:
|
||||
|
||||
bool createHLSLVertexShader(const char* vertexShaderProgram,
|
||||
const char* shaderEntryPointName,
|
||||
const char* shaderTargetName);
|
||||
|
||||
bool createHLSLPixelShader(const char* pixelShaderProgram,
|
||||
const char* shaderEntryPointName,
|
||||
const char* shaderTargetName);
|
||||
|
||||
void printHLSLVariables(LPD3DXCONSTANTTABLE table);
|
||||
|
||||
LPD3DXCONSTANTTABLE VSConstantsTable;
|
||||
LPD3DXCONSTANTTABLE PSConstantsTable;
|
||||
};
|
||||
|
||||
|
||||
} // end namespace video
|
||||
} // end namespace irr
|
||||
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
615
source/Irrlicht/CD3D9MaterialRenderer.h
Normal file
615
source/Irrlicht/CD3D9MaterialRenderer.h
Normal file
@ -0,0 +1,615 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#ifndef __C_D3D9_MATERIAL_RENDERER_H_INCLUDED__
|
||||
#define __C_D3D9_MATERIAL_RENDERER_H_INCLUDED__
|
||||
|
||||
#include "IrrCompileConfig.h"
|
||||
#ifdef _IRR_WINDOWS_
|
||||
|
||||
#ifdef _IRR_COMPILE_WITH_DIRECT3D_9_
|
||||
#if defined(__BORLANDC__) || defined (__BCPLUSPLUS__)
|
||||
#include "irrMath.h" // needed by borland for sqrtf define
|
||||
#endif
|
||||
#include <d3d9.h>
|
||||
|
||||
#include "IMaterialRenderer.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace video
|
||||
{
|
||||
|
||||
namespace
|
||||
{
|
||||
D3DMATRIX UnitMatrixD3D9;
|
||||
D3DMATRIX SphereMapMatrixD3D9;
|
||||
inline void setTextureColorStage(IDirect3DDevice9* dev, DWORD i,
|
||||
DWORD arg1, DWORD op, DWORD arg2)
|
||||
{
|
||||
dev->SetTextureStageState(i, D3DTSS_COLOROP, op);
|
||||
dev->SetTextureStageState(i, D3DTSS_COLORARG1, arg1);
|
||||
dev->SetTextureStageState(i, D3DTSS_COLORARG2, arg2);
|
||||
}
|
||||
inline void setTextureColorStage(IDirect3DDevice9* dev, DWORD i, DWORD arg1)
|
||||
{
|
||||
dev->SetTextureStageState(i, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
|
||||
dev->SetTextureStageState(i, D3DTSS_COLORARG1, arg1);
|
||||
}
|
||||
|
||||
inline void setTextureAlphaStage(IDirect3DDevice9* dev, DWORD i,
|
||||
DWORD arg1, DWORD op, DWORD arg2)
|
||||
{
|
||||
dev->SetTextureStageState(i, D3DTSS_ALPHAOP, op);
|
||||
dev->SetTextureStageState(i, D3DTSS_ALPHAARG1, arg1);
|
||||
dev->SetTextureStageState(i, D3DTSS_ALPHAARG2, arg2);
|
||||
}
|
||||
inline void setTextureAlphaStage(IDirect3DDevice9* dev, DWORD i, DWORD arg1)
|
||||
{
|
||||
dev->SetTextureStageState(i, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
|
||||
dev->SetTextureStageState(i, D3DTSS_ALPHAARG1, arg1);
|
||||
}
|
||||
} // anonymous namespace
|
||||
|
||||
//! Base class for all internal D3D9 material renderers
|
||||
class CD3D9MaterialRenderer : public IMaterialRenderer
|
||||
{
|
||||
public:
|
||||
|
||||
//! Constructor
|
||||
CD3D9MaterialRenderer(IDirect3DDevice9* d3ddev, video::IVideoDriver* driver)
|
||||
: pID3DDevice(d3ddev), Driver(driver)
|
||||
{
|
||||
}
|
||||
|
||||
//! sets a variable in the shader.
|
||||
//! \param vertexShader: True if this should be set in the vertex shader, false if
|
||||
//! in the pixel shader.
|
||||
//! \param name: Name of the variable
|
||||
//! \param floats: Pointer to array of floats
|
||||
//! \param count: Amount of floats in array.
|
||||
virtual bool setVariable(bool vertexShader, const c8* name, const f32* floats, int count)
|
||||
{
|
||||
os::Printer::log("Invalid material to set variable in.");
|
||||
return false;
|
||||
}
|
||||
|
||||
//! Bool interface for the above.
|
||||
virtual bool setVariable(bool vertexShader, const c8* name, const bool* bools, int count)
|
||||
{
|
||||
os::Printer::log("Invalid material to set variable in.");
|
||||
return false;
|
||||
}
|
||||
|
||||
//! Int interface for the above.
|
||||
virtual bool setVariable(bool vertexShader, const c8* name, const s32* ints, int count)
|
||||
{
|
||||
os::Printer::log("Invalid material to set variable in.");
|
||||
return false;
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
IDirect3DDevice9* pID3DDevice;
|
||||
video::IVideoDriver* Driver;
|
||||
};
|
||||
|
||||
|
||||
//! Solid material renderer
|
||||
class CD3D9MaterialRenderer_SOLID : public CD3D9MaterialRenderer
|
||||
{
|
||||
public:
|
||||
|
||||
CD3D9MaterialRenderer_SOLID(IDirect3DDevice9* p, video::IVideoDriver* d)
|
||||
: CD3D9MaterialRenderer(p, d) {}
|
||||
|
||||
virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial,
|
||||
bool resetAllRenderstates, IMaterialRendererServices* services)
|
||||
{
|
||||
services->setBasicRenderStates(material, lastMaterial, resetAllRenderstates);
|
||||
|
||||
if (material.MaterialType != lastMaterial.MaterialType || resetAllRenderstates)
|
||||
{
|
||||
setTextureColorStage(pID3DDevice, 0,
|
||||
D3DTA_TEXTURE, D3DTOP_MODULATE, D3DTA_DIFFUSE);
|
||||
}
|
||||
|
||||
pID3DDevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE);
|
||||
pID3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
|
||||
}
|
||||
};
|
||||
|
||||
//! Generic Texture Blend
|
||||
class CD3D9MaterialRenderer_ONETEXTURE_BLEND : public CD3D9MaterialRenderer
|
||||
{
|
||||
public:
|
||||
|
||||
CD3D9MaterialRenderer_ONETEXTURE_BLEND(IDirect3DDevice9* p, video::IVideoDriver* d)
|
||||
: CD3D9MaterialRenderer(p, d) {}
|
||||
|
||||
virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial,
|
||||
bool resetAllRenderstates, IMaterialRendererServices* services)
|
||||
{
|
||||
services->setBasicRenderStates(material, lastMaterial, resetAllRenderstates);
|
||||
|
||||
if (material.MaterialType != lastMaterial.MaterialType ||
|
||||
material.MaterialTypeParam != lastMaterial.MaterialTypeParam ||
|
||||
resetAllRenderstates)
|
||||
{
|
||||
|
||||
E_BLEND_FACTOR srcFact,dstFact;
|
||||
E_MODULATE_FUNC modulate;
|
||||
u32 alphaSource;
|
||||
unpack_textureBlendFunc ( srcFact, dstFact, modulate, alphaSource, material.MaterialTypeParam );
|
||||
|
||||
if (srcFact == EBF_SRC_COLOR && dstFact == EBF_ZERO)
|
||||
{
|
||||
pID3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
|
||||
}
|
||||
else
|
||||
{
|
||||
pID3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
|
||||
pID3DDevice->SetRenderState(D3DRS_SRCBLEND, getD3DBlend ( srcFact ) );
|
||||
pID3DDevice->SetRenderState(D3DRS_DESTBLEND, getD3DBlend ( dstFact ) );
|
||||
}
|
||||
|
||||
setTextureColorStage(pID3DDevice, 0,
|
||||
D3DTA_TEXTURE, getD3DModulate(modulate), D3DTA_DIFFUSE);
|
||||
|
||||
if ( textureBlendFunc_hasAlpha ( srcFact ) || textureBlendFunc_hasAlpha ( dstFact ) )
|
||||
{
|
||||
if (alphaSource==EAS_VERTEX_COLOR)
|
||||
{
|
||||
setTextureAlphaStage(pID3DDevice, 0, D3DTA_DIFFUSE);
|
||||
}
|
||||
else if (alphaSource==EAS_TEXTURE)
|
||||
{
|
||||
setTextureAlphaStage(pID3DDevice, 0, D3DTA_TEXTURE);
|
||||
}
|
||||
else
|
||||
{
|
||||
setTextureAlphaStage(pID3DDevice, 0,
|
||||
D3DTA_TEXTURE, D3DTOP_MODULATE, D3DTA_DIFFUSE);
|
||||
}
|
||||
}
|
||||
|
||||
pID3DDevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
//! Returns if the material is transparent.
|
||||
/** The scene management needs to know this for being able to sort the
|
||||
materials by opaque and transparent.
|
||||
The return value could be optimized, but we'd need to know the
|
||||
MaterialTypeParam for it. */
|
||||
virtual bool isTransparent() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
u32 getD3DBlend ( E_BLEND_FACTOR factor ) const
|
||||
{
|
||||
u32 r = 0;
|
||||
switch ( factor )
|
||||
{
|
||||
case EBF_ZERO: r = D3DBLEND_ZERO; break;
|
||||
case EBF_ONE: r = D3DBLEND_ONE; break;
|
||||
case EBF_DST_COLOR: r = D3DBLEND_DESTCOLOR; break;
|
||||
case EBF_ONE_MINUS_DST_COLOR: r = D3DBLEND_INVDESTCOLOR; break;
|
||||
case EBF_SRC_COLOR: r = D3DBLEND_SRCCOLOR; break;
|
||||
case EBF_ONE_MINUS_SRC_COLOR: r = D3DBLEND_INVSRCCOLOR; break;
|
||||
case EBF_SRC_ALPHA: r = D3DBLEND_SRCALPHA; break;
|
||||
case EBF_ONE_MINUS_SRC_ALPHA: r = D3DBLEND_INVSRCALPHA; break;
|
||||
case EBF_DST_ALPHA: r = D3DBLEND_DESTALPHA; break;
|
||||
case EBF_ONE_MINUS_DST_ALPHA: r = D3DBLEND_INVDESTALPHA; break;
|
||||
case EBF_SRC_ALPHA_SATURATE: r = D3DBLEND_SRCALPHASAT; break;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
u32 getD3DModulate ( E_MODULATE_FUNC func ) const
|
||||
{
|
||||
u32 r = D3DTOP_MODULATE;
|
||||
switch ( func )
|
||||
{
|
||||
case EMFN_MODULATE_1X: r = D3DTOP_MODULATE; break;
|
||||
case EMFN_MODULATE_2X: r = D3DTOP_MODULATE2X; break;
|
||||
case EMFN_MODULATE_4X: r = D3DTOP_MODULATE4X; break;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
bool transparent;
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
//! Solid 2 layer material renderer
|
||||
class CD3D9MaterialRenderer_SOLID_2_LAYER : public CD3D9MaterialRenderer
|
||||
{
|
||||
public:
|
||||
|
||||
CD3D9MaterialRenderer_SOLID_2_LAYER(IDirect3DDevice9* p, video::IVideoDriver* d)
|
||||
: CD3D9MaterialRenderer(p, d) {}
|
||||
|
||||
virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial,
|
||||
bool resetAllRenderstates, IMaterialRendererServices* services)
|
||||
{
|
||||
services->setBasicRenderStates(material, lastMaterial, resetAllRenderstates);
|
||||
|
||||
if (material.MaterialType != lastMaterial.MaterialType || resetAllRenderstates)
|
||||
{
|
||||
setTextureColorStage(pID3DDevice, 0, D3DTA_TEXTURE);
|
||||
|
||||
pID3DDevice->SetTextureStageState(1, D3DTSS_TEXCOORDINDEX, 0);
|
||||
pID3DDevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_BLENDDIFFUSEALPHA);
|
||||
|
||||
pID3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//! Transparent add color material renderer
|
||||
class CD3D9MaterialRenderer_TRANSPARENT_ADD_COLOR : public CD3D9MaterialRenderer
|
||||
{
|
||||
public:
|
||||
|
||||
CD3D9MaterialRenderer_TRANSPARENT_ADD_COLOR(IDirect3DDevice9* p, video::IVideoDriver* d)
|
||||
: CD3D9MaterialRenderer(p, d) {}
|
||||
|
||||
virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial,
|
||||
bool resetAllRenderstates, IMaterialRendererServices* services)
|
||||
{
|
||||
services->setBasicRenderStates(material, lastMaterial, resetAllRenderstates);
|
||||
|
||||
if (material.MaterialType != lastMaterial.MaterialType || resetAllRenderstates)
|
||||
{
|
||||
setTextureColorStage(pID3DDevice, 0,
|
||||
D3DTA_TEXTURE, D3DTOP_MODULATE, D3DTA_DIFFUSE);
|
||||
|
||||
pID3DDevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE);
|
||||
pID3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
|
||||
pID3DDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ONE);
|
||||
pID3DDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCCOLOR);
|
||||
}
|
||||
}
|
||||
|
||||
//! Returns if the material is transparent. The scene management needs to know this
|
||||
//! for being able to sort the materials by opaque and transparent.
|
||||
virtual bool isTransparent() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//! Transparent vertex alpha material renderer
|
||||
class CD3D9MaterialRenderer_TRANSPARENT_VERTEX_ALPHA : public CD3D9MaterialRenderer
|
||||
{
|
||||
public:
|
||||
|
||||
CD3D9MaterialRenderer_TRANSPARENT_VERTEX_ALPHA(IDirect3DDevice9* p, video::IVideoDriver* d)
|
||||
: CD3D9MaterialRenderer(p, d) {}
|
||||
|
||||
virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial,
|
||||
bool resetAllRenderstates, IMaterialRendererServices* services)
|
||||
{
|
||||
services->setBasicRenderStates(material, lastMaterial, resetAllRenderstates);
|
||||
|
||||
if (material.MaterialType != lastMaterial.MaterialType || resetAllRenderstates)
|
||||
{
|
||||
setTextureColorStage(pID3DDevice, 0,
|
||||
D3DTA_TEXTURE, D3DTOP_MODULATE, D3DTA_DIFFUSE);
|
||||
setTextureAlphaStage(pID3DDevice, 0, D3DTA_DIFFUSE);
|
||||
|
||||
pID3DDevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE);
|
||||
pID3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
|
||||
pID3DDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
|
||||
pID3DDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
|
||||
}
|
||||
}
|
||||
|
||||
//! Returns if the material is transparent. The scene managment needs to know this
|
||||
//! for being able to sort the materials by opaque and transparent.
|
||||
virtual bool isTransparent() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//! Transparent alpha channel material renderer
|
||||
class CD3D9MaterialRenderer_TRANSPARENT_ALPHA_CHANNEL : public CD3D9MaterialRenderer
|
||||
{
|
||||
public:
|
||||
|
||||
CD3D9MaterialRenderer_TRANSPARENT_ALPHA_CHANNEL(IDirect3DDevice9* p, video::IVideoDriver* d)
|
||||
: CD3D9MaterialRenderer(p, d) {}
|
||||
|
||||
virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial,
|
||||
bool resetAllRenderstates, IMaterialRendererServices* services)
|
||||
{
|
||||
services->setBasicRenderStates(material, lastMaterial, resetAllRenderstates);
|
||||
|
||||
if (material.MaterialType != lastMaterial.MaterialType || resetAllRenderstates
|
||||
|| material.MaterialTypeParam != lastMaterial.MaterialTypeParam )
|
||||
{
|
||||
setTextureColorStage(pID3DDevice, 0,
|
||||
D3DTA_TEXTURE, D3DTOP_MODULATE, D3DTA_CURRENT);
|
||||
setTextureAlphaStage(pID3DDevice, 0, D3DTA_TEXTURE);
|
||||
|
||||
pID3DDevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE);
|
||||
pID3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
|
||||
pID3DDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
|
||||
pID3DDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA );
|
||||
|
||||
pID3DDevice->SetRenderState(D3DRS_ALPHAREF, core::floor32(material.MaterialTypeParam * 255.f));
|
||||
pID3DDevice->SetRenderState(D3DRS_ALPHAFUNC, D3DCMP_GREATEREQUAL);
|
||||
pID3DDevice->SetRenderState(D3DRS_ALPHATESTENABLE, TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
virtual void OnUnsetMaterial()
|
||||
{
|
||||
pID3DDevice->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE);
|
||||
}
|
||||
|
||||
//! Returns if the material is transparent. The scene managment needs to know this
|
||||
//! for being able to sort the materials by opaque and transparent.
|
||||
virtual bool isTransparent() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
//! Transparent alpha channel material renderer
|
||||
class CD3D9MaterialRenderer_TRANSPARENT_ALPHA_CHANNEL_REF : public CD3D9MaterialRenderer
|
||||
{
|
||||
public:
|
||||
|
||||
CD3D9MaterialRenderer_TRANSPARENT_ALPHA_CHANNEL_REF(IDirect3DDevice9* p, video::IVideoDriver* d)
|
||||
: CD3D9MaterialRenderer(p, d) {}
|
||||
|
||||
virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial,
|
||||
bool resetAllRenderstates, IMaterialRendererServices* services)
|
||||
{
|
||||
services->setBasicRenderStates(material, lastMaterial, resetAllRenderstates);
|
||||
|
||||
if (material.MaterialType != lastMaterial.MaterialType || resetAllRenderstates)
|
||||
{
|
||||
setTextureColorStage(pID3DDevice, 0,
|
||||
D3DTA_TEXTURE, D3DTOP_MODULATE, D3DTA_CURRENT);
|
||||
setTextureAlphaStage(pID3DDevice, 0, D3DTA_TEXTURE);
|
||||
|
||||
pID3DDevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE);
|
||||
|
||||
pID3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
|
||||
|
||||
// 127 is required by EMT_TRANSPARENT_ALPHA_CHANNEL_REF
|
||||
pID3DDevice->SetRenderState(D3DRS_ALPHAREF, 127);
|
||||
pID3DDevice->SetRenderState(D3DRS_ALPHAFUNC, D3DCMP_GREATEREQUAL);
|
||||
pID3DDevice->SetRenderState(D3DRS_ALPHATESTENABLE, TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
virtual void OnUnsetMaterial()
|
||||
{
|
||||
pID3DDevice->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE);
|
||||
}
|
||||
|
||||
//! Returns if the material is transparent. The scene managment needs to know this
|
||||
//! for being able to sort the materials by opaque and transparent.
|
||||
virtual bool isTransparent() const
|
||||
{
|
||||
return false; // this material is not really transparent because it does no blending.
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//! material renderer for all kinds of lightmaps
|
||||
class CD3D9MaterialRenderer_LIGHTMAP : public CD3D9MaterialRenderer
|
||||
{
|
||||
public:
|
||||
|
||||
CD3D9MaterialRenderer_LIGHTMAP(IDirect3DDevice9* p, video::IVideoDriver* d)
|
||||
: CD3D9MaterialRenderer(p, d) {}
|
||||
|
||||
virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial,
|
||||
bool resetAllRenderstates, IMaterialRendererServices* services)
|
||||
{
|
||||
services->setBasicRenderStates(material, lastMaterial, resetAllRenderstates);
|
||||
|
||||
if (material.MaterialType != lastMaterial.MaterialType || resetAllRenderstates)
|
||||
{
|
||||
if (material.MaterialType >= EMT_LIGHTMAP_LIGHTING)
|
||||
{
|
||||
// with lighting
|
||||
setTextureColorStage(pID3DDevice, 0,
|
||||
D3DTA_TEXTURE, D3DTOP_MODULATE, D3DTA_DIFFUSE);
|
||||
}
|
||||
else
|
||||
{
|
||||
setTextureColorStage(pID3DDevice, 0, D3DTA_TEXTURE);
|
||||
}
|
||||
|
||||
pID3DDevice->SetTextureStageState(1, D3DTSS_TEXCOORDINDEX, 1);
|
||||
|
||||
setTextureColorStage(pID3DDevice, 1,
|
||||
D3DTA_TEXTURE,
|
||||
(material.MaterialType == EMT_LIGHTMAP_ADD)?
|
||||
D3DTOP_ADD:
|
||||
(material.MaterialType == EMT_LIGHTMAP_M4 || material.MaterialType == EMT_LIGHTMAP_LIGHTING_M4)?
|
||||
D3DTOP_MODULATE4X:
|
||||
(material.MaterialType == EMT_LIGHTMAP_M2 || material.MaterialType == EMT_LIGHTMAP_LIGHTING_M2)?
|
||||
D3DTOP_MODULATE2X:
|
||||
D3DTOP_MODULATE,
|
||||
D3DTA_CURRENT);
|
||||
|
||||
pID3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
//! material renderer for detail maps
|
||||
class CD3D9MaterialRenderer_DETAIL_MAP : public CD3D9MaterialRenderer
|
||||
{
|
||||
public:
|
||||
|
||||
CD3D9MaterialRenderer_DETAIL_MAP(IDirect3DDevice9* p, video::IVideoDriver* d)
|
||||
: CD3D9MaterialRenderer(p, d) {}
|
||||
|
||||
virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial,
|
||||
bool resetAllRenderstates, IMaterialRendererServices* services)
|
||||
{
|
||||
services->setBasicRenderStates(material, lastMaterial, resetAllRenderstates);
|
||||
|
||||
if (material.MaterialType != lastMaterial.MaterialType || resetAllRenderstates)
|
||||
{
|
||||
setTextureColorStage(pID3DDevice, 0,
|
||||
D3DTA_TEXTURE, D3DTOP_MODULATE, D3DTA_DIFFUSE);
|
||||
setTextureColorStage(pID3DDevice, 1,
|
||||
D3DTA_TEXTURE, D3DTOP_ADDSIGNED, D3DTA_CURRENT);
|
||||
pID3DDevice->SetTextureStageState(1, D3DTSS_TEXCOORDINDEX, 1);
|
||||
pID3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//! sphere map material renderer
|
||||
class CD3D9MaterialRenderer_SPHERE_MAP : public CD3D9MaterialRenderer
|
||||
{
|
||||
public:
|
||||
|
||||
CD3D9MaterialRenderer_SPHERE_MAP(IDirect3DDevice9* p, video::IVideoDriver* d)
|
||||
: CD3D9MaterialRenderer(p, d) {}
|
||||
|
||||
virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial,
|
||||
bool resetAllRenderstates, IMaterialRendererServices* services)
|
||||
{
|
||||
services->setBasicRenderStates(material, lastMaterial, resetAllRenderstates);
|
||||
|
||||
if (material.MaterialType != lastMaterial.MaterialType || resetAllRenderstates)
|
||||
{
|
||||
setTextureColorStage(pID3DDevice, 0,
|
||||
D3DTA_TEXTURE, D3DTOP_MODULATE, D3DTA_DIFFUSE);
|
||||
|
||||
pID3DDevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE);
|
||||
pID3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
|
||||
|
||||
pID3DDevice->SetTransform( D3DTS_TEXTURE0, &SphereMapMatrixD3D9 );
|
||||
pID3DDevice->SetTextureStageState( 0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT2 );
|
||||
pID3DDevice->SetTextureStageState( 0, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_CAMERASPACENORMAL );
|
||||
}
|
||||
}
|
||||
|
||||
virtual void OnUnsetMaterial()
|
||||
{
|
||||
pID3DDevice->SetTextureStageState( 0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_DISABLE );
|
||||
pID3DDevice->SetTextureStageState( 0, D3DTSS_TEXCOORDINDEX, 0);
|
||||
pID3DDevice->SetTransform( D3DTS_TEXTURE0, &UnitMatrixD3D9 );
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//! reflection 2 layer material renderer
|
||||
class CD3D9MaterialRenderer_REFLECTION_2_LAYER : public CD3D9MaterialRenderer
|
||||
{
|
||||
public:
|
||||
|
||||
CD3D9MaterialRenderer_REFLECTION_2_LAYER(IDirect3DDevice9* p, video::IVideoDriver* d)
|
||||
: CD3D9MaterialRenderer(p, d) {}
|
||||
|
||||
virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial,
|
||||
bool resetAllRenderstates, IMaterialRendererServices* services)
|
||||
{
|
||||
services->setBasicRenderStates(material, lastMaterial, resetAllRenderstates);
|
||||
|
||||
if (material.MaterialType != lastMaterial.MaterialType || resetAllRenderstates)
|
||||
{
|
||||
setTextureColorStage(pID3DDevice, 0,
|
||||
D3DTA_TEXTURE, D3DTOP_MODULATE, D3DTA_DIFFUSE);
|
||||
|
||||
setTextureColorStage(pID3DDevice, 1,
|
||||
D3DTA_TEXTURE, D3DTOP_MODULATE, D3DTA_CURRENT);
|
||||
|
||||
pID3DDevice->SetTransform( D3DTS_TEXTURE1, &SphereMapMatrixD3D9 );
|
||||
pID3DDevice->SetTextureStageState( 1, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT2 );
|
||||
pID3DDevice->SetTextureStageState( 1, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR);
|
||||
pID3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
virtual void OnUnsetMaterial()
|
||||
{
|
||||
pID3DDevice->SetTextureStageState( 1, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_DISABLE );
|
||||
pID3DDevice->SetTextureStageState( 1, D3DTSS_TEXCOORDINDEX, 1);
|
||||
pID3DDevice->SetTransform( D3DTS_TEXTURE1, &UnitMatrixD3D9 );
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//! reflection 2 layer material renderer
|
||||
class CD3D9MaterialRenderer_TRANSPARENT_REFLECTION_2_LAYER : public CD3D9MaterialRenderer
|
||||
{
|
||||
public:
|
||||
|
||||
CD3D9MaterialRenderer_TRANSPARENT_REFLECTION_2_LAYER(IDirect3DDevice9* p, video::IVideoDriver* d)
|
||||
: CD3D9MaterialRenderer(p, d) {}
|
||||
|
||||
virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial,
|
||||
bool resetAllRenderstates, IMaterialRendererServices* services)
|
||||
{
|
||||
services->setBasicRenderStates(material, lastMaterial, resetAllRenderstates);
|
||||
|
||||
if (material.MaterialType != lastMaterial.MaterialType || resetAllRenderstates)
|
||||
{
|
||||
setTextureColorStage(pID3DDevice, 0,
|
||||
D3DTA_TEXTURE, D3DTOP_MODULATE, D3DTA_DIFFUSE);
|
||||
setTextureAlphaStage(pID3DDevice, 0, D3DTA_DIFFUSE);
|
||||
setTextureColorStage(pID3DDevice, 1,
|
||||
D3DTA_TEXTURE, D3DTOP_MODULATE, D3DTA_CURRENT);
|
||||
setTextureAlphaStage(pID3DDevice, 1, D3DTA_CURRENT);
|
||||
|
||||
pID3DDevice->SetTransform(D3DTS_TEXTURE1, &SphereMapMatrixD3D9 );
|
||||
pID3DDevice->SetTextureStageState(1, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT2 );
|
||||
pID3DDevice->SetTextureStageState(1, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR);
|
||||
|
||||
pID3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
|
||||
pID3DDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
|
||||
pID3DDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
|
||||
}
|
||||
}
|
||||
|
||||
virtual void OnUnsetMaterial()
|
||||
{
|
||||
pID3DDevice->SetTextureStageState(1, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_DISABLE);
|
||||
pID3DDevice->SetTextureStageState(1, D3DTSS_TEXCOORDINDEX, 1);
|
||||
pID3DDevice->SetTransform(D3DTS_TEXTURE1, &UnitMatrixD3D9);
|
||||
}
|
||||
|
||||
//! Returns if the material is transparent. The scene managment needs to know this
|
||||
//! for being able to sort the materials by opaque and transparent.
|
||||
virtual bool isTransparent() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
} // end namespace video
|
||||
} // end namespace irr
|
||||
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
306
source/Irrlicht/CD3D9NormalMapRenderer.cpp
Normal file
306
source/Irrlicht/CD3D9NormalMapRenderer.cpp
Normal file
@ -0,0 +1,306 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#include "IrrCompileConfig.h"
|
||||
#ifdef _IRR_COMPILE_WITH_DIRECT3D_9_
|
||||
|
||||
#include "CD3D9NormalMapRenderer.h"
|
||||
#include "IVideoDriver.h"
|
||||
#include "IMaterialRendererServices.h"
|
||||
#include "os.h"
|
||||
#include "SLight.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace video
|
||||
{
|
||||
|
||||
// 1.1 Shaders with two lights and vertex based attenuation
|
||||
|
||||
// Irrlicht Engine D3D9 render path normal map vertex shader
|
||||
const char D3D9_NORMAL_MAP_VSH[] =
|
||||
";Irrlicht Engine 0.8 D3D9 render path normal map vertex shader\n"\
|
||||
"; c0-3: Transposed world matrix \n"\
|
||||
"; c8-11: Transposed worldViewProj matrix (Projection * View * World) \n"\
|
||||
"; c12: Light01 position \n"\
|
||||
"; c13: x,y,z: Light01 color; .w: 1/LightRadius<75> \n"\
|
||||
"; c14: Light02 position \n"\
|
||||
"; c15: x,y,z: Light02 color; .w: 1/LightRadius<75> \n"\
|
||||
"vs.1.1\n"\
|
||||
"dcl_position v0 ; position \n"\
|
||||
"dcl_normal v1 ; normal \n"\
|
||||
"dcl_color v2 ; color \n"\
|
||||
"dcl_texcoord0 v3 ; texture coord \n"\
|
||||
"dcl_texcoord1 v4 ; tangent \n"\
|
||||
"dcl_texcoord2 v5 ; binormal \n"\
|
||||
"\n"\
|
||||
"def c95, 0.5, 0.5, 0.5, 0.5 ; used for moving light vector to ps \n"\
|
||||
"\n"\
|
||||
"m4x4 oPos, v0, c8 ; transform position to clip space with worldViewProj matrix\n"\
|
||||
"\n"\
|
||||
"m3x3 r5, v4, c0 ; transform tangent U\n"\
|
||||
"m3x3 r7, v1, c0 ; transform normal W\n"\
|
||||
"m3x3 r6, v5, c0 ; transform binormal V\n"\
|
||||
"\n"\
|
||||
"m4x4 r4, v0, c0 ; vertex into world position\n"\
|
||||
"add r2, c12, -r4 ; vtxpos - lightpos1\n"\
|
||||
"add r3, c14, -r4 ; vtxpos - lightpos2\n"\
|
||||
"\n"\
|
||||
"dp3 r8.x, r5, r2 ; transform the light vector 1 with U, V, W\n"\
|
||||
"dp3 r8.y, r6, r2 \n"\
|
||||
"dp3 r8.z, r7, r2 \n"\
|
||||
"dp3 r9.x, r5, r3 ; transform the light vector 2 with U, V, W\n"\
|
||||
"dp3 r9.y, r6, r3 \n"\
|
||||
"dp3 r9.z, r7, r3 \n"\
|
||||
"\n"\
|
||||
"dp3 r8.w, r8, r8 ; normalize light vector 1 (r8)\n"\
|
||||
"rsq r8.w, r8.w \n"\
|
||||
"mul r8, r8, r8.w \n"\
|
||||
"dp3 r9.w, r9, r9 ; normalize light vector 2 (r9)\n"\
|
||||
"rsq r9.w, r9.w \n"\
|
||||
"mul r9, r9, r9.w \n"\
|
||||
"\n"\
|
||||
"mad oT2.xyz, r8.xyz, c95, c95 ; move light vector 1 from -1..1 into 0..1 \n"\
|
||||
"mad oT3.xyz, r9.xyz, c95, c95 ; move light vector 2 from -1..1 into 0..1 \n"\
|
||||
"\n"\
|
||||
" ; calculate attenuation of light 1 \n"\
|
||||
"dp3 r2.x, r2.xyz, r2.xyz ; r2.x = r2.x<> + r2.y<> + r2.z<> \n"\
|
||||
"mul r2.x, r2.x, c13.w ; r2.x * attenutation \n"\
|
||||
"rsq r2, r2.x ; r2.xyzw = 1/sqrt(r2.x * attenutation)\n"\
|
||||
"mul oD0, r2, c13 ; resulting light color = lightcolor * attenuation \n"\
|
||||
"\n"\
|
||||
" ; calculate attenuation of light 2 \n"\
|
||||
"dp3 r3.x, r3.xyz, r3.xyz ; r3.x = r3.x<> + r3.y<> + r3.z<> \n"\
|
||||
"mul r3.x, r3.x, c15.w ; r2.x * attenutation \n"\
|
||||
"rsq r3, r3.x ; r2.xyzw = 1/sqrt(r2.x * attenutation)\n"\
|
||||
"mul oD1, r3, c15 ; resulting light color = lightcolor * attenuation \n"\
|
||||
"\n"\
|
||||
"mov oT0.xy, v3.xy ; move out texture coordinates 1\n"\
|
||||
"mov oT1.xy, v3.xy ; move out texture coordinates 2\n"\
|
||||
"mov oD0.a, v2.a ; move out original alpha value \n"\
|
||||
"\n";
|
||||
|
||||
// Irrlicht Engine D3D9 render path normal map pixel shader
|
||||
const char D3D9_NORMAL_MAP_PSH_1_1[] =
|
||||
";Irrlicht Engine 0.8 D3D9 render path normal map pixel shader\n"\
|
||||
";Input: \n"\
|
||||
";t0: color map texture coord \n"\
|
||||
";t1: normal map texture coords \n"\
|
||||
";t2: light 1 vector in tangent space \n"\
|
||||
";v0: light 1 color \n"\
|
||||
";t3: light 2 vector in tangent space \n"\
|
||||
";v1: light 2 color \n"\
|
||||
";v0.a: vertex alpha value \n"\
|
||||
"ps.1.1 \n"\
|
||||
"tex t0 ; sample color map \n"\
|
||||
"tex t1 ; sample normal map\n"\
|
||||
"texcoord t2 ; fetch light vector 1\n"\
|
||||
"texcoord t3 ; fetch light vector 2\n"\
|
||||
"\n"\
|
||||
"dp3_sat r0, t1_bx2, t2_bx2 ; normal dot light 1 (_bx2 because moved into 0..1)\n"\
|
||||
"mul r0, r0, v0 ; luminance1 * light color 1 \n"\
|
||||
"\n"\
|
||||
"dp3_sat r1, t1_bx2, t3_bx2 ; normal dot light 2 (_bx2 because moved into 0..1)\n"\
|
||||
"mad r0, r1, v1, r0 ; (luminance2 * light color 2) + luminance 1 \n"\
|
||||
"\n"\
|
||||
"mul r0.xyz, t0, r0 ; total luminance * base color\n"\
|
||||
"+mov r0.a, v0.a ; write interpolated vertex alpha value \n"\
|
||||
"\n"\
|
||||
"";
|
||||
|
||||
// Higher-quality normal map pixel shader (requires PS 2.0)
|
||||
// uses per-pixel normalization for improved accuracy
|
||||
const char D3D9_NORMAL_MAP_PSH_2_0[] =
|
||||
";Irrlicht Engine 0.8 D3D9 render path normal map pixel shader\n"\
|
||||
";Input: \n"\
|
||||
";t0: color map texture coord \n"\
|
||||
";t1: normal map texture coords \n"\
|
||||
";t2: light 1 vector in tangent space \n"\
|
||||
";v0: light 1 color \n"\
|
||||
";t3: light 2 vector in tangent space \n"\
|
||||
";v1: light 2 color \n"\
|
||||
";v0.a: vertex alpha value \n"\
|
||||
|
||||
"ps_2_0 \n"\
|
||||
"def c0, 0, 0, 0, 0\n"\
|
||||
"def c1, 1.0, 1.0, 1.0, 1.0\n"\
|
||||
"def c2, 2.0, 2.0, 2.0, 2.0\n"\
|
||||
"def c3, -.5, -.5, -.5, -.5\n"\
|
||||
"dcl t0\n"\
|
||||
"dcl t1\n"\
|
||||
"dcl t2\n"\
|
||||
"dcl t3\n"\
|
||||
"dcl v1\n"\
|
||||
"dcl v0\n"\
|
||||
"dcl_2d s0\n"\
|
||||
"dcl_2d s1\n"\
|
||||
|
||||
"texld r0, t0, s0 ; sample color map into r0 \n"\
|
||||
"texld r4, t0, s1 ; sample normal map into r4\n"\
|
||||
"add r4, r4, c3 ; bias the normal vector\n"\
|
||||
"add r5, t2, c3 ; bias the light 1 vector into r5\n"\
|
||||
"add r6, t3, c3 ; bias the light 2 vector into r6\n"\
|
||||
|
||||
"nrm r1, r4 ; normalize the normal vector into r1\n"\
|
||||
"nrm r2, r5 ; normalize the light1 vector into r2\n"\
|
||||
"nrm r3, r6 ; normalize the light2 vector into r3\n"\
|
||||
|
||||
"dp3 r2, r2, r1 ; let r2 = normal DOT light 1 vector\n"\
|
||||
"max r2, r2, c0 ; clamp result to positive numbers\n"\
|
||||
"mul r2, r2, v0 ; let r2 = luminance1 * light color 1 \n"\
|
||||
|
||||
"dp3 r3, r3, r1 ; let r3 = normal DOT light 2 vector\n"\
|
||||
"max r3, r3, c0 ; clamp result to positive numbers\n"\
|
||||
|
||||
"mad r2, r3, v1, r2 ; let r2 = (luminance2 * light color 2) + (luminance2 * light color 1) \n"\
|
||||
|
||||
"mul r2, r2, r0 ; let r2 = total luminance * base color\n"\
|
||||
"mov r2.w, v0.w ; write interpolated vertex alpha value \n"\
|
||||
|
||||
"mov oC0, r2 ; copy r2 to the output register \n"\
|
||||
|
||||
"\n"\
|
||||
"";
|
||||
|
||||
CD3D9NormalMapRenderer::CD3D9NormalMapRenderer(
|
||||
IDirect3DDevice9* d3ddev, video::IVideoDriver* driver,
|
||||
s32& outMaterialTypeNr, IMaterialRenderer* baseMaterial)
|
||||
: CD3D9ShaderMaterialRenderer(d3ddev, driver, 0, baseMaterial)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
setDebugName("CD3D9NormalMapRenderer");
|
||||
#endif
|
||||
|
||||
// set this as callback. We could have done this in
|
||||
// the initialization list, but some compilers don't like it.
|
||||
|
||||
CallBack = this;
|
||||
|
||||
// basically, this thing simply compiles the hardcoded shaders
|
||||
// if the hardware is able to do them, otherwise it maps to the
|
||||
// base material
|
||||
|
||||
if (!driver->queryFeature(video::EVDF_PIXEL_SHADER_1_1) ||
|
||||
!driver->queryFeature(video::EVDF_VERTEX_SHADER_1_1))
|
||||
{
|
||||
// this hardware is not able to do shaders. Fall back to
|
||||
// base material.
|
||||
outMaterialTypeNr = driver->addMaterialRenderer(this);
|
||||
return;
|
||||
}
|
||||
|
||||
// check if already compiled normal map shaders are there.
|
||||
|
||||
video::IMaterialRenderer* renderer = driver->getMaterialRenderer(EMT_NORMAL_MAP_SOLID);
|
||||
if (renderer)
|
||||
{
|
||||
// use the already compiled shaders
|
||||
video::CD3D9NormalMapRenderer* nmr = (video::CD3D9NormalMapRenderer*)renderer;
|
||||
VertexShader = nmr->VertexShader;
|
||||
if (VertexShader)
|
||||
VertexShader->AddRef();
|
||||
|
||||
PixelShader = nmr->PixelShader;
|
||||
if (PixelShader)
|
||||
PixelShader->AddRef();
|
||||
|
||||
outMaterialTypeNr = driver->addMaterialRenderer(this);
|
||||
}
|
||||
else
|
||||
{
|
||||
// compile shaders on our own
|
||||
if (driver->queryFeature(video::EVDF_PIXEL_SHADER_2_0))
|
||||
{
|
||||
init(outMaterialTypeNr, D3D9_NORMAL_MAP_VSH, D3D9_NORMAL_MAP_PSH_2_0);
|
||||
}
|
||||
else
|
||||
{
|
||||
init(outMaterialTypeNr, D3D9_NORMAL_MAP_VSH, D3D9_NORMAL_MAP_PSH_1_1);
|
||||
}
|
||||
}
|
||||
// something failed, use base material
|
||||
if (-1==outMaterialTypeNr)
|
||||
driver->addMaterialRenderer(this);
|
||||
}
|
||||
|
||||
|
||||
CD3D9NormalMapRenderer::~CD3D9NormalMapRenderer()
|
||||
{
|
||||
if (CallBack == this)
|
||||
CallBack = 0;
|
||||
}
|
||||
|
||||
|
||||
bool CD3D9NormalMapRenderer::OnRender(IMaterialRendererServices* service, E_VERTEX_TYPE vtxtype)
|
||||
{
|
||||
if (vtxtype != video::EVT_TANGENTS)
|
||||
{
|
||||
os::Printer::log("Error: Normal map renderer only supports vertices of type EVT_TANGENTS", ELL_ERROR);
|
||||
return false;
|
||||
}
|
||||
|
||||
return CD3D9ShaderMaterialRenderer::OnRender(service, vtxtype);
|
||||
}
|
||||
|
||||
|
||||
//! Returns the render capability of the material.
|
||||
s32 CD3D9NormalMapRenderer::getRenderCapability() const
|
||||
{
|
||||
if (Driver->queryFeature(video::EVDF_PIXEL_SHADER_1_1) &&
|
||||
Driver->queryFeature(video::EVDF_VERTEX_SHADER_1_1))
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
//! Called by the engine when the vertex and/or pixel shader constants
|
||||
//! for an material renderer should be set.
|
||||
void CD3D9NormalMapRenderer::OnSetConstants(IMaterialRendererServices* services, s32 userData)
|
||||
{
|
||||
video::IVideoDriver* driver = services->getVideoDriver();
|
||||
|
||||
// set transposed world matrix
|
||||
services->setVertexShaderConstant(driver->getTransform(video::ETS_WORLD).getTransposed().pointer(), 0, 4);
|
||||
|
||||
// set transposed worldViewProj matrix
|
||||
core::matrix4 worldViewProj(driver->getTransform(video::ETS_PROJECTION));
|
||||
worldViewProj *= driver->getTransform(video::ETS_VIEW);
|
||||
worldViewProj *= driver->getTransform(video::ETS_WORLD);
|
||||
services->setVertexShaderConstant(worldViewProj.getTransposed().pointer(), 8, 4);
|
||||
|
||||
// here we've got to fetch the fixed function lights from the
|
||||
// driver and set them as constants
|
||||
|
||||
u32 cnt = driver->getDynamicLightCount();
|
||||
|
||||
for (u32 i=0; i<2; ++i)
|
||||
{
|
||||
SLight light;
|
||||
|
||||
if (i<cnt)
|
||||
light = driver->getDynamicLight(i);
|
||||
else
|
||||
{
|
||||
light.DiffuseColor.set(0,0,0); // make light dark
|
||||
light.Radius = 1.0f;
|
||||
}
|
||||
|
||||
light.DiffuseColor.a = 1.0f/(light.Radius*light.Radius); // set attenuation
|
||||
|
||||
services->setVertexShaderConstant(reinterpret_cast<const f32*>(&light.Position), 12+(i*2), 1);
|
||||
services->setVertexShaderConstant(reinterpret_cast<const f32*>(&light.DiffuseColor), 13+(i*2), 1);
|
||||
}
|
||||
|
||||
// this is not really necessary in d3d9 (used a def instruction), but to be sure:
|
||||
f32 c95[] = {0.5f, 0.5f, 0.5f, 0.5f};
|
||||
services->setVertexShaderConstant(c95, 95, 1);
|
||||
}
|
||||
|
||||
|
||||
} // end namespace video
|
||||
} // end namespace irr
|
||||
|
||||
#endif // _IRR_COMPILE_WITH_DIRECT3D_9_
|
||||
|
56
source/Irrlicht/CD3D9NormalMapRenderer.h
Normal file
56
source/Irrlicht/CD3D9NormalMapRenderer.h
Normal file
@ -0,0 +1,56 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#ifndef __C_D3D9_NORMAL_MAPMATERIAL_RENDERER_H_INCLUDED__
|
||||
#define __C_D3D9_NORMAL_MAPMATERIAL_RENDERER_H_INCLUDED__
|
||||
|
||||
#include "IrrCompileConfig.h"
|
||||
#ifdef _IRR_WINDOWS_
|
||||
|
||||
#ifdef _IRR_COMPILE_WITH_DIRECT3D_9_
|
||||
#if defined(__BORLANDC__) || defined (__BCPLUSPLUS__)
|
||||
#include "irrMath.h" // needed by borland for sqrtf define
|
||||
#endif
|
||||
#include <d3d9.h>
|
||||
|
||||
#include "CD3D9ShaderMaterialRenderer.h"
|
||||
#include "IShaderConstantSetCallBack.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace video
|
||||
{
|
||||
|
||||
//! Renderer for normal maps
|
||||
class CD3D9NormalMapRenderer :
|
||||
public CD3D9ShaderMaterialRenderer, IShaderConstantSetCallBack
|
||||
{
|
||||
public:
|
||||
|
||||
CD3D9NormalMapRenderer(
|
||||
IDirect3DDevice9* d3ddev, video::IVideoDriver* driver,
|
||||
s32& outMaterialTypeNr, IMaterialRenderer* baseMaterial);
|
||||
|
||||
~CD3D9NormalMapRenderer();
|
||||
|
||||
//! Called by the engine when the vertex and/or pixel shader constants for an
|
||||
//! material renderer should be set.
|
||||
virtual void OnSetConstants(IMaterialRendererServices* services, s32 userData);
|
||||
|
||||
virtual bool OnRender(IMaterialRendererServices* service, E_VERTEX_TYPE vtxtype);
|
||||
|
||||
//! Returns the render capability of the material.
|
||||
virtual s32 getRenderCapability() const;
|
||||
|
||||
private:
|
||||
|
||||
};
|
||||
|
||||
} // end namespace video
|
||||
} // end namespace irr
|
||||
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
410
source/Irrlicht/CD3D9ParallaxMapRenderer.cpp
Normal file
410
source/Irrlicht/CD3D9ParallaxMapRenderer.cpp
Normal file
@ -0,0 +1,410 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#include "IrrCompileConfig.h"
|
||||
#ifdef _IRR_COMPILE_WITH_DIRECT3D_9_
|
||||
|
||||
#include "CD3D9ParallaxMapRenderer.h"
|
||||
#include "IMaterialRendererServices.h"
|
||||
#include "IVideoDriver.h"
|
||||
#include "os.h"
|
||||
#include "SLight.h"
|
||||
|
||||
//#define SHADER_EXTERNAL_DEBUG
|
||||
|
||||
#ifdef SHADER_EXTERNAL_DEBUG
|
||||
#include "CReadFile.h"
|
||||
#endif
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace video
|
||||
{
|
||||
// 1.1/1.4 Shaders with two lights and vertex based attenuation
|
||||
|
||||
// Irrlicht Engine D3D9 render path normal map vertex shader
|
||||
const char D3D9_PARALLAX_MAP_VSH[] =
|
||||
";Irrlicht Engine 0.10 D3D9 render path parallax mapping vertex shader\n"\
|
||||
"; c0-3: Transposed world matrix \n"\
|
||||
"; c4: Eye position \n"\
|
||||
"; c8-11: Transposed worldViewProj matrix (Projection * View * World) \n"\
|
||||
"; c12: Light01 position \n"\
|
||||
"; c13: x,y,z: Light01 color; .w: 1/LightRadius<75> \n"\
|
||||
"; c14: Light02 position \n"\
|
||||
"; c15: x,y,z: Light02 color; .w: 1/LightRadius<75> \n"\
|
||||
"vs.1.1\n"\
|
||||
"dcl_position v0 ; position \n"\
|
||||
"dcl_normal v1 ; normal \n"\
|
||||
"dcl_color v2 ; color \n"\
|
||||
"dcl_texcoord0 v3 ; texture coord \n"\
|
||||
"dcl_texcoord1 v4 ; tangent \n"\
|
||||
"dcl_texcoord2 v5 ; binormal \n"\
|
||||
"\n"\
|
||||
"def c95, 0.5, 0.5, 0.5, 0.5 ; used for moving light vector to ps \n"\
|
||||
"def c96, -1, 1, 1, 1 ; somewhere I've got a bug. flipping the vectors with this fixes it. \n"\
|
||||
"\n"\
|
||||
"m4x4 oPos, v0, c8 ; transform position to clip space with worldViewProj matrix\n"\
|
||||
"\n"\
|
||||
"m3x3 r5, v4, c0 ; transform tangent U\n"\
|
||||
"m3x3 r7, v1, c0 ; transform normal W\n"\
|
||||
"m3x3 r6, v5, c0 ; transform binormal V\n"\
|
||||
"\n"\
|
||||
"m4x4 r4, v0, c0 ; vertex into world position\n"\
|
||||
"add r2, c12, -r4 ; vtxpos - light1 pos\n"\
|
||||
"add r3, c14, -r4 ; vtxpos - light2 pos\n"\
|
||||
"add r1, -c4, r4 ; eye - vtxpos \n"\
|
||||
"\n"\
|
||||
"dp3 r8.x, r5, r2 ; transform the light1 vector with U, V, W\n"\
|
||||
"dp3 r8.y, r6, r2 \n"\
|
||||
"dp3 r8.z, r7, r2 \n"\
|
||||
"dp3 r9.x, r5, r3 ; transform the light2 vector with U, V, W\n"\
|
||||
"dp3 r9.y, r6, r3 \n"\
|
||||
"dp3 r9.z, r7, r3 \n"\
|
||||
"dp3 r10.x, r5, r1 ; transform the eye vector with U, V, W\n"\
|
||||
"dp3 r10.y, r6, r1 \n"\
|
||||
"dp3 r10.z, r7, r1 \n"\
|
||||
"\n"\
|
||||
"dp3 r8.w, r8, r8 ; normalize light vector 1 (r8)\n"\
|
||||
"rsq r8.w, r8.w \n"\
|
||||
"mul r8, r8, r8.w \n"\
|
||||
";mul r8, r8, c96 \n"\
|
||||
"dp3 r9.w, r9, r9 ; normalize light vector 2 (r9)\n"\
|
||||
"rsq r9.w, r9.w \n"\
|
||||
"mul r9, r9, r9.w \n"\
|
||||
";mul r9, r9, c96 \n"\
|
||||
"dp3 r10.w, r10, r10 ; normalize eye vector (r10)\n"\
|
||||
"rsq r10.w, r10.w \n"\
|
||||
"mul r10, r10, r10.w \n"\
|
||||
"mul r10, r10, c96 \n"\
|
||||
"\n"\
|
||||
"\n"\
|
||||
"mad oT2.xyz, r8.xyz, c95, c95 ; move light vector 1 from -1..1 into 0..1 \n"\
|
||||
"mad oT3.xyz, r9.xyz, c95, c95 ; move light vector 2 from -1..1 into 0..1 \n"\
|
||||
"mad oT4.xyz, r10.xyz, c95, c95 ; move eye vector from -1..1 into 0..1 \n"\
|
||||
"\n"\
|
||||
" ; calculate attenuation of light 1 \n"\
|
||||
"dp3 r2.x, r2.xyz, r2.xyz ; r2.x = r2.x<> + r2.y<> + r2.z<> \n"\
|
||||
"mul r2.x, r2.x, c13.w ; r2.x * attenutation \n"\
|
||||
"rsq r2, r2.x ; r2.xyzw = 1/sqrt(r2.x * attenutation)\n"\
|
||||
"mul oD0, r2, c13 ; resulting light color = lightcolor * attenuation \n"\
|
||||
"\n"\
|
||||
" ; calculate attenuation of light 2 \n"\
|
||||
"dp3 r3.x, r3.xyz, r3.xyz ; r3.x = r3.x<> + r3.y<> + r3.z<> \n"\
|
||||
"mul r3.x, r3.x, c15.w ; r2.x * attenutation \n"\
|
||||
"rsq r3, r3.x ; r2.xyzw = 1/sqrt(r2.x * attenutation)\n"\
|
||||
"mul oD1, r3, c15 ; resulting light color = lightcolor * attenuation \n"\
|
||||
"\n"\
|
||||
"mov oT0.xy, v3.xy ; move out texture coordinates 1\n"\
|
||||
"mov oT1.xy, v3.xy ; move out texture coordinates 2\n"\
|
||||
"mov oD0.a, v2.a ; move out original alpha value \n"\
|
||||
"\n";
|
||||
|
||||
|
||||
// Irrlicht Engine D3D9 render path normal map pixel shader version 1.4
|
||||
const char D3D9_PARALLAX_MAP_PSH[] =
|
||||
";Irrlicht Engine 0.10 D3D9 render path parallax mapping pixel shader \n"\
|
||||
";Input: \n"\
|
||||
";t0: color map texture coord \n"\
|
||||
";t1: normal map texture coords \n"\
|
||||
";t2: light 1 vector in tangent space \n"\
|
||||
";t4: eye vector in tangent space \n"\
|
||||
";v0: light 1 color \n"\
|
||||
";t3: light 2 vector in tangent space \n"\
|
||||
";v1: light 2 color \n"\
|
||||
";v0.a: vertex alpha value \n"\
|
||||
" \n"\
|
||||
"ps.1.4 \n"\
|
||||
" \n"\
|
||||
";def c6, 0.02f, 0.02f, 0.02f, 0.0f ; scale factor, now set in callback \n"\
|
||||
"def c5, 0.5f, 0.5f, 0.5f, 0.0f ; for specular division \n"\
|
||||
" \n"\
|
||||
"texld r1, t1 ; sample (normal.x, normal.y, normal.z, height) \n"\
|
||||
"texcrd r4.xyz, t4 ; fetch eye vector \n"\
|
||||
"texcrd r0.xyz, t0 ; color map \n"\
|
||||
" \n"\
|
||||
"; original parallax mapping: \n"\
|
||||
";mul r3, r1_bx2.wwww, c6; ; r3 = (height, height, height) * scale \n"\
|
||||
";mad r2.xyz, r3, r4_bx2, r0 ; newTexCoord = height * eye + oldTexCoord \n"\
|
||||
" \n"\
|
||||
"; modified parallax mapping to reduce swimming effect: \n"\
|
||||
"mul r3, r1_bx2.wwww, r1_bx2.zzzz ; (nh,nh,nh,nh) = (h,h,h,h) * (n.z,n.z,n.z,n.z,) \n"\
|
||||
"mul r3, r3, c6; ; r3 = (nh, nh, nh) * scale \n"\
|
||||
"mad r2.xyz, r3, r4_bx2, r0 ; newTexCoord = height * eye + oldTexCoord \n"\
|
||||
" \n"\
|
||||
"phase \n"\
|
||||
" \n"\
|
||||
"texld r0, r2 ; load diffuse texture with new tex coord \n"\
|
||||
"texld r1, r2 ; sample normal map \n"\
|
||||
"texcrd r2.xyz, t2 ; fetch light vector 1 \n"\
|
||||
"texcrd r3.xyz, t3 ; fetch light vector 2 \n"\
|
||||
" \n"\
|
||||
"dp3_sat r5, r1_bx2, r2_bx2 ; normal dot light 1 (_bx2 because moved into 0..1) \n"\
|
||||
"mul r5, r5, v0 ; luminance1 * light color 1 \n"\
|
||||
" \n"\
|
||||
"dp3_sat r3, r1_bx2, r3_bx2 ; normal dot light 2 (_bx2 because moved into 0..1) \n"\
|
||||
"mad r3, r3, v1, r5 ; (luminance2 * light color 2) + luminance1 \n"\
|
||||
" \n"\
|
||||
"mul r0.xyz, r0, r3 ; total luminance * base color \n"\
|
||||
"+mov r0.a, v0.a ; write original alpha value \n"\
|
||||
"\n";
|
||||
|
||||
// Irrlicht Engine D3D9 render path normal map pixel shader version 2.0
|
||||
const char D3D9_PARALLAX_MAP_PSH_20[] =
|
||||
";Irrlicht Engine D3D9 render path parallax mapping pixel shader \n"\
|
||||
";Input: \n"\
|
||||
" \n"\
|
||||
";t0: color map texture coord \n"\
|
||||
";t1: normal map texture coords \n"\
|
||||
";t2: light 1 vector in tangent space \n"\
|
||||
";t4: eye vector in tangent space \n"\
|
||||
";v0: light 1 color \n"\
|
||||
";t3: light 2 vector in tangent space \n"\
|
||||
";v1: light 2 color \n"\
|
||||
";v0.a: vertex alpha value \n"\
|
||||
" \n"\
|
||||
"ps.2.0 \n"\
|
||||
" \n"\
|
||||
"dcl_2d s0 ; Declare the s0 register to be the sampler for stage 0 \n"\
|
||||
"dcl t0.xy ; Declare t0 to have 2D texture coordinates from stage 0 \n"\
|
||||
"dcl t1.xy ; Declare t0 to have 2D texture coordinates from stage 0 \n"\
|
||||
"dcl_2d s1 ; Declare the s1 register to be the sampler for stage 1 \n"\
|
||||
" \n"\
|
||||
"dcl t2.xyz ; \n"\
|
||||
"dcl t3.xyz ; \n"\
|
||||
"dcl t4.xyz ; \n"\
|
||||
"dcl v0.xyzw; \n"\
|
||||
"dcl v1.xyzw; \n"\
|
||||
" \n"\
|
||||
"def c0, -1.0f, -1.0f, -1.0f, -1.0f ; for _bx2 emulation \n"\
|
||||
"def c1, 2.0f, 2.0f, 2.0f, 2.0f ; for _bx2 emulation \n"\
|
||||
"mov r11, c1; \n"\
|
||||
" \n"\
|
||||
"texld r1, t1, s1 ; sample (normal.x, normal.y, normal.z, height) \n"\
|
||||
"mov r4.xyz, t4 ; fetch eye vector \n"\
|
||||
"mov r0.xy, t0 ; color map \n"\
|
||||
" \n"\
|
||||
"; original parallax mapping: \n"\
|
||||
"; emulate ps1x _bx2, so substract 0.5f and multiply by 2 \n"\
|
||||
"mad r1.xyz, r1, r11, c0; \n"\
|
||||
" \n"\
|
||||
"mul r3, r1.wwww, c6; ; r3 = (height, height, height) * scale \n"\
|
||||
" \n"\
|
||||
"; emulate ps1x _bx2, so substract 0.5f and multiply by 2 \n"\
|
||||
"mad r4.xyz, r4, r11, c0; \n"\
|
||||
" \n"\
|
||||
"mad r2.xy, r3, r4, r0 ; newTexCoord = height * eye + oldTexCoord \n"\
|
||||
" \n"\
|
||||
"; modified parallax mapping to avoid swimming: \n"\
|
||||
";mul r3, r1_bx2.wwww, r1_bx2.zzzz ; r3 = (h,h,h,h) * (n.z, n.z, n.z, n.z,) \n"\
|
||||
";mul r3, r3, c6; ; r3 = (nh, nh, nh) * scale \n"\
|
||||
";mad r2.xyz, r3, r4_bx2, r0 ; newTexCoord = height * eye + oldTexCoord \n"\
|
||||
" \n"\
|
||||
"texld r0, r2, s0 ; load diffuse texture with new tex coord \n"\
|
||||
"texld r1, r2, s1 ; sample normal map \n"\
|
||||
"mov r2.xyz, t2 ; fetch light vector 1 \n"\
|
||||
"mov r3.xyz, t3 ; fetch light vector 2 \n"\
|
||||
" \n"\
|
||||
"; emulate ps1x _bx2, so substract 0.5f and multiply by 2 \n"\
|
||||
"mad r1.xyz, r1, r11, c0; \n"\
|
||||
"mad r2.xyz, r2, r11, c0; \n"\
|
||||
"mad r3.xyz, r3, r11, c0; \n"\
|
||||
" \n"\
|
||||
"dp3_sat r2, r1, r2 ; normal dot light 1 (_bx2 because moved into 0..1) \n"\
|
||||
"mul r2, r2, v0 ; luminance1 * light color 1 \n"\
|
||||
" \n"\
|
||||
"dp3_sat r3, r1, r3 ; normal dot light 2 (_bx2 because moved into 0..1) \n"\
|
||||
"mad r3, r3, v1, r2 ; (luminance2 * light color 2) + luminance1 \n"\
|
||||
" \n"\
|
||||
"mul r0.xyz, r0, r3 ; total luminance * base color \n"\
|
||||
"mov r0.a, v0.a ; write original alpha value \n"\
|
||||
"mov oC0, r0; \n"\
|
||||
"\n";
|
||||
|
||||
CD3D9ParallaxMapRenderer::CD3D9ParallaxMapRenderer(
|
||||
IDirect3DDevice9* d3ddev, video::IVideoDriver* driver,
|
||||
s32& outMaterialTypeNr, IMaterialRenderer* baseMaterial)
|
||||
: CD3D9ShaderMaterialRenderer(d3ddev, driver, 0, baseMaterial),
|
||||
CurrentScale(0.0f)
|
||||
{
|
||||
|
||||
#ifdef _DEBUG
|
||||
setDebugName("CD3D9ParallaxMapRenderer");
|
||||
#endif
|
||||
|
||||
// set this as callback. We could have done this in
|
||||
// the initialization list, but some compilers don't like it.
|
||||
|
||||
CallBack = this;
|
||||
|
||||
// basicly, this thing simply compiles these hardcoded shaders if the
|
||||
// hardware is able to do them, otherwise it maps to the base material
|
||||
|
||||
if (!driver->queryFeature(video::EVDF_PIXEL_SHADER_1_4) ||
|
||||
!driver->queryFeature(video::EVDF_VERTEX_SHADER_1_1))
|
||||
{
|
||||
// this hardware is not able to do shaders. Fall back to
|
||||
// base material.
|
||||
outMaterialTypeNr = driver->addMaterialRenderer(this);
|
||||
return;
|
||||
}
|
||||
|
||||
// check if already compiled parallax map shaders are there.
|
||||
|
||||
video::IMaterialRenderer* renderer = driver->getMaterialRenderer(EMT_PARALLAX_MAP_SOLID);
|
||||
if (renderer)
|
||||
{
|
||||
// use the already compiled shaders
|
||||
video::CD3D9ParallaxMapRenderer* nmr = (video::CD3D9ParallaxMapRenderer*)renderer;
|
||||
VertexShader = nmr->VertexShader;
|
||||
if (VertexShader)
|
||||
VertexShader->AddRef();
|
||||
|
||||
PixelShader = nmr->PixelShader;
|
||||
if (PixelShader)
|
||||
PixelShader->AddRef();
|
||||
|
||||
outMaterialTypeNr = driver->addMaterialRenderer(this);
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef SHADER_EXTERNAL_DEBUG
|
||||
|
||||
// quickly load shader from external file
|
||||
io::CReadFile* file = new io::CReadFile("parallax.psh");
|
||||
s32 sz = file->getSize();
|
||||
char* s = new char[sz+1];
|
||||
file->read(s, sz);
|
||||
s[sz] = 0;
|
||||
|
||||
init(outMaterialTypeNr, D3D9_PARALLAX_MAP_VSH, s);
|
||||
|
||||
delete [] s;
|
||||
file->drop();
|
||||
|
||||
#else
|
||||
|
||||
// compile shaders on our own
|
||||
init(outMaterialTypeNr, D3D9_PARALLAX_MAP_VSH, D3D9_PARALLAX_MAP_PSH);
|
||||
|
||||
#endif // SHADER_EXTERNAL_DEBUG
|
||||
}
|
||||
// something failed, use base material
|
||||
if (-1==outMaterialTypeNr)
|
||||
driver->addMaterialRenderer(this);
|
||||
}
|
||||
|
||||
|
||||
CD3D9ParallaxMapRenderer::~CD3D9ParallaxMapRenderer()
|
||||
{
|
||||
if (CallBack == this)
|
||||
CallBack = 0;
|
||||
}
|
||||
|
||||
bool CD3D9ParallaxMapRenderer::OnRender(IMaterialRendererServices* service, E_VERTEX_TYPE vtxtype)
|
||||
{
|
||||
if (vtxtype != video::EVT_TANGENTS)
|
||||
{
|
||||
os::Printer::log("Error: Parallax map renderer only supports vertices of type EVT_TANGENTS", ELL_ERROR);
|
||||
return false;
|
||||
}
|
||||
|
||||
return CD3D9ShaderMaterialRenderer::OnRender(service, vtxtype);
|
||||
}
|
||||
|
||||
|
||||
void CD3D9ParallaxMapRenderer::OnSetMaterial(const video::SMaterial& material,
|
||||
const video::SMaterial& lastMaterial,
|
||||
bool resetAllRenderstates, video::IMaterialRendererServices* services)
|
||||
{
|
||||
CD3D9ShaderMaterialRenderer::OnSetMaterial(material, lastMaterial,
|
||||
resetAllRenderstates, services);
|
||||
|
||||
CurrentScale = material.MaterialTypeParam;
|
||||
}
|
||||
|
||||
|
||||
//! Returns the render capability of the material.
|
||||
s32 CD3D9ParallaxMapRenderer::getRenderCapability() const
|
||||
{
|
||||
if (Driver->queryFeature(video::EVDF_PIXEL_SHADER_1_4) &&
|
||||
Driver->queryFeature(video::EVDF_VERTEX_SHADER_1_1))
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
//! Called by the engine when the vertex and/or pixel shader constants
|
||||
//! for an material renderer should be set.
|
||||
void CD3D9ParallaxMapRenderer::OnSetConstants(IMaterialRendererServices* services, s32 userData)
|
||||
{
|
||||
video::IVideoDriver* driver = services->getVideoDriver();
|
||||
|
||||
// set transposed world matrix
|
||||
services->setVertexShaderConstant(driver->getTransform(video::ETS_WORLD).getTransposed().pointer(), 0, 4);
|
||||
|
||||
// set eye position
|
||||
|
||||
// The viewpoint is at (0., 0., 0.) in eye space.
|
||||
// Turning this into a vector [0 0 0 1] and multiply it by
|
||||
// the inverse of the view matrix, the resulting vector is the
|
||||
// object space location of the camera.
|
||||
|
||||
f32 floats[4] = {0,0,0,1};
|
||||
core::matrix4 minv = driver->getTransform(video::ETS_VIEW);
|
||||
minv.makeInverse();
|
||||
minv.multiplyWith1x4Matrix(floats);
|
||||
services->setVertexShaderConstant(floats, 4, 1);
|
||||
|
||||
// set transposed worldViewProj matrix
|
||||
core::matrix4 worldViewProj;
|
||||
worldViewProj = driver->getTransform(video::ETS_PROJECTION);
|
||||
worldViewProj *= driver->getTransform(video::ETS_VIEW);
|
||||
worldViewProj *= driver->getTransform(video::ETS_WORLD);
|
||||
services->setVertexShaderConstant(worldViewProj.getTransposed().pointer(), 8, 4);
|
||||
|
||||
// here we've got to fetch the fixed function lights from the
|
||||
// driver and set them as constants
|
||||
|
||||
const u32 cnt = driver->getDynamicLightCount();
|
||||
|
||||
for (u32 i=0; i<2; ++i)
|
||||
{
|
||||
SLight light;
|
||||
|
||||
if (i<cnt)
|
||||
light = driver->getDynamicLight(i);
|
||||
else
|
||||
{
|
||||
light.DiffuseColor.set(0,0,0); // make light dark
|
||||
light.Radius = 1.0f;
|
||||
}
|
||||
|
||||
light.DiffuseColor.a = 1.0f/(light.Radius*light.Radius); // set attenuation
|
||||
|
||||
services->setVertexShaderConstant(reinterpret_cast<const f32*>(&light.Position), 12+(i*2), 1);
|
||||
services->setVertexShaderConstant(reinterpret_cast<const f32*>(&light.DiffuseColor), 13+(i*2), 1);
|
||||
}
|
||||
|
||||
// this is not really necessary in d3d9 (used a def instruction), but to be sure:
|
||||
f32 c95[] = {0.5f, 0.5f, 0.5f, 0.5f};
|
||||
services->setVertexShaderConstant(c95, 95, 1);
|
||||
f32 c96[] = {-1, 1, 1, 1};
|
||||
services->setVertexShaderConstant(c96, 96, 1);
|
||||
|
||||
// set scale factor
|
||||
f32 factor = 0.02f; // default value
|
||||
if (CurrentScale != 0)
|
||||
factor = CurrentScale;
|
||||
|
||||
f32 c6[] = {factor, factor, factor, 0};
|
||||
services->setPixelShaderConstant(c6, 6, 1);
|
||||
}
|
||||
|
||||
|
||||
} // end namespace video
|
||||
} // end namespace irr
|
||||
|
||||
#endif // _IRR_COMPILE_WITH_DIRECT3D_9_
|
||||
|
63
source/Irrlicht/CD3D9ParallaxMapRenderer.h
Normal file
63
source/Irrlicht/CD3D9ParallaxMapRenderer.h
Normal file
@ -0,0 +1,63 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#ifndef __C_D3D9_PARALLAX_MAPMATERIAL_RENDERER_H_INCLUDED__
|
||||
#define __C_D3D9_PARALLAX_MAPMATERIAL_RENDERER_H_INCLUDED__
|
||||
|
||||
#include "IrrCompileConfig.h"
|
||||
#ifdef _IRR_WINDOWS_
|
||||
|
||||
#ifdef _IRR_COMPILE_WITH_DIRECT3D_9_
|
||||
#if defined(__BORLANDC__) || defined (__BCPLUSPLUS__)
|
||||
#include "irrMath.h" // needed by borland for sqrtf define
|
||||
#endif
|
||||
#include <d3d9.h>
|
||||
|
||||
#include "CD3D9ShaderMaterialRenderer.h"
|
||||
#include "IShaderConstantSetCallBack.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace video
|
||||
{
|
||||
|
||||
//! Renderer for normal maps using parallax mapping
|
||||
class CD3D9ParallaxMapRenderer :
|
||||
public CD3D9ShaderMaterialRenderer, IShaderConstantSetCallBack
|
||||
{
|
||||
public:
|
||||
|
||||
CD3D9ParallaxMapRenderer(
|
||||
IDirect3DDevice9* d3ddev, video::IVideoDriver* driver,
|
||||
s32& outMaterialTypeNr, IMaterialRenderer* baseMaterial);
|
||||
|
||||
~CD3D9ParallaxMapRenderer();
|
||||
|
||||
//! Called by the engine when the vertex and/or pixel shader constants for an
|
||||
//! material renderer should be set.
|
||||
virtual void OnSetConstants(IMaterialRendererServices* services, s32 userData);
|
||||
|
||||
virtual bool OnRender(IMaterialRendererServices* service, E_VERTEX_TYPE vtxtype);
|
||||
|
||||
//! Returns the render capability of the material.
|
||||
virtual s32 getRenderCapability() const;
|
||||
|
||||
virtual void OnSetMaterial(const SMaterial& material) { }
|
||||
virtual void OnSetMaterial(const video::SMaterial& material,
|
||||
const video::SMaterial& lastMaterial,
|
||||
bool resetAllRenderstates, video::IMaterialRendererServices* services);
|
||||
|
||||
private:
|
||||
|
||||
f32 CurrentScale;
|
||||
|
||||
};
|
||||
|
||||
} // end namespace video
|
||||
} // end namespace irr
|
||||
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
540
source/Irrlicht/CD3D9ShaderMaterialRenderer.cpp
Normal file
540
source/Irrlicht/CD3D9ShaderMaterialRenderer.cpp
Normal file
@ -0,0 +1,540 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#include "IrrCompileConfig.h"
|
||||
#ifdef _IRR_COMPILE_WITH_DIRECT3D_9_
|
||||
|
||||
#include "CD3D9ShaderMaterialRenderer.h"
|
||||
#include "IShaderConstantSetCallBack.h"
|
||||
#include "IMaterialRendererServices.h"
|
||||
#include "IVideoDriver.h"
|
||||
#include "os.h"
|
||||
#include "irrString.h"
|
||||
|
||||
#ifndef _IRR_D3D_NO_SHADER_DEBUGGING
|
||||
#include <stdio.h>
|
||||
#endif
|
||||
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace video
|
||||
{
|
||||
|
||||
//! Public constructor
|
||||
CD3D9ShaderMaterialRenderer::CD3D9ShaderMaterialRenderer(IDirect3DDevice9* d3ddev, video::IVideoDriver* driver,
|
||||
s32& outMaterialTypeNr, const c8* vertexShaderProgram, const c8* pixelShaderProgram,
|
||||
IShaderConstantSetCallBack* callback, IMaterialRenderer* baseMaterial, s32 userData)
|
||||
: pID3DDevice(d3ddev), Driver(driver), CallBack(callback), BaseMaterial(baseMaterial),
|
||||
VertexShader(0), OldVertexShader(0), PixelShader(0), UserData(userData)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
setDebugName("CD3D9ShaderMaterialRenderer");
|
||||
#endif
|
||||
|
||||
if (BaseMaterial)
|
||||
BaseMaterial->grab();
|
||||
|
||||
if (CallBack)
|
||||
CallBack->grab();
|
||||
|
||||
init(outMaterialTypeNr, vertexShaderProgram, pixelShaderProgram);
|
||||
}
|
||||
|
||||
|
||||
//! constructor only for use by derived classes who want to
|
||||
//! create a fall back material for example.
|
||||
CD3D9ShaderMaterialRenderer::CD3D9ShaderMaterialRenderer(IDirect3DDevice9* d3ddev,
|
||||
video::IVideoDriver* driver,
|
||||
IShaderConstantSetCallBack* callback,
|
||||
IMaterialRenderer* baseMaterial, s32 userData)
|
||||
: pID3DDevice(d3ddev), Driver(driver), CallBack(callback), BaseMaterial(baseMaterial),
|
||||
VertexShader(0), OldVertexShader(0), PixelShader(0), UserData(userData)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
setDebugName("CD3D9ShaderMaterialRenderer");
|
||||
#endif
|
||||
|
||||
if (BaseMaterial)
|
||||
BaseMaterial->grab();
|
||||
|
||||
if (CallBack)
|
||||
CallBack->grab();
|
||||
}
|
||||
|
||||
|
||||
void CD3D9ShaderMaterialRenderer::init(s32& outMaterialTypeNr,
|
||||
const c8* vertexShaderProgram, const c8* pixelShaderProgram)
|
||||
{
|
||||
outMaterialTypeNr = -1;
|
||||
|
||||
// create vertex shader
|
||||
if (!createVertexShader(vertexShaderProgram))
|
||||
return;
|
||||
|
||||
// create pixel shader
|
||||
if (!createPixelShader(pixelShaderProgram))
|
||||
return;
|
||||
|
||||
// register myself as new material
|
||||
outMaterialTypeNr = Driver->addMaterialRenderer(this);
|
||||
}
|
||||
|
||||
|
||||
//! Destructor
|
||||
CD3D9ShaderMaterialRenderer::~CD3D9ShaderMaterialRenderer()
|
||||
{
|
||||
if (CallBack)
|
||||
CallBack->drop();
|
||||
|
||||
if (VertexShader)
|
||||
VertexShader->Release();
|
||||
|
||||
if (PixelShader)
|
||||
PixelShader->Release();
|
||||
|
||||
if (BaseMaterial)
|
||||
BaseMaterial->drop();
|
||||
}
|
||||
|
||||
|
||||
bool CD3D9ShaderMaterialRenderer::OnRender(IMaterialRendererServices* service, E_VERTEX_TYPE vtxtype)
|
||||
{
|
||||
// call callback to set shader constants
|
||||
if (CallBack && (VertexShader || PixelShader))
|
||||
CallBack->OnSetConstants(service, UserData);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void CD3D9ShaderMaterialRenderer::OnSetMaterial(const video::SMaterial& material, const video::SMaterial& lastMaterial,
|
||||
bool resetAllRenderstates, video::IMaterialRendererServices* services)
|
||||
{
|
||||
if (material.MaterialType != lastMaterial.MaterialType || resetAllRenderstates)
|
||||
{
|
||||
if (VertexShader)
|
||||
{
|
||||
// save old vertex shader
|
||||
pID3DDevice->GetVertexShader(&OldVertexShader);
|
||||
|
||||
// set new vertex shader
|
||||
if (FAILED(pID3DDevice->SetVertexShader(VertexShader)))
|
||||
os::Printer::log("Could not set vertex shader.", ELL_WARNING);
|
||||
}
|
||||
|
||||
// set new pixel shader
|
||||
if (PixelShader)
|
||||
{
|
||||
if (FAILED(pID3DDevice->SetPixelShader(PixelShader)))
|
||||
os::Printer::log("Could not set pixel shader.", ELL_WARNING);
|
||||
}
|
||||
|
||||
if (BaseMaterial)
|
||||
BaseMaterial->OnSetMaterial(material, material, true, services);
|
||||
}
|
||||
|
||||
//let callback know used material
|
||||
if (CallBack)
|
||||
CallBack->OnSetMaterial(material);
|
||||
|
||||
services->setBasicRenderStates(material, lastMaterial, resetAllRenderstates);
|
||||
}
|
||||
|
||||
|
||||
void CD3D9ShaderMaterialRenderer::OnUnsetMaterial()
|
||||
{
|
||||
if (VertexShader)
|
||||
pID3DDevice->SetVertexShader(OldVertexShader);
|
||||
|
||||
if (PixelShader)
|
||||
pID3DDevice->SetPixelShader(0);
|
||||
|
||||
if (BaseMaterial)
|
||||
BaseMaterial->OnUnsetMaterial();
|
||||
}
|
||||
|
||||
|
||||
//! Returns if the material is transparent. The scene managment needs to know this
|
||||
//! for being able to sort the materials by opaque and transparent.
|
||||
bool CD3D9ShaderMaterialRenderer::isTransparent() const
|
||||
{
|
||||
return BaseMaterial ? BaseMaterial->isTransparent() : false;
|
||||
}
|
||||
|
||||
|
||||
bool CD3D9ShaderMaterialRenderer::createPixelShader(const c8* pxsh)
|
||||
{
|
||||
if (!pxsh)
|
||||
return true;
|
||||
|
||||
// compile shader
|
||||
|
||||
LPD3DXBUFFER code = 0;
|
||||
LPD3DXBUFFER errors = 0;
|
||||
|
||||
#ifdef _IRR_D3D_NO_SHADER_DEBUGGING
|
||||
|
||||
// compile shader without debug info
|
||||
stubD3DXAssembleShader(pxsh, (UINT)strlen(pxsh), 0, 0, 0, &code, &errors);
|
||||
#else
|
||||
|
||||
// compile shader and emitt some debug informations to
|
||||
// make it possible to debug the shader in visual studio
|
||||
|
||||
static int irr_dbg_file_nr = 0;
|
||||
++irr_dbg_file_nr;
|
||||
char tmp[32];
|
||||
sprintf(tmp, "irr_d3d9_dbg_shader_%d.psh", irr_dbg_file_nr);
|
||||
|
||||
FILE* f = fopen(tmp, "wb");
|
||||
fwrite(pxsh, strlen(pxsh), 1, f);
|
||||
fflush(f);
|
||||
fclose(f);
|
||||
|
||||
stubD3DXAssembleShaderFromFile(tmp, 0, 0, D3DXSHADER_DEBUG, &code, &errors);
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
if (errors)
|
||||
{
|
||||
// print out compilation errors.
|
||||
os::Printer::log("Pixel shader compilation failed:", ELL_ERROR);
|
||||
os::Printer::log((c8*)errors->GetBufferPointer(), ELL_ERROR);
|
||||
|
||||
if (code)
|
||||
code->Release();
|
||||
|
||||
errors->Release();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (FAILED(pID3DDevice->CreatePixelShader((DWORD*)code->GetBufferPointer(), &PixelShader)))
|
||||
{
|
||||
os::Printer::log("Could not create pixel shader.", ELL_ERROR);
|
||||
code->Release();
|
||||
return false;
|
||||
}
|
||||
|
||||
code->Release();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool CD3D9ShaderMaterialRenderer::createVertexShader(const char* vtxsh)
|
||||
{
|
||||
if (!vtxsh)
|
||||
return true;
|
||||
|
||||
// compile shader
|
||||
|
||||
LPD3DXBUFFER code = 0;
|
||||
LPD3DXBUFFER errors = 0;
|
||||
|
||||
#ifdef _IRR_D3D_NO_SHADER_DEBUGGING
|
||||
|
||||
// compile shader without debug info
|
||||
stubD3DXAssembleShader(vtxsh, (UINT)strlen(vtxsh), 0, 0, 0, &code, &errors);
|
||||
|
||||
#else
|
||||
|
||||
// compile shader and emitt some debug informations to
|
||||
// make it possible to debug the shader in visual studio
|
||||
|
||||
static int irr_dbg_file_nr = 0;
|
||||
++irr_dbg_file_nr;
|
||||
char tmp[32];
|
||||
sprintf(tmp, "irr_d3d9_dbg_shader_%d.vsh", irr_dbg_file_nr);
|
||||
|
||||
FILE* f = fopen(tmp, "wb");
|
||||
fwrite(vtxsh, strlen(vtxsh), 1, f);
|
||||
fflush(f);
|
||||
fclose(f);
|
||||
|
||||
stubD3DXAssembleShaderFromFile(tmp, 0, 0, D3DXSHADER_DEBUG, &code, &errors);
|
||||
|
||||
#endif
|
||||
|
||||
if (errors)
|
||||
{
|
||||
// print out compilation errors.
|
||||
os::Printer::log("Vertex shader compilation failed:", ELL_ERROR);
|
||||
os::Printer::log((c8*)errors->GetBufferPointer(), ELL_ERROR);
|
||||
|
||||
if (code)
|
||||
code->Release();
|
||||
|
||||
errors->Release();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!code || FAILED(pID3DDevice->CreateVertexShader((DWORD*)code->GetBufferPointer(), &VertexShader)))
|
||||
{
|
||||
os::Printer::log("Could not create vertex shader.", ELL_ERROR);
|
||||
if (code)
|
||||
code->Release();
|
||||
return false;
|
||||
}
|
||||
|
||||
code->Release();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
HRESULT CD3D9ShaderMaterialRenderer::stubD3DXAssembleShader(LPCSTR pSrcData,
|
||||
UINT SrcDataLen, CONST D3DXMACRO* pDefines,
|
||||
LPD3DXINCLUDE pInclude, DWORD Flags, LPD3DXBUFFER* ppShader,
|
||||
LPD3DXBUFFER* ppErrorMsgs)
|
||||
{
|
||||
// Because Irrlicht needs to be able to start up even without installed d3d dlls, it
|
||||
// needs to load external d3d dlls manually. examples for the dlls are:
|
||||
// SDK dll name D3DX_SDK_VERSION
|
||||
// Summer 2004: no dll 22
|
||||
// February 2005: d3dx9_24.dll 24
|
||||
// April 2005: d3dx9_25.dll 25
|
||||
// June 2005: d3dx9_26.dll 26
|
||||
// August 2005: d3dx9_27.dll 27
|
||||
// October 2005,
|
||||
// December 2005: d3dx9_28.dll 28
|
||||
|
||||
#if ( D3DX_SDK_VERSION < 24 )
|
||||
// directly link functions, old d3d sdks didn't try to load external dlls
|
||||
// when linking to the d3dx9.lib
|
||||
#ifdef _MSC_VER
|
||||
#pragma comment (lib, "d3dx9.lib")
|
||||
#endif
|
||||
|
||||
// invoke static linked function
|
||||
return D3DXAssembleShader(pSrcData, SrcDataLen, pDefines, pInclude,
|
||||
Flags, ppShader, ppErrorMsgs);
|
||||
#else
|
||||
{
|
||||
// try to load shader functions from the dll and print error if failed.
|
||||
|
||||
// D3DXAssembleShader signature
|
||||
typedef HRESULT (WINAPI *AssembleShaderFunction)(LPCSTR pSrcData, UINT SrcDataLen,
|
||||
CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude,
|
||||
DWORD Flags, LPD3DXBUFFER* ppShader,
|
||||
LPD3DXBUFFER* ppErrorMsgs);
|
||||
|
||||
static bool LoadFailed = false;
|
||||
static AssembleShaderFunction pFn = 0;
|
||||
|
||||
if (!pFn && !LoadFailed)
|
||||
{
|
||||
// try to load dll
|
||||
io::path strDllName = "d3dx9_";
|
||||
strDllName += (int)D3DX_SDK_VERSION;
|
||||
strDllName += ".dll";
|
||||
|
||||
HMODULE hMod = LoadLibrary(strDllName.c_str());
|
||||
if (hMod)
|
||||
pFn = (AssembleShaderFunction)GetProcAddress(hMod, "D3DXAssembleShader");
|
||||
|
||||
if (!pFn)
|
||||
{
|
||||
LoadFailed = true;
|
||||
os::Printer::log("Could not load shader function D3DXAssembleShader from dll, shaders disabled",
|
||||
strDllName.c_str(), ELL_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
if (pFn)
|
||||
{
|
||||
// call already loaded function
|
||||
return (*pFn)(pSrcData, SrcDataLen, pDefines, pInclude, Flags, ppShader, ppErrorMsgs);
|
||||
}
|
||||
}
|
||||
#endif // D3DX_SDK_VERSION < 24
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
HRESULT CD3D9ShaderMaterialRenderer::stubD3DXAssembleShaderFromFile(LPCSTR pSrcFile,
|
||||
CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, DWORD Flags,
|
||||
LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs)
|
||||
{
|
||||
// wondering what I'm doing here?
|
||||
// see comment in CD3D9ShaderMaterialRenderer::stubD3DXAssembleShader()
|
||||
|
||||
#if ( D3DX_SDK_VERSION < 24 )
|
||||
// directly link functions, old d3d sdks didn't try to load external dlls
|
||||
// when linking to the d3dx9.lib
|
||||
#ifdef _MSC_VER
|
||||
#pragma comment (lib, "d3dx9.lib")
|
||||
#endif
|
||||
|
||||
// invoke static linked function
|
||||
return D3DXAssembleShaderFromFileA(pSrcFile, pDefines, pInclude, Flags,
|
||||
ppShader, ppErrorMsgs);
|
||||
#else
|
||||
{
|
||||
// try to load shader functions from the dll and print error if failed.
|
||||
|
||||
// D3DXAssembleShaderFromFileA signature
|
||||
typedef HRESULT (WINAPI *AssembleShaderFromFileFunction)(LPCSTR pSrcFile,
|
||||
CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, DWORD Flags,
|
||||
LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs);
|
||||
|
||||
static bool LoadFailed = false;
|
||||
static AssembleShaderFromFileFunction pFn = 0;
|
||||
|
||||
if (!pFn && !LoadFailed)
|
||||
{
|
||||
// try to load dll
|
||||
io::path strDllName = "d3dx9_";
|
||||
strDllName += (int)D3DX_SDK_VERSION;
|
||||
strDllName += ".dll";
|
||||
|
||||
HMODULE hMod = LoadLibrary(strDllName.c_str());
|
||||
if (hMod)
|
||||
pFn = (AssembleShaderFromFileFunction)GetProcAddress(hMod, "D3DXAssembleShaderFromFileA");
|
||||
|
||||
if (!pFn)
|
||||
{
|
||||
LoadFailed = true;
|
||||
os::Printer::log("Could not load shader function D3DXAssembleShaderFromFileA from dll, shaders disabled",
|
||||
strDllName.c_str(), ELL_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
if (pFn)
|
||||
{
|
||||
// call already loaded function
|
||||
return (*pFn)(pSrcFile, pDefines, pInclude, Flags, ppShader, ppErrorMsgs);
|
||||
}
|
||||
}
|
||||
#endif // D3DX_SDK_VERSION < 24
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
HRESULT CD3D9ShaderMaterialRenderer::stubD3DXCompileShader(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines,
|
||||
LPD3DXINCLUDE pInclude, LPCSTR pFunctionName,
|
||||
LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader,
|
||||
LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable)
|
||||
{
|
||||
// wondering what I'm doing here?
|
||||
// see comment in CD3D9ShaderMaterialRenderer::stubD3DXAssembleShader()
|
||||
|
||||
#if ( D3DX_SDK_VERSION < 24 )
|
||||
// directly link functions, old d3d sdks didn't try to load external dlls
|
||||
// when linking to the d3dx9.lib
|
||||
#ifdef _MSC_VER
|
||||
#pragma comment (lib, "d3dx9.lib")
|
||||
#endif
|
||||
|
||||
// invoke static linked function
|
||||
return D3DXCompileShader(pSrcData, SrcDataLen, pDefines, pInclude, pFunctionName, pProfile, Flags, ppShader, ppErrorMsgs, ppConstantTable);
|
||||
#else
|
||||
{
|
||||
// try to load shader functions from the dll and print error if failed.
|
||||
|
||||
// D3DXCompileShader
|
||||
typedef HRESULT (WINAPI *D3DXCompileShaderFunction)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines,
|
||||
LPD3DXINCLUDE pInclude, LPCSTR pFunctionName,
|
||||
LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader,
|
||||
LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
|
||||
|
||||
static bool LoadFailed = false;
|
||||
static D3DXCompileShaderFunction pFn = 0;
|
||||
|
||||
if (!pFn && !LoadFailed)
|
||||
{
|
||||
// try to load dll
|
||||
io::path strDllName = "d3dx9_";
|
||||
strDllName += (int)D3DX_SDK_VERSION;
|
||||
strDllName += ".dll";
|
||||
|
||||
HMODULE hMod = LoadLibrary(strDllName.c_str());
|
||||
if (hMod)
|
||||
pFn = (D3DXCompileShaderFunction)GetProcAddress(hMod, "D3DXCompileShader");
|
||||
|
||||
if (!pFn)
|
||||
{
|
||||
LoadFailed = true;
|
||||
os::Printer::log("Could not load shader function D3DXCompileShader from dll, shaders disabled",
|
||||
strDllName.c_str(), ELL_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
if (pFn)
|
||||
{
|
||||
// call already loaded function
|
||||
return (*pFn)(pSrcData, SrcDataLen, pDefines, pInclude, pFunctionName, pProfile, Flags, ppShader, ppErrorMsgs, ppConstantTable);
|
||||
}
|
||||
}
|
||||
#endif // D3DX_SDK_VERSION < 24
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
HRESULT CD3D9ShaderMaterialRenderer::stubD3DXCompileShaderFromFile(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines,
|
||||
LPD3DXINCLUDE pInclude, LPCSTR pFunctionName,
|
||||
LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs,
|
||||
LPD3DXCONSTANTTABLE* ppConstantTable)
|
||||
{
|
||||
// wondering what I'm doing here?
|
||||
// see comment in CD3D9ShaderMaterialRenderer::stubD3DXAssembleShader()
|
||||
|
||||
#if ( D3DX_SDK_VERSION < 24 )
|
||||
// directly link functions, old d3d sdks didn't try to load external dlls
|
||||
// when linking to the d3dx9.lib
|
||||
#ifdef _MSC_VER
|
||||
#pragma comment (lib, "d3dx9.lib")
|
||||
#endif
|
||||
|
||||
// invoke static linked function
|
||||
return D3DXCompileShaderFromFileA(pSrcFile, pDefines, pInclude, pFunctionName, pProfile, Flags, ppShader, ppErrorMsgs, ppConstantTable);
|
||||
#else
|
||||
{
|
||||
// try to load shader functions from the dll and print error if failed.
|
||||
|
||||
// D3DXCompileShaderFromFileA
|
||||
typedef HRESULT (WINAPI *D3DXCompileShaderFromFileFunction)(LPCSTR pSrcFile,
|
||||
CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName,
|
||||
LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs,
|
||||
LPD3DXCONSTANTTABLE* ppConstantTable);
|
||||
|
||||
static bool LoadFailed = false;
|
||||
static D3DXCompileShaderFromFileFunction pFn = 0;
|
||||
|
||||
if (!pFn && !LoadFailed)
|
||||
{
|
||||
// try to load dll
|
||||
io::path strDllName = "d3dx9_";
|
||||
strDllName += (int)D3DX_SDK_VERSION;
|
||||
strDllName += ".dll";
|
||||
|
||||
HMODULE hMod = LoadLibrary(strDllName.c_str());
|
||||
if (hMod)
|
||||
pFn = (D3DXCompileShaderFromFileFunction)GetProcAddress(hMod, "D3DXCompileShaderFromFileA");
|
||||
|
||||
if (!pFn)
|
||||
{
|
||||
LoadFailed = true;
|
||||
os::Printer::log("Could not load shader function D3DXCompileShaderFromFileA from dll, shaders disabled",
|
||||
strDllName.c_str(), ELL_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
if (pFn)
|
||||
{
|
||||
// call already loaded function
|
||||
return (*pFn)(pSrcFile, pDefines, pInclude, pFunctionName, pProfile, Flags, ppShader, ppErrorMsgs, ppConstantTable);
|
||||
}
|
||||
}
|
||||
#endif // D3DX_SDK_VERSION < 24
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
} // end namespace video
|
||||
} // end namespace irr
|
||||
|
||||
#endif // _IRR_COMPILE_WITH_DIRECT3D_9_
|
102
source/Irrlicht/CD3D9ShaderMaterialRenderer.h
Normal file
102
source/Irrlicht/CD3D9ShaderMaterialRenderer.h
Normal file
@ -0,0 +1,102 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#ifndef __C_D3D9_SHADER_MATERIAL_RENDERER_H_INCLUDED__
|
||||
#define __C_D3D9_SHADER_MATERIAL_RENDERER_H_INCLUDED__
|
||||
|
||||
#include "IrrCompileConfig.h"
|
||||
#ifdef _IRR_WINDOWS_
|
||||
|
||||
#ifdef _IRR_COMPILE_WITH_DIRECT3D_9_
|
||||
#if defined(__BORLANDC__) || defined (__BCPLUSPLUS__)
|
||||
#include "irrMath.h" // needed by borland for sqrtf define
|
||||
#endif
|
||||
#include <d3dx9shader.h>
|
||||
|
||||
#include "IMaterialRenderer.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace video
|
||||
{
|
||||
|
||||
class IVideoDriver;
|
||||
class IShaderConstantSetCallBack;
|
||||
class IMaterialRenderer;
|
||||
|
||||
//! Class for using vertex and pixel shaders with D3D9
|
||||
class CD3D9ShaderMaterialRenderer : public IMaterialRenderer
|
||||
{
|
||||
public:
|
||||
|
||||
//! Public constructor
|
||||
CD3D9ShaderMaterialRenderer(IDirect3DDevice9* d3ddev, video::IVideoDriver* driver,
|
||||
s32& outMaterialTypeNr, const c8* vertexShaderProgram, const c8* pixelShaderProgram,
|
||||
IShaderConstantSetCallBack* callback, IMaterialRenderer* baseMaterial, s32 userData);
|
||||
|
||||
//! Destructor
|
||||
~CD3D9ShaderMaterialRenderer();
|
||||
|
||||
virtual void OnSetMaterial(const video::SMaterial& material, const video::SMaterial& lastMaterial,
|
||||
bool resetAllRenderstates, video::IMaterialRendererServices* services);
|
||||
|
||||
virtual void OnUnsetMaterial();
|
||||
|
||||
virtual bool OnRender(IMaterialRendererServices* service, E_VERTEX_TYPE vtxtype);
|
||||
|
||||
//! Returns if the material is transparent.
|
||||
virtual bool isTransparent() const;
|
||||
|
||||
protected:
|
||||
|
||||
//! constructor only for use by derived classes who want to
|
||||
//! create a fall back material for example.
|
||||
CD3D9ShaderMaterialRenderer(IDirect3DDevice9* d3ddev,
|
||||
video::IVideoDriver* driver,
|
||||
IShaderConstantSetCallBack* callback,
|
||||
IMaterialRenderer* baseMaterial,
|
||||
s32 userData=0);
|
||||
|
||||
void init(s32& outMaterialTypeNr, const c8* vertexShaderProgram, const c8* pixelShaderProgram);
|
||||
bool createPixelShader(const c8* pxsh);
|
||||
bool createVertexShader(const char* vtxsh);
|
||||
|
||||
HRESULT stubD3DXAssembleShader(LPCSTR pSrcData, UINT SrcDataLen,
|
||||
CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude,
|
||||
DWORD Flags, LPD3DXBUFFER* ppShader,
|
||||
LPD3DXBUFFER* ppErrorMsgs);
|
||||
|
||||
HRESULT stubD3DXAssembleShaderFromFile(LPCSTR pSrcFile,
|
||||
CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, DWORD Flags,
|
||||
LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs);
|
||||
|
||||
HRESULT stubD3DXCompileShader(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines,
|
||||
LPD3DXINCLUDE pInclude, LPCSTR pFunctionName,
|
||||
LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader,
|
||||
LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
|
||||
|
||||
HRESULT stubD3DXCompileShaderFromFile(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines,
|
||||
LPD3DXINCLUDE pInclude, LPCSTR pFunctionName,
|
||||
LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs,
|
||||
LPD3DXCONSTANTTABLE* ppConstantTable);
|
||||
|
||||
IDirect3DDevice9* pID3DDevice;
|
||||
video::IVideoDriver* Driver;
|
||||
IShaderConstantSetCallBack* CallBack;
|
||||
IMaterialRenderer* BaseMaterial;
|
||||
|
||||
IDirect3DVertexShader9* VertexShader;
|
||||
IDirect3DVertexShader9* OldVertexShader;
|
||||
IDirect3DPixelShader9* PixelShader;
|
||||
s32 UserData;
|
||||
};
|
||||
|
||||
|
||||
} // end namespace video
|
||||
} // end namespace irr
|
||||
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
699
source/Irrlicht/CD3D9Texture.cpp
Normal file
699
source/Irrlicht/CD3D9Texture.cpp
Normal file
@ -0,0 +1,699 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#include "IrrCompileConfig.h"
|
||||
#ifdef _IRR_COMPILE_WITH_DIRECT3D_9_
|
||||
|
||||
#define _IRR_DONT_DO_MEMORY_DEBUGGING_HERE
|
||||
#include "CD3D9Texture.h"
|
||||
#include "CD3D9Driver.h"
|
||||
#include "os.h"
|
||||
|
||||
#include <d3dx9tex.h>
|
||||
|
||||
#ifndef _IRR_COMPILE_WITH_DIRECT3D_8_
|
||||
// The D3DXFilterTexture function seems to get linked wrong when
|
||||
// compiling with both D3D8 and 9, causing it not to work in the D3D9 device.
|
||||
// So mipmapgeneration is replaced with my own bad generation in d3d 8 when
|
||||
// compiling with both D3D 8 and 9.
|
||||
// #define _IRR_USE_D3DXFilterTexture_
|
||||
#endif // _IRR_COMPILE_WITH_DIRECT3D_8_
|
||||
|
||||
#ifdef _IRR_USE_D3DXFilterTexture_
|
||||
#pragma comment(lib, "d3dx9.lib")
|
||||
#endif
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace video
|
||||
{
|
||||
|
||||
//! rendertarget constructor
|
||||
CD3D9Texture::CD3D9Texture(CD3D9Driver* driver, const core::dimension2d<u32>& size,
|
||||
const io::path& name, const ECOLOR_FORMAT format)
|
||||
: ITexture(name), Texture(0), RTTSurface(0), Driver(driver), DepthSurface(0),
|
||||
TextureSize(size), ImageSize(size), Pitch(0), ColorFormat(ECF_UNKNOWN),
|
||||
HasMipMaps(false), HardwareMipMaps(false), IsRenderTarget(true)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
setDebugName("CD3D9Texture");
|
||||
#endif
|
||||
|
||||
Device=driver->getExposedVideoData().D3D9.D3DDev9;
|
||||
if (Device)
|
||||
Device->AddRef();
|
||||
|
||||
createRenderTarget(format);
|
||||
}
|
||||
|
||||
|
||||
//! constructor
|
||||
CD3D9Texture::CD3D9Texture(IImage* image, CD3D9Driver* driver,
|
||||
u32 flags, const io::path& name, void* mipmapData)
|
||||
: ITexture(name), Texture(0), RTTSurface(0), Driver(driver), DepthSurface(0),
|
||||
TextureSize(0,0), ImageSize(0,0), Pitch(0), ColorFormat(ECF_UNKNOWN),
|
||||
HasMipMaps(false), HardwareMipMaps(false), IsRenderTarget(false)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
setDebugName("CD3D9Texture");
|
||||
#endif
|
||||
|
||||
HasMipMaps = Driver->getTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS);
|
||||
|
||||
Device=driver->getExposedVideoData().D3D9.D3DDev9;
|
||||
if (Device)
|
||||
Device->AddRef();
|
||||
|
||||
if (image)
|
||||
{
|
||||
if (createTexture(flags, image))
|
||||
{
|
||||
if (copyTexture(image))
|
||||
{
|
||||
regenerateMipMapLevels(mipmapData);
|
||||
}
|
||||
}
|
||||
else
|
||||
os::Printer::log("Could not create DIRECT3D9 Texture.", ELL_WARNING);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//! destructor
|
||||
CD3D9Texture::~CD3D9Texture()
|
||||
{
|
||||
if (Texture)
|
||||
Texture->Release();
|
||||
|
||||
if (RTTSurface)
|
||||
RTTSurface->Release();
|
||||
|
||||
// if this texture was the last one using the depth buffer
|
||||
// we can release the surface. We only use the value of the pointer
|
||||
// hence it is safe to use the dropped pointer...
|
||||
if (DepthSurface)
|
||||
{
|
||||
if (DepthSurface->drop())
|
||||
Driver->removeDepthSurface(DepthSurface);
|
||||
}
|
||||
|
||||
if (Device)
|
||||
Device->Release();
|
||||
}
|
||||
|
||||
|
||||
void CD3D9Texture::createRenderTarget(const ECOLOR_FORMAT format)
|
||||
{
|
||||
// are texture size restrictions there ?
|
||||
if(!Driver->queryFeature(EVDF_TEXTURE_NPOT))
|
||||
{
|
||||
if (TextureSize != ImageSize)
|
||||
os::Printer::log("RenderTarget size has to be a power of two", ELL_INFORMATION);
|
||||
}
|
||||
TextureSize = TextureSize.getOptimalSize(!Driver->queryFeature(EVDF_TEXTURE_NPOT), !Driver->queryFeature(EVDF_TEXTURE_NSQUARE), true, Driver->Caps.MaxTextureWidth);
|
||||
|
||||
D3DFORMAT d3dformat = Driver->getD3DColorFormat();
|
||||
|
||||
if(ColorFormat == ECF_UNKNOWN)
|
||||
{
|
||||
// get irrlicht format from backbuffer
|
||||
// (This will get overwritten by the custom format if it is provided, else kept.)
|
||||
ColorFormat = Driver->getColorFormat();
|
||||
setPitch(d3dformat);
|
||||
|
||||
// Use color format if provided.
|
||||
if(format != ECF_UNKNOWN)
|
||||
{
|
||||
ColorFormat = format;
|
||||
d3dformat = Driver->getD3DFormatFromColorFormat(format);
|
||||
setPitch(d3dformat); // This will likely set pitch to 0 for now.
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
d3dformat = Driver->getD3DFormatFromColorFormat(ColorFormat);
|
||||
}
|
||||
|
||||
// create texture
|
||||
HRESULT hr;
|
||||
|
||||
hr = Device->CreateTexture(
|
||||
TextureSize.Width,
|
||||
TextureSize.Height,
|
||||
1, // mip map level count, we don't want mipmaps here
|
||||
D3DUSAGE_RENDERTARGET,
|
||||
d3dformat,
|
||||
D3DPOOL_DEFAULT,
|
||||
&Texture,
|
||||
NULL);
|
||||
|
||||
if (FAILED(hr))
|
||||
{
|
||||
if (D3DERR_INVALIDCALL == hr)
|
||||
os::Printer::log("Could not create render target texture", "Invalid Call");
|
||||
else
|
||||
if (D3DERR_OUTOFVIDEOMEMORY == hr)
|
||||
os::Printer::log("Could not create render target texture", "Out of Video Memory");
|
||||
else
|
||||
if (E_OUTOFMEMORY == hr)
|
||||
os::Printer::log("Could not create render target texture", "Out of Memory");
|
||||
else
|
||||
os::Printer::log("Could not create render target texture");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool CD3D9Texture::createMipMaps(u32 level)
|
||||
{
|
||||
if (level==0)
|
||||
return true;
|
||||
|
||||
if (HardwareMipMaps && Texture)
|
||||
{
|
||||
// generate mipmaps in hardware
|
||||
Texture->GenerateMipSubLevels();
|
||||
return true;
|
||||
}
|
||||
|
||||
// manual mipmap generation
|
||||
IDirect3DSurface9* upperSurface = 0;
|
||||
IDirect3DSurface9* lowerSurface = 0;
|
||||
|
||||
// get upper level
|
||||
HRESULT hr = Texture->GetSurfaceLevel(level-1, &upperSurface);
|
||||
if (FAILED(hr) || !upperSurface)
|
||||
{
|
||||
os::Printer::log("Could not get upper surface level for mip map generation", ELL_WARNING);
|
||||
return false;
|
||||
}
|
||||
|
||||
// get lower level
|
||||
hr = Texture->GetSurfaceLevel(level, &lowerSurface);
|
||||
if (FAILED(hr) || !lowerSurface)
|
||||
{
|
||||
os::Printer::log("Could not get lower surface level for mip map generation", ELL_WARNING);
|
||||
upperSurface->Release();
|
||||
return false;
|
||||
}
|
||||
|
||||
D3DSURFACE_DESC upperDesc, lowerDesc;
|
||||
upperSurface->GetDesc(&upperDesc);
|
||||
lowerSurface->GetDesc(&lowerDesc);
|
||||
|
||||
D3DLOCKED_RECT upperlr;
|
||||
D3DLOCKED_RECT lowerlr;
|
||||
|
||||
// lock upper surface
|
||||
if (FAILED(upperSurface->LockRect(&upperlr, NULL, 0)))
|
||||
{
|
||||
upperSurface->Release();
|
||||
lowerSurface->Release();
|
||||
os::Printer::log("Could not lock upper texture for mip map generation", ELL_WARNING);
|
||||
return false;
|
||||
}
|
||||
|
||||
// lock lower surface
|
||||
if (FAILED(lowerSurface->LockRect(&lowerlr, NULL, 0)))
|
||||
{
|
||||
upperSurface->UnlockRect();
|
||||
upperSurface->Release();
|
||||
lowerSurface->Release();
|
||||
os::Printer::log("Could not lock lower texture for mip map generation", ELL_WARNING);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (upperDesc.Format != lowerDesc.Format)
|
||||
{
|
||||
os::Printer::log("Cannot copy mip maps with different formats.", ELL_WARNING);
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((upperDesc.Format == D3DFMT_A1R5G5B5) || (upperDesc.Format == D3DFMT_R5G6B5))
|
||||
copy16BitMipMap((char*)upperlr.pBits, (char*)lowerlr.pBits,
|
||||
lowerDesc.Width, lowerDesc.Height,
|
||||
upperlr.Pitch, lowerlr.Pitch);
|
||||
else
|
||||
if (upperDesc.Format == D3DFMT_A8R8G8B8)
|
||||
copy32BitMipMap((char*)upperlr.pBits, (char*)lowerlr.pBits,
|
||||
lowerDesc.Width, lowerDesc.Height,
|
||||
upperlr.Pitch, lowerlr.Pitch);
|
||||
else
|
||||
os::Printer::log("Unsupported mipmap format, cannot copy.", ELL_WARNING);
|
||||
}
|
||||
|
||||
bool result=true;
|
||||
// unlock
|
||||
if (FAILED(upperSurface->UnlockRect()))
|
||||
result=false;
|
||||
if (FAILED(lowerSurface->UnlockRect()))
|
||||
result=false;
|
||||
|
||||
// release
|
||||
upperSurface->Release();
|
||||
lowerSurface->Release();
|
||||
|
||||
if (!result || (upperDesc.Width <= 3 && upperDesc.Height <= 3))
|
||||
return result; // stop generating levels
|
||||
|
||||
// generate next level
|
||||
return createMipMaps(level+1);
|
||||
}
|
||||
|
||||
|
||||
//! creates the hardware texture
|
||||
bool CD3D9Texture::createTexture(u32 flags, IImage * image)
|
||||
{
|
||||
ImageSize = image->getDimension();
|
||||
|
||||
core::dimension2d<u32> optSize = ImageSize.getOptimalSize(!Driver->queryFeature(EVDF_TEXTURE_NPOT), !Driver->queryFeature(EVDF_TEXTURE_NSQUARE), true, Driver->Caps.MaxTextureWidth);
|
||||
|
||||
D3DFORMAT format = D3DFMT_A1R5G5B5;
|
||||
|
||||
switch(getTextureFormatFromFlags(flags))
|
||||
{
|
||||
case ETCF_ALWAYS_16_BIT:
|
||||
format = D3DFMT_A1R5G5B5; break;
|
||||
case ETCF_ALWAYS_32_BIT:
|
||||
format = D3DFMT_A8R8G8B8; break;
|
||||
case ETCF_OPTIMIZED_FOR_QUALITY:
|
||||
{
|
||||
switch(image->getColorFormat())
|
||||
{
|
||||
case ECF_R8G8B8:
|
||||
case ECF_A8R8G8B8:
|
||||
format = D3DFMT_A8R8G8B8; break;
|
||||
case ECF_A1R5G5B5:
|
||||
case ECF_R5G6B5:
|
||||
format = D3DFMT_A1R5G5B5; break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case ETCF_OPTIMIZED_FOR_SPEED:
|
||||
format = D3DFMT_A1R5G5B5;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (Driver->getTextureCreationFlag(video::ETCF_NO_ALPHA_CHANNEL))
|
||||
{
|
||||
if (format == D3DFMT_A8R8G8B8)
|
||||
format = D3DFMT_R8G8B8;
|
||||
else if (format == D3DFMT_A1R5G5B5)
|
||||
format = D3DFMT_R5G6B5;
|
||||
}
|
||||
|
||||
const bool mipmaps = Driver->getTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS);
|
||||
|
||||
DWORD usage = 0;
|
||||
|
||||
// This enables hardware mip map generation.
|
||||
if (mipmaps && Driver->queryFeature(EVDF_MIP_MAP_AUTO_UPDATE))
|
||||
{
|
||||
LPDIRECT3D9 intf = Driver->getExposedVideoData().D3D9.D3D9;
|
||||
D3DDISPLAYMODE d3ddm;
|
||||
intf->GetAdapterDisplayMode(Driver->Params.DisplayAdapter, &d3ddm);
|
||||
|
||||
if (D3D_OK==intf->CheckDeviceFormat(Driver->Params.DisplayAdapter,D3DDEVTYPE_HAL,d3ddm.Format,D3DUSAGE_AUTOGENMIPMAP,D3DRTYPE_TEXTURE,format))
|
||||
{
|
||||
usage = D3DUSAGE_AUTOGENMIPMAP;
|
||||
HardwareMipMaps = true;
|
||||
}
|
||||
}
|
||||
|
||||
HRESULT hr = Device->CreateTexture(optSize.Width, optSize.Height,
|
||||
mipmaps ? 0 : 1, // number of mipmaplevels (0 = automatic all)
|
||||
usage, // usage
|
||||
format, D3DPOOL_MANAGED , &Texture, NULL);
|
||||
|
||||
if (FAILED(hr))
|
||||
{
|
||||
// try brute force 16 bit
|
||||
HardwareMipMaps = false;
|
||||
if (format == D3DFMT_A8R8G8B8)
|
||||
format = D3DFMT_A1R5G5B5;
|
||||
else if (format == D3DFMT_R8G8B8)
|
||||
format = D3DFMT_R5G6B5;
|
||||
else
|
||||
return false;
|
||||
|
||||
hr = Device->CreateTexture(optSize.Width, optSize.Height,
|
||||
mipmaps ? 0 : 1, // number of mipmaplevels (0 = automatic all)
|
||||
0, format, D3DPOOL_MANAGED, &Texture, NULL);
|
||||
}
|
||||
|
||||
ColorFormat = Driver->getColorFormatFromD3DFormat(format);
|
||||
setPitch(format);
|
||||
return (SUCCEEDED(hr));
|
||||
}
|
||||
|
||||
|
||||
//! copies the image to the texture
|
||||
bool CD3D9Texture::copyTexture(IImage * image)
|
||||
{
|
||||
if (Texture && image)
|
||||
{
|
||||
D3DSURFACE_DESC desc;
|
||||
Texture->GetLevelDesc(0, &desc);
|
||||
|
||||
TextureSize.Width = desc.Width;
|
||||
TextureSize.Height = desc.Height;
|
||||
|
||||
D3DLOCKED_RECT rect;
|
||||
HRESULT hr = Texture->LockRect(0, &rect, 0, 0);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
os::Printer::log("Texture data not copied", "Could not LockRect D3D9 Texture.", ELL_ERROR);
|
||||
return false;
|
||||
}
|
||||
|
||||
Pitch = rect.Pitch;
|
||||
image->copyToScaling(rect.pBits, TextureSize.Width, TextureSize.Height, ColorFormat, Pitch);
|
||||
|
||||
hr = Texture->UnlockRect(0);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
os::Printer::log("Texture data not copied", "Could not UnlockRect D3D9 Texture.", ELL_ERROR);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
//! lock function
|
||||
void* CD3D9Texture::lock(E_TEXTURE_LOCK_MODE mode, u32 mipmapLevel)
|
||||
{
|
||||
if (!Texture)
|
||||
return 0;
|
||||
|
||||
MipLevelLocked=mipmapLevel;
|
||||
HRESULT hr;
|
||||
D3DLOCKED_RECT rect;
|
||||
if(!IsRenderTarget)
|
||||
{
|
||||
hr = Texture->LockRect(mipmapLevel, &rect, 0, (mode==ETLM_READ_ONLY)?D3DLOCK_READONLY:0);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
os::Printer::log("Could not lock DIRECT3D9 Texture.", ELL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!RTTSurface)
|
||||
{
|
||||
// Make RTT surface large enough for all miplevels (including 0)
|
||||
D3DSURFACE_DESC desc;
|
||||
Texture->GetLevelDesc(0, &desc);
|
||||
hr = Device->CreateOffscreenPlainSurface(desc.Width, desc.Height, desc.Format, D3DPOOL_SYSTEMMEM, &RTTSurface, 0);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
os::Printer::log("Could not lock DIRECT3D9 Texture", "Offscreen surface creation failed.", ELL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
IDirect3DSurface9 *surface = 0;
|
||||
hr = Texture->GetSurfaceLevel(mipmapLevel, &surface);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
os::Printer::log("Could not lock DIRECT3D9 Texture", "Could not get surface.", ELL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
hr = Device->GetRenderTargetData(surface, RTTSurface);
|
||||
surface->Release();
|
||||
if(FAILED(hr))
|
||||
{
|
||||
os::Printer::log("Could not lock DIRECT3D9 Texture", "Data copy failed.", ELL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
hr = RTTSurface->LockRect(&rect, 0, (mode==ETLM_READ_ONLY)?D3DLOCK_READONLY:0);
|
||||
if(FAILED(hr))
|
||||
{
|
||||
os::Printer::log("Could not lock DIRECT3D9 Texture", "LockRect failed.", ELL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return rect.pBits;
|
||||
}
|
||||
|
||||
|
||||
//! unlock function
|
||||
void CD3D9Texture::unlock()
|
||||
{
|
||||
if (!Texture)
|
||||
return;
|
||||
|
||||
if (!IsRenderTarget)
|
||||
Texture->UnlockRect(MipLevelLocked);
|
||||
else if (RTTSurface)
|
||||
RTTSurface->UnlockRect();
|
||||
}
|
||||
|
||||
|
||||
//! Returns original size of the texture.
|
||||
const core::dimension2d<u32>& CD3D9Texture::getOriginalSize() const
|
||||
{
|
||||
return ImageSize;
|
||||
}
|
||||
|
||||
|
||||
//! Returns (=size) of the texture.
|
||||
const core::dimension2d<u32>& CD3D9Texture::getSize() const
|
||||
{
|
||||
return TextureSize;
|
||||
}
|
||||
|
||||
|
||||
//! returns driver type of texture (=the driver, who created the texture)
|
||||
E_DRIVER_TYPE CD3D9Texture::getDriverType() const
|
||||
{
|
||||
return EDT_DIRECT3D9;
|
||||
}
|
||||
|
||||
|
||||
//! returns color format of texture
|
||||
ECOLOR_FORMAT CD3D9Texture::getColorFormat() const
|
||||
{
|
||||
return ColorFormat;
|
||||
}
|
||||
|
||||
|
||||
//! returns pitch of texture (in bytes)
|
||||
u32 CD3D9Texture::getPitch() const
|
||||
{
|
||||
return Pitch;
|
||||
}
|
||||
|
||||
|
||||
//! returns the DIRECT3D9 Texture
|
||||
IDirect3DBaseTexture9* CD3D9Texture::getDX9Texture() const
|
||||
{
|
||||
return Texture;
|
||||
}
|
||||
|
||||
|
||||
//! returns if texture has mipmap levels
|
||||
bool CD3D9Texture::hasMipMaps() const
|
||||
{
|
||||
return HasMipMaps;
|
||||
}
|
||||
|
||||
|
||||
void CD3D9Texture::copy16BitMipMap(char* src, char* tgt,
|
||||
s32 width, s32 height,
|
||||
s32 pitchsrc, s32 pitchtgt) const
|
||||
{
|
||||
for (s32 y=0; y<height; ++y)
|
||||
{
|
||||
for (s32 x=0; x<width; ++x)
|
||||
{
|
||||
u32 a=0, r=0, g=0, b=0;
|
||||
|
||||
for (s32 dy=0; dy<2; ++dy)
|
||||
{
|
||||
const s32 tgy = (y*2)+dy;
|
||||
for (s32 dx=0; dx<2; ++dx)
|
||||
{
|
||||
const s32 tgx = (x*2)+dx;
|
||||
|
||||
SColor c;
|
||||
if (ColorFormat == ECF_A1R5G5B5)
|
||||
c = A1R5G5B5toA8R8G8B8(*(u16*)(&src[(tgx*2)+(tgy*pitchsrc)]));
|
||||
else
|
||||
c = R5G6B5toA8R8G8B8(*(u16*)(&src[(tgx*2)+(tgy*pitchsrc)]));
|
||||
|
||||
a += c.getAlpha();
|
||||
r += c.getRed();
|
||||
g += c.getGreen();
|
||||
b += c.getBlue();
|
||||
}
|
||||
}
|
||||
|
||||
a /= 4;
|
||||
r /= 4;
|
||||
g /= 4;
|
||||
b /= 4;
|
||||
|
||||
u16 c;
|
||||
if (ColorFormat == ECF_A1R5G5B5)
|
||||
c = RGBA16(r,g,b,a);
|
||||
else
|
||||
c = A8R8G8B8toR5G6B5(SColor(a,r,g,b).color);
|
||||
*(u16*)(&tgt[(x*2)+(y*pitchtgt)]) = c;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CD3D9Texture::copy32BitMipMap(char* src, char* tgt,
|
||||
s32 width, s32 height,
|
||||
s32 pitchsrc, s32 pitchtgt) const
|
||||
{
|
||||
for (s32 y=0; y<height; ++y)
|
||||
{
|
||||
for (s32 x=0; x<width; ++x)
|
||||
{
|
||||
u32 a=0, r=0, g=0, b=0;
|
||||
SColor c;
|
||||
|
||||
for (s32 dy=0; dy<2; ++dy)
|
||||
{
|
||||
const s32 tgy = (y*2)+dy;
|
||||
for (s32 dx=0; dx<2; ++dx)
|
||||
{
|
||||
const s32 tgx = (x*2)+dx;
|
||||
|
||||
c = *(u32*)(&src[(tgx*4)+(tgy*pitchsrc)]);
|
||||
|
||||
a += c.getAlpha();
|
||||
r += c.getRed();
|
||||
g += c.getGreen();
|
||||
b += c.getBlue();
|
||||
}
|
||||
}
|
||||
|
||||
a /= 4;
|
||||
r /= 4;
|
||||
g /= 4;
|
||||
b /= 4;
|
||||
|
||||
c.set(a, r, g, b);
|
||||
*(u32*)(&tgt[(x*4)+(y*pitchtgt)]) = c.color;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//! Regenerates the mip map levels of the texture. Useful after locking and
|
||||
//! modifying the texture
|
||||
void CD3D9Texture::regenerateMipMapLevels(void* mipmapData)
|
||||
{
|
||||
if (mipmapData)
|
||||
{
|
||||
core::dimension2du size = TextureSize;
|
||||
u32 level=0;
|
||||
do
|
||||
{
|
||||
if (size.Width>1)
|
||||
size.Width /=2;
|
||||
if (size.Height>1)
|
||||
size.Height /=2;
|
||||
++level;
|
||||
IDirect3DSurface9* mipSurface = 0;
|
||||
HRESULT hr = Texture->GetSurfaceLevel(level, &mipSurface);
|
||||
if (FAILED(hr) || !mipSurface)
|
||||
{
|
||||
os::Printer::log("Could not get mipmap level", ELL_WARNING);
|
||||
return;
|
||||
}
|
||||
D3DSURFACE_DESC mipDesc;
|
||||
mipSurface->GetDesc(&mipDesc);
|
||||
D3DLOCKED_RECT miplr;
|
||||
|
||||
// lock mipmap surface
|
||||
if (FAILED(mipSurface->LockRect(&miplr, NULL, 0)))
|
||||
{
|
||||
mipSurface->Release();
|
||||
os::Printer::log("Could not lock texture", ELL_WARNING);
|
||||
return;
|
||||
}
|
||||
|
||||
memcpy(miplr.pBits, mipmapData, size.getArea()*getPitch()/TextureSize.Width);
|
||||
mipmapData = (u8*)mipmapData+size.getArea()*getPitch()/TextureSize.Width;
|
||||
// unlock
|
||||
mipSurface->UnlockRect();
|
||||
// release
|
||||
mipSurface->Release();
|
||||
} while (size.Width != 1 || size.Height != 1);
|
||||
}
|
||||
else if (HasMipMaps)
|
||||
{
|
||||
// create mip maps.
|
||||
#ifdef _IRR_USE_D3DXFilterTexture_
|
||||
// The D3DXFilterTexture function seems to get linked wrong when
|
||||
// compiling with both D3D8 and 9, causing it not to work in the D3D9 device.
|
||||
// So mipmapgeneration is replaced with my own bad generation
|
||||
HRESULT hr = D3DXFilterTexture(Texture, NULL, D3DX_DEFAULT, D3DX_DEFAULT);
|
||||
if (FAILED(hr))
|
||||
#endif
|
||||
createMipMaps();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//! returns if it is a render target
|
||||
bool CD3D9Texture::isRenderTarget() const
|
||||
{
|
||||
return IsRenderTarget;
|
||||
}
|
||||
|
||||
|
||||
//! Returns pointer to the render target surface
|
||||
IDirect3DSurface9* CD3D9Texture::getRenderTargetSurface()
|
||||
{
|
||||
if (!IsRenderTarget)
|
||||
return 0;
|
||||
|
||||
IDirect3DSurface9 *pRTTSurface = 0;
|
||||
if (Texture)
|
||||
Texture->GetSurfaceLevel(0, &pRTTSurface);
|
||||
|
||||
if (pRTTSurface)
|
||||
pRTTSurface->Release();
|
||||
|
||||
return pRTTSurface;
|
||||
}
|
||||
|
||||
|
||||
void CD3D9Texture::setPitch(D3DFORMAT d3dformat)
|
||||
{
|
||||
switch(d3dformat)
|
||||
{
|
||||
case D3DFMT_X1R5G5B5:
|
||||
case D3DFMT_A1R5G5B5:
|
||||
Pitch = TextureSize.Width * 2;
|
||||
break;
|
||||
case D3DFMT_A8B8G8R8:
|
||||
case D3DFMT_A8R8G8B8:
|
||||
case D3DFMT_X8R8G8B8:
|
||||
Pitch = TextureSize.Width * 4;
|
||||
break;
|
||||
case D3DFMT_R5G6B5:
|
||||
Pitch = TextureSize.Width * 2;
|
||||
break;
|
||||
case D3DFMT_R8G8B8:
|
||||
Pitch = TextureSize.Width * 3;
|
||||
break;
|
||||
default:
|
||||
Pitch = 0;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
} // end namespace video
|
||||
} // end namespace irr
|
||||
|
||||
#endif // _IRR_COMPILE_WITH_DIRECT3D_9_
|
130
source/Irrlicht/CD3D9Texture.h
Normal file
130
source/Irrlicht/CD3D9Texture.h
Normal file
@ -0,0 +1,130 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#ifndef __C_DIRECTX9_TEXTURE_H_INCLUDED__
|
||||
#define __C_DIRECTX9_TEXTURE_H_INCLUDED__
|
||||
|
||||
#include "IrrCompileConfig.h"
|
||||
#ifdef _IRR_COMPILE_WITH_DIRECT3D_9_
|
||||
|
||||
#include "ITexture.h"
|
||||
#include "IImage.h"
|
||||
#if defined(__BORLANDC__) || defined (__BCPLUSPLUS__)
|
||||
#include "irrMath.h" // needed by borland for sqrtf define
|
||||
#endif
|
||||
#include <d3d9.h>
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace video
|
||||
{
|
||||
|
||||
class CD3D9Driver;
|
||||
// forward declaration for RTT depth buffer handling
|
||||
struct SDepthSurface;
|
||||
/*!
|
||||
interface for a Video Driver dependent Texture.
|
||||
*/
|
||||
class CD3D9Texture : public ITexture
|
||||
{
|
||||
public:
|
||||
|
||||
//! constructor
|
||||
CD3D9Texture(IImage* image, CD3D9Driver* driver,
|
||||
u32 flags, const io::path& name, void* mipmapData=0);
|
||||
|
||||
//! rendertarget constructor
|
||||
CD3D9Texture(CD3D9Driver* driver, const core::dimension2d<u32>& size, const io::path& name,
|
||||
const ECOLOR_FORMAT format = ECF_UNKNOWN);
|
||||
|
||||
//! destructor
|
||||
virtual ~CD3D9Texture();
|
||||
|
||||
//! lock function
|
||||
virtual void* lock(E_TEXTURE_LOCK_MODE mode=ETLM_READ_WRITE, u32 mipmapLevel=0);
|
||||
|
||||
//! unlock function
|
||||
virtual void unlock();
|
||||
|
||||
//! Returns original size of the texture.
|
||||
virtual const core::dimension2d<u32>& getOriginalSize() const;
|
||||
|
||||
//! Returns (=size) of the texture.
|
||||
virtual const core::dimension2d<u32>& getSize() const;
|
||||
|
||||
//! returns driver type of texture (=the driver, who created the texture)
|
||||
virtual E_DRIVER_TYPE getDriverType() const;
|
||||
|
||||
//! returns color format of texture
|
||||
virtual ECOLOR_FORMAT getColorFormat() const;
|
||||
|
||||
//! returns pitch of texture (in bytes)
|
||||
virtual u32 getPitch() const;
|
||||
|
||||
//! returns the DIRECT3D9 Texture
|
||||
IDirect3DBaseTexture9* getDX9Texture() const;
|
||||
|
||||
//! returns if texture has mipmap levels
|
||||
bool hasMipMaps() const;
|
||||
|
||||
//! Regenerates the mip map levels of the texture. Useful after locking and
|
||||
//! modifying the texture
|
||||
virtual void regenerateMipMapLevels(void* mipmapData=0);
|
||||
|
||||
//! returns if it is a render target
|
||||
virtual bool isRenderTarget() const;
|
||||
|
||||
//! Returns pointer to the render target surface
|
||||
IDirect3DSurface9* getRenderTargetSurface();
|
||||
|
||||
private:
|
||||
friend class CD3D9Driver;
|
||||
|
||||
void createRenderTarget(const ECOLOR_FORMAT format = ECF_UNKNOWN);
|
||||
|
||||
//! creates the hardware texture
|
||||
bool createTexture(u32 flags, IImage * image);
|
||||
|
||||
//! copies the image to the texture
|
||||
bool copyTexture(IImage * image);
|
||||
|
||||
//! Helper function for mipmap generation.
|
||||
bool createMipMaps(u32 level=1);
|
||||
|
||||
//! Helper function for mipmap generation.
|
||||
void copy16BitMipMap(char* src, char* tgt,
|
||||
s32 width, s32 height, s32 pitchsrc, s32 pitchtgt) const;
|
||||
|
||||
//! Helper function for mipmap generation.
|
||||
void copy32BitMipMap(char* src, char* tgt,
|
||||
s32 width, s32 height, s32 pitchsrc, s32 pitchtgt) const;
|
||||
|
||||
//! set Pitch based on the d3d format
|
||||
void setPitch(D3DFORMAT d3dformat);
|
||||
|
||||
IDirect3DDevice9* Device;
|
||||
IDirect3DTexture9* Texture;
|
||||
IDirect3DSurface9* RTTSurface;
|
||||
CD3D9Driver* Driver;
|
||||
SDepthSurface* DepthSurface;
|
||||
core::dimension2d<u32> TextureSize;
|
||||
core::dimension2d<u32> ImageSize;
|
||||
s32 Pitch;
|
||||
u32 MipLevelLocked;
|
||||
ECOLOR_FORMAT ColorFormat;
|
||||
|
||||
bool HasMipMaps;
|
||||
bool HardwareMipMaps;
|
||||
bool IsRenderTarget;
|
||||
};
|
||||
|
||||
|
||||
} // end namespace video
|
||||
} // end namespace irr
|
||||
|
||||
#endif // _IRR_COMPILE_WITH_DIRECT3D_9_
|
||||
|
||||
#endif // __C_DIRECTX9_TEXTURE_H_INCLUDED__
|
||||
|
||||
|
436
source/Irrlicht/CDMFLoader.cpp
Normal file
436
source/Irrlicht/CDMFLoader.cpp
Normal file
@ -0,0 +1,436 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
//
|
||||
// This file was originally written by Salvatore Russo.
|
||||
// I (Nikolaus Gebhardt) did some minor modifications and changes to it and
|
||||
// integrated it into Irrlicht.
|
||||
// Thanks a lot to Salvatore for his work on this and that he gave me
|
||||
// his permission to add it into Irrlicht using the zlib license.
|
||||
/*
|
||||
CDMFLoader by Salvatore Russo (September 2005)
|
||||
|
||||
See the header file for additional information including use and distribution rights.
|
||||
*/
|
||||
|
||||
#include "IrrCompileConfig.h"
|
||||
#ifdef _IRR_COMPILE_WITH_DMF_LOADER_
|
||||
|
||||
#ifdef _DEBUG
|
||||
#define _IRR_DMF_DEBUG_
|
||||
#include "os.h"
|
||||
#endif
|
||||
|
||||
#include "CDMFLoader.h"
|
||||
#include "ISceneManager.h"
|
||||
#include "IAttributes.h"
|
||||
#include "SAnimatedMesh.h"
|
||||
#include "SSkinMeshBuffer.h"
|
||||
#include "irrString.h"
|
||||
#include "irrMath.h"
|
||||
#include "dmfsupport.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace scene
|
||||
{
|
||||
|
||||
/** Constructor*/
|
||||
CDMFLoader::CDMFLoader(ISceneManager* smgr, io::IFileSystem* filesys)
|
||||
: SceneMgr(smgr), FileSystem(filesys)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
IReferenceCounted::setDebugName("CDMFLoader");
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void CDMFLoader::findFile(bool use_mat_dirs, const core::stringc& path, const core::stringc& matPath, core::stringc& filename)
|
||||
{
|
||||
// path + texpath + full name
|
||||
if (use_mat_dirs && FileSystem->existFile(path+matPath+filename))
|
||||
filename = path+matPath+filename;
|
||||
// path + full name
|
||||
else if (FileSystem->existFile(path+filename))
|
||||
filename = path+filename;
|
||||
// path + texpath + base name
|
||||
else if (use_mat_dirs && FileSystem->existFile(path+matPath+FileSystem->getFileBasename(filename)))
|
||||
filename = path+matPath+FileSystem->getFileBasename(filename);
|
||||
// path + base name
|
||||
else if (FileSystem->existFile(path+FileSystem->getFileBasename(filename)))
|
||||
filename = path+FileSystem->getFileBasename(filename);
|
||||
// texpath + full name
|
||||
else if (use_mat_dirs && FileSystem->existFile(matPath+filename))
|
||||
filename = matPath+filename;
|
||||
// texpath + base name
|
||||
else if (use_mat_dirs && FileSystem->existFile(matPath+FileSystem->getFileBasename(filename)))
|
||||
filename = matPath+FileSystem->getFileBasename(filename);
|
||||
// base name
|
||||
else if (FileSystem->existFile(FileSystem->getFileBasename(filename)))
|
||||
filename = FileSystem->getFileBasename(filename);
|
||||
}
|
||||
|
||||
|
||||
/**Creates/loads an animated mesh from the file.
|
||||
\return Pointer to the created mesh. Returns 0 if loading failed.
|
||||
If you no longer need the mesh, you should call IAnimatedMesh::drop().
|
||||
See IReferenceCounted::drop() for more information.*/
|
||||
IAnimatedMesh* CDMFLoader::createMesh(io::IReadFile* file)
|
||||
{
|
||||
if (!file)
|
||||
return 0;
|
||||
video::IVideoDriver* driver = SceneMgr->getVideoDriver();
|
||||
|
||||
//Load stringlist
|
||||
StringList dmfRawFile;
|
||||
LoadFromFile(file, dmfRawFile);
|
||||
|
||||
if (dmfRawFile.size()==0)
|
||||
return 0;
|
||||
|
||||
SMesh * mesh = new SMesh();
|
||||
|
||||
u32 i;
|
||||
|
||||
dmfHeader header;
|
||||
|
||||
//load header
|
||||
core::array<dmfMaterial> materiali;
|
||||
if (GetDMFHeader(dmfRawFile, header))
|
||||
{
|
||||
//let's set ambient light
|
||||
SceneMgr->setAmbientLight(header.dmfAmbient);
|
||||
|
||||
//let's create the correct number of materials, vertices and faces
|
||||
dmfVert *verts=new dmfVert[header.numVertices];
|
||||
dmfFace *faces=new dmfFace[header.numFaces];
|
||||
|
||||
//let's get the materials
|
||||
#ifdef _IRR_DMF_DEBUG_
|
||||
os::Printer::log("Loading materials", core::stringc(header.numMaterials).c_str());
|
||||
#endif
|
||||
GetDMFMaterials(dmfRawFile, materiali, header.numMaterials);
|
||||
|
||||
//let's get vertices and faces
|
||||
#ifdef _IRR_DMF_DEBUG_
|
||||
os::Printer::log("Loading geometry");
|
||||
#endif
|
||||
GetDMFVerticesFaces(dmfRawFile, verts, faces);
|
||||
|
||||
//create a meshbuffer for each material, then we'll remove empty ones
|
||||
#ifdef _IRR_DMF_DEBUG_
|
||||
os::Printer::log("Creating meshbuffers.");
|
||||
#endif
|
||||
for (i=0; i<header.numMaterials; i++)
|
||||
{
|
||||
//create a new SMeshBufferLightMap for each material
|
||||
SSkinMeshBuffer* buffer = new SSkinMeshBuffer();
|
||||
buffer->Material.MaterialType = video::EMT_LIGHTMAP_LIGHTING;
|
||||
buffer->Material.Wireframe = false;
|
||||
buffer->Material.Lighting = true;
|
||||
mesh->addMeshBuffer(buffer);
|
||||
buffer->drop();
|
||||
}
|
||||
|
||||
// Build the mesh buffers
|
||||
#ifdef _IRR_DMF_DEBUG_
|
||||
os::Printer::log("Adding geometry to mesh.");
|
||||
#endif
|
||||
for (i = 0; i < header.numFaces; i++)
|
||||
{
|
||||
#ifdef _IRR_DMF_DEBUG_
|
||||
os::Printer::log("Polygon with #vertices", core::stringc(faces[i].numVerts).c_str());
|
||||
#endif
|
||||
if (faces[i].numVerts < 3)
|
||||
continue;
|
||||
|
||||
const core::vector3df normal =
|
||||
core::triangle3df(verts[faces[i].firstVert].pos,
|
||||
verts[faces[i].firstVert+1].pos,
|
||||
verts[faces[i].firstVert+2].pos).getNormal().normalize();
|
||||
|
||||
SSkinMeshBuffer* meshBuffer = (SSkinMeshBuffer*)mesh->getMeshBuffer(
|
||||
faces[i].materialID);
|
||||
|
||||
const bool use2TCoords = meshBuffer->Vertices_2TCoords.size() ||
|
||||
materiali[faces[i].materialID].lightmapName.size();
|
||||
if (use2TCoords && meshBuffer->Vertices_Standard.size())
|
||||
meshBuffer->convertTo2TCoords();
|
||||
const u32 base = meshBuffer->Vertices_2TCoords.size()?meshBuffer->Vertices_2TCoords.size():meshBuffer->Vertices_Standard.size();
|
||||
|
||||
// Add this face's verts
|
||||
if (use2TCoords)
|
||||
{
|
||||
// make sure we have the proper type set
|
||||
meshBuffer->VertexType=video::EVT_2TCOORDS;
|
||||
for (u32 v = 0; v < faces[i].numVerts; v++)
|
||||
{
|
||||
const dmfVert& vv = verts[faces[i].firstVert + v];
|
||||
video::S3DVertex2TCoords vert(vv.pos,
|
||||
normal, video::SColor(255,255,255,255), vv.tc, vv.lc);
|
||||
if (materiali[faces[i].materialID].textureBlend==4 &&
|
||||
SceneMgr->getParameters()->getAttributeAsBool(DMF_FLIP_ALPHA_TEXTURES))
|
||||
{
|
||||
vert.TCoords.set(vv.tc.X,-vv.tc.Y);
|
||||
}
|
||||
meshBuffer->Vertices_2TCoords.push_back(vert);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (u32 v = 0; v < faces[i].numVerts; v++)
|
||||
{
|
||||
const dmfVert& vv = verts[faces[i].firstVert + v];
|
||||
video::S3DVertex vert(vv.pos,
|
||||
normal, video::SColor(255,255,255,255), vv.tc);
|
||||
if (materiali[faces[i].materialID].textureBlend==4 &&
|
||||
SceneMgr->getParameters()->getAttributeAsBool(DMF_FLIP_ALPHA_TEXTURES))
|
||||
{
|
||||
vert.TCoords.set(vv.tc.X,-vv.tc.Y);
|
||||
}
|
||||
meshBuffer->Vertices_Standard.push_back(vert);
|
||||
}
|
||||
}
|
||||
|
||||
// Now add the indices
|
||||
// This weird loop turns convex polygons into triangle strips.
|
||||
// I do it this way instead of a simple fan because it usually
|
||||
// looks a lot better in wireframe, for example.
|
||||
u32 h = faces[i].numVerts - 1, l = 0, c; // High, Low, Center
|
||||
for (u32 v = 0; v < faces[i].numVerts - 2; v++)
|
||||
{
|
||||
if (v & 1) // odd
|
||||
c = h - 1;
|
||||
else // even
|
||||
c = l + 1;
|
||||
|
||||
meshBuffer->Indices.push_back(base + h);
|
||||
meshBuffer->Indices.push_back(base + l);
|
||||
meshBuffer->Indices.push_back(base + c);
|
||||
|
||||
if (v & 1) // odd
|
||||
h--;
|
||||
else // even
|
||||
l++;
|
||||
}
|
||||
}
|
||||
|
||||
delete [] verts;
|
||||
delete [] faces;
|
||||
}
|
||||
|
||||
// delete all buffers without geometry in it.
|
||||
#ifdef _IRR_DMF_DEBUG_
|
||||
os::Printer::log("Cleaning meshbuffers.");
|
||||
#endif
|
||||
i = 0;
|
||||
while(i < mesh->MeshBuffers.size())
|
||||
{
|
||||
if (mesh->MeshBuffers[i]->getVertexCount() == 0 ||
|
||||
mesh->MeshBuffers[i]->getIndexCount() == 0)
|
||||
{
|
||||
// Meshbuffer is empty -- drop it
|
||||
mesh->MeshBuffers[i]->drop();
|
||||
mesh->MeshBuffers.erase(i);
|
||||
materiali.erase(i);
|
||||
}
|
||||
else
|
||||
{
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
{
|
||||
//load textures and lightmaps in materials.
|
||||
//don't worry if you receive a could not load texture, cause if you don't need
|
||||
//a particular material in your scene it will be loaded and then destroyed.
|
||||
#ifdef _IRR_DMF_DEBUG_
|
||||
os::Printer::log("Loading textures.");
|
||||
#endif
|
||||
const bool use_mat_dirs=!SceneMgr->getParameters()->getAttributeAsBool(DMF_IGNORE_MATERIALS_DIRS);
|
||||
|
||||
core::stringc path;
|
||||
if ( SceneMgr->getParameters()->existsAttribute(DMF_TEXTURE_PATH) )
|
||||
path = SceneMgr->getParameters()->getAttributeAsString(DMF_TEXTURE_PATH);
|
||||
else
|
||||
path = FileSystem->getFileDir(file->getFileName());
|
||||
path += ('/');
|
||||
|
||||
for (i=0; i<mesh->getMeshBufferCount(); i++)
|
||||
{
|
||||
//texture and lightmap
|
||||
video::ITexture *tex = 0;
|
||||
video::ITexture *lig = 0;
|
||||
|
||||
//current buffer to apply material
|
||||
video::SMaterial& mat = mesh->getMeshBuffer(i)->getMaterial();
|
||||
|
||||
//Primary texture is normal
|
||||
if (materiali[i].textureFlag==0)
|
||||
{
|
||||
if (materiali[i].textureBlend==4)
|
||||
driver->setTextureCreationFlag(video::ETCF_ALWAYS_32_BIT,true);
|
||||
findFile(use_mat_dirs, path, materiali[i].pathName, materiali[i].textureName);
|
||||
tex = driver->getTexture(materiali[i].textureName);
|
||||
}
|
||||
//Primary texture is just a color
|
||||
else if(materiali[i].textureFlag==1)
|
||||
{
|
||||
video::SColor color(axtoi(materiali[i].textureName.c_str()));
|
||||
|
||||
//just for compatibility with older Irrlicht versions
|
||||
//to support transparent materials
|
||||
if (color.getAlpha()!=255 && materiali[i].textureBlend==4)
|
||||
driver->setTextureCreationFlag(video::ETCF_ALWAYS_32_BIT,true);
|
||||
|
||||
video::IImage *immagine= driver->createImage(video::ECF_A8R8G8B8,
|
||||
core::dimension2d<u32>(8,8));
|
||||
immagine->fill(color);
|
||||
tex = driver->addTexture("", immagine);
|
||||
immagine->drop();
|
||||
|
||||
//to support transparent materials
|
||||
if (color.getAlpha()!=255 && materiali[i].textureBlend==4)
|
||||
{
|
||||
mat.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
|
||||
mat.MaterialTypeParam =(((f32) (color.getAlpha()-1))/255.0f);
|
||||
}
|
||||
}
|
||||
|
||||
//Lightmap is present
|
||||
if (materiali[i].lightmapFlag == 0)
|
||||
{
|
||||
findFile(use_mat_dirs, path, materiali[i].pathName, materiali[i].lightmapName);
|
||||
lig = driver->getTexture(materiali[i].lightmapName);
|
||||
}
|
||||
else //no lightmap
|
||||
{
|
||||
mat.MaterialType = video::EMT_SOLID;
|
||||
const f32 mult = 100.0f - header.dmfShadow;
|
||||
mat.AmbientColor=header.dmfAmbient.getInterpolated(video::SColor(255,0,0,0),mult/100.f);
|
||||
}
|
||||
|
||||
if (materiali[i].textureBlend==4)
|
||||
{
|
||||
mat.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
|
||||
mat.MaterialTypeParam =
|
||||
SceneMgr->getParameters()->getAttributeAsFloat(DMF_ALPHA_CHANNEL_REF);
|
||||
}
|
||||
|
||||
//if texture is present mirror vertically owing to DeleD representation
|
||||
if (tex && header.dmfVersion<1.1)
|
||||
{
|
||||
const core::dimension2d<u32> texsize = tex->getSize();
|
||||
void* pp = tex->lock();
|
||||
if (pp)
|
||||
{
|
||||
const video::ECOLOR_FORMAT format = tex->getColorFormat();
|
||||
if (format == video::ECF_A1R5G5B5)
|
||||
{
|
||||
s16* p = (s16*)pp;
|
||||
s16 tmp=0;
|
||||
for (u32 x=0; x<texsize.Width; x++)
|
||||
for (u32 y=0; y<texsize.Height/2; y++)
|
||||
{
|
||||
tmp=p[y*texsize.Width + x];
|
||||
p[y*texsize.Width + x] = p[(texsize.Height-y-1)*texsize.Width + x];
|
||||
p[(texsize.Height-y-1)*texsize.Width + x]=tmp;
|
||||
}
|
||||
}
|
||||
else
|
||||
if (format == video::ECF_A8R8G8B8)
|
||||
{
|
||||
s32* p = (s32*)pp;
|
||||
s32 tmp=0;
|
||||
for (u32 x=0; x<texsize.Width; x++)
|
||||
for (u32 y=0; y<texsize.Height/2; y++)
|
||||
{
|
||||
tmp=p[y*texsize.Width + x];
|
||||
p[y*texsize.Width + x] = p[(texsize.Height-y-1)*texsize.Width + x];
|
||||
p[(texsize.Height-y-1)*texsize.Width + x]=tmp;
|
||||
}
|
||||
}
|
||||
}
|
||||
tex->unlock();
|
||||
tex->regenerateMipMapLevels();
|
||||
}
|
||||
|
||||
//if lightmap is present mirror vertically owing to DeleD rapresentation
|
||||
if (lig && header.dmfVersion<1.1)
|
||||
{
|
||||
const core::dimension2d<u32> ligsize=lig->getSize();
|
||||
void* pp = lig->lock();
|
||||
if (pp)
|
||||
{
|
||||
video::ECOLOR_FORMAT format = lig->getColorFormat();
|
||||
if (format == video::ECF_A1R5G5B5)
|
||||
{
|
||||
s16* p = (s16*)pp;
|
||||
s16 tmp=0;
|
||||
for (u32 x=0; x<ligsize.Width; x++)
|
||||
{
|
||||
for (u32 y=0; y<ligsize.Height/2; y++)
|
||||
{
|
||||
tmp=p[y*ligsize.Width + x];
|
||||
p[y*ligsize.Width + x] = p[(ligsize.Height-y-1)*ligsize.Width + x];
|
||||
p[(ligsize.Height-y-1)*ligsize.Width + x]=tmp;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (format == video::ECF_A8R8G8B8)
|
||||
{
|
||||
s32* p = (s32*)pp;
|
||||
s32 tmp=0;
|
||||
for (u32 x=0; x<ligsize.Width; x++)
|
||||
{
|
||||
for (u32 y=0; y<ligsize.Height/2; y++)
|
||||
{
|
||||
tmp=p[y*ligsize.Width + x];
|
||||
p[y*ligsize.Width + x] = p[(ligsize.Height-y-1)*ligsize.Width + x];
|
||||
p[(ligsize.Height-y-1)*ligsize.Width + x]=tmp;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
lig->unlock();
|
||||
lig->regenerateMipMapLevels();
|
||||
}
|
||||
|
||||
mat.setTexture(0, tex);
|
||||
mat.setTexture(1, lig);
|
||||
}
|
||||
}
|
||||
|
||||
// create bounding box
|
||||
for (i = 0; i < mesh->MeshBuffers.size(); ++i)
|
||||
{
|
||||
mesh->MeshBuffers[i]->recalculateBoundingBox();
|
||||
}
|
||||
mesh->recalculateBoundingBox();
|
||||
|
||||
// Set up an animated mesh to hold the mesh
|
||||
SAnimatedMesh* AMesh = new SAnimatedMesh();
|
||||
AMesh->Type = EAMT_UNKNOWN;
|
||||
AMesh->addMesh(mesh);
|
||||
AMesh->recalculateBoundingBox();
|
||||
mesh->drop();
|
||||
|
||||
return AMesh;
|
||||
}
|
||||
|
||||
|
||||
/** \brief Tell us if this file is able to be loaded by this class
|
||||
based on the file extension (e.g. ".bsp")
|
||||
\return true if file is loadable.*/
|
||||
bool CDMFLoader::isALoadableFileExtension(const io::path& filename) const
|
||||
{
|
||||
return core::hasFileExtension ( filename, "dmf" );
|
||||
}
|
||||
|
||||
|
||||
} // end namespace scene
|
||||
} // end namespace irr
|
||||
|
||||
#endif // _IRR_COMPILE_WITH_DMF_LOADER_
|
||||
|
91
source/Irrlicht/CDMFLoader.h
Normal file
91
source/Irrlicht/CDMFLoader.h
Normal file
@ -0,0 +1,91 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
//
|
||||
// This file was originally written by Salvatore Russo.
|
||||
// I (Nikolaus Gebhardt) did some minor modifications changes to it and integrated
|
||||
// it into Irrlicht:
|
||||
// - removed STL dependency
|
||||
// - removed log file and replaced it with irrlicht logging
|
||||
// - adapted code formatting a bit to Irrlicht style
|
||||
// - removed memory leaks
|
||||
// Thanks a lot to Salvatore for his work on this and that he gave me
|
||||
// his permission to add it into Irrlicht.
|
||||
|
||||
/*
|
||||
CDMFLoader by Salvatore Russo
|
||||
Version 1.3
|
||||
|
||||
This loader is used to load DMF files in Irrlicht.
|
||||
Look at the documentation for a sample application.
|
||||
|
||||
Parts of this code are from Murphy McCauley COCTLoader just like
|
||||
GetFaceNormal() or indexes creation routines and a routine to add faces. So
|
||||
please refer to COCTLoader.h to know more about rights granted.
|
||||
|
||||
You can use this software as you wish but you must not remove these notes about license nor
|
||||
credits to others for parts of this code.
|
||||
*/
|
||||
|
||||
#ifndef __C_DMF_LOADER_H_INCLUDED__
|
||||
#define __C_DMF_LOADER_H_INCLUDED__
|
||||
|
||||
#include "IMeshLoader.h"
|
||||
#include "IReadFile.h"
|
||||
#include "IFileSystem.h"
|
||||
#include "SMesh.h"
|
||||
#include "IVideoDriver.h"
|
||||
#include "ISceneManager.h"
|
||||
#include "SAnimatedMesh.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace scene
|
||||
{
|
||||
/** A class to load DeleD mesh files.*/
|
||||
class CDMFLoader : public IMeshLoader
|
||||
{
|
||||
public:
|
||||
|
||||
/** constructor*/
|
||||
CDMFLoader(ISceneManager* smgr, io::IFileSystem* filesys);
|
||||
|
||||
//! returns true if the file maybe is able to be loaded by this class
|
||||
//! based on the file extension (e.g. ".cob")
|
||||
virtual bool isALoadableFileExtension(const io::path& filename) const;
|
||||
|
||||
/** creates/loads an animated mesh from the file.
|
||||
\return Pointer to the created mesh. Returns 0 if loading failed.
|
||||
If you no longer need the mesh, you should call IAnimatedMesh::drop().
|
||||
See IReferenceCounted::drop() for more information.*/
|
||||
virtual IAnimatedMesh* createMesh(io::IReadFile* file);
|
||||
|
||||
/** loads dynamic lights present in this scene.
|
||||
Note that loaded lights from DeleD must have the suffix \b dynamic_ and must be \b pointlight.
|
||||
Irrlicht correctly loads specular color, diffuse color , position and distance of object affected by light.
|
||||
\return number of lights loaded or 0 if loading failed.*/
|
||||
int loadLights(const c8 * filename, ISceneManager* smgr,
|
||||
ISceneNode* parent = 0, s32 base_id = 1000);
|
||||
|
||||
/** loads water plains present in this scene.
|
||||
Note that loaded water plains from DeleD must have the suffix \b water_ and must be \b rectangle (with just 1 rectangular face).
|
||||
Irrlicht correctly loads position and rotation of water plain as well as texture layers.
|
||||
\return number of water plains loaded or 0 if loading failed.*/
|
||||
int loadWaterPlains(const c8 *filename,
|
||||
ISceneManager* smgr,
|
||||
ISceneNode * parent = 0,
|
||||
s32 base_id = 2000,
|
||||
bool mode = true);
|
||||
|
||||
private:
|
||||
void findFile(bool use_mat_dirs, const core::stringc& path, const core::stringc& matPath, core::stringc& filename);
|
||||
|
||||
ISceneManager* SceneMgr;
|
||||
io::IFileSystem* FileSystem;
|
||||
};
|
||||
|
||||
} // end namespace scene
|
||||
} // end namespace irr
|
||||
|
||||
#endif
|
||||
|
164
source/Irrlicht/CDefaultGUIElementFactory.cpp
Normal file
164
source/Irrlicht/CDefaultGUIElementFactory.cpp
Normal file
@ -0,0 +1,164 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#include "CDefaultGUIElementFactory.h"
|
||||
|
||||
#ifdef _IRR_COMPILE_WITH_GUI_
|
||||
|
||||
#include "IGUIEnvironment.h"
|
||||
|
||||
#include "IGUIButton.h"
|
||||
#include "IGUICheckBox.h"
|
||||
#include "IGUIColorSelectDialog.h"
|
||||
#include "IGUIComboBox.h"
|
||||
#include "IGUIContextMenu.h"
|
||||
#include "IGUIEditBox.h"
|
||||
#include "IGUIFileOpenDialog.h"
|
||||
#include "IGUIInOutFader.h"
|
||||
#include "IGUIImage.h"
|
||||
#include "IGUIListBox.h"
|
||||
#include "IGUIMeshViewer.h"
|
||||
#include "IGUIScrollBar.h"
|
||||
#include "IGUISpinBox.h"
|
||||
#include "IGUIStaticText.h"
|
||||
#include "IGUITabControl.h"
|
||||
#include "IGUITable.h"
|
||||
#include "IGUIToolbar.h"
|
||||
#include "IGUIWindow.h"
|
||||
#include "IGUITreeView.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace gui
|
||||
{
|
||||
|
||||
CDefaultGUIElementFactory::CDefaultGUIElementFactory(IGUIEnvironment* env)
|
||||
: Environment(env)
|
||||
{
|
||||
|
||||
#ifdef _DEBUG
|
||||
setDebugName("CDefaultGUIElementFactory");
|
||||
#endif
|
||||
|
||||
// don't grab the gui environment here to prevent cyclic references
|
||||
}
|
||||
|
||||
|
||||
//! adds an element to the env based on its type id
|
||||
IGUIElement* CDefaultGUIElementFactory::addGUIElement(EGUI_ELEMENT_TYPE type, IGUIElement* parent)
|
||||
{
|
||||
switch(type)
|
||||
{
|
||||
case EGUIET_BUTTON:
|
||||
return Environment->addButton(core::rect<s32>(0,0,100,100),parent);
|
||||
case EGUIET_CHECK_BOX:
|
||||
return Environment->addCheckBox(false, core::rect<s32>(0,0,100,100), parent);
|
||||
case EGUIET_COLOR_SELECT_DIALOG:
|
||||
return Environment->addColorSelectDialog(0,true,parent);
|
||||
case EGUIET_COMBO_BOX:
|
||||
return Environment->addComboBox(core::rect<s32>(0,0,100,100),parent);
|
||||
case EGUIET_CONTEXT_MENU:
|
||||
return Environment->addContextMenu(core::rect<s32>(0,0,100,100),parent);
|
||||
case EGUIET_MENU:
|
||||
return Environment->addMenu(parent);
|
||||
case EGUIET_EDIT_BOX:
|
||||
return Environment->addEditBox(0,core::rect<s32>(0,0,100,100),true, parent);
|
||||
case EGUIET_FILE_OPEN_DIALOG:
|
||||
return Environment->addFileOpenDialog(0,true,parent);
|
||||
case EGUIET_IMAGE:
|
||||
return Environment->addImage(0,core::position2di(0,0), true, parent);
|
||||
case EGUIET_IN_OUT_FADER:
|
||||
return Environment->addInOutFader(0,parent);
|
||||
case EGUIET_LIST_BOX:
|
||||
return Environment->addListBox(core::rect<s32>(0,0,100,100),parent);
|
||||
case EGUIET_MESH_VIEWER:
|
||||
return Environment->addMeshViewer(core::rect<s32>(0,0,100,100),parent);
|
||||
case EGUIET_MODAL_SCREEN:
|
||||
return Environment->addModalScreen(parent);
|
||||
case EGUIET_MESSAGE_BOX:
|
||||
return Environment->addMessageBox(0,0,false,0,parent);
|
||||
case EGUIET_SCROLL_BAR:
|
||||
return Environment->addScrollBar(false,core::rect<s32>(0,0,100,100),parent);
|
||||
case EGUIET_STATIC_TEXT:
|
||||
return Environment->addStaticText(0,core::rect<s32>(0,0,100,100),false,true,parent);
|
||||
case EGUIET_TAB:
|
||||
return Environment->addTab(core::rect<s32>(0,0,100,100),parent);
|
||||
case EGUIET_TAB_CONTROL:
|
||||
return Environment->addTabControl(core::rect<s32>(0,0,100,100),parent);
|
||||
case EGUIET_TABLE:
|
||||
return Environment->addTable(core::rect<s32>(0,0,100,100), parent);
|
||||
case EGUIET_TOOL_BAR:
|
||||
return Environment->addToolBar(parent);
|
||||
case EGUIET_WINDOW:
|
||||
return Environment->addWindow(core::rect<s32>(0,0,100,100),false,0,parent);
|
||||
case EGUIET_SPIN_BOX:
|
||||
return Environment->addSpinBox(L"0.0", core::rect<s32>(0,0,100,100), true, parent);
|
||||
case EGUIET_TREE_VIEW:
|
||||
return Environment->addTreeView(core::rect<s32>(0,0,100,100),parent);
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//! adds an element to the environment based on its type name
|
||||
IGUIElement* CDefaultGUIElementFactory::addGUIElement(const c8* typeName, IGUIElement* parent)
|
||||
{
|
||||
return addGUIElement( getTypeFromName(typeName), parent );
|
||||
}
|
||||
|
||||
|
||||
//! Returns the amount of element types this factory is able to create.
|
||||
s32 CDefaultGUIElementFactory::getCreatableGUIElementTypeCount() const
|
||||
{
|
||||
return EGUIET_COUNT;
|
||||
}
|
||||
|
||||
|
||||
//! Returns the type of a createable element type.
|
||||
EGUI_ELEMENT_TYPE CDefaultGUIElementFactory::getCreateableGUIElementType(s32 idx) const
|
||||
{
|
||||
if (idx>=0 && idx<EGUIET_COUNT)
|
||||
return (EGUI_ELEMENT_TYPE)idx;
|
||||
|
||||
return EGUIET_ELEMENT;
|
||||
}
|
||||
|
||||
|
||||
//! Returns the type name of a createable element type.
|
||||
const c8* CDefaultGUIElementFactory::getCreateableGUIElementTypeName(s32 idx) const
|
||||
{
|
||||
if (idx>=0 && idx<EGUIET_COUNT)
|
||||
return GUIElementTypeNames[idx];
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
//! Returns the type name of a createable element type.
|
||||
const c8* CDefaultGUIElementFactory::getCreateableGUIElementTypeName(EGUI_ELEMENT_TYPE type) const
|
||||
{
|
||||
// for this factory, type == index
|
||||
|
||||
if (type>=0 && type<EGUIET_COUNT)
|
||||
return GUIElementTypeNames[type];
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
EGUI_ELEMENT_TYPE CDefaultGUIElementFactory::getTypeFromName(const c8* name) const
|
||||
{
|
||||
for ( u32 i=0; GUIElementTypeNames[i]; ++i)
|
||||
if (!strcmp(name, GUIElementTypeNames[i]) )
|
||||
return (EGUI_ELEMENT_TYPE)i;
|
||||
|
||||
return EGUIET_ELEMENT;
|
||||
}
|
||||
|
||||
|
||||
} // end namespace gui
|
||||
} // end namespace irr
|
||||
|
||||
#endif // _IRR_COMPILE_WITH_GUI_
|
||||
|
70
source/Irrlicht/CDefaultGUIElementFactory.h
Normal file
70
source/Irrlicht/CDefaultGUIElementFactory.h
Normal file
@ -0,0 +1,70 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#ifndef __C_DEFAULT_GUI_ELEMENT_FACTORY_H_INCLUDED__
|
||||
#define __C_DEFAULT_GUI_ELEMENT_FACTORY_H_INCLUDED__
|
||||
|
||||
#include "IrrCompileConfig.h"
|
||||
#ifdef _IRR_COMPILE_WITH_GUI_
|
||||
|
||||
#include "IGUIElementFactory.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace gui
|
||||
{
|
||||
class IGUIElement;
|
||||
class IGUIEnvironment;
|
||||
|
||||
//! This interface makes it possible to dynamically create gui elements.
|
||||
class CDefaultGUIElementFactory : public IGUIElementFactory
|
||||
{
|
||||
public:
|
||||
|
||||
CDefaultGUIElementFactory(IGUIEnvironment* env);
|
||||
|
||||
//! Adds an element to the gui environment based on its type id.
|
||||
/** \param type: Type of the element to add.
|
||||
\param parent: Parent scene node of the new element. A value of 0 adds it to the root.
|
||||
\return Returns pointer to the new element or 0 if unsuccessful. */
|
||||
virtual IGUIElement* addGUIElement(EGUI_ELEMENT_TYPE type, IGUIElement* parent=0);
|
||||
|
||||
//! Adds a GUI element to the GUI Environment based on its type name.
|
||||
/** \param typeName: Type name of the element to add. Taken from the GUIElementTypeNames c8* array.
|
||||
\param parent: Parent scene node of the new element. A value of 0 adds it to the root.
|
||||
\return Returns pointer to the new element or 0 if unsuccessful. */
|
||||
virtual IGUIElement* addGUIElement(const c8* typeName, IGUIElement* parent=0);
|
||||
|
||||
//! Returns the amount of GUI element types this factory is able to create.
|
||||
virtual s32 getCreatableGUIElementTypeCount() const;
|
||||
|
||||
//! Returns the type of a createable GUI element type based on the index.
|
||||
/** \param idx: Index of the element type in this factory. The value must be equal or greater than 0
|
||||
and lower than getCreatableGUIElementTypeCount(). */
|
||||
virtual EGUI_ELEMENT_TYPE getCreateableGUIElementType(s32 idx) const;
|
||||
|
||||
//! Returns the type name of a createable GUI element type based on the index.
|
||||
/** \param idx: Index of the element type in this factory. The value must be equal or greater than 0
|
||||
and lower than getCreatableGUIElementTypeCount(). */
|
||||
virtual const c8* getCreateableGUIElementTypeName(s32 idx) const;
|
||||
|
||||
//! Returns the type name of a createable GUI element based on its type.
|
||||
/** \param type: Type of the GUI element.
|
||||
\return: Returns the name of the type if this factory can create it, otherwise it returns 0. */
|
||||
virtual const c8* getCreateableGUIElementTypeName(EGUI_ELEMENT_TYPE type) const;
|
||||
|
||||
private:
|
||||
|
||||
EGUI_ELEMENT_TYPE getTypeFromName(const c8* name) const;
|
||||
|
||||
IGUIEnvironment* Environment;
|
||||
};
|
||||
|
||||
|
||||
} // end namespace gui
|
||||
} // end namespace irr
|
||||
|
||||
#endif // _IRR_COMPILE_WITH_GUI_
|
||||
|
||||
#endif // __C_DEFAULT_GUI_ELEMENT_FACTORY_H_INCLUDED__
|
162
source/Irrlicht/CDefaultSceneNodeAnimatorFactory.cpp
Normal file
162
source/Irrlicht/CDefaultSceneNodeAnimatorFactory.cpp
Normal file
@ -0,0 +1,162 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#include "CDefaultSceneNodeAnimatorFactory.h"
|
||||
#include "CSceneNodeAnimatorCameraFPS.h"
|
||||
#include "CSceneNodeAnimatorCameraMaya.h"
|
||||
#include "ICursorControl.h"
|
||||
#include "ISceneNodeAnimatorCollisionResponse.h"
|
||||
#include "ISceneManager.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace scene
|
||||
{
|
||||
|
||||
//! Names for scene node types
|
||||
const c8* const SceneNodeAnimatorTypeNames[] =
|
||||
{
|
||||
"flyCircle",
|
||||
"flyStraight",
|
||||
"followSpline",
|
||||
"rotation",
|
||||
"texture",
|
||||
"deletion",
|
||||
"collisionResponse",
|
||||
"cameraFPS",
|
||||
"cameraMaya",
|
||||
0
|
||||
};
|
||||
|
||||
|
||||
CDefaultSceneNodeAnimatorFactory::CDefaultSceneNodeAnimatorFactory(ISceneManager* mgr, gui::ICursorControl* crs)
|
||||
: Manager(mgr), CursorControl(crs)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
setDebugName("CDefaultSceneNodeAnimatorFactory");
|
||||
#endif
|
||||
|
||||
// don't grab the scene manager here to prevent cyclic references
|
||||
if (CursorControl)
|
||||
CursorControl->grab();
|
||||
}
|
||||
|
||||
|
||||
CDefaultSceneNodeAnimatorFactory::~CDefaultSceneNodeAnimatorFactory()
|
||||
{
|
||||
if (CursorControl)
|
||||
CursorControl->drop();
|
||||
}
|
||||
|
||||
|
||||
//! creates a scene node animator based on its type id
|
||||
ISceneNodeAnimator* CDefaultSceneNodeAnimatorFactory::createSceneNodeAnimator(ESCENE_NODE_ANIMATOR_TYPE type, ISceneNode* target)
|
||||
{
|
||||
scene::ISceneNodeAnimator* anim = 0;
|
||||
|
||||
switch(type)
|
||||
{
|
||||
case ESNAT_FLY_CIRCLE:
|
||||
anim = Manager->createFlyCircleAnimator(core::vector3df(0,0,0), 10);
|
||||
break;
|
||||
case ESNAT_FLY_STRAIGHT:
|
||||
anim = Manager->createFlyStraightAnimator(core::vector3df(0,0,0), core::vector3df(100,100,100), 10000, true );
|
||||
break;
|
||||
case ESNAT_FOLLOW_SPLINE:
|
||||
{
|
||||
core::array<core::vector3df> points;
|
||||
points.push_back(core::vector3df(0,0,0));
|
||||
points.push_back(core::vector3df(10,5,10));
|
||||
anim = Manager->createFollowSplineAnimator(0, points);
|
||||
}
|
||||
break;
|
||||
case ESNAT_ROTATION:
|
||||
anim = Manager->createRotationAnimator(core::vector3df(0.3f,0,0));
|
||||
break;
|
||||
case ESNAT_TEXTURE:
|
||||
{
|
||||
core::array<video::ITexture*> textures;
|
||||
anim = Manager->createTextureAnimator(textures, 250);
|
||||
}
|
||||
break;
|
||||
case ESNAT_DELETION:
|
||||
anim = Manager->createDeleteAnimator(5000);
|
||||
break;
|
||||
case ESNAT_COLLISION_RESPONSE:
|
||||
anim = Manager->createCollisionResponseAnimator(0, target);
|
||||
break;
|
||||
case ESNAT_CAMERA_FPS:
|
||||
anim = new CSceneNodeAnimatorCameraFPS(CursorControl);
|
||||
break;
|
||||
case ESNAT_CAMERA_MAYA:
|
||||
anim = new CSceneNodeAnimatorCameraMaya(CursorControl);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (anim && target)
|
||||
target->addAnimator(anim);
|
||||
|
||||
return anim;
|
||||
}
|
||||
|
||||
|
||||
//! creates a scene node animator based on its type name
|
||||
ISceneNodeAnimator* CDefaultSceneNodeAnimatorFactory::createSceneNodeAnimator(const c8* typeName, ISceneNode* target)
|
||||
{
|
||||
return createSceneNodeAnimator( getTypeFromName(typeName), target );
|
||||
}
|
||||
|
||||
|
||||
//! returns amount of scene node animator types this factory is able to create
|
||||
u32 CDefaultSceneNodeAnimatorFactory::getCreatableSceneNodeAnimatorTypeCount() const
|
||||
{
|
||||
return ESNAT_COUNT;
|
||||
}
|
||||
|
||||
|
||||
//! returns type of a createable scene node animator type
|
||||
ESCENE_NODE_ANIMATOR_TYPE CDefaultSceneNodeAnimatorFactory::getCreateableSceneNodeAnimatorType(u32 idx) const
|
||||
{
|
||||
if (idx<ESNAT_COUNT)
|
||||
return (ESCENE_NODE_ANIMATOR_TYPE)idx;
|
||||
else
|
||||
return ESNAT_UNKNOWN;
|
||||
}
|
||||
|
||||
|
||||
//! returns type name of a createable scene node animator type
|
||||
const c8* CDefaultSceneNodeAnimatorFactory::getCreateableSceneNodeAnimatorTypeName(u32 idx) const
|
||||
{
|
||||
if (idx<ESNAT_COUNT)
|
||||
return SceneNodeAnimatorTypeNames[idx];
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
//! returns type name of a createable scene node animator type
|
||||
const c8* CDefaultSceneNodeAnimatorFactory::getCreateableSceneNodeAnimatorTypeName(ESCENE_NODE_ANIMATOR_TYPE type) const
|
||||
{
|
||||
// for this factory: index == type
|
||||
|
||||
if (type<ESNAT_COUNT)
|
||||
return SceneNodeAnimatorTypeNames[type];
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
ESCENE_NODE_ANIMATOR_TYPE CDefaultSceneNodeAnimatorFactory::getTypeFromName(const c8* name) const
|
||||
{
|
||||
for ( u32 i=0; SceneNodeAnimatorTypeNames[i]; ++i)
|
||||
if (!strcmp(name, SceneNodeAnimatorTypeNames[i]) )
|
||||
return (ESCENE_NODE_ANIMATOR_TYPE)i;
|
||||
|
||||
return ESNAT_UNKNOWN;
|
||||
}
|
||||
|
||||
|
||||
} // end namespace scene
|
||||
} // end namespace irr
|
||||
|
75
source/Irrlicht/CDefaultSceneNodeAnimatorFactory.h
Normal file
75
source/Irrlicht/CDefaultSceneNodeAnimatorFactory.h
Normal file
@ -0,0 +1,75 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#ifndef __C_DEFAULT_SCENE_NODE_ANIMATOR_FACTORY_H_INCLUDED__
|
||||
#define __C_DEFAULT_SCENE_NODE_ANIMATOR_FACTORY_H_INCLUDED__
|
||||
|
||||
#include "ISceneNodeAnimatorFactory.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace gui
|
||||
{
|
||||
class ICursorControl;
|
||||
}
|
||||
namespace scene
|
||||
{
|
||||
class ISceneNodeAnimator;
|
||||
class ISceneManager;
|
||||
|
||||
//! Interface making it possible to dynamicly create scene nodes animators
|
||||
class CDefaultSceneNodeAnimatorFactory : public ISceneNodeAnimatorFactory
|
||||
{
|
||||
public:
|
||||
|
||||
CDefaultSceneNodeAnimatorFactory(ISceneManager* mgr, gui::ICursorControl* crs);
|
||||
|
||||
virtual ~CDefaultSceneNodeAnimatorFactory();
|
||||
|
||||
//! creates a scene node animator based on its type id
|
||||
/** \param type: Type of the scene node animator to add.
|
||||
\param target: Target scene node of the new animator.
|
||||
\return Returns pointer to the new scene node animator or null if not successful. You need to
|
||||
drop this pointer after calling this, see IReferenceCounted::drop() for details. */
|
||||
virtual ISceneNodeAnimator* createSceneNodeAnimator(ESCENE_NODE_ANIMATOR_TYPE type, ISceneNode* target);
|
||||
|
||||
//! creates a scene node animator based on its type name
|
||||
/** \param typeName: Type of the scene node animator to add.
|
||||
\param target: Target scene node of the new animator.
|
||||
\return Returns pointer to the new scene node animator or null if not successful. You need to
|
||||
drop this pointer after calling this, see IReferenceCounted::drop() for details. */
|
||||
virtual ISceneNodeAnimator* createSceneNodeAnimator(const char* typeName, ISceneNode* target);
|
||||
|
||||
//! returns amount of scene node animator types this factory is able to create
|
||||
virtual u32 getCreatableSceneNodeAnimatorTypeCount() const;
|
||||
|
||||
//! returns type of a createable scene node animator type
|
||||
/** \param idx: Index of scene node animator type in this factory. Must be a value between 0 and
|
||||
getCreatableSceneNodeTypeCount() */
|
||||
virtual ESCENE_NODE_ANIMATOR_TYPE getCreateableSceneNodeAnimatorType(u32 idx) const;
|
||||
|
||||
//! returns type name of a createable scene node animator type
|
||||
/** \param idx: Index of scene node animator type in this factory. Must be a value between 0 and
|
||||
getCreatableSceneNodeAnimatorTypeCount() */
|
||||
virtual const c8* getCreateableSceneNodeAnimatorTypeName(u32 idx) const;
|
||||
|
||||
//! returns type name of a createable scene node animator type
|
||||
/** \param type: Type of scene node animator.
|
||||
\return: Returns name of scene node animator type if this factory can create the type, otherwise 0. */
|
||||
virtual const c8* getCreateableSceneNodeAnimatorTypeName(ESCENE_NODE_ANIMATOR_TYPE type) const;
|
||||
|
||||
private:
|
||||
|
||||
ESCENE_NODE_ANIMATOR_TYPE getTypeFromName(const c8* name) const;
|
||||
|
||||
ISceneManager* Manager;
|
||||
gui::ICursorControl* CursorControl;
|
||||
};
|
||||
|
||||
|
||||
} // end namespace scene
|
||||
} // end namespace irr
|
||||
|
||||
#endif
|
||||
|
179
source/Irrlicht/CDefaultSceneNodeFactory.cpp
Normal file
179
source/Irrlicht/CDefaultSceneNodeFactory.cpp
Normal file
@ -0,0 +1,179 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#include "CDefaultSceneNodeFactory.h"
|
||||
#include "ISceneManager.h"
|
||||
#include "ITextSceneNode.h"
|
||||
#include "ITerrainSceneNode.h"
|
||||
#include "IDummyTransformationSceneNode.h"
|
||||
#include "ICameraSceneNode.h"
|
||||
#include "IBillboardSceneNode.h"
|
||||
#include "IAnimatedMeshSceneNode.h"
|
||||
#include "IParticleSystemSceneNode.h"
|
||||
#include "ILightSceneNode.h"
|
||||
#include "IMeshSceneNode.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace scene
|
||||
{
|
||||
|
||||
|
||||
CDefaultSceneNodeFactory::CDefaultSceneNodeFactory(ISceneManager* mgr)
|
||||
: Manager(mgr)
|
||||
{
|
||||
|
||||
#ifdef _DEBUG
|
||||
setDebugName("CDefaultSceneNodeFactory");
|
||||
#endif
|
||||
|
||||
// don't grab the scene manager here to prevent cyclic references
|
||||
|
||||
SupportedSceneNodeTypes.push_back(SSceneNodeTypePair(ESNT_CUBE, "cube"));
|
||||
SupportedSceneNodeTypes.push_back(SSceneNodeTypePair(ESNT_SPHERE, "sphere"));
|
||||
SupportedSceneNodeTypes.push_back(SSceneNodeTypePair(ESNT_TEXT, "text"));
|
||||
SupportedSceneNodeTypes.push_back(SSceneNodeTypePair(ESNT_WATER_SURFACE, "waterSurface"));
|
||||
SupportedSceneNodeTypes.push_back(SSceneNodeTypePair(ESNT_TERRAIN, "terrain"));
|
||||
SupportedSceneNodeTypes.push_back(SSceneNodeTypePair(ESNT_SKY_BOX, "skyBox"));
|
||||
SupportedSceneNodeTypes.push_back(SSceneNodeTypePair(ESNT_SKY_DOME, "skyDome"));
|
||||
SupportedSceneNodeTypes.push_back(SSceneNodeTypePair(ESNT_SHADOW_VOLUME, "shadowVolume"));
|
||||
SupportedSceneNodeTypes.push_back(SSceneNodeTypePair(ESNT_OCTREE, "octree"));
|
||||
// Legacy support
|
||||
SupportedSceneNodeTypes.push_back(SSceneNodeTypePair(ESNT_OCTREE, "octTree"));
|
||||
SupportedSceneNodeTypes.push_back(SSceneNodeTypePair(ESNT_MESH, "mesh"));
|
||||
SupportedSceneNodeTypes.push_back(SSceneNodeTypePair(ESNT_LIGHT, "light"));
|
||||
SupportedSceneNodeTypes.push_back(SSceneNodeTypePair(ESNT_EMPTY, "empty"));
|
||||
SupportedSceneNodeTypes.push_back(SSceneNodeTypePair(ESNT_DUMMY_TRANSFORMATION, "dummyTransformation"));
|
||||
SupportedSceneNodeTypes.push_back(SSceneNodeTypePair(ESNT_CAMERA, "camera"));
|
||||
SupportedSceneNodeTypes.push_back(SSceneNodeTypePair(ESNT_BILLBOARD, "billBoard"));
|
||||
SupportedSceneNodeTypes.push_back(SSceneNodeTypePair(ESNT_ANIMATED_MESH, "animatedMesh"));
|
||||
SupportedSceneNodeTypes.push_back(SSceneNodeTypePair(ESNT_PARTICLE_SYSTEM, "particleSystem"));
|
||||
SupportedSceneNodeTypes.push_back(SSceneNodeTypePair(ESNT_VOLUME_LIGHT, "volumeLight"));
|
||||
// SupportedSceneNodeTypes.push_back(SSceneNodeTypePair(ESNT_MD3_SCENE_NODE, "md3"));
|
||||
|
||||
// legacy, for version <= 1.4.x irr files
|
||||
SupportedSceneNodeTypes.push_back(SSceneNodeTypePair(ESNT_CAMERA_MAYA, "cameraMaya"));
|
||||
SupportedSceneNodeTypes.push_back(SSceneNodeTypePair(ESNT_CAMERA_FPS, "cameraFPS"));
|
||||
SupportedSceneNodeTypes.push_back(SSceneNodeTypePair(ESNT_Q3SHADER_SCENE_NODE, "quake3Shader"));
|
||||
}
|
||||
|
||||
|
||||
//! adds a scene node to the scene graph based on its type id
|
||||
ISceneNode* CDefaultSceneNodeFactory::addSceneNode(ESCENE_NODE_TYPE type, ISceneNode* parent)
|
||||
{
|
||||
switch(type)
|
||||
{
|
||||
case ESNT_CUBE:
|
||||
return Manager->addCubeSceneNode(10, parent);
|
||||
case ESNT_SPHERE:
|
||||
return Manager->addSphereSceneNode(5, 16, parent);
|
||||
case ESNT_TEXT:
|
||||
return Manager->addTextSceneNode(0, L"example");
|
||||
case ESNT_WATER_SURFACE:
|
||||
return Manager->addWaterSurfaceSceneNode(0, 2.0f, 300.0f, 10.0f, parent);
|
||||
case ESNT_TERRAIN:
|
||||
return Manager->addTerrainSceneNode("", parent, -1,
|
||||
core::vector3df(0.0f,0.0f,0.0f),
|
||||
core::vector3df(0.0f,0.0f,0.0f),
|
||||
core::vector3df(1.0f,1.0f,1.0f),
|
||||
video::SColor(255,255,255,255),
|
||||
4, ETPS_17, 0, true);
|
||||
case ESNT_SKY_BOX:
|
||||
return Manager->addSkyBoxSceneNode(0,0,0,0,0,0, parent);
|
||||
case ESNT_SKY_DOME:
|
||||
return Manager->addSkyDomeSceneNode(0, 16, 8, 0.9f, 2.0f, 1000.0f, parent);
|
||||
case ESNT_SHADOW_VOLUME:
|
||||
return 0;
|
||||
case ESNT_OCTREE:
|
||||
return Manager->addOctreeSceneNode((IMesh*)0, parent, -1, 128, true);
|
||||
case ESNT_MESH:
|
||||
return Manager->addMeshSceneNode(0, parent, -1, core::vector3df(),
|
||||
core::vector3df(), core::vector3df(1,1,1), true);
|
||||
case ESNT_LIGHT:
|
||||
return Manager->addLightSceneNode(parent);
|
||||
case ESNT_EMPTY:
|
||||
return Manager->addEmptySceneNode(parent);
|
||||
case ESNT_DUMMY_TRANSFORMATION:
|
||||
return Manager->addDummyTransformationSceneNode(parent);
|
||||
case ESNT_CAMERA:
|
||||
return Manager->addCameraSceneNode(parent);
|
||||
case ESNT_CAMERA_MAYA:
|
||||
return Manager->addCameraSceneNodeMaya(parent);
|
||||
case ESNT_CAMERA_FPS:
|
||||
return Manager->addCameraSceneNodeFPS(parent);
|
||||
case ESNT_BILLBOARD:
|
||||
return Manager->addBillboardSceneNode(parent);
|
||||
case ESNT_ANIMATED_MESH:
|
||||
return Manager->addAnimatedMeshSceneNode(0, parent, -1, core::vector3df(),
|
||||
core::vector3df(), core::vector3df(1,1,1), true);
|
||||
case ESNT_PARTICLE_SYSTEM:
|
||||
return Manager->addParticleSystemSceneNode(true, parent);
|
||||
case ESNT_VOLUME_LIGHT:
|
||||
return (ISceneNode*)Manager->addVolumeLightSceneNode(parent);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
//! adds a scene node to the scene graph based on its type name
|
||||
ISceneNode* CDefaultSceneNodeFactory::addSceneNode(const c8* typeName, ISceneNode* parent)
|
||||
{
|
||||
return addSceneNode( getTypeFromName(typeName), parent );
|
||||
}
|
||||
|
||||
|
||||
//! returns amount of scene node types this factory is able to create
|
||||
u32 CDefaultSceneNodeFactory::getCreatableSceneNodeTypeCount() const
|
||||
{
|
||||
return SupportedSceneNodeTypes.size();
|
||||
}
|
||||
|
||||
|
||||
//! returns type of a createable scene node type
|
||||
ESCENE_NODE_TYPE CDefaultSceneNodeFactory::getCreateableSceneNodeType(u32 idx) const
|
||||
{
|
||||
if (idx<SupportedSceneNodeTypes.size())
|
||||
return SupportedSceneNodeTypes[idx].Type;
|
||||
else
|
||||
return ESNT_UNKNOWN;
|
||||
}
|
||||
|
||||
|
||||
//! returns type name of a createable scene node type
|
||||
const c8* CDefaultSceneNodeFactory::getCreateableSceneNodeTypeName(u32 idx) const
|
||||
{
|
||||
if (idx<SupportedSceneNodeTypes.size())
|
||||
return SupportedSceneNodeTypes[idx].TypeName.c_str();
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
//! returns type name of a createable scene node type
|
||||
const c8* CDefaultSceneNodeFactory::getCreateableSceneNodeTypeName(ESCENE_NODE_TYPE type) const
|
||||
{
|
||||
for (u32 i=0; i<SupportedSceneNodeTypes.size(); ++i)
|
||||
if (SupportedSceneNodeTypes[i].Type == type)
|
||||
return SupportedSceneNodeTypes[i].TypeName.c_str();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
ESCENE_NODE_TYPE CDefaultSceneNodeFactory::getTypeFromName(const c8* name) const
|
||||
{
|
||||
for (u32 i=0; i<SupportedSceneNodeTypes.size(); ++i)
|
||||
if (SupportedSceneNodeTypes[i].TypeName == name)
|
||||
return SupportedSceneNodeTypes[i].Type;
|
||||
|
||||
return ESNT_UNKNOWN;
|
||||
}
|
||||
|
||||
|
||||
} // end namespace scene
|
||||
} // end namespace irr
|
||||
|
80
source/Irrlicht/CDefaultSceneNodeFactory.h
Normal file
80
source/Irrlicht/CDefaultSceneNodeFactory.h
Normal file
@ -0,0 +1,80 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#ifndef __C_DEFAULT_SCENE_NODE_FACTORY_H_INCLUDED__
|
||||
#define __C_DEFAULT_SCENE_NODE_FACTORY_H_INCLUDED__
|
||||
|
||||
#include "ISceneNodeFactory.h"
|
||||
#include "irrArray.h"
|
||||
#include "irrString.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace scene
|
||||
{
|
||||
class ISceneNode;
|
||||
class ISceneManager;
|
||||
|
||||
//! Interface making it possible to dynamicly create scene nodes and animators
|
||||
class CDefaultSceneNodeFactory : public ISceneNodeFactory
|
||||
{
|
||||
public:
|
||||
|
||||
CDefaultSceneNodeFactory(ISceneManager* mgr);
|
||||
|
||||
//! adds a scene node to the scene graph based on its type id
|
||||
/** \param type: Type of the scene node to add.
|
||||
\param parent: Parent scene node of the new node, can be null to add the scene node to the root.
|
||||
\return Returns pointer to the new scene node or null if not successful. */
|
||||
virtual ISceneNode* addSceneNode(ESCENE_NODE_TYPE type, ISceneNode* parent=0);
|
||||
|
||||
//! adds a scene node to the scene graph based on its type name
|
||||
/** \param typeName: Type name of the scene node to add.
|
||||
\param parent: Parent scene node of the new node, can be null to add the scene node to the root.
|
||||
\return Returns pointer to the new scene node or null if not successful. */
|
||||
virtual ISceneNode* addSceneNode(const c8* typeName, ISceneNode* parent=0);
|
||||
|
||||
//! returns amount of scene node types this factory is able to create
|
||||
virtual u32 getCreatableSceneNodeTypeCount() const;
|
||||
|
||||
//! returns type name of a createable scene node type by index
|
||||
/** \param idx: Index of scene node type in this factory. Must be a value between 0 and
|
||||
uetCreatableSceneNodeTypeCount() */
|
||||
virtual const c8* getCreateableSceneNodeTypeName(u32 idx) const;
|
||||
|
||||
//! returns type of a createable scene node type
|
||||
/** \param idx: Index of scene node type in this factory. Must be a value between 0 and
|
||||
getCreatableSceneNodeTypeCount() */
|
||||
virtual ESCENE_NODE_TYPE getCreateableSceneNodeType(u32 idx) const;
|
||||
|
||||
//! returns type name of a createable scene node type
|
||||
/** \param idx: Type of scene node.
|
||||
\return: Returns name of scene node type if this factory can create the type, otherwise 0. */
|
||||
virtual const c8* getCreateableSceneNodeTypeName(ESCENE_NODE_TYPE type) const;
|
||||
|
||||
private:
|
||||
|
||||
ESCENE_NODE_TYPE getTypeFromName(const c8* name) const;
|
||||
|
||||
struct SSceneNodeTypePair
|
||||
{
|
||||
SSceneNodeTypePair(ESCENE_NODE_TYPE type, const c8* name)
|
||||
: Type(type), TypeName(name)
|
||||
{}
|
||||
|
||||
ESCENE_NODE_TYPE Type;
|
||||
core::stringc TypeName;
|
||||
};
|
||||
|
||||
core::array<SSceneNodeTypePair> SupportedSceneNodeTypes;
|
||||
|
||||
ISceneManager* Manager;
|
||||
};
|
||||
|
||||
|
||||
} // end namespace scene
|
||||
} // end namespace irr
|
||||
|
||||
#endif
|
||||
|
176
source/Irrlicht/CDepthBuffer.cpp
Normal file
176
source/Irrlicht/CDepthBuffer.cpp
Normal file
@ -0,0 +1,176 @@
|
||||
// Copyright (C) 2002-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
|
||||
|
||||
#include "IrrCompileConfig.h"
|
||||
#include "SoftwareDriver2_compile_config.h"
|
||||
#include "CDepthBuffer.h"
|
||||
|
||||
#ifdef _IRR_COMPILE_WITH_BURNINGSVIDEO_
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace video
|
||||
{
|
||||
|
||||
|
||||
//! constructor
|
||||
CDepthBuffer::CDepthBuffer(const core::dimension2d<u32>& size)
|
||||
: Buffer(0), Size(0,0)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
setDebugName("CDepthBuffer");
|
||||
#endif
|
||||
|
||||
setSize(size);
|
||||
}
|
||||
|
||||
|
||||
|
||||
//! destructor
|
||||
CDepthBuffer::~CDepthBuffer()
|
||||
{
|
||||
if (Buffer)
|
||||
delete [] Buffer;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//! clears the zbuffer
|
||||
void CDepthBuffer::clear()
|
||||
{
|
||||
|
||||
#ifdef SOFTWARE_DRIVER_2_USE_WBUFFER
|
||||
f32 zMax = 0.f;
|
||||
#else
|
||||
f32 zMax = 1.f;
|
||||
#endif
|
||||
|
||||
u32 zMaxValue;
|
||||
zMaxValue = IR(zMax);
|
||||
|
||||
memset32 ( Buffer, zMaxValue, TotalSize );
|
||||
}
|
||||
|
||||
|
||||
|
||||
//! sets the new size of the zbuffer
|
||||
void CDepthBuffer::setSize(const core::dimension2d<u32>& size)
|
||||
{
|
||||
if (size == Size)
|
||||
return;
|
||||
|
||||
Size = size;
|
||||
|
||||
if (Buffer)
|
||||
delete [] Buffer;
|
||||
|
||||
Pitch = size.Width * sizeof ( fp24 );
|
||||
TotalSize = Pitch * size.Height;
|
||||
Buffer = new u8[TotalSize];
|
||||
clear ();
|
||||
}
|
||||
|
||||
|
||||
|
||||
//! returns the size of the zbuffer
|
||||
const core::dimension2d<u32>& CDepthBuffer::getSize() const
|
||||
{
|
||||
return Size;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------
|
||||
|
||||
//! constructor
|
||||
CStencilBuffer::CStencilBuffer(const core::dimension2d<u32>& size)
|
||||
: Buffer(0), Size(0,0)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
setDebugName("CDepthBuffer");
|
||||
#endif
|
||||
|
||||
setSize(size);
|
||||
}
|
||||
|
||||
|
||||
|
||||
//! destructor
|
||||
CStencilBuffer::~CStencilBuffer()
|
||||
{
|
||||
if (Buffer)
|
||||
delete [] Buffer;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//! clears the zbuffer
|
||||
void CStencilBuffer::clear()
|
||||
{
|
||||
memset32 ( Buffer, 0, TotalSize );
|
||||
}
|
||||
|
||||
|
||||
|
||||
//! sets the new size of the zbuffer
|
||||
void CStencilBuffer::setSize(const core::dimension2d<u32>& size)
|
||||
{
|
||||
if (size == Size)
|
||||
return;
|
||||
|
||||
Size = size;
|
||||
|
||||
if (Buffer)
|
||||
delete [] Buffer;
|
||||
|
||||
Pitch = size.Width * sizeof ( u32 );
|
||||
TotalSize = Pitch * size.Height;
|
||||
Buffer = new u8[TotalSize];
|
||||
clear ();
|
||||
}
|
||||
|
||||
|
||||
|
||||
//! returns the size of the zbuffer
|
||||
const core::dimension2d<u32>& CStencilBuffer::getSize() const
|
||||
{
|
||||
return Size;
|
||||
}
|
||||
|
||||
|
||||
|
||||
} // end namespace video
|
||||
} // end namespace irr
|
||||
|
||||
#endif // _IRR_COMPILE_WITH_BURNINGSVIDEO_
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace video
|
||||
{
|
||||
|
||||
//! creates a ZBuffer
|
||||
IDepthBuffer* createDepthBuffer(const core::dimension2d<u32>& size)
|
||||
{
|
||||
#ifdef _IRR_COMPILE_WITH_BURNINGSVIDEO_
|
||||
return new CDepthBuffer(size);
|
||||
#else
|
||||
return 0;
|
||||
#endif // _IRR_COMPILE_WITH_BURNINGSVIDEO_
|
||||
}
|
||||
|
||||
|
||||
//! creates a ZBuffer
|
||||
IStencilBuffer* createStencilBuffer(const core::dimension2d<u32>& size)
|
||||
{
|
||||
#ifdef _IRR_COMPILE_WITH_BURNINGSVIDEO_
|
||||
return new CStencilBuffer(size);
|
||||
#else
|
||||
return 0;
|
||||
#endif // _IRR_COMPILE_WITH_BURNINGSVIDEO_
|
||||
}
|
||||
|
||||
} // end namespace video
|
||||
} // end namespace irr
|
||||
|
||||
|
||||
|
94
source/Irrlicht/CDepthBuffer.h
Normal file
94
source/Irrlicht/CDepthBuffer.h
Normal file
@ -0,0 +1,94 @@
|
||||
// Copyright (C) 2002-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 __C_Z_BUFFER_H_INCLUDED__
|
||||
#define __C_Z_BUFFER_H_INCLUDED__
|
||||
|
||||
#include "IDepthBuffer.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace video
|
||||
{
|
||||
|
||||
class CDepthBuffer : public IDepthBuffer
|
||||
{
|
||||
public:
|
||||
|
||||
//! constructor
|
||||
CDepthBuffer(const core::dimension2d<u32>& size);
|
||||
|
||||
//! destructor
|
||||
virtual ~CDepthBuffer();
|
||||
|
||||
//! clears the zbuffer
|
||||
virtual void clear();
|
||||
|
||||
//! sets the new size of the zbuffer
|
||||
virtual void setSize(const core::dimension2d<u32>& size);
|
||||
|
||||
//! returns the size of the zbuffer
|
||||
virtual const core::dimension2d<u32>& getSize() const;
|
||||
|
||||
//! locks the zbuffer
|
||||
virtual void* lock() { return (void*) Buffer; }
|
||||
|
||||
//! unlocks the zbuffer
|
||||
virtual void unlock() {}
|
||||
|
||||
//! returns pitch of depthbuffer (in bytes)
|
||||
virtual u32 getPitch() const { return Pitch; }
|
||||
|
||||
|
||||
private:
|
||||
|
||||
u8* Buffer;
|
||||
core::dimension2d<u32> Size;
|
||||
u32 TotalSize;
|
||||
u32 Pitch;
|
||||
};
|
||||
|
||||
|
||||
class CStencilBuffer : public IStencilBuffer
|
||||
{
|
||||
public:
|
||||
|
||||
//! constructor
|
||||
CStencilBuffer(const core::dimension2d<u32>& size);
|
||||
|
||||
//! destructor
|
||||
virtual ~CStencilBuffer();
|
||||
|
||||
//! clears the zbuffer
|
||||
virtual void clear();
|
||||
|
||||
//! sets the new size of the zbuffer
|
||||
virtual void setSize(const core::dimension2d<u32>& size);
|
||||
|
||||
//! returns the size of the zbuffer
|
||||
virtual const core::dimension2d<u32>& getSize() const;
|
||||
|
||||
//! locks the zbuffer
|
||||
virtual void* lock() { return (void*) Buffer; }
|
||||
|
||||
//! unlocks the zbuffer
|
||||
virtual void unlock() {}
|
||||
|
||||
//! returns pitch of depthbuffer (in bytes)
|
||||
virtual u32 getPitch() const { return Pitch; }
|
||||
|
||||
|
||||
private:
|
||||
|
||||
u8* Buffer;
|
||||
core::dimension2d<u32> Size;
|
||||
u32 TotalSize;
|
||||
u32 Pitch;
|
||||
};
|
||||
|
||||
} // end namespace video
|
||||
} // end namespace irr
|
||||
|
||||
#endif
|
||||
|
105
source/Irrlicht/CDummyTransformationSceneNode.cpp
Normal file
105
source/Irrlicht/CDummyTransformationSceneNode.cpp
Normal file
@ -0,0 +1,105 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#include "CDummyTransformationSceneNode.h"
|
||||
#include "os.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace scene
|
||||
{
|
||||
|
||||
//! constructor
|
||||
CDummyTransformationSceneNode::CDummyTransformationSceneNode(
|
||||
ISceneNode* parent, ISceneManager* mgr, s32 id)
|
||||
: IDummyTransformationSceneNode(parent, mgr, id)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
setDebugName("CDummyTransformationSceneNode");
|
||||
#endif
|
||||
|
||||
setAutomaticCulling(scene::EAC_OFF);
|
||||
}
|
||||
|
||||
|
||||
//! returns the axis aligned bounding box of this node
|
||||
const core::aabbox3d<f32>& CDummyTransformationSceneNode::getBoundingBox() const
|
||||
{
|
||||
return Box;
|
||||
}
|
||||
|
||||
|
||||
//! Returns a reference to the current relative transformation matrix.
|
||||
//! This is the matrix, this scene node uses instead of scale, translation
|
||||
//! and rotation.
|
||||
core::matrix4& CDummyTransformationSceneNode::getRelativeTransformationMatrix()
|
||||
{
|
||||
return RelativeTransformationMatrix;
|
||||
}
|
||||
|
||||
|
||||
//! Returns the relative transformation of the scene node.
|
||||
core::matrix4 CDummyTransformationSceneNode::getRelativeTransformation() const
|
||||
{
|
||||
return RelativeTransformationMatrix;
|
||||
}
|
||||
|
||||
//! Creates a clone of this scene node and its children.
|
||||
ISceneNode* CDummyTransformationSceneNode::clone(ISceneNode* newParent, ISceneManager* newManager)
|
||||
{
|
||||
if (!newParent)
|
||||
newParent = Parent;
|
||||
if (!newManager)
|
||||
newManager = SceneManager;
|
||||
|
||||
CDummyTransformationSceneNode* nb = new CDummyTransformationSceneNode(newParent,
|
||||
newManager, ID);
|
||||
|
||||
nb->cloneMembers(this, newManager);
|
||||
nb->RelativeTransformationMatrix = RelativeTransformationMatrix;
|
||||
nb->Box = Box;
|
||||
|
||||
if ( newParent )
|
||||
nb->drop();
|
||||
return nb;
|
||||
}
|
||||
|
||||
const core::vector3df& CDummyTransformationSceneNode::getScale() const
|
||||
{
|
||||
os::Printer::log("CDummyTransformationSceneNode::getScale() does not contain the relative transformation.", ELL_DEBUG);
|
||||
return RelativeScale;
|
||||
}
|
||||
|
||||
void CDummyTransformationSceneNode::setScale(const core::vector3df& scale)
|
||||
{
|
||||
os::Printer::log("CDummyTransformationSceneNode::setScale() does not affect the relative transformation.", ELL_DEBUG);
|
||||
RelativeScale = scale;
|
||||
}
|
||||
|
||||
const core::vector3df& CDummyTransformationSceneNode::getRotation() const
|
||||
{
|
||||
os::Printer::log("CDummyTransformationSceneNode::getRotation() does not contain the relative transformation.", ELL_DEBUG);
|
||||
return RelativeRotation;
|
||||
}
|
||||
|
||||
void CDummyTransformationSceneNode::setRotation(const core::vector3df& rotation)
|
||||
{
|
||||
os::Printer::log("CDummyTransformationSceneNode::setRotation() does not affect the relative transformation.", ELL_DEBUG);
|
||||
RelativeRotation = rotation;
|
||||
}
|
||||
|
||||
const core::vector3df& CDummyTransformationSceneNode::getPosition() const
|
||||
{
|
||||
os::Printer::log("CDummyTransformationSceneNode::getPosition() does not contain the relative transformation.", ELL_DEBUG);
|
||||
return RelativeTranslation;
|
||||
}
|
||||
|
||||
void CDummyTransformationSceneNode::setPosition(const core::vector3df& newpos)
|
||||
{
|
||||
os::Printer::log("CDummyTransformationSceneNode::setPosition() does not affect the relative transformation.", ELL_DEBUG);
|
||||
RelativeTranslation = newpos;
|
||||
}
|
||||
|
||||
} // end namespace scene
|
||||
} // end namespace irr
|
62
source/Irrlicht/CDummyTransformationSceneNode.h
Normal file
62
source/Irrlicht/CDummyTransformationSceneNode.h
Normal file
@ -0,0 +1,62 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#ifndef __C_DUMMY_TRANSFORMATION_SCENE_NODE_H_INCLUDED__
|
||||
#define __C_DUMMY_TRANSFORMATION_SCENE_NODE_H_INCLUDED__
|
||||
|
||||
#include "IDummyTransformationSceneNode.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace scene
|
||||
{
|
||||
|
||||
class CDummyTransformationSceneNode : public IDummyTransformationSceneNode
|
||||
{
|
||||
public:
|
||||
|
||||
//! constructor
|
||||
CDummyTransformationSceneNode(ISceneNode* parent, ISceneManager* mgr, s32 id);
|
||||
|
||||
//! returns the axis aligned bounding box of this node
|
||||
virtual const core::aabbox3d<f32>& getBoundingBox() const;
|
||||
|
||||
//! Returns a reference to the current relative transformation matrix.
|
||||
//! This is the matrix, this scene node uses instead of scale, translation
|
||||
//! and rotation.
|
||||
virtual core::matrix4& getRelativeTransformationMatrix();
|
||||
|
||||
//! Returns the relative transformation of the scene node.
|
||||
virtual core::matrix4 getRelativeTransformation() const;
|
||||
|
||||
//! does nothing.
|
||||
virtual void render() {}
|
||||
|
||||
//! Returns type of the scene node
|
||||
virtual ESCENE_NODE_TYPE getType() const { return ESNT_DUMMY_TRANSFORMATION; }
|
||||
|
||||
//! Creates a clone of this scene node and its children.
|
||||
virtual ISceneNode* clone(ISceneNode* newParent=0, ISceneManager* newManager=0);
|
||||
|
||||
|
||||
private:
|
||||
|
||||
// TODO: We can add least add some warnings to find troubles faster until we have
|
||||
// fixed bug id 2318691.
|
||||
virtual const core::vector3df& getScale() const;
|
||||
virtual void setScale(const core::vector3df& scale);
|
||||
virtual const core::vector3df& getRotation() const;
|
||||
virtual void setRotation(const core::vector3df& rotation);
|
||||
virtual const core::vector3df& getPosition() const;
|
||||
virtual void setPosition(const core::vector3df& newpos);
|
||||
|
||||
core::matrix4 RelativeTransformationMatrix;
|
||||
core::aabbox3d<f32> Box;
|
||||
};
|
||||
|
||||
} // end namespace scene
|
||||
} // end namespace irr
|
||||
|
||||
#endif
|
||||
|
70
source/Irrlicht/CEmptySceneNode.cpp
Normal file
70
source/Irrlicht/CEmptySceneNode.cpp
Normal file
@ -0,0 +1,70 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#include "CEmptySceneNode.h"
|
||||
#include "ISceneManager.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace scene
|
||||
{
|
||||
|
||||
//! constructor
|
||||
CEmptySceneNode::CEmptySceneNode(ISceneNode* parent, ISceneManager* mgr, s32 id)
|
||||
: ISceneNode(parent, mgr, id)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
setDebugName("CEmptySceneNode");
|
||||
#endif
|
||||
|
||||
setAutomaticCulling(scene::EAC_OFF);
|
||||
}
|
||||
|
||||
|
||||
//! pre render event
|
||||
void CEmptySceneNode::OnRegisterSceneNode()
|
||||
{
|
||||
if (IsVisible)
|
||||
SceneManager->registerNodeForRendering(this);
|
||||
|
||||
ISceneNode::OnRegisterSceneNode();
|
||||
}
|
||||
|
||||
|
||||
//! render
|
||||
void CEmptySceneNode::render()
|
||||
{
|
||||
// do nothing
|
||||
}
|
||||
|
||||
|
||||
//! returns the axis aligned bounding box of this node
|
||||
const core::aabbox3d<f32>& CEmptySceneNode::getBoundingBox() const
|
||||
{
|
||||
return Box;
|
||||
}
|
||||
|
||||
|
||||
//! Creates a clone of this scene node and its children.
|
||||
ISceneNode* CEmptySceneNode::clone(ISceneNode* newParent, ISceneManager* newManager)
|
||||
{
|
||||
if (!newParent)
|
||||
newParent = Parent;
|
||||
if (!newManager)
|
||||
newManager = SceneManager;
|
||||
|
||||
CEmptySceneNode* nb = new CEmptySceneNode(newParent,
|
||||
newManager, ID);
|
||||
|
||||
nb->cloneMembers(this, newManager);
|
||||
nb->Box = Box;
|
||||
|
||||
if ( newParent )
|
||||
nb->drop();
|
||||
return nb;
|
||||
}
|
||||
|
||||
|
||||
} // end namespace scene
|
||||
} // end namespace irr
|
46
source/Irrlicht/CEmptySceneNode.h
Normal file
46
source/Irrlicht/CEmptySceneNode.h
Normal file
@ -0,0 +1,46 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#ifndef __C_EMPTY_SCENE_NODE_H_INCLUDED__
|
||||
#define __C_EMPTY_SCENE_NODE_H_INCLUDED__
|
||||
|
||||
#include "ISceneNode.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace scene
|
||||
{
|
||||
|
||||
class CEmptySceneNode : public ISceneNode
|
||||
{
|
||||
public:
|
||||
|
||||
//! constructor
|
||||
CEmptySceneNode(ISceneNode* parent, ISceneManager* mgr, s32 id);
|
||||
|
||||
//! returns the axis aligned bounding box of this node
|
||||
virtual const core::aabbox3d<f32>& getBoundingBox() const;
|
||||
|
||||
//! This method is called just before the rendering process of the whole scene.
|
||||
virtual void OnRegisterSceneNode();
|
||||
|
||||
//! does nothing.
|
||||
virtual void render();
|
||||
|
||||
//! Returns type of the scene node
|
||||
virtual ESCENE_NODE_TYPE getType() const { return ESNT_EMPTY; }
|
||||
|
||||
//! Creates a clone of this scene node and its children.
|
||||
virtual ISceneNode* clone(ISceneNode* newParent=0, ISceneManager* newManager=0);
|
||||
|
||||
private:
|
||||
|
||||
core::aabbox3d<f32> Box;
|
||||
};
|
||||
|
||||
} // end namespace scene
|
||||
} // end namespace irr
|
||||
|
||||
#endif
|
||||
|
76
source/Irrlicht/CFPSCounter.cpp
Normal file
76
source/Irrlicht/CFPSCounter.cpp
Normal file
@ -0,0 +1,76 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#include "CFPSCounter.h"
|
||||
#include "irrMath.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace video
|
||||
{
|
||||
|
||||
|
||||
CFPSCounter::CFPSCounter()
|
||||
: FPS(60), Primitive(0), StartTime(0), FramesCounted(0),
|
||||
PrimitivesCounted(0), PrimitiveAverage(0), PrimitiveTotal(0)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
//! returns current fps
|
||||
s32 CFPSCounter::getFPS() const
|
||||
{
|
||||
return FPS;
|
||||
}
|
||||
|
||||
|
||||
//! returns current primitive count
|
||||
u32 CFPSCounter::getPrimitive() const
|
||||
{
|
||||
return Primitive;
|
||||
}
|
||||
|
||||
|
||||
//! returns average primitive count of last period
|
||||
u32 CFPSCounter::getPrimitiveAverage() const
|
||||
{
|
||||
return PrimitiveAverage;
|
||||
}
|
||||
|
||||
|
||||
//! returns accumulated primitive count since start
|
||||
u32 CFPSCounter::getPrimitiveTotal() const
|
||||
{
|
||||
return PrimitiveTotal;
|
||||
}
|
||||
|
||||
|
||||
//! to be called every frame
|
||||
void CFPSCounter::registerFrame(u32 now, u32 primitivesDrawn)
|
||||
{
|
||||
++FramesCounted;
|
||||
PrimitiveTotal += primitivesDrawn;
|
||||
PrimitivesCounted += primitivesDrawn;
|
||||
Primitive = primitivesDrawn;
|
||||
|
||||
const u32 milliseconds = now - StartTime;
|
||||
|
||||
if (milliseconds >= 1500 )
|
||||
{
|
||||
const f32 invMilli = core::reciprocal ( (f32) milliseconds );
|
||||
|
||||
FPS = core::ceil32 ( ( 1000 * FramesCounted ) * invMilli );
|
||||
PrimitiveAverage = core::ceil32 ( ( 1000 * PrimitivesCounted ) * invMilli );
|
||||
|
||||
FramesCounted = 0;
|
||||
PrimitivesCounted = 0;
|
||||
StartTime = now;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
} // end namespace video
|
||||
} // end namespace irr
|
||||
|
54
source/Irrlicht/CFPSCounter.h
Normal file
54
source/Irrlicht/CFPSCounter.h
Normal file
@ -0,0 +1,54 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#ifndef __C_FPSCOUNTER_H_INCLUDED__
|
||||
#define __C_FPSCOUNTER_H_INCLUDED__
|
||||
|
||||
#include "irrTypes.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace video
|
||||
{
|
||||
|
||||
|
||||
class CFPSCounter
|
||||
{
|
||||
public:
|
||||
CFPSCounter();
|
||||
|
||||
//! returns current fps
|
||||
s32 getFPS() const;
|
||||
|
||||
//! returns primitive count
|
||||
u32 getPrimitive() const;
|
||||
|
||||
//! returns average primitive count of last period
|
||||
u32 getPrimitiveAverage() const;
|
||||
|
||||
//! returns accumulated primitive count since start
|
||||
u32 getPrimitiveTotal() const;
|
||||
|
||||
//! to be called every frame
|
||||
void registerFrame(u32 now, u32 primitive);
|
||||
|
||||
private:
|
||||
|
||||
s32 FPS;
|
||||
u32 Primitive;
|
||||
u32 StartTime;
|
||||
|
||||
u32 FramesCounted;
|
||||
u32 PrimitivesCounted;
|
||||
u32 PrimitiveAverage;
|
||||
u32 PrimitiveTotal;
|
||||
};
|
||||
|
||||
|
||||
} // end namespace video
|
||||
} // end namespace irr
|
||||
|
||||
|
||||
#endif
|
||||
|
165
source/Irrlicht/CFileList.cpp
Normal file
165
source/Irrlicht/CFileList.cpp
Normal file
@ -0,0 +1,165 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#include "CFileList.h"
|
||||
#include "IrrCompileConfig.h"
|
||||
#include "irrArray.h"
|
||||
#include "coreutil.h"
|
||||
|
||||
#include "os.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace io
|
||||
{
|
||||
|
||||
static const io::path emptyFileListEntry;
|
||||
|
||||
CFileList::CFileList(const io::path& path, bool ignoreCase, bool ignorePaths)
|
||||
: IgnorePaths(ignorePaths), IgnoreCase(ignoreCase), Path(path)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
setDebugName("CFileList");
|
||||
#endif
|
||||
|
||||
Path.replace('\\', '/');
|
||||
}
|
||||
|
||||
CFileList::~CFileList()
|
||||
{
|
||||
Files.clear();
|
||||
}
|
||||
|
||||
u32 CFileList::getFileCount() const
|
||||
{
|
||||
return Files.size();
|
||||
}
|
||||
|
||||
void CFileList::sort()
|
||||
{
|
||||
Files.sort();
|
||||
}
|
||||
|
||||
const io::path& CFileList::getFileName(u32 index) const
|
||||
{
|
||||
if (index >= Files.size())
|
||||
return emptyFileListEntry;
|
||||
|
||||
return Files[index].Name;
|
||||
}
|
||||
|
||||
|
||||
//! Gets the full name of a file in the list, path included, based on an index.
|
||||
const io::path& CFileList::getFullFileName(u32 index) const
|
||||
{
|
||||
if (index >= Files.size())
|
||||
return emptyFileListEntry;
|
||||
|
||||
return Files[index].FullName;
|
||||
}
|
||||
|
||||
//! adds a file or folder
|
||||
u32 CFileList::addItem(const io::path& fullPath, u32 offset, u32 size, bool isDirectory, u32 id)
|
||||
{
|
||||
SFileListEntry entry;
|
||||
entry.ID = id ? id : Files.size();
|
||||
entry.Offset = offset;
|
||||
entry.Size = size;
|
||||
entry.Name = fullPath;
|
||||
entry.Name.replace('\\', '/');
|
||||
entry.IsDirectory = isDirectory;
|
||||
|
||||
// remove trailing slash
|
||||
if (entry.Name.lastChar() == '/')
|
||||
{
|
||||
entry.IsDirectory = true;
|
||||
entry.Name[entry.Name.size()-1] = 0;
|
||||
entry.Name.validate();
|
||||
}
|
||||
|
||||
if (IgnoreCase)
|
||||
entry.Name.make_lower();
|
||||
|
||||
entry.FullName = entry.Name;
|
||||
|
||||
core::deletePathFromFilename(entry.Name);
|
||||
|
||||
if (IgnorePaths)
|
||||
entry.FullName = entry.Name;
|
||||
|
||||
//os::Printer::log(Path.c_str(), entry.FullName);
|
||||
|
||||
Files.push_back(entry);
|
||||
|
||||
return Files.size() - 1;
|
||||
}
|
||||
|
||||
//! Returns the ID of a file in the file list, based on an index.
|
||||
u32 CFileList::getID(u32 index) const
|
||||
{
|
||||
return index < Files.size() ? Files[index].ID : 0;
|
||||
}
|
||||
|
||||
bool CFileList::isDirectory(u32 index) const
|
||||
{
|
||||
bool ret = false;
|
||||
if (index < Files.size())
|
||||
ret = Files[index].IsDirectory;
|
||||
|
||||
_IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX;
|
||||
return ret;
|
||||
}
|
||||
|
||||
//! Returns the size of a file
|
||||
u32 CFileList::getFileSize(u32 index) const
|
||||
{
|
||||
return index < Files.size() ? Files[index].Size : 0;
|
||||
}
|
||||
|
||||
//! Returns the size of a file
|
||||
u32 CFileList::getFileOffset(u32 index) const
|
||||
{
|
||||
return index < Files.size() ? Files[index].Offset : 0;
|
||||
}
|
||||
|
||||
|
||||
//! Searches for a file or folder within the list, returns the index
|
||||
s32 CFileList::findFile(const io::path& filename, bool isDirectory = false) const
|
||||
{
|
||||
SFileListEntry entry;
|
||||
// we only need FullName to be set for the search
|
||||
entry.FullName = filename;
|
||||
entry.IsDirectory = isDirectory;
|
||||
|
||||
// exchange
|
||||
entry.FullName.replace('\\', '/');
|
||||
|
||||
// remove trailing slash
|
||||
if (entry.FullName.lastChar() == '/')
|
||||
{
|
||||
entry.IsDirectory = true;
|
||||
entry.FullName[entry.FullName.size()-1] = 0;
|
||||
entry.FullName.validate();
|
||||
}
|
||||
|
||||
if (IgnoreCase)
|
||||
entry.FullName.make_lower();
|
||||
|
||||
if (IgnorePaths)
|
||||
core::deletePathFromFilename(entry.FullName);
|
||||
|
||||
return Files.binary_search(entry);
|
||||
}
|
||||
|
||||
|
||||
//! Returns the base path of the file list
|
||||
const io::path& CFileList::getPath() const
|
||||
{
|
||||
return Path;
|
||||
}
|
||||
|
||||
|
||||
} // end namespace irr
|
||||
} // end namespace io
|
||||
|
138
source/Irrlicht/CFileList.h
Normal file
138
source/Irrlicht/CFileList.h
Normal file
@ -0,0 +1,138 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#ifndef __C_FILE_LIST_H_INCLUDED__
|
||||
#define __C_FILE_LIST_H_INCLUDED__
|
||||
|
||||
#include "IFileList.h"
|
||||
#include "irrString.h"
|
||||
#include "irrArray.h"
|
||||
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace io
|
||||
{
|
||||
|
||||
//! An entry in a list of files, can be a folder or a file.
|
||||
struct SFileListEntry
|
||||
{
|
||||
//! The name of the file
|
||||
/** If this is a file or folder in the virtual filesystem and the archive
|
||||
was created with the ignoreCase flag then the file name will be lower case. */
|
||||
io::path Name;
|
||||
|
||||
//! The name of the file including the path
|
||||
/** If this is a file or folder in the virtual filesystem and the archive was
|
||||
created with the ignoreDirs flag then it will be the same as Name. */
|
||||
io::path FullName;
|
||||
|
||||
//! The size of the file in bytes
|
||||
u32 Size;
|
||||
|
||||
//! The ID of the file in an archive
|
||||
/** This is used to link the FileList entry to extra info held about this
|
||||
file in an archive, which can hold things like data offset and CRC. */
|
||||
u32 ID;
|
||||
|
||||
//! FileOffset inside an archive
|
||||
u32 Offset;
|
||||
|
||||
//! True if this is a folder, false if not.
|
||||
bool IsDirectory;
|
||||
|
||||
//! The == operator is provided so that CFileList can slowly search the list!
|
||||
bool operator ==(const struct SFileListEntry& other) const
|
||||
{
|
||||
if (IsDirectory != other.IsDirectory)
|
||||
return false;
|
||||
|
||||
return FullName.equals_ignore_case(other.FullName);
|
||||
}
|
||||
|
||||
//! The < operator is provided so that CFileList can sort and quickly search the list.
|
||||
bool operator <(const struct SFileListEntry& other) const
|
||||
{
|
||||
if (IsDirectory != other.IsDirectory)
|
||||
return IsDirectory;
|
||||
|
||||
return FullName.lower_ignore_case(other.FullName);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//! Implementation of a file list
|
||||
class CFileList : public IFileList
|
||||
{
|
||||
public:
|
||||
|
||||
// CFileList methods
|
||||
|
||||
//! Constructor
|
||||
/** \param path The path of this file archive */
|
||||
CFileList(const io::path& path, bool ignoreCase, bool ignorePaths);
|
||||
|
||||
//! Destructor
|
||||
virtual ~CFileList();
|
||||
|
||||
//! Add as a file or folder to the list
|
||||
/** \param fullPath The file name including path, up to the root of the file list.
|
||||
\param isDirectory True if this is a directory rather than a file.
|
||||
\param offset The offset where the file is stored in an archive
|
||||
\param size The size of the file in bytes.
|
||||
\param id The ID of the file in the archive which owns it */
|
||||
virtual u32 addItem(const io::path& fullPath, u32 offset, u32 size, bool isDirectory, u32 id=0);
|
||||
|
||||
//! Sorts the file list. You should call this after adding any items to the file list
|
||||
virtual void sort();
|
||||
|
||||
//! Returns the amount of files in the filelist.
|
||||
virtual u32 getFileCount() const;
|
||||
|
||||
//! Gets the name of a file in the list, based on an index.
|
||||
virtual const io::path& getFileName(u32 index) const;
|
||||
|
||||
//! Gets the full name of a file in the list, path included, based on an index.
|
||||
virtual const io::path& getFullFileName(u32 index) const;
|
||||
|
||||
//! Returns the ID of a file in the file list, based on an index.
|
||||
virtual u32 getID(u32 index) const;
|
||||
|
||||
//! Returns true if the file is a directory
|
||||
virtual bool isDirectory(u32 index) const;
|
||||
|
||||
//! Returns the size of a file
|
||||
virtual u32 getFileSize(u32 index) const;
|
||||
|
||||
//! Returns the offest of a file
|
||||
virtual u32 getFileOffset(u32 index) const;
|
||||
|
||||
//! Searches for a file or folder within the list, returns the index
|
||||
virtual s32 findFile(const io::path& filename, bool isFolder) const;
|
||||
|
||||
//! Returns the base path of the file list
|
||||
virtual const io::path& getPath() const;
|
||||
|
||||
protected:
|
||||
|
||||
//! Ignore paths when adding or searching for files
|
||||
bool IgnorePaths;
|
||||
|
||||
//! Ignore case when adding or searching for files
|
||||
bool IgnoreCase;
|
||||
|
||||
//! Path to the file list
|
||||
io::path Path;
|
||||
|
||||
//! List of files
|
||||
core::array<SFileListEntry> Files;
|
||||
};
|
||||
|
||||
|
||||
} // end namespace irr
|
||||
} // end namespace io
|
||||
|
||||
|
||||
#endif
|
||||
|
1081
source/Irrlicht/CFileSystem.cpp
Normal file
1081
source/Irrlicht/CFileSystem.cpp
Normal file
File diff suppressed because it is too large
Load Diff
173
source/Irrlicht/CFileSystem.h
Normal file
173
source/Irrlicht/CFileSystem.h
Normal file
@ -0,0 +1,173 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#ifndef __C_FILE_SYSTEM_H_INCLUDED__
|
||||
#define __C_FILE_SYSTEM_H_INCLUDED__
|
||||
|
||||
#include "IFileSystem.h"
|
||||
#include "irrArray.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace io
|
||||
{
|
||||
|
||||
class CZipReader;
|
||||
class CPakReader;
|
||||
class CMountPointReader;
|
||||
|
||||
/*!
|
||||
FileSystem which uses normal files and one zipfile
|
||||
*/
|
||||
class CFileSystem : public IFileSystem
|
||||
{
|
||||
public:
|
||||
|
||||
//! constructor
|
||||
CFileSystem();
|
||||
|
||||
//! destructor
|
||||
virtual ~CFileSystem();
|
||||
|
||||
//! opens a file for read access
|
||||
virtual IReadFile* createAndOpenFile(const io::path& filename);
|
||||
|
||||
//! Creates an IReadFile interface for accessing memory like a file.
|
||||
virtual IReadFile* createMemoryReadFile(void* memory, s32 len, const io::path& fileName, bool deleteMemoryWhenDropped = false);
|
||||
|
||||
//! Creates an IReadFile interface for accessing files inside files
|
||||
virtual IReadFile* createLimitReadFile(const io::path& fileName, IReadFile* alreadyOpenedFile, long pos, long areaSize);
|
||||
|
||||
//! Creates an IWriteFile interface for accessing memory like a file.
|
||||
virtual IWriteFile* createMemoryWriteFile(void* memory, s32 len, const io::path& fileName, bool deleteMemoryWhenDropped=false);
|
||||
|
||||
//! Opens a file for write access.
|
||||
virtual IWriteFile* createAndWriteFile(const io::path& filename, bool append=false);
|
||||
|
||||
//! Adds an archive to the file system.
|
||||
virtual bool addFileArchive(const io::path& filename,
|
||||
bool ignoreCase = true, bool ignorePaths = true,
|
||||
E_FILE_ARCHIVE_TYPE archiveType = EFAT_UNKNOWN,
|
||||
const core::stringc& password="",
|
||||
IFileArchive** retArchive = 0);
|
||||
|
||||
//! Adds an archive to the file system.
|
||||
virtual bool addFileArchive(IReadFile* file, bool ignoreCase=true,
|
||||
bool ignorePaths=true,
|
||||
E_FILE_ARCHIVE_TYPE archiveType=EFAT_UNKNOWN,
|
||||
const core::stringc& password="",
|
||||
IFileArchive** retArchive = 0);
|
||||
|
||||
//! Adds an archive to the file system.
|
||||
virtual bool addFileArchive(IFileArchive* archive);
|
||||
|
||||
//! move the hirarchy of the filesystem. moves sourceIndex relative up or down
|
||||
virtual bool moveFileArchive(u32 sourceIndex, s32 relative);
|
||||
|
||||
//! Adds an external archive loader to the engine.
|
||||
virtual void addArchiveLoader(IArchiveLoader* loader);
|
||||
|
||||
//! Returns the total number of archive loaders added.
|
||||
virtual u32 getArchiveLoaderCount() const;
|
||||
|
||||
//! Gets the archive loader by index.
|
||||
virtual IArchiveLoader* getArchiveLoader(u32 index) const;
|
||||
|
||||
//! gets the file archive count
|
||||
virtual u32 getFileArchiveCount() const;
|
||||
|
||||
//! gets an archive
|
||||
virtual IFileArchive* getFileArchive(u32 index);
|
||||
|
||||
//! removes an archive from the file system.
|
||||
virtual bool removeFileArchive(u32 index);
|
||||
|
||||
//! removes an archive from the file system.
|
||||
virtual bool removeFileArchive(const io::path& filename);
|
||||
|
||||
//! Removes an archive from the file system.
|
||||
virtual bool removeFileArchive(const IFileArchive* archive);
|
||||
|
||||
//! Returns the string of the current working directory
|
||||
virtual const io::path& getWorkingDirectory();
|
||||
|
||||
//! Changes the current Working Directory to the string given.
|
||||
//! The string is operating system dependent. Under Windows it will look
|
||||
//! like this: "drive:\directory\sudirectory\"
|
||||
virtual bool changeWorkingDirectoryTo(const io::path& newDirectory);
|
||||
|
||||
//! Converts a relative path to an absolute (unique) path, resolving symbolic links
|
||||
virtual io::path getAbsolutePath(const io::path& filename) const;
|
||||
|
||||
//! Returns the directory a file is located in.
|
||||
/** \param filename: The file to get the directory from */
|
||||
virtual io::path getFileDir(const io::path& filename) const;
|
||||
|
||||
//! Returns the base part of a filename, i.e. the name without the directory
|
||||
//! part. If no directory is prefixed, the full name is returned.
|
||||
/** \param filename: The file to get the basename from */
|
||||
virtual io::path getFileBasename(const io::path& filename, bool keepExtension=true) const;
|
||||
|
||||
//! flatten a path and file name for example: "/you/me/../." becomes "/you"
|
||||
virtual io::path& flattenFilename( io::path& directory, const io::path& root = "/" ) const;
|
||||
|
||||
//! Get the relative filename, relative to the given directory
|
||||
virtual path getRelativeFilename(const path& filename, const path& directory) const;
|
||||
|
||||
virtual EFileSystemType setFileListSystem(EFileSystemType listType);
|
||||
|
||||
//! Creates a list of files and directories in the current working directory
|
||||
//! and returns it.
|
||||
virtual IFileList* createFileList();
|
||||
|
||||
//! Creates an empty filelist
|
||||
virtual IFileList* createEmptyFileList(const io::path& path, bool ignoreCase, bool ignorePaths);
|
||||
|
||||
//! determines if a file exists and would be able to be opened.
|
||||
virtual bool existFile(const io::path& filename) const;
|
||||
|
||||
//! Creates a XML Reader from a file.
|
||||
virtual IXMLReader* createXMLReader(const io::path& filename);
|
||||
|
||||
//! Creates a XML Reader from a file.
|
||||
virtual IXMLReader* createXMLReader(IReadFile* file);
|
||||
|
||||
//! Creates a XML Reader from a file.
|
||||
virtual IXMLReaderUTF8* createXMLReaderUTF8(const io::path& filename);
|
||||
|
||||
//! Creates a XML Reader from a file.
|
||||
virtual IXMLReaderUTF8* createXMLReaderUTF8(IReadFile* file);
|
||||
|
||||
//! Creates a XML Writer from a file.
|
||||
virtual IXMLWriter* createXMLWriter(const io::path& filename);
|
||||
|
||||
//! Creates a XML Writer from a file.
|
||||
virtual IXMLWriter* createXMLWriter(IWriteFile* file);
|
||||
|
||||
//! Creates a new empty collection of attributes, usable for serialization and more.
|
||||
virtual IAttributes* createEmptyAttributes(video::IVideoDriver* driver);
|
||||
|
||||
private:
|
||||
|
||||
// don't expose, needs refactoring
|
||||
bool changeArchivePassword(const path& filename,
|
||||
const core::stringc& password,
|
||||
IFileArchive** archive = 0);
|
||||
|
||||
//! Currently used FileSystemType
|
||||
EFileSystemType FileSystemType;
|
||||
//! WorkingDirectory for Native and Virtual filesystems
|
||||
io::path WorkingDirectory [2];
|
||||
//! currently attached ArchiveLoaders
|
||||
core::array<IArchiveLoader*> ArchiveLoader;
|
||||
//! currently attached Archives
|
||||
core::array<IFileArchive*> FileArchives;
|
||||
};
|
||||
|
||||
|
||||
} // end namespace irr
|
||||
} // end namespace io
|
||||
|
||||
#endif
|
||||
|
531
source/Irrlicht/CGUIButton.cpp
Normal file
531
source/Irrlicht/CGUIButton.cpp
Normal file
@ -0,0 +1,531 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#include "CGUIButton.h"
|
||||
#ifdef _IRR_COMPILE_WITH_GUI_
|
||||
|
||||
#include "IGUISkin.h"
|
||||
#include "IGUIEnvironment.h"
|
||||
#include "IVideoDriver.h"
|
||||
#include "IGUIFont.h"
|
||||
#include "os.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace gui
|
||||
{
|
||||
|
||||
//! constructor
|
||||
CGUIButton::CGUIButton(IGUIEnvironment* environment, IGUIElement* parent,
|
||||
s32 id, core::rect<s32> rectangle, bool noclip)
|
||||
: IGUIButton(environment, parent, id, rectangle),
|
||||
SpriteBank(0), OverrideFont(0), Image(0), PressedImage(0),
|
||||
ClickTime(0), HoverTime(0), FocusTime(0),
|
||||
IsPushButton(false), Pressed(false),
|
||||
UseAlphaChannel(false), DrawBorder(true), ScaleImage(false)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
setDebugName("CGUIButton");
|
||||
#endif
|
||||
setNotClipped(noclip);
|
||||
|
||||
// Initialize the sprites.
|
||||
for (u32 i=0; i<EGBS_COUNT; ++i)
|
||||
ButtonSprites[i].Index = -1;
|
||||
|
||||
// This element can be tabbed.
|
||||
setTabStop(true);
|
||||
setTabOrder(-1);
|
||||
}
|
||||
|
||||
|
||||
//! destructor
|
||||
CGUIButton::~CGUIButton()
|
||||
{
|
||||
if (OverrideFont)
|
||||
OverrideFont->drop();
|
||||
|
||||
if (Image)
|
||||
Image->drop();
|
||||
|
||||
if (PressedImage)
|
||||
PressedImage->drop();
|
||||
|
||||
if (SpriteBank)
|
||||
SpriteBank->drop();
|
||||
}
|
||||
|
||||
|
||||
//! Sets if the images should be scaled to fit the button
|
||||
void CGUIButton::setScaleImage(bool scaleImage)
|
||||
{
|
||||
ScaleImage = scaleImage;
|
||||
}
|
||||
|
||||
|
||||
//! Returns whether the button scale the used images
|
||||
bool CGUIButton::isScalingImage() const
|
||||
{
|
||||
_IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX;
|
||||
return ScaleImage;
|
||||
}
|
||||
|
||||
|
||||
//! Sets if the button should use the skin to draw its border
|
||||
void CGUIButton::setDrawBorder(bool border)
|
||||
{
|
||||
DrawBorder = border;
|
||||
}
|
||||
|
||||
|
||||
void CGUIButton::setSpriteBank(IGUISpriteBank* sprites)
|
||||
{
|
||||
if (sprites)
|
||||
sprites->grab();
|
||||
|
||||
if (SpriteBank)
|
||||
SpriteBank->drop();
|
||||
|
||||
SpriteBank = sprites;
|
||||
}
|
||||
|
||||
|
||||
void CGUIButton::setSprite(EGUI_BUTTON_STATE state, s32 index, video::SColor color, bool loop)
|
||||
{
|
||||
if (SpriteBank)
|
||||
{
|
||||
ButtonSprites[(u32)state].Index = index;
|
||||
ButtonSprites[(u32)state].Color = color;
|
||||
ButtonSprites[(u32)state].Loop = loop;
|
||||
}
|
||||
else
|
||||
{
|
||||
ButtonSprites[(u32)state].Index = -1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//! called if an event happened.
|
||||
bool CGUIButton::OnEvent(const SEvent& event)
|
||||
{
|
||||
if (!isEnabled())
|
||||
return IGUIElement::OnEvent(event);
|
||||
|
||||
switch(event.EventType)
|
||||
{
|
||||
case EET_KEY_INPUT_EVENT:
|
||||
if (event.KeyInput.PressedDown &&
|
||||
(event.KeyInput.Key == KEY_RETURN || event.KeyInput.Key == KEY_SPACE))
|
||||
{
|
||||
if (!IsPushButton)
|
||||
setPressed(true);
|
||||
else
|
||||
setPressed(!Pressed);
|
||||
|
||||
return true;
|
||||
}
|
||||
if (Pressed && !IsPushButton && event.KeyInput.PressedDown && event.KeyInput.Key == KEY_ESCAPE)
|
||||
{
|
||||
setPressed(false);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
if (!event.KeyInput.PressedDown && Pressed &&
|
||||
(event.KeyInput.Key == KEY_RETURN || event.KeyInput.Key == KEY_SPACE))
|
||||
{
|
||||
|
||||
if (!IsPushButton)
|
||||
setPressed(false);
|
||||
|
||||
if (Parent)
|
||||
{
|
||||
SEvent newEvent;
|
||||
newEvent.EventType = EET_GUI_EVENT;
|
||||
newEvent.GUIEvent.Caller = this;
|
||||
newEvent.GUIEvent.Element = 0;
|
||||
newEvent.GUIEvent.EventType = EGET_BUTTON_CLICKED;
|
||||
Parent->OnEvent(newEvent);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
case EET_GUI_EVENT:
|
||||
if (event.GUIEvent.Caller == this)
|
||||
{
|
||||
if (event.GUIEvent.EventType == EGET_ELEMENT_FOCUS_LOST)
|
||||
{
|
||||
if (!IsPushButton)
|
||||
setPressed(false);
|
||||
FocusTime = os::Timer::getTime();
|
||||
}
|
||||
else if (event.GUIEvent.EventType == EGET_ELEMENT_FOCUSED)
|
||||
{
|
||||
FocusTime = os::Timer::getTime();
|
||||
}
|
||||
else if (event.GUIEvent.EventType == EGET_ELEMENT_HOVERED || event.GUIEvent.EventType == EGET_ELEMENT_LEFT)
|
||||
{
|
||||
HoverTime = os::Timer::getTime();
|
||||
}
|
||||
}
|
||||
break;
|
||||
case EET_MOUSE_INPUT_EVENT:
|
||||
if (event.MouseInput.Event == EMIE_LMOUSE_PRESSED_DOWN)
|
||||
{
|
||||
if (Environment->hasFocus(this) &&
|
||||
!AbsoluteClippingRect.isPointInside(core::position2d<s32>(event.MouseInput.X, event.MouseInput.Y)))
|
||||
{
|
||||
Environment->removeFocus(this);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!IsPushButton)
|
||||
setPressed(true);
|
||||
|
||||
Environment->setFocus(this);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
if (event.MouseInput.Event == EMIE_LMOUSE_LEFT_UP)
|
||||
{
|
||||
bool wasPressed = Pressed;
|
||||
|
||||
if ( !AbsoluteClippingRect.isPointInside( core::position2d<s32>(event.MouseInput.X, event.MouseInput.Y ) ) )
|
||||
{
|
||||
if (!IsPushButton)
|
||||
setPressed(false);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!IsPushButton)
|
||||
setPressed(false);
|
||||
else
|
||||
{
|
||||
setPressed(!Pressed);
|
||||
}
|
||||
|
||||
if ((!IsPushButton && wasPressed && Parent) ||
|
||||
(IsPushButton && wasPressed != Pressed))
|
||||
{
|
||||
SEvent newEvent;
|
||||
newEvent.EventType = EET_GUI_EVENT;
|
||||
newEvent.GUIEvent.Caller = this;
|
||||
newEvent.GUIEvent.Element = 0;
|
||||
newEvent.GUIEvent.EventType = EGET_BUTTON_CLICKED;
|
||||
Parent->OnEvent(newEvent);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return Parent ? Parent->OnEvent(event) : false;
|
||||
}
|
||||
|
||||
|
||||
//! draws the element and its children
|
||||
void CGUIButton::draw()
|
||||
{
|
||||
if (!IsVisible)
|
||||
return;
|
||||
|
||||
IGUISkin* skin = Environment->getSkin();
|
||||
video::IVideoDriver* driver = Environment->getVideoDriver();
|
||||
|
||||
// todo: move sprite up and text down if the pressed state has a sprite
|
||||
const core::position2di spritePos = AbsoluteRect.getCenter();
|
||||
|
||||
if (!Pressed)
|
||||
{
|
||||
if (DrawBorder)
|
||||
skin->draw3DButtonPaneStandard(this, AbsoluteRect, &AbsoluteClippingRect);
|
||||
|
||||
if (Image)
|
||||
{
|
||||
core::position2d<s32> pos = spritePos;
|
||||
pos.X -= ImageRect.getWidth() / 2;
|
||||
pos.Y -= ImageRect.getHeight() / 2;
|
||||
|
||||
driver->draw2DImage(Image,
|
||||
ScaleImage? AbsoluteRect :
|
||||
core::recti(pos, ImageRect.getSize()),
|
||||
ImageRect, &AbsoluteClippingRect,
|
||||
0, UseAlphaChannel);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (DrawBorder)
|
||||
skin->draw3DButtonPanePressed(this, AbsoluteRect, &AbsoluteClippingRect);
|
||||
|
||||
if (PressedImage)
|
||||
{
|
||||
core::position2d<s32> pos = spritePos;
|
||||
pos.X -= PressedImageRect.getWidth() / 2;
|
||||
pos.Y -= PressedImageRect.getHeight() / 2;
|
||||
|
||||
if (Image == PressedImage && PressedImageRect == ImageRect)
|
||||
{
|
||||
pos.X += skin->getSize(EGDS_BUTTON_PRESSED_IMAGE_OFFSET_X);
|
||||
pos.Y += skin->getSize(EGDS_BUTTON_PRESSED_IMAGE_OFFSET_Y);
|
||||
}
|
||||
driver->draw2DImage(PressedImage,
|
||||
ScaleImage? AbsoluteRect :
|
||||
core::recti(pos, PressedImageRect.getSize()),
|
||||
PressedImageRect, &AbsoluteClippingRect,
|
||||
0, UseAlphaChannel);
|
||||
}
|
||||
}
|
||||
|
||||
if (SpriteBank)
|
||||
{
|
||||
// pressed / unpressed animation
|
||||
u32 state = Pressed ? (u32)EGBS_BUTTON_DOWN : (u32)EGBS_BUTTON_UP;
|
||||
if (ButtonSprites[state].Index != -1)
|
||||
{
|
||||
SpriteBank->draw2DSprite(ButtonSprites[state].Index, spritePos,
|
||||
&AbsoluteClippingRect, ButtonSprites[state].Color, ClickTime, os::Timer::getTime(),
|
||||
ButtonSprites[state].Loop, true);
|
||||
}
|
||||
|
||||
// focused / unfocused animation
|
||||
state = Environment->hasFocus(this) ? (u32)EGBS_BUTTON_FOCUSED : (u32)EGBS_BUTTON_NOT_FOCUSED;
|
||||
if (ButtonSprites[state].Index != -1)
|
||||
{
|
||||
SpriteBank->draw2DSprite(ButtonSprites[state].Index, spritePos,
|
||||
&AbsoluteClippingRect, ButtonSprites[state].Color, FocusTime, os::Timer::getTime(),
|
||||
ButtonSprites[state].Loop, true);
|
||||
}
|
||||
|
||||
// mouse over / off animation
|
||||
if (isEnabled())
|
||||
{
|
||||
state = Environment->getHovered() == this ? (u32)EGBS_BUTTON_MOUSE_OVER : (u32)EGBS_BUTTON_MOUSE_OFF;
|
||||
if (ButtonSprites[state].Index != -1)
|
||||
{
|
||||
SpriteBank->draw2DSprite(ButtonSprites[state].Index, spritePos,
|
||||
&AbsoluteClippingRect, ButtonSprites[state].Color, HoverTime, os::Timer::getTime(),
|
||||
ButtonSprites[state].Loop, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (Text.size())
|
||||
{
|
||||
IGUIFont* font = getActiveFont();
|
||||
|
||||
core::rect<s32> rect = AbsoluteRect;
|
||||
if (Pressed)
|
||||
{
|
||||
rect.UpperLeftCorner.X += skin->getSize(EGDS_BUTTON_PRESSED_TEXT_OFFSET_X);
|
||||
rect.UpperLeftCorner.Y += skin->getSize(EGDS_BUTTON_PRESSED_TEXT_OFFSET_Y);
|
||||
}
|
||||
|
||||
if (font)
|
||||
font->draw(Text.c_str(), rect,
|
||||
skin->getColor(isEnabled() ? EGDC_BUTTON_TEXT : EGDC_GRAY_TEXT),
|
||||
true, true, &AbsoluteClippingRect);
|
||||
}
|
||||
|
||||
IGUIElement::draw();
|
||||
}
|
||||
|
||||
|
||||
//! sets another skin independent font. if this is set to zero, the button uses the font of the skin.
|
||||
void CGUIButton::setOverrideFont(IGUIFont* font)
|
||||
{
|
||||
if (OverrideFont == font)
|
||||
return;
|
||||
|
||||
if (OverrideFont)
|
||||
OverrideFont->drop();
|
||||
|
||||
OverrideFont = font;
|
||||
|
||||
if (OverrideFont)
|
||||
OverrideFont->grab();
|
||||
}
|
||||
|
||||
//! Gets the override font (if any)
|
||||
IGUIFont * CGUIButton::getOverrideFont() const
|
||||
{
|
||||
return OverrideFont;
|
||||
}
|
||||
|
||||
//! Get the font which is used right now for drawing
|
||||
IGUIFont* CGUIButton::getActiveFont() const
|
||||
{
|
||||
if ( OverrideFont )
|
||||
return OverrideFont;
|
||||
IGUISkin* skin = Environment->getSkin();
|
||||
if (skin)
|
||||
return skin->getFont(EGDF_BUTTON);
|
||||
return 0;
|
||||
}
|
||||
|
||||
//! Sets an image which should be displayed on the button when it is in normal state.
|
||||
void CGUIButton::setImage(video::ITexture* image)
|
||||
{
|
||||
if (image)
|
||||
image->grab();
|
||||
if (Image)
|
||||
Image->drop();
|
||||
|
||||
Image = image;
|
||||
if (image)
|
||||
ImageRect = core::rect<s32>(core::position2d<s32>(0,0), image->getOriginalSize());
|
||||
|
||||
if (!PressedImage)
|
||||
setPressedImage(Image);
|
||||
}
|
||||
|
||||
|
||||
//! Sets the image which should be displayed on the button when it is in its normal state.
|
||||
void CGUIButton::setImage(video::ITexture* image, const core::rect<s32>& pos)
|
||||
{
|
||||
setImage(image);
|
||||
ImageRect = pos;
|
||||
}
|
||||
|
||||
|
||||
//! Sets an image which should be displayed on the button when it is in pressed state.
|
||||
void CGUIButton::setPressedImage(video::ITexture* image)
|
||||
{
|
||||
if (image)
|
||||
image->grab();
|
||||
|
||||
if (PressedImage)
|
||||
PressedImage->drop();
|
||||
|
||||
PressedImage = image;
|
||||
if (image)
|
||||
PressedImageRect = core::rect<s32>(core::position2d<s32>(0,0), image->getOriginalSize());
|
||||
}
|
||||
|
||||
|
||||
//! Sets the image which should be displayed on the button when it is in its pressed state.
|
||||
void CGUIButton::setPressedImage(video::ITexture* image, const core::rect<s32>& pos)
|
||||
{
|
||||
setPressedImage(image);
|
||||
PressedImageRect = pos;
|
||||
}
|
||||
|
||||
|
||||
//! Sets if the button should behave like a push button. Which means it
|
||||
//! can be in two states: Normal or Pressed. With a click on the button,
|
||||
//! the user can change the state of the button.
|
||||
void CGUIButton::setIsPushButton(bool isPushButton)
|
||||
{
|
||||
IsPushButton = isPushButton;
|
||||
}
|
||||
|
||||
|
||||
//! Returns if the button is currently pressed
|
||||
bool CGUIButton::isPressed() const
|
||||
{
|
||||
_IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX;
|
||||
return Pressed;
|
||||
}
|
||||
|
||||
|
||||
//! Sets the pressed state of the button if this is a pushbutton
|
||||
void CGUIButton::setPressed(bool pressed)
|
||||
{
|
||||
if (Pressed != pressed)
|
||||
{
|
||||
ClickTime = os::Timer::getTime();
|
||||
Pressed = pressed;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//! Returns whether the button is a push button
|
||||
bool CGUIButton::isPushButton() const
|
||||
{
|
||||
_IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX;
|
||||
return IsPushButton;
|
||||
}
|
||||
|
||||
|
||||
//! Sets if the alpha channel should be used for drawing images on the button (default is false)
|
||||
void CGUIButton::setUseAlphaChannel(bool useAlphaChannel)
|
||||
{
|
||||
UseAlphaChannel = useAlphaChannel;
|
||||
}
|
||||
|
||||
|
||||
//! Returns if the alpha channel should be used for drawing images on the button
|
||||
bool CGUIButton::isAlphaChannelUsed() const
|
||||
{
|
||||
_IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX;
|
||||
return UseAlphaChannel;
|
||||
}
|
||||
|
||||
|
||||
bool CGUIButton::isDrawingBorder() const
|
||||
{
|
||||
_IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX;
|
||||
return DrawBorder;
|
||||
}
|
||||
|
||||
|
||||
//! Writes attributes of the element.
|
||||
void CGUIButton::serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options=0) const
|
||||
{
|
||||
IGUIButton::serializeAttributes(out,options);
|
||||
|
||||
out->addBool ("PushButton", IsPushButton );
|
||||
if (IsPushButton)
|
||||
out->addBool("Pressed", Pressed);
|
||||
|
||||
out->addTexture ("Image", Image);
|
||||
out->addRect ("ImageRect", ImageRect);
|
||||
out->addTexture ("PressedImage", PressedImage);
|
||||
out->addRect ("PressedImageRect", PressedImageRect);
|
||||
|
||||
out->addBool ("UseAlphaChannel", isAlphaChannelUsed());
|
||||
out->addBool ("Border", isDrawingBorder());
|
||||
out->addBool ("ScaleImage", isScalingImage());
|
||||
|
||||
// out->addString ("OverrideFont", OverrideFont);
|
||||
}
|
||||
|
||||
|
||||
//! Reads attributes of the element
|
||||
void CGUIButton::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options=0)
|
||||
{
|
||||
IGUIButton::deserializeAttributes(in,options);
|
||||
|
||||
IsPushButton = in->getAttributeAsBool("PushButton");
|
||||
Pressed = IsPushButton ? in->getAttributeAsBool("Pressed") : false;
|
||||
|
||||
core::rect<s32> rec = in->getAttributeAsRect("ImageRect");
|
||||
if (rec.isValid())
|
||||
setImage( in->getAttributeAsTexture("Image"), rec);
|
||||
else
|
||||
setImage( in->getAttributeAsTexture("Image") );
|
||||
|
||||
rec = in->getAttributeAsRect("PressedImageRect");
|
||||
if (rec.isValid())
|
||||
setPressedImage( in->getAttributeAsTexture("PressedImage"), rec);
|
||||
else
|
||||
setPressedImage( in->getAttributeAsTexture("PressedImage") );
|
||||
|
||||
setDrawBorder(in->getAttributeAsBool("Border"));
|
||||
setUseAlphaChannel(in->getAttributeAsBool("UseAlphaChannel"));
|
||||
setScaleImage(in->getAttributeAsBool("ScaleImage"));
|
||||
|
||||
// setOverrideFont(in->getAttributeAsString("OverrideFont"));
|
||||
|
||||
updateAbsolutePosition();
|
||||
}
|
||||
|
||||
|
||||
} // end namespace gui
|
||||
} // end namespace irr
|
||||
|
||||
#endif // _IRR_COMPILE_WITH_GUI_
|
||||
|
143
source/Irrlicht/CGUIButton.h
Normal file
143
source/Irrlicht/CGUIButton.h
Normal file
@ -0,0 +1,143 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#ifndef __C_GUI_BUTTON_H_INCLUDED__
|
||||
#define __C_GUI_BUTTON_H_INCLUDED__
|
||||
|
||||
#include "IrrCompileConfig.h"
|
||||
#ifdef _IRR_COMPILE_WITH_GUI_
|
||||
|
||||
#include "IGUIButton.h"
|
||||
#include "IGUISpriteBank.h"
|
||||
#include "SColor.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace gui
|
||||
{
|
||||
|
||||
class CGUIButton : public IGUIButton
|
||||
{
|
||||
public:
|
||||
|
||||
//! constructor
|
||||
CGUIButton(IGUIEnvironment* environment, IGUIElement* parent,
|
||||
s32 id, core::rect<s32> rectangle, bool noclip=false);
|
||||
|
||||
//! destructor
|
||||
virtual ~CGUIButton();
|
||||
|
||||
//! called if an event happened.
|
||||
virtual bool OnEvent(const SEvent& event);
|
||||
|
||||
//! draws the element and its children
|
||||
virtual void draw();
|
||||
|
||||
//! sets another skin independent font. if this is set to zero, the button uses the font of the skin.
|
||||
virtual void setOverrideFont(IGUIFont* font=0);
|
||||
|
||||
//! Gets the override font (if any)
|
||||
virtual IGUIFont* getOverrideFont() const;
|
||||
|
||||
//! Get the font which is used right now for drawing
|
||||
virtual IGUIFont* getActiveFont() const;
|
||||
|
||||
//! Sets an image which should be displayed on the button when it is in normal state.
|
||||
virtual void setImage(video::ITexture* image=0);
|
||||
|
||||
//! Sets an image which should be displayed on the button when it is in normal state.
|
||||
virtual void setImage(video::ITexture* image, const core::rect<s32>& pos);
|
||||
|
||||
//! Sets an image which should be displayed on the button when it is in pressed state.
|
||||
virtual void setPressedImage(video::ITexture* image=0);
|
||||
|
||||
//! Sets an image which should be displayed on the button when it is in pressed state.
|
||||
virtual void setPressedImage(video::ITexture* image, const core::rect<s32>& pos);
|
||||
|
||||
//! Sets the sprite bank used by the button
|
||||
virtual void setSpriteBank(IGUISpriteBank* bank=0);
|
||||
|
||||
//! Sets the animated sprite for a specific button state
|
||||
/** \param index: Number of the sprite within the sprite bank, use -1 for no sprite
|
||||
\param state: State of the button to set the sprite for
|
||||
\param index: The sprite number from the current sprite bank
|
||||
\param color: The color of the sprite
|
||||
*/
|
||||
virtual void setSprite(EGUI_BUTTON_STATE state, s32 index,
|
||||
video::SColor color=video::SColor(255,255,255,255), bool loop=false);
|
||||
|
||||
//! Sets if the button should behave like a push button. Which means it
|
||||
//! can be in two states: Normal or Pressed. With a click on the button,
|
||||
//! the user can change the state of the button.
|
||||
virtual void setIsPushButton(bool isPushButton=true);
|
||||
|
||||
//! Checks whether the button is a push button
|
||||
virtual bool isPushButton() const;
|
||||
|
||||
//! Sets the pressed state of the button if this is a pushbutton
|
||||
virtual void setPressed(bool pressed=true);
|
||||
|
||||
//! Returns if the button is currently pressed
|
||||
virtual bool isPressed() const;
|
||||
|
||||
//! Sets if the button should use the skin to draw its border
|
||||
virtual void setDrawBorder(bool border=true);
|
||||
|
||||
//! Checks if the button face and border are being drawn
|
||||
virtual bool isDrawingBorder() const;
|
||||
|
||||
//! Sets if the alpha channel should be used for drawing images on the button (default is false)
|
||||
virtual void setUseAlphaChannel(bool useAlphaChannel=true);
|
||||
|
||||
//! Checks if the alpha channel should be used for drawing images on the button
|
||||
virtual bool isAlphaChannelUsed() const;
|
||||
|
||||
//! Sets if the button should scale the button images to fit
|
||||
virtual void setScaleImage(bool scaleImage=true);
|
||||
|
||||
//! Checks whether the button scales the used images
|
||||
virtual bool isScalingImage() const;
|
||||
|
||||
//! Writes attributes of the element.
|
||||
virtual void serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options) const;
|
||||
|
||||
//! Reads attributes of the element
|
||||
virtual void deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options);
|
||||
|
||||
private:
|
||||
|
||||
struct ButtonSprite
|
||||
{
|
||||
s32 Index;
|
||||
video::SColor Color;
|
||||
bool Loop;
|
||||
};
|
||||
|
||||
ButtonSprite ButtonSprites[EGBS_COUNT];
|
||||
|
||||
IGUISpriteBank* SpriteBank;
|
||||
IGUIFont* OverrideFont;
|
||||
|
||||
video::ITexture* Image;
|
||||
video::ITexture* PressedImage;
|
||||
|
||||
core::rect<s32> ImageRect;
|
||||
core::rect<s32> PressedImageRect;
|
||||
|
||||
u32 ClickTime, HoverTime, FocusTime;
|
||||
|
||||
bool IsPushButton;
|
||||
bool Pressed;
|
||||
bool UseAlphaChannel;
|
||||
bool DrawBorder;
|
||||
bool ScaleImage;
|
||||
};
|
||||
|
||||
} // end namespace gui
|
||||
} // end namespace irr
|
||||
|
||||
#endif // _IRR_COMPILE_WITH_GUI_
|
||||
|
||||
#endif // __C_GUI_BUTTON_H_INCLUDED__
|
||||
|
205
source/Irrlicht/CGUICheckBox.cpp
Normal file
205
source/Irrlicht/CGUICheckBox.cpp
Normal file
@ -0,0 +1,205 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#include "CGUICheckBox.h"
|
||||
|
||||
#ifdef _IRR_COMPILE_WITH_GUI_
|
||||
|
||||
#include "IGUISkin.h"
|
||||
#include "IGUIEnvironment.h"
|
||||
#include "IVideoDriver.h"
|
||||
#include "IGUIFont.h"
|
||||
#include "os.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace gui
|
||||
{
|
||||
|
||||
//! constructor
|
||||
CGUICheckBox::CGUICheckBox(bool checked, IGUIEnvironment* environment, IGUIElement* parent, s32 id, core::rect<s32> rectangle)
|
||||
: IGUICheckBox(environment, parent, id, rectangle), checkTime(0), Pressed(false), Checked(checked)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
setDebugName("CGUICheckBox");
|
||||
#endif
|
||||
|
||||
// this element can be tabbed into
|
||||
setTabStop(true);
|
||||
setTabOrder(-1);
|
||||
}
|
||||
|
||||
|
||||
//! called if an event happened.
|
||||
bool CGUICheckBox::OnEvent(const SEvent& event)
|
||||
{
|
||||
if (isEnabled())
|
||||
{
|
||||
switch(event.EventType)
|
||||
{
|
||||
case EET_KEY_INPUT_EVENT:
|
||||
if (event.KeyInput.PressedDown &&
|
||||
(event.KeyInput.Key == KEY_RETURN || event.KeyInput.Key == KEY_SPACE))
|
||||
{
|
||||
Pressed = true;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
if (Pressed && event.KeyInput.PressedDown && event.KeyInput.Key == KEY_ESCAPE)
|
||||
{
|
||||
Pressed = false;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
if (!event.KeyInput.PressedDown && Pressed &&
|
||||
(event.KeyInput.Key == KEY_RETURN || event.KeyInput.Key == KEY_SPACE))
|
||||
{
|
||||
Pressed = false;
|
||||
if (Parent)
|
||||
{
|
||||
SEvent newEvent;
|
||||
newEvent.EventType = EET_GUI_EVENT;
|
||||
newEvent.GUIEvent.Caller = this;
|
||||
newEvent.GUIEvent.Element = 0;
|
||||
Checked = !Checked;
|
||||
newEvent.GUIEvent.EventType = EGET_CHECKBOX_CHANGED;
|
||||
Parent->OnEvent(newEvent);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
case EET_GUI_EVENT:
|
||||
if (event.GUIEvent.EventType == EGET_ELEMENT_FOCUS_LOST)
|
||||
{
|
||||
if (event.GUIEvent.Caller == this)
|
||||
Pressed = false;
|
||||
}
|
||||
break;
|
||||
case EET_MOUSE_INPUT_EVENT:
|
||||
if (event.MouseInput.Event == EMIE_LMOUSE_PRESSED_DOWN)
|
||||
{
|
||||
Pressed = true;
|
||||
checkTime = os::Timer::getTime();
|
||||
Environment->setFocus(this);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
if (event.MouseInput.Event == EMIE_LMOUSE_LEFT_UP)
|
||||
{
|
||||
bool wasPressed = Pressed;
|
||||
Environment->removeFocus(this);
|
||||
Pressed = false;
|
||||
|
||||
if (wasPressed && Parent)
|
||||
{
|
||||
if ( !AbsoluteClippingRect.isPointInside( core::position2d<s32>(event.MouseInput.X, event.MouseInput.Y) ) )
|
||||
{
|
||||
Pressed = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
SEvent newEvent;
|
||||
newEvent.EventType = EET_GUI_EVENT;
|
||||
newEvent.GUIEvent.Caller = this;
|
||||
newEvent.GUIEvent.Element = 0;
|
||||
Checked = !Checked;
|
||||
newEvent.GUIEvent.EventType = EGET_CHECKBOX_CHANGED;
|
||||
Parent->OnEvent(newEvent);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return IGUIElement::OnEvent(event);
|
||||
}
|
||||
|
||||
|
||||
//! draws the element and its children
|
||||
void CGUICheckBox::draw()
|
||||
{
|
||||
if (!IsVisible)
|
||||
return;
|
||||
|
||||
IGUISkin* skin = Environment->getSkin();
|
||||
if (skin)
|
||||
{
|
||||
const s32 height = skin->getSize(EGDS_CHECK_BOX_WIDTH);
|
||||
|
||||
core::rect<s32> checkRect(AbsoluteRect.UpperLeftCorner.X,
|
||||
((AbsoluteRect.getHeight() - height) / 2) + AbsoluteRect.UpperLeftCorner.Y,
|
||||
0, 0);
|
||||
|
||||
checkRect.LowerRightCorner.X = checkRect.UpperLeftCorner.X + height;
|
||||
checkRect.LowerRightCorner.Y = checkRect.UpperLeftCorner.Y + height;
|
||||
|
||||
EGUI_DEFAULT_COLOR col = EGDC_GRAY_EDITABLE;
|
||||
if ( isEnabled() )
|
||||
col = Pressed ? EGDC_FOCUSED_EDITABLE : EGDC_EDITABLE;
|
||||
skin->draw3DSunkenPane(this, skin->getColor(col),
|
||||
false, true, checkRect, &AbsoluteClippingRect);
|
||||
|
||||
if (Checked)
|
||||
{
|
||||
skin->drawIcon(this, EGDI_CHECK_BOX_CHECKED, checkRect.getCenter(),
|
||||
checkTime, os::Timer::getTime(), false, &AbsoluteClippingRect);
|
||||
}
|
||||
if (Text.size())
|
||||
{
|
||||
checkRect = AbsoluteRect;
|
||||
checkRect.UpperLeftCorner.X += height + 5;
|
||||
|
||||
IGUIFont* font = skin->getFont();
|
||||
if (font)
|
||||
{
|
||||
font->draw(Text.c_str(), checkRect,
|
||||
skin->getColor(isEnabled() ? EGDC_BUTTON_TEXT : EGDC_GRAY_TEXT), false, true, &AbsoluteClippingRect);
|
||||
}
|
||||
}
|
||||
}
|
||||
IGUIElement::draw();
|
||||
}
|
||||
|
||||
|
||||
//! set if box is checked
|
||||
void CGUICheckBox::setChecked(bool checked)
|
||||
{
|
||||
Checked = checked;
|
||||
}
|
||||
|
||||
|
||||
//! returns if box is checked
|
||||
bool CGUICheckBox::isChecked() const
|
||||
{
|
||||
_IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX;
|
||||
return Checked;
|
||||
}
|
||||
|
||||
|
||||
//! Writes attributes of the element.
|
||||
void CGUICheckBox::serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options=0) const
|
||||
{
|
||||
IGUICheckBox::serializeAttributes(out,options);
|
||||
out->addBool("Checked", Checked);
|
||||
}
|
||||
|
||||
|
||||
//! Reads attributes of the element
|
||||
void CGUICheckBox::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options=0)
|
||||
{
|
||||
Checked = in->getAttributeAsBool ("Checked");
|
||||
|
||||
IGUICheckBox::deserializeAttributes(in,options);
|
||||
}
|
||||
|
||||
|
||||
} // end namespace gui
|
||||
} // end namespace irr
|
||||
|
||||
#endif // _IRR_COMPILE_WITH_GUI_
|
||||
|
55
source/Irrlicht/CGUICheckBox.h
Normal file
55
source/Irrlicht/CGUICheckBox.h
Normal file
@ -0,0 +1,55 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#ifndef __C_GUI_CHECKBOX_H_INCLUDED__
|
||||
#define __C_GUI_CHECKBOX_H_INCLUDED__
|
||||
|
||||
#include "IrrCompileConfig.h"
|
||||
#ifdef _IRR_COMPILE_WITH_GUI_
|
||||
|
||||
#include "IGUICheckBox.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace gui
|
||||
{
|
||||
|
||||
class CGUICheckBox : public IGUICheckBox
|
||||
{
|
||||
public:
|
||||
|
||||
//! constructor
|
||||
CGUICheckBox(bool checked, IGUIEnvironment* environment, IGUIElement* parent, s32 id, core::rect<s32> rectangle);
|
||||
|
||||
//! set if box is checked
|
||||
virtual void setChecked(bool checked);
|
||||
|
||||
//! returns if box is checked
|
||||
virtual bool isChecked() const;
|
||||
|
||||
//! called if an event happened.
|
||||
virtual bool OnEvent(const SEvent& event);
|
||||
|
||||
//! draws the element and its children
|
||||
virtual void draw();
|
||||
|
||||
//! Writes attributes of the element.
|
||||
virtual void serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options) const;
|
||||
|
||||
//! Reads attributes of the element
|
||||
virtual void deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options);
|
||||
|
||||
private:
|
||||
|
||||
u32 checkTime;
|
||||
bool Pressed;
|
||||
bool Checked;
|
||||
};
|
||||
|
||||
} // end namespace gui
|
||||
} // end namespace irr
|
||||
|
||||
#endif // __C_GUI_CHECKBOX_H_INCLUDED__
|
||||
|
||||
#endif // _IRR_COMPILE_WITH_GUI_
|
483
source/Irrlicht/CGUIColorSelectDialog.cpp
Normal file
483
source/Irrlicht/CGUIColorSelectDialog.cpp
Normal file
@ -0,0 +1,483 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#include "CGUIColorSelectDialog.h"
|
||||
|
||||
#ifdef _IRR_COMPILE_WITH_GUI_
|
||||
|
||||
#include "IGUISkin.h"
|
||||
#include "IGUIEnvironment.h"
|
||||
#include "IVideoDriver.h"
|
||||
#include "IGUIButton.h"
|
||||
#include "IGUIStaticText.h"
|
||||
#include "IGUIFont.h"
|
||||
#include "IGUISpriteBank.h"
|
||||
#include "IFileList.h"
|
||||
#include "os.h"
|
||||
#include "fast_atof.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace gui
|
||||
{
|
||||
|
||||
const s32 CSD_WIDTH = 350;
|
||||
const s32 CSD_HEIGHT = 300;
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
struct subElementPredefines
|
||||
{
|
||||
const wchar_t *pre;
|
||||
const wchar_t *init;
|
||||
const wchar_t *post;
|
||||
int x, y;
|
||||
int range_down ,range_up;
|
||||
};
|
||||
|
||||
static const subElementPredefines Template [] =
|
||||
{
|
||||
{ L"A:", L"0", 0,50,165, 0, 255 },
|
||||
{ L"R:", L"0", 0,20,205, 0, 255 },
|
||||
{ L"G:", L"0", 0,20,230, 0, 255 },
|
||||
{ L"B:", L"0", 0,20,255, 0, 255 },
|
||||
{ L"H:", L"0", L"°",80,205, 0, 360 },
|
||||
{ L"S:", L"0", L"%",80,230, 0, 100 },
|
||||
{ L"L:", L"0", L"%",80,255, 0, 100 },
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
//! constructor
|
||||
CGUIColorSelectDialog::CGUIColorSelectDialog(const wchar_t* title, IGUIEnvironment* environment, IGUIElement* parent, s32 id)
|
||||
: IGUIColorSelectDialog(environment, parent, id,
|
||||
core::rect<s32>((parent->getAbsolutePosition().getWidth()-CSD_WIDTH)/2,
|
||||
(parent->getAbsolutePosition().getHeight()-CSD_HEIGHT)/2,
|
||||
(parent->getAbsolutePosition().getWidth()-CSD_WIDTH)/2+CSD_WIDTH,
|
||||
(parent->getAbsolutePosition().getHeight()-CSD_HEIGHT)/2+CSD_HEIGHT)),
|
||||
Dragging(false)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
IGUIElement::setDebugName("CGUIColorSelectDialog");
|
||||
#endif
|
||||
|
||||
Text = title;
|
||||
|
||||
IGUISkin* skin = Environment->getSkin();
|
||||
|
||||
const s32 buttonw = environment->getSkin()->getSize(EGDS_WINDOW_BUTTON_WIDTH);
|
||||
const s32 posx = RelativeRect.getWidth() - buttonw - 4;
|
||||
|
||||
CloseButton = Environment->addButton(core::rect<s32>(posx, 3, posx + buttonw, 3 + buttonw),
|
||||
this, -1, L"", skin ? skin->getDefaultText(EGDT_WINDOW_CLOSE) : L"Close");
|
||||
if (skin && skin->getSpriteBank())
|
||||
{
|
||||
CloseButton->setSpriteBank(skin->getSpriteBank());
|
||||
CloseButton->setSprite(EGBS_BUTTON_UP, skin->getIcon(EGDI_WINDOW_CLOSE), skin->getColor(EGDC_WINDOW_SYMBOL));
|
||||
CloseButton->setSprite(EGBS_BUTTON_DOWN, skin->getIcon(EGDI_WINDOW_CLOSE), skin->getColor(EGDC_WINDOW_SYMBOL));
|
||||
}
|
||||
CloseButton->setSubElement(true);
|
||||
CloseButton->setTabStop(false);
|
||||
CloseButton->setAlignment(EGUIA_LOWERRIGHT, EGUIA_LOWERRIGHT, EGUIA_UPPERLEFT, EGUIA_UPPERLEFT);
|
||||
CloseButton->grab();
|
||||
|
||||
OKButton = Environment->addButton(
|
||||
core::rect<s32>(RelativeRect.getWidth()-80, 30, RelativeRect.getWidth()-10, 50),
|
||||
this, -1, skin ? skin->getDefaultText(EGDT_MSG_BOX_OK) : L"OK");
|
||||
OKButton->setSubElement(true);
|
||||
OKButton->setAlignment(EGUIA_LOWERRIGHT, EGUIA_LOWERRIGHT, EGUIA_UPPERLEFT, EGUIA_UPPERLEFT);
|
||||
OKButton->grab();
|
||||
|
||||
CancelButton = Environment->addButton(
|
||||
core::rect<s32>(RelativeRect.getWidth()-80, 55, RelativeRect.getWidth()-10, 75),
|
||||
this, -1, skin ? skin->getDefaultText(EGDT_MSG_BOX_CANCEL) : L"Cancel");
|
||||
CancelButton->setSubElement(true);
|
||||
CancelButton->setAlignment(EGUIA_LOWERRIGHT, EGUIA_LOWERRIGHT, EGUIA_UPPERLEFT, EGUIA_UPPERLEFT);
|
||||
CancelButton->grab();
|
||||
|
||||
video::IVideoDriver* driver = Environment->getVideoDriver();
|
||||
ColorRing.Texture = driver->getTexture ( "#colorring" );
|
||||
if ( 0 == ColorRing.Texture )
|
||||
{
|
||||
buildColorRing(core::dimension2d<u32>(128, 128), 1,
|
||||
Environment->getSkin()->getColor(EGDC_3D_SHADOW));
|
||||
}
|
||||
|
||||
core::rect<s32> r(20,20, 0,0);
|
||||
|
||||
ColorRing.Control = Environment->addImage(ColorRing.Texture, r.UpperLeftCorner, true, this);
|
||||
ColorRing.Control->setSubElement(true);
|
||||
ColorRing.Control->grab();
|
||||
|
||||
for ( u32 i = 0; i != sizeof (Template) / sizeof ( subElementPredefines ); ++i )
|
||||
{
|
||||
if ( Template[i].pre )
|
||||
{
|
||||
r.UpperLeftCorner.X = Template[i].x;
|
||||
r.UpperLeftCorner.Y = Template[i].y;
|
||||
r.LowerRightCorner.X = r.UpperLeftCorner.X + 15;
|
||||
r.LowerRightCorner.Y = r.UpperLeftCorner.Y + 20;
|
||||
IGUIElement *t = Environment->addStaticText(Template[i].pre, r, false, false, this);
|
||||
t->setSubElement(true);
|
||||
}
|
||||
|
||||
if ( Template[i].post )
|
||||
{
|
||||
r.UpperLeftCorner.X = Template[i].x + 56;
|
||||
r.UpperLeftCorner.Y = Template[i].y;
|
||||
r.LowerRightCorner.X = r.UpperLeftCorner.X + 15;
|
||||
r.LowerRightCorner.Y = r.UpperLeftCorner.Y + 20;
|
||||
IGUIElement *t = Environment->addStaticText( Template[i].post, r, false, false, this);
|
||||
t->setSubElement(true);
|
||||
}
|
||||
|
||||
r.UpperLeftCorner.X = Template[i].x + 15;
|
||||
r.UpperLeftCorner.Y = Template[i].y-2;
|
||||
r.LowerRightCorner.X = r.UpperLeftCorner.X + 40;
|
||||
r.LowerRightCorner.Y = r.UpperLeftCorner.Y + 20;
|
||||
|
||||
gui::IGUISpinBox* spin = Environment->addSpinBox( Template[i].init, r, true, this);
|
||||
spin->setSubElement(true);
|
||||
spin->setDecimalPlaces(0);
|
||||
spin->setRange((f32)Template[i].range_down, (f32)Template[i].range_up);
|
||||
spin->grab();
|
||||
|
||||
Battery.push_back(spin);
|
||||
}
|
||||
|
||||
bringToFront(CancelButton);
|
||||
bringToFront(OKButton);
|
||||
}
|
||||
|
||||
|
||||
//! destructor
|
||||
CGUIColorSelectDialog::~CGUIColorSelectDialog()
|
||||
{
|
||||
if (CloseButton)
|
||||
CloseButton->drop();
|
||||
|
||||
if (OKButton)
|
||||
OKButton->drop();
|
||||
|
||||
if (CancelButton)
|
||||
CancelButton->drop();
|
||||
|
||||
for (u32 i = 0; i != Battery.size(); ++i)
|
||||
Battery[i]->drop();
|
||||
|
||||
if (ColorRing.Control)
|
||||
ColorRing.Control->drop();
|
||||
}
|
||||
|
||||
|
||||
//! renders a antialiased, colored ring
|
||||
void CGUIColorSelectDialog::buildColorRing( const core::dimension2d<u32> & dim, s32 supersample, const video::SColor& borderColor )
|
||||
{
|
||||
const core::dimension2d<u32> d(dim.Width * supersample, dim.Height * supersample);
|
||||
video::IVideoDriver* driver = Environment->getVideoDriver();
|
||||
|
||||
video::IImage *RawTexture = driver->createImage(video::ECF_A8R8G8B8, d);
|
||||
|
||||
RawTexture->fill ( 0x00808080 );
|
||||
|
||||
const s32 radiusOut = ( d.Width / 2 ) - 4;
|
||||
const s32 fullR2 = radiusOut * radiusOut;
|
||||
|
||||
video::SColorf rgb(0,0,0);
|
||||
video::SColorHSL hsl;
|
||||
hsl.Luminance = 50;
|
||||
hsl.Saturation = 100;
|
||||
|
||||
core::position2d<s32> p;
|
||||
for ( p.Y = -radiusOut; p.Y <= radiusOut; p.Y += 1 )
|
||||
{
|
||||
s32 y2 = p.Y * p.Y;
|
||||
|
||||
for (p.X = -radiusOut; p.X <= radiusOut; p.X += 1)
|
||||
{
|
||||
s32 r2 = y2 + ( p.X * p.X );
|
||||
|
||||
// test point in circle
|
||||
s32 testa = r2 - fullR2;
|
||||
|
||||
if ( testa < 0 )
|
||||
{
|
||||
// dotproduct u ( x,y ) * v ( 1, 0 ) = cosinus(a)
|
||||
|
||||
const f32 r = sqrtf((f32) r2);
|
||||
|
||||
// normalize, dotproduct = xnorm
|
||||
const f32 xn = r == 0.f ? 0.f : -p.X * core::reciprocal(r);
|
||||
|
||||
hsl.Hue = acosf(xn)*core::RADTODEG;
|
||||
if ( p.Y > 0 )
|
||||
hsl.Hue = 360 - hsl.Hue;
|
||||
hsl.Hue -= 90;
|
||||
|
||||
const f32 rTest = r / radiusOut;
|
||||
#if 0
|
||||
if (rTest < 0.33f)
|
||||
{
|
||||
// luminance from 0 to 50
|
||||
hsl.Luminance = 50*(rTest/0.33);
|
||||
hsl.Saturation = 0.f;
|
||||
hsl.toRGB(rgb);
|
||||
}
|
||||
else
|
||||
if ( rTest < 0.66f )
|
||||
{
|
||||
// saturation from 0 to 100
|
||||
hsl.Saturation = 100*(( rTest - 0.33f ) / 0.33f);
|
||||
hsl.Luminance = 50;
|
||||
hsl.toRGB(rgb);
|
||||
}
|
||||
else
|
||||
{
|
||||
// luminance from 50 to 100
|
||||
hsl.Luminance = 100*(0.5f + ( ( rTest - 0.66f ) / .66f ));
|
||||
hsl.Saturation = 100;
|
||||
hsl.toRGB(rgb);
|
||||
}
|
||||
// borders should be slightly transparent
|
||||
if ( rTest >= 0.95f )
|
||||
rgb.a = (1.f-rTest)*20;
|
||||
else
|
||||
rgb.a=1.f;
|
||||
#else
|
||||
if ( rTest > 0.5f )
|
||||
{
|
||||
hsl.Saturation = 100;
|
||||
hsl.Luminance = 50;
|
||||
hsl.toRGB(rgb);
|
||||
}
|
||||
// borders should be slightly transparent
|
||||
if ( rTest < 0.5f )
|
||||
rgb.a = 0;
|
||||
else if ( rTest >= 0.95f )
|
||||
rgb.a = (1.f-rTest)*20;
|
||||
else if ( rTest <= 0.55f )
|
||||
rgb.a = (rTest-0.5f)*20;
|
||||
else
|
||||
rgb.a=1.f;
|
||||
#endif
|
||||
RawTexture->setPixel(4+p.X+radiusOut, 4+p.Y+radiusOut, rgb.toSColor());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
RawTexture->unlock ();
|
||||
|
||||
if ( supersample > 1 )
|
||||
{
|
||||
video::IImage * filter = driver->createImage(video::ECF_A8R8G8B8, dim );
|
||||
RawTexture->copyToScalingBoxFilter(filter);
|
||||
RawTexture->drop();
|
||||
RawTexture = filter;
|
||||
}
|
||||
|
||||
bool generateMipLevels = driver->getTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS);
|
||||
driver->setTextureCreationFlag( video::ETCF_CREATE_MIP_MAPS, false);
|
||||
|
||||
ColorRing.Texture = driver->addTexture ( "#colorring", RawTexture);
|
||||
RawTexture->drop();
|
||||
|
||||
driver->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, generateMipLevels);
|
||||
}
|
||||
|
||||
|
||||
//! called if an event happened.
|
||||
bool CGUIColorSelectDialog::OnEvent(const SEvent& event)
|
||||
{
|
||||
if (isEnabled())
|
||||
{
|
||||
switch(event.EventType)
|
||||
{
|
||||
case EET_GUI_EVENT:
|
||||
switch(event.GUIEvent.EventType)
|
||||
{
|
||||
case EGET_SPINBOX_CHANGED:
|
||||
{
|
||||
for ( u32 i = 0; i!= Battery.size (); ++i )
|
||||
{
|
||||
if ( event.GUIEvent.Caller == Battery[i] )
|
||||
{
|
||||
if (i<4)
|
||||
{
|
||||
video::SColor rgb((u32)Battery[0]->getValue(), (u32)Battery[1]->getValue(),
|
||||
(u32)Battery[2]->getValue(), (u32)Battery[3]->getValue());
|
||||
video::SColorHSL hsl;
|
||||
video::SColorf rgb2(rgb);
|
||||
hsl.fromRGB(rgb2);
|
||||
Battery[4]->setValue(hsl.Hue);
|
||||
Battery[5]->setValue(hsl.Saturation);
|
||||
Battery[6]->setValue(hsl.Luminance);
|
||||
}
|
||||
else
|
||||
{
|
||||
video::SColorHSL hsl(Battery[4]->getValue(), Battery[5]->getValue(),
|
||||
Battery[6]->getValue());
|
||||
video::SColorf rgb2;
|
||||
hsl.toRGB(rgb2);
|
||||
video::SColor rgb = rgb2.toSColor();
|
||||
Battery[1]->setValue((f32)rgb.getRed());
|
||||
Battery[2]->setValue((f32)rgb.getGreen());
|
||||
Battery[3]->setValue((f32)rgb.getBlue());
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
case EGET_ELEMENT_FOCUS_LOST:
|
||||
Dragging = false;
|
||||
break;
|
||||
case EGET_BUTTON_CLICKED:
|
||||
if (event.GUIEvent.Caller == CloseButton ||
|
||||
event.GUIEvent.Caller == CancelButton)
|
||||
{
|
||||
sendCancelEvent();
|
||||
remove();
|
||||
return true;
|
||||
}
|
||||
else
|
||||
if (event.GUIEvent.Caller == OKButton)
|
||||
{
|
||||
sendSelectedEvent();
|
||||
remove();
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
|
||||
case EGET_LISTBOX_CHANGED:
|
||||
case EGET_LISTBOX_SELECTED_AGAIN:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case EET_MOUSE_INPUT_EVENT:
|
||||
switch(event.MouseInput.Event)
|
||||
{
|
||||
case EMIE_LMOUSE_PRESSED_DOWN:
|
||||
DragStart.X = event.MouseInput.X;
|
||||
DragStart.Y = event.MouseInput.Y;
|
||||
Dragging = true;
|
||||
Environment->setFocus(this);
|
||||
return true;
|
||||
case EMIE_LMOUSE_LEFT_UP:
|
||||
Dragging = false;
|
||||
Environment->removeFocus(this);
|
||||
return true;
|
||||
case EMIE_MOUSE_MOVED:
|
||||
if (Dragging)
|
||||
{
|
||||
// gui window should not be dragged outside its parent
|
||||
if (Parent)
|
||||
if (event.MouseInput.X < Parent->getAbsolutePosition().UpperLeftCorner.X +1 ||
|
||||
event.MouseInput.Y < Parent->getAbsolutePosition().UpperLeftCorner.Y +1 ||
|
||||
event.MouseInput.X > Parent->getAbsolutePosition().LowerRightCorner.X -1 ||
|
||||
event.MouseInput.Y > Parent->getAbsolutePosition().LowerRightCorner.Y -1)
|
||||
|
||||
return true;
|
||||
|
||||
move(core::position2d<s32>(event.MouseInput.X - DragStart.X, event.MouseInput.Y - DragStart.Y));
|
||||
DragStart.X = event.MouseInput.X;
|
||||
DragStart.Y = event.MouseInput.Y;
|
||||
return true;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return IGUIElement::OnEvent(event);
|
||||
}
|
||||
|
||||
|
||||
//! draws the element and its children
|
||||
void CGUIColorSelectDialog::draw()
|
||||
{
|
||||
if (!IsVisible)
|
||||
return;
|
||||
|
||||
IGUISkin* skin = Environment->getSkin();
|
||||
core::rect<s32> rect = skin->draw3DWindowBackground(this, true, skin->getColor(EGDC_ACTIVE_BORDER),
|
||||
AbsoluteRect, &AbsoluteClippingRect);
|
||||
|
||||
if (Text.size())
|
||||
{
|
||||
rect.UpperLeftCorner.X += 2;
|
||||
rect.LowerRightCorner.X -= skin->getSize(EGDS_WINDOW_BUTTON_WIDTH) + 5;
|
||||
|
||||
IGUIFont* font = skin->getFont(EGDF_WINDOW);
|
||||
if (font)
|
||||
font->draw(Text.c_str(), rect, skin->getColor(EGDC_ACTIVE_CAPTION), false, true,
|
||||
&AbsoluteClippingRect);
|
||||
}
|
||||
|
||||
IGUIElement::draw();
|
||||
|
||||
// draw color selector after the window elements
|
||||
core::vector2di pos(ColorRing.Control->getAbsolutePosition().UpperLeftCorner);
|
||||
pos.X += ColorRing.Texture->getOriginalSize().Width/2;
|
||||
pos.Y += ColorRing.Texture->getOriginalSize().Height/2;
|
||||
#if 0
|
||||
const f32 h = Battery[4]->getValue();
|
||||
const f32 s = Battery[5]->getValue();
|
||||
const f32 l = Battery[6]->getValue();
|
||||
const f32 factor = 58.f*(((s==0)&&(l<50))?(l*0.33f/50):(
|
||||
(s<100)?((.33f+(s*0.33f/100))):((0.66f+(l-50)*0.33f/50))));
|
||||
|
||||
#else
|
||||
const f32 factor = 44;
|
||||
#endif
|
||||
pos.X += core::round32(sinf(Battery[4]->getValue()*core::DEGTORAD)*factor);
|
||||
pos.Y -= core::round32(cosf(Battery[4]->getValue()*core::DEGTORAD)*factor);
|
||||
Environment->getVideoDriver()->draw2DPolygon(pos, 4, 0xffffffff, 4);
|
||||
}
|
||||
|
||||
|
||||
video::SColor CGUIColorSelectDialog::getColor()
|
||||
{
|
||||
return video::SColor((u32)Battery[0]->getValue(), (u32)Battery[1]->getValue(),
|
||||
(u32)Battery[2]->getValue(), (u32)Battery[3]->getValue());
|
||||
}
|
||||
|
||||
video::SColorHSL CGUIColorSelectDialog::getColorHSL()
|
||||
{
|
||||
return video::SColorHSL(Battery[4]->getValue(), Battery[5]->getValue(),
|
||||
Battery[6]->getValue());
|
||||
}
|
||||
|
||||
//! sends the event that the file has been selected.
|
||||
void CGUIColorSelectDialog::sendSelectedEvent()
|
||||
{
|
||||
SEvent event;
|
||||
event.EventType = EET_GUI_EVENT;
|
||||
event.GUIEvent.Caller = this;
|
||||
event.GUIEvent.Element = 0;
|
||||
event.GUIEvent.EventType = EGET_FILE_SELECTED;
|
||||
Parent->OnEvent(event);
|
||||
}
|
||||
|
||||
|
||||
//! sends the event that the file choose process has been canceld
|
||||
void CGUIColorSelectDialog::sendCancelEvent()
|
||||
{
|
||||
SEvent event;
|
||||
event.EventType = EET_GUI_EVENT;
|
||||
event.GUIEvent.Caller = this;
|
||||
event.GUIEvent.Element = 0;
|
||||
event.GUIEvent.EventType = EGET_FILE_CHOOSE_DIALOG_CANCELLED;
|
||||
Parent->OnEvent(event);
|
||||
}
|
||||
|
||||
|
||||
} // end namespace gui
|
||||
} // end namespace irr
|
||||
|
||||
#endif // _IRR_COMPILE_WITH_GUI_
|
74
source/Irrlicht/CGUIColorSelectDialog.h
Normal file
74
source/Irrlicht/CGUIColorSelectDialog.h
Normal file
@ -0,0 +1,74 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#ifndef __C_GUI_COLOR_SELECT_DIALOG_H_INCLUDED__
|
||||
#define __C_GUI_COLOR_SELECT_DIALOG_H_INCLUDED__
|
||||
|
||||
#include "IrrCompileConfig.h"
|
||||
#ifdef _IRR_COMPILE_WITH_GUI_
|
||||
|
||||
#include "IGUIColorSelectDialog.h"
|
||||
#include "IGUIButton.h"
|
||||
#include "IGUISpinBox.h"
|
||||
#include "IGUIImage.h"
|
||||
#include "irrArray.h"
|
||||
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace gui
|
||||
{
|
||||
|
||||
class CGUIColorSelectDialog : public IGUIColorSelectDialog
|
||||
{
|
||||
public:
|
||||
|
||||
//! constructor
|
||||
CGUIColorSelectDialog(const wchar_t* title, IGUIEnvironment* environment, IGUIElement* parent, s32 id);
|
||||
|
||||
//! destructor
|
||||
virtual ~CGUIColorSelectDialog();
|
||||
|
||||
//! called if an event happened.
|
||||
virtual bool OnEvent(const SEvent& event);
|
||||
|
||||
//! draws the element and its children
|
||||
virtual void draw();
|
||||
|
||||
virtual video::SColor getColor();
|
||||
virtual video::SColorHSL getColorHSL();
|
||||
|
||||
private:
|
||||
|
||||
//! sends the event that the file has been selected.
|
||||
void sendSelectedEvent();
|
||||
|
||||
//! sends the event that the file choose process has been canceld
|
||||
void sendCancelEvent();
|
||||
|
||||
core::position2d<s32> DragStart;
|
||||
bool Dragging;
|
||||
IGUIButton* CloseButton;
|
||||
IGUIButton* OKButton;
|
||||
IGUIButton* CancelButton;
|
||||
|
||||
core::array<IGUISpinBox*> Battery;
|
||||
|
||||
struct SColorCircle
|
||||
{
|
||||
IGUIImage * Control;
|
||||
video::ITexture * Texture;
|
||||
};
|
||||
SColorCircle ColorRing;
|
||||
|
||||
void buildColorRing( const core::dimension2d<u32> & dim, s32 supersample, const video::SColor& borderColor );
|
||||
};
|
||||
|
||||
|
||||
} // end namespace gui
|
||||
} // end namespace irr
|
||||
|
||||
#endif // _IRR_COMPILE_WITH_GUI_
|
||||
|
||||
#endif // __C_GUI_COLOR_SELECT_DIALOG_H_INCLUDED__
|
523
source/Irrlicht/CGUIComboBox.cpp
Normal file
523
source/Irrlicht/CGUIComboBox.cpp
Normal file
@ -0,0 +1,523 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#include "CGUIComboBox.h"
|
||||
#ifdef _IRR_COMPILE_WITH_GUI_
|
||||
|
||||
#include "IGUIEnvironment.h"
|
||||
#include "IVideoDriver.h"
|
||||
#include "IGUISkin.h"
|
||||
#include "IGUIEnvironment.h"
|
||||
#include "IGUIFont.h"
|
||||
#include "IGUIButton.h"
|
||||
#include "CGUIListBox.h"
|
||||
#include "os.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace gui
|
||||
{
|
||||
|
||||
//! constructor
|
||||
CGUIComboBox::CGUIComboBox(IGUIEnvironment* environment, IGUIElement* parent,
|
||||
s32 id, core::rect<s32> rectangle)
|
||||
: IGUIComboBox(environment, parent, id, rectangle),
|
||||
ListButton(0), SelectedText(0), ListBox(0), LastFocus(0),
|
||||
Selected(-1), HAlign(EGUIA_UPPERLEFT), VAlign(EGUIA_CENTER), MaxSelectionRows(5), HasFocus(false)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
setDebugName("CGUIComboBox");
|
||||
#endif
|
||||
|
||||
IGUISkin* skin = Environment->getSkin();
|
||||
|
||||
s32 width = 15;
|
||||
if (skin)
|
||||
width = skin->getSize(EGDS_WINDOW_BUTTON_WIDTH);
|
||||
|
||||
core::rect<s32> r;
|
||||
r.UpperLeftCorner.X = rectangle.getWidth() - width - 2;
|
||||
r.LowerRightCorner.X = rectangle.getWidth() - 2;
|
||||
|
||||
r.UpperLeftCorner.Y = 2;
|
||||
r.LowerRightCorner.Y = rectangle.getHeight() - 2;
|
||||
|
||||
ListButton = Environment->addButton(r, this, -1, L"");
|
||||
if (skin && skin->getSpriteBank())
|
||||
{
|
||||
ListButton->setSpriteBank(skin->getSpriteBank());
|
||||
ListButton->setSprite(EGBS_BUTTON_UP, skin->getIcon(EGDI_CURSOR_DOWN), skin->getColor(EGDC_WINDOW_SYMBOL));
|
||||
ListButton->setSprite(EGBS_BUTTON_DOWN, skin->getIcon(EGDI_CURSOR_DOWN), skin->getColor(EGDC_WINDOW_SYMBOL));
|
||||
}
|
||||
ListButton->setAlignment(EGUIA_LOWERRIGHT, EGUIA_LOWERRIGHT, EGUIA_UPPERLEFT, EGUIA_LOWERRIGHT);
|
||||
ListButton->setSubElement(true);
|
||||
ListButton->setTabStop(false);
|
||||
|
||||
r.UpperLeftCorner.X = 2;
|
||||
r.UpperLeftCorner.Y = 2;
|
||||
r.LowerRightCorner.X = RelativeRect.getWidth() - (ListButton->getAbsolutePosition().getWidth() + 2);
|
||||
r.LowerRightCorner.Y = RelativeRect.getHeight() - 2;
|
||||
|
||||
SelectedText = Environment->addStaticText(L"", r, false, false, this, -1, false);
|
||||
SelectedText->setSubElement(true);
|
||||
SelectedText->setAlignment(EGUIA_UPPERLEFT, EGUIA_LOWERRIGHT, EGUIA_UPPERLEFT, EGUIA_LOWERRIGHT);
|
||||
SelectedText->setTextAlignment(EGUIA_UPPERLEFT, EGUIA_CENTER);
|
||||
if (skin)
|
||||
SelectedText->setOverrideColor(skin->getColor(EGDC_BUTTON_TEXT));
|
||||
SelectedText->enableOverrideColor(true);
|
||||
|
||||
// this element can be tabbed to
|
||||
setTabStop(true);
|
||||
setTabOrder(-1);
|
||||
}
|
||||
|
||||
|
||||
void CGUIComboBox::setTextAlignment(EGUI_ALIGNMENT horizontal, EGUI_ALIGNMENT vertical)
|
||||
{
|
||||
HAlign = horizontal;
|
||||
VAlign = vertical;
|
||||
SelectedText->setTextAlignment(horizontal, vertical);
|
||||
}
|
||||
|
||||
|
||||
//! Set the maximal number of rows for the selection listbox
|
||||
void CGUIComboBox::setMaxSelectionRows(u32 max)
|
||||
{
|
||||
MaxSelectionRows = max;
|
||||
|
||||
// force recalculation of open listbox
|
||||
if (ListBox)
|
||||
{
|
||||
openCloseMenu();
|
||||
openCloseMenu();
|
||||
}
|
||||
}
|
||||
|
||||
//! Get the maximimal number of rows for the selection listbox
|
||||
u32 CGUIComboBox::getMaxSelectionRows() const
|
||||
{
|
||||
return MaxSelectionRows;
|
||||
}
|
||||
|
||||
|
||||
//! Returns amount of items in box
|
||||
u32 CGUIComboBox::getItemCount() const
|
||||
{
|
||||
return Items.size();
|
||||
}
|
||||
|
||||
|
||||
//! returns string of an item. the idx may be a value from 0 to itemCount-1
|
||||
const wchar_t* CGUIComboBox::getItem(u32 idx) const
|
||||
{
|
||||
if (idx >= Items.size())
|
||||
return 0;
|
||||
|
||||
return Items[idx].Name.c_str();
|
||||
}
|
||||
|
||||
//! returns string of an item. the idx may be a value from 0 to itemCount-1
|
||||
u32 CGUIComboBox::getItemData(u32 idx) const
|
||||
{
|
||||
if (idx >= Items.size())
|
||||
return 0;
|
||||
|
||||
return Items[idx].Data;
|
||||
}
|
||||
|
||||
//! Returns index based on item data
|
||||
s32 CGUIComboBox::getIndexForItemData(u32 data ) const
|
||||
{
|
||||
for ( u32 i = 0; i < Items.size (); ++i )
|
||||
{
|
||||
if ( Items[i].Data == data )
|
||||
return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
//! Removes an item from the combo box.
|
||||
void CGUIComboBox::removeItem(u32 idx)
|
||||
{
|
||||
if (idx >= Items.size())
|
||||
return;
|
||||
|
||||
if (Selected == (s32)idx)
|
||||
setSelected(-1);
|
||||
|
||||
Items.erase(idx);
|
||||
}
|
||||
|
||||
|
||||
//! Returns caption of this element.
|
||||
const wchar_t* CGUIComboBox::getText() const
|
||||
{
|
||||
return getItem(Selected);
|
||||
}
|
||||
|
||||
|
||||
//! adds an item and returns the index of it
|
||||
u32 CGUIComboBox::addItem(const wchar_t* text, u32 data)
|
||||
{
|
||||
Items.push_back( SComboData ( text, data ) );
|
||||
|
||||
if (Selected == -1)
|
||||
setSelected(0);
|
||||
|
||||
return Items.size() - 1;
|
||||
}
|
||||
|
||||
|
||||
//! deletes all items in the combo box
|
||||
void CGUIComboBox::clear()
|
||||
{
|
||||
Items.clear();
|
||||
setSelected(-1);
|
||||
}
|
||||
|
||||
|
||||
//! returns id of selected item. returns -1 if no item is selected.
|
||||
s32 CGUIComboBox::getSelected() const
|
||||
{
|
||||
return Selected;
|
||||
}
|
||||
|
||||
|
||||
//! sets the selected item. Set this to -1 if no item should be selected
|
||||
void CGUIComboBox::setSelected(s32 idx)
|
||||
{
|
||||
if (idx < -1 || idx >= (s32)Items.size())
|
||||
return;
|
||||
|
||||
Selected = idx;
|
||||
if (Selected == -1)
|
||||
SelectedText->setText(L"");
|
||||
else
|
||||
SelectedText->setText(Items[Selected].Name.c_str());
|
||||
}
|
||||
|
||||
|
||||
//! called if an event happened.
|
||||
bool CGUIComboBox::OnEvent(const SEvent& event)
|
||||
{
|
||||
if (isEnabled())
|
||||
{
|
||||
switch(event.EventType)
|
||||
{
|
||||
|
||||
case EET_KEY_INPUT_EVENT:
|
||||
if (ListBox && event.KeyInput.PressedDown && event.KeyInput.Key == KEY_ESCAPE)
|
||||
{
|
||||
// hide list box
|
||||
openCloseMenu();
|
||||
return true;
|
||||
}
|
||||
else
|
||||
if (event.KeyInput.Key == KEY_RETURN || event.KeyInput.Key == KEY_SPACE)
|
||||
{
|
||||
if (!event.KeyInput.PressedDown)
|
||||
{
|
||||
openCloseMenu();
|
||||
}
|
||||
|
||||
ListButton->setPressed(ListBox == 0);
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
if (event.KeyInput.PressedDown)
|
||||
{
|
||||
s32 oldSelected = Selected;
|
||||
bool absorb = true;
|
||||
switch (event.KeyInput.Key)
|
||||
{
|
||||
case KEY_DOWN:
|
||||
setSelected(Selected+1);
|
||||
break;
|
||||
case KEY_UP:
|
||||
setSelected(Selected-1);
|
||||
break;
|
||||
case KEY_HOME:
|
||||
case KEY_PRIOR:
|
||||
setSelected(0);
|
||||
break;
|
||||
case KEY_END:
|
||||
case KEY_NEXT:
|
||||
setSelected((s32)Items.size()-1);
|
||||
break;
|
||||
default:
|
||||
absorb = false;
|
||||
}
|
||||
|
||||
if (Selected <0)
|
||||
setSelected(0);
|
||||
|
||||
if (Selected >= (s32)Items.size())
|
||||
setSelected((s32)Items.size() -1);
|
||||
|
||||
if (Selected != oldSelected)
|
||||
{
|
||||
sendSelectionChangedEvent();
|
||||
return true;
|
||||
}
|
||||
|
||||
if (absorb)
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
|
||||
case EET_GUI_EVENT:
|
||||
|
||||
switch(event.GUIEvent.EventType)
|
||||
{
|
||||
case EGET_ELEMENT_FOCUS_LOST:
|
||||
if (ListBox &&
|
||||
(Environment->hasFocus(ListBox) || ListBox->isMyChild(event.GUIEvent.Caller) ) &&
|
||||
event.GUIEvent.Element != this &&
|
||||
!isMyChild(event.GUIEvent.Element) &&
|
||||
!ListBox->isMyChild(event.GUIEvent.Element))
|
||||
{
|
||||
openCloseMenu();
|
||||
}
|
||||
break;
|
||||
case EGET_BUTTON_CLICKED:
|
||||
if (event.GUIEvent.Caller == ListButton)
|
||||
{
|
||||
openCloseMenu();
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
case EGET_LISTBOX_SELECTED_AGAIN:
|
||||
case EGET_LISTBOX_CHANGED:
|
||||
if (event.GUIEvent.Caller == ListBox)
|
||||
{
|
||||
setSelected(ListBox->getSelected());
|
||||
if (Selected <0 || Selected >= (s32)Items.size())
|
||||
setSelected(-1);
|
||||
openCloseMenu();
|
||||
|
||||
sendSelectionChangedEvent();
|
||||
}
|
||||
return true;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case EET_MOUSE_INPUT_EVENT:
|
||||
|
||||
switch(event.MouseInput.Event)
|
||||
{
|
||||
case EMIE_LMOUSE_PRESSED_DOWN:
|
||||
{
|
||||
core::position2d<s32> p(event.MouseInput.X, event.MouseInput.Y);
|
||||
|
||||
// send to list box
|
||||
if (ListBox && ListBox->isPointInside(p) && ListBox->OnEvent(event))
|
||||
return true;
|
||||
|
||||
return true;
|
||||
}
|
||||
case EMIE_LMOUSE_LEFT_UP:
|
||||
{
|
||||
core::position2d<s32> p(event.MouseInput.X, event.MouseInput.Y);
|
||||
|
||||
// send to list box
|
||||
if (!(ListBox &&
|
||||
ListBox->getAbsolutePosition().isPointInside(p) &&
|
||||
ListBox->OnEvent(event)))
|
||||
{
|
||||
openCloseMenu();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
case EMIE_MOUSE_WHEEL:
|
||||
{
|
||||
s32 oldSelected = Selected;
|
||||
setSelected( Selected + ((event.MouseInput.Wheel < 0) ? 1 : -1));
|
||||
|
||||
if (Selected <0)
|
||||
setSelected(0);
|
||||
|
||||
if (Selected >= (s32)Items.size())
|
||||
setSelected((s32)Items.size() -1);
|
||||
|
||||
if (Selected != oldSelected)
|
||||
{
|
||||
sendSelectionChangedEvent();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return IGUIElement::OnEvent(event);
|
||||
}
|
||||
|
||||
|
||||
void CGUIComboBox::sendSelectionChangedEvent()
|
||||
{
|
||||
if (Parent)
|
||||
{
|
||||
SEvent event;
|
||||
|
||||
event.EventType = EET_GUI_EVENT;
|
||||
event.GUIEvent.Caller = this;
|
||||
event.GUIEvent.Element = 0;
|
||||
event.GUIEvent.EventType = EGET_COMBO_BOX_CHANGED;
|
||||
Parent->OnEvent(event);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//! draws the element and its children
|
||||
void CGUIComboBox::draw()
|
||||
{
|
||||
if (!IsVisible)
|
||||
return;
|
||||
|
||||
IGUISkin* skin = Environment->getSkin();
|
||||
IGUIElement *currentFocus = Environment->getFocus();
|
||||
if (currentFocus != LastFocus)
|
||||
{
|
||||
HasFocus = currentFocus == this || isMyChild(currentFocus);
|
||||
LastFocus = currentFocus;
|
||||
}
|
||||
|
||||
// set colors each time as skin-colors can be changed
|
||||
SelectedText->setBackgroundColor(skin->getColor(EGDC_HIGH_LIGHT));
|
||||
if(isEnabled())
|
||||
{
|
||||
SelectedText->setDrawBackground(HasFocus);
|
||||
SelectedText->setOverrideColor(skin->getColor(HasFocus ? EGDC_HIGH_LIGHT_TEXT : EGDC_BUTTON_TEXT));
|
||||
}
|
||||
else
|
||||
{
|
||||
SelectedText->setDrawBackground(false);
|
||||
SelectedText->setOverrideColor(skin->getColor(EGDC_GRAY_TEXT));
|
||||
}
|
||||
ListButton->setSprite(EGBS_BUTTON_UP, skin->getIcon(EGDI_CURSOR_DOWN), skin->getColor(isEnabled() ? EGDC_WINDOW_SYMBOL : EGDC_GRAY_WINDOW_SYMBOL));
|
||||
ListButton->setSprite(EGBS_BUTTON_DOWN, skin->getIcon(EGDI_CURSOR_DOWN), skin->getColor(isEnabled() ? EGDC_WINDOW_SYMBOL : EGDC_GRAY_WINDOW_SYMBOL));
|
||||
|
||||
|
||||
core::rect<s32> frameRect(AbsoluteRect);
|
||||
|
||||
// draw the border
|
||||
|
||||
skin->draw3DSunkenPane(this, skin->getColor(EGDC_3D_HIGH_LIGHT),
|
||||
true, true, frameRect, &AbsoluteClippingRect);
|
||||
|
||||
// draw children
|
||||
IGUIElement::draw();
|
||||
}
|
||||
|
||||
|
||||
void CGUIComboBox::openCloseMenu()
|
||||
{
|
||||
if (ListBox)
|
||||
{
|
||||
// close list box
|
||||
Environment->setFocus(this);
|
||||
ListBox->remove();
|
||||
ListBox = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (Parent)
|
||||
Parent->bringToFront(this);
|
||||
|
||||
IGUISkin* skin = Environment->getSkin();
|
||||
u32 h = Items.size();
|
||||
|
||||
if (h > getMaxSelectionRows())
|
||||
h = getMaxSelectionRows();
|
||||
if (h == 0)
|
||||
h = 1;
|
||||
|
||||
IGUIFont* font = skin->getFont();
|
||||
if (font)
|
||||
h *= (font->getDimension(L"A").Height + 4);
|
||||
|
||||
// open list box
|
||||
core::rect<s32> r(0, AbsoluteRect.getHeight(),
|
||||
AbsoluteRect.getWidth(), AbsoluteRect.getHeight() + h);
|
||||
|
||||
ListBox = new CGUIListBox(Environment, this, -1, r, false, true, true);
|
||||
ListBox->setSubElement(true);
|
||||
ListBox->setNotClipped(true);
|
||||
ListBox->drop();
|
||||
|
||||
// ensure that list box is always completely visible
|
||||
if (ListBox->getAbsolutePosition().LowerRightCorner.Y > Environment->getRootGUIElement()->getAbsolutePosition().getHeight())
|
||||
ListBox->setRelativePosition( core::rect<s32>(0, -ListBox->getAbsolutePosition().getHeight(), AbsoluteRect.getWidth(), 0) );
|
||||
|
||||
for (s32 i=0; i<(s32)Items.size(); ++i)
|
||||
ListBox->addItem(Items[i].Name.c_str());
|
||||
|
||||
ListBox->setSelected(Selected);
|
||||
|
||||
// set focus
|
||||
Environment->setFocus(ListBox);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//! Writes attributes of the element.
|
||||
void CGUIComboBox::serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options=0) const
|
||||
{
|
||||
IGUIComboBox::serializeAttributes(out,options);
|
||||
|
||||
out->addEnum ("HTextAlign", HAlign, GUIAlignmentNames);
|
||||
out->addEnum ("VTextAlign", VAlign, GUIAlignmentNames);
|
||||
out->addInt("MaxSelectionRows", (s32)MaxSelectionRows );
|
||||
|
||||
out->addInt ("Selected", Selected );
|
||||
out->addInt ("ItemCount", Items.size());
|
||||
for (u32 i=0; i < Items.size(); ++i)
|
||||
{
|
||||
core::stringc s = "Item";
|
||||
s += i;
|
||||
s += "Text";
|
||||
out->addString(s.c_str(), Items[i].Name.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//! Reads attributes of the element
|
||||
void CGUIComboBox::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options=0)
|
||||
{
|
||||
IGUIComboBox::deserializeAttributes(in,options);
|
||||
|
||||
setTextAlignment( (EGUI_ALIGNMENT) in->getAttributeAsEnumeration("HTextAlign", GUIAlignmentNames),
|
||||
(EGUI_ALIGNMENT) in->getAttributeAsEnumeration("VTextAlign", GUIAlignmentNames));
|
||||
setMaxSelectionRows( (u32)(in->getAttributeAsInt("MaxSelectionRows")) );
|
||||
|
||||
// clear the list
|
||||
clear();
|
||||
// get item count
|
||||
u32 c = in->getAttributeAsInt("ItemCount");
|
||||
// add items
|
||||
for (u32 i=0; i < c; ++i)
|
||||
{
|
||||
core::stringc s = "Item";
|
||||
s += i;
|
||||
s += "Text";
|
||||
addItem(in->getAttributeAsStringW(s.c_str()).c_str(), 0);
|
||||
}
|
||||
|
||||
setSelected(in->getAttributeAsInt("Selected"));
|
||||
}
|
||||
|
||||
} // end namespace gui
|
||||
} // end namespace irr
|
||||
|
||||
|
||||
#endif // _IRR_COMPILE_WITH_GUI_
|
||||
|
117
source/Irrlicht/CGUIComboBox.h
Normal file
117
source/Irrlicht/CGUIComboBox.h
Normal file
@ -0,0 +1,117 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#ifndef __C_GUI_COMBO_BOX_H_INCLUDED__
|
||||
#define __C_GUI_COMBO_BOX_H_INCLUDED__
|
||||
|
||||
#include "IrrCompileConfig.h"
|
||||
#ifdef _IRR_COMPILE_WITH_GUI_
|
||||
|
||||
#include "IGUIComboBox.h"
|
||||
#include "IGUIStaticText.h"
|
||||
#include "irrString.h"
|
||||
#include "irrArray.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace gui
|
||||
{
|
||||
class IGUIButton;
|
||||
class IGUIListBox;
|
||||
|
||||
//! Single line edit box for editing simple text.
|
||||
class CGUIComboBox : public IGUIComboBox
|
||||
{
|
||||
public:
|
||||
|
||||
//! constructor
|
||||
CGUIComboBox(IGUIEnvironment* environment, IGUIElement* parent,
|
||||
s32 id, core::rect<s32> rectangle);
|
||||
|
||||
//! Returns amount of items in box
|
||||
virtual u32 getItemCount() const;
|
||||
|
||||
//! returns string of an item. the idx may be a value from 0 to itemCount-1
|
||||
virtual const wchar_t* getItem(u32 idx) const;
|
||||
|
||||
//! Returns item data of an item. the idx may be a value from 0 to itemCount-1
|
||||
virtual u32 getItemData(u32 idx) const;
|
||||
|
||||
//! Returns index based on item data
|
||||
virtual s32 getIndexForItemData( u32 data ) const;
|
||||
|
||||
//! adds an item and returns the index of it
|
||||
virtual u32 addItem(const wchar_t* text, u32 data);
|
||||
|
||||
//! Removes an item from the combo box.
|
||||
virtual void removeItem(u32 id);
|
||||
|
||||
//! deletes all items in the combo box
|
||||
virtual void clear();
|
||||
|
||||
//! returns the text of the currently selected item
|
||||
virtual const wchar_t* getText() const;
|
||||
|
||||
//! returns id of selected item. returns -1 if no item is selected.
|
||||
virtual s32 getSelected() const;
|
||||
|
||||
//! sets the selected item. Set this to -1 if no item should be selected
|
||||
virtual void setSelected(s32 idx);
|
||||
|
||||
//! sets the text alignment of the text part
|
||||
virtual void setTextAlignment(EGUI_ALIGNMENT horizontal, EGUI_ALIGNMENT vertical);
|
||||
|
||||
//! Set the maximal number of rows for the selection listbox
|
||||
virtual void setMaxSelectionRows(u32 max);
|
||||
|
||||
//! Get the maximimal number of rows for the selection listbox
|
||||
virtual u32 getMaxSelectionRows() const;
|
||||
|
||||
//! called if an event happened.
|
||||
virtual bool OnEvent(const SEvent& event);
|
||||
|
||||
//! draws the element and its children
|
||||
virtual void draw();
|
||||
|
||||
//! Writes attributes of the element.
|
||||
virtual void serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options) const;
|
||||
|
||||
//! Reads attributes of the element
|
||||
virtual void deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options);
|
||||
|
||||
private:
|
||||
|
||||
void openCloseMenu();
|
||||
void sendSelectionChangedEvent();
|
||||
|
||||
IGUIButton* ListButton;
|
||||
IGUIStaticText* SelectedText;
|
||||
IGUIListBox* ListBox;
|
||||
IGUIElement *LastFocus;
|
||||
|
||||
|
||||
struct SComboData
|
||||
{
|
||||
SComboData ( const wchar_t * text, u32 data )
|
||||
: Name (text), Data ( data ) {}
|
||||
|
||||
core::stringw Name;
|
||||
u32 Data;
|
||||
};
|
||||
core::array< SComboData > Items;
|
||||
|
||||
s32 Selected;
|
||||
EGUI_ALIGNMENT HAlign, VAlign;
|
||||
u32 MaxSelectionRows;
|
||||
bool HasFocus;
|
||||
};
|
||||
|
||||
|
||||
} // end namespace gui
|
||||
} // end namespace irr
|
||||
|
||||
#endif // _IRR_COMPILE_WITH_GUI_
|
||||
|
||||
#endif // __C_GUI_COMBO_BOX_H_INCLUDED__
|
||||
|
869
source/Irrlicht/CGUIContextMenu.cpp
Normal file
869
source/Irrlicht/CGUIContextMenu.cpp
Normal file
@ -0,0 +1,869 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#include "CGUIContextMenu.h"
|
||||
|
||||
#ifdef _IRR_COMPILE_WITH_GUI_
|
||||
|
||||
#include "IGUISkin.h"
|
||||
#include "IGUIEnvironment.h"
|
||||
#include "IVideoDriver.h"
|
||||
#include "IGUIFont.h"
|
||||
#include "IGUISpriteBank.h"
|
||||
#include "os.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace gui
|
||||
{
|
||||
|
||||
|
||||
//! constructor
|
||||
CGUIContextMenu::CGUIContextMenu(IGUIEnvironment* environment,
|
||||
IGUIElement* parent, s32 id,
|
||||
core::rect<s32> rectangle, bool getFocus, bool allowFocus)
|
||||
: IGUIContextMenu(environment, parent, id, rectangle), EventParent(0), LastFont(0),
|
||||
CloseHandling(ECMC_REMOVE), HighLighted(-1), ChangeTime(0), AllowFocus(allowFocus)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
setDebugName("CGUIContextMenu");
|
||||
#endif
|
||||
|
||||
Pos = rectangle.UpperLeftCorner;
|
||||
recalculateSize();
|
||||
|
||||
if (getFocus)
|
||||
Environment->setFocus(this);
|
||||
|
||||
setNotClipped(true);
|
||||
}
|
||||
|
||||
|
||||
//! destructor
|
||||
CGUIContextMenu::~CGUIContextMenu()
|
||||
{
|
||||
for (u32 i=0; i<Items.size(); ++i)
|
||||
if (Items[i].SubMenu)
|
||||
Items[i].SubMenu->drop();
|
||||
|
||||
if (LastFont)
|
||||
LastFont->drop();
|
||||
}
|
||||
|
||||
//! set behavior when menus are closed
|
||||
void CGUIContextMenu::setCloseHandling(ECONTEXT_MENU_CLOSE onClose)
|
||||
{
|
||||
CloseHandling = onClose;
|
||||
}
|
||||
|
||||
//! get current behavior when the menue will be closed
|
||||
ECONTEXT_MENU_CLOSE CGUIContextMenu::getCloseHandling() const
|
||||
{
|
||||
return CloseHandling;
|
||||
}
|
||||
|
||||
//! Returns amount of menu items
|
||||
u32 CGUIContextMenu::getItemCount() const
|
||||
{
|
||||
return Items.size();
|
||||
}
|
||||
|
||||
|
||||
//! Adds a menu item.
|
||||
u32 CGUIContextMenu::addItem(const wchar_t* text, s32 commandId, bool enabled, bool hasSubMenu, bool checked, bool autoChecking)
|
||||
{
|
||||
return insertItem(Items.size(), text, commandId, enabled, hasSubMenu, checked, autoChecking);
|
||||
}
|
||||
|
||||
//! Insert a menu item at specified position.
|
||||
u32 CGUIContextMenu::insertItem(u32 idx, const wchar_t* text, s32 commandId, bool enabled,
|
||||
bool hasSubMenu, bool checked, bool autoChecking)
|
||||
{
|
||||
SItem s;
|
||||
s.Enabled = enabled;
|
||||
s.Checked = checked;
|
||||
s.AutoChecking = autoChecking;
|
||||
s.Text = text;
|
||||
s.IsSeparator = (text == 0);
|
||||
s.SubMenu = 0;
|
||||
s.CommandId = commandId;
|
||||
|
||||
if (hasSubMenu)
|
||||
{
|
||||
s.SubMenu = new CGUIContextMenu(Environment, this, commandId,
|
||||
core::rect<s32>(0,0,100,100), false, false);
|
||||
s.SubMenu->setVisible(false);
|
||||
}
|
||||
|
||||
u32 result = idx;
|
||||
if ( idx < Items.size() )
|
||||
{
|
||||
Items.insert(s, idx);
|
||||
}
|
||||
else
|
||||
{
|
||||
Items.push_back(s);
|
||||
result = Items.size() - 1;
|
||||
}
|
||||
|
||||
recalculateSize();
|
||||
return result;
|
||||
}
|
||||
|
||||
s32 CGUIContextMenu::findItemWithCommandId(s32 commandId, u32 idxStartSearch) const
|
||||
{
|
||||
for ( u32 i=idxStartSearch; i<Items.size(); ++i )
|
||||
{
|
||||
if ( Items[i].CommandId == commandId )
|
||||
{
|
||||
return (s32)i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
//! Adds a sub menu from an element that already exists.
|
||||
void CGUIContextMenu::setSubMenu(u32 index, CGUIContextMenu* menu)
|
||||
{
|
||||
if (index >= Items.size())
|
||||
return;
|
||||
|
||||
if (menu)
|
||||
menu->grab();
|
||||
if (Items[index].SubMenu)
|
||||
Items[index].SubMenu->drop();
|
||||
|
||||
Items[index].SubMenu = menu;
|
||||
menu->setVisible(false);
|
||||
|
||||
if (Items[index].SubMenu)
|
||||
{
|
||||
menu->AllowFocus = false;
|
||||
if ( Environment->getFocus() == menu )
|
||||
{
|
||||
Environment->setFocus( this );
|
||||
}
|
||||
}
|
||||
|
||||
recalculateSize();
|
||||
}
|
||||
|
||||
|
||||
//! Adds a separator item to the menu
|
||||
void CGUIContextMenu::addSeparator()
|
||||
{
|
||||
addItem(0, -1, true, false, false, false);
|
||||
}
|
||||
|
||||
|
||||
//! Returns text of the menu item.
|
||||
const wchar_t* CGUIContextMenu::getItemText(u32 idx) const
|
||||
{
|
||||
if (idx >= Items.size())
|
||||
return 0;
|
||||
|
||||
return Items[idx].Text.c_str();
|
||||
}
|
||||
|
||||
|
||||
//! Sets text of the menu item.
|
||||
void CGUIContextMenu::setItemText(u32 idx, const wchar_t* text)
|
||||
{
|
||||
if (idx >= Items.size())
|
||||
return;
|
||||
|
||||
Items[idx].Text = text;
|
||||
recalculateSize();
|
||||
}
|
||||
|
||||
//! should the element change the checked status on clicking
|
||||
void CGUIContextMenu::setItemAutoChecking(u32 idx, bool autoChecking)
|
||||
{
|
||||
if ( idx >= Items.size())
|
||||
return;
|
||||
|
||||
Items[idx].AutoChecking = autoChecking;
|
||||
}
|
||||
|
||||
//! does the element change the checked status on clicking
|
||||
bool CGUIContextMenu::getItemAutoChecking(u32 idx) const
|
||||
{
|
||||
if (idx >= Items.size())
|
||||
return false;
|
||||
|
||||
return Items[idx].AutoChecking;
|
||||
}
|
||||
|
||||
|
||||
//! Returns if a menu item is enabled
|
||||
bool CGUIContextMenu::isItemEnabled(u32 idx) const
|
||||
{
|
||||
if (idx >= Items.size())
|
||||
{
|
||||
_IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX;
|
||||
return false;
|
||||
}
|
||||
|
||||
_IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX;
|
||||
return Items[idx].Enabled;
|
||||
}
|
||||
|
||||
|
||||
//! Returns if a menu item is checked
|
||||
bool CGUIContextMenu::isItemChecked(u32 idx) const
|
||||
{
|
||||
if (idx >= Items.size())
|
||||
{
|
||||
_IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX;
|
||||
return false;
|
||||
}
|
||||
|
||||
_IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX;
|
||||
return Items[idx].Checked;
|
||||
}
|
||||
|
||||
|
||||
//! Sets if the menu item should be enabled.
|
||||
void CGUIContextMenu::setItemEnabled(u32 idx, bool enabled)
|
||||
{
|
||||
if (idx >= Items.size())
|
||||
return;
|
||||
|
||||
Items[idx].Enabled = enabled;
|
||||
}
|
||||
|
||||
|
||||
//! Sets if the menu item should be checked.
|
||||
void CGUIContextMenu::setItemChecked(u32 idx, bool checked )
|
||||
{
|
||||
if (idx >= Items.size())
|
||||
return;
|
||||
|
||||
Items[idx].Checked = checked;
|
||||
}
|
||||
|
||||
|
||||
//! Removes a menu item
|
||||
void CGUIContextMenu::removeItem(u32 idx)
|
||||
{
|
||||
if (idx >= Items.size())
|
||||
return;
|
||||
|
||||
if (Items[idx].SubMenu)
|
||||
{
|
||||
Items[idx].SubMenu->drop();
|
||||
Items[idx].SubMenu = 0;
|
||||
}
|
||||
|
||||
Items.erase(idx);
|
||||
recalculateSize();
|
||||
}
|
||||
|
||||
|
||||
//! Removes all menu items
|
||||
void CGUIContextMenu::removeAllItems()
|
||||
{
|
||||
for (u32 i=0; i<Items.size(); ++i)
|
||||
if (Items[i].SubMenu)
|
||||
Items[i].SubMenu->drop();
|
||||
|
||||
Items.clear();
|
||||
recalculateSize();
|
||||
}
|
||||
|
||||
|
||||
//! called if an event happened.
|
||||
bool CGUIContextMenu::OnEvent(const SEvent& event)
|
||||
{
|
||||
if (isEnabled())
|
||||
{
|
||||
|
||||
switch(event.EventType)
|
||||
{
|
||||
case EET_GUI_EVENT:
|
||||
switch(event.GUIEvent.EventType)
|
||||
{
|
||||
case EGET_ELEMENT_FOCUS_LOST:
|
||||
if (event.GUIEvent.Caller == this && !isMyChild(event.GUIEvent.Element) && AllowFocus)
|
||||
{
|
||||
// set event parent of submenus
|
||||
IGUIElement * p = EventParent ? EventParent : Parent;
|
||||
setEventParent(p);
|
||||
|
||||
SEvent event;
|
||||
event.EventType = EET_GUI_EVENT;
|
||||
event.GUIEvent.Caller = this;
|
||||
event.GUIEvent.Element = 0;
|
||||
event.GUIEvent.EventType = EGET_ELEMENT_CLOSED;
|
||||
if ( !p->OnEvent(event) )
|
||||
{
|
||||
if ( CloseHandling & ECMC_HIDE )
|
||||
{
|
||||
setVisible(false);
|
||||
}
|
||||
if ( CloseHandling & ECMC_REMOVE )
|
||||
{
|
||||
remove();
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case EGET_ELEMENT_FOCUSED:
|
||||
if (event.GUIEvent.Caller == this && !AllowFocus)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case EET_MOUSE_INPUT_EVENT:
|
||||
switch(event.MouseInput.Event)
|
||||
{
|
||||
case EMIE_LMOUSE_LEFT_UP:
|
||||
{
|
||||
// menu might be removed if it loses focus in sendClick, so grab a reference
|
||||
grab();
|
||||
const u32 t = sendClick(core::position2d<s32>(event.MouseInput.X, event.MouseInput.Y));
|
||||
if ((t==0 || t==1) && Environment->hasFocus(this))
|
||||
Environment->removeFocus(this);
|
||||
drop();
|
||||
}
|
||||
return true;
|
||||
case EMIE_LMOUSE_PRESSED_DOWN:
|
||||
return true;
|
||||
case EMIE_MOUSE_MOVED:
|
||||
if (Environment->hasFocus(this))
|
||||
highlight(core::position2d<s32>(event.MouseInput.X, event.MouseInput.Y), true);
|
||||
return true;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return IGUIElement::OnEvent(event);
|
||||
}
|
||||
|
||||
|
||||
//! Sets the visible state of this element.
|
||||
void CGUIContextMenu::setVisible(bool visible)
|
||||
{
|
||||
HighLighted = -1;
|
||||
ChangeTime = os::Timer::getTime();
|
||||
for (u32 j=0; j<Items.size(); ++j)
|
||||
if (Items[j].SubMenu)
|
||||
Items[j].SubMenu->setVisible(false);
|
||||
|
||||
IGUIElement::setVisible(visible);
|
||||
}
|
||||
|
||||
|
||||
//! sends a click Returns:
|
||||
//! 0 if click went outside of the element,
|
||||
//! 1 if a valid button was clicked,
|
||||
//! 2 if a nonclickable element was clicked
|
||||
u32 CGUIContextMenu::sendClick(const core::position2d<s32>& p)
|
||||
{
|
||||
u32 t = 0;
|
||||
|
||||
// get number of open submenu
|
||||
s32 openmenu = -1;
|
||||
s32 j;
|
||||
for (j=0; j<(s32)Items.size(); ++j)
|
||||
if (Items[j].SubMenu && Items[j].SubMenu->isVisible())
|
||||
{
|
||||
openmenu = j;
|
||||
break;
|
||||
}
|
||||
|
||||
// delegate click operation to submenu
|
||||
if (openmenu != -1)
|
||||
{
|
||||
t = Items[j].SubMenu->sendClick(p);
|
||||
if (t != 0)
|
||||
return t; // clicked something
|
||||
}
|
||||
|
||||
// check click on myself
|
||||
if (isPointInside(p) &&
|
||||
(u32)HighLighted < Items.size())
|
||||
{
|
||||
if (!Items[HighLighted].Enabled ||
|
||||
Items[HighLighted].IsSeparator ||
|
||||
Items[HighLighted].SubMenu)
|
||||
return 2;
|
||||
|
||||
if ( Items[HighLighted].AutoChecking )
|
||||
{
|
||||
Items[HighLighted].Checked = Items[HighLighted].Checked ? false : true;
|
||||
}
|
||||
|
||||
SEvent event;
|
||||
event.EventType = EET_GUI_EVENT;
|
||||
event.GUIEvent.Caller = this;
|
||||
event.GUIEvent.Element = 0;
|
||||
event.GUIEvent.EventType = EGET_MENU_ITEM_SELECTED;
|
||||
if (EventParent)
|
||||
EventParent->OnEvent(event);
|
||||
else if (Parent)
|
||||
Parent->OnEvent(event);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
//! returns true, if an element was highligted
|
||||
bool CGUIContextMenu::highlight(const core::position2d<s32>& p, bool canOpenSubMenu)
|
||||
{
|
||||
if (!isEnabled())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// get number of open submenu
|
||||
s32 openmenu = -1;
|
||||
s32 i;
|
||||
for (i=0; i<(s32)Items.size(); ++i)
|
||||
if (Items[i].Enabled && Items[i].SubMenu && Items[i].SubMenu->isVisible())
|
||||
{
|
||||
openmenu = i;
|
||||
break;
|
||||
}
|
||||
|
||||
// delegate highlight operation to submenu
|
||||
if (openmenu != -1)
|
||||
{
|
||||
if (Items[openmenu].Enabled && Items[openmenu].SubMenu->highlight(p, canOpenSubMenu))
|
||||
{
|
||||
HighLighted = openmenu;
|
||||
ChangeTime = os::Timer::getTime();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// highlight myself
|
||||
for (i=0; i<(s32)Items.size(); ++i)
|
||||
{
|
||||
if (Items[i].Enabled && getHRect(Items[i], AbsoluteRect).isPointInside(p))
|
||||
{
|
||||
HighLighted = i;
|
||||
ChangeTime = os::Timer::getTime();
|
||||
|
||||
// make submenus visible/invisible
|
||||
for (s32 j=0; j<(s32)Items.size(); ++j)
|
||||
if (Items[j].SubMenu)
|
||||
{
|
||||
if ( j == i && canOpenSubMenu && Items[j].Enabled )
|
||||
Items[j].SubMenu->setVisible(true);
|
||||
else if ( j != i )
|
||||
Items[j].SubMenu->setVisible(false);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
HighLighted = openmenu;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
//! returns the item highlight-area
|
||||
core::rect<s32> CGUIContextMenu::getHRect(const SItem& i, const core::rect<s32>& absolute) const
|
||||
{
|
||||
core::rect<s32> r = absolute;
|
||||
r.UpperLeftCorner.Y += i.PosY;
|
||||
r.LowerRightCorner.Y = r.UpperLeftCorner.Y + i.Dim.Height;
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
//! Gets drawing rect of Item
|
||||
core::rect<s32> CGUIContextMenu::getRect(const SItem& i, const core::rect<s32>& absolute) const
|
||||
{
|
||||
core::rect<s32> r = absolute;
|
||||
r.UpperLeftCorner.Y += i.PosY;
|
||||
r.LowerRightCorner.Y = r.UpperLeftCorner.Y + i.Dim.Height;
|
||||
r.UpperLeftCorner.X += 20;
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
//! draws the element and its children
|
||||
void CGUIContextMenu::draw()
|
||||
{
|
||||
if (!IsVisible)
|
||||
return;
|
||||
|
||||
IGUISkin* skin = Environment->getSkin();
|
||||
|
||||
if (!skin)
|
||||
return;
|
||||
|
||||
IGUIFont* font = skin->getFont(EGDF_MENU);
|
||||
if (font != LastFont)
|
||||
{
|
||||
if (LastFont)
|
||||
LastFont->drop();
|
||||
LastFont = font;
|
||||
if (LastFont)
|
||||
LastFont->grab();
|
||||
|
||||
recalculateSize();
|
||||
}
|
||||
|
||||
IGUISpriteBank* sprites = skin->getSpriteBank();
|
||||
|
||||
core::rect<s32> rect = AbsoluteRect;
|
||||
core::rect<s32>* clip = 0;
|
||||
|
||||
// draw frame
|
||||
skin->draw3DMenuPane(this, AbsoluteRect, clip);
|
||||
|
||||
// loop through all menu items
|
||||
|
||||
rect = AbsoluteRect;
|
||||
s32 y = AbsoluteRect.UpperLeftCorner.Y;
|
||||
|
||||
for (s32 i=0; i<(s32)Items.size(); ++i)
|
||||
{
|
||||
if (Items[i].IsSeparator)
|
||||
{
|
||||
// draw separator
|
||||
rect = AbsoluteRect;
|
||||
rect.UpperLeftCorner.Y += Items[i].PosY + 3;
|
||||
rect.LowerRightCorner.Y = rect.UpperLeftCorner.Y + 1;
|
||||
rect.UpperLeftCorner.X += 5;
|
||||
rect.LowerRightCorner.X -= 5;
|
||||
skin->draw2DRectangle(this, skin->getColor(EGDC_3D_SHADOW), rect, clip);
|
||||
|
||||
rect.LowerRightCorner.Y += 1;
|
||||
rect.UpperLeftCorner.Y += 1;
|
||||
skin->draw2DRectangle(this, skin->getColor(EGDC_3D_HIGH_LIGHT), rect, clip);
|
||||
|
||||
y += 10;
|
||||
}
|
||||
else
|
||||
{
|
||||
rect = getRect(Items[i], AbsoluteRect);
|
||||
|
||||
// draw highlighted
|
||||
|
||||
if (i == HighLighted && Items[i].Enabled)
|
||||
{
|
||||
core::rect<s32> r = AbsoluteRect;
|
||||
r.LowerRightCorner.Y = rect.LowerRightCorner.Y;
|
||||
r.UpperLeftCorner.Y = rect.UpperLeftCorner.Y;
|
||||
r.LowerRightCorner.X -= 5;
|
||||
r.UpperLeftCorner.X += 5;
|
||||
skin->draw2DRectangle(this, skin->getColor(EGDC_HIGH_LIGHT), r, clip);
|
||||
}
|
||||
|
||||
// draw text
|
||||
|
||||
EGUI_DEFAULT_COLOR c = EGDC_BUTTON_TEXT;
|
||||
|
||||
if (i == HighLighted)
|
||||
c = EGDC_HIGH_LIGHT_TEXT;
|
||||
|
||||
if (!Items[i].Enabled)
|
||||
c = EGDC_GRAY_TEXT;
|
||||
|
||||
if (font)
|
||||
font->draw(Items[i].Text.c_str(), rect,
|
||||
skin->getColor(c), false, true, clip);
|
||||
|
||||
// draw submenu symbol
|
||||
if (Items[i].SubMenu && sprites)
|
||||
{
|
||||
core::rect<s32> r = rect;
|
||||
r.UpperLeftCorner.X = r.LowerRightCorner.X - 15;
|
||||
|
||||
sprites->draw2DSprite(skin->getIcon(EGDI_CURSOR_RIGHT),
|
||||
r.getCenter(), clip, skin->getColor(c),
|
||||
(i == HighLighted) ? ChangeTime : 0,
|
||||
(i == HighLighted) ? os::Timer::getTime() : 0,
|
||||
(i == HighLighted), true);
|
||||
}
|
||||
|
||||
// draw checked symbol
|
||||
if (Items[i].Checked && sprites)
|
||||
{
|
||||
core::rect<s32> r = rect;
|
||||
r.LowerRightCorner.X = r.UpperLeftCorner.X - 15;
|
||||
r.UpperLeftCorner.X = r.LowerRightCorner.X + 15;
|
||||
sprites->draw2DSprite(skin->getIcon(EGDI_CHECK_BOX_CHECKED),
|
||||
r.getCenter(), clip, skin->getColor(c),
|
||||
(i == HighLighted) ? ChangeTime : 0,
|
||||
(i == HighLighted) ? os::Timer::getTime() : 0,
|
||||
(i == HighLighted), true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
IGUIElement::draw();
|
||||
}
|
||||
|
||||
|
||||
void CGUIContextMenu::recalculateSize()
|
||||
{
|
||||
IGUIFont* font = Environment->getSkin()->getFont(EGDF_MENU);
|
||||
|
||||
if (!font)
|
||||
return;
|
||||
|
||||
core::rect<s32> rect;
|
||||
rect.UpperLeftCorner = RelativeRect.UpperLeftCorner;
|
||||
u32 width = 100;
|
||||
u32 height = 3;
|
||||
|
||||
u32 i;
|
||||
for (i=0; i<Items.size(); ++i)
|
||||
{
|
||||
if (Items[i].IsSeparator)
|
||||
{
|
||||
Items[i].Dim.Width = 100;
|
||||
Items[i].Dim.Height = 10;
|
||||
}
|
||||
else
|
||||
{
|
||||
Items[i].Dim = font->getDimension(Items[i].Text.c_str());
|
||||
Items[i].Dim.Width += 40;
|
||||
|
||||
if (Items[i].Dim.Width > width)
|
||||
width = Items[i].Dim.Width;
|
||||
}
|
||||
|
||||
Items[i].PosY = height;
|
||||
height += Items[i].Dim.Height;
|
||||
}
|
||||
|
||||
height += 5;
|
||||
|
||||
if (height < 10)
|
||||
height = 10;
|
||||
|
||||
rect.LowerRightCorner.X = RelativeRect.UpperLeftCorner.X + width;
|
||||
rect.LowerRightCorner.Y = RelativeRect.UpperLeftCorner.Y + height;
|
||||
|
||||
setRelativePosition(rect);
|
||||
|
||||
// recalculate submenus
|
||||
for (i=0; i<Items.size(); ++i)
|
||||
{
|
||||
if (Items[i].SubMenu)
|
||||
{
|
||||
// move submenu
|
||||
const s32 w = Items[i].SubMenu->getAbsolutePosition().getWidth();
|
||||
const s32 h = Items[i].SubMenu->getAbsolutePosition().getHeight();
|
||||
|
||||
core::rect<s32> subRect(width-5, Items[i].PosY, width+w-5, Items[i].PosY+h);
|
||||
|
||||
// if it would be drawn beyond the right border, then add it to the left side
|
||||
gui::IGUIElement * root = Environment->getRootGUIElement();
|
||||
if ( root )
|
||||
{
|
||||
core::rect<s32> rectRoot( root->getAbsolutePosition() );
|
||||
if ( getAbsolutePosition().UpperLeftCorner.X+subRect.LowerRightCorner.X > rectRoot.LowerRightCorner.X )
|
||||
{
|
||||
subRect.UpperLeftCorner.X = -w;
|
||||
subRect.LowerRightCorner.X = 0;
|
||||
}
|
||||
}
|
||||
|
||||
Items[i].SubMenu->setRelativePosition(subRect);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//! Returns the selected item in the menu
|
||||
s32 CGUIContextMenu::getSelectedItem() const
|
||||
{
|
||||
return HighLighted;
|
||||
}
|
||||
|
||||
|
||||
//! \return Returns a pointer to the submenu of an item.
|
||||
IGUIContextMenu* CGUIContextMenu::getSubMenu(u32 idx) const
|
||||
{
|
||||
if (idx >= Items.size())
|
||||
return 0;
|
||||
|
||||
return Items[idx].SubMenu;
|
||||
}
|
||||
|
||||
|
||||
//! Returns command id of a menu item
|
||||
s32 CGUIContextMenu::getItemCommandId(u32 idx) const
|
||||
{
|
||||
if (idx >= Items.size())
|
||||
return -1;
|
||||
|
||||
return Items[idx].CommandId;
|
||||
}
|
||||
|
||||
|
||||
//! Sets the command id of a menu item
|
||||
void CGUIContextMenu::setItemCommandId(u32 idx, s32 id)
|
||||
{
|
||||
if (idx >= Items.size())
|
||||
return;
|
||||
|
||||
Items[idx].CommandId = id;
|
||||
}
|
||||
|
||||
|
||||
//! Writes attributes of the element.
|
||||
void CGUIContextMenu::serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options=0) const
|
||||
{
|
||||
IGUIElement::serializeAttributes(out,options);
|
||||
out->addPosition2d("Position", Pos);
|
||||
|
||||
if (Parent->getType() == EGUIET_CONTEXT_MENU || Parent->getType() == EGUIET_MENU )
|
||||
{
|
||||
const IGUIContextMenu* const ptr = (const IGUIContextMenu*)Parent;
|
||||
// find the position of this item in its parent's list
|
||||
u32 i;
|
||||
// VC6 needs the cast for this
|
||||
for (i=0; (i<ptr->getItemCount()) && (ptr->getSubMenu(i) != (const IGUIContextMenu*)this); ++i)
|
||||
; // do nothing
|
||||
|
||||
out->addInt("ParentItem", i);
|
||||
}
|
||||
|
||||
out->addInt("CloseHandling", (s32)CloseHandling);
|
||||
|
||||
// write out the item list
|
||||
out->addInt("ItemCount", Items.size());
|
||||
|
||||
core::stringc tmp;
|
||||
|
||||
for (u32 i=0; i < Items.size(); ++i)
|
||||
{
|
||||
tmp = "IsSeparator"; tmp += i;
|
||||
out->addBool(tmp.c_str(), Items[i].IsSeparator);
|
||||
|
||||
if (!Items[i].IsSeparator)
|
||||
{
|
||||
tmp = "Text"; tmp += i;
|
||||
out->addString(tmp.c_str(), Items[i].Text.c_str());
|
||||
tmp = "CommandID"; tmp += i;
|
||||
out->addInt(tmp.c_str(), Items[i].CommandId);
|
||||
tmp = "Enabled"; tmp += i;
|
||||
out->addBool(tmp.c_str(), Items[i].Enabled);
|
||||
tmp = "Checked"; tmp += i;
|
||||
out->addBool(tmp.c_str(), Items[i].Checked);
|
||||
tmp = "AutoChecking"; tmp += i;
|
||||
out->addBool(tmp.c_str(), Items[i].AutoChecking);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//! Reads attributes of the element
|
||||
void CGUIContextMenu::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options=0)
|
||||
{
|
||||
IGUIElement::deserializeAttributes(in,options);
|
||||
|
||||
Pos = in->getAttributeAsPosition2d("Position");
|
||||
|
||||
// link to this item's parent
|
||||
if (Parent && ( Parent->getType() == EGUIET_CONTEXT_MENU || Parent->getType() == EGUIET_MENU ) )
|
||||
((CGUIContextMenu*)Parent)->setSubMenu(in->getAttributeAsInt("ParentItem"),this);
|
||||
|
||||
CloseHandling = (ECONTEXT_MENU_CLOSE)in->getAttributeAsInt("CloseHandling");
|
||||
|
||||
removeAllItems();
|
||||
|
||||
// read the item list
|
||||
const s32 count = in->getAttributeAsInt("ItemCount");
|
||||
|
||||
for (s32 i=0; i<count; ++i)
|
||||
{
|
||||
core::stringc tmp;
|
||||
core::stringw txt;
|
||||
s32 commandid=-1;
|
||||
bool enabled=true;
|
||||
bool checked=false;
|
||||
bool autochecking=false;
|
||||
|
||||
tmp = "IsSeparator"; tmp += i;
|
||||
if ( in->existsAttribute(tmp.c_str()) && in->getAttributeAsBool(tmp.c_str()) )
|
||||
addSeparator();
|
||||
else
|
||||
{
|
||||
tmp = "Text"; tmp += i;
|
||||
if ( in->existsAttribute(tmp.c_str()) )
|
||||
txt = in->getAttributeAsStringW(tmp.c_str());
|
||||
|
||||
tmp = "CommandID"; tmp += i;
|
||||
if ( in->existsAttribute(tmp.c_str()) )
|
||||
commandid = in->getAttributeAsInt(tmp.c_str());
|
||||
|
||||
tmp = "Enabled"; tmp += i;
|
||||
if ( in->existsAttribute(tmp.c_str()) )
|
||||
enabled = in->getAttributeAsBool(tmp.c_str());
|
||||
|
||||
tmp = "Checked"; tmp += i;
|
||||
if ( in->existsAttribute(tmp.c_str()) )
|
||||
checked = in->getAttributeAsBool(tmp.c_str());
|
||||
|
||||
tmp = "AutoChecking"; tmp += i;
|
||||
if ( in->existsAttribute(tmp.c_str()) )
|
||||
autochecking = in->getAttributeAsBool(tmp.c_str());
|
||||
|
||||
addItem(core::stringw(txt.c_str()).c_str(), commandid, enabled, false, checked, autochecking);
|
||||
}
|
||||
}
|
||||
|
||||
recalculateSize();
|
||||
}
|
||||
|
||||
|
||||
// because sometimes the element has no parent at click time
|
||||
void CGUIContextMenu::setEventParent(IGUIElement *parent)
|
||||
{
|
||||
EventParent = parent;
|
||||
|
||||
for (u32 i=0; i<Items.size(); ++i)
|
||||
if (Items[i].SubMenu)
|
||||
Items[i].SubMenu->setEventParent(parent);
|
||||
}
|
||||
|
||||
|
||||
bool CGUIContextMenu::hasOpenSubMenu() const
|
||||
{
|
||||
for (u32 i=0; i<Items.size(); ++i)
|
||||
if (Items[i].SubMenu && Items[i].SubMenu->isVisible())
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
void CGUIContextMenu::closeAllSubMenus()
|
||||
{
|
||||
for (u32 i=0; i<Items.size(); ++i)
|
||||
if (Items[i].SubMenu)
|
||||
Items[i].SubMenu->setVisible(false);
|
||||
|
||||
//HighLighted = -1;
|
||||
}
|
||||
|
||||
|
||||
} // end namespace
|
||||
} // end namespace
|
||||
|
||||
#endif // _IRR_COMPILE_WITH_GUI_
|
||||
|
174
source/Irrlicht/CGUIContextMenu.h
Normal file
174
source/Irrlicht/CGUIContextMenu.h
Normal file
@ -0,0 +1,174 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#ifndef __C_GUI_CONTEXT_MENU_H_INCLUDED__
|
||||
#define __C_GUI_CONTEXT_MENU_H_INCLUDED__
|
||||
|
||||
#include "IrrCompileConfig.h"
|
||||
#ifdef _IRR_COMPILE_WITH_GUI_
|
||||
|
||||
#include "IGUIContextMenu.h"
|
||||
#include "irrString.h"
|
||||
#include "irrArray.h"
|
||||
#include "IGUIFont.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace gui
|
||||
{
|
||||
|
||||
//! GUI Context menu interface.
|
||||
class CGUIContextMenu : public IGUIContextMenu
|
||||
{
|
||||
public:
|
||||
|
||||
//! constructor
|
||||
CGUIContextMenu(IGUIEnvironment* environment,
|
||||
IGUIElement* parent, s32 id, core::rect<s32> rectangle,
|
||||
bool getFocus = true, bool allowFocus = true);
|
||||
|
||||
//! destructor
|
||||
virtual ~CGUIContextMenu();
|
||||
|
||||
//! set behavior when menus are closed
|
||||
virtual void setCloseHandling(ECONTEXT_MENU_CLOSE onClose);
|
||||
|
||||
//! get current behavior when the menue will be closed
|
||||
virtual ECONTEXT_MENU_CLOSE getCloseHandling() const;
|
||||
|
||||
//! Returns amount of menu items
|
||||
virtual u32 getItemCount() const;
|
||||
|
||||
//! Adds a menu item.
|
||||
virtual u32 addItem(const wchar_t* text, s32 commandid,
|
||||
bool enabled, bool hasSubMenu, bool checked, bool autoChecking);
|
||||
|
||||
//! Insert a menu item at specified position.
|
||||
virtual u32 insertItem(u32 idx, const wchar_t* text, s32 commandId, bool enabled,
|
||||
bool hasSubMenu, bool checked, bool autoChecking);
|
||||
|
||||
//! Find a item which has the given CommandId starting from given index
|
||||
virtual s32 findItemWithCommandId(s32 commandId, u32 idxStartSearch) const;
|
||||
|
||||
//! Adds a separator item to the menu
|
||||
virtual void addSeparator();
|
||||
|
||||
//! Returns text of the menu item.
|
||||
virtual const wchar_t* getItemText(u32 idx) const;
|
||||
|
||||
//! Sets text of the menu item.
|
||||
virtual void setItemText(u32 idx, const wchar_t* text);
|
||||
|
||||
//! Returns if a menu item is enabled
|
||||
virtual bool isItemEnabled(u32 idx) const;
|
||||
|
||||
//! Sets if the menu item should be enabled.
|
||||
virtual void setItemEnabled(u32 idx, bool enabled);
|
||||
|
||||
//! Returns if a menu item is checked
|
||||
virtual bool isItemChecked(u32 idx) const;
|
||||
|
||||
//! Sets if the menu item should be checked.
|
||||
virtual void setItemChecked(u32 idx, bool enabled);
|
||||
|
||||
//! Removes a menu item
|
||||
virtual void removeItem(u32 idx);
|
||||
|
||||
//! Removes all menu items
|
||||
virtual void removeAllItems();
|
||||
|
||||
//! called if an event happened.
|
||||
virtual bool OnEvent(const SEvent& event);
|
||||
|
||||
//! draws the element and its children
|
||||
virtual void draw();
|
||||
|
||||
//! Returns the selected item in the menu
|
||||
virtual s32 getSelectedItem() const;
|
||||
|
||||
//! Returns a pointer to the submenu of an item.
|
||||
//! \return Pointer to the submenu of an item.
|
||||
virtual IGUIContextMenu* getSubMenu(u32 idx) const;
|
||||
|
||||
//! Sets the visible state of this element.
|
||||
virtual void setVisible(bool visible);
|
||||
|
||||
//! should the element change the checked status on clicking
|
||||
virtual void setItemAutoChecking(u32 idx, bool autoChecking);
|
||||
|
||||
//! does the element change the checked status on clicking
|
||||
virtual bool getItemAutoChecking(u32 idx) const;
|
||||
|
||||
//! Returns command id of a menu item
|
||||
virtual s32 getItemCommandId(u32 idx) const;
|
||||
|
||||
//! Sets the command id of a menu item
|
||||
virtual void setItemCommandId(u32 idx, s32 id);
|
||||
|
||||
//! Adds a sub menu from an element that already exists.
|
||||
virtual void setSubMenu(u32 index, CGUIContextMenu* menu);
|
||||
|
||||
//! When an eventparent is set it receives events instead of the usual parent element
|
||||
virtual void setEventParent(IGUIElement *parent);
|
||||
|
||||
//! Writes attributes of the element.
|
||||
virtual void serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options) const;
|
||||
|
||||
//! Reads attributes of the element
|
||||
virtual void deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options);
|
||||
|
||||
protected:
|
||||
|
||||
void closeAllSubMenus();
|
||||
bool hasOpenSubMenu() const;
|
||||
|
||||
struct SItem
|
||||
{
|
||||
core::stringw Text;
|
||||
bool IsSeparator;
|
||||
bool Enabled;
|
||||
bool Checked;
|
||||
bool AutoChecking;
|
||||
core::dimension2d<u32> Dim;
|
||||
s32 PosY;
|
||||
CGUIContextMenu* SubMenu;
|
||||
s32 CommandId;
|
||||
};
|
||||
|
||||
virtual void recalculateSize();
|
||||
|
||||
//! returns true, if an element was highlighted
|
||||
virtual bool highlight(const core::position2d<s32>& p, bool canOpenSubMenu);
|
||||
|
||||
//! sends a click Returns:
|
||||
//! 0 if click went outside of the element,
|
||||
//! 1 if a valid button was clicked,
|
||||
//! 2 if a nonclickable element was clicked
|
||||
virtual u32 sendClick(const core::position2d<s32>& p);
|
||||
|
||||
//! returns the item highlight-area
|
||||
virtual core::rect<s32> getHRect(const SItem& i, const core::rect<s32>& absolute) const;
|
||||
|
||||
//! Gets drawing rect of Item
|
||||
virtual core::rect<s32> getRect(const SItem& i, const core::rect<s32>& absolute) const;
|
||||
|
||||
|
||||
core::array<SItem> Items;
|
||||
core::position2d<s32> Pos;
|
||||
IGUIElement* EventParent;
|
||||
IGUIFont *LastFont;
|
||||
ECONTEXT_MENU_CLOSE CloseHandling;
|
||||
s32 HighLighted;
|
||||
u32 ChangeTime;
|
||||
bool AllowFocus;
|
||||
};
|
||||
|
||||
|
||||
} // end namespace gui
|
||||
} // end namespace irr
|
||||
|
||||
#endif // _IRR_COMPILE_WITH_GUI_
|
||||
|
||||
#endif // __C_GUI_CONTEXT_MENU_H_INCLUDED__
|
||||
|
1564
source/Irrlicht/CGUIEditBox.cpp
Normal file
1564
source/Irrlicht/CGUIEditBox.cpp
Normal file
File diff suppressed because it is too large
Load Diff
182
source/Irrlicht/CGUIEditBox.h
Normal file
182
source/Irrlicht/CGUIEditBox.h
Normal file
@ -0,0 +1,182 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#ifndef __C_GUI_EDIT_BOX_H_INCLUDED__
|
||||
#define __C_GUI_EDIT_BOX_H_INCLUDED__
|
||||
|
||||
#include "IrrCompileConfig.h"
|
||||
#ifdef _IRR_COMPILE_WITH_GUI_
|
||||
|
||||
#include "IGUIEditBox.h"
|
||||
#include "irrArray.h"
|
||||
#include "IOSOperator.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace gui
|
||||
{
|
||||
class CGUIEditBox : public IGUIEditBox
|
||||
{
|
||||
public:
|
||||
|
||||
//! constructor
|
||||
CGUIEditBox(const wchar_t* text, bool border, IGUIEnvironment* environment,
|
||||
IGUIElement* parent, s32 id, const core::rect<s32>& rectangle);
|
||||
|
||||
//! destructor
|
||||
virtual ~CGUIEditBox();
|
||||
|
||||
//! Sets another skin independent font.
|
||||
virtual void setOverrideFont(IGUIFont* font=0);
|
||||
|
||||
//! Gets the override font (if any)
|
||||
/** \return The override font (may be 0) */
|
||||
virtual IGUIFont* getOverrideFont() const;
|
||||
|
||||
//! Get the font which is used right now for drawing
|
||||
/** Currently this is the override font when one is set and the
|
||||
font of the active skin otherwise */
|
||||
virtual IGUIFont* getActiveFont() const;
|
||||
|
||||
//! Sets another color for the text.
|
||||
virtual void setOverrideColor(video::SColor color);
|
||||
|
||||
//! Gets the override color
|
||||
virtual video::SColor getOverrideColor() const;
|
||||
|
||||
//! Sets if the text should use the overide color or the
|
||||
//! color in the gui skin.
|
||||
virtual void enableOverrideColor(bool enable);
|
||||
|
||||
//! Checks if an override color is enabled
|
||||
/** \return true if the override color is enabled, false otherwise */
|
||||
virtual bool isOverrideColorEnabled(void) const;
|
||||
|
||||
//! Sets whether to draw the background
|
||||
virtual void setDrawBackground(bool draw);
|
||||
|
||||
//! Turns the border on or off
|
||||
virtual void setDrawBorder(bool border);
|
||||
|
||||
//! Enables or disables word wrap for using the edit box as multiline text editor.
|
||||
virtual void setWordWrap(bool enable);
|
||||
|
||||
//! Checks if word wrap is enabled
|
||||
//! \return true if word wrap is enabled, false otherwise
|
||||
virtual bool isWordWrapEnabled() const;
|
||||
|
||||
//! Enables or disables newlines.
|
||||
/** \param enable: If set to true, the EGET_EDITBOX_ENTER event will not be fired,
|
||||
instead a newline character will be inserted. */
|
||||
virtual void setMultiLine(bool enable);
|
||||
|
||||
//! Checks if multi line editing is enabled
|
||||
//! \return true if mult-line is enabled, false otherwise
|
||||
virtual bool isMultiLineEnabled() const;
|
||||
|
||||
//! Enables or disables automatic scrolling with cursor position
|
||||
//! \param enable: If set to true, the text will move around with the cursor position
|
||||
virtual void setAutoScroll(bool enable);
|
||||
|
||||
//! Checks to see if automatic scrolling is enabled
|
||||
//! \return true if automatic scrolling is enabled, false if not
|
||||
virtual bool isAutoScrollEnabled() const;
|
||||
|
||||
//! Gets the size area of the text in the edit box
|
||||
//! \return Returns the size in pixels of the text
|
||||
virtual core::dimension2du getTextDimension();
|
||||
|
||||
//! Sets text justification
|
||||
virtual void setTextAlignment(EGUI_ALIGNMENT horizontal, EGUI_ALIGNMENT vertical);
|
||||
|
||||
//! called if an event happened.
|
||||
virtual bool OnEvent(const SEvent& event);
|
||||
|
||||
//! draws the element and its children
|
||||
virtual void draw();
|
||||
|
||||
//! Sets the new caption of this element.
|
||||
virtual void setText(const wchar_t* text);
|
||||
|
||||
//! Sets the maximum amount of characters which may be entered in the box.
|
||||
//! \param max: Maximum amount of characters. If 0, the character amount is
|
||||
//! infinity.
|
||||
virtual void setMax(u32 max);
|
||||
|
||||
//! Returns maximum amount of characters, previously set by setMax();
|
||||
virtual u32 getMax() const;
|
||||
|
||||
//! Sets whether the edit box is a password box. Setting this to true will
|
||||
/** disable MultiLine, WordWrap and the ability to copy with ctrl+c or ctrl+x
|
||||
\param passwordBox: true to enable password, false to disable
|
||||
\param passwordChar: the character that is displayed instead of letters */
|
||||
virtual void setPasswordBox(bool passwordBox, wchar_t passwordChar = L'*');
|
||||
|
||||
//! Returns true if the edit box is currently a password box.
|
||||
virtual bool isPasswordBox() const;
|
||||
|
||||
//! Updates the absolute position, splits text if required
|
||||
virtual void updateAbsolutePosition();
|
||||
|
||||
//! Writes attributes of the element.
|
||||
virtual void serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options) const;
|
||||
|
||||
//! Reads attributes of the element
|
||||
virtual void deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options);
|
||||
|
||||
protected:
|
||||
//! Breaks the single text line.
|
||||
void breakText();
|
||||
//! sets the area of the given line
|
||||
void setTextRect(s32 line);
|
||||
//! returns the line number that the cursor is on
|
||||
s32 getLineFromPos(s32 pos);
|
||||
//! adds a letter to the edit box
|
||||
void inputChar(wchar_t c);
|
||||
//! calculates the current scroll position
|
||||
void calculateScrollPos();
|
||||
//! calculated the FrameRect
|
||||
void calculateFrameRect();
|
||||
//! send some gui event to parent
|
||||
void sendGuiEvent(EGUI_EVENT_TYPE type);
|
||||
//! set text markers
|
||||
void setTextMarkers(s32 begin, s32 end);
|
||||
|
||||
bool processKey(const SEvent& event);
|
||||
bool processMouse(const SEvent& event);
|
||||
s32 getCursorPos(s32 x, s32 y);
|
||||
|
||||
bool MouseMarking;
|
||||
bool Border;
|
||||
bool Background;
|
||||
bool OverrideColorEnabled;
|
||||
s32 MarkBegin;
|
||||
s32 MarkEnd;
|
||||
|
||||
video::SColor OverrideColor;
|
||||
gui::IGUIFont *OverrideFont, *LastBreakFont;
|
||||
IOSOperator* Operator;
|
||||
|
||||
u32 BlinkStartTime;
|
||||
s32 CursorPos;
|
||||
s32 HScrollPos, VScrollPos; // scroll position in characters
|
||||
u32 Max;
|
||||
|
||||
bool WordWrap, MultiLine, AutoScroll, PasswordBox;
|
||||
wchar_t PasswordChar;
|
||||
EGUI_ALIGNMENT HAlign, VAlign;
|
||||
|
||||
core::array< core::stringw > BrokenText;
|
||||
core::array< s32 > BrokenTextPositions;
|
||||
|
||||
core::rect<s32> CurrentTextRect, FrameRect; // temporary values
|
||||
};
|
||||
|
||||
|
||||
} // end namespace gui
|
||||
} // end namespace irr
|
||||
|
||||
#endif // _IRR_COMPILE_WITH_GUI_
|
||||
#endif // __C_GUI_EDIT_BOX_H_INCLUDED__
|
||||
|
1658
source/Irrlicht/CGUIEnvironment.cpp
Normal file
1658
source/Irrlicht/CGUIEnvironment.cpp
Normal file
File diff suppressed because it is too large
Load Diff
323
source/Irrlicht/CGUIEnvironment.h
Normal file
323
source/Irrlicht/CGUIEnvironment.h
Normal file
@ -0,0 +1,323 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#ifndef __C_GUI_ENVIRONMENT_H_INCLUDED__
|
||||
#define __C_GUI_ENVIRONMENT_H_INCLUDED__
|
||||
|
||||
#include "IrrCompileConfig.h"
|
||||
#ifdef _IRR_COMPILE_WITH_GUI_
|
||||
|
||||
#include "IGUIEnvironment.h"
|
||||
#include "IGUIElement.h"
|
||||
#include "irrArray.h"
|
||||
#include "IFileSystem.h"
|
||||
#include "IOSOperator.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace io
|
||||
{
|
||||
class IXMLWriter;
|
||||
}
|
||||
namespace gui
|
||||
{
|
||||
|
||||
class CGUIEnvironment : public IGUIEnvironment, public IGUIElement
|
||||
{
|
||||
public:
|
||||
|
||||
//! constructor
|
||||
CGUIEnvironment(io::IFileSystem* fs, video::IVideoDriver* driver, IOSOperator* op);
|
||||
|
||||
//! destructor
|
||||
virtual ~CGUIEnvironment();
|
||||
|
||||
//! draws all gui elements
|
||||
virtual void drawAll();
|
||||
|
||||
//! returns the current video driver
|
||||
virtual video::IVideoDriver* getVideoDriver() const;
|
||||
|
||||
//! returns pointer to the filesystem
|
||||
virtual io::IFileSystem* getFileSystem() const;
|
||||
|
||||
//! returns a pointer to the OS operator
|
||||
virtual IOSOperator* getOSOperator() const;
|
||||
|
||||
//! posts an input event to the environment
|
||||
virtual bool postEventFromUser(const SEvent& event);
|
||||
|
||||
//! This sets a new event receiver for gui events. Usually you do not have to
|
||||
//! use this method, it is used by the internal engine.
|
||||
virtual void setUserEventReceiver(IEventReceiver* evr);
|
||||
|
||||
//! removes all elements from the environment
|
||||
virtual void clear();
|
||||
|
||||
//! called if an event happened.
|
||||
virtual bool OnEvent(const SEvent& event);
|
||||
|
||||
//! returns the current gui skin
|
||||
virtual IGUISkin* getSkin() const;
|
||||
|
||||
//! Sets a new GUI Skin
|
||||
virtual void setSkin(IGUISkin* skin);
|
||||
|
||||
//! Creates a new GUI Skin based on a template.
|
||||
/** \return Returns a pointer to the created skin.
|
||||
If you no longer need the skin, you should call IGUISkin::drop().
|
||||
See IReferenceCounted::drop() for more information. */
|
||||
virtual IGUISkin* createSkin(EGUI_SKIN_TYPE type);
|
||||
|
||||
//! Creates the image list from the given texture.
|
||||
virtual IGUIImageList* createImageList( video::ITexture* texture,
|
||||
core::dimension2d<s32> imageSize, bool useAlphaChannel );
|
||||
|
||||
//! returns the font
|
||||
virtual IGUIFont* getFont(const io::path& filename);
|
||||
|
||||
//! add an externally loaded font
|
||||
virtual IGUIFont* addFont(const io::path& name, IGUIFont* font);
|
||||
|
||||
//! remove loaded font
|
||||
virtual void removeFont(IGUIFont* font);
|
||||
|
||||
//! returns default font
|
||||
virtual IGUIFont* getBuiltInFont() const;
|
||||
|
||||
//! returns the sprite bank
|
||||
virtual IGUISpriteBank* getSpriteBank(const io::path& filename);
|
||||
|
||||
//! returns the sprite bank
|
||||
virtual IGUISpriteBank* addEmptySpriteBank(const io::path& name);
|
||||
|
||||
//! adds an button. The returned pointer must not be dropped.
|
||||
virtual IGUIButton* addButton(const core::rect<s32>& rectangle, IGUIElement* parent=0, s32 id=-1, const wchar_t* text=0,const wchar_t* tooltiptext = 0);
|
||||
|
||||
//! adds a window. The returned pointer must not be dropped.
|
||||
virtual IGUIWindow* addWindow(const core::rect<s32>& rectangle, bool modal = false,
|
||||
const wchar_t* text=0, IGUIElement* parent=0, s32 id=-1);
|
||||
|
||||
//! adds a modal screen. The returned pointer must not be dropped.
|
||||
virtual IGUIElement* addModalScreen(IGUIElement* parent);
|
||||
|
||||
//! Adds a message box.
|
||||
virtual IGUIWindow* addMessageBox(const wchar_t* caption, const wchar_t* text=0,
|
||||
bool modal = true, s32 flag = EMBF_OK, IGUIElement* parent=0, s32 id=-1, video::ITexture* image=0);
|
||||
|
||||
//! adds a scrollbar. The returned pointer must not be dropped.
|
||||
virtual IGUIScrollBar* addScrollBar(bool horizontal, const core::rect<s32>& rectangle,
|
||||
IGUIElement* parent=0, s32 id=-1);
|
||||
|
||||
//! Adds an image element.
|
||||
virtual IGUIImage* addImage(video::ITexture* image, core::position2d<s32> pos,
|
||||
bool useAlphaChannel=true, IGUIElement* parent=0, s32 id=-1, const wchar_t* text=0);
|
||||
|
||||
//! adds an image. The returned pointer must not be dropped.
|
||||
virtual IGUIImage* addImage(const core::rect<s32>& rectangle,
|
||||
IGUIElement* parent=0, s32 id=-1, const wchar_t* text=0, bool useAlphaChannel=true);
|
||||
|
||||
//! adds a checkbox
|
||||
virtual IGUICheckBox* addCheckBox(bool checked, const core::rect<s32>& rectangle, IGUIElement* parent=0, s32 id=-1, const wchar_t* text=0);
|
||||
|
||||
//! adds a list box
|
||||
virtual IGUIListBox* addListBox(const core::rect<s32>& rectangle,
|
||||
IGUIElement* parent=0, s32 id=-1, bool drawBackground=false);
|
||||
|
||||
//! adds a tree view
|
||||
virtual IGUITreeView* addTreeView(const core::rect<s32>& rectangle,
|
||||
IGUIElement* parent=0, s32 id=-1, bool drawBackground=false,
|
||||
bool scrollBarVertical = true, bool scrollBarHorizontal = false);
|
||||
|
||||
//! adds an mesh viewer. The returned pointer must not be dropped.
|
||||
virtual IGUIMeshViewer* addMeshViewer(const core::rect<s32>& rectangle, IGUIElement* parent=0, s32 id=-1, const wchar_t* text=0);
|
||||
|
||||
//! Adds a file open dialog.
|
||||
virtual IGUIFileOpenDialog* addFileOpenDialog(const wchar_t* title = 0,
|
||||
bool modal=true, IGUIElement* parent=0, s32 id=-1,
|
||||
bool restoreCWD=false, io::path::char_type* startDir=0);
|
||||
|
||||
//! Adds a color select dialog.
|
||||
virtual IGUIColorSelectDialog* addColorSelectDialog(const wchar_t* title = 0, bool modal=true, IGUIElement* parent=0, s32 id=-1);
|
||||
|
||||
//! adds a static text. The returned pointer must not be dropped.
|
||||
virtual IGUIStaticText* addStaticText(const wchar_t* text, const core::rect<s32>& rectangle,
|
||||
bool border=false, bool wordWrap=true, IGUIElement* parent=0, s32 id=-1, bool drawBackground = false);
|
||||
|
||||
//! Adds an edit box. The returned pointer must not be dropped.
|
||||
virtual IGUIEditBox* addEditBox(const wchar_t* text, const core::rect<s32>& rectangle,
|
||||
bool border=false, IGUIElement* parent=0, s32 id=-1);
|
||||
|
||||
//! Adds a spin box to the environment
|
||||
virtual IGUISpinBox* addSpinBox(const wchar_t* text, const core::rect<s32>& rectangle,
|
||||
bool border=false,IGUIElement* parent=0, s32 id=-1);
|
||||
|
||||
//! Adds a tab control to the environment.
|
||||
virtual IGUITabControl* addTabControl(const core::rect<s32>& rectangle,
|
||||
IGUIElement* parent=0, bool fillbackground=false, bool border=true, s32 id=-1);
|
||||
|
||||
//! Adds tab to the environment.
|
||||
virtual IGUITab* addTab(const core::rect<s32>& rectangle,
|
||||
IGUIElement* parent=0, s32 id=-1);
|
||||
|
||||
//! Adds a context menu to the environment.
|
||||
virtual IGUIContextMenu* addContextMenu(const core::rect<s32>& rectangle,
|
||||
IGUIElement* parent=0, s32 id=-1);
|
||||
|
||||
//! Adds a menu to the environment.
|
||||
virtual IGUIContextMenu* addMenu(IGUIElement* parent=0, s32 id=-1);
|
||||
|
||||
//! Adds a toolbar to the environment. It is like a menu is always placed on top
|
||||
//! in its parent, and contains buttons.
|
||||
virtual IGUIToolBar* addToolBar(IGUIElement* parent=0, s32 id=-1);
|
||||
|
||||
//! Adds a combo box to the environment.
|
||||
virtual IGUIComboBox* addComboBox(const core::rect<s32>& rectangle,
|
||||
IGUIElement* parent=0, s32 id=-1);
|
||||
|
||||
//! Adds a table element.
|
||||
virtual IGUITable* addTable(const core::rect<s32>& rectangle,
|
||||
IGUIElement* parent=0, s32 id=-1, bool drawBackground=false);
|
||||
|
||||
//! sets the focus to an element
|
||||
virtual bool setFocus(IGUIElement* element);
|
||||
|
||||
//! removes the focus from an element
|
||||
virtual bool removeFocus(IGUIElement* element);
|
||||
|
||||
//! Returns if the element has focus
|
||||
virtual bool hasFocus(IGUIElement* element) const;
|
||||
|
||||
//! Returns the element with the focus
|
||||
virtual IGUIElement* getFocus() const;
|
||||
|
||||
//! Returns the element last known to be under the mouse
|
||||
virtual IGUIElement* getHovered() const;
|
||||
|
||||
//! Adds an element for fading in or out.
|
||||
virtual IGUIInOutFader* addInOutFader(const core::rect<s32>* rectangle=0, IGUIElement* parent=0, s32 id=-1);
|
||||
|
||||
//! Returns the root gui element.
|
||||
virtual IGUIElement* getRootGUIElement();
|
||||
|
||||
virtual void OnPostRender( u32 time );
|
||||
|
||||
//! Returns the default element factory which can create all built in elements
|
||||
virtual IGUIElementFactory* getDefaultGUIElementFactory() const;
|
||||
|
||||
//! Adds an element factory to the gui environment.
|
||||
/** Use this to extend the gui environment with new element types which it should be
|
||||
able to create automaticly, for example when loading data from xml files. */
|
||||
virtual void registerGUIElementFactory(IGUIElementFactory* factoryToAdd);
|
||||
|
||||
//! Returns amount of registered scene node factories.
|
||||
virtual u32 getRegisteredGUIElementFactoryCount() const;
|
||||
|
||||
//! Returns a scene node factory by index
|
||||
virtual IGUIElementFactory* getGUIElementFactory(u32 index) const;
|
||||
|
||||
//! Adds a GUI Element by its name
|
||||
virtual IGUIElement* addGUIElement(const c8* elementName, IGUIElement* parent=0);
|
||||
|
||||
//! Saves the current gui into a file.
|
||||
/** \param filename: Name of the file.
|
||||
\param start: The element to start saving from.
|
||||
if not specified, the root element will be used */
|
||||
virtual bool saveGUI( const io::path& filename, IGUIElement* start=0);
|
||||
|
||||
//! Saves the current gui into a file.
|
||||
/** \param file: The file to save the GUI to.
|
||||
\param start: The element to start saving from.
|
||||
if not specified, the root element will be used */
|
||||
virtual bool saveGUI(io::IWriteFile* file, IGUIElement* start=0);
|
||||
|
||||
//! Loads the gui. Note that the current gui is not cleared before.
|
||||
/** \param filename: Name of the file.
|
||||
\param parent: The parent of all loaded GUI elements,
|
||||
if not specified, the root element will be used */
|
||||
virtual bool loadGUI(const io::path& filename, IGUIElement* parent=0);
|
||||
|
||||
//! Loads the gui. Note that the current gui is not cleared before.
|
||||
/** \param file: IReadFile to load the GUI from
|
||||
\param parent: The parent of all loaded GUI elements,
|
||||
if not specified, the root element will be used */
|
||||
virtual bool loadGUI(io::IReadFile* file, IGUIElement* parent=0);
|
||||
|
||||
//! Writes attributes of the environment
|
||||
virtual void serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options=0) const;
|
||||
|
||||
//! Reads attributes of the environment.
|
||||
virtual void deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options=0);
|
||||
|
||||
//! writes an element
|
||||
virtual void writeGUIElement(io::IXMLWriter* writer, IGUIElement* node);
|
||||
|
||||
//! reads an element
|
||||
virtual void readGUIElement(io::IXMLReader* reader, IGUIElement* node);
|
||||
|
||||
private:
|
||||
|
||||
IGUIElement* getNextElement(bool reverse=false, bool group=false);
|
||||
|
||||
void updateHoveredElement(core::position2d<s32> mousePos);
|
||||
|
||||
void loadBuiltInFont();
|
||||
|
||||
struct SFont
|
||||
{
|
||||
io::SNamedPath NamedPath;
|
||||
IGUIFont* Font;
|
||||
|
||||
bool operator < (const SFont& other) const
|
||||
{
|
||||
return (NamedPath < other.NamedPath);
|
||||
}
|
||||
};
|
||||
|
||||
struct SSpriteBank
|
||||
{
|
||||
io::SNamedPath NamedPath;
|
||||
IGUISpriteBank* Bank;
|
||||
|
||||
bool operator < (const SSpriteBank& other) const
|
||||
{
|
||||
return (NamedPath < other.NamedPath);
|
||||
}
|
||||
};
|
||||
|
||||
struct SToolTip
|
||||
{
|
||||
IGUIStaticText* Element;
|
||||
u32 LastTime;
|
||||
u32 EnterTime;
|
||||
u32 LaunchTime;
|
||||
u32 RelaunchTime;
|
||||
};
|
||||
|
||||
SToolTip ToolTip;
|
||||
|
||||
core::array<IGUIElementFactory*> GUIElementFactoryList;
|
||||
|
||||
core::array<SFont> Fonts;
|
||||
core::array<SSpriteBank> Banks;
|
||||
video::IVideoDriver* Driver;
|
||||
IGUIElement* Hovered;
|
||||
IGUIElement* HoveredNoSubelement; // subelements replaced by their parent, so you only have 'real' elements here
|
||||
IGUIElement* Focus;
|
||||
core::position2d<s32> LastHoveredMousePos;
|
||||
IGUISkin* CurrentSkin;
|
||||
io::IFileSystem* FileSystem;
|
||||
IEventReceiver* UserReceiver;
|
||||
IOSOperator* Operator;
|
||||
static const io::path DefaultFontName;
|
||||
};
|
||||
|
||||
} // end namespace gui
|
||||
} // end namespace irr
|
||||
|
||||
#endif // _IRR_COMPILE_WITH_GUI_
|
||||
|
||||
#endif // __C_GUI_ENVIRONMENT_H_INCLUDED__
|
||||
|
||||
|
446
source/Irrlicht/CGUIFileOpenDialog.cpp
Normal file
446
source/Irrlicht/CGUIFileOpenDialog.cpp
Normal file
@ -0,0 +1,446 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#include "CGUIFileOpenDialog.h"
|
||||
#ifdef _IRR_COMPILE_WITH_GUI_
|
||||
|
||||
#include <locale.h>
|
||||
|
||||
#include "IGUISkin.h"
|
||||
#include "IGUIEnvironment.h"
|
||||
#include "IVideoDriver.h"
|
||||
#include "IGUIButton.h"
|
||||
#include "IGUIStaticText.h"
|
||||
#include "IGUIFont.h"
|
||||
#include "IGUIFontBitmap.h"
|
||||
#include "IFileList.h"
|
||||
#include "os.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace gui
|
||||
{
|
||||
|
||||
const s32 FOD_WIDTH = 350;
|
||||
const s32 FOD_HEIGHT = 250;
|
||||
|
||||
|
||||
//! constructor
|
||||
CGUIFileOpenDialog::CGUIFileOpenDialog(const wchar_t* title,
|
||||
IGUIEnvironment* environment, IGUIElement* parent, s32 id,
|
||||
bool restoreCWD, io::path::char_type* startDir)
|
||||
: IGUIFileOpenDialog(environment, parent, id,
|
||||
core::rect<s32>((parent->getAbsolutePosition().getWidth()-FOD_WIDTH)/2,
|
||||
(parent->getAbsolutePosition().getHeight()-FOD_HEIGHT)/2,
|
||||
(parent->getAbsolutePosition().getWidth()-FOD_WIDTH)/2+FOD_WIDTH,
|
||||
(parent->getAbsolutePosition().getHeight()-FOD_HEIGHT)/2+FOD_HEIGHT)),
|
||||
FileNameText(0), FileList(0), Dragging(false)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
IGUIElement::setDebugName("CGUIFileOpenDialog");
|
||||
#endif
|
||||
|
||||
Text = title;
|
||||
|
||||
FileSystem = Environment?Environment->getFileSystem():0;
|
||||
|
||||
if (FileSystem)
|
||||
{
|
||||
FileSystem->grab();
|
||||
|
||||
if (restoreCWD)
|
||||
RestoreDirectory = FileSystem->getWorkingDirectory();
|
||||
if (startDir)
|
||||
{
|
||||
StartDirectory = startDir;
|
||||
FileSystem->changeWorkingDirectoryTo(startDir);
|
||||
}
|
||||
}
|
||||
else
|
||||
return;
|
||||
|
||||
IGUISpriteBank* sprites = 0;
|
||||
video::SColor color(255,255,255,255);
|
||||
IGUISkin* skin = Environment->getSkin();
|
||||
if (skin)
|
||||
{
|
||||
sprites = skin->getSpriteBank();
|
||||
color = skin->getColor(EGDC_WINDOW_SYMBOL);
|
||||
}
|
||||
|
||||
const s32 buttonw = skin->getSize(EGDS_WINDOW_BUTTON_WIDTH);
|
||||
const s32 posx = RelativeRect.getWidth() - buttonw - 4;
|
||||
|
||||
CloseButton = Environment->addButton(core::rect<s32>(posx, 3, posx + buttonw, 3 + buttonw), this, -1,
|
||||
L"", skin ? skin->getDefaultText(EGDT_WINDOW_CLOSE) : L"Close");
|
||||
CloseButton->setSubElement(true);
|
||||
CloseButton->setTabStop(false);
|
||||
if (sprites)
|
||||
{
|
||||
CloseButton->setSpriteBank(sprites);
|
||||
CloseButton->setSprite(EGBS_BUTTON_UP, skin->getIcon(EGDI_WINDOW_CLOSE), color);
|
||||
CloseButton->setSprite(EGBS_BUTTON_DOWN, skin->getIcon(EGDI_WINDOW_CLOSE), color);
|
||||
}
|
||||
CloseButton->setAlignment(EGUIA_LOWERRIGHT, EGUIA_LOWERRIGHT, EGUIA_UPPERLEFT, EGUIA_UPPERLEFT);
|
||||
CloseButton->grab();
|
||||
|
||||
OKButton = Environment->addButton(
|
||||
core::rect<s32>(RelativeRect.getWidth()-80, 30, RelativeRect.getWidth()-10, 50),
|
||||
this, -1, skin ? skin->getDefaultText(EGDT_MSG_BOX_OK) : L"OK");
|
||||
OKButton->setSubElement(true);
|
||||
OKButton->setAlignment(EGUIA_LOWERRIGHT, EGUIA_LOWERRIGHT, EGUIA_UPPERLEFT, EGUIA_UPPERLEFT);
|
||||
OKButton->grab();
|
||||
|
||||
CancelButton = Environment->addButton(
|
||||
core::rect<s32>(RelativeRect.getWidth()-80, 55, RelativeRect.getWidth()-10, 75),
|
||||
this, -1, skin ? skin->getDefaultText(EGDT_MSG_BOX_CANCEL) : L"Cancel");
|
||||
CancelButton->setSubElement(true);
|
||||
CancelButton->setAlignment(EGUIA_LOWERRIGHT, EGUIA_LOWERRIGHT, EGUIA_UPPERLEFT, EGUIA_UPPERLEFT);
|
||||
CancelButton->grab();
|
||||
|
||||
FileBox = Environment->addListBox(core::rect<s32>(10, 55, RelativeRect.getWidth()-90, 230), this, -1, true);
|
||||
FileBox->setSubElement(true);
|
||||
FileBox->setAlignment(EGUIA_UPPERLEFT, EGUIA_LOWERRIGHT, EGUIA_UPPERLEFT, EGUIA_LOWERRIGHT);
|
||||
FileBox->grab();
|
||||
|
||||
FileNameText = Environment->addEditBox(0, core::rect<s32>(10, 30, RelativeRect.getWidth()-90, 50), true, this);
|
||||
FileNameText->setSubElement(true);
|
||||
FileNameText->setAlignment(EGUIA_UPPERLEFT, EGUIA_LOWERRIGHT, EGUIA_UPPERLEFT, EGUIA_UPPERLEFT);
|
||||
FileNameText->grab();
|
||||
|
||||
setTabGroup(true);
|
||||
|
||||
fillListBox();
|
||||
}
|
||||
|
||||
|
||||
//! destructor
|
||||
CGUIFileOpenDialog::~CGUIFileOpenDialog()
|
||||
{
|
||||
if (CloseButton)
|
||||
CloseButton->drop();
|
||||
|
||||
if (OKButton)
|
||||
OKButton->drop();
|
||||
|
||||
if (CancelButton)
|
||||
CancelButton->drop();
|
||||
|
||||
if (FileBox)
|
||||
FileBox->drop();
|
||||
|
||||
if (FileNameText)
|
||||
FileNameText->drop();
|
||||
|
||||
if (FileSystem)
|
||||
{
|
||||
// revert to original CWD if path was set in constructor
|
||||
if (RestoreDirectory.size())
|
||||
FileSystem->changeWorkingDirectoryTo(RestoreDirectory);
|
||||
FileSystem->drop();
|
||||
}
|
||||
|
||||
if (FileList)
|
||||
FileList->drop();
|
||||
}
|
||||
|
||||
|
||||
//! returns the filename of the selected file. Returns NULL, if no file was selected.
|
||||
const wchar_t* CGUIFileOpenDialog::getFileName() const
|
||||
{
|
||||
return FileName.c_str();
|
||||
}
|
||||
|
||||
//! Returns the directory of the selected file. Returns NULL, if no directory was selected.
|
||||
const io::path& CGUIFileOpenDialog::getDirectoryName()
|
||||
{
|
||||
FileSystem->flattenFilename ( FileDirectory );
|
||||
return FileDirectory;
|
||||
}
|
||||
|
||||
|
||||
//! called if an event happened.
|
||||
bool CGUIFileOpenDialog::OnEvent(const SEvent& event)
|
||||
{
|
||||
if (isEnabled())
|
||||
{
|
||||
switch(event.EventType)
|
||||
{
|
||||
case EET_GUI_EVENT:
|
||||
switch(event.GUIEvent.EventType)
|
||||
{
|
||||
case EGET_ELEMENT_FOCUS_LOST:
|
||||
Dragging = false;
|
||||
break;
|
||||
case EGET_BUTTON_CLICKED:
|
||||
if (event.GUIEvent.Caller == CloseButton ||
|
||||
event.GUIEvent.Caller == CancelButton)
|
||||
{
|
||||
sendCancelEvent();
|
||||
remove();
|
||||
return true;
|
||||
}
|
||||
else
|
||||
if (event.GUIEvent.Caller == OKButton )
|
||||
{
|
||||
if ( FileDirectory != L"" )
|
||||
{
|
||||
sendSelectedEvent( EGET_DIRECTORY_SELECTED );
|
||||
}
|
||||
if ( FileName != L"" )
|
||||
{
|
||||
sendSelectedEvent( EGET_FILE_SELECTED );
|
||||
remove();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case EGET_LISTBOX_CHANGED:
|
||||
{
|
||||
s32 selected = FileBox->getSelected();
|
||||
if (FileList && FileSystem)
|
||||
{
|
||||
if (FileList->isDirectory(selected))
|
||||
{
|
||||
FileName = L"";
|
||||
FileDirectory = FileList->getFullFileName(selected);
|
||||
}
|
||||
else
|
||||
{
|
||||
FileDirectory = L"";
|
||||
FileName = FileList->getFullFileName(selected);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case EGET_LISTBOX_SELECTED_AGAIN:
|
||||
{
|
||||
const s32 selected = FileBox->getSelected();
|
||||
if (FileList && FileSystem)
|
||||
{
|
||||
if (FileList->isDirectory(selected))
|
||||
{
|
||||
FileDirectory = FileList->getFullFileName(selected);
|
||||
FileSystem->changeWorkingDirectoryTo(FileList->getFileName(selected));
|
||||
fillListBox();
|
||||
FileName = "";
|
||||
}
|
||||
else
|
||||
{
|
||||
FileName = FileList->getFullFileName(selected);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case EGET_EDITBOX_ENTER:
|
||||
if (event.GUIEvent.Caller == FileNameText)
|
||||
{
|
||||
io::path dir( FileNameText->getText () );
|
||||
if ( FileSystem->changeWorkingDirectoryTo( dir ) )
|
||||
{
|
||||
fillListBox();
|
||||
FileName = L"";
|
||||
}
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case EET_MOUSE_INPUT_EVENT:
|
||||
switch(event.MouseInput.Event)
|
||||
{
|
||||
case EMIE_MOUSE_WHEEL:
|
||||
return FileBox->OnEvent(event);
|
||||
case EMIE_LMOUSE_PRESSED_DOWN:
|
||||
DragStart.X = event.MouseInput.X;
|
||||
DragStart.Y = event.MouseInput.Y;
|
||||
Dragging = true;
|
||||
Environment->setFocus(this);
|
||||
return true;
|
||||
case EMIE_LMOUSE_LEFT_UP:
|
||||
Dragging = false;
|
||||
return true;
|
||||
case EMIE_MOUSE_MOVED:
|
||||
|
||||
if ( !event.MouseInput.isLeftPressed () )
|
||||
Dragging = false;
|
||||
|
||||
if (Dragging)
|
||||
{
|
||||
// gui window should not be dragged outside its parent
|
||||
if (Parent)
|
||||
if (event.MouseInput.X < Parent->getAbsolutePosition().UpperLeftCorner.X +1 ||
|
||||
event.MouseInput.Y < Parent->getAbsolutePosition().UpperLeftCorner.Y +1 ||
|
||||
event.MouseInput.X > Parent->getAbsolutePosition().LowerRightCorner.X -1 ||
|
||||
event.MouseInput.Y > Parent->getAbsolutePosition().LowerRightCorner.Y -1)
|
||||
|
||||
return true;
|
||||
|
||||
move(core::position2d<s32>(event.MouseInput.X - DragStart.X, event.MouseInput.Y - DragStart.Y));
|
||||
DragStart.X = event.MouseInput.X;
|
||||
DragStart.Y = event.MouseInput.Y;
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return IGUIElement::OnEvent(event);
|
||||
}
|
||||
|
||||
|
||||
//! draws the element and its children
|
||||
void CGUIFileOpenDialog::draw()
|
||||
{
|
||||
if (!IsVisible)
|
||||
return;
|
||||
|
||||
IGUISkin* skin = Environment->getSkin();
|
||||
|
||||
core::rect<s32> rect = AbsoluteRect;
|
||||
|
||||
rect = skin->draw3DWindowBackground(this, true, skin->getColor(EGDC_ACTIVE_BORDER),
|
||||
rect, &AbsoluteClippingRect);
|
||||
|
||||
if (Text.size())
|
||||
{
|
||||
rect.UpperLeftCorner.X += 2;
|
||||
rect.LowerRightCorner.X -= skin->getSize(EGDS_WINDOW_BUTTON_WIDTH) + 5;
|
||||
|
||||
IGUIFont* font = skin->getFont(EGDF_WINDOW);
|
||||
if (font)
|
||||
font->draw(Text.c_str(), rect,
|
||||
skin->getColor(EGDC_ACTIVE_CAPTION),
|
||||
false, true, &AbsoluteClippingRect);
|
||||
}
|
||||
|
||||
IGUIElement::draw();
|
||||
}
|
||||
|
||||
|
||||
//! Writes attributes of the element.
|
||||
/* Not sure if this will really work out properly. Saving paths can be
|
||||
rather problematic. */
|
||||
void CGUIFileOpenDialog::serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options) const
|
||||
{
|
||||
IGUIFileOpenDialog::serializeAttributes(out,options);
|
||||
|
||||
out->addString("StartDirectory", StartDirectory.c_str());
|
||||
out->addBool("RestoreDirectory", (RestoreDirectory.size()!=0));
|
||||
}
|
||||
|
||||
|
||||
//! Reads attributes of the element
|
||||
/* Note that thiese paths changes will happen at arbitrary places upon
|
||||
load of the gui description. This may be undesired. */
|
||||
void CGUIFileOpenDialog::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options)
|
||||
{
|
||||
StartDirectory = in->getAttributeAsString("StartDirectory");
|
||||
const bool restore = in->getAttributeAsBool("RestoreDirectory");
|
||||
if (restore)
|
||||
RestoreDirectory = FileSystem->getWorkingDirectory();
|
||||
else
|
||||
RestoreDirectory = "";
|
||||
if (StartDirectory.size())
|
||||
FileSystem->changeWorkingDirectoryTo(StartDirectory);
|
||||
|
||||
IGUIFileOpenDialog::deserializeAttributes(in,options);
|
||||
}
|
||||
|
||||
|
||||
//! fills the listbox with files.
|
||||
void CGUIFileOpenDialog::fillListBox()
|
||||
{
|
||||
IGUISkin *skin = Environment->getSkin();
|
||||
|
||||
if (!FileSystem || !FileBox || !skin)
|
||||
return;
|
||||
|
||||
if (FileList)
|
||||
FileList->drop();
|
||||
|
||||
FileBox->clear();
|
||||
|
||||
FileList = FileSystem->createFileList();
|
||||
core::stringw s;
|
||||
|
||||
#if !defined(_IRR_WINDOWS_CE_PLATFORM_)
|
||||
setlocale(LC_ALL,"");
|
||||
#endif
|
||||
|
||||
if (FileList)
|
||||
{
|
||||
for (u32 i=0; i < FileList->getFileCount(); ++i)
|
||||
{
|
||||
#ifndef _IRR_WCHAR_FILESYSTEM
|
||||
const c8 *cs = (const c8 *)FileList->getFileName(i).c_str();
|
||||
wchar_t *ws = new wchar_t[strlen(cs) + 1];
|
||||
int len = mbstowcs(ws,cs,strlen(cs));
|
||||
ws[len] = 0;
|
||||
s = ws;
|
||||
delete [] ws;
|
||||
#else
|
||||
s = FileList->getFileName(i).c_str();
|
||||
#endif
|
||||
FileBox->addItem(s.c_str(), skin->getIcon(FileList->isDirectory(i) ? EGDI_DIRECTORY : EGDI_FILE));
|
||||
}
|
||||
}
|
||||
|
||||
if (FileNameText)
|
||||
{
|
||||
#ifndef _IRR_WCHAR_FILESYSTEM
|
||||
const c8 *cs = (const c8 *)FileSystem->getWorkingDirectory().c_str();
|
||||
wchar_t *ws = new wchar_t[strlen(cs) + 1];
|
||||
int len = mbstowcs(ws,cs,strlen(cs));
|
||||
ws[len] = 0;
|
||||
s = ws;
|
||||
delete [] ws;
|
||||
#else
|
||||
s = FileSystem->getWorkingDirectory();
|
||||
#endif
|
||||
|
||||
FileDirectory = s;
|
||||
FileNameText->setText(s.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//! sends the event that the file has been selected.
|
||||
void CGUIFileOpenDialog::sendSelectedEvent( EGUI_EVENT_TYPE type)
|
||||
{
|
||||
SEvent event;
|
||||
event.EventType = EET_GUI_EVENT;
|
||||
event.GUIEvent.Caller = this;
|
||||
event.GUIEvent.Element = 0;
|
||||
event.GUIEvent.EventType = type;
|
||||
Parent->OnEvent(event);
|
||||
}
|
||||
|
||||
|
||||
//! sends the event that the file choose process has been canceld
|
||||
void CGUIFileOpenDialog::sendCancelEvent()
|
||||
{
|
||||
SEvent event;
|
||||
event.EventType = EET_GUI_EVENT;
|
||||
event.GUIEvent.Caller = this;
|
||||
event.GUIEvent.Element = 0;
|
||||
event.GUIEvent.EventType = EGET_FILE_CHOOSE_DIALOG_CANCELLED;
|
||||
Parent->OnEvent(event);
|
||||
}
|
||||
|
||||
} // end namespace gui
|
||||
} // end namespace irr
|
||||
|
||||
#endif // _IRR_COMPILE_WITH_GUI_
|
84
source/Irrlicht/CGUIFileOpenDialog.h
Normal file
84
source/Irrlicht/CGUIFileOpenDialog.h
Normal file
@ -0,0 +1,84 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#ifndef __C_GUI_FILE_OPEN_DIALOG_H_INCLUDED__
|
||||
#define __C_GUI_FILE_OPEN_DIALOG_H_INCLUDED__
|
||||
|
||||
#include "IrrCompileConfig.h"
|
||||
#ifdef _IRR_COMPILE_WITH_GUI_
|
||||
|
||||
#include "IGUIFileOpenDialog.h"
|
||||
#include "IGUIButton.h"
|
||||
#include "IGUIListBox.h"
|
||||
#include "IGUIEditBox.h"
|
||||
#include "IFileSystem.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace gui
|
||||
{
|
||||
|
||||
class CGUIFileOpenDialog : public IGUIFileOpenDialog
|
||||
{
|
||||
public:
|
||||
|
||||
//! constructor
|
||||
CGUIFileOpenDialog(const wchar_t* title, IGUIEnvironment* environment,
|
||||
IGUIElement* parent, s32 id, bool restoreCWD=false,
|
||||
io::path::char_type* startDir=0);
|
||||
|
||||
//! destructor
|
||||
virtual ~CGUIFileOpenDialog();
|
||||
|
||||
//! returns the filename of the selected file. Returns NULL, if no file was selected.
|
||||
virtual const wchar_t* getFileName() const;
|
||||
|
||||
//! Returns the directory of the selected file. Returns NULL, if no directory was selected.
|
||||
virtual const io::path& getDirectoryName();
|
||||
|
||||
//! called if an event happened.
|
||||
virtual bool OnEvent(const SEvent& event);
|
||||
|
||||
//! draws the element and its children
|
||||
virtual void draw();
|
||||
|
||||
virtual void serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options=0) const;
|
||||
virtual void deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options=0);
|
||||
|
||||
protected:
|
||||
|
||||
//! fills the listbox with files.
|
||||
void fillListBox();
|
||||
|
||||
//! sends the event that the file has been selected.
|
||||
void sendSelectedEvent( EGUI_EVENT_TYPE type );
|
||||
|
||||
//! sends the event that the file choose process has been canceld
|
||||
void sendCancelEvent();
|
||||
|
||||
core::position2d<s32> DragStart;
|
||||
core::stringw FileName;
|
||||
io::path FileDirectory;
|
||||
io::path RestoreDirectory;
|
||||
io::path StartDirectory;
|
||||
|
||||
IGUIButton* CloseButton;
|
||||
IGUIButton* OKButton;
|
||||
IGUIButton* CancelButton;
|
||||
IGUIListBox* FileBox;
|
||||
IGUIEditBox* FileNameText;
|
||||
IGUIElement* EventParent;
|
||||
io::IFileSystem* FileSystem;
|
||||
io::IFileList* FileList;
|
||||
bool Dragging;
|
||||
};
|
||||
|
||||
|
||||
} // end namespace gui
|
||||
} // end namespace irr
|
||||
|
||||
#endif // _IRR_COMPILE_WITH_GUI_
|
||||
|
||||
#endif // __C_GUI_FILE_OPEN_DIALOG_H_INCLUDED__
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user