Merge branch 'master' of github.com:supertuxkart/stk-code

This commit is contained in:
hiker 2015-01-16 11:55:31 +11:00
commit 111b3f6361
48 changed files with 52 additions and 5215 deletions

View File

@ -4,7 +4,7 @@ out vec4 FragColor;
void main(void)
{
vec3 eyedir = gl_FragCoord.xyz / vec3(screen, 1.);
vec3 eyedir = vec3(gl_FragCoord.xy / screen, 1.);
eyedir = 2.0 * eyedir - 1.0;
vec4 tmp = (InverseProjectionMatrix * vec4(eyedir, 1.));
tmp /= tmp.w;

10
data/shaders/sky.vert Normal file
View File

@ -0,0 +1,10 @@
#if __VERSION__ >= 330
layout(location = 0) in vec3 Position;
#else
in vec3 Position;
#endif
void main()
{
gl_Position = vec4(Position, 1.);
}

View File

@ -6,6 +6,6 @@ vec3 SpecularIBL(vec3 normal, vec3 V, float roughness)
sampleDirection = (InverseViewMatrix * vec4(sampleDirection, 0.)).xyz;
// Assume 8 level of lod (ie 256x256 texture)
float lodval = 8. * (1. - roughness);
return clamp( textureLod(probe, sampleDirection, lodval).rgb, 0., 1.);
float lodval = 7. * (1. - roughness);
return clamp(textureLod(probe, sampleDirection, lodval).rgb, 0., 1.);
}

View File

@ -61,9 +61,7 @@ source/Irrlicht/CGUIFileOpenDialog.cpp
source/Irrlicht/CGUISpriteBank.cpp
source/Irrlicht/CParticleFadeOutAffector.cpp
source/Irrlicht/CGUIMenu.cpp
source/Irrlicht/CImageWriterPSD.cpp
source/Irrlicht/CSphereSceneNode.cpp
source/Irrlicht/CImageWriterTGA.cpp
source/Irrlicht/CImageWriterPNG.cpp
source/Irrlicht/CSceneNodeAnimatorFollowSpline.cpp
source/Irrlicht/CGUIMessageBox.cpp
@ -73,7 +71,6 @@ source/Irrlicht/CBoneSceneNode.cpp
source/Irrlicht/CNPKReader.cpp
source/Irrlicht/COpenGLSLMaterialRenderer.cpp
source/Irrlicht/CParticleRotationAffector.cpp
source/Irrlicht/CImageLoaderPSD.cpp
source/Irrlicht/CTriangleBBSelector.cpp
source/Irrlicht/CGUIComboBox.cpp
source/Irrlicht/CSceneNodeAnimatorTexture.cpp
@ -93,7 +90,6 @@ source/Irrlicht/CParticlePointEmitter.cpp
source/Irrlicht/CTextSceneNode.cpp
source/Irrlicht/CIrrDeviceLinux.cpp
source/Irrlicht/CIrrDeviceStub.cpp
source/Irrlicht/CImageWriterPCX.cpp
source/Irrlicht/CGUIInOutFader.cpp
source/Irrlicht/CGUITreeView.cpp
source/Irrlicht/CAnimatedMeshSceneNode.cpp
@ -105,7 +101,6 @@ source/Irrlicht/CColorConverter.cpp
source/Irrlicht/CMeshCache.cpp
source/Irrlicht/CIrrDeviceFB.cpp
source/Irrlicht/CMemoryFile.cpp
source/Irrlicht/CImageWriterPPM.cpp
source/Irrlicht/CMountPointReader.cpp
source/Irrlicht/CBillboardSceneNode.cpp
source/Irrlicht/CGUIImageList.cpp
@ -124,29 +119,23 @@ source/Irrlicht/CGUIEditBox.cpp
source/Irrlicht/CLogger.cpp
source/Irrlicht/CMeshManipulator.cpp
source/Irrlicht/CLightSceneNode.cpp
source/Irrlicht/CImageLoaderDDS.cpp
source/Irrlicht/CSkyBoxSceneNode.cpp
source/Irrlicht/CWriteFile.cpp
source/Irrlicht/COctreeTriangleSelector.cpp
source/Irrlicht/CFileList.cpp
source/Irrlicht/CImageLoaderPCX.cpp
source/Irrlicht/CIrrDeviceSDL.cpp
source/Irrlicht/COSOperator.cpp
source/Irrlicht/CImageLoaderJPG.cpp
source/Irrlicht/COpenGLExtensionHandler.cpp
source/Irrlicht/CImageLoaderWAL.cpp
source/Irrlicht/CXMLWriter.cpp
source/Irrlicht/CSceneNodeAnimatorCameraFPS.cpp
source/Irrlicht/CImageLoaderPPM.cpp
source/Irrlicht/CGUIColorSelectDialog.cpp
source/Irrlicht/CSceneManager.cpp
source/Irrlicht/Irrlicht.cpp
source/Irrlicht/COpenGLShaderMaterialRenderer.cpp
source/Irrlicht/CImageLoaderTGA.cpp
source/Irrlicht/COpenGLDriver.cpp
source/Irrlicht/CSceneNodeAnimatorFlyStraight.cpp
source/Irrlicht/irrXML.cpp
source/Irrlicht/CImageLoaderRGB.cpp
source/Irrlicht/CSkinnedMesh.cpp
source/Irrlicht/CXMLReader.cpp
source/Irrlicht/CDummyTransformationSceneNode.cpp
@ -159,7 +148,6 @@ source/Irrlicht/CGUISpinBox.cpp
source/Irrlicht/CReadFile.cpp
source/Irrlicht/CParticleRingEmitter.cpp
source/Irrlicht/CMetaTriangleSelector.cpp
source/Irrlicht/CShadowVolumeSceneNode.cpp
source/Irrlicht/CDefaultSceneNodeFactory.cpp
source/Irrlicht/CGUIImage.cpp
source/Irrlicht/CGUIEnvironment.cpp
@ -174,20 +162,17 @@ source/Irrlicht/CIrrDeviceLinux.h
source/Irrlicht/CMeshCache.h
source/Irrlicht/CAttributes.h
source/Irrlicht/CParticleMeshEmitter.h
source/Irrlicht/CImageWriterPPM.h
source/Irrlicht/CParticlePointEmitter.h
source/Irrlicht/CParticleRotationAffector.h
source/Irrlicht/CMountPointReader.h
source/Irrlicht/CIrrDeviceConsole.h
source/Irrlicht/CTerrainSceneNode.h
source/Irrlicht/CSceneNodeAnimatorCollisionResponse.h
source/Irrlicht/CImageLoaderWAL.h
source/Irrlicht/CImageLoaderBMP.h
source/Irrlicht/CSkinnedMesh.h
source/Irrlicht/COpenGLParallaxMapRenderer.h
source/Irrlicht/CParticleRingEmitter.h
source/Irrlicht/COpenGLShaderMaterialRenderer.h
source/Irrlicht/CImageWriterTGA.h
source/Irrlicht/CImageLoaderPNG.h
source/Irrlicht/COctreeTriangleSelector.h
source/Irrlicht/COpenGLTexture.h
@ -229,7 +214,6 @@ source/Irrlicht/MacOSX/AppDelegate.h
source/Irrlicht/MacOSX/CIrrDeviceMacOSX.h
source/Irrlicht/MacOSX/OSXClipboard.h
source/Irrlicht/CSceneManager.h
source/Irrlicht/CImageLoaderPSD.h
source/Irrlicht/COpenGLDriver.h
source/Irrlicht/CGUIComboBox.h
source/Irrlicht/CVolumeLightSceneNode.h
@ -248,10 +232,8 @@ source/Irrlicht/CSphereSceneNode.h
source/Irrlicht/CIrrDeviceStub.h
source/Irrlicht/CDummyTransformationSceneNode.h
source/Irrlicht/CParticleBoxEmitter.h
source/Irrlicht/CShadowVolumeSceneNode.h
source/Irrlicht/COctreeSceneNode.h
source/Irrlicht/CReadFile.h
source/Irrlicht/CImageLoaderDDS.h
source/Irrlicht/COSOperator.h
source/Irrlicht/CLightSceneNode.h
source/Irrlicht/CParticleSphereEmitter.h
@ -262,19 +244,15 @@ source/Irrlicht/CGUIEditBox.h
source/Irrlicht/CGUISpriteBank.h
source/Irrlicht/CSceneNodeAnimatorFlyStraight.h
source/Irrlicht/COpenGLExtensionHandler.h
source/Irrlicht/CImageWriterPSD.h
source/Irrlicht/CGUIScrollBar.h
source/Irrlicht/CImageLoaderPCX.h
source/Irrlicht/CTriangleSelector.h
source/Irrlicht/CParticleGravityAffector.h
source/Irrlicht/CGUIModalScreen.h
source/Irrlicht/CDefaultSceneNodeFactory.h
source/Irrlicht/CImageLoaderPPM.h
source/Irrlicht/CXMLReaderImpl.h
source/Irrlicht/COpenGLMaterialRenderer.h
source/Irrlicht/CVideoModeList.h
source/Irrlicht/CParticleAnimatedMeshSceneNodeEmitter.h
source/Irrlicht/CImageLoaderTGA.h
source/Irrlicht/CColorConverter.h
source/Irrlicht/CWaterSurfaceSceneNode.h
source/Irrlicht/SoftwareDriver2_compile_config.h
@ -284,7 +262,6 @@ source/Irrlicht/CEmptySceneNode.h
source/Irrlicht/CParticleSystemSceneNode.h
source/Irrlicht/CImageWriterPNG.h
source/Irrlicht/CParticleScaleAffector.h
source/Irrlicht/CImageWriterPCX.h
source/Irrlicht/CImageLoaderJPG.h
source/Irrlicht/CBillboardSceneNode.h
source/Irrlicht/CIrrDeviceSDL.h
@ -304,7 +281,6 @@ source/Irrlicht/CGUIToolBar.h
source/Irrlicht/CImageWriterJPG.h
source/Irrlicht/IAttribute.h
source/Irrlicht/CNullDriver.h
source/Irrlicht/CImageLoaderRGB.h
source/Irrlicht/CWriteFile.h
source/Irrlicht/CSceneNodeAnimatorFollowSpline.h
source/Irrlicht/glxext.h

View File

@ -94,27 +94,6 @@ namespace scene
/** \return The importance of the animation: 1.f keeps the original animation, 0.f is no animation. */
virtual f32 getAnimationStrength() const =0;
//! Creates shadow volume scene node as child of this node.
/** The shadow can be rendered using the ZPass or the zfail
method. ZPass is a little bit faster because the shadow volume
creation is easier, but with this method there occur ugly
looking artifacs when the camera is inside the shadow volume.
These error do not occur with the ZFail method.
\param shadowMesh: Optional custom mesh for shadow volume.
\param id: Id of the shadow scene node. This id can be used to
identify the node later.
\param zfailmethod: If set to true, the shadow will use the
zfail method, if not, zpass is used.
\param infinity: Value used by the shadow volume algorithm to
scale the shadow volume (for zfail shadow volume we support only
finite shadows, so camera zfar must be larger than shadow back cap,
which is depend on infinity parameter).
\return Pointer to the created shadow scene node. This pointer
should not be dropped. See IReferenceCounted::drop() for more
information. */
virtual IShadowVolumeSceneNode* addShadowVolumeSceneNode(const IMesh* shadowMesh=0,
s32 id=-1, bool zfailmethod=true, f32 infinity=1000.0f) = 0;
//! Get a pointer to a joint in the mesh (if the mesh is a bone based mesh).
/** With this method it is possible to attach scene nodes to

View File

@ -38,27 +38,6 @@ public:
/** \return Pointer to mesh which is displayed by this node. */
virtual IMesh* getMesh(void) = 0;
//! Creates shadow volume scene node as child of this node.
/** The shadow can be rendered using the ZPass or the zfail
method. ZPass is a little bit faster because the shadow volume
creation is easier, but with this method there occur ugly
looking artifacs when the camera is inside the shadow volume.
These error do not occur with the ZFail method.
\param shadowMesh: Optional custom mesh for shadow volume.
\param id: Id of the shadow scene node. This id can be used to
identify the node later.
\param zfailmethod: If set to true, the shadow will use the
zfail method, if not, zpass is used.
\param infinity: Value used by the shadow volume algorithm to
scale the shadow volume (for zfail shadow volume we support only
finite shadows, so camera zfar must be larger than shadow back cap,
which is depend on infinity parameter).
\return Pointer to the created shadow scene node. This pointer
should not be dropped. See IReferenceCounted::drop() for more
information. */
virtual IShadowVolumeSceneNode* addShadowVolumeSceneNode(const IMesh* shadowMesh=0,
s32 id=-1, bool zfailmethod=true, f32 infinity=1000.0f) = 0;
//! 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 of a mesh
causing all mesh scene nodes referencing this mesh to change, too.

View File

@ -279,56 +279,11 @@ B3D, MS3D or X meshes */
#ifdef NO_IRR_COMPILE_WITH_JPG_LOADER_
#undef _IRR_COMPILE_WITH_JPG_LOADER_
#endif
//! Define _IRR_COMPILE_WITH_PCX_LOADER_ if you want to load .pcx files
//#define _IRR_COMPILE_WITH_PCX_LOADER_
#ifdef NO_IRR_COMPILE_WITH_PCX_LOADER_
#undef _IRR_COMPILE_WITH_PCX_LOADER_
#endif
//! Define _IRR_COMPILE_WITH_PNG_LOADER_ if you want to load .png files
#define _IRR_COMPILE_WITH_PNG_LOADER_
#ifdef NO_IRR_COMPILE_WITH_PNG_LOADER_
#undef _IRR_COMPILE_WITH_PNG_LOADER_
#endif
//! Define _IRR_COMPILE_WITH_PPM_LOADER_ if you want to load .ppm/.pgm/.pbm files
//#define _IRR_COMPILE_WITH_PPM_LOADER_
#ifdef NO_IRR_COMPILE_WITH_PPM_LOADER_
#undef _IRR_COMPILE_WITH_PPM_LOADER_
#endif
//! Define _IRR_COMPILE_WITH_PSD_LOADER_ if you want to load .psd files
//#define _IRR_COMPILE_WITH_PSD_LOADER_
#ifdef NO_IRR_COMPILE_WITH_PSD_LOADER_
#undef _IRR_COMPILE_WITH_PSD_LOADER_
#endif
//! Define _IRR_COMPILE_WITH_DDS_LOADER_ if you want to load .dds files
// Outcommented because
// a) it doesn't compile on 64-bit currently
// b) anyone enabling it should be aware that S3TC compression algorithm which might be used in that loader
// is patented in the US by S3 and they do collect license fees when it's used in applications.
// So if you are unfortunate enough to develop applications for US market and their broken patent system be careful.
// #define _IRR_COMPILE_WITH_DDS_LOADER_
#ifdef NO_IRR_COMPILE_WITH_DDS_LOADER_
#undef _IRR_COMPILE_WITH_DDS_LOADER_
#endif
//! Define _IRR_COMPILE_WITH_TGA_LOADER_ if you want to load .tga files
#define _IRR_COMPILE_WITH_TGA_LOADER_
#ifdef NO_IRR_COMPILE_WITH_TGA_LOADER_
#undef _IRR_COMPILE_WITH_TGA_LOADER_
#endif
//! Define _IRR_COMPILE_WITH_WAL_LOADER_ if you want to load .wal files
#define _IRR_COMPILE_WITH_WAL_LOADER_
#ifdef NO_IRR_COMPILE_WITH_WAL_LOADER_
#undef _IRR_COMPILE_WITH_WAL_LOADER_
#endif
//! Define _IRR_COMPILE_WITH_LMP_LOADER_ if you want to load .lmp files
#define _IRR_COMPILE_WITH_LMP_LOADER_
#ifdef NO_IRR_COMPILE_WITH_LMP_LOADER_
#undef _IRR_COMPILE_WITH_LMP_LOADER_
#endif
//! Define _IRR_COMPILE_WITH_RGB_LOADER_ if you want to load Silicon Graphics .rgb/.rgba/.sgi/.int/.inta/.bw files
#define _IRR_COMPILE_WITH_RGB_LOADER_
#ifdef NO_IRR_COMPILE_WITH_RGB_LOADER_
#undef _IRR_COMPILE_WITH_RGB_LOADER_
#endif
//! Define _IRR_COMPILE_WITH_BMP_WRITER_ if you want to write .bmp files
#define _IRR_COMPILE_WITH_BMP_WRITER_
@ -340,31 +295,11 @@ B3D, MS3D or X meshes */
#ifdef NO_IRR_COMPILE_WITH_JPG_WRITER_
#undef _IRR_COMPILE_WITH_JPG_WRITER_
#endif
//! Define _IRR_COMPILE_WITH_PCX_WRITER_ if you want to write .pcx files
//#define _IRR_COMPILE_WITH_PCX_WRITER_
#ifdef NO_IRR_COMPILE_WITH_PCX_WRITER_
#undef _IRR_COMPILE_WITH_PCX_WRITER_
#endif
//! Define _IRR_COMPILE_WITH_PNG_WRITER_ if you want to write .png files
#define _IRR_COMPILE_WITH_PNG_WRITER_
#ifdef NO_IRR_COMPILE_WITH_PNG_WRITER_
#undef _IRR_COMPILE_WITH_PNG_WRITER_
#endif
//! Define _IRR_COMPILE_WITH_PPM_WRITER_ if you want to write .ppm files
//#define _IRR_COMPILE_WITH_PPM_WRITER_
#ifdef NO_IRR_COMPILE_WITH_PPM_WRITER_
#undef _IRR_COMPILE_WITH_PPM_WRITER_
#endif
//! Define _IRR_COMPILE_WITH_PSD_WRITER_ if you want to write .psd files
//#define _IRR_COMPILE_WITH_PSD_WRITER_
#ifdef NO_IRR_COMPILE_WITH_PSD_WRITER_
#undef _IRR_COMPILE_WITH_PSD_WRITER_
#endif
//! Define _IRR_COMPILE_WITH_TGA_WRITER_ if you want to write .tga files
//#define _IRR_COMPILE_WITH_TGA_WRITER_
#ifdef NO_IRR_COMPILE_WITH_TGA_WRITER_
#undef _IRR_COMPILE_WITH_TGA_WRITER_
#endif
//! Define __IRR_COMPILE_WITH_ZIP_ARCHIVE_LOADER_ if you want to open ZIP and GZIP archives
/** ZIP reading has several more options below to configure. */

View File

