Merge branch 'minlicht'
This commit is contained in:
commit
a6b2aa8217
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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"
|
||||
|
@ -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_
|
@ -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
|
||||
|
@ -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_
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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_
|
||||
|
@ -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
|
||||
|
@ -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_
|
@ -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
|
||||
|
@ -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
|
@ -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
@ -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
@ -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
|
@ -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_
|
||||
|
@ -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
|
||||
|
@ -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_
|
||||
|
@ -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__
|
@ -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_
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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_
|
@ -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
@ -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
|
@ -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_
|
@ -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__
|
||||
|
@ -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_
|
@ -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
|
||||
|
@ -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__
|
||||
|
@ -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_
|
||||
|
@ -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__
|
@ -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_
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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_
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
};
|
||||
|
@ -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;
|
||||
|
@ -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_
|
||||
|
@ -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
|
||||
|
@ -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_
|
||||
|
@ -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
|
@ -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
@ -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
@ -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
|
||||
|
@ -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
|
||||
|
@ -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__
|
||||
|
@ -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_
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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.
|
||||
*/
|
||||
|
Loading…
Reference in New Issue
Block a user