Merge branch 'minlicht'

This commit is contained in:
Vincent Lejeune 2015-01-10 21:31:00 +01:00
commit a6b2aa8217
72 changed files with 6 additions and 26475 deletions

View File

@ -40,7 +40,6 @@ source/Irrlicht/CVideoModeList.cpp
source/Irrlicht/CDefaultGUIElementFactory.cpp
source/Irrlicht/CCubeSceneNode.cpp
source/Irrlicht/CGUIMeshViewer.cpp
source/Irrlicht/CBSPMeshFileLoader.cpp
source/Irrlicht/CParticleSphereEmitter.cpp
source/Irrlicht/CParticleAnimatedMeshSceneNodeEmitter.cpp
source/Irrlicht/CGUITabControl.cpp
@ -52,11 +51,9 @@ source/Irrlicht/os.cpp
source/Irrlicht/CFPSCounter.cpp
source/Irrlicht/CGUIContextMenu.cpp
source/Irrlicht/CImageWriterJPG.cpp
source/Irrlicht/CAnimatedMeshMD2.cpp
source/Irrlicht/CZipReader.cpp
source/Irrlicht/CImageLoaderPNG.cpp
source/Irrlicht/CImageLoaderBMP.cpp
source/Irrlicht/CIrrDeviceWinCE.cpp
source/Irrlicht/CVolumeLightSceneNode.cpp
source/Irrlicht/CDefaultSceneNodeAnimatorFactory.cpp
source/Irrlicht/CSkyDomeSceneNode.cpp
@ -64,12 +61,8 @@ source/Irrlicht/CGUIFileOpenDialog.cpp
source/Irrlicht/CGUISpriteBank.cpp
source/Irrlicht/CParticleFadeOutAffector.cpp
source/Irrlicht/CGUIMenu.cpp
source/Irrlicht/CCgMaterialRenderer.cpp
source/Irrlicht/CMD2MeshFileLoader.cpp
source/Irrlicht/CImageWriterPSD.cpp
source/Irrlicht/CLWOMeshFileLoader.cpp
source/Irrlicht/CSphereSceneNode.cpp
source/Irrlicht/CLMTSMeshFileLoader.cpp
source/Irrlicht/CImageWriterTGA.cpp
source/Irrlicht/CImageWriterPNG.cpp
source/Irrlicht/CSceneNodeAnimatorFollowSpline.cpp
@ -78,25 +71,19 @@ source/Irrlicht/CParticleGravityAffector.cpp
source/Irrlicht/CGUISkin.cpp
source/Irrlicht/CBoneSceneNode.cpp
source/Irrlicht/CNPKReader.cpp
source/Irrlicht/CIrrMeshFileLoader.cpp
source/Irrlicht/COpenGLSLMaterialRenderer.cpp
source/Irrlicht/CParticleRotationAffector.cpp
source/Irrlicht/CDepthBuffer.cpp
source/Irrlicht/CImageLoaderPSD.cpp
source/Irrlicht/CTriangleBBSelector.cpp
source/Irrlicht/CAnimatedMeshMD3.cpp
source/Irrlicht/CGUIComboBox.cpp
source/Irrlicht/CSceneNodeAnimatorTexture.cpp
source/Irrlicht/CColladaMeshWriter.cpp
source/Irrlicht/COpenGLTexture.cpp
source/Irrlicht/COctreeSceneNode.cpp
source/Irrlicht/CWaterSurfaceSceneNode.cpp
source/Irrlicht/CQuake3ShaderSceneNode.cpp
source/Irrlicht/CWADReader.cpp
source/Irrlicht/CParticleAttractionAffector.cpp
source/Irrlicht/CMeshSceneNode.cpp
source/Irrlicht/CCSMLoader.cpp
source/Irrlicht/COBJMeshWriter.cpp
source/Irrlicht/CGUIScrollBar.cpp
source/Irrlicht/CAttributes.cpp
source/Irrlicht/CGUIStaticText.cpp
@ -108,15 +95,12 @@ source/Irrlicht/CTextSceneNode.cpp
source/Irrlicht/COpenGLCgMaterialRenderer.cpp
source/Irrlicht/CIrrDeviceLinux.cpp
source/Irrlicht/CIrrDeviceStub.cpp
source/Irrlicht/CQ3LevelMesh.cpp
source/Irrlicht/CDMFLoader.cpp
source/Irrlicht/CImageWriterPCX.cpp
source/Irrlicht/CGUIInOutFader.cpp
source/Irrlicht/CGUITreeView.cpp
source/Irrlicht/CAnimatedMeshSceneNode.cpp
source/Irrlicht/CGUICheckBox.cpp
source/Irrlicht/CGUIWindow.cpp
source/Irrlicht/CPLYMeshFileLoader.cpp
source/Irrlicht/CSceneNodeAnimatorCameraMaya.cpp
source/Irrlicht/CSceneNodeAnimatorFlyCircle.cpp
source/Irrlicht/CColorConverter.cpp
@ -124,7 +108,6 @@ source/Irrlicht/CMeshCache.cpp
source/Irrlicht/CIrrDeviceFB.cpp
source/Irrlicht/CMemoryFile.cpp
source/Irrlicht/CImageWriterPPM.cpp
source/Irrlicht/CSTLMeshFileLoader.cpp
source/Irrlicht/CMountPointReader.cpp
source/Irrlicht/CBillboardSceneNode.cpp
source/Irrlicht/CGUIImageList.cpp
@ -147,24 +130,17 @@ source/Irrlicht/CLightSceneNode.cpp
source/Irrlicht/CImageLoaderDDS.cpp
source/Irrlicht/CSkyBoxSceneNode.cpp
source/Irrlicht/CWriteFile.cpp
source/Irrlicht/CSTLMeshWriter.cpp
source/Irrlicht/COctreeTriangleSelector.cpp
source/Irrlicht/CSMFMeshFileLoader.cpp
source/Irrlicht/CFileList.cpp
source/Irrlicht/CImageLoaderPCX.cpp
source/Irrlicht/CIrrDeviceSDL.cpp
source/Irrlicht/COSOperator.cpp
source/Irrlicht/CImageLoaderJPG.cpp
source/Irrlicht/CMD3MeshFileLoader.cpp
source/Irrlicht/CIrrMeshWriter.cpp
source/Irrlicht/COpenGLExtensionHandler.cpp
source/Irrlicht/CImageLoaderWAL.cpp
source/Irrlicht/CXMLWriter.cpp
source/Irrlicht/COCTLoader.cpp
source/Irrlicht/COBJMeshFileLoader.cpp
source/Irrlicht/CSceneNodeAnimatorCameraFPS.cpp
source/Irrlicht/CImageLoaderPPM.cpp
source/Irrlicht/CMY3DMeshFileLoader.cpp
source/Irrlicht/CGUIColorSelectDialog.cpp
source/Irrlicht/CSceneManager.cpp
source/Irrlicht/Irrlicht.cpp
@ -184,7 +160,6 @@ source/Irrlicht/CNullDriver.cpp
source/Irrlicht/CCameraSceneNode.cpp
source/Irrlicht/CGUISpinBox.cpp
source/Irrlicht/CReadFile.cpp
source/Irrlicht/CColladaFileLoader.cpp
source/Irrlicht/CParticleRingEmitter.cpp
source/Irrlicht/CMetaTriangleSelector.cpp
source/Irrlicht/CShadowVolumeSceneNode.cpp
@ -193,7 +168,6 @@ source/Irrlicht/CGUIImage.cpp
source/Irrlicht/CGUIEnvironment.cpp
source/Irrlicht/CParticleScaleAffector.cpp
source/Irrlicht/CSceneNodeAnimatorDelete.cpp
source/Irrlicht/CPLYMeshWriter.cpp
source/Irrlicht/CImageWriterBMP.cpp
source/Irrlicht/CParticleMeshEmitter.cpp
source/Irrlicht/CSceneNodeAnimatorRotation.cpp
@ -212,12 +186,10 @@ source/Irrlicht/CIrrDeviceConsole.h
source/Irrlicht/CTerrainSceneNode.h
source/Irrlicht/CSceneNodeAnimatorCollisionResponse.h
source/Irrlicht/CImageLoaderWAL.h
source/Irrlicht/CIrrMeshFileLoader.h
source/Irrlicht/CSceneLoaderIrr.h
source/Irrlicht/CImageLoaderBMP.h
source/Irrlicht/CSkinnedMesh.h
source/Irrlicht/COpenGLParallaxMapRenderer.h
source/Irrlicht/CLWOMeshFileLoader.h
source/Irrlicht/CParticleRingEmitter.h
source/Irrlicht/COpenGLShaderMaterialRenderer.h
source/Irrlicht/CImageWriterTGA.h
@ -228,7 +200,6 @@ source/Irrlicht/Octree.h
source/Irrlicht/os.h
source/Irrlicht/CDefaultGUIElementFactory.h
source/Irrlicht/CSceneNodeAnimatorFlyCircle.h
source/Irrlicht/CBSPMeshFileLoader.h
source/Irrlicht/CTriangleBBSelector.h
source/Irrlicht/S2DVertex.h
source/Irrlicht/CDefaultSceneNodeAnimatorFactory.h
@ -242,9 +213,7 @@ source/Irrlicht/COpenGLNormalMapRenderer.h
source/Irrlicht/CSceneNodeAnimatorCameraMaya.h
source/Irrlicht/SoftwareDriver2_helper.h
source/Irrlicht/CGUIWindow.h
source/Irrlicht/CMD2MeshFileLoader.h
source/Irrlicht/dmfsupport.h
source/Irrlicht/CSTLMeshFileLoader.h
source/Irrlicht/CGUICheckBox.h
source/Irrlicht/CMeshManipulator.h
source/Irrlicht/IImagePresenter.h
@ -257,14 +226,11 @@ source/Irrlicht/CAnimatedMeshSceneNode.h
source/Irrlicht/CGUIStaticText.h
source/Irrlicht/wglext.h
source/Irrlicht/CTimer.h
source/Irrlicht/CCSMLoader.h
source/Irrlicht/CWADReader.h
source/Irrlicht/CColladaMeshWriter.h
source/Irrlicht/CSceneNodeAnimatorCameraFPS.h
source/Irrlicht/CParticleFadeOutAffector.h
source/Irrlicht/COpenGLSLMaterialRenderer.h
source/Irrlicht/CParticleAttractionAffector.h
source/Irrlicht/CMY3DMeshFileLoader.h
source/Irrlicht/MacOSX/AppDelegate.h
source/Irrlicht/MacOSX/CIrrDeviceMacOSX.h
source/Irrlicht/MacOSX/OSXClipboard.h
@ -272,7 +238,6 @@ source/Irrlicht/CSceneManager.h
source/Irrlicht/CImageLoaderPSD.h
source/Irrlicht/COpenGLDriver.h
source/Irrlicht/CGUIComboBox.h
source/Irrlicht/CPLYMeshFileLoader.h
source/Irrlicht/CVolumeLightSceneNode.h
source/Irrlicht/CSceneCollisionManager.h
source/Irrlicht/ISceneNodeAnimatorFinishing.h
@ -284,7 +249,6 @@ source/Irrlicht/aesGladman/aes.h
source/Irrlicht/aesGladman/sha1.h
source/Irrlicht/aesGladman/prng.h
source/Irrlicht/aesGladman/aesopt.h
source/Irrlicht/COBJMeshWriter.h
source/Irrlicht/CGUITabControl.h
source/Irrlicht/CSphereSceneNode.h
source/Irrlicht/CIrrDeviceStub.h
@ -293,7 +257,6 @@ source/Irrlicht/CParticleBoxEmitter.h
source/Irrlicht/CShadowVolumeSceneNode.h
source/Irrlicht/COctreeSceneNode.h
source/Irrlicht/CReadFile.h
source/Irrlicht/CMY3DHelper.h
source/Irrlicht/CImageLoaderDDS.h
source/Irrlicht/COSOperator.h
source/Irrlicht/CLightSceneNode.h
@ -304,7 +267,6 @@ source/Irrlicht/CIrrDeviceWin32.h
source/Irrlicht/CGUIEditBox.h
source/Irrlicht/CGUISpriteBank.h
source/Irrlicht/CSceneNodeAnimatorFlyStraight.h
source/Irrlicht/COCTLoader.h
source/Irrlicht/COpenGLExtensionHandler.h
source/Irrlicht/CImageWriterPSD.h
source/Irrlicht/CGUIScrollBar.h
@ -313,7 +275,6 @@ source/Irrlicht/CTriangleSelector.h
source/Irrlicht/CParticleGravityAffector.h
source/Irrlicht/CGUIModalScreen.h
source/Irrlicht/CDefaultSceneNodeFactory.h
source/Irrlicht/CIrrDeviceWinCE.h
source/Irrlicht/CImageLoaderPPM.h
source/Irrlicht/CXMLReaderImpl.h
source/Irrlicht/COpenGLMaterialRenderer.h
@ -325,29 +286,20 @@ source/Irrlicht/CWaterSurfaceSceneNode.h
source/Irrlicht/SoftwareDriver2_compile_config.h
source/Irrlicht/CSceneNodeAnimatorTexture.h
source/Irrlicht/CXMLReader.h
source/Irrlicht/CColladaFileLoader.h
source/Irrlicht/CEmptySceneNode.h
source/Irrlicht/CCgMaterialRenderer.h
source/Irrlicht/CParticleSystemSceneNode.h
source/Irrlicht/CImageWriterPNG.h
source/Irrlicht/CParticleScaleAffector.h
source/Irrlicht/CImageWriterPCX.h
source/Irrlicht/CLogger.h
source/Irrlicht/CMD3MeshFileLoader.h
source/Irrlicht/CImageLoaderJPG.h
source/Irrlicht/CBillboardSceneNode.h
source/Irrlicht/CIrrDeviceSDL.h
source/Irrlicht/CSkyDomeSceneNode.h
source/Irrlicht/CPLYMeshWriter.h
source/Irrlicht/CDepthBuffer.h
source/Irrlicht/CGUIInOutFader.h
source/Irrlicht/CGUIFont.h
source/Irrlicht/CGUIImageList.h
source/Irrlicht/CAnimatedMeshMD2.h
source/Irrlicht/CIrrMeshWriter.h
source/Irrlicht/COBJMeshFileLoader.h
source/Irrlicht/CFileSystem.h
source/Irrlicht/CQ3LevelMesh.h
source/Irrlicht/CSceneNodeAnimatorRotation.h
source/Irrlicht/CGUISkin.h
source/Irrlicht/CNPKReader.h
@ -359,13 +311,10 @@ source/Irrlicht/CZipReader.h
source/Irrlicht/CGUIToolBar.h
source/Irrlicht/CImageWriterJPG.h
source/Irrlicht/IAttribute.h
source/Irrlicht/CDMFLoader.h
source/Irrlicht/CNullDriver.h
source/Irrlicht/CImageLoaderRGB.h
source/Irrlicht/CWriteFile.h
source/Irrlicht/CLMTSMeshFileLoader.h
source/Irrlicht/CSceneNodeAnimatorFollowSpline.h
source/Irrlicht/CQuake3ShaderSceneNode.h
source/Irrlicht/glxext.h
source/Irrlicht/CMetaTriangleSelector.h
source/Irrlicht/CTarReader.h
@ -373,13 +322,10 @@ source/Irrlicht/CXMLWriter.h
source/Irrlicht/CParticleCylinderEmitter.h
source/Irrlicht/ITriangleRenderer.h
source/Irrlicht/CSceneNodeAnimatorDelete.h
source/Irrlicht/CSTLMeshWriter.h
source/Irrlicht/CIrrDeviceFB.h
source/Irrlicht/CGUIEnvironment.h
source/Irrlicht/CTerrainTriangleSelector.h
source/Irrlicht/CSMFMeshFileLoader.h
source/Irrlicht/CAttributeImpl.h
source/Irrlicht/CAnimatedMeshMD3.h
source/Irrlicht/CGeometryCreator.h
source/Irrlicht/CSkyBoxSceneNode.h
source/Irrlicht/CImageWriterBMP.h
@ -438,7 +384,6 @@ include/ITimer.h
include/IImage.h
include/position2d.h
include/IGUIToolbar.h
include/IColladaMeshWriter.h
include/IGUISpinBox.h
include/IGUITabControl.h
include/IBillboardTextSceneNode.h
@ -483,7 +428,6 @@ include/IParticleMeshEmitter.h
include/IGUIColorSelectDialog.h
include/IGUIImage.h
include/IGUIListBox.h
include/IQ3LevelMesh.h
include/vector2d.h
include/CIndexBuffer.h
include/IAnimatedMesh.h
@ -507,14 +451,12 @@ include/ITriangleSelector.h
include/coreutil.h
include/SMeshBufferTangents.h
include/ILightSceneNode.h
include/IAnimatedMeshMD3.h
include/dimension2d.h
include/ISceneCollisionManager.h
include/heapsort.h
include/IGUIComboBox.h
include/Keycodes.h
include/SParticle.h
include/IQ3Shader.h
include/EDriverTypes.h
include/IFileSystem.h
include/SMesh.h
@ -555,7 +497,6 @@ include/IGUITable.h
include/IGUIButton.h
include/EMaterialFlags.h
include/EDeviceTypes.h
include/IAnimatedMeshMD2.h
include/IGUIWindow.h
include/EAttributes.h
include/S3DVertex.h

View File

@ -1,79 +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 __I_ANIMATED_MESH_MD2_H_INCLUDED__
#define __I_ANIMATED_MESH_MD2_H_INCLUDED__
#include "IAnimatedMesh.h"
namespace irr
{
namespace scene
{
//! Types of standard md2 animations
enum EMD2_ANIMATION_TYPE
{
EMAT_STAND = 0,
EMAT_RUN,
EMAT_ATTACK,
EMAT_PAIN_A,
EMAT_PAIN_B,
EMAT_PAIN_C,
EMAT_JUMP,
EMAT_FLIP,
EMAT_SALUTE,
EMAT_FALLBACK,
EMAT_WAVE,
EMAT_POINT,
EMAT_CROUCH_STAND,
EMAT_CROUCH_WALK,
EMAT_CROUCH_ATTACK,
EMAT_CROUCH_PAIN,
EMAT_CROUCH_DEATH,
EMAT_DEATH_FALLBACK,
EMAT_DEATH_FALLFORWARD,
EMAT_DEATH_FALLBACKSLOW,
EMAT_BOOM,
//! Not an animation, but amount of animation types.
EMAT_COUNT
};
//! Interface for using some special functions of MD2 meshes
class IAnimatedMeshMD2 : public IAnimatedMesh
{
public:
//! Get frame loop data for a default MD2 animation type.
/** \param l The EMD2_ANIMATION_TYPE to get the frames for.
\param outBegin The returned beginning frame for animation type specified.
\param outEnd The returned ending frame for the animation type specified.
\param outFPS The number of frames per second, this animation should be played at.
\return beginframe, endframe and frames per second for a default MD2 animation type. */
virtual void getFrameLoop(EMD2_ANIMATION_TYPE l, s32& outBegin,
s32& outEnd, s32& outFPS) const = 0;
//! Get frame loop data for a special MD2 animation type, identified by name.
/** \param name Name of the animation.
\param outBegin The returned beginning frame for animation type specified.
\param outEnd The returned ending frame for the animation type specified.
\param outFPS The number of frames per second, this animation should be played at.
\return beginframe, endframe and frames per second for a special MD2 animation type. */
virtual bool getFrameLoop(const c8* name,
s32& outBegin, s32& outEnd, s32& outFPS) const = 0;
//! Get amount of md2 animations in this file.
virtual s32 getAnimationCount() const = 0;
//! Get name of md2 animation.
/** \param nr: Zero based index of animation. */
virtual const c8* getAnimationName(s32 nr) const = 0;
};
} // end namespace scene
} // end namespace irr
#endif

View File

@ -1,304 +0,0 @@
// Copyright (C) 2007-2012 Nikolaus Gebhardt / Thomas Alten
// This file is part of the "Irrlicht Engine".
// For conditions of distribution and use, see copyright notice in irrlicht.h
#ifndef __I_ANIMATED_MESH_MD3_H_INCLUDED__
#define __I_ANIMATED_MESH_MD3_H_INCLUDED__
#include "IAnimatedMesh.h"
#include "IQ3Shader.h"
#include "quaternion.h"
namespace irr
{
namespace scene
{
enum eMD3Models
{
EMD3_HEAD = 0,
EMD3_UPPER,
EMD3_LOWER,
EMD3_WEAPON,
EMD3_NUMMODELS
};
//! Animation list
enum EMD3_ANIMATION_TYPE
{
// Animations for both lower and upper parts of the player
EMD3_BOTH_DEATH_1 = 0,
EMD3_BOTH_DEAD_1,
EMD3_BOTH_DEATH_2,
EMD3_BOTH_DEAD_2,
EMD3_BOTH_DEATH_3,
EMD3_BOTH_DEAD_3,
// Animations for the upper part
EMD3_TORSO_GESTURE,
EMD3_TORSO_ATTACK_1,
EMD3_TORSO_ATTACK_2,
EMD3_TORSO_DROP,
EMD3_TORSO_RAISE,
EMD3_TORSO_STAND_1,
EMD3_TORSO_STAND_2,
// Animations for the lower part
EMD3_LEGS_WALK_CROUCH,
EMD3_LEGS_WALK,
EMD3_LEGS_RUN,
EMD3_LEGS_BACK,
EMD3_LEGS_SWIM,
EMD3_LEGS_JUMP_1,
EMD3_LEGS_LAND_1,
EMD3_LEGS_JUMP_2,
EMD3_LEGS_LAND_2,
EMD3_LEGS_IDLE,
EMD3_LEGS_IDLE_CROUCH,
EMD3_LEGS_TURN,
//! Not an animation, but amount of animation types.
EMD3_ANIMATION_COUNT
};
struct SMD3AnimationInfo
{
//! First frame
s32 first;
//! Last frame
s32 num;
//! Looping frames
s32 looping;
//! Frames per second
s32 fps;
};
// byte-align structures
#include "irrpack.h"
//! this holds the header info of the MD3 file
struct SMD3Header
{
c8 headerID[4]; //id of file, always "IDP3"
s32 Version; //this is a version number, always 15
s8 fileName[68]; //sometimes left Blank... 65 chars, 32bit aligned == 68 chars
s32 numFrames; //number of KeyFrames
s32 numTags; //number of 'tags' per frame
s32 numMeshes; //number of meshes/skins
s32 numMaxSkins; //maximum number of unique skins used in md3 file. artefact md2
s32 frameStart; //starting position of frame-structur
s32 tagStart; //starting position of tag-structures
s32 tagEnd; //ending position of tag-structures/starting position of mesh-structures
s32 fileSize;
} PACK_STRUCT;
//! this holds the header info of an MD3 mesh section
struct SMD3MeshHeader
{
c8 meshID[4]; //id, must be IDP3
c8 meshName[68]; //name of mesh 65 chars, 32 bit aligned == 68 chars
s32 numFrames; //number of meshframes in mesh
s32 numShader; //number of skins in mesh
s32 numVertices; //number of vertices
s32 numTriangles; //number of Triangles
s32 offset_triangles; //starting position of Triangle data, relative to start of Mesh_Header
s32 offset_shaders; //size of header
s32 offset_st; //starting position of texvector data, relative to start of Mesh_Header
s32 vertexStart; //starting position of vertex data,relative to start of Mesh_Header
s32 offset_end;
} PACK_STRUCT;
//! Compressed Vertex Data
struct SMD3Vertex
{
s16 position[3];
u8 normal[2];
} PACK_STRUCT;
//! Texture Coordinate
struct SMD3TexCoord
{
f32 u;
f32 v;
} PACK_STRUCT;
//! Triangle Index
struct SMD3Face
{
s32 Index[3];
} PACK_STRUCT;
// Default alignment
#include "irrunpack.h"
//! Holding Frame Data for a Mesh
struct SMD3MeshBuffer : public IReferenceCounted
{
SMD3MeshHeader MeshHeader;
core::stringc Shader;
core::array < s32 > Indices;
core::array < SMD3Vertex > Vertices;
core::array < SMD3TexCoord > Tex;
};
//! hold a tag info for connecting meshes
/** Basically its an alternate way to describe a transformation. */
struct SMD3QuaternionTag
{
virtual ~SMD3QuaternionTag()
{
position.X = 0.f;
}
// construct copy constructor
SMD3QuaternionTag( const SMD3QuaternionTag & copyMe )
{
*this = copyMe;
}
// construct for searching
SMD3QuaternionTag( const core::stringc& name )
: Name ( name ) {}
// construct from a position and euler angles in degrees
SMD3QuaternionTag ( const core::vector3df &pos, const core::vector3df &angle )
: position(pos), rotation(angle * core::DEGTORAD) {}
// set to matrix
void setto ( core::matrix4 &m )
{
rotation.getMatrix ( m, position );
}
bool operator == ( const SMD3QuaternionTag &other ) const
{
return Name == other.Name;
}
SMD3QuaternionTag & operator=( const SMD3QuaternionTag & copyMe )
{
Name = copyMe.Name;
position = copyMe.position;
rotation = copyMe.rotation;
return *this;
}
core::stringc Name;
core::vector3df position;
core::quaternion rotation;
};
//! holds a associative list of named quaternions
struct SMD3QuaternionTagList
{
SMD3QuaternionTagList()
{
Container.setAllocStrategy(core::ALLOC_STRATEGY_SAFE);
}
// construct copy constructor
SMD3QuaternionTagList(const SMD3QuaternionTagList& copyMe)
{
*this = copyMe;
}
virtual ~SMD3QuaternionTagList() {}
SMD3QuaternionTag* get(const core::stringc& name)
{
SMD3QuaternionTag search ( name );
s32 index = Container.linear_search ( search );
if ( index >= 0 )
return &Container[index];
return 0;
}
u32 size () const
{
return Container.size();
}
void set_used(u32 new_size)
{
s32 diff = (s32) new_size - (s32) Container.allocated_size();
if ( diff > 0 )
{
SMD3QuaternionTag e("");
for ( s32 i = 0; i < diff; ++i )
Container.push_back(e);
}
}
const SMD3QuaternionTag& operator[](u32 index) const
{
return Container[index];
}
SMD3QuaternionTag& operator[](u32 index)
{
return Container[index];
}
void push_back(const SMD3QuaternionTag& other)
{
Container.push_back(other);
}
SMD3QuaternionTagList& operator = (const SMD3QuaternionTagList & copyMe)
{
Container = copyMe.Container;
return *this;
}
private:
core::array < SMD3QuaternionTag > Container;
};
//! Holding Frames Buffers and Tag Infos
struct SMD3Mesh: public IReferenceCounted
{
SMD3Mesh ()
{
MD3Header.numFrames = 0;
}
virtual ~SMD3Mesh()
{
for (u32 i=0; i<Buffer.size(); ++i)
Buffer[i]->drop();
}
core::stringc Name;
core::array<SMD3MeshBuffer*> Buffer;
SMD3QuaternionTagList TagList;
SMD3Header MD3Header;
};
//! Interface for using some special functions of MD3 meshes
class IAnimatedMeshMD3 : public IAnimatedMesh
{
public:
//! tune how many frames you want to render inbetween.
virtual void setInterpolationShift(u32 shift, u32 loopMode) =0;
//! get the tag list of the mesh.
virtual SMD3QuaternionTagList* getTagList(s32 frame, s32 detailLevel, s32 startFrameLoop, s32 endFrameLoop) =0;
//! get the original md3 mesh.
virtual SMD3Mesh* getOriginalMesh() =0;
};
} // end namespace scene
} // end namespace irr
#endif

View File

@ -7,8 +7,8 @@
#include "ISceneNode.h"
#include "IBoneSceneNode.h"
#include "IAnimatedMeshMD2.h"
#include "IAnimatedMeshMD3.h"
#include "IMesh.h"
#include "IAnimatedMesh.h"
namespace irr
{
@ -140,31 +140,6 @@ namespace scene
/** \return Amount of joints in the mesh. */
virtual u32 getJointCount() const = 0;
//! Starts a default MD2 animation.
/** With this method it is easily possible to start a Run,
Attack, Die or whatever animation, if the mesh contained in
this scene node is an md2 mesh. Otherwise, nothing happens.
\param anim: An MD2 animation type, which should be played, for
example EMAT_STAND for the standing animation.
\return True if successful, and false if not, for example if
the mesh in the scene node is not a md2 mesh. */
virtual bool setMD2Animation(EMD2_ANIMATION_TYPE anim) = 0;
//! Starts a special MD2 animation.
/** With this method it is easily possible to start a Run,
Attack, Die or whatever animation, if the mesh contained in
this scene node is an md2 mesh. Otherwise, nothing happens.
This method uses a character string to identify the animation.
If the animation is a standard md2 animation, you might want to
start this animation with the EMD2_ANIMATION_TYPE enumeration
instead.
\param animationName: Name of the animation which should be
played.
\return Returns true if successful, and false if not, for
example if the mesh in the scene node is not an md2 mesh, or no
animation with this name could be found. */
virtual bool setMD2Animation(const c8* animationName) = 0;
//! Returns the currently displayed frame number.
virtual f32 getFrameNr() const = 0;
//! Returns the current start frame number.
@ -201,9 +176,6 @@ namespace scene
//! Returns the current mesh
virtual IAnimatedMesh* getMesh(void) = 0;
//! Get the absolute transformation for a special MD3 Tag if the mesh is a md3 mesh, or the absolutetransformation if it's a normal scenenode
virtual const SMD3QuaternionTag* getMD3TagTransformation( const core::stringc & tagname) = 0;
//! Set how the joints should be updated on render
virtual void setJointMode(E_JOINT_UPDATE_ON_RENDER mode)=0;

View File

@ -1,404 +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 __IRR_I_COLLADA_MESH_WRITER_H_INCLUDED__
#define __IRR_I_COLLADA_MESH_WRITER_H_INCLUDED__
#include "IMeshWriter.h"
#include "ISceneNode.h"
#include "IAnimatedMesh.h"
#include "SMaterial.h"
namespace irr
{
namespace io
{
class IWriteFile;
} // end namespace io
namespace scene
{
//! Lighting models - more or less the way Collada categorizes materials
enum E_COLLADA_TECHNIQUE_FX
{
//! Blinn-phong which is default for opengl and dx fixed function pipelines.
//! But several well-known renderers don't support it and prefer phong.
ECTF_BLINN,
//! Phong shading, default in many external renderers.
ECTF_PHONG,
//! diffuse shaded surface that is independent of lighting.
ECTF_LAMBERT,
// constantly shaded surface that is independent of lighting.
ECTF_CONSTANT
};
//! How to interpret the opacity in collada
enum E_COLLADA_TRANSPARENT_FX
{
//! default - only alpha channel of color or texture is used.
ECOF_A_ONE = 0,
//! Alpha values for each RGB channel of color or texture are used.
ECOF_RGB_ZERO = 1
};
//! Color names collada uses in it's color samplers
enum E_COLLADA_COLOR_SAMPLER
{
ECCS_DIFFUSE,
ECCS_AMBIENT,
ECCS_EMISSIVE,
ECCS_SPECULAR,
ECCS_TRANSPARENT,
ECCS_REFLECTIVE
};
//! Irrlicht colors which can be mapped to E_COLLADA_COLOR_SAMPLER values
enum E_COLLADA_IRR_COLOR
{
//! Don't write this element at all
ECIC_NONE,
//! Check IColladaMeshWriterProperties for custom color
ECIC_CUSTOM,
//! Use SMaterial::DiffuseColor
ECIC_DIFFUSE,
//! Use SMaterial::AmbientColor
ECIC_AMBIENT,
//! Use SMaterial::EmissiveColor
ECIC_EMISSIVE,
//! Use SMaterial::SpecularColor
ECIC_SPECULAR
};
//! Control when geometry elements are created
enum E_COLLADA_GEOMETRY_WRITING
{
//! Default - write each mesh exactly once to collada. Optimal but will not work with many tools.
ECGI_PER_MESH,
//! Write each mesh as often as it's used with different materials-names in the scene.
//! Material names which are used here are created on export, so using the IColladaMeshWriterNames
//! interface you have some control over how many geometries are written.
ECGI_PER_MESH_AND_MATERIAL
};
//! Callback interface for properties which can be used to influence collada writing
class IColladaMeshWriterProperties : public virtual IReferenceCounted
{
public:
virtual ~IColladaMeshWriterProperties () {}
//! Which lighting model should be used in the technique (FX) section when exporting effects (materials)
virtual E_COLLADA_TECHNIQUE_FX getTechniqueFx(const video::SMaterial& material) const = 0;
//! Which texture index should be used when writing the texture of the given sampler color.
/** \return the index to the texture-layer or -1 if that texture should never be exported
Note: for ECCS_TRANSPARENT by default the alpha channel is used, if you want to use RGB you have to set
also the ECOF_RGB_ZERO flag in getTransparentFx. */
virtual s32 getTextureIdx(const video::SMaterial & material, E_COLLADA_COLOR_SAMPLER cs) const = 0;
//! Return which color from Irrlicht should be used for the color requested by collada
/** Note that collada allows exporting either texture or color, not both.
So color mapping is only checked if we have no valid texture already.
By default we try to return best fits when possible. For example ECCS_DIFFUSE is mapped to ECIC_DIFFUSE.
When ECIC_CUSTOM is returned then the result of getCustomColor will be used. */
virtual E_COLLADA_IRR_COLOR getColorMapping(const video::SMaterial & material, E_COLLADA_COLOR_SAMPLER cs) const = 0;
//! Return custom colors for certain color types requested by collada.
/** Only used when getColorMapping returns ECIC_CUSTOM for the same paramters. */
virtual video::SColor getCustomColor(const video::SMaterial & material, E_COLLADA_COLOR_SAMPLER cs) const = 0;
//! Return the transparence color interpretation.
/** Not this is only about ECCS_TRANSPARENT and does not affect getTransparency. */
virtual E_COLLADA_TRANSPARENT_FX getTransparentFx(const video::SMaterial& material) const = 0;
//! Transparency value for that material.
/** This value is additional to transparent settings, if both are set they will be multiplicated.
\return 1.0 for fully transparent, 0.0 for not transparent and not written at all when < 0.f */
virtual f32 getTransparency(const video::SMaterial& material) const = 0;
//! Reflectivity value for that material
/** The amount of perfect mirror reflection to be added to the reflected light
\return 0.0 - 1.0 for reflectivity and element is not written at all when < 0.f */
virtual f32 getReflectivity(const video::SMaterial& material) const = 0;
//! Return index of refraction for that material
/** By default we don't write that.
\return a value greater equal 0.f to write \<index_of_refraction\> when it is lesser than 0 nothing will be written */
virtual f32 getIndexOfRefraction(const video::SMaterial& material) const = 0;
//! Should node be used in scene export? (only needed for scene-writing, ignored in mesh-writing)
//! By default all visible nodes are exported.
virtual bool isExportable(const irr::scene::ISceneNode * node) const = 0;
//! Return the mesh for the given node. If it has no mesh or shouldn't export it's mesh
//! you can return 0 in which case only the transformation matrix of the node will be used.
// Note: Function is not const because there is no const getMesh() function.
virtual IMesh* getMesh(irr::scene::ISceneNode * node) = 0;
//! Return if the node has it's own material overwriting the mesh-materials
/** Usually true except for mesh-nodes which have isReadOnlyMaterials set.
This is mostly important for naming (as ISceneNode::getMaterial() already returns the correct material).
You have to override it when exporting custom scenenodes with own materials.
\return true => The node's own material is used, false => ignore node material and use the one from the mesh */
virtual bool useNodeMaterial(const scene::ISceneNode* node) const = 0;
};
//! Callback interface to use custom names on collada writing.
/** You can either modify names and id's written to collada or you can use
this interface to just find out which names are used on writing.
*/
class IColladaMeshWriterNames : public virtual IReferenceCounted
{
public:
virtual ~IColladaMeshWriterNames () {}
//! Return a unique name for the given mesh
/** Note that names really must be unique here per mesh-pointer, so
mostly it's a good idea to return the nameForMesh from
IColladaMeshWriter::getDefaultNameGenerator(). Also names must follow
the xs::NCName standard to be valid, you can run them through
IColladaMeshWriter::toNCName to ensure that.
\param mesh Pointer to the mesh which needs a name
\param instance When E_COLLADA_GEOMETRY_WRITING is not ECGI_PER_MESH then
several instances of the same mesh can be written and this counts them.
*/
virtual irr::core::stringw nameForMesh(const scene::IMesh* mesh, int instance) = 0;
//! Return a unique name for the given node
/** Note that names really must be unique here per node-pointer, so
mostly it's a good idea to return the nameForNode from
IColladaMeshWriter::getDefaultNameGenerator(). Also names must follow
the xs::NCName standard to be valid, you can run them through
IColladaMeshWriter::toNCName to ensure that.
*/
virtual irr::core::stringw nameForNode(const scene::ISceneNode* node) = 0;
//! Return a name for the material
/** There is one material created in the writer for each unique name.
So you can use this to control the number of materials which get written.
For example Irrlicht does by default write one material for each material
instanced by a node. So if you know that in your application material
instances per node are identical between different nodes you can reduce
the number of exported materials using that knowledge by using identical
names for such shared materials.
Names must follow the xs::NCName standard to be valid, you can run them
through IColladaMeshWriter::toNCName to ensure that.
*/
virtual irr::core::stringw nameForMaterial(const video::SMaterial & material, int materialId, const scene::IMesh* mesh, const scene::ISceneNode* node) = 0;
};
//! Interface for writing meshes
class IColladaMeshWriter : public IMeshWriter
{
public:
IColladaMeshWriter()
: Properties(0), DefaultProperties(0), NameGenerator(0), DefaultNameGenerator(0)
, WriteTextures(true), WriteDefaultScene(true), ExportSMaterialOnce(true)
, AmbientLight(0.f, 0.f, 0.f, 1.f)
{
}
//! Destructor
virtual ~IColladaMeshWriter()
{
if ( Properties )
Properties->drop();
if ( DefaultProperties )
DefaultProperties->drop();
if ( NameGenerator )
NameGenerator->drop();
if ( DefaultNameGenerator )
DefaultNameGenerator->drop();
}
//! writes a scene starting with the given node
virtual bool writeScene(io::IWriteFile* file, scene::ISceneNode* root) = 0;
//! Set if texture information should be written
virtual void setWriteTextures(bool write)
{
WriteTextures = write;
}
//! Get if texture information should be written
virtual bool getWriteTextures() const
{
return WriteTextures;
}
//! Set if a default scene should be written when writing meshes.
/** Many collada readers fail to read a mesh if the collada files doesn't contain a scene as well.
The scene is doing an instantiation of the mesh.
When using writeScene this flag is ignored (as we have scene there already)
*/
virtual void setWriteDefaultScene(bool write)
{
WriteDefaultScene = write;
}
//! Get if a default scene should be written
virtual bool getWriteDefaultScene() const
{
return WriteDefaultScene;
}
//! Sets ambient color of the scene to write
virtual void setAmbientLight(const video::SColorf &ambientColor)
{
AmbientLight = ambientColor;
}
//! Return ambient light of the scene which is written
virtual video::SColorf getAmbientLight() const
{
return AmbientLight;
}
//! Control when and how often a mesh is written
/** Optimally ECGI_PER_MESH would be always sufficent - writing geometry once per mesh.
Unfortunately many tools (at the time of writing this nearly all of them) have trouble
on import when different materials are used per node. So when you override materials
per node and importing the resuling collada has materials problems in other tools try
using other values here.
\param writeStyle One of the E_COLLADA_GEOMETRY_WRITING settings.
*/
virtual void setGeometryWriting(E_COLLADA_GEOMETRY_WRITING writeStyle)
{
GeometryWriting = writeStyle;
}
//! Get the current style of geometry writing.
virtual E_COLLADA_GEOMETRY_WRITING getGeometryWriting() const
{
return GeometryWriting;
}
//! Make certain there is only one collada material generated per Irrlicht material
/** Checks before creating a collada material-name if an identical
irr:::video::SMaterial has been exported already. If so don't export it with
another name. This is set by default and leads to way smaller .dae files.
Note that if you need to disable this flag for some reason you can still
get a similar effect using the IColladaMeshWriterNames::nameForMaterial
by returning identical names for identical materials there.
*/
virtual void setExportSMaterialsOnlyOnce(bool exportOnce)
{
ExportSMaterialOnce = exportOnce;
}
virtual bool getExportSMaterialsOnlyOnce() const
{
return ExportSMaterialOnce;
}
//! Set properties to use by the meshwriter instead of it's default properties.
/** Overloading properties with an own class allows modifying the writing process in certain ways.
By default properties are set to the DefaultProperties. */
virtual void setProperties(IColladaMeshWriterProperties * p)
{
if ( p == Properties )
return;
if ( p )
p->grab();
if ( Properties )
Properties->drop();
Properties = p;
}
//! Get properties which are currently used.
virtual IColladaMeshWriterProperties * getProperties() const
{
return Properties;
}
//! Return the original default properties of the writer.
/** You can use this pointer in your own properties to access and return default values. */
IColladaMeshWriterProperties * getDefaultProperties() const
{
return DefaultProperties;
}
//! Install a generator to create custom names on export.
virtual void setNameGenerator(IColladaMeshWriterNames * nameGenerator)
{
if ( nameGenerator == NameGenerator )
return;
if ( nameGenerator )
nameGenerator->grab();
if ( NameGenerator )
NameGenerator->drop();
NameGenerator = nameGenerator;
}
//! Get currently used name generator
virtual IColladaMeshWriterNames * getNameGenerator() const
{
return NameGenerator;
}
//! Return the original default name generator of the writer.
/** You can use this pointer in your own generator to access and return default values. */
IColladaMeshWriterNames * getDefaultNameGenerator() const
{
return DefaultNameGenerator;
}
//! Restrict the characters of oldString a set of allowed characters in xs::NCName and add the prefix.
/** A tool function to help when using a custom name generator to generative valid names for collada names and id's. */
virtual irr::core::stringw toNCName(const irr::core::stringw& oldString, const irr::core::stringw& prefix=irr::core::stringw(L"_NC_")) const = 0;
protected:
// NOTE: You usually should also call setProperties with the same paraemter when using setDefaultProperties
virtual void setDefaultProperties(IColladaMeshWriterProperties * p)
{
if ( p == DefaultProperties )
return;
if ( p )
p->grab();
if ( DefaultProperties )
DefaultProperties->drop();
DefaultProperties = p;
}
// NOTE: You usually should also call setNameGenerator with the same paraemter when using setDefaultProperties
virtual void setDefaultNameGenerator(IColladaMeshWriterNames * p)
{
if ( p == DefaultNameGenerator )
return;
if ( p )
p->grab();
if ( DefaultNameGenerator )
DefaultNameGenerator->drop();
DefaultNameGenerator = p;
}
private:
IColladaMeshWriterProperties * Properties;
IColladaMeshWriterProperties * DefaultProperties;
IColladaMeshWriterNames * NameGenerator;
IColladaMeshWriterNames * DefaultNameGenerator;
bool WriteTextures;
bool WriteDefaultScene;
bool ExportSMaterialOnce;
video::SColorf AmbientLight;
E_COLLADA_GEOMETRY_WRITING GeometryWriting;
};
} // end namespace
} // end namespace
#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
#ifndef __I_Q3_LEVEL_MESH_H_INCLUDED__
#define __I_Q3_LEVEL_MESH_H_INCLUDED__
#include "IAnimatedMesh.h"
#include "IQ3Shader.h"
namespace irr
{
namespace scene
{
//! Interface for a Mesh which can be loaded directly from a Quake3 .bsp-file.
/** The Mesh tries to load all textures of the map.*/
class IQ3LevelMesh : public IAnimatedMesh
{
public:
//! loads the shader definition from file
/** \param filename Name of the shaderfile, defaults to /scripts if fileNameIsValid is false.
\param fileNameIsValid Specifies whether the filename is valid in the current situation. */
virtual const quake3::IShader* getShader( const c8* filename, bool fileNameIsValid=true ) = 0;
//! returns a already loaded Shader
virtual const quake3::IShader* getShader(u32 index) const = 0;
//! get's an interface to the entities
virtual quake3::tQ3EntityList& getEntityList() = 0;
//! returns the requested brush entity
/** \param num The number from the model key of the entity.
Use this interface if you parse the entities yourself.*/
virtual IMesh* getBrushEntityMesh(s32 num) const = 0;
//! returns the requested brush entity
virtual IMesh* getBrushEntityMesh(quake3::IEntity &ent) const = 0;
};
} // end namespace scene
} // end namespace irr
#endif

View File

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

View File

@ -124,11 +124,6 @@ namespace scene
class ITriangleSelector;
class IVolumeLightSceneNode;
namespace quake3
{
struct IShader;
} // end namespace quake3
//! The Scene Manager manages scene nodes, mesh recources, cameras and all the other stuff.
/** All Scene nodes can be created only here. There is a always growing
list of scene nodes for lots of purposes: Indoor rendering scene nodes
@ -914,14 +909,6 @@ namespace scene
s32 maxLOD=5, E_TERRAIN_PATCH_SIZE patchSize=ETPS_17, s32 smoothFactor=0,
bool addAlsoIfHeightmapEmpty = false) = 0;
//! Adds a quake3 scene node to the scene graph.
/** A Quake3 Scene renders multiple meshes for a specific HighLanguage Shader (Quake3 Style )
\return Pointer to the quake3 scene node if successful, otherwise NULL.
This pointer should not be dropped. See IReferenceCounted::drop() for more information. */
virtual IMeshSceneNode* addQuake3SceneNode(const IMeshBuffer* meshBuffer, const quake3::IShader * shader,
ISceneNode* parent=0, s32 id=-1
) = 0;
//! Adds an empty scene node to the scene graph.
/** Can be used for doing advanced transformations

View File

@ -244,53 +244,14 @@ the engine will no longer read .png images. */
#undef _IRR_USE_NON_SYSTEM_LIB_PNG_
#endif
//! Define _IRR_COMPILE_WITH_CG_ to enable Cg Shading Language support
//#define _IRR_COMPILE_WITH_CG_
#ifdef NO_IRR_COMPILE_WITH_CG_
#undef _IRR_COMPILE_WITH_CG_
#endif
#if !defined(_IRR_COMPILE_WITH_OPENGL_) && !defined(_IRR_COMPILE_WITH_DIRECT3D_9_)
#undef _IRR_COMPILE_WITH_CG_
#endif
//! Define _IRR_USE_NVIDIA_PERFHUD_ to opt-in to using the nVidia PerHUD tool
/** Enable, by opting-in, to use the nVidia PerfHUD performance analysis driver
tool <http://developer.nvidia.com/object/nvperfhud_home.html>. */
#undef _IRR_USE_NVIDIA_PERFHUD_
//! Define one of the three setting for Burning's Video Software Rasterizer
/** So if we were marketing guys we could say Irrlicht has 4 Software-Rasterizers.
In a Nutshell:
All Burnings Rasterizers use 32 Bit Backbuffer, 32Bit Texture & 32 Bit Z or WBuffer,
16 Bit/32 Bit can be adjusted on a global flag.
BURNINGVIDEO_RENDERER_BEAUTIFUL
32 Bit + Vertexcolor + Lighting + Per Pixel Perspective Correct + SubPixel/SubTexel Correct +
Bilinear Texturefiltering + WBuffer
BURNINGVIDEO_RENDERER_FAST
32 Bit + Per Pixel Perspective Correct + SubPixel/SubTexel Correct + WBuffer +
Bilinear Dithering TextureFiltering + WBuffer
BURNINGVIDEO_RENDERER_ULTRA_FAST
16Bit + SubPixel/SubTexel Correct + ZBuffer
*/
#define BURNINGVIDEO_RENDERER_BEAUTIFUL
//#define BURNINGVIDEO_RENDERER_FAST
//#define BURNINGVIDEO_RENDERER_ULTRA_FAST
//#define BURNINGVIDEO_RENDERER_CE
//! Uncomment the following line if you want to ignore the deprecated warnings
//#define IGNORE_DEPRECATED_WARNING
//! Define _IRR_COMPILE_WITH_IRR_SCENE_LOADER_ if you want to be able to load
/** .irr scenes using ISceneManager::loadScene */
#define _IRR_COMPILE_WITH_IRR_SCENE_LOADER_
#ifdef NO_IRR_COMPILE_WITH_IRR_SCENE_LOADER_
#undef _IRR_COMPILE_WITH_IRR_SCENE_LOADER_
#endif
//! Define _IRR_COMPILE_WITH_SKINNED_MESH_SUPPORT_ if you want to use bone based
/** animated meshes. If you compile without this, you will be unable to load
B3D, MS3D or X meshes */
@ -307,108 +268,6 @@ B3D, MS3D or X meshes */
#endif
#endif // _IRR_COMPILE_WITH_SKINNED_MESH_SUPPORT_
//! Define _IRR_COMPILE_WITH_IRR_MESH_LOADER_ if you want to load Irrlicht Engine .irrmesh files
#define _IRR_COMPILE_WITH_IRR_MESH_LOADER_
#ifdef NO_IRR_COMPILE_WITH_IRR_MESH_LOADER_
#undef _IRR_COMPILE_WITH_IRR_MESH_LOADER_
#endif
//! Define _IRR_COMPILE_WITH_MD2_LOADER_ if you want to load Quake 2 animated files
#define _IRR_COMPILE_WITH_MD2_LOADER_
#ifdef NO_IRR_COMPILE_WITH_MD2_LOADER_
#undef _IRR_COMPILE_WITH_MD2_LOADER_
#endif
//! Define _IRR_COMPILE_WITH_MD3_LOADER_ if you want to load Quake 3 animated files
#define _IRR_COMPILE_WITH_MD3_LOADER_
#ifdef NO_IRR_COMPILE_WITH_MD3_LOADER_
#undef _IRR_COMPILE_WITH_MD3_LOADER_
#endif
//! Define _IRR_COMPILE_WITH_COLLADA_LOADER_ if you want to load Collada files
#define _IRR_COMPILE_WITH_COLLADA_LOADER_
#ifdef NO_IRR_COMPILE_WITH_COLLADA_LOADER_
#undef _IRR_COMPILE_WITH_COLLADA_LOADER_
#endif
//! Define _IRR_COMPILE_WITH_CSM_LOADER_ if you want to load Cartography Shop files
#define _IRR_COMPILE_WITH_CSM_LOADER_
#ifdef NO_IRR_COMPILE_WITH_CSM_LOADER_
#undef _IRR_COMPILE_WITH_CSM_LOADER_
#endif
//! Define _IRR_COMPILE_WITH_BSP_LOADER_ if you want to load Quake 3 BSP files
#define _IRR_COMPILE_WITH_BSP_LOADER_
#ifdef NO_IRR_COMPILE_WITH_BSP_LOADER_
#undef _IRR_COMPILE_WITH_BSP_LOADER_
#endif
//! Define _IRR_COMPILE_WITH_DMF_LOADER_ if you want to load DeleD files
#define _IRR_COMPILE_WITH_DMF_LOADER_
#ifdef NO_IRR_COMPILE_WITH_DMF_LOADER_
#undef _IRR_COMPILE_WITH_DMF_LOADER_
#endif
//! Define _IRR_COMPILE_WITH_LMTS_LOADER_ if you want to load LMTools files
#define _IRR_COMPILE_WITH_LMTS_LOADER_
#ifdef NO_IRR_COMPILE_WITH_LMTS_LOADER_
#undef _IRR_COMPILE_WITH_LMTS_LOADER_
#endif
//! Define _IRR_COMPILE_WITH_MY3D_LOADER_ if you want to load MY3D files
#define _IRR_COMPILE_WITH_MY3D_LOADER_
#ifdef NO_IRR_COMPILE_WITH_MY3D_LOADER_
#undef _IRR_COMPILE_WITH_MY3D_LOADER_
#endif
//! Define _IRR_COMPILE_WITH_OBJ_LOADER_ if you want to load Wavefront OBJ files
#define _IRR_COMPILE_WITH_OBJ_LOADER_
#ifdef NO_IRR_COMPILE_WITH_OBJ_LOADER_
#undef _IRR_COMPILE_WITH_OBJ_LOADER_
#endif
//! Define _IRR_COMPILE_WITH_OCT_LOADER_ if you want to load FSRad OCT files
#define _IRR_COMPILE_WITH_OCT_LOADER_
#ifdef NO_IRR_COMPILE_WITH_OCT_LOADER_
#undef _IRR_COMPILE_WITH_OCT_LOADER_
#endif
//! Define _IRR_COMPILE_WITH_LWO_LOADER_ if you want to load Lightwave3D files
#define _IRR_COMPILE_WITH_LWO_LOADER_
#ifdef NO_IRR_COMPILE_WITH_LWO_LOADER_
#undef _IRR_COMPILE_WITH_LWO_LOADER_
#endif
//! Define _IRR_COMPILE_WITH_STL_LOADER_ if you want to load stereolithography files
#define _IRR_COMPILE_WITH_STL_LOADER_
#ifdef NO_IRR_COMPILE_WITH_STL_LOADER_
#undef _IRR_COMPILE_WITH_STL_LOADER_
#endif
//! Define _IRR_COMPILE_WITH_PLY_LOADER_ if you want to load Polygon (Stanford Triangle) files
#define _IRR_COMPILE_WITH_PLY_LOADER_
#ifdef NO_IRR_COMPILE_WITH_PLY_LOADER_
#undef _IRR_COMPILE_WITH_PLY_LOADER_
#endif
//! Define _IRR_COMPILE_WITH_SMF_LOADER_ if you want to load 3D World Studio mesh files
#define _IRR_COMPILE_WITH_SMF_LOADER_
#ifdef NO_IRR_COMPILE_WITH_SMF_LOADER_
#undef _IRR_COMPILE_WITH_SMF_LOADER_
#endif
//! Define _IRR_COMPILE_WITH_IRR_WRITER_ if you want to write static .irrMesh files
//#define _IRR_COMPILE_WITH_IRR_WRITER_
#ifdef NO_IRR_COMPILE_WITH_IRR_WRITER_
#undef _IRR_COMPILE_WITH_IRR_WRITER_
#endif
//! Define _IRR_COMPILE_WITH_COLLADA_WRITER_ if you want to write Collada files
//#define _IRR_COMPILE_WITH_COLLADA_WRITER_
#ifdef NO_IRR_COMPILE_WITH_COLLADA_WRITER_
#undef _IRR_COMPILE_WITH_COLLADA_WRITER_
#endif
//! Define _IRR_COMPILE_WITH_STL_WRITER_ if you want to write .stl files
//#define _IRR_COMPILE_WITH_STL_WRITER_
#ifdef NO_IRR_COMPILE_WITH_STL_WRITER_
#undef _IRR_COMPILE_WITH_STL_WRITER_
#endif
//! Define _IRR_COMPILE_WITH_OBJ_WRITER_ if you want to write .obj files
//#define _IRR_COMPILE_WITH_OBJ_WRITER_
#ifdef NO_IRR_COMPILE_WITH_OBJ_WRITER_
#undef _IRR_COMPILE_WITH_OBJ_WRITER_
#endif
//! Define _IRR_COMPILE_WITH_PLY_WRITER_ if you want to write .ply files
//#define _IRR_COMPILE_WITH_PLY_WRITER_
#ifdef NO_IRR_COMPILE_WITH_PLY_WRITER_
#undef _IRR_COMPILE_WITH_PLY_WRITER_
#endif
//! Define _IRR_COMPILE_WITH_BMP_LOADER_ if you want to load .bmp files
//! Disabling this loader will also disable the built-in font
#define _IRR_COMPILE_WITH_BMP_LOADER_
@ -644,64 +503,6 @@ precision will be lower but speed higher. currently X86 only
#endif
#endif
// XBox does not have OpenGL or DirectX9
#if defined(_IRR_XBOX_PLATFORM_)
#undef _IRR_COMPILE_WITH_OPENGL_
#undef _IRR_COMPILE_WITH_DIRECT3D_9_
#endif
//! WinCE does not have OpenGL or DirectX9. use minimal loaders
#if defined(_WIN32_WCE)
#undef _IRR_COMPILE_WITH_OPENGL_
#undef _IRR_COMPILE_WITH_DIRECT3D_8_
#undef _IRR_COMPILE_WITH_DIRECT3D_9_
#undef BURNINGVIDEO_RENDERER_BEAUTIFUL
#undef BURNINGVIDEO_RENDERER_FAST
#undef BURNINGVIDEO_RENDERER_ULTRA_FAST
#define BURNINGVIDEO_RENDERER_CE
#undef _IRR_COMPILE_WITH_WINDOWS_DEVICE_
#define _IRR_COMPILE_WITH_WINDOWS_CE_DEVICE_
//#define _IRR_WCHAR_FILESYSTEM
#undef _IRR_COMPILE_WITH_IRR_MESH_LOADER_
//#undef _IRR_COMPILE_WITH_MD2_LOADER_
#undef _IRR_COMPILE_WITH_MD3_LOADER_
#undef _IRR_COMPILE_WITH_3DS_LOADER_
#undef _IRR_COMPILE_WITH_COLLADA_LOADER_
#undef _IRR_COMPILE_WITH_CSM_LOADER_
#undef _IRR_COMPILE_WITH_BSP_LOADER_
#undef _IRR_COMPILE_WITH_DMF_LOADER_
#undef _IRR_COMPILE_WITH_LMTS_LOADER_
#undef _IRR_COMPILE_WITH_MY3D_LOADER_
#undef _IRR_COMPILE_WITH_OBJ_LOADER_
#undef _IRR_COMPILE_WITH_OCT_LOADER_
#undef _IRR_COMPILE_WITH_OGRE_LOADER_
#undef _IRR_COMPILE_WITH_LWO_LOADER_
#undef _IRR_COMPILE_WITH_STL_LOADER_
#undef _IRR_COMPILE_WITH_IRR_WRITER_
#undef _IRR_COMPILE_WITH_COLLADA_WRITER_
#undef _IRR_COMPILE_WITH_STL_WRITER_
#undef _IRR_COMPILE_WITH_OBJ_WRITER_
//#undef _IRR_COMPILE_WITH_BMP_LOADER_
//#undef _IRR_COMPILE_WITH_JPG_LOADER_
#undef _IRR_COMPILE_WITH_PCX_LOADER_
//#undef _IRR_COMPILE_WITH_PNG_LOADER_
#undef _IRR_COMPILE_WITH_PPM_LOADER_
#undef _IRR_COMPILE_WITH_PSD_LOADER_
//#undef _IRR_COMPILE_WITH_TGA_LOADER_
#undef _IRR_COMPILE_WITH_WAL_LOADER_
#undef _IRR_COMPILE_WITH_BMP_WRITER_
#undef _IRR_COMPILE_WITH_JPG_WRITER_
#undef _IRR_COMPILE_WITH_PCX_WRITER_
#undef _IRR_COMPILE_WITH_PNG_WRITER_
#undef _IRR_COMPILE_WITH_PPM_WRITER_
#undef _IRR_COMPILE_WITH_PSD_WRITER_
#undef _IRR_COMPILE_WITH_TGA_WRITER_
#endif
#ifndef _IRR_WINDOWS_API_
#undef _IRR_WCHAR_FILESYSTEM
#endif

View File

@ -54,8 +54,6 @@
#include "fast_atof.h"
#include "heapsort.h"
#include "IAnimatedMesh.h"
#include "IAnimatedMeshMD2.h"
#include "IAnimatedMeshMD3.h"
#include "IAnimatedMeshSceneNode.h"
#include "IAttributeExchangingObject.h"
#include "IAttributes.h"
@ -112,12 +110,9 @@
#include "IMeshManipulator.h"
#include "IMeshSceneNode.h"
#include "IMeshWriter.h"
#include "IColladaMeshWriter.h"
#include "IMetaTriangleSelector.h"
#include "IOSOperator.h"
#include "IParticleSystemSceneNode.h" // also includes all emitters and attractors
#include "IQ3LevelMesh.h"
#include "IQ3Shader.h"
#include "IReadFile.h"
#include "IReferenceCounted.h"
#include "irrArray.h"

View File

@ -1,457 +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 "IrrCompileConfig.h"
#ifdef _IRR_COMPILE_WITH_MD2_LOADER_
#include "CAnimatedMeshMD2.h"
#include "SColor.h"
#include "irrMath.h"
namespace irr
{
namespace scene
{
const s32 MD2_FRAME_SHIFT = 2;
const f32 MD2_FRAME_SHIFT_RECIPROCAL = 1.f / (1 << MD2_FRAME_SHIFT);
const s32 Q2_VERTEX_NORMAL_TABLE_SIZE = 162;
static const f32 Q2_VERTEX_NORMAL_TABLE[Q2_VERTEX_NORMAL_TABLE_SIZE][3] = {
{-0.525731f, 0.000000f, 0.850651f},
{-0.442863f, 0.238856f, 0.864188f},
{-0.295242f, 0.000000f, 0.955423f},
{-0.309017f, 0.500000f, 0.809017f},
{-0.162460f, 0.262866f, 0.951056f},
{0.000000f, 0.000000f, 1.000000f},
{0.000000f, 0.850651f, 0.525731f},
{-0.147621f, 0.716567f, 0.681718f},
{0.147621f, 0.716567f, 0.681718f},
{0.000000f, 0.525731f, 0.850651f},
{0.309017f, 0.500000f, 0.809017f},
{0.525731f, 0.000000f, 0.850651f},
{0.295242f, 0.000000f, 0.955423f},
{0.442863f, 0.238856f, 0.864188f},
{0.162460f, 0.262866f, 0.951056f},
{-0.681718f, 0.147621f, 0.716567f},
{-0.809017f, 0.309017f, 0.500000f},
{-0.587785f, 0.425325f, 0.688191f},
{-0.850651f, 0.525731f, 0.000000f},
{-0.864188f, 0.442863f, 0.238856f},
{-0.716567f, 0.681718f, 0.147621f},
{-0.688191f, 0.587785f, 0.425325f},
{-0.500000f, 0.809017f, 0.309017f},
{-0.238856f, 0.864188f, 0.442863f},
{-0.425325f, 0.688191f, 0.587785f},
{-0.716567f, 0.681718f, -0.147621f},
{-0.500000f, 0.809017f, -0.309017f},
{-0.525731f, 0.850651f, 0.000000f},
{0.000000f, 0.850651f, -0.525731f},
{-0.238856f, 0.864188f, -0.442863f},
{0.000000f, 0.955423f, -0.295242f},
{-0.262866f, 0.951056f, -0.162460f},
{0.000000f, 1.000000f, 0.000000f},
{0.000000f, 0.955423f, 0.295242f},
{-0.262866f, 0.951056f, 0.162460f},
{0.238856f, 0.864188f, 0.442863f},
{0.262866f, 0.951056f, 0.162460f},
{0.500000f, 0.809017f, 0.309017f},
{0.238856f, 0.864188f, -0.442863f},
{0.262866f, 0.951056f, -0.162460f},
{0.500000f, 0.809017f, -0.309017f},
{0.850651f, 0.525731f, 0.000000f},
{0.716567f, 0.681718f, 0.147621f},
{0.716567f, 0.681718f, -0.147621f},
{0.525731f, 0.850651f, 0.000000f},
{0.425325f, 0.688191f, 0.587785f},
{0.864188f, 0.442863f, 0.238856f},
{0.688191f, 0.587785f, 0.425325f},
{0.809017f, 0.309017f, 0.500000f},
{0.681718f, 0.147621f, 0.716567f},
{0.587785f, 0.425325f, 0.688191f},
{0.955423f, 0.295242f, 0.000000f},
{1.000000f, 0.000000f, 0.000000f},
{0.951056f, 0.162460f, 0.262866f},
{0.850651f, -0.525731f, 0.000000f},
{0.955423f, -0.295242f, 0.000000f},
{0.864188f, -0.442863f, 0.238856f},
{0.951056f, -0.162460f, 0.262866f},
{0.809017f, -0.309017f, 0.500000f},
{0.681718f, -0.147621f, 0.716567f},
{0.850651f, 0.000000f, 0.525731f},
{0.864188f, 0.442863f, -0.238856f},
{0.809017f, 0.309017f, -0.500000f},
{0.951056f, 0.162460f, -0.262866f},
{0.525731f, 0.000000f, -0.850651f},
{0.681718f, 0.147621f, -0.716567f},
{0.681718f, -0.147621f, -0.716567f},
{0.850651f, 0.000000f, -0.525731f},
{0.809017f, -0.309017f, -0.500000f},
{0.864188f, -0.442863f, -0.238856f},
{0.951056f, -0.162460f, -0.262866f},
{0.147621f, 0.716567f, -0.681718f},
{0.309017f, 0.500000f, -0.809017f},
{0.425325f, 0.688191f, -0.587785f},
{0.442863f, 0.238856f, -0.864188f},
{0.587785f, 0.425325f, -0.688191f},
{0.688191f, 0.587785f, -0.425325f},
{-0.147621f, 0.716567f, -0.681718f},
{-0.309017f, 0.500000f, -0.809017f},
{0.000000f, 0.525731f, -0.850651f},
{-0.525731f, 0.000000f, -0.850651f},
{-0.442863f, 0.238856f, -0.864188f},
{-0.295242f, 0.000000f, -0.955423f},
{-0.162460f, 0.262866f, -0.951056f},
{0.000000f, 0.000000f, -1.000000f},
{0.295242f, 0.000000f, -0.955423f},
{0.162460f, 0.262866f, -0.951056f},
{-0.442863f, -0.238856f, -0.864188f},
{-0.309017f, -0.500000f, -0.809017f},
{-0.162460f, -0.262866f, -0.951056f},
{0.000000f, -0.850651f, -0.525731f},
{-0.147621f, -0.716567f, -0.681718f},
{0.147621f, -0.716567f, -0.681718f},
{0.000000f, -0.525731f, -0.850651f},
{0.309017f, -0.500000f, -0.809017f},
{0.442863f, -0.238856f, -0.864188f},
{0.162460f, -0.262866f, -0.951056f},
{0.238856f, -0.864188f, -0.442863f},
{0.500000f, -0.809017f, -0.309017f},
{0.425325f, -0.688191f, -0.587785f},
{0.716567f, -0.681718f, -0.147621f},
{0.688191f, -0.587785f, -0.425325f},
{0.587785f, -0.425325f, -0.688191f},
{0.000000f, -0.955423f, -0.295242f},
{0.000000f, -1.000000f, 0.000000f},
{0.262866f, -0.951056f, -0.162460f},
{0.000000f, -0.850651f, 0.525731f},
{0.000000f, -0.955423f, 0.295242f},
{0.238856f, -0.864188f, 0.442863f},
{0.262866f, -0.951056f, 0.162460f},
{0.500000f, -0.809017f, 0.309017f},
{0.716567f, -0.681718f, 0.147621f},
{0.525731f, -0.850651f, 0.000000f},
{-0.238856f, -0.864188f, -0.442863f},
{-0.500000f, -0.809017f, -0.309017f},
{-0.262866f, -0.951056f, -0.162460f},
{-0.850651f, -0.525731f, 0.000000f},
{-0.716567f, -0.681718f, -0.147621f},
{-0.716567f, -0.681718f, 0.147621f},
{-0.525731f, -0.850651f, 0.000000f},
{-0.500000f, -0.809017f, 0.309017f},
{-0.238856f, -0.864188f, 0.442863f},
{-0.262866f, -0.951056f, 0.162460f},
{-0.864188f, -0.442863f, 0.238856f},
{-0.809017f, -0.309017f, 0.500000f},
{-0.688191f, -0.587785f, 0.425325f},
{-0.681718f, -0.147621f, 0.716567f},
{-0.442863f, -0.238856f, 0.864188f},
{-0.587785f, -0.425325f, 0.688191f},
{-0.309017f, -0.500000f, 0.809017f},
{-0.147621f, -0.716567f, 0.681718f},
{-0.425325f, -0.688191f, 0.587785f},
{-0.162460f, -0.262866f, 0.951056f},
{0.442863f, -0.238856f, 0.864188f},
{0.162460f, -0.262866f, 0.951056f},
{0.309017f, -0.500000f, 0.809017f},
{0.147621f, -0.716567f, 0.681718f},
{0.000000f, -0.525731f, 0.850651f},
{0.425325f, -0.688191f, 0.587785f},
{0.587785f, -0.425325f, 0.688191f},
{0.688191f, -0.587785f, 0.425325f},
{-0.955423f, 0.295242f, 0.000000f},
{-0.951056f, 0.162460f, 0.262866f},
{-1.000000f, 0.000000f, 0.000000f},
{-0.850651f, 0.000000f, 0.525731f},
{-0.955423f, -0.295242f, 0.000000f},
{-0.951056f, -0.162460f, 0.262866f},
{-0.864188f, 0.442863f, -0.238856f},
{-0.951056f, 0.162460f, -0.262866f},
{-0.809017f, 0.309017f, -0.500000f},
{-0.864188f, -0.442863f, -0.238856f},
{-0.951056f, -0.162460f, -0.262866f},
{-0.809017f, -0.309017f, -0.500000f},
{-0.681718f, 0.147621f, -0.716567f},
{-0.681718f, -0.147621f, -0.716567f},
{-0.850651f, 0.000000f, -0.525731f},
{-0.688191f, 0.587785f, -0.425325f},
{-0.587785f, 0.425325f, -0.688191f},
{-0.425325f, 0.688191f, -0.587785f},
{-0.425325f, -0.688191f, -0.587785f},
{-0.587785f, -0.425325f, -0.688191f},
{-0.688191f, -0.587785f, -0.425325f},
};
struct SMD2AnimationType
{
s32 begin;
s32 end;
s32 fps;
};
static const SMD2AnimationType MD2AnimationTypeList[21] =
{
{ 0, 39, 9}, // STAND
{ 40, 45, 10}, // RUN
{ 46, 53, 10}, // ATTACK
{ 54, 57, 7}, // PAIN_A
{ 58, 61, 7}, // PAIN_B
{ 62, 65, 7}, // PAIN_C
{ 66, 71, 7}, // JUMP
{ 72, 83, 7}, // FLIP
{ 84, 94, 7}, // SALUTE
{ 95, 111, 10}, // FALLBACK
{112, 122, 7}, // WAVE
{123, 134, 6}, // POINT
{135, 153, 10}, // CROUCH_STAND
{154, 159, 7}, // CROUCH_WALK
{160, 168, 10}, // CROUCH_ATTACK
{169, 172, 7}, // CROUCH_PAIN
{173, 177, 5}, // CROUCH_DEATH
{178, 183, 7}, // DEATH_FALLBACK
{184, 189, 7}, // DEATH_FALLFORWARD
{190, 197, 7}, // DEATH_FALLBACKSLOW
{198, 198, 5}, // BOOM
};
//! constructor
CAnimatedMeshMD2::CAnimatedMeshMD2()
: InterpolationBuffer(0), FrameList(0), FrameCount(0), FramesPerSecond((f32)(MD2AnimationTypeList[0].fps << MD2_FRAME_SHIFT))
{
#ifdef _DEBUG
IAnimatedMesh::setDebugName("CAnimatedMeshMD2 IAnimatedMesh");
IMesh::setDebugName("CAnimatedMeshMD2 IMesh");
#endif
InterpolationBuffer = new SMeshBuffer;
}
//! destructor
CAnimatedMeshMD2::~CAnimatedMeshMD2()
{
delete [] FrameList;
if (InterpolationBuffer)
InterpolationBuffer->drop();
}
//! returns the amount of frames in milliseconds. If the amount is 1, it is a static (=non animated) mesh.
u32 CAnimatedMeshMD2::getFrameCount() const
{
return FrameCount<<MD2_FRAME_SHIFT;
}
//! returns the animated mesh based on a detail level. 0 is the lowest, 255 the highest detail. Note, that some Meshes will ignore the detail level.
IMesh* CAnimatedMeshMD2::getMesh(s32 frame, s32 detailLevel, s32 startFrameLoop, s32 endFrameLoop)
{
if ((u32)frame > getFrameCount())
frame = (frame % getFrameCount());
if (startFrameLoop == -1 && endFrameLoop == -1)
{
startFrameLoop = 0;
endFrameLoop = getFrameCount();
}
updateInterpolationBuffer(frame, startFrameLoop, endFrameLoop);
return this;
}
//! returns amount of mesh buffers. MD2 meshes only have one buffer
u32 CAnimatedMeshMD2::getMeshBufferCount() const
{
return 1;
}
//! returns pointer to a mesh buffer
IMeshBuffer* CAnimatedMeshMD2::getMeshBuffer(u32 nr) const
{
if (nr == 0)
return InterpolationBuffer;
else
return 0;
}
//! Returns pointer to a mesh buffer which fits a material
IMeshBuffer* CAnimatedMeshMD2::getMeshBuffer(const video::SMaterial &material) const
{
if (InterpolationBuffer->Material == material)
return InterpolationBuffer;
else
return 0;
}
// updates the interpolation buffer
void CAnimatedMeshMD2::updateInterpolationBuffer(s32 frame, s32 startFrameLoop, s32 endFrameLoop)
{
u32 firstFrame, secondFrame;
f32 div;
// TA: resolve missing ipol in loop between end-start
if (endFrameLoop - startFrameLoop == 0)
{
firstFrame = frame>>MD2_FRAME_SHIFT;
secondFrame = frame>>MD2_FRAME_SHIFT;
div = 1.0f;
}
else
{
// key frames
u32 s = startFrameLoop >> MD2_FRAME_SHIFT;
u32 e = endFrameLoop >> MD2_FRAME_SHIFT;
firstFrame = frame >> MD2_FRAME_SHIFT;
secondFrame = core::if_c_a_else_b(firstFrame + 1 > e, s, firstFrame + 1);
firstFrame = core::s32_min(FrameCount - 1, firstFrame);
secondFrame = core::s32_min(FrameCount - 1, secondFrame);
//div = (frame % (1<<MD2_FRAME_SHIFT)) / (f32)(1<<MD2_FRAME_SHIFT);
frame &= (1<<MD2_FRAME_SHIFT) - 1;
div = frame * MD2_FRAME_SHIFT_RECIPROCAL;
}
video::S3DVertex* target = static_cast<video::S3DVertex*>(InterpolationBuffer->getVertices());
SMD2Vert* first = FrameList[firstFrame].pointer();
SMD2Vert* second = FrameList[secondFrame].pointer();
// interpolate both frames
const u32 count = FrameList[firstFrame].size();
for (u32 i=0; i<count; ++i)
{
const core::vector3df one = core::vector3df(f32(first->Pos.X) * FrameTransforms[firstFrame].scale.X + FrameTransforms[firstFrame].translate.X,
f32(first->Pos.Y) * FrameTransforms[firstFrame].scale.Y + FrameTransforms[firstFrame].translate.Y,
f32(first->Pos.Z) * FrameTransforms[firstFrame].scale.Z + FrameTransforms[firstFrame].translate.Z);
const core::vector3df two = core::vector3df(f32(second->Pos.X) * FrameTransforms[secondFrame].scale.X + FrameTransforms[secondFrame].translate.X,
f32(second->Pos.Y) * FrameTransforms[secondFrame].scale.Y + FrameTransforms[secondFrame].translate.Y,
f32(second->Pos.Z) * FrameTransforms[secondFrame].scale.Z + FrameTransforms[secondFrame].translate.Z);
target->Pos = two.getInterpolated(one, div);
const core::vector3df n1(
Q2_VERTEX_NORMAL_TABLE[first->NormalIdx][0],
Q2_VERTEX_NORMAL_TABLE[first->NormalIdx][2],
Q2_VERTEX_NORMAL_TABLE[first->NormalIdx][1]);
const core::vector3df n2(
Q2_VERTEX_NORMAL_TABLE[second->NormalIdx][0],
Q2_VERTEX_NORMAL_TABLE[second->NormalIdx][2],
Q2_VERTEX_NORMAL_TABLE[second->NormalIdx][1]);
target->Normal = n2.getInterpolated(n1, div);
++target;
++first;
++second;
}
//update bounding box
InterpolationBuffer->setBoundingBox(BoxList[secondFrame].getInterpolated(BoxList[firstFrame], div));
InterpolationBuffer->setDirty();
}
//! sets a flag of all contained materials to a new value
void CAnimatedMeshMD2::setMaterialFlag(video::E_MATERIAL_FLAG flag, bool newvalue)
{
InterpolationBuffer->Material.setFlag(flag, newvalue);
}
//! set the hardware mapping hint, for driver
void CAnimatedMeshMD2::setHardwareMappingHint(E_HARDWARE_MAPPING newMappingHint,
E_BUFFER_TYPE buffer)
{
InterpolationBuffer->setHardwareMappingHint(newMappingHint, buffer);
}
//! flags the meshbuffer as changed, reloads hardware buffers
void CAnimatedMeshMD2::setDirty(E_BUFFER_TYPE buffer)
{
InterpolationBuffer->setDirty(buffer);
}
//! returns an axis aligned bounding box
const core::aabbox3d<f32>& CAnimatedMeshMD2::getBoundingBox() const
{
return InterpolationBuffer->BoundingBox;
}
//! set user axis aligned bounding box
void CAnimatedMeshMD2::setBoundingBox(const core::aabbox3df& box)
{
InterpolationBuffer->BoundingBox = box;
}
//! Returns the type of the animated mesh.
E_ANIMATED_MESH_TYPE CAnimatedMeshMD2::getMeshType() const
{
return EAMT_MD2;
}
//! Returns frame loop data for a special MD2 animation type.
void CAnimatedMeshMD2::getFrameLoop(EMD2_ANIMATION_TYPE l,
s32& outBegin, s32& outEnd, s32& outFPS) const
{
if (l < 0 || l >= EMAT_COUNT)
return;
outBegin = MD2AnimationTypeList[l].begin << MD2_FRAME_SHIFT;
outEnd = MD2AnimationTypeList[l].end << MD2_FRAME_SHIFT;
// correct to anim between last->first frame
outEnd += MD2_FRAME_SHIFT == 0 ? 1 : (1 << MD2_FRAME_SHIFT) - 1;
outFPS = MD2AnimationTypeList[l].fps << MD2_FRAME_SHIFT;
}
//! Returns frame loop data for a special MD2 animation type.
bool CAnimatedMeshMD2::getFrameLoop(const c8* name,
s32& outBegin, s32&outEnd, s32& outFPS) const
{
for (u32 i=0; i < AnimationData.size(); ++i)
{
if (AnimationData[i].name == name)
{
outBegin = AnimationData[i].begin << MD2_FRAME_SHIFT;
outEnd = AnimationData[i].end << MD2_FRAME_SHIFT;
outEnd += MD2_FRAME_SHIFT == 0 ? 1 : (1 << MD2_FRAME_SHIFT) - 1;
outFPS = AnimationData[i].fps << MD2_FRAME_SHIFT;
return true;
}
}
return false;
}
//! Returns amount of md2 animations in this file.
s32 CAnimatedMeshMD2::getAnimationCount() const
{
return AnimationData.size();
}
//! Returns name of md2 animation.
const c8* CAnimatedMeshMD2::getAnimationName(s32 nr) const
{
if ((u32)nr >= AnimationData.size())
return 0;
return AnimationData[nr].name.c_str();
}
} // end namespace scene
} // end namespace irr
#endif // _IRR_COMPILE_WITH_MD2_LOADER_

View File

@ -1,154 +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_ANIMATED_MESH_MD2_H_INCLUDED__
#define __C_ANIMATED_MESH_MD2_H_INCLUDED__
#include "IAnimatedMeshMD2.h"
#include "IMesh.h"
#include "CMeshBuffer.h"
#include "IReadFile.h"
#include "S3DVertex.h"
#include "irrArray.h"
#include "irrString.h"
namespace irr
{
namespace scene
{
class CAnimatedMeshMD2 : public IAnimatedMeshMD2
{
public:
//! constructor
CAnimatedMeshMD2();
//! destructor
virtual ~CAnimatedMeshMD2();
//! returns the amount of frames. If the amount is 1, it is a static (=non animated) mesh.
virtual u32 getFrameCount() const;
//! Gets the default animation speed of the animated mesh.
/** \return Amount of frames per second. If the amount is 0, it is a static, non animated mesh. */
virtual f32 getAnimationSpeed() const
{
return FramesPerSecond;
}
//! Gets the frame count of the animated mesh.
/** \param fps Frames per second to play the animation with. If the amount is 0, it is not animated.
The actual speed is set in the scene node the mesh is instantiated in.*/
virtual void setAnimationSpeed(f32 fps)
{
FramesPerSecond=fps;
}
//! returns the animated mesh based on a detail level. 0 is the lowest, 255 the highest detail. Note, that some Meshes will ignore the detail level.
virtual IMesh* getMesh(s32 frame, s32 detailLevel=255, s32 startFrameLoop=-1, s32 endFrameLoop=-1);
//! returns amount of mesh buffers.
virtual u32 getMeshBufferCount() const;
//! returns pointer to a mesh buffer
virtual IMeshBuffer* getMeshBuffer(u32 nr) const;
//! Returns pointer to a mesh buffer which fits a material
/** \param material: material to search for
\return Returns the pointer to the mesh buffer or
NULL if there is no such mesh buffer. */
virtual IMeshBuffer* getMeshBuffer( const video::SMaterial &material) const;
//! returns an axis aligned bounding box
virtual const core::aabbox3d<f32>& getBoundingBox() const;
//! set user axis aligned bounding box
virtual void setBoundingBox( const core::aabbox3df& box);
//! sets a flag of all contained materials to a new value
virtual void setMaterialFlag(video::E_MATERIAL_FLAG flag, bool newvalue);
//! set the hardware mapping hint, for driver
virtual void setHardwareMappingHint(E_HARDWARE_MAPPING newMappingHint, E_BUFFER_TYPE buffer=EBT_VERTEX_AND_INDEX);
//! flags the meshbuffer as changed, reloads hardware buffers
virtual void setDirty(E_BUFFER_TYPE buffer=EBT_VERTEX_AND_INDEX);
//! Returns the type of the animated mesh.
virtual E_ANIMATED_MESH_TYPE getMeshType() const;
//! Returns frame loop data for a special MD2 animation type.
virtual void getFrameLoop(EMD2_ANIMATION_TYPE,
s32& outBegin, s32& outEnd, s32& outFps) const;
//! Returns frame loop data for a special MD2 animation type.
virtual bool getFrameLoop(const c8* name,
s32& outBegin, s32& outEnd, s32& outFps) const;
//! Returns amount of md2 animations in this file.
virtual s32 getAnimationCount() const;
//! Returns name of md2 animation.
//! \param nr: Zero based index of animation.
virtual const c8* getAnimationName(s32 nr) const;
//
// exposed for loader
//
//! the buffer that contains the most recent animation
SMeshBuffer* InterpolationBuffer;
//! named animations
struct SAnimationData
{
core::stringc name;
s32 begin;
s32 end;
s32 fps;
};
//! scale and translations for keyframes
struct SKeyFrameTransform
{
core::vector3df scale;
core::vector3df translate;
};
//! md2 vertex data
struct SMD2Vert
{
core::vector3d<u8> Pos;
u8 NormalIdx;
};
//! keyframe transformations
core::array<SKeyFrameTransform> FrameTransforms;
//! keyframe vertex data
core::array<SMD2Vert> *FrameList;
//! bounding boxes for each keyframe
core::array<core::aabbox3d<f32> > BoxList;
//! named animations
core::array< SAnimationData > AnimationData;
u32 FrameCount;
private:
//! updates the interpolation buffer
void updateInterpolationBuffer(s32 frame, s32 startFrame, s32 endFrame);
f32 FramesPerSecond;
};
} // end namespace scene
} // end namespace irr
#endif

View File

@ -1,468 +0,0 @@
// Copyright (C) 2002-2012 Nikolaus Gebhardt / Fabio Concas / Thomas Alten
// This file is part of the "Irrlicht Engine".
// For conditions of distribution and use, see copyright notice in irrlicht.h
#include "IrrCompileConfig.h"
#ifdef _IRR_COMPILE_WITH_MD3_LOADER_
#include "CAnimatedMeshMD3.h"
#include "os.h"
namespace irr
{
namespace scene
{
// byte-align structures
#include "irrpack.h"
//! General properties of a single animation frame.
struct SMD3Frame
{
f32 mins[3]; // bounding box per frame
f32 maxs[3];
f32 position[3]; // position of bounding box
f32 radius; // radius of bounding sphere
c8 creator[16]; // name of frame
} PACK_STRUCT;
//! An attachment point for another MD3 model.
struct SMD3Tag
{
c8 Name[64]; //name of 'tag' as it's usually called in the md3 files try to see it as a sub-mesh/seperate mesh-part.
f32 position[3]; //relative position of tag
f32 rotationMatrix[9]; //3x3 rotation direction of tag
} PACK_STRUCT;
//!Shader
struct SMD3Shader
{
c8 name[64]; // name of shader
s32 shaderIndex;
} PACK_STRUCT;
// Default alignment
#include "irrunpack.h"
//! Constructor
CAnimatedMeshMD3::CAnimatedMeshMD3()
:Mesh(0), IPolShift(0), LoopMode(0), Scaling(1.f)//, FramesPerSecond(25.f)
{
#ifdef _DEBUG
setDebugName("CAnimatedMeshMD3");
#endif
Mesh = new SMD3Mesh();
MeshIPol = new SMesh();
setInterpolationShift(0, 0);
}
//! Destructor
CAnimatedMeshMD3::~CAnimatedMeshMD3()
{
if (Mesh)
Mesh->drop();
if (MeshIPol)
MeshIPol->drop();
}
//! Returns the amount of frames in milliseconds. If the amount is 1, it is a static (=non animated) mesh.
u32 CAnimatedMeshMD3::getFrameCount() const
{
return Mesh->MD3Header.numFrames << IPolShift;
}
//! Rendering Hint
void CAnimatedMeshMD3::setInterpolationShift(u32 shift, u32 loopMode)
{
IPolShift = shift;
LoopMode = loopMode;
}
//! returns amount of mesh buffers.
u32 CAnimatedMeshMD3::getMeshBufferCount() const
{
return MeshIPol->getMeshBufferCount();
}
//! returns pointer to a mesh buffer
IMeshBuffer* CAnimatedMeshMD3::getMeshBuffer(u32 nr) const
{
return MeshIPol->getMeshBuffer(nr);
}
//! Returns pointer to a mesh buffer which fits a material
IMeshBuffer* CAnimatedMeshMD3::getMeshBuffer(const video::SMaterial &material) const
{
return MeshIPol->getMeshBuffer(material);
}
void CAnimatedMeshMD3::setMaterialFlag(video::E_MATERIAL_FLAG flag, bool newvalue)
{
MeshIPol->setMaterialFlag(flag, newvalue);
}
//! set the hardware mapping hint, for driver
void CAnimatedMeshMD3::setHardwareMappingHint(E_HARDWARE_MAPPING newMappingHint,
E_BUFFER_TYPE buffer)
{
MeshIPol->setHardwareMappingHint(newMappingHint, buffer);
}
//! flags the meshbuffer as changed, reloads hardware buffers
void CAnimatedMeshMD3::setDirty(E_BUFFER_TYPE buffer)
{
MeshIPol->setDirty(buffer);
}
//! set user axis aligned bounding box
void CAnimatedMeshMD3::setBoundingBox(const core::aabbox3df& box)
{
MeshIPol->setBoundingBox(box);
}
//! Returns the animated tag list based on a detail level. 0 is the lowest, 255 the highest detail.
SMD3QuaternionTagList *CAnimatedMeshMD3::getTagList(s32 frame, s32 detailLevel, s32 startFrameLoop, s32 endFrameLoop)
{
if (0 == Mesh)
return 0;
getMesh(frame, detailLevel, startFrameLoop, endFrameLoop);
return &TagListIPol;
}
//! Returns the animated mesh based on a detail level. 0 is the lowest, 255 the highest detail.
IMesh* CAnimatedMeshMD3::getMesh(s32 frame, s32 detailLevel, s32 startFrameLoop, s32 endFrameLoop)
{
if (0 == Mesh)
return 0;
//! check if we have the mesh in our private cache
SCacheInfo candidate(frame, startFrameLoop, endFrameLoop);
if (candidate == Current)
return MeshIPol;
startFrameLoop = core::s32_max(0, startFrameLoop >> IPolShift);
endFrameLoop = core::if_c_a_else_b(endFrameLoop < 0, Mesh->MD3Header.numFrames - 1, endFrameLoop >> IPolShift);
const u32 mask = 1 << IPolShift;
s32 frameA;
s32 frameB;
f32 iPol;
if (LoopMode)
{
// correct frame to "pixel center"
frame -= mask >> 1;
// interpolation
iPol = f32(frame & (mask - 1)) * core::reciprocal(f32(mask));
// wrap anim
frame >>= IPolShift;
frameA = core::if_c_a_else_b(frame < startFrameLoop, endFrameLoop, frame);
frameB = core::if_c_a_else_b(frameA + 1 > endFrameLoop, startFrameLoop, frameA + 1);
}
else
{
// correct frame to "pixel center"
frame -= mask >> 1;
iPol = f32(frame & (mask - 1)) * core::reciprocal(f32(mask));
// clamp anim
frame >>= IPolShift;
frameA = core::s32_clamp(frame, startFrameLoop, endFrameLoop);
frameB = core::s32_min(frameA + 1, endFrameLoop);
}
// build current vertex
for (u32 i = 0; i!= Mesh->Buffer.size(); ++i)
{
buildVertexArray(frameA, frameB, iPol,
Mesh->Buffer[i],
(SMeshBufferLightMap*) MeshIPol->getMeshBuffer(i));
}
MeshIPol->recalculateBoundingBox();
// build current tags
buildTagArray(frameA, frameB, iPol);
Current = candidate;
return MeshIPol;
}
//! create a Irrlicht MeshBuffer for a MD3 MeshBuffer
IMeshBuffer * CAnimatedMeshMD3::createMeshBuffer(const SMD3MeshBuffer* source,
io::IFileSystem* fs, video::IVideoDriver * driver)
{
SMeshBufferLightMap * dest = new SMeshBufferLightMap();
dest->Vertices.set_used(source->MeshHeader.numVertices);
dest->Indices.set_used(source->Indices.size());
u32 i;
// fill in static face info
for (i = 0; i < source->Indices.size(); i += 3)
{
dest->Indices[i + 0] = (u16) source->Indices[i + 0];
dest->Indices[i + 1] = (u16) source->Indices[i + 1];
dest->Indices[i + 2] = (u16) source->Indices[i + 2];
}
// fill in static vertex info
for (i = 0; i!= (u32)source->MeshHeader.numVertices; ++i)
{
video::S3DVertex2TCoords &v = dest->Vertices[i];
v.Color = 0xFFFFFFFF;
v.TCoords.X = source->Tex[i].u;
v.TCoords.Y = source->Tex[i].v;
v.TCoords2.X = 0.f;
v.TCoords2.Y = 0.f;
}
// load static texture
u32 pos = 0;
quake3::tTexArray textureArray;
quake3::getTextures(textureArray, source->Shader, pos, fs, driver);
dest->Material.MaterialType = video::EMT_SOLID;
dest->Material.setTexture(0, textureArray[0]);
dest->Material.Lighting = false;
return dest;
}
//! build final mesh's vertices from frames frameA and frameB with linear interpolation.
void CAnimatedMeshMD3::buildVertexArray(u32 frameA, u32 frameB, f32 interpolate,
const SMD3MeshBuffer* source,
SMeshBufferLightMap* dest)
{
const u32 frameOffsetA = frameA * source->MeshHeader.numVertices;
const u32 frameOffsetB = frameB * source->MeshHeader.numVertices;
const f32 scale = (1.f/ 64.f);
for (s32 i = 0; i != source->MeshHeader.numVertices; ++i)
{
video::S3DVertex2TCoords &v = dest->Vertices [ i ];
const SMD3Vertex &vA = source->Vertices [ frameOffsetA + i ];
const SMD3Vertex &vB = source->Vertices [ frameOffsetB + i ];
// position
v.Pos.X = scale * (vA.position[0] + interpolate * (vB.position[0] - vA.position[0]));
v.Pos.Y = scale * (vA.position[2] + interpolate * (vB.position[2] - vA.position[2]));
v.Pos.Z = scale * (vA.position[1] + interpolate * (vB.position[1] - vA.position[1]));
// normal
const core::vector3df nA(quake3::getMD3Normal(vA.normal[0], vA.normal[1]));
const core::vector3df nB(quake3::getMD3Normal(vB.normal[0], vB.normal[1]));
v.Normal.X = nA.X + interpolate * (nB.X - nA.X);
v.Normal.Y = nA.Z + interpolate * (nB.Z - nA.Z);
v.Normal.Z = nA.Y + interpolate * (nB.Y - nA.Y);
}
dest->recalculateBoundingBox();
}
//! build final mesh's tag from frames frameA and frameB with linear interpolation.
void CAnimatedMeshMD3::buildTagArray(u32 frameA, u32 frameB, f32 interpolate)
{
const u32 frameOffsetA = frameA * Mesh->MD3Header.numTags;
const u32 frameOffsetB = frameB * Mesh->MD3Header.numTags;
for (s32 i = 0; i != Mesh->MD3Header.numTags; ++i)
{
SMD3QuaternionTag &d = TagListIPol [ i ];
const SMD3QuaternionTag &qA = Mesh->TagList[ frameOffsetA + i];
const SMD3QuaternionTag &qB = Mesh->TagList[ frameOffsetB + i];
// rotation
d.rotation.slerp(qA.rotation, qB.rotation, interpolate);
// position
d.position.X = qA.position.X + interpolate * (qB.position.X - qA.position.X);
d.position.Y = qA.position.Y + interpolate * (qB.position.Y - qA.position.Y);
d.position.Z = qA.position.Z + interpolate * (qB.position.Z - qA.position.Z);
}
}
/*!
loads a model
*/
bool CAnimatedMeshMD3::loadModelFile(u32 modelIndex, io::IReadFile* file,
io::IFileSystem* fs, video::IVideoDriver* driver)
{
if (!file)
return false;
//! Check MD3Header
{
file->read(&Mesh->MD3Header, sizeof(SMD3Header));
if (strncmp("IDP3", Mesh->MD3Header.headerID, 4))
{
os::Printer::log("MD3 Loader: invalid header");
return false;
}
}
//! store model name
Mesh->Name = file->getFileName();
u32 i;
//! Frame Data (ignore)
#if 0
SMD3Frame frameImport;
file->seek(Mesh->MD3Header.frameStart);
for (i = 0; i != Mesh->MD3Header.numFrames; ++i)
{
file->read(&frameImport, sizeof(frameImport));
}
#endif
//! Tag Data
const u32 totalTags = Mesh->MD3Header.numTags * Mesh->MD3Header.numFrames;
SMD3Tag import;
file->seek(Mesh->MD3Header.tagStart);
Mesh->TagList.set_used(totalTags);
for (i = 0; i != totalTags; ++i)
{
file->read(&import, sizeof(import));
SMD3QuaternionTag &exp = Mesh->TagList[i];
//! tag name
exp.Name = import.Name;
//! position
exp.position.X = import.position[0];
exp.position.Y = import.position[2];
exp.position.Z = import.position[1];
//! construct quaternion from a RH 3x3 Matrix
exp.rotation.set(import.rotationMatrix[7],
0.f,
-import.rotationMatrix[6],
1 + import.rotationMatrix[8]);
exp.rotation.normalize();
}
//! Meshes
u32 offset = Mesh->MD3Header.tagEnd;
for (i = 0; i != (u32)Mesh->MD3Header.numMeshes; ++i)
{
//! construct a new mesh buffer
SMD3MeshBuffer * buf = new SMD3MeshBuffer();
// !read mesh header info
SMD3MeshHeader &meshHeader = buf->MeshHeader;
//! read mesh info
file->seek(offset);
file->read(&meshHeader, sizeof(SMD3MeshHeader));
//! prepare memory
buf->Vertices.set_used(meshHeader.numVertices * Mesh->MD3Header.numFrames);
buf->Indices.set_used(meshHeader.numTriangles * 3);
buf->Tex.set_used(meshHeader.numVertices);
//! read skins (shaders). should be 1 per meshbuffer
SMD3Shader skin;
file->seek(offset + buf->MeshHeader.offset_shaders);
for (s32 g = 0; g != buf->MeshHeader.numShader; ++g)
{
file->read(&skin, sizeof(skin));
io::path name;
cutFilenameExtension(name, skin.name);
name.replace('\\', '/');
buf->Shader = name;
}
//! read texture coordinates
file->seek(offset + buf->MeshHeader.offset_st);
file->read(buf->Tex.pointer(), buf->MeshHeader.numVertices * sizeof(SMD3TexCoord));
//! read vertices
file->seek(offset + meshHeader.vertexStart);
file->read(buf->Vertices.pointer(), Mesh->MD3Header.numFrames * meshHeader.numVertices * sizeof(SMD3Vertex));
//! read indices
file->seek(offset + meshHeader.offset_triangles);
file->read(buf->Indices.pointer(), meshHeader.numTriangles * sizeof(SMD3Face));
//! store meshBuffer
Mesh->Buffer.push_back(buf);
offset += meshHeader.offset_end;
}
// Init Mesh Interpolation
for (i = 0; i != Mesh->Buffer.size(); ++i)
{
IMeshBuffer * buffer = createMeshBuffer(Mesh->Buffer[i], fs, driver);
MeshIPol->addMeshBuffer(buffer);
buffer->drop();
}
MeshIPol->recalculateBoundingBox();
// Init Tag Interpolation
for (i = 0; i != (u32)Mesh->MD3Header.numTags; ++i)
{
TagListIPol.push_back(Mesh->TagList[i]);
}
return true;
}
SMD3Mesh * CAnimatedMeshMD3::getOriginalMesh()
{
return Mesh;
}
//! Returns an axis aligned bounding box
const core::aabbox3d<f32>& CAnimatedMeshMD3::getBoundingBox() const
{
return MeshIPol->BoundingBox;
}
//! Returns the type of the animated mesh.
E_ANIMATED_MESH_TYPE CAnimatedMeshMD3::getMeshType() const
{
return EAMT_MD3;
}
} // end namespace scene
} // end namespace irr
#endif // _IRR_COMPILE_WITH_MD3_LOADER_

View File

@ -1,135 +0,0 @@
// Copyright (C) 2002-2012 Nikolaus Gebhardt / Thomas Alten
// This file is part of the "Irrlicht Engine".
// For conditions of distribution and use, see copyright notice in irrlicht.h
#ifndef __C_ANIMATED_MESH_MD3_H_INCLUDED__
#define __C_ANIMATED_MESH_MD3_H_INCLUDED__
#include "IAnimatedMeshMD3.h"
#include "IReadFile.h"
#include "IFileSystem.h"
#include "irrArray.h"
#include "irrString.h"
#include "SMesh.h"
#include "SMeshBuffer.h"
#include "IQ3Shader.h"
namespace irr
{
namespace scene
{
class CAnimatedMeshMD3 : public IAnimatedMeshMD3
{
public:
//! constructor
CAnimatedMeshMD3();
//! destructor
virtual ~CAnimatedMeshMD3();
//! loads a quake3 md3 file
virtual bool loadModelFile(u32 modelIndex, io::IReadFile* file,
io::IFileSystem* fs, video::IVideoDriver* driver);
// IAnimatedMeshMD3
virtual void setInterpolationShift(u32 shift, u32 loopMode);
virtual SMD3Mesh* getOriginalMesh();
virtual SMD3QuaternionTagList* getTagList(s32 frame, s32 detailLevel, s32 startFrameLoop, s32 endFrameLoop);
//IAnimatedMesh
virtual u32 getFrameCount() const;
//! Gets the default animation speed of the animated mesh.
/** \return Amount of frames per second. If the amount is 0, it is a static, non animated mesh. */
virtual f32 getAnimationSpeed() const
{
return FramesPerSecond;
}
//! Gets the frame count of the animated mesh.
/** \param fps Frames per second to play the animation with. If the amount is 0, it is not animated.
The actual speed is set in the scene node the mesh is instantiated in.*/
virtual void setAnimationSpeed(f32 fps)
{
FramesPerSecond=fps;
}
virtual IMesh* getMesh(s32 frame, s32 detailLevel,
s32 startFrameLoop, s32 endFrameLoop);
virtual const core::aabbox3d<f32>& getBoundingBox() const;
virtual E_ANIMATED_MESH_TYPE getMeshType() const;
//! returns amount of mesh buffers.
virtual u32 getMeshBufferCount() const;
//! returns pointer to a mesh buffer
virtual IMeshBuffer* getMeshBuffer(u32 nr) const;
//! Returns pointer to a mesh buffer which fits a material
virtual IMeshBuffer* getMeshBuffer(const video::SMaterial &material) const;
virtual void setMaterialFlag(video::E_MATERIAL_FLAG flag, bool newvalue);
//! set user axis aligned bounding box
virtual void setBoundingBox(const core::aabbox3df& box);
//! set the hardware mapping hint, for driver
virtual void setHardwareMappingHint(E_HARDWARE_MAPPING newMappingHint, E_BUFFER_TYPE buffer=EBT_VERTEX_AND_INDEX);
//! flags the meshbuffer as changed, reloads hardware buffers
virtual void setDirty(E_BUFFER_TYPE buffer=EBT_VERTEX_AND_INDEX);
private:
//! animates one frame
inline void Animate(u32 frame);
video::SMaterial Material;
//! hold original compressed MD3 Info
SMD3Mesh *Mesh;
u32 IPolShift;
u32 LoopMode;
f32 Scaling;
//! Cache Info
struct SCacheInfo
{
SCacheInfo(s32 frame=-1, s32 start=-1, s32 end=-1 ) :
Frame(frame), startFrameLoop(start),
endFrameLoop(end)
{}
bool operator == ( const SCacheInfo &other ) const
{
return 0 == memcmp ( this, &other, sizeof ( SCacheInfo ) );
}
s32 Frame;
s32 startFrameLoop;
s32 endFrameLoop;
};
SCacheInfo Current;
//! return a Mesh per frame
SMesh* MeshIPol;
SMD3QuaternionTagList TagListIPol;
IMeshBuffer* createMeshBuffer(const SMD3MeshBuffer* source,
io::IFileSystem* fs, video::IVideoDriver* driver);
void buildVertexArray(u32 frameA, u32 frameB, f32 interpolate,
const SMD3MeshBuffer* source,
SMeshBufferLightMap* dest);
void buildTagArray(u32 frameA, u32 frameB, f32 interpolate);
f32 FramesPerSecond;
};
} // end namespace scene
} // end namespace irr
#endif

View File

@ -8,7 +8,6 @@
#include "S3DVertex.h"
#include "os.h"
#include "CShadowVolumeSceneNode.h"
#include "IAnimatedMeshMD3.h"
#include "CSkinnedMesh.h"
#include "IDummyTransformationSceneNode.h"
#include "IBoneSceneNode.h"
@ -17,6 +16,7 @@
#include "IMeshCache.h"
#include "IAnimatedMesh.h"
#include "quaternion.h"
#include "IFileSystem.h"
namespace irr
@ -37,7 +37,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), MD3Special(0)
LoopCallBack(0), PassCount(0), Shadow(0)
{
#ifdef _DEBUG
setDebugName("CAnimatedMeshSceneNode");
@ -50,9 +50,6 @@ CAnimatedMeshSceneNode::CAnimatedMeshSceneNode(IAnimatedMesh* mesh,
//! destructor
CAnimatedMeshSceneNode::~CAnimatedMeshSceneNode()
{
if (MD3Special)
MD3Special->drop();
if (Mesh)
Mesh->drop();
@ -407,40 +404,6 @@ void CAnimatedMeshSceneNode::render()
}
}
}
// show tag for quake3 models
if (Mesh->getMeshType() == EAMT_MD3)
{
IAnimatedMesh * arrow =
SceneManager->addArrowMesh (
"__tag_show",
0xFF0000FF, 0xFF000088,
4, 8, 5.f, 4.f, 0.5f,
1.f);
if (!arrow)
{
arrow = SceneManager->getMesh ( "__tag_show" );
}
IMesh *arrowMesh = arrow->getMesh(0);
core::matrix4 matr;
SMD3QuaternionTagList *taglist = ((IAnimatedMeshMD3*)Mesh)->getTagList(
(s32)getFrameNr(), 255,
getStartFrame(), getEndFrame());
if (taglist)
{
for ( u32 ts = 0; ts != taglist->size(); ++ts )
{
(*taglist)[ts].setto(matr);
driver->setTransform(video::ETS_WORLD, matr );
for ( u32 a = 0; a != arrowMesh->getMeshBufferCount(); ++a )
driver->drawMeshBuffer(arrowMesh->getMeshBuffer(a));
}
}
}
}
// show mesh
@ -706,42 +669,6 @@ bool CAnimatedMeshSceneNode::removeChild(ISceneNode* child)
return false;
}
//! Starts a MD2 animation.
bool CAnimatedMeshSceneNode::setMD2Animation(EMD2_ANIMATION_TYPE anim)
{
if (!Mesh || Mesh->getMeshType() != EAMT_MD2)
return false;
IAnimatedMeshMD2* md = (IAnimatedMeshMD2*)Mesh;
s32 begin, end, speed;
md->getFrameLoop(anim, begin, end, speed);
setAnimationSpeed( f32(speed) );
setFrameLoop(begin, end);
return true;
}
//! Starts a special MD2 animation.
bool CAnimatedMeshSceneNode::setMD2Animation(const c8* animationName)
{
if (!Mesh || Mesh->getMeshType() != EAMT_MD2)
return false;
IAnimatedMeshMD2* md = (IAnimatedMeshMD2*)Mesh;
s32 begin, end, speed;
if (!md->getFrameLoop(animationName, begin, end, speed))
return false;
setAnimationSpeed( (f32)speed );
setFrameLoop(begin, end);
return true;
}
//! Sets looping mode which is on by default. If set to false,
//! animations will not be looped.
void CAnimatedMeshSceneNode::setLoopMode(bool playAnimationLooped)
@ -883,51 +810,10 @@ void CAnimatedMeshSceneNode::setMesh(IAnimatedMesh* mesh)
setFrameLoop(0, Mesh->getFrameCount());
}
// returns the absolute transformation for a special MD3 Tag if the mesh is a md3 mesh,
// or the absolutetransformation if it's a normal scenenode
const SMD3QuaternionTag* CAnimatedMeshSceneNode::getMD3TagTransformation(const core::stringc& tagname)
{
return MD3Special ? MD3Special->AbsoluteTagList.get(tagname) : 0;
}
//! updates the absolute position based on the relative and the parents position
void CAnimatedMeshSceneNode::updateAbsolutePosition()
{
IAnimatedMeshSceneNode::updateAbsolutePosition();
if (!Mesh || Mesh->getMeshType() != EAMT_MD3)
return;
SMD3QuaternionTagList *taglist;
taglist = ( (IAnimatedMeshMD3*) Mesh )->getTagList ( (s32)getFrameNr(),255,getStartFrame (),getEndFrame () );
if (taglist)
{
if (!MD3Special)
{
MD3Special = new SMD3Special();
}
SMD3QuaternionTag parent ( MD3Special->Tagname );
if (Parent && Parent->getType() == ESNT_ANIMATED_MESH)
{
const SMD3QuaternionTag * p = ((IAnimatedMeshSceneNode*) Parent)->getMD3TagTransformation
( MD3Special->Tagname );
if (p)
parent = *p;
}
SMD3QuaternionTag relative( RelativeTranslation, RelativeRotation );
MD3Special->AbsoluteTagList.set_used ( taglist->size () );
for ( u32 i=0; i!= taglist->size (); ++i )
{
MD3Special->AbsoluteTagList[i].position = parent.position + (*taglist)[i].position + relative.position;
MD3Special->AbsoluteTagList[i].rotation = parent.rotation * (*taglist)[i].rotation * relative.rotation;
}
}
}
//! Set the joint update mode (0-unused, 1-get joints only, 2-set joints only, 3-move and set)
@ -1134,7 +1020,6 @@ ISceneNode* CAnimatedMeshSceneNode::clone(ISceneNode* newParent, ISceneManager*
newNode->JointChildSceneNodes = JointChildSceneNodes;
newNode->PretransitingSave = PretransitingSave;
newNode->RenderFromIdentity = RenderFromIdentity;
newNode->MD3Special = MD3Special;
return newNode;
}

View File

@ -110,12 +110,6 @@ namespace scene
//! or to remove attached childs.
virtual bool removeChild(ISceneNode* child);
//! Starts a MD2 animation.
virtual bool setMD2Animation(EMD2_ANIMATION_TYPE anim);
//! Starts a special MD2 animation.
virtual bool setMD2Animation(const c8* animationName);
//! Returns the current displayed frame number.
virtual f32 getFrameNr() const;
//! Returns the current start frame number.
@ -146,10 +140,6 @@ namespace scene
//! Returns type of the scene node
virtual ESCENE_NODE_TYPE getType() const { return ESNT_ANIMATED_MESH; }
// returns the absolute transformation for a special MD3 Tag if the mesh is a md3 mesh,
// or the absolutetransformation if it's a normal scenenode
const SMD3QuaternionTag* getMD3TagTransformation( const core::stringc & tagname);
//! updates the absolute position based on the relative and the parents position
virtual void updateAbsolutePosition();
@ -213,21 +203,6 @@ namespace scene
core::array<IBoneSceneNode* > JointChildSceneNodes;
core::array<core::matrix4> PretransitingSave;
// Quake3 Model
struct SMD3Special : public virtual IReferenceCounted
{
core::stringc Tagname;
SMD3QuaternionTagList AbsoluteTagList;
SMD3Special & operator = (const SMD3Special & copyMe)
{
Tagname = copyMe.Tagname;
AbsoluteTagList = copyMe.AbsoluteTagList;
return *this;
}
};
SMD3Special *MD3Special;
};
} // end namespace scene

View File

@ -1,107 +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 "IrrCompileConfig.h"
#ifdef _IRR_COMPILE_WITH_BSP_LOADER_
#include "CBSPMeshFileLoader.h"
#include "CQ3LevelMesh.h"
namespace irr
{
namespace scene
{
//! Constructor
CBSPMeshFileLoader::CBSPMeshFileLoader(scene::ISceneManager* smgr,
io::IFileSystem* fs)
: FileSystem(fs), SceneManager(smgr)
{
#ifdef _DEBUG
setDebugName("CBSPMeshFileLoader");
#endif
if (FileSystem)
FileSystem->grab();
}
//! destructor
CBSPMeshFileLoader::~CBSPMeshFileLoader()
{
if (FileSystem)
FileSystem->drop();
}
//! returns true if the file maybe is able to be loaded by this class
//! based on the file extension (e.g. ".bsp")
bool CBSPMeshFileLoader::isALoadableFileExtension(const io::path& filename) const
{
return core::hasFileExtension ( filename, "bsp", "shader", "cfg" );
}
//! creates/loads an animated mesh from the file.
//! \return Pointer to the created mesh. Returns 0 if loading failed.
//! If you no longer need the mesh, you should call IAnimatedMesh::drop().
//! See IReferenceCounted::drop() for more information.
IAnimatedMesh* CBSPMeshFileLoader::createMesh(io::IReadFile* file)
{
s32 type = core::isFileExtension ( file->getFileName(), "bsp", "shader", "cfg" );
CQ3LevelMesh* q = 0;
switch ( type )
{
case 1:
q = new CQ3LevelMesh(FileSystem, SceneManager, LoadParam);
// determine real shaders in LoadParam
if ( 0 == LoadParam.loadAllShaders )
{
q->getShader("scripts/common.shader");
q->getShader("scripts/sfx.shader");
q->getShader("scripts/gfx.shader");
q->getShader("scripts/liquid.shader");
q->getShader("scripts/models.shader");
q->getShader("scripts/walls.shader");
//q->getShader("scripts/sky.shader");
}
if ( q->loadFile(file) )
return q;
q->drop();
break;
case 2:
q = new CQ3LevelMesh(FileSystem, SceneManager,LoadParam);
q->getShader( file );
return q;
break;
case 3:
// load quake 3 loading parameter
if ( file->getFileName() == "levelparameter.cfg" )
{
file->read ( &LoadParam, sizeof ( LoadParam ) );
}
else
{
q = new CQ3LevelMesh(FileSystem, SceneManager,LoadParam);
q->getConfiguration( file );
return q;
}
break;
}
return 0;
}
} // end namespace scene
} // end namespace irr
#endif // _IRR_COMPILE_WITH_BSP_LOADER_

View File

@ -1,52 +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_BSP_MESH_FILE_LOADER_H_INCLUDED__
#define __C_BSP_MESH_FILE_LOADER_H_INCLUDED__
#include "IMeshLoader.h"
#include "IFileSystem.h"
#include "IVideoDriver.h"
#include "ISceneManager.h"
#include "IQ3Shader.h"
namespace irr
{
namespace scene
{
//! Meshloader capable of loading Quake 3 BSP files and shaders
class CBSPMeshFileLoader : public IMeshLoader
{
public:
//! Constructor
CBSPMeshFileLoader(scene::ISceneManager* smgr, io::IFileSystem* fs);
//! destructor
virtual ~CBSPMeshFileLoader();
//! returns true if the file maybe is able to be loaded by this class
//! based on the file extension (e.g. ".bsp")
virtual bool isALoadableFileExtension(const io::path& filename) const;
//! creates/loads an animated mesh from the file.
//! \return Pointer to the created mesh. Returns 0 if loading failed.
//! If you no longer need the mesh, you should call IAnimatedMesh::drop().
//! See IReferenceCounted::drop() for more information.
virtual IAnimatedMesh* createMesh(io::IReadFile* file);
private:
io::IFileSystem* FileSystem;
scene::ISceneManager* SceneManager;
quake3::Q3LevelLoadParameter LoadParam;
};
} // end namespace scene
} // end namespace irr
#endif

View File

@ -1,872 +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
//
// This file was written by Saurav Mohapatra and modified by Nikolaus Gebhardt.
// See CCSMLoader.h for details.
#include "IrrCompileConfig.h"
#ifdef _IRR_COMPILE_WITH_CSM_LOADER_
#include "CCSMLoader.h"
#include "os.h"
#include "IFileSystem.h"
#include "IReadFile.h"
#include "ISceneManager.h"
#include "IAttributes.h"
#include "SMesh.h"
#include "IVideoDriver.h"
#include "SAnimatedMesh.h"
#include "SMeshBufferLightMap.h"
#ifdef _DEBUG
#define _IRR_DEBUG_CSM_LOADER_
#endif
namespace irr
{
namespace scene
{
//
// the CSM data types
//
struct color_rgb_t
{
s32 red;
s32 green;
s32 blue;
color_rgb_t() : red(0), green(0), blue(0) {}
void clear() { red=0; green=0; blue=0; }
video::SColor toSColor() const { return video::SColor(255, red, green, blue); }
};
//
// A Binary File Reader
//
struct BinaryFileReader
{
BinaryFileReader(io::IReadFile* pFile) : file(pFile) { }
s32 readBuffer(void* buffer, s32 len)
{
return file->read(buffer,len);
}
s32 readLong();
f32 readFloat();
void readString(core::stringc &str);
void readVec3f(core::vector3df* v);
void readVec2f(core::vector2df* v);
void readColorRGB(color_rgb_t* color);
io::IReadFile *file;
};
//
// The file header
//
class Header
{
public:
enum E_CSM_VERSION
{
VERSION_4 = 4,
VERSION_4_1 = 5
};
Header(){ clear(); }
s32 getVersion() const { return version; }
void clear(){ version = 0; }
void load(BinaryFileReader* pReader)
{
version = pReader->readLong();
}
private:
s32 version;
};
//
// The groups
//
class Group
{
public:
Group(){ clear(); }
~Group(){ clear(); }
void clear();
void load(BinaryFileReader* pReader);
s32 getFlags() const { return flags; }
s32 getParentGroupID() const { return parentGroup; }
const core::stringc& getProperties() const { return props; }
video::SColor getColor() const { return color.toSColor(); }
private:
s32 flags;
s32 parentGroup;
core::stringc props;
color_rgb_t color;
};
//
// The visgroups
//
class VisGroup
{
public:
VisGroup(){ clear(); }
~VisGroup(){ clear(); }
void clear();
void load(BinaryFileReader* pReader);
s32 getFlags() const{ return flags; }
const core::stringc& getName() const{ return name; }
video::SColor getColor() const{ return color.toSColor(); }
private:
core::stringc name;
s32 flags;
color_rgb_t color;
};
//
// Lightmaps
//
class LightMap
{
public:
LightMap() : pixelData(0){ clear(); }
~LightMap(){ clear(); }
void clear();
void load(BinaryFileReader* pReader);
s32 getWidth() const{ return width; }
s32 getHeight() const{ return height; }
s32* getPixelData() const{ return pixelData; }
private:
s32 width;
s32 height;
s32* pixelData;
};
struct Triangle
{
s32 a,b,c;
};
struct Line
{
s32 a,b;
};
class Vertex
{
public:
Vertex(){ clear(); }
~Vertex(){ clear(); }
void clear();
void load(BinaryFileReader* pReader);
const core::vector3df& getPosition() const { return position; }
const core::vector3df& getNormal() const { return normal; }
video::SColor getColor() const { return color.toSColor(); }
const core::vector3df& getTextureCoordinates() const { return texCoords; }
const core::vector3df& getLightMapCoordinates() const { return lmapCoords; }
private:
core::vector3df position;
core::vector3df normal;
color_rgb_t color;
core::vector3df texCoords;
core::vector3df lmapCoords;
};
class Surface
{
public:
Surface() { clear(); }
~Surface(){ clear(); }
void clear();
void load(BinaryFileReader *pReader);
s32 getFlags() const{ return flags; }
const core::stringc& getTextureName() const{ return textureName; }
s32 getLightMapId() const{ return lightMapId; }
const core::vector2df* getUVOffset() const{ return &uvOffset; }
const core::vector2df* getUVScale() const{ return &uvScale; }
f32 getUVRotation() const{ return uvRotation; }
u32 getVertexCount() const{ return vertices.size(); }
const Vertex& getVertexAt(const s32 index) const{ return vertices[index]; }
u32 getTriangleCount() const{ return triangles.size(); }
const Triangle& getTriangleAt(const s32 index) const{ return triangles[index]; }
private:
s32 flags;
core::stringc textureName;
s32 lightMapId;
core::vector2df uvOffset;
core::vector2df uvScale;
f32 uvRotation;
core::array<Vertex> vertices;
core::array<Triangle> triangles;
core::array<Line> lines;
};
class Mesh
{
public:
Mesh(){ clear(); }
~Mesh(){ clear(); }
void clear();
void load(BinaryFileReader* pReader, bool bReadVisGroups);
s32 getFlags() const { return flags; }
s32 getGroupID() const { return groupId; }
const core::stringc& getProperties() const { return props; }
video::SColor getColor() const { return color.toSColor(); }
const core::vector3df* getPosition() const { return &position; }
s32 getVisgroupID() const { return visgroupId; }
s32 getSurfaceCount() const { return surfaces.size(); }
const Surface* getSurfaceAt(const s32 index) const { return surfaces[index]; }
private:
s32 flags;
s32 groupId;
core::stringc props;
color_rgb_t color;
core::vector3df position;
s32 visgroupId;
core::array<Surface*> surfaces;
};
class Entity
{
public:
Entity() { clear(); }
~Entity() { clear(); }
void clear();
void load(BinaryFileReader* pReader);
s32 getVisgroupID() const { return visgroupId; }
s32 getGroupID() const { return groupId; }
const core::stringc& getProperties() const { return props; }
const core::vector3df* getPosition() const { return &position; }
private:
s32 visgroupId;
s32 groupId;
core::stringc props;
core::vector3df position;
};
class CameraData
{
public:
CameraData(){ clear(); }
~CameraData(){ clear(); }
void clear();
void load(BinaryFileReader* pReader);
const core::vector3df* getPosition(){ return &position; }
f32 getPitch(){ return pitch; }
f32 getYaw(){ return yaw; }
private:
core::vector3df position;
f32 pitch;
f32 yaw;
};
//
// A CSM File
//
class CSMFile
{
public:
CSMFile(){ clear(); }
~CSMFile(){ clear(); }
void clear();
void load(BinaryFileReader* pReader);
const Header* getHeader() const{ return &header; }
u32 getGroupCount() const{ return groups.size(); }
const Group* getGroupAt(const s32 index) const{ return groups[index]; }
u32 getVisGroupCount() const{ return visgroups.size(); }
const VisGroup* getVisGroupAt(const s32 index) const{ return visgroups[index]; }
u32 getLightMapCount() const{ return lightmaps.size(); }
const LightMap* getLightMapAt(const s32 index) const { return lightmaps[index]; }
u32 getMeshCount() const{ return meshes.size(); }
const Mesh* getMeshAt(const s32 index) const{ return meshes[index]; }
u32 getEntityCount() const{ return entities.size(); }
const Entity* getEntityAt(const s32 index) const{ return entities[index]; }
const CameraData* getCameraData() const{ return &cameraData; }
private:
Header header;
core::array<Group*> groups;
core::array<VisGroup*> visgroups;
core::array<LightMap*> lightmaps;
core::array<Mesh*> meshes;
core::array<Entity*> entities;
CameraData cameraData;
};
CCSMLoader::CCSMLoader(scene::ISceneManager* manager, io::IFileSystem* fs)
: FileSystem(fs), SceneManager(manager)
{
#ifdef _DEBUG
setDebugName("CCSMLoader");
#endif
}
//! returns true if the file maybe is able to be loaded by this class
//! based on the file extension (e.g. ".bsp")
bool CCSMLoader::isALoadableFileExtension(const io::path& filename) const
{
return core::hasFileExtension ( filename, "csm" );
}
//! creates/loads an animated mesh from the file.
IAnimatedMesh* CCSMLoader::createMesh(io::IReadFile* file)
{
scene::IMesh* m = createCSMMesh(file);
if (!m)
return 0;
SAnimatedMesh* am = new SAnimatedMesh();
am->Type = EAMT_CSM;
am->addMesh(m);
m->drop();
am->recalculateBoundingBox();
return am;
}
scene::IMesh* CCSMLoader::createCSMMesh(io::IReadFile* file)
{
if (!file)
return 0;
BinaryFileReader reader(file);
CSMFile csmFile;
csmFile.load(&reader);
return createIrrlichtMesh(&csmFile,
SceneManager->getParameters()->getAttributeAsString(CSM_TEXTURE_PATH),
file->getFileName());
}
scene::IMesh* CCSMLoader::createIrrlichtMesh(const CSMFile* csmFile,
const core::stringc& textureRoot, const io::path& lmprefix)
{
scene::SMesh *pMesh = new scene::SMesh();
video::IVideoDriver* driver = SceneManager->getVideoDriver();
for(u32 l = 0; l<csmFile->getLightMapCount(); l++)
{
const LightMap* lmap = csmFile->getLightMapAt(l);
io::path lmapName = lmprefix;
lmapName += "LMAP_";
lmapName += io::path(l+1);
os::Printer::log("CCSMLoader loading light map", lmapName.c_str());
video::IImage* lmapImg = driver->createImageFromData(
video::ECF_A8R8G8B8,
core::dimension2d<u32>(lmap->getWidth(),lmap->getHeight()),
lmap->getPixelData());
driver->addTexture(lmapName.c_str(), lmapImg);
lmapImg->drop();
}
for(u32 m = 0; m<csmFile->getMeshCount(); m++)
{
const Mesh* mshPtr = csmFile->getMeshAt(m);
for(s32 s = 0; s < mshPtr->getSurfaceCount(); s++)
{
const Surface* surface = mshPtr->getSurfaceAt(s);
core::stringc texName;
if (textureRoot.size())
{
texName += textureRoot;
texName += "/";
}
texName+= surface->getTextureName();
video::ITexture* texture = 0;
if (texName.size())
{
if (FileSystem->existFile(texName))
texture = driver->getTexture(texName);
else if (FileSystem->existFile(surface->getTextureName()))
texture = driver->getTexture(surface->getTextureName());
else if (FileSystem->existFile(FileSystem->getFileBasename(surface->getTextureName())))
texture = driver->getTexture(FileSystem->getFileBasename(surface->getTextureName()));
else if (FileSystem->existFile(FileSystem->getFileDir(lmprefix)+"/"+surface->getTextureName()))
texture = driver->getTexture(FileSystem->getFileDir(lmprefix)+"/"+surface->getTextureName());
else
texture = driver->getTexture(FileSystem->getFileDir(lmprefix)+"/"+FileSystem->getFileBasename(surface->getTextureName()));
}
//material
io::path lmapName = lmprefix;
lmapName += "LMAP_";
lmapName += io::path(surface->getLightMapId());
scene::SMeshBufferLightMap *buffer = new scene::SMeshBufferLightMap();
buffer->Material.setTexture(0, texture);
if (surface->getLightMapId())
{
buffer->Material.setTexture(1, driver->getTexture(lmapName));
buffer->Material.Lighting = false;
buffer->Material.MaterialType = video::EMT_LIGHTMAP_ADD;
}
buffer->Vertices.reallocate(surface->getVertexCount());
for(u32 v = 0; v < surface->getVertexCount(); ++v)
{
const Vertex& vtxPtr = surface->getVertexAt(v);
video::S3DVertex2TCoords vtx;
vtx.Pos = vtxPtr.getPosition();
vtx.Normal = vtxPtr.getPosition();
vtx.Color=vtxPtr.getColor();
vtx.TCoords.set(vtxPtr.getTextureCoordinates().X, 1.f-vtxPtr.getTextureCoordinates().Y);
vtx.TCoords2.set(vtxPtr.getLightMapCoordinates().X, 1.f-vtxPtr.getLightMapCoordinates().Y);
buffer->Vertices.push_back(vtx);
}
buffer->Indices.reallocate(surface->getTriangleCount()*3);
for(u32 t = 0; t < surface->getTriangleCount(); ++t)
{
const Triangle& tri = surface->getTriangleAt(t);
buffer->Indices.push_back(tri.c);
buffer->Indices.push_back(tri.b);
buffer->Indices.push_back(tri.a);
}
buffer->recalculateBoundingBox();
pMesh->addMeshBuffer(buffer);
buffer->drop();
}
}
pMesh->recalculateBoundingBox();
return pMesh;
}
void Group::clear()
{
color.clear();
flags = 0;
parentGroup = 0;
props = "";
}
void Group::load(BinaryFileReader* pReader)
{
flags = pReader->readLong();
parentGroup = pReader->readLong();
pReader->readString(props);
pReader->readColorRGB(&color);
}
void VisGroup::clear()
{
color.clear();
flags = 0;
name = "";
}
void VisGroup::load(BinaryFileReader* pReader)
{
pReader->readString(name);
flags = pReader->readLong();
pReader->readColorRGB(&color);
}
void LightMap::clear()
{
delete[] pixelData;
pixelData = 0;
width = height = 0;
}
void LightMap::load(BinaryFileReader* pReader)
{
width = pReader->readLong();
height = pReader->readLong();
pixelData = new s32[width * height];
pReader->readBuffer(pixelData, width * height * sizeof(s32));
}
void Mesh::clear()
{
flags = 0;
groupId = 0;
visgroupId = 0;
props = "";
color.clear();
position.set(0,0,0);
for(u32 s = 0; s < surfaces.size(); s++)
{
delete surfaces[s];
}
surfaces.clear();
}
void Mesh::load(BinaryFileReader* pReader, bool bReadVisGroups)
{
flags = pReader->readLong();
groupId = pReader->readLong();
pReader->readString(props);
pReader->readColorRGB(&color);
pReader->readVec3f(&position);
if(bReadVisGroups)
visgroupId = pReader->readLong();
else
visgroupId = 0;
s32 count = pReader->readLong();
for(s32 i = 0; i < count; i++)
{
Surface* surf = new Surface();
surf->load(pReader);
surfaces.push_back(surf);
}
}
void Surface::clear()
{
flags = 0;
lightMapId = 0;
textureName = "";
uvOffset.set(0.0f,0.0f);
uvScale.set(0.0f,0.0f);
uvRotation = 0.0f;
triangles.clear();
lines.clear();
vertices.clear();
}
void Surface::load(BinaryFileReader* pReader)
{
flags = pReader->readLong();
pReader->readString(textureName);
textureName.replace('\\', '/');
lightMapId = pReader->readLong();
pReader->readVec2f(&uvOffset);
pReader->readVec2f(&uvScale);
uvRotation = pReader->readFloat();
s32 vtxCount = pReader->readLong();
s32 triCount = pReader->readLong();
s32 lineCount = pReader->readLong();
for(s32 v = 0; v < vtxCount; v++)
{
vertices.push_back(Vertex());
vertices.getLast().load(pReader);
}
for(s32 t = 0; t < triCount; t++)
{
Triangle tri;
pReader->readBuffer(&tri, sizeof(tri));
triangles.push_back(tri);
}
for(s32 l = 0; l < lineCount; l++)
{
Line line;
pReader->readBuffer(&line,sizeof(line));
lines.push_back(line);
}
}
void Vertex::clear()
{
position.set(0,0,0);
normal.set(0,0,0);
color.clear();
texCoords.set(0,0,0);
lmapCoords.set(0,0,0);
}
void Vertex::load(BinaryFileReader* pReader)
{
pReader->readVec3f(&position);
pReader->readVec3f(&normal);
pReader->readColorRGB(&color);
pReader->readVec3f(&texCoords);
pReader->readVec3f(&lmapCoords);
}
void Entity::clear()
{
visgroupId = groupId = 0;
props = "";
position.set(0,0,0);
}
void Entity::load(BinaryFileReader* pReader)
{
visgroupId = pReader->readLong();
groupId = pReader->readLong();
pReader->readString(props);
pReader->readVec3f(&position);
}
void CameraData::clear()
{
position.set(0,0,0);
pitch = 0;
yaw = 0;
}
void CameraData::load(BinaryFileReader* pReader)
{
pReader->readVec3f(&position);
pitch = pReader->readFloat();
yaw = pReader->readFloat();
}
void CSMFile::clear()
{
header.clear();
cameraData.clear();
u32 x =0;
for( x= 0; x < groups.size(); x++)
delete groups[x];
groups.clear();
for(x= 0; x < visgroups.size(); x++)
delete visgroups[x];
visgroups.clear();
for(x= 0; x < lightmaps.size(); x++)
delete lightmaps[x];
lightmaps.clear();
for(x= 0; x < meshes.size(); x++)
delete meshes[x];
meshes.clear();
for(x= 0; x < entities.size(); x++)
delete entities[x];
entities.clear();
}
void CSMFile::load(BinaryFileReader* pReader)
{
clear();
header.load(pReader);
//groups
{
const s32 count = pReader->readLong();
#ifdef _IRR_DEBUG_CSM_LOADER_
os::Printer::log("CSM Version", core::stringc(header.getVersion()).c_str());
os::Printer::log("Loading groups. Count", core::stringc(count));
#endif
groups.reallocate(count);
for (s32 i = 0; i < count; i++)
{
Group* grp = new Group();
grp->load(pReader);
groups.push_back(grp);
}
}
const bool bHasVGroups = (header.getVersion() == Header::VERSION_4_1);
if (bHasVGroups)
{
//visgroups
const s32 count = pReader->readLong();
#ifdef _IRR_DEBUG_CSM_LOADER_
os::Printer::log("Loading visgroups. Count", core::stringc(count));
#endif
visgroups.reallocate(count);
for (s32 i = 0; i < count; i++)
{
VisGroup* grp = new VisGroup();
grp->load(pReader);
visgroups.push_back(grp);
}
}
//lightmaps
{
const s32 count = pReader->readLong();
#ifdef _IRR_DEBUG_CSM_LOADER_
os::Printer::log("Loading lightmaps. Count", core::stringc(count));
#endif
lightmaps.reallocate(count);
for(s32 i = 0; i < count; i++)
{
LightMap* lm = new LightMap();
lm->load(pReader);
lightmaps.push_back(lm);
}
}
//meshes
{
const s32 count = pReader->readLong();
#ifdef _IRR_DEBUG_CSM_LOADER_
os::Printer::log("Loading meshes. Count", core::stringc(count));
#endif
meshes.reallocate(count);
for(s32 i = 0; i < count; i++)
{
Mesh* mesh = new Mesh();
mesh->load(pReader,bHasVGroups);
meshes.push_back(mesh);
}
}
//entities
{
const s32 count = pReader->readLong();
#ifdef _IRR_DEBUG_CSM_LOADER_
os::Printer::log("Loading entitites. Count", core::stringc(count));
#endif
entities.reallocate(count);
for(s32 i = 0; i < count; i++)
{
Entity* ent = new Entity();
ent->load(pReader);
entities.push_back(ent);
}
}
//camera data
#ifdef _IRR_DEBUG_CSM_LOADER_
os::Printer::log("Loading camera data.");
#endif
cameraData.load(pReader);
}
s32 BinaryFileReader::readLong()
{
int ret = 0;
readBuffer(&ret,sizeof(int));
#ifdef __BIG_ENDIAN__
ret = os::Byteswap::byteswap(ret);
#endif
return ret;
}
f32 BinaryFileReader::readFloat()
{
float ret = 0;
readBuffer(&ret,sizeof(float));
#ifdef __BIG_ENDIAN__
ret = os::Byteswap::byteswap(ret);
#endif
return ret;
}
void BinaryFileReader::readString(core::stringc &str)
{
str = "";
c8 c;
readBuffer(&c,sizeof(char));
while(c != 0)
{
str += c;
readBuffer(&c,sizeof(char));
}
}
void BinaryFileReader::readVec3f(core::vector3df* v)
{
v->X = readFloat();
v->Y = readFloat();
v->Z = readFloat();
}
void BinaryFileReader::readVec2f(core::vector2df* v)
{
v->X = readFloat();
v->Y = readFloat();
}
void BinaryFileReader::readColorRGB(color_rgb_t* color)
{
readBuffer(color,sizeof(color_rgb_t));
}
} // end namespace
} // end namespace
#endif // _IRR_COMPILE_WITH_CSM_LOADER_

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
//
// This Loader has been originally written by Saurav Mohapatra. I (Nikolaus Gebhardt)
// modified some minor things and integrated it into Irrlicht 0.9. Thanks a lot
// to Saurav Mohapatra for his work on this and that he gave me his permission to
// add it into Irrlicht.
// I did some changes to Saurav Mohapatra's loader, so I'm writing this down here:
// - Replaced all dependencies to STL and stdio with irr:: methods/constructs.
// - Moved everything into namespace irr::scene
// - Replaced logging with Irrlicht's internal logger.
// - Removed dependency to IrrlichtDevice
// - Moved all internal structures into CCSMLoader.cpp
// - Made the texture root parameter dependent on a ISceneManager string parameter
// - removed exceptions
// - Implemented CCCSMLoader as IMeshLoader
// - Fixed some problems with memory leaks
// - Fixed bounding box calculation
//
// The original readme of this file looks like this:
//
// This component provides a loader for the Cartography shop 4.x .csm maps for Irrlicht Engine.
// This is a part of the M_TRIX Project.
// This is licensed under the ZLib/LibPNG license
// The IrrCSM library is written by Saurav Mohapatra.
//
// Features
//
// The IrrCSM library features the following capabilities
//
// * Loads the .csm 4.0 and 4.1 files transparently
// * Presents the loaded file as irr::scene::IAnimatedMesh for easy creation of IOctreeSceneNode
// * Loads the textures given the correct texture root. hence map and textures can be in separate directories
//
// For more informations go to http://www.geocities.com/standard_template/irrcsm/downloads.html
#ifndef __CSM_LOADER_H_INCLUDED__
#define __CSM_LOADER_H_INCLUDED__
#include "irrArray.h"
#include "IMesh.h"
#include "irrString.h"
#include "IFileSystem.h"
#include "IMeshLoader.h"
namespace irr
{
namespace scene
{
class CSMFile;
class ISceneManager;
class CCSMLoader : public scene::IMeshLoader
{
public:
CCSMLoader(ISceneManager* manager, io::IFileSystem* fs);
//! returns true if the file maybe is able to be loaded by this class
//! based on the file extension (e.g. ".bsp")
virtual bool isALoadableFileExtension(const io::path& filename) const;
//! creates/loads an animated mesh from the file.
virtual IAnimatedMesh* createMesh(io::IReadFile* file);
private:
scene::IMesh* createCSMMesh(io::IReadFile* file);
scene::IMesh* createIrrlichtMesh(const CSMFile* csmFile,
const core::stringc& textureRoot, const io::path& lmprefix);
io::IFileSystem* FileSystem;
scene::ISceneManager* SceneManager;
};
} // end namespace
} // end namespace
#endif

View File

@ -1,361 +0,0 @@
// Copyright (C) 2012 Patryk Nadrowski
// This file is part of the "Irrlicht Engine".
// For conditions of distribution and use, see copyright notice in irrlicht.h
#include "IrrCompileConfig.h"
#ifdef _IRR_COMPILE_WITH_CG_
#include "CCgMaterialRenderer.h"
namespace irr
{
namespace video
{
CCgUniform::CCgUniform(const CGparameter& parameter, bool global) : Parameter(parameter), Type(CG_UNKNOWN_TYPE)
{
Name = cgGetParameterName(Parameter);
if(global)
Space = CG_GLOBAL;
else
Space = CG_PROGRAM;
}
const core::stringc& CCgUniform::getName() const
{
return Name;
}
const CGparameter& CCgUniform::getParameter() const
{
return Parameter;
}
CGenum CCgUniform::getSpace() const
{
return Space;
}
CGtype CCgUniform::getType() const
{
return Type;
}
CCgUniform1f::CCgUniform1f(const CGparameter& parameter, bool global) : CCgUniform(parameter, global)
{
Type = CG_FLOAT;
}
void CCgUniform1f::update(const void* data, const SMaterial& material) const
{
f32* Data = (f32*)data;
cgSetParameter1f(Parameter, *Data);
}
CCgUniform2f::CCgUniform2f(const CGparameter& parameter, bool global) : CCgUniform(parameter, global)
{
Type = CG_FLOAT2;
}
void CCgUniform2f::update(const void* data, const SMaterial& material) const
{
f32* Data = (f32*)data;
cgSetParameter2f(Parameter, *Data, *(Data+1));
}
CCgUniform3f::CCgUniform3f(const CGparameter& parameter, bool global) : CCgUniform(parameter, global)
{
Type = CG_FLOAT3;
}
void CCgUniform3f::update(const void* data, const SMaterial& material) const
{
f32* Data = (f32*)data;
cgSetParameter3f(Parameter, *Data, *(Data+1), *(Data+2));
}
CCgUniform4f::CCgUniform4f(const CGparameter& parameter, bool global) : CCgUniform(parameter, global)
{
Type = CG_FLOAT4;
}
void CCgUniform4f::update(const void* data, const SMaterial& material) const
{
f32* Data = (f32*)data;
cgSetParameter4f(Parameter, *Data, *(Data+1), *(Data+2), *(Data+3));
}
CCgUniform1i::CCgUniform1i(const CGparameter& parameter, bool global) : CCgUniform(parameter, global)
{
Type = CG_INT;
}
void CCgUniform1i::update(const void* data, const SMaterial& material) const
{
s32* Data = (s32*)data;
cgSetParameter1i(Parameter, *Data);
}
CCgUniform2i::CCgUniform2i(const CGparameter& parameter, bool global) : CCgUniform(parameter, global)
{
Type = CG_INT2;
}
void CCgUniform2i::update(const void* data, const SMaterial& material) const
{
s32* Data = (s32*)data;
cgSetParameter2i(Parameter, *Data, *(Data+1));
}
CCgUniform3i::CCgUniform3i(const CGparameter& parameter, bool global) : CCgUniform(parameter, global)
{
Type = CG_INT3;
}
void CCgUniform3i::update(const void* data, const SMaterial& material) const
{
s32* Data = (s32*)data;
cgSetParameter3i(Parameter, *Data, *(Data+1), *(Data+2));
}
CCgUniform4i::CCgUniform4i(const CGparameter& parameter, bool global) : CCgUniform(parameter, global)
{
Type = CG_INT4;
}
void CCgUniform4i::update(const void* data, const SMaterial& material) const
{
s32* Data = (s32*)data;
cgSetParameter4i(Parameter, *Data, *(Data+1), *(Data+2), *(Data+3));
}
CCgUniform4x4f::CCgUniform4x4f(const CGparameter& parameter, bool global) : CCgUniform(parameter, global)
{
Type = CG_FLOAT4x4;
}
void CCgUniform4x4f::update(const void* data, const SMaterial& material) const
{
f32* Data = (f32*)data;
cgSetMatrixParameterfr(Parameter, Data);
}
CCgUniformSampler2D::CCgUniformSampler2D(const CGparameter& parameter, bool global) : CCgUniform(parameter, global)
{
Type = CG_SAMPLER2D;
}
void CCgUniformSampler2D::update(const void* data, const SMaterial& material) const
{
}
CCgMaterialRenderer::CCgMaterialRenderer(IShaderConstantSetCallBack* callback, IMaterialRenderer* baseMaterial, s32 userData) :
CallBack(callback), BaseMaterial(baseMaterial), UserData(userData),
VertexProgram(0), FragmentProgram(0), GeometryProgram(0), VertexProfile(CG_PROFILE_UNKNOWN), FragmentProfile(CG_PROFILE_UNKNOWN), GeometryProfile(CG_PROFILE_UNKNOWN),
Material(IdentityMaterial), Error(CG_NO_ERROR)
{
#ifdef _DEBUG
setDebugName("CCgMaterialRenderer");
#endif
if(BaseMaterial)
BaseMaterial->grab();
if(CallBack)
CallBack->grab();
}
CCgMaterialRenderer::~CCgMaterialRenderer()
{
if(CallBack)
CallBack->drop();
if(BaseMaterial)
BaseMaterial->drop();
for(unsigned int i = 0; i < UniformInfo.size(); ++i)
delete UniformInfo[i];
UniformInfo.clear();
}
bool CCgMaterialRenderer::isTransparent() const
{
return BaseMaterial ? BaseMaterial->isTransparent() : false;
}
void CCgMaterialRenderer::setVertexShaderConstant(const f32* data, s32 startRegister, s32 constantAmount)
{
os::Printer::log("Cannot set constant, please use high level shader call instead.", ELL_WARNING);
}
bool CCgMaterialRenderer::setVertexShaderConstant(const c8* name, const f32* floats, int count)
{
return setPixelShaderConstant(name, floats, count);
}
bool CCgMaterialRenderer::setVertexShaderConstant(const c8* name, const bool* bools, int count)
{
return setPixelShaderConstant(name, bools, count);
}
bool CCgMaterialRenderer::setVertexShaderConstant(const c8* name, const s32* ints, int count)
{
return setPixelShaderConstant(name, ints, count);
}
void CCgMaterialRenderer::setPixelShaderConstant(const f32* data, s32 startRegister, s32 constantAmount)
{
os::Printer::log("Cannot set constant, please use high level shader call instead.", ELL_WARNING);
}
bool CCgMaterialRenderer::setPixelShaderConstant(const c8* name, const f32* floats, int count)
{
bool Status = false;
for(unsigned int i = 0; i < UniformInfo.size(); ++i)
{
if(UniformInfo[i]->getName() == name)
{
UniformInfo[i]->update(floats, Material);
Status = true;
}
}
return Status;
}
bool CCgMaterialRenderer::setPixelShaderConstant(const c8* name, const s32* ints, int count)
{
bool Status = false;
for(unsigned int i = 0; i < UniformInfo.size(); ++i)
{
if(UniformInfo[i]->getName() == name)
{
UniformInfo[i]->update(ints, Material);
Status = true;
}
}
return Status;
}
bool CCgMaterialRenderer::setPixelShaderConstant(const c8* name, const bool* bools, int count)
{
bool Status = false;
for(unsigned int i = 0; i < UniformInfo.size(); ++i)
{
if(UniformInfo[i]->getName() == name)
{
UniformInfo[i]->update(bools, Material);
Status = true;
}
}
return Status;
}
void CCgMaterialRenderer::getUniformList()
{
for(unsigned int i = 0; i < UniformInfo.size(); ++i)
delete UniformInfo[i];
UniformInfo.clear();
for(unsigned int i = 0; i < 2; ++i)
{
CGenum Space = CG_GLOBAL;
bool IsGlobal = 1;
if(i == 1)
{
Space = CG_PROGRAM;
IsGlobal = 0;
}
for(unsigned int j = 0; j < 3; ++j)
{
CGprogram* Program = 0;
switch(j)
{
case 0:
Program = &VertexProgram;
break;
case 1:
Program = &FragmentProgram;
break;
case 2:
Program = &GeometryProgram;
break;
}
if(*Program)
{
CGparameter Parameter = cgGetFirstParameter(*Program, Space);
while(Parameter)
{
if(cgGetParameterVariability(Parameter) == CG_UNIFORM && cgGetParameterDirection(Parameter) == CG_IN)
{
CCgUniform* Uniform = 0;
CGtype Type = cgGetParameterType(Parameter);
switch(Type)
{
case CG_FLOAT:
case CG_FLOAT1:
Uniform = new CCgUniform1f(Parameter, IsGlobal);
break;
case CG_FLOAT2:
Uniform = new CCgUniform2f(Parameter, IsGlobal);
break;
case CG_FLOAT3:
Uniform = new CCgUniform3f(Parameter, IsGlobal);
break;
case CG_FLOAT4:
Uniform = new CCgUniform4f(Parameter, IsGlobal);
break;
case CG_INT:
case CG_INT1:
Uniform = new CCgUniform1i(Parameter, IsGlobal);
break;
case CG_INT2:
Uniform = new CCgUniform2i(Parameter, IsGlobal);
break;
case CG_INT3:
Uniform = new CCgUniform3i(Parameter, IsGlobal);
break;
case CG_INT4:
Uniform = new CCgUniform4i(Parameter, IsGlobal);
break;
case CG_FLOAT4x4:
Uniform = new CCgUniform4x4f(Parameter, IsGlobal);
break;
case CG_SAMPLER2D:
Uniform = new CCgUniformSampler2D(Parameter, IsGlobal);
break;
}
if(Uniform)
UniformInfo.push_back(Uniform);
}
Parameter = cgGetNextParameter(Parameter);
}
}
}
}
}
}
}
#endif

View File

@ -1,176 +0,0 @@
// Copyright (C) 2012 Patryk Nadrowski
// This file is part of the "Irrlicht Engine".
// For conditions of distribution and use, see copyright notice in irrlicht.h
#ifndef __C_CG_MATERIAL_RENDERER_H_INCLUDED__
#define __C_CG_MATERIAL_RENDERER_H_INCLUDED__
#include "IrrCompileConfig.h"
#ifdef _IRR_COMPILE_WITH_CG_
#include "IMaterialRenderer.h"
#include "IMaterialRendererServices.h"
#include "IShaderConstantSetCallBack.h"
#include "IGPUProgrammingServices.h"
#include "irrArray.h"
#include "irrString.h"
#include "IVideoDriver.h"
#include "os.h"
#include "Cg/cg.h"
#ifdef _MSC_VER
#pragma comment(lib, "cg.lib")
#endif
namespace irr
{
namespace video
{
class CCgUniform
{
public:
CCgUniform(const CGparameter& parameter, bool global);
const core::stringc& getName() const;
const CGparameter& getParameter() const;
CGenum getSpace() const;
CGtype getType() const;
virtual void update(const void* data, const SMaterial& material) const = 0;
protected:
core::stringc Name;
CGparameter Parameter;
CGenum Space;
CGtype Type;
};
class CCgUniform1f : public CCgUniform
{
public:
CCgUniform1f(const CGparameter& parameter, bool global);
void update(const void* data, const SMaterial& material) const;
};
class CCgUniform2f : public CCgUniform
{
public:
CCgUniform2f(const CGparameter& parameter, bool global);
void update(const void* data, const SMaterial& material) const;
};
class CCgUniform3f : public CCgUniform
{
public:
CCgUniform3f(const CGparameter& parameter, bool global);
void update(const void* data, const SMaterial& material) const;
};
class CCgUniform4f : public CCgUniform
{
public:
CCgUniform4f(const CGparameter& parameter, bool global);
void update(const void* data, const SMaterial& material) const;
};
class CCgUniform1i : public CCgUniform
{
public:
CCgUniform1i(const CGparameter& parameter, bool global);
void update(const void* data, const SMaterial& material) const;
};
class CCgUniform2i : public CCgUniform
{
public:
CCgUniform2i(const CGparameter& parameter, bool global);
void update(const void* data, const SMaterial& material) const;
};
class CCgUniform3i : public CCgUniform
{
public:
CCgUniform3i(const CGparameter& parameter, bool global);
void update(const void* data, const SMaterial& material) const;
};
class CCgUniform4i : public CCgUniform
{
public:
CCgUniform4i(const CGparameter& parameter, bool global);
void update(const void* data, const SMaterial& material) const;
};
class CCgUniform4x4f : public CCgUniform
{
public:
CCgUniform4x4f(const CGparameter& parameter, bool global);
void update(const void* data, const SMaterial& material) const;
};
class CCgUniformSampler2D : public CCgUniform
{
public:
CCgUniformSampler2D(const CGparameter& parameter, bool global);
void update(const void* data, const SMaterial& material) const;
};
class CCgMaterialRenderer : public IMaterialRenderer, public IMaterialRendererServices
{
public:
CCgMaterialRenderer(IShaderConstantSetCallBack* callback = 0, IMaterialRenderer* baseMaterial = 0, s32 userData = 0);
virtual ~CCgMaterialRenderer();
virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial, bool resetAllRenderstates, IMaterialRendererServices* services) = 0;
virtual bool OnRender(IMaterialRendererServices* service, E_VERTEX_TYPE vtxtype) = 0;
virtual void OnUnsetMaterial() = 0;
virtual bool isTransparent() const;
virtual void setBasicRenderStates(const SMaterial& material, const SMaterial& lastMaterial, bool resetAllRenderstates) = 0;
virtual bool setVertexShaderConstant(const c8* name, const f32* floats, int count);
virtual bool setVertexShaderConstant(const c8* name, const bool* bools, int count);
virtual bool setVertexShaderConstant(const c8* name, const s32* ints, int count);
virtual void setVertexShaderConstant(const f32* data, s32 startRegister, s32 constantAmount=1);
virtual bool setPixelShaderConstant(const c8* name, const f32* floats, int count);
virtual bool setPixelShaderConstant(const c8* name, const bool* bools, int count);
virtual bool setPixelShaderConstant(const c8* name, const s32* ints, int count);
virtual void setPixelShaderConstant(const f32* data, s32 startRegister, s32 constantAmount=1);
virtual IVideoDriver* getVideoDriver() = 0;
protected:
void getUniformList();
IShaderConstantSetCallBack* CallBack;
IMaterialRenderer* BaseMaterial;
s32 UserData;
core::array<CCgUniform*> UniformInfo;
CGprogram VertexProgram;
CGprogram FragmentProgram;
CGprogram GeometryProgram;
CGprofile VertexProfile;
CGprofile FragmentProfile;
CGprofile GeometryProfile;
SMaterial Material;
CGerror Error;
};
}
}
#endif
#endif

File diff suppressed because it is too large Load Diff

View File

@ -1,389 +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_COLLADA_MESH_FILE_LOADER_H_INCLUDED__
#define __C_COLLADA_MESH_FILE_LOADER_H_INCLUDED__
#include "IMeshLoader.h"
#include "IFileSystem.h"
#include "IVideoDriver.h"
#include "irrString.h"
#include "SMesh.h"
#include "SMeshBuffer.h"
#include "ISceneManager.h"
#include "irrMap.h"
#include "CAttributes.h"
namespace irr
{
namespace scene
{
#ifdef _DEBUG
//#define COLLADA_READER_DEBUG
#endif
class IColladaPrefab;
enum ECOLLADA_PARAM_NAME
{
ECPN_COLOR = 0,
ECPN_AMBIENT,
ECPN_DIFFUSE,
ECPN_SPECULAR,
ECPN_SHININESS,
ECPN_TRANSPARENCY,
ECPN_YFOV,
ECPN_ZNEAR,
ECPN_ZFAR,
ECPN_COUNT
};
enum ECOLLADA_PARAM_TYPE
{
ECPT_FLOAT = 0,
ECPT_FLOAT2,
ECPT_FLOAT3,
ECPT_FLOAT4,
ECPT_COUNT
};
//! Collada Parameter
struct SColladaParam
{
SColladaParam()
: Name(ECPN_COUNT), Type(ECPT_COUNT)
{
for (int i=0; i<4; ++i) Floats[i] = 0;
}
ECOLLADA_PARAM_NAME Name;
ECOLLADA_PARAM_TYPE Type;
f32 Floats[4];
};
enum ECOLLADA_INPUT_SEMANTIC
{
ECIS_POSITION = 0,
ECIS_VERTEX,
ECIS_NORMAL,
ECIS_TEXCOORD,
ECIS_UV,
ECIS_TANGENT,
ECIS_IMAGE,
ECIS_TEXTURE,
ECIS_COUNT
};
//! Collada Input
struct SColladaInput
{
SColladaInput()
: Semantic(ECIS_COUNT), Data(0), Offset(0), Set(0), Stride(1)
{
}
ECOLLADA_INPUT_SEMANTIC Semantic;
core::stringc Source;
f32* Data;
u32 Offset;
u32 Set;
u32 Stride;
};
//! Collada images
struct SColladaImage
{
core::stringc Id;
core::stringc Source;
core::dimension2du Dimension;
bool SourceIsFilename;
};
//! Collada texture
struct SColladaTexture
{
video::ITexture* Texture;
core::stringc Id;
};
//! Collada material
struct SColladaMaterial
{
video::SMaterial Mat;
core::stringc Id;
core::stringc InstanceEffectId;
f32 Transparency;
inline bool operator< (const SColladaMaterial & other) const
{
return Id < other.Id;
}
};
//! Collada effect (materials, shaders, and programs)
struct SColladaEffect
{
core::stringc Id;
f32 Transparency;
core::array<core::stringc> Textures;
video::SMaterial Mat;
// TODO: Parameters looks somewhat lazy workaround, I think we should really read all parameters correct.
io::IAttributes * Parameters;
inline bool operator< (const SColladaEffect & other) const
{
return Id < other.Id;
}
};
struct SNumberArray // for storing float and int arrays
{
core::stringc Name;
core::array<f32> Data;
};
struct SAccessor
{
SAccessor()
: Count(0), Offset(0), Stride(1) {}
// I don't store the source of the accessor here because I assume
// it to use the array of the source this accessor is located in.
int Count;
int Offset;
int Stride;
core::array<SColladaParam> Parameters; // parameters defining the accessor
};
struct SSource
{
core::stringc Id;
SNumberArray Array;
core::array<SAccessor> Accessors;
};
class CScenePrefab;
//! Meshloader capable of loading COLLADA meshes and scene descriptions into Irrlicht.
class CColladaFileLoader : public IMeshLoader
{
public:
//! Constructor
CColladaFileLoader(scene::ISceneManager* smgr, io::IFileSystem* fs);
//! destructor
virtual ~CColladaFileLoader();
//! returns true if the file maybe is able to be loaded by this class
//! based on the file extension (e.g. ".cob")
virtual bool isALoadableFileExtension(const io::path& filename) const;
//! creates/loads an animated mesh from the file.
//! \return Pointer to the created mesh. Returns 0 if loading failed.
//! If you no longer need the mesh, you should call IAnimatedMesh::drop().
//! See IReferenceCounted::drop() for more information.
virtual IAnimatedMesh* createMesh(io::IReadFile* file);
private:
//! skips an (unknown) section in the collada document
void skipSection(io::IXMLReaderUTF8* reader, bool reportSkipping);
//! reads the <COLLADA> section and its content
void readColladaSection(io::IXMLReaderUTF8* reader);
//! reads a <library> section and its content
void readLibrarySection(io::IXMLReaderUTF8* reader);
//! reads a <visual_scene> element and stores it as a prefab
void readVisualScene(io::IXMLReaderUTF8* reader);
//! reads a <scene> section and its content
void readSceneSection(io::IXMLReaderUTF8* reader);
//! reads a <asset> section and its content
void readAssetSection(io::IXMLReaderUTF8* reader);
//! reads a <node> section and its content
//! if a prefab pointer is passed the nodes are created as scene prefabs children of that prefab
void readNodeSection(io::IXMLReaderUTF8* reader, scene::ISceneNode* parent, CScenePrefab* p=0);
//! reads a <lookat> element and its content and creates a matrix from it
core::matrix4 readLookAtNode(io::IXMLReaderUTF8* reader);
//! reads a <matrix> element and its content and creates a matrix from it
core::matrix4 readMatrixNode(io::IXMLReaderUTF8* reader);
//! reads a <perspective> element and its content and creates a matrix from it
core::matrix4 readPerspectiveNode(io::IXMLReaderUTF8* reader);
//! reads a <rotate> element and its content and creates a matrix from it
core::matrix4 readRotateNode(io::IXMLReaderUTF8* reader);
//! reads a <skew> element and its content and creates a matrix from it
core::matrix4 readSkewNode(io::IXMLReaderUTF8* reader);
//! reads a <boundingbox> element and its content and stores it in bbox
void readBboxNode(io::IXMLReaderUTF8* reader, core::aabbox3df& bbox);
//! reads a <scale> element and its content and creates a matrix from it
core::matrix4 readScaleNode(io::IXMLReaderUTF8* reader);
//! reads a <translate> element and its content and creates a matrix from it
core::matrix4 readTranslateNode(io::IXMLReaderUTF8* reader);
//! reads a <color> element
video::SColorf readColorNode(io::IXMLReaderUTF8* reader);
//! reads a <float> element
f32 readFloatNode(io::IXMLReaderUTF8* reader);
//! reads a <instance> node
void readInstanceNode(io::IXMLReaderUTF8* reader,
scene::ISceneNode* parent, scene::ISceneNode** outNode,
CScenePrefab* p=0, const core::stringc& type=core::stringc());
//! creates a scene node from Prefabs (with name given in 'url')
void instantiateNode(scene::ISceneNode* parent, scene::ISceneNode** outNode=0,
CScenePrefab* p=0, const core::stringc& url="",
const core::stringc& type=core::stringc());
//! reads a <light> element and stores it as prefab
void readLightPrefab(io::IXMLReaderUTF8* reader);
//! reads a <camera> element and stores it as prefab
void readCameraPrefab(io::IXMLReaderUTF8* reader);
//! reads a <image> element and stores it in the image section
void readImage(io::IXMLReaderUTF8* reader);
//! reads a <texture> element and stores it in the texture section
void readTexture(io::IXMLReaderUTF8* reader);
//! reads a <material> element and stores it in the material section
void readMaterial(io::IXMLReaderUTF8* reader);
//! reads a <effect> element and stores it in the effects section
void readEffect(io::IXMLReaderUTF8* reader, SColladaEffect * effect = 0);
//! reads a <geometry> element and stores it as mesh if possible
void readGeometry(io::IXMLReaderUTF8* reader);
//! parses a float from a char pointer and moves the pointer to
//! the end of the parsed float
inline f32 readFloat(const c8** p);
//! parses an int from a char pointer and moves the pointer to
//! the end of the parsed float
inline s32 readInt(const c8** p);
//! places pointer to next begin of a token
void findNextNoneWhiteSpace(const c8** p);
//! reads floats from inside of xml element until end of xml element
void readFloatsInsideElement(io::IXMLReaderUTF8* reader, f32* floats, u32 count);
//! reads ints from inside of xml element until end of xml element
void readIntsInsideElement(io::IXMLReaderUTF8* reader, s32* ints, u32 count);
//! clears all loaded data
void clearData();
//! parses all collada parameters inside an element and stores them in ColladaParameters
void readColladaParameters(io::IXMLReaderUTF8* reader, const core::stringc& parentName);
//! returns a collada parameter or none if not found
SColladaParam* getColladaParameter(ECOLLADA_PARAM_NAME name);
//! parses all collada inputs inside an element and stores them in Inputs. Reads
//! until first tag which is not an input tag or the end of the parent is reached
void readColladaInputs(io::IXMLReaderUTF8* reader, const core::stringc& parentName);
//! reads a collada input tag and adds it to the input parameter
void readColladaInput(io::IXMLReaderUTF8* reader, core::array<SColladaInput>& inputs);
//! returns a collada input or none if not found
SColladaInput* getColladaInput(ECOLLADA_INPUT_SEMANTIC input);
//! read Collada Id, uses id or name if id is missing
core::stringc readId(io::IXMLReaderUTF8* reader);
//! changes the XML URI into an internal id
void uriToId(core::stringc& str);
//! reads a polygons section and creates a mesh from it
void readPolygonSection(io::IXMLReaderUTF8* reader,
core::array<SSource>& sources, scene::SMesh* mesh,
const core::stringc& geometryId);
//! finds a material, possible instancing it
const SColladaMaterial * findMaterial(const core::stringc & materialName);
//! reads and bind materials as given by the symbol->target bind mapping
void readBindMaterialSection(io::IXMLReaderUTF8* reader, const core::stringc & id);
//! create an Irrlicht texture from the SColladaImage
video::ITexture* getTextureFromImage(core::stringc uri, SColladaEffect * effect);
//! read a parameter and value
void readParameter(io::IXMLReaderUTF8* reader, io::IAttributes* parameters);
scene::ISceneManager* SceneManager;
io::IFileSystem* FileSystem;
scene::IAnimatedMesh* DummyMesh;
core::stringc CurrentlyLoadingMesh;
scene::IAnimatedMesh* FirstLoadedMesh;
io::path FirstLoadedMeshName;
s32 LoadedMeshCount;
u32 Version;
bool FlipAxis;
core::array<IColladaPrefab*> Prefabs;
core::array<SColladaParam> ColladaParameters;
core::array<SColladaImage> Images;
core::array<SColladaTexture> Textures;
core::array<SColladaMaterial> Materials;
core::array<SColladaInput> Inputs;
core::array<SColladaEffect> Effects;
//! meshbuffer reference ("geomid/matname") -> index into MeshesToBind
core::map<core::stringc,u32> MaterialsToBind;
//! Array of buffers for each material binding
core::array< core::array<irr::scene::IMeshBuffer*> > MeshesToBind;
bool CreateInstances;
};
//! following class is for holding and createing instances of library objects,
//! named prefabs in this loader.
class IColladaPrefab : public virtual IReferenceCounted
{
public:
//! creates an instance of this prefab
virtual scene::ISceneNode* addInstance(scene::ISceneNode* parent,
scene::ISceneManager* mgr) = 0;
//! returns id of this prefab
virtual const core::stringc& getId() = 0;
};
} // end namespace scene
} // end namespace irr
#endif

File diff suppressed because it is too large Load Diff

View File

@ -1,271 +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 __IRR_C_COLLADA_MESH_WRITER_H_INCLUDED__
#define __IRR_C_COLLADA_MESH_WRITER_H_INCLUDED__
#include "IColladaMeshWriter.h"
#include "S3DVertex.h"
#include "irrMap.h"
#include "IVideoDriver.h"
namespace irr
{
namespace io
{
class IXMLWriter;
class IFileSystem;
}
namespace scene
{
//! Callback interface for properties which can be used to influence collada writing
// (Implementer note: keep namespace labels here to make it easier for users copying this one)
class CColladaMeshWriterProperties : public virtual IColladaMeshWriterProperties
{
public:
//! Which lighting model should be used in the technique (FX) section when exporting effects (materials)
virtual irr::scene::E_COLLADA_TECHNIQUE_FX getTechniqueFx(const irr::video::SMaterial& material) const;
//! Which texture index should be used when writing the texture of the given sampler color.
virtual irr::s32 getTextureIdx(const irr::video::SMaterial & material, irr::scene::E_COLLADA_COLOR_SAMPLER cs) const;
//! Return which color from Irrlicht should be used for the color requested by collada
virtual irr::scene::E_COLLADA_IRR_COLOR getColorMapping(const irr::video::SMaterial & material, irr::scene::E_COLLADA_COLOR_SAMPLER cs) const;
//! Return custom colors for certain color types requested by collada.
virtual irr::video::SColor getCustomColor(const irr::video::SMaterial & material, irr::scene::E_COLLADA_COLOR_SAMPLER cs) const;
//! Return the settings for transparence
virtual irr::scene::E_COLLADA_TRANSPARENT_FX getTransparentFx(const irr::video::SMaterial& material) const;
//! Transparency value for that material.
virtual irr::f32 getTransparency(const irr::video::SMaterial& material) const;
//! Reflectivity value for that material
virtual irr::f32 getReflectivity(const irr::video::SMaterial& material) const;
//! Return index of refraction for that material
virtual irr::f32 getIndexOfRefraction(const irr::video::SMaterial& material) const;
//! Should node be used in scene export? By default all visible nodes are exported.
virtual bool isExportable(const irr::scene::ISceneNode * node) const;
//! Return the mesh for the given nod. If it has no mesh or shouldn't export it's mesh return 0.
virtual irr::scene::IMesh* getMesh(irr::scene::ISceneNode * node);
//! Return if the node has it's own material overwriting the mesh-materials
virtual bool useNodeMaterial(const scene::ISceneNode* node) const;
};
class CColladaMeshWriterNames : public virtual IColladaMeshWriterNames
{
public:
CColladaMeshWriterNames(IColladaMeshWriter * writer);
virtual irr::core::stringw nameForMesh(const scene::IMesh* mesh, int instance);
virtual irr::core::stringw nameForNode(const scene::ISceneNode* node);
virtual irr::core::stringw nameForMaterial(const video::SMaterial & material, int materialId, const scene::IMesh* mesh, const scene::ISceneNode* node);
protected:
irr::core::stringw nameForPtr(const void* ptr) const;
private:
IColladaMeshWriter * ColladaMeshWriter;
};
//! class to write meshes, implementing a COLLADA (.dae, .xml) writer
/** This writer implementation has been originally developed for irrEdit and then
merged out to the Irrlicht Engine */
class CColladaMeshWriter : public IColladaMeshWriter
{
public:
CColladaMeshWriter(ISceneManager * smgr, video::IVideoDriver* driver, io::IFileSystem* fs);
virtual ~CColladaMeshWriter();
//! Returns the type of the mesh writer
virtual EMESH_WRITER_TYPE getType() const;
//! writes a scene starting with the given node
virtual bool writeScene(io::IWriteFile* file, scene::ISceneNode* root);
//! writes a mesh
virtual bool writeMesh(io::IWriteFile* file, scene::IMesh* mesh, s32 flags=EMWF_NONE);
// Restrict the characters of oldString a set of allowed characters in xs::NCName and add the prefix.
virtual irr::core::stringw toNCName(const irr::core::stringw& oldString, const irr::core::stringw& prefix=irr::core::stringw(L"_NC_")) const;
protected:
void reset();
bool hasSecondTextureCoordinates(video::E_VERTEX_TYPE type) const;
void writeUv(const irr::core::vector2df& vec);
void writeVector(const irr::core::vector2df& vec);
void writeVector(const irr::core::vector3df& vec);
void writeColor(const irr::video::SColorf& colorf, bool writeAlpha=true);
inline irr::core::stringw toString(const irr::video::ECOLOR_FORMAT format) const;
inline irr::core::stringw toString(const irr::video::E_TEXTURE_CLAMP clamp) const;
inline irr::core::stringw toString(const irr::scene::E_COLLADA_TRANSPARENT_FX opaque) const;
inline irr::core::stringw toRef(const irr::core::stringw& source) const;
bool isCamera(const scene::ISceneNode* node) const;
irr::core::stringw nameForMesh(const scene::IMesh* mesh, int instance) const;
irr::core::stringw nameForNode(const scene::ISceneNode* node) const;
irr::core::stringw nameForMaterial(const video::SMaterial & material, int materialId, const scene::IMesh* mesh, const scene::ISceneNode* node);
irr::core::stringw nameForMaterialSymbol(const scene::IMesh* mesh, int materialId) const;
irr::core::stringw findCachedMaterialName(const irr::video::SMaterial& material) const;
irr::core::stringw minTexfilterToString(bool bilinear, bool trilinear) const;
irr::core::stringw magTexfilterToString(bool bilinear, bool trilinear) const;
irr::core::stringw pathToURI(const irr::io::path& path) const;
inline bool isXmlNameStartChar(wchar_t c) const;
inline bool isXmlNameChar(wchar_t c) const;
s32 getCheckedTextureIdx(const video::SMaterial & material, E_COLLADA_COLOR_SAMPLER cs);
video::SColor getColorMapping(const video::SMaterial & material, E_COLLADA_COLOR_SAMPLER cs, E_COLLADA_IRR_COLOR colType);
void writeAsset();
void makeMeshNames(irr::scene::ISceneNode * node);
void writeNodeMaterials(irr::scene::ISceneNode * node);
void writeNodeEffects(irr::scene::ISceneNode * node);
void writeNodeLights(irr::scene::ISceneNode * node);
void writeNodeCameras(irr::scene::ISceneNode * node);
void writeAllMeshGeometries();
void writeSceneNode(irr::scene::ISceneNode * node);
void writeMeshMaterials(scene::IMesh* mesh, irr::core::array<irr::core::stringw> * materialNamesOut=0);
void writeMeshEffects(scene::IMesh* mesh);
void writeMaterialEffect(const irr::core::stringw& materialname, const video::SMaterial & material);
void writeMeshGeometry(const irr::core::stringw& meshname, scene::IMesh* mesh);
void writeMeshInstanceGeometry(const irr::core::stringw& meshname, scene::IMesh* mesh, scene::ISceneNode* node=0);
void writeMaterial(const irr::core::stringw& materialname);
void writeLightInstance(const irr::core::stringw& lightName);
void writeCameraInstance(const irr::core::stringw& cameraName);
void writeLibraryImages();
void writeColorFx(const video::SMaterial & material, const wchar_t * colorname, E_COLLADA_COLOR_SAMPLER cs, const wchar_t* attr1Name=0, const wchar_t* attr1Value=0);
void writeAmbientLightElement(const video::SColorf & col);
void writeColorElement(const video::SColor & col, bool writeAlpha=true);
void writeColorElement(const video::SColorf & col, bool writeAlpha=true);
void writeTextureSampler(s32 textureIdx);
void writeFxElement(const video::SMaterial & material, E_COLLADA_TECHNIQUE_FX techFx);
void writeNode(const wchar_t * nodeName, const wchar_t * content);
void writeFloatElement(irr::f32 value);
void writeRotateElement(const irr::core::vector3df& axis, irr::f32 angle);
void writeScaleElement(const irr::core::vector3df& scale);
void writeTranslateElement(const irr::core::vector3df& translate);
void writeMatrixElement(const irr::core::matrix4& matrix);
struct SComponentGlobalStartPos
{
SComponentGlobalStartPos() : PosStartIndex(-1), PosLastIndex(-1),
NormalStartIndex(-1), NormalLastIndex(-1),
TCoord0StartIndex(-1), TCoord0LastIndex(-1),
TCoord1StartIndex(-1), TCoord1LastIndex(-1)
{ }
s32 PosStartIndex;
s32 PosLastIndex;
s32 NormalStartIndex;
s32 NormalLastIndex;
s32 TCoord0StartIndex;
s32 TCoord0LastIndex;
s32 TCoord1StartIndex;
s32 TCoord1LastIndex;
};
io::IFileSystem* FileSystem;
video::IVideoDriver* VideoDriver;
io::IXMLWriter* Writer;
core::array<video::ITexture*> LibraryImages;
io::path Directory;
// Helper struct for creating geometry copies for the ECGI_PER_MESH_AND_MATERIAL settings.
struct SGeometryMeshMaterials
{
bool equals(const core::array<irr::core::stringw>& names) const
{
if ( names.size() != MaterialNames.size() )
return false;
for ( irr::u32 i=0; i<MaterialNames.size(); ++i )
if ( names[i] != MaterialNames[i] )
return false;
return true;
}
irr::core::stringw GeometryName; // replacing the usual ColladaMesh::Name
core::array<irr::core::stringw> MaterialNames; // Material names exported for this instance
core::array<const ISceneNode*> MaterialOwners; // Nodes using this specific mesh-material combination
};
// Check per mesh-ptr if stuff has been written for this mesh already
struct SColladaMesh
{
SColladaMesh() : MaterialsWritten(false), EffectsWritten(false)
{
}
SGeometryMeshMaterials * findGeometryMeshMaterials(const irr::core::array<irr::core::stringw> materialNames)
{
for ( irr::u32 i=0; i<GeometryMeshMaterials.size(); ++i )
{
if ( GeometryMeshMaterials[i].equals(materialNames) )
return &(GeometryMeshMaterials[i]);
}
return NULL;
}
const irr::core::stringw& findGeometryNameForNode(const ISceneNode* node) const
{
if ( GeometryMeshMaterials.size() < 2 )
return Name;
for ( irr::u32 i=0; i<GeometryMeshMaterials.size(); ++i )
{
if ( GeometryMeshMaterials[i].MaterialOwners.linear_search(node) >= 0 )
return GeometryMeshMaterials[i].GeometryName;
}
return Name; // (shouldn't get here usually)
}
irr::core::stringw Name;
bool MaterialsWritten; // just an optimization doing that here in addition to the MaterialsWritten map
bool EffectsWritten; // just an optimization doing that here in addition to the EffectsWritten map
core::array<SGeometryMeshMaterials> GeometryMeshMaterials;
};
typedef core::map<IMesh*, SColladaMesh>::Node MeshNode;
core::map<IMesh*, SColladaMesh> Meshes;
// structure for the lights library
struct SColladaLight
{
SColladaLight() {}
irr::core::stringw Name;
};
typedef core::map<ISceneNode*, SColladaLight>::Node LightNode;
core::map<ISceneNode*, SColladaLight> LightNodes;
// structure for the camera library
typedef core::map<ISceneNode*, irr::core::stringw>::Node CameraNode;
core::map<ISceneNode*, irr::core::stringw> CameraNodes;
// Check per name if stuff has been written already
// TODO: second parameter not needed, we just don't have a core::set class yet in Irrlicht
core::map<irr::core::stringw, bool> MaterialsWritten;
core::map<irr::core::stringw, bool> EffectsWritten;
// Cache material names
struct MaterialName
{
MaterialName(const irr::video::SMaterial & material, const irr::core::stringw& name)
: Material(material), Name(name)
{}
irr::video::SMaterial Material;
irr::core::stringw Name;
};
irr::core::array< MaterialName > MaterialNameCache;
};
} // end namespace
} // end namespace
#endif

View File

@ -1,436 +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
//
// This file was originally written by Salvatore Russo.
// I (Nikolaus Gebhardt) did some minor modifications and changes to it and
// integrated it into Irrlicht.
// Thanks a lot to Salvatore for his work on this and that he gave me
// his permission to add it into Irrlicht using the zlib license.
/*
CDMFLoader by Salvatore Russo (September 2005)
See the header file for additional information including use and distribution rights.
*/
#include "IrrCompileConfig.h"
#ifdef _IRR_COMPILE_WITH_DMF_LOADER_
#ifdef _DEBUG
#define _IRR_DMF_DEBUG_
#include "os.h"
#endif
#include "CDMFLoader.h"
#include "ISceneManager.h"
#include "IAttributes.h"
#include "SAnimatedMesh.h"
#include "SSkinMeshBuffer.h"
#include "irrString.h"
#include "irrMath.h"
#include "dmfsupport.h"
namespace irr
{
namespace scene
{
/** Constructor*/
CDMFLoader::CDMFLoader(ISceneManager* smgr, io::IFileSystem* filesys)
: SceneMgr(smgr), FileSystem(filesys)
{
#ifdef _DEBUG
IReferenceCounted::setDebugName("CDMFLoader");
#endif
}
void CDMFLoader::findFile(bool use_mat_dirs, const core::stringc& path, const core::stringc& matPath, core::stringc& filename)
{
// path + texpath + full name
if (use_mat_dirs && FileSystem->existFile(path+matPath+filename))
filename = path+matPath+filename;
// path + full name
else if (FileSystem->existFile(path+filename))
filename = path+filename;
// path + texpath + base name
else if (use_mat_dirs && FileSystem->existFile(path+matPath+FileSystem->getFileBasename(filename)))
filename = path+matPath+FileSystem->getFileBasename(filename);
// path + base name
else if (FileSystem->existFile(path+FileSystem->getFileBasename(filename)))
filename = path+FileSystem->getFileBasename(filename);
// texpath + full name
else if (use_mat_dirs && FileSystem->existFile(matPath+filename))
filename = matPath+filename;
// texpath + base name
else if (use_mat_dirs && FileSystem->existFile(matPath+FileSystem->getFileBasename(filename)))
filename = matPath+FileSystem->getFileBasename(filename);
// base name
else if (FileSystem->existFile(FileSystem->getFileBasename(filename)))
filename = FileSystem->getFileBasename(filename);
}
/**Creates/loads an animated mesh from the file.
\return Pointer to the created mesh. Returns 0 if loading failed.
If you no longer need the mesh, you should call IAnimatedMesh::drop().
See IReferenceCounted::drop() for more information.*/
IAnimatedMesh* CDMFLoader::createMesh(io::IReadFile* file)
{
if (!file)
return 0;
video::IVideoDriver* driver = SceneMgr->getVideoDriver();
//Load stringlist
StringList dmfRawFile;
LoadFromFile(file, dmfRawFile);
if (dmfRawFile.size()==0)
return 0;
SMesh * mesh = new SMesh();
u32 i;
dmfHeader header;
//load header
core::array<dmfMaterial> materiali;
if (GetDMFHeader(dmfRawFile, header))
{
//let's set ambient light
SceneMgr->setAmbientLight(header.dmfAmbient);
//let's create the correct number of materials, vertices and faces
dmfVert *verts=new dmfVert[header.numVertices];
dmfFace *faces=new dmfFace[header.numFaces];
//let's get the materials
#ifdef _IRR_DMF_DEBUG_
os::Printer::log("Loading materials", core::stringc(header.numMaterials).c_str());
#endif
GetDMFMaterials(dmfRawFile, materiali, header.numMaterials);
//let's get vertices and faces
#ifdef _IRR_DMF_DEBUG_
os::Printer::log("Loading geometry");
#endif
GetDMFVerticesFaces(dmfRawFile, verts, faces);
//create a meshbuffer for each material, then we'll remove empty ones
#ifdef _IRR_DMF_DEBUG_
os::Printer::log("Creating meshbuffers.");
#endif
for (i=0; i<header.numMaterials; i++)
{
//create a new SMeshBufferLightMap for each material
SSkinMeshBuffer* buffer = new SSkinMeshBuffer();
buffer->Material.MaterialType = video::EMT_LIGHTMAP_LIGHTING;
buffer->Material.Wireframe = false;
buffer->Material.Lighting = true;
mesh->addMeshBuffer(buffer);
buffer->drop();
}
// Build the mesh buffers
#ifdef _IRR_DMF_DEBUG_
os::Printer::log("Adding geometry to mesh.");
#endif
for (i = 0; i < header.numFaces; i++)
{
#ifdef _IRR_DMF_DEBUG_
os::Printer::log("Polygon with #vertices", core::stringc(faces[i].numVerts).c_str());
#endif
if (faces[i].numVerts < 3)
continue;
const core::vector3df normal =
core::triangle3df(verts[faces[i].firstVert].pos,
verts[faces[i].firstVert+1].pos,
verts[faces[i].firstVert+2].pos).getNormal().normalize();
SSkinMeshBuffer* meshBuffer = (SSkinMeshBuffer*)mesh->getMeshBuffer(
faces[i].materialID);
const bool use2TCoords = meshBuffer->Vertices_2TCoords.size() ||
materiali[faces[i].materialID].lightmapName.size();
if (use2TCoords && meshBuffer->Vertices_Standard.size())
meshBuffer->convertTo2TCoords();
const u32 base = meshBuffer->Vertices_2TCoords.size()?meshBuffer->Vertices_2TCoords.size():meshBuffer->Vertices_Standard.size();
// Add this face's verts
if (use2TCoords)
{
// make sure we have the proper type set
meshBuffer->VertexType=video::EVT_2TCOORDS;
for (u32 v = 0; v < faces[i].numVerts; v++)
{
const dmfVert& vv = verts[faces[i].firstVert + v];
video::S3DVertex2TCoords vert(vv.pos,
normal, video::SColor(255,255,255,255), vv.tc, vv.lc);
if (materiali[faces[i].materialID].textureBlend==4 &&
SceneMgr->getParameters()->getAttributeAsBool(DMF_FLIP_ALPHA_TEXTURES))
{
vert.TCoords.set(vv.tc.X,-vv.tc.Y);
}
meshBuffer->Vertices_2TCoords.push_back(vert);
}
}
else
{
for (u32 v = 0; v < faces[i].numVerts; v++)
{
const dmfVert& vv = verts[faces[i].firstVert + v];
video::S3DVertex vert(vv.pos,
normal, video::SColor(255,255,255,255), vv.tc);
if (materiali[faces[i].materialID].textureBlend==4 &&
SceneMgr->getParameters()->getAttributeAsBool(DMF_FLIP_ALPHA_TEXTURES))
{
vert.TCoords.set(vv.tc.X,-vv.tc.Y);
}
meshBuffer->Vertices_Standard.push_back(vert);
}
}
// Now add the indices
// This weird loop turns convex polygons into triangle strips.
// I do it this way instead of a simple fan because it usually
// looks a lot better in wireframe, for example.
u32 h = faces[i].numVerts - 1, l = 0, c; // High, Low, Center
for (u32 v = 0; v < faces[i].numVerts - 2; v++)
{
if (v & 1) // odd
c = h - 1;
else // even
c = l + 1;
meshBuffer->Indices.push_back(base + h);
meshBuffer->Indices.push_back(base + l);
meshBuffer->Indices.push_back(base + c);
if (v & 1) // odd
h--;
else // even
l++;
}
}
delete [] verts;
delete [] faces;
}
// delete all buffers without geometry in it.
#ifdef _IRR_DMF_DEBUG_
os::Printer::log("Cleaning meshbuffers.");
#endif
i = 0;
while(i < mesh->MeshBuffers.size())
{
if (mesh->MeshBuffers[i]->getVertexCount() == 0 ||
mesh->MeshBuffers[i]->getIndexCount() == 0)
{
// Meshbuffer is empty -- drop it
mesh->MeshBuffers[i]->drop();
mesh->MeshBuffers.erase(i);
materiali.erase(i);
}
else
{
i++;
}
}
{
//load textures and lightmaps in materials.
//don't worry if you receive a could not load texture, cause if you don't need
//a particular material in your scene it will be loaded and then destroyed.
#ifdef _IRR_DMF_DEBUG_
os::Printer::log("Loading textures.");
#endif
const bool use_mat_dirs=!SceneMgr->getParameters()->getAttributeAsBool(DMF_IGNORE_MATERIALS_DIRS);
core::stringc path;
if ( SceneMgr->getParameters()->existsAttribute(DMF_TEXTURE_PATH) )
path = SceneMgr->getParameters()->getAttributeAsString(DMF_TEXTURE_PATH);
else
path = FileSystem->getFileDir(file->getFileName());
path += ('/');
for (i=0; i<mesh->getMeshBufferCount(); i++)
{
//texture and lightmap
video::ITexture *tex = 0;
video::ITexture *lig = 0;
//current buffer to apply material
video::SMaterial& mat = mesh->getMeshBuffer(i)->getMaterial();
//Primary texture is normal
if (materiali[i].textureFlag==0)
{
if (materiali[i].textureBlend==4)
driver->setTextureCreationFlag(video::ETCF_ALWAYS_32_BIT,true);
findFile(use_mat_dirs, path, materiali[i].pathName, materiali[i].textureName);
tex = driver->getTexture(materiali[i].textureName);
}
//Primary texture is just a color
else if(materiali[i].textureFlag==1)
{
video::SColor color(axtoi(materiali[i].textureName.c_str()));
//just for compatibility with older Irrlicht versions
//to support transparent materials
if (color.getAlpha()!=255 && materiali[i].textureBlend==4)
driver->setTextureCreationFlag(video::ETCF_ALWAYS_32_BIT,true);
video::IImage *immagine= driver->createImage(video::ECF_A8R8G8B8,
core::dimension2d<u32>(8,8));
immagine->fill(color);
tex = driver->addTexture("", immagine);
immagine->drop();
//to support transparent materials
if (color.getAlpha()!=255 && materiali[i].textureBlend==4)
{
mat.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
mat.MaterialTypeParam =(((f32) (color.getAlpha()-1))/255.0f);
}
}
//Lightmap is present
if (materiali[i].lightmapFlag == 0)
{
findFile(use_mat_dirs, path, materiali[i].pathName, materiali[i].lightmapName);
lig = driver->getTexture(materiali[i].lightmapName);
}
else //no lightmap
{
mat.MaterialType = video::EMT_SOLID;
const f32 mult = 100.0f - header.dmfShadow;
mat.AmbientColor=header.dmfAmbient.getInterpolated(video::SColor(255,0,0,0),mult/100.f);
}
if (materiali[i].textureBlend==4)
{
mat.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
mat.MaterialTypeParam =
SceneMgr->getParameters()->getAttributeAsFloat(DMF_ALPHA_CHANNEL_REF);
}
//if texture is present mirror vertically owing to DeleD representation
if (tex && header.dmfVersion<1.1)
{
const core::dimension2d<u32> texsize = tex->getSize();
void* pp = tex->lock();
if (pp)
{
const video::ECOLOR_FORMAT format = tex->getColorFormat();
if (format == video::ECF_A1R5G5B5)
{
s16* p = (s16*)pp;
s16 tmp=0;
for (u32 x=0; x<texsize.Width; x++)
for (u32 y=0; y<texsize.Height/2; y++)
{
tmp=p[y*texsize.Width + x];
p[y*texsize.Width + x] = p[(texsize.Height-y-1)*texsize.Width + x];
p[(texsize.Height-y-1)*texsize.Width + x]=tmp;
}
}
else
if (format == video::ECF_A8R8G8B8)
{
s32* p = (s32*)pp;
s32 tmp=0;
for (u32 x=0; x<texsize.Width; x++)
for (u32 y=0; y<texsize.Height/2; y++)
{
tmp=p[y*texsize.Width + x];
p[y*texsize.Width + x] = p[(texsize.Height-y-1)*texsize.Width + x];
p[(texsize.Height-y-1)*texsize.Width + x]=tmp;
}
}
}
tex->unlock();
tex->regenerateMipMapLevels();
}
//if lightmap is present mirror vertically owing to DeleD rapresentation
if (lig && header.dmfVersion<1.1)
{
const core::dimension2d<u32> ligsize=lig->getSize();
void* pp = lig->lock();
if (pp)
{
video::ECOLOR_FORMAT format = lig->getColorFormat();
if (format == video::ECF_A1R5G5B5)
{
s16* p = (s16*)pp;
s16 tmp=0;
for (u32 x=0; x<ligsize.Width; x++)
{
for (u32 y=0; y<ligsize.Height/2; y++)
{
tmp=p[y*ligsize.Width + x];
p[y*ligsize.Width + x] = p[(ligsize.Height-y-1)*ligsize.Width + x];
p[(ligsize.Height-y-1)*ligsize.Width + x]=tmp;
}
}
}
else if (format == video::ECF_A8R8G8B8)
{
s32* p = (s32*)pp;
s32 tmp=0;
for (u32 x=0; x<ligsize.Width; x++)
{
for (u32 y=0; y<ligsize.Height/2; y++)
{
tmp=p[y*ligsize.Width + x];
p[y*ligsize.Width + x] = p[(ligsize.Height-y-1)*ligsize.Width + x];
p[(ligsize.Height-y-1)*ligsize.Width + x]=tmp;
}
}
}
}
lig->unlock();
lig->regenerateMipMapLevels();
}
mat.setTexture(0, tex);
mat.setTexture(1, lig);
}
}
// create bounding box
for (i = 0; i < mesh->MeshBuffers.size(); ++i)
{
mesh->MeshBuffers[i]->recalculateBoundingBox();
}
mesh->recalculateBoundingBox();
// Set up an animated mesh to hold the mesh
SAnimatedMesh* AMesh = new SAnimatedMesh();
AMesh->Type = EAMT_UNKNOWN;
AMesh->addMesh(mesh);
AMesh->recalculateBoundingBox();
mesh->drop();
return AMesh;
}
/** \brief Tell us if this file is able to be loaded by this class
based on the file extension (e.g. ".bsp")
\return true if file is loadable.*/
bool CDMFLoader::isALoadableFileExtension(const io::path& filename) const
{
return core::hasFileExtension ( filename, "dmf" );
}
} // end namespace scene
} // end namespace irr
#endif // _IRR_COMPILE_WITH_DMF_LOADER_

View File

@ -1,91 +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
//
// This file was originally written by Salvatore Russo.
// I (Nikolaus Gebhardt) did some minor modifications changes to it and integrated
// it into Irrlicht:
// - removed STL dependency
// - removed log file and replaced it with irrlicht logging
// - adapted code formatting a bit to Irrlicht style
// - removed memory leaks
// Thanks a lot to Salvatore for his work on this and that he gave me
// his permission to add it into Irrlicht.
/*
CDMFLoader by Salvatore Russo
Version 1.3
This loader is used to load DMF files in Irrlicht.
Look at the documentation for a sample application.
Parts of this code are from Murphy McCauley COCTLoader just like
GetFaceNormal() or indexes creation routines and a routine to add faces. So
please refer to COCTLoader.h to know more about rights granted.
You can use this software as you wish but you must not remove these notes about license nor
credits to others for parts of this code.
*/
#ifndef __C_DMF_LOADER_H_INCLUDED__
#define __C_DMF_LOADER_H_INCLUDED__
#include "IMeshLoader.h"
#include "IReadFile.h"
#include "IFileSystem.h"
#include "SMesh.h"
#include "IVideoDriver.h"
#include "ISceneManager.h"
#include "SAnimatedMesh.h"
namespace irr
{
namespace scene
{
/** A class to load DeleD mesh files.*/
class CDMFLoader : public IMeshLoader
{
public:
/** constructor*/
CDMFLoader(ISceneManager* smgr, io::IFileSystem* filesys);
//! returns true if the file maybe is able to be loaded by this class
//! based on the file extension (e.g. ".cob")
virtual bool isALoadableFileExtension(const io::path& filename) const;
/** creates/loads an animated mesh from the file.
\return Pointer to the created mesh. Returns 0 if loading failed.
If you no longer need the mesh, you should call IAnimatedMesh::drop().
See IReferenceCounted::drop() for more information.*/
virtual IAnimatedMesh* createMesh(io::IReadFile* file);
/** loads dynamic lights present in this scene.
Note that loaded lights from DeleD must have the suffix \b dynamic_ and must be \b pointlight.
Irrlicht correctly loads specular color, diffuse color , position and distance of object affected by light.
\return number of lights loaded or 0 if loading failed.*/
int loadLights(const c8 * filename, ISceneManager* smgr,
ISceneNode* parent = 0, s32 base_id = 1000);
/** loads water plains present in this scene.
Note that loaded water plains from DeleD must have the suffix \b water_ and must be \b rectangle (with just 1 rectangular face).
Irrlicht correctly loads position and rotation of water plain as well as texture layers.
\return number of water plains loaded or 0 if loading failed.*/
int loadWaterPlains(const c8 *filename,
ISceneManager* smgr,
ISceneNode * parent = 0,
s32 base_id = 2000,
bool mode = true);
private:
void findFile(bool use_mat_dirs, const core::stringc& path, const core::stringc& matPath, core::stringc& filename);
ISceneManager* SceneMgr;
io::IFileSystem* FileSystem;
};
} // end namespace scene
} // end namespace irr
#endif

View File

@ -1,868 +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 "IrrCompileConfig.h"
#ifdef _IRR_COMPILE_WITH_WINDOWS_CE_DEVICE_
#include "CIrrDeviceWinCE.h"
#include "IEventReceiver.h"
#include "irrList.h"
#include "os.h"
#include "CTimer.h"
#include "irrString.h"
#include "COSOperator.h"
#include "dimension2d.h"
#include <winuser.h>
#include "irrlicht.h"
#ifdef _MSC_VER
#pragma comment (lib, "aygshell.lib")
#endif
namespace irr
{
namespace video
{
#ifdef _IRR_COMPILE_WITH_DIRECT3D_8_
IVideoDriver* createDirectX8Driver(const irr::SIrrlichtCreationParameters& params,
io::IFileSystem* io, HWND window);
#endif
#ifdef _IRR_COMPILE_WITH_DIRECT3D_9_
IVideoDriver* createDirectX9Driver(const irr::SIrrlichtCreationParameters& params,
io::IFileSystem* io, HWND window);
#endif
#ifdef _IRR_COMPILE_WITH_OPENGL_
IVideoDriver* createOpenGLDriver(const irr::SIrrlichtCreationParameters& params, io::IFileSystem* io, this);
#endif
}
} // end namespace irr
struct SEnvMapper
{
HWND hWnd;
irr::CIrrDeviceWinCE* irrDev;
};
irr::core::list<SEnvMapper> EnvMap;
SEnvMapper* getEnvMapperFromHWnd(HWND hWnd)
{
irr::core::list<SEnvMapper>::Iterator it = EnvMap.begin();
for (; it!= EnvMap.end(); ++it)
if ((*it).hWnd == hWnd)
return &(*it);
return 0;
}
irr::CIrrDeviceWinCE* getDeviceFromHWnd(HWND hWnd)
{
irr::core::list<SEnvMapper>::Iterator it = EnvMap.begin();
for (; it!= EnvMap.end(); ++it)
if ((*it).hWnd == hWnd)
return (*it).irrDev;
return 0;
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
#ifndef WM_MOUSEWHEEL
#define WM_MOUSEWHEEL 0x020A
#endif
#ifndef WHEEL_DELTA
#define WHEEL_DELTA 120
#endif
irr::CIrrDeviceWinCE* dev = 0;
irr::SEvent event;
SEnvMapper* envm = 0;
//BYTE allKeys[256];
static irr::s32 ClickCount=0;
if (GetCapture() != hWnd && ClickCount > 0)
ClickCount = 0;
switch (message)
{
case WM_PAINT:
{
PAINTSTRUCT ps;
BeginPaint(hWnd, &ps);
EndPaint(hWnd, &ps);
}
return 0;
case WM_ERASEBKGND:
return 0;
case WM_SETCURSOR:
envm = getEnvMapperFromHWnd(hWnd);
if (envm && !envm->irrDev->getWin32CursorControl()->isVisible())
{
SetCursor(NULL);
return 0;
}
break;
case WM_MOUSEWHEEL:
event.EventType = irr::EET_MOUSE_INPUT_EVENT;
event.MouseInput.Wheel = ((irr::f32)((short)HIWORD(wParam))) / (irr::f32)WHEEL_DELTA;
event.MouseInput.Event = irr::EMIE_MOUSE_WHEEL;
POINT p; // fixed by jox
p.x = 0; p.y = 0;
ClientToScreen(hWnd, &p);
event.MouseInput.X = LOWORD(lParam) - p.x;
event.MouseInput.Y = HIWORD(lParam) - p.y;
event.MouseInput.Shift = ((LOWORD(wParam) & MK_SHIFT) != 0);
event.MouseInput.Control = ((LOWORD(wParam) & MK_CONTROL) != 0);
// left and right mouse buttons
event.MouseInput.ButtonStates = wParam & ( MK_LBUTTON | MK_RBUTTON);
// middle and extra buttons
if (wParam & MK_MBUTTON)
event.MouseInput.ButtonStates |= irr::EMBSM_MIDDLE;
dev = getDeviceFromHWnd(hWnd);
if (dev)
dev->postEventFromUser(event);
break;
case WM_LBUTTONDOWN:
ClickCount++;
SetCapture(hWnd);
event.EventType = irr::EET_MOUSE_INPUT_EVENT;
event.MouseInput.Event = irr::EMIE_LMOUSE_PRESSED_DOWN;
event.MouseInput.X = (short)LOWORD(lParam);
event.MouseInput.Y = (short)HIWORD(lParam);
event.MouseInput.Shift = ((LOWORD(wParam) & MK_SHIFT) != 0);
event.MouseInput.Control = ((LOWORD(wParam) & MK_CONTROL) != 0);
// left and right mouse buttons
event.MouseInput.ButtonStates = wParam & ( MK_LBUTTON | MK_RBUTTON);
// middle and extra buttons
if (wParam & MK_MBUTTON)
event.MouseInput.ButtonStates |= irr::EMBSM_MIDDLE;
dev = getDeviceFromHWnd(hWnd);
if (dev)
dev->postEventFromUser(event);
return 0;
case WM_LBUTTONUP:
ClickCount--;
if (ClickCount<1)
{
ClickCount=0;
ReleaseCapture();
}
event.EventType = irr::EET_MOUSE_INPUT_EVENT;
event.MouseInput.Event = irr::EMIE_LMOUSE_LEFT_UP;
event.MouseInput.X = (short)LOWORD(lParam);
event.MouseInput.Y = (short)HIWORD(lParam);
event.MouseInput.Shift = ((LOWORD(wParam) & MK_SHIFT) != 0);
event.MouseInput.Control = ((LOWORD(wParam) & MK_CONTROL) != 0);
// left and right mouse buttons
event.MouseInput.ButtonStates = wParam & ( MK_LBUTTON | MK_RBUTTON);
// middle and extra buttons
if (wParam & MK_MBUTTON)
event.MouseInput.ButtonStates |= irr::EMBSM_MIDDLE;
dev = getDeviceFromHWnd(hWnd);
if (dev)
dev->postEventFromUser(event);
return 0;
case WM_RBUTTONDOWN:
ClickCount++;
SetCapture(hWnd);
event.EventType = irr::EET_MOUSE_INPUT_EVENT;
event.MouseInput.Event = irr::EMIE_RMOUSE_PRESSED_DOWN;
event.MouseInput.X = (short)LOWORD(lParam);
event.MouseInput.Y = (short)HIWORD(lParam);
event.MouseInput.Shift = ((LOWORD(wParam) & MK_SHIFT) != 0);
event.MouseInput.Control = ((LOWORD(wParam) & MK_CONTROL) != 0);
// left and right mouse buttons
event.MouseInput.ButtonStates = wParam & ( MK_LBUTTON | MK_RBUTTON);
// middle and extra buttons
if (wParam & MK_MBUTTON)
event.MouseInput.ButtonStates |= irr::EMBSM_MIDDLE;
dev = getDeviceFromHWnd(hWnd);
if (dev)
dev->postEventFromUser(event);
return 0;
case WM_RBUTTONUP:
ClickCount--;
if (ClickCount<1)
{
ClickCount=0;
ReleaseCapture();
}
event.EventType = irr::EET_MOUSE_INPUT_EVENT;
event.MouseInput.Event = irr::EMIE_RMOUSE_LEFT_UP;
event.MouseInput.X = (short)LOWORD(lParam);
event.MouseInput.Y = (short)HIWORD(lParam);
event.MouseInput.Shift = ((LOWORD(wParam) & MK_SHIFT) != 0);
event.MouseInput.Control = ((LOWORD(wParam) & MK_CONTROL) != 0);
// left and right mouse buttons
event.MouseInput.ButtonStates = wParam & ( MK_LBUTTON | MK_RBUTTON);
// middle and extra buttons
if (wParam & MK_MBUTTON)
event.MouseInput.ButtonStates |= irr::EMBSM_MIDDLE;
dev = getDeviceFromHWnd(hWnd);
if (dev)
dev->postEventFromUser(event);
return 0;
case WM_MBUTTONDOWN:
ClickCount++;
SetCapture(hWnd);
event.EventType = irr::EET_MOUSE_INPUT_EVENT;
event.MouseInput.Event = irr::EMIE_MMOUSE_PRESSED_DOWN;
event.MouseInput.X = (short)LOWORD(lParam);
event.MouseInput.Y = (short)HIWORD(lParam);
event.MouseInput.Shift = ((LOWORD(wParam) & MK_SHIFT) != 0);
event.MouseInput.Control = ((LOWORD(wParam) & MK_CONTROL) != 0);
// left and right mouse buttons
event.MouseInput.ButtonStates = wParam & ( MK_LBUTTON | MK_RBUTTON);
// middle and extra buttons
if (wParam & MK_MBUTTON)
event.MouseInput.ButtonStates |= irr::EMBSM_MIDDLE;
dev = getDeviceFromHWnd(hWnd);
if (dev)
dev->postEventFromUser(event);
return 0;
case WM_MBUTTONUP:
ClickCount--;
if (ClickCount<1)
{
ClickCount=0;
ReleaseCapture();
}
event.EventType = irr::EET_MOUSE_INPUT_EVENT;
event.MouseInput.Event = irr::EMIE_MMOUSE_LEFT_UP;
event.MouseInput.X = (short)LOWORD(lParam);
event.MouseInput.Y = (short)HIWORD(lParam);
event.MouseInput.Shift = ((LOWORD(wParam) & MK_SHIFT) != 0);
event.MouseInput.Control = ((LOWORD(wParam) & MK_CONTROL) != 0);
// left and right mouse buttons
event.MouseInput.ButtonStates = wParam & ( MK_LBUTTON | MK_RBUTTON);
// middle and extra buttons
if (wParam & MK_MBUTTON)
event.MouseInput.ButtonStates |= irr::EMBSM_MIDDLE;
dev = getDeviceFromHWnd(hWnd);
if (dev)
dev->postEventFromUser(event);
return 0;
case WM_MOUSEMOVE:
event.EventType = irr::EET_MOUSE_INPUT_EVENT;
event.MouseInput.Event = irr::EMIE_MOUSE_MOVED;
event.MouseInput.X = (short)LOWORD(lParam);
event.MouseInput.Y = (short)HIWORD(lParam);
event.MouseInput.Shift = ((LOWORD(wParam) & MK_SHIFT) != 0);
event.MouseInput.Control = ((LOWORD(wParam) & MK_CONTROL) != 0);
// left and right mouse buttons
event.MouseInput.ButtonStates = wParam & ( MK_LBUTTON | MK_RBUTTON);
// middle and extra buttons
if (wParam & MK_MBUTTON)
event.MouseInput.ButtonStates |= irr::EMBSM_MIDDLE;
dev = getDeviceFromHWnd(hWnd);
if (dev)
dev->postEventFromUser(event);
return 0;
case WM_SYSKEYDOWN:
case WM_SYSKEYUP:
case WM_KEYDOWN:
case WM_KEYUP:
{
event.EventType = irr::EET_KEY_INPUT_EVENT;
event.KeyInput.Key = (irr::EKEY_CODE)wParam;
event.KeyInput.PressedDown = (message==WM_KEYDOWN || message == WM_SYSKEYDOWN);
dev = getDeviceFromHWnd(hWnd);
/*
WORD KeyAsc=0;
GetKeyboardState(allKeys);
ToAscii(wParam,lParam,allKeys,&KeyAsc,0);
*/
// event.KeyInput.Shift = ((allKeys[VK_SHIFT] & 0x80)!=0);
// event.KeyInput.Control = ((allKeys[VK_CONTROL] & 0x80)!=0);
// event.KeyInput.Char = (KeyAsc & 0x00ff); //KeyAsc >= 0 ? KeyAsc : 0;
if (dev)
dev->postEventFromUser(event);
return 0;
}
case WM_SIZE:
{
// resize
dev = getDeviceFromHWnd(hWnd);
if (dev)
dev->OnResized();
}
return 0;
case WM_DESTROY:
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hWnd, message, wParam, lParam);
}
namespace irr
{
//! constructor
CIrrDeviceWinCE::CIrrDeviceWinCE(const SIrrlichtCreationParameters& params)
: CIrrDeviceStub(params), HWnd(0),
Win32CursorControl(0), ChangedToFullScreen(false), Resized(false),
ExternalWindow(false)
{
#ifdef _DEBUG
setDebugName("CIrrDeviceWinCE");
#endif
core::stringc winversion;
getWindowsVersion(winversion);
Operator = new COSOperator(winversion);
os::Printer::log(winversion.c_str(), ELL_INFORMATION);
HINSTANCE hInstance = GetModuleHandle(0);
// create the window only if we do not use the null device
if (!CreationParams.WindowId && (CreationParams.DriverType != video::EDT_NULL))
{
const wchar_t* ClassName = L"CIrrDeviceWinCE";
// Register Class
WNDCLASS wc;
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = WndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = NULL;
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wc.lpszMenuName = 0;
wc.lpszClassName = ClassName;
// if there is an icon, load it
wc.hIcon = (HICON)LoadImageW(hInstance, L"irrlicht.ico", IMAGE_ICON, 0,0, 0);
RegisterClass(&wc);
// calculate client size
RECT clientSize;
clientSize.top = 0;
clientSize.left = 0;
clientSize.right = CreationParams.WindowSize.Width;
clientSize.bottom = CreationParams.WindowSize.Height;
DWORD style = WS_POPUP;
if (!CreationParams.Fullscreen)
style = WS_SYSMENU | WS_BORDER | WS_CAPTION | WS_CLIPCHILDREN | WS_CLIPSIBLINGS;
AdjustWindowRectEx(&clientSize, style, FALSE, 0);
const s32 realWidth = clientSize.right - clientSize.left;
const s32 realHeight = clientSize.bottom - clientSize.top;
const s32 windowLeft = core::s32_max ( 0, (GetSystemMetrics(SM_CXSCREEN) - realWidth) >> 1 );
const s32 windowTop = core::s32_max ( 0, (GetSystemMetrics(SM_CYSCREEN) - realHeight) >> 1 );
// create window
HWnd = CreateWindowW( ClassName, L"", style, windowLeft, windowTop,
realWidth, realHeight, NULL, NULL, hInstance, NULL);
ShowWindow(HWnd , SW_SHOW);
UpdateWindow(HWnd);
// fix ugly ATI driver bugs. Thanks to ariaci
MoveWindow(HWnd, windowLeft, windowTop, realWidth, realHeight, TRUE);
}
else if (CreationParams.WindowId)
{
// attach external window
HWnd = static_cast<HWND>(CreationParams.WindowId);
RECT r;
GetWindowRect(HWnd, &r);
CreationParams.WindowSize.Width = r.right - r.left;
CreationParams.WindowSize.Height = r.bottom - r.top;
CreationParams.Fullscreen = false;
ExternalWindow = true;
}
// create cursor control
Win32CursorControl = new CCursorControl(CreationParams.WindowSize, HWnd, CreationParams.Fullscreen);
CursorControl = Win32CursorControl;
// create driver
createDriver();
if (VideoDriver)
createGUIAndScene();
// register environment
SEnvMapper em;
em.irrDev = this;
em.hWnd = HWnd;
EnvMap.push_back(em);
// set this as active window
SetActiveWindow(HWnd);
SetForegroundWindow(HWnd);
}
//! destructor
CIrrDeviceWinCE::~CIrrDeviceWinCE()
{
// unregister environment
if (ChangedToFullScreen)
SHFullScreen(HWnd, SHFS_SHOWTASKBAR | SHFS_SHOWSTARTICON | SHFS_SHOWSIPBUTTON);
irr::core::list<SEnvMapper>::Iterator it = EnvMap.begin();
for (; it!= EnvMap.end(); ++it)
if ((*it).hWnd == HWnd)
{
EnvMap.erase(it);
break;
}
}
//! create the driver
void CIrrDeviceWinCE::createDriver()
{
switch(CreationParams.DriverType)
{
case video::EDT_DIRECT3D8:
#ifdef _IRR_COMPILE_WITH_DIRECT3D_8_
VideoDriver = video::createDirectX8Driver(CreationParams, FileSystem, HWnd);
if (!VideoDriver)
{
os::Printer::log("Could not create DIRECT3D8 Driver.", ELL_ERROR);
}
#else
os::Printer::log("DIRECT3D8 Driver was not compiled into this dll. Try another one.", ELL_ERROR);
#endif // _IRR_COMPILE_WITH_DIRECT3D_8_
break;
case video::EDT_DIRECT3D9:
#ifdef _IRR_COMPILE_WITH_DIRECT3D_9_
VideoDriver = video::createDirectX9Driver(CreationParams, FileSystem, HWnd);
if (!VideoDriver)
{
os::Printer::log("Could not create DIRECT3D9 Driver.", ELL_ERROR);
}
#else
os::Printer::log("DIRECT3D9 Driver was not compiled into this dll. Try another one.", ELL_ERROR);
#endif // _IRR_COMPILE_WITH_DIRECT3D_9_
break;
case video::EDT_OPENGL:
#ifdef _IRR_COMPILE_WITH_OPENGL_
if (CreationParams.Fullscreen)
switchToFullScreen();
VideoDriver = video::createOpenGLDriver(CreationParams, FileSystem);
if (!VideoDriver)
{
os::Printer::log("Could not create OpenGL driver.", ELL_ERROR);
}
#else
os::Printer::log("OpenGL driver was not compiled in.", ELL_ERROR);
#endif
break;
case video::EDT_SOFTWARE:
#ifdef _IRR_COMPILE_WITH_SOFTWARE_
if (CreationParams.Fullscreen)
switchToFullScreen();
VideoDriver = video::createSoftwareDriver(CreationParams.WindowSize, CreationParams.Fullscreen, FileSystem, this);
#else
os::Printer::log("Software driver was not compiled in.", ELL_ERROR);
#endif
break;
case video::EDT_BURNINGSVIDEO:
#ifdef _IRR_COMPILE_WITH_BURNINGSVIDEO_
if (CreationParams.Fullscreen)
switchToFullScreen();
VideoDriver = video::createBurningVideoDriver(CreationParams, FileSystem, this);
#else
os::Printer::log("Burning's Video driver was not compiled in.", ELL_ERROR);
#endif
break;
case video::EDT_NULL:
// create null driver
VideoDriver = video::createNullDriver(FileSystem, CreationParams.WindowSize);
break;
default:
os::Printer::log("Unable to create video driver of unknown type.", ELL_ERROR);
break;
}
}
//! runs the device. Returns false if device wants to be deleted
bool CIrrDeviceWinCE::run()
{
os::Timer::tick();
MSG msg;
while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
TranslateMessage(&msg);
if (ExternalWindow && msg.hwnd == HWnd)
WndProc(HWnd, msg.message, msg.wParam, msg.lParam);
else
DispatchMessage(&msg);
if (msg.message == WM_QUIT)
Close = true;
}
if (!Close)
resizeIfNecessary();
_IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX;
return !Close;
}
//! Pause the current process for the minimum time allowed only to allow other processes to execute
void CIrrDeviceWinCE::yield()
{
Sleep(1);
}
//! Pause execution and let other processes to run for a specified amount of time.
void CIrrDeviceWinCE::sleep(u32 timeMs, bool pauseTimer)
{
const bool wasStopped = Timer ? Timer->isStopped() : true;
if (pauseTimer && !wasStopped)
Timer->stop();
Sleep(timeMs);
if (pauseTimer && !wasStopped)
Timer->start();
}
void CIrrDeviceWinCE::resizeIfNecessary()
{
if (!Resized)
return;
RECT r;
GetClientRect(HWnd, &r);
char tmp[255];
if (r.right < 2 || r.bottom < 2)
{
sprintf(tmp, "Ignoring resize operation to (%ld %ld)", r.right, r.bottom);
os::Printer::log(tmp);
}
else
{
sprintf(tmp, "Resizing window (%ld %ld)", r.right, r.bottom);
os::Printer::log(tmp);
getVideoDriver()->OnResize(irr::core::dimension2d<irr::u32>(r.right, r.bottom));
getWin32CursorControl()->OnResize(getVideoDriver()->getScreenSize());
}
Resized = false;
}
//! sets the caption of the window
void CIrrDeviceWinCE::setWindowCaption(const wchar_t* text)
{
SetWindowTextW(HWnd, text);
}
#if !defined(BITMAPV4HEADER)
typedef struct {
DWORD bV4Size;
LONG bV4Width;
LONG bV4Height;
WORD bV4Planes;
WORD bV4BitCount;
DWORD bV4V4Compression;
DWORD bV4SizeImage;
LONG bV4XPelsPerMeter;
LONG bV4YPelsPerMeter;
DWORD bV4ClrUsed;
DWORD bV4ClrImportant;
DWORD bV4RedMask;
DWORD bV4GreenMask;
DWORD bV4BlueMask;
DWORD bV4AlphaMask;
DWORD bV4CSType;
DWORD un[9];
} BITMAPV4HEADER, *PBITMAPV4HEADER;
#endif
//! presents a surface in the client area
bool CIrrDeviceWinCE::present(video::IImage* image, void* windowId, core::rect<s32>* src)
{
HWND hwnd = HWnd;
if ( windowId )
hwnd = (HWND)windowId;
HDC dc = GetDC(hwnd);
if ( dc )
{
RECT rect;
GetClientRect(hwnd, &rect);
const void* memory = (const void *)image->lock();
BITMAPV4HEADER bi;
memset (&bi, 0, sizeof(bi));
bi.bV4Size = sizeof(BITMAPINFOHEADER);
bi.bV4BitCount = image->getBitsPerPixel();
bi.bV4Planes = 1;
bi.bV4Width = image->getDimension().Width;
bi.bV4Height = 0 - image->getDimension().Height;
bi.bV4V4Compression = BI_BITFIELDS;
bi.bV4AlphaMask = image->getAlphaMask ();
bi.bV4RedMask = image->getRedMask ();
bi.bV4GreenMask = image->getGreenMask();
bi.bV4BlueMask = image->getBlueMask();
int r = 0;
if ( src )
{
r = StretchDIBits(dc, 0,0, rect.right, rect.bottom,
src->UpperLeftCorner.X, src->UpperLeftCorner.Y,
src->getWidth(), src->getHeight(),
memory, (const BITMAPINFO*)(&bi), DIB_RGB_COLORS, SRCCOPY);
}
else
{
r = StretchDIBits(dc, 0,0, rect.right, rect.bottom,
0, 0, image->getDimension().Width, image->getDimension().Height,
memory, (const BITMAPINFO*)(&bi), DIB_RGB_COLORS, SRCCOPY);
}
image->unlock();
ReleaseDC(hwnd, dc);
}
return true;
}
//! notifies the device that it should close itself
void CIrrDeviceWinCE::closeDevice()
{
MSG msg;
PeekMessage(&msg, NULL, WM_QUIT, WM_QUIT, PM_REMOVE);
PostQuitMessage(0);
PeekMessage(&msg, NULL, WM_QUIT, WM_QUIT, PM_REMOVE);
if (!ExternalWindow)
{
DestroyWindow(HWnd);
const fschar_t* ClassName = __TEXT("CIrrDeviceWin32");
HINSTANCE hInstance = GetModuleHandle(0);
UnregisterClass(ClassName, hInstance);
}
Close=true;
}
//! returns if window is active. if not, nothing need to be drawn
bool CIrrDeviceWinCE::isWindowActive() const
{
bool ret = (GetActiveWindow() == HWnd);
_IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX;
return ret;
}
//! returns if window has focus
bool CIrrDeviceWinCE::isWindowFocused() const
{
bool ret = (GetFocus() == HWnd);
_IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX;
return ret;
}
//! returns if window is minimized
bool CIrrDeviceWinCE::isWindowMinimized() const
{
#if 0
WINDOWPLACEMENT plc;
plc.length=sizeof(WINDOWPLACEMENT);
bool ret=false;
if (GetWindowPlacement(HWnd,&plc))
ret=(plc.showCmd & SW_SHOWMINIMIZED);
_IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX;
return ret;
#endif
return false;
}
//! switches to fullscreen
bool CIrrDeviceWinCE::switchToFullScreen()
{
ChangedToFullScreen = SHFullScreen(HWnd, SHFS_HIDESIPBUTTON | SHFS_HIDETASKBAR) != 0;
return ChangedToFullScreen;
}
//! returns the win32 cursor control
CIrrDeviceWinCE::CCursorControl* CIrrDeviceWinCE::getWin32CursorControl()
{
return Win32CursorControl;
}
//! Return pointer to a list with all video modes supported by the gfx adapter.
/** \return Pointer to video modes list */
video::IVideoModeList* CIrrDeviceWinCE::getVideoModeList()
{
if (!VideoModeList.getVideoModeCount())
{
// enumerate video modes.
DWORD i=0;
DEVMODE mode;
memset(&mode, 0, sizeof(mode));
mode.dmSize = sizeof(mode);
while (EnumDisplaySettings(NULL, i, &mode))
{
VideoModeList.addMode(core::dimension2d<u32>(mode.dmPelsWidth, mode.dmPelsHeight),
mode.dmBitsPerPel);
++i;
}
if (EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &mode))
VideoModeList.setDesktop(mode.dmBitsPerPel, core::dimension2d<u32>(mode.dmPelsWidth, mode.dmPelsHeight));
}
return &VideoModeList;
}
void CIrrDeviceWinCE::getWindowsVersion(core::stringc& out)
{
out = "WinCE";
}
//! Notifies the device, that it has been resized
void CIrrDeviceWinCE::OnResized()
{
Resized = true;
}
//! Sets if the window should be resizable in windowed mode.
void CIrrDeviceWinCE::setResizable(bool resize)
{
if (ExternalWindow || !getVideoDriver() || CreationParams.Fullscreen)
return;
LONG style = WS_POPUP;
if (!resize)
style = WS_SYSMENU | WS_BORDER | WS_CAPTION | WS_CLIPCHILDREN | WS_CLIPSIBLINGS;
else
style = WS_THICKFRAME | WS_SYSMENU | WS_CAPTION | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | WS_MAXIMIZEBOX;
if (!SetWindowLong(HWnd, GWL_STYLE, style))
os::Printer::log("Could not change window style.");
RECT clientSize;
clientSize.top = 0;
clientSize.left = 0;
clientSize.right = getVideoDriver()->getScreenSize().Width;
clientSize.bottom = getVideoDriver()->getScreenSize().Height;
AdjustWindowRectEx(&clientSize, style, FALSE, 0);
const s32 realWidth = clientSize.right - clientSize.left;
const s32 realHeight = clientSize.bottom - clientSize.top;
const s32 windowLeft = (GetSystemMetrics(SM_CXSCREEN) - realWidth) / 2;
const s32 windowTop = (GetSystemMetrics(SM_CYSCREEN) - realHeight) / 2;
SetWindowPos(HWnd, HWND_TOP, windowLeft, windowTop, realWidth, realHeight,
SWP_FRAMECHANGED | SWP_NOMOVE | SWP_SHOWWINDOW);
}
//! Minimizes the window.
void CIrrDeviceWinCE::minimizeWindow()
{
// do nothing
}
//! Maximize window
void CIrrDeviceWinCE::maximizeWindow()
{
// do nothing
}
//! Restore original window size
void CIrrDeviceWinCE::restoreWindow()
{
// do nothing
}
} // end namespace
#endif // _IRR_COMPILE_WITH_WINDOWS_CE_DEVICE_

View File

@ -1,296 +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_IRR_DEVICE_WINCE_H_INCLUDED__
#define __C_IRR_DEVICE_WINCE_H_INCLUDED__
#include "IrrCompileConfig.h"
#ifdef _IRR_COMPILE_WITH_WINDOWS_CE_DEVICE_
#include "CIrrDeviceStub.h"
#include "IrrlichtDevice.h"
#include "IImagePresenter.h"
#include <windows.h>
#include <windowsx.h>
#include <commctrl.h>
#include <aygshell.h>
#include <sipapi.h>
#include <gx.h>
namespace irr
{
class CIrrDeviceWinCE : public CIrrDeviceStub, video::IImagePresenter
{
public:
//! constructor
CIrrDeviceWinCE( const SIrrlichtCreationParameters& params);
//! destructor
virtual ~CIrrDeviceWinCE();
//! runs the device. Returns false if device wants to be deleted
virtual bool run();
//! Cause the device to temporarily pause execution and let other processes to run
// This should bring down processor usage without major performance loss for Irrlicht
virtual void yield();
//! Pause execution and let other processes to run for a specified amount of time.
virtual void sleep(u32 timeMs, bool pauseTimer);
//! sets the caption of the window
virtual void setWindowCaption(const wchar_t* text);
//! returns if window is active. if not, nothing need to be drawn
virtual bool isWindowActive() const;
//! returns if window has focus
virtual bool isWindowFocused() const;
//! returns if window is minimized
virtual bool isWindowMinimized() const;
//! presents a surface in the client area
virtual bool present(video::IImage* surface, void* windowId = 0, core::rect<s32>* src=0 );
//! notifies the device that it should close itself
virtual void closeDevice();
//! \return Returns a pointer to a list with all video modes
//! supported by the gfx adapter.
video::IVideoModeList* getVideoModeList();
//! Notifies the device, that it has been resized
void OnResized();
//! Sets if the window should be resizable in windowed mode.
virtual void setResizable(bool resize=false);
//! Minimizes the window.
virtual void minimizeWindow();
//! Maximizes the window.
virtual void maximizeWindow();
//! Restores the window size.
virtual void restoreWindow();
//! Get the device type
virtual E_DEVICE_TYPE getType() const
{
return EIDT_WINCE;
}
//! Implementation of the win32 cursor control
class CCursorControl : public gui::ICursorControl
{
public:
CCursorControl(const core::dimension2d<u32>& wsize, HWND hwnd, bool fullscreen)
: WindowSize(wsize), InvWindowSize(0.0f, 0.0f),
HWnd(hwnd), BorderX(0), BorderY(0),
UseReferenceRect(false), IsVisible(true)
{
if (WindowSize.Width!=0)
InvWindowSize.Width = 1.0f / WindowSize.Width;
if (WindowSize.Height!=0)
InvWindowSize.Height = 1.0f / WindowSize.Height;
if (!fullscreen)
{
BorderX = GetSystemMetrics(SM_CXDLGFRAME);
BorderY = GetSystemMetrics(SM_CYCAPTION) + GetSystemMetrics(SM_CYDLGFRAME);
}
}
//! Changes the visible state of the mouse cursor.
virtual void setVisible(bool visible)
{
IsVisible = visible;
}
//! Returns if the cursor is currently visible.
virtual bool isVisible() const
{
_IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX;
return IsVisible;
}
//! Sets the new position of the cursor.
virtual void setPosition(const core::position2d<f32> &pos)
{
setPosition(pos.X, pos.Y);
}
//! Sets the new position of the cursor.
virtual void setPosition(f32 x, f32 y)
{
if (!UseReferenceRect)
setPosition(core::round32(x*WindowSize.Width), core::round32(y*WindowSize.Height));
else
setPosition(core::round32(x*ReferenceRect.getWidth()), core::round32(y*ReferenceRect.getHeight()));
}
//! Sets the new position of the cursor.
virtual void setPosition(const core::position2d<s32> &pos)
{
setPosition(pos.X, pos.Y);
}
//! Sets the new position of the cursor.
virtual void setPosition(s32 x, s32 y)
{
RECT rect;
if (UseReferenceRect)
{
SetCursorPos(ReferenceRect.UpperLeftCorner.X + x,
ReferenceRect.UpperLeftCorner.Y + y);
}
else
{
if (GetWindowRect(HWnd, &rect))
SetCursorPos(x + rect.left + BorderX, y + rect.top + BorderY);
}
CursorPos.X = x;
CursorPos.Y = y;
}
//! Returns the current position of the mouse cursor.
virtual const core::position2d<s32>& getPosition()
{
updateInternalCursorPosition();
return CursorPos;
}
//! Returns the current position of the mouse cursor.
virtual core::position2d<f32> getRelativePosition()
{
updateInternalCursorPosition();
if (!UseReferenceRect)
{
return core::position2d<f32>(CursorPos.X * InvWindowSize.Width,
CursorPos.Y * InvWindowSize.Height);
}
return core::position2d<f32>(CursorPos.X / (f32)ReferenceRect.getWidth(),
CursorPos.Y / (f32)ReferenceRect.getHeight());
}
//! Sets an absolute reference rect for calculating the cursor position.
virtual void setReferenceRect(core::rect<s32>* rect=0)
{
if (rect)
{
ReferenceRect = *rect;
UseReferenceRect = true;
// prevent division through zero and uneven sizes
if (!ReferenceRect.getHeight() || ReferenceRect.getHeight()%2)
ReferenceRect.LowerRightCorner.Y += 1;
if (!ReferenceRect.getWidth() || ReferenceRect.getWidth()%2)
ReferenceRect.LowerRightCorner.X += 1;
}
else
UseReferenceRect = false;
}
/** Used to notify the cursor that the window was resized. */
virtual void OnResize(const core::dimension2d<u32>& size)
{
WindowSize = size;
if (size.Width!=0)
InvWindowSize.Width = 1.0f / size.Width;
else
InvWindowSize.Width = 0.f;
if (size.Height!=0)
InvWindowSize.Height = 1.0f / size.Height;
else
InvWindowSize.Height = 0.f;
}
private:
//! Updates the internal cursor position
void updateInternalCursorPosition()
{
POINT p;
if (!GetCursorPos(&p))
{
DWORD xy = GetMessagePos();
p.x = GET_X_LPARAM(xy);
p.y = GET_Y_LPARAM(xy);
}
if (UseReferenceRect)
{
CursorPos.X = p.x - ReferenceRect.UpperLeftCorner.X;
CursorPos.Y = p.y - ReferenceRect.UpperLeftCorner.Y;
}
else
{
RECT rect;
if (GetWindowRect(HWnd, &rect))
{
CursorPos.X = p.x-rect.left-BorderX;
CursorPos.Y = p.y-rect.top-BorderY;
}
else
{
// window seems not to be existent, so set cursor to
// a negative value
CursorPos.X = -1;
CursorPos.Y = -1;
}
}
}
core::position2d<s32> CursorPos;
core::dimension2d<s32> WindowSize;
core::dimension2d<f32> InvWindowSize;
HWND HWnd;
s32 BorderX, BorderY;
core::rect<s32> ReferenceRect;
bool UseReferenceRect;
bool IsVisible;
};
//! returns the win32 cursor control
CCursorControl* getWin32CursorControl();
private:
//! create the driver
void createDriver();
//! switchs to fullscreen
bool switchToFullScreen();
void getWindowsVersion(core::stringc& version);
void resizeIfNecessary();
HWND HWnd;
CCursorControl* Win32CursorControl;
bool ChangedToFullScreen;
bool Resized;
bool ExternalWindow;
};
} // end namespace irr
#endif // _IRR_COMPILE_WITH_WINDOWS_CE_DEVICE_
#endif // __C_IRR_DEVICE_WINCE_H_INCLUDED__

View File

@ -1,554 +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 "IrrCompileConfig.h"
#ifdef _IRR_COMPILE_WITH_IRR_MESH_LOADER_
#include "CIrrMeshFileLoader.h"
#include "os.h"
#include "IXMLReader.h"
#include "SAnimatedMesh.h"
#include "fast_atof.h"
#include "IReadFile.h"
#include "IAttributes.h"
#include "IMeshSceneNode.h"
#include "CDynamicMeshBuffer.h"
#include "SMeshBufferLightMap.h"
namespace irr
{
namespace scene
{
//! Constructor
CIrrMeshFileLoader::CIrrMeshFileLoader(scene::ISceneManager* smgr,
io::IFileSystem* fs)
: SceneManager(smgr), FileSystem(fs)
{
#ifdef _DEBUG
setDebugName("CIrrMeshFileLoader");
#endif
}
//! Returns true if the file maybe is able to be loaded by this class.
/** This decision should be based only on the file extension (e.g. ".cob") */
bool CIrrMeshFileLoader::isALoadableFileExtension(const io::path& filename) const
{
return core::hasFileExtension ( filename, "xml", "irrmesh" );
}
//! creates/loads an animated mesh from the file.
//! \return Pointer to the created mesh. Returns 0 if loading failed.
//! If you no longer need the mesh, you should call IAnimatedMesh::drop().
//! See IReferenceCounted::drop() for more information.
IAnimatedMesh* CIrrMeshFileLoader::createMesh(io::IReadFile* file)
{
io::IXMLReader* reader = FileSystem->createXMLReader(file);
if (!reader)
return 0;
// read until mesh section, skip other parts
const core::stringc meshTagName = "mesh";
IAnimatedMesh* mesh = 0;
while(reader->read())
{
if (reader->getNodeType() == io::EXN_ELEMENT)
{
if (meshTagName == reader->getNodeName())
{
mesh = readMesh(reader);
break;
}
else
skipSection(reader, true); // unknown section
}
}
reader->drop();
return mesh;
}
//! reads a mesh sections and creates a mesh from it
IAnimatedMesh* CIrrMeshFileLoader::readMesh(io::IXMLReader* reader)
{
SAnimatedMesh* animatedmesh = new SAnimatedMesh();
SMesh* mesh = new SMesh();
animatedmesh->addMesh(mesh);
mesh->drop();
core::stringc bbSectionName = "boundingBox";
core::stringc bufferSectionName = "buffer";
core::stringc meshSectionName = "mesh";
if (!reader->isEmptyElement())
while(reader->read())
{
if (reader->getNodeType() == io::EXN_ELEMENT)
{
const wchar_t* nodeName = reader->getNodeName();
if (bbSectionName == nodeName)
{
// inside a bounding box, ignore it for now because
// we are calculating this anyway ourselves later.
}
else
if (bufferSectionName == nodeName)
{
// we've got a mesh buffer
IMeshBuffer* buffer = readMeshBuffer(reader);
if (buffer)
{
mesh->addMeshBuffer(buffer);
buffer->drop();
}
}
else
skipSection(reader, true); // unknown section
} // end if node type is element
else
if (reader->getNodeType() == io::EXN_ELEMENT_END)
{
if (meshSectionName == reader->getNodeName())
{
// end of mesh section reached, cancel out
break;
}
}
} // end while reader->read();
mesh->recalculateBoundingBox();
animatedmesh->recalculateBoundingBox();
return animatedmesh;
}
//! reads a mesh sections and creates a mesh buffer from it
IMeshBuffer* CIrrMeshFileLoader::readMeshBuffer(io::IXMLReader* reader)
{
CDynamicMeshBuffer* buffer = 0;
core::stringc verticesSectionName = "vertices";
core::stringc bbSectionName = "boundingBox";
core::stringc materialSectionName = "material";
core::stringc indicesSectionName = "indices";
core::stringc bufferSectionName = "buffer";
bool insideVertexSection = false;
bool insideIndexSection = false;
int vertexCount = 0;
int indexCount = 0;
video::SMaterial material;
if (!reader->isEmptyElement())
while(reader->read())
{
if (reader->getNodeType() == io::EXN_ELEMENT)
{
const wchar_t* nodeName = reader->getNodeName();
if (bbSectionName == nodeName)
{
// inside a bounding box, ignore it for now because
// we are calculating this anyway ourselves later.
}
else
if (materialSectionName == nodeName)
{
//we've got a material
io::IAttributes* attributes = FileSystem->createEmptyAttributes(SceneManager->getVideoDriver());
attributes->read(reader, true, L"material");
SceneManager->getVideoDriver()->fillMaterialStructureFromAttributes(material, attributes);
attributes->drop();
}
else
if (verticesSectionName == nodeName)
{
// vertices section
const core::stringc vertexTypeName1 = "standard";
const core::stringc vertexTypeName2 = "2tcoords";
const core::stringc vertexTypeName3 = "tangents";
const wchar_t* vertexType = reader->getAttributeValue(L"type");
vertexCount = reader->getAttributeValueAsInt(L"vertexCount");
insideVertexSection = true;
video::E_INDEX_TYPE itype = (vertexCount > 65536)?irr::video::EIT_32BIT:irr::video::EIT_16BIT;
if (vertexTypeName1 == vertexType)
{
buffer = new CDynamicMeshBuffer(irr::video::EVT_STANDARD, itype);
}
else
if (vertexTypeName2 == vertexType)
{
buffer = new CDynamicMeshBuffer(irr::video::EVT_2TCOORDS, itype);
}
else
if (vertexTypeName3 == vertexType)
{
buffer = new CDynamicMeshBuffer(irr::video::EVT_TANGENTS, itype);
}
buffer->getVertexBuffer().reallocate(vertexCount);
buffer->Material = material;
}
else
if (indicesSectionName == nodeName)
{
// indices section
indexCount = reader->getAttributeValueAsInt(L"indexCount");
insideIndexSection = true;
}
} // end if node type is element
else
if (reader->getNodeType() == io::EXN_TEXT)
{
// read vertex data
if (insideVertexSection)
{
readMeshBuffer(reader, vertexCount, buffer);
insideVertexSection = false;
} // end reading vertex array
else
if (insideIndexSection)
{
readIndices(reader, indexCount, buffer->getIndexBuffer());
insideIndexSection = false;
}
} // end if node type is text
else
if (reader->getNodeType() == io::EXN_ELEMENT_END)
{
if (bufferSectionName == reader->getNodeName())
{
// end of buffer section reached, cancel out
break;
}
}
} // end while reader->read();
if (buffer)
buffer->recalculateBoundingBox();
return buffer;
}
//! read indices
void CIrrMeshFileLoader::readIndices(io::IXMLReader* reader, int indexCount, IIndexBuffer& indices)
{
indices.reallocate(indexCount);
core::stringc data = reader->getNodeData();
const c8* p = &data[0];
for (int i=0; i<indexCount && *p; ++i)
{
findNextNoneWhiteSpace(&p);
indices.push_back(readInt(&p));
}
}
void CIrrMeshFileLoader::readMeshBuffer(io::IXMLReader* reader, int vertexCount, CDynamicMeshBuffer* sbuffer)
{
core::stringc data = reader->getNodeData();
const c8* p = &data[0];
scene::IVertexBuffer& Vertices = sbuffer->getVertexBuffer();
video::E_VERTEX_TYPE vType = Vertices.getType();
if (sbuffer)
{
for (int i=0; i<vertexCount && *p; ++i)
{
switch(vType)
{
case video::EVT_STANDARD:
{
video::S3DVertex vtx;
// position
findNextNoneWhiteSpace(&p);
vtx.Pos.X = readFloat(&p);
findNextNoneWhiteSpace(&p);
vtx.Pos.Y = readFloat(&p);
findNextNoneWhiteSpace(&p);
vtx.Pos.Z = readFloat(&p);
// normal
findNextNoneWhiteSpace(&p);
vtx.Normal.X = readFloat(&p);
findNextNoneWhiteSpace(&p);
vtx.Normal.Y = readFloat(&p);
findNextNoneWhiteSpace(&p);
vtx.Normal.Z = readFloat(&p);
// color
u32 col;
findNextNoneWhiteSpace(&p);
sscanf(p, "%08x", &col);
vtx.Color.set(col);
skipCurrentNoneWhiteSpace(&p);
// tcoord1
findNextNoneWhiteSpace(&p);
vtx.TCoords.X = readFloat(&p);
findNextNoneWhiteSpace(&p);
vtx.TCoords.Y = readFloat(&p);
Vertices.push_back(vtx);
}
break;
case video::EVT_2TCOORDS:
{
video::S3DVertex2TCoords vtx;
// position
findNextNoneWhiteSpace(&p);
vtx.Pos.X = readFloat(&p);
findNextNoneWhiteSpace(&p);
vtx.Pos.Y = readFloat(&p);
findNextNoneWhiteSpace(&p);
vtx.Pos.Z = readFloat(&p);
// normal
findNextNoneWhiteSpace(&p);
vtx.Normal.X = readFloat(&p);
findNextNoneWhiteSpace(&p);
vtx.Normal.Y = readFloat(&p);
findNextNoneWhiteSpace(&p);
vtx.Normal.Z = readFloat(&p);
// color
u32 col;
findNextNoneWhiteSpace(&p);
sscanf(p, "%08x", &col);
vtx.Color.set(col);
skipCurrentNoneWhiteSpace(&p);
// tcoord1
findNextNoneWhiteSpace(&p);
vtx.TCoords.X = readFloat(&p);
findNextNoneWhiteSpace(&p);
vtx.TCoords.Y = readFloat(&p);
// tcoord2
findNextNoneWhiteSpace(&p);
vtx.TCoords2.X = readFloat(&p);
findNextNoneWhiteSpace(&p);
vtx.TCoords2.Y = readFloat(&p);
Vertices.push_back(vtx);
}
break;
case video::EVT_TANGENTS:
{
video::S3DVertexTangents vtx;
// position
findNextNoneWhiteSpace(&p);
vtx.Pos.X = readFloat(&p);
findNextNoneWhiteSpace(&p);
vtx.Pos.Y = readFloat(&p);
findNextNoneWhiteSpace(&p);
vtx.Pos.Z = readFloat(&p);
// normal
findNextNoneWhiteSpace(&p);
vtx.Normal.X = readFloat(&p);
findNextNoneWhiteSpace(&p);
vtx.Normal.Y = readFloat(&p);
findNextNoneWhiteSpace(&p);
vtx.Normal.Z = readFloat(&p);
// color
u32 col;
findNextNoneWhiteSpace(&p);
sscanf(p, "%08x", &col);
vtx.Color.set(col);
skipCurrentNoneWhiteSpace(&p);
// tcoord1
findNextNoneWhiteSpace(&p);
vtx.TCoords.X = readFloat(&p);
findNextNoneWhiteSpace(&p);
vtx.TCoords.Y = readFloat(&p);
// tangent
findNextNoneWhiteSpace(&p);
vtx.Tangent.X = readFloat(&p);
findNextNoneWhiteSpace(&p);
vtx.Tangent.Y = readFloat(&p);
findNextNoneWhiteSpace(&p);
vtx.Tangent.Z = readFloat(&p);
// binormal
findNextNoneWhiteSpace(&p);
vtx.Binormal.X = readFloat(&p);
findNextNoneWhiteSpace(&p);
vtx.Binormal.Y = readFloat(&p);
findNextNoneWhiteSpace(&p);
vtx.Binormal.Z = readFloat(&p);
Vertices.push_back(vtx);
}
break;
};
}
}
}
//! skips an (unknown) section in the irrmesh document
void CIrrMeshFileLoader::skipSection(io::IXMLReader* reader, bool reportSkipping)
{
#ifdef _DEBUG
os::Printer::log("irrMesh skipping section", core::stringc(reader->getNodeName()).c_str());
#endif
// skip if this element is empty anyway.
if (reader->isEmptyElement())
return;
// read until we've reached the last element in this section
u32 tagCounter = 1;
while(tagCounter && reader->read())
{
if (reader->getNodeType() == io::EXN_ELEMENT &&
!reader->isEmptyElement())
{
#ifdef _DEBUG
if (reportSkipping)
os::Printer::log("irrMesh unknown element:", core::stringc(reader->getNodeName()).c_str());
#endif
++tagCounter;
}
else
if (reader->getNodeType() == io::EXN_ELEMENT_END)
--tagCounter;
}
}
//! parses a float from a char pointer and moves the pointer
//! to the end of the parsed float
inline f32 CIrrMeshFileLoader::readFloat(const c8** p)
{
f32 ftmp;
*p = core::fast_atof_move(*p, ftmp);
return ftmp;
}
//! parses an int from a char pointer and moves the pointer to
//! the end of the parsed float
inline s32 CIrrMeshFileLoader::readInt(const c8** p)
{
return (s32)readFloat(p);
}
//! places pointer to next begin of a token
void CIrrMeshFileLoader::skipCurrentNoneWhiteSpace(const c8** start)
{
const c8* p = *start;
while(*p && !(*p==' ' || *p=='\n' || *p=='\r' || *p=='\t'))
++p;
// TODO: skip comments <!-- -->
*start = p;
}
//! places pointer to next begin of a token
void CIrrMeshFileLoader::findNextNoneWhiteSpace(const c8** start)
{
const c8* p = *start;
while(*p && (*p==' ' || *p=='\n' || *p=='\r' || *p=='\t'))
++p;
// TODO: skip comments <!-- -->
*start = p;
}
//! reads floats from inside of xml element until end of xml element
void CIrrMeshFileLoader::readFloatsInsideElement(io::IXMLReader* reader, f32* floats, u32 count)
{
if (reader->isEmptyElement())
return;
while(reader->read())
{
// TODO: check for comments inside the element
// and ignore them.
if (reader->getNodeType() == io::EXN_TEXT)
{
// parse float data
core::stringc data = reader->getNodeData();
const c8* p = &data[0];
for (u32 i=0; i<count; ++i)
{
findNextNoneWhiteSpace(&p);
if (*p)
floats[i] = readFloat(&p);
else
floats[i] = 0.0f;
}
}
else
if (reader->getNodeType() == io::EXN_ELEMENT_END)
break; // end parsing text
}
}
} // end namespace scene
} // end namespace irr
#endif // _IRR_COMPILE_WITH_IRR_MESH_LOADER_

View File

@ -1,90 +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_IRR_MESH_FILE_LOADER_H_INCLUDED__
#define __C_IRR_MESH_FILE_LOADER_H_INCLUDED__
#include "IMeshLoader.h"
#include "IFileSystem.h"
#include "IVideoDriver.h"
#include "irrString.h"
#include "SMesh.h"
#include "SMeshBuffer.h"
#include "CDynamicMeshBuffer.h"
#include "ISceneManager.h"
namespace irr
{
namespace scene
{
//! Meshloader capable of loading .irrmesh meshes, the Irrlicht Engine mesh format for static meshes
class CIrrMeshFileLoader : public IMeshLoader
{
public:
//! Constructor
CIrrMeshFileLoader(scene::ISceneManager* smgr, io::IFileSystem* fs);
//! returns true if the file maybe is able to be loaded by this class
//! based on the file extension (e.g. ".cob")
virtual bool isALoadableFileExtension(const io::path& filename) const;
//! creates/loads an animated mesh from the file.
//! \return Pointer to the created mesh. Returns 0 if loading failed.
//! If you no longer need the mesh, you should call IAnimatedMesh::drop().
//! See IReferenceCounted::drop() for more information.
virtual IAnimatedMesh* createMesh(io::IReadFile* file);
private:
//! reads a mesh sections and creates a mesh from it
IAnimatedMesh* readMesh(io::IXMLReader* reader);
//! reads a mesh sections and creates a mesh buffer from it
IMeshBuffer* readMeshBuffer(io::IXMLReader* reader);
//! skips an (unknown) section in the irrmesh file
void skipSection(io::IXMLReader* reader, bool reportSkipping);
//! reads a <material> element and stores it in the material section
void readMaterial(io::IXMLReader* reader);
//! parses a float from a char pointer and moves the pointer to
//! the end of the parsed float
inline f32 readFloat(const c8** p);
//! parses an int from a char pointer and moves the pointer to
//! the end of the parsed float
inline s32 readInt(const c8** p);
//! places pointer to next begin of a token
void findNextNoneWhiteSpace(const c8** p);
//! places pointer to next begin of a token
void skipCurrentNoneWhiteSpace(const c8** p);
//! reads floats from inside of xml element until end of xml element
void readFloatsInsideElement(io::IXMLReader* reader, f32* floats, u32 count);
//! read the mesh buffers
void readMeshBuffer(io::IXMLReader* reader, int vertexCount, CDynamicMeshBuffer* sbuffer);
//! read indices
void readIndices(io::IXMLReader* reader, int indexCount, IIndexBuffer& indices);
// member variables
scene::ISceneManager* SceneManager;
io::IFileSystem* FileSystem;
};
} // end namespace scene
} // end namespace irr
#endif

View File

@ -1,315 +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 "IrrCompileConfig.h"
#ifdef _IRR_COMPILE_WITH_IRR_WRITER_
#include "CIrrMeshWriter.h"
#include "os.h"
#include "IWriteFile.h"
#include "IXMLWriter.h"
#include "IMesh.h"
#include "IAttributes.h"
namespace irr
{
namespace scene
{
CIrrMeshWriter::CIrrMeshWriter(video::IVideoDriver* driver,
io::IFileSystem* fs)
: FileSystem(fs), VideoDriver(driver), Writer(0)
{
#ifdef _DEBUG
setDebugName("CIrrMeshWriter");
#endif
if (VideoDriver)
VideoDriver->grab();
if (FileSystem)
FileSystem->grab();
}
CIrrMeshWriter::~CIrrMeshWriter()
{
if (VideoDriver)
VideoDriver->drop();
if (FileSystem)
FileSystem->drop();
}
//! Returns the type of the mesh writer
EMESH_WRITER_TYPE CIrrMeshWriter::getType() const
{
return EMWT_IRR_MESH;
}
//! writes a mesh
bool CIrrMeshWriter::writeMesh(io::IWriteFile* file, scene::IMesh* mesh, s32 flags)
{
if (!file)
return false;
Writer = FileSystem->createXMLWriter(file);
if (!Writer)
{
os::Printer::log("Could not write file", file->getFileName());
return false;
}
os::Printer::log("Writing mesh", file->getFileName());
// write IRR MESH header
Writer->writeXMLHeader();
Writer->writeElement(L"mesh", false,
L"xmlns", L"http://irrlicht.sourceforge.net/IRRMESH_09_2007",
L"version", L"1.0");
Writer->writeLineBreak();
// add some informational comment. Add a space after and before the comment
// tags so that some braindead xml parsers (AS anyone?) are able to parse this too.
core::stringw infoComment = L" This file contains a static mesh in the Irrlicht Engine format with ";
infoComment += core::stringw(mesh->getMeshBufferCount());
infoComment += L" materials.";
Writer->writeComment(infoComment.c_str());
Writer->writeLineBreak();
// write mesh bounding box
writeBoundingBox(mesh->getBoundingBox());
Writer->writeLineBreak();
// write mesh buffers
for (int i=0; i<(int)mesh->getMeshBufferCount(); ++i)
{
scene::IMeshBuffer* buffer = mesh->getMeshBuffer(i);
if (buffer)
{
writeMeshBuffer(buffer);
Writer->writeLineBreak();
}
}
Writer->writeClosingTag(L"mesh");
Writer->drop();
return true;
}
void CIrrMeshWriter::writeBoundingBox(const core::aabbox3df& box)
{
Writer->writeElement(L"boundingBox", true,
L"minEdge", getVectorAsStringLine(box.MinEdge).c_str(),
L"maxEdge", getVectorAsStringLine(box.MaxEdge).c_str());
}
core::stringw CIrrMeshWriter::getVectorAsStringLine(const core::vector3df& v) const
{
core::stringw str;
str = core::stringw(v.X);
str += L" ";
str += core::stringw(v.Y);
str += L" ";
str += core::stringw(v.Z);
return str;
}
core::stringw CIrrMeshWriter::getVectorAsStringLine(const core::vector2df& v) const
{
core::stringw str;
str = core::stringw(v.X);
str += L" ";
str += core::stringw(v.Y);
return str;
}
void CIrrMeshWriter::writeMeshBuffer(const scene::IMeshBuffer* buffer)
{
Writer->writeElement(L"buffer", false);
Writer->writeLineBreak();
// write bounding box
writeBoundingBox(buffer->getBoundingBox());
Writer->writeLineBreak();
// write material
writeMaterial(buffer->getMaterial());
// write vertices
const core::stringw vertexTypeStr = video::sBuiltInVertexTypeNames[buffer->getVertexType()];
Writer->writeElement(L"vertices", false,
L"type", vertexTypeStr.c_str(),
L"vertexCount", core::stringw(buffer->getVertexCount()).c_str());
Writer->writeLineBreak();
u32 vertexCount = buffer->getVertexCount();
switch(buffer->getVertexType())
{
case video::EVT_STANDARD:
{
video::S3DVertex* vtx = (video::S3DVertex*)buffer->getVertices();
for (u32 j=0; j<vertexCount; ++j)
{
core::stringw str = getVectorAsStringLine(vtx[j].Pos);
str += L" ";
str += getVectorAsStringLine(vtx[j].Normal);
char tmp[12];
sprintf(tmp, " %02x%02x%02x%02x ", vtx[j].Color.getAlpha(), vtx[j].Color.getRed(), vtx[j].Color.getGreen(), vtx[j].Color.getBlue());
str += tmp;
str += getVectorAsStringLine(vtx[j].TCoords);
Writer->writeText(str.c_str());
Writer->writeLineBreak();
}
}
break;
case video::EVT_2TCOORDS:
{
video::S3DVertex2TCoords* vtx = (video::S3DVertex2TCoords*)buffer->getVertices();
for (u32 j=0; j<vertexCount; ++j)
{
core::stringw str = getVectorAsStringLine(vtx[j].Pos);
str += L" ";
str += getVectorAsStringLine(vtx[j].Normal);
char tmp[12];
sprintf(tmp, " %02x%02x%02x%02x ", vtx[j].Color.getAlpha(), vtx[j].Color.getRed(), vtx[j].Color.getGreen(), vtx[j].Color.getBlue());
str += tmp;
str += getVectorAsStringLine(vtx[j].TCoords);
str += L" ";
str += getVectorAsStringLine(vtx[j].TCoords2);
Writer->writeText(str.c_str());
Writer->writeLineBreak();
}
}
break;
case video::EVT_TANGENTS:
{
video::S3DVertexTangents* vtx = (video::S3DVertexTangents*)buffer->getVertices();
for (u32 j=0; j<vertexCount; ++j)
{
core::stringw str = getVectorAsStringLine(vtx[j].Pos);
str += L" ";
str += getVectorAsStringLine(vtx[j].Normal);
char tmp[12];
sprintf(tmp, " %02x%02x%02x%02x ", vtx[j].Color.getAlpha(), vtx[j].Color.getRed(), vtx[j].Color.getGreen(), vtx[j].Color.getBlue());
str += tmp;
str += getVectorAsStringLine(vtx[j].TCoords);
str += L" ";
str += getVectorAsStringLine(vtx[j].Tangent);
str += L" ";
str += getVectorAsStringLine(vtx[j].Binormal);
Writer->writeText(str.c_str());
Writer->writeLineBreak();
}
}
break;
}
Writer->writeClosingTag(L"vertices");
Writer->writeLineBreak();
// write indices
Writer->writeElement(L"indices", false,
L"indexCount", core::stringw(buffer->getIndexCount()).c_str());
Writer->writeLineBreak();
int indexCount = (int)buffer->getIndexCount();
video::E_INDEX_TYPE iType = buffer->getIndexType();
const u16* idx16 = buffer->getIndices();
const u32* idx32 = (u32*) buffer->getIndices();
const int maxIndicesPerLine = 25;
for (int i=0; i<indexCount; ++i)
{
if(iType == video::EIT_16BIT)
{
core::stringw str((int)idx16[i]);
Writer->writeText(str.c_str());
}
else
{
core::stringw str((int)idx32[i]);
Writer->writeText(str.c_str());
}
if (i % maxIndicesPerLine != maxIndicesPerLine)
{
if (i % maxIndicesPerLine == maxIndicesPerLine-1)
Writer->writeLineBreak();
else
Writer->writeText(L" ");
}
}
if ((indexCount-1) % maxIndicesPerLine != maxIndicesPerLine-1)
Writer->writeLineBreak();
Writer->writeClosingTag(L"indices");
Writer->writeLineBreak();
// close buffer tag
Writer->writeClosingTag(L"buffer");
}
void CIrrMeshWriter::writeMaterial(const video::SMaterial& material)
{
// simply use irrlichts built-in attribute serialization capabilities here:
io::IAttributes* attributes =
VideoDriver->createAttributesFromMaterial(material);
if (attributes)
{
attributes->write(Writer, false, L"material");
attributes->drop();
}
}
} // end namespace
} // end namespace
#endif

View File

@ -1,63 +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 __IRR_IRR_MESH_WRITER_H_INCLUDED__
#define __IRR_IRR_MESH_WRITER_H_INCLUDED__
#include "IMeshWriter.h"
#include "S3DVertex.h"
#include "IVideoDriver.h"
#include "IFileSystem.h"
namespace irr
{
namespace io
{
class IXMLWriter;
}
namespace scene
{
class IMeshBuffer;
//! class to write meshes, implementing a IrrMesh (.irrmesh, .xml) writer
/** This writer implementation has been originally developed for irrEdit and then
merged out to the Irrlicht Engine */
class CIrrMeshWriter : public IMeshWriter
{
public:
CIrrMeshWriter(video::IVideoDriver* driver, io::IFileSystem* fs);
virtual ~CIrrMeshWriter();
//! Returns the type of the mesh writer
virtual EMESH_WRITER_TYPE getType() const;
//! writes a mesh
virtual bool writeMesh(io::IWriteFile* file, scene::IMesh* mesh, s32 flags=EMWF_NONE);
protected:
void writeBoundingBox(const core::aabbox3df& box);
void writeMeshBuffer(const scene::IMeshBuffer* buffer);
void writeMaterial(const video::SMaterial& material);
core::stringw getVectorAsStringLine(const core::vector3df& v) const;
core::stringw getVectorAsStringLine(const core::vector2df& v) const;
// member variables:
io::IFileSystem* FileSystem;
video::IVideoDriver* VideoDriver;
io::IXMLWriter* Writer;
};
} // end namespace
} // end namespace
#endif

View File

@ -1,373 +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
// This file was written by Jonas Petersen and modified by Nikolaus Gebhardt.
// See CLMTSMeshFileLoder.h for details.
/*
CLMTSMeshFileLoader.cpp
LMTSMeshFileLoader
Written by Jonas Petersen (a.k.a. jox)
Version 1.5 - 15 March 2005
Get the latest version here: http://development.mindfloaters.de/
This class allows loading meshes with lightmaps (*.lmts + *.tga files) that were created
using Pulsar LMTools by Lord Trancos (http://www.geocities.com/dxlab/index_en.html)
Notes:
- This version does not support user data in the *.lmts files, but still loads those files (by skipping the extra data).
License:
--------
It's free. You are encouraged to give me credit if you use it in your software.
Version History:
----------------
Version 1.5 - 15 March 2005
- Did a better cleanup. No memory leaks in case of an loading error.
- Added "#include <stdio.h>" for sprintf.
Version 1.4 - 12 March 2005
- Fixed bug in texture and subset loading code that would possibly cause crash.
- Fixed memory cleanup to avoid leak when loading more then one mesh
- Used the irrlicht Logger instead of cerr to output warnings and errors.
For this I had to change the constructor
from:
CLMTSMeshFileLoader(io::IFileSystem* fs, video::IVideoDriver* driver)
to:
CLMTSMeshFileLoader(IrrlichtDevice* device)
Version 1.3 - 15 February 2005
- Fixed bug that prevented loading more than one different lmts files.
- Removed unnecessary "#include <os.h>".
- Added "std::" in front of "cerr". This was necessary for Visual Studio .NET,
I hope it's not disturbing other compilers.
- Added warning message when a texture can not be loaded.
- Changed the documentation a bit (minor).
Version 1.2
- To avoid confusion I skipped version 1.2 because the website was offering
version 1.2 even though it was only version 1.1. Sorry about that.
Version 1.1 - 29 July 2004
- Added setTexturePath() function
- Minor improvements
Version 1.0 - 29 July 2004
- Initial release
*/
//////////////////////////////////////////////////////////////////////
#include "IrrCompileConfig.h"
#ifdef _IRR_COMPILE_WITH_LMTS_LOADER_
#include "SMeshBufferLightMap.h"
#include "SAnimatedMesh.h"
#include "SMeshBuffer.h"
#include "irrString.h"
#include "IReadFile.h"
#include "IAttributes.h"
#include "ISceneManager.h"
#include "CLMTSMeshFileLoader.h"
#include "os.h"
namespace irr
{
namespace scene
{
CLMTSMeshFileLoader::CLMTSMeshFileLoader(io::IFileSystem* fs,
video::IVideoDriver* driver, io::IAttributes* parameters)
: Textures(0), Subsets(0), Triangles(0),
Parameters(parameters), Driver(driver), FileSystem(fs), FlipEndianess(false)
{
#ifdef _DEBUG
setDebugName("CLMTSMeshFileLoader");
#endif
if (Driver)
Driver->grab();
if (FileSystem)
FileSystem->grab();
}
CLMTSMeshFileLoader::~CLMTSMeshFileLoader()
{
cleanup();
if (Driver)
Driver->drop();
if (FileSystem)
FileSystem->drop();
}
void CLMTSMeshFileLoader::cleanup()
{
delete [] Textures;
Textures = 0;
delete [] Subsets;
Subsets = 0;
delete [] Triangles;
Triangles = 0;
}
bool CLMTSMeshFileLoader::isALoadableFileExtension(const io::path& filename) const
{
return core::hasFileExtension ( filename, "lmts" );
}
IAnimatedMesh* CLMTSMeshFileLoader::createMesh(io::IReadFile* file)
{
u32 i;
u32 id;
// HEADER
file->read(&Header, sizeof(SLMTSHeader));
if (Header.MagicID == 0x4C4D5354)
{
FlipEndianess = true;
Header.MagicID = os::Byteswap::byteswap(Header.MagicID);
Header.Version = os::Byteswap::byteswap(Header.Version);
Header.HeaderSize = os::Byteswap::byteswap(Header.HeaderSize);
Header.TextureCount = os::Byteswap::byteswap(Header.TextureCount);
Header.SubsetCount = os::Byteswap::byteswap(Header.SubsetCount);
Header.TriangleCount = os::Byteswap::byteswap(Header.TriangleCount);
Header.SubsetSize = os::Byteswap::byteswap(Header.SubsetSize);
Header.VertexSize = os::Byteswap::byteswap(Header.VertexSize);
}
if (Header.MagicID != 0x53544D4C) { // "LMTS"
os::Printer::log("LMTS ERROR: wrong header magic id!", ELL_ERROR);
return 0;
}
//Skip any User Data (arbitrary app specific data)
const s32 userSize = Header.HeaderSize - sizeof(SLMTSHeader);
if (userSize>0)
file->seek(userSize,true);
// TEXTURES
file->read(&id, sizeof(u32));
if (FlipEndianess)
id = os::Byteswap::byteswap(id);
if (id != 0x54584554) { // "TEXT"
os::Printer::log("LMTS ERROR: wrong texture magic id!", ELL_ERROR);
return 0;
}
Textures = new SLMTSTextureInfoEntry[Header.TextureCount];
file->read(Textures, sizeof(SLMTSTextureInfoEntry)*Header.TextureCount);
if (FlipEndianess)
{
for (i=0; i<Header.TextureCount; ++i)
Textures[i].Flags = os::Byteswap::byteswap(Textures[i].Flags);
}
// SUBSETS
file->read(&id, sizeof(u32));
if (FlipEndianess)
id = os::Byteswap::byteswap(id);
if (id != 0x53425553) // "SUBS"
{
os::Printer::log("LMTS ERROR: wrong subset magic id!", ELL_ERROR);
cleanup();
return 0;
}
Subsets = new SLMTSSubsetInfoEntry[Header.SubsetCount];
const s32 subsetUserSize = Header.SubsetSize - sizeof(SLMTSSubsetInfoEntry);
for (i=0; i<Header.SubsetCount; ++i)
{
file->read(&Subsets[i], sizeof(SLMTSSubsetInfoEntry));
if (FlipEndianess)
{
Subsets[i].Offset = os::Byteswap::byteswap(Subsets[i].Offset);
Subsets[i].Count = os::Byteswap::byteswap(Subsets[i].Count);
Subsets[i].TextID1 = os::Byteswap::byteswap(Subsets[i].TextID1);
Subsets[i].TextID2 = os::Byteswap::byteswap(Subsets[i].TextID2);
}
if (subsetUserSize>0)
file->seek(subsetUserSize,true);
}
// TRIANGLES
file->read(&id, sizeof(u32));
if (FlipEndianess)
id = os::Byteswap::byteswap(id);
if (id != 0x53495254) // "TRIS"
{
os::Printer::log("LMTS ERROR: wrong triangle magic id!", ELL_ERROR);
cleanup();
return 0;
}
Triangles = new SLMTSTriangleDataEntry[(Header.TriangleCount*3)];
const s32 triUserSize = Header.VertexSize - sizeof(SLMTSTriangleDataEntry);
for (i=0; i<(Header.TriangleCount*3); ++i)
{
file->read(&Triangles[i], sizeof(SLMTSTriangleDataEntry));
if (FlipEndianess)
{
Triangles[i].X = os::Byteswap::byteswap(Triangles[i].X);
Triangles[i].Y = os::Byteswap::byteswap(Triangles[i].Y);
Triangles[i].Z = os::Byteswap::byteswap(Triangles[i].Z);
Triangles[i].U1 = os::Byteswap::byteswap(Triangles[i].U1);
Triangles[i].V1 = os::Byteswap::byteswap(Triangles[i].U2);
Triangles[i].U2 = os::Byteswap::byteswap(Triangles[i].V1);
Triangles[i].V2 = os::Byteswap::byteswap(Triangles[i].V2);
}
if (triUserSize>0)
file->seek(triUserSize,true);
}
/////////////////////////////////////////////////////////////////
SMesh* mesh = new SMesh();
constructMesh(mesh);
loadTextures(mesh);
cleanup();
SAnimatedMesh* am = new SAnimatedMesh();
am->Type = EAMT_LMTS; // not unknown to irrlicht anymore
am->addMesh(mesh);
am->recalculateBoundingBox();
mesh->drop();
return am;
}
void CLMTSMeshFileLoader::constructMesh(SMesh* mesh)
{
for (s32 i=0; i<Header.SubsetCount; ++i)
{
scene::SMeshBufferLightMap* meshBuffer = new scene::SMeshBufferLightMap();
// EMT_LIGHTMAP_M2/EMT_LIGHTMAP_M4 also possible
meshBuffer->Material.MaterialType = video::EMT_LIGHTMAP;
meshBuffer->Material.Wireframe = false;
meshBuffer->Material.Lighting = false;
mesh->addMeshBuffer(meshBuffer);
const u32 offs = Subsets[i].Offset * 3;
for (u32 sc=0; sc<Subsets[i].Count; sc++)
{
const u32 idx = meshBuffer->getVertexCount();
for (u32 vu=0; vu<3; ++vu)
{
const SLMTSTriangleDataEntry& v = Triangles[offs+(3*sc)+vu];
meshBuffer->Vertices.push_back(
video::S3DVertex2TCoords(
v.X, v.Y, v.Z,
video::SColor(255,255,255,255),
v.U1, v.V1, v.U2, v.V2));
}
const core::vector3df normal = core::plane3df(
meshBuffer->Vertices[idx].Pos,
meshBuffer->Vertices[idx+1].Pos,
meshBuffer->Vertices[idx+2].Pos).Normal;
meshBuffer->Vertices[idx].Normal = normal;
meshBuffer->Vertices[idx+1].Normal = normal;
meshBuffer->Vertices[idx+2].Normal = normal;
meshBuffer->Indices.push_back(idx);
meshBuffer->Indices.push_back(idx+1);
meshBuffer->Indices.push_back(idx+2);
}
meshBuffer->drop();
}
for (u32 j=0; j<mesh->MeshBuffers.size(); ++j)
mesh->MeshBuffers[j]->recalculateBoundingBox();
mesh->recalculateBoundingBox();
}
void CLMTSMeshFileLoader::loadTextures(SMesh* mesh)
{
if (!Driver || !FileSystem)
return;
// load textures
// a little too much space, but won't matter here
core::array<video::ITexture*> tex;
tex.reallocate(Header.TextureCount);
core::array<video::ITexture*> lig;
lig.reallocate(Header.TextureCount);
core::array<u32> id2id;
id2id.reallocate(Header.TextureCount);
const core::stringc Path = Parameters->getAttributeAsString(LMTS_TEXTURE_PATH);
core::stringc s;
for (u32 t=0; t<Header.TextureCount; ++t)
{
video::ITexture* tmptex = 0;
s = Path;
s.append(Textures[t].Filename);
if (FileSystem->existFile(s))
tmptex = Driver->getTexture(s);
else
os::Printer::log("LMTS WARNING: Texture does not exist", s.c_str(), ELL_WARNING);
if (Textures[t].Flags & 0x01)
{
id2id.push_back(lig.size());
lig.push_back(tmptex);
}
else
{
id2id.push_back(tex.size());
tex.push_back(tmptex);
}
}
// attach textures to materials.
for (u32 i=0; i<Header.SubsetCount; ++i)
{
if (Subsets[i].TextID1 < Header.TextureCount && id2id[Subsets[i].TextID1] < tex.size())
mesh->getMeshBuffer(i)->getMaterial().setTexture(0, tex[id2id[Subsets[i].TextID1]]);
if (Subsets[i].TextID2 < Header.TextureCount && id2id[Subsets[i].TextID2] < lig.size())
mesh->getMeshBuffer(i)->getMaterial().setTexture(1, lig[id2id[Subsets[i].TextID2]]);
if (!mesh->getMeshBuffer(i)->getMaterial().getTexture(1))
mesh->getMeshBuffer(i)->getMaterial().MaterialType = video::EMT_SOLID;
}
}
} // end namespace scene
} // end namespace irr
#endif // _IRR_COMPILE_WITH_LMTS_LOADER_

View File

@ -1,109 +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
//
// I (Nikolaus Gebhardt) did some few changes to Jonas Petersen's original loader:
// - removed setTexturePath() and replaced with the ISceneManager::getStringParameter()-stuff.
// - added EAMT_LMTS enumeration value
// Thanks a lot to Jonas Petersen for his work
// on this and that he gave me his permission to add it into Irrlicht.
/*
CLMTSMeshFileLoader.h
LMTSMeshFileLoader
Written by Jonas Petersen (a.k.a. jox)
Version 1.5 - 15 March 2005
*/
#if !defined(__C_LMTS_MESH_FILE_LOADER_H_INCLUDED__)
#define __C_LMTS_MESH_FILE_LOADER_H_INCLUDED__
#include "IMeshLoader.h"
#include "SMesh.h"
#include "IFileSystem.h"
#include "IVideoDriver.h"
namespace irr
{
namespace scene
{
class CLMTSMeshFileLoader : public IMeshLoader
{
public:
CLMTSMeshFileLoader(io::IFileSystem* fs,
video::IVideoDriver* driver, io::IAttributes* parameters);
virtual ~CLMTSMeshFileLoader();
virtual bool isALoadableFileExtension(const io::path& filename) const;
virtual IAnimatedMesh* createMesh(io::IReadFile* file);
private:
void constructMesh(SMesh* mesh);
void loadTextures(SMesh* mesh);
void cleanup();
// byte-align structures
#include "irrpack.h"
struct SLMTSHeader
{
u32 MagicID;
u32 Version;
u32 HeaderSize;
u16 TextureCount;
u16 SubsetCount;
u32 TriangleCount;
u16 SubsetSize;
u16 VertexSize;
} PACK_STRUCT;
struct SLMTSTextureInfoEntry
{
c8 Filename[256];
u16 Flags;
} PACK_STRUCT;
struct SLMTSSubsetInfoEntry
{
u32 Offset;
u32 Count;
u16 TextID1;
u16 TextID2;
} PACK_STRUCT;
struct SLMTSTriangleDataEntry
{
f32 X;
f32 Y;
f32 Z;
f32 U1;
f32 V1;
f32 U2;
f32 V2;
} PACK_STRUCT;
// Default alignment
#include "irrunpack.h"
SLMTSHeader Header;
SLMTSTextureInfoEntry* Textures;
SLMTSSubsetInfoEntry* Subsets;
SLMTSTriangleDataEntry* Triangles;
io::IAttributes* Parameters;
video::IVideoDriver* Driver;
io::IFileSystem* FileSystem;
bool FlipEndianess;
};
} // end namespace scene
} // end namespace irr
#endif // !defined(__C_LMTS_MESH_FILE_LOADER_H_INCLUDED__)

File diff suppressed because it is too large Load Diff

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_LWO_MESH_FILE_LOADER_H_INCLUDED__
#define __C_LWO_MESH_FILE_LOADER_H_INCLUDED__
#include "IMeshLoader.h"
#include "SMeshBuffer.h"
#include "irrString.h"
namespace irr
{
namespace io
{
class IReadFile;
class IFileSystem;
} // end namespace io
namespace scene
{
struct SMesh;
class ISceneManager;
//! Meshloader capable of loading Lightwave 3D meshes.
class CLWOMeshFileLoader : public IMeshLoader
{
public:
//! Constructor
CLWOMeshFileLoader(scene::ISceneManager* smgr, io::IFileSystem* fs);
//! destructor
virtual ~CLWOMeshFileLoader();
//! returns true if the file maybe is able to be loaded by this class
//! based on the file extension (e.g. ".bsp")
virtual bool isALoadableFileExtension(const io::path& filename) const;
//! creates/loads an animated mesh from the file.
//! \return Pointer to the created mesh. Returns 0 if loading failed.
//! If you no longer need the mesh, you should call IAnimatedMesh::drop().
//! See IUnknown::drop() for more information.
virtual IAnimatedMesh* createMesh(io::IReadFile* file);
private:
struct tLWOMaterial;
bool readFileHeader();
bool readChunks();
void readObj1(u32 size);
void readTagMapping(u32 size);
void readVertexMapping(u32 size);
void readDiscVertexMapping (u32 size);
void readObj2(u32 size);
void readMat(u32 size);
u32 readString(core::stringc& name, u32 size=0);
u32 readVec(core::vector3df& vec);
u32 readVX(u32& num);
u32 readColor(video::SColor& color);
video::ITexture* loadTexture(const core::stringc& file);
scene::ISceneManager* SceneManager;
io::IFileSystem* FileSystem;
io::IReadFile* File;
SMesh* Mesh;
core::array<core::vector3df> Points;
core::array<core::array<u32> > Indices;
core::array<core::stringc> UvName;
core::array<core::array<u32> > UvIndex;
core::array<core::stringc> DUvName;
core::array<core::array<u32> > VmPolyPointsIndex;
core::array<core::array<core::vector2df> > VmCoordsIndex;
core::array<u16> MaterialMapping;
core::array<core::array<core::vector2df> > TCoords;
core::array<tLWOMaterial*> Materials;
core::array<core::stringc> Images;
u8 FormatVersion;
};
} // end namespace scene
} // end namespace irr
#endif

View File

@ -1,364 +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 "IrrCompileConfig.h"
#ifdef _IRR_COMPILE_WITH_MD2_LOADER_
#include "CMD2MeshFileLoader.h"
#include "CAnimatedMeshMD2.h"
#include "os.h"
namespace irr
{
namespace scene
{
// structs needed to load the md2-format
const s32 MD2_MAGIC_NUMBER = 844121161;
const s32 MD2_VERSION = 8;
const s32 MD2_MAX_VERTS = 2048;
// byte-align structures
#include "irrpack.h"
struct SMD2Header
{
s32 magic; // four character code "IDP2"
s32 version; // must be 8
s32 skinWidth; // width of the texture
s32 skinHeight; // height of the texture
s32 frameSize; // size in bytes of an animation frame
s32 numSkins; // number of textures
s32 numVertices; // total number of vertices
s32 numTexcoords; // number of vertices with texture coords
s32 numTriangles; // number of triangles
s32 numGlCommands; // number of opengl commands (triangle strip or triangle fan)
s32 numFrames; // animation keyframe count
s32 offsetSkins; // offset in bytes to 64 character skin names
s32 offsetTexcoords; // offset in bytes to texture coordinate list
s32 offsetTriangles; // offset in bytes to triangle list
s32 offsetFrames; // offset in bytes to frame list
s32 offsetGlCommands;// offset in bytes to opengl commands
s32 offsetEnd; // offset in bytes to end of file
} PACK_STRUCT;
struct SMD2Vertex
{
u8 vertex[3]; // [0] = X, [1] = Z, [2] = Y
u8 lightNormalIndex; // index in the normal table
} PACK_STRUCT;
struct SMD2Frame
{
f32 scale[3]; // first scale the vertex position
f32 translate[3]; // then translate the position
c8 name[16]; // the name of the animation that this key belongs to
SMD2Vertex vertices[1]; // vertex 1 of SMD2Header.numVertices
} PACK_STRUCT;
struct SMD2Triangle
{
u16 vertexIndices[3];
u16 textureIndices[3];
} PACK_STRUCT;
struct SMD2TextureCoordinate
{
s16 s;
s16 t;
} PACK_STRUCT;
struct SMD2GLCommand
{
f32 s, t;
s32 vertexIndex;
} PACK_STRUCT;
// Default alignment
#include "irrunpack.h"
//! Constructor
CMD2MeshFileLoader::CMD2MeshFileLoader()
{
#ifdef _DEBUG
setDebugName("CMD2MeshFileLoader");
#endif
}
//! returns true if the file maybe is able to be loaded by this class
//! based on the file extension (e.g. ".bsp")
bool CMD2MeshFileLoader::isALoadableFileExtension(const io::path& filename) const
{
return core::hasFileExtension ( filename, "md2" );
}
//! creates/loads an animated mesh from the file.
//! \return Pointer to the created mesh. Returns 0 if loading failed.
//! If you no longer need the mesh, you should call IAnimatedMesh::drop().
//! See IReferenceCounted::drop() for more information.
IAnimatedMesh* CMD2MeshFileLoader::createMesh(io::IReadFile* file)
{
IAnimatedMesh* msh = new CAnimatedMeshMD2();
if (msh)
{
if (loadFile(file, (CAnimatedMeshMD2*)msh) )
return msh;
msh->drop();
}
return 0;
}
//! loads an md2 file
bool CMD2MeshFileLoader::loadFile(io::IReadFile* file, CAnimatedMeshMD2* mesh)
{
if (!file)
return false;
SMD2Header header;
file->read(&header, sizeof(SMD2Header));
#ifdef __BIG_ENDIAN__
header.magic = os::Byteswap::byteswap(header.magic);
header.version = os::Byteswap::byteswap(header.version);
header.skinWidth = os::Byteswap::byteswap(header.skinWidth);
header.skinHeight = os::Byteswap::byteswap(header.skinHeight);
header.frameSize = os::Byteswap::byteswap(header.frameSize);
header.numSkins = os::Byteswap::byteswap(header.numSkins);
header.numVertices = os::Byteswap::byteswap(header.numVertices);
header.numTexcoords = os::Byteswap::byteswap(header.numTexcoords);
header.numTriangles = os::Byteswap::byteswap(header.numTriangles);
header.numGlCommands = os::Byteswap::byteswap(header.numGlCommands);
header.numFrames = os::Byteswap::byteswap(header.numFrames);
header.offsetSkins = os::Byteswap::byteswap(header.offsetSkins);
header.offsetTexcoords = os::Byteswap::byteswap(header.offsetTexcoords);
header.offsetTriangles = os::Byteswap::byteswap(header.offsetTriangles);
header.offsetFrames = os::Byteswap::byteswap(header.offsetFrames);
header.offsetGlCommands = os::Byteswap::byteswap(header.offsetGlCommands);
header.offsetEnd = os::Byteswap::byteswap(header.offsetEnd);
#endif
if (header.magic != MD2_MAGIC_NUMBER || header.version != MD2_VERSION)
{
os::Printer::log("MD2 Loader: Wrong file header", file->getFileName(), ELL_WARNING);
return false;
}
//
// prepare mesh and allocate memory
//
mesh->FrameCount = header.numFrames;
// create keyframes
mesh->FrameTransforms.set_used(header.numFrames);
// create vertex arrays for each keyframe
if (mesh->FrameList)
delete [] mesh->FrameList;
mesh->FrameList = new core::array<CAnimatedMeshMD2::SMD2Vert>[header.numFrames];
// allocate space in vertex arrays
s32 i;
for (i=0; i<header.numFrames; ++i)
mesh->FrameList[i].reallocate(header.numVertices);
// allocate interpolation buffer vertices
mesh->InterpolationBuffer->Vertices.set_used(header.numTriangles*3);
// populate triangles
mesh->InterpolationBuffer->Indices.reallocate(header.numTriangles*3);
const s32 count = header.numTriangles*3;
for (i=0; i<count; i+=3)
{
mesh->InterpolationBuffer->Indices.push_back(i);
mesh->InterpolationBuffer->Indices.push_back(i+1);
mesh->InterpolationBuffer->Indices.push_back(i+2);
}
//
// read texture coordinates
//
file->seek(header.offsetTexcoords);
SMD2TextureCoordinate* textureCoords = new SMD2TextureCoordinate[header.numTexcoords];
if (!file->read(textureCoords, sizeof(SMD2TextureCoordinate)*header.numTexcoords))
{
delete[] textureCoords;
os::Printer::log("MD2 Loader: Error reading TextureCoords.", file->getFileName(), ELL_ERROR);
return false;
}
#ifdef __BIG_ENDIAN__
for (i=0; i<header.numTexcoords; ++i)
{
textureCoords[i].s = os::Byteswap::byteswap(textureCoords[i].s);
textureCoords[i].t = os::Byteswap::byteswap(textureCoords[i].t);
}
#endif
// read Triangles
file->seek(header.offsetTriangles);
SMD2Triangle *triangles = new SMD2Triangle[header.numTriangles];
if (!file->read(triangles, header.numTriangles *sizeof(SMD2Triangle)))
{
delete[] triangles;
delete[] textureCoords;
os::Printer::log("MD2 Loader: Error reading triangles.", file->getFileName(), ELL_ERROR);
return false;
}
#ifdef __BIG_ENDIAN__
for (i=0; i<header.numTriangles; ++i)
{
triangles[i].vertexIndices[0] = os::Byteswap::byteswap(triangles[i].vertexIndices[0]);
triangles[i].vertexIndices[1] = os::Byteswap::byteswap(triangles[i].vertexIndices[1]);
triangles[i].vertexIndices[2] = os::Byteswap::byteswap(triangles[i].vertexIndices[2]);
triangles[i].textureIndices[0] = os::Byteswap::byteswap(triangles[i].textureIndices[0]);
triangles[i].textureIndices[1] = os::Byteswap::byteswap(triangles[i].textureIndices[1]);
triangles[i].textureIndices[2] = os::Byteswap::byteswap(triangles[i].textureIndices[2]);
}
#endif
// read Vertices
u8 buffer[MD2_MAX_VERTS*4+128];
SMD2Frame* frame = (SMD2Frame*)buffer;
file->seek(header.offsetFrames);
for (i = 0; i<header.numFrames; ++i)
{
// read vertices
file->read(frame, header.frameSize);
#ifdef __BIG_ENDIAN__
frame->scale[0] = os::Byteswap::byteswap(frame->scale[0]);
frame->scale[1] = os::Byteswap::byteswap(frame->scale[1]);
frame->scale[2] = os::Byteswap::byteswap(frame->scale[2]);
frame->translate[0] = os::Byteswap::byteswap(frame->translate[0]);
frame->translate[1] = os::Byteswap::byteswap(frame->translate[1]);
frame->translate[2] = os::Byteswap::byteswap(frame->translate[2]);
#endif
//
// store frame data
//
CAnimatedMeshMD2::SAnimationData adata;
adata.begin = i;
adata.end = i;
adata.fps = 7;
// Add new named animation if necessary
if (frame->name[0])
{
// get animation name
for (s32 s = 0; s < 16 && frame->name[s]!=0 && (frame->name[s] < '0' || frame->name[s] > '9'); ++s)
{
adata.name += frame->name[s];
}
// Does this keyframe have the same animation name as the current animation?
if (!mesh->AnimationData.empty() && mesh->AnimationData[mesh->AnimationData.size()-1].name == adata.name)
{
// Increase the length of the animation
++mesh->AnimationData[mesh->AnimationData.size() - 1].end;
}
else
{
// Add the new animation
mesh->AnimationData.push_back(adata);
}
}
// save keyframe scale and translation
mesh->FrameTransforms[i].scale.X = frame->scale[0];
mesh->FrameTransforms[i].scale.Z = frame->scale[1];
mesh->FrameTransforms[i].scale.Y = frame->scale[2];
mesh->FrameTransforms[i].translate.X = frame->translate[0];
mesh->FrameTransforms[i].translate.Z = frame->translate[1];
mesh->FrameTransforms[i].translate.Y = frame->translate[2];
// add vertices
for (s32 j=0; j<header.numTriangles; ++j)
{
for (u32 ti=0; ti<3; ++ti)
{
CAnimatedMeshMD2::SMD2Vert v;
u32 num = triangles[j].vertexIndices[ti];
v.Pos.X = frame->vertices[num].vertex[0];
v.Pos.Z = frame->vertices[num].vertex[1];
v.Pos.Y = frame->vertices[num].vertex[2];
v.NormalIdx = frame->vertices[num].lightNormalIndex;
mesh->FrameList[i].push_back(v);
}
}
// calculate bounding boxes
if (header.numVertices)
{
core::aabbox3d<f32> box;
core::vector3df pos;
pos.X = f32(mesh->FrameList[i] [0].Pos.X) * mesh->FrameTransforms[i].scale.X + mesh->FrameTransforms[i].translate.X;
pos.Y = f32(mesh->FrameList[i] [0].Pos.Y) * mesh->FrameTransforms[i].scale.Y + mesh->FrameTransforms[i].translate.Y;
pos.Z = f32(mesh->FrameList[i] [0].Pos.Z) * mesh->FrameTransforms[i].scale.Z + mesh->FrameTransforms[i].translate.Z;
box.reset(pos);
for (s32 j=1; j<header.numTriangles*3; ++j)
{
pos.X = f32(mesh->FrameList[i] [j].Pos.X) * mesh->FrameTransforms[i].scale.X + mesh->FrameTransforms[i].translate.X;
pos.Y = f32(mesh->FrameList[i] [j].Pos.Y) * mesh->FrameTransforms[i].scale.Y + mesh->FrameTransforms[i].translate.Y;
pos.Z = f32(mesh->FrameList[i] [j].Pos.Z) * mesh->FrameTransforms[i].scale.Z + mesh->FrameTransforms[i].translate.Z;
box.addInternalPoint(pos);
}
mesh->BoxList.push_back(box);
}
}
// populate interpolation buffer with texture coordinates and colors
if (header.numFrames)
{
f32 dmaxs = 1.0f/(header.skinWidth);
f32 dmaxt = 1.0f/(header.skinHeight);
for (s32 t=0; t<header.numTriangles; ++t)
{
for (s32 n=0; n<3; ++n)
{
mesh->InterpolationBuffer->Vertices[t*3 + n].TCoords.X = (textureCoords[triangles[t].textureIndices[n]].s + 0.5f) * dmaxs;
mesh->InterpolationBuffer->Vertices[t*3 + n].TCoords.Y = (textureCoords[triangles[t].textureIndices[n]].t + 0.5f) * dmaxt;
mesh->InterpolationBuffer->Vertices[t*3 + n].Color = video::SColor(255,255,255,255);
}
}
}
// clean up
delete [] triangles;
delete [] textureCoords;
// init buffer with start frame.
mesh->getMesh(0);
return true;
}
} // end namespace scene
} // end namespace irr
#endif // _IRR_COMPILE_WITH_MD2_LOADER_

View File

@ -1,45 +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_MD2_MESH_FILE_LOADER_H_INCLUDED__
#define __C_MD2_MESH_FILE_LOADER_H_INCLUDED__
#include "IMeshLoader.h"
namespace irr
{
namespace scene
{
class CAnimatedMeshMD2;
//! Meshloader capable of loading MD2 files
class CMD2MeshFileLoader : public IMeshLoader
{
public:
//! Constructor
CMD2MeshFileLoader();
//! returns true if the file maybe is able to be loaded by this class
//! based on the file extension (e.g. ".bsp")
virtual bool isALoadableFileExtension(const io::path& filename) const;
//! creates/loads an animated mesh from the file.
//! \return Pointer to the created mesh. Returns 0 if loading failed.
//! If you no longer need the mesh, you should call IAnimatedMesh::drop().
//! See IReferenceCounted::drop() for more information.
virtual IAnimatedMesh* createMesh(io::IReadFile* file);
private:
//! Loads the file data into the mesh
bool loadFile(io::IReadFile* file, CAnimatedMeshMD2* mesh);
};
} // end namespace scene
} // end namespace irr
#endif // __C_MD2_MESH_LOADER_H_INCLUDED__

View File

@ -1,53 +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 "IrrCompileConfig.h"
#ifdef _IRR_COMPILE_WITH_MD3_LOADER_
#include "CMD3MeshFileLoader.h"
#include "CAnimatedMeshMD3.h"
#include "irrString.h"
namespace irr
{
namespace scene
{
//! Constructor
CMD3MeshFileLoader::CMD3MeshFileLoader( scene::ISceneManager* smgr)
: SceneManager(smgr)
{
}
//! destructor
CMD3MeshFileLoader::~CMD3MeshFileLoader()
{
}
//! returns true if the file maybe is able to be loaded by this class
//! based on the file extension (e.g. ".bsp")
bool CMD3MeshFileLoader::isALoadableFileExtension(const io::path& filename) const
{
return core::hasFileExtension ( filename, "md3" );
}
IAnimatedMesh* CMD3MeshFileLoader::createMesh(io::IReadFile* file)
{
CAnimatedMeshMD3 * mesh = new CAnimatedMeshMD3();
if ( mesh->loadModelFile ( 0, file, SceneManager->getFileSystem(), SceneManager->getVideoDriver() ) )
return mesh;
mesh->drop ();
return 0;
}
} // end namespace scene
} // end namespace irr
#endif // _IRR_COMPILE_WITH_MD3_LOADER_

View File

@ -1,49 +0,0 @@
// Copyright (C) 2002-2012 Nikolaus Gebhardt / Thomas Alten
// This file is part of the "Irrlicht Engine".
// For conditions of distribution and use, see copyright notice in irrlicht.h
#ifndef __C_MD3_MESH_FILE_LOADER_H_INCLUDED__
#define __C_MD3_MESH_FILE_LOADER_H_INCLUDED__
#include "IMeshLoader.h"
#include "IFileSystem.h"
#include "IVideoDriver.h"
#include "ISceneManager.h"
#include "IQ3Shader.h"
namespace irr
{
namespace scene
{
//! Meshloader capable of loading md3 files.
class CMD3MeshFileLoader : public IMeshLoader
{
public:
//! Constructor
CMD3MeshFileLoader( scene::ISceneManager* smgr );
//! destructor
virtual ~CMD3MeshFileLoader();
//! returns true if the file maybe is able to be loaded by this class
//! based on the file extension (e.g. ".bsp")
virtual bool isALoadableFileExtension(const io::path& filename) const;
//! creates/loads an animated mesh from the file.
//! \return Pointer to the created mesh. Returns 0 if loading failed.
//! If you no longer need the mesh, you should call IAnimatedMesh::drop().
//! See IReferenceCounted::drop() for more information.
virtual IAnimatedMesh* createMesh(io::IReadFile* file);
private:
scene::ISceneManager* SceneManager;
};
} // end namespace scene
} // end namespace irr
#endif

View File

@ -1,447 +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
//
// This file was originally written by ZDimitor.
//----------------------------------------------------------------------
// somefuncs.h - part of the My3D Tools
//
// This tool was created by Zhuck Dmitry (ZDimitor).
// Everyone can use it as wants ( i'll be happy if it helps to someone :) ).
//----------------------------------------------------------------------
//**********************************************************************
// some useful functions
//**********************************************************************
#ifndef __C_MY3D_HELPER_H_INCLUDED__
#define __C_MY3D_HELPER_H_INCLUDED__
#include <irrTypes.h>
namespace irr
{
namespace scene
{
//**********************************************************************
// MY3D stuff
//**********************************************************************
// byte-align structures
#include "irrpack.h"
struct SMyVector3
{ SMyVector3 () {;}
SMyVector3 (f32 __X, f32 __Y, f32 __Z)
: X(__X), Y(__Y), Z(__Z) {}
f32 X, Y, Z;
} PACK_STRUCT;
struct SMyVector2
{ SMyVector2 () {;}
SMyVector2(f32 __X, f32 __Y)
: X(__X), Y(__Y) {}
f32 X, Y;
} PACK_STRUCT;
struct SMyVertex
{ SMyVertex () {;}
SMyVertex (SMyVector3 _Coord, SMyColor _Color, SMyVector3 _Normal)
:Coord(_Coord), Color(_Color), Normal(_Normal) {;}
SMyVector3 Coord;
SMyColor Color;
SMyVector3 Normal;
} PACK_STRUCT;
struct SMyTVertex
{ SMyTVertex () {;}
SMyTVertex (SMyVector2 _TCoord)
: TCoord(_TCoord) {;}
SMyVector2 TCoord;
} PACK_STRUCT;
struct SMyFace
{ SMyFace() {;}
SMyFace(u32 __A, u32 __B, u32 __C)
: A(__A), B(__B), C(__C) {}
u32 A, B, C;
} PACK_STRUCT;
// file header (6 bytes)
struct SMyFileHeader
{ u32 MyId; // MY3D
u16 Ver; // Version
} PACK_STRUCT;
// scene header
struct SMySceneHeader
{ SMyColor BackgrColor; // background color
SMyColor AmbientColor; // ambient color
s32 MaterialCount; // material count
s32 MeshCount; // mesh count
} PACK_STRUCT;
// mesh header
struct SMyMeshHeader
{ c8 Name[256]; // material name
u32 MatIndex; // index of the mesh material
u32 TChannelCnt; // mesh mapping channels count
} PACK_STRUCT;
// texture data header
struct SMyTexDataHeader
{ c8 Name[256]; // texture name
u32 ComprMode; //compression mode
u32 PixelFormat;
u32 Width; // image width
u32 Height; // image height
} PACK_STRUCT;
// pixel color 24bit (R8G8B8)
struct SMyPixelColor24
{ SMyPixelColor24() {;}
SMyPixelColor24(u8 __r, u8 __g, u8 __b)
: r(__r), g(__g), b(__b) {}
u8 r, g, b;
} PACK_STRUCT;
// pixel color 16bit (A1R5G5B5)
struct SMyPixelColor16
{ SMyPixelColor16() {;}
SMyPixelColor16(s16 _argb): argb(_argb) {;}
SMyPixelColor16(u8 r, u8 g, u8 b)
{ argb = ((r&0x1F)<<10) | ((g&0x1F)<<5) | (b&0x1F);
}
s16 argb;
} PACK_STRUCT;
// RLE Header
struct SMyRLEHeader
{ SMyRLEHeader() {}
u32 nEncodedBytes;
u32 nDecodedBytes;
} PACK_STRUCT;
// Default alignment
#include "irrunpack.h"
} // end namespace
} // end namespace
//-----------------------------------------------------------------------------
namespace irr
{
namespace core
{
//-----------------RLE stuff-----------------------------------------
int rle_encode (
unsigned char *in_buf, int in_buf_size,
unsigned char *out_buf, int out_buf_size
);
unsigned long process_comp(
unsigned char *buf, int buf_size,
unsigned char *out_buf, int out_buf_size
);
void process_uncomp(
unsigned char, unsigned char *out_buf, int out_buf_size
);
void flush_outbuf(
unsigned char *out_buf, int out_buf_size
);
unsigned long get_byte (
unsigned char *ch,
unsigned char *in_buf, int in_buf_size,
unsigned char *out_buf, int out_buf_size
);
void put_byte(
unsigned char ch, unsigned char *out_buf, int out_buf_size
);
//-----------------------------------------------------------
const unsigned long LIMIT = 1; // was #define LIMIT 1
const unsigned long NON_MATCH = 2; // was: #define NON_MATCH 2
const unsigned long EOD_FOUND = 3; // was: #define EOD_FOUND 3
const unsigned long EOD = 0x00454f44; // was: #define EOD 'EOD'
//-----------------------------------------------------------
// number of decoded bytes
static int nDecodedBytes=0;
// number of coded bytes
static int nCodedBytes=0;
// number of read bytes
static int nReadedBytes=0;
// table used to look for sequences of repeating bytes
static unsigned char tmpbuf[4]; // we use subscripts 1 - 3
static int tmpbuf_cnt;
// output buffer for non-compressed output data
static unsigned char outbuf[128];
static int outbuf_cnt;
//-----------------------------------------------------------
int rle_encode (
unsigned char *in_buf, int in_buf_size,
unsigned char *out_buf, int out_buf_size
)
{
unsigned long ret_code;
unsigned char ch;
nCodedBytes=0;
nReadedBytes=0;
tmpbuf_cnt = 0; // no. of char's in tmpbuf
outbuf_cnt = 0; // no. of char's in outbuf
while (1)
{
if (get_byte(&ch, in_buf, in_buf_size,
out_buf, out_buf_size) == (int)EOD) // read next byte into ch
break;
tmpbuf[++tmpbuf_cnt] = (unsigned char) ch;
if (tmpbuf_cnt == 3)
{
// see if all 3 match each other
if ((tmpbuf[1] == tmpbuf[2]) && (tmpbuf[2] == tmpbuf[3]))
{
// they do - add compression
// this will process all bytes in input file until
// a non-match occurs, or 128 bytes are processed,
// or we find eod */
ret_code = process_comp(in_buf, in_buf_size, out_buf, out_buf_size);
if (ret_code == (int)EOD_FOUND)
break; // stop compressing
if (ret_code == (int)NON_MATCH)
tmpbuf_cnt=1; /* save the char that didn't match */
else
// we just compressed the max. of 128 bytes
tmpbuf_cnt=0; /* start over for next chunk */
}
else
{
// we know the first byte doesn't match 2 or more
// others, so just send it out as uncompressed. */
process_uncomp(tmpbuf[1], out_buf, out_buf_size);
// see if the last 2 bytes in the buffer match
if (tmpbuf[2] == tmpbuf[3])
{
// move byte 3 to position 1 and pretend we just
// have 2 bytes -- note that the first byte was
// already sent to output */
tmpbuf[1]=tmpbuf[3];
tmpbuf_cnt=2;
}
else
{
// send byte 2 and keep byte 3 - it may match the
// next byte. Move byte 3 to position 1 and set
// count to 1. Note that the first byte was
// already sent to output
process_uncomp(tmpbuf[2], out_buf, out_buf_size);
tmpbuf[1]=tmpbuf[3];
tmpbuf_cnt=1;
}
}
}
} // end while
flush_outbuf(out_buf, out_buf_size);
return nCodedBytes;
}
//------------------------------------------------------------------
// This flushes any non-compressed data not yet sent, then it processes
// repeating bytes until > 128, or EOD, or non-match.
// return values: LIMIT, EOD_FOUND, NON_MATCH
// Prior to ANY return, it writes out the 2 byte compressed code.
// If a NON_MATCH was found, this returns with the non-matching char
// residing in tmpbuf[0].
// Inputs: tmpbuf[0], input file
// Outputs: tmpbuf[0] (sometimes), output file, and return code
//------------------------------------------------------------------
unsigned long process_comp(
unsigned char *buf, int buf_size,
unsigned char *out_buf, int out_buf_size)
{
// we start out with 3 repeating bytes
register int len = 3;
unsigned char ch;
// we're starting a repeating chunk - end the non-repeaters
flush_outbuf(out_buf, out_buf_size);
while (get_byte(&ch, buf, buf_size, out_buf, out_buf_size) != (int)EOD)
{
if (ch != tmpbuf[1])
{
// send no. of repeated bytes to be encoded
put_byte((unsigned char)((--len) | 0x80), out_buf, out_buf_size);
// send the byte's value being repeated
put_byte((unsigned char)tmpbuf[1], out_buf, out_buf_size);
/* save the non-matching character just read */
tmpbuf[1]=(unsigned char) ch;
return NON_MATCH;
}
/* we know the new byte is part of the repeating seq */
len++;
if (len == 128)
{
// send no. of repeated bytes to be encoded
put_byte((unsigned char)((--len) | 0x80), out_buf, out_buf_size);
// send the byte's value being repeated
put_byte((unsigned char)tmpbuf[1], out_buf, out_buf_size);
return LIMIT;
}
} // end while
// if flow comes here, we just read an EOD
// send no. of repeated bytes to be encoded
put_byte((unsigned char)((--len) | 0x80), out_buf, out_buf_size);
// send the byte's value being repeated
put_byte((unsigned char)tmpbuf[1], out_buf, out_buf_size);
return EOD_FOUND;
}
//----------------------------------------------------------------
// This adds 1 non-repeating byte to outbuf. If outbuf becomes full
// with 128 bytes, it flushes outbuf.
// There are no return codes and no bytes are read from the input.
//----------------------------------------------------------------
void process_uncomp(
unsigned char char1, unsigned char *out_buf, int out_buf_size
)
{
outbuf[outbuf_cnt++] = char1;
if (outbuf_cnt == 128)
flush_outbuf(out_buf, out_buf_size);
}
//-----------------------------------------------------------
// This flushes any non-compressed data not yet sent.
// On exit, outbuf_cnt will equal zero.
//-----------------------------------------------------------
void flush_outbuf(unsigned char *out_buf, int out_buf_size)
{
register int pos=0;
if(!outbuf_cnt)
return; // nothing to do */
// send no. of unencoded bytes to be sent
put_byte((unsigned char)(outbuf_cnt - 1), out_buf, out_buf_size);
for ( ; outbuf_cnt; outbuf_cnt--)
put_byte((unsigned char)outbuf[pos++], out_buf, out_buf_size);
}
//---------------------------------------------------
void put_byte(unsigned char ch, unsigned char *out_buf, int out_buf_size)
{
if (nCodedBytes<=(out_buf_size-1))
{ out_buf[nCodedBytes++]=ch;
out_buf[nCodedBytes]=0;
}
}
//---------------------------------------------------
// This reads the next byte into ch. It returns EOD
// at end-of-data
//---------------------------------------------------
unsigned long get_byte(
unsigned char *ch,
unsigned char *in_buf, int in_buf_size,
unsigned char *out_buf, int out_buf_size
)
{
if (nReadedBytes>=in_buf_size)
{
// there are either 0, 1, or 2 char's to write before we quit
if (tmpbuf_cnt == 1)
process_uncomp(tmpbuf[1], out_buf, out_buf_size);
else
{
if (tmpbuf_cnt == 2)
{
process_uncomp(tmpbuf[1], out_buf, out_buf_size);
process_uncomp(tmpbuf[2], out_buf, out_buf_size);
}
}
nReadedBytes =0;
return EOD;
}
(*ch) = (unsigned char)in_buf[nReadedBytes++];
return 0;
}
//-----------------------------------------------------------
int rle_decode (
unsigned char *in_buf, int in_buf_size,
unsigned char *out_buf, int out_buf_size
)
{
nDecodedBytes=0;
nReadedBytes=0;
int ch, i;
while (1)
{
if (nReadedBytes>=in_buf_size)
break;
else
ch=in_buf[nReadedBytes];
nReadedBytes++;
if (ch > 127)
{
i = ch - 127; // i is the number of repetitions
// get the byte to be repeated
if (nReadedBytes>=in_buf_size)
break;
else
ch=in_buf[nReadedBytes];
nReadedBytes++;
// uncompress a chunk
for ( ; i ; i--)
{
if (nDecodedBytes<out_buf_size)
out_buf[nDecodedBytes] = ch;
nDecodedBytes++;
}
}
else
{
// copy out some uncompressed bytes
i = ch + 1; // i is the no. of bytes
// uncompress a chunk
for ( ; i ; i--)
{
if (nReadedBytes>=in_buf_size)
break;
else
ch=in_buf[nReadedBytes];
nReadedBytes++;
if (nDecodedBytes<out_buf_size)
out_buf[nDecodedBytes] = ch;
nDecodedBytes++;
}
}
} // end while
return nDecodedBytes;
}
} //end namespace core
} //end namespace irr
#endif // __C_MY3D_HELPER_H_INCLUDED__

View File

@ -1,882 +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
//
// This file was originally written by ZDimitor.
//-----------------------------------------------------------------------------
// This tool created by ZDimitor everyone can use it as wants
//-----------------------------------------------------------------------------
#include "IrrCompileConfig.h"
#ifdef _IRR_COMPILE_WITH_MY3D_LOADER_
#include "CMY3DMeshFileLoader.h"
#include "SAnimatedMesh.h"
#include "SMeshBuffer.h"
#include "IReadFile.h"
#include "IAttributes.h"
#include "CMY3DHelper.h"
#include "os.h"
// v3.15 - May 16, 2005
namespace irr
{
namespace scene
{
static const u32 MY3D_ID = 0x4d593344;
static const u16 MY3D_VER = 0x0003;
static const u16 MY3D_SCENE_HEADER_ID = 0x1000;
static const u16 MY3D_MAT_LIST_ID = 0x2000;
static const u16 MY3D_MAT_HEADER_ID = 0x2100;
static const u16 MY3D_TEX_FNAME_ID = 0x2101;
static const u16 MY3D_TEXDATA_HEADER_ID = 0x2501;
static const u16 MY3D_TEXDATA_RLE_HEADER_ID = 0x2502;
static const u16 MY3D_MESH_LIST_ID = 0x3000;
static const u16 MY3D_MESH_HEADER_ID = 0x3100;
static const u16 MY3D_VERTS_ID = 0x3101;
static const u16 MY3D_FACES_ID = 0x3102;
static const u16 MY3D_TVERTS_ID = 0x3103;
static const u16 MY3D_TFACES_ID = 0x3104;
static const u16 MY3D_FILE_END_ID = 0xFFFF;
static const unsigned long MY3D_TEXDATA_COMPR_NONE_ID = 0x4e4f4e45;
static const unsigned long MY3D_TEXDATA_COMPR_SIMPLE_ID = 0x53494d50;
static const unsigned long MY3D_TEXDATA_COMPR_RLE_ID = 0x20524c45;
static const unsigned long MY3D_PIXEL_FORMAT_24 = 0x5f32345f;
static const unsigned long MY3D_PIXEL_FORMAT_16 = 0x5f31365f;
CMY3DMeshFileLoader::CMY3DMeshFileLoader(ISceneManager* scmgr, io::IFileSystem* fs)
: SceneManager(scmgr), FileSystem(fs)
{
#ifdef _DEBUG
setDebugName("CMY3DMeshFileLoader");
#endif
if (FileSystem)
FileSystem->grab();
}
CMY3DMeshFileLoader::~CMY3DMeshFileLoader()
{
if (FileSystem)
FileSystem->drop();
}
bool CMY3DMeshFileLoader::isALoadableFileExtension(const io::path& filename) const
{
return core::hasFileExtension ( filename, "my3d" );
}
IAnimatedMesh* CMY3DMeshFileLoader::createMesh(io::IReadFile* file)
{
MaterialEntry.clear();
MeshBufferEntry.clear();
ChildNodes.clear();
// working directory (from which we load the scene)
core::stringc filepath = FileSystem->getFileDir(file->getFileName());
if (filepath==".")
filepath="";
else
filepath.append("/");
// read file into memory
SMyFileHeader fileHeader;
file->read(&fileHeader, sizeof(SMyFileHeader));
#ifdef __BIG_ENDIAN__
fileHeader.MyId = os::Byteswap::byteswap(fileHeader.MyId);
fileHeader.Ver = os::Byteswap::byteswap(fileHeader.Ver);
#endif
if (fileHeader.MyId!=MY3D_ID || fileHeader.Ver!=MY3D_VER)
{
os::Printer::log("Bad MY3D file header, loading failed!", ELL_ERROR);
return 0;
}
u16 id;
file->read(&id, sizeof(id));
#ifdef __BIG_ENDIAN__
id = os::Byteswap::byteswap(id);
#endif
if (id!=MY3D_SCENE_HEADER_ID)
{
os::Printer::log("Cannot find MY3D_SCENE_HEADER_ID, loading failed!", ELL_ERROR);
return 0;
}
SMySceneHeader sceneHeader;
file->read(&sceneHeader, sizeof(SMySceneHeader));
#ifdef __BIG_ENDIAN__
sceneHeader.MaterialCount = os::Byteswap::byteswap(sceneHeader.MaterialCount);
sceneHeader.MeshCount = os::Byteswap::byteswap(sceneHeader.MeshCount);
#endif
file->read(&id, sizeof(id));
#ifdef __BIG_ENDIAN__
id = os::Byteswap::byteswap(id);
#endif
if (id!=MY3D_MAT_LIST_ID)
{
os::Printer::log("Can not find MY3D_MAT_LIST_ID, loading failed!", ELL_ERROR);
return 0;
}
core::stringc texturePath =
SceneManager->getParameters()->getAttributeAsString(MY3D_TEXTURE_PATH);
file->read(&id, sizeof(id));
#ifdef __BIG_ENDIAN__
id = os::Byteswap::byteswap(id);
#endif
c8 namebuf[256];
for (s32 m=0; m<sceneHeader.MaterialCount; ++m)
{
if (id != MY3D_MAT_HEADER_ID)
{
os::Printer::log("Cannot find MY3D_MAT_HEADER_ID, loading failed!", ELL_ERROR);
return 0;
}
// read material header
MaterialEntry.push_back(SMyMaterialEntry());
SMyMaterialEntry& me=MaterialEntry.getLast();
file->read(&(me.Header), sizeof(SMyMaterialHeader));
// read next identificator
file->read(&id, sizeof(id));
#ifdef __BIG_ENDIAN__
id = os::Byteswap::byteswap(id);
#endif
bool gotLightMap=false, gotMainMap=false;
for (u32 t=0; t<me.Header.TextureCount; ++t)
{
if (id==MY3D_TEX_FNAME_ID)
file->read(namebuf, 256);
else
{
me.Texture2 = readEmbeddedLightmap(file, namebuf);
if (!me.Texture2)
return 0;
gotLightMap = true;
}
const core::stringc name(namebuf);
const s32 pos = name.findLast('.');
const core::stringc LightingMapStr = "LightingMap";
const s32 ls = LightingMapStr.size();
const bool isSubString = (LightingMapStr == name.subString(core::max_(0, (pos - ls)), ls));
if ((isSubString || (name[pos-1]=='m' &&
name[pos-2]=='l' && name[pos-3]=='_')) &&
!gotLightMap)
{
const bool oldMipMapState = SceneManager->getVideoDriver()->getTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS);
SceneManager->getVideoDriver()->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, false);
me.Texture2FileName = texturePath.size() ? texturePath : filepath;
me.Texture2FileName.append("Lightmaps/");
me.Texture2FileName.append(name);
if (name.size())
me.Texture2 = SceneManager->getVideoDriver()->getTexture(me.Texture2FileName);
me.MaterialType = video::EMT_LIGHTMAP_M2;
gotLightMap = true;
SceneManager->getVideoDriver()->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, oldMipMapState);
}
else
if (!gotLightMap && gotMainMap)
{
me.Texture2FileName = texturePath.size() ? texturePath : filepath;
me.Texture2FileName.append(name);
if (name.size())
me.Texture2 = SceneManager->getVideoDriver()->getTexture(me.Texture2FileName);
me.MaterialType = video::EMT_REFLECTION_2_LAYER;
}
else
if (!gotMainMap && !gotLightMap)
{
me.Texture1FileName = filepath;
me.Texture1FileName.append(name);
if (name.size())
me.Texture1 = SceneManager->getVideoDriver()->getTexture(me.Texture1FileName);
gotMainMap = true;
me.MaterialType = video::EMT_SOLID;
}
else
if (gotLightMap)
{
me.MaterialType = video::EMT_LIGHTMAP_M2;
}
file->read(&id, sizeof(id));
#ifdef __BIG_ENDIAN__
id = os::Byteswap::byteswap(id);
#endif
}
// override material types based on their names
if (!strncmp(me.Header.Name, "AlphaChannel-", 13))
me.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
else
if (!strncmp(me.Header.Name, "SphereMap-", 10))
me.MaterialType = video::EMT_SPHERE_MAP;
}
// loading meshes
if (id!=MY3D_MESH_LIST_ID)
{
os::Printer::log("Can not find MY3D_MESH_LIST_ID, loading failed!", ELL_ERROR);
return 0;
}
file->read(&id, sizeof(id));
#ifdef __BIG_ENDIAN__
id = os::Byteswap::byteswap(id);
#endif
for (s32 mesh_id=0; mesh_id<sceneHeader.MeshCount; mesh_id++)
{
// Warning!!! In some cases MY3D exporter uncorrectly calculates
// MeshCount (it's a problem, has to be solved) thats why
// i added this code line
if (id!=MY3D_MESH_HEADER_ID)
break;
if (id!=MY3D_MESH_HEADER_ID)
{
os::Printer::log("Can not find MY3D_MESH_HEADER_ID, loading failed!", ELL_ERROR);
return 0;
}
SMyMeshHeader meshHeader;
file->read(&meshHeader, sizeof(SMyMeshHeader));
core::array <SMyVertex> Vertex;
core::array <SMyFace> Face;
core::array <SMyTVertex> TVertex1, TVertex2;
core::array <SMyFace> TFace1, TFace2;
s32 vertsNum=0;
s32 facesNum=0;
// vertices
file->read(&id, sizeof(id));
#ifdef __BIG_ENDIAN__
id = os::Byteswap::byteswap(id);
#endif
if (id!=MY3D_VERTS_ID)
{
os::Printer::log("Can not find MY3D_VERTS_ID, loading failed!", ELL_ERROR);
return 0;
}
file->read(&vertsNum, sizeof(vertsNum));
Vertex.set_used(vertsNum);
file->read(Vertex.pointer(), sizeof(SMyVertex)*vertsNum);
// faces
file->read(&id, sizeof(id));
#ifdef __BIG_ENDIAN__
id = os::Byteswap::byteswap(id);
#endif
if (id!=MY3D_FACES_ID)
{
os::Printer::log("Can not find MY3D_FACES_ID, loading failed!", ELL_ERROR);
return 0;
}
file->read(&facesNum, sizeof(facesNum));
Face.set_used(facesNum);
file->read(Face.pointer(), sizeof(SMyFace)*facesNum);
// reading texture channels
for (s32 tex=0; tex<(s32)meshHeader.TChannelCnt; tex++)
{
// Max 2 texture channels allowed (but in format .my3d can be more)
s32 tVertsNum=0, tFacesNum=0;
// reading texture coords
file->read(&id, sizeof(id));
#ifdef __BIG_ENDIAN__
id = os::Byteswap::byteswap(id);
#endif
if (id!=MY3D_TVERTS_ID)
{
core::stringc msg="Can not find MY3D_TVERTS_ID (";
msg.append(core::stringc(tex));
msg.append("texture channel), loading failed!");
os::Printer::log(msg.c_str(), ELL_ERROR);
return 0;
}
file->read(&tVertsNum, sizeof(tVertsNum));
if (tex==0)
{
// 1st texture channel
TVertex1.set_used(tVertsNum);
file->read(TVertex1.pointer(), sizeof(SMyTVertex)*tVertsNum);
}
else
if (tex==1)
{
// 2nd texture channel
TVertex2.set_used(tVertsNum);
file->read(TVertex2.pointer(), sizeof(SMyTVertex)*tVertsNum);
}
else
{
// skip other texture channels
file->seek(file->getPos()+sizeof(SMyTVertex)*tVertsNum);
}
// reading texture faces
file->read(&id, sizeof(id));
#ifdef __BIG_ENDIAN__
id = os::Byteswap::byteswap(id);
#endif
if (id!=MY3D_TFACES_ID)
{
core::stringc msg="Can not find MY3D_TFACES_ID (";
msg.append(core::stringc(tex));
msg.append("texture channel), loading failed!");
os::Printer::log(msg.c_str(), ELL_ERROR);
return 0;
}
file->read(&tFacesNum, sizeof(tFacesNum));
if (tex==0)
{
// 1st texture channel
TFace1.set_used(tFacesNum);
file->read(TFace1.pointer(), sizeof(SMyFace)*tFacesNum);
}
else if (tex==1)
{
// 2nd texture channel
TFace2.set_used(tFacesNum);
file->read(TFace2.pointer(), sizeof(SMyFace)*tFacesNum);
}
else
{
// skip other texture channels
file->seek(file->getPos()+sizeof(SMyFace)*tFacesNum);
}
}
// trying to find material
SMyMaterialEntry* matEnt = getMaterialEntryByIndex(meshHeader.MatIndex);
// creating geometry for the mesh
// trying to find mesh buffer for this material
SMeshBufferLightMap* buffer = getMeshBufferByMaterialIndex(meshHeader.MatIndex);
if (!buffer ||
(buffer->Vertices.size()+vertsNum) > SceneManager->getVideoDriver()->getMaximalPrimitiveCount())
{
// creating new mesh buffer for this material
buffer = new scene::SMeshBufferLightMap();
buffer->Material.MaterialType = video::EMT_LIGHTMAP_M2; // EMT_LIGHTMAP_M4 also possible
buffer->Material.Wireframe = false;
buffer->Material.Lighting = false;
if (matEnt)
{
buffer->Material.MaterialType = matEnt->MaterialType;
if (buffer->Material.MaterialType == video::EMT_REFLECTION_2_LAYER)
{
buffer->Material.Lighting = true;
buffer->Material.setTexture(1, matEnt->Texture1);
buffer->Material.setTexture(0, matEnt->Texture2);
}
else
{
buffer->Material.setTexture(0, matEnt->Texture1);
buffer->Material.setTexture(1, matEnt->Texture2);
}
if (buffer->Material.MaterialType == video::EMT_TRANSPARENT_ALPHA_CHANNEL)
{
buffer->Material.BackfaceCulling = true;
buffer->Material.Lighting = true;
}
else
if (buffer->Material.MaterialType == video::EMT_SPHERE_MAP)
{
buffer->Material.Lighting = true;
}
buffer->Material.AmbientColor = video::SColor(
matEnt->Header.AmbientColor.A, matEnt->Header.AmbientColor.R,
matEnt->Header.AmbientColor.G, matEnt->Header.AmbientColor.B
);
buffer->Material.DiffuseColor = video::SColor(
matEnt->Header.DiffuseColor.A, matEnt->Header.DiffuseColor.R,
matEnt->Header.DiffuseColor.G, matEnt->Header.DiffuseColor.B
);
buffer->Material.EmissiveColor = video::SColor(
matEnt->Header.EmissiveColor.A, matEnt->Header.EmissiveColor.R,
matEnt->Header.EmissiveColor.G, matEnt->Header.EmissiveColor.B
);
buffer->Material.SpecularColor = video::SColor(
matEnt->Header.SpecularColor.A, matEnt->Header.SpecularColor.R,
matEnt->Header.SpecularColor.G, matEnt->Header.SpecularColor.B
);
}
else
{
buffer->Material.setTexture(0, 0);
buffer->Material.setTexture(1, 0);
buffer->Material.AmbientColor = video::SColor(255, 255, 255, 255);
buffer->Material.DiffuseColor = video::SColor(255, 255, 255, 255);
buffer->Material.EmissiveColor = video::SColor(0, 0, 0, 0);
buffer->Material.SpecularColor = video::SColor(0, 0, 0, 0);
}
if (matEnt && matEnt->Header.Transparency!=0)
{
if (buffer->Material.MaterialType == video::EMT_REFLECTION_2_LAYER )
{
buffer->Material.MaterialType = video::EMT_TRANSPARENT_REFLECTION_2_LAYER;
buffer->Material.Lighting = true;
buffer->Material.BackfaceCulling = true;
}
else
{
buffer->Material.MaterialType = video::EMT_TRANSPARENT_VERTEX_ALPHA;
buffer->Material.Lighting = false;
buffer->Material.BackfaceCulling = false;
}
}
else if (
!buffer->Material.getTexture(1) &&
buffer->Material.MaterialType != video::EMT_TRANSPARENT_ALPHA_CHANNEL &&
buffer->Material.MaterialType != video::EMT_SPHERE_MAP)
{
buffer->Material.MaterialType = video::EMT_SOLID;
buffer->Material.Lighting = true;
}
MeshBufferEntry.push_back(
SMyMeshBufferEntry(meshHeader.MatIndex, buffer));
}
video::S3DVertex2TCoords VertexA, VertexB, VertexC;
// vertices (A, B, C) color
video::SColor vert_color;
if (matEnt &&
(buffer->Material.MaterialType == video::EMT_TRANSPARENT_VERTEX_ALPHA ||
buffer->Material.MaterialType == video::EMT_TRANSPARENT_REFLECTION_2_LAYER))
{
video::SColor color(
matEnt->Header.DiffuseColor.A, matEnt->Header.DiffuseColor.R,
matEnt->Header.DiffuseColor.G, matEnt->Header.DiffuseColor.B);
vert_color = color.getInterpolated(video::SColor(0,0,0,0),
1-matEnt->Header.Transparency);
}
else
{
vert_color = buffer->Material.DiffuseColor;
}
VertexA.Color = VertexB.Color = VertexC.Color = vert_color;
if (buffer->Material.MaterialType == video::EMT_TRANSPARENT_ALPHA_CHANNEL)
{
buffer->Indices.reallocate(buffer->Indices.size()+6*facesNum);
buffer->Vertices.reallocate(buffer->Vertices.size()+6*facesNum);
}
else
{
buffer->Indices.reallocate(buffer->Indices.size()+3*facesNum);
buffer->Vertices.reallocate(buffer->Vertices.size()+3*facesNum);
}
for (int f=0; f<facesNum; f++)
{
// vertex A
VertexA.Pos.X = Vertex[Face[f].C].Coord.X;
VertexA.Pos.Y = Vertex[Face[f].C].Coord.Y;
VertexA.Pos.Z = Vertex[Face[f].C].Coord.Z;
VertexA.Normal.X = Vertex[Face[f].C].Normal.X;
VertexA.Normal.Y = Vertex[Face[f].C].Normal.Y;
VertexA.Normal.Z = Vertex[Face[f].C].Normal.Z;
if (meshHeader.TChannelCnt>0)
{
VertexA.TCoords.X = TVertex1[TFace1[f].C].TCoord.X;
VertexA.TCoords.Y = TVertex1[TFace1[f].C].TCoord.Y;
}
if (meshHeader.TChannelCnt>1)
{
VertexA.TCoords2.X = TVertex2[TFace2[f].C].TCoord.X;
VertexA.TCoords2.Y = TVertex2[TFace2[f].C].TCoord.Y;
}
// vertex B
VertexB.Pos.X = Vertex[Face[f].B].Coord.X;
VertexB.Pos.Y = Vertex[Face[f].B].Coord.Y;
VertexB.Pos.Z = Vertex[Face[f].B].Coord.Z;
VertexB.Normal.X = Vertex[Face[f].B].Normal.X;
VertexB.Normal.Y = Vertex[Face[f].B].Normal.Y;
VertexB.Normal.Z = Vertex[Face[f].B].Normal.Z;
if (meshHeader.TChannelCnt>0)
{
VertexB.TCoords.X = TVertex1[TFace1[f].B].TCoord.X;
VertexB.TCoords.Y = TVertex1[TFace1[f].B].TCoord.Y;
}
if (meshHeader.TChannelCnt>1)
{
VertexB.TCoords2.X = TVertex2[TFace2[f].B].TCoord.X;
VertexB.TCoords2.Y = TVertex2[TFace2[f].B].TCoord.Y;
}
// vertex C
VertexC.Pos.X = Vertex[Face[f].A].Coord.X;
VertexC.Pos.Y = Vertex[Face[f].A].Coord.Y;
VertexC.Pos.Z = Vertex[Face[f].A].Coord.Z;
VertexC.Normal.X = Vertex[Face[f].A].Normal.X;
VertexC.Normal.Y = Vertex[Face[f].A].Normal.Y;
VertexC.Normal.Z = Vertex[Face[f].A].Normal.Z;
if (meshHeader.TChannelCnt>0)
{
VertexC.TCoords.X = TVertex1[TFace1[f].A].TCoord.X;
VertexC.TCoords.Y = TVertex1[TFace1[f].A].TCoord.Y;
}
if (meshHeader.TChannelCnt>1)
{
VertexC.TCoords2.X = TVertex2[TFace2[f].A].TCoord.X;
VertexC.TCoords2.Y = TVertex2[TFace2[f].A].TCoord.Y;
}
// store 3d data in mesh buffer
buffer->Indices.push_back(buffer->Vertices.size());
buffer->Vertices.push_back(VertexA);
buffer->Indices.push_back(buffer->Vertices.size());
buffer->Vertices.push_back(VertexB);
buffer->Indices.push_back(buffer->Vertices.size());
buffer->Vertices.push_back(VertexC);
//*****************************************************************
// !!!!!! W A R N I N G !!!!!!!
//*****************************************************************
// For materials with alpha channel we duplicate all faces.
// This has be done for proper lighting calculation of the back faces.
// So you must remember this while you creating your models !!!!!
//*****************************************************************
// !!!!!! W A R N I N G !!!!!!!
//*****************************************************************
if (buffer->Material.MaterialType == video::EMT_TRANSPARENT_ALPHA_CHANNEL)
{
VertexA.Normal = core::vector3df(-VertexA.Normal.X, -VertexA.Normal.Y, -VertexA.Normal.Z);
VertexB.Normal = core::vector3df(-VertexB.Normal.X, -VertexB.Normal.Y, -VertexB.Normal.Z);
VertexC.Normal = core::vector3df(-VertexC.Normal.X, -VertexC.Normal.Y, -VertexC.Normal.Z);
buffer->Indices.push_back(buffer->Vertices.size());
buffer->Vertices.push_back(VertexC);
buffer->Indices.push_back(buffer->Vertices.size());
buffer->Vertices.push_back(VertexB);
buffer->Indices.push_back(buffer->Vertices.size());
buffer->Vertices.push_back(VertexA);
}
}
file->read(&id, sizeof(id));
#ifdef __BIG_ENDIAN__
id = os::Byteswap::byteswap(id);
#endif
}
// creating mesh
SMesh* mesh = new SMesh();
for (u32 num=0; num<MeshBufferEntry.size(); ++num)
{
SMeshBufferLightMap* buffer = MeshBufferEntry[num].MeshBuffer;
if (!buffer)
continue;
mesh->addMeshBuffer(buffer);
buffer->recalculateBoundingBox();
buffer->drop();
}
mesh->recalculateBoundingBox();
if (id != MY3D_FILE_END_ID)
os::Printer::log("Loading finished, but can not find MY3D_FILE_END_ID token.", ELL_WARNING);
SAnimatedMesh* am = new SAnimatedMesh();
am->addMesh(mesh);
mesh->drop();
am->recalculateBoundingBox();
return am;
}
video::ITexture* CMY3DMeshFileLoader::readEmbeddedLightmap(io::IReadFile* file, char* namebuf)
{
static int LightMapIndex=0;
u16 id;
file->read(&id, sizeof(id));
#ifdef __BIG_ENDIAN__
id = os::Byteswap::byteswap(id);
#endif
if (id!=MY3D_TEXDATA_HEADER_ID)
{
os::Printer::log("Can not find MY3D_TEXDATA_HEADER_ID, loading failed!", ELL_ERROR);
return 0;
}
SMyTexDataHeader texDataHeader;
file->read(&texDataHeader, sizeof(SMyTexDataHeader));
strcpy(texDataHeader.Name, namebuf);
char LightMapName[255];
sprintf(LightMapName,"My3D.Lightmap.%d",++LightMapIndex);
core::stringc pixFormatStr;
if (texDataHeader.PixelFormat == MY3D_PIXEL_FORMAT_24)
pixFormatStr = "24bit,";
else
if (texDataHeader.PixelFormat == MY3D_PIXEL_FORMAT_16)
pixFormatStr = "16bit,";
else
{
core::stringc msg="Unknown format of image data (";
msg.append(LightMapName);
msg.append("), loading failed!");
os::Printer::log(msg.c_str(), ELL_ERROR);
return 0;
}
if (texDataHeader.ComprMode != MY3D_TEXDATA_COMPR_NONE_ID &&
texDataHeader.ComprMode != MY3D_TEXDATA_COMPR_RLE_ID &&
texDataHeader.ComprMode != MY3D_TEXDATA_COMPR_SIMPLE_ID )
{
os::Printer::log("Unknown method of compression image data, loading failed!", ELL_ERROR);
return 0;
}
const u32 num_pixels = texDataHeader.Width*texDataHeader.Height;
void* data = 0;
if (texDataHeader.ComprMode==MY3D_TEXDATA_COMPR_NONE_ID)
{
// none compressed image data
if (texDataHeader.PixelFormat == MY3D_PIXEL_FORMAT_24)
{
data = (void*) new SMyPixelColor24[num_pixels];
file->read(data, sizeof(SMyPixelColor24)*num_pixels);
}
else
{
data = (void*) new SMyPixelColor16[num_pixels];
file->read(data, sizeof(SMyPixelColor16)*num_pixels);
}
}
else
if (texDataHeader.ComprMode==MY3D_TEXDATA_COMPR_RLE_ID)
{
// read RLE header identificator
file->read(&id, sizeof(id));
#ifdef __BIG_ENDIAN__
id = os::Byteswap::byteswap(id);
#endif
if (id!=MY3D_TEXDATA_RLE_HEADER_ID)
{
os::Printer::log("Can not find MY3D_TEXDATA_RLE_HEADER_ID, loading failed!", ELL_ERROR);
return 0;
}
// read RLE header
SMyRLEHeader rleHeader;
file->read(&rleHeader, sizeof(SMyRLEHeader));
//allocate memory for input and output buffers
void *input_buffer = (void*) new unsigned char[rleHeader.nEncodedBytes];
void *output_buffer = (void*) new unsigned char[rleHeader.nDecodedBytes];
// read encoded data
file->read(input_buffer, rleHeader.nEncodedBytes);
// decode data
data = 0;//(void*) new unsigned char[rleHeader.nDecodedBytes];
s32 decodedBytes = core::rle_decode(
(unsigned char*)input_buffer, rleHeader.nEncodedBytes,
(unsigned char*)output_buffer, rleHeader.nDecodedBytes);
if (decodedBytes!=(s32)rleHeader.nDecodedBytes)
{
os::Printer::log("Error extracting data from RLE compression, loading failed!", ELL_ERROR);
return 0;
}
// free input buffer
delete [] (unsigned char*)input_buffer;
// here decoded data
data = output_buffer;
}
else if (texDataHeader.ComprMode==MY3D_TEXDATA_COMPR_SIMPLE_ID)
{
// simple compressed image data
if (texDataHeader.PixelFormat == MY3D_PIXEL_FORMAT_24)
data = (void*) new SMyPixelColor24[num_pixels];
else
data = (void*) new SMyPixelColor16[num_pixels];
u32 nReadedPixels=0, nToRead=0;
while (true)
{
file->read(&nToRead, sizeof(nToRead));
if ((nReadedPixels+nToRead) > num_pixels)
break;
if (texDataHeader.PixelFormat == MY3D_PIXEL_FORMAT_24)
{
SMyPixelColor24 col24;
file->read(&col24, sizeof(SMyPixelColor24));
for (u32 p=0; p<nToRead; p++)
{
((SMyPixelColor24*)data)[nReadedPixels+p] =
SMyPixelColor24(col24.r, col24.g, col24.b);
}
}
else
{
SMyPixelColor16 col16;
file->read(&col16, sizeof(SMyPixelColor16));
for (u32 p=0; p<nToRead; p++)
((SMyPixelColor16*)data)[nReadedPixels+p].argb = col16.argb;
}
nReadedPixels+=nToRead;
if (nReadedPixels >= num_pixels)
break;
}
if (nReadedPixels != num_pixels)
{
os::Printer::log("Image data seems to be corrupted, loading failed!", ELL_ERROR);
return 0;
}
}
//! Creates a software image from a byte array.
video::IImage* light_img = 0;
if (texDataHeader.PixelFormat == MY3D_PIXEL_FORMAT_24)
{
// 24 bit lightmap format
light_img = SceneManager->getVideoDriver()->createImageFromData(
video::ECF_R8G8B8,
core::dimension2d<u32>(texDataHeader.Width, texDataHeader.Height),
data, true);
}
else
{
// 16 bit lightmap format
light_img = SceneManager->getVideoDriver()->createImageFromData(
video::ECF_A1R5G5B5,
core::dimension2d<u32>(texDataHeader.Width, texDataHeader.Height),
data, true);
}
const bool oldMipMapState = SceneManager->getVideoDriver()->getTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS);
SceneManager->getVideoDriver()->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, false);
video::ITexture* lmtex = SceneManager->getVideoDriver()->addTexture(LightMapName, light_img);
SceneManager->getVideoDriver()->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, oldMipMapState);
light_img->drop();
return lmtex;
}
CMY3DMeshFileLoader::SMyMaterialEntry* CMY3DMeshFileLoader::getMaterialEntryByIndex(u32 matInd)
{
for (u32 m=0; m<MaterialEntry.size(); ++m)
if (MaterialEntry[m].Header.Index == matInd)
return &MaterialEntry[m];
return 0;
}
SMeshBufferLightMap* CMY3DMeshFileLoader::getMeshBufferByMaterialIndex(u32 matInd)
{
for (u32 m=0; m<MeshBufferEntry.size(); ++m)
{
if (MeshBufferEntry[m].MaterialIndex == (s32)matInd)
return MeshBufferEntry[m].MeshBuffer;
}
return 0;
}
const core::array<ISceneNode*>& CMY3DMeshFileLoader::getChildNodes() const
{
return ChildNodes;
}
} // end namespace scnene
} // end namespace irr
#endif // _IRR_COMPILE_WITH_MY3D_LOADER_

View File

@ -1,131 +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
//
// This file was originally written by ZDimitor.
// I (Nikolaus Gebhardt) did some few changes to this:
// - replaced logging calls to their os:: counterparts
// - removed some logging calls
// - removed setTexture path and replaced it with the directory of the mesh
// - added EAMT_MY3D file type
// - fixed a memory leak when decompressing RLE data.
// - cleaned multi character constant problems with gcc
// - removed octree child scene node generation because irrlicht is now able to draw
// scene nodes with transparent and sold materials in them at the same time. (see changes.txt)
// Thanks a lot to ZDimitor for his work on this and that he gave me
// his permission to add it into Irrlicht.
//--------------------------------------------------------------------------------
// This tool created by ZDimitor everyone can use it as wants
//--------------------------------------------------------------------------------
#ifndef __CMY3D_MESH_FILE_LOADER_H_INCLUDED__
#define __CMY3D_MESH_FILE_LOADER_H_INCLUDED__
#ifdef _MSC_VER
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
#endif
#include "IMeshLoader.h"
#include "SMesh.h"
#include "SMeshBufferLightMap.h"
#include "IFileSystem.h"
#include "IVideoDriver.h"
#include "irrString.h"
#include "ISceneManager.h"
namespace irr
{
namespace scene
{
// byte-align structures
#include "irrpack.h"
struct SMyColor
{ SMyColor () {;}
SMyColor (s32 __R, s32 __G, s32 __B, s32 __A)
: R(__R), G(__G), B(__B), A(__A) {}
s32 R, G, B, A;
} PACK_STRUCT;
// material header
struct SMyMaterialHeader
{ c8 Name[256]; // material name
u32 Index;
SMyColor AmbientColor;
SMyColor DiffuseColor;
SMyColor EmissiveColor;
SMyColor SpecularColor;
f32 Shininess;
f32 Transparency;
u32 TextureCount; // texture count
} PACK_STRUCT;
// Default alignment
#include "irrunpack.h"
class CMY3DMeshFileLoader : public IMeshLoader
{
public:
CMY3DMeshFileLoader(ISceneManager *scmgr, io::IFileSystem* fs);
virtual ~CMY3DMeshFileLoader();
virtual bool isALoadableFileExtension(const io::path& filename) const;
virtual IAnimatedMesh* createMesh(io::IReadFile* file);
//! getting access to the nodes (with transparent material), creating
//! while loading .my3d file
const core::array<ISceneNode*>& getChildNodes() const;
private:
video::ITexture* readEmbeddedLightmap(io::IReadFile* file, char* namebuf);
scene::ISceneManager* SceneManager;
io::IFileSystem* FileSystem;
struct SMyMaterialEntry
{
SMyMaterialEntry ()
: Texture1FileName("null"), Texture2FileName("null"),
Texture1(0), Texture2(0), MaterialType(video::EMT_SOLID) {}
SMyMaterialHeader Header;
core::stringc Texture1FileName;
core::stringc Texture2FileName;
video::ITexture *Texture1;
video::ITexture *Texture2;
video::E_MATERIAL_TYPE MaterialType;
};
struct SMyMeshBufferEntry
{
SMyMeshBufferEntry() : MaterialIndex(-1), MeshBuffer(0) {}
SMyMeshBufferEntry(s32 mi, SMeshBufferLightMap* mb)
: MaterialIndex(mi), MeshBuffer(mb) {}
s32 MaterialIndex;
SMeshBufferLightMap* MeshBuffer;
};
SMyMaterialEntry* getMaterialEntryByIndex (u32 matInd);
SMeshBufferLightMap* getMeshBufferByMaterialIndex(u32 matInd);
core::array<SMyMaterialEntry> MaterialEntry;
core::array<SMyMeshBufferEntry> MeshBufferEntry;
core::array<ISceneNode*> ChildNodes;
};
} // end namespace scene
} // end namespace irr
#endif // __CMY3D_MESH_FILE_LOADER_H_INCLUDED__

View File

@ -1,931 +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 "IrrCompileConfig.h"
#ifdef _IRR_COMPILE_WITH_OBJ_LOADER_
#include "COBJMeshFileLoader.h"
#include "IMeshManipulator.h"
#include "IVideoDriver.h"
#include "SMesh.h"
#include "SMeshBuffer.h"
#include "SAnimatedMesh.h"
#include "IReadFile.h"
#include "IAttributes.h"
#include "fast_atof.h"
#include "coreutil.h"
#include "os.h"
namespace irr
{
namespace scene
{
#ifdef _DEBUG
#define _IRR_DEBUG_OBJ_LOADER_
#endif
static const u32 WORD_BUFFER_LENGTH = 512;
//! Constructor
COBJMeshFileLoader::COBJMeshFileLoader(scene::ISceneManager* smgr, io::IFileSystem* fs)
: SceneManager(smgr), FileSystem(fs)
{
#ifdef _DEBUG
setDebugName("COBJMeshFileLoader");
#endif
if (FileSystem)
FileSystem->grab();
}
//! destructor
COBJMeshFileLoader::~COBJMeshFileLoader()
{
if (FileSystem)
FileSystem->drop();
}
//! returns true if the file maybe is able to be loaded by this class
//! based on the file extension (e.g. ".bsp")
bool COBJMeshFileLoader::isALoadableFileExtension(const io::path& filename) const
{
return core::hasFileExtension ( filename, "obj" );
}
//! creates/loads an animated mesh from the file.
//! \return Pointer to the created mesh. Returns 0 if loading failed.
//! If you no longer need the mesh, you should call IAnimatedMesh::drop().
//! See IReferenceCounted::drop() for more information.
IAnimatedMesh* COBJMeshFileLoader::createMesh(io::IReadFile* file)
{
const long filesize = file->getSize();
if (!filesize)
return 0;
const u32 WORD_BUFFER_LENGTH = 512;
core::array<core::vector3df> vertexBuffer;
core::array<core::vector3df> normalsBuffer;
core::array<core::vector2df> textureCoordBuffer;
SObjMtl * currMtl = new SObjMtl();
Materials.push_back(currMtl);
u32 smoothingGroup=0;
const io::path fullName = file->getFileName();
const io::path relPath = FileSystem->getFileDir(fullName)+"/";
c8* buf = new c8[filesize];
memset(buf, 0, filesize);
file->read((void*)buf, filesize);
const c8* const bufEnd = buf+filesize;
// Process obj information
const c8* bufPtr = buf;
core::stringc grpName, mtlName;
bool mtlChanged=false;
bool useGroups = !SceneManager->getParameters()->getAttributeAsBool(OBJ_LOADER_IGNORE_GROUPS);
bool useMaterials = !SceneManager->getParameters()->getAttributeAsBool(OBJ_LOADER_IGNORE_MATERIAL_FILES);
while(bufPtr != bufEnd)
{
switch(bufPtr[0])
{
case 'm': // mtllib (material)
{
if (useMaterials)
{
c8 name[WORD_BUFFER_LENGTH];
bufPtr = goAndCopyNextWord(name, bufPtr, WORD_BUFFER_LENGTH, bufEnd);
#ifdef _IRR_DEBUG_OBJ_LOADER_
os::Printer::log("Reading material file",name);
#endif
readMTL(name, relPath);
}
}
break;
case 'v': // v, vn, vt
switch(bufPtr[1])
{
case ' ': // vertex
{
core::vector3df vec;
bufPtr = readVec3(bufPtr, vec, bufEnd);
vertexBuffer.push_back(vec);
}
break;
case 'n': // normal
{
core::vector3df vec;
bufPtr = readVec3(bufPtr, vec, bufEnd);
normalsBuffer.push_back(vec);
}
break;
case 't': // texcoord
{
core::vector2df vec;
bufPtr = readUV(bufPtr, vec, bufEnd);
textureCoordBuffer.push_back(vec);
}
break;
}
break;
case 'g': // group name
{
c8 grp[WORD_BUFFER_LENGTH];
bufPtr = goAndCopyNextWord(grp, bufPtr, WORD_BUFFER_LENGTH, bufEnd);
#ifdef _IRR_DEBUG_OBJ_LOADER_
os::Printer::log("Loaded group start",grp, ELL_DEBUG);
#endif
if (useGroups)
{
if (0 != grp[0])
grpName = grp;
else
grpName = "default";
}
mtlChanged=true;
}
break;
case 's': // smoothing can be a group or off (equiv. to 0)
{
c8 smooth[WORD_BUFFER_LENGTH];
bufPtr = goAndCopyNextWord(smooth, bufPtr, WORD_BUFFER_LENGTH, bufEnd);
#ifdef _IRR_DEBUG_OBJ_LOADER_
os::Printer::log("Loaded smoothing group start",smooth, ELL_DEBUG);
#endif
if (core::stringc("off")==smooth)
smoothingGroup=0;
else
smoothingGroup=core::strtoul10(smooth);
}
break;
case 'u': // usemtl
// get name of material
{
c8 matName[WORD_BUFFER_LENGTH];
bufPtr = goAndCopyNextWord(matName, bufPtr, WORD_BUFFER_LENGTH, bufEnd);
#ifdef _IRR_DEBUG_OBJ_LOADER_
os::Printer::log("Loaded material start",matName, ELL_DEBUG);
#endif
mtlName=matName;
mtlChanged=true;
}
break;
case 'f': // face
{
c8 vertexWord[WORD_BUFFER_LENGTH]; // for retrieving vertex data
video::S3DVertex v;
// Assign vertex color from currently active material's diffuse color
if (mtlChanged)
{
// retrieve the material
SObjMtl *useMtl = findMtl(mtlName, grpName);
// only change material if we found it
if (useMtl)
currMtl = useMtl;
mtlChanged=false;
}
if (currMtl)
v.Color = currMtl->Meshbuffer->Material.DiffuseColor;
// get all vertices data in this face (current line of obj file)
const core::stringc wordBuffer = copyLine(bufPtr, bufEnd);
const c8* linePtr = wordBuffer.c_str();
const c8* const endPtr = linePtr+wordBuffer.size();
core::array<int> faceCorners;
faceCorners.reallocate(32); // should be large enough
// read in all vertices
linePtr = goNextWord(linePtr, endPtr);
while (0 != linePtr[0])
{
// Array to communicate with retrieveVertexIndices()
// sends the buffer sizes and gets the actual indices
// if index not set returns -1
s32 Idx[3];
Idx[1] = Idx[2] = -1;
// read in next vertex's data
u32 wlength = copyWord(vertexWord, linePtr, WORD_BUFFER_LENGTH, endPtr);
// this function will also convert obj's 1-based index to c++'s 0-based index
retrieveVertexIndices(vertexWord, Idx, vertexWord+wlength+1, vertexBuffer.size(), textureCoordBuffer.size(), normalsBuffer.size());
v.Pos = vertexBuffer[Idx[0]];
if ( -1 != Idx[1] )
v.TCoords = textureCoordBuffer[Idx[1]];
else
v.TCoords.set(0.0f,0.0f);
if ( -1 != Idx[2] )
v.Normal = normalsBuffer[Idx[2]];
else
{
v.Normal.set(0.0f,0.0f,0.0f);
currMtl->RecalculateNormals=true;
}
int vertLocation;
core::map<video::S3DVertex, int>::Node* n = currMtl->VertMap.find(v);
if (n)
{
vertLocation = n->getValue();
}
else
{
currMtl->Meshbuffer->Vertices.push_back(v);
vertLocation = currMtl->Meshbuffer->Vertices.size() -1;
currMtl->VertMap.insert(v, vertLocation);
}
faceCorners.push_back(vertLocation);
// go to next vertex
linePtr = goNextWord(linePtr, endPtr);
}
// triangulate the face
for ( u32 i = 1; i < faceCorners.size() - 1; ++i )
{
// Add a triangle
currMtl->Meshbuffer->Indices.push_back( faceCorners[i+1] );
currMtl->Meshbuffer->Indices.push_back( faceCorners[i] );
currMtl->Meshbuffer->Indices.push_back( faceCorners[0] );
}
faceCorners.set_used(0); // fast clear
faceCorners.reallocate(32);
}
break;
case '#': // comment
default:
break;
} // end switch(bufPtr[0])
// eat up rest of line
bufPtr = goNextLine(bufPtr, bufEnd);
} // end while(bufPtr && (bufPtr-buf<filesize))
SMesh* mesh = new SMesh();
// Combine all the groups (meshbuffers) into the mesh
for ( u32 m = 0; m < Materials.size(); ++m )
{
if ( Materials[m]->Meshbuffer->getIndexCount() > 0 )
{
Materials[m]->Meshbuffer->recalculateBoundingBox();
if (Materials[m]->RecalculateNormals)
SceneManager->getMeshManipulator()->recalculateNormals(Materials[m]->Meshbuffer);
if (Materials[m]->Meshbuffer->Material.MaterialType == video::EMT_PARALLAX_MAP_SOLID)
{
SMesh tmp;
tmp.addMeshBuffer(Materials[m]->Meshbuffer);
IMesh* tangentMesh = SceneManager->getMeshManipulator()->createMeshWithTangents(&tmp);
mesh->addMeshBuffer(tangentMesh->getMeshBuffer(0));
tangentMesh->drop();
}
else
mesh->addMeshBuffer( Materials[m]->Meshbuffer );
}
}
// Create the Animated mesh if there's anything in the mesh
SAnimatedMesh* animMesh = 0;
if ( 0 != mesh->getMeshBufferCount() )
{
mesh->recalculateBoundingBox();
animMesh = new SAnimatedMesh();
animMesh->Type = EAMT_OBJ;
animMesh->addMesh(mesh);
animMesh->recalculateBoundingBox();
}
// Clean up the allocate obj file contents
delete [] buf;
// more cleaning up
cleanUp();
mesh->drop();
return animMesh;
}
const c8* COBJMeshFileLoader::readTextures(const c8* bufPtr, const c8* const bufEnd, SObjMtl* currMaterial, const io::path& relPath)
{
u8 type=0; // map_Kd - diffuse color texture map
// map_Ks - specular color texture map
// map_Ka - ambient color texture map
// map_Ns - shininess texture map
if ((!strncmp(bufPtr,"map_bump",8)) || (!strncmp(bufPtr,"bump",4)))
type=1; // normal map
else if ((!strncmp(bufPtr,"map_d",5)) || (!strncmp(bufPtr,"map_opacity",11)))
type=2; // opacity map
else if (!strncmp(bufPtr,"map_refl",8))
type=3; // reflection map
// extract new material's name
c8 textureNameBuf[WORD_BUFFER_LENGTH];
bufPtr = goAndCopyNextWord(textureNameBuf, bufPtr, WORD_BUFFER_LENGTH, bufEnd);
f32 bumpiness = 6.0f;
bool clamp = false;
// handle options
while (textureNameBuf[0]=='-')
{
if (!strncmp(bufPtr,"-bm",3))
{
bufPtr = goAndCopyNextWord(textureNameBuf, bufPtr, WORD_BUFFER_LENGTH, bufEnd);
currMaterial->Meshbuffer->Material.MaterialTypeParam=core::fast_atof(textureNameBuf);
bufPtr = goAndCopyNextWord(textureNameBuf, bufPtr, WORD_BUFFER_LENGTH, bufEnd);
continue;
}
else
if (!strncmp(bufPtr,"-blendu",7))
bufPtr = goAndCopyNextWord(textureNameBuf, bufPtr, WORD_BUFFER_LENGTH, bufEnd);
else
if (!strncmp(bufPtr,"-blendv",7))
bufPtr = goAndCopyNextWord(textureNameBuf, bufPtr, WORD_BUFFER_LENGTH, bufEnd);
else
if (!strncmp(bufPtr,"-cc",3))
bufPtr = goAndCopyNextWord(textureNameBuf, bufPtr, WORD_BUFFER_LENGTH, bufEnd);
else
if (!strncmp(bufPtr,"-clamp",6))
bufPtr = readBool(bufPtr, clamp, bufEnd);
else
if (!strncmp(bufPtr,"-texres",7))
bufPtr = goAndCopyNextWord(textureNameBuf, bufPtr, WORD_BUFFER_LENGTH, bufEnd);
else
if (!strncmp(bufPtr,"-type",5))
bufPtr = goAndCopyNextWord(textureNameBuf, bufPtr, WORD_BUFFER_LENGTH, bufEnd);
else
if (!strncmp(bufPtr,"-mm",3))
{
bufPtr = goAndCopyNextWord(textureNameBuf, bufPtr, WORD_BUFFER_LENGTH, bufEnd);
bufPtr = goAndCopyNextWord(textureNameBuf, bufPtr, WORD_BUFFER_LENGTH, bufEnd);
}
else
if (!strncmp(bufPtr,"-o",2)) // texture coord translation
{
bufPtr = goAndCopyNextWord(textureNameBuf, bufPtr, WORD_BUFFER_LENGTH, bufEnd);
// next parameters are optional, so skip rest of loop if no number is found
bufPtr = goAndCopyNextWord(textureNameBuf, bufPtr, WORD_BUFFER_LENGTH, bufEnd);
if (!core::isdigit(textureNameBuf[0]))
continue;
bufPtr = goAndCopyNextWord(textureNameBuf, bufPtr, WORD_BUFFER_LENGTH, bufEnd);
if (!core::isdigit(textureNameBuf[0]))
continue;
}
else
if (!strncmp(bufPtr,"-s",2)) // texture coord scale
{
bufPtr = goAndCopyNextWord(textureNameBuf, bufPtr, WORD_BUFFER_LENGTH, bufEnd);
// next parameters are optional, so skip rest of loop if no number is found
bufPtr = goAndCopyNextWord(textureNameBuf, bufPtr, WORD_BUFFER_LENGTH, bufEnd);
if (!core::isdigit(textureNameBuf[0]))
continue;
bufPtr = goAndCopyNextWord(textureNameBuf, bufPtr, WORD_BUFFER_LENGTH, bufEnd);
if (!core::isdigit(textureNameBuf[0]))
continue;
}
else
if (!strncmp(bufPtr,"-t",2))
{
bufPtr = goAndCopyNextWord(textureNameBuf, bufPtr, WORD_BUFFER_LENGTH, bufEnd);
// next parameters are optional, so skip rest of loop if no number is found
bufPtr = goAndCopyNextWord(textureNameBuf, bufPtr, WORD_BUFFER_LENGTH, bufEnd);
if (!core::isdigit(textureNameBuf[0]))
continue;
bufPtr = goAndCopyNextWord(textureNameBuf, bufPtr, WORD_BUFFER_LENGTH, bufEnd);
if (!core::isdigit(textureNameBuf[0]))
continue;
}
// get next word
bufPtr = goAndCopyNextWord(textureNameBuf, bufPtr, WORD_BUFFER_LENGTH, bufEnd);
}
if ((type==1) && (core::isdigit(textureNameBuf[0])))
{
currMaterial->Meshbuffer->Material.MaterialTypeParam=core::fast_atof(textureNameBuf);
bufPtr = goAndCopyNextWord(textureNameBuf, bufPtr, WORD_BUFFER_LENGTH, bufEnd);
}
if (clamp)
currMaterial->Meshbuffer->Material.setFlag(video::EMF_TEXTURE_WRAP, video::ETC_CLAMP);
io::path texname(textureNameBuf);
texname.replace('\\', '/');
video::ITexture * texture = 0;
bool newTexture=false;
if (texname.size())
{
io::path texnameWithUserPath( SceneManager->getParameters()->getAttributeAsString(OBJ_TEXTURE_PATH) );
if ( texnameWithUserPath.size() )
{
texnameWithUserPath += '/';
texnameWithUserPath += texname;
}
if (FileSystem->existFile(texnameWithUserPath))
texture = SceneManager->getVideoDriver()->getTexture(texnameWithUserPath);
else if (FileSystem->existFile(texname))
{
newTexture = SceneManager->getVideoDriver()->findTexture(texname) == 0;
texture = SceneManager->getVideoDriver()->getTexture(texname);
}
else
{
newTexture = SceneManager->getVideoDriver()->findTexture(relPath + texname) == 0;
// try to read in the relative path, the .obj is loaded from
texture = SceneManager->getVideoDriver()->getTexture( relPath + texname );
}
}
if ( texture )
{
if (type==0)
currMaterial->Meshbuffer->Material.setTexture(0, texture);
else if (type==1)
{
if (newTexture)
SceneManager->getVideoDriver()->makeNormalMapTexture(texture, bumpiness);
currMaterial->Meshbuffer->Material.setTexture(1, texture);
currMaterial->Meshbuffer->Material.MaterialType=video::EMT_PARALLAX_MAP_SOLID;
currMaterial->Meshbuffer->Material.MaterialTypeParam=0.035f;
}
else if (type==2)
{
currMaterial->Meshbuffer->Material.setTexture(0, texture);
currMaterial->Meshbuffer->Material.MaterialType=video::EMT_TRANSPARENT_ADD_COLOR;
}
else if (type==3)
{
// currMaterial->Meshbuffer->Material.Textures[1] = texture;
// currMaterial->Meshbuffer->Material.MaterialType=video::EMT_REFLECTION_2_LAYER;
}
// Set diffuse material color to white so as not to affect texture color
// Because Maya set diffuse color Kd to black when you use a diffuse color map
// But is this the right thing to do?
currMaterial->Meshbuffer->Material.DiffuseColor.set(
currMaterial->Meshbuffer->Material.DiffuseColor.getAlpha(), 255, 255, 255 );
}
return bufPtr;
}
void COBJMeshFileLoader::readMTL(const c8* fileName, const io::path& relPath)
{
const io::path realFile(fileName);
io::IReadFile * mtlReader;
if (FileSystem->existFile(realFile))
mtlReader = FileSystem->createAndOpenFile(realFile);
else if (FileSystem->existFile(relPath + realFile))
mtlReader = FileSystem->createAndOpenFile(relPath + realFile);
else if (FileSystem->existFile(FileSystem->getFileBasename(realFile)))
mtlReader = FileSystem->createAndOpenFile(FileSystem->getFileBasename(realFile));
else
mtlReader = FileSystem->createAndOpenFile(relPath + FileSystem->getFileBasename(realFile));
if (!mtlReader) // fail to open and read file
{
os::Printer::log("Could not open material file", realFile, ELL_WARNING);
return;
}
const long filesize = mtlReader->getSize();
if (!filesize)
{
os::Printer::log("Skipping empty material file", realFile, ELL_WARNING);
mtlReader->drop();
return;
}
c8* buf = new c8[filesize];
mtlReader->read((void*)buf, filesize);
const c8* bufEnd = buf+filesize;
SObjMtl* currMaterial = 0;
const c8* bufPtr = buf;
while(bufPtr != bufEnd)
{
switch(*bufPtr)
{
case 'n': // newmtl
{
// if there's an existing material, store it first
if ( currMaterial )
Materials.push_back( currMaterial );
// extract new material's name
c8 mtlNameBuf[WORD_BUFFER_LENGTH];
bufPtr = goAndCopyNextWord(mtlNameBuf, bufPtr, WORD_BUFFER_LENGTH, bufEnd);
currMaterial = new SObjMtl;
currMaterial->Name = mtlNameBuf;
}
break;
case 'i': // illum - illumination
if ( currMaterial )
{
const u32 COLOR_BUFFER_LENGTH = 16;
c8 illumStr[COLOR_BUFFER_LENGTH];
bufPtr = goAndCopyNextWord(illumStr, bufPtr, COLOR_BUFFER_LENGTH, bufEnd);
currMaterial->Illumination = (c8)atol(illumStr);
}
break;
case 'N':
if ( currMaterial )
{
switch(bufPtr[1])
{
case 's': // Ns - shininess
{
const u32 COLOR_BUFFER_LENGTH = 16;
c8 nsStr[COLOR_BUFFER_LENGTH];
bufPtr = goAndCopyNextWord(nsStr, bufPtr, COLOR_BUFFER_LENGTH, bufEnd);
f32 shininessValue = core::fast_atof(nsStr);
// wavefront shininess is from [0, 1000], so scale for OpenGL
shininessValue *= 0.128f;
currMaterial->Meshbuffer->Material.Shininess = shininessValue;
}
break;
case 'i': // Ni - refraction index
{
c8 tmpbuf[WORD_BUFFER_LENGTH];
bufPtr = goAndCopyNextWord(tmpbuf, bufPtr, WORD_BUFFER_LENGTH, bufEnd);
}
break;
}
}
break;
case 'K':
if ( currMaterial )
{
switch(bufPtr[1])
{
case 'd': // Kd = diffuse
{
bufPtr = readColor(bufPtr, currMaterial->Meshbuffer->Material.DiffuseColor, bufEnd);
}
break;
case 's': // Ks = specular
{
bufPtr = readColor(bufPtr, currMaterial->Meshbuffer->Material.SpecularColor, bufEnd);
}
break;
case 'a': // Ka = ambience
{
bufPtr=readColor(bufPtr, currMaterial->Meshbuffer->Material.AmbientColor, bufEnd);
}
break;
case 'e': // Ke = emissive
{
bufPtr=readColor(bufPtr, currMaterial->Meshbuffer->Material.EmissiveColor, bufEnd);
}
break;
} // end switch(bufPtr[1])
} // end case 'K': if ( 0 != currMaterial )...
break;
case 'b': // bump
case 'm': // texture maps
if (currMaterial)
{
bufPtr=readTextures(bufPtr, bufEnd, currMaterial, relPath);
}
break;
case 'd': // d - transparency
if ( currMaterial )
{
const u32 COLOR_BUFFER_LENGTH = 16;
c8 dStr[COLOR_BUFFER_LENGTH];
bufPtr = goAndCopyNextWord(dStr, bufPtr, COLOR_BUFFER_LENGTH, bufEnd);
f32 dValue = core::fast_atof(dStr);
currMaterial->Meshbuffer->Material.DiffuseColor.setAlpha( (s32)(dValue * 255) );
if (dValue<1.0f)
currMaterial->Meshbuffer->Material.MaterialType = video::EMT_TRANSPARENT_VERTEX_ALPHA;
}
break;
case 'T':
if ( currMaterial )
{
switch ( bufPtr[1] )
{
case 'f': // Tf - Transmitivity
const u32 COLOR_BUFFER_LENGTH = 16;
c8 redStr[COLOR_BUFFER_LENGTH];
c8 greenStr[COLOR_BUFFER_LENGTH];
c8 blueStr[COLOR_BUFFER_LENGTH];
bufPtr = goAndCopyNextWord(redStr, bufPtr, COLOR_BUFFER_LENGTH, bufEnd);
bufPtr = goAndCopyNextWord(greenStr, bufPtr, COLOR_BUFFER_LENGTH, bufEnd);
bufPtr = goAndCopyNextWord(blueStr, bufPtr, COLOR_BUFFER_LENGTH, bufEnd);
f32 transparency = ( core::fast_atof(redStr) + core::fast_atof(greenStr) + core::fast_atof(blueStr) ) / 3;
currMaterial->Meshbuffer->Material.DiffuseColor.setAlpha( (s32)(transparency * 255) );
if (transparency < 1.0f)
currMaterial->Meshbuffer->Material.MaterialType = video::EMT_TRANSPARENT_VERTEX_ALPHA;
}
}
break;
default: // comments or not recognised
break;
} // end switch(bufPtr[0])
// go to next line
bufPtr = goNextLine(bufPtr, bufEnd);
} // end while (bufPtr)
// end of file. if there's an existing material, store it
if ( currMaterial )
Materials.push_back( currMaterial );
delete [] buf;
mtlReader->drop();
}
//! Read RGB color
const c8* COBJMeshFileLoader::readColor(const c8* bufPtr, video::SColor& color, const c8* const bufEnd)
{
const u32 COLOR_BUFFER_LENGTH = 16;
c8 colStr[COLOR_BUFFER_LENGTH];
color.setAlpha(255);
bufPtr = goAndCopyNextWord(colStr, bufPtr, COLOR_BUFFER_LENGTH, bufEnd);
color.setRed((s32)(core::fast_atof(colStr) * 255.0f));
bufPtr = goAndCopyNextWord(colStr, bufPtr, COLOR_BUFFER_LENGTH, bufEnd);
color.setGreen((s32)(core::fast_atof(colStr) * 255.0f));
bufPtr = goAndCopyNextWord(colStr, bufPtr, COLOR_BUFFER_LENGTH, bufEnd);
color.setBlue((s32)(core::fast_atof(colStr) * 255.0f));
return bufPtr;
}
//! Read 3d vector of floats
const c8* COBJMeshFileLoader::readVec3(const c8* bufPtr, core::vector3df& vec, const c8* const bufEnd)
{
const u32 WORD_BUFFER_LENGTH = 256;
c8 wordBuffer[WORD_BUFFER_LENGTH];
bufPtr = goAndCopyNextWord(wordBuffer, bufPtr, WORD_BUFFER_LENGTH, bufEnd);
vec.X=-core::fast_atof(wordBuffer); // change handedness
bufPtr = goAndCopyNextWord(wordBuffer, bufPtr, WORD_BUFFER_LENGTH, bufEnd);
vec.Y=core::fast_atof(wordBuffer);
bufPtr = goAndCopyNextWord(wordBuffer, bufPtr, WORD_BUFFER_LENGTH, bufEnd);
vec.Z=core::fast_atof(wordBuffer);
return bufPtr;
}
//! Read 2d vector of floats
const c8* COBJMeshFileLoader::readUV(const c8* bufPtr, core::vector2df& vec, const c8* const bufEnd)
{
const u32 WORD_BUFFER_LENGTH = 256;
c8 wordBuffer[WORD_BUFFER_LENGTH];
bufPtr = goAndCopyNextWord(wordBuffer, bufPtr, WORD_BUFFER_LENGTH, bufEnd);
vec.X=core::fast_atof(wordBuffer);
bufPtr = goAndCopyNextWord(wordBuffer, bufPtr, WORD_BUFFER_LENGTH, bufEnd);
vec.Y=1-core::fast_atof(wordBuffer); // change handedness
return bufPtr;
}
//! Read boolean value represented as 'on' or 'off'
const c8* COBJMeshFileLoader::readBool(const c8* bufPtr, bool& tf, const c8* const bufEnd)
{
const u32 BUFFER_LENGTH = 8;
c8 tfStr[BUFFER_LENGTH];
bufPtr = goAndCopyNextWord(tfStr, bufPtr, BUFFER_LENGTH, bufEnd);
tf = strcmp(tfStr, "off") != 0;
return bufPtr;
}
COBJMeshFileLoader::SObjMtl* COBJMeshFileLoader::findMtl(const core::stringc& mtlName, const core::stringc& grpName)
{
COBJMeshFileLoader::SObjMtl* defMaterial = 0;
// search existing Materials for best match
// exact match does return immediately, only name match means a new group
for (u32 i = 0; i < Materials.size(); ++i)
{
if ( Materials[i]->Name == mtlName )
{
if ( Materials[i]->Group == grpName )
return Materials[i];
else
defMaterial = Materials[i];
}
}
// we found a partial match
if (defMaterial)
{
Materials.push_back(new SObjMtl(*defMaterial));
Materials.getLast()->Group = grpName;
return Materials.getLast();
}
// we found a new group for a non-existant material
else if (grpName.size())
{
Materials.push_back(new SObjMtl(*Materials[0]));
Materials.getLast()->Group = grpName;
return Materials.getLast();
}
return 0;
}
//! skip space characters and stop on first non-space
const c8* COBJMeshFileLoader::goFirstWord(const c8* buf, const c8* const bufEnd, bool acrossNewlines)
{
// skip space characters
if (acrossNewlines)
while((buf != bufEnd) && core::isspace(*buf))
++buf;
else
while((buf != bufEnd) && core::isspace(*buf) && (*buf != '\n'))
++buf;
return buf;
}
//! skip current word and stop at beginning of next one
const c8* COBJMeshFileLoader::goNextWord(const c8* buf, const c8* const bufEnd, bool acrossNewlines)
{
// skip current word
while(( buf != bufEnd ) && !core::isspace(*buf))
++buf;
return goFirstWord(buf, bufEnd, acrossNewlines);
}
//! Read until line break is reached and stop at the next non-space character
const c8* COBJMeshFileLoader::goNextLine(const c8* buf, const c8* const bufEnd)
{
// look for newline characters
while(buf != bufEnd)
{
// found it, so leave
if (*buf=='\n' || *buf=='\r')
break;
++buf;
}
return goFirstWord(buf, bufEnd);
}
u32 COBJMeshFileLoader::copyWord(c8* outBuf, const c8* const inBuf, u32 outBufLength, const c8* const bufEnd)
{
if (!outBufLength)
return 0;
if (!inBuf)
{
*outBuf = 0;
return 0;
}
u32 i = 0;
while(inBuf[i])
{
if (core::isspace(inBuf[i]) || &(inBuf[i]) == bufEnd)
break;
++i;
}
u32 length = core::min_(i, outBufLength-1);
for (u32 j=0; j<length; ++j)
outBuf[j] = inBuf[j];
outBuf[length] = 0;
return length;
}
core::stringc COBJMeshFileLoader::copyLine(const c8* inBuf, const c8* bufEnd)
{
if (!inBuf)
return core::stringc();
const c8* ptr = inBuf;
while (ptr<bufEnd)
{
if (*ptr=='\n' || *ptr=='\r')
break;
++ptr;
}
// we must avoid the +1 in case the array is used up
return core::stringc(inBuf, (u32)(ptr-inBuf+((ptr < bufEnd) ? 1 : 0)));
}
const c8* COBJMeshFileLoader::goAndCopyNextWord(c8* outBuf, const c8* inBuf, u32 outBufLength, const c8* bufEnd)
{
inBuf = goNextWord(inBuf, bufEnd, false);
copyWord(outBuf, inBuf, outBufLength, bufEnd);
return inBuf;
}
bool COBJMeshFileLoader::retrieveVertexIndices(c8* vertexData, s32* idx, const c8* bufEnd, u32 vbsize, u32 vtsize, u32 vnsize)
{
c8 word[16] = "";
const c8* p = goFirstWord(vertexData, bufEnd);
u32 idxType = 0; // 0 = posIdx, 1 = texcoordIdx, 2 = normalIdx
u32 i = 0;
while ( p != bufEnd )
{
if ( ( core::isdigit(*p)) || (*p == '-') )
{
// build up the number
word[i++] = *p;
}
else if ( *p == '/' || *p == ' ' || *p == '\0' )
{
// number is completed. Convert and store it
word[i] = '\0';
// if no number was found index will become 0 and later on -1 by decrement
idx[idxType] = core::strtol10(word);
if (idx[idxType]<0)
{
switch (idxType)
{
case 0:
idx[idxType] += vbsize;
break;
case 1:
idx[idxType] += vtsize;
break;
case 2:
idx[idxType] += vnsize;
break;
}
}
else
idx[idxType]-=1;
// reset the word
word[0] = '\0';
i = 0;
// go to the next kind of index type
if (*p == '/')
{
if ( ++idxType > 2 )
{
// error checking, shouldn't reach here unless file is wrong
idxType = 0;
}
}
else
{
// set all missing values to disable (=-1)
while (++idxType < 3)
idx[idxType]=-1;
++p;
break; // while
}
}
// go to the next char
++p;
}
return true;
}
void COBJMeshFileLoader::cleanUp()
{
for (u32 i=0; i < Materials.size(); ++i )
{
Materials[i]->Meshbuffer->drop();
delete Materials[i];
}
Materials.clear();
}
} // end namespace scene
} // end namespace irr
#endif // _IRR_COMPILE_WITH_OBJ_LOADER_

View File

@ -1,122 +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_OBJ_MESH_FILE_LOADER_H_INCLUDED__
#define __C_OBJ_MESH_FILE_LOADER_H_INCLUDED__
#include "IMeshLoader.h"
#include "IFileSystem.h"
#include "ISceneManager.h"
#include "irrString.h"
#include "SMeshBuffer.h"
#include "irrMap.h"
namespace irr
{
namespace scene
{
//! Meshloader capable of loading obj meshes.
class COBJMeshFileLoader : public IMeshLoader
{
public:
//! Constructor
COBJMeshFileLoader(scene::ISceneManager* smgr, io::IFileSystem* fs);
//! destructor
virtual ~COBJMeshFileLoader();
//! returns true if the file maybe is able to be loaded by this class
//! based on the file extension (e.g. ".obj")
virtual bool isALoadableFileExtension(const io::path& filename) const;
//! creates/loads an animated mesh from the file.
//! \return Pointer to the created mesh. Returns 0 if loading failed.
//! If you no longer need the mesh, you should call IAnimatedMesh::drop().
//! See IReferenceCounted::drop() for more information.
virtual IAnimatedMesh* createMesh(io::IReadFile* file);
private:
struct SObjMtl
{
SObjMtl() : Meshbuffer(0), Bumpiness (1.0f), Illumination(0),
RecalculateNormals(false)
{
Meshbuffer = new SMeshBuffer();
Meshbuffer->Material.Shininess = 0.0f;
Meshbuffer->Material.AmbientColor = video::SColorf(0.2f, 0.2f, 0.2f, 1.0f).toSColor();
Meshbuffer->Material.DiffuseColor = video::SColorf(0.8f, 0.8f, 0.8f, 1.0f).toSColor();
Meshbuffer->Material.SpecularColor = video::SColorf(1.0f, 1.0f, 1.0f, 1.0f).toSColor();
}
SObjMtl(const SObjMtl& o)
: Name(o.Name), Group(o.Group),
Bumpiness(o.Bumpiness), Illumination(o.Illumination),
RecalculateNormals(false)
{
Meshbuffer = new SMeshBuffer();
Meshbuffer->Material = o.Meshbuffer->Material;
}
core::map<video::S3DVertex, int> VertMap;
scene::SMeshBuffer *Meshbuffer;
core::stringc Name;
core::stringc Group;
f32 Bumpiness;
c8 Illumination;
bool RecalculateNormals;
};
// helper method for material reading
const c8* readTextures(const c8* bufPtr, const c8* const bufEnd, SObjMtl* currMaterial, const io::path& relPath);
// returns a pointer to the first printable character available in the buffer
const c8* goFirstWord(const c8* buf, const c8* const bufEnd, bool acrossNewlines=true);
// returns a pointer to the first printable character after the first non-printable
const c8* goNextWord(const c8* buf, const c8* const bufEnd, bool acrossNewlines=true);
// returns a pointer to the next printable character after the first line break
const c8* goNextLine(const c8* buf, const c8* const bufEnd);
// copies the current word from the inBuf to the outBuf
u32 copyWord(c8* outBuf, const c8* inBuf, u32 outBufLength, const c8* const pBufEnd);
// copies the current line from the inBuf to the outBuf
core::stringc copyLine(const c8* inBuf, const c8* const bufEnd);
// combination of goNextWord followed by copyWord
const c8* goAndCopyNextWord(c8* outBuf, const c8* inBuf, u32 outBufLength, const c8* const pBufEnd);
//! Read the material from the given file
void readMTL(const c8* fileName, const io::path& relPath);
//! Find and return the material with the given name
SObjMtl* findMtl(const core::stringc& mtlName, const core::stringc& grpName);
//! Read RGB color
const c8* readColor(const c8* bufPtr, video::SColor& color, const c8* const pBufEnd);
//! Read 3d vector of floats
const c8* readVec3(const c8* bufPtr, core::vector3df& vec, const c8* const pBufEnd);
//! Read 2d vector of floats
const c8* readUV(const c8* bufPtr, core::vector2df& vec, const c8* const pBufEnd);
//! Read boolean value represented as 'on' or 'off'
const c8* readBool(const c8* bufPtr, bool& tf, const c8* const bufEnd);
// reads and convert to integer the vertex indices in a line of obj file's face statement
// -1 for the index if it doesn't exist
// indices are changed to 0-based index instead of 1-based from the obj file
bool retrieveVertexIndices(c8* vertexData, s32* idx, const c8* bufEnd, u32 vbsize, u32 vtsize, u32 vnsize);
void cleanUp();
scene::ISceneManager* SceneManager;
io::IFileSystem* FileSystem;
core::array<SObjMtl*> Materials;
};
} // end namespace scene
} // end namespace irr
#endif

View File

@ -1,243 +0,0 @@
// Copyright (C) 2008-2012 Christian Stehno
// This file is part of the "Irrlicht Engine".
// For conditions of distribution and use, see copyright notice in irrlicht.h
#include "IrrCompileConfig.h"
#ifdef _IRR_COMPILE_WITH_OBJ_WRITER_
#include "COBJMeshWriter.h"
#include "os.h"
#include "IMesh.h"
#include "IMeshBuffer.h"
#include "IAttributes.h"
#include "ISceneManager.h"
#include "IMeshCache.h"
#include "IWriteFile.h"
#include "IFileSystem.h"
#include "ITexture.h"
namespace irr
{
namespace scene
{
COBJMeshWriter::COBJMeshWriter(scene::ISceneManager* smgr, io::IFileSystem* fs)
: SceneManager(smgr), FileSystem(fs)
{
#ifdef _DEBUG
setDebugName("COBJMeshWriter");
#endif
if (SceneManager)
SceneManager->grab();
if (FileSystem)
FileSystem->grab();
}
COBJMeshWriter::~COBJMeshWriter()
{
if (SceneManager)
SceneManager->drop();
if (FileSystem)
FileSystem->drop();
}
//! Returns the type of the mesh writer
EMESH_WRITER_TYPE COBJMeshWriter::getType() const
{
return EMWT_OBJ;
}
//! writes a mesh
bool COBJMeshWriter::writeMesh(io::IWriteFile* file, scene::IMesh* mesh, s32 flags)
{
if (!file)
return false;
os::Printer::log("Writing mesh", file->getFileName());
// write OBJ MESH header
const core::stringc name(FileSystem->getFileBasename(SceneManager->getMeshCache()->getMeshName(mesh), false)+".mtl");
file->write("# exported by Irrlicht\n",23);
file->write("mtllib ",7);
file->write(name.c_str(),name.size());
file->write("\n\n",2);
// write mesh buffers
core::array<video::SMaterial*> mat;
u32 allVertexCount=1; // count vertices over the whole file
for (u32 i=0; i<mesh->getMeshBufferCount(); ++i)
{
core::stringc num(i+1);
IMeshBuffer* buffer = mesh->getMeshBuffer(i);
if (buffer && buffer->getVertexCount())
{
file->write("g grp", 5);
file->write(num.c_str(), num.size());
file->write("\n",1);
u32 j;
const u32 vertexCount = buffer->getVertexCount();
for (j=0; j<vertexCount; ++j)
{
file->write("v ",2);
getVectorAsStringLine(buffer->getPosition(j), num);
file->write(num.c_str(), num.size());
}
for (j=0; j<vertexCount; ++j)
{
file->write("vt ",3);
getVectorAsStringLine(buffer->getTCoords(j), num);
file->write(num.c_str(), num.size());
}
for (j=0; j<vertexCount; ++j)
{
file->write("vn ",3);
getVectorAsStringLine(buffer->getNormal(j), num);
file->write(num.c_str(), num.size());
}
file->write("usemtl mat",10);
num = "";
for (j=0; j<mat.size(); ++j)
{
if (*mat[j]==buffer->getMaterial())
{
num = core::stringc(j);
break;
}
}
if (num == "")
{
num = core::stringc(mat.size());
mat.push_back(&buffer->getMaterial());
}
file->write(num.c_str(), num.size());
file->write("\n",1);
const u32 indexCount = buffer->getIndexCount();
for (j=0; j<indexCount; j+=3)
{
file->write("f ",2);
num = core::stringc(buffer->getIndices()[j+2]+allVertexCount);
file->write(num.c_str(), num.size());
file->write("/",1);
file->write(num.c_str(), num.size());
file->write("/",1);
file->write(num.c_str(), num.size());
file->write(" ",1);
num = core::stringc(buffer->getIndices()[j+1]+allVertexCount);
file->write(num.c_str(), num.size());
file->write("/",1);
file->write(num.c_str(), num.size());
file->write("/",1);
file->write(num.c_str(), num.size());
file->write(" ",1);
num = core::stringc(buffer->getIndices()[j+0]+allVertexCount);
file->write(num.c_str(), num.size());
file->write("/",1);
file->write(num.c_str(), num.size());
file->write("/",1);
file->write(num.c_str(), num.size());
file->write(" ",1);
file->write("\n",1);
}
file->write("\n",1);
allVertexCount += vertexCount;
}
}
if (mat.size() == 0)
return true;
file = FileSystem->createAndWriteFile( name );
if (file)
{
os::Printer::log("Writing material", file->getFileName());
file->write("# exported by Irrlicht\n\n",24);
for (u32 i=0; i<mat.size(); ++i)
{
core::stringc num(i);
file->write("newmtl mat",10);
file->write(num.c_str(),num.size());
file->write("\n",1);
getColorAsStringLine(mat[i]->AmbientColor, "Ka", num);
file->write(num.c_str(),num.size());
getColorAsStringLine(mat[i]->DiffuseColor, "Kd", num);
file->write(num.c_str(),num.size());
getColorAsStringLine(mat[i]->SpecularColor, "Ks", num);
file->write(num.c_str(),num.size());
getColorAsStringLine(mat[i]->EmissiveColor, "Ke", num);
file->write(num.c_str(),num.size());
num = core::stringc((double)(mat[i]->Shininess/0.128f));
file->write("Ns ", 3);
file->write(num.c_str(),num.size());
file->write("\n", 1);
if (mat[i]->getTexture(0))
{
file->write("map_Kd ", 7);
file->write(mat[i]->getTexture(0)->getName().getPath().c_str(), mat[i]->getTexture(0)->getName().getPath().size());
file->write("\n",1);
}
file->write("\n",1);
}
file->drop();
}
return true;
}
void COBJMeshWriter::getVectorAsStringLine(const core::vector3df& v, core::stringc& s) const
{
s = core::stringc(-v.X);
s += " ";
s += core::stringc(v.Y);
s += " ";
s += core::stringc(v.Z);
s += "\n";
}
void COBJMeshWriter::getVectorAsStringLine(const core::vector2df& v, core::stringc& s) const
{
s = core::stringc(v.X);
s += " ";
s += core::stringc(-v.Y);
s += "\n";
}
void COBJMeshWriter::getColorAsStringLine(const video::SColor& color, const c8* const prefix, core::stringc& s) const
{
s = prefix;
s += " ";
s += core::stringc((double)(color.getRed()/255.f));
s += " ";
s += core::stringc((double)(color.getGreen()/255.f));
s += " ";
s += core::stringc((double)(color.getBlue()/255.f));
s += "\n";
}
} // end namespace
} // end namespace
#endif

View File

@ -1,58 +0,0 @@
// Copyright (C) 2008-2012 Christian Stehno
// This file is part of the "Irrlicht Engine".
// For conditions of distribution and use, see copyright notice in irrlicht.h
#ifndef __IRR_OBJ_MESH_WRITER_H_INCLUDED__
#define __IRR_OBJ_MESH_WRITER_H_INCLUDED__
#include "IMeshWriter.h"
#include "S3DVertex.h"
#include "irrString.h"
namespace irr
{
namespace io
{
class IFileSystem;
} // end namespace io
namespace scene
{
class IMeshBuffer;
class ISceneManager;
//! class to write meshes, implementing a OBJ writer
class COBJMeshWriter : public IMeshWriter
{
public:
COBJMeshWriter(scene::ISceneManager* smgr, io::IFileSystem* fs);
virtual ~COBJMeshWriter();
//! Returns the type of the mesh writer
virtual EMESH_WRITER_TYPE getType() const;
//! writes a mesh
virtual bool writeMesh(io::IWriteFile* file, scene::IMesh* mesh, s32 flags=EMWF_NONE);
protected:
// create vector output with line end into string
void getVectorAsStringLine(const core::vector3df& v,
core::stringc& s) const;
// create vector output with line end into string
void getVectorAsStringLine(const core::vector2df& v,
core::stringc& s) const;
// create color output with line end into string
void getColorAsStringLine(const video::SColor& color,
const c8* const prefix, core::stringc& s) const;
scene::ISceneManager* SceneManager;
io::IFileSystem* FileSystem;
};
} // end namespace
} // end namespace
#endif

View File

@ -1,336 +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
//
// originally written by Murphy McCauley, see COCTLoader.h for details.
//
// COCTLoader by Murphy McCauley (February 2005)
// An Irrlicht loader for OCT files
//
// See the header file for additional information including use and distribution rights.
#include "IrrCompileConfig.h"
#ifdef _IRR_COMPILE_WITH_OCT_LOADER_
#include "COCTLoader.h"
#include "IVideoDriver.h"
#include "IFileSystem.h"
#include "os.h"
#include "SAnimatedMesh.h"
#include "SMeshBufferLightMap.h"
#include "irrString.h"
#include "ISceneManager.h"
namespace irr
{
namespace scene
{
//! constructor
COCTLoader::COCTLoader(ISceneManager* smgr, io::IFileSystem* fs)
: SceneManager(smgr), FileSystem(fs)
{
#ifdef _DEBUG
setDebugName("COCTLoader");
#endif
if (FileSystem)
FileSystem->grab();
}
//! destructor
COCTLoader::~COCTLoader()
{
if (FileSystem)
FileSystem->drop();
}
// Doesn't really belong here, but it's jammed in for now.
void COCTLoader::OCTLoadLights(io::IReadFile* file, scene::ISceneNode * parent, f32 radius, f32 intensityScale, bool rewind)
{
if (rewind)
file->seek(0);
octHeader header;
file->read(&header, sizeof(octHeader));
file->seek(sizeof(octVert)*header.numVerts, true);
file->seek(sizeof(octFace)*header.numFaces, true);
file->seek(sizeof(octTexture)*header.numTextures, true);
file->seek(sizeof(octLightmap)*header.numLightmaps, true);
octLight * lights = new octLight[header.numLights];
file->read(lights, header.numLights * sizeof(octLight));
//TODO: Skip past my extended data just for good form
for (u32 i = 0; i < header.numLights; i++)
{
const f32 intensity = lights[i].intensity * intensityScale;
SceneManager->addLightSceneNode(parent, core::vector3df(lights[i].pos[0], lights[i].pos[2], lights[i].pos[1]),
video::SColorf(lights[i].color[0] * intensity, lights[i].color[1] * intensity, lights[i].color[2] * intensity, 1.0f),
radius);
}
}
//! creates/loads an animated mesh from the file.
//! \return Pointer to the created mesh. Returns 0 if loading failed.
//! If you no longer need the mesh, you should call IAnimatedMesh::drop().
//! See IReferenceCounted::drop() for more information.
IAnimatedMesh* COCTLoader::createMesh(io::IReadFile* file)
{
if (!file)
return 0;
octHeader header;
file->read(&header, sizeof(octHeader));
octVert * verts = new octVert[header.numVerts];
octFace * faces = new octFace[header.numFaces];
octTexture * textures = new octTexture[header.numTextures];
octLightmap * lightmaps = new octLightmap[header.numLightmaps];
octLight * lights = new octLight[header.numLights];
file->read(verts, sizeof(octVert) * header.numVerts);
file->read(faces, sizeof(octFace) * header.numFaces);
//TODO: Make sure id is in the legal range for Textures and Lightmaps
u32 i;
for (i = 0; i < header.numTextures; i++) {
octTexture t;
file->read(&t, sizeof(octTexture));
textures[t.id] = t;
}
for (i = 0; i < header.numLightmaps; i++) {
octLightmap t;
file->read(&t, sizeof(octLightmap));
lightmaps[t.id] = t;
}
file->read(lights, sizeof(octLight) * header.numLights);
//TODO: Now read in my extended OCT header (flexible lightmaps and vertex normals)
// This is the method Nikolaus Gebhardt used in the Q3 loader -- create a
// meshbuffer for every possible combination of lightmap and texture including
// a "null" texture and "null" lightmap. Ones that end up with nothing in them
// will be removed later.
SMesh * Mesh = new SMesh();
for (i=0; i<(header.numTextures+1) * (header.numLightmaps+1); ++i)
{
scene::SMeshBufferLightMap* buffer = new scene::SMeshBufferLightMap();
buffer->Material.MaterialType = video::EMT_LIGHTMAP;
buffer->Material.Lighting = false;
Mesh->addMeshBuffer(buffer);
buffer->drop();
}
// Build the mesh buffers
for (i = 0; i < header.numFaces; i++)
{
if (faces[i].numVerts < 3)
continue;
const f32* const a = verts[faces[i].firstVert].pos;
const f32* const b = verts[faces[i].firstVert+1].pos;
const f32* const c = verts[faces[i].firstVert+2].pos;
const core::vector3df normal =
core::plane3df(core::vector3df(a[0],a[1],a[2]), core::vector3df(b[0],c[1],c[2]), core::vector3df(c[0],c[1],c[2])).Normal;
const u32 textureID = core::min_(s32(faces[i].textureID), s32(header.numTextures - 1)) + 1;
const u32 lightmapID = core::min_(s32(faces[i].lightmapID),s32(header.numLightmaps - 1)) + 1;
SMeshBufferLightMap * meshBuffer = (SMeshBufferLightMap*)Mesh->getMeshBuffer(lightmapID * (header.numTextures + 1) + textureID);
const u32 base = meshBuffer->Vertices.size();
// Add this face's verts
u32 v;
for (v = 0; v < faces[i].numVerts; ++v)
{
octVert * vv = &verts[faces[i].firstVert + v];
video::S3DVertex2TCoords vert;
vert.Pos.set(vv->pos[0], vv->pos[1], vv->pos[2]);
vert.Color = video::SColor(0,255,255,255);
vert.Normal.set(normal);
if (textureID == 0)
{
// No texture -- just a lightmap. Thus, use lightmap coords for texture 1.
// (the actual texture will be swapped later)
vert.TCoords.set(vv->lc[0], vv->lc[1]);
}
else
{
vert.TCoords.set(vv->tc[0], vv->tc[1]);
vert.TCoords2.set(vv->lc[0], vv->lc[1]);
}
meshBuffer->Vertices.push_back(vert);
}
// Now add the indices
// This weird loop turns convex polygons into triangle strips.
// I do it this way instead of a simple fan because it usually looks a lot better in wireframe, for example.
// High, Low
u32 h = faces[i].numVerts - 1;
u32 l = 0;
for (v = 0; v < faces[i].numVerts - 2; ++v)
{
const u32 center = (v & 1)? h - 1: l + 1;
meshBuffer->Indices.push_back(base + h);
meshBuffer->Indices.push_back(base + l);
meshBuffer->Indices.push_back(base + center);
if (v & 1)
--h;
else
++l;
}
}
// load textures
core::array<video::ITexture*> tex;
tex.reallocate(header.numTextures + 1);
tex.push_back(0);
const core::stringc relpath = FileSystem->getFileDir(file->getFileName())+"/";
for (i = 1; i < (header.numTextures + 1); i++)
{
core::stringc path(textures[i-1].fileName);
path.replace('\\','/');
if (FileSystem->existFile(path))
tex.push_back(SceneManager->getVideoDriver()->getTexture(path));
else
// try to read in the relative path of the OCT file
tex.push_back(SceneManager->getVideoDriver()->getTexture( (relpath + path) ));
}
// prepare lightmaps
core::array<video::ITexture*> lig;
lig.set_used(header.numLightmaps + 1);
lig[0] = 0;
const u32 lightmapWidth = 128;
const u32 lightmapHeight = 128;
const core::dimension2d<u32> lmapsize(lightmapWidth, lightmapHeight);
bool oldMipMapState = SceneManager->getVideoDriver()->getTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS);
SceneManager->getVideoDriver()->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, false);
video::IImage* tmpImage = SceneManager->getVideoDriver()->createImage(video::ECF_R8G8B8, lmapsize);
for (i = 1; i < (header.numLightmaps + 1); ++i)
{
core::stringc lightmapname = file->getFileName();
lightmapname += ".lightmap.";
lightmapname += (int)i;
const octLightmap* lm = &lightmaps[i-1];
for (u32 x=0; x<lightmapWidth; ++x)
{
for (u32 y=0; y<lightmapHeight; ++y)
{
tmpImage->setPixel(x, y,
video::SColor(255,
lm->data[x][y][2],
lm->data[x][y][1],
lm->data[x][y][0]));
}
}
lig[i] = SceneManager->getVideoDriver()->addTexture(lightmapname.c_str(), tmpImage);
}
tmpImage->drop();
SceneManager->getVideoDriver()->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, oldMipMapState);
// Free stuff
delete [] verts;
delete [] faces;
delete [] textures;
delete [] lightmaps;
delete [] lights;
// attach materials
for (i = 0; i < header.numLightmaps + 1; i++)
{
for (u32 j = 0; j < header.numTextures + 1; j++)
{
u32 mb = i * (header.numTextures + 1) + j;
SMeshBufferLightMap * meshBuffer = (SMeshBufferLightMap*)Mesh->getMeshBuffer(mb);
meshBuffer->Material.setTexture(0, tex[j]);
meshBuffer->Material.setTexture(1, lig[i]);
if (meshBuffer->Material.getTexture(0) == 0)
{
// This material has no texture, so we'll just show the lightmap if there is one.
// We swapped the texture coordinates earlier.
meshBuffer->Material.setTexture(0, meshBuffer->Material.getTexture(1));
meshBuffer->Material.setTexture(1, 0);
}
if (meshBuffer->Material.getTexture(1) == 0)
{
// If there is only one texture, it should be solid and lit.
// Among other things, this way you can preview OCT lights.
meshBuffer->Material.MaterialType = video::EMT_SOLID;
meshBuffer->Material.Lighting = true;
}
}
}
// delete all buffers without geometry in it.
i = 0;
while(i < Mesh->MeshBuffers.size())
{
if (Mesh->MeshBuffers[i]->getVertexCount() == 0 ||
Mesh->MeshBuffers[i]->getIndexCount() == 0 ||
Mesh->MeshBuffers[i]->getMaterial().getTexture(0) == 0)
{
// Meshbuffer is empty -- drop it
Mesh->MeshBuffers[i]->drop();
Mesh->MeshBuffers.erase(i);
}
else
{
++i;
}
}
// create bounding box
for (i = 0; i < Mesh->MeshBuffers.size(); ++i)
{
Mesh->MeshBuffers[i]->recalculateBoundingBox();
}
Mesh->recalculateBoundingBox();
// Set up an animated mesh to hold the mesh
SAnimatedMesh* AMesh = new SAnimatedMesh();
AMesh->Type = EAMT_OCT;
AMesh->addMesh(Mesh);
AMesh->recalculateBoundingBox();
Mesh->drop();
return AMesh;
}
//! returns true if the file maybe is able to be loaded by this class
//! based on the file extension (e.g. ".bsp")
bool COCTLoader::isALoadableFileExtension(const io::path& filename) const
{
return core::hasFileExtension ( filename, "oct" );
}
} // end namespace scene
} // end namespace irr
#endif // _IRR_COMPILE_WITH_OCT_LOADER_

View File

@ -1,141 +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
//
// Because I (Nikolaus Gebhardt) did some changes to Murphy McCauley's loader,
// I'm writing this down here:
// - Replaced all dependencies to STL and stdio with irr:: methods/constructs
// - Disabled logging define
// - Changed some minor things (Don't remember what exactly.)
// Thanks a lot to Murphy McCauley for writing this loader.
//
// COCTLoader by Murphy McCauley (February 2005)
// An Irrlicht loader for OCT files
//
// OCT file format information comes from the sourcecode of the Fluid Studios
// Radiosity Processor by Paul Nettle. You can get that sourcecode from
// http://www.fluidstudios.com .
//
// Parts of this code are from Irrlicht's CQ3LevelMesh and C3DSMeshFileLoader,
// and are Copyright (C) 2002-2004 Nikolaus Gebhardt.
//
// Use of this code is subject to the following:
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
// arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it
// freely, subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented; you must not
// claim that you wrote the original software. If you use this software
// in a product, an acknowledgment in the product documentation would be
// appreciated but is not required.
// 2. Altered source versions must be plainly marked as such, and must not be
// misrepresented as being the original software.
// 3. This notice may not be removed or altered from any source distribution.
// 4. You may not use this software to directly or indirectly cause harm to others.
#ifndef __C_OCT_LOADER_H_INCLUDED__
#define __C_OCT_LOADER_H_INCLUDED__
#include "IMeshLoader.h"
#include "IReadFile.h"
#include "SMesh.h"
#include "irrString.h"
namespace irr
{
namespace io
{
class IFileSystem;
} // end namespace io
namespace scene
{
class ISceneManager;
class ISceneNode;
class COCTLoader : public IMeshLoader
{
public:
//! constructor
COCTLoader(ISceneManager* smgr, io::IFileSystem* fs);
//! destructor
virtual ~COCTLoader();
//! returns true if the file maybe is able to be loaded by this class
//! based on the file extension (e.g. ".cob")
virtual bool isALoadableFileExtension(const io::path& filename) const;
//! creates/loads an animated mesh from the file.
//! \return Pointer to the created mesh. Returns 0 if loading failed.
//! If you no longer need the mesh, you should call IAnimatedMesh::drop().
//! See IReferenceCounted::drop() for more information.
virtual IAnimatedMesh* createMesh(io::IReadFile* file);
void OCTLoadLights(io::IReadFile* file,
ISceneNode * parent = 0, f32 radius = 500.0f,
f32 intensityScale = 0.0000001f*2.5,
bool rewind = true);
private:
struct octHeader {
u32 numVerts;
u32 numFaces;
u32 numTextures;
u32 numLightmaps;
u32 numLights;
};
struct octHeaderEx {
u32 magic; // 'OCTX' - 0x4F435458L
u32 numLightmaps;
u32 lightmapWidth;
u32 lightmapHeight;
u32 containsVertexNormals;
};
struct octFace {
u32 firstVert;
u32 numVerts;
u32 textureID;
u32 lightmapID;
f32 plane[4];
};
struct octVert {
f32 tc[2];
f32 lc[2];
f32 pos[3];
};
struct octTexture {
u32 id;
char fileName[64];
};
struct octLightmap {
u32 id;
u8 data[128][128][3];
};
struct octLight {
f32 pos[3];
f32 color[3];
u32 intensity;
};
ISceneManager* SceneManager;
io::IFileSystem* FileSystem;
};
} // end namespace scene
} // end namespace irr
#endif

View File

@ -50,10 +50,6 @@ COpenGLDriver::COpenGLDriver(const irr::SIrrlichtCreationParameters& params,
#ifdef _DEBUG
setDebugName("COpenGLDriver");
#endif
#ifdef _IRR_COMPILE_WITH_CG_
CgContext = 0;
#endif
}
@ -585,10 +581,6 @@ COpenGLDriver::COpenGLDriver(const SIrrlichtCreationParameters& params,
setDebugName("COpenGLDriver");
#endif
#ifdef _IRR_COMPILE_WITH_CG_
CgContext = 0;
#endif
genericDriverInit();
}
@ -611,10 +603,6 @@ COpenGLDriver::COpenGLDriver(const SIrrlichtCreationParameters& params,
#ifdef _DEBUG
setDebugName("COpenGLDriver");
#endif
#ifdef _IRR_COMPILE_WITH_CG_
CgContext = 0;
#endif
}
@ -705,10 +693,6 @@ COpenGLDriver::COpenGLDriver(const SIrrlichtCreationParameters& params,
setDebugName("COpenGLDriver");
#endif
#ifdef _IRR_COMPILE_WITH_CG_
CgContext = 0;
#endif
genericDriverInit();
}
@ -718,11 +702,6 @@ COpenGLDriver::COpenGLDriver(const SIrrlichtCreationParameters& params,
//! destructor
COpenGLDriver::~COpenGLDriver()
{
#ifdef _IRR_COMPILE_WITH_CG_
if (CgContext)
cgDestroyContext(CgContext);
#endif
RequestedLights.clear();
deleteMaterialRenders();
@ -868,10 +847,6 @@ bool COpenGLDriver::genericDriverInit()
// This fixes problems with intermediate changes to the material during texture load.
ResetRenderStates = true;
#ifdef _IRR_COMPILE_WITH_CG_
CgContext = cgCreateContext();
#endif
return true;
}
@ -4091,21 +4066,6 @@ s32 COpenGLDriver::addHighLevelShaderMaterial(
{
s32 nr = -1;
#ifdef _IRR_COMPILE_WITH_CG_
if (shadingLang == EGSL_CG)
{
COpenGLCgMaterialRenderer* r = new COpenGLCgMaterialRenderer(
this, nr,
vertexShaderProgram, vertexShaderEntryPointName, vsCompileTarget,
pixelShaderProgram, pixelShaderEntryPointName, psCompileTarget,
geometryShaderProgram, geometryShaderEntryPointName, gsCompileTarget,
inType, outType, verticesOut,
callback,getMaterialRenderer(baseMaterial), userData);
r->drop();
}
else
#endif
{
COpenGLSLMaterialRenderer* r = new COpenGLSLMaterialRenderer(
this, nr,
@ -4878,13 +4838,6 @@ GLenum COpenGLDriver::getZBufferBits() const
return bits;
}
#ifdef _IRR_COMPILE_WITH_CG_
const CGcontext& COpenGLDriver::getCgContext()
{
return CgContext;
}
#endif
} // end namespace
} // end namespace

View File

@ -25,10 +25,6 @@ namespace irr
#include "COpenGLExtensionHandler.h"
#include "COpenGLTexture.h"
#ifdef _IRR_COMPILE_WITH_CG_
#include "Cg/cg.h"
#endif
namespace irr
{
@ -411,11 +407,6 @@ namespace video
//! sets the needed renderstates
void setRenderStates3DMode();
//! Get Cg context
#ifdef _IRR_COMPILE_WITH_CG_
const CGcontext& getCgContext();
#endif
private:
//! clears the zbuffer and color buffer
@ -600,9 +591,6 @@ namespace video
#ifdef _IRR_COMPILE_WITH_SDL_DEVICE_
CIrrDeviceSDL *SDLDevice;
#endif
#ifdef _IRR_COMPILE_WITH_CG_
CGcontext CgContext;
#endif
E_DEVICE_TYPE DeviceType;
};

View File

@ -791,10 +791,6 @@ bool COpenGLExtensionHandler::queryFeature(E_VIDEO_DRIVER_FEATURE feature) const
return (Version>=120) || FeatureAvailable[IRR_EXT_blend_minmax] ||
FeatureAvailable[IRR_EXT_blend_subtract] || FeatureAvailable[IRR_EXT_blend_logic_op];
case EVDF_TEXTURE_MATRIX:
#ifdef _IRR_COMPILE_WITH_CG_
// available iff. define is present
case EVDF_CG:
#endif
return true;
default:
return false;

View File

@ -1,817 +0,0 @@
// Copyright (C) 2009-2012 Gaz Davidson
// This file is part of the "Irrlicht Engine".
// For conditions of distribution and use, see copyright notice in irrlicht.h
#include "IrrCompileConfig.h"
#ifdef _IRR_COMPILE_WITH_PLY_LOADER_
#include "CPLYMeshFileLoader.h"
#include "IMeshManipulator.h"
#include "SMesh.h"
#include "CDynamicMeshBuffer.h"
#include "SAnimatedMesh.h"
#include "IReadFile.h"
#include "fast_atof.h"
#include "os.h"
namespace irr
{
namespace scene
{
// input buffer must be at least twice as long as the longest line in the file
#define PLY_INPUT_BUFFER_SIZE 51200 // file is loaded in 50k chunks
// constructor
CPLYMeshFileLoader::CPLYMeshFileLoader(scene::ISceneManager* smgr)
: SceneManager(smgr), File(0), Buffer(0)
{
}
CPLYMeshFileLoader::~CPLYMeshFileLoader()
{
// delete the buffer in case we didn't earlier
// (we do, but this could be disabled to increase the speed of loading hundreds of meshes)
if (Buffer)
{
delete [] Buffer;
Buffer = 0;
}
// Destroy the element list if it exists
for (u32 i=0; i<ElementList.size(); ++i)
delete ElementList[i];
ElementList.clear();
}
//! returns true if the file maybe is able to be loaded by this class
bool CPLYMeshFileLoader::isALoadableFileExtension(const io::path& filename) const
{
return core::hasFileExtension(filename, "ply");
}
//! creates/loads an animated mesh from the file.
IAnimatedMesh* CPLYMeshFileLoader::createMesh(io::IReadFile* file)
{
if (!file)
return 0;
File = file;
File->grab();
// attempt to allocate the buffer and fill with data
if (!allocateBuffer())
{
File->drop();
File = 0;
return 0;
}
// start with empty mesh
SAnimatedMesh* animMesh = 0;
u32 vertCount=0;
// Currently only supports ASCII meshes
if (strcmp(getNextLine(), "ply"))
{
os::Printer::log("Not a valid PLY file", file->getFileName().c_str(), ELL_ERROR);
}
else
{
// cut the next line out
getNextLine();
// grab the word from this line
c8 *word = getNextWord();
// ignore comments
while (strcmp(word, "comment") == 0)
{
getNextLine();
word = getNextWord();
}
bool readingHeader = true;
bool continueReading = true;
IsBinaryFile = false;
IsWrongEndian= false;
do
{
if (strcmp(word, "format") == 0)
{
word = getNextWord();
if (strcmp(word, "binary_little_endian") == 0)
{
IsBinaryFile = true;
#ifdef __BIG_ENDIAN__
IsWrongEndian = true;
#endif
}
else if (strcmp(word, "binary_big_endian") == 0)
{
IsBinaryFile = true;
#ifndef __BIG_ENDIAN__
IsWrongEndian = true;
#endif
}
else if (strcmp(word, "ascii"))
{
// abort if this isn't an ascii or a binary mesh
os::Printer::log("Unsupported PLY mesh format", word, ELL_ERROR);
continueReading = false;
}
if (continueReading)
{
word = getNextWord();
if (strcmp(word, "1.0"))
{
os::Printer::log("Unsupported PLY mesh version", word, ELL_WARNING);
}
}
}
else if (strcmp(word, "property") == 0)
{
word = getNextWord();
if (!ElementList.size())
{
os::Printer::log("PLY property found before element", word, ELL_WARNING);
}
else
{
// get element
SPLYElement* el = ElementList[ElementList.size()-1];
// fill property struct
SPLYProperty prop;
prop.Type = getPropertyType(word);
el->KnownSize += prop.size();
if (prop.Type == EPLYPT_LIST)
{
el->IsFixedWidth = false;
word = getNextWord();
prop.Data.List.CountType = getPropertyType(word);
if (IsBinaryFile && prop.Data.List.CountType == EPLYPT_UNKNOWN)
{
os::Printer::log("Cannot read binary PLY file containing data types of unknown length", word, ELL_ERROR);
continueReading = false;
}
else
{
word = getNextWord();
prop.Data.List.ItemType = getPropertyType(word);
if (IsBinaryFile && prop.Data.List.ItemType == EPLYPT_UNKNOWN)
{
os::Printer::log("Cannot read binary PLY file containing data types of unknown length", word, ELL_ERROR);
continueReading = false;
}
}
}
else if (IsBinaryFile && prop.Type == EPLYPT_UNKNOWN)
{
os::Printer::log("Cannot read binary PLY file containing data types of unknown length", word, ELL_ERROR);
continueReading = false;
}
prop.Name = getNextWord();
// add property to element
el->Properties.push_back(prop);
}
}
else if (strcmp(word, "element") == 0)
{
SPLYElement* el = new SPLYElement;
el->Name = getNextWord();
el->Count = atoi(getNextWord());
el->IsFixedWidth = true;
el->KnownSize = 0;
ElementList.push_back(el);
if (el->Name == "vertex")
vertCount = el->Count;
}
else if (strcmp(word, "end_header") == 0)
{
readingHeader = false;
if (IsBinaryFile)
{
StartPointer = LineEndPointer + 1;
}
}
else if (strcmp(word, "comment") == 0)
{
// ignore line
}
else
{
os::Printer::log("Unknown item in PLY file", word, ELL_WARNING);
}
if (readingHeader && continueReading)
{
getNextLine();
word = getNextWord();
}
}
while (readingHeader && continueReading);
// now to read the actual data from the file
if (continueReading)
{
// create a mesh buffer
CDynamicMeshBuffer *mb = new CDynamicMeshBuffer(video::EVT_STANDARD, vertCount > 65565 ? video::EIT_32BIT : video::EIT_16BIT);
mb->getVertexBuffer().reallocate(vertCount);
mb->getIndexBuffer().reallocate(vertCount);
mb->setHardwareMappingHint(EHM_STATIC);
bool hasNormals=true;
// loop through each of the elements
for (u32 i=0; i<ElementList.size(); ++i)
{
// do we want this element type?
if (ElementList[i]->Name == "vertex")
{
// loop through vertex properties
for (u32 j=0; j < ElementList[i]->Count; ++j)
hasNormals &= readVertex(*ElementList[i], mb);
}
else if (ElementList[i]->Name == "face")
{
// read faces
for (u32 j=0; j < ElementList[i]->Count; ++j)
readFace(*ElementList[i], mb);
}
else
{
// skip these elements
for (u32 j=0; j < ElementList[i]->Count; ++j)
skipElement(*ElementList[i]);
}
}
mb->recalculateBoundingBox();
if (!hasNormals)
SceneManager->getMeshManipulator()->recalculateNormals(mb);
SMesh* m = new SMesh();
m->addMeshBuffer(mb);
m->recalculateBoundingBox();
mb->drop();
animMesh = new SAnimatedMesh();
animMesh->addMesh(m);
animMesh->recalculateBoundingBox();
m->drop();
}
}
// free the buffer
delete [] Buffer;
Buffer = 0;
File->drop();
File = 0;
// if we managed to create a mesh, return it
return animMesh;
}
bool CPLYMeshFileLoader::readVertex(const SPLYElement &Element, scene::CDynamicMeshBuffer* mb)
{
if (!IsBinaryFile)
getNextLine();
video::S3DVertex vert;
vert.Color.set(255,255,255,255);
vert.TCoords.X = 0.0f;
vert.TCoords.Y = 0.0f;
vert.Normal.X = 0.0f;
vert.Normal.Y = 1.0f;
vert.Normal.Z = 0.0f;
bool result=false;
for (u32 i=0; i < Element.Properties.size(); ++i)
{
E_PLY_PROPERTY_TYPE t = Element.Properties[i].Type;
if (Element.Properties[i].Name == "x")
vert.Pos.X = getFloat(t);
else if (Element.Properties[i].Name == "y")
vert.Pos.Z = getFloat(t);
else if (Element.Properties[i].Name == "z")
vert.Pos.Y = getFloat(t);
else if (Element.Properties[i].Name == "nx")
{
vert.Normal.X = getFloat(t);
result=true;
}
else if (Element.Properties[i].Name == "ny")
{
vert.Normal.Z = getFloat(t);
result=true;
}
else if (Element.Properties[i].Name == "nz")
{
vert.Normal.Y = getFloat(t);
result=true;
}
else if (Element.Properties[i].Name == "u")
vert.TCoords.X = getFloat(t);
else if (Element.Properties[i].Name == "v")
vert.TCoords.Y = getFloat(t);
else if (Element.Properties[i].Name == "red")
{
u32 value = Element.Properties[i].isFloat() ? (u32)(getFloat(t)*255.0f) : getInt(t);
vert.Color.setRed(value);
}
else if (Element.Properties[i].Name == "green")
{
u32 value = Element.Properties[i].isFloat() ? (u32)(getFloat(t)*255.0f) : getInt(t);
vert.Color.setGreen(value);
}
else if (Element.Properties[i].Name == "blue")
{
u32 value = Element.Properties[i].isFloat() ? (u32)(getFloat(t)*255.0f) : getInt(t);
vert.Color.setBlue(value);
}
else if (Element.Properties[i].Name == "alpha")
{
u32 value = Element.Properties[i].isFloat() ? (u32)(getFloat(t)*255.0f) : getInt(t);
vert.Color.setAlpha(value);
}
else
skipProperty(Element.Properties[i]);
}
mb->getVertexBuffer().push_back(vert);
return result;
}
bool CPLYMeshFileLoader::readFace(const SPLYElement &Element, scene::CDynamicMeshBuffer* mb)
{
if (!IsBinaryFile)
getNextLine();
for (u32 i=0; i < Element.Properties.size(); ++i)
{
if ( (Element.Properties[i].Name == "vertex_indices" ||
Element.Properties[i].Name == "vertex_index") && Element.Properties[i].Type == EPLYPT_LIST)
{
// get count
s32 count = getInt(Element.Properties[i].Data.List.CountType);
u32 a = getInt(Element.Properties[i].Data.List.ItemType),
b = getInt(Element.Properties[i].Data.List.ItemType),
c = getInt(Element.Properties[i].Data.List.ItemType);
s32 j = 3;
mb->getIndexBuffer().push_back(a);
mb->getIndexBuffer().push_back(c);
mb->getIndexBuffer().push_back(b);
for (; j < count; ++j)
{
b = c;
c = getInt(Element.Properties[i].Data.List.ItemType);
mb->getIndexBuffer().push_back(a);
mb->getIndexBuffer().push_back(c);
mb->getIndexBuffer().push_back(b);
}
}
else if (Element.Properties[i].Name == "intensity")
{
// todo: face intensity
skipProperty(Element.Properties[i]);
}
else
skipProperty(Element.Properties[i]);
}
return true;
}
// skips an element and all properties. return false on EOF
void CPLYMeshFileLoader::skipElement(const SPLYElement &Element)
{
if (IsBinaryFile)
if (Element.IsFixedWidth)
moveForward(Element.KnownSize);
else
for (u32 i=0; i < Element.Properties.size(); ++i)
skipProperty(Element.Properties[i]);
else
getNextLine();
}
void CPLYMeshFileLoader::skipProperty(const SPLYProperty &Property)
{
if (Property.Type == EPLYPT_LIST)
{
s32 count = getInt(Property.Data.List.CountType);
for (s32 i=0; i < count; ++i)
getInt(Property.Data.List.CountType);
}
else
{
if (IsBinaryFile)
moveForward(Property.size());
else
getNextWord();
}
}
bool CPLYMeshFileLoader::allocateBuffer()
{
// Destroy the element list if it exists
for (u32 i=0; i<ElementList.size(); ++i)
delete ElementList[i];
ElementList.clear();
if (!Buffer)
Buffer = new c8[PLY_INPUT_BUFFER_SIZE];
// not enough memory?
if (!Buffer)
return false;
// blank memory
memset(Buffer, 0, PLY_INPUT_BUFFER_SIZE);
StartPointer = Buffer;
EndPointer = Buffer;
LineEndPointer = Buffer-1;
WordLength = -1;
EndOfFile = false;
// get data from the file
fillBuffer();
return true;
}
// gets more data from the file. returns false on EOF
void CPLYMeshFileLoader::fillBuffer()
{
if (EndOfFile)
return;
u32 length = (u32)(EndPointer - StartPointer);
if (length && StartPointer != Buffer)
{
// copy the remaining data to the start of the buffer
memcpy(Buffer, StartPointer, length);
}
// reset start position
StartPointer = Buffer;
EndPointer = StartPointer + length;
if (File->getPos() == File->getSize())
{
EndOfFile = true;
}
else
{
// read data from the file
u32 count = File->read(EndPointer, PLY_INPUT_BUFFER_SIZE - length);
// increment the end pointer by the number of bytes read
EndPointer = EndPointer + count;
// if we didn't completely fill the buffer
if (count != PLY_INPUT_BUFFER_SIZE - length)
{
// blank the rest of the memory
memset(EndPointer, 0, Buffer + PLY_INPUT_BUFFER_SIZE - EndPointer);
// end of file
EndOfFile = true;
}
}
}
// skips x bytes in the file, getting more data if required
void CPLYMeshFileLoader::moveForward(u32 bytes)
{
if (StartPointer + bytes >= EndPointer)
fillBuffer();
if (StartPointer + bytes < EndPointer)
StartPointer += bytes;
else
StartPointer = EndPointer;
}
E_PLY_PROPERTY_TYPE CPLYMeshFileLoader::getPropertyType(const c8* typeString) const
{
if (strcmp(typeString, "char") == 0 ||
strcmp(typeString, "uchar") == 0 ||
strcmp(typeString, "int8") == 0 ||
strcmp(typeString, "uint8") == 0)
{
return EPLYPT_INT8;
}
else if (strcmp(typeString, "uint") == 0 ||
strcmp(typeString, "int16") == 0 ||
strcmp(typeString, "uint16") == 0 ||
strcmp(typeString, "short") == 0 ||
strcmp(typeString, "ushort") == 0)
{
return EPLYPT_INT16;
}
else if (strcmp(typeString, "int") == 0 ||
strcmp(typeString, "long") == 0 ||
strcmp(typeString, "ulong") == 0 ||
strcmp(typeString, "int32") == 0 ||
strcmp(typeString, "uint32") == 0)
{
return EPLYPT_INT32;
}
else if (strcmp(typeString, "float") == 0 ||
strcmp(typeString, "float32") == 0)
{
return EPLYPT_FLOAT32;
}
else if (strcmp(typeString, "float64") == 0 ||
strcmp(typeString, "double") == 0)
{
return EPLYPT_FLOAT64;
}
else if ( strcmp(typeString, "list") == 0 )
{
return EPLYPT_LIST;
}
else
{
// unsupported type.
// cannot be loaded in binary mode
return EPLYPT_UNKNOWN;
}
}
// Split the string data into a line in place by terminating it instead of copying.
c8* CPLYMeshFileLoader::getNextLine()
{
// move the start pointer along
StartPointer = LineEndPointer + 1;
// crlf split across buffer move
if (*StartPointer == '\n')
{
*StartPointer = '\0';
++StartPointer;
}
// begin at the start of the next line
c8* pos = StartPointer;
while (pos < EndPointer && *pos && *pos != '\r' && *pos != '\n')
++pos;
if ( pos < EndPointer && ( *(pos+1) == '\r' || *(pos+1) == '\n') )
{
*pos = '\0';
++pos;
}
// we have reached the end of the buffer
if (pos >= EndPointer)
{
// get data from the file
if (!EndOfFile)
{
fillBuffer();
// reset line end pointer
LineEndPointer = StartPointer - 1;
if (StartPointer != EndPointer)
return getNextLine();
else
return Buffer;
}
else
{
// EOF
StartPointer = EndPointer-1;
*StartPointer = '\0';
return StartPointer;
}
}
else
{
// null terminate the string in place
*pos = '\0';
LineEndPointer = pos;
WordLength = -1;
// return pointer to the start of the line
return StartPointer;
}
}
// null terminate the next word on the previous line and move the next word pointer along
// since we already have a full line in the buffer, we never need to retrieve more data
c8* CPLYMeshFileLoader::getNextWord()
{
// move the start pointer along
StartPointer += WordLength + 1;
if (StartPointer == LineEndPointer)
{
WordLength = -1; //
return LineEndPointer;
}
// begin at the start of the next word
c8* pos = StartPointer;
while (*pos && pos < LineEndPointer && pos < EndPointer && *pos != ' ' && *pos != '\t')
++pos;
while(*pos && pos < LineEndPointer && pos < EndPointer && (*pos == ' ' || *pos == '\t') )
{
// null terminate the string in place
*pos = '\0';
++pos;
}
--pos;
WordLength = (s32)(pos-StartPointer);
// return pointer to the start of the word
return StartPointer;
}
// read the next float from the file and move the start pointer along
f32 CPLYMeshFileLoader::getFloat(E_PLY_PROPERTY_TYPE t)
{
f32 retVal = 0.0f;
if (IsBinaryFile)
{
if (EndPointer - StartPointer < 8)
fillBuffer();
if (EndPointer - StartPointer > 0)
{
switch (t)
{
case EPLYPT_INT8:
retVal = *StartPointer;
StartPointer++;
break;
case EPLYPT_INT16:
if (IsWrongEndian)
retVal = os::Byteswap::byteswap(*(reinterpret_cast<s16*>(StartPointer)));
else
retVal = *(reinterpret_cast<s16*>(StartPointer));
StartPointer += 2;
break;
case EPLYPT_INT32:
if (IsWrongEndian)
retVal = f32(os::Byteswap::byteswap(*(reinterpret_cast<s32*>(StartPointer))));
else
retVal = f32(*(reinterpret_cast<s32*>(StartPointer)));
StartPointer += 4;
break;
case EPLYPT_FLOAT32:
if (IsWrongEndian)
retVal = os::Byteswap::byteswap(*(reinterpret_cast<f32*>(StartPointer)));
else
retVal = *(reinterpret_cast<f32*>(StartPointer));
StartPointer += 4;
break;
case EPLYPT_FLOAT64:
// todo: byteswap 64-bit
retVal = f32(*(reinterpret_cast<f64*>(StartPointer)));
StartPointer += 8;
break;
case EPLYPT_LIST:
case EPLYPT_UNKNOWN:
default:
retVal = 0.0f;
StartPointer++; // ouch!
}
}
else
retVal = 0.0f;
}
else
{
c8* word = getNextWord();
switch (t)
{
case EPLYPT_INT8:
case EPLYPT_INT16:
case EPLYPT_INT32:
retVal = f32(atoi(word));
break;
case EPLYPT_FLOAT32:
case EPLYPT_FLOAT64:
retVal = f32(atof(word));
break;
case EPLYPT_LIST:
case EPLYPT_UNKNOWN:
default:
retVal = 0.0f;
}
}
return retVal;
}
// read the next int from the file and move the start pointer along
u32 CPLYMeshFileLoader::getInt(E_PLY_PROPERTY_TYPE t)
{
u32 retVal = 0;
if (IsBinaryFile)
{
if (!EndOfFile && EndPointer - StartPointer < 8)
fillBuffer();
if (EndPointer - StartPointer)
{
switch (t)
{
case EPLYPT_INT8:
retVal = *StartPointer;
StartPointer++;
break;
case EPLYPT_INT16:
if (IsWrongEndian)
retVal = os::Byteswap::byteswap(*(reinterpret_cast<u16*>(StartPointer)));
else
retVal = *(reinterpret_cast<u16*>(StartPointer));
StartPointer += 2;
break;
case EPLYPT_INT32:
if (IsWrongEndian)
retVal = os::Byteswap::byteswap(*(reinterpret_cast<s32*>(StartPointer)));
else
retVal = *(reinterpret_cast<s32*>(StartPointer));
StartPointer += 4;
break;
case EPLYPT_FLOAT32:
if (IsWrongEndian)
retVal = (u32)os::Byteswap::byteswap(*(reinterpret_cast<f32*>(StartPointer)));
else
retVal = (u32)(*(reinterpret_cast<f32*>(StartPointer)));
StartPointer += 4;
break;
case EPLYPT_FLOAT64:
// todo: byteswap 64-bit
retVal = (u32)(*(reinterpret_cast<f64*>(StartPointer)));
StartPointer += 8;
break;
case EPLYPT_LIST:
case EPLYPT_UNKNOWN:
default:
retVal = 0;
StartPointer++; // ouch!
}
}
else
retVal = 0;
}
else
{
c8* word = getNextWord();
switch (t)
{
case EPLYPT_INT8:
case EPLYPT_INT16:
case EPLYPT_INT32:
retVal = atoi(word);
break;
case EPLYPT_FLOAT32:
case EPLYPT_FLOAT64:
retVal = u32(atof(word));
break;
case EPLYPT_LIST:
case EPLYPT_UNKNOWN:
default:
retVal = 0;
}
}
return retVal;
}
} // end namespace scene
} // end namespace irr
#endif // _IRR_COMPILE_WITH_PLY_LOADER_

View File

@ -1,148 +0,0 @@
// Copyright (C) 2009-2012 Gaz Davidson
// This file is part of the "Irrlicht Engine".
// For conditions of distribution and use, see copyright notice in irrlicht.h
#ifndef __C_PLY_MESH_FILE_LOADER_H_INCLUDED__
#define __C_PLY_MESH_FILE_LOADER_H_INCLUDED__
#include "IMeshLoader.h"
#include "ISceneManager.h"
#include "CDynamicMeshBuffer.h"
namespace irr
{
namespace scene
{
enum E_PLY_PROPERTY_TYPE
{
EPLYPT_INT8 = 0,
EPLYPT_INT16,
EPLYPT_INT32,
EPLYPT_FLOAT32,
EPLYPT_FLOAT64,
EPLYPT_LIST,
EPLYPT_UNKNOWN
};
//! Meshloader capable of loading obj meshes.
class CPLYMeshFileLoader : public IMeshLoader
{
public:
//! Constructor
CPLYMeshFileLoader(scene::ISceneManager* smgr);
//! Destructor
virtual ~CPLYMeshFileLoader();
//! returns true if the file maybe is able to be loaded by this class
//! based on the file extension (e.g. ".ply")
virtual bool isALoadableFileExtension(const io::path& filename) const;
//! creates/loads an animated mesh from the file.
virtual IAnimatedMesh* createMesh(io::IReadFile* file);
private:
struct SPLYProperty
{
core::stringc Name;
E_PLY_PROPERTY_TYPE Type;
union
{
u8 Int8;
u16 Int16;
u32 Int32;
f32 Float32;
f64 Double;
struct SPLYListProperty
{
E_PLY_PROPERTY_TYPE CountType;
E_PLY_PROPERTY_TYPE ItemType;
} List;
} Data;
inline u32 size() const
{
switch(Type)
{
case EPLYPT_INT8:
return 1;
case EPLYPT_INT16:
return 2;
case EPLYPT_INT32:
case EPLYPT_FLOAT32:
return 4;
case EPLYPT_FLOAT64:
return 8;
case EPLYPT_LIST:
case EPLYPT_UNKNOWN:
default:
return 0;
}
}
inline bool isFloat() const
{
switch(Type)
{
case EPLYPT_FLOAT32:
case EPLYPT_FLOAT64:
return true;
case EPLYPT_INT8:
case EPLYPT_INT16:
case EPLYPT_INT32:
case EPLYPT_LIST:
case EPLYPT_UNKNOWN:
default:
return false;
}
}
};
struct SPLYElement
{
// name of the element. We only want "vertex" and "face" elements
// but we have to parse the others anyway.
core::stringc Name;
// The number of elements in the file
u32 Count;
// Properties of this element
core::array<SPLYProperty> Properties;
// in binary files, true if this is a fixed size
bool IsFixedWidth;
// known size in bytes, 0 if unknown
u32 KnownSize;
};
bool allocateBuffer();
c8* getNextLine();
c8* getNextWord();
void fillBuffer();
E_PLY_PROPERTY_TYPE getPropertyType(const c8* typeString) const;
bool readVertex(const SPLYElement &Element, scene::CDynamicMeshBuffer* mb);
bool readFace(const SPLYElement &Element, scene::CDynamicMeshBuffer* mb);
void skipElement(const SPLYElement &Element);
void skipProperty(const SPLYProperty &Property);
f32 getFloat(E_PLY_PROPERTY_TYPE t);
u32 getInt(E_PLY_PROPERTY_TYPE t);
void moveForward(u32 bytes);
core::array<SPLYElement*> ElementList;
scene::ISceneManager* SceneManager;
io::IReadFile *File;
c8 *Buffer;
bool IsBinaryFile, IsWrongEndian, EndOfFile;
s32 LineLength, WordLength;
c8 *StartPointer, *EndPointer, *LineEndPointer;
};
} // end namespace scene
} // end namespace irr
#endif

View File

@ -1,183 +0,0 @@
// Copyright (C) 2008-2012 Christian Stehno
// This file is part of the "Irrlicht Engine".
// For conditions of distribution and use, see copyright notice in irrlicht.h
#include "IrrCompileConfig.h"
#ifdef _IRR_COMPILE_WITH_PLY_WRITER_
#include "CPLYMeshWriter.h"
#include "os.h"
#include "IMesh.h"
#include "IMeshBuffer.h"
#include "IWriteFile.h"
namespace irr
{
namespace scene
{
CPLYMeshWriter::CPLYMeshWriter()
{
#ifdef _DEBUG
setDebugName("CPLYMeshWriter");
#endif
}
//! Returns the type of the mesh writer
EMESH_WRITER_TYPE CPLYMeshWriter::getType() const
{
return EMWT_PLY;
}
//! writes a mesh
bool CPLYMeshWriter::writeMesh(io::IWriteFile* file, scene::IMesh* mesh, s32 flags)
{
if (!file || !mesh)
return false;
os::Printer::log("Writing mesh", file->getFileName());
// write PLY header
core::stringc header =
"ply\n"
"format ascii 1.0\n"
"comment Irrlicht Engine ";
header += IRRLICHT_SDK_VERSION;
// get vertex and triangle counts
u32 VertexCount = 0;
u32 TriangleCount = 0;
for (u32 i=0; i < mesh->getMeshBufferCount(); ++i)
{
VertexCount += mesh->getMeshBuffer(i)->getVertexCount();
TriangleCount += mesh->getMeshBuffer(i)->getIndexCount() / 3;
}
// vertex definition
header += "\nelement vertex ";
header += VertexCount;
header += "\n"
"property float x\n"
"property float y\n"
"property float z\n"
"property float nx\n"
"property float ny\n"
"property float nz\n";
// todo: writer flags for extended (r,g,b,u,v) and non-standard (alpha,u1,uv,tx,ty,tz) properties
// "property uchar red\n"
// "property uchar green\n"
// "property uchar blue\n"
// "property uchar alpha\n"
// "property float u\n"
// "property float v\n";
// "property float u1\n
// "property float v1\n"
// "property float tx\n"
// "property float ty\n"
// "property float tz\n"
// face definition
header += "element face ";
header += TriangleCount;
header += "\n"
"property list uchar int vertex_indices\n"
"end_header\n";
// write header
file->write(header.c_str(), header.size());
// write vertices
c8 outLine[1024];
for (u32 i=0; i < mesh->getMeshBufferCount(); ++i)
{
scene::IMeshBuffer* mb = mesh->getMeshBuffer(i);
for (u32 j=0; j < mb->getVertexCount(); ++j)
{
const core::vector3df& pos = mb->getPosition(j);
const core::vector3df& n = mb->getNormal(j);
// const core::vector2df& tc = mb->getTCoords(j);
u8 *buf = (u8*)mb->getVertices();
switch(mb->getVertexType())
{
case video::EVT_STANDARD:
buf += sizeof(video::S3DVertex)*j;
break;
case video::EVT_2TCOORDS:
buf += sizeof(video::S3DVertex2TCoords)*j;
break;
case video::EVT_TANGENTS:
buf += sizeof(video::S3DVertexTangents)*j;
break;
}
// video::SColor &col = ( (video::S3DVertex*)buf )->Color;
// x y z nx ny nz red green blue alpha u v [u1 v1 | tx ty tz]\n
snprintf(outLine, 1024,
"%f %f %f %f %f %f\n",// %u %u %u %u %f %f\n",
pos.X, pos.Z, pos.Y, // Y and Z are flipped
n.X, n.Z, n.Y);
/*col.getRed(), col.getGreen(), col.getBlue(), col.getAlpha(),
tc.X, tc.Y);*/
// write the line
file->write(outLine, strlen(outLine));
}
}
// index of the first vertex in the current mesh buffer
u32 StartOffset = 0;
// write triangles
for (u32 i=0; i < mesh->getMeshBufferCount(); ++i)
{
scene::IMeshBuffer* mb = mesh->getMeshBuffer(i);
for (u32 j=0; j < mb->getIndexCount(); j+=3)
{
// y and z are flipped so triangles are reversed
u32 a=StartOffset,
b=StartOffset,
c=StartOffset;
switch(mb->getIndexType())
{
case video::EIT_16BIT:
a += mb->getIndices()[j+0];
c += mb->getIndices()[j+1];
b += mb->getIndices()[j+2];
break;
case video::EIT_32BIT:
a += ((u32*)mb->getIndices()) [j+0];
c += ((u32*)mb->getIndices()) [j+0];
b += ((u32*)mb->getIndices()) [j+0];
break;
}
// count a b c\n
snprintf(outLine, 1024, "3 %u %u %u\n", a, b, c);
// write the line
file->write(outLine, strlen(outLine));
}
// increment offset
StartOffset += mb->getVertexCount();
}
// all done!
return true;
}
} // end namespace
} // end namespace
#endif // _IRR_COMPILE_WITH_PLY_WRITER_

View File

@ -1,35 +0,0 @@
// Copyright (C) 2009-2012 Gaz Davidson
// This file is part of the "Irrlicht Engine".
// For conditions of distribution and use, see copyright notice in irrlicht.h
#ifndef __IRR_PLY_MESH_WRITER_H_INCLUDED__
#define __IRR_PLY_MESH_WRITER_H_INCLUDED__
#include "IMeshWriter.h"
namespace irr
{
namespace scene
{
class IMeshBuffer;
//! class to write PLY mesh files
class CPLYMeshWriter : public IMeshWriter
{
public:
CPLYMeshWriter();
//! Returns the type of the mesh writer
virtual EMESH_WRITER_TYPE getType() const;
//! writes a mesh
virtual bool writeMesh(io::IWriteFile* file, scene::IMesh* mesh, s32 flags=EMWF_NONE);
};
} // end namespace
} // end namespace
#endif

View File

@ -5,6 +5,7 @@
#include "CParticleAnimatedMeshSceneNodeEmitter.h"
#include "IAnimatedMeshSceneNode.h"
#include "IMesh.h"
#include "IMeshBuffer.h"
#include "os.h"
namespace irr

File diff suppressed because it is too large Load Diff

View File

@ -1,491 +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_Q3_LEVEL_MESH_H_INCLUDED__
#define __C_Q3_LEVEL_MESH_H_INCLUDED__
#include "IQ3LevelMesh.h"
#include "IReadFile.h"
#include "IFileSystem.h"
#include "SMesh.h"
#include "SMeshBufferLightMap.h"
#include "IVideoDriver.h"
#include "irrString.h"
#include "ISceneManager.h"
#include "os.h"
namespace irr
{
namespace scene
{
class CQ3LevelMesh : public IQ3LevelMesh
{
public:
//! constructor
CQ3LevelMesh(io::IFileSystem* fs, scene::ISceneManager* smgr,
const quake3::Q3LevelLoadParameter &loadParam);
//! destructor
virtual ~CQ3LevelMesh();
//! loads a level from a .bsp-File. Also tries to load all
//! needed textures. Returns true if successful.
bool loadFile(io::IReadFile* file);
//! returns the amount of frames in milliseconds. If the amount
//! is 1, it is a static (=non animated) mesh.
virtual u32 getFrameCount() const;
//! Gets the default animation speed of the animated mesh.
/** \return Amount of frames per second. If the amount is 0, it is a static, non animated mesh. */
virtual f32 getAnimationSpeed() const
{
return FramesPerSecond;
}
//! Gets the frame count of the animated mesh.
/** \param fps Frames per second to play the animation with. If the amount is 0, it is not animated.
The actual speed is set in the scene node the mesh is instantiated in.*/
virtual void setAnimationSpeed(f32 fps)
{
FramesPerSecond=fps;
}
//! returns the animated mesh based on a detail level. 0 is the
//! lowest, 255 the highest detail. Note, that some Meshes will
//! ignore the detail level.
virtual IMesh* getMesh(s32 frameInMs, s32 detailLevel=255,
s32 startFrameLoop=-1, s32 endFrameLoop=-1);
//! Returns an axis aligned bounding box of the mesh.
//! \return A bounding box of this mesh is returned.
virtual const core::aabbox3d<f32>& getBoundingBox() const;
virtual void setBoundingBox( const core::aabbox3df& box);
//! Returns the type of the animated mesh.
virtual E_ANIMATED_MESH_TYPE getMeshType() const;
//! loads the shader definition
virtual void getShader( io::IReadFile* file );
//! loads the shader definition
virtual const quake3::IShader * getShader( const c8 * filename, bool fileNameIsValid=true );
//! returns a already loaded Shader
virtual const quake3::IShader * getShader( u32 index ) const;
//! loads a configuration file
virtual void getConfiguration( io::IReadFile* file );
//! get's an interface to the entities
virtual quake3::tQ3EntityList & getEntityList();
//! returns the requested brush entity
virtual IMesh* getBrushEntityMesh(s32 num) const;
//! returns the requested brush entity
virtual IMesh* getBrushEntityMesh(quake3::IEntity &ent) const;
//Link to held meshes? ...
//! returns amount of mesh buffers.
virtual u32 getMeshBufferCount() const
{
return 0;
}
//! returns pointer to a mesh buffer
virtual IMeshBuffer* getMeshBuffer(u32 nr) const
{
return 0;
}
//! Returns pointer to a mesh buffer which fits a material
/** \param material: material to search for
\return Pointer to the mesh buffer or 0 if there is no such mesh buffer. */
virtual IMeshBuffer* getMeshBuffer( const video::SMaterial &material) const
{
return 0;
}
virtual void setMaterialFlag(video::E_MATERIAL_FLAG flag, bool newvalue)
{
return;
}
//! set the hardware mapping hint, for driver
virtual void setHardwareMappingHint(E_HARDWARE_MAPPING newMappingHint, E_BUFFER_TYPE buffer=EBT_VERTEX_AND_INDEX)
{
return;
}
//! flags the meshbuffer as changed, reloads hardware buffers
virtual void setDirty(E_BUFFER_TYPE buffer=EBT_VERTEX_AND_INDEX)
{
return;
}
private:
void constructMesh();
void solveTJunction();
void loadTextures();
scene::SMesh** buildMesh(s32 num);
struct STexShader
{
video::ITexture* Texture;
s32 ShaderID;
};
core::array< STexShader > Tex;
core::array<video::ITexture*> Lightmap;
enum eLumps
{
kEntities = 0, // Stores player/object positions, etc...
kShaders = 1, // Stores texture information
kPlanes = 2, // Stores the splitting planes
kNodes = 3, // Stores the BSP nodes
kLeafs = 4, // Stores the leafs of the nodes
kLeafFaces = 5, // Stores the leaf's indices into the faces
kLeafBrushes = 6, // Stores the leaf's indices into the brushes
kModels = 7, // Stores the info of world models
kBrushes = 8, // Stores the brushes info (for collision)
kBrushSides = 9, // Stores the brush surfaces info
kVertices = 10, // Stores the level vertices
kMeshVerts = 11, // Stores the model vertices offsets
kFogs = 12, // Stores the shader files (blending, anims..)
kFaces = 13, // Stores the faces for the level
kLightmaps = 14, // Stores the lightmaps for the level
kLightGrid = 15, // Stores extra world lighting information
kVisData = 16, // Stores PVS and cluster info (visibility)
kLightArray = 17, // RBSP
kMaxLumps // A constant to store the number of lumps
};
enum eBspSurfaceType
{
BSP_MST_BAD,
BSP_MST_PLANAR,
BSP_MST_PATCH,
BSP_MST_TRIANGLE_SOUP,
BSP_MST_FLARE,
BSP_MST_FOLIAGE
};
struct tBSPHeader
{
s32 strID; // This should always be 'IBSP'
s32 version; // This should be 0x2e for Quake 3 files
};
tBSPHeader header;
struct tBSPLump
{
s32 offset;
s32 length;
};
struct tBSPVertex
{
f32 vPosition[3]; // (x, y, z) position.
f32 vTextureCoord[2]; // (u, v) texture coordinate
f32 vLightmapCoord[2]; // (u, v) lightmap coordinate
f32 vNormal[3]; // (x, y, z) normal vector
u8 color[4]; // RGBA color for the vertex
};
struct tBSPFace
{
s32 textureID; // The index into the texture array
s32 fogNum; // The index for the effects (or -1 = n/a)
s32 type; // 1=polygon, 2=patch, 3=mesh, 4=billboard
s32 vertexIndex; // The index into this face's first vertex
s32 numOfVerts; // The number of vertices for this face
s32 meshVertIndex; // The index into the first meshvertex
s32 numMeshVerts; // The number of mesh vertices
s32 lightmapID; // The texture index for the lightmap
s32 lMapCorner[2]; // The face's lightmap corner in the image
s32 lMapSize[2]; // The size of the lightmap section
f32 lMapPos[3]; // The 3D origin of lightmap.
f32 lMapBitsets[2][3]; // The 3D space for s and t unit vectors.
f32 vNormal[3]; // The face normal.
s32 size[2]; // The bezier patch dimensions.
};
struct tBSPTexture
{
c8 strName[64]; // The name of the texture w/o the extension
u32 flags; // The surface flags (unknown)
u32 contents; // The content flags (unknown)
};
struct tBSPLightmap
{
u8 imageBits[128][128][3]; // The RGB data in a 128x128 image
};
struct tBSPNode
{
s32 plane; // The index into the planes array
s32 front; // The child index for the front node
s32 back; // The child index for the back node
s32 mins[3]; // The bounding box min position.
s32 maxs[3]; // The bounding box max position.
};
struct tBSPLeaf
{
s32 cluster; // The visibility cluster
s32 area; // The area portal
s32 mins[3]; // The bounding box min position
s32 maxs[3]; // The bounding box max position
s32 leafface; // The first index into the face array
s32 numOfLeafFaces; // The number of faces for this leaf
s32 leafBrush; // The first index for into the brushes
s32 numOfLeafBrushes; // The number of brushes for this leaf
};
struct tBSPPlane
{
f32 vNormal[3]; // Plane normal.
f32 d; // The plane distance from origin
};
struct tBSPVisData
{
s32 numOfClusters; // The number of clusters
s32 bytesPerCluster; // Bytes (8 bits) in the cluster's bitset
c8 *pBitsets; // Array of bytes holding the cluster vis.
};
struct tBSPBrush
{
s32 brushSide; // The starting brush side for the brush
s32 numOfBrushSides; // Number of brush sides for the brush
s32 textureID; // The texture index for the brush
};
struct tBSPBrushSide
{
s32 plane; // The plane index
s32 textureID; // The texture index
};
struct tBSPModel
{
f32 min[3]; // The min position for the bounding box
f32 max[3]; // The max position for the bounding box.
s32 faceIndex; // The first face index in the model
s32 numOfFaces; // The number of faces in the model
s32 brushIndex; // The first brush index in the model
s32 numOfBrushes; // The number brushes for the model
};
struct tBSPFog
{
c8 shader[64]; // The name of the shader file
s32 brushIndex; // The brush index for this shader
s32 visibleSide; // the brush side that ray tests need to clip against (-1 == none
};
core::array < STexShader > FogMap;
struct tBSPLights
{
u8 ambient[3]; // This is the ambient color in RGB
u8 directional[3]; // This is the directional color in RGB
u8 direction[2]; // The direction of the light: [phi,theta]
};
void loadTextures (tBSPLump* l, io::IReadFile* file); // Load the textures
void loadLightmaps (tBSPLump* l, io::IReadFile* file); // Load the lightmaps
void loadVerts (tBSPLump* l, io::IReadFile* file); // Load the vertices
void loadFaces (tBSPLump* l, io::IReadFile* file); // Load the faces
void loadPlanes (tBSPLump* l, io::IReadFile* file); // Load the Planes of the BSP
void loadNodes (tBSPLump* l, io::IReadFile* file); // load the Nodes of the BSP
void loadLeafs (tBSPLump* l, io::IReadFile* file); // load the Leafs of the BSP
void loadLeafFaces (tBSPLump* l, io::IReadFile* file); // load the Faces of the Leafs of the BSP
void loadVisData (tBSPLump* l, io::IReadFile* file); // load the visibility data of the clusters
void loadEntities (tBSPLump* l, io::IReadFile* file); // load the entities
void loadModels (tBSPLump* l, io::IReadFile* file); // load the models
void loadMeshVerts (tBSPLump* l, io::IReadFile* file); // load the mesh vertices
void loadBrushes (tBSPLump* l, io::IReadFile* file); // load the brushes of the BSP
void loadBrushSides (tBSPLump* l, io::IReadFile* file); // load the brushsides of the BSP
void loadLeafBrushes(tBSPLump* l, io::IReadFile* file); // load the brushes of the leaf
void loadFogs (tBSPLump* l, io::IReadFile* file); // load the shaders
//bi-quadratic bezier patches
void createCurvedSurface_bezier(SMeshBufferLightMap* meshBuffer,
s32 faceIndex, s32 patchTesselation, s32 storevertexcolor);
void createCurvedSurface_nosubdivision(SMeshBufferLightMap* meshBuffer,
s32 faceIndex, s32 patchTesselation, s32 storevertexcolor);
struct S3DVertex2TCoords_64
{
core::vector3d<f64> Pos;
core::vector3d<f64> Normal;
video::SColorf Color;
core::vector2d<f64> TCoords;
core::vector2d<f64> TCoords2;
void copy( video::S3DVertex2TCoords &dest ) const;
S3DVertex2TCoords_64() {}
S3DVertex2TCoords_64(const core::vector3d<f64>& pos, const core::vector3d<f64>& normal, const video::SColorf& color,
const core::vector2d<f64>& tcoords, const core::vector2d<f64>& tcoords2)
: Pos(pos), Normal(normal), Color(color), TCoords(tcoords), TCoords2(tcoords2) {}
S3DVertex2TCoords_64 getInterpolated_quadratic(const S3DVertex2TCoords_64& v2,
const S3DVertex2TCoords_64& v3, const f64 d) const
{
return S3DVertex2TCoords_64 (
Pos.getInterpolated_quadratic ( v2.Pos, v3.Pos, d ),
Normal.getInterpolated_quadratic ( v2.Normal, v3.Normal, d ),
Color.getInterpolated_quadratic ( v2.Color, v3.Color, (f32) d ),
TCoords.getInterpolated_quadratic ( v2.TCoords, v3.TCoords, d ),
TCoords2.getInterpolated_quadratic ( v2.TCoords2, v3.TCoords2, d ));
}
};
inline void copy( video::S3DVertex2TCoords * dest, const tBSPVertex * source,
s32 vertexcolor ) const;
void copy( S3DVertex2TCoords_64 * dest, const tBSPVertex * source, s32 vertexcolor ) const;
struct SBezier
{
SMeshBufferLightMap *Patch;
S3DVertex2TCoords_64 control[9];
void tesselate(s32 level);
private:
s32 Level;
core::array<S3DVertex2TCoords_64> column[3];
};
SBezier Bezier;
quake3::Q3LevelLoadParameter LoadParam;
tBSPLump Lumps[kMaxLumps];
tBSPTexture* Textures;
s32 NumTextures;
tBSPLightmap* LightMaps;
s32 NumLightMaps;
tBSPVertex* Vertices;
s32 NumVertices;
tBSPFace* Faces;
s32 NumFaces;
tBSPModel* Models;
s32 NumModels;
tBSPPlane* Planes;
s32 NumPlanes;
tBSPNode* Nodes;
s32 NumNodes;
tBSPLeaf* Leafs;
s32 NumLeafs;
s32 *LeafFaces;
s32 NumLeafFaces;
s32 *MeshVerts; // The vertex offsets for a mesh
s32 NumMeshVerts;
tBSPBrush* Brushes;
s32 NumBrushes;
scene::SMesh** BrushEntities;
scene::SMesh* Mesh[quake3::E_Q3_MESH_SIZE];
video::IVideoDriver* Driver;
core::stringc LevelName;
io::IFileSystem* FileSystem; // needs because there are no file extenstions stored in .bsp files.
// Additional content
scene::ISceneManager* SceneManager;
enum eToken
{
Q3_TOKEN_UNRESOLVED = 0,
Q3_TOKEN_EOF = 1,
Q3_TOKEN_START_LIST,
Q3_TOKEN_END_LIST,
Q3_TOKEN_ENTITY,
Q3_TOKEN_TOKEN,
Q3_TOKEN_EOL,
Q3_TOKEN_COMMENT,
Q3_TOKEN_MATH_DIVIDE,
Q3_TOKEN_MATH_ADD,
Q3_TOKEN_MATH_MULTIPY
};
struct SQ3Parser
{
const c8 *source;
u32 sourcesize;
u32 index;
core::stringc token;
eToken tokenresult;
};
SQ3Parser Parser;
typedef void( CQ3LevelMesh::*tParserCallback ) ( quake3::SVarGroupList *& groupList, eToken token );
void parser_parse( const void * data, u32 size, tParserCallback callback );
void parser_nextToken();
void dumpVarGroup( const quake3::SVarGroup * group, s32 stack ) const;
void scriptcallback_entity( quake3::SVarGroupList *& grouplist, eToken token );
void scriptcallback_shader( quake3::SVarGroupList *& grouplist, eToken token );
void scriptcallback_config( quake3::SVarGroupList *& grouplist, eToken token );
core::array < quake3::IShader > Shader;
core::array < quake3::IShader > Entity; //quake3::tQ3EntityList Entity;
quake3::tStringList ShaderFile;
void InitShader();
void ReleaseShader();
void ReleaseEntity();
s32 setShaderMaterial( video::SMaterial & material, const tBSPFace * face ) const;
s32 setShaderFogMaterial( video::SMaterial &material, const tBSPFace * face ) const;
struct SToBuffer
{
s32 takeVertexColor;
u32 index;
};
void cleanMeshes();
void cleanMesh(SMesh *m, const bool texture0important = false);
void cleanLoader ();
void calcBoundingBoxes();
c8 buf[128];
f32 FramesPerSecond;
};
} // end namespace scene
} // end namespace irr
#endif

File diff suppressed because it is too large Load Diff

View File

@ -1,118 +0,0 @@
// Copyright (C) 2002-2012 Nikolaus Gebhardt / Thomas Alten
// This file is part of the "Irrlicht Engine".
// For conditions of distribution and use, see copyright notice in irrlicht.h
#ifndef __C_QUAKE3_SCENE_NODE_H_INCLUDED__
#define __C_QUAKE3_SCENE_NODE_H_INCLUDED__
#include "IMeshSceneNode.h"
#include "IQ3Shader.h"
#include "IFileSystem.h"
#include "SMeshBuffer.h"
#include "SMeshBufferLightMap.h"
#include "SMesh.h"
#include "ISceneManager.h"
namespace irr
{
namespace scene
{
//! Scene node which is a quake3 shader.
class CQuake3ShaderSceneNode : public scene::IMeshSceneNode
{
public:
CQuake3ShaderSceneNode( ISceneNode* parent, ISceneManager* mgr, s32 id,
io::IFileSystem* fileSystem,
const IMeshBuffer* original,
const quake3::IShader* shader
);
virtual ~CQuake3ShaderSceneNode();
virtual void OnRegisterSceneNode();
virtual void render();
virtual void OnAnimate(u32 timeMs);
virtual const core::aabbox3d<f32>& getBoundingBox() const;
virtual u32 getMaterialCount() const;
virtual video::SMaterial& getMaterial(u32 i);
//! Returns type of the scene node
virtual ESCENE_NODE_TYPE getType() const { return ESNT_Q3SHADER_SCENE_NODE; }
virtual void setMesh(IMesh* mesh){}
virtual IMesh* getMesh() { return Mesh; }
virtual void setReadOnlyMaterials(bool readonly) {}
virtual bool isReadOnlyMaterials() const { return true; }
//! 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.
virtual bool removeChild(ISceneNode* child);
private:
const quake3::IShader* Shader;
SMesh *Mesh;
IShadowVolumeSceneNode* Shadow;
const SMeshBufferLightMap* Original;
SMeshBuffer* MeshBuffer;
core::vector3df MeshOffset;
struct SQ3Texture
{
SQ3Texture () :
TextureIndex ( 0 ),
TextureFrequency(0.f),
TextureAddressMode( video::ETC_REPEAT )
{
Texture.setAllocStrategy ( core::ALLOC_STRATEGY_SAFE );
}
quake3::tTexArray Texture;
u32 TextureIndex;
f32 TextureFrequency;
video::E_TEXTURE_CLAMP TextureAddressMode; // Wrapping/Clamping
};
core::array< SQ3Texture > Q3Texture;
void loadTextures ( io::IFileSystem * fileSystem );
void addBuffer ( scene::SMeshBufferLightMap * buffer );
void cloneBuffer ( scene::SMeshBuffer *dest, const scene::SMeshBufferLightMap * buffer, bool translateCenter );
void deformvertexes_wave ( f32 dt, quake3::SModifierFunction &function );
void deformvertexes_move ( f32 dt, quake3::SModifierFunction &function );
void deformvertexes_bulge( f32 dt, quake3::SModifierFunction &function );
void deformvertexes_autosprite( f32 dt, quake3::SModifierFunction &function );
void deformvertexes_autosprite2( f32 dt, quake3::SModifierFunction &function );
void deformvertexes_normal ( f32 dt, quake3::SModifierFunction &function );
void vertextransform_tcgen ( f32 dt, quake3::SModifierFunction &function );
void vertextransform_rgbgen ( f32 dt, quake3::SModifierFunction &function );
void vertextransform_alphagen ( f32 dt, quake3::SModifierFunction &function );
void transformtex ( const core::matrix4 &m, const u32 clamp );
f32 TimeAbs;
void animate( u32 stage, core::matrix4 &texture );
E_SCENE_NODE_RENDER_PASS getRenderStage() const;
};
} // end namespace scene
} // end namespace irr
#endif

View File

@ -1,232 +0,0 @@
// Copyright (C) 2010-2012 Gaz Davidson / Joseph Ellis
// This file is part of the "Irrlicht Engine".
// For conditions of distribution and use, see copyright notice in irrlicht.h
#include "IrrCompileConfig.h"
#ifdef _IRR_COMPILE_WITH_SMF_LOADER_
#include "CSMFMeshFileLoader.h"
#include "SAnimatedMesh.h"
#include "SMeshBuffer.h"
#include "IReadFile.h"
#include "coreutil.h"
#include "os.h"
#include "IVideoDriver.h"
namespace irr
{
namespace scene
{
CSMFMeshFileLoader::CSMFMeshFileLoader(video::IVideoDriver* driver)
: Driver(driver)
{
}
//! Returns true if the file might be loaded by this class.
bool CSMFMeshFileLoader::isALoadableFileExtension(const io::path& filename) const
{
return core::hasFileExtension(filename, "smf");
}
//! Creates/loads an animated mesh from the file.
IAnimatedMesh* CSMFMeshFileLoader::createMesh(io::IReadFile* file)
{
// create empty mesh
SMesh *mesh = new SMesh();
// load file
u16 version;
u8 flags;
s32 limbCount;
s32 i;
io::BinaryFile::read(file, version);
io::BinaryFile::read(file, flags);
io::BinaryFile::read(file, limbCount);
// load mesh data
core::matrix4 identity;
for (i=0; i < limbCount; ++i)
loadLimb(file, mesh, identity);
// recalculate buffer bounding boxes
for (i=0; i < (s32)mesh->getMeshBufferCount(); ++i)
mesh->getMeshBuffer(i)->recalculateBoundingBox();
mesh->recalculateBoundingBox();
SAnimatedMesh *am = new SAnimatedMesh();
am->addMesh(mesh);
mesh->drop();
am->recalculateBoundingBox();
return am;
}
void CSMFMeshFileLoader::loadLimb(io::IReadFile* file, SMesh* mesh, const core::matrix4 &parentTransformation)
{
core::matrix4 transformation;
// limb transformation
core::vector3df translate, rotate, scale;
io::BinaryFile::read(file, translate);
io::BinaryFile::read(file, rotate);
io::BinaryFile::read(file, scale);
transformation.setTranslation(translate);
transformation.setRotationDegrees(rotate);
transformation.setScale(scale);
transformation = parentTransformation * transformation;
core::stringc textureName, textureGroupName;
// texture information
io::BinaryFile::read(file, textureGroupName);
io::BinaryFile::read(file, textureName);
// attempt to load texture using known formats
video::ITexture* texture = 0;
const c8* extensions[] = {".jpg", ".png", ".tga", ".bmp", 0};
for (const c8 **ext = extensions; !texture && *ext; ++ext)
{
texture = Driver->getTexture(textureName + *ext);
if (texture)
textureName = textureName + *ext;
}
// find the correct mesh buffer
u32 i;
for (i=0; i<mesh->MeshBuffers.size(); ++i)
if (mesh->MeshBuffers[i]->getMaterial().TextureLayer[0].Texture == texture)
break;
// create mesh buffer if none was found
if (i == mesh->MeshBuffers.size())
{
CMeshBuffer<video::S3DVertex>* mb = new CMeshBuffer<video::S3DVertex>();
mb->Material.TextureLayer[0].Texture = texture;
// horribly hacky way to do this, maybe it's in the flags?
if (core::hasFileExtension(textureName, "tga", "png"))
mb->Material.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
else
mb->Material.MaterialType = video::EMT_SOLID;
mesh->MeshBuffers.push_back(mb);
}
CMeshBuffer<video::S3DVertex>* mb = (CMeshBuffer<video::S3DVertex>*)mesh->MeshBuffers[i];
u16 vertexCount, firstVertex = mb->getVertexCount();
io::BinaryFile::read(file, vertexCount);
mb->Vertices.reallocate(mb->Vertices.size() + vertexCount);
// add vertices and set positions
for (i=0; i<vertexCount; ++i)
{
core::vector3df pos;
io::BinaryFile::read(file, pos);
transformation.transformVect(pos);
video::S3DVertex vert;
vert.Color = 0xFFFFFFFF;
vert.Pos = pos;
mb->Vertices.push_back(vert);
}
// set vertex normals
for (i=0; i < vertexCount; ++i)
{
core::vector3df normal;
io::BinaryFile::read(file, normal);
transformation.rotateVect(normal);
mb->Vertices[firstVertex + i].Normal = normal;
}
// set texture coordinates
for (i=0; i < vertexCount; ++i)
{
core::vector2df tcoords;
io::BinaryFile::read(file, tcoords);
mb->Vertices[firstVertex + i].TCoords = tcoords;
}
// triangles
u32 triangleCount;
// vertexCount used as temporary
io::BinaryFile::read(file, vertexCount);
triangleCount=3*vertexCount;
mb->Indices.reallocate(mb->Indices.size() + triangleCount);
for (i=0; i < triangleCount; ++i)
{
u16 index;
io::BinaryFile::read(file, index);
mb->Indices.push_back(firstVertex + index);
}
// read limbs
s32 limbCount;
io::BinaryFile::read(file, limbCount);
for (s32 l=0; l < limbCount; ++l)
loadLimb(file, mesh, transformation);
}
} // namespace scene
// todo: at some point in the future let's move these to a place where everyone can use them.
namespace io
{
#if _BIGENDIAN
#define _SYSTEM_BIG_ENDIAN_ (true)
#else
#define _SYSTEM_BIG_ENDIAN_ (false)
#endif
template <class T>
void BinaryFile::read(io::IReadFile* file, T &out, bool bigEndian)
{
file->read((void*)&out, sizeof(out));
if (bigEndian != (_SYSTEM_BIG_ENDIAN_))
out = os::Byteswap::byteswap(out);
}
//! reads a 3d vector from the file, moving the file pointer along
void BinaryFile::read(io::IReadFile* file, core::vector3df &outVector2d, bool bigEndian)
{
BinaryFile::read(file, outVector2d.X, bigEndian);
BinaryFile::read(file, outVector2d.Y, bigEndian);
BinaryFile::read(file, outVector2d.Z, bigEndian);
}
//! reads a 2d vector from the file, moving the file pointer along
void BinaryFile::read(io::IReadFile* file, core::vector2df &outVector2d, bool bigEndian)
{
BinaryFile::read(file, outVector2d.X, bigEndian);
BinaryFile::read(file, outVector2d.Y, bigEndian);
}
//! reads a null terminated string from the file, moving the file pointer along
void BinaryFile::read(io::IReadFile* file, core::stringc &outString, bool bigEndian)
{
c8 c;
file->read((void*)&c, 1);
while (c)
{
outString += c;
file->read((void*)&c, 1);
}
}
} // namespace io
} // namespace irr
#endif // compile with SMF loader

View File

@ -1,67 +0,0 @@
// Copyright (C) 2010-2012 Gaz Davidson
// This file is part of the "Irrlicht Engine".
// For conditions of distribution and use, see copyright notice in irrlicht.h
#ifndef __C_SMF_MESH_LOADER_H_INCLUDED__
#define __C_SMF_MESH_LOADER_H_INCLUDED__
#include "IMeshLoader.h"
#include "SMesh.h"
namespace irr
{
namespace video
{
class IVideoDriver;
}
namespace scene
{
//! Class which can load
class CSMFMeshFileLoader : public virtual IMeshLoader
{
public:
CSMFMeshFileLoader(video::IVideoDriver* driver);
//! Returns true if the file might be loaded by this class.
virtual bool isALoadableFileExtension(const io::path& filename) const;
//! Creates/loads an animated mesh from the file.
virtual IAnimatedMesh* createMesh(io::IReadFile* file);
private:
void loadLimb(io::IReadFile* file, scene::SMesh* mesh, const core::matrix4 &parentTransformation);
video::IVideoDriver* Driver;
};
} // end namespace scene
namespace io
{
class BinaryFile
{
public:
//! reads most types from the given file, moving the file pointer along
template <class T>
static void read(io::IReadFile* file, T &out, bool bigEndian=false);
//! reads a 3d vector from the file, moving the file pointer along
static void read(io::IReadFile* file, core::vector3df &outVector2d, bool bigEndian=false);
//! reads a 2d vector from the file, moving the file pointer along
static void read(io::IReadFile* file, core::vector2df &outVector2d, bool bigEndian=false);
//! reads a null terminated string from the file, moving the file pointer along
static void read(io::IReadFile* file, core::stringc &outString, bool bigEndian=false);
};
}
} // end namespace irr
#endif // __C_SMF_MESH_LOADER_H_INCLUDED__

View File

@ -1,253 +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 "IrrCompileConfig.h"
#ifdef _IRR_COMPILE_WITH_STL_LOADER_
#include "CSTLMeshFileLoader.h"
#include "SMesh.h"
#include "SMeshBuffer.h"
#include "SAnimatedMesh.h"
#include "IReadFile.h"
#include "fast_atof.h"
#include "coreutil.h"
#include "os.h"
namespace irr
{
namespace scene
{
//! returns true if the file maybe is able to be loaded by this class
//! based on the file extension (e.g. ".bsp")
bool CSTLMeshFileLoader::isALoadableFileExtension(const io::path& filename) const
{
return core::hasFileExtension ( filename, "stl" );
}
//! creates/loads an animated mesh from the file.
//! \return Pointer to the created mesh. Returns 0 if loading failed.
//! If you no longer need the mesh, you should call IAnimatedMesh::drop().
//! See IReferenceCounted::drop() for more information.
IAnimatedMesh* CSTLMeshFileLoader::createMesh(io::IReadFile* file)
{
const long filesize = file->getSize();
if (filesize < 6) // we need a header
return 0;
SMesh* mesh = new SMesh();
SMeshBuffer* meshBuffer = new SMeshBuffer();
mesh->addMeshBuffer(meshBuffer);
meshBuffer->drop();
core::vector3df vertex[3];
core::vector3df normal;
bool binary = false;
core::stringc token;
if (getNextToken(file, token) != "solid")
binary = true;
// read/skip header
u32 binFaceCount = 0;
if (binary)
{
file->seek(80);
file->read(&binFaceCount, 4);
#ifdef __BIG_ENDIAN__
binFaceCount = os::Byteswap::byteswap(binFaceCount);
#endif
}
else
goNextLine(file);
u16 attrib=0;
token.reserve(32);
while (file->getPos() < filesize)
{
if (!binary)
{
if (getNextToken(file, token) != "facet")
{
if (token=="endsolid")
break;
mesh->drop();
return 0;
}
if (getNextToken(file, token) != "normal")
{
mesh->drop();
return 0;
}
}
getNextVector(file, normal, binary);
if (!binary)
{
if (getNextToken(file, token) != "outer")
{
mesh->drop();
return 0;
}
if (getNextToken(file, token) != "loop")
{
mesh->drop();
return 0;
}
}
for (u32 i=0; i<3; ++i)
{
if (!binary)
{
if (getNextToken(file, token) != "vertex")
{
mesh->drop();
return 0;
}
}
getNextVector(file, vertex[i], binary);
}
if (!binary)
{
if (getNextToken(file, token) != "endloop")
{
mesh->drop();
return 0;
}
if (getNextToken(file, token) != "endfacet")
{
mesh->drop();
return 0;
}
}
else
{
file->read(&attrib, 2);
#ifdef __BIG_ENDIAN__
attrib = os::Byteswap::byteswap(attrib);
#endif
}
SMeshBuffer* mb = reinterpret_cast<SMeshBuffer*>(mesh->getMeshBuffer(mesh->getMeshBufferCount()-1));
u32 vCount = mb->getVertexCount();
video::SColor color(0xffffffff);
if (attrib & 0x8000)
color = video::A1R5G5B5toA8R8G8B8(attrib);
if (normal==core::vector3df())
normal=core::plane3df(vertex[2],vertex[1],vertex[0]).Normal;
mb->Vertices.push_back(video::S3DVertex(vertex[2],normal,color, core::vector2df()));
mb->Vertices.push_back(video::S3DVertex(vertex[1],normal,color, core::vector2df()));
mb->Vertices.push_back(video::S3DVertex(vertex[0],normal,color, core::vector2df()));
mb->Indices.push_back(vCount);
mb->Indices.push_back(vCount+1);
mb->Indices.push_back(vCount+2);
} // end while (file->getPos() < filesize)
mesh->getMeshBuffer(0)->recalculateBoundingBox();
// Create the Animated mesh if there's anything in the mesh
SAnimatedMesh* pAM = 0;
if ( 0 != mesh->getMeshBufferCount() )
{
mesh->recalculateBoundingBox();
pAM = new SAnimatedMesh();
pAM->Type = EAMT_OBJ;
pAM->addMesh(mesh);
pAM->recalculateBoundingBox();
}
mesh->drop();
return pAM;
}
//! Read 3d vector of floats
void CSTLMeshFileLoader::getNextVector(io::IReadFile* file, core::vector3df& vec, bool binary) const
{
if (binary)
{
file->read(&vec.X, 4);
file->read(&vec.Y, 4);
file->read(&vec.Z, 4);
#ifdef __BIG_ENDIAN__
vec.X = os::Byteswap::byteswap(vec.X);
vec.Y = os::Byteswap::byteswap(vec.Y);
vec.Z = os::Byteswap::byteswap(vec.Z);
#endif
}
else
{
goNextWord(file);
core::stringc tmp;
getNextToken(file, tmp);
core::fast_atof_move(tmp.c_str(), vec.X);
getNextToken(file, tmp);
core::fast_atof_move(tmp.c_str(), vec.Y);
getNextToken(file, tmp);
core::fast_atof_move(tmp.c_str(), vec.Z);
}
vec.X=-vec.X;
}
//! Read next word
const core::stringc& CSTLMeshFileLoader::getNextToken(io::IReadFile* file, core::stringc& token) const
{
goNextWord(file);
u8 c;
token = "";
while(file->getPos() != file->getSize())
{
file->read(&c, 1);
// found it, so leave
if (core::isspace(c))
break;
token.append(c);
}
return token;
}
//! skip to next word
void CSTLMeshFileLoader::goNextWord(io::IReadFile* file) const
{
u8 c;
while(file->getPos() != file->getSize())
{
file->read(&c, 1);
// found it, so leave
if (!core::isspace(c))
{
file->seek(-1, true);
break;
}
}
}
//! Read until line break is reached and stop at the next non-space character
void CSTLMeshFileLoader::goNextLine(io::IReadFile* file) const
{
u8 c;
// look for newline characters
while(file->getPos() != file->getSize())
{
file->read(&c, 1);
// found it, so leave
if (c=='\n' || c=='\r')
break;
}
}
} // end namespace scene
} // end namespace irr
#endif // _IRR_COMPILE_WITH_STL_LOADER_

View File

@ -1,49 +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_STL_MESH_FILE_LOADER_H_INCLUDED__
#define __C_STL_MESH_FILE_LOADER_H_INCLUDED__
#include "IMeshLoader.h"
#include "irrString.h"
#include "vector3d.h"
namespace irr
{
namespace scene
{
//! Meshloader capable of loading STL meshes.
class CSTLMeshFileLoader : public IMeshLoader
{
public:
//! returns true if the file maybe is able to be loaded by this class
//! based on the file extension (i.e. ".stl")
virtual bool isALoadableFileExtension(const io::path& filename) const;
//! creates/loads an animated mesh from the file.
//! \return Pointer to the created mesh. Returns 0 if loading failed.
//! If you no longer need the mesh, you should call IAnimatedMesh::drop().
//! See IReferenceCounted::drop() for more information.
virtual IAnimatedMesh* createMesh(io::IReadFile* file);
private:
// skips to the first non-space character available
void goNextWord(io::IReadFile* file) const;
// returns the next word
const core::stringc& getNextToken(io::IReadFile* file, core::stringc& token) const;
// skip to next printable character after the first line break
void goNextLine(io::IReadFile* file) const;
//! Read 3d vector of floats
void getNextVector(io::IReadFile* file, core::vector3df& vec, bool binary) const;
};
} // end namespace scene
} // end namespace irr
#endif

View File

@ -1,187 +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 "IrrCompileConfig.h"
#ifdef _IRR_COMPILE_WITH_STL_WRITER_
#include "CSTLMeshWriter.h"
#include "os.h"
#include "IMesh.h"
#include "IMeshBuffer.h"
#include "IAttributes.h"
#include "ISceneManager.h"
#include "IMeshCache.h"
#include "IWriteFile.h"
namespace irr
{
namespace scene
{
CSTLMeshWriter::CSTLMeshWriter(scene::ISceneManager* smgr)
: SceneManager(smgr)
{
#ifdef _DEBUG
setDebugName("CSTLMeshWriter");
#endif
if (SceneManager)
SceneManager->grab();
}
CSTLMeshWriter::~CSTLMeshWriter()
{
if (SceneManager)
SceneManager->drop();
}
//! Returns the type of the mesh writer
EMESH_WRITER_TYPE CSTLMeshWriter::getType() const
{
return EMWT_STL;
}
//! writes a mesh
bool CSTLMeshWriter::writeMesh(io::IWriteFile* file, scene::IMesh* mesh, s32 flags)
{
if (!file)
return false;
os::Printer::log("Writing mesh", file->getFileName());
if (flags & scene::EMWF_WRITE_COMPRESSED)
return writeMeshBinary(file, mesh, flags);
else
return writeMeshASCII(file, mesh, flags);
}
bool CSTLMeshWriter::writeMeshBinary(io::IWriteFile* file, scene::IMesh* mesh, s32 flags)
{
// write STL MESH header
file->write("binary ",7);
const core::stringc name(SceneManager->getMeshCache()->getMeshName(mesh));
const s32 sizeleft = 73-name.size(); // 80 byte header
if (sizeleft<0)
file->write(name.c_str(),73);
else
{
char* buf = new char[80];
memset(buf, 0, 80);
file->write(name.c_str(),name.size());
file->write(buf,sizeleft);
delete [] buf;
}
u32 facenum = 0;
for (u32 j=0; j<mesh->getMeshBufferCount(); ++j)
facenum += mesh->getMeshBuffer(j)->getIndexCount()/3;
file->write(&facenum,4);
// write mesh buffers
for (u32 i=0; i<mesh->getMeshBufferCount(); ++i)
{
IMeshBuffer* buffer = mesh->getMeshBuffer(i);
if (buffer)
{
const u32 indexCount = buffer->getIndexCount();
const u16 attributes = 0;
for (u32 j=0; j<indexCount; j+=3)
{
const core::vector3df& v1 = buffer->getPosition(buffer->getIndices()[j]);
const core::vector3df& v2 = buffer->getPosition(buffer->getIndices()[j+1]);
const core::vector3df& v3 = buffer->getPosition(buffer->getIndices()[j+2]);
const core::plane3df tmpplane(v1,v2,v3);
file->write(&tmpplane.Normal, 12);
file->write(&v1, 12);
file->write(&v2, 12);
file->write(&v3, 12);
file->write(&attributes, 2);
}
}
}
return true;
}
bool CSTLMeshWriter::writeMeshASCII(io::IWriteFile* file, scene::IMesh* mesh, s32 flags)
{
// write STL MESH header
file->write("solid ",6);
const core::stringc name(SceneManager->getMeshCache()->getMeshName(mesh));
file->write(name.c_str(),name.size());
file->write("\n\n",2);
// write mesh buffers
for (u32 i=0; i<mesh->getMeshBufferCount(); ++i)
{
IMeshBuffer* buffer = mesh->getMeshBuffer(i);
if (buffer)
{
const u32 indexCount = buffer->getIndexCount();
for (u32 j=0; j<indexCount; j+=3)
{
writeFace(file,
buffer->getPosition(buffer->getIndices()[j]),
buffer->getPosition(buffer->getIndices()[j+1]),
buffer->getPosition(buffer->getIndices()[j+2]));
}
file->write("\n",1);
}
}
file->write("endsolid ",9);
file->write(name.c_str(),name.size());
return true;
}
void CSTLMeshWriter::getVectorAsStringLine(const core::vector3df& v, core::stringc& s) const
{
s = core::stringc(v.X);
s += " ";
s += core::stringc(v.Y);
s += " ";
s += core::stringc(v.Z);
s += "\n";
}
void CSTLMeshWriter::writeFace(io::IWriteFile* file,
const core::vector3df& v1,
const core::vector3df& v2,
const core::vector3df& v3)
{
core::stringc tmp;
file->write("facet normal ",13);
getVectorAsStringLine(core::plane3df(v1,v2,v3).Normal, tmp);
file->write(tmp.c_str(),tmp.size());
file->write(" outer loop\n",13);
file->write(" vertex ",11);
getVectorAsStringLine(v1, tmp);
file->write(tmp.c_str(),tmp.size());
file->write(" vertex ",11);
getVectorAsStringLine(v2, tmp);
file->write(tmp.c_str(),tmp.size());
file->write(" vertex ",11);
getVectorAsStringLine(v3, tmp);
file->write(tmp.c_str(),tmp.size());
file->write(" endloop\n",10);
file->write("endfacet\n",9);
}
} // end namespace
} // end namespace
#endif

View File

@ -1,55 +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 __IRR_STL_MESH_WRITER_H_INCLUDED__
#define __IRR_STL_MESH_WRITER_H_INCLUDED__
#include "IMeshWriter.h"
#include "S3DVertex.h"
#include "irrString.h"
namespace irr
{
namespace scene
{
class IMeshBuffer;
class ISceneManager;
//! class to write meshes, implementing a STL writer
class CSTLMeshWriter : public IMeshWriter
{
public:
CSTLMeshWriter(scene::ISceneManager* smgr);
virtual ~CSTLMeshWriter();
//! Returns the type of the mesh writer
virtual EMESH_WRITER_TYPE getType() const;
//! writes a mesh
virtual bool writeMesh(io::IWriteFile* file, scene::IMesh* mesh, s32 flags=EMWF_NONE);
protected:
// write binary format
bool writeMeshBinary(io::IWriteFile* file, scene::IMesh* mesh, s32 flags);
// write text format
bool writeMeshASCII(io::IWriteFile* file, scene::IMesh* mesh, s32 flags);
// create vector output with line end into string
void getVectorAsStringLine(const core::vector3df& v,
core::stringc& s) const;
// write face information to file
void writeFace(io::IWriteFile* file, const core::vector3df& v1,
const core::vector3df& v2, const core::vector3df& v3);
scene::ISceneManager* SceneManager;
};
} // end namespace
} // end namespace
#endif

View File

@ -24,114 +24,10 @@
#include "CSkinnedMesh.h"
#endif
#ifdef _IRR_COMPILE_WITH_IRR_MESH_LOADER_
#include "CIrrMeshFileLoader.h"
#endif
#ifdef _IRR_COMPILE_WITH_BSP_LOADER_
#include "CBSPMeshFileLoader.h"
#endif
#ifdef _IRR_COMPILE_WITH_MD2_LOADER_
#include "CMD2MeshFileLoader.h"
#endif
#ifdef _IRR_COMPILE_WITH_HALFLIFE_LOADER_
#include "CAnimatedMeshHalfLife.h"
#endif
#ifdef _IRR_COMPILE_WITH_MS3D_LOADER_
#include "CMS3DMeshFileLoader.h"
#endif
#ifdef _IRR_COMPILE_WITH_3DS_LOADER_
#include "C3DSMeshFileLoader.h"
#endif
#ifdef _IRR_COMPILE_WITH_X_LOADER_
#include "CXMeshFileLoader.h"
#endif
#ifdef _IRR_COMPILE_WITH_OCT_LOADER_
#include "COCTLoader.h"
#endif
#ifdef _IRR_COMPILE_WITH_CSM_LOADER_
#include "CCSMLoader.h"
#endif
#ifdef _IRR_COMPILE_WITH_LMTS_LOADER_
#include "CLMTSMeshFileLoader.h"
#endif
#ifdef _IRR_COMPILE_WITH_MY3D_LOADER_
#include "CMY3DMeshFileLoader.h"
#endif
#ifdef _IRR_COMPILE_WITH_COLLADA_LOADER_
#include "CColladaFileLoader.h"
#endif
#ifdef _IRR_COMPILE_WITH_DMF_LOADER_
#include "CDMFLoader.h"
#endif
#ifdef _IRR_COMPILE_WITH_OGRE_LOADER_
#include "COgreMeshFileLoader.h"
#endif
#ifdef _IRR_COMPILE_WITH_OBJ_LOADER_
#include "COBJMeshFileLoader.h"
#endif
#ifdef _IRR_COMPILE_WITH_MD3_LOADER_
#include "CMD3MeshFileLoader.h"
#endif
#ifdef _IRR_COMPILE_WITH_B3D_LOADER_
#include "CB3DMeshFileLoader.h"
#endif
#ifdef _IRR_COMPILE_WITH_LWO_LOADER_
#include "CLWOMeshFileLoader.h"
#endif
#ifdef _IRR_COMPILE_WITH_STL_LOADER_
#include "CSTLMeshFileLoader.h"
#endif
#ifdef _IRR_COMPILE_WITH_PLY_LOADER_
#include "CPLYMeshFileLoader.h"
#endif
#ifdef _IRR_COMPILE_WITH_SMF_LOADER_
#include "CSMFMeshFileLoader.h"
#endif
#ifdef _IRR_COMPILE_WITH_IRR_SCENE_LOADER_
#include "CSceneLoaderIrr.h"
#endif
#ifdef _IRR_COMPILE_WITH_COLLADA_WRITER_
#include "CColladaMeshWriter.h"
#endif
#ifdef _IRR_COMPILE_WITH_IRR_WRITER_
#include "CIrrMeshWriter.h"
#endif
#ifdef _IRR_COMPILE_WITH_STL_WRITER_
#include "CSTLMeshWriter.h"
#endif
#ifdef _IRR_COMPILE_WITH_OBJ_WRITER_
#include "COBJMeshWriter.h"
#endif
#ifdef _IRR_COMPILE_WITH_PLY_WRITER_
#include "CPLYMeshWriter.h"
#endif
#include "CCubeSceneNode.h"
#include "CSphereSceneNode.h"
#include "CAnimatedMeshSceneNode.h"
@ -148,7 +44,6 @@
#include "CTerrainSceneNode.h"
#include "CEmptySceneNode.h"
#include "CTextSceneNode.h"
#include "CQuake3ShaderSceneNode.h"
#include "CVolumeLightSceneNode.h"
#include "CDefaultSceneNodeFactory.h"
@ -229,79 +124,10 @@ CSceneManager::CSceneManager(video::IVideoDriver* driver, io::IFileSystem* fs,
// add file format loaders. add the least commonly used ones first,
// as these are checked last
// TODO: now that we have multiple scene managers, these should be
// shallow copies from the previous manager if there is one.
#ifdef _IRR_COMPILE_WITH_STL_LOADER_
MeshLoaderList.push_back(new CSTLMeshFileLoader());
#endif
#ifdef _IRR_COMPILE_WITH_PLY_LOADER_
MeshLoaderList.push_back(new CPLYMeshFileLoader(this));
#endif
#ifdef _IRR_COMPILE_WITH_SMF_LOADER_
MeshLoaderList.push_back(new CSMFMeshFileLoader(Driver));
#endif
#ifdef _IRR_COMPILE_WITH_OCT_LOADER_
MeshLoaderList.push_back(new COCTLoader(this, FileSystem));
#endif
#ifdef _IRR_COMPILE_WITH_CSM_LOADER_
MeshLoaderList.push_back(new CCSMLoader(this, FileSystem));
#endif
#ifdef _IRR_COMPILE_WITH_LMTS_LOADER_
MeshLoaderList.push_back(new CLMTSMeshFileLoader(FileSystem, Driver, &Parameters));
#endif
#ifdef _IRR_COMPILE_WITH_MY3D_LOADER_
MeshLoaderList.push_back(new CMY3DMeshFileLoader(this, FileSystem));
#endif
#ifdef _IRR_COMPILE_WITH_DMF_LOADER_
MeshLoaderList.push_back(new CDMFLoader(this, FileSystem));
#endif
#ifdef _IRR_COMPILE_WITH_OGRE_LOADER_
MeshLoaderList.push_back(new COgreMeshFileLoader(FileSystem, Driver));
#endif
#ifdef _IRR_COMPILE_WITH_HALFLIFE_LOADER_
MeshLoaderList.push_back(new CHalflifeMDLMeshFileLoader( this ));
#endif
#ifdef _IRR_COMPILE_WITH_MD3_LOADER_
MeshLoaderList.push_back(new CMD3MeshFileLoader( this));
#endif
#ifdef _IRR_COMPILE_WITH_LWO_LOADER_
MeshLoaderList.push_back(new CLWOMeshFileLoader(this, FileSystem));
#endif
#ifdef _IRR_COMPILE_WITH_MD2_LOADER_
MeshLoaderList.push_back(new CMD2MeshFileLoader());
#endif
#ifdef _IRR_COMPILE_WITH_IRR_MESH_LOADER_
MeshLoaderList.push_back(new CIrrMeshFileLoader(this, FileSystem));
#endif
#ifdef _IRR_COMPILE_WITH_BSP_LOADER_
MeshLoaderList.push_back(new CBSPMeshFileLoader(this, FileSystem));
#endif
#ifdef _IRR_COMPILE_WITH_COLLADA_LOADER_
MeshLoaderList.push_back(new CColladaFileLoader(this, FileSystem));
#endif
#ifdef _IRR_COMPILE_WITH_3DS_LOADER_
MeshLoaderList.push_back(new C3DSMeshFileLoader(this, FileSystem));
#endif
#ifdef _IRR_COMPILE_WITH_X_LOADER_
MeshLoaderList.push_back(new CXMeshFileLoader(this, FileSystem));
#endif
#ifdef _IRR_COMPILE_WITH_MS3D_LOADER_
MeshLoaderList.push_back(new CMS3DMeshFileLoader(Driver));
#endif
#ifdef _IRR_COMPILE_WITH_OBJ_LOADER_
MeshLoaderList.push_back(new COBJMeshFileLoader(this, FileSystem));
#endif
#ifdef _IRR_COMPILE_WITH_B3D_LOADER_
MeshLoaderList.push_back(new CB3DMeshFileLoader(this));
#endif
// scene loaders
#ifdef _IRR_COMPILE_WITH_IRR_SCENE_LOADER_
SceneLoaderList.push_back(new CSceneLoaderIrr(this, FileSystem));
#endif
// factories
ISceneNodeFactory* factory = new CDefaultSceneNodeFactory(this);
@ -520,31 +346,6 @@ IBillboardTextSceneNode* CSceneManager::addBillboardTextSceneNode(gui::IGUIFont*
}
//! Adds a scene node, which can render a quake3 shader
IMeshSceneNode* CSceneManager::addQuake3SceneNode(const IMeshBuffer* meshBuffer,
const quake3::IShader * shader,
ISceneNode* parent, s32 id )
{
#ifdef _IRR_COMPILE_WITH_BSP_LOADER_
if (!shader)
return 0;
if (!parent)
parent = this;
CQuake3ShaderSceneNode* node = new CQuake3ShaderSceneNode( parent,
this, id, FileSystem,
meshBuffer, shader );
node->drop();
return node;
#else
return 0;
#endif
}
//! adds Volume Lighting Scene Node.
//! the returned pointer must not be dropped.
IVolumeLightSceneNode* CSceneManager::addVolumeLightSceneNode(
@ -2500,36 +2301,10 @@ IMeshWriter* CSceneManager::createMeshWriter(EMESH_WRITER_TYPE type)
switch(type)
{
case EMWT_IRR_MESH:
#ifdef _IRR_COMPILE_WITH_IRR_WRITER_
return new CIrrMeshWriter(Driver, FileSystem);
#else
return 0;
#endif
case EMWT_COLLADA:
#ifdef _IRR_COMPILE_WITH_COLLADA_WRITER_
return new CColladaMeshWriter(this, Driver, FileSystem);
#else
return 0;
#endif
case EMWT_STL:
#ifdef _IRR_COMPILE_WITH_STL_WRITER_
return new CSTLMeshWriter(this);
#else
return 0;
#endif
case EMWT_OBJ:
#ifdef _IRR_COMPILE_WITH_OBJ_WRITER_
return new COBJMeshWriter(this, FileSystem);
#else
return 0;
#endif
case EMWT_PLY:
#ifdef _IRR_COMPILE_WITH_PLY_WRITER_
return new CPLYMeshWriter();
#else
return 0;
#endif
}
return 0;

View File

@ -195,11 +195,6 @@ namespace scene
const core::vector3df& position = core::vector3df(0,0,0), s32 id=-1,
video::SColor colorTop = 0xFFFFFFFF, video::SColor colorBottom = 0xFFFFFFFF);
//! Adds a scene node, which can render a quake3 shader
virtual IMeshSceneNode* addQuake3SceneNode(const IMeshBuffer* meshBuffer, const quake3::IShader * shader,
ISceneNode* parent=0, s32 id=-1
);
//! Adds a Hill Plane mesh to the mesh pool. The mesh is
//! generated on the fly and looks like a plane with some hills

View File

@ -37,6 +37,7 @@ using namespace irr;
#include <ISceneManager.h>
#include <IMeshSceneNode.h>
#include <ITexture.h>
/** Creates a physical Settings object with the given type, radius and mass.
*/