@ -7,7 +7,6 @@
#include "ISceneManager.h"
#include "S3DVertex.h"
#include "os.h"
#include "CShadowVolumeSceneNode.h"
#include "CSkinnedMesh.h"
#include "IDummyTransformationSceneNode.h"
#include "IBoneSceneNode.h"
@ -37,7 +36,7 @@ CAnimatedMeshSceneNode::CAnimatedMeshSceneNode(IAnimatedMesh* mesh,
TransitionTime(0), Transiting(0.f), TransitingBlend(0.f),
JointMode(EJUOR_NONE), JointsUsed(false),
Looping(true), ReadOnlyMaterials(false), RenderFromIdentity(false),
LoopCallBack(0), PassCount(0), Shadow(0)
LoopCallBack(0), PassCount(0)
{
#ifdef _DEBUG
setDebugName("CAnimatedMeshSceneNode");
@ -53,9 +52,6 @@ CAnimatedMeshSceneNode::~CAnimatedMeshSceneNode()
if (Mesh)
Mesh->drop();
if (Shadow)
Shadow->drop();
if (LoopCallBack)
LoopCallBack->drop();
}
@ -287,9 +283,6 @@ void CAnimatedMeshSceneNode::render()
driver->setTransform(video::ETS_WORLD, AbsoluteTransformation);
if (Shadow && PassCount==1)
Shadow->updateShadowVolumes();
// for debug purposes only:
bool renderMeshes = true;
@ -523,23 +516,6 @@ u32 CAnimatedMeshSceneNode::getMaterialCount() const
}
//! Creates shadow volume scene node as child of this node
//! and returns a pointer to it.
IShadowVolumeSceneNode* CAnimatedMeshSceneNode::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;
}
//! Returns a pointer to a child node, which has the same transformation as
//! the corresponding joint, if the mesh in this scene node is a skinned mesh.
@ -644,12 +620,6 @@ ISceneNode* CAnimatedMeshSceneNode::getXJointNode(const c8* jointName)
//! or to remove attached childs.
bool CAnimatedMeshSceneNode::removeChild(ISceneNode* child)
{
if (child && Shadow == child)
{
Shadow->drop();
Shadow = 0;
}
if (ISceneNode::removeChild(child))
{
if (JointsUsed) //stop weird bugs caused while changing parents as the joints are being created
@ -1015,8 +985,6 @@ ISceneNode* CAnimatedMeshSceneNode::clone(ISceneNode* newParent, ISceneManager*
newNode->ReadOnlyMaterials = ReadOnlyMaterials;
newNode->LoopCallBack = LoopCallBack;
newNode->PassCount = PassCount;
newNode->Shadow = Shadow;
newNode->Shadow->grab();
newNode->JointChildSceneNodes = JointChildSceneNodes;
newNode->PretransitingSave = PretransitingSave;
newNode->RenderFromIdentity = RenderFromIdentity;

View File

@ -84,11 +84,6 @@ namespace scene
//! 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);
@ -199,8 +194,6 @@ namespace scene
IAnimationEndCallBack* LoopCallBack;
s32 PassCount;
IShadowVolumeSceneNode* Shadow;
core::array<IBoneSceneNode* > JointChildSceneNodes;
core::array<core::matrix4> PretransitingSave;
};

View File

@ -8,7 +8,6 @@
#include "S3DVertex.h"
#include "SMeshBuffer.h"
#include "os.h"
#include "CShadowVolumeSceneNode.h"
namespace irr
{
@ -33,7 +32,7 @@ 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)
Mesh(0), Size(size)
{
#ifdef _DEBUG
setDebugName("CCubeSceneNode");
@ -45,8 +44,6 @@ CCubeSceneNode::CCubeSceneNode(f32 size, ISceneNode* parent, ISceneManager* mgr,
CCubeSceneNode::~CCubeSceneNode()
{
if (Shadow)
Shadow->drop();
if (Mesh)
Mesh->drop();
}
@ -66,9 +63,6 @@ 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();
@ -132,35 +126,10 @@ const core::aabbox3d<f32>& CCubeSceneNode::getBoundingBox() const
//! 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)
@ -220,8 +189,6 @@ ISceneNode* CCubeSceneNode::clone(ISceneNode* newParent, ISceneManager* newManag
nb->cloneMembers(this, newManager);
nb->getMaterial(0) = getMaterial(0);
nb->Shadow = Shadow;
nb->Shadow->grab();
if ( newParent )
nb->drop();

View File

@ -45,11 +45,6 @@ namespace scene
//! 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;
@ -82,7 +77,6 @@ namespace scene
void setSize();
IMesh* Mesh;
IShadowVolumeSceneNode* Shadow;
f32 Size;
};

View File

@ -1,712 +0,0 @@
// 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
/*
Based on Code from Copyright (c) 2003 Randy Reddig
Based on code from Nvidia's DDS example:
http://www.nvidia.com/object/dxtc_decompression_code.html
mainly c to cpp
*/
#include "CImageLoaderDDS.h"
#ifdef _IRR_COMPILE_WITH_DDS_LOADER_
#include "IReadFile.h"
#include "os.h"
#include "CColorConverter.h"
#include "CImage.h"
#include "irrString.h"
namespace irr
{
namespace video
{
namespace
{
/*!
DDSDecodePixelFormat()
determines which pixel format the dds texture is in
*/
void DDSDecodePixelFormat( ddsBuffer *dds, eDDSPixelFormat *pf )
{
/* dummy check */
if( dds == NULL || pf == NULL )
return;
/* extract fourCC */
const u32 fourCC = dds->pixelFormat.fourCC;
/* test it */
if( fourCC == 0 )
*pf = DDS_PF_ARGB8888;
else if( fourCC == *((u32*) "DXT1") )
*pf = DDS_PF_DXT1;
else if( fourCC == *((u32*) "DXT2") )
*pf = DDS_PF_DXT2;
else if( fourCC == *((u32*) "DXT3") )
*pf = DDS_PF_DXT3;
else if( fourCC == *((u32*) "DXT4") )
*pf = DDS_PF_DXT4;
else if( fourCC == *((u32*) "DXT5") )
*pf = DDS_PF_DXT5;
else
*pf = DDS_PF_UNKNOWN;
}
/*!
DDSGetInfo()
extracts relevant info from a dds texture, returns 0 on success
*/
s32 DDSGetInfo( ddsBuffer *dds, s32 *width, s32 *height, eDDSPixelFormat *pf )
{
/* dummy test */
if( dds == NULL )
return -1;
/* test dds header */
if( *((s32*) dds->magic) != *((s32*) "DDS ") )
return -1;
if( DDSLittleLong( dds->size ) != 124 )
return -1;
/* extract width and height */
if( width != NULL )
*width = DDSLittleLong( dds->width );
if( height != NULL )
*height = DDSLittleLong( dds->height );
/* get pixel format */
DDSDecodePixelFormat( dds, pf );
/* return ok */
return 0;
}
/*!
DDSGetColorBlockColors()
extracts colors from a dds color block
*/
void DDSGetColorBlockColors( ddsColorBlock *block, ddsColor colors[ 4 ] )
{
u16 word;
/* color 0 */
word = DDSLittleShort( block->colors[ 0 ] );
colors[ 0 ].a = 0xff;
/* extract rgb bits */
colors[ 0 ].b = (u8) word;
colors[ 0 ].b <<= 3;
colors[ 0 ].b |= (colors[ 0 ].b >> 5);
word >>= 5;
colors[ 0 ].g = (u8) word;
colors[ 0 ].g <<= 2;
colors[ 0 ].g |= (colors[ 0 ].g >> 5);
word >>= 6;
colors[ 0 ].r = (u8) word;
colors[ 0 ].r <<= 3;
colors[ 0 ].r |= (colors[ 0 ].r >> 5);
/* same for color 1 */
word = DDSLittleShort( block->colors[ 1 ] );
colors[ 1 ].a = 0xff;
/* extract rgb bits */
colors[ 1 ].b = (u8) word;
colors[ 1 ].b <<= 3;
colors[ 1 ].b |= (colors[ 1 ].b >> 5);
word >>= 5;
colors[ 1 ].g = (u8) word;
colors[ 1 ].g <<= 2;
colors[ 1 ].g |= (colors[ 1 ].g >> 5);
word >>= 6;
colors[ 1 ].r = (u8) word;
colors[ 1 ].r <<= 3;
colors[ 1 ].r |= (colors[ 1 ].r >> 5);
/* use this for all but the super-freak math method */
if( block->colors[ 0 ] > block->colors[ 1 ] )
{
/* four-color block: derive the other two colors.
00 = color 0, 01 = color 1, 10 = color 2, 11 = color 3
these two bit codes correspond to the 2-bit fields
stored in the 64-bit block. */
word = ((u16) colors[ 0 ].r * 2 + (u16) colors[ 1 ].r ) / 3;
/* no +1 for rounding */
/* as bits have been shifted to 888 */
colors[ 2 ].r = (u8) word;
word = ((u16) colors[ 0 ].g * 2 + (u16) colors[ 1 ].g) / 3;
colors[ 2 ].g = (u8) word;
word = ((u16) colors[ 0 ].b * 2 + (u16) colors[ 1 ].b) / 3;
colors[ 2 ].b = (u8) word;
colors[ 2 ].a = 0xff;
word = ((u16) colors[ 0 ].r + (u16) colors[ 1 ].r * 2) / 3;
colors[ 3 ].r = (u8) word;
word = ((u16) colors[ 0 ].g + (u16) colors[ 1 ].g * 2) / 3;
colors[ 3 ].g = (u8) word;
word = ((u16) colors[ 0 ].b + (u16) colors[ 1 ].b * 2) / 3;
colors[ 3 ].b = (u8) word;
colors[ 3 ].a = 0xff;
}
else
{
/* three-color block: derive the other color.
00 = color 0, 01 = color 1, 10 = color 2,
11 = transparent.
These two bit codes correspond to the 2-bit fields
stored in the 64-bit block */
word = ((u16) colors[ 0 ].r + (u16) colors[ 1 ].r) / 2;
colors[ 2 ].r = (u8) word;
word = ((u16) colors[ 0 ].g + (u16) colors[ 1 ].g) / 2;
colors[ 2 ].g = (u8) word;
word = ((u16) colors[ 0 ].b + (u16) colors[ 1 ].b) / 2;
colors[ 2 ].b = (u8) word;
colors[ 2 ].a = 0xff;
/* random color to indicate alpha */
colors[ 3 ].r = 0x00;
colors[ 3 ].g = 0xff;
colors[ 3 ].b = 0xff;
colors[ 3 ].a = 0x00;
}
}
/*
DDSDecodeColorBlock()
decodes a dds color block
fixme: make endian-safe
*/
void DDSDecodeColorBlock( u32 *pixel, ddsColorBlock *block, s32 width, u32 colors[ 4 ] )
{
s32 r, n;
u32 bits;
u32 masks[] = { 3, 12, 3 << 4, 3 << 6 }; /* bit masks = 00000011, 00001100, 00110000, 11000000 */
s32 shift[] = { 0, 2, 4, 6 };
/* r steps through lines in y */
for( r = 0; r < 4; r++, pixel += (width - 4) ) /* no width * 4 as u32 ptr inc will * 4 */
{
/* width * 4 bytes per pixel per line, each j dxtc row is 4 lines of pixels */
/* n steps through pixels */
for( n = 0; n < 4; n++ )
{
bits = block->row[ r ] & masks[ n ];
bits >>= shift[ n ];
switch( bits )
{
case 0:
*pixel = colors[ 0 ];
pixel++;
break;
case 1:
*pixel = colors[ 1 ];
pixel++;
break;
case 2:
*pixel = colors[ 2 ];
pixel++;
break;
case 3:
*pixel = colors[ 3 ];
pixel++;
break;
default:
/* invalid */
pixel++;
break;
}
}
}
}
/*
DDSDecodeAlphaExplicit()
decodes a dds explicit alpha block
*/
void DDSDecodeAlphaExplicit( u32 *pixel, ddsAlphaBlockExplicit *alphaBlock, s32 width, u32 alphaZero )
{
s32 row, pix;
u16 word;
ddsColor color;
/* clear color */
color.r = 0;
color.g = 0;
color.b = 0;
/* walk rows */
for( row = 0; row < 4; row++, pixel += (width - 4) )
{
word = DDSLittleShort( alphaBlock->row[ row ] );
/* walk pixels */
for( pix = 0; pix < 4; pix++ )
{
/* zero the alpha bits of image pixel */
*pixel &= alphaZero;
color.a = word & 0x000F;
color.a = color.a | (color.a << 4);
*pixel |= *((u32*) &color);
word >>= 4; /* move next bits to lowest 4 */
pixel++; /* move to next pixel in the row */
}
}
}
/*
DDSDecodeAlpha3BitLinear()
decodes interpolated alpha block
*/
void DDSDecodeAlpha3BitLinear( u32 *pixel, ddsAlphaBlock3BitLinear *alphaBlock, s32 width, u32 alphaZero )
{
s32 row, pix;
u32 stuff;
u8 bits[ 4 ][ 4 ];
u16 alphas[ 8 ];
ddsColor aColors[ 4 ][ 4 ];
/* get initial alphas */
alphas[ 0 ] = alphaBlock->alpha0;
alphas[ 1 ] = alphaBlock->alpha1;
/* 8-alpha block */
if( alphas[ 0 ] > alphas[ 1 ] )
{
/* 000 = alpha_0, 001 = alpha_1, others are interpolated */
alphas[ 2 ] = ( 6 * alphas[ 0 ] + alphas[ 1 ]) / 7; /* bit code 010 */
alphas[ 3 ] = ( 5 * alphas[ 0 ] + 2 * alphas[ 1 ]) / 7; /* bit code 011 */
alphas[ 4 ] = ( 4 * alphas[ 0 ] + 3 * alphas[ 1 ]) / 7; /* bit code 100 */
alphas[ 5 ] = ( 3 * alphas[ 0 ] + 4 * alphas[ 1 ]) / 7; /* bit code 101 */
alphas[ 6 ] = ( 2 * alphas[ 0 ] + 5 * alphas[ 1 ]) / 7; /* bit code 110 */
alphas[ 7 ] = ( alphas[ 0 ] + 6 * alphas[ 1 ]) / 7; /* bit code 111 */
}
/* 6-alpha block */
else
{
/* 000 = alpha_0, 001 = alpha_1, others are interpolated */
alphas[ 2 ] = (4 * alphas[ 0 ] + alphas[ 1 ]) / 5; /* bit code 010 */
alphas[ 3 ] = (3 * alphas[ 0 ] + 2 * alphas[ 1 ]) / 5; /* bit code 011 */
alphas[ 4 ] = (2 * alphas[ 0 ] + 3 * alphas[ 1 ]) / 5; /* bit code 100 */
alphas[ 5 ] = ( alphas[ 0 ] + 4 * alphas[ 1 ]) / 5; /* bit code 101 */
alphas[ 6 ] = 0; /* bit code 110 */
alphas[ 7 ] = 255; /* bit code 111 */
}
/* decode 3-bit fields into array of 16 bytes with same value */
/* first two rows of 4 pixels each */
stuff = *((u32*) &(alphaBlock->stuff[ 0 ]));
bits[ 0 ][ 0 ] = (u8) (stuff & 0x00000007);
stuff >>= 3;
bits[ 0 ][ 1 ] = (u8) (stuff & 0x00000007);
stuff >>= 3;
bits[ 0 ][ 2 ] = (u8) (stuff & 0x00000007);
stuff >>= 3;
bits[ 0 ][ 3 ] = (u8) (stuff & 0x00000007);
stuff >>= 3;
bits[ 1 ][ 0 ] = (u8) (stuff & 0x00000007);
stuff >>= 3;
bits[ 1 ][ 1 ] = (u8) (stuff & 0x00000007);
stuff >>= 3;
bits[ 1 ][ 2 ] = (u8) (stuff & 0x00000007);
stuff >>= 3;
bits[ 1 ][ 3 ] = (u8) (stuff & 0x00000007);
/* last two rows */
stuff = *((u32*) &(alphaBlock->stuff[ 3 ])); /* last 3 bytes */
bits[ 2 ][ 0 ] = (u8) (stuff & 0x00000007);
stuff >>= 3;
bits[ 2 ][ 1 ] = (u8) (stuff & 0x00000007);
stuff >>= 3;
bits[ 2 ][ 2 ] = (u8) (stuff & 0x00000007);
stuff >>= 3;
bits[ 2 ][ 3 ] = (u8) (stuff & 0x00000007);
stuff >>= 3;
bits[ 3 ][ 0 ] = (u8) (stuff & 0x00000007);
stuff >>= 3;
bits[ 3 ][ 1 ] = (u8) (stuff & 0x00000007);
stuff >>= 3;
bits[ 3 ][ 2 ] = (u8) (stuff & 0x00000007);
stuff >>= 3;
bits[ 3 ][ 3 ] = (u8) (stuff & 0x00000007);
/* decode the codes into alpha values */
for( row = 0; row < 4; row++ )
{
for( pix=0; pix < 4; pix++ )
{
aColors[ row ][ pix ].r = 0;
aColors[ row ][ pix ].g = 0;
aColors[ row ][ pix ].b = 0;
aColors[ row ][ pix ].a = (u8) alphas[ bits[ row ][ pix ] ];
}
}
/* write out alpha values to the image bits */
for( row = 0; row < 4; row++, pixel += width-4 )
{
for( pix = 0; pix < 4; pix++ )
{
/* zero the alpha bits of image pixel */
*pixel &= alphaZero;
/* or the bits into the prev. nulled alpha */
*pixel |= *((u32*) &(aColors[ row ][ pix ]));
pixel++;
}
}
}
/*
DDSDecompressDXT1()
decompresses a dxt1 format texture
*/
s32 DDSDecompressDXT1( ddsBuffer *dds, s32 width, s32 height, u8 *pixels )
{
s32 x, y, xBlocks, yBlocks;
u32 *pixel;
ddsColorBlock *block;
ddsColor colors[ 4 ];
/* setup */
xBlocks = width / 4;
yBlocks = height / 4;
/* walk y */
for( y = 0; y < yBlocks; y++ )
{
/* 8 bytes per block */
block = (ddsColorBlock*) (dds->data + y * xBlocks * 8);
/* walk x */
for( x = 0; x < xBlocks; x++, block++ )
{
DDSGetColorBlockColors( block, colors );
pixel = (u32*) (pixels + x * 16 + (y * 4) * width * 4);
DDSDecodeColorBlock( pixel, block, width, (u32*) colors );
}
}
/* return ok */
return 0;
}
/*
DDSDecompressDXT3()
decompresses a dxt3 format texture
*/
s32 DDSDecompressDXT3( ddsBuffer *dds, s32 width, s32 height, u8 *pixels )
{
s32 x, y, xBlocks, yBlocks;
u32 *pixel, alphaZero;
ddsColorBlock *block;
ddsAlphaBlockExplicit *alphaBlock;
ddsColor colors[ 4 ];
/* setup */
xBlocks = width / 4;
yBlocks = height / 4;
/* create zero alpha */
colors[ 0 ].a = 0;
colors[ 0 ].r = 0xFF;
colors[ 0 ].g = 0xFF;
colors[ 0 ].b = 0xFF;
alphaZero = *((u32*) &colors[ 0 ]);
/* walk y */
for( y = 0; y < yBlocks; y++ )
{
/* 8 bytes per block, 1 block for alpha, 1 block for color */
block = (ddsColorBlock*) (dds->data + y * xBlocks * 16);
/* walk x */
for( x = 0; x < xBlocks; x++, block++ )
{
/* get alpha block */
alphaBlock = (ddsAlphaBlockExplicit*) block;
/* get color block */
block++;
DDSGetColorBlockColors( block, colors );
/* decode color block */
pixel = (u32*) (pixels + x * 16 + (y * 4) * width * 4);
DDSDecodeColorBlock( pixel, block, width, (u32*) colors );
/* overwrite alpha bits with alpha block */
DDSDecodeAlphaExplicit( pixel, alphaBlock, width, alphaZero );
}
}
/* return ok */
return 0;
}
/*
DDSDecompressDXT5()
decompresses a dxt5 format texture
*/
s32 DDSDecompressDXT5( ddsBuffer *dds, s32 width, s32 height, u8 *pixels )
{
s32 x, y, xBlocks, yBlocks;
u32 *pixel, alphaZero;
ddsColorBlock *block;
ddsAlphaBlock3BitLinear *alphaBlock;
ddsColor colors[ 4 ];
/* setup */
xBlocks = width / 4;
yBlocks = height / 4;
/* create zero alpha */
colors[ 0 ].a = 0;
colors[ 0 ].r = 0xFF;
colors[ 0 ].g = 0xFF;
colors[ 0 ].b = 0xFF;
alphaZero = *((u32*) &colors[ 0 ]);
/* walk y */
for( y = 0; y < yBlocks; y++ )
{
/* 8 bytes per block, 1 block for alpha, 1 block for color */
block = (ddsColorBlock*) (dds->data + y * xBlocks * 16);
/* walk x */
for( x = 0; x < xBlocks; x++, block++ )
{
/* get alpha block */
alphaBlock = (ddsAlphaBlock3BitLinear*) block;
/* get color block */
block++;
DDSGetColorBlockColors( block, colors );
/* decode color block */
pixel = (u32*) (pixels + x * 16 + (y * 4) * width * 4);
DDSDecodeColorBlock( pixel, block, width, (u32*) colors );
/* overwrite alpha bits with alpha block */
DDSDecodeAlpha3BitLinear( pixel, alphaBlock, width, alphaZero );
}
}
/* return ok */
return 0;
}
/*
DDSDecompressDXT2()
decompresses a dxt2 format texture (fixme: un-premultiply alpha)
*/
s32 DDSDecompressDXT2( ddsBuffer *dds, s32 width, s32 height, u8 *pixels )
{
/* decompress dxt3 first */
const s32 r = DDSDecompressDXT3( dds, width, height, pixels );
/* return to sender */
return r;
}
/*
DDSDecompressDXT4()
decompresses a dxt4 format texture (fixme: un-premultiply alpha)
*/
s32 DDSDecompressDXT4( ddsBuffer *dds, s32 width, s32 height, u8 *pixels )
{
/* decompress dxt5 first */
const s32 r = DDSDecompressDXT5( dds, width, height, pixels );
/* return to sender */
return r;
}
/*
DDSDecompressARGB8888()
decompresses an argb 8888 format texture
*/
s32 DDSDecompressARGB8888( ddsBuffer *dds, s32 width, s32 height, u8 *pixels )
{
/* setup */
u8* in = dds->data;
u8* out = pixels;
/* walk y */
for(s32 y = 0; y < height; y++)
{
/* walk x */
for(s32 x = 0; x < width; x++)
{
*out++ = *in++;
*out++ = *in++;
*out++ = *in++;
*out++ = *in++;
}
}
/* return ok */
return 0;
}
/*
DDSDecompress()
decompresses a dds texture into an rgba image buffer, returns 0 on success
*/
s32 DDSDecompress( ddsBuffer *dds, u8 *pixels )
{
s32 width, height;
eDDSPixelFormat pf;
/* get dds info */
s32 r = DDSGetInfo( dds, &width, &height, &pf );
if ( r )
return r;
/* decompress */
switch( pf )
{
case DDS_PF_ARGB8888:
/* fixme: support other [a]rgb formats */
r = DDSDecompressARGB8888( dds, width, height, pixels );
break;
case DDS_PF_DXT1:
r = DDSDecompressDXT1( dds, width, height, pixels );
break;
case DDS_PF_DXT2:
r = DDSDecompressDXT2( dds, width, height, pixels );
break;
case DDS_PF_DXT3:
r = DDSDecompressDXT3( dds, width, height, pixels );
break;
case DDS_PF_DXT4:
r = DDSDecompressDXT4( dds, width, height, pixels );
break;
case DDS_PF_DXT5:
r = DDSDecompressDXT5( dds, width, height, pixels );
break;
default:
case DDS_PF_UNKNOWN:
memset( pixels, 0xFF, width * height * 4 );
r = -1;
break;
}
/* return to sender */
return r;
}
} // end anonymous namespace
//! returns true if the file maybe is able to be loaded by this class
//! based on the file extension (e.g. ".tga")
bool CImageLoaderDDS::isALoadableFileExtension(const io::path& filename) const
{
return core::hasFileExtension ( filename, "dds" );
}
//! returns true if the file maybe is able to be loaded by this class
bool CImageLoaderDDS::isALoadableFileFormat(io::IReadFile* file) const
{
if (!file)
return false;
ddsBuffer header;
file->read(&header, sizeof(header));
s32 width, height;
eDDSPixelFormat pixelFormat;
return (0 == DDSGetInfo( &header, &width, &height, &pixelFormat));
}
//! creates a surface from the file
IImage* CImageLoaderDDS::loadImage(io::IReadFile* file) const
{
u8 *memFile = new u8 [ file->getSize() ];
file->read ( memFile, file->getSize() );
ddsBuffer *header = (ddsBuffer*) memFile;
IImage* image = 0;
s32 width, height;
eDDSPixelFormat pixelFormat;
if ( 0 == DDSGetInfo( header, &width, &height, &pixelFormat) )
{
image = new CImage(ECF_A8R8G8B8, core::dimension2d<u32>(width, height));
if ( DDSDecompress( header, (u8*) image->lock() ) == -1)
{
image->unlock();
image->drop();
image = 0;
}
}
delete [] memFile;
if ( image )
image->unlock();
return image;
}
//! creates a loader which is able to load dds images
IImageLoader* createImageLoaderDDS()
{
return new CImageLoaderDDS();
}
} // end namespace video
} // end namespace irr
#endif

View File

@ -1,296 +0,0 @@
// 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_IMAGE_LOADER_DDS_H_INCLUDED__
#define __C_IMAGE_LOADER_DDS_H_INCLUDED__
#include "IrrCompileConfig.h"
#if defined(_IRR_COMPILE_WITH_DDS_LOADER_)
#include "IImageLoader.h"
namespace irr
{
namespace video
{
/* dependencies */
/* dds definition */
enum eDDSPixelFormat
{
DDS_PF_ARGB8888,
DDS_PF_DXT1,
DDS_PF_DXT2,
DDS_PF_DXT3,
DDS_PF_DXT4,
DDS_PF_DXT5,
DDS_PF_UNKNOWN
};
/* 16bpp stuff */
#define DDS_LOW_5 0x001F;
#define DDS_MID_6 0x07E0;
#define DDS_HIGH_5 0xF800;
#define DDS_MID_555 0x03E0;
#define DDS_HI_555 0x7C00;
// byte-align structures
#include "irrpack.h"
/* structures */
struct ddsColorKey
{
u32 colorSpaceLowValue;
u32 colorSpaceHighValue;
} PACK_STRUCT;
struct ddsCaps
{
u32 caps1;
u32 caps2;
u32 caps3;
u32 caps4;
} PACK_STRUCT;
struct ddsMultiSampleCaps
{
u16 flipMSTypes;
u16 bltMSTypes;
} PACK_STRUCT;
struct ddsPixelFormat
{
u32 size;
u32 flags;
u32 fourCC;
union
{
u32 rgbBitCount;
u32 yuvBitCount;
u32 zBufferBitDepth;
u32 alphaBitDepth;
u32 luminanceBitCount;
u32 bumpBitCount;
u32 privateFormatBitCount;
};
union
{
u32 rBitMask;
u32 yBitMask;
u32 stencilBitDepth;
u32 luminanceBitMask;
u32 bumpDuBitMask;
u32 operations;
};
union
{
u32 gBitMask;
u32 uBitMask;
u32 zBitMask;
u32 bumpDvBitMask;
ddsMultiSampleCaps multiSampleCaps;
};
union
{
u32 bBitMask;
u32 vBitMask;
u32 stencilBitMask;
u32 bumpLuminanceBitMask;
};
union
{
u32 rgbAlphaBitMask;
u32 yuvAlphaBitMask;
u32 luminanceAlphaBitMask;
u32 rgbZBitMask;
u32 yuvZBitMask;
};
} PACK_STRUCT;
struct ddsBuffer
{
/* magic: 'dds ' */
c8 magic[ 4 ];
/* directdraw surface */
u32 size;
u32 flags;
u32 height;
u32 width;
union
{
s32 pitch;
u32 linearSize;
};
u32 backBufferCount;
union
{
u32 mipMapCount;
u32 refreshRate;
u32 srcVBHandle;
};
u32 alphaBitDepth;
u32 reserved;
void *surface;
union
{
ddsColorKey ckDestOverlay;
u32 emptyFaceColor;
};
ddsColorKey ckDestBlt;
ddsColorKey ckSrcOverlay;
ddsColorKey ckSrcBlt;
union
{
ddsPixelFormat pixelFormat;
u32 fvf;
};
ddsCaps caps;
u32 textureStage;
/* data (Varying size) */
u8 data[ 4 ];
} PACK_STRUCT;
struct ddsColorBlock
{
u16 colors[ 2 ];
u8 row[ 4 ];
} PACK_STRUCT;
struct ddsAlphaBlockExplicit
{
u16 row[ 4 ];
} PACK_STRUCT;
struct ddsAlphaBlock3BitLinear
{
u8 alpha0;
u8 alpha1;
u8 stuff[ 6 ];
} PACK_STRUCT;
struct ddsColor
{
u8 r, g, b, a;
} PACK_STRUCT;
// Default alignment
#include "irrunpack.h"
/* endian tomfoolery */
typedef union
{
f32 f;
c8 c[ 4 ];
}
floatSwapUnion;
#ifndef __BIG_ENDIAN__
#ifdef _SGI_SOURCE
#define __BIG_ENDIAN__
#endif
#endif
#ifdef __BIG_ENDIAN__
s32 DDSBigLong( s32 src ) { return src; }
s16 DDSBigShort( s16 src ) { return src; }
f32 DDSBigFloat( f32 src ) { return src; }
s32 DDSLittleLong( s32 src )
{
return ((src & 0xFF000000) >> 24) |
((src & 0x00FF0000) >> 8) |
((src & 0x0000FF00) << 8) |
((src & 0x000000FF) << 24);
}
s16 DDSLittleShort( s16 src )
{
return ((src & 0xFF00) >> 8) |
((src & 0x00FF) << 8);
}
f32 DDSLittleFloat( f32 src )
{
floatSwapUnion in,out;
in.f = src;
out.c[ 0 ] = in.c[ 3 ];
out.c[ 1 ] = in.c[ 2 ];
out.c[ 2 ] = in.c[ 1 ];
out.c[ 3 ] = in.c[ 0 ];
return out.f;
}
#else /*__BIG_ENDIAN__*/
s32 DDSLittleLong( s32 src ) { return src; }
s16 DDSLittleShort( s16 src ) { return src; }
f32 DDSLittleFloat( f32 src ) { return src; }
s32 DDSBigLong( s32 src )
{
return ((src & 0xFF000000) >> 24) |
((src & 0x00FF0000) >> 8) |
((src & 0x0000FF00) << 8) |
((src & 0x000000FF) << 24);
}
s16 DDSBigShort( s16 src )
{
return ((src & 0xFF00) >> 8) |
((src & 0x00FF) << 8);
}
f32 DDSBigFloat( f32 src )
{
floatSwapUnion in,out;
in.f = src;
out.c[ 0 ] = in.c[ 3 ];
out.c[ 1 ] = in.c[ 2 ];
out.c[ 2 ] = in.c[ 1 ];
out.c[ 3 ] = in.c[ 0 ];
return out.f;
}
#endif /*__BIG_ENDIAN__*/
/*!
Surface Loader for DDS images
*/
class CImageLoaderDDS : public IImageLoader
{
public:
//! returns true if the file maybe is able to be loaded by this class
//! based on the file extension (e.g. ".tga")
virtual bool isALoadableFileExtension(const io::path& filename) const;
//! returns true if the file maybe is able to be loaded by this class
virtual bool isALoadableFileFormat(io::IReadFile* file) const;
//! creates a surface from the file
virtual IImage* loadImage(io::IReadFile* file) const;
};
} // end namespace video
} // end namespace irr
#endif // compiled with DDS loader
#endif

View File

@ -1,231 +0,0 @@
// 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 "CImageLoaderPCX.h"
#ifdef _IRR_COMPILE_WITH_PCX_LOADER_
#include "IReadFile.h"
#include "SColor.h"
#include "CColorConverter.h"
#include "CImage.h"
#include "os.h"
#include "irrString.h"
namespace irr
{
namespace video
{
//! constructor
CImageLoaderPCX::CImageLoaderPCX()
{
#ifdef _DEBUG
setDebugName("CImageLoaderPCX");
#endif
}
//! returns true if the file maybe is able to be loaded by this class
//! based on the file extension (e.g. ".tga")
bool CImageLoaderPCX::isALoadableFileExtension(const io::path& filename) const
{
return core::hasFileExtension ( filename, "pcx" );
}
//! returns true if the file maybe is able to be loaded by this class
bool CImageLoaderPCX::isALoadableFileFormat(io::IReadFile* file) const
{
u8 headerID;
file->read(&headerID, sizeof(headerID));
return headerID == 0x0a;
}
//! creates a image from the file
IImage* CImageLoaderPCX::loadImage(io::IReadFile* file) const
{
SPCXHeader header;
s32* paletteData = 0;
file->read(&header, sizeof(header));
#ifdef __BIG_ENDIAN__
header.XMin = os::Byteswap::byteswap(header.XMin);
header.YMin = os::Byteswap::byteswap(header.YMin);
header.XMax = os::Byteswap::byteswap(header.XMax);
header.YMax = os::Byteswap::byteswap(header.YMax);
header.HorizDPI = os::Byteswap::byteswap(header.HorizDPI);
header.VertDPI = os::Byteswap::byteswap(header.VertDPI);
header.BytesPerLine = os::Byteswap::byteswap(header.BytesPerLine);
header.PaletteType = os::Byteswap::byteswap(header.PaletteType);
header.HScrSize = os::Byteswap::byteswap(header.HScrSize);
header.VScrSize = os::Byteswap::byteswap(header.VScrSize);
#endif
//! return if the header is wrong
if (header.Manufacturer != 0x0a && header.Encoding != 0x01)
return 0;
// return if this isn't a supported type
if ((header.BitsPerPixel != 8) && (header.BitsPerPixel != 4) && (header.BitsPerPixel != 1))
{
os::Printer::log("Unsupported bits per pixel in PCX file.",
file->getFileName(), irr::ELL_WARNING);
return 0;
}
// read palette
if( (header.BitsPerPixel == 8) && (header.Planes == 1) )
{
// the palette indicator (usually a 0x0c is found infront of the actual palette data)
// is ignored because some exporters seem to forget to write it. This would result in
// no image loaded before, now only wrong colors will be set.
const long pos = file->getPos();
file->seek( file->getSize()-256*3, false );
u8 *tempPalette = new u8[768];
paletteData = new s32[256];
file->read( tempPalette, 768 );
for( s32 i=0; i<256; i++ )
{
paletteData[i] = (0xff000000 |
(tempPalette[i*3+0] << 16) |
(tempPalette[i*3+1] << 8) |
(tempPalette[i*3+2]));
}
delete [] tempPalette;
file->seek(pos);
}
else if( header.BitsPerPixel == 4 )
{
paletteData = new s32[16];
for( s32 i=0; i<16; i++ )
{
paletteData[i] = (0xff000000 |
(header.Palette[i*3+0] << 16) |
(header.Palette[i*3+1] << 8) |
(header.Palette[i*3+2]));
}
}
// read image data
const s32 width = header.XMax - header.XMin + 1;
const s32 height = header.YMax - header.YMin + 1;
const s32 imagebytes = header.BytesPerLine * header.Planes * header.BitsPerPixel * height / 8;
u8* PCXData = new u8[imagebytes];
u8 cnt, value;
s32 lineoffset=0, linestart=0, nextmode=1;
for(s32 offset = 0; offset < imagebytes; offset += cnt)
{
file->read(&cnt, 1);
if( !((cnt & 0xc0) == 0xc0) )
{
value = cnt;
cnt = 1;
}
else
{
cnt &= 0x3f;
file->read(&value, 1);
}
if (header.Planes==1)
memset(PCXData+offset, value, cnt);
else
{
for (u32 i=0; i<cnt; ++i)
{
PCXData[linestart+lineoffset]=value;
lineoffset += 3;
if (lineoffset>=3*header.BytesPerLine)
{
lineoffset=nextmode;
if (++nextmode==3)
nextmode=0;
if (lineoffset==0)
linestart += 3*header.BytesPerLine;
}
}
}
}
// create image
video::IImage* image = 0;
s32 pad = (header.BytesPerLine - width * header.BitsPerPixel / 8) * header.Planes;
if (pad < 0)
pad = -pad;
if (header.BitsPerPixel==8)
{
switch(header.Planes) // TODO: Other formats
{
case 1:
image = new CImage(ECF_A1R5G5B5, core::dimension2d<u32>(width, height));
if (image)
CColorConverter::convert8BitTo16Bit(PCXData, (s16*)image->lock(), width, height, paletteData, pad);
break;
case 3:
image = new CImage(ECF_R8G8B8, core::dimension2d<u32>(width, height));
if (image)
CColorConverter::convert24BitTo24Bit(PCXData, (u8*)image->lock(), width, height, pad);
break;
}
}
else if (header.BitsPerPixel==4)
{
if (header.Planes==1)
{
image = new CImage(ECF_A1R5G5B5, core::dimension2d<u32>(width, height));
if (image)
CColorConverter::convert4BitTo16Bit(PCXData, (s16*)image->lock(), width, height, paletteData, pad);
}
}
else if (header.BitsPerPixel==1)
{
if (header.Planes==4)
{
image = new CImage(ECF_A1R5G5B5, core::dimension2d<u32>(width, height));
if (image)
CColorConverter::convert4BitTo16Bit(PCXData, (s16*)image->lock(), width, height, paletteData, pad);
}
else if (header.Planes==1)
{
image = new CImage(ECF_A1R5G5B5, core::dimension2d<u32>(width, height));
if (image)
CColorConverter::convert1BitTo16Bit(PCXData, (s16*)image->lock(), width, height, pad);
}
}
if (image)
image->unlock();
// clean up
delete [] paletteData;
delete [] PCXData;
return image;
}
//! creates a loader which is able to load pcx images
IImageLoader* createImageLoaderPCX()
{
return new CImageLoaderPCX();
}
} // end namespace video
} // end namespace irr
#endif

View File

@ -1,82 +0,0 @@
// 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_IMAGE_LOADER_PCX_H_INCLUDED__
#define __C_IMAGE_LOADER_PCX_H_INCLUDED__
#include "IrrCompileConfig.h"
#include "IImageLoader.h"
namespace irr
{
namespace video
{
#if defined(_IRR_COMPILE_WITH_PCX_LOADER_) || defined(_IRR_COMPILE_WITH_PCX_WRITER_)
// byte-align structures
#include "irrpack.h"
struct SPCXHeader
{
u8 Manufacturer;
u8 Version;
u8 Encoding;
u8 BitsPerPixel;
u16 XMin;
u16 YMin;
u16 XMax;
u16 YMax;
u16 HorizDPI;
u16 VertDPI;
u8 Palette[48];
u8 Reserved;
u8 Planes;
u16 BytesPerLine;
u16 PaletteType;
u16 HScrSize;
u16 VScrSize;
u8 Filler[54];
} PACK_STRUCT;
// Default alignment
#include "irrunpack.h"
#endif // compile with loader or writer
#ifdef _IRR_COMPILE_WITH_PCX_LOADER_
/*!
Image Loader for Windows PCX bitmaps.
This loader was written and sent in by Dean P. Macri. I modified
only some small bits of it.
*/
class CImageLoaderPCX : public IImageLoader
{
public:
//! constructor
CImageLoaderPCX();
//! returns true if the file maybe is able to be loaded by this class
//! based on the file extension (e.g. ".tga")
virtual bool isALoadableFileExtension(const io::path& filename) const;
//! returns true if the file maybe is able to be loaded by this class
virtual bool isALoadableFileFormat(io::IReadFile* file) const;
//! creates a surface from the file
virtual IImage* loadImage(io::IReadFile* file) const;
};
#endif // compile with loader
} // end namespace video
} // end namespace irr
#endif

View File

@ -1,277 +0,0 @@
// Copyright (C) 2007-2012 Christian Stehno
// This file is part of the "Irrlicht Engine".
// For conditions of distribution and use, see copyright notice in irrlicht.h
#include "CImageLoaderPPM.h"
#ifdef _IRR_COMPILE_WITH_PPM_LOADER_
#include "IReadFile.h"
#include "CColorConverter.h"
#include "CImage.h"
#include "os.h"
#include "fast_atof.h"
#include "coreutil.h"
namespace irr
{
namespace video
{
//! constructor
CImageLoaderPPM::CImageLoaderPPM()
{
#ifdef _DEBUG
setDebugName("CImageLoaderPPM");
#endif
}
//! returns true if the file maybe is able to be loaded by this class
//! based on the file extension (e.g. ".tga")
bool CImageLoaderPPM::isALoadableFileExtension(const io::path& filename) const
{
return core::hasFileExtension ( filename, "ppm", "pgm", "pbm" );
}
//! returns true if the file maybe is able to be loaded by this class
bool CImageLoaderPPM::isALoadableFileFormat(io::IReadFile* file) const
{
c8 id[2]={0};
file->read(&id, 2);
return (id[0]=='P' && id[1]>'0' && id[1]<'7');
}
//! creates a surface from the file
IImage* CImageLoaderPPM::loadImage(io::IReadFile* file) const
{
IImage* image;
if (file->getSize() < 12)
return 0;
c8 id[2];
file->read(&id, 2);
if (id[0]!='P' || id[1]<'1' || id[1]>'6')
return 0;
const u8 format = id[1] - '0';
const bool binary = format>3;
core::stringc token;
getNextToken(file, token);
const u32 width = core::strtoul10(token.c_str());
getNextToken(file, token);
const u32 height = core::strtoul10(token.c_str());
u8* data = 0;
const u32 size = width*height;
if (format==1 || format==4)
{
skipToNextToken(file); // go to start of data
const u32 bytesize = size/8+(size & 3)?1:0;
if (binary)
{
if (file->getSize()-file->getPos() < (long)bytesize)
return 0;
data = new u8[bytesize];
file->read(data, bytesize);
}
else
{
if (file->getSize()-file->getPos() < (long)(2*size)) // optimistic test
return 0;
data = new u8[bytesize];
memset(data, 0, bytesize);
u32 shift=0;
for (u32 i=0; i<size; ++i)
{
getNextToken(file, token);
if (token == "1")
data[i/8] |= (0x01 << shift);
if (++shift == 8)
shift=0;
}
}
image = new CImage(ECF_A1R5G5B5, core::dimension2d<u32>(width, height));
if (image)
CColorConverter::convert1BitTo16Bit(data, (s16*)image->lock(), width, height);
}
else
{
getNextToken(file, token);
const u32 maxDepth = core::strtoul10(token.c_str());
if (maxDepth > 255) // no double bytes yet
return 0;
skipToNextToken(file); // go to start of data
if (format==2 || format==5)
{
if (binary)
{
if (file->getSize()-file->getPos() < (long)size)
return 0;
data = new u8[size];
file->read(data, size);
image = new CImage(ECF_A8R8G8B8, core::dimension2d<u32>(width, height));
if (image)
{
u8* ptr = (u8*)image->lock();
for (u32 i=0; i<size; ++i)
{
*ptr++ = data[i];
*ptr++ = data[i];
*ptr++ = data[i];
*ptr++ = 255;
}
}
}
else
{
if (file->getSize()-file->getPos() < (long)(2*size)) // optimistic test
return 0;
image = new CImage(ECF_A8R8G8B8, core::dimension2d<u32>(width, height));
if (image)
{
u8* ptr = (u8*)image->lock();
for (u32 i=0; i<size; ++i)
{
getNextToken(file, token);
const u8 num = (u8)core::strtoul10(token.c_str());
*ptr++ = num;
*ptr++ = num;
*ptr++ = num;
*ptr++ = 255;
}
}
}
}
else
{
const u32 bytesize = 3*size;
if (binary)
{
if (file->getSize()-file->getPos() < (long)bytesize)
return 0;
data = new u8[bytesize];
file->read(data, bytesize);
image = new CImage(ECF_A8R8G8B8, core::dimension2d<u32>(width, height));
if (image)
{
u8* ptr = (u8*)image->lock();
for (u32 i=0; i<size; ++i)
{
*ptr++ = data[3*i];
*ptr++ = data[3*i+1];
*ptr++ = data[3*i+2];
*ptr++ = 255;
}
}
}
else
{
if (file->getSize()-file->getPos() < (long)(2*bytesize)) // optimistic test
return 0;
image = new CImage(ECF_A8R8G8B8, core::dimension2d<u32>(width, height));
if (image)
{
u8* ptr = (u8*)image->lock();
for (u32 i=0; i<size; ++i)
{
getNextToken(file, token);
*ptr++ = (u8)core::strtoul10(token.c_str());
getNextToken(file, token);
*ptr++ = (u8)core::strtoul10(token.c_str());
getNextToken(file, token);
*ptr++ = (u8)core::strtoul10(token.c_str());
*ptr++ = 255;
}
}
}
}
}
if (image)
image->unlock();
delete [] data;
return image;
}
//! read the next token from file
void CImageLoaderPPM::getNextToken(io::IReadFile* file, core::stringc& token) const
{
token = "";
c8 c;
while(file->getPos()<file->getSize())
{
file->read(&c, 1);
if (c=='#')
{
while (c!='\n' && c!='\r' && (file->getPos()<file->getSize()))
file->read(&c, 1);
}
else if (!core::isspace(c))
{
token.append(c);
break;
}
}
while(file->getPos()<file->getSize())
{
file->read(&c, 1);
if (c=='#')
{
while (c!='\n' && c!='\r' && (file->getPos()<file->getSize()))
file->read(&c, 1);
}
else if (!core::isspace(c))
token.append(c);
else
break;
}
}
//! skip to next token (skip whitespace)
void CImageLoaderPPM::skipToNextToken(io::IReadFile* file) const
{
c8 c;
while(file->getPos()<file->getSize())
{
file->read(&c, 1);
if (c=='#')
{
while (c!='\n' && c!='\r' && (file->getPos()<file->getSize()))
file->read(&c, 1);
}
else if (!core::isspace(c))
{
file->seek(-1, true); // put back
break;
}
}
}
//! creates a loader which is able to load windows bitmaps
IImageLoader* createImageLoaderPPM()
{
return new CImageLoaderPPM;
}
} // end namespace video
} // end namespace irr
#endif

View File

@ -1,55 +0,0 @@
// Copyright (C) 2007-2012 Christian Stehno
// This file is part of the "Irrlicht Engine".
// For conditions of distribution and use, see copyright notice in irrlicht.h
#ifndef __C_IMAGE_LOADER_PPM_H_INCLUDED__
#define __C_IMAGE_LOADER_PPM_H_INCLUDED__
#include "IrrCompileConfig.h"
#ifdef _IRR_COMPILE_WITH_PPM_LOADER_
#include "IImageLoader.h"
#include "irrString.h"
namespace irr
{
namespace video
{
/*!
Surface Loader for SUN Pixmaps
*/
class CImageLoaderPPM : public IImageLoader
{
public:
//! constructor
CImageLoaderPPM();
//! returns true if the file maybe is able to be loaded by this class
//! based on the file extension (e.g. ".tga")
virtual bool isALoadableFileExtension(const io::path& filename) const;
//! returns true if the file maybe is able to be loaded by this class
virtual bool isALoadableFileFormat(io::IReadFile* file) const;
//! creates a surface from the file
virtual IImage* loadImage(io::IReadFile* file) const;
private:
//! read the next token from file
void getNextToken(io::IReadFile* file, core::stringc& token) const;
//! skip to next token (skip whitespace)
void skipToNextToken(io::IReadFile* file) const;
};
} // end namespace video
} // end namespace irr
#endif
#endif

View File

@ -1,375 +0,0 @@
// 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 "CImageLoaderPSD.h"
#ifdef _IRR_COMPILE_WITH_PSD_LOADER_
#include "IReadFile.h"
#include "os.h"
#include "CImage.h"
#include "irrString.h"
namespace irr
{
namespace video
{
//! constructor
CImageLoaderPSD::CImageLoaderPSD()
{
#ifdef _DEBUG
setDebugName("CImageLoaderPSD");
#endif
}
//! returns true if the file maybe is able to be loaded by this class
//! based on the file extension (e.g. ".tga")
bool CImageLoaderPSD::isALoadableFileExtension(const io::path& filename) const
{
return core::hasFileExtension ( filename, "psd" );
}
//! returns true if the file maybe is able to be loaded by this class
bool CImageLoaderPSD::isALoadableFileFormat(io::IReadFile* file) const
{
if (!file)
return false;
u8 type[3];
file->read(&type, sizeof(u8)*3);
return (type[2]==2); // we currently only handle tgas of type 2.
}
//! creates a surface from the file
IImage* CImageLoaderPSD::loadImage(io::IReadFile* file) const
{
u32* imageData = 0;
PsdHeader header;
file->read(&header, sizeof(PsdHeader));
#ifndef __BIG_ENDIAN__
header.version = os::Byteswap::byteswap(header.version);
header.channels = os::Byteswap::byteswap(header.channels);
header.height = os::Byteswap::byteswap(header.height);
header.width = os::Byteswap::byteswap(header.width);
header.depth = os::Byteswap::byteswap(header.depth);
header.mode = os::Byteswap::byteswap(header.mode);
#endif
if (header.signature[0] != '8' ||
header.signature[1] != 'B' ||
header.signature[2] != 'P' ||
header.signature[3] != 'S')
return 0;
if (header.version != 1)
{
os::Printer::log("Unsupported PSD file version", file->getFileName(), ELL_ERROR);
return 0;
}
if (header.mode != 3 || header.depth != 8)
{
os::Printer::log("Unsupported PSD color mode or depth.\n", file->getFileName(), ELL_ERROR);
return 0;
}
// skip color mode data
u32 l;
file->read(&l, sizeof(u32));
#ifndef __BIG_ENDIAN__
l = os::Byteswap::byteswap(l);
#endif
if (!file->seek(l, true))
{
os::Printer::log("Error seeking file pos to image resources.\n", file->getFileName(), ELL_ERROR);
return 0;
}
// skip image resources
file->read(&l, sizeof(u32));
#ifndef __BIG_ENDIAN__
l = os::Byteswap::byteswap(l);
#endif
if (!file->seek(l, true))
{
os::Printer::log("Error seeking file pos to layer and mask.\n", file->getFileName(), ELL_ERROR);
return 0;
}
// skip layer & mask
file->read(&l, sizeof(u32));
#ifndef __BIG_ENDIAN__
l = os::Byteswap::byteswap(l);
#endif
if (!file->seek(l, true))
{
os::Printer::log("Error seeking file pos to image data section.\n", file->getFileName(), ELL_ERROR);
return 0;
}
// read image data
u16 compressionType;
file->read(&compressionType, sizeof(u16));
#ifndef __BIG_ENDIAN__
compressionType = os::Byteswap::byteswap(compressionType);
#endif
if (compressionType != 1 && compressionType != 0)
{
os::Printer::log("Unsupported psd compression mode.\n", file->getFileName(), ELL_ERROR);
return 0;
}
// create image data block
imageData = new u32[header.width * header.height];
bool res = false;
if (compressionType == 0)
res = readRawImageData(file, header, imageData); // RAW image data
else
res = readRLEImageData(file, header, imageData); // RLE compressed data
video::IImage* image = 0;
if (res)
{
// create surface
image = new CImage(ECF_A8R8G8B8,
core::dimension2d<u32>(header.width, header.height), imageData);
}
if (!image)
delete [] imageData;
imageData = 0;
return image;
}
bool CImageLoaderPSD::readRawImageData(io::IReadFile* file, const PsdHeader& header, u32* imageData) const
{
u8* tmpData = new u8[header.width * header.height];
for (s32 channel=0; channel<header.channels && channel < 3; ++channel)
{
if (!file->read(tmpData, sizeof(c8) * header.width * header.height))
{
os::Printer::log("Error reading color channel\n", file->getFileName(), ELL_ERROR);
break;
}
s16 shift = getShiftFromChannel((c8)channel, header);
if (shift != -1)
{
u32 mask = 0xff << shift;
for (u32 x=0; x<header.width; ++x)
{
for (u32 y=0; y<header.height; ++y)
{
s32 index = x + y*header.width;
imageData[index] = ~(~imageData[index] | mask);
imageData[index] |= tmpData[index] << shift;
}
}
}
}
delete [] tmpData;
return true;
}
bool CImageLoaderPSD::readRLEImageData(io::IReadFile* file, const PsdHeader& header, u32* imageData) const
{
/* If the compression code is 1, the image data
starts with the byte counts for all the scan lines in the channel
(LayerBottom LayerTop), with each count stored as a two
byte value. The RLE compressed data follows, with each scan line
compressed separately. The RLE compression is the same compres-sion
algorithm used by the Macintosh ROM routine PackBits, and
the TIFF standard.
If the Layer's Size, and therefore the data, is odd, a pad byte will
be inserted at the end of the row.
*/
/*
A pseudo code fragment to unpack might look like this:
Loop until you get the number of unpacked bytes you are expecting:
Read the next source byte into n.
If n is between 0 and 127 inclusive, copy the next n+1 bytes literally.
Else if n is between -127 and -1 inclusive, copy the next byte -n+1
times.
Else if n is -128, noop.
Endloop
In the inverse routine, it is best to encode a 2-byte repeat run as a replicate run
except when preceded and followed by a literal run. In that case, it is best to merge
the three runs into one literal run. Always encode 3-byte repeats as replicate runs.
That is the essence of the algorithm. Here are some additional rules:
- Pack each row separately. Do not compress across row boundaries.
- The number of uncompressed bytes per row is defined to be (ImageWidth + 7)
/ 8. If the uncompressed bitmap is required to have an even number of bytes per
row, decompress into word-aligned buffers.
- If a run is larger than 128 bytes, encode the remainder of the run as one or more
additional replicate runs.
When PackBits data is decompressed, the result should be interpreted as per com-pression
type 1 (no compression).
*/
u8* tmpData = new u8[header.width * header.height];
u16 *rleCount= new u16 [header.height * header.channels];
s32 size=0;
for (u32 y=0; y<header.height * header.channels; ++y)
{
if (!file->read(&rleCount[y], sizeof(u16)))
{
delete [] tmpData;
delete [] rleCount;
os::Printer::log("Error reading rle rows\n", file->getFileName(), ELL_ERROR);
return false;
}
#ifndef __BIG_ENDIAN__
rleCount[y] = os::Byteswap::byteswap(rleCount[y]);
#endif
size += rleCount[y];
}
s8 *buf = new s8[size];
if (!file->read(buf, size))
{
delete [] rleCount;
delete [] buf;
delete [] tmpData;
os::Printer::log("Error reading rle rows\n", file->getFileName(), ELL_ERROR);
return false;
}
u16 *rcount=rleCount;
s8 rh;
u16 bytesRead;
u8 *dest;
s8 *pBuf = buf;
// decompress packbit rle
for (s32 channel=0; channel<header.channels; channel++)
{
for (u32 y=0; y<header.height; ++y, ++rcount)
{
bytesRead=0;
dest = &tmpData[y*header.width];
while (bytesRead < *rcount)
{
rh = *pBuf++;
++bytesRead;
if (rh >= 0)
{
++rh;
while (rh--)
{
*dest = *pBuf++;
++bytesRead;
++dest;
}
}
else
if (rh > -128)
{
rh = -rh +1;
while (rh--)
{
*dest = *pBuf;
++dest;
}
++pBuf;
++bytesRead;
}
}
}
s16 shift = getShiftFromChannel((c8)channel, header);
if (shift != -1)
{
u32 mask = 0xff << shift;
for (u32 x=0; x<header.width; ++x)
for (u32 y=0; y<header.height; ++y)
{
s32 index = x + y*header.width;
imageData[index] = ~(~imageData[index] | mask);
imageData[index] |= tmpData[index] << shift;
}
}
}
delete [] rleCount;
delete [] buf;
delete [] tmpData;
return true;
}
s16 CImageLoaderPSD::getShiftFromChannel(c8 channelNr, const PsdHeader& header) const
{
switch(channelNr)
{
case 0:
return 16; // red
case 1:
return 8; // green
case 2:
return 0; // blue
case 3:
return header.channels == 4 ? 24 : -1; // ?
case 4:
return 24; // alpha
default:
return -1;
}
}
//! creates a loader which is able to load tgas
IImageLoader* createImageLoaderPSD()
{
return new CImageLoaderPSD();
}
} // end namespace video
} // end namespace irr
#endif

View File

@ -1,72 +0,0 @@
// 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_IMAGE_LOADER_PSD_H_INCLUDED__
#define __C_IMAGE_LOADER_PSD_H_INCLUDED__
#include "IrrCompileConfig.h"
#ifdef _IRR_COMPILE_WITH_PSD_LOADER_
#include "IImageLoader.h"
namespace irr
{
namespace video
{
// byte-align structures
#include "irrpack.h"
struct PsdHeader
{
c8 signature [4]; // Always equal to 8BPS.
u16 version; // Always equal to 1
c8 reserved [6]; // Must be zero
u16 channels; // Number of any channels inc. alphas
u32 height; // Rows Height of image in pixel
u32 width; // Colums Width of image in pixel
u16 depth; // Bits/channel
u16 mode; // Color mode of the file (Bitmap/Grayscale..)
} PACK_STRUCT;
// Default alignment
#include "irrunpack.h"
/*!
Surface Loader for psd images
*/
class CImageLoaderPSD : public IImageLoader
{
public:
//! constructor
CImageLoaderPSD();
//! returns true if the file maybe is able to be loaded by this class
//! based on the file extension (e.g. ".tga")
virtual bool isALoadableFileExtension(const io::path& filename) const;
//! returns true if the file maybe is able to be loaded by this class
virtual bool isALoadableFileFormat(io::IReadFile* file) const;
//! creates a surface from the file
virtual IImage* loadImage(io::IReadFile* file) const;
private:
bool readRawImageData(io::IReadFile* file, const PsdHeader& header, u32* imageData) const;
bool readRLEImageData(io::IReadFile* file, const PsdHeader& header, u32* imageData) const;
s16 getShiftFromChannel(c8 channelNr, const PsdHeader& header) const;
};
} // end namespace video
} // end namespace irr
#endif
#endif

View File

@ -1,654 +0,0 @@
//! Copyright (C) 2009-2012 Gary Conway
//! This file is part of the "Irrlicht Engine".
//! For conditions of distribution and use, see copyright notice in irrlicht.h
/*
Author: Gary Conway (Viper) - co-author of the ZIP file format, Feb 1989,
see the story at http://www.idcnet.us/ziphistory.html
Website: http://idcnet.us
Email: codeslinger@vipergc.com
Created: March 1, 2009
Version: 1.0
Updated:
This module will load SGI .rgb files (along with the other extensions). The module complies
with version 1.0 of the SGI Image File Format by Paul Haeberli of Silicon Graphics Computer Systems
The module handles BW, RGB and RGBA images.
RGB images are stored with either 8 bits per COLOR VALUE, one each for red,green,blue (24bpp)
or 16 bits per COLOR VALUE, again one each for red,green,blue (48 bpp), not including the alpha channel
OPTIONS NOT SUPPORTED
1. 16 bit COLOR VALUES (48bpp modes)
2. COLORMAP = DITHERED mode
For non- run length encoded files, this is the structure
The Header
The Image Data
If the image is run length encoded, this is the structure:
The Header
The Offset Tables
The Image Data
The Header consists of the following:
Size | Type | Name | Description
2 bytes | short | MAGIC | IRIS image file magic number
1 byte | char | STORAGE | Storage format
1 byte | char | BPC | Number of bytes per pixel channel
2 bytes | ushort | DIMENSION | Number of dimensions
2 bytes | ushort | XSIZE | X size in pixels
2 bytes | ushort | YSIZE | Y size in pixels
2 bytes | ushort | ZSIZE | Number of channels
4 bytes | long | PIXMIN | Minimum pixel value
4 bytes | long | PIXMAX | Maximum pixel value
4 bytes | char | DUMMY | Ignored
80 bytes | char | IMAGENAME | Image name
4 bytes | long | COLORMAP | Colormap ID
404 bytes | char | DUMMY | Ignored
Here is a description of each field in the image file Header:
MAGIC - This is the decimal value 474 saved as a short. This identifies the file as an SGI image file.
STORAGE - specifies whether the image is stored using run length encoding (RLE) or not (VERBATIM).
If RLE is used, the value of this byte will be 1. Otherwise the value of this byte will
be 0. The only allowed values for this field are 0 or 1.
BPC - describes the precision that is used to store each channel of an image. This is the number of
bytes per pixel component. The majority of SGI image files use 1 byte per pixel component,
giving 256 levels. Some SGI image files use 2 bytes per component. The only allowed values
for this field are 1 or 2.
DIMENSION - described the number of dimensions in the data stored in the image file.
The only allowed values are 1, 2, or 3. If this value is 1, the image file
consists of only 1 channel and only 1 scanline (row). The length of this
scanline is given by the value of XSIZE below. If this value is 2, the file
consists of a single channel with a number of scanlines. The width and height
of the image are given by the values of XSIZE and YSIZE below.
If this value is 3, the file consists of a number of channels.
The width and height of the image are given by the values of XSIZE and YSIZE below.
The number of channels is given by the value of ZSIZE below.
XSIZE - The width of the image in pixels
YSIZE - The height of the image in pixels
ZSIZE - The number of channels in the image. B/W (greyscale) images are stored as 2 dimensional
images with a ZSIZE of 1. RGB color images are stored as 3 dimensional images with a
ZSIZE of 3. An RGB image with an ALPHA channel is stored as a 3 dimensional image with
a ZSIZE of 4. There are no inherent limitations in the SGI image file format that would
preclude the creation of image files with more than 4 channels.
PINMIN - The minimum pixel value in the image. The value of 0 may be used if no pixel has a value
that is smaller than 0.
PINMAX - The maximum pixel value in the image. The value of 255 may be used if no pixel has a
value that is greater than 255. This is the value that is considered to be full
brightness in the image.
DUMMY - This 4 bytes of data should be set to 0.
IMAGENAME - An null terminated ascii string of up to 79 characters terminated by a null may be
included here. This is not commonly used.
COLORMAP - This controls how the pixel values in the file should be interpreted. It can have one
of these four values:
0: NORMAL - The data in the channels represent B/W values for images with 1 channel, RGB values
for images with 3 channels, and RGBA values for images with 4 channels. Almost all
the SGI image files are of this type.
1: DITHERED - The image will have only 1 channel of data. For each pixel, RGB data is packed
into one 8 bit value. 3 bits are used for red and green, while blue uses 2 bits.
Red data is found in bits[2..0], green data in bits[5..3], and blue data in
bits[7..6]. This format is obsolete.
2: SCREEN - The image will have only 1 channel of data. This format was used to store
color-indexed pixels. To convert the pixel values into RGB values a colormap
must be used. The appropriate color map varies from image to image. This format is obsolete.
3: COLORMAP - The image is used to store a color map from an SGI machine. In this case the
image is not displayable in the conventional sense.
DUMMY - This 404 bytes of data should be set to 0. This makes the Header exactly 512 bytes.
*/
#include "CImageLoaderRGB.h"
#ifdef _IRR_COMPILE_WITH_RGB_LOADER_
#include "IReadFile.h"
#include "SColor.h"
#include "CColorConverter.h"
#include "CImage.h"
#include "os.h"
#include "irrString.h"
namespace irr
{
namespace video
{
//! constructor
CImageLoaderRGB::CImageLoaderRGB()
{
#ifdef _DEBUG
setDebugName("CImageLoaderRGB");
#endif
}
//! returns true if the file maybe is able to be loaded by this class
//! based on the file extensions listed here
bool CImageLoaderRGB::isALoadableFileExtension(const io::path& filename) const
{
return core::hasFileExtension( filename, "rgb", "rgba", "sgi" ) ||
core::hasFileExtension( filename, "int", "inta", "bw" );
}
//! returns true if the file maybe is able to be loaded by this class
bool CImageLoaderRGB::isALoadableFileFormat(io::IReadFile* file) const
{
rgbStruct rgb;
return checkFormat(file, rgb);
}
/** The main entry point, read and format the image file.
\return Pointer to the image data on success
null pointer on fail */
IImage* CImageLoaderRGB::loadImage(io::IReadFile* file) const
{
IImage* image = 0;
s32* paletteData = 0;
rgbStruct rgb; // construct our structure for holding data
// read Header information
if (checkFormat(file, rgb))
{
// 16 bits per COLOR VALUE, not supported, this is 48bpp mode
if (rgb.Header.BPC != 1)
{
os::Printer::log("Only one byte per pixel RGB files are supported", file->getFileName(), ELL_ERROR);
}
else if (rgb.Header.Colormap != 0)
{
os::Printer::log("Dithered, Screen and Colormap RGB files are not supported", file->getFileName(), ELL_ERROR);
}
else if (rgb.Header.Storage == 1 && !readOffsetTables(file, rgb))
{
os::Printer::log("Failed to read RLE table in RGB file", file->getFileName(), ELL_ERROR);
}
else if (!rgb.allocateTemps())
{
os::Printer::log("Out of memory in RGB file loader", file->getFileName(), ELL_ERROR);
}
else
{
// read and process the file to rgbData
processFile(file, rgb);
/*
ZSIZE Description
1 BW (grayscale) image
3 RGB image
4 RGBa image with one alpha channel
When the Alpha channel is present, I am not sure with RGB files if
it's a precomputed RGB color or it needs to be completely calculated. My guess
would be that it's not precomputed for two reasons.
1. the loss of precision when calculating the fraction, then storing the result as an int
2. the loss of the original color data when the image might be composited with another. Yes
the original color data could be computed, however, not without another loss in precision
Also, I don't know where to find the background color
Pixmin and Pixmax are apparently the min and max alpha blend values (0-100%)
Complete Alpha blending computation
The actual resulting merged color is computed this way:
(image color alpha) + (background color (100% - alpha)).
Using precomputed blending
(image color) + (background color (100% - alpha)).
Alternatively, the RGB files could use another blending technique entirely
*/
switch (rgb.Header.Zsize)
{
case 1:
// BW (grayscale) image
paletteData = new s32[256];
for (int n=0; n<256; n++)
paletteData[n] = n;
image = new CImage(ECF_A1R5G5B5, core::dimension2d<u32>(rgb.Header.Xsize, rgb.Header.Ysize));
if (image)
CColorConverter::convert8BitTo16Bit(rgb.rgbData, (s16*)image->lock(), rgb.Header.Xsize, rgb.Header.Ysize, paletteData, 0, true);
break;
case 3:
// RGB image
// one byte per COLOR VALUE, eg, 24bpp
image = new CImage(ECF_R8G8B8, core::dimension2d<u32>(rgb.Header.Xsize, rgb.Header.Ysize));
if (image)
CColorConverter::convert24BitTo24Bit(rgb.rgbData, (u8*)image->lock(), rgb.Header.Xsize, rgb.Header.Ysize, 0, true, false);
break;
case 4:
// RGBa image with one alpha channel (32bpp)
// image is stored in rgbData as RGBA
converttoARGB(reinterpret_cast<u32*>(rgb.rgbData), rgb.Header.Ysize * rgb.Header.Xsize);
image = new CImage(ECF_A8R8G8B8, core::dimension2d<u32>(rgb.Header.Xsize, rgb.Header.Ysize));
if (image)
CColorConverter::convert32BitTo32Bit((s32*)rgb.rgbData, (s32*)image->lock(), rgb.Header.Xsize, rgb.Header.Ysize, 0, true);
break;
default:
// Format unknown
os::Printer::log("Unsupported pixel format in RGB file", file->getFileName(), ELL_ERROR);
}
if (image)
image->unlock();
}
}
// and tidy up allocated memory
delete [] paletteData;
return image;
}
// returns true on success
bool CImageLoaderRGB::readHeader(io::IReadFile* file, rgbStruct& rgb) const
{
if ( file->read(&rgb.Header, sizeof(rgb.Header)) < s32(sizeof(rgb.Header)) )
return false;
// test for INTEL or BIG ENDIAN processor
// if INTEL, then swap the byte order on 16 bit INT's to make them BIG ENDIAN
// because that is the native format for the .rgb file
#ifndef __BIG_ENDIAN__
rgb.Header.Magic = os::Byteswap::byteswap(rgb.Header.Magic);
rgb.Header.Storage = os::Byteswap::byteswap(rgb.Header.Storage);
rgb.Header.Dimension = os::Byteswap::byteswap(rgb.Header.Dimension);
rgb.Header.Xsize = os::Byteswap::byteswap(rgb.Header.Xsize);
rgb.Header.Ysize = os::Byteswap::byteswap(rgb.Header.Ysize);
rgb.Header.Zsize = os::Byteswap::byteswap(rgb.Header.Zsize);
rgb.Header.Pixmin = os::Byteswap::byteswap(rgb.Header.Pixmin);
rgb.Header.Pixmax = os::Byteswap::byteswap(rgb.Header.Pixmax);
rgb.Header.Colormap = os::Byteswap::byteswap(rgb.Header.Colormap);
#endif
// calculate the size of the buffer needed: XSIZE * YSIZE * ZSIZE * BPC
rgb.ImageSize = (rgb.Header.Xsize)*(rgb.Header.Ysize)*(rgb.Header.Zsize)*(rgb.Header.BPC);
return true;
}
bool CImageLoaderRGB::checkFormat(io::IReadFile* file, rgbStruct& rgb) const
{
if (!readHeader(file, rgb))
return false;
return (rgb.Header.Magic == 0x1DA);
}
/*
If the image is stored using run length encoding, offset tables follow the Header that
describe what the file offsets are to the RLE for each scanline. This information only
applies if the value for STORAGE above is 1.
Size | Type | Name | Description
tablen longs | long | STARTTAB | Start table
tablen longs | long | LENGTHTAB | Length table
One entry in each table is needed for each scanline of RLE data. The total number of scanlines in the image (tablen) is determined by the product of the YSIZE and ZSIZE. There are two tables of longs that are written. Each consists of tablen longs of data. The first table has the file offsets to the RLE data for each scanline in the image. In a file with more than 1 channel (ZSIZE > 1) this table first has all the offsets for the scanlines in the first channel, followed be offsets for the scanlines in the second channel, etc. The second table has the RLE data length for each scanline in the image. In a file with more than 1 channel (ZSIZE > 1) this table first has all the RLE data lengths for the scanlines in the first channel, followed be RLE data lengths for the scanlines in the second channel, etc.
To find the the file offset, and the number of bytes in the RLE data for a particular scanline, these
two arrays may be read in and indexed as follows:
To read in the tables:
unsigned long *starttab, *lengthtab;
tablen = YSIZE*ZSIZE*sizeof(long);
starttab = (unsigned long *)mymalloc(tablen);
lengthtab = (unsigned long *)mymalloc(tablen);
fseek(rgb->inf,512,SEEK_SET);
readlongtab(rgb->inf,starttab);
readlongtab(rgb->inf,lengthtab);
To find the file offset and RLE data length for a scanline:
rowno is an integer in the range 0 to YSIZE-1 channo is an integer in the range 0 to ZSIZE-1
rleoffset = starttab[rowno+channo*YSIZE]
rlelength = lengthtab[rowno+channo*YSIZE]
It is possible for two identical rows (scanlines) to share compressed data. A completely
white image could be written as a single compressed row and having all table entries point
to that row. Another little hack that should work is if you are writing out a RGB RLE file,
and a particular scanline is achromatic (greyscale), you could just make the r, g and b rows
point to the same data!!
RETURNS: on success true, else returns false
*/
bool CImageLoaderRGB::readOffsetTables(io::IReadFile* file, rgbStruct& rgb) const
{
rgb.TableLen = rgb.Header.Ysize * rgb.Header.Zsize ; // calc size of tables
// return error if unable to allocate tables
rgb.StartTable = new u32[rgb.TableLen];
if (!rgb.StartTable)
return false;
rgb.LengthTable = new u32[rgb.TableLen];
if (!rgb.LengthTable)
return false;
file->seek(512);
file->read(rgb.StartTable, rgb.TableLen* sizeof(u32));
file->read(rgb.LengthTable, rgb.TableLen* sizeof(u32));
// if we are on an INTEL platform, swap the bytes
#ifndef __BIG_ENDIAN__
const u32 length = rgb.TableLen;
for (u32 i=0; i<length; ++i)
{
rgb.StartTable[i] = os::Byteswap::byteswap(rgb.StartTable[i]);
rgb.LengthTable[i] = os::Byteswap::byteswap(rgb.LengthTable[i]);
}
#endif
return true;
}
/*
The Header has already been read into rgb structure
The Tables have been read if necessary
Now process the actual data
*/
void CImageLoaderRGB::processFile(io::IReadFile* file, rgbStruct& rgb) const
{
u16 *tempShort;
// calculate the size of the buffer needed: XSIZE * YSIZE * ZSIZE * BPC
rgb.rgbData = new u8 [(rgb.Header.Xsize)*(rgb.Header.Ysize)*(rgb.Header.Zsize)*(rgb.Header.BPC)];
u8 *ptr = rgb.rgbData;
// cycle through all scanlines
#ifdef _IRR_RGB_FILE_INVERTED_IMAGE_
// preserve the image as stored, eg, inverted
for (u32 i = 0; i < rgb.Header.Ysize; ++i)
#else
// invert the image to make it upright
for (s32 i = (s32)(rgb.Header.Ysize)-1; i>=0; --i)
#endif
{
// check the number of channels and read a row of data
if (rgb.Header.Zsize >= 1)
readRGBrow( rgb.tmpR, i, 0, file, rgb);
if (rgb.Header.Zsize >= 2)
readRGBrow( rgb.tmpG, i, 1, file, rgb);
if (rgb.Header.Zsize >= 3)
readRGBrow( rgb.tmpB, i, 2, file, rgb);
if (rgb.Header.Zsize >= 4)
readRGBrow( rgb.tmpA, i, 3, file, rgb);
// cycle thru all values for this row
for (u32 j = 0; j < rgb.Header.Xsize; ++j)
{
if(rgb.Header.BPC == 1)
{
// ONE byte per color
if (rgb.Header.Zsize >= 1)
*ptr++ = rgb.tmpR[j];
if (rgb.Header.Zsize >= 2)
*ptr++ = rgb.tmpG[j];
if (rgb.Header.Zsize >= 3)
*ptr++ = rgb.tmpB[j];
if (rgb.Header.Zsize >= 4)
*ptr++ = rgb.tmpA[j];
}
else
{
// TWO bytes per color
if( rgb.Header.Zsize >= 1 )
{
// two bytes of color data
tempShort = (u16 *) (ptr);
*tempShort = *( (u16 *) (rgb.tmpR) + j);
tempShort++;
ptr = ( u8 *)(tempShort);
}
if( rgb.Header.Zsize >= 2 )
{
tempShort = ( u16 *) (ptr);
*tempShort = *( ( u16 *) (rgb.tmpG) + j);
tempShort++;
ptr = ( u8 *) (tempShort);
}
if( rgb.Header.Zsize >= 3 )
{
tempShort = ( u16 *) (ptr);
*tempShort = *( ( u16 *) (rgb.tmpB) + j);
tempShort++;
ptr = ( u8 *)(tempShort);
}
if( rgb.Header.Zsize >= 4 )
{
tempShort = ( u16 *) (ptr);
*tempShort = *( ( u16 *) (rgb.tmpA) + j);
tempShort++;
ptr = ( u8 *)(tempShort);
}
} // end if(rgb.Header.BPC == 1)
} // end for
} // end for
}
/*
This information only applies if the value for STORAGE is 1. If the image is
stored using run length encoding, the image data follows the offset/length tables.
The RLE data is not in any particular order. The offset tables are used to
locate the rle data for any scanline.
The RLE data must be read in from the file and expanded into pixel data in the following manner:
If BPC is 1, then there is one byte per pixel. In this case the RLE data should be
read into an array of chars. To expand data, the low order seven bits of the first
byte: bits[6..0] are used to form a count. If the high order bit of the first byte
is 1: bit[7], then the count is used to specify how many bytes to copy from the RLE
data buffer to the destination. Otherwise, if the high order bit of the first byte
is 0: bit[7], then the count is used to specify how many times to repeat the value
of the following byte, in the destination. This process continues until a count
of 0 is found. This should decompress exactly XSIZE pixels.
One entry in each table is needed for each scanline of RLE data. The total number of
scanlines in the image (tablen) is determined by the product of the YSIZE and ZSIZE.
There are two tables of longs that are written. Each consists of tablen longs of data.
The first table has the file offsets to the RLE data for each scanline in the image. In
a file with more than 1 channel (ZSIZE > 1) this table first has all the offsets for the
scanlines in the first channel, followed be offsets for the scanlines in the second
channel, etc. The second table has the RLE data length for each scanline in the image.
In a file with more than 1 channel (ZSIZE > 1) this table first has all the RLE data
lengths for the scanlines in the first channel, followed be RLE data lengths for the
scanlines in the second channel, etc.
Return a row of data, expanding RLE compression if necessary
*/
void CImageLoaderRGB::readRGBrow(u8 *buf, int y, int z, io::IReadFile* file, rgbStruct& rgb) const
{
if (rgb.Header.Storage != 1)
{
// stored VERBATIM
file->seek(512+(y*rgb.Header.Xsize * rgb.Header.BPC)+(z* rgb.Header.Xsize * rgb.Header.Ysize * rgb.Header.BPC));
file->read(buf, rgb.Header.Xsize * rgb.Header.BPC);
#ifndef __BIG_ENDIAN__
if (rgb.Header.BPC != 1)
{
u16* tmpbuf = reinterpret_cast<u16*>(buf);
for (u32 i=0; i<rgb.Header.Xsize; ++i)
tmpbuf[i] = os::Byteswap::byteswap(tmpbuf[i]);
}
#endif
return;
}
// the file is stored as Run Length Encoding (RLE)
// each sequence is stored as 0x80 NumRepeats ByteToRepeat
// get the file offset from StartTable and SEEK
// then read the data
file->seek((long) rgb.StartTable[y+z * rgb.Header.Ysize]);
file->read(rgb.tmp, rgb.LengthTable[y+z * rgb.Header.Ysize]);
// rgb.tmp has the data
u16 pixel;
u16 *tempShort;
u8* iPtr = rgb.tmp;
u8* oPtr = buf;
while (true)
{
// if BPC = 1, then one byte per pixel
if (rgb.Header.BPC == 1)
{
pixel = *iPtr++;
}
else
{
// BPC = 2, so two bytes per pixel
tempShort = (u16 *) iPtr;
pixel = *tempShort;
tempShort++;
iPtr = (u8 *) tempShort;
}
#ifndef __BIG_ENDIAN__
if (rgb.Header.BPC != 1)
pixel = os::Byteswap::byteswap(pixel);
#endif
s32 count = (s32)(pixel & 0x7F);
// limit the count value to the remaining row size
if (oPtr + count*rgb.Header.BPC > buf + rgb.Header.Xsize * rgb.Header.BPC)
{
count = ( (buf + rgb.Header.Xsize * rgb.Header.BPC) - oPtr ) / rgb.Header.BPC;
}
if (count<=0)
break;
else if (pixel & 0x80)
{
// repeat the byte pointed to by iPtr, count times
while (count--)
{
if(rgb.Header.BPC == 1)
{
*oPtr++ = *iPtr++;
}
else
{
// write pixel from iPtr to oPtr, move both two bytes ahead
tempShort = (u16 *) (iPtr);
pixel = *tempShort;
tempShort++;
iPtr = (u8 *) (tempShort);
#ifndef __BIG_ENDIAN__
pixel = os::Byteswap::byteswap(pixel);
#endif
tempShort = (u16 *) (oPtr);
*tempShort = pixel;
tempShort++;
oPtr = (u8 *) (tempShort);
}
}
}
else
{
if (rgb.Header.BPC == 1)
{
pixel = *iPtr++;
}
else
{
tempShort = (u16 *) (iPtr);
pixel = *tempShort;
tempShort++;
iPtr = (u8 *) (tempShort);
}
#ifndef __BIG_ENDIAN__
if (rgb.Header.BPC != 1)
pixel = os::Byteswap::byteswap(pixel);
#endif
while (count--)
{
if(rgb.Header.BPC == 1)
{
*oPtr++ = (u8) pixel;
}
else
{
tempShort = (u16 *) (oPtr);
*tempShort = pixel;
tempShort++;
oPtr = (u8 *) (tempShort);
}
}
} // else if (pixel & 0x80)
} // while (true)
}
// we have 1 byte per COLOR VALUE, eg 24bpp and 1 alpha channel
// color values are stored as RGBA, convert to ARGB
// todo: replace with CColorConverter method
void CImageLoaderRGB::converttoARGB(u32* in, const u32 size) const
{
for (u32 x=0; x < size; ++x)
{
*in=(*in>>8)|(*in<<24);
++in;
}
}
//! creates a loader which is able to load SGI RGB images
IImageLoader* createImageLoaderRGB()
{
return new CImageLoaderRGB;
}
} // end namespace video
} // end namespace irr
#endif

View File

@ -1,165 +0,0 @@
// Copyright (C) 2009-2012 Gary Conway
// This file is part of the "Irrlicht Engine".
// For conditions of distribution and use, see copyright notice in irrlicht.h
/*
Author: Gary Conway (Viper) - co-author of the ZIP file format, Feb 1989,
see the story at http://www.idcnet.us/ziphistory.html
Website: http://idcnet.us
Email: codeslinger@vipergc.com
Created: March 1, 2009
Version: 1.0
Updated:
*/
#ifndef __C_IMAGE_LOADER_RGB_H_INCLUDED__
#define __C_IMAGE_LOADER_RGB_H_INCLUDED__
// define _IRR_RGB_FILE_INVERTED_IMAGE_ to preserve the inverted format of the RGB file
// commenting this out will invert the inverted image,resulting in the image being upright
#define _IRR_RGB_FILE_INVERTED_IMAGE_
#include "IrrCompileConfig.h"
#ifdef _IRR_COMPILE_WITH_RGB_LOADER_
#include "IImageLoader.h"
namespace irr
{
namespace video
{
// byte-align structures
#include "irrpack.h"
// the RGB image file header structure
struct SRGBHeader
{
u16 Magic; // IRIS image file magic number
u8 Storage; // Storage format
u8 BPC; // Number of bytes per pixel channel
u16 Dimension; // Number of dimensions
u16 Xsize; // X size in pixels
u16 Ysize; // Y size in pixels
u16 Zsize; // Z size in pixels
u32 Pixmin; // Minimum pixel value
u32 Pixmax; // Maximum pixel value
u32 Dummy1; // ignored
char Imagename[80];// Image name
u32 Colormap; // Colormap ID
// char Dummy2[404];// Ignored
} PACK_STRUCT;
// Default alignment
#include "irrunpack.h"
// this structure holds context specific data about the file being loaded.
typedef struct _RGBdata
{
u8 *tmp,
*tmpR,
*tmpG,
*tmpB,
*tmpA;
u32 *StartTable; // compressed data table, holds file offsets
u32 *LengthTable; // length for the above data, hold lengths for above
u32 TableLen; // len of above tables
SRGBHeader Header; // define the .rgb file header
u32 ImageSize;
u8 *rgbData;
public:
_RGBdata() : tmp(0), tmpR(0), tmpG(0), tmpB(0), tmpA(0),
StartTable(0), LengthTable(0), TableLen(0), ImageSize(0), rgbData(0)
{
}
~_RGBdata()
{
delete [] tmp;
delete [] tmpR;
delete [] tmpG;
delete [] tmpB;
delete [] tmpA;
delete [] StartTable;
delete [] LengthTable;
delete [] rgbData;
}
bool allocateTemps()
{
tmp = tmpR = tmpG = tmpB = tmpA = 0;
tmp = new u8 [Header.Xsize * 256 * Header.BPC];
if (!tmp)
return false;
if (Header.Zsize >= 1)
{
tmpR = new u8[Header.Xsize * Header.BPC];
if (!tmpR)
return false;
}
if (Header.Zsize >= 2)
{
tmpG = new u8[Header.Xsize * Header.BPC];
if (!tmpG)
return false;
}
if (Header.Zsize >= 3)
{
tmpB = new u8[Header.Xsize * Header.BPC];
if (!tmpB)
return false;
}
if (Header.Zsize >= 4)
{
tmpA = new u8[Header.Xsize * Header.BPC];
if (!tmpA)
return false;
}
return true;
}
} rgbStruct;
//! Surface Loader for Silicon Graphics RGB files
class CImageLoaderRGB : public IImageLoader
{
public:
//! constructor
CImageLoaderRGB();
//! returns true if the file maybe is able to be loaded by this class
//! based on the file extension (e.g. ".tga")
virtual bool isALoadableFileExtension(const io::path& filename) const;
//! returns true if the file maybe is able to be loaded by this class
virtual bool isALoadableFileFormat(io::IReadFile* file) const;
//! creates a surface from the file
virtual IImage* loadImage(io::IReadFile* file) const;
private:
bool readHeader(io::IReadFile* file, rgbStruct& rgb) const;
void readRGBrow(u8 *buf, int y, int z, io::IReadFile* file, rgbStruct& rgb) const;
void processFile(io::IReadFile *file, rgbStruct& rgb) const;
bool checkFormat(io::IReadFile *file, rgbStruct& rgb) const;
bool readOffsetTables(io::IReadFile* file, rgbStruct& rgb) const;
void converttoARGB(u32* in, const u32 size) const;
};
} // end namespace video
} // end namespace irr
#endif // _IRR_COMPILE_WITH_RGB_LOADER_
#endif // __C_IMAGE_LOADER_RGB_H_INCLUDED__

View File

@ -1,239 +0,0 @@
// 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 "CImageLoaderTGA.h"
#ifdef _IRR_COMPILE_WITH_TGA_LOADER_
#include "IReadFile.h"
#include "os.h"
#include "CColorConverter.h"
#include "CImage.h"
#include "irrString.h"
namespace irr
{
namespace video
{
//! returns true if the file maybe is able to be loaded by this class
//! based on the file extension (e.g. ".tga")
bool CImageLoaderTGA::isALoadableFileExtension(const io::path& filename) const
{
return core::hasFileExtension ( filename, "tga" );
}
//! loads a compressed tga.
u8 *CImageLoaderTGA::loadCompressedImage(io::IReadFile *file, const STGAHeader& header) const
{
// This was written and sent in by Jon Pry, thank you very much!
// I only changed the formatting a little bit.
s32 bytesPerPixel = header.PixelDepth/8;
s32 imageSize = header.ImageHeight * header.ImageWidth * bytesPerPixel;
u8* data = new u8[imageSize];
s32 currentByte = 0;
while(currentByte < imageSize)
{
u8 chunkheader = 0;
file->read(&chunkheader, sizeof(u8)); // Read The Chunk's Header
if(chunkheader < 128) // If The Chunk Is A 'RAW' Chunk
{
chunkheader++; // Add 1 To The Value To Get Total Number Of Raw Pixels
file->read(&data[currentByte], bytesPerPixel * chunkheader);
currentByte += bytesPerPixel * chunkheader;
}
else
{
// thnx to neojzs for some fixes with this code
// If It's An RLE Header
chunkheader -= 127; // Subtract 127 To Get Rid Of The ID Bit
s32 dataOffset = currentByte;
file->read(&data[dataOffset], bytesPerPixel);
currentByte += bytesPerPixel;
for(s32 counter = 1; counter < chunkheader; counter++)
{
for(s32 elementCounter=0; elementCounter < bytesPerPixel; elementCounter++)
data[currentByte + elementCounter] = data[dataOffset + elementCounter];
currentByte += bytesPerPixel;
}
}
}
return data;
}
//! returns true if the file maybe is able to be loaded by this class
bool CImageLoaderTGA::isALoadableFileFormat(io::IReadFile* file) const
{
if (!file)
return false;
STGAFooter footer;
memset(&footer, 0, sizeof(STGAFooter));
file->seek(file->getSize()-sizeof(STGAFooter));
file->read(&footer, sizeof(STGAFooter));
return (!strcmp(footer.Signature,"TRUEVISION-XFILE.")); // very old tgas are refused.
}
//! creates a surface from the file
IImage* CImageLoaderTGA::loadImage(io::IReadFile* file) const
{
STGAHeader header;
u32 *palette = 0;
file->read(&header, sizeof(STGAHeader));
#ifdef __BIG_ENDIAN__
header.ColorMapLength = os::Byteswap::byteswap(header.ColorMapLength);
header.ImageWidth = os::Byteswap::byteswap(header.ImageWidth);
header.ImageHeight = os::Byteswap::byteswap(header.ImageHeight);
#endif
// skip image identification field
if (header.IdLength)
file->seek(header.IdLength, true);
if (header.ColorMapType)
{
// create 32 bit palette
palette = new u32[ header.ColorMapLength];
// read color map
u8 * colorMap = new u8[header.ColorMapEntrySize/8 * header.ColorMapLength];
file->read(colorMap,header.ColorMapEntrySize/8 * header.ColorMapLength);
// convert to 32-bit palette
switch ( header.ColorMapEntrySize )
{
case 16:
CColorConverter::convert_A1R5G5B5toA8R8G8B8(colorMap, header.ColorMapLength, palette);
break;
case 24:
CColorConverter::convert_B8G8R8toA8R8G8B8(colorMap, header.ColorMapLength, palette);
break;
case 32:
CColorConverter::convert_B8G8R8A8toA8R8G8B8(colorMap, header.ColorMapLength, palette);
break;
}
delete [] colorMap;
}
// read image
u8* data = 0;
if ( header.ImageType == 1 || // Uncompressed, color-mapped images.
header.ImageType == 2 || // Uncompressed, RGB images
header.ImageType == 3 // Uncompressed, black and white images
)
{
const s32 imageSize = header.ImageHeight * header.ImageWidth * header.PixelDepth/8;
data = new u8[imageSize];
file->read(data, imageSize);
}
else
if(header.ImageType == 10)
{
// Runlength encoded RGB images
data = loadCompressedImage(file, header);
}
else
{
os::Printer::log("Unsupported TGA file type", file->getFileName(), ELL_ERROR);
delete [] palette;
return 0;
}
IImage* image = 0;
switch(header.PixelDepth)
{
case 8:
{
if (header.ImageType==3) // grey image
{
image = new CImage(ECF_R8G8B8,
core::dimension2d<u32>(header.ImageWidth, header.ImageHeight));
if (image)
CColorConverter::convert8BitTo24Bit((u8*)data,
(u8*)image->lock(),
header.ImageWidth,header.ImageHeight,
0, 0, (header.ImageDescriptor&0x20)==0);
}
else
{
image = new CImage(ECF_A1R5G5B5,
core::dimension2d<u32>(header.ImageWidth, header.ImageHeight));
if (image)
CColorConverter::convert8BitTo16Bit((u8*)data,
(s16*)image->lock(),
header.ImageWidth,header.ImageHeight,
(s32*) palette, 0,
(header.ImageDescriptor&0x20)==0);
}
}
break;
case 16:
image = new CImage(ECF_A1R5G5B5,
core::dimension2d<u32>(header.ImageWidth, header.ImageHeight));
if (image)
CColorConverter::convert16BitTo16Bit((s16*)data,
(s16*)image->lock(), header.ImageWidth, header.ImageHeight, 0, (header.ImageDescriptor&0x20)==0);
break;
case 24:
image = new CImage(ECF_R8G8B8,
core::dimension2d<u32>(header.ImageWidth, header.ImageHeight));
if (image)
CColorConverter::convert24BitTo24Bit(
(u8*)data, (u8*)image->lock(), header.ImageWidth, header.ImageHeight, 0, (header.ImageDescriptor&0x20)==0, true);
break;
case 32:
image = new CImage(ECF_A8R8G8B8,
core::dimension2d<u32>(header.ImageWidth, header.ImageHeight));
if (image)
CColorConverter::convert32BitTo32Bit((s32*)data,
(s32*)image->lock(), header.ImageWidth, header.ImageHeight, 0, (header.ImageDescriptor&0x20)==0);
break;
default:
os::Printer::log("Unsupported TGA format", file->getFileName(), ELL_ERROR);
break;
}
if (image)
image->unlock();
delete [] data;
delete [] palette;
return image;
}
//! creates a loader which is able to load tgas
IImageLoader* createImageLoaderTGA()
{
return new CImageLoaderTGA();
}
} // end namespace video
} // end namespace irr
#endif

View File

@ -1,82 +0,0 @@
// 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_IMAGE_LOADER_TGA_H_INCLUDED__
#define __C_IMAGE_LOADER_TGA_H_INCLUDED__
#include "IrrCompileConfig.h"
#include "IImageLoader.h"
namespace irr
{
namespace video
{
#if defined(_IRR_COMPILE_WITH_TGA_LOADER_) || defined(_IRR_COMPILE_WITH_TGA_WRITER_)
// byte-align structures
#include "irrpack.h"
// these structs are also used in the TGA writer
struct STGAHeader{
u8 IdLength;
u8 ColorMapType;
u8 ImageType;
u8 FirstEntryIndex[2];
u16 ColorMapLength;
u8 ColorMapEntrySize;
u8 XOrigin[2];
u8 YOrigin[2];
u16 ImageWidth;
u16 ImageHeight;
u8 PixelDepth;
u8 ImageDescriptor;
} PACK_STRUCT;
struct STGAFooter
{
u32 ExtensionOffset;
u32 DeveloperOffset;
c8 Signature[18];
} PACK_STRUCT;
// Default alignment
#include "irrunpack.h"
#endif // compiled with loader or reader
#ifdef _IRR_COMPILE_WITH_TGA_LOADER_
/*!
Surface Loader for targa images
*/
class CImageLoaderTGA : public IImageLoader
{
public:
//! returns true if the file maybe is able to be loaded by this class
//! based on the file extension (e.g. ".tga")
virtual bool isALoadableFileExtension(const io::path& filename) const;
//! returns true if the file maybe is able to be loaded by this class
virtual bool isALoadableFileFormat(io::IReadFile* file) const;
//! creates a surface from the file
virtual IImage* loadImage(io::IReadFile* file) const;
private:
//! loads a compressed tga. Was written and sent in by Jon Pry, thank you very much!
u8* loadCompressedImage(io::IReadFile *file, const STGAHeader& header) const;
};
#endif // compiled with loader
} // end namespace video
} // end namespace irr
#endif

View File

@ -1,285 +0,0 @@
// Copyright (C) 2004 Murphy McCauley
// Copyright (C) 2007-2012 Christian Stehno
// This file is part of the "Irrlicht Engine".
// For conditions of distribution and use, see copyright notice in irrlicht.h
#include "CImageLoaderWAL.h"
#include "CColorConverter.h"
#include "CImage.h"
#include "os.h"
#include "dimension2d.h"
#include "IVideoDriver.h"
#include "IFileSystem.h"
#include "IReadFile.h"
#include "irrString.h"
namespace irr
{
namespace video
{
#ifdef _IRR_COMPILE_WITH_LMP_LOADER_
// Palette quake2 colormap.h, 768 byte, last is transparent
static const u32 colormap_h[256] = {
0xFF000000,0xFF0F0F0F,0xFF1F1F1F,0xFF2F2F2F,0xFF3F3F3F,0xFF4B4B4B,0xFF5B5B5B,0xFF6B6B6B,
0xFF7B7B7B,0xFF8B8B8B,0xFF9B9B9B,0xFFABABAB,0xFFBBBBBB,0xFFCBCBCB,0xFFDBDBDB,0xFFEBEBEB,
0xFF0F0B07,0xFF170F0B,0xFF1F170B,0xFF271B0F,0xFF2F2313,0xFF372B17,0xFF3F2F17,0xFF4B371B,
0xFF533B1B,0xFF5B431F,0xFF634B1F,0xFF6B531F,0xFF73571F,0xFF7B5F23,0xFF836723,0xFF8F6F23,
0xFF0B0B0F,0xFF13131B,0xFF1B1B27,0xFF272733,0xFF2F2F3F,0xFF37374B,0xFF3F3F57,0xFF474767,
0xFF4F4F73,0xFF5B5B7F,0xFF63638B,0xFF6B6B97,0xFF7373A3,0xFF7B7BAF,0xFF8383BB,0xFF8B8BCB,
0xFF000000,0xFF070700,0xFF0B0B00,0xFF131300,0xFF1B1B00,0xFF232300,0xFF2B2B07,0xFF2F2F07,
0xFF373707,0xFF3F3F07,0xFF474707,0xFF4B4B0B,0xFF53530B,0xFF5B5B0B,0xFF63630B,0xFF6B6B0F,
0xFF070000,0xFF0F0000,0xFF170000,0xFF1F0000,0xFF270000,0xFF2F0000,0xFF370000,0xFF3F0000,
0xFF470000,0xFF4F0000,0xFF570000,0xFF5F0000,0xFF670000,0xFF6F0000,0xFF770000,0xFF7F0000,
0xFF131300,0xFF1B1B00,0xFF232300,0xFF2F2B00,0xFF372F00,0xFF433700,0xFF4B3B07,0xFF574307,
0xFF5F4707,0xFF6B4B0B,0xFF77530F,0xFF835713,0xFF8B5B13,0xFF975F1B,0xFFA3631F,0xFFAF6723,
0xFF231307,0xFF2F170B,0xFF3B1F0F,0xFF4B2313,0xFF572B17,0xFF632F1F,0xFF733723,0xFF7F3B2B,
0xFF8F4333,0xFF9F4F33,0xFFAF632F,0xFFBF772F,0xFFCF8F2B,0xFFDFAB27,0xFFEFCB1F,0xFFFFF31B,
0xFF0B0700,0xFF1B1300,0xFF2B230F,0xFF372B13,0xFF47331B,0xFF533723,0xFF633F2B,0xFF6F4733,
0xFF7F533F,0xFF8B5F47,0xFF9B6B53,0xFFA77B5F,0xFFB7876B,0xFFC3937B,0xFFD3A38B,0xFFE3B397,
0xFFAB8BA3,0xFF9F7F97,0xFF937387,0xFF8B677B,0xFF7F5B6F,0xFF775363,0xFF6B4B57,0xFF5F3F4B,
0xFF573743,0xFF4B2F37,0xFF43272F,0xFF371F23,0xFF2B171B,0xFF231313,0xFF170B0B,0xFF0F0707,
0xFFBB739F,0xFFAF6B8F,0xFFA35F83,0xFF975777,0xFF8B4F6B,0xFF7F4B5F,0xFF734353,0xFF6B3B4B,
0xFF5F333F,0xFF532B37,0xFF47232B,0xFF3B1F23,0xFF2F171B,0xFF231313,0xFF170B0B,0xFF0F0707,
0xFFDBC3BB,0xFFCBB3A7,0xFFBFA39B,0xFFAF978B,0xFFA3877B,0xFF977B6F,0xFF876F5F,0xFF7B6353,
0xFF6B5747,0xFF5F4B3B,0xFF533F33,0xFF433327,0xFF372B1F,0xFF271F17,0xFF1B130F,0xFF0F0B07,
0xFF6F837B,0xFF677B6F,0xFF5F7367,0xFF576B5F,0xFF4F6357,0xFF475B4F,0xFF3F5347,0xFF374B3F,
0xFF2F4337,0xFF2B3B2F,0xFF233327,0xFF1F2B1F,0xFF172317,0xFF0F1B13,0xFF0B130B,0xFF070B07,
0xFFFFF31B,0xFFEFDF17,0xFFDBCB13,0xFFCBB70F,0xFFBBA70F,0xFFAB970B,0xFF9B8307,0xFF8B7307,
0xFF7B6307,0xFF6B5300,0xFF5B4700,0xFF4B3700,0xFF3B2B00,0xFF2B1F00,0xFF1B0F00,0xFF0B0700,
0xFF0000FF,0xFF0B0BEF,0xFF1313DF,0xFF1B1BCF,0xFF2323BF,0xFF2B2BAF,0xFF2F2F9F,0xFF2F2F8F,
0xFF2F2F7F,0xFF2F2F6F,0xFF2F2F5F,0xFF2B2B4F,0xFF23233F,0xFF1B1B2F,0xFF13131F,0xFF0B0B0F,
0xFF2B0000,0xFF3B0000,0xFF4B0700,0xFF5F0700,0xFF6F0F00,0xFF7F1707,0xFF931F07,0xFFA3270B,
0xFFB7330F,0xFFC34B1B,0xFFCF632B,0xFFDB7F3B,0xFFE3974F,0xFFE7AB5F,0xFFEFBF77,0xFFF7D38B,
0xFFA77B3B,0xFFB79B37,0xFFC7C337,0xFFE7E357,0xFF7FBFFF,0xFFABE7FF,0xFFD7FFFF,0xFF670000,
0xFF8B0000,0xFFB30000,0xFFD70000,0xFFFF0000,0xFFFFF393,0xFFFFF7C7,0xFFFFFFFF,0x009F5B53
};
bool CImageLoaderLMP::isALoadableFileExtension(const io::path& filename) const
{
return core::hasFileExtension ( filename, "lmp" );
}
bool CImageLoaderLMP::isALoadableFileFormat(irr::io::IReadFile* file) const
{
return false;
}
/*!
Quake1, Quake2, Hallife lmp texture
*/
IImage* CImageLoaderLMP::loadImage(irr::io::IReadFile* file) const
{
SLMPHeader header;
file->seek(0);
file->read(&header, sizeof(header));
// maybe palette file
u32 rawtexsize = header.width * header.height;
if ( rawtexsize + sizeof ( header ) != (u32)file->getSize() )
return 0;
u8 *rawtex = new u8 [ rawtexsize ];
file->read(rawtex, rawtexsize);
IImage* image = new CImage(ECF_A8R8G8B8, core::dimension2d<u32>(header.width, header.height));
CColorConverter::convert8BitTo32Bit(rawtex, (u8*)image->lock(), header.width, header.height, (u8*) colormap_h, 0, false);
image->unlock();
delete [] rawtex;
return image;
}
IImageLoader* createImageLoaderLMP()
{
return new irr::video::CImageLoaderLMP();
}
#endif
#ifdef _IRR_COMPILE_WITH_WAL_LOADER_
// Palette quake2 demo pics/colormap.pcx, last is transparent
static const u32 colormap_pcx[256] = {
0xFF000000,0xFF0F0F0F,0xFF1F1F1F,0xFF2F2F2F,0xFF3F3F3F,0xFF4B4B4B,0xFF5B5B5B,0xFF6B6B6B,
0xFF7B7B7B,0xFF8B8B8B,0xFF9B9B9B,0xFFABABAB,0xFFBBBBBB,0xFFCBCBCB,0xFFDBDBDB,0xFFEBEBEB,
0xFF634B23,0xFF5B431F,0xFF533F1F,0xFF4F3B1B,0xFF47371B,0xFF3F2F17,0xFF3B2B17,0xFF332713,
0xFF2F2313,0xFF2B1F13,0xFF271B0F,0xFF23170F,0xFF1B130B,0xFF170F0B,0xFF130F07,0xFF0F0B07,
0xFF5F5F6F,0xFF5B5B67,0xFF5B535F,0xFF574F5B,0xFF534B53,0xFF4F474B,0xFF473F43,0xFF3F3B3B,
0xFF3B3737,0xFF332F2F,0xFF2F2B2B,0xFF272727,0xFF232323,0xFF1B1B1B,0xFF171717,0xFF131313,
0xFF8F7753,0xFF7B6343,0xFF735B3B,0xFF674F2F,0xFFCF974B,0xFFA77B3B,0xFF8B672F,0xFF6F5327,
0xFFEB9F27,0xFFCB8B23,0xFFAF771F,0xFF93631B,0xFF774F17,0xFF5B3B0F,0xFF3F270B,0xFF231707,
0xFFA73B2B,0xFF9F2F23,0xFF972B1B,0xFF8B2713,0xFF7F1F0F,0xFF73170B,0xFF671707,0xFF571300,
0xFF4B0F00,0xFF430F00,0xFF3B0F00,0xFF330B00,0xFF2B0B00,0xFF230B00,0xFF1B0700,0xFF130700,
0xFF7B5F4B,0xFF735743,0xFF6B533F,0xFF674F3B,0xFF5F4737,0xFF574333,0xFF533F2F,0xFF4B372B,
0xFF433327,0xFF3F2F23,0xFF37271B,0xFF2F2317,0xFF271B13,0xFF1F170F,0xFF170F0B,0xFF0F0B07,
0xFF6F3B17,0xFF5F3717,0xFF532F17,0xFF432B17,0xFF372313,0xFF271B0F,0xFF1B130B,0xFF0F0B07,
0xFFB35B4F,0xFFBF7B6F,0xFFCB9B93,0xFFD7BBB7,0xFFCBD7DF,0xFFB3C7D3,0xFF9FB7C3,0xFF87A7B7,
0xFF7397A7,0xFF5B879B,0xFF47778B,0xFF2F677F,0xFF17536F,0xFF134B67,0xFF0F435B,0xFF0B3F53,
0xFF07374B,0xFF072F3F,0xFF072733,0xFF001F2B,0xFF00171F,0xFF000F13,0xFF00070B,0xFF000000,
0xFF8B5757,0xFF834F4F,0xFF7B4747,0xFF734343,0xFF6B3B3B,0xFF633333,0xFF5B2F2F,0xFF572B2B,
0xFF4B2323,0xFF3F1F1F,0xFF331B1B,0xFF2B1313,0xFF1F0F0F,0xFF130B0B,0xFF0B0707,0xFF000000,
0xFF979F7B,0xFF8F9773,0xFF878B6B,0xFF7F8363,0xFF777B5F,0xFF737357,0xFF6B6B4F,0xFF636347,
0xFF5B5B43,0xFF4F4F3B,0xFF434333,0xFF37372B,0xFF2F2F23,0xFF23231B,0xFF171713,0xFF0F0F0B,
0xFF9F4B3F,0xFF934337,0xFF8B3B2F,0xFF7F3727,0xFF772F23,0xFF6B2B1B,0xFF632317,0xFF571F13,
0xFF4F1B0F,0xFF43170B,0xFF37130B,0xFF2B0F07,0xFF1F0B07,0xFF170700,0xFF0B0000,0xFF000000,
0xFF777BCF,0xFF6F73C3,0xFF676BB7,0xFF6363A7,0xFF5B5B9B,0xFF53578F,0xFF4B4F7F,0xFF474773,
0xFF3F3F67,0xFF373757,0xFF2F2F4B,0xFF27273F,0xFF231F2F,0xFF1B1723,0xFF130F17,0xFF0B0707,
0xFF9BAB7B,0xFF8F9F6F,0xFF879763,0xFF7B8B57,0xFF73834B,0xFF677743,0xFF5F6F3B,0xFF576733,
0xFF4B5B27,0xFF3F4F1B,0xFF374313,0xFF2F3B0B,0xFF232F07,0xFF1B2300,0xFF131700,0xFF0B0F00,
0xFF00FF00,0xFF23E70F,0xFF3FD31B,0xFF53BB27,0xFF5FA72F,0xFF5F8F33,0xFF5F7B33,0xFFFFFFFF,
0xFFFFFFD3,0xFFFFFFA7,0xFFFFFF7F,0xFFFFFF53,0xFFFFFF27,0xFFFFEB1F,0xFFFFD717,0xFFFFBF0F,
0xFFFFAB07,0xFFFF9300,0xFFEF7F00,0xFFE36B00,0xFFD35700,0xFFC74700,0xFFB73B00,0xFFAB2B00,
0xFF9B1F00,0xFF8F1700,0xFF7F0F00,0xFF730700,0xFF5F0000,0xFF470000,0xFF2F0000,0xFF1B0000,
0xFFEF0000,0xFF3737FF,0xFFFF0000,0xFF0000FF,0xFF2B2B23,0xFF1B1B17,0xFF13130F,0xFFEB977F,
0xFFC37353,0xFF9F5733,0xFF7B3F1B,0xFFEBD3C7,0xFFC7AB9B,0xFFA78B77,0xFF876B57,0x009F5B53
};
/*!
Halflife
*/
bool CImageLoaderWAL2::isALoadableFileExtension(const io::path& filename) const
{
// embedded in Wad(WAD3 format). originally it has no extension
return core::hasFileExtension ( filename, "wal2" );
}
bool CImageLoaderWAL2::isALoadableFileFormat(irr::io::IReadFile* file) const
{
return false;
}
/*
Halflite Texture WAD
*/
IImage* CImageLoaderWAL2::loadImage(irr::io::IReadFile* file) const
{
miptex_halflife header;
file->seek(0);
file->read(&header, sizeof(header));
#ifdef __BIG_ENDIAN__
header.width = os::Byteswap::byteswap(header.width);
header.height = os::Byteswap::byteswap(header.height);
#endif
// palette
//u32 paletteofs = header.mipmap[0] + ((rawtexsize * 85) >> 6) + 2;
u32 *pal = new u32 [ 192 + 256 ];
u8 *s = (u8*) pal;
file->seek ( file->getSize() - 768 - 2 );
file->read ( s, 768 );
u32 i;
for ( i = 0; i < 256; ++i, s+= 3 )
{
pal [ 192 + i ] = 0xFF000000 | s[0] << 16 | s[1] << 8 | s[2];
}
ECOLOR_FORMAT format = ECF_R8G8B8;
// transparency in filename;-) funny. rgb:0x0000FF is colorkey
if ( file->getFileName().findFirst ( '{' ) >= 0 )
{
format = ECF_A8R8G8B8;
pal [ 192 + 255 ] &= 0x00FFFFFF;
}
u32 rawtexsize = header.width * header.height;
u8 *rawtex = new u8 [ rawtexsize ];
file->seek ( header.mipmap[0] );
file->read(rawtex, rawtexsize);
IImage* image = new CImage(format, core::dimension2d<u32>(header.width, header.height));
switch ( format )
{
case ECF_R8G8B8:
CColorConverter::convert8BitTo24Bit(rawtex, (u8*)image->lock(), header.width, header.height, (u8*) pal + 768, 0, false);
break;
case ECF_A8R8G8B8:
CColorConverter::convert8BitTo32Bit(rawtex, (u8*)image->lock(), header.width, header.height, (u8*) pal + 768, 0, false);
break;
}
image->unlock();
delete [] rawtex;
delete [] pal;
return image;
}
bool CImageLoaderWAL::isALoadableFileExtension(const io::path& filename) const
{
return core::hasFileExtension ( filename, "wal" );
}
bool CImageLoaderWAL::isALoadableFileFormat(irr::io::IReadFile* file) const
{
return false;
}
/*!
quake2
*/
IImage* CImageLoaderWAL::loadImage(irr::io::IReadFile* file) const
{
miptex_quake2 header;
file->seek(0);
file->read(&header, sizeof(header));
#ifdef __BIG_ENDIAN__
header.width = os::Byteswap::byteswap(header.width);
header.height = os::Byteswap::byteswap(header.height);
#endif
u32 rawtexsize = header.width * header.height;
u8 *rawtex = new u8 [ rawtexsize ];
file->seek ( header.mipmap[0] );
file->read(rawtex, rawtexsize);
IImage* image = new CImage(ECF_A8R8G8B8, core::dimension2d<u32>(header.width, header.height));
CColorConverter::convert8BitTo32Bit(rawtex, (u8*)image->lock(), header.width, header.height, (u8*) colormap_pcx, 0, false);
image->unlock();
delete [] rawtex;
return image;
}
IImageLoader* createImageLoaderWAL()
{
return new irr::video::CImageLoaderWAL();
}
IImageLoader* createImageLoaderHalfLife()
{
return new irr::video::CImageLoaderWAL2();
}
#endif
} // end namespace video
} // end namespace irr

View File

@ -1,100 +0,0 @@
// Copyright (C) 2004 Murphy McCauley
// Copyright (C) 2007-2012 Christian Stehno
// This file is part of the "Irrlicht Engine".
// For conditions of distribution and use, see copyright notice in irrlicht.h
/*
Thanks to:
Max McGuire for his Flipcode article about WAL textures
Nikolaus Gebhardt for the Irrlicht 3D engine
*/
#ifndef __C_IMAGE_LOADER_WAL_H_INCLUDED__
#define __C_IMAGE_LOADER_WAL_H_INCLUDED__
#include "IrrCompileConfig.h"
#include "IImageLoader.h"
namespace irr
{
namespace video
{
#ifdef _IRR_COMPILE_WITH_LMP_LOADER_
// byte-align structures
#include "irrpack.h"
struct SLMPHeader {
u32 width; // width
u32 height; // height
// variably sized
} PACK_STRUCT;
// Default alignment
#include "irrunpack.h"
//! An Irrlicht image loader for Quake1,2 engine lmp textures/palette
class CImageLoaderLMP : public irr::video::IImageLoader
{
public:
virtual bool isALoadableFileExtension(const io::path& filename) const;
virtual bool isALoadableFileFormat(irr::io::IReadFile* file) const;
virtual irr::video::IImage* loadImage(irr::io::IReadFile* file) const;
};
#endif
#ifdef _IRR_COMPILE_WITH_WAL_LOADER_
//! An Irrlicht image loader for quake2 wal engine textures
class CImageLoaderWAL : public irr::video::IImageLoader
{
public:
virtual bool isALoadableFileExtension(const io::path& filename) const;
virtual bool isALoadableFileFormat(irr::io::IReadFile* file) const;
virtual irr::video::IImage* loadImage(irr::io::IReadFile* file) const;
};
//! An Irrlicht image loader for Halflife 1 engine textures
class CImageLoaderWAL2 : public irr::video::IImageLoader
{
public:
virtual bool isALoadableFileExtension(const io::path& filename) const;
virtual bool isALoadableFileFormat(irr::io::IReadFile* file) const;
virtual irr::video::IImage* loadImage(irr::io::IReadFile* file) const;
};
// byte-align structures
#include "irrpack.h"
// Halfelife wad3 type 67 file
struct miptex_halflife
{
c8 name[16];
u32 width, height;
u32 mipmap[4]; // four mip maps stored
} PACK_STRUCT;
//quake2 texture
struct miptex_quake2
{
c8 name[32];
u32 width;
u32 height;
u32 mipmap[4]; // four mip maps stored
c8 animname[32]; // next frame in animation chain
s32 flags;
s32 contents;
s32 value;
} PACK_STRUCT;
// Default alignment
#include "irrunpack.h"
#endif
}
}
#endif

View File

@ -1,162 +0,0 @@
// 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 "CImageWriterPCX.h"
#ifdef _IRR_COMPILE_WITH_PCX_WRITER_
#include "CImageLoaderPCX.h"
#include "IWriteFile.h"
#include "os.h" // for logging
#include "irrString.h"
namespace irr
{
namespace video
{
IImageWriter* createImageWriterPCX()
{
return new CImageWriterPCX;
}
CImageWriterPCX::CImageWriterPCX()
{
#ifdef _DEBUG
setDebugName("CImageWriterPCX");
#endif
}
bool CImageWriterPCX::isAWriteableFileExtension(const io::path& filename) const
{
return core::hasFileExtension ( filename, "pcx" );
}
bool CImageWriterPCX::writeImage(io::IWriteFile *file, IImage *image,u32 param) const
{
if (!file || !image)
return false;
u8 d1;
u16 d2;
u32 i;
d1 = 10; // Manufacturer
file->write(&d1, 1);
d1 = 5; // Version
file->write(&d1, 1);
d1 = 1; // Encoding
file->write(&d1, 1);
d1 = 8; // Bits per Pixel
file->write(&d1, 1);
d2 = 0; // pixel origin
file->write(&d2, 2);
file->write(&d2, 2);
d2 = image->getDimension().Width-1; // width
#ifdef __BIG_ENDIAN__
d2 = os::Byteswap::byteswap(d2);
#endif
file->write(&d2, 2);
d2 = image->getDimension().Height-1; // height
#ifdef __BIG_ENDIAN__
d2 = os::Byteswap::byteswap(d2);
#endif
file->write(&d2, 2);
d2 = 300; // dpi
#ifdef __BIG_ENDIAN__
d2 = os::Byteswap::byteswap(d2);
#endif
file->write(&d2, 2);
file->write(&d2, 2);
d2 = 0; // palette (not used)
for (i=0; i<24; ++i)
{
file->write(&d2, 2);
}
d1 = 0; // reserved
file->write(&d1, 1);
d1 = 3; // planes
file->write(&d1, 1);
d2 = image->getDimension().Width; // pitch
if (d2&0x0001) // must be even
++d2;
#ifdef __BIG_ENDIAN__
d2 = os::Byteswap::byteswap(d2);
#endif
file->write(&d2, 2);
d2 = 1; // color mode
#ifdef __BIG_ENDIAN__
d2 = os::Byteswap::byteswap(d2);
#endif
file->write(&d2, 2);
d2 = 800; // screen width
#ifdef __BIG_ENDIAN__
d2 = os::Byteswap::byteswap(d2);
#endif
file->write(&d2, 2);
d2 = 600; // screen height
#ifdef __BIG_ENDIAN__
d2 = os::Byteswap::byteswap(d2);
#endif
file->write(&d2, 2);
d2 = 0; // filler (not used)
for (i=0; i<27; ++i)
{
file->write(&d2, 2);
}
u8 cnt, value;
for (i=0; i<image->getDimension().Height; ++i)
{
cnt = 0;
value = 0;
for (u32 j=0; j<3; ++j) // color planes
{
for (u32 k=0; k<image->getDimension().Width; ++k)
{
const SColor pix = image->getPixel(k,i);
if ((cnt!=0) && (cnt<63) &&
(((j==0) && (value==pix.getRed())) ||
((j==1) && (value==pix.getGreen())) ||
((j==2) && (value==pix.getBlue()))))
{
++cnt;
}
else
{
if (cnt!=0)
{
if ((cnt>1) || ((value&0xc0)==0xc0))
{
cnt |= 0xc0;
file->write(&cnt, 1);
}
file->write(&value, 1);
}
cnt=1;
if (j==0)
value=(u8)pix.getRed();
else if (j==1)
value=(u8)pix.getGreen();
else if (j==2)
value=(u8)pix.getBlue();
}
}
}
if ((cnt>1) || ((value&0xc0)==0xc0))
{
cnt |= 0xc0;
file->write(&cnt, 1);
}
file->write(&value, 1);
}
return true;
}
} // namespace video
} // namespace irr
#endif

View File

@ -1,37 +0,0 @@
// 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_IMAGE_WRITER_PCX_H_INCLUDED__
#define _C_IMAGE_WRITER_PCX_H_INCLUDED__
#include "IrrCompileConfig.h"
#ifdef _IRR_COMPILE_WITH_PCX_WRITER_
#include "IImageWriter.h"
namespace irr
{
namespace video
{
class CImageWriterPCX : public IImageWriter
{
public:
//! constructor
CImageWriterPCX();
//! return true if this writer can write a file with the given extension
virtual bool isAWriteableFileExtension(const io::path& filename) const;
//! write image to file
virtual bool writeImage(io::IWriteFile *file, IImage *image, u32 param) const;
};
} // namespace video
} // namespace irr
#endif
#endif // _C_IMAGE_WRITER_PCX_H_INCLUDED__

View File

@ -1,105 +0,0 @@
// 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 "CImageWriterPPM.h"
#ifdef _IRR_COMPILE_WITH_PPM_WRITER_
#include "IWriteFile.h"
#include "IImage.h"
#include "dimension2d.h"
#include "irrString.h"
namespace irr
{
namespace video
{
IImageWriter* createImageWriterPPM()
{
return new CImageWriterPPM;
}
CImageWriterPPM::CImageWriterPPM()
{
#ifdef _DEBUG
setDebugName("CImageWriterPPM");
#endif
}
bool CImageWriterPPM::isAWriteableFileExtension(const io::path& filename) const
{
return core::hasFileExtension ( filename, "ppm" );
}
bool CImageWriterPPM::writeImage(io::IWriteFile *file, IImage *image, u32 param) const
{
char cache[70];
int size;
const core::dimension2d<u32>& imageSize = image->getDimension();
const bool binary = false;
if (binary)
size = snprintf(cache, 70, "P6\n");
else
size = snprintf(cache, 70, "P3\n");
if (file->write(cache, size) != size)
return false;
size = snprintf(cache, 70, "%d %d\n", imageSize.Width, imageSize.Height);
if (file->write(cache, size) != size)
return false;
size = snprintf(cache, 70, "255\n");
if (file->write(cache, size) != size)
return false;
if (binary)
{
for (u32 h = 0; h < imageSize.Height; ++h)
{
for (u32 c = 0; c < imageSize.Width; ++c)
{
const video::SColor& pixel = image->getPixel(c, h);
const u8 r = (u8)(pixel.getRed() & 0xff);
const u8 g = (u8)(pixel.getGreen() & 0xff);
const u8 b = (u8)(pixel.getBlue() & 0xff);
file->write(&r, 1);
file->write(&g, 1);
file->write(&b, 1);
}
}
}
else
{
s32 n = 0;
for (u32 h = 0; h < imageSize.Height; ++h)
{
for (u32 c = 0; c < imageSize.Width; ++c, ++n)
{
const video::SColor& pixel = image->getPixel(c, h);
size = snprintf(cache, 70, "%.3u %.3u %.3u%s", pixel.getRed(), pixel.getGreen(), pixel.getBlue(), n % 5 == 4 ? "\n" : " ");
if (file->write(cache, size) != size)
return false;
}
}
}
return true;
}
} // namespace video
} // namespace irr
#endif

View File

@ -1,37 +0,0 @@
// 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_IMAGE_WRITER_PPM_H_INCLUDED__
#define _C_IMAGE_WRITER_PPM_H_INCLUDED__
#include "IrrCompileConfig.h"
#ifdef _IRR_COMPILE_WITH_PPM_WRITER_
#include "IImageWriter.h"
namespace irr
{
namespace video
{
class CImageWriterPPM : public IImageWriter
{
public:
//! constructor
CImageWriterPPM();
//! return true if this writer can write a file with the given extension
virtual bool isAWriteableFileExtension(const io::path& filename) const;
//! write image to file
virtual bool writeImage(io::IWriteFile *file, IImage *image, u32 param) const;
};
} // namespace video
} // namespace irr
#endif // _C_IMAGE_WRITER_PPM_H_INCLUDED__
#endif

View File

@ -1,46 +0,0 @@
// 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 "CImageWriterPSD.h"
#ifdef _IRR_COMPILE_WITH_PSD_WRITER_
#include "CImageLoaderPSD.h"
#include "IWriteFile.h"
#include "os.h" // for logging
#include "irrString.h"
namespace irr
{
namespace video
{
IImageWriter* createImageWriterPSD()
{
return new CImageWriterPSD;
}
CImageWriterPSD::CImageWriterPSD()
{
#ifdef _DEBUG
setDebugName("CImageWriterPSD");
#endif
}
bool CImageWriterPSD::isAWriteableFileExtension(const io::path& filename) const
{
return core::hasFileExtension ( filename, "psd" );
}
bool CImageWriterPSD::writeImage(io::IWriteFile *file, IImage *image,u32 param) const
{
os::Printer::log("PSD writer not yet implemented. Image not written.", ELL_WARNING);
return false;
}
} // namespace video
} // namespace irr
#endif

View File

@ -1,37 +0,0 @@
// 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_IMAGE_WRITER_PSD_H_INCLUDED__
#define _C_IMAGE_WRITER_PSD_H_INCLUDED__
#include "IrrCompileConfig.h"
#ifdef _IRR_COMPILE_WITH_PSD_WRITER_
#include "IImageWriter.h"
namespace irr
{
namespace video
{
class CImageWriterPSD : public IImageWriter
{
public:
//! constructor
CImageWriterPSD();
//! return true if this writer can write a file with the given extension
virtual bool isAWriteableFileExtension(const io::path& filename) const;
//! write image to file
virtual bool writeImage(io::IWriteFile *file, IImage *image,u32 param) const;
};
} // namespace video
} // namespace irr
#endif // _I_IMAGE_WRITER_PSD_H_INCLUDED__
#endif

View File

@ -1,147 +0,0 @@
// 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 "CImageWriterTGA.h"
#ifdef _IRR_COMPILE_WITH_TGA_WRITER_
#include "CImageLoaderTGA.h"
#include "IWriteFile.h"
#include "CColorConverter.h"
#include "irrString.h"
namespace irr
{
namespace video
{
IImageWriter* createImageWriterTGA()
{
return new CImageWriterTGA;
}
CImageWriterTGA::CImageWriterTGA()
{
#ifdef _DEBUG
setDebugName("CImageWriterTGA");
#endif
}
bool CImageWriterTGA::isAWriteableFileExtension(const io::path& filename) const
{
return core::hasFileExtension ( filename, "tga" );
}
bool CImageWriterTGA::writeImage(io::IWriteFile *file, IImage *image,u32 param) const
{
STGAHeader imageHeader;
imageHeader.IdLength = 0;
imageHeader.ColorMapType = 0;
imageHeader.ImageType = 2;
imageHeader.FirstEntryIndex[0] = 0;
imageHeader.FirstEntryIndex[1] = 0;
imageHeader.ColorMapLength = 0;
imageHeader.ColorMapEntrySize = 0;
imageHeader.XOrigin[0] = 0;
imageHeader.XOrigin[1] = 0;
imageHeader.YOrigin[0] = 0;
imageHeader.YOrigin[1] = 0;
imageHeader.ImageWidth = image->getDimension().Width;
imageHeader.ImageHeight = image->getDimension().Height;
// top left of image is the top. the image loader needs to
// be fixed to only swap/flip
imageHeader.ImageDescriptor = (1 << 5);
// chances are good we'll need to swizzle data, so i'm going
// to convert and write one scan line at a time. it's also
// a bit cleaner this way
void (*CColorConverter_convertFORMATtoFORMAT)(const void*, s32, void*) = 0;
switch(image->getColorFormat())
{
case ECF_A8R8G8B8:
CColorConverter_convertFORMATtoFORMAT
= CColorConverter::convert_A8R8G8B8toA8R8G8B8;
imageHeader.PixelDepth = 32;
imageHeader.ImageDescriptor |= 8;
break;
case ECF_A1R5G5B5:
CColorConverter_convertFORMATtoFORMAT
= CColorConverter::convert_A1R5G5B5toA1R5G5B5;
imageHeader.PixelDepth = 16;
imageHeader.ImageDescriptor |= 1;
break;
case ECF_R5G6B5:
CColorConverter_convertFORMATtoFORMAT
= CColorConverter::convert_R5G6B5toA1R5G5B5;
imageHeader.PixelDepth = 16;
imageHeader.ImageDescriptor |= 1;
break;
case ECF_R8G8B8:
CColorConverter_convertFORMATtoFORMAT
= CColorConverter::convert_R8G8B8toR8G8B8;
imageHeader.PixelDepth = 24;
imageHeader.ImageDescriptor |= 0;
break;
#ifndef _DEBUG
default:
break;
#endif
}
// couldn't find a color converter
if (!CColorConverter_convertFORMATtoFORMAT)
return false;
if (file->write(&imageHeader, sizeof(imageHeader)) != sizeof(imageHeader))
return false;
u8* scan_lines = (u8*)image->lock();
if (!scan_lines)
return false;
// size of one pixel in bytes
u32 pixel_size = image->getBytesPerPixel();
// length of one row of the source image in bytes
u32 row_stride = (pixel_size * imageHeader.ImageWidth);
// length of one output row in bytes
s32 row_size = ((imageHeader.PixelDepth / 8) * imageHeader.ImageWidth);
// allocate a row do translate data into
u8* row_pointer = new u8[row_size];
u32 y;
for (y = 0; y < imageHeader.ImageHeight; ++y)
{
// source, length [pixels], destination
if (image->getColorFormat()==ECF_R8G8B8)
CColorConverter::convert24BitTo24Bit(&scan_lines[y * row_stride], row_pointer, imageHeader.ImageWidth, 1, 0, 0, true);
else
CColorConverter_convertFORMATtoFORMAT(&scan_lines[y * row_stride], imageHeader.ImageWidth, row_pointer);
if (file->write(row_pointer, row_size) != row_size)
break;
}
delete [] row_pointer;
image->unlock();
STGAFooter imageFooter;
imageFooter.ExtensionOffset = 0;
imageFooter.DeveloperOffset = 0;
strncpy(imageFooter.Signature, "TRUEVISION-XFILE.", 18);
if (file->write(&imageFooter, sizeof(imageFooter)) < (s32)sizeof(imageFooter))
return false;
return imageHeader.ImageHeight <= y;
}
} // namespace video
} // namespace irr
#endif

View File

@ -1,37 +0,0 @@
// 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_IMAGE_WRITER_TGA_H_INCLUDED__
#define _C_IMAGE_WRITER_TGA_H_INCLUDED__
#include "IrrCompileConfig.h"
#ifdef _IRR_COMPILE_WITH_TGA_WRITER_
#include "IImageWriter.h"
namespace irr
{
namespace video
{
class CImageWriterTGA : public IImageWriter
{
public:
//! constructor
CImageWriterTGA();
//! return true if this writer can write a file with the given extension
virtual bool isAWriteableFileExtension(const io::path& filename) const;
//! write image to file
virtual bool writeImage(io::IWriteFile *file, IImage *image,u32 param) const;
};
} // namespace video
} // namespace irr
#endif // _C_IMAGE_WRITER_TGA_H_INCLUDED__
#endif

View File

@ -11,7 +11,6 @@
#include "IAnimatedMesh.h"
#include "IMaterialRenderer.h"
#include "IFileSystem.h"
#include "CShadowVolumeSceneNode.h"
namespace irr
{
@ -24,7 +23,7 @@ namespace scene
CMeshSceneNode::CMeshSceneNode(IMesh* mesh, 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),
: IMeshSceneNode(parent, mgr, id, position, rotation, scale), Mesh(0),
PassCount(0), ReadOnlyMaterials(false)
{
#ifdef _DEBUG
@ -38,8 +37,6 @@ CMeshSceneNode::CMeshSceneNode(IMesh* mesh, ISceneNode* parent, ISceneManager* m
//! destructor
CMeshSceneNode::~CMeshSceneNode()
{
if (Shadow)
Shadow->drop();
if (Mesh)
Mesh->drop();
}
@ -128,9 +125,6 @@ void CMeshSceneNode::render()
driver->setTransform(video::ETS_WORLD, AbsoluteTransformation);
Box = Mesh->getBoundingBox();
if (Shadow && PassCount==1)
Shadow->updateShadowVolumes();
// for debug purposes only:
bool renderMeshes = true;
@ -232,12 +226,6 @@ void CMeshSceneNode::render()
//! or to remove attached childs.
bool CMeshSceneNode::removeChild(ISceneNode* child)
{
if (child && Shadow == child)
{
Shadow->drop();
Shadow = 0;
}
return ISceneNode::removeChild(child);
}
@ -294,25 +282,6 @@ void CMeshSceneNode::setMesh(IMesh* mesh)
}
//! Creates shadow volume scene node as child of this node
//! and returns a pointer to it.
IShadowVolumeSceneNode* CMeshSceneNode::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 CMeshSceneNode::copyMaterials()
{
Materials.clear();
@ -432,8 +401,6 @@ ISceneNode* CMeshSceneNode::clone(ISceneNode* newParent, ISceneManager* newManag
nb->cloneMembers(this, newManager);
nb->ReadOnlyMaterials = ReadOnlyMaterials;
nb->Materials = Materials;
nb->Shadow = Shadow;
nb->Shadow->grab();
if (newParent)
nb->drop();

View File

@ -60,11 +60,6 @@ namespace scene
//! Returns the current mesh
virtual IMesh* getMesh(void) { return Mesh; }
//! 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);
//! 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. */
@ -90,7 +85,6 @@ namespace scene
video::SMaterial ReadOnlyMaterial;
IMesh* Mesh;
IShadowVolumeSceneNode* Shadow;
s32 PassCount;
bool ReadOnlyMaterials;

View File

@ -121,33 +121,6 @@ CNullDriver::CNullDriver(io::IFileSystem* io, const core::dimension2d<u32>& scre
// create surface loader
#ifdef _IRR_COMPILE_WITH_HALFLIFE_LOADER_
SurfaceLoader.push_back(video::createImageLoaderHalfLife());
#endif
#ifdef _IRR_COMPILE_WITH_WAL_LOADER_
SurfaceLoader.push_back(video::createImageLoaderWAL());
#endif
#ifdef _IRR_COMPILE_WITH_LMP_LOADER_
SurfaceLoader.push_back(video::createImageLoaderLMP());
#endif
#ifdef _IRR_COMPILE_WITH_PPM_LOADER_
SurfaceLoader.push_back(video::createImageLoaderPPM());
#endif
#ifdef _IRR_COMPILE_WITH_RGB_LOADER_
SurfaceLoader.push_back(video::createImageLoaderRGB());
#endif
#ifdef _IRR_COMPILE_WITH_PSD_LOADER_
SurfaceLoader.push_back(video::createImageLoaderPSD());
#endif
#ifdef _IRR_COMPILE_WITH_DDS_LOADER_
SurfaceLoader.push_back(video::createImageLoaderDDS());
#endif
#ifdef _IRR_COMPILE_WITH_PCX_LOADER_
SurfaceLoader.push_back(video::createImageLoaderPCX());
#endif
#ifdef _IRR_COMPILE_WITH_TGA_LOADER_
SurfaceLoader.push_back(video::createImageLoaderTGA());
#endif
#ifdef _IRR_COMPILE_WITH_PNG_LOADER_
SurfaceLoader.push_back(video::createImageLoaderPNG());
#endif
@ -157,20 +130,6 @@ CNullDriver::CNullDriver(io::IFileSystem* io, const core::dimension2d<u32>& scre
#ifdef _IRR_COMPILE_WITH_BMP_LOADER_
SurfaceLoader.push_back(video::createImageLoaderBMP());
#endif
#ifdef _IRR_COMPILE_WITH_PPM_WRITER_
SurfaceWriter.push_back(video::createImageWriterPPM());
#endif
#ifdef _IRR_COMPILE_WITH_PCX_WRITER_
SurfaceWriter.push_back(video::createImageWriterPCX());
#endif
#ifdef _IRR_COMPILE_WITH_PSD_WRITER_
SurfaceWriter.push_back(video::createImageWriterPSD());
#endif
#ifdef _IRR_COMPILE_WITH_TGA_WRITER_
SurfaceWriter.push_back(video::createImageWriterTGA());
#endif
#ifdef _IRR_COMPILE_WITH_JPG_WRITER_
SurfaceWriter.push_back(video::createImageWriterJPG());
#endif

View File

@ -11,7 +11,6 @@
#include "IAnimatedMesh.h"
#include "IMaterialRenderer.h"
#include "os.h"
#include "CShadowVolumeSceneNode.h"
namespace irr
{
@ -24,7 +23,7 @@ COctreeSceneNode::COctreeSceneNode(ISceneNode* parent, ISceneManager* mgr,
s32 id, s32 minimalPolysPerNode)
: IMeshSceneNode(parent, mgr, id), StdOctree(0), LightMapOctree(0),
TangentsOctree(0), VertexType((video::E_VERTEX_TYPE)-1),
MinimalPolysPerNode(minimalPolysPerNode), Mesh(0), Shadow(0),
MinimalPolysPerNode(minimalPolysPerNode), Mesh(0),
UseVBOs(OCTREE_USE_HARDWARE), UseVisibilityAndVBOs(OCTREE_USE_VISIBILITY),
BoxBased(OCTREE_BOX_BASED)
{
@ -37,8 +36,6 @@ COctreeSceneNode::COctreeSceneNode(ISceneNode* parent, ISceneManager* mgr,
//! destructor
COctreeSceneNode::~COctreeSceneNode()
{
if (Shadow)
Shadow->drop();
deleteTree();
}
@ -104,9 +101,6 @@ void COctreeSceneNode::render()
driver->setTransform(video::ETS_WORLD, AbsoluteTransformation);
if (Shadow)
Shadow->updateShadowVolumes();
SViewFrustum frust = *camera->getViewFrustum();
//transform the frustum to the current absolute transformation
@ -291,35 +285,10 @@ void COctreeSceneNode::render()
//! or to remove attached childs.
bool COctreeSceneNode::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* COctreeSceneNode::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;
}
//! returns the axis aligned bounding box of this node
const core::aabbox3d<f32>& COctreeSceneNode::getBoundingBox() const
{

View File

@ -66,11 +66,6 @@ namespace scene
//! Check if the scene node should not copy the materials of the mesh but use them in a read only style
virtual bool isReadOnlyMaterials() 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=10000.0f);
//! 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.
@ -99,7 +94,6 @@ namespace scene
s32 PassCount;
IMesh * Mesh;
IShadowVolumeSceneNode* Shadow;
//! use VBOs for rendering where possible
bool UseVBOs;
//! use visibility information together with VBOs

View File

@ -1,419 +0,0 @@
// 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 "CShadowVolumeSceneNode.h"
#include "ISceneManager.h"
#include "IMesh.h"
#include "IVideoDriver.h"
#include "ICameraSceneNode.h"
#include "SViewFrustum.h"
#include "SLight.h"
#include "os.h"
namespace irr
{
namespace scene
{
//! constructor
CShadowVolumeSceneNode::CShadowVolumeSceneNode(const IMesh* shadowMesh, ISceneNode* parent,
ISceneManager* mgr, s32 id, bool zfailmethod, f32 infinity)
: IShadowVolumeSceneNode(parent, mgr, id),
ShadowMesh(0), IndexCount(0), VertexCount(0), ShadowVolumesUsed(0),
Infinity(infinity), UseZFailMethod(zfailmethod)
{
#ifdef _DEBUG
setDebugName("CShadowVolumeSceneNode");
#endif
setShadowMesh(shadowMesh);
setAutomaticCulling(scene::EAC_OFF);
}
//! destructor
CShadowVolumeSceneNode::~CShadowVolumeSceneNode()
{
if (ShadowMesh)
ShadowMesh->drop();
}
void CShadowVolumeSceneNode::createShadowVolume(const core::vector3df& light, bool isDirectional)
{
SShadowVolume* svp = 0;
core::aabbox3d<f32>* bb = 0;
// builds the shadow volume and adds it to the shadow volume list.
if (ShadowVolumes.size() > ShadowVolumesUsed)
{
// get the next unused buffer
svp = &ShadowVolumes[ShadowVolumesUsed];
svp->set_used(0);
bb = &ShadowBBox[ShadowVolumesUsed];
}
else
{
ShadowVolumes.push_back(SShadowVolume());
svp = &ShadowVolumes.getLast();
ShadowBBox.push_back(core::aabbox3d<f32>());
bb = &ShadowBBox.getLast();
}
svp->reallocate(IndexCount*5);
++ShadowVolumesUsed;
// We use triangle lists
Edges.set_used(IndexCount*2);
u32 numEdges = 0;
numEdges=createEdgesAndCaps(light, svp, bb);
// for all edges add the near->far quads
for (u32 i=0; i<numEdges; ++i)
{
const core::vector3df &v1 = Vertices[Edges[2*i+0]];
const core::vector3df &v2 = Vertices[Edges[2*i+1]];
const core::vector3df v3(v1+(v1 - light).normalize()*Infinity);
const core::vector3df v4(v2+(v2 - light).normalize()*Infinity);
// Add a quad (two triangles) to the vertex list
#ifdef _DEBUG
if (svp->size() >= svp->allocated_size()-5)
os::Printer::log("Allocation too small.", ELL_DEBUG);
#endif
svp->push_back(v1);
svp->push_back(v2);
svp->push_back(v3);
svp->push_back(v2);
svp->push_back(v4);
svp->push_back(v3);
}
}
#define IRR_USE_ADJACENCY
#define IRR_USE_REVERSE_EXTRUDED
u32 CShadowVolumeSceneNode::createEdgesAndCaps(const core::vector3df& light,
SShadowVolume* svp, core::aabbox3d<f32>* bb)
{
u32 numEdges=0;
const u32 faceCount = IndexCount / 3;
if(faceCount >= 1)
bb->reset(Vertices[Indices[0]]);
else
bb->reset(0,0,0);
// Check every face if it is front or back facing the light.
for (u32 i=0; i<faceCount; ++i)
{
const core::vector3df v0 = Vertices[Indices[3*i+0]];
const core::vector3df v1 = Vertices[Indices[3*i+1]];
const core::vector3df v2 = Vertices[Indices[3*i+2]];
#ifdef IRR_USE_REVERSE_EXTRUDED
FaceData[i]=core::triangle3df(v0,v1,v2).isFrontFacing(light);
#else
FaceData[i]=core::triangle3df(v2,v1,v0).isFrontFacing(light);
#endif
if (UseZFailMethod && FaceData[i])
{
#ifdef _DEBUG
if (svp->size() >= svp->allocated_size()-5)
os::Printer::log("Allocation too small.", ELL_DEBUG);
#endif
// add front cap from light-facing faces
svp->push_back(v2);
svp->push_back(v1);
svp->push_back(v0);
// add back cap
const core::vector3df i0 = v0+(v0-light).normalize()*Infinity;
const core::vector3df i1 = v1+(v1-light).normalize()*Infinity;
const core::vector3df i2 = v2+(v2-light).normalize()*Infinity;
svp->push_back(i0);
svp->push_back(i1);
svp->push_back(i2);
bb->addInternalPoint(i0);
bb->addInternalPoint(i1);
bb->addInternalPoint(i2);
}
}
// Create edges
for (u32 i=0; i<faceCount; ++i)
{
// check all front facing faces
if (FaceData[i] == true)
{
const u16 wFace0 = Indices[3*i+0];
const u16 wFace1 = Indices[3*i+1];
const u16 wFace2 = Indices[3*i+2];
const u16 adj0 = Adjacency[3*i+0];
const u16 adj1 = Adjacency[3*i+1];
const u16 adj2 = Adjacency[3*i+2];
// add edges if face is adjacent to back-facing face
// or if no adjacent face was found
#ifdef IRR_USE_ADJACENCY
if (adj0 == i || FaceData[adj0] == false)
#endif
{
// add edge v0-v1
Edges[2*numEdges+0] = wFace0;
Edges[2*numEdges+1] = wFace1;
++numEdges;
}
#ifdef IRR_USE_ADJACENCY
if (adj1 == i || FaceData[adj1] == false)
#endif
{
// add edge v1-v2
Edges[2*numEdges+0] = wFace1;
Edges[2*numEdges+1] = wFace2;
++numEdges;
}
#ifdef IRR_USE_ADJACENCY
if (adj2 == i || FaceData[adj2] == false)
#endif
{
// add edge v2-v0
Edges[2*numEdges+0] = wFace2;
Edges[2*numEdges+1] = wFace0;
++numEdges;
}
}
}
return numEdges;
}
void CShadowVolumeSceneNode::setShadowMesh(const IMesh* mesh)
{
if (ShadowMesh == mesh)
return;
if (ShadowMesh)
ShadowMesh->drop();
ShadowMesh = mesh;
if (ShadowMesh)
{
ShadowMesh->grab();
Box = ShadowMesh->getBoundingBox();
}
}
void CShadowVolumeSceneNode::updateShadowVolumes()
{
const u32 oldIndexCount = IndexCount;
const u32 oldVertexCount = VertexCount;
const IMesh* const mesh = ShadowMesh;
if (!mesh)
return;
// create as much shadow volumes as there are lights but
// do not ignore the max light settings.
const u32 lightCount = SceneManager->getVideoDriver()->getDynamicLightCount();
if (!lightCount)
return;
// calculate total amount of vertices and indices
VertexCount = 0;
IndexCount = 0;
ShadowVolumesUsed = 0;
u32 i;
u32 totalVertices = 0;
u32 totalIndices = 0;
const u32 bufcnt = mesh->getMeshBufferCount();
for (i=0; i<bufcnt; ++i)
{
const IMeshBuffer* buf = mesh->getMeshBuffer(i);
totalIndices += buf->getIndexCount();
totalVertices += buf->getVertexCount();
}
// allocate memory if necessary
Vertices.set_used(totalVertices);
Indices.set_used(totalIndices);
FaceData.set_used(totalIndices / 3);
// copy mesh
for (i=0; i<bufcnt; ++i)
{
const IMeshBuffer* buf = mesh->getMeshBuffer(i);
const u16* idxp = buf->getIndices();
const u16* idxpend = idxp + buf->getIndexCount();
for (; idxp!=idxpend; ++idxp)
Indices[IndexCount++] = *idxp + VertexCount;
const u32 vtxcnt = buf->getVertexCount();
for (u32 j=0; j<vtxcnt; ++j)
Vertices[VertexCount++] = buf->getPosition(j);
}
// recalculate adjacency if necessary
if (oldVertexCount != VertexCount || oldIndexCount != IndexCount)
calculateAdjacency();
core::matrix4 mat = Parent->getAbsoluteTransformation();
mat.makeInverse();
const core::vector3df parentpos = Parent->getAbsolutePosition();
// TODO: Only correct for point lights.
for (i=0; i<lightCount; ++i)
{
const video::SLight& dl = SceneManager->getVideoDriver()->getDynamicLight(i);
core::vector3df lpos = dl.Position;
if (dl.CastShadows &&
fabs((lpos - parentpos).getLengthSQ()) <= (dl.Radius*dl.Radius*4.0f))
{
mat.transformVect(lpos);
createShadowVolume(lpos);
}
}
}
//! pre render method
void CShadowVolumeSceneNode::OnRegisterSceneNode()
{
if (IsVisible)
{
SceneManager->registerNodeForRendering(this, scene::ESNRP_SHADOW);
ISceneNode::OnRegisterSceneNode();
}
}
//! renders the node.
void CShadowVolumeSceneNode::render()
{
video::IVideoDriver* driver = SceneManager->getVideoDriver();
if (!ShadowVolumesUsed || !driver)
return;
driver->setTransform(video::ETS_WORLD, Parent->getAbsoluteTransformation());
for (u32 i=0; i<ShadowVolumesUsed; ++i)
{
bool drawShadow = true;
if (UseZFailMethod && SceneManager->getActiveCamera())
{
// Disable shadows drawing, when back cap is behind of ZFar plane.
SViewFrustum frust = *SceneManager->getActiveCamera()->getViewFrustum();
core::matrix4 invTrans(Parent->getAbsoluteTransformation(), core::matrix4::EM4CONST_INVERSE);
frust.transform(invTrans);
core::vector3df edges[8];
ShadowBBox[i].getEdges(edges);
core::vector3df largestEdge = edges[0];
f32 maxDistance = core::vector3df(SceneManager->getActiveCamera()->getPosition() - edges[0]).getLength();
f32 curDistance = 0.f;
for(int j = 1; j < 8; ++j)
{
curDistance = core::vector3df(SceneManager->getActiveCamera()->getPosition() - edges[j]).getLength();
if(curDistance > maxDistance)
{
maxDistance = curDistance;
largestEdge = edges[j];
}
}
if (!(frust.planes[scene::SViewFrustum::VF_FAR_PLANE].classifyPointRelation(largestEdge) != core::ISREL3D_FRONT))
drawShadow = false;
}
if(drawShadow)
driver->drawStencilShadowVolume(ShadowVolumes[i], UseZFailMethod, DebugDataVisible);
else
{
core::array<core::vector3df> triangles;
driver->drawStencilShadowVolume(triangles, UseZFailMethod, DebugDataVisible);
}
}
}
//! returns the axis aligned bounding box of this node
const core::aabbox3d<f32>& CShadowVolumeSceneNode::getBoundingBox() const
{
return Box;
}
//! Generates adjacency information based on mesh indices.
void CShadowVolumeSceneNode::calculateAdjacency()
{
Adjacency.set_used(IndexCount);
// go through all faces and fetch their three neighbours
for (u32 f=0; f<IndexCount; f+=3)
{
for (u32 edge = 0; edge<3; ++edge)
{
const core::vector3df& v1 = Vertices[Indices[f+edge]];
const core::vector3df& v2 = Vertices[Indices[f+((edge+1)%3)]];
// now we search an_O_ther _F_ace with these two
// vertices, which is not the current face.
u32 of;
for (of=0; of<IndexCount; of+=3)
{
// only other faces
if (of != f)
{
bool cnt1 = false;
bool cnt2 = false;
for (s32 e=0; e<3; ++e)
{
if (v1.equals(Vertices[Indices[of+e]]))
cnt1=true;
if (v2.equals(Vertices[Indices[of+e]]))
cnt2=true;
}
// one match for each vertex, i.e. edge is the same
if (cnt1 && cnt2)
break;
}
}
// no adjacent edges -> store face number, else store adjacent face
if (of >= IndexCount)
Adjacency[f + edge] = f/3;
else
Adjacency[f + edge] = of/3;
}
}
}
} // end namespace scene
} // end namespace irr

View File

@ -1,87 +0,0 @@
// 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_SHADOW_VOLUME_SCENE_NODE_H_INCLUDED__
#define __C_SHADOW_VOLUME_SCENE_NODE_H_INCLUDED__
#include "IShadowVolumeSceneNode.h"
namespace irr
{
namespace scene
{
//! Scene node for rendering a shadow volume into a stencil buffer.
class CShadowVolumeSceneNode : public IShadowVolumeSceneNode
{
public:
//! constructor
CShadowVolumeSceneNode(const IMesh* shadowMesh, ISceneNode* parent, ISceneManager* mgr,
s32 id, bool zfailmethod=true, f32 infinity=10000.0f);
//! destructor
virtual ~CShadowVolumeSceneNode();
//! Sets the mesh from which the shadow volume should be generated.
/** To optimize shadow rendering, use a simpler mesh for shadows.
*/
virtual void setShadowMesh(const IMesh* mesh);
//! Updates the shadow volumes for current light positions.
/** Called each render cycle from Animated Mesh SceneNode render method. */
virtual void updateShadowVolumes();
//! pre render method
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 type of the scene node
virtual ESCENE_NODE_TYPE getType() const { return ESNT_SHADOW_VOLUME; }
private:
typedef core::array<core::vector3df> SShadowVolume;
void createShadowVolume(const core::vector3df& pos, bool isDirectional=false);
u32 createEdgesAndCaps(const core::vector3df& light, SShadowVolume* svp, core::aabbox3d<f32>* bb);
//! Generates adjacency information based on mesh indices.
void calculateAdjacency();
core::aabbox3d<f32> Box;
// a shadow volume for every light
core::array<SShadowVolume> ShadowVolumes;
// a back cap bounding box for every light
core::array<core::aabbox3d<f32> > ShadowBBox;
core::array<core::vector3df> Vertices;
core::array<u16> Indices;
core::array<u16> Adjacency;
core::array<u16> Edges;
// tells if face is front facing
core::array<bool> FaceData;
const scene::IMesh* ShadowMesh;
u32 IndexCount;
u32 VertexCount;
u32 ShadowVolumesUsed;
f32 Infinity;
bool UseZFailMethod;
};
} // end namespace scene
} // end namespace irr
#endif

View File

@ -7,7 +7,6 @@
#include "ISceneManager.h"
#include "S3DVertex.h"
#include "os.h"
#include "CShadowVolumeSceneNode.h"
namespace irr
{
@ -17,7 +16,7 @@ namespace scene
//! constructor
CSphereSceneNode::CSphereSceneNode(f32 radius, u32 polyCountX, u32 polyCountY, 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),
: IMeshSceneNode(parent, mgr, id, position, rotation, scale), Mesh(0),
Radius(radius), PolyCountX(polyCountX), PolyCountY(polyCountY)
{
#ifdef _DEBUG
@ -32,8 +31,6 @@ CSphereSceneNode::CSphereSceneNode(f32 radius, u32 polyCountX, u32 polyCountY, I
//! destructor
CSphereSceneNode::~CSphereSceneNode()
{
if (Shadow)
Shadow->drop();
if (Mesh)
Mesh->drop();
}
@ -48,8 +45,6 @@ void CSphereSceneNode::render()
{
driver->setMaterial(Mesh->getMeshBuffer(0)->getMaterial());
driver->setTransform(video::ETS_WORLD, AbsoluteTransformation);
if (Shadow)
Shadow->updateShadowVolumes();
driver->drawMeshBuffer(Mesh->getMeshBuffer(0));
if ( DebugDataVisible & scene::EDS_BBOX )
@ -68,35 +63,10 @@ void CSphereSceneNode::render()
//! or to remove attached childs.
bool CSphereSceneNode::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* CSphereSceneNode::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;
}
//! returns the axis aligned bounding box of this node
const core::aabbox3d<f32>& CSphereSceneNode::getBoundingBox() const
{
@ -185,8 +155,6 @@ ISceneNode* CSphereSceneNode::clone(ISceneNode* newParent, ISceneManager* newMan
nb->cloneMembers(this, newManager);
nb->getMaterial(0) = Mesh->getMeshBuffer(0)->getMaterial();
nb->Shadow = Shadow;
nb->Shadow->grab();
if ( newParent )
nb->drop();

View File

@ -69,11 +69,6 @@ namespace scene
//! 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; }
//! 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);
//! 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.
@ -82,7 +77,6 @@ namespace scene
private:
IMesh* Mesh;
IShadowVolumeSceneNode* Shadow;
core::aabbox3d<f32> Box;
f32 Radius;
u32 PolyCountX;

View File

@ -553,8 +553,15 @@ void Material::initCustomSFX(const XMLNode *sfx)
sfx->get("max-pitch", &m_sfx_max_pitch); // 2.4 style
sfx->get("max_pitch", &m_sfx_max_pitch); // 2.5 style
m_sfx_pitch_per_speed = (m_sfx_max_pitch - m_sfx_min_pitch)
/ (m_sfx_max_speed - m_sfx_min_speed);
if (m_sfx_max_speed == m_sfx_min_speed)
{
m_sfx_pitch_per_speed = 0.0f;
}
else
{
m_sfx_pitch_per_speed = (m_sfx_max_pitch - m_sfx_min_pitch)
/ (m_sfx_max_speed - m_sfx_min_speed);
}
if(!SFXManager::get()->soundExist(m_sfx_name))
{
@ -675,6 +682,8 @@ void Material::setSFXSpeed(SFXBase *sfx, float speed, bool should_be_paused) con
return;
}
assert(!isnan(speed));
float f = m_sfx_pitch_per_speed*(speed-m_sfx_min_speed) + m_sfx_min_pitch;
assert(!isnan(f));
sfx->setSpeed(f);

View File

@ -380,27 +380,18 @@ void IrrDriver::renderSkybox(const scene::ICameraSceneNode *camera)
{
if (SkyboxTextures.empty())
return;
glBindVertexArray(MeshShader::SkyboxShader::getInstance()->cubevao);
glEnable(GL_DEPTH_TEST);
glDisable(GL_CULL_FACE);
assert(SkyboxTextures.size() == 6);
core::matrix4 translate;
translate.setTranslation(camera->getAbsolutePosition());
// Draw the sky box between the near and far clip plane
const f32 viewDistance = (camera->getNearValue() + camera->getFarValue()) * 0.5f;
core::matrix4 scale;
scale.setScale(core::vector3df(viewDistance, viewDistance, viewDistance));
core::matrix4 transform = translate * scale;
core::matrix4 invtransform;
transform.getInverse(invtransform);
glDisable(GL_BLEND);
glUseProgram(MeshShader::SkyboxShader::getInstance()->Program);
MeshShader::SkyboxShader::getInstance()->setUniforms(transform);
glBindVertexArray(MeshShader::SkyboxShader::getInstance()->vao);
MeshShader::SkyboxShader::getInstance()->setUniforms();
MeshShader::SkyboxShader::getInstance()->SetTextureUnits(SkyboxCubeMap);
glDrawElements(GL_TRIANGLES, 6 * 6, GL_UNSIGNED_INT, 0);
glDrawArrays(GL_TRIANGLES, 0, 3);
glBindVertexArray(0);
}

View File

@ -48,26 +48,6 @@ static GLuint generateRTT(const core::dimension2du &res, GLint internalFormat, G
return result;
}
static GLuint generateFBO(GLuint ColorAttachement)
{
GLuint fbo;
glGenFramebuffers(1, &fbo);
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, ColorAttachement, 0);
GLenum result = glCheckFramebufferStatus(GL_FRAMEBUFFER);
assert(result == GL_FRAMEBUFFER_COMPLETE_EXT);
return fbo;
}
static GLuint generateFBO(GLuint ColorAttachement, GLuint DepthAttachement)
{
GLuint fbo = generateFBO(ColorAttachement);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, DepthAttachement, 0);
GLenum result = glCheckFramebufferStatus(GL_FRAMEBUFFER);
assert(result == GL_FRAMEBUFFER_COMPLETE_EXT);
return fbo;
}
RTT::RTT(size_t width, size_t height)
{
m_width = width;

View File

@ -336,66 +336,19 @@ static void initBillboardVBO()
glBufferData(GL_ARRAY_BUFFER, 16 * sizeof(float), quad, GL_STATIC_DRAW);
}
GLuint SharedObject::cubevbo = 0;
GLuint SharedObject::cubeindexes = 0;
GLuint SharedObject::skytrivbo = 0;
static void initCubeVBO()
static void initSkyTriVBO()
{
// From CSkyBoxSceneNode
float corners[] =
{
// top side
1., 1., -1.,
1., 1., 1.,
-1., 1., 1.,
-1., 1., -1.,
const float tri_vertex[] = {
-1., -1., 1.,
-1., 3., 1.,
3., -1., 1.,
};
// Bottom side
1., -1., 1.,
1., -1., -1.,
-1., -1., -1.,
-1., -1., 1.,
// right side
1., -1, -1,
1., -1, 1,
1., 1., 1.,
1., 1., -1.,
// left side
-1., -1., 1.,
-1., -1., -1.,
-1., 1., -1.,
-1., 1., 1.,
// back side
-1., -1., -1.,
1., -1, -1.,
1, 1, -1.,
-1, 1, -1.,
// front side
1., -1., 1.,
-1., -1., 1.,
-1, 1., 1.,
1., 1., 1.,
};
int indices[] = {
0, 1, 2, 2, 3, 0,
4, 5, 6, 6, 7, 4,
8, 9, 10, 10, 11, 8,
12, 13, 14, 14, 15, 12,
16, 17, 18, 18, 19, 16,
20, 21, 22, 22, 23, 20
};
glGenBuffers(1, &SharedObject::cubevbo);
glBindBuffer(GL_ARRAY_BUFFER, SharedObject::cubevbo);
glBufferData(GL_ARRAY_BUFFER, 6 * 4 * 3 * sizeof(float), corners, GL_STATIC_DRAW);
glGenBuffers(1, &SharedObject::cubeindexes);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, SharedObject::cubeindexes);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, 6 * 6 * sizeof(int), indices, GL_STATIC_DRAW);
glGenBuffers(1, &SharedObject::skytrivbo);
glBindBuffer(GL_ARRAY_BUFFER, SharedObject::skytrivbo);
glBufferData(GL_ARRAY_BUFFER, 3 * 3 * sizeof(float), tri_vertex, GL_STATIC_DRAW);
}
GLuint SharedObject::frustrumvbo = 0;
@ -535,7 +488,7 @@ void Shaders::loadShaders()
initQuadVBO();
initQuadBuffer();
initBillboardVBO();
initCubeVBO();
initSkyTriVBO();
initFrustrumVBO();
initShadowVPMUBO();
initLightingDataUBO();
@ -1417,17 +1370,16 @@ namespace MeshShader
SkyboxShader::SkyboxShader()
{
Program = LoadProgram(OBJECT,
GL_VERTEX_SHADER, file_manager->getAsset("shaders/object_pass.vert").c_str(),
GL_VERTEX_SHADER, file_manager->getAsset("shaders/sky.vert").c_str(),
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/sky.frag").c_str());
AssignUniforms("ModelMatrix");
AssignUniforms();
AssignSamplerNames(Program, 0, "tex");
glGenVertexArrays(1, &cubevao);
glBindVertexArray(cubevao);
glBindBuffer(GL_ARRAY_BUFFER, SharedObject::cubevbo);
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
glBindBuffer(GL_ARRAY_BUFFER, SharedObject::skytrivbo);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, SharedObject::cubeindexes);
glBindVertexArray(0);
}

View File

@ -30,7 +30,7 @@ class SharedObject
{
public:
static GLuint billboardvbo;
static GLuint cubevbo, cubeindexes, frustrumvbo, frustrumindexes, ParticleQuadVBO;
static GLuint skytrivbo, frustrumvbo, frustrumindexes, ParticleQuadVBO;
static GLuint ViewProjectionMatrixesUBO, LightingDataUBO;
static GLuint FullScreenQuadVAO;
static GLuint UIVAO;
@ -281,11 +281,11 @@ public:
DisplaceShader();
};
class SkyboxShader : public ShaderHelperSingleton<SkyboxShader, core::matrix4>, public TextureRead<Trilinear_cubemap>
class SkyboxShader : public ShaderHelperSingleton<SkyboxShader>, public TextureRead<Trilinear_cubemap>
{
public:
SkyboxShader();
GLuint cubevao;
GLuint vao;
};
class NormalVisualizer : public ShaderHelperSingleton<NormalVisualizer, video::SColor>

View File

@ -55,8 +55,6 @@ public:
virtual scene::IMesh *getMesh() OVERRIDE { return m_mesh; }
virtual void setReadOnlyMaterials(bool) OVERRIDE {}
virtual bool isReadOnlyMaterials() const OVERRIDE { return false; }
virtual scene::IShadowVolumeSceneNode* addShadowVolumeSceneNode
(const scene::IMesh*, int, bool, f32) OVERRIDE { return NULL; }
protected:
video::SMaterial m_mat;