diff --git a/changes.txt b/changes.txt index 8468a11c..bb608da8 100644 --- a/changes.txt +++ b/changes.txt @@ -1,12 +1,81 @@ Changes in 1.7 + - Define sorting order for vector2d and vector3d in operators <, <=, > and >= to fix bugs 2783509 and 2783510. Operators order now by X,Y,Z and use float tolerances. + + - Fix tooltips for gui-elements with sub-element like IGUISpinBox (id: 2927079, found by ArakisTheKitsune) + + - ITimer no longer stops when started twice + + - Add hasType to IGUIElement as a dynamic_cast substitute. + + - Add another parameter to IGUISkin::draw3DWindowBackground to allow getting the client area without actually drawing + + - Add function getClientRect to IGUIWindow for getting the draw-able area + + - Fix bug that menus on IGUIWindows with titlebar got drawn too high (id: 2714400) + + - Renamed OctTree to Octree + + - Allow getting a ConstIterator from a non-const core:list + + - Add swap functions to irrMath and to the core classes. + + - Deprecate map::isEmpty() and replace it with map::empty() to make it similar to other base classes. + + - Allow to set the logging level already in SIrrlichtCreationParameters. + + - Add clearSystemMessages to devices (implemented only for Linux and Win32 so far). + + - Fix incorrect cursorpos for resizable windows on Windows Vista (found and patched by buffer) + + - Change the beginScene window parameter from void* to SExposedVideoData&. This will allow to manage contexts for OpenGL at some point. + + - Add bzip2 and LZMA decompression modes for zip loader. + + - Add OBJ_TEXTURE_PATH and B3D_TEXTURE_PATH to SceneParameters to allow setting texture-paths for obj and b3d. + + - Irrlicht keeps now filenames additionally to the internally used names, thereby fixing some problems with uppercase-filenames on Linux. + + - Bugfix: Mousewheel no longer sends EMIE_MOUSE_WHEEL messages twice on Linux. + + - refactoring: E_ATTRIBUTE_TYPE and IAttribute have now own headers + + - CStringWArrayAttribute speedup + + - SceneNodeAnimatorFollowSpline can now loop and pingpong + + - Meshviewer.example got some fast-scale buttons. + + - Support AES-encrypted zip files. Should work with 128, 196, and 256 bit AES. This addition also adds a new PRNG, SHA, and other algorithms to the engine, though no interface is yet added for them. The implementation of the encryption algorithms is provided by Dr Brian Gladman. + + - Added geometry shaders for OpenGL. A first version of the code was submitted by Matthew Kielan (devsh). + + - Bugfix: irrArray should no longer crash when using other allocators. + + - Add MaterialViewer example. + + - Checkbox uses now disabled text color when disabled. + + - Changed colors for window-title caption to keep them readable when not active. + + - Draw sub-menus to left side if they would be outside main-window otherwise. + + - Give ListBox better defaults for the ScrollBar stepsizes. + + - Double and triple click events now for each mouse-button. Old events for that got removed. + + - Fix adding archives twice, which caused multiple archives of the same name and type covering each other. This one required a texture name change from using backslashes to slashes under Windows. + + - Give access to texture mipmaps. You can provide custom mipmap textures upon generation, regeneration, and locking. + Make sure the provided data is large enough and covers all miplevels. Also the returned pointer (from lock) will only cover the smaller data of the mipmap level dimension chosen (level 0 is the original texture). + - Separate TextureWrap mode into U and V fields - Add mirror texture wrap modes - windows show now active/inactive state - - remove unneed drop/grab calls found by manik_sheeri + - remove unneeded drop/grab calls found by manik_sheeri - fix rounding problem in IGUIElements which have EGUIA_SCALE alignments. @@ -52,13 +121,13 @@ Changes in 1.7 - Bounding Box updates for skinned meshes fixed - - The current FPS for an animated scene node cn be queried now, added some variables to serialization + - The current FPS for an animated scene node can be queried now, added some variables to serialization - Scrollbars fixed - Fixed 2d vertex primitive method to correctly handle transparency - - Fullscreen handling has been ehanced for Windows, now proper resolution is restored on Alt-Tab etc. + - Fullscreen handling has been enhanced for Windows, now proper resolution is restored on Alt-Tab etc. - Cameras can now be added to the scene node without automatically activating them Clone method added @@ -84,8 +153,49 @@ Changes in 1.7 ---------------- Changes in 1.6.1 + - Fix pingpong for CSceneNodeAnimatorFlyStraight (found by gbox) + + - Fix bug with IGUIEditBox where the cursor position is reset on text change. + + - Make sure the window top-left corner on Windows is not negative on start so that Windows sytem-menu is always visible. + + - Fix problem that the window did sometimes not get the keyboard focus in X11 in fullscreen. Add more debug output in case focus grabbing goes wrong. + + - Fix screensize in videodriver when we didn't get the requested window size. This also prevents that gui-clicks are no longer synchronized with gui-drawing and elements can't be hit anymore. + + - Bugfix: Prevent a crash when getTypeName was called for the guienvironment. EGUIET_ELEMENT got changed for this. + + - Bugfix: Horizontal centered font with linebreaks draw now all lines. For example multiline TextSceneNodes work again. + + - Bugfix: spinbox can no longer get in an endless loop due to floating point rounding error (found by slavik262) + + - !!API change!! Disabled AntiAliasing of Lines in material default + Please enable this manually per material when sure that it won't lead to SW rendering. + + - IGUIComboBox: clicking on the statictext displaying the active selection does now close and open listbox correctly. (Bug found by Reiko) + + - Scrollbuttons in IGUITabControl adapt now to tab-height. + + - Fix texturing of cylinder mesh + + - Fix modal dialog position (found by LoneBoco: http://sourceforge.net/tracker/?func=detail&aid=2900266&group_id=74339&atid=540676) + + - Fix DMF loading + + - Fixing left+right special keys (ctrl, shift, alt) on Win32 (thanks to pc0de for good patch-ideas). + + - Make stringarrays for enums in IGUISkin a little safer + + - Add support for keys KEY_PRINT, KEY_HOME (on numpad) and KEY_NUMLOCK on Linux. + + - Fix material handling in createMeshWith1TCoords + - Fix another (OldValue == NewValue) before drop()/grap(), this time in CTextureAttribute::setTexture. + - Fix LIGHTMAP_LIGHTING for D3D drivers. + + - AntiAliasing disabled for debug render elements. + - Bugfix: CGUIToolBar::addButton does no longer mess up when no image is set and does now actually work with the text. - Fix ninja animation range which got messed up a little when b3d animations got fixed (thx gbox for finding) @@ -742,7 +852,13 @@ Changes in 1.6 (23.09.2009) - Add a hitPosition out parameter to ISceneCollisionManager::getCollisionResultPosition() - this is a (small) API breaking change. ------------------------------------- -Changes in version 1.5.2 (??.??.2009) +Changes in version 1.5.2 (16.12.2009) + + - Properly check boundaries in getFont and setFont. + + - Reinit values in the driver when scene manager is cleared. + + - Normals handling fixed in createMeshWithTangents, existing normals are not always destroyed now. - Fix terrain smoothing, bug found by loverlinfish diff --git a/doc/aesGladman.txt b/doc/aesGladman.txt new file mode 100644 index 00000000..e7ebb1c4 --- /dev/null +++ b/doc/aesGladman.txt @@ -0,0 +1,34 @@ +The Irrlicht Engine may be compiled to provide support for AES encrypted files. The implementation used by Irrlicht is provided by Dr Brian Gladman. The license for these files (including AES, a PRNG, SHA, and other algorithms) is as follows + +/* + --------------------------------------------------------------------------- + Copyright (c) 2002, Dr Brian Gladman < >, Worcester, UK. + All rights reserved. + + LICENSE TERMS + + The free distribution and use of this software in both source and binary + form is allowed (with or without changes) provided that: + + 1. distributions of this source code include the above copyright + notice, this list of conditions and the following disclaimer; + + 2. distributions in binary form include the above copyright + notice, this list of conditions and the following disclaimer + in the documentation and/or other associated materials; + + 3. the copyright holder's name is not used to endorse products + built using this software without specific written permission. + + ALTERNATIVELY, provided that this notice is retained in full, this product + may be distributed under the terms of the GNU General Public License (GPL), + in which case the provisions of the GPL apply INSTEAD OF those given above. + + DISCLAIMER + + This software is provided 'as is' with no explicit or implied warranties + in respect of its properties, including, but not limited to, correctness + and/or fitness for purpose. + --------------------------------------------------------------------------- +*/ + diff --git a/doc/bzip2-license.txt b/doc/bzip2-license.txt new file mode 100644 index 00000000..f420cffb --- /dev/null +++ b/doc/bzip2-license.txt @@ -0,0 +1,42 @@ + +-------------------------------------------------------------------------- + +This program, "bzip2", the associated library "libbzip2", and all +documentation, are copyright (C) 1996-2007 Julian R Seward. All +rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + +2. 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. + +3. Altered source versions must be plainly marked as such, and must + not be misrepresented as being the original software. + +4. The name of the author may not be used to endorse or promote + products derived from this software without specific prior written + permission. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS +OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +Julian Seward, jseward@bzip.org +bzip2/libbzip2 version 1.0.5 of 10 December 2007 + +-------------------------------------------------------------------------- diff --git a/doc/upgrade-guide.txt b/doc/upgrade-guide.txt index fd5ccbef..a7bb726a 100644 --- a/doc/upgrade-guide.txt +++ b/doc/upgrade-guide.txt @@ -1642,3 +1642,860 @@ Split hardware mapping hint into vertex and index part vector2d.h Fix angle calculation for integer vectors +Changes for Version 1.5.2 +------------------------- +Even less visible changes have been made in this version. Only the automatic Solaris OS recognition has changed, so make sure you have all things defined properly if you compile for Solaris. And the float parser bugfix is a visible change, though non-interfering for existing code. + +Changes for Version 1.6.0 +------------------------- +This releases has many changes in method signatures. The most obvious ones are signedness changes from s32 to u32. Since many templates won't accept both types, you need to change the types manually in your code. The other major change is from many different types of strings to the new class io::path. These changes should be transparent to the app, unless you need proper overrides in derived classes. +Finally, some deprecated methods have been removed, and some were simply renamed. Just check the API if some methods is not found anymore. + +IMeshSceneNode.h +Added default parameters for identity transformation + IMeshSceneNode(ISceneNode* parent, ISceneManager* mgr, s32 id, + const core::vector3df& position = core::vector3df(0,0,0), + const core::vector3df& rotation = core::vector3df(0,0,0), + const core::vector3df& scale = core::vector3df(1,1,1)) + +path.h +This is a new type, which handles stuff with UTF file systems. +typedef core::string io::path; + +ESceneNodeTypes.h +New scene node identifiers + ESNT_SKY_DOME = MAKE_IRR_ID('s','k','y','d'), + ESNT_Q3SHADER_SCENE_NODE = MAKE_IRR_ID('q','3','s','h'), + ESNT_VOLUME_LIGHT = MAKE_IRR_ID('v','o','l','l'), + +IGUIListBox.h +New methods + virtual void setSelected(const wchar_t *item) = 0; + virtual void setItemHeight( s32 height ) = 0; + virtual void setDrawBackground(bool draw) = 0; + +ITexture.h +New texture generation flag for burnings video driver + //! Allow the Driver to use Non-Power-2-Textures + ETCF_ALLOW_NON_POWER_2 = 0x00000040, +Parameter change (now using path type instead of C-strings) + ITexture(const io::path& name) +Signedness change + virtual const core::dimension2d& getOriginalSize() const = 0; + virtual const core::dimension2d& getSize() const = 0; +New method + virtual bool hasAlpha() const +Parameter change (now using path type instead of stringc) + const io::path& getName() const + +ILightManager.h +This is a new interface for the light manager + class ILightManager : public IReferenceCounted + +IGUIEditBox.h +Signedness change + virtual core::dimension2du getTextDimension() = 0; + +ITriangleSelector.h +New method + virtual const ISceneNode* getSceneNodeForTriangle(u32 triangleIndex) const = 0; + +IMeshManipulator.h +New methods + virtual void makePlanarTextureMapping(scene::IMeshBuffer* meshbuffer, f32 resolution=0.001f) const =0; + virtual void makePlanarTextureMapping(scene::IMeshBuffer* buffer, f32 resolutionS, f32 resolutionT, u8 axis, const core::vector3df& offset) const =0; + virtual IMesh* createMeshWith1TCoords(IMesh* mesh) const = 0; + +SceneParameters.h +Removed parameter + const c8* const DMF_USE_MATERIALS_DIRS = "DMF_MaterialsDir"; +New parameters + const c8* const DMF_IGNORE_MATERIALS_DIRS = "DMF_IgnoreMaterialsDir"; + const c8* const OBJ_LOADER_IGNORE_MATERIAL_FILES = "OBJ_IgnoreMaterialFiles"; + const c8* const B3D_LOADER_IGNORE_MIPMAP_FLAG = "B3D_IgnoreMipmapFlag"; + const c8* const DEBUG_NORMAL_LENGTH = "DEBUG_Normal_Length"; + const c8* const DEBUG_NORMAL_COLOR = "DEBUG_Normal_Color"; + +SViewFrustum.h +Removed method (use getTransform) + void setTransformState( video::E_TRANSFORMATION_STATE state); +New methods + core::matrix4& getTransform( video::E_TRANSFORMATION_STATE state); + const core::matrix4& getTransform( video::E_TRANSFORMATION_STATE state) const; + bool clipLine(core::line3d& line) const; + +IFileList.h +Changed parameters (to io::path) + virtual const io::path& getFileName(u32 index) const = 0; + virtual const io::path& getFullFileName(u32 index) const = 0; +New methods + virtual u32 getFileSize(u32 index) const = 0; + virtual s32 findFile(const io::path& filename, bool isFolder=false) const = 0; + virtual const io::path& getPath() const = 0; + +coreutil.h +New methods + s32 isFileExtension(const io::path& filename, + const io::path& ext0, const io::path& ext1, const io::path& ext2) + bool hasFileExtension(const io::path& filename, + const io::path& ext0, const io::path& ext1 = "", const io::path& ext2 = "") + stringw& cutFilenameExtension ( stringw &dest, const stringw &source ) + core::stringw& deletePathFromFilename(core::stringw& filename) + core::stringc& deletePathFromFilename(core::stringc& filename) + io::path& deletePathFromPath(io::path& filename, s32 pathCount) + s32 isInSameDirectory ( const io::path& path, const io::path& file ) + +IGUIComboBox.h +New methods + virtual u32 getItemData(u32 idx) const = 0; + virtual s32 getIndexForItemData(u32 data ) const = 0; +New parameter + virtual u32 addItem(const wchar_t* text, u32 data = 0) = 0; + +irrArray.h +New allocation scheme member + array() +Use overload instead of different name + s32 binary_search(const T& element) const +New method + void setAllocStrategy ( eAllocStrategy newStrategy = ALLOC_STRATEGY_DOUBLE ) + s32 binary_search_multi(const T& element, s32 &last) + +IrrCompileConfig.h +New compiler flags + #define _IRR_MATERIAL_MAX_TEXTURES_ 4 + //! Define _IRR_D3D_USE_LEGACY_HLSL_COMPILER to enable the old HLSL compiler in recent DX SDKs + #define BURNINGVIDEO_RENDERER_CE + #define IGNORE_DEPRECATED_WARNING + #define _IRR_COMPILE_WITH_PLY_LOADER_ + #define _IRR_COMPILE_WITH_PLY_WRITER_ + #define _IRR_COMPILE_WITH_RGB_LOADER_ + #define __IRR_COMPILE_WITH_ZIP_ARCHIVE_LOADER_ + #define __IRR_COMPILE_WITH_MOUNT_ARCHIVE_LOADER_ + #define __IRR_COMPILE_WITH_PAK_ARCHIVE_LOADER_ + #define __IRR_COMPILE_WITH_TAR_ARCHIVE_LOADER_ + //! _IRR_WINDOWS_CE_PLATFORM_ for Windows CE + //! _IRR_COMPILE_WITH_WINDOWS_DEVICE_ for Windows API based device + //! _IRR_COMPILE_WITH_WINDOWS_CE_DEVICE_ for Windows CE API based device + //! _IRR_COMPILE_WITH_OSX_DEVICE_ for Cocoa native windowing on OSX + //! _IRR_COMPILE_WITH_X11_DEVICE_ for Linux X11 based device + //! _IRR_COMPILE_WITH_SDL_DEVICE_ for platform independent SDL framework + //! _IRR_COMPILE_WITH_CONSOLE_DEVICE_ for no windowing system, used as a fallback +Removed compiler flags + //! _IRR_USE_SDL_DEVICE_ for platform independent SDL framework + //! _IRR_USE_WINDOWS_DEVICE_ for Windows API based device + //! _IRR_USE_WINDOWS_CE_DEVICE_ for Windows CE API based device + //! _IRR_USE_LINUX_DEVICE_ for X11 based device + //! _IRR_USE_OSX_DEVICE_ for Cocoa native windowing on OSX +Old compilers rejected + # error "Only Microsoft Visual Studio 7.0 and later are supported." +Force symbol export in shared libraries built with gcc. + #define IRRLICHT_API __attribute__ ((visibility("default"))) + +IGUIFileOpenDialog.h +New method + virtual const io::path& getDirectoryName() = 0; + +EDeviceTypes.h +New enum for multi-device support + enum E_DEVICE_TYPE + +IMeshLoader.h +Changed parameter to use io::path instead of C strings + virtual bool isALoadableFileExtension(const io::path& filename) const = 0; + +IAnimatedMeshSceneNode.h +Changed return value to pointer type + virtual const SMD3QuaternionTag* getMD3TagTransformation( const core::stringc & tagname) = 0; + +ISceneManager.h +New enum values and numbering + enum E_SCENE_NODE_RENDER_PASS + ESNRP_NONE =0, + ESNRP_TRANSPARENT =16, + ESNRP_TRANSPARENT_EFFECT =32, +Changed parameter to use io::path instead of C strings + virtual IAnimatedMesh* getMesh(const io::path& filename) = 0; +New methods + virtual io::IFileSystem* getFileSystem() = 0; + virtual ITriangleSelector* createTriangleSelector(IAnimatedMeshSceneNode* node) = 0; + virtual const c8* getAnimatorTypeName(ESCENE_NODE_ANIMATOR_TYPE type) = 0; + virtual ISkinnedMesh* createSkinnedMesh() = 0; + virtual void setLightManager(ILightManager* lightManager) = 0; + virtual const IGeometryCreator* getGeometryCreator(void) const = 0; + virtual bool isCulled(const ISceneNode* node) const =0; +Changed return type to IMeshSceneNode + virtual IMeshSceneNode* addOctTreeSceneNode(IAnimatedMesh* mesh, ISceneNode* parent=0, + s32 id=-1, s32 minimalPolysPerNode=512, bool alsoAddIfMeshPointerZero=false) = 0; + virtual IMeshSceneNode* addOctTreeSceneNode(IMesh* mesh, ISceneNode* parent=0, + s32 id=-1, s32 minimalPolysPerNode=256, bool alsoAddIfMeshPointerZero=false) = 0; + virtual IMeshSceneNode* addQuake3SceneNode(IMeshBuffer* meshBuffer, const quake3::IShader * shader, + ISceneNode* parent=0, s32 id=-1) = 0; +New parameter invertMouse + virtual ICameraSceneNode* addCameraSceneNodeFPS(ISceneNode* parent = 0, + f32 rotateSpeed = 100.0f, f32 moveSpeed = 0.5f, s32 id=-1, + SKeyMap* keyMapArray=0, s32 keyMapSize=0, bool noVerticalMovement=false, + f32 jumpSpeed = 0.f, bool invertMouse=false) = 0; +New parameter radius + virtual ISceneNode* addSkyDomeSceneNode(video::ITexture* texture, + u32 horiRes=16, u32 vertRes=8, + f32 texturePercentage=0.9, f32 spherePercentage=2.0,f32 radius = 1000.f, + ISceneNode* parent=0, s32 id=-1) = 0; +Changed to use io::path instead of C strings + virtual ITerrainSceneNode* addTerrainSceneNode( + const io::path& heightMapFileName, + ISceneNode* parent=0, s32 id=-1, + virtual IAnimatedMesh* addHillPlaneMesh(const io::path& name, + const core::dimension2d& tileSize, const core::dimension2d& tileCount, + video::SMaterial* material = 0, f32 hillHeight = 0.0f, + const core::dimension2d& countHills = core::dimension2d(0.0f, 0.0f), + const core::dimension2d& textureRepeatCount = core::dimension2d(1.0f, 1.0f)) = 0; + virtual IAnimatedMesh* addArrowMesh(const io::path& name, + video::SColor vtxColor0=0xFFFFFFFF, + video::SColor vtxColor1=0xFFFFFFFF, + u32 tesselationCylinder=4, u32 tesselationCone=8, + virtual IAnimatedMesh* addSphereMesh(const io::path& name, + f32 radius=5.f, u32 polyCountX = 16, + u32 polyCountY = 16) = 0; + virtual bool saveScene(const io::path& filename, ISceneUserDataSerializer* userDataSerializer=0) = 0; + virtual bool loadScene(const io::path& filename, ISceneUserDataSerializer* userDataSerializer=0) = 0; +Changed to use io::path instead of C strings and signedness change + virtual IAnimatedMesh* addTerrainMesh(const io::path& meshname, + video::IImage* texture, video::IImage* heightmap, + const core::dimension2d& stretchSize = core::dimension2d(10.0f,10.0f), + f32 maxHeight=200.0f, + const core::dimension2d& defaultVertexBlockSize = core::dimension2d(64,64)) = 0; +New method + virtual IAnimatedMesh* addVolumeLightMesh(const io::path& name, + const u32 SubdivideU = 32, const u32 SubdivideV = 32, + const video::SColor FootColor = video::SColor(51, 0, 230, 180), + const video::SColor TailColor = video::SColor(0, 0, 0, 0)) = 0; +Constification of method + virtual ICameraSceneNode* getActiveCamera() const =0; +New parameters + virtual ISceneNodeAnimator* createFlyCircleAnimator( + const core::vector3df& center=core::vector3df(0.f,0.f,0.f), + f32 radius=100.f, f32 speed=0.001f, + const core::vector3df& direction=core::vector3df(0.f, 1.f, 0.f), + f32 startPosition = 0.f, + f32 radiusEllipsoid = 0.f) = 0; + virtual ISceneNodeAnimator* createFlyStraightAnimator(const core::vector3df& startPoint, + const core::vector3df& endPoint, u32 timeForWay, bool loop=false, bool pingpong = false) = 0; + +ISceneNodeAnimatorCollisionResponse.h +New interface + class ICollisionCallback : public virtual IReferenceCounted +New methods for ISceneNodeAnimatorCollisionResponse + virtual void setAnimateTarget ( bool enable ) = 0; + virtual bool getAnimateTarget () const = 0; + virtual void setTargetNode(ISceneNode * node) = 0; + virtual ISceneNode* getTargetNode(void) const = 0; + virtual bool collisionOccurred() const = 0; + virtual const core::vector3df & getCollisionPoint() const = 0; + virtual const core::triangle3df & getCollisionTriangle() const = 0; + virtual const core::vector3df & getCollisionResultPosition(void) const = 0; + virtual const ISceneNode* getCollisionNode(void) const = 0; + virtual void setCollisionCallback(ICollisionCallback* callback) = 0; + +ILightSceneNode.h +New methods + virtual void setVisible(bool isVisible) = 0; + +EMeshWriterEnums.h +New enums + EMWT_PLY = MAKE_IRR_ID('p','l','y',0) + EMWF_WRITE_BINARY = 0x4 + +ISceneNodeAnimator.h +New method + virtual bool hasFinished(void) const + +SMaterialLayer.h +Changed types + u8 TextureWrap; + bool BilinearFilter:1; + bool TrilinearFilter:1; + u8 AnisotropicFilter; +New member + s8 LODBias; + +IVideoModeList.h +Signedness change + virtual core::dimension2d getVideoModeResolution(s32 modeNumber) const = 0; + virtual core::dimension2d getVideoModeResolution(const core::dimension2d& minSize, const core::dimension2d& maxSize) const = 0; + virtual const core::dimension2d& getDesktopResolution() const = 0; + +EMaterialFlags.h +Enum values changed (all renumbered) + +ISkinnedMesh.h +Renamed methods (was create... before, but these methods grab the things they create) + virtual SSkinMeshBuffer* addMeshBuffer() = 0; + virtual SJoint* addJoint(SJoint *parent=0) = 0; + virtual SWeight* addWeight(SJoint *joint) = 0; + virtual SPositionKey* addPositionKey(SJoint *joint) = 0; + virtual SScaleKey* addScaleKey(SJoint *joint) = 0; + virtual SRotationKey* addRotationKey(SJoint *joint) = 0; + +SLight.h +Type change + bool CastShadows:1; + +IGUITreeView.h +New element +// written by Reinhard Ostermeier, reinhard@nospam.r-ostermeier.de + class IGUITreeView : public IGUIElement + +IAnimatedMeshMD3.h +Renamed class (from SMD3QuaterionTag) + struct SMD3QuaternionTag + +IGUIEnvironment.h +New methods + virtual IGUIImageList* createImageList( video::ITexture* texture, + core::dimension2d imageSize, bool useAlphaChannel ) = 0; + virtual IGUITreeView* addTreeView(const core::rect& rectangle, + IGUIElement* parent=0, s32 id=-1, bool drawBackground=false, + bool scrollBarVertical = true, bool scrollBarHorizontal = false) = 0; +Changed parameters to use io::path (instead of C strings) + virtual IGUIFont* getFont(const io::path& filename) = 0; + virtual IGUISpriteBank* getSpriteBank(const io::path& filename) = 0; + virtual IGUISpriteBank* addEmptySpriteBank(const io::path& name) = 0; + virtual bool saveGUI(const io::path& filename, IGUIElement* start=0) = 0; + virtual bool loadGUI(const io::path& filename, IGUIElement* parent=0) = 0; +New parameter "border" + virtual IGUISpinBox* addSpinBox(const wchar_t* text, const core::rect& rectangle, + bool border=true,IGUIElement* parent=0, s32 id=-1) = 0; + +IQ3Shader.h +Made non-const + static core::stringc irrEmptyStringc(""); +New enum values + enum eQ3MeshIndex + E_Q3_MESH_FOG, + E_Q3_MESH_UNRESOLVED, + +IGeometryCreator.h +New interface + class IGeometryCreator : public IReferenceCounted + +IFileArchive.h +New interfaces + class IFileArchive : public virtual IReferenceCounted + class IArchiveLoader : public virtual IReferenceCounted + +IFileSystem.h +Changed parameters to use io::path (instead of C strings/stringc) + virtual IReadFile* createAndOpenFile(const path& filename) =0; + virtual IReadFile* createMemoryReadFile(void* memory, s32 len, const path& fileName, bool deleteMemoryWhenDropped=false) =0; + virtual IWriteFile* createAndWriteFile(const path& filename, bool append=false) =0; + virtual const path& getWorkingDirectory() =0; + virtual bool changeWorkingDirectoryTo(const path& newDirectory) =0; + virtual path getAbsolutePath(const path& filename) const =0; + virtual path getFileDir(const path& filename) const =0; + virtual path getFileBasename(const path& filename, bool keepExtension=true) const =0; + virtual bool existFile(const path& filename) const =0; + virtual IXMLReader* createXMLReader(const path& filename) =0; + virtual IXMLReaderUTF8* createXMLReaderUTF8(const path& filename) =0; + virtual IXMLWriter* createXMLWriter(const path& filename) =0; +New methods + virtual IReadFile* createLimitReadFile(const path& fileName, + IReadFile* alreadyOpenedFile, long pos, long areaSize) =0; + virtual IWriteFile* createMemoryWriteFile(void* memory, s32 len, const path& fileName, bool deleteMemoryWhenDropped=false) =0; + virtual bool addFileArchive(const path& filename, bool ignoreCase=true, bool ignorePaths=true, + E_FILE_ARCHIVE_TYPE archiveType=EFAT_UNKNOWN) =0; + virtual void addArchiveLoader(IArchiveLoader* loader) =0; + virtual u32 getFileArchiveCount() const =0; + virtual bool removeFileArchive(u32 index) =0; + virtual bool removeFileArchive(const path& filename) =0; + virtual bool moveFileArchive(u32 sourceIndex, s32 relative) =0; + virtual IFileArchive* getFileArchive(u32 index) =0; + virtual path& flattenFilename(path& directory, const path& root="/") const =0; + virtual EFileSystemType setFileListSystem(EFileSystemType listType) =0; +Deprecate methods + virtual bool addZipFileArchive(const c8* filename, bool ignoreCase=true, bool ignorePaths=true) + virtual bool addFolderFileArchive(const c8* filename, bool ignoreCase=true, bool ignorePaths=true) + virtual bool addPakFileArchive(const c8* filename, bool ignoreCase=true, bool ignorePaths=true) +Constification of method + virtual IFileList* createFileList() =0; + +IrrlichtDevice.h +Renamed method (from setResizeAble) + virtual void setResizable(bool resize=false) = 0; +New methods + virtual void minimizeWindow() =0; + virtual void maximizeWindow() =0; + virtual void restoreWindow() =0; + virtual bool setGammaRamp(f32 red, f32 green, f32 blue, + f32 relativebrightness, f32 relativecontrast) =0; + virtual bool getGammaRamp(f32 &red, f32 &green, f32 &blue, + f32 &brightness, f32 &contrast) =0; + virtual E_DEVICE_TYPE getType() const = 0; + +irrMath.h +Renamed from ROUNDING_ERROR_32 + const f32 ROUNDING_ERROR_f32 = 0.000001f; +Renamed from ROUNDING_ERROR_64 + const f64 ROUNDING_ERROR_f64 = 0.00000001; +New constant + const s32 ROUNDING_ERROR_S32 = 1; +New methods + bool isnotzero(const f32 a, const f32 tolerance = ROUNDING_ERROR_f32) + u16 if_c_a_else_b ( const s16 condition, const u16 a, const u16 b ) + f32 squareroot(const f32 f) + f64 squareroot(const f64 f) + s32 squareroot(const s32 f) + f64 reciprocal_squareroot(const f64 x) + s32 reciprocal_squareroot(const s32 x) + f64 reciprocal ( const f64 f ) + +IGPUProgrammingServices.h +Changed parameters to use io::path + virtual s32 addHighLevelShaderMaterialFromFiles( + const io::path& vertexShaderProgramFileName, + const c8* vertexShaderEntryPointName = "main", + E_VERTEX_SHADER_TYPE vsCompileTarget = EVST_VS_1_1, + const io::path& pixelShaderProgramFileName = "", + const c8* pixelShaderEntryPointName = "main", + E_PIXEL_SHADER_TYPE psCompileTarget = EPST_PS_1_1, + IShaderConstantSetCallBack* callback = 0, + virtual s32 addShaderMaterialFromFiles(const io::path& vertexShaderProgramFileName, + const io::path& pixelShaderProgramFileName, + IShaderConstantSetCallBack* callback = 0, + E_MATERIAL_TYPE baseMaterial = video::EMT_SOLID, + s32 userData = 0) = 0; + +ISceneNode.h +New method + virtual bool isTrulyVisible() const + +IEventReceiver.h +New enum values + EMIE_MOUSE_DOUBLE_CLICK, + EMIE_MOUSE_TRIPLE_CLICK, + EGET_DIRECTORY_SELECTED, + EGET_EDITBOX_CHANGED, + EGET_EDITBOX_MARKING_CHANGED, + EGET_TREEVIEW_NODE_DESELECT, + EGET_TREEVIEW_NODE_SELECT, + EGET_TREEVIEW_NODE_EXPAND, + EGET_TREEVIEW_NODE_COLLAPS, + EGET_COUNT +New enum + enum E_MOUSE_BUTTON_STATE_MASK +New members + bool Shift:1; + bool Control:1; + u32 ButtonStates; +New methods + bool isLeftPressed() const { return 0 != ( ButtonStates & EMBSM_LEFT ); } + bool isRightPressed() const { return 0 != ( ButtonStates & EMBSM_RIGHT ); } + bool isMiddlePressed() const { return 0 != ( ButtonStates & EMBSM_MIDDLE ); } +Types changed + bool PressedDown:1; + bool Shift:1; + bool Control:1; + +IGUISpriteBank.h +New method + virtual void draw2DSpriteBatch(const core::array& indices, const core::array& pos, + const core::rect* clip=0, + const video::SColor& color= video::SColor(255,255,255,255), + u32 starttime=0, u32 currenttime=0, + bool loop=true, bool center=false) = 0; + +SMaterial.h +New enums + enum E_COMPARISON_FUNC + enum E_COLOR_PLANE + enum E_ALPHA_SOURCE + enum E_ANTI_ALIASING_MODE + enum E_COLOR_MATERIAL +New parameters + inline f32 pack_texureBlendFunc ( const E_BLEND_FACTOR srcFact, const E_BLEND_FACTOR dstFact, const E_MODULATE_FUNC modulate=EMFN_MODULATE_1X, const u32 alphaSource=EAS_TEXTURE ) + inline void unpack_texureBlendFunc ( E_BLEND_FACTOR &srcFact, E_BLEND_FACTOR &dstFact, + E_MODULATE_FUNC &modulo, u32& alphaSource, const f32 param ) +New methods + inline bool textureBlendFunc_hasAlpha ( const E_BLEND_FACTOR factor ) +Default value set elsewhere now (see IrrCompileConfig.h) + const u32 MATERIAL_MAX_TEXTURES = _IRR_MATERIAL_MAX_TEXTURES_; +Types changed + u8 ZBuffer; + bool Wireframe:1; + bool PointCloud:1; + bool GouraudShading:1; + bool Lighting:1; + bool ZWriteEnable:1; + bool BackfaceCulling:1; + bool FrontfaceCulling:1; + bool FogEnable:1; + bool NormalizeNormals:1; +New members + u8 AntiAliasing; + u8 ColorMask:4; + u8 ColorMaterial:3; +New constant + IRRLICHT_API extern SMaterial IdentityMaterial; + +IGUISkin.h +New enum values + EGDS_TITLEBARTEXT_DISTANCE_X, + EGDS_TITLEBARTEXT_DISTANCE_Y, + +quaternion.h +New parameters + void getMatrix( matrix4 &dest, const vector3df &translation ) const; +New method + void getMatrixCenter( matrix4 &dest, const vector3df ¢er, const vector3df &translation ) const; + +ISceneNodeAnimatorCameraFPS.h +New method + virtual void setInvertMouse(bool invert) = 0; + +IImage.h +New enum values + /** Floating Point formats. The following formats may only be used for render target textures. */ + ECF_R16F, + ECF_G16R16F, + ECF_A16B16G16R16F, + ECF_R32F, + ECF_G32R32F, + ECF_A32B32G32R32F, + ECF_UNKNOWN +Signedness change + virtual const core::dimension2d& getDimension() const = 0; + virtual void copyToScaling(void* target, u32 width, u32 height, ECOLOR_FORMAT format=ECF_A8R8G8B8, u32 pitch=0) =0; +New parameter + virtual void setPixel(u32 x, u32 y, const SColor &color, bool blend = false ) = 0; +New method + virtual void copyToScalingBoxFilter(IImage* target, s32 bias = 0, bool blend = false) = 0; + static u32 getBitsPerPixelFromFormat(const ECOLOR_FORMAT format) + static bool isRenderTargetOnlyFormat(const ECOLOR_FORMAT format) + +IVideoDriver.h +New enum values (only existing if _IRR_MATERIAL_MAX_TEXTURES_ large enough) + ETS_TEXTURE_4 + ETS_TEXTURE_5 + ETS_TEXTURE_6 + ETS_TEXTURE_7 +New enums + enum E_RENDER_TARGET + enum E_FOG_TYPE +New type + struct SOverrideMaterial +New methods + virtual u32 getImageLoaderCount() const = 0; + virtual IImageLoader* getImageLoader(u32 n) = 0; + virtual u32 getImageWriterCount() const = 0; + virtual IImageWriter* getImageWriter(u32 n) = 0; + virtual bool setRenderTarget(E_RENDER_TARGET target, bool clearTarget=true, + bool clearZBuffer=true, SColor color=video::SColor(0,0,0,0)) =0; + virtual void draw2DVertexPrimitiveList(const void* vertices, u32 vertexCount, + const void* indexList, u32 primCount, + E_VERTEX_TYPE vType=EVT_STANDARD, + scene::E_PRIMITIVE_TYPE pType=scene::EPT_TRIANGLES, + E_INDEX_TYPE iType=EIT_16BIT) =0; + virtual void draw2DImageBatch(const video::ITexture* texture, + const core::array >& positions, + const core::array >& sourceRects, + const core::rect* clipRect=0, + SColor color=SColor(255,255,255,255), + bool useAlphaChannelOfTexture=false) =0; + virtual void turnLightOn(s32 lightIndex, bool turnOn) =0; + virtual bool writeImageToFile(IImage* image, io::IWriteFile* file, u32 param =0) =0; + virtual IImage* createImage(ITexture* texture, + const core::position2d& pos, const core::dimension2d& size) =0; + virtual void setMinHardwareBufferVertexCount(u32 count) =0; + virtual SOverrideMaterial& getOverrideMaterial() =0; +Changed parameters to use io::path + virtual ITexture* getTexture(const io::path& filename) = 0; + virtual void renameTexture(ITexture* texture, const io::path& newName) = 0; + virtual ITexture* addTexture(const io::path& name, IImage* image) = 0; + virtual IImage* createImageFromFile(const io::path& filename) = 0; + virtual bool writeImageToFile(IImage* image, const io::path& filename, u32 param = 0) = 0; + virtual video::ITexture* findTexture(const io::path& filename) = 0; +Changed signedness + virtual ITexture* addTexture(const core::dimension2d& size, + const io::path& name, ECOLOR_FORMAT format = ECF_A8R8G8B8) = 0; + virtual const core::dimension2d& getScreenSize() const =0; + virtual const core::dimension2d& getCurrentRenderTargetSize() const =0; + virtual IImage* createImageFromData(ECOLOR_FORMAT format, + const core::dimension2d& size, void *data, + bool ownForeignMemory=false, + bool deleteMemory = true) =0; + virtual IImage* createImage(ECOLOR_FORMAT format, const core::dimension2d& size) =0; + virtual IImage* createImage(IImage* imageToCopy, + const core::position2d& pos, + const core::dimension2d& size) =0; + virtual void OnResize(const core::dimension2d& size) =0; +Changed signedness and usage of io::path + virtual ITexture* addRenderTargetTexture(const core::dimension2d& size, + const io::path& name = "rt", const ECOLOR_FORMAT format = ECF_UNKNOWN) =0; +Removed deprecated method + virtual ITexture* createRenderTargetTexture(const core::dimension2d& size, + const c8* name=0) =0; +New parameter + virtual void makeColorKeyTexture(video::ITexture* texture, + video::SColor color, bool zeroTexels = false) const =0; + virtual void makeColorKeyTexture(video::ITexture* texture, + core::position2d colorKeyPixelPos, bool zeroTexels = false) const =0; +Changed parameters + virtual void setFog(SColor color=SColor(0,255,255,255), + E_FOG_TYPE fogType=EFT_FOG_LINEAR, + f32 start=50.0f, f32 end=100.0f, f32 density=0.01f, + bool pixelFog=false, bool rangeFog=false) =0; +Changed return types + virtual s32 addDynamicLight(const SLight& light) =0; + +EDriverFeatures.h +New enum values + EVDF_ALPHA_TO_COVERAGE, + EVDF_COLOR_MASK, + +IGUIScrollBar.h +New methods + virtual void setMin(s32 max) = 0; + virtual s32 getMin() const = 0; + +IQ3LevelMesh.h +Removed method + virtual void releaseMesh(s32 index) = 0; +Made return value non-const + virtual quake3::tQ3EntityList& getEntityList() = 0; + +ISceneCollisionManager.h +New parameter + virtual bool getCollisionPoint(const core::line3d& ray, + ITriangleSelector* selector, core::vector3df& outCollisionPoint, + core::triangle3df& outTriangle, const ISceneNode*& outNode) =0; + virtual core::vector3df getCollisionResultPosition( + ITriangleSelector* selector, + const core::vector3df &ellipsoidPosition, + const core::vector3df& ellipsoidRadius, + const core::vector3df& ellipsoidDirectionAndSpeed, + core::triangle3df& triout, + core::vector3df& hitPosition, + bool& outFalling, + const ISceneNode*& outNode, + f32 slidingSpeed = 0.0005f, + const core::vector3df& gravityDirectionAndSpeed = core::vector3df(0.0f, 0.0f, 0.0f)) = 0; +Made parameter const& + virtual core::line3d getRayFromScreenCoordinates( + const core::position2d & pos, ICameraSceneNode* camera = 0) = 0; + virtual core::position2d getScreenCoordinatesFrom3DPosition( + const core::vector3df & pos, ICameraSceneNode* camera=0) = 0; +Made parameter const& and added new parameter + virtual ISceneNode* getSceneNodeFromScreenCoordinatesBB(const core::position2d& pos, + s32 idBitMask=0, bool bNoDebugObjects=false, ISceneNode* root=0) =0; + virtual ISceneNode* getSceneNodeFromRayBB(const core::line3d& ray, + s32 idBitMask=0, bool bNoDebugObjects=false, ISceneNode* root=0) =0; +New method + virtual ISceneNode* getSceneNodeAndCollisionPointFromRay( + core::line3df ray, core::vector3df & outCollisionPoint, + core::triangle3df & outTriangle, s32 idBitMask = 0, + ISceneNode * collisionRootNode = 0, bool noDebugObjects = false) = 0; + +irrlicht.h +Changed interface of method (qualifiers and signedness) + extern "C" IRRLICHT_API IrrlichtDevice* IRRCALLCONV createDevice( + video::E_DRIVER_TYPE deviceType = video::EDT_SOFTWARE, + // parantheses are necessary for some compilers + const core::dimension2d& windowSize = (core::dimension2d(640,480)), + u32 bits = 16, + bool fullscreen = false, + bool stencilbuffer = false, + bool vsync = false, + IEventReceiver* receiver = 0); + extern "C" IRRLICHT_API IrrlichtDevice* IRRCALLCONV createDeviceEx( + const SIrrlichtCreationParameters& parameters); + +IImageLoader.h +Changed parameters to use io::path + virtual bool isALoadableFileExtension(const io::path& filename) const = 0; + +IGUIWindow.h +New methods + virtual bool isDraggable() const = 0; + virtual void setDraggable(bool draggable) = 0; + virtual void setDrawBackground(bool draw) = 0; + virtual bool getDrawBackground() const = 0; + virtual void setDrawTitlebar(bool draw) = 0; + virtual bool getDrawTitlebar() const = 0; + +ICameraSceneNode.h +New methods + virtual void setViewMatrixAffector(const core::matrix4& affector) =0; + virtual const core::matrix4& getViewMatrixAffector() const =0; + +EGUIElementTypes.h +New enum value + EGUIET_TREE_VIEW, + +IImageWriter.h +Changed parameters to use io::path + virtual bool isAWriteableFileExtension(const io::path& filename) const = 0; + +SIrrCreationParameters.h +Added members + E_DEVICE_TYPE DeviceType; + bool Doublebuffer; + bool Stereobuffer; +Changed signedness + core::dimension2d WindowSize; +Changed type (from bool) + u8 AntiAlias; + +matrix4.h +New methods + bool isOrthogonal() const; + CMatrix4& buildRotateFromTo(const core::vector3df& from, const core::vector3df& to); + void setRotationCenter(const core::vector3df& center, const core::vector3df& translate); + void buildAxisAlignedBillboard( const core::vector3df& camPos, + const core::vector3df& center, const core::vector3df& translation, + const core::vector3df& axis, const core::vector3df& from); + +IWriteFile.h +Changed parameters to use io::path + virtual const path& getFileName() const = 0; + +IGUITable.h +New methods + virtual void setSelected( s32 index ) = 0; +Changed type (from wide c string) + virtual void setCellText(u32 rowIndex, u32 columnIndex, const core::stringw& text) = 0; + virtual void setCellText(u32 rowIndex, u32 columnIndex, const core::stringw& text, video::SColor color) = 0; + +SKeyMap.h +New enum value + EKA_CROUCH, + +IGUIFont.h +Changed type (from wide c string) + virtual void draw(const core::stringw& text, const core::rect& position, + video::SColor color, bool hcenter=false, bool vcenter=false, + const core::rect* clip=0) = 0; +Changed signedness + virtual core::dimension2d getDimension(const wchar_t* text) const = 0; +New method + virtual void setInvisibleCharacters( const wchar_t *s ) = 0; + +IMeshCache.h +Changed parameters to use io::path + virtual void addMesh(const io::path& filename, IAnimatedMesh* mesh) = 0; + virtual IAnimatedMesh* getMeshByFilename(const io::path& filename) = 0; + virtual const io::path& getMeshFilename(u32 index) const = 0; + virtual const io::path& getMeshFilename(const IAnimatedMesh* const mesh) const = 0; + virtual const io::path& getMeshFilename(const IMesh* const mesh) const = 0; + virtual bool setMeshFilename(u32 index, const io::path& filename) = 0; + virtual bool setMeshFilename(const IAnimatedMesh* const mesh, const io::path& filename) = 0; + virtual bool setMeshFilename(const IMesh* const mesh, const io::path& filename) = 0; + virtual bool isMeshLoaded(const io::path& filename) = 0; + +IGUIButton.h +Added default value + virtual void setImage(video::ITexture* image=0) = 0; + virtual void setPressedImage(video::ITexture* image=0) = 0; + virtual void setSpriteBank(IGUISpriteBank* bank=0) = 0; + virtual void setIsPushButton(bool isPushButton=true) = 0; + virtual void setPressed(bool pressed=true) = 0; + virtual void setUseAlphaChannel(bool useAlphaChannel=true) = 0; + virtual void setDrawBorder(bool border=true) = 0; +New methods + virtual void setScaleImage(bool scaleImage=true) = 0; + virtual bool isScalingImage() const = 0; + +position2d.h +Replaced by vector2d + +IGUIImageList.h +New interface + class IGUIImageList : public virtual IReferenceCounted + +rect.h +Added second template parameter to allow mismatched signedness + template + rect(const position2d& pos, const dimension2d& size) + +IParticleEmitter.h +Removed wrong overrides + virtual void serializeAttributes(io::IAttributes* out, + io::SAttributeReadWriteOptions* options=0) const {} + virtual s32 deserializeAttributes(s32 startIndex, io::IAttributes* in, + io::SAttributeReadWriteOptions* options=0) { return 0; } + +IOSOperator.h +Return const string + virtual const c8* getTextFromClipboard() const = 0; + +IGUIElement.h +Signedness change + void setMaxSize(core::dimension2du size) + void setMinSize(core::dimension2du size) + +IReadFile.h +Changed parameters to use io::path + virtual const io::path& getFileName() const = 0; + IReadFile* createReadFile(const io::path& fileName); + IReadFile* createLimitReadFile(const io::path& fileName, IReadFile* alreadyOpenedFile, long pos, long areaSize); + IReadFile* createMemoryReadFile(void* memory, long size, const io::path& fileName, bool deleteMemoryWhenDropped); + +IGUITabControl.h +New methods + virtual void setTabMaxWidth(s32 width ) = 0; + virtual s32 getTabMaxWidth() const = 0; + +IParticleAffector.h +Removed wrong overrides + virtual void serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options=0) const {} + virtual s32 deserializeAttributes(s32 startIndex, io::IAttributes* in, io::SAttributeReadWriteOptions* options=0) { return 0; } + +ILogger.h +New method + virtual void log(const c8* text, const wchar_t* hint, ELOG_LEVEL ll=ELL_INFORMATION) = 0; + +vector2d.h +New methods + vector2d(const dimension2d& other) : X(other.Width), Y(other.Height) {} + vector2d& operator=(const dimension2d& other) { X = other.Width; Y = other.Height; return *this; } + vector2d operator+(const dimension2d& other) const { return vector2d(X + other.Width, Y + other.Height); } + vector2d& operator+=(const dimension2d& other) { X += other.Width; Y += other.Height; return *this; } + vector2d operator-(const dimension2d& other) const { return vector2d(X - other.Width, Y - other.Height); } + vector2d& operator-=(const dimension2d& other) { X -= other.Width; Y -= other.Height; return *this; } + // These methods are declared in dimension2d, but need definitions of vector2d + template + dimension2d::dimension2d(const vector2d& other) : Width(other.X), Height(other.Y) { } + template + bool dimension2d::operator==(const vector2d& other) const { return Width == other.X && Height == other.Y; } + +Changes for Version 1.6.1 +------------------------- +This is again just a bugfix release. However, some minor API changes have happened. The most important one is the removal of lins anti-aliasing from SMaterial's default values. Please add that line smoothing flag to the materials you want to be smoothed. But note that this may lead to drastically reduced performance, if no multi-sampling is active. + +IFileList.h +new methods + virtual u32 getID(u32 index) const = 0; + virtual u32 addItem(const io::path& fullPath, u32 size, bool isDirectory, u32 id=0) = 0; + virtual void sort() = 0; + +IrrCompileConfig.h +Removed auto recognition of Solaris OS, please define the setting on your own if you need it + _IRR_SOLARIS_PLATFORM_ + +IGUITreeView.h +removed methods (use automatically generated versions) + IGUITreeViewNode() {} + virtual ~IGUITreeViewNode() {} + virtual ~IGUITreeView() {} + +IFileSystem.h +new method + virtual IFileList* createEmptyFileList(const io::path& path, bool ignoreCase, bool ignorePaths) =0; + +SMaterial.h +Removed default value (EAAM_LINE_SMOOTH from AntiAliasing) + ZBuffer(ECFN_LESSEQUAL), AntiAliasing(EAAM_SIMPLE), ColorMask(ECP_ALL), + +IGUISkin.h +new enum value + EGST_COUNT + diff --git a/examples/02.Quake3Map/main.cpp b/examples/02.Quake3Map/main.cpp index 61cc2b1d..364e4bdb 100644 --- a/examples/02.Quake3Map/main.cpp +++ b/examples/02.Quake3Map/main.cpp @@ -6,7 +6,7 @@ controlled camera. Please note that you should know the basics of the engine before starting this tutorial. Just take a short look at the first tutorial, if you haven't done -this yet: http://irrlicht.sourceforge.net/tut001.html +this yet: http://irrlicht.sourceforge.net/tut001.html Lets start like the HelloWorld example: We include the irrlicht header files and an additional file to be able to ask the user for a driver type using the @@ -71,7 +71,7 @@ int main() case 'f': driverType = video::EDT_BURNINGSVIDEO;break; case 'g': driverType = video::EDT_NULL; break; default: return 1; - } + } // create device and exit if creation failed @@ -105,24 +105,24 @@ int main() really animated, they are only a huge chunk of static geometry with some materials attached. Hence the IAnimatedMesh consists of only one frame, so we get the "first frame" of the "animation", which is our - quake level and create an OctTree scene node with it, using - irr::scene::ISceneManager::addOctTreeSceneNode(). - The OctTree optimizes the scene a little bit, trying to draw only geometry - which is currently visible. An alternative to the OctTree would be a + quake level and create an Octree scene node with it, using + irr::scene::ISceneManager::addOctreeSceneNode(). + The Octree optimizes the scene a little bit, trying to draw only geometry + which is currently visible. An alternative to the Octree would be a irr::scene::IMeshSceneNode, which would always draw the complete geometry of the mesh, without optimization. Try it: Use irr::scene::ISceneManager::addMeshSceneNode() instead of - addOctTreeSceneNode() and compare the primitives drawn by the video + addOctreeSceneNode() and compare the primitives drawn by the video driver. (There is a irr::video::IVideoDriver::getPrimitiveCountDrawn() method in the irr::video::IVideoDriver class). Note that this - optimization with the OctTree is only useful when drawing huge meshes + optimization with the Octree is only useful when drawing huge meshes consisting of lots of geometry. */ scene::IAnimatedMesh* mesh = smgr->getMesh("20kdm2.bsp"); scene::ISceneNode* node = 0; - + if (mesh) - node = smgr->addOctTreeSceneNode(mesh->getMesh(0), 0, -1, 1024); + node = smgr->addOctreeSceneNode(mesh->getMesh(0), 0, -1, 1024); // node = smgr->addMeshSceneNode(mesh->getMesh(0)); /* diff --git a/examples/03.CustomSceneNode/main.cpp b/examples/03.CustomSceneNode/main.cpp index d9584e9f..2fd83d7b 100644 --- a/examples/03.CustomSceneNode/main.cpp +++ b/examples/03.CustomSceneNode/main.cpp @@ -132,7 +132,7 @@ public: driver->setMaterial(Material); driver->setTransform(video::ETS_WORLD, AbsoluteTransformation); - driver->drawVertexPrimitiveList(&Vertices[0], 4, &indices[0], 4, video::EVT_STANDARD, scene::EPT_POINTS); + driver->drawVertexPrimitiveList(&Vertices[0], 4, &indices[0], 4, video::EVT_STANDARD, scene::EPT_TRIANGLES, video::EIT_16BIT); } /* diff --git a/examples/06.2DGraphics/main.cpp b/examples/06.2DGraphics/main.cpp index d60d2e18..36ef63a5 100644 --- a/examples/06.2DGraphics/main.cpp +++ b/examples/06.2DGraphics/main.cpp @@ -89,6 +89,12 @@ int main() core::rect imp1(349,15,385,78); core::rect imp2(387,15,423,78); + /* + Prepare a nicely filtering 2d render mode for special cases. + */ + driver->getMaterial2D().TextureLayer[0].BilinearFilter=true; + driver->getMaterial2D().AntiAliasing=video::EAAM_FULL_BASIC; + /* Everything is prepared, now we can draw everything in the draw loop, between the begin scene and end scene calls. In this example, we are @@ -148,16 +154,18 @@ int main() video::SColor(255,time % 255,time % 255,255)); /* - At last, we draw the Irrlicht Engine logo (without - using a color or an alpha channel) and a transparent 2d - Rectangle at the position of the mouse cursor. + Next, we draw the Irrlicht Engine logo (without + using a color or an alpha channel). Since we slightly scale + the image we use the prepared filter mode. */ - - // draw logo - driver->draw2DImage(images, core::position2d(10,10), + driver->enableMaterial2D(); + driver->draw2DImage(images, core::rect(10,10,108,48), core::rect(354,87,442,118)); + driver->enableMaterial2D(false); - // draw transparent rect under cursor + /* + Finally draw a half-transparent rect under the mouse cursor. + */ core::position2d m = device->getCursorControl()->getPosition(); driver->draw2DRectangle(video::SColor(100,255,255,255), core::rect(m.X-20, m.Y-20, m.X+20, m.Y+20)); diff --git a/examples/07.Collision/main.cpp b/examples/07.Collision/main.cpp index df6e65b8..5c8e3b44 100644 --- a/examples/07.Collision/main.cpp +++ b/examples/07.Collision/main.cpp @@ -78,7 +78,7 @@ int main() // The Quake mesh is pickable, but doesn't get highlighted. if (q3levelmesh) - q3node = smgr->addOctTreeSceneNode(q3levelmesh->getMesh(0), 0, IDFlag_IsPickable); + q3node = smgr->addOctreeSceneNode(q3levelmesh->getMesh(0), 0, IDFlag_IsPickable); /* So far so good, we've loaded the quake 3 level like in tutorial 2. Now, @@ -87,7 +87,7 @@ int main() nodes for doing different things with them, for example collision detection. There are different triangle selectors, and all can be created with the ISceneManager. In this example, we create an - OctTreeTriangleSelector, which optimizes the triangle output a little + OctreeTriangleSelector, which optimizes the triangle output a little bit by reducing it like an octree. This is very useful for huge meshes like quake 3 levels. After we created the triangle selector, we attach it to the q3node. This is not necessary, but in this way, we do not @@ -101,7 +101,7 @@ int main() { q3node->setPosition(core::vector3df(-1350,-130,-1400)); - selector = smgr->createOctTreeTriangleSelector( + selector = smgr->createOctreeTriangleSelector( q3node->getMesh(), q3node, 128); q3node->setTriangleSelector(selector); // We're not done with this selector yet, so don't drop it. @@ -237,6 +237,9 @@ int main() scene::ISceneCollisionManager* collMan = smgr->getSceneCollisionManager(); int lastFPS = -1; + // draw the selection triangle only as wireframe + material.Wireframe=true; + while(device->run()) if (device->isWindowActive()) { diff --git a/examples/09.Meshviewer/main.cpp b/examples/09.Meshviewer/main.cpp index efae647d..58288d05 100644 --- a/examples/09.Meshviewer/main.cpp +++ b/examples/09.Meshviewer/main.cpp @@ -16,7 +16,6 @@ tutorial, we use a lot stuff from the gui namespace. #include #include - using namespace irr; using namespace gui; @@ -35,7 +34,7 @@ core::stringw Caption; scene::ISceneNode* Model = 0; scene::ISceneNode* SkyBox = 0; bool Octree=false; -bool useLight=false; +bool UseLight=false; scene::ICameraSceneNode* Camera[2] = {0, 0}; @@ -76,11 +75,24 @@ enum GUI_ID_ABOUT, GUI_ID_QUIT, + GUI_ID_TEXTUREFILTER, + GUI_ID_SKIN_TRANSPARENCY, + GUI_ID_SKIN_ANIMATION_FPS, + + GUI_ID_BUTTON_SET_SCALE, + GUI_ID_BUTTON_SCALE_MUL10, + GUI_ID_BUTTON_SCALE_DIV10, + GUI_ID_BUTTON_OPEN_MODEL, + GUI_ID_BUTTON_SHOW_ABOUT, + GUI_ID_BUTTON_SHOW_TOOLBOX, + GUI_ID_BUTTON_SELECT_ARCHIVE, + // And some magic numbers MAX_FRAMERATE = 1000, DEFAULT_FRAMERATE = 30 }; + /* Toggle between various cameras */ @@ -96,6 +108,42 @@ void setActiveCamera(scene::ICameraSceneNode* newActive) Device->getSceneManager()->setActiveCamera(newActive); } +/* + Set the skin transparency by changing the alpha values of all skin-colors +*/ +void SetSkinTransparency(s32 alpha, irr::gui::IGUISkin * skin) +{ + for (s32 i=0; igetColor((EGUI_DEFAULT_COLOR)i); + col.setAlpha(alpha); + skin->setColor((EGUI_DEFAULT_COLOR)i, col); + } +} + +/* + Update the display of the model scaling +*/ +void UpdateScaleInfo(scene::ISceneNode* model) +{ + IGUIElement* toolboxWnd = Device->getGUIEnvironment()->getRootGUIElement()->getElementFromId(GUI_ID_DIALOG_ROOT_WINDOW, true); + if (!toolboxWnd) + return; + if (!model) + { + toolboxWnd->getElementFromId(GUI_ID_X_SCALE, true)->setText( L"-" ); + toolboxWnd->getElementFromId(GUI_ID_Y_SCALE, true)->setText( L"-" ); + toolboxWnd->getElementFromId(GUI_ID_Z_SCALE, true)->setText( L"-" ); + } + else + { + core::vector3df scale = model->getScale(); + toolboxWnd->getElementFromId(GUI_ID_X_SCALE, true)->setText( core::stringw(scale.X).c_str() ); + toolboxWnd->getElementFromId(GUI_ID_Y_SCALE, true)->setText( core::stringw(scale.Y).c_str() ); + toolboxWnd->getElementFromId(GUI_ID_Z_SCALE, true)->setText( core::stringw(scale.Z).c_str() ); + } +} + /* The three following functions do several stuff used by the mesh viewer. The first function showAboutText() simply displays a messagebox with a caption and @@ -131,7 +179,8 @@ void loadModel(const c8* fn) extension == ".png" || extension == ".ppm" || extension == ".pgm" || extension == ".pbm" || extension == ".psd" || extension == ".tga" || - extension == ".bmp" || extension == ".wal") + extension == ".bmp" || extension == ".wal" || + extension == ".rgb" || extension == ".rgba") { video::ITexture * texture = Device->getVideoDriver()->getTexture( filename ); @@ -146,14 +195,9 @@ void loadModel(const c8* fn) return; } // if a archive is loaded add it to the FileArchive.. - else if (extension == ".pk3" || extension == ".zip") + else if (extension == ".pk3" || extension == ".zip" || extension == ".pak" || extension == ".npk") { - Device->getFileSystem()->addZipFileArchive(filename.c_str()); - return; - } - else if (extension == ".pak") - { - Device->getFileSystem()->addPakFileArchive(filename.c_str()); + Device->getFileSystem()->addFileArchive(filename.c_str()); return; } @@ -164,6 +208,16 @@ void loadModel(const c8* fn) Model = 0; + if (extension==".irr") + { + core::array outNodes; + Device->getSceneManager()->loadScene(filename); + Device->getSceneManager()->getSceneNodesFromType(scene::ESNT_ANIMATED_MESH, outNodes); + if (outNodes.size()) + Model = outNodes[0]; + return; + } + scene::IAnimatedMesh* m = Device->getSceneManager()->getMesh( filename.c_str() ); if (!m) @@ -180,15 +234,15 @@ void loadModel(const c8* fn) // set default material properties if (Octree) - Model = Device->getSceneManager()->addOctTreeSceneNode(m->getMesh(0)); + Model = Device->getSceneManager()->addOctreeSceneNode(m->getMesh(0)); else { scene::IAnimatedMeshSceneNode* animModel = Device->getSceneManager()->addAnimatedMeshSceneNode(m); animModel->setAnimationSpeed(30); Model = animModel; } - Model->setMaterialFlag(video::EMF_LIGHTING, useLight); - Model->setMaterialFlag(video::EMF_NORMALIZE_NORMALS, useLight); + Model->setMaterialFlag(video::EMF_LIGHTING, UseLight); + Model->setMaterialFlag(video::EMF_NORMALIZE_NORMALS, UseLight); // Model->setMaterialFlag(video::EMF_BACK_FACE_CULLING, false); Model->setDebugDataVisible(scene::EDS_OFF); @@ -198,13 +252,7 @@ void loadModel(const c8* fn) if (menu) for(int item = 1; item < 6; ++item) menu->setItemChecked(item, false); - IGUIElement* toolboxWnd = Device->getGUIEnvironment()->getRootGUIElement()->getElementFromId(GUI_ID_DIALOG_ROOT_WINDOW, true); - if ( toolboxWnd ) - { - toolboxWnd->getElementFromId(GUI_ID_X_SCALE, true)->setText(L"1.0"); - toolboxWnd->getElementFromId(GUI_ID_Y_SCALE, true)->setText(L"1.0"); - toolboxWnd->getElementFromId(GUI_ID_Z_SCALE, true)->setText(L"1.0"); - } + UpdateScaleInfo(Model); } @@ -234,7 +282,7 @@ void createToolBox() // add some edit boxes and a button to tab one env->addStaticText(L"Scale:", - core::rect(10,20,150,45), false, false, t1); + core::rect(10,20,60,45), false, false, t1); env->addStaticText(L"X:", core::rect(22,48,40,66), false, false, t1); env->addEditBox(L"1.0", core::rect(40,46,130,66), true, t1, GUI_ID_X_SCALE); env->addStaticText(L"Y:", core::rect(22,82,40,GUI_ID_OPEN_MODEL), false, false, t1); @@ -242,13 +290,19 @@ void createToolBox() env->addStaticText(L"Z:", core::rect(22,108,40,126), false, false, t1); env->addEditBox(L"1.0", core::rect(40,106,130,126), true, t1, GUI_ID_Z_SCALE); - env->addButton(core::rect(10,134,85,165), t1, 1101, L"Set"); + env->addButton(core::rect(10,134,85,165), t1, GUI_ID_BUTTON_SET_SCALE, L"Set"); + + // quick scale buttons + env->addButton(core::rect(65,20,95,40), t1, GUI_ID_BUTTON_SCALE_MUL10, L"* 10"); + env->addButton(core::rect(100,20,130,40), t1, GUI_ID_BUTTON_SCALE_DIV10, L"* 0.1"); + + UpdateScaleInfo(Model); // add transparency control env->addStaticText(L"GUI Transparency Control:", core::rect(10,200,150,225), true, false, t1); IGUIScrollBar* scrollbar = env->addScrollBar(true, - core::rect(10,225,150,240), t1, 104); + core::rect(10,225,150,240), t1, GUI_ID_SKIN_TRANSPARENCY); scrollbar->setMax(255); scrollbar->setPos(255); @@ -256,8 +310,9 @@ void createToolBox() env->addStaticText(L"Framerate:", core::rect(10,240,150,265), true, false, t1); scrollbar = env->addScrollBar(true, - core::rect(10,265,150,280), t1, 105); + core::rect(10,265,150,280), t1, GUI_ID_SKIN_ANIMATION_FPS); scrollbar->setMax(MAX_FRAMERATE); + scrollbar->setMin(-MAX_FRAMERATE); scrollbar->setPos(DEFAULT_FRAMERATE); // bring irrlicht engine logo to front, because it @@ -265,7 +320,6 @@ void createToolBox() root->bringToFront(root->getElementFromId(666, true)); } - /* To get all the events sent by the GUI Elements, we need to create an event receiver. This one is really simple. If an event occurs, it checks the id of @@ -281,42 +335,8 @@ public: if (event.EventType == EET_KEY_INPUT_EVENT && event.KeyInput.PressedDown == false) { - if (event.KeyInput.Key == irr::KEY_ESCAPE) - { - if (Device) - { - scene::ICameraSceneNode * camera = - Device->getSceneManager()->getActiveCamera(); - if (camera) - { - camera->setInputReceiverEnabled( !camera->isInputReceiverEnabled() ); - } - return true; - } - } - else if (event.KeyInput.Key == irr::KEY_F1) - { - if (Device) - { - IGUIElement* elem = Device->getGUIEnvironment()->getRootGUIElement()->getElementFromId(GUI_ID_POSITION_TEXT); - if (elem) - elem->setVisible(!elem->isVisible()); - } - } - else if (event.KeyInput.Key == irr::KEY_KEY_M) - { - if (Device) - Device->minimizeWindow(); - } - else if (event.KeyInput.Key == irr::KEY_KEY_L) - { - useLight=!useLight; - if (Model) - { - Model->setMaterialFlag(video::EMF_LIGHTING, useLight); - Model->setMaterialFlag(video::EMF_NORMALIZE_NORMALS, useLight); - } - } + if ( OnKeyUp(event.KeyInput.Key) ) + return true; } if (event.EventType == EET_GUI_EVENT) @@ -327,107 +347,9 @@ public: switch(event.GUIEvent.EventType) { case EGET_MENU_ITEM_SELECTED: - { // a menu item was clicked - - IGUIContextMenu* menu = (IGUIContextMenu*)event.GUIEvent.Caller; - s32 id = menu->getItemCommandId(menu->getSelectedItem()); - - switch(id) - { - case GUI_ID_OPEN_MODEL: // File -> Open Model - env->addFileOpenDialog(L"Please select a model file to open"); - break; - case GUI_ID_SET_MODEL_ARCHIVE: // File -> Set Model Archive - env->addFileOpenDialog(L"Please select your game archive/directory"); - break; - case GUI_ID_LOAD_AS_OCTREE: // File -> LoadAsOctree - Octree = !Octree; - menu->setItemChecked(menu->getSelectedItem(), Octree); - break; - case GUI_ID_QUIT: // File -> Quit - Device->closeDevice(); - break; - case GUI_ID_SKY_BOX_VISIBLE: // View -> Skybox - menu->setItemChecked(menu->getSelectedItem(), !menu->isItemChecked(menu->getSelectedItem())); - SkyBox->setVisible(!SkyBox->isVisible()); - break; - case GUI_ID_DEBUG_OFF: // View -> Debug Information - menu->setItemChecked(menu->getSelectedItem()+1, false); - menu->setItemChecked(menu->getSelectedItem()+2, false); - menu->setItemChecked(menu->getSelectedItem()+3, false); - menu->setItemChecked(menu->getSelectedItem()+4, false); - menu->setItemChecked(menu->getSelectedItem()+5, false); - menu->setItemChecked(menu->getSelectedItem()+6, false); - if (Model) - Model->setDebugDataVisible(scene::EDS_OFF); - break; - case GUI_ID_DEBUG_BOUNDING_BOX: // View -> Debug Information - menu->setItemChecked(menu->getSelectedItem(), !menu->isItemChecked(menu->getSelectedItem())); - if (Model) - Model->setDebugDataVisible((scene::E_DEBUG_SCENE_TYPE)(Model->isDebugDataVisible()^scene::EDS_BBOX)); - break; - case GUI_ID_DEBUG_NORMALS: // View -> Debug Information - menu->setItemChecked(menu->getSelectedItem(), !menu->isItemChecked(menu->getSelectedItem())); - if (Model) - Model->setDebugDataVisible((scene::E_DEBUG_SCENE_TYPE)(Model->isDebugDataVisible()^scene::EDS_NORMALS)); - break; - case GUI_ID_DEBUG_SKELETON: // View -> Debug Information - menu->setItemChecked(menu->getSelectedItem(), !menu->isItemChecked(menu->getSelectedItem())); - if (Model) - Model->setDebugDataVisible((scene::E_DEBUG_SCENE_TYPE)(Model->isDebugDataVisible()^scene::EDS_SKELETON)); - break; - case GUI_ID_DEBUG_WIRE_OVERLAY: // View -> Debug Information - menu->setItemChecked(menu->getSelectedItem(), !menu->isItemChecked(menu->getSelectedItem())); - if (Model) - Model->setDebugDataVisible((scene::E_DEBUG_SCENE_TYPE)(Model->isDebugDataVisible()^scene::EDS_MESH_WIRE_OVERLAY)); - break; - case GUI_ID_DEBUG_HALF_TRANSPARENT: // View -> Debug Information - menu->setItemChecked(menu->getSelectedItem(), !menu->isItemChecked(menu->getSelectedItem())); - if (Model) - Model->setDebugDataVisible((scene::E_DEBUG_SCENE_TYPE)(Model->isDebugDataVisible()^scene::EDS_HALF_TRANSPARENCY)); - break; - case GUI_ID_DEBUG_BUFFERS_BOUNDING_BOXES: // View -> Debug Information - menu->setItemChecked(menu->getSelectedItem(), !menu->isItemChecked(menu->getSelectedItem())); - if (Model) - Model->setDebugDataVisible((scene::E_DEBUG_SCENE_TYPE)(Model->isDebugDataVisible()^scene::EDS_BBOX_BUFFERS)); - break; - case GUI_ID_DEBUG_ALL: // View -> Debug Information - menu->setItemChecked(menu->getSelectedItem()-1, true); - menu->setItemChecked(menu->getSelectedItem()-2, true); - menu->setItemChecked(menu->getSelectedItem()-3, true); - menu->setItemChecked(menu->getSelectedItem()-4, true); - menu->setItemChecked(menu->getSelectedItem()-5, true); - menu->setItemChecked(menu->getSelectedItem()-6, true); - if (Model) - Model->setDebugDataVisible(scene::EDS_FULL); - break; - case GUI_ID_ABOUT: // Help->About - showAboutText(); - break; - case GUI_ID_MODEL_MATERIAL_SOLID: // View -> Material -> Solid - if (Model) - Model->setMaterialType(video::EMT_SOLID); - break; - case GUI_ID_MODEL_MATERIAL_TRANSPARENT: // View -> Material -> Transparent - if (Model) - Model->setMaterialType(video::EMT_TRANSPARENT_ADD_COLOR); - break; - case GUI_ID_MODEL_MATERIAL_REFLECTION: // View -> Material -> Reflection - if (Model) - Model->setMaterialType(video::EMT_SPHERE_MAP); - break; - - case GUI_ID_CAMERA_MAYA: - setActiveCamera(Camera[0]); - break; - case GUI_ID_CAMERA_FIRST_PERSON: - setActiveCamera(Camera[1]); - break; - - } + OnMenuItemSelected( (IGUIContextMenu*)event.GUIEvent.Caller ); break; - } case EGET_FILE_SELECTED: { @@ -441,17 +363,13 @@ public: case EGET_SCROLL_BAR_CHANGED: // control skin transparency - if (id == 104) + if (id == GUI_ID_SKIN_TRANSPARENCY) { const s32 pos = ((IGUIScrollBar*)event.GUIEvent.Caller)->getPos(); - for (s32 i=0; igetSkin()->getColor((EGUI_DEFAULT_COLOR)i); - col.setAlpha(pos); - env->getSkin()->setColor((EGUI_DEFAULT_COLOR)i, col); - } + SetSkinTransparency(pos, env->getSkin()); } - else if (id == 105) + // control animation speed + else if (id == GUI_ID_SKIN_ANIMATION_FPS) { const s32 pos = ((IGUIScrollBar*)event.GUIEvent.Caller)->getPos(); if (scene::ESNT_ANIMATED_MESH == Model->getType()) @@ -462,46 +380,9 @@ public: case EGET_COMBO_BOX_CHANGED: // control anti-aliasing/filtering - if (id == 108) + if (id == GUI_ID_TEXTUREFILTER) { - s32 pos = ((IGUIComboBox*)event.GUIEvent.Caller)->getSelected(); - switch (pos) - { - case 0: - if (Model) - { - Model->setMaterialFlag(video::EMF_BILINEAR_FILTER, false); - Model->setMaterialFlag(video::EMF_TRILINEAR_FILTER, false); - Model->setMaterialFlag(video::EMF_ANISOTROPIC_FILTER, false); - } - break; - case 1: - if (Model) - { - Model->setMaterialFlag(video::EMF_BILINEAR_FILTER, true); - Model->setMaterialFlag(video::EMF_TRILINEAR_FILTER, false); - } - break; - case 2: - if (Model) - { - Model->setMaterialFlag(video::EMF_BILINEAR_FILTER, false); - Model->setMaterialFlag(video::EMF_TRILINEAR_FILTER, true); - } - break; - case 3: - if (Model) - { - Model->setMaterialFlag(video::EMF_ANISOTROPIC_FILTER, true); - } - break; - case 4: - if (Model) - { - Model->setMaterialFlag(video::EMF_ANISOTROPIC_FILTER, false); - } - break; - } + OnTextureFilterSelected( (IGUIComboBox*)event.GUIEvent.Caller ); } break; @@ -509,7 +390,7 @@ public: switch(id) { - case 1101: + case GUI_ID_BUTTON_SET_SCALE: { // set scale gui::IGUIElement* root = env->getRootGUIElement(); @@ -525,18 +406,29 @@ public: if (Model) Model->setScale(scale); + UpdateScaleInfo(Model); } break; - case 1102: + case GUI_ID_BUTTON_SCALE_MUL10: + if (Model) + Model->setScale(Model->getScale()*10.f); + UpdateScaleInfo(Model); + break; + case GUI_ID_BUTTON_SCALE_DIV10: + if (Model) + Model->setScale(Model->getScale()*0.1f); + UpdateScaleInfo(Model); + break; + case GUI_ID_BUTTON_OPEN_MODEL: env->addFileOpenDialog(L"Please select a model file to open"); break; - case 1103: + case GUI_ID_BUTTON_SHOW_ABOUT: showAboutText(); break; - case 1104: + case GUI_ID_BUTTON_SHOW_TOOLBOX: createToolBox(); break; - case 1105: + case GUI_ID_BUTTON_SELECT_ARCHIVE: env->addFileOpenDialog(L"Please select your game archive/directory"); break; } @@ -549,6 +441,199 @@ public: return false; } + + + /* + Handle key-up events + */ + bool OnKeyUp(irr::EKEY_CODE keyCode) + { + if (keyCode == irr::KEY_ESCAPE) + { + if (Device) + { + scene::ICameraSceneNode * camera = + Device->getSceneManager()->getActiveCamera(); + if (camera) + { + camera->setInputReceiverEnabled( !camera->isInputReceiverEnabled() ); + } + return true; + } + } + else if (keyCode == irr::KEY_F1) + { + if (Device) + { + IGUIElement* elem = Device->getGUIEnvironment()->getRootGUIElement()->getElementFromId(GUI_ID_POSITION_TEXT); + if (elem) + elem->setVisible(!elem->isVisible()); + } + } + else if (keyCode == irr::KEY_KEY_M) + { + if (Device) + Device->minimizeWindow(); + } + else if (keyCode == irr::KEY_KEY_L) + { + UseLight=!UseLight; + if (Model) + { + Model->setMaterialFlag(video::EMF_LIGHTING, UseLight); + Model->setMaterialFlag(video::EMF_NORMALIZE_NORMALS, UseLight); + } + } + return false; + } + + + /* + Handle "menu item clicked" events. + */ + void OnMenuItemSelected( IGUIContextMenu* menu ) + { + s32 id = menu->getItemCommandId(menu->getSelectedItem()); + IGUIEnvironment* env = Device->getGUIEnvironment(); + + switch(id) + { + case GUI_ID_OPEN_MODEL: // FilOnButtonSetScalinge -> Open Model + env->addFileOpenDialog(L"Please select a model file to open"); + break; + case GUI_ID_SET_MODEL_ARCHIVE: // File -> Set Model Archive + env->addFileOpenDialog(L"Please select your game archive/directory"); + break; + case GUI_ID_LOAD_AS_OCTREE: // File -> LoadAsOctree + Octree = !Octree; + menu->setItemChecked(menu->getSelectedItem(), Octree); + break; + case GUI_ID_QUIT: // File -> Quit + Device->closeDevice(); + break; + case GUI_ID_SKY_BOX_VISIBLE: // View -> Skybox + menu->setItemChecked(menu->getSelectedItem(), !menu->isItemChecked(menu->getSelectedItem())); + SkyBox->setVisible(!SkyBox->isVisible()); + break; + case GUI_ID_DEBUG_OFF: // View -> Debug Information + menu->setItemChecked(menu->getSelectedItem()+1, false); + menu->setItemChecked(menu->getSelectedItem()+2, false); + menu->setItemChecked(menu->getSelectedItem()+3, false); + menu->setItemChecked(menu->getSelectedItem()+4, false); + menu->setItemChecked(menu->getSelectedItem()+5, false); + menu->setItemChecked(menu->getSelectedItem()+6, false); + if (Model) + Model->setDebugDataVisible(scene::EDS_OFF); + break; + case GUI_ID_DEBUG_BOUNDING_BOX: // View -> Debug Information + menu->setItemChecked(menu->getSelectedItem(), !menu->isItemChecked(menu->getSelectedItem())); + if (Model) + Model->setDebugDataVisible((scene::E_DEBUG_SCENE_TYPE)(Model->isDebugDataVisible()^scene::EDS_BBOX)); + break; + case GUI_ID_DEBUG_NORMALS: // View -> Debug Information + menu->setItemChecked(menu->getSelectedItem(), !menu->isItemChecked(menu->getSelectedItem())); + if (Model) + Model->setDebugDataVisible((scene::E_DEBUG_SCENE_TYPE)(Model->isDebugDataVisible()^scene::EDS_NORMALS)); + break; + case GUI_ID_DEBUG_SKELETON: // View -> Debug Information + menu->setItemChecked(menu->getSelectedItem(), !menu->isItemChecked(menu->getSelectedItem())); + if (Model) + Model->setDebugDataVisible((scene::E_DEBUG_SCENE_TYPE)(Model->isDebugDataVisible()^scene::EDS_SKELETON)); + break; + case GUI_ID_DEBUG_WIRE_OVERLAY: // View -> Debug Information + menu->setItemChecked(menu->getSelectedItem(), !menu->isItemChecked(menu->getSelectedItem())); + if (Model) + Model->setDebugDataVisible((scene::E_DEBUG_SCENE_TYPE)(Model->isDebugDataVisible()^scene::EDS_MESH_WIRE_OVERLAY)); + break; + case GUI_ID_DEBUG_HALF_TRANSPARENT: // View -> Debug Information + menu->setItemChecked(menu->getSelectedItem(), !menu->isItemChecked(menu->getSelectedItem())); + if (Model) + Model->setDebugDataVisible((scene::E_DEBUG_SCENE_TYPE)(Model->isDebugDataVisible()^scene::EDS_HALF_TRANSPARENCY)); + break; + case GUI_ID_DEBUG_BUFFERS_BOUNDING_BOXES: // View -> Debug Information + menu->setItemChecked(menu->getSelectedItem(), !menu->isItemChecked(menu->getSelectedItem())); + if (Model) + Model->setDebugDataVisible((scene::E_DEBUG_SCENE_TYPE)(Model->isDebugDataVisible()^scene::EDS_BBOX_BUFFERS)); + break; + case GUI_ID_DEBUG_ALL: // View -> Debug Information + menu->setItemChecked(menu->getSelectedItem()-1, true); + menu->setItemChecked(menu->getSelectedItem()-2, true); + menu->setItemChecked(menu->getSelectedItem()-3, true); + menu->setItemChecked(menu->getSelectedItem()-4, true); + menu->setItemChecked(menu->getSelectedItem()-5, true); + menu->setItemChecked(menu->getSelectedItem()-6, true); + if (Model) + Model->setDebugDataVisible(scene::EDS_FULL); + break; + case GUI_ID_ABOUT: // Help->About + showAboutText(); + break; + case GUI_ID_MODEL_MATERIAL_SOLID: // View -> Material -> Solid + if (Model) + Model->setMaterialType(video::EMT_SOLID); + break; + case GUI_ID_MODEL_MATERIAL_TRANSPARENT: // View -> Material -> Transparent + if (Model) + Model->setMaterialType(video::EMT_TRANSPARENT_ADD_COLOR); + break; + case GUI_ID_MODEL_MATERIAL_REFLECTION: // View -> Material -> Reflection + if (Model) + Model->setMaterialType(video::EMT_SPHERE_MAP); + break; + + case GUI_ID_CAMERA_MAYA: + setActiveCamera(Camera[0]); + break; + case GUI_ID_CAMERA_FIRST_PERSON: + setActiveCamera(Camera[1]); + break; + } + } + + /* + Handle the event that one of the texture-filters was selected in the corresponding combobox. + */ + void OnTextureFilterSelected( IGUIComboBox* combo ) + { + s32 pos = combo->getSelected(); + switch (pos) + { + case 0: + if (Model) + { + Model->setMaterialFlag(video::EMF_BILINEAR_FILTER, false); + Model->setMaterialFlag(video::EMF_TRILINEAR_FILTER, false); + Model->setMaterialFlag(video::EMF_ANISOTROPIC_FILTER, false); + } + break; + case 1: + if (Model) + { + Model->setMaterialFlag(video::EMF_BILINEAR_FILTER, true); + Model->setMaterialFlag(video::EMF_TRILINEAR_FILTER, false); + } + break; + case 2: + if (Model) + { + Model->setMaterialFlag(video::EMF_BILINEAR_FILTER, false); + Model->setMaterialFlag(video::EMF_TRILINEAR_FILTER, true); + } + break; + case 3: + if (Model) + { + Model->setMaterialFlag(video::EMF_ANISOTROPIC_FILTER, true); + } + break; + case 4: + if (Model) + { + Model->setMaterialFlag(video::EMF_ANISOTROPIC_FILTER, false); + } + break; + } + } }; @@ -586,7 +671,6 @@ int main(int argc, char* argv[]) } // create device and exit if creation failed - MyEventReceiver receiver; Device = createDevice(driverType, core::dimension2d(800, 600), 16, false, false, false, &receiver); @@ -605,9 +689,9 @@ int main(int argc, char* argv[]) driver->setTextureCreationFlag(video::ETCF_ALWAYS_32_BIT, true); - smgr->addLightSceneNode(); smgr->addLightSceneNode(0, core::vector3df(200,200,200), video::SColorf(1.0f,1.0f,1.0f),2000); + smgr->setAmbientLight(video::SColorf(0.3f,0.3f,0.3f)); // add our media directory as "search path" Device->getFileSystem()->addFolderFileArchive("../../media/"); @@ -733,20 +817,20 @@ int main(int argc, char* argv[]) gui::IGUIToolBar* bar = env->addToolBar(); video::ITexture* image = driver->getTexture("open.png"); - bar->addButton(1102, 0, L"Open a model",image, 0, false, true); + bar->addButton(GUI_ID_BUTTON_OPEN_MODEL, 0, L"Open a model",image, 0, false, true); image = driver->getTexture("tools.png"); - bar->addButton(1104, 0, L"Open Toolset",image, 0, false, true); + bar->addButton(GUI_ID_BUTTON_SHOW_TOOLBOX, 0, L"Open Toolset",image, 0, false, true); image = driver->getTexture("zip.png"); - bar->addButton(1105, 0, L"Set Model Archive",image, 0, false, true); + bar->addButton(GUI_ID_BUTTON_SELECT_ARCHIVE, 0, L"Set Model Archive",image, 0, false, true); image = driver->getTexture("help.png"); - bar->addButton(1103, 0, L"Open Help", image, 0, false, true); + bar->addButton(GUI_ID_BUTTON_SHOW_ABOUT, 0, L"Open Help", image, 0, false, true); // create a combobox with some senseless texts - gui::IGUIComboBox* box = env->addComboBox(core::rect(250,4,350,23), bar, 108); + gui::IGUIComboBox* box = env->addComboBox(core::rect(250,4,350,23), bar, GUI_ID_TEXTUREFILTER); box->addItem(L"No filtering"); box->addItem(L"Bilinear"); box->addItem(L"Trilinear"); diff --git a/examples/14.Win32Window/Win32Window_vc9.vcproj b/examples/14.Win32Window/Win32Window_vc9.vcproj index 40279f95..2902fba4 100644 --- a/examples/14.Win32Window/Win32Window_vc9.vcproj +++ b/examples/14.Win32Window/Win32Window_vc9.vcproj @@ -1,7 +1,7 @@ // this example only runs with windows +#include using namespace irr; @@ -50,9 +51,45 @@ static LRESULT CALLBACK CustomWndProc(HWND hWnd, UINT message, } +/* + Now ask for the driver and create the Windows specific window. +*/ int main() //int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hpre, LPSTR cmd, int cc) { + // ask user for driver + + video::E_DRIVER_TYPE driverType = video::EDT_DIRECT3D8; + + printf("Please select the driver you want for this example:\n"\ + " (a) Direct3D 9.0c\n (b) Direct3D 8.1\n (c) OpenGL 1.5\n"\ + " (d) Software Renderer\n (e) Burning's Software Renderer\n"\ + " (f) NullDevice\n (otherKey) exit\n\n"); + + char key; + std::cin >> key; + + switch(key) + { + case 'a': driverType = video::EDT_DIRECT3D9;break; + case 'b': driverType = video::EDT_DIRECT3D8;break; + case 'c': driverType = video::EDT_OPENGL; break; + case 'd': driverType = video::EDT_SOFTWARE; break; + case 'e': driverType = video::EDT_BURNINGSVIDEO;break; + case 'f': driverType = video::EDT_NULL; break; + default: return 1; + } + + printf("Select the render window (some dead window may exist too):\n"\ + " (a) Window with button (via CreationParam)\n"\ + " (b) Window with button (via beginScene)\n"\ + " (c) Own Irrlicht window (default behavior)\n"\ + " (otherKey) exit\n\n"); + + std::cin >> key; + if (key != 'a' && key != 'b' && key != 'c') + return 1; + HINSTANCE hInstance = 0; // create dialog @@ -105,6 +142,7 @@ int main() HWND hIrrlichtWindow = CreateWindow("BUTTON", "", WS_CHILD | WS_VISIBLE | BS_OWNERDRAW, 50, 80, 320, 220, hWnd, NULL, hInstance, NULL); + video::SExposedVideoData videodata((key=='b')?hIrrlichtWindow:0); /* So now that we have some window, we can create an Irrlicht device @@ -115,8 +153,9 @@ int main() // create irrlicht device in the button window irr::SIrrlichtCreationParameters param; - param.WindowId = reinterpret_cast(hIrrlichtWindow); // hColorButton - param.DriverType = video::EDT_OPENGL; + param.DriverType = driverType; + if (key=='a') + param.WindowId = reinterpret_cast(hIrrlichtWindow); irr::IrrlichtDevice* device = irr::createDeviceEx(param); @@ -125,6 +164,21 @@ int main() irr::scene::ISceneManager* smgr = device->getSceneManager(); video::IVideoDriver* driver = device->getVideoDriver(); + if (driverType==video::EDT_OPENGL) + { + HDC HDc=GetDC(hIrrlichtWindow); + PIXELFORMATDESCRIPTOR pfd={0}; + pfd.nSize=sizeof(PIXELFORMATDESCRIPTOR); + int pf = GetPixelFormat(HDc); + DescribePixelFormat(HDc, pf, sizeof(PIXELFORMATDESCRIPTOR), &pfd); + pfd.dwFlags |= PFD_DOUBLEBUFFER | PFD_SUPPORT_OPENGL | PFD_DRAW_TO_WINDOW; + pfd.cDepthBits=16; + pf = ChoosePixelFormat(HDc, &pfd); + SetPixelFormat(HDc, pf, &pfd); + videodata.OpenGLWin32.HDc = HDc; + videodata.OpenGLWin32.HRc=wglCreateContext(HDc); + wglShareLists((HGLRC)driver->getExposedVideoData().OpenGLWin32.HRc, (HGLRC)videodata.OpenGLWin32.HRc); + } scene::ICameraSceneNode* cam = smgr->addCameraSceneNode(); cam->setTarget(core::vector3df(0,0,0)); @@ -169,7 +223,7 @@ int main() while (device->run()) { - driver->beginScene(true, true, 0); + driver->beginScene(true, true, 0, videodata); smgr->drawAll(); driver->endScene(); } @@ -195,7 +249,7 @@ int main() device->getTimer()->tick(); // draw engine picture - driver->beginScene(true, true, 0); + driver->beginScene(true, true, 0, (key=='c')?hIrrlichtWindow:0); smgr->drawAll(); driver->endScene(); }*/ diff --git a/examples/15.LoadIrrFile/main.cpp b/examples/15.LoadIrrFile/main.cpp index 53cf702e..f2d52cdf 100644 --- a/examples/15.LoadIrrFile/main.cpp +++ b/examples/15.LoadIrrFile/main.cpp @@ -115,8 +115,8 @@ int main(int argc, char** argv) selector = smgr->createTerrainTriangleSelector((scene::ITerrainSceneNode*)node); break; - case scene::ESNT_OCT_TREE: - selector = smgr->createOctTreeTriangleSelector(((scene::IMeshSceneNode*)node)->getMesh(), node); + case scene::ESNT_OCTREE: + selector = smgr->createOctreeTriangleSelector(((scene::IMeshSceneNode*)node)->getMesh(), node); break; default: diff --git a/examples/16.Quake3MapShader/main.cpp b/examples/16.Quake3MapShader/main.cpp index eca1303d..3eef7b1f 100644 --- a/examples/16.Quake3MapShader/main.cpp +++ b/examples/16.Quake3MapShader/main.cpp @@ -97,7 +97,10 @@ public: else if (event.KeyInput.Key == KEY_F8) { - Node->setDebugDataVisible(scene::EDS_BBOX_ALL); + if (Node->isDebugDataVisible()) + Node->setDebugDataVisible(scene::EDS_OFF); + else + Node->setDebugDataVisible(scene::EDS_BBOX_ALL); } } return false; @@ -146,10 +149,10 @@ int IRRCALLCONV main(int argc, char* argv[]) case 'e': driverType = video::EDT_BURNINGSVIDEO;break; case 'f': driverType = video::EDT_NULL; break; default: return 1; - } + } // create device and exit if creation failed - const core::dimension2du videoDim ( 800,600 ); + const core::dimension2du videoDim(800,600); IrrlichtDevice *device = createDevice(driverType, videoDim, 32, false ); @@ -182,15 +185,13 @@ int IRRCALLCONV main(int argc, char* argv[]) directly be stored on disk. */ if (argc>2) - device->getFileSystem()->QUAKE3_STORAGE_FORMAT (argv[1]); + device->getFileSystem()->QUAKE3_STORAGE_FORMAT(argv[1]); else - device->getFileSystem()->QUAKE3_STORAGE_FORMAT ( QUAKE3_STORAGE_1 ); + device->getFileSystem()->QUAKE3_STORAGE_FORMAT(QUAKE3_STORAGE_1); #ifdef QUAKE3_STORAGE_2 - device->getFileSystem()->QUAKE3_STORAGE_FORMAT ( QUAKE3_STORAGE_2 ); + device->getFileSystem()->QUAKE3_STORAGE_FORMAT(QUAKE3_STORAGE_2); #endif - - // Quake3 Shader controls Z-Writing smgr->getParameters()->setAttribute(scene::ALLOW_ZWRITE_ON_TRANSPARENT, true); @@ -200,17 +201,17 @@ int IRRCALLCONV main(int argc, char* argv[]) they are only a huge chunk of static geometry with some materials attached. Hence the IAnimated mesh consists of only one frame, so we get the "first frame" of the "animation", which is our quake level - and create an OctTree scene node with it, using addOctTreeSceneNode(). - The OctTree optimizes the scene a little bit, trying to draw only geometry - which is currently visible. An alternative to the OctTree would be a + and create an Octree scene node with it, using addOctreeSceneNode(). + The Octree optimizes the scene a little bit, trying to draw only geometry + which is currently visible. An alternative to the Octree would be a AnimatedMeshSceneNode, which would draw always the complete geometry of the mesh, without optimization. Try it out: Write addAnimatedMeshSceneNode - instead of addOctTreeSceneNode and compare the primitives drawed by the + instead of addOctreeSceneNode and compare the primitives drawed by the video driver. (There is a getPrimitiveCountDrawed() method in the IVideoDriver class). Note that this optimization with the Octree is only useful when drawing huge meshes consisting of lots of geometry. */ - scene::IQ3LevelMesh* mesh = + scene::IQ3LevelMesh* const mesh = (scene::IQ3LevelMesh*) smgr->getMesh(mapname); /* @@ -218,16 +219,15 @@ int IRRCALLCONV main(int argc, char* argv[]) The Geometry mesh is optimised for faster drawing */ scene::ISceneNode* node = 0; - if ( mesh ) + if (mesh) { - scene::IMesh *geometry = mesh->getMesh(quake3::E_Q3_MESH_GEOMETRY); -// node = smgr->addMeshSceneNode ( geometry ); - node = smgr->addOctTreeSceneNode(geometry, 0, -1, 1024); + scene::IMesh * const geometry = mesh->getMesh(quake3::E_Q3_MESH_GEOMETRY); + node = smgr->addOctreeSceneNode(geometry, 0, -1, 1024); } // create an event receiver for making screenshots - CScreenShotFactory screenshotFactory ( device, mapname, node ); - device->setEventReceiver ( &screenshotFactory ); + CScreenShotFactory screenshotFactory(device, mapname, node); + device->setEventReceiver(&screenshotFactory); /* now construct SceneNodes for each Shader @@ -238,24 +238,24 @@ int IRRCALLCONV main(int argc, char* argv[]) if ( mesh ) { // the additional mesh can be quite huge and is unoptimized - scene::IMesh * additional_mesh = mesh->getMesh ( quake3::E_Q3_MESH_ITEMS ); + const scene::IMesh * const additional_mesh = mesh->getMesh(quake3::E_Q3_MESH_ITEMS); #ifdef SHOW_SHADER_NAME gui::IGUIFont *font = device->getGUIEnvironment()->getFont("../../media/fontlucida.png"); u32 count = 0; #endif - for ( u32 i = 0; i!= additional_mesh->getMeshBufferCount (); ++i ) + for ( u32 i = 0; i!= additional_mesh->getMeshBufferCount(); ++i ) { - IMeshBuffer *meshBuffer = additional_mesh->getMeshBuffer ( i ); - const video::SMaterial &material = meshBuffer->getMaterial(); + const IMeshBuffer* meshBuffer = additional_mesh->getMeshBuffer(i); + const video::SMaterial& material = meshBuffer->getMaterial(); - //! The ShaderIndex is stored in the material parameter - s32 shaderIndex = (s32) material.MaterialTypeParam2; + // The ShaderIndex is stored in the material parameter + const s32 shaderIndex = (s32) material.MaterialTypeParam2; // the meshbuffer can be rendered without additional support, or it has no shader - const quake3::IShader *shader = mesh->getShader ( shaderIndex ); - if ( 0 == shader ) + const quake3::IShader *shader = mesh->getShader(shaderIndex); + if (0 == shader) { continue; } @@ -266,25 +266,17 @@ int IRRCALLCONV main(int argc, char* argv[]) // would be full... // quake3::dumpShader ( Shader ); -#ifndef SHOW_SHADER_NAME - smgr->addQuake3SceneNode ( meshBuffer, shader ); -#else + node = smgr->addQuake3SceneNode(meshBuffer, shader); + +#ifdef SHOW_SHADER_NAME count += 1; - - node = smgr->addQuake3SceneNode ( meshBuffer, shader ); - core::stringw name( node->getName() ); node = smgr->addBillboardTextSceneNode( - font, - name.c_str(), - node, + font, name.c_str(), node, core::dimension2d(80.0f, 8.0f), - core::vector3df(0, 10, 0) - ); + core::vector3df(0, 10, 0)); #endif } - - } /* @@ -305,38 +297,36 @@ int IRRCALLCONV main(int argc, char* argv[]) we can ask the Quake3 Loader for all entities with class_name "info_player_deathmatch" we choose a random launch - */ if ( mesh ) { - quake3::tQ3EntityList &entityList = mesh->getEntityList (); + quake3::tQ3EntityList &entityList = mesh->getEntityList(); quake3::IEntity search; search.name = "info_player_deathmatch"; - s32 index = entityList.binary_search ( search ); - if ( index >= 0 ) + s32 index = entityList.binary_search(search); + if (index >= 0) { - const quake3::SVarGroup *group; s32 notEndList; do { - group = entityList[ index ].getGroup(1); + const quake3::SVarGroup *group = entityList[index].getGroup(1); u32 parsepos = 0; - core::vector3df pos = - quake3::getAsVector3df ( group->get ( "origin" ), parsepos ); + const core::vector3df pos = + quake3::getAsVector3df(group->get("origin"), parsepos); parsepos = 0; - f32 angle = quake3::getAsFloat ( group->get ( "angle"), parsepos ); + const f32 angle = quake3::getAsFloat(group->get("angle"), parsepos); - core::vector3df target ( 0.f, 0.f, 1.f ); - target.rotateXZBy ( angle, core::vector3df () ); + core::vector3df target(0.f, 0.f, 1.f); + target.rotateXZBy(angle); - camera->setPosition ( pos ); - camera->setTarget ( pos + target ); + camera->setPosition(pos); + camera->setTarget(pos + target); - index += 1; + ++index; /* notEndList = ( index < (s32) entityList.size () && entityList[index].name == search.name && @@ -346,7 +336,6 @@ int IRRCALLCONV main(int argc, char* argv[]) notEndList = index == 2; } while ( notEndList ); } - } /* @@ -360,19 +349,19 @@ int IRRCALLCONV main(int argc, char* argv[]) core::position2d(10, 10)); // show the driver logo - core::position2di pos ( videoDim.Width - 128, videoDim.Height - 64 ); + const core::position2di pos(videoDim.Width - 128, videoDim.Height - 64); switch ( driverType ) { case video::EDT_BURNINGSVIDEO: - gui->addImage(driver->getTexture("burninglogo.png"),pos); + gui->addImage(driver->getTexture("burninglogo.png"), pos); break; case video::EDT_OPENGL: - gui->addImage(driver->getTexture("opengllogo.png"),pos); + gui->addImage(driver->getTexture("opengllogo.png"), pos); break; case video::EDT_DIRECT3D8: case video::EDT_DIRECT3D9: - gui->addImage(driver->getTexture("directxlogo.png"),pos); + gui->addImage(driver->getTexture("directxlogo.png"), pos); break; } @@ -391,32 +380,26 @@ int IRRCALLCONV main(int argc, char* argv[]) driver->beginScene(true, true, video::SColor(255,20,20,40)); smgr->drawAll(); gui->drawAll(); - driver->endScene(); int fps = driver->getFPS(); - //if (lastFPS != fps) { - io::IAttributes * attr = smgr->getParameters(); - - s32 calls = attr->getAttributeAsInt ( "calls" ); - s32 culled = attr->getAttributeAsInt ( "culled" ); - + io::IAttributes * const attr = smgr->getParameters(); core::stringw str = L"Q3 ["; str += driver->getName(); str += "] FPS:"; str += fps; str += " Cull:"; - str += calls; + str += attr->getAttributeAsInt("calls"); str += "/"; - str += culled; + str += attr->getAttributeAsInt("culled"); str += " Draw: "; - str += attr->getAttributeAsInt ( "drawn_solid" ); + str += attr->getAttributeAsInt("drawn_solid"); str += "/"; - str += attr->getAttributeAsInt ( "drawn_transparent" ); + str += attr->getAttributeAsInt("drawn_transparent"); str += "/"; - str += attr->getAttributeAsInt ( "drawn_transparent_effect" ); + str += attr->getAttributeAsInt("drawn_transparent_effect"); device->setWindowCaption(str.c_str()); lastFPS = fps; @@ -427,7 +410,7 @@ int IRRCALLCONV main(int argc, char* argv[]) In the end, delete the Irrlicht device. */ device->drop(); - + return 0; } diff --git a/examples/17.HelloWorld_Mobile/17. HelloWorld for Windows Mobile on PC_v9.vcproj b/examples/17.HelloWorld_Mobile/17. HelloWorld for Windows Mobile on PC_v9.vcproj new file mode 100644 index 00000000..f73a5d49 --- /dev/null +++ b/examples/17.HelloWorld_Mobile/17. HelloWorld for Windows Mobile on PC_v9.vcproj @@ -0,0 +1,182 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/17.HelloWorld_Mobile/main.cpp b/examples/17.HelloWorld_Mobile/main.cpp index 8a4e7fd7..d1395865 100644 --- a/examples/17.HelloWorld_Mobile/main.cpp +++ b/examples/17.HelloWorld_Mobile/main.cpp @@ -134,9 +134,9 @@ IrrlichtDevice *startup() wchar_t buf[255]; GetModuleFileNameW ( 0, buf, 255 ); - string base = buf; + io::path base = buf; base = base.subString ( 0, base.findLast ( '\\' ) + 1 ); - device->getFileSystem()->registerFileArchive ( base ); + device->getFileSystem()->addFileArchive ( base ); } #endif diff --git a/examples/18.SplitScreen/SplitScreen_vc9.vcproj b/examples/18.SplitScreen/SplitScreen_vc9.vcproj index 24f8b1ae..86f6552b 100644 --- a/examples/18.SplitScreen/SplitScreen_vc9.vcproj +++ b/examples/18.SplitScreen/SplitScreen_vc9.vcproj @@ -128,7 +128,7 @@ UsePrecompiledHeader="0" WarningLevel="3" DebugInformationFormat="0" - CallingConvention="1" + CallingConvention="0" /> getMesh("20kdm2.bsp"); if (map) { - ISceneNode *map_node = smgr->addOctTreeSceneNode(map->getMesh(0)); + ISceneNode *map_node = smgr->addOctreeSceneNode(map->getMesh(0)); //Set position map_node->setPosition(vector3df(-850,-220,-850)); } diff --git a/examples/21.Quake3Explorer/Quake3Explorer.sln b/examples/21.Quake3Explorer/Quake3Explorer.sln index 5e99c055..0a110de2 100644 --- a/examples/21.Quake3Explorer/Quake3Explorer.sln +++ b/examples/21.Quake3Explorer/Quake3Explorer.sln @@ -1,5 +1,5 @@ Microsoft Visual Studio Solution File, Format Version 8.00 -Project("{830FD174-FABE-4667-B9FC-F7F8B8378EE7}") = "19.Quake3MapExplorer", "Quake3MapShader.vcproj", "{CDC4AAA9-72E1-4ffa-A04D-7EF59D8B97CD}" +Project("{830FD174-FABE-4667-B9FC-F7F8B8378EE7}") = "21.Quake3MapExplorer", "Quake3MapShader.vcproj", "{CDC4AAA9-72E1-4ffa-A04D-7EF59D8B97CD}" ProjectSection(ProjectDependencies) = postProject EndProjectSection EndProject diff --git a/examples/21.Quake3Explorer/Quake3Explorer.vcproj b/examples/21.Quake3Explorer/Quake3Explorer.vcproj index 282497f8..b869cc4c 100644 --- a/examples/21.Quake3Explorer/Quake3Explorer.vcproj +++ b/examples/21.Quake3Explorer/Quake3Explorer.vcproj @@ -32,7 +32,7 @@ Name="VCCustomBuildTool"/> diff --git a/examples/21.Quake3Explorer/main.cpp b/examples/21.Quake3Explorer/main.cpp index 7a1f9967..8d26c734 100644 --- a/examples/21.Quake3Explorer/main.cpp +++ b/examples/21.Quake3Explorer/main.cpp @@ -85,7 +85,7 @@ void GameData::setDefault () deviceParam.WindowSize.Width = 800; deviceParam.WindowSize.Height = 600; deviceParam.Fullscreen = false; - deviceParam.Bits = 32; + deviceParam.Bits = 24; deviceParam.ZBufferBits = 16; deviceParam.Vsync = false; deviceParam.AntiAlias = false; @@ -1040,12 +1040,14 @@ void CQuake3EventHandler::LoadMap ( const stringw &mapName, s32 collision ) IFileSystem *fs = Game->Device->getFileSystem(); ISceneManager *smgr = Game->Device->getSceneManager (); - IReadFile* file = fs->createMemoryReadFile ( &Game->loadParam, sizeof ( Game->loadParam ), - L"levelparameter.cfg", false); + IReadFile* file = fs->createMemoryReadFile(&Game->loadParam, + sizeof(Game->loadParam), L"levelparameter.cfg", false); + // load cfg file smgr->getMesh( file ); file->drop (); + // load the actual map Mesh = (IQ3LevelMesh*) smgr->getMesh(mapName); if ( 0 == Mesh ) return; @@ -1072,12 +1074,11 @@ void CQuake3EventHandler::LoadMap ( const stringw &mapName, s32 collision ) //s32 minimalNodes = b0 ? core::s32_max ( 2048, b0->getVertexCount() / 32 ) : 2048; s32 minimalNodes = 2048; - MapParent = smgr->addMeshSceneNode( geometry ); - //MapParent = smgr->addOctTreeSceneNode(geometry, 0, -1, minimalNodes); + MapParent = smgr->addOctreeSceneNode(geometry, 0, -1, minimalNodes); MapParent->setName ( mapName ); if ( Meta ) { - selector = smgr->createOctTreeTriangleSelector( geometry,MapParent, minimalNodes); + selector = smgr->createOctreeTriangleSelector( geometry,MapParent, minimalNodes); //selector = smgr->createTriangleSelector ( geometry, MapParent ); Meta->addTriangleSelector( selector); selector->drop (); @@ -1105,7 +1106,6 @@ void CQuake3EventHandler::LoadMap ( const stringw &mapName, s32 collision ) if ( BulletParent ) BulletParent->setName ( "Bullet Container" ); - /* now construct SceneNodes for each Shader The Objects are stored in the quake mesh E_Q3_MESH_ITEMS @@ -1116,12 +1116,10 @@ void CQuake3EventHandler::LoadMap ( const stringw &mapName, s32 collision ) Q3ShaderFactory ( Game->loadParam, Game->Device, Mesh, E_Q3_MESH_FOG,FogParent, 0, false ); Q3ShaderFactory ( Game->loadParam, Game->Device, Mesh, E_Q3_MESH_UNRESOLVED,UnresolvedParent, Meta, true ); - /* Now construct Models from Entity List */ Q3ModelFactory ( Game->loadParam, Game->Device, Mesh, ItemParent, false ); - } /* @@ -1142,7 +1140,7 @@ void CQuake3EventHandler::addSceneTreeItem( ISceneNode * parent, IGUITreeViewNod case ESNT_CAMERA: imageIndex = 1; break; case ESNT_EMPTY: imageIndex = 2; break; case ESNT_MESH: imageIndex = 3; break; - case ESNT_OCT_TREE: imageIndex = 3; break; + case ESNT_OCTREE: imageIndex = 3; break; case ESNT_ANIMATED_MESH: imageIndex = 4; break; case ESNT_SKY_BOX: imageIndex = 5; break; case ESNT_BILLBOARD: imageIndex = 6; break; @@ -1193,7 +1191,6 @@ void CQuake3EventHandler::addSceneTreeItem( ISceneNode * parent, IGUITreeViewNod addSceneTreeItem ( *it, node ); } - } @@ -1203,6 +1200,7 @@ void CQuake3EventHandler::CreatePlayers() Player[0].create ( Game->Device, Mesh, MapParent, Meta ); } + // Adds a skydome to the scene void CQuake3EventHandler::AddSky( u32 dome, const c8 *texture) { @@ -1237,28 +1235,16 @@ void CQuake3EventHandler::AddSky( u32 dome, const c8 *texture) { snprintf ( buf, 64, "%s.jpg", texture ); SkyNode = smgr->addSkyDomeSceneNode( - driver->getTexture( buf ), - 32,32, - 1.f, - 1.f, - 1000.f, - 0, - 11 - ); + driver->getTexture( buf ), 32,32, + 1.f, 1.f, 1000.f, 0, 11); } else if ( 2 == dome ) { snprintf ( buf, 64, "%s.jpg", texture ); SkyNode = smgr->addSkyDomeSceneNode( - driver->getTexture( buf ), - 16,8, - 0.95f, - 2.f, - 1000.f, - 0, - 11 - ); + driver->getTexture( buf ), 16,8, + 0.95f, 2.f, 1000.f, 0, 11); } if (SkyNode) @@ -1266,7 +1252,6 @@ void CQuake3EventHandler::AddSky( u32 dome, const c8 *texture) //SkyNode->getMaterial(0).ZBuffer = video::EMDF_DEPTH_LESS_EQUAL; driver->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, oldMipMapState); - } @@ -1311,7 +1296,6 @@ void CQuake3EventHandler::SetGUIActive( s32 command) } - /* Handle game input */ diff --git a/examples/21.Quake3Explorer/q3factory.cpp b/examples/21.Quake3Explorer/q3factory.cpp index b929268e..a4d51b90 100644 --- a/examples/21.Quake3Explorer/q3factory.cpp +++ b/examples/21.Quake3Explorer/q3factory.cpp @@ -1,6 +1,6 @@ /*! Model Factory. - create the additional scenenodes for ( bullets, health... ) + create the additional scenenodes for ( bullets, health... ) Defines the Entities for Quake3 */ @@ -122,7 +122,7 @@ static const SItemElement Quake3ItemElement [] = { SPECIAL_SFX_ROTATE }, { - "item_armor_body", + "item_armor_body", {"models/powerups/armor/armor_red.md3", ""}, "sound/misc/ar2_pkup.wav", @@ -134,7 +134,7 @@ static const SItemElement Quake3ItemElement [] = { SPECIAL_SFX_ROTATE }, { - "item_armor_combat", + "item_armor_combat", {"models/powerups/armor/armor_yel.md3", ""}, "sound/misc/ar2_pkup.wav", @@ -146,7 +146,7 @@ static const SItemElement Quake3ItemElement [] = { SPECIAL_SFX_ROTATE }, { - "item_armor_shard", + "item_armor_shard", {"models/powerups/armor/shard.md3", ""}, "sound/misc/ar1_pkup.wav", @@ -158,7 +158,7 @@ static const SItemElement Quake3ItemElement [] = { SPECIAL_SFX_ROTATE }, { - "weapon_gauntlet", + "weapon_gauntlet", {"models/weapons2/gauntlet/gauntlet.md3", ""}, "sound/misc/w_pkup.wav", @@ -170,7 +170,7 @@ static const SItemElement Quake3ItemElement [] = { SPECIAL_SFX_ROTATE }, { - "weapon_shotgun", + "weapon_shotgun", {"models/weapons2/shotgun/shotgun.md3", ""}, "sound/misc/w_pkup.wav", @@ -290,7 +290,7 @@ const SItemElement * getItemElement ( const stringc& key ) { const SItemElement *item = Quake3ItemElement; - while ( item->key[0] ) + while ( item->key ) { if ( 0 == strcmp ( key.c_str(), item->key ) ) return item; @@ -304,8 +304,8 @@ const SItemElement * getItemElement ( const stringc& key ) Takes the mesh buffers and creates scenenodes for their associated shaders */ void Q3ShaderFactory ( Q3LevelLoadParameter &loadParam, - IrrlichtDevice *device, - IQ3LevelMesh* mesh, + IrrlichtDevice *device, + IQ3LevelMesh* mesh, eQ3MeshIndex meshIndex, ISceneNode *parent, IMetaTriangleSelector *meta, @@ -463,7 +463,7 @@ void Q3ShaderFactory ( Q3LevelLoadParameter &loadParam, m = node->getMesh(); } - //selector = smgr->createOctTreeTriangleSelector ( m, 0, 128 ); + //selector = smgr->createOctreeTriangleSelector ( m, 0, 128 ); selector = smgr->createTriangleSelector ( m, 0 ); meta->addTriangleSelector ( selector ); selector->drop (); @@ -479,7 +479,7 @@ void Q3ShaderFactory ( Q3LevelLoadParameter &loadParam, #if 0 if ( meta ) { - selector = smgr->createOctTreeTriangleSelector ( additional_mesh, 0 ); + selector = smgr->createOctreeTriangleSelector ( additional_mesh, 0 ); meta->addTriangleSelector ( selector ); selector->drop (); } @@ -488,8 +488,8 @@ void Q3ShaderFactory ( Q3LevelLoadParameter &loadParam, if ( loadParam.verbose > 0 ) { loadParam.endTime = device->getTimer()->getRealTime (); - snprintf(buf, 128, "q3shaderfactory needed %04d ms to create %d shader nodes", - loadParam.endTime - loadParam.startTime, + snprintf(buf, 128, "q3shaderfactory needed %04d ms to create %d shader nodes", + loadParam.endTime - loadParam.startTime, sceneNodeID ); device->getLogger()->log(buf, ELL_INFORMATION); @@ -502,8 +502,8 @@ void Q3ShaderFactory ( Q3LevelLoadParameter &loadParam, create Items from Entity */ void Q3ModelFactory ( Q3LevelLoadParameter &loadParam, - IrrlichtDevice *device, - IQ3LevelMesh* masterMesh, + IrrlichtDevice *device, + IQ3LevelMesh* masterMesh, ISceneNode *parent, bool showShaderName ) @@ -620,7 +620,7 @@ void Q3ModelFactory ( Q3LevelLoadParameter &loadParam, if ( itemElement->special & SPECIAL_SFX_BOUNCE ) { - //anim = smgr->createFlyStraightAnimator ( + //anim = smgr->createFlyStraightAnimator ( // p, p + vector3df ( 0.f, 60.f, 0.f ), 1000, true, true ); anim = smgr->createFlyCircleAnimator ( p + vector3df( 0.f, 20.f, 0.f ), @@ -745,7 +745,7 @@ vector3df getGravity ( const c8 * surface ) if ( 0 == strcmp ( surface, "moon" ) ) return vector3df ( 0.f, -6.f / 100.f, 0.f ); if ( 0 == strcmp ( surface, "water" ) ) return vector3df ( 0.1f / 100.f, -2.f / 100.f, 0.f ); if ( 0 == strcmp ( surface, "ice" ) ) return vector3df ( 0.2f / 100.f, -9.f / 100.f, 0.3f / 100.f ); - + return vector3df ( 0.f, 0.f, 0.f ); } diff --git a/examples/22.MaterialViewer/Makefile b/examples/22.MaterialViewer/Makefile new file mode 100644 index 00000000..c12e6608 --- /dev/null +++ b/examples/22.MaterialViewer/Makefile @@ -0,0 +1,38 @@ +# Makefile for Irrlicht Examples +# It's usually sufficient to change just the target name and source file list +# and be sure that CXX is set to a valid compiler +Target = 22.MaterialViewer +Sources = main.cpp + +# general compiler settings +CPPFLAGS = -I../../include -I/usr/X11R6/include +#CXXFLAGS = -O3 -ffast-math +CXXFLAGS = -g -Wall + +#default target is Linux +all: all_linux + +ifeq ($(HOSTTYPE), x86_64) +LIBSELECT=64 +endif + +# target specific settings +all_linux: LDFLAGS = -L/usr/X11R6/lib$(LIBSELECT) -L../../lib/Linux -lIrrlicht -lGL -lXxf86vm -lXext -lX11 +all_linux clean_linux: SYSTEM=Linux +all_win32: LDFLAGS = -L../../lib/Win32-gcc -lIrrlicht -lopengl32 -lm +all_win32 clean_win32: SYSTEM=Win32-gcc +all_win32 clean_win32: SUF=.exe +# name of the binary - only valid for targets which set SYSTEM +DESTPATH = ../../bin/$(SYSTEM)/$(Target)$(SUF) + +all_linux all_win32: + $(warning Building...) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) $(Sources) -o $(DESTPATH) $(LDFLAGS) + +clean: clean_linux clean_win32 + $(warning Cleaning...) + +clean_linux clean_win32: + @$(RM) $(DESTPATH) + +.PHONY: all all_win32 clean clean_linux clean_win32 diff --git a/examples/22.MaterialViewer/MaterialViewer.cbp b/examples/22.MaterialViewer/MaterialViewer.cbp new file mode 100644 index 00000000..84e85473 --- /dev/null +++ b/examples/22.MaterialViewer/MaterialViewer.cbp @@ -0,0 +1,57 @@ + + + + + + diff --git a/examples/22.MaterialViewer/MaterialViewer.dev b/examples/22.MaterialViewer/MaterialViewer.dev new file mode 100644 index 00000000..dfd9d4db --- /dev/null +++ b/examples/22.MaterialViewer/MaterialViewer.dev @@ -0,0 +1,59 @@ +[Project] +FileName=example.dev +Name=Irrlicht Example 22 Material Viewer +UnitCount=1 +Type=1 +Ver=1 +ObjFiles= +Includes=..\..\include +Libs= +PrivateResource= +ResourceIncludes= +MakeIncludes= +Compiler= +CppCompiler= +Linker=../../lib/Win32-gcc/libIrrlicht.a_@@_ +IsCpp=1 +Icon= +ExeOutput=../../bin/Win32-gcc +ObjectOutput=obj +OverrideOutput=1 +OverrideOutputName=22.MaterialViewer.exe +HostApplication= +Folders= +CommandLine= +IncludeVersionInfo=0 +SupportXPThemes=0 +CompilerSet=0 +CompilerSettings=0000000000000000000000 +UseCustomMakefile=0 +CustomMakefile= + +[Unit1] +FileName=main.cpp +CompileCpp=1 +Folder=Projekt1 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[VersionInfo] +Major=0 +Minor=1 +Release=1 +Build=1 +LanguageID=1033 +CharsetID=1252 +CompanyName= +FileVersion= +FileDescription=Irrlicht Engine example compiled using DevCpp and gcc +InternalName= +LegalCopyright= +LegalTrademarks= +OriginalFilename= +ProductName= +ProductVersion= +AutoIncBuildNr=0 + diff --git a/examples/22.MaterialViewer/MaterialViewer.sln b/examples/22.MaterialViewer/MaterialViewer.sln new file mode 100644 index 00000000..f8c0b6bf --- /dev/null +++ b/examples/22.MaterialViewer/MaterialViewer.sln @@ -0,0 +1,21 @@ +Microsoft Visual Studio Solution File, Format Version 8.00 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "MaterialViewer", "MaterialViewer.vcproj", "{C4F5BB37-D873-4DE2-B7D0-A60A936798E1}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Global + GlobalSection(SolutionConfiguration) = preSolution + Debug = Debug + Release = Release + EndGlobalSection + GlobalSection(ProjectConfiguration) = postSolution + {C4F5BB37-D873-4DE2-B7D0-A60A936798E1}.Debug.ActiveCfg = Debug|Win32 + {C4F5BB37-D873-4DE2-B7D0-A60A936798E1}.Debug.Build.0 = Debug|Win32 + {C4F5BB37-D873-4DE2-B7D0-A60A936798E1}.Release.ActiveCfg = Release|Win32 + {C4F5BB37-D873-4DE2-B7D0-A60A936798E1}.Release.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + EndGlobalSection + GlobalSection(ExtensibilityAddIns) = postSolution + EndGlobalSection +EndGlobal diff --git a/examples/22.MaterialViewer/MaterialViewer.vcproj b/examples/22.MaterialViewer/MaterialViewer.vcproj new file mode 100644 index 00000000..4e3cfbea --- /dev/null +++ b/examples/22.MaterialViewer/MaterialViewer.vcproj @@ -0,0 +1,163 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/22.MaterialViewer/MaterialViewer_vc8.vcproj b/examples/22.MaterialViewer/MaterialViewer_vc8.vcproj new file mode 100644 index 00000000..d3e9a129 --- /dev/null +++ b/examples/22.MaterialViewer/MaterialViewer_vc8.vcproj @@ -0,0 +1,231 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/22.MaterialViewer/MaterialViewer_vc9.vcproj b/examples/22.MaterialViewer/MaterialViewer_vc9.vcproj new file mode 100644 index 00000000..0e06903e --- /dev/null +++ b/examples/22.MaterialViewer/MaterialViewer_vc9.vcproj @@ -0,0 +1,230 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/22.MaterialViewer/main.cpp b/examples/22.MaterialViewer/main.cpp new file mode 100755 index 00000000..d2351456 --- /dev/null +++ b/examples/22.MaterialViewer/main.cpp @@ -0,0 +1,1074 @@ +/** Example 022 Material Viewer + +This example can be used to play around with material settings and watch the results. +Only the default non-shader materials are used in here. + +You have two nodes to make it easier to see which difference your settings will make. +Additionally you have one lightscenenode and you can set the global ambient values. + +*/ + +#include +#include + +using namespace irr; + +#ifdef _MSC_VER +#pragma comment(lib, "Irrlicht.lib") +#endif + +/* + Variables within the empty namespace are globals which are restricted to this file. +*/ +namespace +{ + const wchar_t* const DriverTypeNames[] = + { + L"NULL", + L"SOFTWARE", + L"BURNINGSVIDEO", + L"DIRECT3D8", + L"DIRECT3D9", + L"OPENGL", + 0, + }; + + // For the gui id's + enum EGUI_IDS + { + GUI_ID_OPEN_TEXTURE = 1, + GUI_ID_QUIT, + GUI_ID_MAX + }; + + // Name used in texture selection to clear the textures on the node + const core::stringw CLEAR_TEXTURE = L"CLEAR texture"; + + // some useful color constants + const video::SColor SCOL_BLACK = video::SColor(255, 0, 0, 0); + const video::SColor SCOL_BLUE = video::SColor(255, 0, 0, 255); + const video::SColor SCOL_CYAN = video::SColor(255, 0, 255, 255); + const video::SColor SCOL_GRAY = video::SColor(255, 128,128, 128); + const video::SColor SCOL_GREEN = video::SColor(255, 0, 255, 0); + const video::SColor SCOL_MAGENTA = video::SColor(255, 255, 0, 255); + const video::SColor SCOL_RED = video::SColor(255, 255, 0, 0); + const video::SColor SCOL_YELLOW = video::SColor(255, 255, 255, 0); + const video::SColor SCOL_WHITE = video::SColor(255, 255, 255, 255); +}; // namespace + +/* + Returns a new unique number on each call. +*/ +s32 makeUniqueId() +{ + static int unique = GUI_ID_MAX; + ++unique; + return unique; +} + +/* + Find out which vertex-type is needed for the given material type. +*/ +video::E_VERTEX_TYPE getVertexTypeForMaterialType(video::E_MATERIAL_TYPE materialType) +{ + using namespace video; + + switch ( materialType ) + { + case EMT_SOLID: + return EVT_STANDARD; + + case EMT_SOLID_2_LAYER: + return EVT_STANDARD; + + case EMT_LIGHTMAP: + case EMT_LIGHTMAP_ADD: + case EMT_LIGHTMAP_M2: + case EMT_LIGHTMAP_M4: + case EMT_LIGHTMAP_LIGHTING: + case EMT_LIGHTMAP_LIGHTING_M2: + case EMT_LIGHTMAP_LIGHTING_M4: + return EVT_2TCOORDS; + + case EMT_DETAIL_MAP: + return EVT_2TCOORDS; + + case EMT_SPHERE_MAP: + return EVT_STANDARD; + + case EMT_REFLECTION_2_LAYER: + return EVT_2TCOORDS; + + case EMT_TRANSPARENT_ADD_COLOR: + return EVT_STANDARD; + + case EMT_TRANSPARENT_ALPHA_CHANNEL: + return EVT_STANDARD; + + case EMT_TRANSPARENT_ALPHA_CHANNEL_REF: + return EVT_STANDARD; + + case EMT_TRANSPARENT_VERTEX_ALPHA: + return EVT_STANDARD; + + case EMT_TRANSPARENT_REFLECTION_2_LAYER: + return EVT_2TCOORDS; + + case EMT_NORMAL_MAP_SOLID: + case EMT_NORMAL_MAP_TRANSPARENT_ADD_COLOR: + case EMT_NORMAL_MAP_TRANSPARENT_VERTEX_ALPHA: + case EMT_PARALLAX_MAP_SOLID: + case EMT_PARALLAX_MAP_TRANSPARENT_ADD_COLOR: + case EMT_PARALLAX_MAP_TRANSPARENT_VERTEX_ALPHA: + return EVT_TANGENTS; + + case EMT_ONETEXTURE_BLEND: + return EVT_STANDARD; + + case EMT_FORCE_32BIT: + return EVT_STANDARD; + } + return EVT_STANDARD; +} + +/* + Custom GUI-control to edit colorvalues. +*/ +class CColorControl : public gui::IGUIElement +{ +public: + // Constructor + CColorControl(gui::IGUIEnvironment* guiEnv, const core::position2d & pos, const wchar_t *text, IGUIElement* parent, s32 id=-1 ) + : gui::IGUIElement(gui::EGUIET_ELEMENT, guiEnv, parent,id, core::rect< s32 >(pos, pos+core::dimension2d(80, 75))) + , DirtyFlag(true) + , ColorStatic(0) + , EditAlpha(0) + , EditRed(0) + , EditGreen(0) + , EditBlue(0) + { + using namespace gui; + ButtonSetId = makeUniqueId(); + + const core::rect< s32 > rectControls(0,0,AbsoluteRect.getWidth(),AbsoluteRect.getHeight() ); + IGUIStaticText * groupElement = guiEnv->addStaticText (L"", rectControls, true, false, this, -1, false); + groupElement->setNotClipped(true); + + guiEnv->addStaticText (text, core::rect(0,0,80,15), false, false, groupElement, -1, false); + + EditAlpha = addEditForNumbers(guiEnv, core::position2d(0,15), L"a", -1, groupElement ); + EditRed = addEditForNumbers(guiEnv, core::position2d(0,30), L"r", -1, groupElement ); + EditGreen = addEditForNumbers(guiEnv, core::position2d(0,45), L"g", -1, groupElement ); + EditBlue = addEditForNumbers(guiEnv, core::position2d(0,60), L"b", -1, groupElement ); + + ColorStatic = guiEnv->addStaticText (L"", core::rect(60,15,80,75), true, false, groupElement, -1, true); + + guiEnv->addButton (core::rect(60,35,80,50), groupElement, ButtonSetId, L"set"); + SetEditsFromColor(Color); + } + + // event receiver + virtual bool OnEvent(const SEvent &event) + { + if ( event.EventType != EET_GUI_EVENT ) + return false; + + if ( event.GUIEvent.Caller->getID() == ButtonSetId && event.GUIEvent.EventType == gui::EGET_BUTTON_CLICKED ) + { + Color = GetColorFromEdits(); + SetEditsFromColor(Color); + } + + return false; + } + + // set the color values + void setColor(const video::SColor& col) + { + DirtyFlag = true; + Color = col; + SetEditsFromColor(Color); + } + + // get the color values + const video::SColor& getColor() const + { + return Color; + } + + // To reset the dirty flag + void resetDirty() + { + DirtyFlag = false; + } + + // when the color was changed the dirty flag is set + bool isDirty() const + { + return DirtyFlag; + }; + +protected: + + // Add a staticbox for a description + an editbox so users can enter numbers + gui::IGUIEditBox* addEditForNumbers(gui::IGUIEnvironment* guiEnv, const core::position2d & pos, const wchar_t *text, s32 id, gui::IGUIElement * parent) + { + using namespace gui; + + core::rect< s32 > rect(pos, pos+core::dimension2d(10, 15)); + guiEnv->addStaticText (text, rect, false, false, parent, -1, false); + rect += core::position2d( 20, 0 ); + rect.LowerRightCorner.X += 20; + gui::IGUIEditBox* edit = guiEnv->addEditBox(L"0", rect, true, parent, id); + return edit; + } + + // Get the color value from the editfields + video::SColor GetColorFromEdits() + { + video::SColor col; + + u32 alpha=col.getAlpha(); + if ( EditAlpha ) + { + alpha = (u32)core::strtol10( core::stringc( EditAlpha->getText() ).c_str(), 0); + if ( alpha > 255 ) + alpha = 255; + } + col.setAlpha(alpha); + + u32 red=col.getRed(); + if ( EditRed ) + { + red = (u32)core::strtol10( core::stringc( EditRed->getText() ).c_str(), 0); + if ( red > 255 ) + red = 255; + } + col.setRed(red); + + u32 green=col.getGreen(); + if ( EditGreen ) + { + green = (u32)core::strtol10( core::stringc( EditGreen->getText() ).c_str(), 0); + if ( green > 255 ) + green = 255; + } + col.setGreen(green); + + u32 blue=col.getBlue(); + if ( EditBlue ) + { + blue = (u32)core::strtol10( core::stringc( EditBlue->getText() ).c_str(), 0); + if ( blue > 255 ) + blue = 255; + } + col.setBlue(blue); + + return col; + } + + // Fill the editfields with the value for the given color + void SetEditsFromColor(video::SColor col) + { + DirtyFlag = true; + if ( EditAlpha ) + EditAlpha->setText( core::stringw(col.getAlpha()).c_str() ); + if ( EditRed ) + EditRed->setText( core::stringw(col.getRed()).c_str() ); + if ( EditGreen ) + EditGreen->setText( core::stringw(col.getGreen()).c_str() ); + if ( EditBlue ) + EditBlue->setText( core::stringw(col.getBlue()).c_str() ); + if ( ColorStatic ) + ColorStatic->setBackgroundColor(col); + } + +private: + + bool DirtyFlag; + video::SColor Color; + s32 ButtonSetId; + gui::IGUIStaticText * ColorStatic; + gui::IGUIEditBox * EditAlpha; + gui::IGUIEditBox * EditRed; + gui::IGUIEditBox * EditGreen; + gui::IGUIEditBox * EditBlue; +}; + +/* + Custom GUI-control for to edit all colors typically used in materials and lights +*/ +class CAllColorsControl : public gui::IGUIElement +{ +public: + // Constructor + CAllColorsControl(gui::IGUIEnvironment* guiEnv, const core::position2d & pos, const wchar_t * description, bool hasEmissive, IGUIElement* parent, s32 id=-1) + : gui::IGUIElement(gui::EGUIET_ELEMENT, guiEnv, parent,id, core::rect(pos,pos+core::dimension2d(60,250))) + , ControlAmbientColor(0), ControlDiffuseColor(0), ControlSpecularColor(0), ControlEmissiveColor(0) + { + core::rect rect(0, 0, 60, 15); + guiEnv->addStaticText (description, rect, false, false, this, -1, false); + createColorControls(guiEnv, core::position2d(0, 15), hasEmissive); + } + + // Destructor + virtual ~CAllColorsControl() + { + ControlAmbientColor->drop(); + ControlDiffuseColor->drop(); + ControlEmissiveColor->drop(); + ControlSpecularColor->drop(); + } + + // Set the color values to those within the material + void setColorsToMaterialColors(const video::SMaterial & material) + { + ControlAmbientColor->setColor(material.AmbientColor); + ControlDiffuseColor->setColor(material.DiffuseColor); + ControlEmissiveColor->setColor(material.EmissiveColor); + ControlSpecularColor->setColor(material.SpecularColor); + } + + // Update all changed colors in the material + void updateMaterialColors(video::SMaterial & material) + { + if ( ControlAmbientColor->isDirty() ) + material.AmbientColor = ControlAmbientColor->getColor(); + if ( ControlDiffuseColor->isDirty() ) + material.DiffuseColor = ControlDiffuseColor->getColor(); + if ( ControlEmissiveColor->isDirty() ) + material.EmissiveColor = ControlEmissiveColor->getColor(); + if ( ControlSpecularColor->isDirty() ) + material.SpecularColor = ControlSpecularColor->getColor(); + } + + // Set the color values to those from the light data + void setColorsToLightDataColors(const video::SLight & lightData) + { + ControlAmbientColor->setColor(lightData.AmbientColor.toSColor()); + ControlAmbientColor->setColor(lightData.DiffuseColor.toSColor()); + ControlAmbientColor->setColor(lightData.SpecularColor.toSColor()); + } + + // Update all changed colors in the light data + void updateMaterialColors(video::SLight & lightData) + { + if ( ControlAmbientColor->isDirty() ) + lightData.AmbientColor = video::SColorf( ControlAmbientColor->getColor() ); + if ( ControlDiffuseColor->isDirty() ) + lightData.DiffuseColor = video::SColorf( ControlDiffuseColor->getColor() ); + if ( ControlSpecularColor->isDirty() ) + lightData.SpecularColor = video::SColorf(ControlSpecularColor->getColor() ); + } + + // To reset the dirty flags + void resetDirty() + { + ControlAmbientColor->resetDirty(); + ControlDiffuseColor->resetDirty(); + ControlSpecularColor->resetDirty(); + ControlEmissiveColor->resetDirty(); + } + +protected: + void createColorControls(gui::IGUIEnvironment* guiEnv, const core::position2d & pos, bool hasEmissive) + { + ControlAmbientColor = new CColorControl( guiEnv, pos, L"ambient", this); + ControlDiffuseColor = new CColorControl( guiEnv, pos + core::position2d(0, 75), L"diffuse", this ); + ControlSpecularColor = new CColorControl( guiEnv, pos + core::position2d(0, 150), L"specular", this ); + if ( hasEmissive ) + { + ControlEmissiveColor = new CColorControl( guiEnv, pos + core::position2d(0, 225), L"emissive", this ); + } + } + +private: + CColorControl* ControlAmbientColor; + CColorControl* ControlDiffuseColor; + CColorControl* ControlSpecularColor; + CColorControl* ControlEmissiveColor; +}; + +/* + GUI-Control to offer a selection of available textures. +*/ +class CTextureControl : public gui::IGUIElement +{ +public: + CTextureControl(gui::IGUIEnvironment* guiEnv, video::IVideoDriver * driver, const core::position2d & pos, IGUIElement* parent, s32 id=-1) + : gui::IGUIElement(gui::EGUIET_ELEMENT, guiEnv, parent,id, core::rect(pos,pos+core::dimension2d(100,15))) + , DirtyFlag(true), ComboTexture(0) + { + core::rect rectCombo(0, 0, AbsoluteRect.getWidth(),AbsoluteRect.getHeight()); + ComboTexture = guiEnv->addComboBox (rectCombo, this); + updateTextures(driver); + } + + virtual bool OnEvent(const SEvent &event) + { + if ( event.EventType != EET_GUI_EVENT ) + return false; + + if ( event.GUIEvent.Caller == ComboTexture && event.GUIEvent.EventType == gui::EGET_COMBO_BOX_CHANGED ) + { + DirtyFlag = true; + } + + return false; + } + + // Workaround for a problem with comboboxes. + // We have to get in front when the combobox wants to get in front or combobox-list might be drawn below other elements. + virtual bool bringToFront(IGUIElement* element) + { + bool result = gui::IGUIElement::bringToFront(element); + if ( Parent && element == ComboTexture ) + result &= Parent->bringToFront(this); + return result; + } + + // return selected texturename (if any, otherwise 0) + const wchar_t * getSelectedTextureName() const + { + s32 selected = ComboTexture->getSelected(); + if ( selected < 0 ) + return 0; + return ComboTexture->getItem(selected); + } + + // reset the dirty flag + void resetDirty() + { + DirtyFlag = false; + } + + // when the texture was changed the dirty flag is set + bool isDirty() const + { + return DirtyFlag; + }; + + // Put the names of all currenlty loaded textures in a combobox + void updateTextures(video::IVideoDriver * driver) + { + s32 oldSelected = ComboTexture->getSelected(); + s32 selectNew = -1; + const wchar_t * oldTextureName = 0; + if ( oldSelected >= 0 ) + { + oldTextureName = ComboTexture->getItem(oldSelected); + } + ComboTexture->clear(); + for ( u32 i=0; i < driver->getTextureCount(); ++i ) + { + video::ITexture * texture = driver->getTextureByIndex(i); + core::stringw name( texture->getName() ); + ComboTexture->addItem( name.c_str() ); + if ( oldTextureName && selectNew < 0 && name == oldTextureName ) + selectNew = i; + } + + // add another name which can be used to clear the texture + ComboTexture->addItem( CLEAR_TEXTURE.c_str() ); + if ( CLEAR_TEXTURE == oldTextureName ) + selectNew = ComboTexture->getItemCount()-1; + + if ( selectNew >= 0 ) + ComboTexture->setSelected(selectNew); + + DirtyFlag = true; + } + +private: + bool DirtyFlag; + gui::IGUIComboBox * ComboTexture; +}; + +/* + Control which allows setting some of the material values for a meshscenenode +*/ +struct SMeshNodeControl +{ + // constructor + SMeshNodeControl() + : Initialized(false), Driver(0), MeshManipulator(0), SceneNode(0), SceneNode2T(0), SceneNodeTangents(0) + , AllColorsControl(0), ButtonLighting(0), InfoLighting(0), ComboMaterial(0), TextureControl1(0), TextureControl2(0), ControlVertexColors(0) + { + } + + // Destructor + virtual ~SMeshNodeControl() + { + if ( TextureControl1 ) + TextureControl1->drop(); + if ( TextureControl2 ) + TextureControl2->drop(); + if ( ControlVertexColors ) + ControlVertexColors->drop(); + } + + void init(scene::IMeshSceneNode* node, IrrlichtDevice * device, const core::position2d & pos, const wchar_t * description) + { + if ( Initialized || !node || !device) // initializing twice or with invalid data not allowed + return; + + Driver = device->getVideoDriver (); + gui::IGUIEnvironment* guiEnv = device->getGUIEnvironment(); + scene::ISceneManager* smgr = device->getSceneManager(); + MeshManipulator = smgr->getMeshManipulator(); + + SceneNode = node; + scene::IMeshManipulator * meshManip = smgr->getMeshManipulator(); + + scene::IMesh * mesh2T = meshManip->createMeshWith2TCoords(node->getMesh()); + SceneNode2T = smgr->addMeshSceneNode(mesh2T, 0, -1, SceneNode->getPosition(), SceneNode->getRotation(), SceneNode->getScale() ); + mesh2T->drop(); + + scene::IMesh * meshTangents = meshManip->createMeshWithTangents(node->getMesh(), false, false, false); + SceneNodeTangents = smgr->addMeshSceneNode(meshTangents, 0, -1 + , SceneNode->getPosition(), SceneNode->getRotation(), SceneNode->getScale() ); + meshTangents->drop(); + + video::SMaterial & material = SceneNode->getMaterial(0); + material.Lighting = true; + AllColorsControl = new CAllColorsControl(guiEnv, pos, description, true, guiEnv->getRootGUIElement()); + AllColorsControl->setColorsToMaterialColors(material); + + core::rect rectBtn(pos + core::position2d(0, 320), core::dimension2d(60, 15)); + ButtonLighting = guiEnv->addButton (rectBtn, 0, -1, L"Lighting"); + ButtonLighting->setIsPushButton(true); + ButtonLighting->setPressed(material.Lighting); + core::rect rectInfo( rectBtn.LowerRightCorner.X, rectBtn.UpperLeftCorner.Y, rectBtn.LowerRightCorner.X+40, rectBtn.UpperLeftCorner.Y+15 ); + InfoLighting = guiEnv->addStaticText(L"", rectInfo, true, false ); + InfoLighting->setTextAlignment(gui::EGUIA_CENTER, gui::EGUIA_CENTER ); + + core::rect rectCombo(pos.X, rectBtn.LowerRightCorner.Y, pos.X+100, rectBtn.LowerRightCorner.Y+15); + ComboMaterial = guiEnv->addComboBox (rectCombo); + for ( int i=0; i <= (int)video::EMT_ONETEXTURE_BLEND; ++i ) + { + ComboMaterial->addItem( core::stringw(video::sBuiltInMaterialTypeNames[i]).c_str() ); + } + ComboMaterial->setSelected( (s32)material.MaterialType ); + + core::position2d posTex(rectCombo.UpperLeftCorner.X,rectCombo.LowerRightCorner.Y); + TextureControl1 = new CTextureControl(guiEnv, Driver, posTex, guiEnv->getRootGUIElement()); + posTex.Y += 15; + TextureControl2 = new CTextureControl(guiEnv, Driver, posTex, guiEnv->getRootGUIElement()); + + core::position2d posVertexColors( posTex.X, posTex.Y + 15); + ControlVertexColors = new CColorControl( guiEnv, posVertexColors, L"Vertex colors", guiEnv->getRootGUIElement()); + + video::S3DVertex * vertices = (video::S3DVertex *)node->getMesh()->getMeshBuffer(0)->getVertices(); + if ( vertices ) + { + ControlVertexColors->setColor(vertices[0].Color); + } + + Initialized = true; + } + + void update() + { + if ( !Initialized ) + return; + + video::SMaterial & material = SceneNode->getMaterial(0); + video::SMaterial & material2T = SceneNode2T->getMaterial(0); + video::SMaterial & materialTangents = SceneNodeTangents->getMaterial(0); + + s32 selectedMaterial = ComboMaterial->getSelected(); + if ( selectedMaterial >= (s32)video::EMT_SOLID && selectedMaterial <= (s32)video::EMT_ONETEXTURE_BLEND) + { + video::E_VERTEX_TYPE vertexType = getVertexTypeForMaterialType((video::E_MATERIAL_TYPE)selectedMaterial); + switch ( vertexType ) + { + case video::EVT_STANDARD: + material.MaterialType = (video::E_MATERIAL_TYPE)selectedMaterial; + SceneNode->setVisible(true); + SceneNode2T->setVisible(false); + SceneNodeTangents->setVisible(false); + break; + case video::EVT_2TCOORDS: + material2T.MaterialType = (video::E_MATERIAL_TYPE)selectedMaterial; + SceneNode->setVisible(false); + SceneNode2T->setVisible(true); + SceneNodeTangents->setVisible(false); + break; + case video::EVT_TANGENTS: + materialTangents.MaterialType = (video::E_MATERIAL_TYPE)selectedMaterial; + SceneNode->setVisible(false); + SceneNode2T->setVisible(false); + SceneNodeTangents->setVisible(true); + break; + } + } + + updateMaterial(material); + updateMaterial(material2T); + updateMaterial(materialTangents); + + if ( ButtonLighting->isPressed() ) + InfoLighting->setText(L"on"); + else + InfoLighting->setText(L"off"); + + AllColorsControl->resetDirty(); + TextureControl1->resetDirty(); + TextureControl2->resetDirty(); + ControlVertexColors->resetDirty(); + } + + void updateTextures() + { + TextureControl1->updateTextures(Driver); + TextureControl2->updateTextures(Driver); + } + +protected: + + void updateMaterial(video::SMaterial & material) + { + AllColorsControl->updateMaterialColors(material); + material.Lighting = ButtonLighting->isPressed(); + if ( TextureControl1->isDirty() ) + { + material.TextureLayer[0].Texture = Driver->getTexture( io::path(TextureControl1->getSelectedTextureName()) ); + } + if ( TextureControl2->isDirty() ) + { + material.TextureLayer[1].Texture = Driver->getTexture( io::path(TextureControl2->getSelectedTextureName()) ); + } + if ( ControlVertexColors->isDirty() ) + { + MeshManipulator->setVertexColors (SceneNode->getMesh(), ControlVertexColors->getColor()); + MeshManipulator->setVertexColors (SceneNode2T->getMesh(), ControlVertexColors->getColor()); + MeshManipulator->setVertexColors (SceneNodeTangents->getMesh(), ControlVertexColors->getColor()); + } + } + + bool Initialized; + video::IVideoDriver * Driver; + scene::IMeshManipulator* MeshManipulator; + scene::IMeshSceneNode* SceneNode; + scene::IMeshSceneNode* SceneNode2T; + scene::IMeshSceneNode* SceneNodeTangents; + CAllColorsControl* AllColorsControl; + gui::IGUIButton * ButtonLighting; + gui::IGUIStaticText* InfoLighting; + gui::IGUIComboBox * ComboMaterial; + CTextureControl* TextureControl1; + CTextureControl* TextureControl2; + CColorControl* ControlVertexColors; +}; + +/* + Control to allow setting the color values of a lightscenenode. +*/ +struct SLightNodeControl +{ + // constructor + SLightNodeControl() : Initialized(false), SceneNode(0), AllColorsControl(0) + { + } + + void init(scene::ILightSceneNode* node, gui::IGUIEnvironment* guiEnv, const core::position2d & pos, const wchar_t * description) + { + if ( Initialized || !node || !guiEnv) // initializing twice or with invalid data not allowed + return; + SceneNode = node; + AllColorsControl = new CAllColorsControl(guiEnv, pos, description, false, guiEnv->getRootGUIElement()); + const video::SLight & lightData = SceneNode->getLightData(); + AllColorsControl->setColorsToLightDataColors(lightData); + Initialized = true; + } + + void update() + { + if ( !Initialized ) + return; + + video::SLight & lightData = SceneNode->getLightData(); + AllColorsControl->updateMaterialColors(lightData); + } + +protected: + bool Initialized; + scene::ILightSceneNode* SceneNode; + CAllColorsControl* AllColorsControl; +}; + +/* + Application configuration +*/ +struct SConfig +{ + SConfig() + : RenderInBackground(true) + , DriverType(video::EDT_BURNINGSVIDEO) + , ScreenSize(640, 480) + { + } + + bool RenderInBackground; + video::E_DRIVER_TYPE DriverType; + core::dimension2d ScreenSize; +}; + +/* + Main application class +*/ +class CApp : public IEventReceiver +{ + friend int main(int argc, char *argv[]); + +public: + // constructor + CApp() + : IsRunning(false) + , Device(0) + , Camera(0) + , GlobalAmbient(0) + { + } + + // destructor + ~CApp() + { + } + + // stop running - will quit at end of mainloop + void stopApp() + { + IsRunning = false; + } + + // Event handler + virtual bool OnEvent(const SEvent &event) + { + if (event.EventType == EET_GUI_EVENT) + { + gui::IGUIEnvironment* env = Device->getGUIEnvironment(); + + switch(event.GUIEvent.EventType) + { + case gui::EGET_MENU_ITEM_SELECTED: + { + gui::IGUIContextMenu* menu = (gui::IGUIContextMenu*)event.GUIEvent.Caller; + s32 id = menu->getItemCommandId(menu->getSelectedItem()); + + switch(id) + { + case GUI_ID_OPEN_TEXTURE: // File -> Open Texture + env->addFileOpenDialog(L"Please select a texture file to open"); + break; + case GUI_ID_QUIT: // File -> Quit + stopApp(); + break; + } + } + break; + + case gui::EGET_FILE_SELECTED: + { + // load the model file, selected in the file open dialog + gui::IGUIFileOpenDialog* dialog = + (gui::IGUIFileOpenDialog*)event.GUIEvent.Caller; + loadTexture(io::path(dialog->getFileName()).c_str()); + } + break; + + default: + break; + } + } + + return false; + } + +protected: + + // Application initialization + // returns true when it was succesful initialized, otherwise false. + bool init(int argc, char *argv[]) + { + // ask user for the driver which should be used + Config.DriverType = getDriverTypeFromConsole(); + if ( (int)Config.DriverType < 0 ) + return false; + + // create the device with the settings from our config + Device = createDevice(Config.DriverType, Config.ScreenSize); + if (!Device) + return false; + Device->setWindowCaption( DriverTypeNames[Config.DriverType] ); + Device->setEventReceiver(this); + + scene::ISceneManager* smgr = Device->getSceneManager(); + video::IVideoDriver * driver = Device->getVideoDriver (); + gui::IGUIEnvironment* guiEnv = Device->getGUIEnvironment(); + + // set a nicer font + gui::IGUISkin* skin = guiEnv->getSkin(); + gui::IGUIFont* font = guiEnv->getFont("../../media/fonthaettenschweiler.bmp"); + if (font) + skin->setFont(font); + + // remove some alpha value because it makes those menus harder to read otherwise + video::SColor col3dHighLight( skin->getColor(gui::EGDC_APP_WORKSPACE) ); + col3dHighLight.setAlpha(255); + video::SColor colHighLight( col3dHighLight ); + skin->setColor(gui::EGDC_HIGH_LIGHT, colHighLight ); + skin->setColor(gui::EGDC_3D_HIGH_LIGHT, col3dHighLight ); + + // Add some textures which are useful to test material settings + createDefaultTextures(driver); + + // create a menu + gui::IGUIContextMenu * menuBar = guiEnv->addMenu(); + menuBar->addItem(L"File", -1, true, true); + + gui::IGUIContextMenu* subMenuFile = menuBar->getSubMenu(0); + subMenuFile->addItem(L"Open texture ...", GUI_ID_OPEN_TEXTURE); + subMenuFile->addSeparator(); + subMenuFile->addItem(L"Quit", GUI_ID_QUIT); + + // a static camera + Camera = smgr->addCameraSceneNode (0, core::vector3df(0, 0, 0), + core::vector3df(0, 0, 100), + -1); + + // add the nodes which are used to show the materials + scene::IMeshSceneNode* nodeL = smgr->addCubeSceneNode (30.0f, 0, -1, + core::vector3df(-35, 0, 100), + core::vector3df(0, 0, 0), + core::vector3df(1.0f, 1.0f, 1.0f)); + NodeLeft.init( nodeL, Device, core::position2d(10,20), L"left node" ); + + scene::IMeshSceneNode* nodeR = smgr->addCubeSceneNode (30.0f, 0, -1, + core::vector3df(35, 0, 100), + core::vector3df(0, 0, 0), + core::vector3df(1.0f, 1.0f, 1.0f)); + NodeRight.init( nodeR, Device, core::position2d(530,20), L"right node" ); + + // add one light + scene::ILightSceneNode* nodeLight = smgr->addLightSceneNode(0, core::vector3df(0, 0, 0), + video::SColorf(1.0f, 1.0f, 1.0f), + 100.0f); + LightControl.init(nodeLight, guiEnv, core::position2d(270,20), L"light" ); + + // one large cube around everything. That's mainly to make the light more obvious. + scene::IMeshSceneNode* backgroundCube = smgr->addCubeSceneNode (200.0f, 0, -1, core::vector3df(0, 0, 0), + core::vector3df(45, 0, 0), + core::vector3df(1.0f, 1.0f, 1.0f)); + backgroundCube->getMaterial(0).BackfaceCulling = false; // we are within the cube, so we have to disable backface culling to see it + backgroundCube->getMaterial(0).EmissiveColor.set(255,50,50,50); // we keep some self lighting to keep texts visible + + // set the ambient light value + GlobalAmbient = new CColorControl( guiEnv, core::position2d(270, 300), L"global ambient", guiEnv->getRootGUIElement()); + GlobalAmbient->setColor( smgr->getAmbientLight().toSColor() ); + + return true; + } + + // Ask the user which driver to use + video::E_DRIVER_TYPE getDriverTypeFromConsole() + { + printf("Please select the driver you want for this example:\n"\ + " (a) Direct3D 9.0c\n (b) Direct3D 8.1\n (c) OpenGL 1.5\n"\ + " (d) Software Renderer\n (e) Burning's Software Renderer\n"\ + " (f) NullDevice\n (otherKey) exit\n\n"); + + char i; + std::cin >> i; + + switch(i) + { + + case 'a': return video::EDT_DIRECT3D9; + case 'b': return video::EDT_DIRECT3D8; + case 'c': return video::EDT_OPENGL; + case 'd': return video::EDT_SOFTWARE; + case 'e': return video::EDT_BURNINGSVIDEO; + case 'f': return video::EDT_NULL; + default: return video::E_DRIVER_TYPE(-1); + } + } + + // Update one frame + bool update() + { + using namespace irr; + + video::IVideoDriver* videoDriver = Device->getVideoDriver(); + if ( !Device->run() ) + return false; + + if ( Device->isWindowActive() || Config.RenderInBackground ) + { + gui::IGUIEnvironment* guiEnv = Device->getGUIEnvironment(); + scene::ISceneManager* smgr = Device->getSceneManager(); + gui::IGUISkin * skin = guiEnv->getSkin(); + + // update our controls + NodeLeft.update(); + NodeRight.update(); + LightControl.update(); + + // update ambient light settings + if ( GlobalAmbient->isDirty() ) + { + smgr->setAmbientLight( GlobalAmbient->getColor() ); + GlobalAmbient->resetDirty(); + } + + // draw everythings + video::SColor bkColor( skin->getColor(gui::EGDC_APP_WORKSPACE) ); + videoDriver->beginScene(true, true, bkColor); + + smgr->drawAll(); + guiEnv->drawAll(); + + videoDriver->endScene(); + } + + return true; + } + + // Run the application. Our main loop. + void run() + { + IsRunning = true; + + if ( !Device ) + return; + + // main application loop + while(IsRunning) + { + if ( !update() ) + break; + + Device->sleep( 5 ); + } + } + + // Close down the application + void quit() + { + IsRunning = false; + GlobalAmbient->drop(); + GlobalAmbient = NULL; + if ( Device ) + { + Device->closeDevice(); + Device->drop(); + Device = NULL; + } + } + + // Create some useful textures. + // Note that the function put readability over speed, you shouldn't use setPixel at runtime but for initialization it's nice. + void createDefaultTextures(video::IVideoDriver * driver) + { + const u32 width = 256; + const u32 height = 256; + video::IImage * imageA8R8G8B8 = driver->createImage (video::ECF_A8R8G8B8, core::dimension2d(width, height)); + if ( !imageA8R8G8B8 ) + return; + const u32 pitch = imageA8R8G8B8->getPitch(); + + // some nice caro with 9 typical colors + for ( u32 y = 0; y < height; ++ y ) + { + for ( u32 x = 0; x < pitch; ++x ) + { + if ( y < height/3 ) + { + if ( x < width/3 ) + imageA8R8G8B8->setPixel (x, y, SCOL_BLACK); + else if ( x < 2*width/3 ) + imageA8R8G8B8->setPixel (x, y, SCOL_BLUE); + else + imageA8R8G8B8->setPixel (x, y, SCOL_CYAN); + } + else if ( y < 2*height/3 ) + { + if ( x < width/3 ) + imageA8R8G8B8->setPixel (x, y, SCOL_GRAY); + else if ( x < 2*width/3 ) + imageA8R8G8B8->setPixel (x, y, SCOL_GREEN); + else + imageA8R8G8B8->setPixel (x, y, SCOL_MAGENTA); + } + else + { + if ( x < width/3 ) + imageA8R8G8B8->setPixel (x, y, SCOL_RED); + else if ( x < 2*width/3 ) + imageA8R8G8B8->setPixel (x, y, SCOL_YELLOW); + else + imageA8R8G8B8->setPixel (x, y, SCOL_WHITE); + } + } + } + driver->addTexture (io::path("CARO_A8R8G8B8"), imageA8R8G8B8); + + // all white + imageA8R8G8B8->fill(SCOL_WHITE); + driver->addTexture (io::path("WHITE_A8R8G8B8"), imageA8R8G8B8); + + // all black + imageA8R8G8B8->fill(SCOL_BLACK); + driver->addTexture (io::path("BLACK_A8R8G8B8"), imageA8R8G8B8); + + // gray-scale + for ( u32 y = 0; y < height; ++ y ) + { + for ( u32 x = 0; x < pitch; ++x ) + { + imageA8R8G8B8->setPixel (x, y, video::SColor(y, x,x,x) ); + } + } + driver->addTexture (io::path("GRAYSCALE_A8R8G8B8"), imageA8R8G8B8); + } + + // Load a texture and make sure nodes know it when more textures are available. + void loadTexture(const io::path &name) + { + Device->getVideoDriver()->getTexture(name); + NodeLeft.updateTextures(); + NodeRight.updateTextures(); + } + +private: + SConfig Config; + volatile bool IsRunning; + IrrlichtDevice * Device; + scene::ICameraSceneNode * Camera; + SMeshNodeControl NodeLeft; + SMeshNodeControl NodeRight; + SLightNodeControl LightControl; + CColorControl * GlobalAmbient; +}; + +/* + A very short main as we do everything else in classes. +*/ +int main(int argc, char *argv[]) +{ + CApp APP; + + if ( !APP.init(argc, argv) ) + { + printf("init failed\n"); + return 1; + } + + APP.run(); + APP.quit(); + + return 0; +} + +/* +**/ diff --git a/examples/23.SMeshHandling/Makefile b/examples/23.SMeshHandling/Makefile new file mode 100644 index 00000000..7a37a7a8 --- /dev/null +++ b/examples/23.SMeshHandling/Makefile @@ -0,0 +1,38 @@ +# Makefile for Irrlicht Examples +# It's usually sufficient to change just the target name and source file list +# and be sure that CXX is set to a valid compiler +Target = 23.SMeshHandling +Sources = main.cpp + +# general compiler settings +CPPFLAGS = -I../../include -I/usr/X11R6/include +CXXFLAGS = -O3 -ffast-math +#CXXFLAGS = -g -Wall + +#default target is Linux +all: all_linux + +ifeq ($(HOSTTYPE), x86_64) +LIBSELECT=64 +endif + +# target specific settings +all_linux: LDFLAGS = -L/usr/X11R6/lib$(LIBSELECT) -L../../lib/Linux -lIrrlicht -lGL -lXxf86vm -lXext -lX11 +all_linux clean_linux: SYSTEM=Linux +all_win32: LDFLAGS = -L../../lib/Win32-gcc -lIrrlicht -lopengl32 -lm +all_win32 clean_win32: SYSTEM=Win32-gcc +all_win32 clean_win32: SUF=.exe +# name of the binary - only valid for targets which set SYSTEM +DESTPATH = ../../bin/$(SYSTEM)/$(Target)$(SUF) + +all_linux all_win32: + $(warning Building...) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) $(Sources) -o $(DESTPATH) $(LDFLAGS) + +clean: clean_linux clean_win32 + $(warning Cleaning...) + +clean_linux clean_win32: + @$(RM) $(DESTPATH) + +.PHONY: all all_win32 clean clean_linux clean_win32 diff --git a/examples/23.SMeshHandling/SMeshHandling.dev b/examples/23.SMeshHandling/SMeshHandling.dev new file mode 100644 index 00000000..94043f38 --- /dev/null +++ b/examples/23.SMeshHandling/SMeshHandling.dev @@ -0,0 +1,59 @@ +[Project] +FileName=example.dev +Name=Irrlicht Example 23 SMeshHandling +UnitCount=1 +Type=1 +Ver=1 +ObjFiles= +Includes=..\..\include +Libs= +PrivateResource= +ResourceIncludes= +MakeIncludes= +Compiler= +CppCompiler= +Linker=../../lib/Win32-gcc/libIrrlicht.a_@@_ +IsCpp=1 +Icon= +ExeOutput=../../bin/Win32-gcc +ObjectOutput=obj +OverrideOutput=1 +OverrideOutputName=23.SMeshHandling.exe +HostApplication= +Folders= +CommandLine= +IncludeVersionInfo=0 +SupportXPThemes=0 +CompilerSet=0 +CompilerSettings=0000000000000000000000 +UseCustomMakefile=0 +CustomMakefile= + +[Unit1] +FileName=main.cpp +CompileCpp=1 +Folder=Projekt1 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[VersionInfo] +Major=0 +Minor=1 +Release=1 +Build=1 +LanguageID=1033 +CharsetID=1252 +CompanyName= +FileVersion= +FileDescription=Irrlicht Engine example compiled using DevCpp and gcc +InternalName= +LegalCopyright= +LegalTrademarks= +OriginalFilename= +ProductName= +ProductVersion= +AutoIncBuildNr=0 + diff --git a/examples/23.SMeshHandling/SMeshHandling.sln b/examples/23.SMeshHandling/SMeshHandling.sln new file mode 100644 index 00000000..30c047f6 --- /dev/null +++ b/examples/23.SMeshHandling/SMeshHandling.sln @@ -0,0 +1,21 @@ +Microsoft Visual Studio Solution File, Format Version 8.00 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "19.SMeshHandling", "SMeshHandling.vcproj", "{EB3B38EA-5CE7-4983-845B-880661E69D09}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Global + GlobalSection(SolutionConfiguration) = preSolution + Debug = Debug + Release = Release + EndGlobalSection + GlobalSection(ProjectConfiguration) = postSolution + {EB3B38EA-5CE7-4983-845B-880661E69D09}.Debug.ActiveCfg = Debug|Win32 + {EB3B38EA-5CE7-4983-845B-880661E69D09}.Debug.Build.0 = Debug|Win32 + {EB3B38EA-5CE7-4983-845B-880661E69D09}.Release.ActiveCfg = Release|Win32 + {EB3B38EA-5CE7-4983-845B-880661E69D09}.Release.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + EndGlobalSection + GlobalSection(ExtensibilityAddIns) = postSolution + EndGlobalSection +EndGlobal diff --git a/examples/TestProject/TestProject.vcproj b/examples/23.SMeshHandling/SMeshHandling.vcproj similarity index 69% rename from examples/TestProject/TestProject.vcproj rename to examples/23.SMeshHandling/SMeshHandling.vcproj index 33a623e5..b85cba8b 100644 --- a/examples/TestProject/TestProject.vcproj +++ b/examples/23.SMeshHandling/SMeshHandling.vcproj @@ -2,8 +2,8 @@ + CharacterSet="2" + WholeProgramOptimization="TRUE"> + DebugInformationFormat="0" + CallingConvention="1"/> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/23.SMeshHandling/SMeshHandling_vc9.vcproj b/examples/23.SMeshHandling/SMeshHandling_vc9.vcproj new file mode 100644 index 00000000..242e00f8 --- /dev/null +++ b/examples/23.SMeshHandling/SMeshHandling_vc9.vcproj @@ -0,0 +1,187 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/23.SMeshHandling/main.cpp b/examples/23.SMeshHandling/main.cpp new file mode 100644 index 00000000..e50fba39 --- /dev/null +++ b/examples/23.SMeshHandling/main.cpp @@ -0,0 +1,441 @@ +/** Example 023 SMeshBufferHandling + +A tutorial by geoff. + +In this tutorial we'll learn how to create custom meshes and deal with them +with Irrlicht. We'll create an interesting heightmap with some lighting effects. +With keys 1,2,3 you can choose a different mesh layout, which is put into the +mesh buffers as desired. All positions, normals, etc. are updated accordingly. + +Ok, let's start with the headers (I think there's nothing to say about it) +*/ + +#include +#include + +#ifdef _MSC_VER +#pragma comment(lib, "Irrlicht.lib") +#endif + +//Namespaces for the engine +using namespace irr; +using namespace video; +using namespace core; +using namespace scene; +using namespace io; +using namespace gui; + +/* This is the type of the functions which work out the colour. */ +typedef SColor colour_func(f32 x, f32 y, f32 z); + +/* Here comes a set of functions which can be used for coloring the nodes while +creating the mesh. */ + +// Greyscale, based on the height. +SColor grey(f32, f32, f32 z) +{ + u32 n = (u32)(255.f * z); + return SColor(255, n, n, n); +} + +// Interpolation between blue and white, with red added in one +// direction and green in the other. +SColor yellow(f32 x, f32 y, f32) +{ + return SColor(255, 128 + (u32)(127.f * x), 128 + (u32)(127.f * y), 255); +} + +// Pure white. +SColor white(f32, f32, f32) { return SColor(255, 255, 255, 255); } + +/* The type of the functions which generate the heightmap. x and y +range between -0.5 and 0.5, and s is the scale of the heightmap. */ + +typedef f32 generate_func(s16 x, s16 y, f32 s); + +// An interesting sample function :-) +f32 eggbox(s16 x, s16 y, f32 s) +{ + const f32 r = 4.f*sqrtf((f32)(x*x + y*y))/s; + const f32 z = expf(-r * 2) * (cosf(0.2f * x) + cosf(0.2f * y)); + return 0.25f+0.25f*z; +} + +// A rather dumb sine function :-/ +f32 moresine(s16 x, s16 y, f32 s) +{ + const f32 xx=0.3f*(f32)x/s; + const f32 yy=12*y/s; + const f32 z = sinf(xx*xx+yy)*sinf(xx+yy*yy); + return 0.25f + 0.25f * z; +} + +// A simple function +f32 justexp(s16 x, s16 y, f32 s) +{ + const f32 xx=6*x/s; + const f32 yy=6*y/s; + const f32 z = (xx*xx+yy*yy); + return 0.3f*z*cosf(xx*yy); +} + +/* A simple class for representing heightmaps. Most of this should be obvious. */ + +class HeightMap +{ +private: + const u16 Width; + const u16 Height; + f32 s; + core::array data; +public: + HeightMap(u16 _w, u16 _h) : Width(_w), Height(_h), s(0.f), data(0) + { + s = sqrtf((f32)(Width * Width + Height * Height)); + data.set_used(Width * Height); + } + + // Fill the heightmap with values generated from f. + void generate(generate_func f) + { + u32 i=0; + for(u16 y = 0; y < Height; ++y) + for(u16 x = 0; x < Width; ++x) + set(i++, calc(f, x, y)); + } + + u16 height() const { return Height; } + u16 width() const { return Width; } + + f32 calc(generate_func f, u16 x, u16 y) const + { + const f32 xx = (f32)x - Width*0.5f; + const f32 yy = (f32)y - Height*0.5f; + return f((u16)xx, (u16)yy, s); + } + + // The height at (x, y) is at position y * Width + x. + + void set(u16 x, u16 y, f32 z) { data[y * Width + x] = z; } + void set(u32 i, f32 z) { data[i] = z; } + f32 get(u16 x, u16 y) const { return data[y * Width + x]; } + + /* The only difficult part. This considers the normal at (x, y) to + be the cross product of the vectors between the adjacent points + in the horizontal and vertical directions. + + s is a scaling factor, which is necessary if the height units are + different from the coordinate units; for example, if your map has + heights in metres and the coordinates are in units of a + kilometer. */ + + vector3df getnormal(u16 x, u16 y, f32 s) const + { + const f32 zc = get(x, y); + f32 zl, zr, zu, zd; + + if (x == 0) + { + zr = get(x + 1, y); + zl = zc + zc - zr; + } + else if (x == Width - 1) + { + zl = get(x - 1, y); + zr = zc + zc - zl; + } + else + { + zr = get(x + 1, y); + zl = get(x - 1, y); + } + + if (y == 0) + { + zd = get(x, y + 1); + zu = zc + zc - zd; + } + else if (y == Height - 1) + { + zu = get(x, y - 1); + zd = zc + zc - zu; + } + else + { + zd = get(x, y + 1); + zu = get(x, y - 1); + } + + return vector3df(s * 2 * (zl - zr), 4, s * 2 * (zd - zu)).normalize(); + } +}; + +/* A class which generates a mesh from a heightmap. */ +class TMesh +{ +private: + u16 Width; + u16 Height; + f32 Scale; +public: + SMesh* Mesh; + + TMesh() : Mesh(0), Width(0), Height(0), Scale(1.f) + { + Mesh = new SMesh(); + } + + ~TMesh() + { + Mesh->drop(); + } + + // Unless the heightmap is small, it won't all fit into a single + // SMeshBuffer. This function chops it into pieces and generates a + // buffer from each one. + + void init(const HeightMap &hm, f32 scale, colour_func cf, IVideoDriver *driver) + { + Scale = scale; + + const u32 mp = driver -> getMaximalPrimitiveCount(); + Width = hm.width(); + Height = hm.height(); + + const u32 sw = mp / (6 * Height); // the width of each piece + + u32 i=0; + for(u32 y0 = 0; y0 < Height; y0 += sw) + { + u16 y1 = y0 + sw; + if (y1 >= Height) + y1 = Height - 1; // the last one might be narrower + addstrip(hm, cf, y0, y1, i); + ++i; + } + if (igetMeshBufferCount()) + { + // clear the rest + for (u32 j=i; jgetMeshBufferCount(); ++j) + { + Mesh->getMeshBuffer(j)->drop(); + } + Mesh->MeshBuffers.erase(i,Mesh->getMeshBufferCount()-i); + } + + Mesh->recalculateBoundingBox(); + } + + // Generate a SMeshBuffer which represents all the vertices and + // indices for values of y between y0 and y1, and add it to the + // mesh. + + void addstrip(const HeightMap &hm, colour_func cf, u16 y0, u16 y1, u32 bufNum) + { + SMeshBuffer *buf = 0; + if (bufNumgetMeshBufferCount()) + { + buf = (SMeshBuffer*)Mesh->getMeshBuffer(bufNum); + } + else + { + // create new buffer + buf = new SMeshBuffer(); + Mesh->addMeshBuffer(buf); + // to simplify things we drop here but continue using buf + buf->drop(); + } + buf->Vertices.set_used((1 + y1 - y0) * Width); + + u32 i=0; + for (u16 y = y0; y <= y1; ++y) + { + for (u16 x = 0; x < Width; ++x) + { + const f32 z = hm.get(x, y); + const f32 xx = (f32)x/(f32)Width; + const f32 yy = (f32)y/(f32)Height; + + S3DVertex& v = buf->Vertices[i++]; + v.Pos.set(x, Scale * z, y); + v.Normal.set(hm.getnormal(x, y, Scale)); + v.Color=cf(xx, yy, z); + v.TCoords.set(xx, yy); + } + } + + buf->Indices.set_used(6 * (Width - 1) * (y1 - y0)); + i=0; + for(u16 y = y0; y < y1; ++y) + { + for(u16 x = 0; x < Width - 1; ++x) + { + const u16 n = (y-y0) * Width + x; + buf->Indices[i]=n; + buf->Indices[++i]=n + Height; + buf->Indices[++i]=n + Height + 1; + buf->Indices[++i]=n + Height + 1; + buf->Indices[++i]=n + 1; + buf->Indices[++i]=n; + ++i; + } + } + + buf->recalculateBoundingBox(); + } +}; + +/* +Our event receiver implementation, taken from tutorial 4. +*/ +class MyEventReceiver : public IEventReceiver +{ +public: + // This is the one method that we have to implement + virtual bool OnEvent(const SEvent& event) + { + // Remember whether each key is down or up + if (event.EventType == irr::EET_KEY_INPUT_EVENT) + KeyIsDown[event.KeyInput.Key] = event.KeyInput.PressedDown; + + return false; + } + + // This is used to check whether a key is being held down + virtual bool IsKeyDown(EKEY_CODE keyCode) const + { + return KeyIsDown[keyCode]; + } + + MyEventReceiver() + { + for (u32 i=0; i> i; + + switch(i) + { + case 'a': driverType = video::EDT_DIRECT3D9;break; + case 'b': driverType = video::EDT_DIRECT3D8;break; + case 'c': driverType = video::EDT_OPENGL; break; + case 'd': driverType = video::EDT_SOFTWARE; break; + case 'e': driverType = video::EDT_BURNINGSVIDEO;break; + case 'f': driverType = video::EDT_NULL; break; + default: return 1; + } + + MyEventReceiver receiver; + IrrlichtDevice* device = createDevice(driverType, + core::dimension2du(800, 600), 32, false, false, false, + &receiver); + + if(device == 0) + return 1; + + IVideoDriver *driver = device->getVideoDriver(); + ISceneManager *smgr = device->getSceneManager(); + device->setWindowCaption(L"Irrlicht Example for SMesh usage."); + + /* + Create the custom mesh and initialize with a heightmap + */ + TMesh mesh; + HeightMap hm = HeightMap(255, 255); + hm.generate(eggbox); + mesh.init(hm, 50.f, grey, driver); + + // Add the mesh to the scene graph + IMeshSceneNode* meshnode = smgr -> addMeshSceneNode(mesh.Mesh); + meshnode->setMaterialFlag(video::EMF_BACK_FACE_CULLING, false); + + // light is just for nice effects + ILightSceneNode *node = smgr->addLightSceneNode(0, vector3df(0,100,0), + SColorf(1.0f, 0.6f, 0.7f, 1.0f), 500.0f); + if (node) + { + node->getLightData().Attenuation.set(0.f, 1.f/500.f, 0.f); + ISceneNodeAnimator* anim = smgr->createFlyCircleAnimator(vector3df(0,150,0),250.0f); + if (anim) + { + node->addAnimator(anim); + anim->drop(); + } + } + + ICameraSceneNode* camera = smgr->addCameraSceneNodeFPS(); + if (camera) + { + camera->setPosition(vector3df(-20.f, 150.f, -20.f)); + camera->setTarget(vector3df(200.f, -80.f, 150.f)); + camera->setFarValue(20000.0f); + } + + /* + Just a usual render loop with event handling. The custom mesh is + a usual part of the scene graph which gets rendered by drawAll. + */ + while(device->run()) + { + if(!device->isWindowActive()) + { + device->sleep(100); + continue; + } + + if(receiver.IsKeyDown(irr::KEY_KEY_W)) + { + meshnode->setMaterialFlag(video::EMF_WIREFRAME, !meshnode->getMaterial(0).Wireframe); + } + else if(receiver.IsKeyDown(irr::KEY_KEY_1)) + { + hm.generate(eggbox); + mesh.init(hm, 50.f, grey, driver); + } + else if(receiver.IsKeyDown(irr::KEY_KEY_2)) + { + hm.generate(moresine); + mesh.init(hm, 50.f, yellow, driver); + } + else if(receiver.IsKeyDown(irr::KEY_KEY_3)) + { + hm.generate(justexp); + mesh.init(hm, 50.f, yellow, driver); + } + + driver->beginScene(true, true, SColor(0xff000000)); + smgr->drawAll(); + driver->endScene(); + } + + device->drop(); + + return 0; +} + +/* +That's it! Just compile and play around with the program. +**/ diff --git a/examples/BuildAllExamples.workspace b/examples/BuildAllExamples.workspace index c6ac0958..490ca036 100644 --- a/examples/BuildAllExamples.workspace +++ b/examples/BuildAllExamples.workspace @@ -21,6 +21,7 @@ + diff --git a/examples/BuildAllExamples_v9.sln b/examples/BuildAllExamples_v9.sln index 5d966b40..40ecd0c2 100644 --- a/examples/BuildAllExamples_v9.sln +++ b/examples/BuildAllExamples_v9.sln @@ -89,12 +89,54 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "16.Quake3MapShader_vc9", "1 EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "18.SplitScreen_vc9", "18.SplitScreen\SplitScreen_vc9.vcproj", "{1AB9413E-4F53-42A3-8CB2-CB4BE22336D0}" + ProjectSection(ProjectDependencies) = postProject + {E08E042A-6C45-411B-92BE-3CC31331019F} = {E08E042A-6C45-411B-92BE-3CC31331019F} + EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "19.MouseAndJoystick_vc9", "19.MouseAndJoystick\MouseAndJoystick_vc9.vcproj", "{FE853A36-E0D1-4AC5-A792-B643E70D2953}" + ProjectSection(ProjectDependencies) = postProject + {E08E042A-6C45-411B-92BE-3CC31331019F} = {E08E042A-6C45-411B-92BE-3CC31331019F} + EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "20.ManagedLights_vc9", "20.ManagedLights\ManagedLights_vc9.vcproj", "{16007FE2-142B-47F8-93E1-519BA3F39E71}" + ProjectSection(ProjectDependencies) = postProject + {E08E042A-6C45-411B-92BE-3CC31331019F} = {E08E042A-6C45-411B-92BE-3CC31331019F} + EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "21.Quake3Explorer_vc9", "21.Quake3Explorer\Quake3Explorer_vc9.vcproj", "{CDC4AAA9-72E1-4FFA-A04D-7EF59D8B97CD}" + ProjectSection(ProjectDependencies) = postProject + {E08E042A-6C45-411B-92BE-3CC31331019F} = {E08E042A-6C45-411B-92BE-3CC31331019F} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "22.MaterialViewer_vc9", "22.MaterialViewer\MaterialViewer_vc9.vcproj", "{4E6C2F8D-BA92-4C5B-96FD-72D4FE8BD7FA}" + ProjectSection(ProjectDependencies) = postProject + {E08E042A-6C45-411B-92BE-3CC31331019F} = {E08E042A-6C45-411B-92BE-3CC31331019F} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "23.SMeshHandling_vc9", "23.SMeshHandling\SMeshHandling_vc9.vcproj", "{6AEC2AA2-C9FF-4B7D-B07A-94A9D34B41D7}" + ProjectSection(ProjectDependencies) = postProject + {E08E042A-6C45-411B-92BE-3CC31331019F} = {E08E042A-6C45-411B-92BE-3CC31331019F} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "17.HelloWorld for Windows Mobile on PC", "17.HelloWorld_Mobile\17. HelloWorld for Windows Mobile on PC_v9.vcproj", "{2A29B6B1-AFC4-46C7-9944-7052AAE66F7B}" + ProjectSection(ProjectDependencies) = postProject + {E08E042A-6C45-411B-92BE-3CC31331019F} = {E08E042A-6C45-411B-92BE-3CC31331019F} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "GUI Editor_v9", "..\tools\GUIEditor\GUI Editor_v9.vcproj", "{853A396E-C031-4C26-A716-5B4E176BE11D}" + ProjectSection(ProjectDependencies) = postProject + {E08E042A-6C45-411B-92BE-3CC31331019F} = {E08E042A-6C45-411B-92BE-3CC31331019F} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Font Tool", "..\tools\IrrFontTool\newFontTool\irrFontTool_v9.vcproj", "{4D53E40F-37E3-42B1-8848-F4C6F8313A17}" + ProjectSection(ProjectDependencies) = postProject + {E08E042A-6C45-411B-92BE-3CC31331019F} = {E08E042A-6C45-411B-92BE-3CC31331019F} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Mesh Converter", "..\tools\MeshConverter\MeshConverter_v9.vcproj", "{E72B637E-4AA6-46F3-885F-AC67B4B470ED}" + ProjectSection(ProjectDependencies) = postProject + {E08E042A-6C45-411B-92BE-3CC31331019F} = {E08E042A-6C45-411B-92BE-3CC31331019F} + EndProjectSection EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -164,8 +206,8 @@ Global {78C9F424-523C-49AC-94B7-823AA4A26BF9}.Release|Win32.Build.0 = Release|Win32 {E08E042A-6C45-411B-92BE-3CC31331019F}.Debug|Win32.ActiveCfg = Debug|Win32 {E08E042A-6C45-411B-92BE-3CC31331019F}.Debug|Win32.Build.0 = Debug|Win32 - {E08E042A-6C45-411B-92BE-3CC31331019F}.Release|Win32.ActiveCfg = Release - Fast FPU|Win32 - {E08E042A-6C45-411B-92BE-3CC31331019F}.Release|Win32.Build.0 = Release - Fast FPU|Win32 + {E08E042A-6C45-411B-92BE-3CC31331019F}.Release|Win32.ActiveCfg = Release|Win32 + {E08E042A-6C45-411B-92BE-3CC31331019F}.Release|Win32.Build.0 = Release|Win32 {6F076455-D955-45D4-9C68-4AD4E45F2D47}.Debug|Win32.ActiveCfg = Debug|Win32 {6F076455-D955-45D4-9C68-4AD4E45F2D47}.Debug|Win32.Build.0 = Debug|Win32 {6F076455-D955-45D4-9C68-4AD4E45F2D47}.Release|Win32.ActiveCfg = Release|Win32 @@ -190,6 +232,30 @@ Global {CDC4AAA9-72E1-4FFA-A04D-7EF59D8B97CD}.Debug|Win32.Build.0 = Debug|Win32 {CDC4AAA9-72E1-4FFA-A04D-7EF59D8B97CD}.Release|Win32.ActiveCfg = Release|Win32 {CDC4AAA9-72E1-4FFA-A04D-7EF59D8B97CD}.Release|Win32.Build.0 = Release|Win32 + {4E6C2F8D-BA92-4C5B-96FD-72D4FE8BD7FA}.Debug|Win32.ActiveCfg = Debug|Win32 + {4E6C2F8D-BA92-4C5B-96FD-72D4FE8BD7FA}.Debug|Win32.Build.0 = Debug|Win32 + {4E6C2F8D-BA92-4C5B-96FD-72D4FE8BD7FA}.Release|Win32.ActiveCfg = Release|Win32 + {4E6C2F8D-BA92-4C5B-96FD-72D4FE8BD7FA}.Release|Win32.Build.0 = Release|Win32 + {6AEC2AA2-C9FF-4B7D-B07A-94A9D34B41D7}.Debug|Win32.ActiveCfg = Debug|Win32 + {6AEC2AA2-C9FF-4B7D-B07A-94A9D34B41D7}.Debug|Win32.Build.0 = Debug|Win32 + {6AEC2AA2-C9FF-4B7D-B07A-94A9D34B41D7}.Release|Win32.ActiveCfg = Release|Win32 + {6AEC2AA2-C9FF-4B7D-B07A-94A9D34B41D7}.Release|Win32.Build.0 = Release|Win32 + {2A29B6B1-AFC4-46C7-9944-7052AAE66F7B}.Debug|Win32.ActiveCfg = Debug|Win32 + {2A29B6B1-AFC4-46C7-9944-7052AAE66F7B}.Debug|Win32.Build.0 = Debug|Win32 + {2A29B6B1-AFC4-46C7-9944-7052AAE66F7B}.Release|Win32.ActiveCfg = Release|Win32 + {2A29B6B1-AFC4-46C7-9944-7052AAE66F7B}.Release|Win32.Build.0 = Release|Win32 + {853A396E-C031-4C26-A716-5B4E176BE11D}.Debug|Win32.ActiveCfg = Debug|Win32 + {853A396E-C031-4C26-A716-5B4E176BE11D}.Debug|Win32.Build.0 = Debug|Win32 + {853A396E-C031-4C26-A716-5B4E176BE11D}.Release|Win32.ActiveCfg = Release|Win32 + {853A396E-C031-4C26-A716-5B4E176BE11D}.Release|Win32.Build.0 = Release|Win32 + {4D53E40F-37E3-42B1-8848-F4C6F8313A17}.Debug|Win32.ActiveCfg = Debug|Win32 + {4D53E40F-37E3-42B1-8848-F4C6F8313A17}.Debug|Win32.Build.0 = Debug|Win32 + {4D53E40F-37E3-42B1-8848-F4C6F8313A17}.Release|Win32.ActiveCfg = Release|Win32 + {4D53E40F-37E3-42B1-8848-F4C6F8313A17}.Release|Win32.Build.0 = Release|Win32 + {E72B637E-4AA6-46F3-885F-AC67B4B470ED}.Debug|Win32.ActiveCfg = Debug|Win32 + {E72B637E-4AA6-46F3-885F-AC67B4B470ED}.Debug|Win32.Build.0 = Debug|Win32 + {E72B637E-4AA6-46F3-885F-AC67B4B470ED}.Release|Win32.ActiveCfg = Release|Win32 + {E72B637E-4AA6-46F3-885F-AC67B4B470ED}.Release|Win32.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/examples/Demo/CDemo.cpp b/examples/Demo/CDemo.cpp index 5ab0b470..d8249736 100644 --- a/examples/Demo/CDemo.cpp +++ b/examples/Demo/CDemo.cpp @@ -60,13 +60,13 @@ void CDemo::run() return; if (device->getFileSystem()->existFile("irrlicht.dat")) - device->getFileSystem()->addZipFileArchive("irrlicht.dat"); + device->getFileSystem()->addFileArchive("irrlicht.dat"); else - device->getFileSystem()->addZipFileArchive("../../media/irrlicht.dat"); + device->getFileSystem()->addFileArchive("../../media/irrlicht.dat"); if (device->getFileSystem()->existFile("map-20kdm2.pk3")) - device->getFileSystem()->addZipFileArchive("map-20kdm2.pk3"); + device->getFileSystem()->addFileArchive("map-20kdm2.pk3"); else - device->getFileSystem()->addZipFileArchive("../../media/map-20kdm2.pk3"); + device->getFileSystem()->addFileArchive("../../media/map-20kdm2.pk3"); video::IVideoDriver* driver = device->getVideoDriver(); scene::ISceneManager* smgr = device->getSceneManager(); @@ -77,12 +77,12 @@ void CDemo::run() // set ambient light smgr->setAmbientLight ( video::SColorf ( 0x00c0c0c0 ) ); - wchar_t tmp[255]; // draw everything s32 now = 0; + s32 lastfps = 0; sceneStartTime = device->getTimer()->getTime(); while(device->run() && driver) { @@ -106,23 +106,19 @@ void CDemo::run() smgr->drawAll(); guienv->drawAll(); - driver->endScene(); // write statistics - static s32 lastfps = 0; - s32 nowfps = driver->getFPS(); + const s32 nowfps = driver->getFPS(); - swprintf(tmp, 255, L"%ls fps:%3d triangles:%0.3f mio", - driver->getName(), - driver->getFPS(), - (f32) driver->getPrimitiveCountDrawn( 1 ) * ( 1.f / 1000000.f ) - ); + swprintf(tmp, 255, L"%ls fps:%3d triangles:%0.3f mio/s", + driver->getName(), driver->getFPS(), + driver->getPrimitiveCountDrawn(1) * (1.f / 1000000.f)); statusText->setText(tmp); if ( nowfps != lastfps ) { - device->setWindowCaption ( tmp ); + device->setWindowCaption(tmp); lastfps = nowfps; } } @@ -340,7 +336,6 @@ void CDemo::switchToNextScene() } sceneStartTime = device->getTimer()->getTime(); - } @@ -362,23 +357,20 @@ void CDemo::loadSceneData() //move all quake level meshes (non-realtime) core::matrix4 m; - m.setTranslation ( core::vector3df(-1300,-70,-1249) ); + m.setTranslation(core::vector3df(-1300,-70,-1249)); for ( i = 0; i!= scene::quake3::E_Q3_MESH_SIZE; ++i ) - { - sm->getMeshManipulator()->transformMesh ( quakeLevelMesh->getMesh(i), m ); - } + sm->getMeshManipulator()->transform(quakeLevelMesh->getMesh(i), m); - quakeLevelNode = sm->addOctTreeSceneNode( - quakeLevelMesh->getMesh( scene::quake3::E_Q3_MESH_GEOMETRY) - ); + quakeLevelNode = sm->addOctreeSceneNode( + quakeLevelMesh->getMesh( scene::quake3::E_Q3_MESH_GEOMETRY)); if (quakeLevelNode) { //quakeLevelNode->setPosition(core::vector3df(-1300,-70,-1249)); quakeLevelNode->setVisible(true); // create map triangle selector - mapSelector = sm->createOctTreeTriangleSelector(quakeLevelMesh->getMesh(0), + mapSelector = sm->createOctreeTriangleSelector(quakeLevelMesh->getMesh(0), quakeLevelNode, 128); // if not using shader and no gamma it's better to use more lighting, because @@ -410,7 +402,6 @@ void CDemo::loadSceneData() // Now add the MeshBuffer(s) with the current Shader to the Manager sm->addQuake3SceneNode ( meshBuffer, shader ); } - } // load sydney model and create 2 instances @@ -427,9 +418,9 @@ void CDemo::loadSceneData() model1->setScale(core::vector3df(2,2,2)); model1->setMD2Animation(scene::EMAT_STAND); model1->setMaterialFlag(video::EMF_LIGHTING, false); + model1->setMaterialFlag(video::EMF_NORMALIZE_NORMALS, true); model1->setMaterialType(video::EMT_SPHERE_MAP); model1->addShadowVolumeSceneNode(); - model1->setAutomaticCulling ( scene::EAC_BOX ); } model2 = sm->addAnimatedMeshSceneNode(mesh); @@ -440,8 +431,8 @@ void CDemo::loadSceneData() model2->setMD2Animation(scene::EMAT_RUN); model2->setMaterialTexture(0, device->getVideoDriver()->getTexture("../../media/sydney.bmp")); model2->setMaterialFlag(video::EMF_LIGHTING, true); + model1->setMaterialFlag(video::EMF_NORMALIZE_NORMALS, true); model2->addShadowVolumeSceneNode(); - model2->setAutomaticCulling ( scene::EAC_BOX ); } } @@ -458,8 +449,6 @@ void CDemo::loadSceneData() driver->getTexture("../../media/irrlicht2_bk.jpg")); driver->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, true); - //driver->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, true); - // create walk-between-portals animation core::vector3df waypoint[2]; @@ -468,8 +457,8 @@ void CDemo::loadSceneData() if (model2) { - anim = device->getSceneManager()->createFlyStraightAnimator(waypoint[0], - waypoint[1], 2000, true); + anim = device->getSceneManager()->createFlyStraightAnimator( + waypoint[0], waypoint[1], 2000, true); model2->addAnimator(anim); anim->drop(); } @@ -533,7 +522,6 @@ void CDemo::loadSceneData() campFire->setPosition(core::vector3df(100,120,600)); campFire->setScale(core::vector3df(2,2,2)); - scene::IParticleEmitter* em = campFire->createBoxEmitter( core::aabbox3d(-7,0,-7,7,1,7), core::vector3df(0.0f,0.06f,0.0f), @@ -563,11 +551,9 @@ void CDemo::loadSceneData() if (music) startSound(); #endif - } - void CDemo::createLoadingScreen() { core::dimension2d size = device->getVideoDriver()->getScreenSize(); @@ -610,7 +596,6 @@ void CDemo::createLoadingScreen() } - void CDemo::shoot() { scene::ISceneManager* sm = device->getSceneManager(); @@ -701,7 +686,6 @@ void CDemo::shoot() } - void CDemo::createParticleImpacts() { u32 now = device->getTimer()->getTime(); @@ -765,7 +749,6 @@ void CDemo::createParticleImpacts() } - #ifdef USE_IRRKLANG void CDemo::startIrrKlang() { diff --git a/examples/Demo/Demo_vc9.vcproj b/examples/Demo/Demo_vc9.vcproj index 75af6034..e0052aae 100644 --- a/examples/Demo/Demo_vc9.vcproj +++ b/examples/Demo/Demo_vc9.vcproj @@ -1,7 +1,7 @@ -#include - -using namespace irr; - -#pragma comment(lib, "Irrlicht.lib") - - -int main() -{ - // let user select driver type - - video::E_DRIVER_TYPE driverType; - - printf("Please select the driver you want for this example:\n"\ - " (a) Direct3D 9.0c\n (b) Direct3D 8.1\n (c) OpenGL 1.5\n"\ - " (d) Software Renderer\n (e) Burning's Software Renderer\n"\ - " (f) NullDevice\n (otherKey) exit\n\n"); - - char i; - std::cin >> i; - - switch(i) - { - case 'a': driverType = video::EDT_DIRECT3D9;break; - case 'b': driverType = video::EDT_DIRECT3D8;break; - case 'c': driverType = video::EDT_OPENGL; break; - case 'd': driverType = video::EDT_OGLES1; break; - case 'e': driverType = video::EDT_BURNINGSVIDEO;break; - case 'f': driverType = video::EDT_NULL; break; - default: return 0; - } - - // create device - - IrrlichtDevice *device = - createDevice(driverType, core::dimension2d(640, 480), 16, false); - - if (device == 0) - return 1; // could not create selected driver. - - video::IVideoDriver* driver = device->getVideoDriver(); - scene::ISceneManager* smgr = device->getSceneManager(); - - - device->getFileSystem()->addZipFileArchive("../../media/map-20kdm2.pk3"); - - - scene::IAnimatedMesh* q3levelmesh = smgr->getMesh("20kdm2.bsp"); - scene::ISceneNode* q3node = 0; - - if (q3levelmesh) - q3node = smgr->addOctTreeSceneNode(q3levelmesh->getMesh(0)); - - /* - So far so good, we've loaded the quake 3 level like in tutorial 2. Now, here - comes something different: We create a triangle selector. A triangle selector - is a class which can fetch the triangles from scene nodes for doing different - things with them, for example collision detection. There are different triangle - selectors, and all can be created with the ISceneManager. In this example, - we create an OctTreeTriangleSelector, which optimizes the triangle output a l - little bit by reducing it like an octree. This is very useful for huge meshes - like quake 3 levels. - Afte we created the triangle selector, we attach it to the q3node. This is not - necessary, but in this way, we do not need to care for the selector, for example - dropping it after we do not need it anymore. - */ - - scene::ITriangleSelector* selector = 0; - - if (q3node) - { - q3node->setPosition(core::vector3df(-1350,-130,-1400)); - - selector = smgr->createOctTreeTriangleSelector( - q3levelmesh->getMesh(0), q3node, 128); - q3node->setTriangleSelector(selector); - selector->drop(); - } - - - /* - We add a first person shooter camera to the scene for being able to - move in the quake 3 level like in tutorial 2. But this, time, we add a - special animator to the camera: A Collision Response animator. This - thing modifies the scene node to which it is attached to in that way, - that it may no more move through walls and is affected by gravity. The - only thing we have to tell the animator is how the world looks like, - how big the scene node is, how gravity and so on. After the collision - response animator is attached to the camera, we do not have to do - anything more for collision detection, anything is done automaticly, - all other collision detection code below is for picking. And please - note another cool feature: The collsion response animator can be - attached also to all other scene nodes, not only to cameras. And it can - be mixed with other scene node animators. In this way, collision - detection and response in the Irrlicht engine is really, really easy. - Now we'll take a closer look on the parameters of - createCollisionResponseAnimator(). - The first parameter is the TriangleSelector, which specifies how the - world, against collision detection is done looks like. The second - parameter is the scene node, which is the object, which is affected by - collision detection, in our case it is the camera. The third defines - how big the object is, it is the radius of an ellipsoid. Try it out and - change the radius to smaller values, the camera will be able to move - closer to walls after this. The next parameter is the direction and - speed of gravity. You could set it to (0,0,0) to disable gravity. And - the last value is just a translation: Without this, the ellipsoid with - which collision detection is done would be around the camera, and the - camera would be in the middle of the ellipsoid. But as human beings, we - are used to have our eyes on top of the body, with which we collide - with our world, not in the middle of it. So we place the scene node 50 - units over the center of the ellipsoid with this parameter. And that's - it, collision detection works now. - */ - - scene::ICameraSceneNode* camera = - smgr->addCameraSceneNodeFPS(0, 100.0f, 300.0f, -1, 0, 0, true); - camera->setPosition(core::vector3df(-100,50,-150)); - - scene::ISceneNodeAnimator* anim = smgr->createCollisionResponseAnimator( - selector, camera, core::vector3df(30,50,30), - core::vector3df(0,-3,0), - core::vector3df(0,50,0)); - camera->addAnimator(anim); - anim->drop(); - - /* - Because collision detection is no big deal in irrlicht, I'll describe how to - do two different types of picking in the next section. But before this, - I'll prepare the scene a little. I need three animated characters which we - could pick later, a dynamic light for lighting them, - a billboard for drawing where we found an intersection, and, yes, I need to - get rid of this mouse cursor. :) - */ - - // disable mouse cursor - - device->getCursorControl()->setVisible(false); - - // add billboard - - scene::IBillboardSceneNode * bill = smgr->addBillboardSceneNode(); - bill->setMaterialType(video::EMT_TRANSPARENT_ADD_COLOR ); - bill->setMaterialTexture(0, driver->getTexture("../../media/particle.bmp")); - bill->setMaterialFlag(video::EMF_LIGHTING, false); - bill->setMaterialFlag(video::EMF_ZBUFFER, false); - bill->setSize(core::dimension2d(20.0f, 20.0f)); - - // add 3 animated faeries. - - video::SMaterial material; - material.Textures[0] = driver->getTexture("../../media/faerie2.bmp"); - material.Lighting = true; - - scene::IAnimatedMeshSceneNode* node = 0; - scene::IAnimatedMesh* faerie = smgr->getMesh("../../media/faerie.md2"); - - if (faerie) - { - node = smgr->addAnimatedMeshSceneNode(faerie); - node->setPosition(core::vector3df(-70,0,-90)); - node->setMD2Animation(scene::EMAT_RUN); - node->getMaterial(0) = material; - - node = smgr->addAnimatedMeshSceneNode(faerie); - node->setPosition(core::vector3df(-70,0,-30)); - node->setMD2Animation(scene::EMAT_SALUTE); - node->getMaterial(0) = material; - - node = smgr->addAnimatedMeshSceneNode(faerie); - node->setPosition(core::vector3df(-70,0,-60)); - node->setMD2Animation(scene::EMAT_JUMP); - node->getMaterial(0) = material; - } - - material.Textures[0] = 0; - material.Lighting = false; - - // Add a light - - smgr->addLightSceneNode(0, core::vector3df(-60,100,400), - video::SColorf(1.0f,1.0f,1.0f,1.0f), - 600.0f); - - - /* - For not making it to complicated, I'm doing picking inside the drawing loop. - We take two pointers for storing the current and the last selected scene node and - start the loop. - */ - - - scene::ISceneNode* selectedSceneNode = 0; - scene::ISceneNode* lastSelectedSceneNode = 0; - - - int lastFPS = -1; - - while(device->run()) - if (device->isWindowActive()) - { - driver->beginScene(true, true, 0); - - smgr->drawAll(); - - /* - After we've drawn the whole scene whit smgr->drawAll(), we'll - do the first picking: We want to know which triangle of the - world we are looking at. In addition, we want the exact point - of the quake 3 level we are looking at. For this, we create a - 3d line starting at the position of the camera and going - through the lookAt-target of it. Then we ask the collision - manager if this line collides with a triangle of the world - stored in the triangle selector. If yes, we draw the 3d - triangle and set the position of the billboard to the - intersection point. - */ - - core::line3d line; - line.start = camera->getPosition(); - line.end = line.start + (camera->getTarget() - line.start).normalize() * 1000.0f; - - core::vector3df intersection; - core::triangle3df tri; - - if (smgr->getSceneCollisionManager()->getCollisionPoint( - line, selector, intersection, tri)) - { - bill->setPosition(intersection); - - driver->setTransform(video::ETS_WORLD, core::matrix4()); - driver->setMaterial(material); - driver->draw3DTriangle(tri, video::SColor(0,255,0,0)); - } - - - /* - Another type of picking supported by the Irrlicht Engine is scene node picking - based on bouding boxes. Every scene node has got a bounding box, and because of - that, it's very fast for example to get the scene node which the camera looks - at. Again, we ask the collision manager for this, and if we've got a scene node, - we highlight it by disabling Lighting in its material, if it is not the - billboard or the quake 3 level. - */ - - selectedSceneNode = - smgr->getSceneCollisionManager()->getSceneNodeFromCameraBB(camera); - - if (lastSelectedSceneNode) - lastSelectedSceneNode->setMaterialFlag(video::EMF_LIGHTING, true); - - if (selectedSceneNode == q3node || selectedSceneNode == bill) - selectedSceneNode = 0; - - if (selectedSceneNode) - selectedSceneNode->setMaterialFlag(video::EMF_LIGHTING, false); - - lastSelectedSceneNode = selectedSceneNode; - - - /* - That's it, we just have to finish drawing. - */ - - driver->endScene(); - - int fps = driver->getFPS(); - - if (lastFPS != fps) - { - core::stringw str = - L"Collision detection example - Irrlicht Engine ["; - str += driver->getName(); - str += "] FPS:"; - str += fps; - - device->setWindowCaption(str.c_str()); - lastFPS = fps; - } - } - - device->drop(); - - return 0; -} - diff --git a/examples/buildAllExamples.sh b/examples/buildAllExamples.sh index 992ffa10..272a3291 100755 --- a/examples/buildAllExamples.sh +++ b/examples/buildAllExamples.sh @@ -1,7 +1,7 @@ #! /bin/bash [ -z $1 ] || TARGET=$1 [ -z $TARGET ] && TARGET=all -for i in [01]* Demo; do +for i in [012]* Demo; do echo "Building $i"; pushd $i && make clean $TARGET; popd; diff --git a/include/EAttributes.h b/include/EAttributes.h new file mode 100644 index 00000000..023ccf1a --- /dev/null +++ b/include/EAttributes.h @@ -0,0 +1,98 @@ +// Copyright (C) 2002-2009 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#ifndef __E_ATTRIBUTES_H_INCLUDED__ +#define __E_ATTRIBUTES_H_INCLUDED__ + +namespace irr +{ +namespace io +{ + +//! Types of attributes available for IAttributes +enum E_ATTRIBUTE_TYPE +{ + // integer attribute + EAT_INT = 0, + + // float attribute + EAT_FLOAT, + + // string attribute + EAT_STRING, + + // boolean attribute + EAT_BOOL, + + // enumeration attribute + EAT_ENUM, + + // color attribute + EAT_COLOR, + + // floating point color attribute + EAT_COLORF, + + // 3d vector attribute + EAT_VECTOR3D, + + // 2d position attribute + EAT_POSITION2D, + + // vector 2d + EAT_VECTOR2D, + + // rectangle attribute + EAT_RECT, + + // matrix attribute + EAT_MATRIX, + + // quaternion attribute + EAT_QUATERNION, + + // 3d bounding box + EAT_BBOX, + + // plane + EAT_PLANE, + + // 3d triangle + EAT_TRIANGLE3D, + + // line 2d + EAT_LINE2D, + + // line 3d + EAT_LINE3D, + + // array of stringws attribute + EAT_STRINGWARRAY, + + // array of float + EAT_FLOATARRAY, + + // array of int + EAT_INTARRAY, + + // binary data attribute + EAT_BINARY, + + // texture reference attribute + EAT_TEXTURE, + + // user pointer void* + EAT_USER_POINTER, + + // known attribute type count + EAT_COUNT, + + // unknown attribute + EAT_UNKNOWN +}; + +} // end namespace io +} // end namespace irr + +#endif diff --git a/include/EDeviceTypes.h b/include/EDeviceTypes.h index d9230d99..249906ac 100644 --- a/include/EDeviceTypes.h +++ b/include/EDeviceTypes.h @@ -34,6 +34,12 @@ namespace irr in by defining the IRR_USE_SDL_DEVICE macro in IrrCompileConfig.h */ EIDT_SDL, + //! A device for raw framebuffer access + /** Best used with embedded devices and mobile systems. + Does not need X11 or other graphical subsystems. + May support hw-acceleration via OpenGL-ES for FBDirect */ + EIDT_FRAMEBUFFER, + //! A simple text only device supported by all platforms. /** This device allows applications to run from the command line without opening a window. It can render the output of the software drivers to the console as ASCII. It only supports diff --git a/include/EGUIElementTypes.h b/include/EGUIElementTypes.h index 48901795..c47eadbe 100644 --- a/include/EGUIElementTypes.h +++ b/include/EGUIElementTypes.h @@ -85,12 +85,12 @@ enum EGUI_ELEMENT_TYPE //! A window EGUIET_WINDOW, - //! Not an element, amount of elements in there - EGUIET_COUNT, - //! Unknown type. EGUIET_ELEMENT, + //! Not an element, amount of elements in there + EGUIET_COUNT, + //! This enum is never used, it only forces the compiler to compile this enumeration to 32 bit. EGUIET_FORCE_32_BIT = 0x7fffffff @@ -122,6 +122,7 @@ const c8* const GUIElementTypeNames[] = "toolBar", "treeview", "window", + "element", 0 }; diff --git a/include/EPrimitiveTypes.h b/include/EPrimitiveTypes.h new file mode 100644 index 00000000..2d105300 --- /dev/null +++ b/include/EPrimitiveTypes.h @@ -0,0 +1,56 @@ +// Copyright (C) 2002-2009 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#ifndef __E_PRIMITIVE_TYPES_H_INCLUDED__ +#define __E_PRIMITIVE_TYPES_H_INCLUDED__ + +namespace irr +{ +namespace scene +{ + + //! Enumeration for all primitive types there are. + enum E_PRIMITIVE_TYPE + { + //! All vertices are non-connected points. + EPT_POINTS=0, + + //! All vertices form a single connected line. + EPT_LINE_STRIP, + + //! Just as LINE_STRIP, but the last and the first vertex is also connected. + EPT_LINE_LOOP, + + //! Every two vertices are connected creating n/2 lines. + EPT_LINES, + + //! After the first two vertices each vertex defines a new triangle. + //! Always the two last and the new one form a new triangle. + EPT_TRIANGLE_STRIP, + + //! After the first two vertices each vertex defines a new triangle. + //! All around the common first vertex. + EPT_TRIANGLE_FAN, + + //! Explicitly set all vertices for each triangle. + EPT_TRIANGLES, + + //! After the first two vertices each further tw vetices create a quad with the preceding two. + EPT_QUAD_STRIP, + + //! Every four vertices create a quad. + EPT_QUADS, + + //! Just as LINE_LOOP, but filled. + EPT_POLYGON, + + //! The single vertices are expanded to quad billboards on the GPU. + EPT_POINT_SPRITES + }; + +} // end namespace scene +} // end namespace irr + +#endif + diff --git a/include/ESceneNodeTypes.h b/include/ESceneNodeTypes.h index 0a36bc92..ee5c2a6d 100644 --- a/include/ESceneNodeTypes.h +++ b/include/ESceneNodeTypes.h @@ -42,8 +42,8 @@ namespace scene //! Shadow Volume Scene Node ESNT_SHADOW_VOLUME = MAKE_IRR_ID('s','h','d','w'), - //! OctTree Scene Node - ESNT_OCT_TREE = MAKE_IRR_ID('o','c','t','t'), + //! Octree Scene Node + ESNT_OCTREE = MAKE_IRR_ID('o','c','t','r'), //! Mesh Scene Node ESNT_MESH = MAKE_IRR_ID('m','e','s','h'), diff --git a/include/EShaderTypes.h b/include/EShaderTypes.h new file mode 100644 index 00000000..691930c9 --- /dev/null +++ b/include/EShaderTypes.h @@ -0,0 +1,90 @@ +#ifndef __E_SHADER_TYPES_H_INCLUDED__ +#define __E_SHADER_TYPES_H_INCLUDED__ + +#include "irrTypes.h" + +namespace irr +{ +namespace video +{ + +//! Compile target enumeration for the addHighLevelShaderMaterial() method. +enum E_VERTEX_SHADER_TYPE +{ + EVST_VS_1_1 = 0, + EVST_VS_2_0, + EVST_VS_2_a, + EVST_VS_3_0, + EVST_VS_4_0, + EVST_VS_4_1, + EVST_VS_5_0, + + //! This is not a type, but a value indicating how much types there are. + EVST_COUNT +}; + +//! Names for all vertex shader types, each entry corresponds to a E_VERTEX_SHADER_TYPE entry. +const c8* const VERTEX_SHADER_TYPE_NAMES[] = { + "vs_1_1", + "vs_2_0", + "vs_2_a", + "vs_3_0", + "vs_4_0", + "vs_4_1", + "vs_5_0", + 0 }; + +//! Compile target enumeration for the addHighLevelShaderMaterial() method. +enum E_PIXEL_SHADER_TYPE +{ + EPST_PS_1_1 = 0, + EPST_PS_1_2, + EPST_PS_1_3, + EPST_PS_1_4, + EPST_PS_2_0, + EPST_PS_2_a, + EPST_PS_2_b, + EPST_PS_3_0, + EPST_PS_4_0, + EPST_PS_4_1, + EPST_PS_5_0, + + //! This is not a type, but a value indicating how much types there are. + EPST_COUNT +}; + +//! Names for all pixel shader types, each entry corresponds to a E_PIXEL_SHADER_TYPE entry. +const c8* const PIXEL_SHADER_TYPE_NAMES[] = { + "ps_1_1", + "ps_1_2", + "ps_1_3", + "ps_1_4", + "ps_2_0", + "ps_2_a", + "ps_2_b", + "ps_3_0", + "ps_4_0", + "ps_4_1", + "ps_5_0", + 0 }; + +//! Enum for supported geometry shader types +enum E_GEOMETRY_SHADER_TYPE +{ + EGST_GS_4_0 = 0, + + //! This is not a type, but a value indicating how much types there are. + EGST_COUNT +}; + +//! String names for supported geometry shader types +const c8* const GEOMETRY_SHADER_TYPE_NAMES[] = { + "gs_4_0", + 0 }; + + +} // end namespace video +} // end namespace irr + +#endif // __E_SHADER_TYPES_H_INCLUDED__ + diff --git a/include/IAnimatedMeshSceneNode.h b/include/IAnimatedMeshSceneNode.h index d942e035..94c79299 100644 --- a/include/IAnimatedMeshSceneNode.h +++ b/include/IAnimatedMeshSceneNode.h @@ -25,10 +25,7 @@ namespace scene EJUOR_READ, //! control joint positions in the mesh (eg. ragdolls, or set the animation from animateJoints() ) - EJUOR_CONTROL, - - //! count of all available interpolation modes - EJUOR_COUNT + EJUOR_CONTROL }; diff --git a/include/IAttributes.h b/include/IAttributes.h index b0a616fb..3db84e97 100644 --- a/include/IAttributes.h +++ b/include/IAttributes.h @@ -23,6 +23,7 @@ #include "irrString.h" #include "irrArray.h" #include "IXMLReader.h" +#include "EAttributes.h" namespace irr { @@ -34,88 +35,6 @@ namespace io { class IXMLWriter; -//! Types of attributes available for IAttributes -enum E_ATTRIBUTE_TYPE -{ - // integer attribute - EAT_INT = 0, - - // float attribute - EAT_FLOAT, - - // string attribute - EAT_STRING, - - // boolean attribute - EAT_BOOL, - - // enumeration attribute - EAT_ENUM, - - // color attribute - EAT_COLOR, - - // floating point color attribute - EAT_COLORF, - - // 3d vector attribute - EAT_VECTOR3D, - - // 2d position attribute - EAT_POSITION2D, - - // vector 2d - EAT_VECTOR2D, - - // rectangle attribute - EAT_RECT, - - // matrix attribute - EAT_MATRIX, - - // quaternion attribute - EAT_QUATERNION, - - // 3d bounding box - EAT_BBOX, - - // plane - EAT_PLANE, - - // 3d triangle - EAT_TRIANGLE3D, - - // line 2d - EAT_LINE2D, - - // line 3d - EAT_LINE3D, - - // array of stringws attribute - EAT_STRINGWARRAY, - - // array of float - EAT_FLOATARRAY, - - // array of int - EAT_INTARRAY, - - // binary data attribute - EAT_BINARY, - - // texture reference attribute - EAT_TEXTURE, - - // user pointer void* - EAT_USER_POINTER, - - // known attribute type count - EAT_COUNT, - - // unknown attribute - EAT_UNKNOWN -}; - //! Provides a generic interface for attributes and their values and the possiblity to serialize them class IAttributes : public virtual IReferenceCounted { @@ -315,12 +234,12 @@ public: */ //! Adds an attribute as wide string array - virtual void addArray(const c8* attributeName, core::array value) = 0; + virtual void addArray(const c8* attributeName, const core::array& value) = 0; //! Sets an attribute value as a wide string array. //! \param attributeName: Name for the attribute //! \param value: Value for the attribute. Set this to 0 to delete the attribute - virtual void setAttribute(const c8* attributeName, const core::array value) = 0; + virtual void setAttribute(const c8* attributeName, const core::array& value) = 0; //! Gets an attribute as an array of wide strings. //! \param attributeName: Name of the attribute to get. @@ -333,7 +252,7 @@ public: virtual core::array getAttributeAsArray(s32 index) = 0; //! Sets an attribute as an array of wide strings - virtual void setAttribute(s32 index, core::array value) = 0; + virtual void setAttribute(s32 index, const core::array& value) = 0; /* diff --git a/include/IEventReceiver.h b/include/IEventReceiver.h index 7c9e139f..ee8bb733 100644 --- a/include/IEventReceiver.h +++ b/include/IEventReceiver.h @@ -99,13 +99,29 @@ namespace irr //! in what direction and how fast. EMIE_MOUSE_WHEEL, - //! Mouse double click. + //! Left mouse button double click. //! This event is generated after the second EMIE_LMOUSE_PRESSED_DOWN event. - EMIE_MOUSE_DOUBLE_CLICK, + EMIE_LMOUSE_DOUBLE_CLICK, - //! Mouse triple click. + //! Right mouse button double click. + //! This event is generated after the second EMIE_RMOUSE_PRESSED_DOWN event. + EMIE_RMOUSE_DOUBLE_CLICK, + + //! Middle mouse button double click. + //! This event is generated after the second EMIE_MMOUSE_PRESSED_DOWN event. + EMIE_MMOUSE_DOUBLE_CLICK, + + //! Left mouse button triple click. //! This event is generated after the third EMIE_LMOUSE_PRESSED_DOWN event. - EMIE_MOUSE_TRIPLE_CLICK, + EMIE_LMOUSE_TRIPLE_CLICK, + + //! Right mouse button triple click. + //! This event is generated after the third EMIE_RMOUSE_PRESSED_DOWN event. + EMIE_RMOUSE_TRIPLE_CLICK, + + //! Middle mouse button triple click. + //! This event is generated after the third EMIE_MMOUSE_PRESSED_DOWN event. + EMIE_MMOUSE_TRIPLE_CLICK, //! No real event. Just for convenience to get number of events EMIE_COUNT @@ -415,7 +431,11 @@ public: virtual ~IEventReceiver() {} //! Called if an event happened. - /** \return True if the event was processed. */ + /** Please take care that you should only return 'true' when you want to _prevent_ Irrlicht + * from processing the event any further. So 'true' does mean that an event is completely done. + * Therefore your return value for all unprocessed events should be 'false'. + \return True if the event was processed. + */ virtual bool OnEvent(const SEvent& event) = 0; }; diff --git a/include/IFileArchive.h b/include/IFileArchive.h index 13103aef..673486d7 100644 --- a/include/IFileArchive.h +++ b/include/IFileArchive.h @@ -71,6 +71,13 @@ public: //! get the archive type virtual E_FILE_ARCHIVE_TYPE getType() const { return EFAT_UNKNOWN; } + + //! An optionally used password string + /** This variable is publicly accessible from the interface in order to + avoid single access patterns to this place, and hence allow some more + obscurity. + */ + core::stringc Password; }; //! Class which is able to create an archive from a file. diff --git a/include/IFileSystem.h b/include/IFileSystem.h index 8af22568..ed798c80 100644 --- a/include/IFileSystem.h +++ b/include/IFileSystem.h @@ -92,26 +92,32 @@ public: virtual IWriteFile* createAndWriteFile(const path& filename, bool append=false) =0; //! Adds an archive to the file system. - /** After calling this, the Irrlicht Engine will also search and open files directly from this archive. - This is useful for hiding data from the end user, speeding up file access and making it possible to - access for example Quake3 .pk3 files, which are no different than .zip files. - By default Irrlicht supports ZIP, PAK, TAR and directories as archives. You can provide your own archive - types by implementing IArchiveLoader and passing an instance to addArchiveLoader. + /** After calling this, the Irrlicht Engine will also search and open + files directly from this archive. This is useful for hiding data from + the end user, speeding up file access and making it possible to access + for example Quake3 .pk3 files, which are just renamed .zip files. By + default Irrlicht supports ZIP, PAK, TAR, PNK, and directories as + archives. You can provide your own archive types by implementing + IArchiveLoader and passing an instance to addArchiveLoader. \param filename: Filename of the archive to add to the file system. \param ignoreCase: If set to true, files in the archive can be accessed without writing all letters in the right case. \param ignorePaths: If set to true, files in the added archive can be accessed without its complete path. - \param archiveType: If no specific E_FILE_ARCHIVE_TYPE is selected then the type of archive will depend on - the extension of the file name. If you use a different extension then you can use this parameter to force + \param archiveType: If no specific E_FILE_ARCHIVE_TYPE is selected then + the type of archive will depend on the extension of the file name. If + you use a different extension then you can use this parameter to force a specific type of archive. + \param password An optional password, which is used in case of encrypted archives. \return Returns true if the archive was added successfully, false if not. */ - virtual bool addFileArchive(const path& filename, bool ignoreCase=true, bool ignorePaths=true, - E_FILE_ARCHIVE_TYPE archiveType=EFAT_UNKNOWN) =0; + virtual bool addFileArchive(const path& filename, bool ignoreCase=true, + bool ignorePaths=true, + E_FILE_ARCHIVE_TYPE archiveType=EFAT_UNKNOWN, + const core::stringc& password="") =0; //! Adds an external archive loader to the engine. - /** Use this function to add support for new archive types to the engine, for example propiatrary or - encyrpted file storage. */ + /** Use this function to add support for new archive types to the + engine, for example proprietary or encrypted file storage. */ virtual void addArchiveLoader(IArchiveLoader* loader) =0; //! Returns the number of archives currently attached to the file system @@ -141,9 +147,10 @@ public: //! Returns the archive at a given index. virtual IFileArchive* getFileArchive(u32 index) =0; - //! Adds a zip archive to the file system. Deprecated! This function is provided for compatibility - /** with older versions of Irrlicht and may be removed in future versions, you should use - addFileArchive instead. + //! Adds a zip archive to the file system. + /** \deprecated This function is provided for compatibility + with older versions of Irrlicht and may be removed in future versions, + you should use addFileArchive instead. After calling this, the Irrlicht Engine will search and open files directly from this archive too. This is useful for hiding data from the end user, speeding up file access and making it possible to access for example Quake3 .pk3 files, which are no different than .zip files. @@ -159,8 +166,9 @@ public: } //! Adds an unzipped archive (or basedirectory with subdirectories..) to the file system. - /** Deprecated! This function is provided for compatibility with older versions of Irrlicht - and may be removed in future versions, you should use addFileArchive instead. + /** \deprecated This function is provided for compatibility + with older versions of Irrlicht and may be removed in future versions, + you should use addFileArchive instead. Useful for handling data which will be in a zip file \param filename: Filename of the unzipped zip archive base directory to add to the file system. \param ignoreCase: If set to true, files in the archive can be accessed without @@ -174,8 +182,9 @@ public: } //! Adds a pak archive to the file system. - /** Deprecated! This function is provided for compatibility with older versions of Irrlicht - and may be removed in future versions, you should use addFileArchive instead. + /** \deprecated This function is provided for compatibility + with older versions of Irrlicht and may be removed in future versions, + you should use addFileArchive instead. After calling this, the Irrlicht Engine will search and open files directly from this archive too. This is useful for hiding data from the end user, speeding up file access and making it possible to access for example Quake2/KingPin/Hexen2 .pak files diff --git a/include/IGPUProgrammingServices.h b/include/IGPUProgrammingServices.h index 42a574ce..c1046f8c 100644 --- a/include/IGPUProgrammingServices.h +++ b/include/IGPUProgrammingServices.h @@ -5,8 +5,9 @@ #ifndef __I_GPU_PROGRAMMING_SERVICES_H_INCLUDED__ #define __I_GPU_PROGRAMMING_SERVICES_H_INCLUDED__ -#include "IReferenceCounted.h" -#include "SMaterial.h" +#include "EShaderTypes.h" +#include "EMaterialTypes.h" +#include "EPrimitiveTypes.h" #include "path.h" namespace irr @@ -23,54 +24,6 @@ namespace video class IVideoDriver; class IShaderConstantSetCallBack; -//! Compile target enumeration for the addHighLevelShaderMaterial() method. -enum E_VERTEX_SHADER_TYPE -{ - EVST_VS_1_1 = 0, - EVST_VS_2_0, - EVST_VS_2_a, - EVST_VS_3_0, - - //! This is not a type, but a value indicating how much types there are. - EVST_COUNT -}; - -//! Names for all vertex shader types, each entry corresponds to a E_VERTEX_SHADER_TYPE entry. -const c8* const VERTEX_SHADER_TYPE_NAMES[] = { - "vs_1_1", - "vs_2_0", - "vs_2_a", - "vs_3_0", - 0 }; - -//! Compile target enumeration for the addHighLevelShaderMaterial() method. -enum E_PIXEL_SHADER_TYPE -{ - EPST_PS_1_1 = 0, - EPST_PS_1_2, - EPST_PS_1_3, - EPST_PS_1_4, - EPST_PS_2_0, - EPST_PS_2_a, - EPST_PS_2_b, - EPST_PS_3_0, - - //! This is not a type, but a value indicating how much types there are. - EPST_COUNT -}; - -//! Names for all pixel shader types, each entry corresponds to a E_PIXEL_SHADER_TYPE entry. -const c8* const PIXEL_SHADER_TYPE_NAMES[] = { - "ps_1_1", - "ps_1_2", - "ps_1_3", - "ps_1_4", - "ps_2_0", - "ps_2_a", - "ps_2_b", - "ps_3_0", - 0 }; - //! Interface making it possible to create and use programs running on the GPU. class IGPUProgrammingServices { @@ -85,17 +38,29 @@ public: shader program. This can be 0 if no vertex program shall be used. \param vertexShaderEntryPointName: Name of the entry function of the vertexShaderProgram - \param vsCompileTarget: Vertex shader version where the high level - shader shall be compiled to. + \param vsCompileTarget: Vertex shader version the high level shader + shall be compiled to. \param pixelShaderProgram: String containing the source of the pixel shader program. This can be 0 if no pixel shader shall be used. \param pixelShaderEntryPointName: Entry name of the function of the pixelShaderEntryPointName - \param psCompileTarget: Pixel shader version where the high level - shader shall be compiled to. + \param psCompileTarget: Pixel shader version the high level shader + shall be compiled to. + \param geometryShaderProgram: String containing the source of the + geometry shader program. This can be 0 if no geometry shader shall be + used. + \param geometryShaderEntryPointName: Entry name of the function of the + geometryShaderEntryPointName + \param gsCompileTarget: Geometry shader version the high level shader + shall be compiled to. + \param inType Type of vertices passed to geometry shader + \param outType Type of vertices created by geometry shader + \param verticesOut Maximal number of vertices created by geometry + shader. If 0, maximal number supported is assumed. \param callback: Pointer to an implementation of - IShaderConstantSetCallBack in which you can set the needed vertex and - pixel shader program constants. Set this to 0 if you don't need this. + IShaderConstantSetCallBack in which you can set the needed vertex, + pixel, and geometry shader program constants. Set this to 0 if you + don't need this. \param baseMaterial: Base material which renderstates will be used to shade the material. \param userData: a user data int. This int can be set to any value and @@ -103,13 +68,30 @@ public: OnSetConstants(). In this way it is easily possible to use the same callback method for multiple materials and distinguish between them during the call. - \return Returns the number of the material type which can be set in - SMaterial::MaterialType to use the renderer. -1 is returned if an - error occured, e.g. if a vertex or pixel shader program could not be - compiled or a compile target is not reachable. The error strings are - then printed to the error log and can be catched with a custom event - receiver. */ + \return Number of the material type which can be set in + SMaterial::MaterialType to use the renderer. -1 is returned if an error + occured, e.g. if a shader program could not be compiled or a compile + target is not reachable. The error strings are then printed to the + error log and can be catched with a custom event receiver. */ virtual s32 addHighLevelShaderMaterial( + const c8* vertexShaderProgram, + const c8* vertexShaderEntryPointName = "main", + E_VERTEX_SHADER_TYPE vsCompileTarget = EVST_VS_1_1, + const c8* pixelShaderProgram = 0, + const c8* pixelShaderEntryPointName = "main", + E_PIXEL_SHADER_TYPE psCompileTarget = EPST_PS_1_1, + const c8* geometryShaderProgram = 0, + const c8* geometryShaderEntryPointName = "main", + E_GEOMETRY_SHADER_TYPE gsCompileTarget = EGST_GS_4_0, + scene::E_PRIMITIVE_TYPE inType = scene::EPT_TRIANGLES, + scene::E_PRIMITIVE_TYPE outType = scene::EPT_TRIANGLE_STRIP, + u32 verticesOut = 0, + IShaderConstantSetCallBack* callback = 0, + E_MATERIAL_TYPE baseMaterial = video::EMT_SOLID, + s32 userData = 0 ) = 0; + + //! convenience function for use without geometry shaders + s32 addHighLevelShaderMaterial( const c8* vertexShaderProgram, const c8* vertexShaderEntryPointName = "main", E_VERTEX_SHADER_TYPE vsCompileTarget = EVST_VS_1_1, @@ -118,31 +100,47 @@ public: E_PIXEL_SHADER_TYPE psCompileTarget = EPST_PS_1_1, IShaderConstantSetCallBack* callback = 0, E_MATERIAL_TYPE baseMaterial = video::EMT_SOLID, - s32 userData = 0 ) = 0; + s32 userData = 0 ) + { + return addHighLevelShaderMaterial( + vertexShaderProgram, vertexShaderEntryPointName, + vsCompileTarget, pixelShaderProgram, + pixelShaderEntryPointName, psCompileTarget, + 0, "main", EGST_GS_4_0, + scene::EPT_TRIANGLES, scene::EPT_TRIANGLE_STRIP, 0, + callback, baseMaterial, userData); + } //! Like IGPUProgrammingServices::addShaderMaterial(), but loads from files. - /** \param vertexShaderProgram: Text file containing the source of the - * vertex shader program. - Set to 0 if no shader shall be created. + /** \param vertexShaderProgramFileName: Text file containing the source + of the vertex shader program. Set to empty string if no vertex shader + shall be created. \param vertexShaderEntryPointName: Name of the entry function of the vertexShaderProgram - \param vsCompileTarget: Vertex shader version where the high level - shader shall be compiled to. - \param pixelShaderProgram: Text file containing the source of the pixel - shader program. Set to 0 if no shader shall be created. - \param vertexShaderEntryPointName: Name of the entry function of the - vertexShaderProgram - \param vsCompileTarget: Vertex shader version where the high level - shader shall be compiled to. - \param pixelShaderProgram: String containing the source of the pixel - shader program. This can be 0 if no pixel shader shall be used. + \param vsCompileTarget: Vertex shader version the high level shader + shall be compiled to. + \param pixelShaderProgramFileName: Text file containing the source of + the pixel shader program. Set to empty string if no pixel shader shall + be created. \param pixelShaderEntryPointName: Entry name of the function of the pixelShaderEntryPointName - \param psCompileTarget: Pixel shader version where the high level - shader shall be compiled to. + \param psCompileTarget: Pixel shader version the high level shader + shall be compiled to. + \param geometryShaderProgramFileName: String containing the source of + the geometry shader program. Set to empty string if no geometry shader + shall be created. + \param geometryShaderEntryPointName: Entry name of the function of the + geometryShaderEntryPointName + \param gsCompileTarget: Geometry shader version the high level shader + shall be compiled to. + \param inType Type of vertices passed to geometry shader + \param outType Type of vertices created by geometry shader + \param verticesOut Maximal number of vertices created by geometry + shader. If 0, maximal number supported is assumed. \param callback: Pointer to an implementation of - IShaderConstantSetCallBack in which you can set the needed vertex and - pixel shader program constants. Set this to 0 if you don't need this. + IShaderConstantSetCallBack in which you can set the needed vertex, + pixel, and geometry shader program constants. Set this to 0 if you + don't need this. \param baseMaterial: Base material which renderstates will be used to shade the material. \param userData: a user data int. This int can be set to any value and @@ -150,13 +148,30 @@ public: OnSetConstants(). In this way it is easily possible to use the same callback method for multiple materials and distinguish between them during the call. - \return Returns the number of the material type which can be set in - SMaterial::MaterialType to use the renderer. -1 is returned if an - error occured, e.g. if a vertex or pixel shader program could not be - compiled or a compile target is not reachable. The error strings are - then printed to the error log and can be catched with a custom event - receiver. */ + \return Number of the material type which can be set in + SMaterial::MaterialType to use the renderer. -1 is returned if an error + occured, e.g. if a shader program could not be compiled or a compile + target is not reachable. The error strings are then printed to the + error log and can be catched with a custom event receiver. */ virtual s32 addHighLevelShaderMaterialFromFiles( + const io::path& vertexShaderProgramFileName, + const c8* vertexShaderEntryPointName = "main", + E_VERTEX_SHADER_TYPE vsCompileTarget = EVST_VS_1_1, + const io::path& pixelShaderProgramFileName = "", + const c8* pixelShaderEntryPointName = "main", + E_PIXEL_SHADER_TYPE psCompileTarget = EPST_PS_1_1, + const io::path& geometryShaderProgramFileName="", + const c8* geometryShaderEntryPointName = "main", + E_GEOMETRY_SHADER_TYPE gsCompileTarget = EGST_GS_4_0, + scene::E_PRIMITIVE_TYPE inType = scene::EPT_TRIANGLES, + scene::E_PRIMITIVE_TYPE outType = scene::EPT_TRIANGLE_STRIP, + u32 verticesOut = 0, + IShaderConstantSetCallBack* callback = 0, + E_MATERIAL_TYPE baseMaterial = video::EMT_SOLID, + s32 userData = 0) = 0; + + //! convenience function for use without geometry shaders + s32 addHighLevelShaderMaterialFromFiles( const io::path& vertexShaderProgramFileName, const c8* vertexShaderEntryPointName = "main", E_VERTEX_SHADER_TYPE vsCompileTarget = EVST_VS_1_1, @@ -165,25 +180,42 @@ public: E_PIXEL_SHADER_TYPE psCompileTarget = EPST_PS_1_1, IShaderConstantSetCallBack* callback = 0, E_MATERIAL_TYPE baseMaterial = video::EMT_SOLID, - s32 userData = 0) = 0; - + s32 userData = 0) + { + return addHighLevelShaderMaterialFromFiles( + vertexShaderProgramFileName, vertexShaderEntryPointName, + vsCompileTarget, pixelShaderProgramFileName, + pixelShaderEntryPointName, psCompileTarget, + "", "main", EGST_GS_4_0, + scene::EPT_TRIANGLES, scene::EPT_TRIANGLE_STRIP, 0, + callback, baseMaterial, userData); + } //! Like IGPUProgrammingServices::addShaderMaterial(), but loads from files. /** \param vertexShaderProgram: Text file handle containing the source - * of the vertex shader program. - Set to 0 if no shader shall be created. + of the vertex shader program. Set to 0 if no vertex shader shall be + created. \param vertexShaderEntryPointName: Name of the entry function of the vertexShaderProgram - \param vsCompileTarget: Vertex shader version where the high level - shader shall be compiled to. - \param pixelShaderProgram: Text file containing the source of the pixel - shader program. Set to + \param vsCompileTarget: Vertex shader version the high level shader + shall be compiled to. \param pixelShaderProgram: Text file handle containing the source of - the pixel shader program. Set to 0 if no shader shall be created. + the pixel shader program. Set to 0 if no pixel shader shall be created. \param pixelShaderEntryPointName: Entry name of the function of the pixelShaderEntryPointName - \param psCompileTarget: Pixel shader version where the high level - shader shall be compiled to. + \param psCompileTarget: Pixel shader version the high level shader + shall be compiled to. + \param geometryShaderProgram: Text file handle containing the source of + the geometry shader program. Set to 0 if no geometry shader shall be + created. + \param geometryShaderEntryPointName: Entry name of the function of the + geometryShaderEntryPointName + \param gsCompileTarget: Geometry shader version the high level shader + shall be compiled to. + \param inType Type of vertices passed to geometry shader + \param outType Type of vertices created by geometry shader + \param verticesOut Maximal number of vertices created by geometry + shader. If 0, maximal number supported is assumed. \param callback: Pointer to an implementation of IShaderConstantSetCallBack in which you can set the needed vertex and pixel shader program constants. Set this to 0 if you don't need this. @@ -194,13 +226,30 @@ public: OnSetConstants(). In this way it is easily possible to use the same callback method for multiple materials and distinguish between them during the call. - \return Returns the number of the material type which can be set in + \return Number of the material type which can be set in SMaterial::MaterialType to use the renderer. -1 is returned if an - error occured, e.g. if a vertex or pixel shader program could not be - compiled or a compile target is not reachable. The error strings are - then printed to the error log and can be catched with a custom event - receiver. */ + error occured, e.g. if a shader program could not be compiled or a + compile target is not reachable. The error strings are then printed to + the error log and can be catched with a custom event receiver. */ virtual s32 addHighLevelShaderMaterialFromFiles( + io::IReadFile* vertexShaderProgram, + const c8* vertexShaderEntryPointName = "main", + E_VERTEX_SHADER_TYPE vsCompileTarget = EVST_VS_1_1, + io::IReadFile* pixelShaderProgram = 0, + const c8* pixelShaderEntryPointName = "main", + E_PIXEL_SHADER_TYPE psCompileTarget = EPST_PS_1_1, + io::IReadFile* geometryShaderProgram = 0, + const c8* geometryShaderEntryPointName = "main", + E_GEOMETRY_SHADER_TYPE gsCompileTarget = EGST_GS_4_0, + scene::E_PRIMITIVE_TYPE inType = scene::EPT_TRIANGLES, + scene::E_PRIMITIVE_TYPE outType = scene::EPT_TRIANGLE_STRIP, + u32 verticesOut = 0, + IShaderConstantSetCallBack* callback = 0, + E_MATERIAL_TYPE baseMaterial = video::EMT_SOLID, + s32 userData = 0) = 0; + + //! convenience function for use without geometry shaders + s32 addHighLevelShaderMaterialFromFiles( io::IReadFile* vertexShaderProgram, const c8* vertexShaderEntryPointName = "main", E_VERTEX_SHADER_TYPE vsCompileTarget = EVST_VS_1_1, @@ -209,7 +258,16 @@ public: E_PIXEL_SHADER_TYPE psCompileTarget = EPST_PS_1_1, IShaderConstantSetCallBack* callback = 0, E_MATERIAL_TYPE baseMaterial = video::EMT_SOLID, - s32 userData = 0) = 0; + s32 userData = 0) + { + return addHighLevelShaderMaterialFromFiles( + vertexShaderProgram, vertexShaderEntryPointName, + vsCompileTarget, pixelShaderProgram, + pixelShaderEntryPointName, psCompileTarget, + 0, "main", EGST_GS_4_0, + scene::EPT_TRIANGLES, scene::EPT_TRIANGLE_STRIP, 0, + callback, baseMaterial, userData); + } //! Adds a new ASM shader material renderer to the VideoDriver /** Note that it is a good idea to call IVideoDriver::queryFeature() in diff --git a/include/IGUIContextMenu.h b/include/IGUIContextMenu.h index 043aa2c9..f18a7396 100644 --- a/include/IGUIContextMenu.h +++ b/include/IGUIContextMenu.h @@ -39,7 +39,7 @@ namespace gui //! set behaviour when menus are closed virtual void setCloseHandling(ECONTEXT_MENU_CLOSE onClose) = 0; - //! get current behaviour when the menue will be closed + //! get current behaviour when the menu will be closed virtual ECONTEXT_MENU_CLOSE getCloseHandling() const = 0; //! Get amount of menu items @@ -53,8 +53,9 @@ namespace gui set to whatever you want. \param enabled: Specifies if the menu item should be enabled. \param hasSubMenu: Set this to true if there should be a submenu - at this item. You can acess this submenu via getSubMenu(). + at this item. You can access this submenu via getSubMenu(). \param checked: Specifies if the menu item should be initially checked. + \param autoChecking: Specifies if the item should be checked by clicking \return Returns the index of the new item */ virtual u32 addItem(const wchar_t* text, s32 commandId=-1, bool enabled=true, bool hasSubMenu=false, bool checked=false, bool autoChecking=false) = 0; @@ -69,16 +70,17 @@ namespace gui set to whatever you want. \param enabled: Specifies if the menu item should be enabled. \param hasSubMenu: Set this to true if there should be a submenu - at this item. You can acess this submenu via getSubMenu(). + at this item. You can access this submenu via getSubMenu(). \param checked: Specifies if the menu item should be initially checked. + \param autoChecking: Specifies if the item should be checked by clicking \return Returns the index of the new item */ virtual u32 insertItem(u32 idx, const wchar_t* text, s32 commandId=-1, bool enabled=true, bool hasSubMenu=false, bool checked=false, bool autoChecking=false) = 0; - //! Find an item by it's CommandID + //! Find an item by it's CommandID /** \param commandId: We are looking for the first item which has this commandID - \param idxStartSearch: Start searching from this index. + \param idxStartSearch: Start searching from this index. \return Returns the index of the item when found or otherwise -1. */ virtual s32 findItemWithCommandId(s32 commandId, u32 idxStartSearch=0) const = 0; diff --git a/include/IGUIEditBox.h b/include/IGUIEditBox.h index 40f9acfc..5666b873 100644 --- a/include/IGUIEditBox.h +++ b/include/IGUIEditBox.h @@ -38,7 +38,7 @@ namespace gui \param color: New color of the text. */ virtual void setOverrideColor(video::SColor color) = 0; - //! Sets if the text should use the overide color or the color in the gui skin. + //! Sets if the text should use the override color or the color in the gui skin. /** \param enable: If set to true, the override color, which can be set with IGUIEditBox::setOverrideColor is used, otherwise the EGDC_BUTTON_TEXT color of the skin. */ @@ -70,7 +70,7 @@ namespace gui virtual void setMultiLine(bool enable) = 0; //! Checks if multi line editing is enabled - /** \return true if mult-line is enabled, false otherwise */ + /** \return true if multi-line is enabled, false otherwise */ virtual bool isMultiLineEnabled() const = 0; //! Enables or disables automatic scrolling with cursor position diff --git a/include/IGUIElement.h b/include/IGUIElement.h index b560fdc2..44ded590 100644 --- a/include/IGUIElement.h +++ b/include/IGUIElement.h @@ -28,7 +28,7 @@ public: //! Constructor IGUIElement(EGUI_ELEMENT_TYPE type, IGUIEnvironment* environment, IGUIElement* parent, - s32 id, core::rect rectangle) + s32 id, const core::rect& rectangle) : Parent(0), RelativeRect(rectangle), AbsoluteRect(rectangle), AbsoluteClippingRect(rectangle), DesiredRect(rectangle), MaxSize(0,0), MinSize(1,1), IsVisible(true), IsEnabled(true), @@ -42,8 +42,10 @@ public: // if we were given a parent to attach to if (parent) - parent->addChild(this); - + { + parent->addChildToEnd(this); + recalculateAbsolutePosition(true); + } } @@ -213,120 +215,7 @@ public: //! Updates the absolute position. virtual void updateAbsolutePosition() { - core::rect parentAbsolute(0,0,0,0); - core::rect parentAbsoluteClip; - f32 fw=0.f, fh=0.f; - - if (Parent) - { - parentAbsolute = Parent->AbsoluteRect; - - if (NoClip) - { - IGUIElement* p=this; - while (p && p->Parent) - p = p->Parent; - parentAbsoluteClip = p->AbsoluteClippingRect; - } - else - parentAbsoluteClip = Parent->AbsoluteClippingRect; - } - - const s32 diffx = parentAbsolute.getWidth() - LastParentRect.getWidth(); - const s32 diffy = parentAbsolute.getHeight() - LastParentRect.getHeight(); - - if (AlignLeft == EGUIA_SCALE || AlignRight == EGUIA_SCALE) - fw = (f32)parentAbsolute.getWidth(); - - if (AlignTop == EGUIA_SCALE || AlignBottom == EGUIA_SCALE) - fh = (f32)parentAbsolute.getHeight(); - - switch (AlignLeft) - { - case EGUIA_UPPERLEFT: - break; - case EGUIA_LOWERRIGHT: - DesiredRect.UpperLeftCorner.X += diffx; - break; - case EGUIA_CENTER: - DesiredRect.UpperLeftCorner.X += diffx/2; - break; - case EGUIA_SCALE: - DesiredRect.UpperLeftCorner.X = core::round32(ScaleRect.UpperLeftCorner.X * fw); - break; - } - - switch (AlignRight) - { - case EGUIA_UPPERLEFT: - break; - case EGUIA_LOWERRIGHT: - DesiredRect.LowerRightCorner.X += diffx; - break; - case EGUIA_CENTER: - DesiredRect.LowerRightCorner.X += diffx/2; - break; - case EGUIA_SCALE: - DesiredRect.LowerRightCorner.X = core::round32(ScaleRect.LowerRightCorner.X * fw); - break; - } - - switch (AlignTop) - { - case EGUIA_UPPERLEFT: - break; - case EGUIA_LOWERRIGHT: - DesiredRect.UpperLeftCorner.Y += diffy; - break; - case EGUIA_CENTER: - DesiredRect.UpperLeftCorner.Y += diffy/2; - break; - case EGUIA_SCALE: - DesiredRect.UpperLeftCorner.Y = core::round32(ScaleRect.UpperLeftCorner.Y * fh); - break; - } - - switch (AlignBottom) - { - case EGUIA_UPPERLEFT: - break; - case EGUIA_LOWERRIGHT: - DesiredRect.LowerRightCorner.Y += diffy; - break; - case EGUIA_CENTER: - DesiredRect.LowerRightCorner.Y += diffy/2; - break; - case EGUIA_SCALE: - DesiredRect.LowerRightCorner.Y = core::round32(ScaleRect.LowerRightCorner.Y * fh); - break; - } - - RelativeRect = DesiredRect; - - const s32 w = RelativeRect.getWidth(); - const s32 h = RelativeRect.getHeight(); - - // make sure the desired rectangle is allowed - if (w < (s32)MinSize.Width) - RelativeRect.LowerRightCorner.X = RelativeRect.UpperLeftCorner.X + MinSize.Width; - if (h < (s32)MinSize.Height) - RelativeRect.LowerRightCorner.Y = RelativeRect.UpperLeftCorner.Y + MinSize.Height; - if (MaxSize.Width && w > (s32)MaxSize.Width) - RelativeRect.LowerRightCorner.X = RelativeRect.UpperLeftCorner.X + MaxSize.Width; - if (MaxSize.Height && h > (s32)MaxSize.Height) - RelativeRect.LowerRightCorner.Y = RelativeRect.UpperLeftCorner.Y + MaxSize.Height; - - RelativeRect.repair(); - - AbsoluteRect = RelativeRect + parentAbsolute.UpperLeftCorner; - - if (!Parent) - parentAbsoluteClip = AbsoluteRect; - - AbsoluteClippingRect = AbsoluteRect; - AbsoluteClippingRect.clipAgainst(parentAbsoluteClip); - - LastParentRect = parentAbsolute; + recalculateAbsolutePosition(false); // update all children core::list::Iterator it = Children.begin(); @@ -348,7 +237,7 @@ public: \param point: The point at which to find a GUI element. \return The topmost GUI element at that point, or 0 if there are no candidate elements at this point. - */ + */ IGUIElement* getElementFromPoint(const core::position2d& point) { IGUIElement* target = 0; @@ -388,13 +277,9 @@ public: //! Adds a GUI element as new child of this element. virtual void addChild(IGUIElement* child) { + addChildToEnd(child); if (child) { - child->grab(); // prevent destruction when removed - child->remove(); // remove from old parent - child->LastParentRect = getAbsolutePosition(); - child->Parent = this; - Children.push_back(child); child->updateAbsolutePosition(); } } @@ -798,6 +683,20 @@ public: return Type; } + //! Returns true if the gui element supports the given type. + /** This is mostly used to check if you can cast a gui element to the class that goes with the type. + Most gui elements will only support their own type, but if you derive your own classes from interfaces + you can overload this function and add a check for the type of the base-class additionally. + This allows for checks comparable to the dynamic_cast of c++ with enabled rtti. + Note that you can't do that by calling BaseClass::hasType(type), but you have to do an explicit + comparison check, because otherwise the base class usually just checks for the membervariable + Type which contains the type of your derived class. + */ + virtual bool hasType(EGUI_ELEMENT_TYPE type) const + { + return type == Type; + } + //! Returns the type name of the gui element. /** This is needed serializing elements. For serializing your own elements, override this function @@ -860,6 +759,149 @@ public: setNotClipped(in->getAttributeAsBool("NoClip")); } +protected: + // not virtual because needed in constructor + void addChildToEnd(IGUIElement* child) + { + if (child) + { + child->grab(); // prevent destruction when removed + child->remove(); // remove from old parent + child->LastParentRect = getAbsolutePosition(); + child->Parent = this; + Children.push_back(child); + } + } + + // not virtual because needed in constructor + void recalculateAbsolutePosition(bool recursive) + { + core::rect parentAbsolute(0,0,0,0); + core::rect parentAbsoluteClip; + f32 fw=0.f, fh=0.f; + + if (Parent) + { + parentAbsolute = Parent->AbsoluteRect; + + if (NoClip) + { + IGUIElement* p=this; + while (p && p->Parent) + p = p->Parent; + parentAbsoluteClip = p->AbsoluteClippingRect; + } + else + parentAbsoluteClip = Parent->AbsoluteClippingRect; + } + + const s32 diffx = parentAbsolute.getWidth() - LastParentRect.getWidth(); + const s32 diffy = parentAbsolute.getHeight() - LastParentRect.getHeight(); + + if (AlignLeft == EGUIA_SCALE || AlignRight == EGUIA_SCALE) + fw = (f32)parentAbsolute.getWidth(); + + if (AlignTop == EGUIA_SCALE || AlignBottom == EGUIA_SCALE) + fh = (f32)parentAbsolute.getHeight(); + + switch (AlignLeft) + { + case EGUIA_UPPERLEFT: + break; + case EGUIA_LOWERRIGHT: + DesiredRect.UpperLeftCorner.X += diffx; + break; + case EGUIA_CENTER: + DesiredRect.UpperLeftCorner.X += diffx/2; + break; + case EGUIA_SCALE: + DesiredRect.UpperLeftCorner.X = core::round32(ScaleRect.UpperLeftCorner.X * fw); + break; + } + + switch (AlignRight) + { + case EGUIA_UPPERLEFT: + break; + case EGUIA_LOWERRIGHT: + DesiredRect.LowerRightCorner.X += diffx; + break; + case EGUIA_CENTER: + DesiredRect.LowerRightCorner.X += diffx/2; + break; + case EGUIA_SCALE: + DesiredRect.LowerRightCorner.X = core::round32(ScaleRect.LowerRightCorner.X * fw); + break; + } + + switch (AlignTop) + { + case EGUIA_UPPERLEFT: + break; + case EGUIA_LOWERRIGHT: + DesiredRect.UpperLeftCorner.Y += diffy; + break; + case EGUIA_CENTER: + DesiredRect.UpperLeftCorner.Y += diffy/2; + break; + case EGUIA_SCALE: + DesiredRect.UpperLeftCorner.Y = core::round32(ScaleRect.UpperLeftCorner.Y * fh); + break; + } + + switch (AlignBottom) + { + case EGUIA_UPPERLEFT: + break; + case EGUIA_LOWERRIGHT: + DesiredRect.LowerRightCorner.Y += diffy; + break; + case EGUIA_CENTER: + DesiredRect.LowerRightCorner.Y += diffy/2; + break; + case EGUIA_SCALE: + DesiredRect.LowerRightCorner.Y = core::round32(ScaleRect.LowerRightCorner.Y * fh); + break; + } + + RelativeRect = DesiredRect; + + const s32 w = RelativeRect.getWidth(); + const s32 h = RelativeRect.getHeight(); + + // make sure the desired rectangle is allowed + if (w < (s32)MinSize.Width) + RelativeRect.LowerRightCorner.X = RelativeRect.UpperLeftCorner.X + MinSize.Width; + if (h < (s32)MinSize.Height) + RelativeRect.LowerRightCorner.Y = RelativeRect.UpperLeftCorner.Y + MinSize.Height; + if (MaxSize.Width && w > (s32)MaxSize.Width) + RelativeRect.LowerRightCorner.X = RelativeRect.UpperLeftCorner.X + MaxSize.Width; + if (MaxSize.Height && h > (s32)MaxSize.Height) + RelativeRect.LowerRightCorner.Y = RelativeRect.UpperLeftCorner.Y + MaxSize.Height; + + RelativeRect.repair(); + + AbsoluteRect = RelativeRect + parentAbsolute.UpperLeftCorner; + + if (!Parent) + parentAbsoluteClip = AbsoluteRect; + + AbsoluteClippingRect = AbsoluteRect; + AbsoluteClippingRect.clipAgainst(parentAbsoluteClip); + + LastParentRect = parentAbsolute; + + if ( recursive ) + { + // update all children + core::list::Iterator it = Children.begin(); + for (; it != Children.end(); ++it) + { + (*it)->recalculateAbsolutePosition(recursive); + } + } + } + protected: //! List of all children of this element diff --git a/include/IGUIElementFactory.h b/include/IGUIElementFactory.h index 1a3a733d..e203c2fb 100644 --- a/include/IGUIElementFactory.h +++ b/include/IGUIElementFactory.h @@ -15,7 +15,7 @@ namespace gui { class IGUIElement; - //! Interface making it possible to dynamicly create GUI elements + //! Interface making it possible to dynamically create GUI elements /** To be able to add custom elements to Irrlicht and to make it possible for the scene manager to save and load them, simply implement this interface and register it in your gui environment via IGUIEnvironment::registerGUIElementFactory. diff --git a/include/IGUIEnvironment.h b/include/IGUIEnvironment.h index 80838913..16dcd00f 100644 --- a/include/IGUIEnvironment.h +++ b/include/IGUIEnvironment.h @@ -166,6 +166,14 @@ public: more information. */ virtual IGUIFont* getFont(const io::path& filename) = 0; + //! Adds an externally loaded font to the font list. + /** This method allows to attach an already loaded font to the list of + existing fonts. The font is grabbed if non-null and adding was successful. + \param name Name the font should be stored as. + \param font Pointer to font to add. + \return Pointer to the font stored. This can differ from given parameter if the name previously existed. */ + virtual IGUIFont* addFont(const io::path& name, IGUIFont* font) = 0; + //! Returns the default built-in font. /** \return Pointer to the default built-in font. This pointer should not be dropped. See IReferenceCounted::drop() for @@ -201,7 +209,7 @@ public: \param id Id with which the gui element can be identified. \param text Text displayed on the button. \param tooltiptext Text displayed in the tooltip. - \return Pointer to the created button. Returns 0 if an error occured. + \return Pointer to the created button. Returns 0 if an error occurred. This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ virtual IGUIButton* addButton(const core::rect& rectangle, @@ -215,7 +223,7 @@ public: \param text Text displayed as the window title. \param parent Parent gui element of the window. \param id Id with which the gui element can be identified. - \return Pointer to the created window. Returns 0 if an error occured. + \return Pointer to the created window. Returns 0 if an error occurred. This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ virtual IGUIWindow* addWindow(const core::rect& rectangle, bool modal = false, @@ -225,7 +233,7 @@ public: /** This control stops its parent's members from being able to receive input until its last child is removed, it then deletes itself. \param parent Parent gui element of the modal. - \return Pointer to the created modal. Returns 0 if an error occured. + \return Pointer to the created modal. Returns 0 if an error occurred. This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ virtual IGUIElement* addModalScreen(IGUIElement* parent) = 0; @@ -243,7 +251,7 @@ public: \param id Id with which the gui element can be identified. \param image Optional texture which will be displayed beside the text as an image \return Pointer to the created message box. Returns 0 if an error - occured. This pointer should not be dropped. See + occurred. This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ virtual IGUIWindow* addMessageBox(const wchar_t* caption, const wchar_t* text=0, bool modal = true, s32 flags = EMBF_OK, IGUIElement* parent=0, s32 id=-1, video::ITexture* image=0) = 0; @@ -255,7 +263,7 @@ public: \param parent Parent gui element of the scroll bar. \param id Id to identify the gui element. \return Pointer to the created scrollbar. Returns 0 if an error - occured. This pointer should not be dropped. See + occurred. This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ virtual IGUIScrollBar* addScrollBar(bool horizontal, const core::rect& rectangle, IGUIElement* parent=0, s32 id=-1) = 0; @@ -270,7 +278,7 @@ public: \param id Id to identify the gui element. \param text Title text of the image. \return Pointer to the created image element. Returns 0 if an error - occured. This pointer should not be dropped. See + occurred. This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ virtual IGUIImage* addImage(video::ITexture* image, core::position2d pos, bool useAlphaChannel=true, IGUIElement* parent=0, s32 id=-1, const wchar_t* text=0) = 0; @@ -282,7 +290,7 @@ public: \param id Id to identify the gui element. \param text Title text of the image. \return Pointer to the created image element. Returns 0 if an error - occured. This pointer should not be dropped. See + occurred. This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ virtual IGUIImage* addImage(const core::rect& rectangle, IGUIElement* parent=0, s32 id=-1, const wchar_t* text=0) = 0; @@ -294,7 +302,7 @@ public: \param id Id to identify the gui element. \param text Title text of the check box. \return Pointer to the created check box. Returns 0 if an error - occured. This pointer should not be dropped. See + occurred. This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ virtual IGUICheckBox* addCheckBox(bool checked, const core::rect& rectangle, IGUIElement* parent=0, s32 id=-1, const wchar_t* text=0) = 0; @@ -304,7 +312,7 @@ public: \param parent Parent gui element of the list box. \param id Id to identify the gui element. \param drawBackground Flag whether the background should be drawn. - \return Pointer to the created list box. Returns 0 if an error occured. + \return Pointer to the created list box. Returns 0 if an error occurred. This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ virtual IGUIListBox* addListBox(const core::rect& rectangle, @@ -317,7 +325,7 @@ public: \param drawBackground Flag whether the background should be drawn. \param scrollBarVertical Flag whether a vertical scrollbar should be used \param scrollBarHorizontal Flag whether a horizontal scrollbar should be used - \return Pointer to the created list box. Returns 0 if an error occured. + \return Pointer to the created list box. Returns 0 if an error occurred. This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ virtual IGUITreeView* addTreeView(const core::rect& rectangle, @@ -330,7 +338,7 @@ public: \param id Id to identify the gui element. \param text Title text of the mesh viewer. \return Pointer to the created mesh viewer. Returns 0 if an error - occured. This pointer should not be dropped. See + occurred. This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ virtual IGUIMeshViewer* addMeshViewer(const core::rect& rectangle, IGUIElement* parent=0, s32 id=-1, const wchar_t* text=0) = 0; @@ -343,7 +351,7 @@ public: \param parent Parent gui element of the dialog. \param id Id to identify the gui element. \return Pointer to the created file open dialog. Returns 0 if an error - occured. This pointer should not be dropped. See + occurred. This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ virtual IGUIFileOpenDialog* addFileOpenDialog(const wchar_t* title = 0, bool modal=true, IGUIElement* parent=0, s32 id=-1) = 0; @@ -356,7 +364,7 @@ public: \param parent The parent of the dialog. \param id The ID of the dialog. \return Pointer to the created file open dialog. Returns 0 if an error - occured. This pointer should not be dropped. See + occurred. This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ virtual IGUIColorSelectDialog* addColorSelectDialog(const wchar_t* title = 0, bool modal=true, IGUIElement* parent=0, s32 id=-1) = 0; @@ -371,7 +379,7 @@ public: \param fillBackground Enable if the background shall be filled. Defaults to false. \return Pointer to the created static text. Returns 0 if an error - occured. This pointer should not be dropped. See + occurred. This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ virtual IGUIStaticText* addStaticText(const wchar_t* text, const core::rect& rectangle, bool border=false, bool wordWrap=true, IGUIElement* parent=0, s32 id=-1, @@ -389,7 +397,7 @@ public: \param parent Parent item of the element, e.g. a window. Set it to 0 to place the edit box directly in the environment. \param id The ID of the element. - \return Pointer to the created edit box. Returns 0 if an error occured. + \return Pointer to the created edit box. Returns 0 if an error occurred. This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ virtual IGUIEditBox* addEditBox(const wchar_t* text, const core::rect& rectangle, @@ -403,7 +411,7 @@ public: \param parent Parent item of the element, e.g. a window. Set it to 0 to place the spin box directly in the environment. \param id The ID of the element. - \return Pointer to the created spin box. Returns 0 if an error occured. + \return Pointer to the created spin box. Returns 0 if an error occurred. This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ virtual IGUISpinBox* addSpinBox(const wchar_t* text, const core::rect& rectangle, @@ -415,7 +423,7 @@ public: \param parent Parent item of the element, e.g. a window. \param id An identifier for the fader. \return Pointer to the created in-out-fader. Returns 0 if an error - occured. This pointer should not be dropped. See + occurred. This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ virtual IGUIInOutFader* addInOutFader(const core::rect* rectangle=0, IGUIElement* parent=0, s32 id=-1) = 0; @@ -430,7 +438,7 @@ public: the environment without a window as parent. \param id An identifier for the tab control. \return Pointer to the created tab control element. Returns 0 if an - error occured. This pointer should not be dropped. See + error occurred. This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ virtual IGUITabControl* addTabControl(const core::rect& rectangle, IGUIElement* parent=0, bool fillbackground=false, @@ -445,7 +453,7 @@ public: Set it to 0 to place the tab directly in the environment. \param id An identifier for the tab. \return Pointer to the created tab. Returns 0 if an - error occured. This pointer should not be dropped. See + error occurred. This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ virtual IGUITab* addTab(const core::rect& rectangle, IGUIElement* parent=0, s32 id=-1) = 0; @@ -457,7 +465,7 @@ public: Set it to 0 to place the menu directly in the environment. \param id An identifier for the menu. \return Pointer to the created context menu. Returns 0 if an - error occured. This pointer should not be dropped. See + error occurred. This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ virtual IGUIContextMenu* addContextMenu(const core::rect& rectangle, IGUIElement* parent=0, s32 id=-1) = 0; @@ -469,7 +477,7 @@ public: Set it to 0 to place the menu directly in the environment. \param id An identifier for the menu. \return Pointer to the created menu. Returns 0 if an - error occured. This pointer should not be dropped. See + error occurred. This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ virtual IGUIContextMenu* addMenu(IGUIElement* parent=0, s32 id=-1) = 0; @@ -480,7 +488,7 @@ public: Set it to 0 to place the tool bar directly in the environment. \param id An identifier for the tool bar. \return Pointer to the created tool bar. Returns 0 if an - error occured. This pointer should not be dropped. See + error occurred. This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ virtual IGUIToolBar* addToolBar(IGUIElement* parent=0, s32 id=-1) = 0; @@ -490,7 +498,7 @@ public: Set it to 0 to place the combo box directly in the environment. \param id An identifier for the combo box. \return Pointer to the created combo box. Returns 0 if an - error occured. This pointer should not be dropped. See + error occurred. This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ virtual IGUIComboBox* addComboBox(const core::rect& rectangle, IGUIElement* parent=0, s32 id=-1) = 0; @@ -501,7 +509,7 @@ public: to place the element directly in the environment. \param id An identifier for the table. \param drawBackground Flag whether the background should be drawn. - \return Pointer to the created table. Returns 0 if an error occured. + \return Pointer to the created table. Returns 0 if an error occurred. This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ virtual IGUITable* addTable(const core::rect& rectangle, diff --git a/include/IGUIFont.h b/include/IGUIFont.h index e601bcd5..60dea3d8 100644 --- a/include/IGUIFont.h +++ b/include/IGUIFont.h @@ -44,7 +44,7 @@ public: /** \param text: Text to draw \param position: Rectangle specifying position where to draw the text. \param color: Color of the text - \param hcenter: Specifiies if the text should be centered horizontally into the rectangle. + \param hcenter: Specifies if the text should be centered horizontally into the rectangle. \param vcenter: Specifies if the text should be centered vertically into the rectangle. \param clip: Optional pointer to a rectangle against which the text will be clipped. If the pointer is null, no clipping will be done. */ diff --git a/include/IGUIImageList.h b/include/IGUIImageList.h index ee6ec879..f1f50c14 100644 --- a/include/IGUIImageList.h +++ b/include/IGUIImageList.h @@ -26,8 +26,8 @@ public: //! \param destPos: Position of the image to draw //! \param clip: Optional pointer to a rectalgle against which the text will be clipped. //! If the pointer is null, no clipping will be done. - virtual void draw( s32 index, const core::position2d& destPos, - const core::rect* clip = 0 ) = 0; + virtual void draw(s32 index, const core::position2d& destPos, + const core::rect* clip = 0) = 0; //! Returns the count of Images in the list. //! \return Returns the count of Images in the list. diff --git a/include/IGUIInOutFader.h b/include/IGUIInOutFader.h index 37324187..2d3bc49b 100644 --- a/include/IGUIInOutFader.h +++ b/include/IGUIInOutFader.h @@ -44,14 +44,14 @@ namespace gui /** In the beginning the whole rect is drawn by the set color (black by default) and at the end of the overgiven time the color has faded out. - \param time: Time specifing how long it should need to fade in, + \param time: Time specifying how long it should need to fade in, in milliseconds. */ virtual void fadeIn(u32 time) = 0; //! Starts the fade out process. /** In the beginning everything is visible, and at the end of the time only the set color (black by the fault) will be drawn. - \param time: Time specifing how long it should need to fade out, + \param time: Time specifying how long it should need to fade out, in milliseconds. */ virtual void fadeOut(u32 time) = 0; diff --git a/include/IGUIListBox.h b/include/IGUIListBox.h index a88e5118..64c02ac5 100644 --- a/include/IGUIListBox.h +++ b/include/IGUIListBox.h @@ -118,8 +118,8 @@ namespace gui //! set global itemHeight virtual void setItemHeight( s32 height ) = 0; - //! Sets whether to draw the background - virtual void setDrawBackground(bool draw) = 0; + //! Sets whether to draw the background + virtual void setDrawBackground(bool draw) = 0; }; diff --git a/include/IGUISkin.h b/include/IGUISkin.h index 4bac9133..ef94c096 100644 --- a/include/IGUISkin.h +++ b/include/IGUISkin.h @@ -38,7 +38,7 @@ namespace gui //! An unknown skin, not serializable at present EGST_UNKNOWN, - + //! this value is not used, it only specifies the number of skin types EGST_COUNT }; @@ -448,11 +448,16 @@ namespace gui \param drawTitleBar: True to enable title drawing. \param rect: Defining area where to draw. \param clip: Clip area. - \return Returns rect where it would be good to draw title bar text. */ + \param checkClientArea: When set to non-null the function will not draw anything, + but will instead return the clientArea which can be used for drawing by the calling window. + That is the area without borders and without titlebar. + \return Returns rect where it would be good to draw title bar text. This will + work even when checkClientArea is set to a non-null value.*/ virtual core::rect draw3DWindowBackground(IGUIElement* element, bool drawTitleBar, video::SColor titleBarColor, const core::rect& rect, - const core::rect* clip=0) = 0; + const core::rect* clip=0, + core::rect* checkClientArea=0) = 0; //! draws a standard 3d menu pane /** Used for drawing for menus and context menus. diff --git a/include/IGUISpriteBank.h b/include/IGUISpriteBank.h index ffe43487..de4bd71b 100644 --- a/include/IGUISpriteBank.h +++ b/include/IGUISpriteBank.h @@ -39,6 +39,9 @@ struct SGUISprite //! Sprite bank interface. +/** See http://irrlicht.sourceforge.net/phpBB2/viewtopic.php?t=25742&highlight=spritebank +* for more information how to use the spritebank. +*/ class IGUISpriteBank : public virtual IReferenceCounted { public: @@ -61,6 +64,14 @@ public: //! Changes one of the textures in the sprite bank virtual void setTexture(u32 index, video::ITexture* texture) = 0; + //! Add the texture and use it for a single non-animated sprite. + //! The texture and the corresponding rectangle and sprite will all be added to the end of each array. + //! returns the index of the sprite or -1 on failure + virtual s32 addTextureAsSprite(video::ITexture* texture) = 0; + + //! clears sprites, rectangles and textures + virtual void clear() = 0; + //! Draws a sprite in 2d with position and color virtual void draw2DSprite(u32 index, const core::position2di& pos, const core::rect* clip=0, diff --git a/include/IGUITabControl.h b/include/IGUITabControl.h index ff73825d..d423646d 100644 --- a/include/IGUITabControl.h +++ b/include/IGUITabControl.h @@ -13,7 +13,8 @@ namespace irr { namespace gui { - //! A tab, onto which other gui elements could be added. + //! A tab-page, onto which other gui elements could be added. + /** IGUITab refers to the page itself, not to the tab in the tabbar of an IGUITabControl. */ class IGUITab : public IGUIElement { public: @@ -88,10 +89,10 @@ namespace gui //! set the maximal width of a tab. Per default width is 0 which means "no width restriction". virtual void setTabMaxWidth(s32 width ) = 0; - + //! get the maximal width of a tab virtual s32 getTabMaxWidth() const = 0; - + //! Set the alignment of the tabs /** Use EGUIA_UPPERLEFT or EGUIA_LOWERRIGHT */ virtual void setTabVerticalAlignment( gui::EGUI_ALIGNMENT alignment ) = 0; diff --git a/include/IGUITable.h b/include/IGUITable.h index dc976726..d7d4c937 100644 --- a/include/IGUITable.h +++ b/include/IGUITable.h @@ -139,7 +139,7 @@ namespace gui will be placed after it. If the row is larger than the actual number of row by more than one, it won't be created. Note that if you create a row that's not at the end, there might be - performance issues. + performance issues. \return index of inserted row. */ virtual u32 addRow(u32 rowIndex) = 0; diff --git a/include/IGUITreeView.h b/include/IGUITreeView.h index bd8554d3..931d3545 100644 --- a/include/IGUITreeView.h +++ b/include/IGUITreeView.h @@ -20,16 +20,10 @@ namespace gui class IGUITreeViewNode : public IReferenceCounted { public: - //! constructor - IGUITreeViewNode() {} - - //! destructor - virtual ~IGUITreeViewNode() {} - //! returns the owner (tree view) of this node virtual IGUITreeView* getOwner() const = 0; - //! Returns the parent node of this node. + //! Returns the parent node of this node. /** For the root node this will return 0. */ virtual IGUITreeViewNode* getParent() const = 0; @@ -87,13 +81,10 @@ namespace gui \param data2 user data2 (IReferenceCounted*) of the new node \return The new node */ - virtual IGUITreeViewNode* addChildBack( - const wchar_t* text, - const wchar_t* icon = 0, - s32 imageIndex = -1, - s32 selectedImageIndex = -1, - void* data = 0, - IReferenceCounted* data2 = 0 ) = 0; + virtual IGUITreeViewNode* addChildBack( + const wchar_t* text, const wchar_t* icon = 0, + s32 imageIndex=-1, s32 selectedImageIndex=-1, + void* data=0, IReferenceCounted* data2=0) =0; //! Adds a new node before the first child node. /** \param text text of the new node @@ -104,15 +95,12 @@ namespace gui \param data2 user data2 (IReferenceCounted*) of the new node \return The new node */ - virtual IGUITreeViewNode* addChildFront( - const wchar_t* text, - const wchar_t* icon = 0, - s32 imageIndex = -1, - s32 selectedImageIndex = -1, - void* data = 0, - IReferenceCounted* data2 = 0 ) = 0; + virtual IGUITreeViewNode* addChildFront( + const wchar_t* text, const wchar_t* icon = 0, + s32 imageIndex=-1, s32 selectedImageIndex=-1, + void* data=0, IReferenceCounted* data2=0 ) =0; - //! Adds a new node behind the other node. + //! Adds a new node behind the other node. /** The other node has also te be a child node from this node. \param other Node to insert after \param text text of the new node @@ -123,16 +111,13 @@ namespace gui \param data2 user data2 (IReferenceCounted*) of the new node \return The new node or 0 if other is no child node from this */ - virtual IGUITreeViewNode* insertChildAfter( - IGUITreeViewNode* other, - const wchar_t* text, - const wchar_t* icon = 0, - s32 imageIndex = -1, - s32 selectedImageIndex = -1, - void* data = 0, - IReferenceCounted* data2 = 0 ) = 0; + virtual IGUITreeViewNode* insertChildAfter( + IGUITreeViewNode* other, + const wchar_t* text, const wchar_t* icon = 0, + s32 imageIndex=-1, s32 selectedImageIndex=-1, + void* data=0, IReferenceCounted* data2=0) =0; - //! Adds a new node before the other node. + //! Adds a new node before the other node. /** The other node has also te be a child node from this node. \param other Node to insert before \param text text of the new node @@ -143,14 +128,11 @@ namespace gui \param data2 user data2 (IReferenceCounted*) of the new node \return The new node or 0 if other is no child node from this */ - virtual IGUITreeViewNode* insertChildBefore( - IGUITreeViewNode* other, - const wchar_t* text, - const wchar_t* icon = 0, - s32 imageIndex = -1, - s32 selectedImageIndex = -1, - void* data = 0, - IReferenceCounted* data2 = 0 ) = 0; + virtual IGUITreeViewNode* insertChildBefore( + IGUITreeViewNode* other, + const wchar_t* text, const wchar_t* icon = 0, + s32 imageIndex=-1, s32 selectedImageIndex=-1, + void* data=0, IReferenceCounted* data2=0) = 0; //! Return the first child node from this node. /** \return The first child node or 0 if this node has no childs. */ @@ -214,21 +196,17 @@ namespace gui //! Default tree view GUI element. - /** Displays a windows like tree buttons to expand/collaps the child nodes of an node - and optional tree lines. - Each node consits of an text, an icon text and a void pointer for user data. - */ + /** Displays a windows like tree buttons to expand/collaps the child + nodes of an node and optional tree lines. Each node consits of an + text, an icon text and a void pointer for user data. */ class IGUITreeView : public IGUIElement { public: //! constructor - IGUITreeView( IGUIEnvironment* environment, IGUIElement* parent, s32 id, - core::rect rectangle ) + IGUITreeView(IGUIEnvironment* environment, IGUIElement* parent, + s32 id, core::rect rectangle) : IGUIElement( EGUIET_TREE_VIEW, environment, parent, id, rectangle ) {} - //! destructor - virtual ~IGUITreeView() {} - //! returns the root node (not visible) from the tree. virtual IGUITreeViewNode* getRoot() const = 0; diff --git a/include/IGUIWindow.h b/include/IGUIWindow.h index 81cd9a41..c5fd2b3d 100644 --- a/include/IGUIWindow.h +++ b/include/IGUIWindow.h @@ -24,12 +24,15 @@ namespace gui : IGUIElement(EGUIET_WINDOW, environment, parent, id, rectangle) {} //! Returns pointer to the close button + /** You can hide the button by calling setVisible(false) on the result. */ virtual IGUIButton* getCloseButton() const = 0; //! Returns pointer to the minimize button + /** You can hide the button by calling setVisible(false) on the result. */ virtual IGUIButton* getMinimizeButton() const = 0; //! Returns pointer to the maximize button + /** You can hide the button by calling setVisible(false) on the result. */ virtual IGUIButton* getMaximizeButton() const = 0; //! Returns true if the window can be dragged with the mouse, false if not @@ -38,18 +41,26 @@ namespace gui //! Sets whether the window can be dragged by the mouse virtual void setDraggable(bool draggable) = 0; - //! Set if the window background will be drawn - virtual void setDrawBackground(bool draw) = 0; + //! Set if the window background will be drawn + virtual void setDrawBackground(bool draw) = 0; - //! Get if the window background will be drawn - virtual bool getDrawBackground() const = 0; + //! Get if the window background will be drawn + virtual bool getDrawBackground() const = 0; - //! Set if the window titlebar will be drawn - //! Note: If the background is not drawn, then the titlebar is automatically also not drawn - virtual void setDrawTitlebar(bool draw) = 0; + //! Set if the window titlebar will be drawn + //! Note: If the background is not drawn, then the titlebar is automatically also not drawn + virtual void setDrawTitlebar(bool draw) = 0; - //! Get if the window titlebar will be drawn - virtual bool getDrawTitlebar() const = 0; + //! Get if the window titlebar will be drawn + virtual bool getDrawTitlebar() const = 0; + + //! Returns the rectangle of the drawable area (without border and without titlebar) + /** The coordinates are given relative to the top-left position of the gui element.
+ So to get absolute positions you have to add the resulting rectangle to getAbsolutePosition().UpperLeftCorner.
+ To get it relative to the parent element you have to add the resulting rectangle to getRelativePosition().UpperLeftCorner. + Beware that adding a menu will not change the clientRect as menus are own gui elements, so in that case you might want to subtract + the menu area additionally. */ + virtual core::rect getClientRect() const = 0; }; diff --git a/include/IGeometryCreator.h b/include/IGeometryCreator.h index d27ea1b8..fcf66973 100644 --- a/include/IGeometryCreator.h +++ b/include/IGeometryCreator.h @@ -35,7 +35,7 @@ public: //! Create a pseudo-random mesh representing a hilly terrain. /** - \param tileSize The size of each time. + \param tileSize The size of each tile. \param tileCount The number of tiles in each dimension. \param material The material to apply to the mesh. \param hillHeight The maximum height of the hills. @@ -50,6 +50,23 @@ public: const core::dimension2d& countHills, const core::dimension2d& textureRepeatCount) const =0; + //! Create a simple rectangular textured plane mesh. + /** + \param tileSize The size of each tile. + \param tileCount The number of tiles in each dimension. + \param material The material to apply to the mesh. + \param textureRepeatCount The number of times to repeat the material texture along each dimension. + \return Generated mesh. + */ + IMesh* createPlaneMesh( + const core::dimension2d& tileSize, + const core::dimension2d& tileCount, + video::SMaterial* material, + const core::dimension2d& textureRepeatCount) const + { + return createHillPlaneMesh(tileSize, tileCount, material, 0.f, core::dimension2df(), textureRepeatCount); + } + //! Create a terrain mesh from an image representing a heightfield. /** \param texture The texture to apply to the terrain. diff --git a/include/IMaterialRendererServices.h b/include/IMaterialRendererServices.h index fc726486..df6ff8ba 100644 --- a/include/IMaterialRendererServices.h +++ b/include/IMaterialRendererServices.h @@ -5,7 +5,6 @@ #ifndef __I_MATERIAL_RENDERER_SERVICES_H_INCLUDED__ #define __I_MATERIAL_RENDERER_SERVICES_H_INCLUDED__ -#include "IReferenceCounted.h" #include "SMaterial.h" #include "S3DVertex.h" diff --git a/include/IMeshBuffer.h b/include/IMeshBuffer.h index 6a5e8ad9..6054d0ab 100644 --- a/include/IMeshBuffer.h +++ b/include/IMeshBuffer.h @@ -11,51 +11,12 @@ #include "S3DVertex.h" #include "SVertexIndex.h" #include "EHardwareBufferFlags.h" +#include "EPrimitiveTypes.h" namespace irr { namespace scene { - - //! Enumeration for all primitive types there are. - enum E_PRIMITIVE_TYPE - { - //! All vertices are non-connected points. - EPT_POINTS=0, - - //! All vertices form a single connected line. - EPT_LINE_STRIP, - - //! Just as LINE_STRIP, but the last and the first vertex is also connected. - EPT_LINE_LOOP, - - //! Every two vertices are connected creating n/2 lines. - EPT_LINES, - - //! After the first two vertices each vertex defines a new triangle. - //! Always the two last and the new one form a new triangle. - EPT_TRIANGLE_STRIP, - - //! After the first two vertices each vertex defines a new triangle. - //! All around the common first vertex. - EPT_TRIANGLE_FAN, - - //! Explicitly set all vertices for each triangle. - EPT_TRIANGLES, - - //! After the first two vertices each further tw vetices create a quad with the preceding two. - EPT_QUAD_STRIP, - - //! Every four vertices create a quad. - EPT_QUADS, - - //! Just as LINE_LOOP, but filled. - EPT_POLYGON, - - //! The single vertices are expanded to quad billboards on the GPU. - EPT_POINT_SPRITES - }; - //! Struct for holding a mesh with a single material. /** A part of an IMesh which has the same material on each face of that group. Logical groups of an IMesh need not be put into separate mesh diff --git a/include/IMeshCache.h b/include/IMeshCache.h index 6747b74e..5d470feb 100644 --- a/include/IMeshCache.h +++ b/include/IMeshCache.h @@ -42,12 +42,12 @@ namespace scene with one call. They can add additional meshes with this method to the scene manager. The COLLADA loader for example uses this method. - \param filename Filename of the mesh. When calling + \param name Name of the mesh. When calling ISceneManager::getMesh() with this name it will return the mesh set by this method. \param mesh Pointer to a mesh which will now be referenced by this name. */ - virtual void addMesh(const io::path& filename, IAnimatedMesh* mesh) = 0; + virtual void addMesh(const io::path& name, IAnimatedMesh* mesh) = 0; //! Removes a mesh from the cache. /** After loading a mesh with getMesh(), the mesh can be @@ -67,7 +67,7 @@ namespace scene /** You can load new meshes into the cache using getMesh() and addMesh(). If you ever need to access the internal mesh cache, you can do this using removeMesh(), getMeshNumber(), - getMeshByIndex() and getMeshFilename(). + getMeshByIndex() and getMeshName(). \return Number of meshes in cache. */ virtual u32 getMeshCount() const = 0; @@ -90,60 +90,106 @@ namespace scene number. */ virtual IAnimatedMesh* getMeshByIndex(u32 index) = 0; - //! Returns a mesh based on its filename. - /** \param filename Name of the mesh. + //! Returns a mesh based on its name (often a filename). + /** \deprecated Use getMeshByName() instead. */ + _IRR_DEPRECATED_ IAnimatedMesh* getMeshByFilename(const io::path& filename) + { + return getMeshByName(filename); + } + + //! Get the name of a loaded mesh, based on its index. (Name is often identical to the filename). + /** \deprecated Use getMeshName() instead. */ + _IRR_DEPRECATED_ const io::path& getMeshFilename(u32 index) const + { + return getMeshName(index).getInternalName(); + } + + //! Get the name of a loaded mesh, if there is any. (Name is often identical to the filename). + /** \deprecated Use getMeshName() instead. */ + _IRR_DEPRECATED_ const io::path& getMeshFilename(const IAnimatedMesh* const mesh) const + { + return getMeshName(mesh).getInternalName(); + } + + //! Get the name of a loaded mesh, if there is any. (Name is often identical to the filename). + /** \deprecated Use getMeshName() instead. */ + _IRR_DEPRECATED_ const io::path& getMeshFilename(const IMesh* const mesh) const + { + return getMeshName(mesh).getInternalName(); + } + + //! Renames a loaded mesh. + /** \deprecated Use renameMesh() instead. */ + _IRR_DEPRECATED_ bool setMeshFilename(u32 index, const io::path& filename) + { + return renameMesh(index, filename); + } + + //! Renames a loaded mesh. + /** \deprecated Use renameMesh() instead. */ + _IRR_DEPRECATED_ bool setMeshFilename(const IAnimatedMesh* const mesh, const io::path& filename) + { + return renameMesh(mesh, filename); + } + + //! Renames a loaded mesh. + /** \deprecated Use renameMesh() instead. */ + _IRR_DEPRECATED_ bool setMeshFilename(const IMesh* const mesh, const io::path& filename) + { + return renameMesh(mesh, filename); + } + + //! Returns a mesh based on its name. + /** \param name Name of the mesh. Usually a filename. \return Pointer to the mesh or 0 if there is none with this number. */ - virtual IAnimatedMesh* getMeshByFilename(const io::path& filename) = 0; + virtual IAnimatedMesh* getMeshByName(const io::path& name) = 0; - //! Get the filename of a loaded mesh, based on its index. + //! Get the name of a loaded mesh, based on its index. /** \param index: Index of the mesh, number between 0 and getMeshCount()-1. - \return String with name if mesh was found and has a name, else - 0. */ - virtual const io::path& getMeshFilename(u32 index) const = 0; + \return The name if mesh was found and has a name, else the path is empty. */ + virtual const io::SNamedPath& getMeshName(u32 index) const = 0; - //! Get the filename of a loaded mesh, if there is any. + //! Get the name of a loaded mesh, if there is any. /** \param mesh Pointer to mesh to query. - \return String with name if mesh was found and has a name, else - 0. */ - virtual const io::path& getMeshFilename(const IAnimatedMesh* const mesh) const = 0; + \return The name if mesh was found and has a name, else the path is empty. */ + virtual const io::SNamedPath& getMeshName(const IAnimatedMesh* const mesh) const = 0; - //! Get the filename of a loaded mesh, if there is any. + //! Get the name of a loaded mesh, if there is any. /** \param mesh Pointer to mesh to query. - \return String with name if mesh was found and has a name, else - 0. */ - virtual const io::path& getMeshFilename(const IMesh* const mesh) const = 0; + \return The name if mesh was found and has a name, else the path is empty. */ + virtual const io::SNamedPath& getMeshName(const IMesh* const mesh) const = 0; //! Renames a loaded mesh. /** Note that renaming meshes might change the ordering of the meshes, and so the index of the meshes as returned by getMeshIndex() or taken by some methods will change. \param index The index of the mesh in the cache. - \param filename New name for the mesh. + \param name New name for the mesh. \return True if mesh was renamed. */ - virtual bool setMeshFilename(u32 index, const io::path& filename) = 0; + virtual bool renameMesh(u32 index, const io::path& name) = 0; //! Renames a loaded mesh. /** Note that renaming meshes might change the ordering of the meshes, and so the index of the meshes as returned by getMeshIndex() or taken by some methods will change. \param mesh Mesh to be renamed. - \param filename New name for the mesh. + \param name New name for the mesh. \return True if mesh was renamed. */ - virtual bool setMeshFilename(const IAnimatedMesh* const mesh, const io::path& filename) = 0; + virtual bool renameMesh(const IAnimatedMesh* const mesh, const io::path& name) = 0; //! Renames a loaded mesh. /** Note that renaming meshes might change the ordering of the meshes, and so the index of the meshes as returned by getMeshIndex() or taken by some methods will change. \param mesh Mesh to be renamed. - \param filename New name for the mesh. + \param name New name for the mesh. \return True if mesh was renamed. */ - virtual bool setMeshFilename(const IMesh* const mesh, const io::path& filename) = 0; + virtual bool renameMesh(const IMesh* const mesh, const io::path& name) = 0; //! Check if a mesh was already loaded. - /** \param filename Name of the mesh. + /** \param name Name of the mesh. Usually a filename. \return True if the mesh has been loaded, else false. */ - virtual bool isMeshLoaded(const io::path& filename) = 0; + virtual bool isMeshLoaded(const io::path& name) = 0; //! Clears the whole mesh cache, removing all meshes. /** All meshes will be reloaded completely when using ISceneManager::getMesh() diff --git a/include/IMeshManipulator.h b/include/IMeshManipulator.h index 5a7230a2..f3ab3a0b 100644 --- a/include/IMeshManipulator.h +++ b/include/IMeshManipulator.h @@ -259,9 +259,9 @@ namespace scene if (boundingBoxUpdate) { if (0==i) - bufferbox.reset(mesh->getBoundingBox()); + bufferbox.reset(mesh->getMeshBuffer(i)->getBoundingBox()); else - bufferbox.addInternalBox(mesh->getBoundingBox()); + bufferbox.addInternalBox(mesh->getMeshBuffer(i)->getBoundingBox()); } } if (boundingBoxUpdate) diff --git a/include/IQ3Shader.h b/include/IQ3Shader.h index e00b57b1..02dd7b3e 100644 --- a/include/IQ3Shader.h +++ b/include/IQ3Shader.h @@ -782,7 +782,7 @@ namespace quake3 textures.clear(); - core::stringc loadFile; + io::path loadFile; for ( u32 i = 0; i!= stringList.size (); ++i ) { video::ITexture* texture = 0; diff --git a/include/ISceneCollisionManager.h b/include/ISceneCollisionManager.h index e8093b0d..9b750a5b 100644 --- a/include/ISceneCollisionManager.h +++ b/include/ISceneCollisionManager.h @@ -25,14 +25,14 @@ namespace scene { public: - //! Finds the collision point of a line and lots of triangles, if there is one. + //! Finds the nearest collision point of a line and lots of triangles, if there is one. /** \param ray: Line with which collisions are tested. \param selector: TriangleSelector containing the triangles. It can be created for example using ISceneManager::createTriangleSelector() or - ISceneManager::createTriangleOctTreeSelector(). + ISceneManager::createTriangleOctreeSelector(). \param outCollisionPoint: If a collision is detected, this will - contain the position of the nearest collision. + contain the position of the nearest collision to the line-start. \param outTriangle: If a collision is detected, this will contain the triangle with which the ray collided. \param outNode: If a collision is detected, this will contain @@ -51,7 +51,7 @@ namespace scene \param selector: TriangleSelector containing the triangles of the world. It can be created for example using ISceneManager::createTriangleSelector() or - ISceneManager::createTriangleOctTreeSelector(). + ISceneManager::createTriangleOctreeSelector(). \param ellipsoidPosition: Position of the ellipsoid. \param ellipsoidRadius: Radius of the ellipsoid. \param ellipsoidDirectionAndSpeed: Direction and speed of the @@ -143,8 +143,8 @@ namespace scene against this ray. The collision tests are done using a bounding box for each scene node. \param camera: Camera from which the ray is casted. - \param idBitMask: Only scene nodes with an id which matches at least one of the - bits contained in this mask will be tested. However, if this parameter is 0, then + \param idBitMask: Only scene nodes with an id which matches at least one of the + bits contained in this mask will be tested. However, if this parameter is 0, then all nodes are checked. feature is disabled. Please note that the default node id of -1 will match with @@ -158,33 +158,33 @@ namespace scene s32 idBitMask=0, bool bNoDebugObjects = false) = 0; //! Perform a ray/box and ray/triangle collision check on a heirarchy of scene nodes. - /** This checks all scene nodes under the specified one, first by ray/bounding + /** This checks all scene nodes under the specified one, first by ray/bounding box, and then by accurate ray/triangle collision, finding the nearest collision, - and the scene node containg it. It returns the node hit, and (via output + and the scene node containg it. It returns the node hit, and (via output parameters) the position of the collision, and the triangle that was hit. All scene nodes in the hierarchy tree under the specified node are checked. Only - notes that are visible, with an ID that matches at least one bit in the supplied + notes that are visible, with an ID that matches at least one bit in the supplied bitmask, and which have a triangle selector are considered as candidates for being hit. - You do not have to build a meta triangle selector; the individual triangle selectors + You do not have to build a meta triangle selector; the individual triangle selectors of each candidate scene node are used automatically. - + \param ray: Line with which collisions are tested. \param outCollisionPoint: If a collision is detected, this will contain the position of the nearest collision. \param outTriangle: If a collision is detected, this will contain the triangle with which the ray collided. - \param idBitMask: Only scene nodes with an id which matches at least one of the - bits contained in this mask will be tested. However, if this parameter is 0, then + \param idBitMask: Only scene nodes with an id which matches at least one of the + bits contained in this mask will be tested. However, if this parameter is 0, then all nodes are checked. \param collisionRootNode: the scene node at which to begin checking. Only this - node and its children will be checked. If you want to check the entire scene, + node and its children will be checked. If you want to check the entire scene, pass 0, and the root scene node will be used (this is the default). \param noDebugObjects: when true, debug objects are not considered viable targets. Debug objects are scene nodes with IsDebugObject() = true. \return Returns the scene node containing the hit triangle nearest to ray.start. If no collision is detected, then 0 is returned. */ - virtual ISceneNode* getSceneNodeAndCollisionPointFromRay( + virtual ISceneNode* getSceneNodeAndCollisionPointFromRay( core::line3df ray, core::vector3df & outCollisionPoint, core::triangle3df & outTriangle, diff --git a/include/ISceneManager.h b/include/ISceneManager.h index e73414e5..f6b65b7c 100644 --- a/include/ISceneManager.h +++ b/include/ISceneManager.h @@ -132,7 +132,7 @@ namespace scene //! 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 - like the Octree (addOctTreeSceneNode()) or the terrain renderer + like the Octree (addOctreeSceneNode()) or the terrain renderer (addTerrainSceneNode()), different Camera scene nodes (addCameraSceneNode(), addCameraSceneNodeMaya()), scene nodes for Light (addLightSceneNode()), Billboards (addBillboardSceneNode()) and so on. @@ -493,38 +493,54 @@ namespace scene const core::vector3df& scale = core::vector3df(1.0f, 1.0f, 1.0f)) = 0; - //! Adds a scene node for rendering using a octtree to the scene graph. + //! Adds a scene node for rendering using a octree to the scene graph. /** This a good method for rendering scenes with lots of geometry. The Octree is built on the fly from the mesh. - \param mesh: The mesh containing all geometry from which the octtree will be build. + \param mesh: The mesh containing all geometry from which the octree will be build. If this animated mesh has more than one frames in it, the first frame is taken. - \param parent: Parent node of the octtree node. + \param parent: Parent node of the octree node. \param id: id of the node. This id can be used to identify the node. \param minimalPolysPerNode: Specifies the minimal polygons contained a octree node. If a node gets less polys than this value it will not be split into smaller nodes. \param alsoAddIfMeshPointerZero: Add the scene node even if a 0 pointer is passed. - \return Pointer to the OctTree if successful, otherwise 0. + \return Pointer to the Octree if successful, otherwise 0. This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ - virtual IMeshSceneNode* addOctTreeSceneNode(IAnimatedMesh* mesh, ISceneNode* parent=0, + virtual IMeshSceneNode* addOctreeSceneNode(IAnimatedMesh* mesh, ISceneNode* parent=0, s32 id=-1, s32 minimalPolysPerNode=512, bool alsoAddIfMeshPointerZero=false) = 0; - //! Adds a scene node for rendering using a octtree to the scene graph. + //! Adds a scene node for rendering using a octree to the scene graph. + /** \deprecated Use addOctreeSceneNode instead. */ + _IRR_DEPRECATED_ IMeshSceneNode* addOctTreeSceneNode(IAnimatedMesh* mesh, ISceneNode* parent=0, + s32 id=-1, s32 minimalPolysPerNode=512, bool alsoAddIfMeshPointerZero=false) + { + return addOctreeSceneNode(mesh, parent, id, minimalPolysPerNode, alsoAddIfMeshPointerZero); + } + + //! Adds a scene node for rendering using a octree to the scene graph. /** This a good method for rendering scenes with lots of geometry. The Octree is built on the fly from the mesh, much faster then a bsp tree. - \param mesh: The mesh containing all geometry from which the octtree will be build. - \param parent: Parent node of the octtree node. + \param mesh: The mesh containing all geometry from which the octree will be build. + \param parent: Parent node of the octree node. \param id: id of the node. This id can be used to identify the node. \param minimalPolysPerNode: Specifies the minimal polygons contained a octree node. If a node gets less polys than this value it will not be split into smaller nodes. \param alsoAddIfMeshPointerZero: Add the scene node even if a 0 pointer is passed. - \return Pointer to the octtree if successful, otherwise 0. + \return Pointer to the octree if successful, otherwise 0. This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ - virtual IMeshSceneNode* addOctTreeSceneNode(IMesh* mesh, ISceneNode* parent=0, + virtual IMeshSceneNode* addOctreeSceneNode(IMesh* mesh, ISceneNode* parent=0, s32 id=-1, s32 minimalPolysPerNode=256, bool alsoAddIfMeshPointerZero=false) = 0; + //! Adds a scene node for rendering using a octree to the scene graph. + /** \deprecated Use addOctreeSceneNode instead. */ + _IRR_DEPRECATED_ IMeshSceneNode* addOctTreeSceneNode(IMesh* mesh, ISceneNode* parent=0, + s32 id=-1, s32 minimalPolysPerNode=256, bool alsoAddIfMeshPointerZero=false) + { + return addOctreeSceneNode(mesh, parent, id, minimalPolysPerNode, alsoAddIfMeshPointerZero); + } + //! Adds a camera scene node to the scene graph and sets it as active camera. /** This camera does not react on user input like for example the one created with addCameraSceneNodeFPS(). If you want to move or animate it, use animators or the @@ -841,7 +857,7 @@ namespace scene /** 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(IMeshBuffer* meshBuffer, const quake3::IShader * shader, + virtual IMeshSceneNode* addQuake3SceneNode(const IMeshBuffer* meshBuffer, const quake3::IShader * shader, ISceneNode* parent=0, s32 id=-1 ) = 0; @@ -981,6 +997,10 @@ namespace scene //! Add a volume light mesh to the meshpool /** \param name Name of the mesh + \param SubdivideU Horizontal subdivision count + \param SubdivideV Vertical subdivision count + \param FootColor Color of the bottom of the light + \param TailColor Color of the top of the light \return Pointer to the volume light mesh if successful, otherwise 0. This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ @@ -1188,13 +1208,13 @@ namespace scene See IReferenceCounted::drop() for more information. */ virtual ISceneNodeAnimator* createFollowSplineAnimator(s32 startTime, const core::array< core::vector3df >& points, - f32 speed = 1.0f, f32 tightness = 0.5f) = 0; + f32 speed = 1.0f, f32 tightness = 0.5f, bool loop=true, bool pingpong=false) = 0; //! Creates a simple ITriangleSelector, based on a mesh. /** Triangle selectors can be used for doing collision detection. Don't use this selector for a huge amount of triangles like in Quake3 maps. - Instead, use for example ISceneManager::createOctTreeTriangleSelector(). + Instead, use for example ISceneManager::createOctreeTriangleSelector(). Please note that the created triangle selector is not automaticly attached to the scene node. You will have to call ISceneNode::setTriangleSelector() for this. To create and attach a triangle selector is done like this: @@ -1231,15 +1251,15 @@ namespace scene See IReferenceCounted::drop() for more information. */ virtual ITriangleSelector* createTriangleSelectorFromBoundingBox(ISceneNode* node) = 0; - //! Creates a Triangle Selector, optimized by an octtree. + //! Creates a Triangle Selector, optimized by an octree. /** Triangle selectors can be used for doing collision detection. This triangle selector is - optimized for huge amounts of triangle, it organizes them in an octtree. + optimized for huge amounts of triangle, it organizes them in an octree. Please note that the created triangle selector is not automaticly attached to the scene node. You will have to call ISceneNode::setTriangleSelector() for this. To create and attach a triangle selector is done like this: \code - ITriangleSelector* s = sceneManager->createOctTreeTriangleSelector(yourMesh, + ITriangleSelector* s = sceneManager->createOctreeTriangleSelector(yourMesh, yourSceneNode); yourSceneNode->setTriangleSelector(s); s->drop(); @@ -1254,9 +1274,17 @@ namespace scene \return The selector, or null if not successful. If you no longer need the selector, you should call ITriangleSelector::drop(). See IReferenceCounted::drop() for more information. */ - virtual ITriangleSelector* createOctTreeTriangleSelector(IMesh* mesh, + virtual ITriangleSelector* createOctreeTriangleSelector(IMesh* mesh, ISceneNode* node, s32 minimalPolysPerNode=32) = 0; + //! //! Creates a Triangle Selector, optimized by an octree. + /** \deprecated Use createOctreeTriangleSelector instead. */ + _IRR_DEPRECATED_ ITriangleSelector* createOctTreeTriangleSelector(IMesh* mesh, + ISceneNode* node, s32 minimalPolysPerNode=32) + { + return createOctreeTriangleSelector(mesh, node, minimalPolysPerNode); + } + //! Creates a meta triangle selector. /** A meta triangle selector is nothing more than a collection of one or more triangle selectors providing together diff --git a/include/ISceneNode.h b/include/ISceneNode.h index a82fe77a..5e4c7a50 100644 --- a/include/ISceneNode.h +++ b/include/ISceneNode.h @@ -120,7 +120,7 @@ namespace scene ISceneNodeAnimator* anim = *ait; ++ait; anim->animateNode(this, timeMs); - } + } // update absolute position updateAbsolutePosition(); @@ -289,7 +289,9 @@ namespace scene //! Removes a child from this scene node. - /** \param child A pointer to the new child. + /** If found in the children list, the child pointer is also + dropped and might be deleted if no other grab exists. + \param child A pointer to the child which shall be removed. \return True if the child was removed, and false if not, e.g. because it couldn't be found in the children list. */ virtual bool removeChild(ISceneNode* child) @@ -310,6 +312,9 @@ namespace scene //! Removes all children of this scene node + /** The scene nodes found in the children list are also dropped + and might be deleted if no other grab exists on them. + */ virtual void removeAll() { ISceneNodeList::Iterator it = Children.begin(); @@ -323,7 +328,9 @@ namespace scene } - //! Removes this scene node from the scene, deleting it. + //! Removes this scene node from the scene + /** If no other grab exists for this node, it will be deleted. + */ virtual void remove() { if (Parent) @@ -352,21 +359,27 @@ namespace scene //! Removes an animator from this scene node. - /** \param animator A pointer to the animator to be deleted. */ + /** If the animator is found, it is also dropped and might be + deleted if not other grab exists for it. + \param animator A pointer to the animator to be deleted. */ virtual void removeAnimator(ISceneNodeAnimator* animator) { ISceneNodeAnimatorList::Iterator it = Animators.begin(); for (; it != Animators.end(); ++it) + { if ((*it) == animator) { (*it)->drop(); Animators.erase(it); return; } + } } //! Removes all animators from this scene node. + /** The animators might also be deleted if no other grab exists + for them. */ virtual void removeAnimators() { ISceneNodeAnimatorList::Iterator it = Animators.begin(); @@ -435,8 +448,8 @@ namespace scene //! Gets the scale of the scene node relative to its parent. - /** This is the scale of this node relative to its parent. - If you want the absolute scale, use + /** This is the scale of this node relative to its parent. + If you want the absolute scale, use getAbsoluteTransformation().getScale() \return The scale of the scene node. */ virtual const core::vector3df& getScale() const @@ -524,7 +537,7 @@ namespace scene //! Sets if debug data like bounding boxes should be drawn. - /** A bitwise OR of the types from @ref irr::scene::E_DEBUG_SCENE_TYPE. + /** A bitwise OR of the types from @ref irr::scene::E_DEBUG_SCENE_TYPE. Please note that not all scene nodes support all debug data types. \param state The debug data visibility state to be used. */ virtual void setDebugDataVisible(s32 state) @@ -533,7 +546,7 @@ namespace scene } //! Returns if debug data like bounding boxes are drawn. - /** \return A bitwise OR of the debug data values from + /** \return A bitwise OR of the debug data values from @ref irr::scene::E_DEBUG_SCENE_TYPE that are currently visible. */ s32 isDebugDataVisible() const { @@ -589,7 +602,7 @@ namespace scene /** The Selector can be used by the engine for doing collision detection. You can create a TriangleSelector with ISceneManager::createTriangleSelector() or - ISceneManager::createOctTreeTriangleSelector and set it with + ISceneManager::createOctreeTriangleSelector and set it with ISceneNode::setTriangleSelector(). If a scene node got no triangle selector, but collision tests should be done with it, a triangle selector is created using the bounding box of the scene node. @@ -605,7 +618,7 @@ namespace scene /** The Selector can be used by the engine for doing collision detection. You can create a TriangleSelector with ISceneManager::createTriangleSelector() or - ISceneManager::createOctTreeTriangleSelector(). Some nodes may + ISceneManager::createOctreeTriangleSelector(). Some nodes may create their own selector by default, so it would be good to check if there is already a selector in this node by calling ISceneNode::getTriangleSelector(). @@ -625,7 +638,7 @@ namespace scene //! Updates the absolute position based on the relative and the parents position - /** Note: This does not recursively update the parents absolute positions, so if you have a deeper + /** Note: This does not recursively update the parents absolute positions, so if you have a deeper hierarchy you might want to update the parents first.*/ virtual void updateAbsolutePosition() { diff --git a/include/ISkinnedMesh.h b/include/ISkinnedMesh.h index 2c8b5bb6..fe59f025 100644 --- a/include/ISkinnedMesh.h +++ b/include/ISkinnedMesh.h @@ -17,7 +17,7 @@ namespace scene enum E_INTERPOLATION_MODE { - // constant interpolation + // constant does use the current key-values without interpolation EIM_CONSTANT = 0, // linear interpolation diff --git a/include/ITexture.h b/include/ITexture.h index f4ae1427..63664002 100644 --- a/include/ITexture.h +++ b/include/ITexture.h @@ -85,9 +85,8 @@ class ITexture : public virtual IReferenceCounted public: //! constructor - ITexture(const io::path& name) : Name(name) + ITexture(const io::path& name) : NamedPath(name) { - Name.make_lower(); } //! Lock function. @@ -98,10 +97,12 @@ public: number of previous locks. \param readOnly Specifies that no changes to the locked texture are made. Unspecified behavior will arise if still write access happens. + \param mipmapLevel Number of the mipmapLevel to lock. 0 is main texture. + Non-existing levels will silently fail and return 0. \return Returns a pointer to the pixel data. The format of the pixel can be determined by using getColorFormat(). 0 is returned, if the texture cannot be locked. */ - virtual void* lock(bool readOnly = false) = 0; + virtual void* lock(bool readOnly = false, u32 mipmapLevel=0) = 0; //! Unlock function. Must be called after a lock() to the texture. /** One should avoid to call unlock more than once before another lock. */ @@ -149,14 +150,14 @@ public: //! Regenerates the mip map levels of the texture. /** Required after modifying the texture, usually after calling unlock(). */ - virtual void regenerateMipMapLevels() = 0; + virtual void regenerateMipMapLevels(void* mipmapData=0) = 0; //! Check whether the texture is a render target /** \return True if this is a render target, otherwise false. */ virtual bool isRenderTarget() const { return false; } //! Get name of texture (in most cases this is the filename) - const io::path& getName() const { return Name; } + const io::SNamedPath& getName() const { return NamedPath; } protected: @@ -176,7 +177,7 @@ protected: return ETCF_OPTIMIZED_FOR_SPEED; } - io::path Name; + io::SNamedPath NamedPath; }; diff --git a/include/IVideoDriver.h b/include/IVideoDriver.h index 6b948760..6c299780 100644 --- a/include/IVideoDriver.h +++ b/include/IVideoDriver.h @@ -18,6 +18,7 @@ #include "triangle3d.h" #include "EDriverTypes.h" #include "EDriverFeatures.h" +#include "SExposedVideoData.h" namespace irr { @@ -39,7 +40,6 @@ namespace video struct S3DVertex2TCoords; struct S3DVertexTangents; struct SLight; - struct SExposedVideoData; class IImageLoader; class IImageWriter; class IMaterialRenderer; @@ -106,6 +106,8 @@ namespace video ERT_FRAME_BUFFER=0, //! Render target is a render texture ERT_RENDER_TEXTURE, + //! Multi-Render target textures + ERT_MULTI_RENDER_TEXTURES, //! Render target is the main color frame buffer ERT_STEREO_LEFT_BUFFER, //! Render target is the right color buffer (left is the main buffer) @@ -247,9 +249,9 @@ namespace video be cleared. It is not nesesarry to do so if only 2d drawing is used. \param color The color used for back buffer clearing - \param windowId Handle of another window, if you want the - bitmap to be displayed on another window. If this is null, - everything will be displayed in the default window. + \param videoData Handle of another window, if you want the + bitmap to be displayed on another window. If this is an empty + element, everything will be displayed in the default window. Note: This feature is not fully implemented for all devices. \param sourceRect Pointer to a rectangle defining the source rectangle of the area to be presented. Set to null to present @@ -257,7 +259,7 @@ namespace video \return False if failed. */ virtual bool beginScene(bool backBuffer=true, bool zBuffer=true, SColor color=SColor(255,0,0,0), - void* windowId=0, + const SExposedVideoData& videoData=SExposedVideoData(), core::rect* sourceRect=0) =0; //! Presents the rendered image to the screen. @@ -380,10 +382,14 @@ namespace video /** \param name A name for the texture. Later calls of getTexture() with this name will return this texture \param image Image the texture is created from. + \param mipmapData Optional pointer to a set of images which + build up the whole mipmap set. Must be images of the same color + type as image. If this parameter is not given, the mipmaps are + derived from image. \return Pointer to the newly created texture. This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ - virtual ITexture* addTexture(const io::path& name, IImage* image) = 0; + virtual ITexture* addTexture(const io::path& name, IImage* image, void* mipmapData=0) = 0; //! Adds a new render target texture to the texture cache. /** \param size Size of the texture, in pixels. Width and @@ -784,8 +790,8 @@ namespace video The subtextures are defined by the array of sourceRects and are positioned using the array of positions. \param texture Texture to be drawn. - \param pos Array of upper left 2d destinations where the images - will be drawn. + \param positions Array of upper left 2d destinations where the + images will be drawn. \param sourceRects Source rectangles of the image. \param clipRect Pointer to rectangle on the screen where the images are clipped to. @@ -1137,7 +1143,7 @@ namespace video virtual IImage* createImage(ECOLOR_FORMAT format, const core::dimension2d& size) =0; //! Creates a software image by converting it to given format from another image. - /** + /** \deprecated Create an empty image and use copyTo() \param format Desired color format of the image. \param imageToCopy Image to copy to the new image. \return The created image. @@ -1146,7 +1152,7 @@ namespace video virtual IImage* createImage(ECOLOR_FORMAT format, IImage *imageToCopy) =0; //! Creates a software image from a part of another image. - /** + /** \deprecated Create an empty image and use copyTo() \param imageToCopy Image to copy to the new image in part. \param pos Position of rectangle to copy. \param size Extents of rectangle to copy. @@ -1317,6 +1323,27 @@ namespace video \return Reference to the Override Material. */ virtual SOverrideMaterial& getOverrideMaterial() =0; + //! Get the 2d override material for altering its values + /** The 2d override materual allows to alter certain render + states of the 2d methods. Not all members of SMaterial are + honored, especially not MaterialType and Textures. Moreover, + the zbuffer is always ignored, and lighting is always off. All + other flags can be changed, though some might have to effect + in most cases. + Please note that you have to enable/disable this effect with + enableInitMaterial2D(). This effect is costly, as it increases + the number of state changes considerably. Always reset the + values when done. + \return Material reference which should be altered to reflect + the new settings. + */ + virtual SMaterial& getMaterial2D() =0; + + //! Enable the 2d override material + /** \param enable Flag which tells whether the material shall be + enabled or disabled. */ + virtual void enableMaterial2D(bool enable=true) =0; + //! Returns the graphics card vendor name. virtual core::stringc getVendorInfo() =0; diff --git a/include/IWriteFile.h b/include/IWriteFile.h index bd68f45b..82e2a815 100644 --- a/include/IWriteFile.h +++ b/include/IWriteFile.h @@ -13,7 +13,7 @@ namespace irr namespace io { - //! Interface providing write acess to a file. + //! Interface providing write access to a file. class IWriteFile : public virtual IReferenceCounted { public: diff --git a/include/IrrCompileConfig.h b/include/IrrCompileConfig.h index e0be00f8..91af188e 100644 --- a/include/IrrCompileConfig.h +++ b/include/IrrCompileConfig.h @@ -8,11 +8,11 @@ //! Irrlicht SDK Version #define IRRLICHT_VERSION_MAJOR 1 #define IRRLICHT_VERSION_MINOR 7 -#define IRRLICHT_VERSION_REVISION 0-alpha +#define IRRLICHT_VERSION_REVISION 0 // This flag will be defined only in SVN, the official release code will have // it undefined -#define IRRLICHT_VERSION_SVN -#define IRRLICHT_SDK_VERSION "1.7.0-alpha" +#define IRRLICHT_VERSION_SVN -beta +#define IRRLICHT_SDK_VERSION "1.7.0-beta" #include // TODO: Although included elsewhere this is required at least for mingw @@ -37,6 +37,7 @@ //! _IRR_COMPILE_WITH_SDL_DEVICE_ for platform independent SDL framework //! _IRR_COMPILE_WITH_CONSOLE_DEVICE_ for no windowing system, used as a fallback //! _IRR_COMPILE_WITH_IPHONE_DEVICE_ for UIKit windowing on iPhoneOS (aka embeded OSX) +//! _IRR_COMPILE_WITH_FB_DEVICE_ for framebuffer systems //! Uncomment this line to compile with the SDL device @@ -199,18 +200,6 @@ disable this feature, the engine behave as before (ansi). This is currently only for Windows based systems. */ //#define _IRR_WCHAR_FILESYSTEM -//! Define _IRR_COMPILE_WITH_ZLIB_ to enable compiling the engine using zlib. -/** This enables the engine to read from compressed .zip archives. If you -disable this feature, the engine can still read archives, but only uncompressed -ones. */ -#define _IRR_COMPILE_WITH_ZLIB_ - -//! Define _IRR_USE_NON_SYSTEM_ZLIB_ to let irrlicht use the zlib which comes with irrlicht. -/** If this is commented out, Irrlicht will try to compile using the zlib installed in the system. - This is only used when _IRR_COMPILE_WITH_ZLIB_ is defined. */ -#define _IRR_USE_NON_SYSTEM_ZLIB_ - - //! Define _IRR_COMPILE_WITH_JPEGLIB_ to enable compiling the engine using libjpeg. /** This enables the engine to read jpeg images. If you comment this out, the engine will no longer read .jpeg images. */ @@ -379,7 +368,37 @@ B3D, MS3D or X meshes */ #define _IRR_COMPILE_WITH_TGA_WRITER_ //! Define __IRR_COMPILE_WITH_ZIP_ARCHIVE_LOADER_ if you want to open ZIP and GZIP archives +/** ZIP reading has several more options below to configure. */ #define __IRR_COMPILE_WITH_ZIP_ARCHIVE_LOADER_ +#ifdef __IRR_COMPILE_WITH_ZIP_ARCHIVE_LOADER_ +//! Define _IRR_COMPILE_WITH_ZLIB_ to enable compiling the engine using zlib. +/** This enables the engine to read from compressed .zip archives. If you +disable this feature, the engine can still read archives, but only uncompressed +ones. */ +#define _IRR_COMPILE_WITH_ZLIB_ +//! Define _IRR_USE_NON_SYSTEM_ZLIB_ to let irrlicht use the zlib which comes with irrlicht. +/** If this is commented out, Irrlicht will try to compile using the zlib +installed on the system. This is only used when _IRR_COMPILE_WITH_ZLIB_ is +defined. */ +#define _IRR_USE_NON_SYSTEM_ZLIB_ +//! Define _IRR_COMPILE_WITH_ZIP_ENCRYPTION_ if you want to read AES-encrypted ZIP archives +#define _IRR_COMPILE_WITH_ZIP_ENCRYPTION_ +//! Define _IRR_COMPILE_WITH_BZIP2_ if you want to support bzip2 compressed zip archives +/** bzip2 is superior to the original zip file compression modes, but requires +a certain amount of memory for decompression and adds several files to the +library. */ +#define _IRR_COMPILE_WITH_BZIP2_ +//! Define _IRR_USE_NON_SYSTEM_BZLIB_ to let irrlicht use the bzlib which comes with irrlicht. +/** If this is commented out, Irrlicht will try to compile using the bzlib +installed on the system. This is only used when _IRR_COMPILE_WITH_BZLIB_ is +defined. */ +#define _IRR_USE_NON_SYSTEM_BZLIB_ +//! Define _IRR_COMPILE_WITH_LZMA_ if you want to use LZMA compressed zip files. +/** LZMA is a very efficient compression code, known from 7zip. Irrlicht +currently only supports zip archives, though. */ +#define _IRR_COMPILE_WITH_LZMA_ +#endif + //! Define __IRR_COMPILE_WITH_MOUNT_ARCHIVE_LOADER_ if you want to mount folders as archives #define __IRR_COMPILE_WITH_MOUNT_ARCHIVE_LOADER_ //! Define __IRR_COMPILE_WITH_PAK_ARCHIVE_LOADER_ if you want to open ID software PAK archives diff --git a/include/IrrlichtDevice.h b/include/IrrlichtDevice.h index 7ab6f844..5c003b5a 100644 --- a/include/IrrlichtDevice.h +++ b/include/IrrlichtDevice.h @@ -179,8 +179,8 @@ namespace irr \return String which contains the version. */ virtual const c8* getVersion() const = 0; - //! Sets a new user event receiver which will receive events from the engine. - /** Return true in IEventReceiver::OnEvent to prevent the event from continuing along + //! Sets a new user event receiver which will receive events from the engine. + /** Return true in IEventReceiver::OnEvent to prevent the event from continuing along the chain of event receivers. The path that an event takes through the system depends on its type. See irr::EEVENT_TYPE for details. \param receiver New receiver to be used. */ @@ -221,7 +221,7 @@ namespace irr //! Activate any joysticks, and generate events for them. /** Irrlicht contains support for joysticks, but does not generate joystick events by default, - as this would consume joystick info that 3rd party libraries might rely on. Call this method to + as this would consume joystick info that 3rd party libraries might rely on. Call this method to activate joystick support in Irrlicht and to receive irr::SJoystickEvent events. \param joystickInfo On return, this will contain an array of each joystick that was found and activated. \return true if joysticks are supported on this device and _IRR_COMPILE_WITH_JOYSTICK_EVENTS_ @@ -237,6 +237,18 @@ namespace irr virtual bool getGammaRamp(f32 &red, f32 &green, f32 &blue, f32 &brightness, f32 &contrast) =0; + //! Remove messages pending in the system message loop + /** This function is usually used after messages have been buffered for a longer time, for example + when loading a large scene. Clearing the message loop prevents that mouse- or buttonclicks which users + have pressed in the meantime will now trigger unexpected actions in the gui.
+ So far the following messages are cleared:
+ Win32: All keyboard and mouse messages
+ Linux: All keyboard and mouse messages
+ All other devices are not yet supported here.
+ The function is still somewhat experimental, as the kind of messages we clear is based on just a few use-cases. + If you think further messages should be cleared, or some messages should not be cleared here, then please tell us. */ + virtual void clearSystemMessages() = 0; + //! Get the type of the device. /** This allows the user to check which windowing system is currently being used. */ diff --git a/include/SExposedVideoData.h b/include/SExposedVideoData.h index d90130cb..81feccc3 100644 --- a/include/SExposedVideoData.h +++ b/include/SExposedVideoData.h @@ -24,6 +24,9 @@ you are using the software or the null device. */ struct SExposedVideoData { + SExposedVideoData() {OpenGLWin32.HDc=0; OpenGLWin32.HRc=0; OpenGLWin32.HWnd=0;} + explicit SExposedVideoData(void* Window) {OpenGLWin32.HDc=0; OpenGLWin32.HRc=0; OpenGLWin32.HWnd=Window;} + union { struct diff --git a/include/SIrrCreationParameters.h b/include/SIrrCreationParameters.h index ed34a7f0..b7bdd0fe 100644 --- a/include/SIrrCreationParameters.h +++ b/include/SIrrCreationParameters.h @@ -8,6 +8,7 @@ #include "EDriverTypes.h" #include "EDeviceTypes.h" #include "dimension2d.h" +#include "ILogger.h" namespace irr { @@ -35,6 +36,7 @@ namespace irr HighPrecisionFPU(false), EventReceiver(0), WindowId(0), + LoggingLevel(ELL_INFORMATION), SDK_version_do_not_use(IRRLICHT_SDK_VERSION) { } @@ -61,6 +63,7 @@ namespace irr HighPrecisionFPU = other.HighPrecisionFPU; EventReceiver = other.EventReceiver; WindowId = other.WindowId; + LoggingLevel = other.LoggingLevel; return *this; } @@ -228,6 +231,14 @@ namespace irr do it how you like. */ void* WindowId; + //! Specifies the logging level used in the logging interface. + /** The default value is ELL_INFORMATION. You can access the ILogger interface + later on from the IrrlichtDevice with getLogger() and set another level. + But if you need more or less logging information already from device creation, + then you have to change it here. + */ + ELOG_LEVEL LoggingLevel; + //! Don't use or change this parameter. /** Always set it to IRRLICHT_SDK_VERSION, which is done by default. This is needed for sdk version checks. */ diff --git a/include/SMaterial.h b/include/SMaterial.h index f0bc5ebb..9f5435fe 100644 --- a/include/SMaterial.h +++ b/include/SMaterial.h @@ -100,7 +100,7 @@ namespace video /** alpha source can be an OR'ed combination of E_ALPHA_SOURCE values. */ inline f32 pack_texureBlendFunc ( const E_BLEND_FACTOR srcFact, const E_BLEND_FACTOR dstFact, const E_MODULATE_FUNC modulate=EMFN_MODULATE_1X, const u32 alphaSource=EAS_TEXTURE ) { - const u32 tmp = (alphaSource << 24) | (modulate << 16) | (srcFact << 8) | dstFact; + const u32 tmp = (alphaSource << 12) | (modulate << 8) | (srcFact << 4) | dstFact; return FR(tmp); } @@ -110,10 +110,10 @@ namespace video E_MODULATE_FUNC &modulo, u32& alphaSource, const f32 param ) { const u32 state = IR(param); - alphaSource = (state & 0xFF000000) >> 24; - modulo = E_MODULATE_FUNC( ( state & 0x00FF0000 ) >> 16 ); - srcFact = E_BLEND_FACTOR ( ( state & 0x0000FF00 ) >> 8 ); - dstFact = E_BLEND_FACTOR ( ( state & 0x000000FF ) ); + alphaSource = (state & 0x0000F000) >> 12; + modulo = E_MODULATE_FUNC( ( state & 0x00000F00 ) >> 8 ); + srcFact = E_BLEND_FACTOR ( ( state & 0x000000F0 ) >> 4 ); + dstFact = E_BLEND_FACTOR ( ( state & 0x0000000F ) ); } //! EMT_ONETEXTURE_BLEND: has BlendFactor Alphablending @@ -194,7 +194,7 @@ namespace video : MaterialType(EMT_SOLID), AmbientColor(255,255,255,255), DiffuseColor(255,255,255,255), EmissiveColor(0,0,0,0), SpecularColor(255,255,255,255), Shininess(0.0f), MaterialTypeParam(0.0f), MaterialTypeParam2(0.0f), Thickness(1.0f), - ZBuffer(ECFN_LESSEQUAL), AntiAliasing(EAAM_SIMPLE|EAAM_LINE_SMOOTH), ColorMask(ECP_ALL), + ZBuffer(ECFN_LESSEQUAL), AntiAliasing(EAAM_SIMPLE), ColorMask(ECP_ALL), ColorMaterial(ECM_DIFFUSE), Wireframe(false), PointCloud(false), GouraudShading(true), Lighting(true), ZWriteEnable(true), BackfaceCulling(true), FrontfaceCulling(false), FogEnable(false), NormalizeNormals(false) diff --git a/include/SViewFrustum.h b/include/SViewFrustum.h index 08eae824..6c97c26f 100644 --- a/include/SViewFrustum.h +++ b/include/SViewFrustum.h @@ -78,10 +78,10 @@ namespace scene //! recalculates the bounding box member based on the planes inline void recalculateBoundingBox(); - //! update the given state's matrix based on video::E_TRANSFORMATION_STATE + //! get the given state's matrix based on frustum E_TRANSFORMATION_STATE core::matrix4& getTransform( video::E_TRANSFORMATION_STATE state); - //! get the given state's matrix based on frustum E_TRANSFORMATION_STATE_FRUSTUM + //! get the given state's matrix based on frustum E_TRANSFORMATION_STATE const core::matrix4& getTransform( video::E_TRANSFORMATION_STATE state) const; //! clips a line to the view frustum. diff --git a/include/SceneParameters.h b/include/SceneParameters.h index 96088071..2dbe69f5 100644 --- a/include/SceneParameters.h +++ b/include/SceneParameters.h @@ -111,6 +111,14 @@ namespace scene const c8* const DMF_FLIP_ALPHA_TEXTURES = "DMF_FlipAlpha"; + //! Name of the parameter for changing the texture path of the built-in obj loader. + /** Use it like this: + \code + SceneManager->getParameters()->setAttribute(scene::OBJ_TEXTURE_PATH, "path/to/your/textures"); + \endcode + **/ + const c8* const OBJ_TEXTURE_PATH = "OBJ_TexturePath"; + //! Flag to avoid loading group structures in .obj files /** Use it like this: \code @@ -137,6 +145,13 @@ namespace scene **/ const c8* const B3D_LOADER_IGNORE_MIPMAP_FLAG = "B3D_IgnoreMipmapFlag"; + //! Name of the parameter for changing the texture path of the built-in b3d loader. + /** Use it like this: + \code + SceneManager->getParameters()->setAttribute(scene::B3D_TEXTURE_PATH, "path/to/your/textures"); + \endcode + **/ + const c8* const B3D_TEXTURE_PATH = "B3D_TexturePath"; //! Flag set as parameter when the scene manager is used as editor /** In this way special animators like deletion animators can be stopped from diff --git a/include/aabbox3d.h b/include/aabbox3d.h index 2c72c6e8..2005f74e 100644 --- a/include/aabbox3d.h +++ b/include/aabbox3d.h @@ -43,23 +43,6 @@ class aabbox3d // functions - //! Adds a point to the bounding box - /** The box grows bigger, if point was outside of the box. - \param p: Point to add into the box. */ - void addInternalPoint(const vector3d& p) - { - addInternalPoint(p.X, p.Y, p.Z); - } - - //! Adds another bounding box - /** The box grows bigger, if the new box was outside of the box. - \param b: Other bounding box to add into this box. */ - void addInternalBox(const aabbox3d& b) - { - addInternalPoint(b.MaxEdge); - addInternalPoint(b.MinEdge); - } - //! Resets the bounding box to a one-point box. /** \param x X coord of the point. \param y Y coord of the point. @@ -85,6 +68,23 @@ class aabbox3d MinEdge = initValue; } + //! Adds a point to the bounding box + /** The box grows bigger, if point was outside of the box. + \param p: Point to add into the box. */ + void addInternalPoint(const vector3d& p) + { + addInternalPoint(p.X, p.Y, p.Z); + } + + //! Adds another bounding box + /** The box grows bigger, if the new box was outside of the box. + \param b: Other bounding box to add into this box. */ + void addInternalBox(const aabbox3d& b) + { + addInternalPoint(b.MaxEdge); + addInternalPoint(b.MinEdge); + } + //! Adds a point to the bounding box /** The box grows bigger, if point is outside of the box. \param x X coordinate of the point to add to this box. @@ -101,8 +101,102 @@ class aabbox3d if (z getCenter() const + { + return (MinEdge + MaxEdge) / 2; + } + + //! Get extent of the box (maximal distance of two points in the box) + /** \return Extent of the bounding box. */ + vector3d getExtent() const + { + return MaxEdge - MinEdge; + } + + //! Check if the box is empty. + /** This means that there is no space between the min and max edge. + \return True if box is empty, else false. */ + bool isEmpty() const + { + return MinEdge.equals ( MaxEdge ); + } + + //! Get the volume enclosed by the box in cubed units + T getVolume() const + { + const vector3d e = getExtent(); + return e.X * e.Y * e.Z; + } + + //! Get the surface area of the box in squared units + T getArea() const + { + const vector3d e = getExtent(); + return 2*(e.X*e.Y + e.X*e.Z + e.Y*e.Z); + } + + //! Stores all 8 edges of the box into an array + /** \param edges: Pointer to array of 8 edges. */ + void getEdges(vector3d *edges) const + { + const core::vector3d middle = getCenter(); + const core::vector3d diag = middle - MaxEdge; + + /* + Edges are stored in this way: + Hey, am I an ascii artist, or what? :) niko. + /3--------/7 + / | / | + / | / | + 1---------5 | + | /2- - -|- -6 + | / | / + |/ | / + 0---------4/ + */ + + edges[0].set(middle.X + diag.X, middle.Y + diag.Y, middle.Z + diag.Z); + edges[1].set(middle.X + diag.X, middle.Y - diag.Y, middle.Z + diag.Z); + edges[2].set(middle.X + diag.X, middle.Y + diag.Y, middle.Z - diag.Z); + edges[3].set(middle.X + diag.X, middle.Y - diag.Y, middle.Z - diag.Z); + edges[4].set(middle.X - diag.X, middle.Y + diag.Y, middle.Z + diag.Z); + edges[5].set(middle.X - diag.X, middle.Y - diag.Y, middle.Z + diag.Z); + edges[6].set(middle.X - diag.X, middle.Y + diag.Y, middle.Z - diag.Z); + edges[7].set(middle.X - diag.X, middle.Y - diag.Y, middle.Z - diag.Z); + } + + //! Repairs the box. + /** Necessary if for example MinEdge and MaxEdge are swapped. */ + void repair() + { + T t; + + if (MinEdge.X > MaxEdge.X) + { t=MinEdge.X; MinEdge.X = MaxEdge.X; MaxEdge.X=t; } + if (MinEdge.Y > MaxEdge.Y) + { t=MinEdge.Y; MinEdge.Y = MaxEdge.Y; MaxEdge.Y=t; } + if (MinEdge.Z > MaxEdge.Z) + { t=MinEdge.Z; MinEdge.Z = MaxEdge.Z; MaxEdge.Z=t; } + } + + //! Calculates a new interpolated bounding box. + /** d=0 returns other, d=1 returns this, all other values blend between + the two boxes. + \param other Other box to interpolate between + \param d Value between 0.0f and 1.0f. + \return Interpolated box. */ + aabbox3d getInterpolated(const aabbox3d& other, f32 d) const + { + f32 inv = 1.0f - d; + return aabbox3d((other.MinEdge*inv) + (MinEdge*d), + (other.MaxEdge*inv) + (MaxEdge*d)); + } + //! Determines if a point is within this box. - /** \param p: Point to check. + /** Border is included (IS part of the box)! + \param p: Point to check. \return True if the point is within the box and false if not */ bool isPointInside(const vector3d& p) const { @@ -111,8 +205,9 @@ class aabbox3d p.Z >= MinEdge.Z && p.Z <= MaxEdge.Z); } - //! Determines if a point is within this box and its borders. - /** \param p: Point to check. + //! Determines if a point is within this box and not its borders. + /** Border is excluded (NOT part of the box)! + \param p: Point to check. \return True if the point is within the box and false if not. */ bool isPointTotalInside(const vector3d& p) const { @@ -121,15 +216,6 @@ class aabbox3d p.Z > MinEdge.Z && p.Z < MaxEdge.Z); } - //! Determines if the box intersects with another box. - /** \param other: Other box to check a intersection with. - \return True if there is an intersection with the other box, - otherwise false. */ - bool intersectsWithBox(const aabbox3d& other) const - { - return (MinEdge <= other.MaxEdge && MaxEdge >= other.MinEdge); - } - //! Check if this box is completely inside the 'other' box. /** \param other: Other box to check against. \return True if this box is completly inside the other box, @@ -139,6 +225,15 @@ class aabbox3d return MinEdge >= other.MinEdge && MaxEdge <= other.MaxEdge; } + //! Determines if the box intersects with another box. + /** \param other: Other box to check a intersection with. + \return True if there is an intersection with the other box, + otherwise false. */ + bool intersectsWithBox(const aabbox3d& other) const + { + return (MinEdge <= other.MaxEdge && MaxEdge >= other.MinEdge); + } + //! Tests if the box intersects with a line /** \param line: Line to test intersection with. \return True if there is an intersection , else false. */ @@ -154,8 +249,7 @@ class aabbox3d \param halflength Half length of the line. \return True if there is an intersection, else false. */ bool intersectsWithLine(const vector3d& linemiddle, - const vector3d& linevect, - T halflength) const + const vector3d& linevect, T halflength) const { const vector3d e = getExtent() * (T)0.5; const vector3d t = getCenter() - linemiddle; @@ -217,103 +311,6 @@ class aabbox3d return ISREL3D_BACK; } - - //! Get center of the bounding box - /** \return Center of the bounding box. */ - vector3d getCenter() const - { - return (MinEdge + MaxEdge) / 2; - } - - - //! Get extent of the box - /** \return Extent of the bounding box. */ - vector3d getExtent() const - { - return MaxEdge - MinEdge; - } - - - //! Stores all 8 edges of the box into an array - /** \param edges: Pointer to array of 8 edges. */ - void getEdges(vector3d *edges) const - { - const core::vector3d middle = getCenter(); - const core::vector3d diag = middle - MaxEdge; - - /* - Edges are stored in this way: - Hey, am I an ascii artist, or what? :) niko. - /3--------/7 - / | / | - / | / | - 1---------5 | - | 2- - -| -6 - | / | / - |/ | / - 0---------4/ - */ - - edges[0].set(middle.X + diag.X, middle.Y + diag.Y, middle.Z + diag.Z); - edges[1].set(middle.X + diag.X, middle.Y - diag.Y, middle.Z + diag.Z); - edges[2].set(middle.X + diag.X, middle.Y + diag.Y, middle.Z - diag.Z); - edges[3].set(middle.X + diag.X, middle.Y - diag.Y, middle.Z - diag.Z); - edges[4].set(middle.X - diag.X, middle.Y + diag.Y, middle.Z + diag.Z); - edges[5].set(middle.X - diag.X, middle.Y - diag.Y, middle.Z + diag.Z); - edges[6].set(middle.X - diag.X, middle.Y + diag.Y, middle.Z - diag.Z); - edges[7].set(middle.X - diag.X, middle.Y - diag.Y, middle.Z - diag.Z); - } - - - //! Check if the box is empty. - /** This means that there is no space between the min and max - edge. - \return True if box is empty, else false. */ - bool isEmpty() const - { - return MinEdge.equals ( MaxEdge ); - } - - - //! Repairs the box. - /** Necessary if for example MinEdge and MaxEdge are swapped. */ - void repair() - { - T t; - - if (MinEdge.X > MaxEdge.X) - { t=MinEdge.X; MinEdge.X = MaxEdge.X; MaxEdge.X=t; } - if (MinEdge.Y > MaxEdge.Y) - { t=MinEdge.Y; MinEdge.Y = MaxEdge.Y; MaxEdge.Y=t; } - if (MinEdge.Z > MaxEdge.Z) - { t=MinEdge.Z; MinEdge.Z = MaxEdge.Z; MaxEdge.Z=t; } - } - - //! Calculates a new interpolated bounding box. - /** \param other: other box to interpolate between - \param d: value between 0.0f and 1.0f. - \return Interpolated box. */ - aabbox3d getInterpolated(const aabbox3d& other, f32 d) const - { - f32 inv = 1.0f - d; - return aabbox3d((other.MinEdge*inv) + (MinEdge*d), - (other.MaxEdge*inv) + (MaxEdge*d)); - } - - //! Get the volume enclosed by the box in cubed units - T getVolume() const - { - const vector3d e = getExtent(); - return e.X * e.Y * e.Z; - } - - //! Get the surface area of the box in squared units - T getArea() const - { - const vector3d e = getExtent(); - return 2*(e.X*e.Y + e.X*e.Z + e.Y*e.Z); - } - //! The near edge vector3d MinEdge; diff --git a/include/coreutil.h b/include/coreutil.h index 96b2ff8c..b75f75fc 100644 --- a/include/coreutil.h +++ b/include/coreutil.h @@ -45,24 +45,16 @@ inline bool hasFileExtension ( const io::path& filename, return isFileExtension ( filename, ext0, ext1, ext2 ) > 0; } -//! cut the filename extension from a source string and stores in the dest string -inline stringc& cutFilenameExtension ( stringc &dest, const stringc &source ) +//! cut the filename extension from a source file path and store it in a dest file path +inline io::path& cutFilenameExtension ( io::path &dest, const io::path &source ) { s32 endPos = source.findLast ( '.' ); dest = source.subString ( 0, endPos < 0 ? source.size () : endPos ); return dest; } -//! cut the filename extension from a source string and stores in the dest string -inline stringw& cutFilenameExtension ( stringw &dest, const stringw &source ) -{ - s32 endPos = source.findLast ( '.' ); - dest = source.subString ( 0, endPos < 0 ? source.size () : endPos ); - return dest; -} - -//! get the filename extension from a string -inline stringc& getFileNameExtension ( stringc &dest, const stringc &source ) +//! get the filename extension from a file path +inline io::path& getFileNameExtension ( io::path &dest, const io::path &source ) { s32 endPos = source.findLast ( '.' ); if ( endPos < 0 ) @@ -73,30 +65,11 @@ inline stringc& getFileNameExtension ( stringc &dest, const stringc &source ) } //! delete path from filename -inline core::stringw& deletePathFromFilename(core::stringw& filename) +inline io::path& deletePathFromFilename(io::path& filename) { // delete path from filename - const wchar_t *s = filename.c_str(); - const wchar_t* p = s + filename.size(); - - // search for path separator or beginning - while ( *p != '/' && *p != '\\' && p != s ) - p--; - - if ( p != s ) - { - ++p; - filename = p; - } - return filename; -} - -//! delete path from filename -inline core::stringc& deletePathFromFilename(core::stringc& filename) -{ - // delete path from filename - const c8 *s = filename.c_str(); - const c8* p = s + filename.size(); + const fschar_t* s = filename.c_str(); + const fschar_t* p = s + filename.size(); // search for path separator or beginning while ( *p != '/' && *p != '\\' && p != s ) @@ -117,21 +90,23 @@ inline io::path& deletePathFromPath(io::path& filename, s32 pathCount) s32 i = filename.size(); // search for path separator or beginning - while ( i ) + while ( i>=0 ) { if ( filename[i] == '/' || filename[i] == '\\' ) { if ( --pathCount <= 0 ) break; } - i -= 1; + --i; } - if ( i ) + if ( i>0 ) { filename [ i + 1 ] = 0; filename.validate(); } + else + filename=""; return filename; } diff --git a/include/irrArray.h b/include/irrArray.h index 3f74faa8..0ba7917a 100644 --- a/include/irrArray.h +++ b/include/irrArray.h @@ -8,6 +8,7 @@ #include "irrTypes.h" #include "heapsort.h" #include "irrAllocator.h" +#include "irrMath.h" namespace irr { @@ -42,7 +43,7 @@ public: //! Copy constructor - array(const array& other) : data(0) + array(const array& other) : data(0) { *this = other; } @@ -163,18 +164,25 @@ public: } else { - // move array content and construct new element - // first move end one up - for (u32 i=used; i>index; --i) + // element inserted not at end + if ( used > index ) { - if (iindex; --i) + { + data[i] = data[i-1]; + } + // insert the new element + data[index] = element; + } + else + { + // insert the new element to the end + allocator.construct(&data[index], element); } - // then add new element - if (used > index) - allocator.destruct(&data[index]); - allocator.construct(&data[index], element); // data[index] = element; } // set to false as we don't know if we have the comparison operators is_sorted = false; @@ -247,8 +255,10 @@ public: //! Assignment operator - void operator=(const array& other) + const array& operator=(const array& other) { + if (this == &other) + return *this; strategy = other.strategy; if (data) @@ -267,11 +277,13 @@ public: for (u32 i=0; i& other) const + bool operator == (const array& other) const { if (used != other.used) return false; @@ -284,7 +296,7 @@ public: //! Inequality operator - bool operator != (const array& other) const + bool operator != (const array& other) const { return !(*this==other); } @@ -372,7 +384,7 @@ public: O(n*log n) in worst case. */ void sort() { - if (!is_sorted || used>1) + if (!is_sorted && used>1) heapsort(data, used); is_sorted = true; } @@ -535,7 +547,10 @@ public: \param count: Amount of elements to be erased. */ void erase(u32 index, s32 count) { - _IRR_DEBUG_BREAK_IF(index>=used || count<1 || index+count>used) // access violation + if (index>=used || count<1) + return; + if (index+count>used) + count = used-index; u32 i; for (i=index; i& other) + { + core::swap(data, other.data); + core::swap(allocated, other.allocated); + core::swap(used, other.used); + core::swap(allocator, other.allocator); // memory is still released by the same allocator used for allocation + eAllocStrategy helper_strategy(strategy); // can't use core::swap with bitfields + strategy = other.strategy; + other.strategy = helper_strategy; + bool helper_free_when_destroyed(free_when_destroyed); + free_when_destroyed = other.free_when_destroyed; + other.free_when_destroyed = helper_free_when_destroyed; + bool helper_is_sorted(is_sorted); + is_sorted = other.is_sorted; + other.is_sorted = helper_is_sorted; + } + + private: T* data; u32 allocated; diff --git a/include/irrList.h b/include/irrList.h index c88a0aa0..333119b7 100644 --- a/include/irrList.h +++ b/include/irrList.h @@ -7,6 +7,7 @@ #include "irrTypes.h" #include "irrAllocator.h" +#include "irrMath.h" namespace irr { @@ -74,11 +75,12 @@ public: T * operator ->() { return &Current->Element; } private: - Iterator(SKListNode* begin) : Current(begin) {} + explicit Iterator(SKListNode* begin) : Current(begin) {} SKListNode* Current; friend class list; + friend class ConstIterator; }; //! List iterator for const access. @@ -87,6 +89,7 @@ public: public: ConstIterator() : Current(0) {} + ConstIterator(const Iterator& iter) : Current(iter.Current) {} ConstIterator& operator ++() { Current = Current->Next; return *this; } ConstIterator& operator --() { Current = Current->Prev; return *this; } @@ -121,7 +124,7 @@ public: ConstIterator & operator =(const Iterator & iterator) { Current = iterator.Current; return *this; } private: - ConstIterator(SKListNode* begin) : Current(begin) {} + explicit ConstIterator(SKListNode* begin) : Current(begin) {} SKListNode* Current; @@ -382,8 +385,22 @@ public: return returnIterator; } + //! Swap the content of this list container with the content of another list + /** Afterwards this object will contain the content of the other object and the other + object will contain the content of this object. Iterators will afterwards be valid for + the swapped object. + \param other Swap content with this object */ + void swap(list& other) + { + core::swap(First, other.First); + core::swap(Last, other.Last); + core::swap(Size, other.Size); + core::swap(allocator, other.allocator); // memory is still released by the same allocator used for allocation + } + + private: - + SKListNode* First; SKListNode* Last; u32 Size; diff --git a/include/irrMap.h b/include/irrMap.h index 778814b8..5f50fbe8 100644 --- a/include/irrMap.h +++ b/include/irrMap.h @@ -6,6 +6,7 @@ #define __IRR_MAP_H_INCLUDED__ #include "irrTypes.h" +#include "irrMath.h" namespace irr { @@ -49,7 +50,7 @@ class map RBTree* getLeftChild() const { return LeftChild; } RBTree* getRightChild() const { return RightChild; } - RBTree* getParent() const { return Parent; } + RBTree* getParent() const { return Parent; } ValueTypeRB getValue() const { @@ -730,12 +731,18 @@ class map //! Is the tree empty? //! \return Returns true if empty, false if not - bool isEmpty() const + bool empty() const { _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; return Root == 0; } + //! \deprecated Use empty() instead. + _IRR_DEPRECATED_ bool isEmpty() const + { + return empty(); + } + //! Search for a node with the specified key. //! \param keyToFind: The key to find //! \return Returns 0 if node couldn't be found. @@ -772,6 +779,17 @@ class map return Size; } + //! Swap the content of this map container with the content of another map + /** Afterwards this object will contain the content of the other object and the other + object will contain the content of this object. Iterators will afterwards be valid for + the swapped object. + \param other Swap content with this object */ + void swap(map& other) + { + core::swap(Root, other.Root); + core::swap(Size, other.Size); + } + //------------------------------ // Public Iterators //------------------------------ diff --git a/include/irrMath.h b/include/irrMath.h index 5c40c70b..3d756411 100644 --- a/include/irrMath.h +++ b/include/irrMath.h @@ -47,7 +47,7 @@ namespace core #endif //! Constant for PI. const f32 PI = 3.14159265359f; - + //! Constant for reciprocal of PI. const f32 RECIPROCAL_PI = 1.0f/PI; @@ -161,6 +161,15 @@ namespace core return min_ (max_(value,low), high); } + //! swaps the content of the passed parameters + template + inline void swap(T& a, T& b) + { + T c(a); + a = b; + b = c; + } + //! returns if a equals b, taking possible rounding errors into account inline bool equals(const f64 a, const f64 b, const f64 tolerance = ROUNDING_ERROR_f64) { @@ -462,7 +471,7 @@ namespace core __asm mulss xmm1, xmm0 // xmm1 = f * rcpss(f) __asm mulss xmm1, xmm0 // xmm2 = f * rcpss(f) * rcpss(f) __asm addss xmm0, xmm0 // xmm0 = 2 * rcpss(f) - __asm subss xmm0, xmm1 // xmm0 = 2 * rcpss(f) + __asm subss xmm0, xmm1 // xmm0 = 2 * rcpss(f) // - f * rcpss(f) * rcpss(f) __asm movss rec, xmm0 // return xmm0 return rec; @@ -502,7 +511,7 @@ namespace core __asm mulss xmm1, xmm0 // xmm1 = f * rcpss(f) __asm mulss xmm1, xmm0 // xmm2 = f * rcpss(f) * rcpss(f) __asm addss xmm0, xmm0 // xmm0 = 2 * rcpss(f) - __asm subss xmm0, xmm1 // xmm0 = 2 * rcpss(f) + __asm subss xmm0, xmm1 // xmm0 = 2 * rcpss(f) // - f * rcpss(f) * rcpss(f) __asm movss rec, xmm0 // return xmm0 return rec; diff --git a/include/irrString.h b/include/irrString.h index acce2239..de8e2136 100644 --- a/include/irrString.h +++ b/include/irrString.h @@ -84,15 +84,15 @@ public: //! Constructor - string(const string& other) + string(const string& other) : array(0), allocated(0), used(0) { *this = other; } //! Constructor from other string types - template - string(const string& other) + template + string(const string& other) : array(0), allocated(0), used(0) { *this = other; @@ -227,7 +227,7 @@ public: //! Assignment operator - string& operator=(const string& other) + string& operator=(const string& other) { if (this == &other) return *this; @@ -248,8 +248,8 @@ public: } //! Assignment operator for other string types - template - string& operator=(const string& other) + template + string& operator=(const string& other) { *this = other.c_str(); return *this; @@ -258,7 +258,7 @@ public: //! Assignment operator for strings, ascii and unicode template - string& operator=(const B* const c) + string& operator=(const B* const c) { if (!c) { @@ -304,9 +304,9 @@ public: //! Append operator for other strings - string operator+(const string& other) const + string operator+(const string& other) const { - string str(*this); + string str(*this); str.append(other); return str; @@ -315,9 +315,9 @@ public: //! Append operator for strings, ascii and unicode template - string operator+(const B* const c) const + string operator+(const B* const c) const { - string str(*this); + string str(*this); str.append(c); return str; @@ -356,7 +356,7 @@ public: //! Equality operator - bool operator ==(const string& other) const + bool operator ==(const string& other) const { for(u32 i=0; array[i] && other.array[i]; ++i) if (array[i] != other.array[i]) @@ -367,7 +367,7 @@ public: //! Is smaller comparator - bool operator <(const string& other) const + bool operator <(const string& other) const { for(u32 i=0; array[i] && other.array[i]; ++i) { @@ -388,7 +388,7 @@ public: //! Inequality operator - bool operator !=(const string& other) const + bool operator !=(const string& other) const { return !(*this == other); } @@ -430,7 +430,7 @@ public: //! Compares the strings ignoring case. /** \param other: Other string to compare. \return True if the strings are equal ignoring case. */ - bool equals_ignore_case(const string& other) const + bool equals_ignore_case(const string& other) const { for(u32 i=0; array[i] && other[i]; ++i) if (locale_lower( array[i]) != locale_lower(other[i])) @@ -443,7 +443,7 @@ public: /** \param other: Other string to compare. \param sourcePos: where to start to compare in the string \return True if the strings are equal ignoring case. */ - bool equals_substring_ignore_case(const string&other, const s32 sourcePos = 0 ) const + bool equals_substring_ignore_case(const string&other, const s32 sourcePos = 0 ) const { if ( (u32) sourcePos > used ) return false; @@ -460,7 +460,7 @@ public: //! Compares the strings ignoring case. /** \param other: Other string to compare. \return True if this string is smaller ignoring case. */ - bool lower_ignore_case(const string& other) const + bool lower_ignore_case(const string& other) const { for(u32 i=0; array[i] && other.array[i]; ++i) { @@ -477,7 +477,7 @@ public: /** \param other Other string to compare. \param n Number of characters to compare \return True if the n first characters of both strings are equal. */ - bool equalsn(const string& other, u32 n) const + bool equalsn(const string& other, u32 n) const { u32 i; for(i=0; array[i] && other[i] && i < n; ++i) @@ -553,7 +553,7 @@ public: //! Appends a string to this string /** \param other: String to append. */ - void append(const string& other) + void append(const string& other) { --used; u32 len = other.size()+1; @@ -571,7 +571,7 @@ public: //! Appends a string of the length l to this string. /** \param other: other String to append to this string. \param length: How much characters of the other string to add to this one. */ - void append(const string& other, u32 length) + void append(const string& other, u32 length) { if (other.size() < length) { @@ -775,17 +775,17 @@ public: //! Returns a substring /** \param begin: Start of substring. \param length: Length of substring. */ - string subString(u32 begin, s32 length) const + string subString(u32 begin, s32 length) const { // if start after string // or no proper substring length if ((length <= 0) || (begin>=size())) - return string(""); + return string(""); // clamp length to maximal value if ((length+begin) > size()) length = size()-begin; - string o; + string o; o.reserve(length+1); for (s32 i=0; i& operator += (T c) + string& operator += (T c) { append(c); return *this; @@ -809,7 +809,7 @@ public: //! Appends a char string to this string /** \param c Char string to append. */ - string& operator += (const T* const c) + string& operator += (const T* const c) { append(c); return *this; @@ -818,7 +818,7 @@ public: //! Appends a string to this string /** \param other String to append. */ - string& operator += (const string& other) + string& operator += (const string& other) { append(other); return *this; @@ -827,54 +827,54 @@ public: //! Appends a string representation of a number to this string /** \param i Number to append. */ - string& operator += (const int i) + string& operator += (const int i) { - append(string(i)); + append(string(i)); return *this; } //! Appends a string representation of a number to this string /** \param i Number to append. */ - string& operator += (const unsigned int i) + string& operator += (const unsigned int i) { - append(string(i)); + append(string(i)); return *this; } //! Appends a string representation of a number to this string /** \param i Number to append. */ - string& operator += (const long i) + string& operator += (const long i) { - append(string(i)); + append(string(i)); return *this; } //! Appends a string representation of a number to this string /** \param i Number to append. */ - string& operator += (const unsigned long& i) + string& operator += (const unsigned long& i) { - append(string(i)); + append(string(i)); return *this; } //! Appends a string representation of a number to this string /** \param i Number to append. */ - string& operator += (const double i) + string& operator += (const double i) { - append(string(i)); + append(string(i)); return *this; } //! Appends a string representation of a number to this string /** \param i Number to append. */ - string& operator += (const float i) + string& operator += (const float i) { - append(string(i)); + append(string(i)); return *this; } @@ -913,7 +913,7 @@ public: //! Removes a string from the string. /** \param toRemove: String to remove. */ - void remove(const string toRemove) + void remove(const string toRemove) { u32 size = toRemove.size(); u32 pos = 0; @@ -943,7 +943,7 @@ public: //! Removes characters from a string. /** \param characters: Characters to remove. */ - void removeChars(const string & characters) + void removeChars(const string & characters) { u32 pos = 0; u32 found = 0; @@ -974,7 +974,7 @@ public: //! Trims the string. /** Removes the specified characters (by default, Latin-1 whitespace) from the begining and the end of the string. */ - string& trim(const string & whitespace = " \t\n\r") + string& trim(const string & whitespace = " \t\n\r") { // find start and end of the substring without the specified characters const s32 begin = findFirstCharNotInList(whitespace.c_str(), whitespace.used); @@ -1068,7 +1068,7 @@ public: { if ((!ignoreEmptyTokens || i - lastpos != 0) && !lastWasSeparator) - ret.push_back(string(&array[lastpos], i - lastpos)); + ret.push_back(string(&array[lastpos], i - lastpos)); foundSeparator = true; lastpos = (keepSeparators ? i : i + 1); break; @@ -1077,7 +1077,7 @@ public: lastWasSeparator = foundSeparator; } if ((used - 1) > lastpos) - ret.push_back(string(&array[lastpos], (used - 1) - lastpos)); + ret.push_back(string(&array[lastpos], (used - 1) - lastpos)); return ret.size()-oldSize; } diff --git a/include/irrTypes.h b/include/irrTypes.h index f0e3f725..d371f8ac 100644 --- a/include/irrTypes.h +++ b/include/irrTypes.h @@ -139,7 +139,7 @@ strings //! define a break macro for debugging. #if defined(_DEBUG) #if defined(_IRR_WINDOWS_API_) && defined(_MSC_VER) && !defined (_WIN32_WCE) - #if defined(_WIN64) // using portable common solution for x64 configuration + #if defined(WIN64) || defined(_WIN64) // using portable common solution for x64 configuration #include #define _IRR_DEBUG_BREAK_IF( _CONDITION_ ) if (_CONDITION_) {_CrtDbgBreak();} #else diff --git a/include/irrlicht.h b/include/irrlicht.h index 389d379b..34a41de3 100644 --- a/include/irrlicht.h +++ b/include/irrlicht.h @@ -263,15 +263,15 @@ * * Irrlicht can load a lot of file formats automaticly, see irr::scene::ISceneManager::getMesh() * for a detailed list. So if you would like to replace the simple blue screen background by - * a cool Quake 3 Map, optimized by an octtree, just insert this code + * a cool Quake 3 Map, optimized by an octree, just insert this code * somewhere before the while loop: * * \code * // add .pk3 archive to the file system * device->getFileSystem()->addZipFileArchive("quake3map.pk3"); * - * // load .bsp file and show it using an octtree - * scenemgr->addOctTreeSceneNode( + * // load .bsp file and show it using an octree + * scenemgr->addOctreeSceneNode( * scenemgr->getMesh("quake3map.bsp")); * \endcode * diff --git a/include/path.h b/include/path.h index 56259d66..b9bc7763 100644 --- a/include/path.h +++ b/include/path.h @@ -16,6 +16,72 @@ namespace io /** This type will transparently handle different file system encodings. */ typedef core::string path; +//! Used in places where we identify objects by a filename, but don't actually work with the real filename +/** Irrlicht is internally not case-sensitive when it comes to names. + Also this class is a first step towards support for correctly serializing renamed objects. +*/ +struct SNamedPath +{ + //! Constructor + SNamedPath() {} + + //! Constructor + SNamedPath(const path& p) : Path(p), InternalName( PathToName(p) ) + { + } + + //! Is smaller comparator + bool operator <(const SNamedPath& other) const + { + return InternalName < other.InternalName; + } + + //! Set the path. + void setPath(const path& p) + { + Path = p; + InternalName = PathToName(p); + } + + //! Get the path. + const path& getPath() const + { + return Path; + }; + + //! Get the name which is used to identify the file. + //! This string is similar to the names and filenames used before Irrlicht 1.7 + const path& getInternalName() const + { + return InternalName; + } + + //! Implicit cast to io::path + operator core::stringc() const + { + return core::stringc(getPath()); + } + //! Implicit cast to io::path + operator core::stringw() const + { + return core::stringw(getPath()); + } + +protected: + // convert the given path string to a name string. + path PathToName(const path& p) const + { + path name(p); + name.replace( '\\', '/' ); + name.make_lower(); + return name; + } + +private: + path Path; + path InternalName; +}; + } // io } // irr diff --git a/include/position2d.h b/include/position2d.h index ea0850b7..ecbfab94 100644 --- a/include/position2d.h +++ b/include/position2d.h @@ -22,8 +22,8 @@ typedef vector2d position2df; //! \deprecated position2d is now a synonym for vector2d, but vector2d should be used directly. typedef vector2d position2di; -}; // namespace core -}; // namespace irr +} // namespace core +} // namespace irr // ...and use a #define to catch the rest, for (e.g.) position2d #define position2d vector2d diff --git a/include/quaternion.h b/include/quaternion.h index fe60d949..8341033a 100644 --- a/include/quaternion.h +++ b/include/quaternion.h @@ -40,6 +40,9 @@ class quaternion //! Equalilty operator bool operator==(const quaternion& other) const; + //! inequality operator + bool operator!=(const quaternion& other) const; + //! Assignment operator inline quaternion& operator=(const quaternion& other); @@ -76,6 +79,9 @@ class quaternion //! Sets new quaternion based on euler angles (radians) inline quaternion& set(const core::vector3df& vec); + //! Sets new quaternion from other quaternion + inline quaternion& set(const core::quaternion& quat); + //! Normalizes the quaternion inline quaternion& normalize(); @@ -171,6 +177,11 @@ inline bool quaternion::operator==(const quaternion& other) const (W == other.W)); } +// inequality operator +inline bool quaternion::operator!=(const quaternion& other) const +{ + return !(*this == other); +} // assignment operator inline quaternion& quaternion::operator=(const quaternion& other) @@ -339,7 +350,7 @@ inline void quaternion::getMatrix( matrix4 &dest, const core::vector3df ¢er m2.setInverseTranslation ( center ); lookat *= m2; */ -inline void quaternion::getMatrixCenter(matrix4 &dest, +inline void quaternion::getMatrixCenter(matrix4 &dest, const core::vector3df ¢er, const core::vector3df &translation) const { @@ -445,6 +456,12 @@ inline quaternion& quaternion::set(const core::vector3df& vec) return set(vec.X, vec.Y, vec.Z); } +// sets new quaternion based on other quaternion +inline quaternion& quaternion::set(const core::quaternion& quat) +{ + return (*this=quat); +} + // normalizes the quaternion inline quaternion& quaternion::normalize() { diff --git a/include/vector2d.h b/include/vector2d.h index ec6589b7..47afaf30 100644 --- a/include/vector2d.h +++ b/include/vector2d.h @@ -64,11 +64,33 @@ public: vector2d operator/(const T v) const { return vector2d(X / v, Y / v); } vector2d& operator/=(const T v) { X/=v; Y/=v; return *this; } - bool operator<=(const vector2d&other) const { return X<=other.X && Y<=other.Y; } - bool operator>=(const vector2d&other) const { return X>=other.X && Y>=other.Y; } + //! sort in order X, Y. Equality with rounding tolerance. + bool operator<=(const vector2d&other) const + { + return (X&other) const { return X(const vector2d&other) const { return X>other.X && Y>other.Y; } + //! sort in order X, Y. Equality with rounding tolerance. + bool operator>=(const vector2d&other) const + { + return (X>other.X || core::equals(X, other.X)) || + (core::equals(X, other.X) && (Y>other.Y || core::equals(Y, other.Y))); + } + + //! sort in order X, Y. Difference must be above rounding tolerance. + bool operator<(const vector2d&other) const + { + return (X(const vector2d&other) const + { + return (X>other.X && !core::equals(X, other.X)) || + (core::equals(X, other.X) && Y>other.Y && !core::equals(Y, other.Y)); + } bool operator==(const vector2d& other) const { return equals(other); } bool operator!=(const vector2d& other) const { return !equals(other); } diff --git a/include/vector3d.h b/include/vector3d.h index 012f74a4..58d48b47 100644 --- a/include/vector3d.h +++ b/include/vector3d.h @@ -57,10 +57,37 @@ namespace core vector3d operator/(const T v) const { T i=(T)1.0/v; return vector3d(X * i, Y * i, Z * i); } vector3d& operator/=(const T v) { T i=(T)1.0/v; X*=i; Y*=i; Z*=i; return *this; } - bool operator<=(const vector3d&other) const { return X<=other.X && Y<=other.Y && Z<=other.Z;} - bool operator>=(const vector3d&other) const { return X>=other.X && Y>=other.Y && Z>=other.Z;} - bool operator<(const vector3d&other) const { return X(const vector3d&other) const { return X>other.X && Y>other.Y && Z>other.Z;} + //! sort in order X, Y, Z. Equality with rounding tolerance. + bool operator<=(const vector3d&other) const + { + return (X=(const vector3d&other) const + { + return (X>other.X || core::equals(X, other.X)) || + (core::equals(X, other.X) && (Y>other.Y || core::equals(Y, other.Y))) || + (core::equals(X, other.X) && core::equals(Y, other.Y) && (Z>other.Z || core::equals(Z, other.Z))); + } + + //! sort in order X, Y, Z. Difference must be above rounding tolerance. + bool operator<(const vector3d&other) const + { + return (X(const vector3d&other) const + { + return (X>other.X && !core::equals(X, other.X)) || + (core::equals(X, other.X) && Y>other.Y && !core::equals(Y, other.Y)) || + (core::equals(X, other.X) && core::equals(Y, other.Y) && Z>other.Z && !core::equals(Z, other.Z)); + } //! use weak float compare bool operator==(const vector3d& other) const @@ -275,7 +302,7 @@ namespace core { vector3d angle; - const f64 tmp = (atan2(X, Z) * RADTODEG64); + const f64 tmp = (atan2((f64)X, (f64)Z) * RADTODEG64); angle.Y = (T)tmp; if (angle.Y < 0) @@ -295,7 +322,7 @@ namespace core return angle; } - //! Get the spherical coordinate angles + //! Get the spherical coordinate angles /** This returns Euler degrees for the point represented by this vector. The calculation assumes the pole at (0,1,0) and returns the angles in X and Y. @@ -309,7 +336,7 @@ namespace core { if (X!=0) { - angle.Y = (T)(atan2(Z,X) * RADTODEG64); + angle.Y = (T)(atan2((f64)Z,(f64)X) * RADTODEG64); } else if (Z<0) angle.Y=180; @@ -317,7 +344,7 @@ namespace core angle.X = (T)(acos(Y * core::reciprocal_squareroot(length)) * RADTODEG64); } return angle; - } + } //! Builds a direction vector from (this) rotation vector. /** This vector is assumed to be a rotation vector composed of 3 Euler angle rotations, in degrees. @@ -377,6 +404,12 @@ namespace core T Z; }; + //! partial specialization for integer vectors + // Implementor note: inline keyword needed due to template specialization for s32. Otherwise put specialization into a .cpp + template <> + inline vector3d vector3d::operator /(s32 val) const {return core::vector3d(X/val,Y/val,Z/val);} + template <> + inline vector3d& vector3d::operator /=(s32 val) {X/=val;Y/=val;Z/=val; return *this;} //! Typedef for a f32 3d vector. typedef vector3d vector3df; diff --git a/media/004shot.jpg b/media/004shot.jpg index a14d6058..20091c24 100644 Binary files a/media/004shot.jpg and b/media/004shot.jpg differ diff --git a/media/007shot.jpg b/media/007shot.jpg index 89cba7bf..24ce868f 100644 Binary files a/media/007shot.jpg and b/media/007shot.jpg differ diff --git a/media/008shot.jpg b/media/008shot.jpg index e321c581..529174ba 100644 Binary files a/media/008shot.jpg and b/media/008shot.jpg differ diff --git a/media/009shot.jpg b/media/009shot.jpg index 7de45634..9bfa1958 100644 Binary files a/media/009shot.jpg and b/media/009shot.jpg differ diff --git a/media/010shot.jpg b/media/010shot.jpg index ffd11ddb..0e798d3f 100644 Binary files a/media/010shot.jpg and b/media/010shot.jpg differ diff --git a/media/012shot.jpg b/media/012shot.jpg index 5b6a693b..aefd2613 100644 Binary files a/media/012shot.jpg and b/media/012shot.jpg differ diff --git a/media/017shot.jpg b/media/017shot.jpg index cbb58ea3..0ff80d2b 100644 Binary files a/media/017shot.jpg and b/media/017shot.jpg differ diff --git a/media/022shot.jpg b/media/022shot.jpg new file mode 100644 index 00000000..c2821974 Binary files /dev/null and b/media/022shot.jpg differ diff --git a/media/023shot.jpg b/media/023shot.jpg new file mode 100644 index 00000000..2be47ce4 Binary files /dev/null and b/media/023shot.jpg differ diff --git a/media/detailmap3.jpg b/media/detailmap3.jpg index 8d2f1a5d..acf5f41d 100644 Binary files a/media/detailmap3.jpg and b/media/detailmap3.jpg differ diff --git a/scripts/doc/doxygen.exe b/scripts/doc/doxygen.exe index e2adcf5e..2d8f3a49 100644 Binary files a/scripts/doc/doxygen.exe and b/scripts/doc/doxygen.exe differ diff --git a/scripts/doc/irrlicht/doxygen.cfg b/scripts/doc/irrlicht/doxygen.cfg index d603003e..e6e5f694 100644 --- a/scripts/doc/irrlicht/doxygen.cfg +++ b/scripts/doc/irrlicht/doxygen.cfg @@ -647,7 +647,7 @@ HTML_ALIGN_MEMBERS = YES # Microsoft HTML help workshop to generate a compressed HTML help file (.chm) # of the generated HTML documentation. -GENERATE_HTMLHELP = YES +GENERATE_HTMLHELP = NO # If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can # be used to specify the file name of the resulting .chm file. You diff --git a/scripts/doc/irrlicht/footer.html b/scripts/doc/irrlicht/footer.html index 0a49505e..7a94244e 100644 --- a/scripts/doc/irrlicht/footer.html +++ b/scripts/doc/irrlicht/footer.html @@ -6,7 +6,7 @@
The Irrlicht Engine
The Irrlicht - Engine Documentation © 2003-2009 by Nikolaus Gebhardt. Generated + Engine Documentation © 2003-2010 by Nikolaus Gebhardt. Generated on $datetime by Doxygen ($doxygenversion)
diff --git a/scripts/doc/irrlicht/makedocumentation.bat b/scripts/doc/irrlicht/makedocumentation.bat index fcfad584..d2bf3b6b 100644 --- a/scripts/doc/irrlicht/makedocumentation.bat +++ b/scripts/doc/irrlicht/makedocumentation.bat @@ -26,6 +26,8 @@ rem for /F %%i in ('dir ..\..\..\examples\[01]*\main.cpp') DO ..\sed.exe -f tuto ..\sed.exe -f tutorials.sed ..\..\..\examples\19.MouseAndJoystick\main.cpp >>tut.txt ..\sed.exe -f tutorials.sed ..\..\..\examples\20.ManagedLights\main.cpp >>tut.txt ..\sed.exe -f tutorials.sed ..\..\..\examples\21.Quake3Explorer\main.cpp >>tut.txt +..\sed.exe -f tutorials.sed ..\..\..\examples\22.MaterialViewer\main.cpp >>tut.txt +..\sed.exe -f tutorials.sed ..\..\..\examples\23.SMeshHandling\main.cpp >>tut.txt ..\doxygen.exe doxygen.cfg diff --git a/scripts/doc/irrlicht/maketut.sed b/scripts/doc/irrlicht/maketut.sed new file mode 100644 index 00000000..8cc7b4d2 --- /dev/null +++ b/scripts/doc/irrlicht/maketut.sed @@ -0,0 +1,5 @@ +1,+18 d +s/src="/src="images\/tutorials\// +s/href="/href="docu\//g +s/\(.*\) %2 +..\sed.exe -f maketut.sed %1 >>%2 +type tut_end.html >>%2 + diff --git a/scripts/doc/irrlicht/maketutorial.sh b/scripts/doc/irrlicht/maketutorial.sh new file mode 100755 index 00000000..4b642add --- /dev/null +++ b/scripts/doc/irrlicht/maketutorial.sh @@ -0,0 +1,4 @@ +cat tut_head.html >$2 +sed -f maketut.sed $1 >>$2 +cat tut_end.html >>$2 + diff --git a/scripts/doc/irrlicht/tut_end.html b/scripts/doc/irrlicht/tut_end.html new file mode 100644 index 00000000..63fa4da0 --- /dev/null +++ b/scripts/doc/irrlicht/tut_end.html @@ -0,0 +1,14 @@ + + + +

 

+ + +

+ Valid XHTML 1.0! + Valid CSS!
+ +


+ Irrlicht Engine and Irrlicht Engine webpage © 2003-2010 by Nikolaus Gebhardt

+ + diff --git a/scripts/doc/irrlicht/tut_head.html b/scripts/doc/irrlicht/tut_head.html new file mode 100644 index 00000000..2436b894 --- /dev/null +++ b/scripts/doc/irrlicht/tut_head.html @@ -0,0 +1,52 @@ + + + + +Irrlicht Engine - A free open source 3d engine + + + + + + + +

+ + + + + + + + + +
Irrlicht Engine logo
+ +
diff --git a/source/Irrlicht/CAnimatedMeshMD3.cpp b/source/Irrlicht/CAnimatedMeshMD3.cpp index f3c179ed..6aa4478f 100644 --- a/source/Irrlicht/CAnimatedMeshMD3.cpp +++ b/source/Irrlicht/CAnimatedMeshMD3.cpp @@ -381,7 +381,7 @@ bool CAnimatedMeshMD3::loadModelFile( u32 modelIndex, io::IReadFile* file, { file->read( &skin, sizeof(skin) ); - core::stringc name; + io::path name; cutFilenameExtension ( name, skin.name ); name.replace ( '\\', '/' ); buf->Shader = name; diff --git a/source/Irrlicht/CAnimatedMeshSceneNode.cpp b/source/Irrlicht/CAnimatedMeshSceneNode.cpp index 75f9aefa..18ce8aa6 100644 --- a/source/Irrlicht/CAnimatedMeshSceneNode.cpp +++ b/source/Irrlicht/CAnimatedMeshSceneNode.cpp @@ -195,7 +195,7 @@ void CAnimatedMeshSceneNode::OnRegisterSceneNode() } } -IMesh * CAnimatedMeshSceneNode::getMeshForCurrentFrame(bool forceRecalcOfControlJoints) +IMesh * CAnimatedMeshSceneNode::getMeshForCurrentFrame() { if(Mesh->getMeshType() != EAMT_SKINNED) { @@ -204,7 +204,7 @@ IMesh * CAnimatedMeshSceneNode::getMeshForCurrentFrame(bool forceRecalcOfControl else { // As multiple scene nodes may be sharing the same skinned mesh, we have to - // re-animated it every frame to ensure that this node gets the mesh that it needs. + // re-animate it every frame to ensure that this node gets the mesh that it needs. CSkinnedMesh* skinnedMesh = reinterpret_cast(Mesh); @@ -246,7 +246,7 @@ void CAnimatedMeshSceneNode::OnAnimate(u32 timeMs) if (Mesh) { - scene::IMesh * mesh = getMeshForCurrentFrame( true ); + scene::IMesh * mesh = getMeshForCurrentFrame(); if (mesh) Box = mesh->getBoundingBox(); @@ -271,7 +271,7 @@ void CAnimatedMeshSceneNode::render() ++PassCount; - scene::IMesh* m = getMeshForCurrentFrame( false ); + scene::IMesh* m = getMeshForCurrentFrame(); if(m) { @@ -568,10 +568,7 @@ IShadowVolumeSceneNode* CAnimatedMeshSceneNode::addShadowVolumeSceneNode(const I return 0; if (Shadow) - { - os::Printer::log("This node already has a shadow.", ELL_WARNING); - return 0; - } + return Shadow; if (!shadowMesh) shadowMesh = Mesh; // if null is given, use the mesh of node @@ -770,7 +767,7 @@ void CAnimatedMeshSceneNode::serializeAttributes(io::IAttributes* out, io::SAttr { IAnimatedMeshSceneNode::serializeAttributes(out, options); - out->addString("Mesh", SceneManager->getMeshCache()->getMeshFilename(Mesh).c_str()); + out->addString("Mesh", SceneManager->getMeshCache()->getMeshName(Mesh).getPath().c_str()); out->addBool("Looping", Looping); out->addBool("ReadOnlyMaterials", ReadOnlyMaterials); out->addFloat("FramesPerSecond", FramesPerSecond); @@ -784,7 +781,7 @@ void CAnimatedMeshSceneNode::deserializeAttributes(io::IAttributes* in, io::SAtt { IAnimatedMeshSceneNode::deserializeAttributes(in, options); - io::path oldMeshStr = SceneManager->getMeshCache()->getMeshFilename(Mesh); + io::path oldMeshStr = SceneManager->getMeshCache()->getMeshName(Mesh); io::path newMeshStr = in->getAttributeAsString("Mesh"); Looping = in->getAttributeAsBool("Looping"); diff --git a/source/Irrlicht/CAnimatedMeshSceneNode.h b/source/Irrlicht/CAnimatedMeshSceneNode.h index 05874e7f..c9f2e7c6 100644 --- a/source/Irrlicht/CAnimatedMeshSceneNode.h +++ b/source/Irrlicht/CAnimatedMeshSceneNode.h @@ -165,7 +165,7 @@ namespace scene private: //! Get a static mesh for the current frame of this animated mesh - IMesh* getMeshForCurrentFrame(bool forceRecalcOfControlJoints); + IMesh* getMeshForCurrentFrame(); void buildFrameNr(u32 timeMs); void checkJoints(); diff --git a/source/Irrlicht/CAttributeImpl.h b/source/Irrlicht/CAttributeImpl.h index beae0beb..49e95476 100644 --- a/source/Irrlicht/CAttributeImpl.h +++ b/source/Irrlicht/CAttributeImpl.h @@ -1828,13 +1828,13 @@ public: virtual core::stringw getStringW() { - return core::stringw(Value ? Value->getName().c_str() : 0); + return core::stringw(Value ? Value->getName().getPath().c_str() : 0); } virtual core::stringc getString() { // since texture names can be stringw we are careful with the types - return core::stringc(Value ? Value->getName().c_str() : 0); + return core::stringc(Value ? Value->getName().getPath().c_str() : 0); } virtual void setString(const char* text) @@ -1852,7 +1852,7 @@ public: { if ( value == Value ) return; - + if (Value) Value->drop(); @@ -1884,7 +1884,7 @@ class CStringWArrayAttribute : public IAttribute { public: - CStringWArrayAttribute(const char* name, core::array value) + CStringWArrayAttribute(const char* name, const core::array& value) { Name = name; setArray(value); @@ -1895,7 +1895,7 @@ public: return Value; } - virtual void setArray(core::array value) + virtual void setArray(const core::array& value) { Value = value; } diff --git a/source/Irrlicht/CAttributes.cpp b/source/Irrlicht/CAttributes.cpp index 260724c6..712d9910 100644 --- a/source/Irrlicht/CAttributes.cpp +++ b/source/Irrlicht/CAttributes.cpp @@ -181,13 +181,13 @@ core::stringw CAttributes::getAttributeAsStringW(s32 index) //! Adds an attribute as an array of wide strings -void CAttributes::addArray(const c8* attributeName, core::array value) +void CAttributes::addArray(const c8* attributeName, const core::array& value) { Attributes.push_back(new CStringWArrayAttribute(attributeName, value)); } //! Sets an attribute value as an array of wide strings. -void CAttributes::setAttribute(const c8* attributeName, const core::array value) +void CAttributes::setAttribute(const c8* attributeName, const core::array& value) { IAttribute* att = getAttributeP(attributeName); if (att) @@ -220,7 +220,7 @@ core::array CAttributes::getAttributeAsArray(s32 index) } //! Sets an attribute as an array of wide strings -void CAttributes::setAttribute(s32 index, core::array value) +void CAttributes::setAttribute(s32 index, const core::array& value) { if (index >= 0 && index < (s32)Attributes.size() ) Attributes[index]->setArray(value); @@ -1487,6 +1487,12 @@ void CAttributes::readAttributeFromXML(io::IXMLReader* reader) } addArray(name.c_str(),tmpArray); } + else + if (element == L"userPointer") + { + // It's debatable if a pointer should be set or not, but it's more likely that adding it now would wreck user-applications. + // Also it probably doesn't makes sense setting this to a value when it comes from file. + } } //! Write these attributes into a xml file diff --git a/source/Irrlicht/CAttributes.h b/source/Irrlicht/CAttributes.h index c08d1ee2..f1e80dfe 100644 --- a/source/Irrlicht/CAttributes.h +++ b/source/Irrlicht/CAttributes.h @@ -6,6 +6,7 @@ #define __C_ATTRIBUTES_H_INCLUDED__ #include "IAttributes.h" +#include "IAttribute.h" namespace irr { @@ -17,7 +18,6 @@ namespace video namespace io { -class IAttribute; //! Implementation of the IAttributes interface class CAttributes : public IAttributes @@ -210,12 +210,12 @@ public: */ //! Adds an attribute as wide string array - virtual void addArray(const c8* attributeName, core::array value); + virtual void addArray(const c8* attributeName, const core::array& value); //! Sets an attribute value as a wide string array. //! \param attributeName: Name for the attribute //! \param value: Value for the attribute. Set this to 0 to delete the attribute - virtual void setAttribute(const c8* attributeName, const core::array value); + virtual void setAttribute(const c8* attributeName, const core::array& value); //! Gets an attribute as an array of wide strings. //! \param attributeName: Name of the attribute to get. @@ -228,7 +228,7 @@ public: virtual core::array getAttributeAsArray(s32 index); //! Sets an attribute as an array of wide strings - virtual void setAttribute(s32 index, core::array value); + virtual void setAttribute(s32 index, const core::array& value); /* @@ -654,77 +654,6 @@ protected: video::IVideoDriver* Driver; }; - -class IAttribute : public virtual IReferenceCounted -{ -public: - - virtual ~IAttribute() {}; - - virtual s32 getInt() { return 0; } - virtual f32 getFloat() { return 0; } - virtual video::SColorf getColorf() { return video::SColorf(1.0f,1.0f,1.0f,1.0f); } - virtual video::SColor getColor() { return video::SColor(255,255,255,255); } - virtual core::stringc getString() { return core::stringc(getStringW().c_str()); } - virtual core::stringw getStringW() { return core::stringw(); } - virtual core::array getArray() { return core::array(); }; - virtual bool getBool() { return false; } - virtual void getBinary(void* outdata, s32 maxLength) {}; - virtual core::vector3df getVector() { return core::vector3df(); } - virtual core::position2di getPosition() { return core::position2di(); } - virtual core::rect getRect() { return core::rect(); } - virtual core::quaternion getQuaternion(){ return core::quaternion(); } - virtual core::matrix4 getMatrix() { return core::matrix4(); } - virtual core::triangle3df getTriangle() { return core::triangle3df(); } - virtual core::vector2df getVector2d() { return core::vector2df(); } - virtual core::vector2di getVector2di() { return core::vector2di(); } - virtual core::line2df getLine2d() { return core::line2df(); } - virtual core::line2di getLine2di() { return core::line2di(); } - virtual core::line3df getLine3d() { return core::line3df(); } - virtual core::line3di getLine3di() { return core::line3di(); } - virtual core::dimension2du getDimension2d() { return core::dimension2du(); } - virtual core::aabbox3d getBBox() { return core::aabbox3d(); } - virtual core::plane3df getPlane() { return core::plane3df(); } - - virtual video::ITexture* getTexture() { return 0; } - virtual const char* getEnum() { return 0; } - virtual void* getUserPointer() { return 0; } - - virtual void setInt(s32 intValue) {}; - virtual void setFloat(f32 floatValue) {}; - virtual void setString(const char* text) {}; - virtual void setString(const wchar_t* text){ setString(core::stringc(text).c_str()); }; - virtual void setArray( core::array arr ) {}; - virtual void setColor(video::SColorf color) {}; - virtual void setColor(video::SColor color) {}; - virtual void setBool(bool boolValue) {}; - virtual void setBinary(void* data, s32 maxLenght) {}; - virtual void setVector(core::vector3df v) {}; - virtual void setPosition(core::position2di v) {}; - virtual void setRect(core::rect v) {}; - virtual void setQuaternion(core::quaternion v) {}; - virtual void setMatrix(core::matrix4 v) {}; - virtual void setTriangle(core::triangle3df v) {}; - virtual void setVector2d(core::vector2df v) {}; - virtual void setVector2d(core::vector2di v) {}; - virtual void setLine2d(core::line2df v) {}; - virtual void setLine2d(core::line2di v) {}; - virtual void setLine3d(core::line3df v) {}; - virtual void setLine3d(core::line3di v) {}; - virtual void setDimension2d(core::dimension2du v) {}; - virtual void setBBox(core::aabbox3d v) {}; - virtual void setPlane(core::plane3df v) {}; - virtual void setUserPointer(void* v) {}; - - virtual void setEnum(const char* enumValue, const char* const* enumerationLiterals) {}; - virtual void setTexture(video::ITexture*) {}; - - core::stringc Name; - - virtual E_ATTRIBUTE_TYPE getType() const = 0; - virtual const wchar_t* getTypeString() const = 0; -}; - } // end namespace io } // end namespace irr diff --git a/source/Irrlicht/CB3DMeshFileLoader.cpp b/source/Irrlicht/CB3DMeshFileLoader.cpp index ee9a35b6..6f64fec8 100644 --- a/source/Irrlicht/CB3DMeshFileLoader.cpp +++ b/source/Irrlicht/CB3DMeshFileLoader.cpp @@ -27,7 +27,7 @@ namespace scene //! Constructor CB3DMeshFileLoader::CB3DMeshFileLoader(scene::ISceneManager* smgr) : SceneManager(smgr), AnimatedMesh(0), B3DFile(0), NormalsInFile(false), - ShowWarning(true) + HasVertexColors(false), ShowWarning(true) { #ifdef _DEBUG setDebugName("CB3DMeshFileLoader"); @@ -56,9 +56,6 @@ IAnimatedMesh* CB3DMeshFileLoader::createMesh(io::IReadFile* f) AnimatedMesh = new scene::CSkinnedMesh(); ShowWarning = true; // If true a warning is issued if too many textures are used - Buffers = &AnimatedMesh->getMeshBuffers(); - AllJoints = &AnimatedMesh->getAllJoints(); - if ( load() ) { AnimatedMesh->finalize(); @@ -78,6 +75,7 @@ bool CB3DMeshFileLoader::load() B3dStack.clear(); NormalsInFile=false; + HasVertexColors=false; //------ Get header ------ @@ -145,9 +143,6 @@ bool CB3DMeshFileLoader::load() Materials.clear(); Textures.clear(); - Buffers=0; - AllJoints=0; - return true; } @@ -250,6 +245,7 @@ bool CB3DMeshFileLoader::readChunkMESH(CSkinnedMesh::SJoint *inJoint) #endif NormalsInFile=false; + HasVertexColors=false; while((B3dStack.getLast().startposition + B3dStack.getLast().length) > B3DFile->getPos()) //this chunk repeats { @@ -354,16 +350,22 @@ bool CB3DMeshFileLoader::readChunkVRTS(CSkinnedMesh::SJoint *inJoint) //------ Allocate Memory, for speed -----------// - s32 NumberOfReads = 3; + s32 numberOfReads = 3; if (flags & 1) - NumberOfReads += 3; + { + NormalsInFile = true; + numberOfReads += 3; + } if (flags & 2) - NumberOfReads += 4; + { + numberOfReads += 4; + HasVertexColors=true; + } - NumberOfReads += tex_coord_sets*tex_coord_set_size; + numberOfReads += tex_coord_sets*tex_coord_set_size; - const s32 memoryNeeded = (B3dStack.getLast().length / sizeof(f32)) / NumberOfReads; + const s32 memoryNeeded = (B3dStack.getLast().length / sizeof(f32)) / numberOfReads; BaseVertices.reallocate(memoryNeeded + BaseVertices.size() + 1); AnimatedVertices_VertexID.reallocate(memoryNeeded + AnimatedVertices_VertexID.size() + 1); @@ -380,11 +382,7 @@ bool CB3DMeshFileLoader::readChunkVRTS(CSkinnedMesh::SJoint *inJoint) readFloats(position, 3); if (flags & 1) - { - NormalsInFile = true; readFloats(normal, 3); - } - if (flags & 2) readFloats(color, 4); @@ -510,7 +508,9 @@ bool CB3DMeshFileLoader::readChunkTRIS(scene::SSkinMeshBuffer *meshBuffer, u32 m // Apply Material/Color/etc... video::S3DVertex *Vertex=meshBuffer->getVertex(meshBuffer->getVertexCount()-1); - if (Vertex->Color.getAlpha() == 255) + if (!HasVertexColors) + Vertex->Color=B3dMaterial->Material.DiffuseColor; + else if (Vertex->Color.getAlpha() == 255) Vertex->Color.setAlpha( (s32)(B3dMaterial->alpha * 255.0f) ); // Use texture's scale @@ -554,24 +554,23 @@ bool CB3DMeshFileLoader::readChunkBONE(CSkinnedMesh::SJoint *inJoint) { while((B3dStack.getLast().startposition + B3dStack.getLast().length) > B3DFile->getPos()) // this chunk repeats { - CSkinnedMesh::SWeight *weight=AnimatedMesh->addWeight(inJoint); - u32 globalVertexID; - + f32 strength; B3DFile->read(&globalVertexID, sizeof(globalVertexID)); - B3DFile->read(&weight->strength, sizeof(weight->strength)); + B3DFile->read(&strength, sizeof(strength)); #ifdef __BIG_ENDIAN__ globalVertexID = os::Byteswap::byteswap(globalVertexID); - weight->strength = os::Byteswap::byteswap(weight->strength); + strength = os::Byteswap::byteswap(strength); #endif if (AnimatedVertices_VertexID[globalVertexID]==-1) { os::Printer::log("B3dMeshLoader: Weight has bad vertex id (no link to meshbuffer index found)"); - weight->vertex_id = weight->buffer_id = 0; } - else + else if (strength >0) { + CSkinnedMesh::SWeight *weight=AnimatedMesh->addWeight(inJoint); + weight->strength=strength; //Find the meshbuffer and Vertex index from the Global Vertex ID: weight->vertex_id = AnimatedVertices_VertexID[globalVertexID]; weight->buffer_id = AnimatedVertices_BufferID[globalVertexID]; @@ -596,6 +595,13 @@ bool CB3DMeshFileLoader::readChunkKEYS(CSkinnedMesh::SJoint *inJoint) flags = os::Byteswap::byteswap(flags); #endif + CSkinnedMesh::SPositionKey *oldPosKey=0; + core::vector3df oldPos[2]; + CSkinnedMesh::SScaleKey *oldScaleKey=0; + core::vector3df oldScale[2]; + CSkinnedMesh::SRotationKey *oldRotKey=0; + core::quaternion oldRot[2]; + bool isFirst[3]={true}; while((B3dStack.getLast().startposition + B3dStack.getLast().length) > B3DFile->getPos()) //this chunk repeats { s32 frame; @@ -610,24 +616,104 @@ bool CB3DMeshFileLoader::readChunkKEYS(CSkinnedMesh::SJoint *inJoint) if (flags & 1) { readFloats(data, 3); - CSkinnedMesh::SPositionKey *Key=AnimatedMesh->addPositionKey(inJoint); - Key->frame = (f32)frame-1; - Key->position.set(data[0], data[1], data[2]); + if ((oldPosKey!=0) && (oldPos[0]==oldPos[1])) + { + const core::vector3df pos(data[0], data[1], data[2]); + if (oldPos[1]==pos) + oldPosKey->frame = (f32)frame-1; + else + { + oldPos[0]=oldPos[1]; + oldPosKey=AnimatedMesh->addPositionKey(inJoint); + oldPosKey->frame = (f32)frame-1; + oldPos[1].set(oldPosKey->position.set(pos)); + } + } + else if (oldPosKey==0 && isFirst[0]) + { + oldPosKey=AnimatedMesh->addPositionKey(inJoint); + oldPosKey->frame = (f32)frame-1; + oldPos[0].set(oldPosKey->position.set(data[0], data[1], data[2])); + oldPosKey=0; + isFirst[0]=false; + } + else + { + if (oldPosKey!=0) + oldPos[0]=oldPos[1]; + oldPosKey=AnimatedMesh->addPositionKey(inJoint); + oldPosKey->frame = (f32)frame-1; + oldPos[1].set(oldPosKey->position.set(data[0], data[1], data[2])); + } } if (flags & 2) { readFloats(data, 3); - CSkinnedMesh::SScaleKey *Key=AnimatedMesh->addScaleKey(inJoint); - Key->frame = (f32)frame-1; - Key->scale.set(data[0], data[1], data[2]); + if ((oldScaleKey!=0) && (oldScale[0]==oldScale[1])) + { + const core::vector3df scale(data[0], data[1], data[2]); + if (oldScale[1]==scale) + oldScaleKey->frame = (f32)frame-1; + else + { + oldScale[0]=oldScale[1]; + oldScaleKey=AnimatedMesh->addScaleKey(inJoint); + oldScaleKey->frame = (f32)frame-1; + oldScale[1].set(oldScaleKey->scale.set(scale)); + } + } + else if (oldScaleKey==0 && isFirst[1]) + { + oldScaleKey=AnimatedMesh->addScaleKey(inJoint); + oldScaleKey->frame = (f32)frame-1; + oldScale[0].set(oldScaleKey->scale.set(data[0], data[1], data[2])); + oldScaleKey=0; + isFirst[1]=false; + } + else + { + if (oldScaleKey!=0) + oldScale[0]=oldScale[1]; + oldScaleKey=AnimatedMesh->addScaleKey(inJoint); + oldScaleKey->frame = (f32)frame-1; + oldScale[1].set(oldScaleKey->scale.set(data[0], data[1], data[2])); + } } if (flags & 4) { readFloats(data, 4); - CSkinnedMesh::SRotationKey *Key=AnimatedMesh->addRotationKey(inJoint); - Key->frame = (f32)frame-1; - // meant to be in this order since b3d stores W first - Key->rotation.set(data[1], data[2], data[3], data[0]); + if ((oldRotKey!=0) && (oldRot[0]==oldRot[1])) + { + // meant to be in this order since b3d stores W first + const core::quaternion rot(data[1], data[2], data[3], data[0]); + if (oldRot[1]==rot) + oldRotKey->frame = (f32)frame-1; + else + { + oldRot[0]=oldRot[1]; + oldRotKey=AnimatedMesh->addRotationKey(inJoint); + oldRotKey->frame = (f32)frame-1; + oldRot[1].set(oldRotKey->rotation.set(data[1], data[2], data[3], data[0])); + } + } + else if (oldRotKey==0 && isFirst[2]) + { + oldRotKey=AnimatedMesh->addRotationKey(inJoint); + oldRotKey->frame = (f32)frame-1; + // meant to be in this order since b3d stores W first + oldRot[0].set(oldRotKey->rotation.set(data[1], data[2], data[3], data[0])); + oldRotKey=0; + isFirst[2]=false; + } + else + { + if (oldRotKey!=0) + oldRot[0]=oldRot[1]; + oldRotKey=AnimatedMesh->addRotationKey(inJoint); + oldRotKey->frame = (f32)frame-1; + // meant to be in this order since b3d stores W first + oldRot[1].set(oldRotKey->rotation.set(data[1], data[2], data[3], data[0])); + } } } @@ -724,7 +810,7 @@ bool CB3DMeshFileLoader::readChunkBRUS() core::stringc name; readString(name); #ifdef _B3D_READER_DEBUG - os::Printer::log("read Material"); + os::Printer::log("read Material", name); #endif Materials.push_back(SB3dMaterial()); SB3dMaterial& B3dMaterial=Materials.getLast(); @@ -859,6 +945,7 @@ bool CB3DMeshFileLoader::readChunkBRUS() } B3dMaterial.Material.DiffuseColor = video::SColorf(B3dMaterial.red, B3dMaterial.green, B3dMaterial.blue, B3dMaterial.alpha).toSColor(); + B3dMaterial.Material.ColorMaterial=video::ECM_NONE; //------ Material fx ------ @@ -870,7 +957,8 @@ bool CB3DMeshFileLoader::readChunkBRUS() else B3dMaterial.Material.AmbientColor = B3dMaterial.Material.DiffuseColor; - //if (B3dMaterial.fx & 2) //use vertex colors instead of brush color + if (B3dMaterial.fx & 2) //use vertex colors instead of brush color + B3dMaterial.Material.ColorMaterial=video::ECM_DIFFUSE_AND_AMBIENT; if (B3dMaterial.fx & 4) //flatshaded B3dMaterial.Material.GouraudShading = false; @@ -912,7 +1000,15 @@ void CB3DMeshFileLoader::loadTextures(SB3dMaterial& material) const { video::ITexture* tex = 0; io::IFileSystem* fs = SceneManager->getFileSystem(); - if (fs->existFile(B3dTexture->TextureName)) + io::path texnameWithUserPath( SceneManager->getParameters()->getAttributeAsString(B3D_TEXTURE_PATH) ); + if ( texnameWithUserPath.size() ) + { + texnameWithUserPath += '/'; + texnameWithUserPath += B3dTexture->TextureName; + } + if (fs->existFile(texnameWithUserPath)) + tex = SceneManager->getVideoDriver()->getTexture(texnameWithUserPath); + else if (fs->existFile(B3dTexture->TextureName)) tex = SceneManager->getVideoDriver()->getTexture(B3dTexture->TextureName); else if (fs->existFile(fs->getFileDir(B3DFile->getFileName()) +"/"+ fs->getFileBasename(B3dTexture->TextureName))) tex = SceneManager->getVideoDriver()->getTexture(fs->getFileDir(B3DFile->getFileName()) +"/"+ fs->getFileBasename(B3dTexture->TextureName)); diff --git a/source/Irrlicht/CB3DMeshFileLoader.h b/source/Irrlicht/CB3DMeshFileLoader.h index ba7da857..bc70dd9f 100644 --- a/source/Irrlicht/CB3DMeshFileLoader.h +++ b/source/Irrlicht/CB3DMeshFileLoader.h @@ -119,14 +119,12 @@ private: core::array BaseVertices; - core::array *Buffers; - core::array *AllJoints; - ISceneManager* SceneManager; CSkinnedMesh* AnimatedMesh; io::IReadFile* B3DFile; bool NormalsInFile; + bool HasVertexColors; bool ShowWarning; }; diff --git a/source/Irrlicht/CCSMLoader.h b/source/Irrlicht/CCSMLoader.h index 190108b0..fc6b0e03 100644 --- a/source/Irrlicht/CCSMLoader.h +++ b/source/Irrlicht/CCSMLoader.h @@ -30,7 +30,7 @@ // 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 IOctTreeSceneNode +// * 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 diff --git a/source/Irrlicht/CCubeSceneNode.cpp b/source/Irrlicht/CCubeSceneNode.cpp index f697f8dc..dfd6c007 100644 --- a/source/Irrlicht/CCubeSceneNode.cpp +++ b/source/Irrlicht/CCubeSceneNode.cpp @@ -61,9 +61,71 @@ void CCubeSceneNode::setSize() void CCubeSceneNode::render() { video::IVideoDriver* driver = SceneManager->getVideoDriver(); - driver->setMaterial(Mesh->getMeshBuffer(0)->getMaterial()); driver->setTransform(video::ETS_WORLD, AbsoluteTransformation); + + // for debug purposes only: + bool renderMeshes = true; + video::SMaterial mat = Mesh->getMeshBuffer(0)->getMaterial(); + + // overwrite half transparency + if (DebugDataVisible & scene::EDS_HALF_TRANSPARENCY) + mat.MaterialType = video::EMT_TRANSPARENT_ADD_COLOR; + else + driver->setMaterial(Mesh->getMeshBuffer(0)->getMaterial()); + driver->setMaterial(mat); driver->drawMeshBuffer(Mesh->getMeshBuffer(0)); + + // for debug purposes only: + if (DebugDataVisible) + { + video::SMaterial m; + m.Lighting = false; + m.AntiAliasing=0; + driver->setMaterial(m); + + if (DebugDataVisible & scene::EDS_BBOX) + { + driver->draw3DBox(Mesh->getMeshBuffer(0)->getBoundingBox(), video::SColor(255,255,255,255)); + } + if (DebugDataVisible & scene::EDS_BBOX_BUFFERS) + { + driver->draw3DBox(Mesh->getMeshBuffer(0)->getBoundingBox(), + video::SColor(255,190,128,128)); + } + if (DebugDataVisible & scene::EDS_NORMALS) + { + // draw normals + core::vector3df normalizedNormal; + const f32 DebugNormalLength = SceneManager->getParameters()->getAttributeAsFloat(DEBUG_NORMAL_LENGTH); + const video::SColor DebugNormalColor = SceneManager->getParameters()->getAttributeAsColor(DEBUG_NORMAL_COLOR); + + const scene::IMeshBuffer* mb = Mesh->getMeshBuffer(0); + const u32 vSize = video::getVertexPitchFromType(mb->getVertexType()); + const video::S3DVertex* v = ( const video::S3DVertex*)mb->getVertices(); + const bool normalize = mb->getMaterial().NormalizeNormals; + + for (u32 i=0; i != mb->getVertexCount(); ++i) + { + normalizedNormal = v->Normal; + if (normalize) + normalizedNormal.normalize(); + + driver->draw3DLine(v->Pos, v->Pos + (normalizedNormal * DebugNormalLength), DebugNormalColor); + + v = (const video::S3DVertex*) ( (u8*) v+vSize ); + } + driver->setTransform(video::ETS_WORLD, AbsoluteTransformation); + } + + // show mesh + if (DebugDataVisible & scene::EDS_MESH_WIRE_OVERLAY) + { + m.Wireframe = true; + driver->setMaterial(m); + + driver->drawMeshBuffer( Mesh->getMeshBuffer(0) ); + } + } } diff --git a/source/Irrlicht/CD3D8Driver.cpp b/source/Irrlicht/CD3D8Driver.cpp index cf3a0137..77e4893e 100644 --- a/source/Irrlicht/CD3D8Driver.cpp +++ b/source/Irrlicht/CD3D8Driver.cpp @@ -400,10 +400,10 @@ bool CD3D8Driver::initDriver(const core::dimension2d& screenSize, //! applications must call this method before performing any rendering. returns false if failed. bool CD3D8Driver::beginScene(bool backBuffer, bool zBuffer, SColor color, - void* windowId, core::rect* sourceRect) + const SExposedVideoData& videoData, core::rect* sourceRect) { - CNullDriver::beginScene(backBuffer, zBuffer, color, windowId, sourceRect); - WindowId = windowId; + CNullDriver::beginScene(backBuffer, zBuffer, color, videoData, sourceRect); + WindowId = (HWND)videoData.D3D8.HWnd; SceneSourceRect = sourceRect; if (!pID3DDevice) @@ -412,8 +412,7 @@ bool CD3D8Driver::beginScene(bool backBuffer, bool zBuffer, SColor color, HRESULT hr; if (DeviceLost) { -#if defined( _IRR_XBOX_PLATFORM_) -#else +#ifndef _IRR_XBOX_PLATFORM_ if(FAILED(hr = pID3DDevice->TestCooperativeLevel())) { if (hr == D3DERR_DEVICELOST) @@ -480,7 +479,7 @@ bool CD3D8Driver::endScene() sourceRectData.bottom = SceneSourceRect->LowerRightCorner.Y; } - hr = pID3DDevice->Present(srcRct, NULL, (HWND)WindowId, NULL); + hr = pID3DDevice->Present(srcRct, NULL, WindowId, NULL); if (SUCCEEDED(hr)) return true; @@ -674,9 +673,9 @@ void CD3D8Driver::setMaterial(const SMaterial& material) //! returns a device dependent texture from a software surface (IImage) -video::ITexture* CD3D8Driver::createDeviceDependentTexture(IImage* surface,const io::path& name) +video::ITexture* CD3D8Driver::createDeviceDependentTexture(IImage* surface,const io::path& name, void* mipmapData) { - return new CD3D8Texture(surface, this, TextureCreationFlags, name); + return new CD3D8Texture(surface, this, TextureCreationFlags, name, mipmapData); } @@ -1755,13 +1754,12 @@ void CD3D8Driver::setRenderStates2DMode(bool alpha, bool texture, bool alphaChan { if (static_cast(LastMaterial.MaterialType) < MaterialRenderers.size()) MaterialRenderers[LastMaterial.MaterialType].Renderer->OnUnsetMaterial(); + } + if (!OverrideMaterial2DEnabled) + { + setBasicRenderStates(InitMaterial2D, LastMaterial, true); + LastMaterial=InitMaterial2D; - SMaterial mat; - mat.ZBuffer=ECFN_NEVER; - mat.Lighting=false; - mat.AntiAliasing=video::EAAM_OFF; - mat.TextureLayer[0].BilinearFilter=false; - setBasicRenderStates(mat, mat, true); // fix everything that is wrongly set by SMaterial default pID3DDevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE); pID3DDevice->SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_DISABLE ); @@ -1772,11 +1770,8 @@ void CD3D8Driver::setRenderStates2DMode(bool alpha, bool texture, bool alphaChan pID3DDevice->SetRenderState( D3DRS_STENCILENABLE, FALSE ); - setTransform(ETS_TEXTURE_0, core::IdentityMatrix); - pID3DDevice->SetTextureStageState(0, D3DTSS_TEXCOORDINDEX, 0); } pID3DDevice->SetTransform(D3DTS_WORLD, &UnitMatrixD3D8); - core::matrix4 m; m.setTranslation(core::vector3df(-0.5f,-0.5f,0)); pID3DDevice->SetTransform(D3DTS_VIEW, (D3DMATRIX*)((void*)m.pointer())); @@ -1788,9 +1783,18 @@ void CD3D8Driver::setRenderStates2DMode(bool alpha, bool texture, bool alphaChan Transformation3DChanged = false; } + if (OverrideMaterial2DEnabled) + { + OverrideMaterial2D.Lighting=false; + OverrideMaterial2D.ZBuffer=ECFN_NEVER; + OverrideMaterial2D.ZWriteEnable=false; + setBasicRenderStates(OverrideMaterial2D, LastMaterial, false); + LastMaterial = OverrideMaterial2D; + } if (texture) { + setTransform(ETS_TEXTURE_0, core::IdentityMatrix); if (alphaChannel) { pID3DDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE ); @@ -2144,13 +2148,6 @@ bool CD3D8Driver::setPixelShaderConstant(const c8* name, const f32* floats, int } -//! Returns pointer to the IGPUProgrammingServices interface. -IGPUProgrammingServices* CD3D8Driver::getGPUProgrammingServices() -{ - return this; -} - - //! Adds a new material renderer to the VideoDriver, using pixel and/or //! vertex shaders to render geometry. s32 CD3D8Driver::addShaderMaterial(const c8* vertexShaderProgram, diff --git a/source/Irrlicht/CD3D8Driver.h b/source/Irrlicht/CD3D8Driver.h index 6d50c996..7394d57e 100644 --- a/source/Irrlicht/CD3D8Driver.h +++ b/source/Irrlicht/CD3D8Driver.h @@ -40,7 +40,7 @@ namespace video //! applications must call this method before performing any rendering. returns false if failed. virtual bool beginScene(bool backBuffer=true, bool zBuffer=true, SColor color=SColor(255,0,0,0), - void* windowId=0, + const SExposedVideoData& videoData=SExposedVideoData(), core::rect* sourceRect=0); //! applications must call this method after performing any rendering. returns false if failed. @@ -187,9 +187,6 @@ namespace video //! Sets a constant for the pixel shader based on a name. virtual bool setPixelShaderConstant(const c8* name, const f32* floats, int count); - //! Returns pointer to the IGPUProgrammingServices interface. - virtual IGPUProgrammingServices* getGPUProgrammingServices(); - //! Returns a pointer to the IVideoDriver interface. (Implementation for //! IMaterialRendererServices) virtual IVideoDriver* getVideoDriver(); @@ -257,7 +254,7 @@ namespace video //! returns a device dependent texture from a software surface (IImage) //! THIS METHOD HAS TO BE OVERRIDDEN BY DERIVED DRIVERS WITH OWN TEXTURES - virtual video::ITexture* createDeviceDependentTexture(IImage* surface, const io::path& name); + virtual video::ITexture* createDeviceDependentTexture(IImage* surface, const io::path& name, void* mipmapData=0); // returns the current size of the screen or rendertarget virtual const core::dimension2d& getCurrentRenderTargetSize() const; @@ -305,7 +302,7 @@ namespace video IDirect3DSurface8* PrevRenderTarget; core::dimension2d CurrentRendertargetSize; - void* WindowId; + HWND WindowId; core::rect* SceneSourceRect; D3DCAPS8 Caps; diff --git a/source/Irrlicht/CD3D8Texture.cpp b/source/Irrlicht/CD3D8Texture.cpp index 34ea33b2..c0ae62b3 100644 --- a/source/Irrlicht/CD3D8Texture.cpp +++ b/source/Irrlicht/CD3D8Texture.cpp @@ -50,7 +50,7 @@ CD3D8Texture::CD3D8Texture(CD3D8Driver* driver, const core::dimension2d& si //! constructor CD3D8Texture::CD3D8Texture(IImage* image, CD3D8Driver* driver, - u32 flags, const io::path& name) + u32 flags, const io::path& name, void* mipmapData) : ITexture(name), Texture(0), RTTSurface(0), Driver(driver), TextureSize(0,0), ImageSize(0,0), Pitch(0), HasMipMaps(false), IsRenderTarget(false) @@ -59,7 +59,7 @@ HasMipMaps(false), IsRenderTarget(false) setDebugName("CD3D8Texture"); #endif - const bool generateMipLevels = Driver->getTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS); + HasMipMaps = Driver->getTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS); Device=driver->getExposedVideoData().D3D8.D3DDev8; if (Device) @@ -67,26 +67,11 @@ HasMipMaps(false), IsRenderTarget(false) if (image) { - if (createTexture(image, flags)) + if (createTexture(flags, image)) { - if (copyTexture(image) && generateMipLevels) + if (copyTexture(image)) { - // create mip maps. - - #ifndef _IRR_USE_D3DXFilterTexture_ - // The D3DXFilterTexture function seems to get linked wrong when - // compiling with both D3D8 and 9, causing it not to work in the D3D9 device. - // So mipmapgeneration is replaced with my own bad generation in d3d 8 when - // compiling with both D3D 8 and 9. - HRESULT hr = D3DXFilterTexture(Texture, NULL, D3DX_DEFAULT , D3DX_DEFAULT ); - if (FAILED(hr)) - os::Printer::log("Could not create direct3d mip map levels.", ELL_WARNING); - else - HasMipMaps = true; - #else - createMipMaps(); - HasMipMaps = true; - #endif + regenerateMipMapLevels(mipmapData); } } else @@ -110,7 +95,7 @@ CD3D8Texture::~CD3D8Texture() //! creates the hardware texture -bool CD3D8Texture::createTexture(video::IImage* image, u32 flags) +bool CD3D8Texture::createTexture(u32 flags, video::IImage* image) { ImageSize = image->getDimension(); @@ -220,23 +205,30 @@ bool CD3D8Texture::copyTexture(video::IImage* image) //! lock function -void* CD3D8Texture::lock(bool readOnly) +void* CD3D8Texture::lock(bool readOnly, u32 mipmapLevel) { if (!Texture) return 0; + MipLevelLocked=mipmapLevel; HRESULT hr; D3DLOCKED_RECT rect; if(!IsRenderTarget) { - hr = Texture->LockRect(0, &rect, 0, readOnly?D3DLOCK_READONLY:0); + hr = Texture->LockRect(mipmapLevel, &rect, 0, readOnly?D3DLOCK_READONLY:0); + if (FAILED(hr)) + { + os::Printer::log("Could not lock DIRECT3D9 Texture.", ELL_ERROR); + return 0; + } } else { - D3DSURFACE_DESC desc; - Texture->GetLevelDesc(0, &desc); if (!RTTSurface) { + // Make RTT surface large enough for all miplevels (including 0) + D3DSURFACE_DESC desc; + Texture->GetLevelDesc(0, &desc); hr = Device->CreateImageSurface(desc.Width, desc.Height, desc.Format, &RTTSurface); if (FAILED(hr)) { @@ -246,33 +238,26 @@ void* CD3D8Texture::lock(bool readOnly) } IDirect3DSurface8 *surface = 0; - hr = Texture->GetSurfaceLevel(0, &surface); + hr = Texture->GetSurfaceLevel(mipmapLevel, &surface); if (FAILED(hr)) { - os::Printer::log("Could not lock DIRECT3D8 Texture.", ELL_ERROR); + os::Printer::log("Could not lock DIRECT3D8 Texture.", "Could not get surface.", ELL_ERROR); return 0; } hr = Device->CopyRects(surface, 0, 0, RTTSurface, 0); surface->Release(); if(FAILED(hr)) { - os::Printer::log("Could not lock DIRECT3D8 Texture.", ELL_ERROR); + os::Printer::log("Could not lock DIRECT3D8 Texture.", "Data copy failed.", ELL_ERROR); return 0; } hr = RTTSurface->LockRect(&rect, 0, readOnly?D3DLOCK_READONLY:0); if(FAILED(hr)) { - os::Printer::log("Could not lock DIRECT3D8 Texture.", ELL_ERROR); + os::Printer::log("Could not lock DIRECT3D8 Texture.", "LockRect failed.", ELL_ERROR); return 0; } - return rect.pBits; } - if (FAILED(hr)) - { - os::Printer::log("Could not lock DIRECT3D8 Texture.", ELL_ERROR); - return 0; - } - return rect.pBits; } @@ -284,7 +269,7 @@ void CD3D8Texture::unlock() return; if (!IsRenderTarget) - Texture->UnlockRect(0); + Texture->UnlockRect(MipLevelLocked); else if (RTTSurface) RTTSurface->UnlockRect(); } @@ -587,10 +572,59 @@ void CD3D8Texture::createRenderTarget() //! Regenerates the mip map levels of the texture. Useful after locking and //! modifying the texture -void CD3D8Texture::regenerateMipMapLevels() +void CD3D8Texture::regenerateMipMapLevels(void* mipmapData) { - if (HasMipMaps) + if (mipmapData) + { + core::dimension2du size = TextureSize; + u32 level=0; + do + { + if (size.Width>1) + size.Width /=2; + if (size.Height>1) + size.Height /=2; + ++level; + IDirect3DSurface8* mipSurface = 0; + HRESULT hr = Texture->GetSurfaceLevel(level, &mipSurface); + if (FAILED(hr) || !mipSurface) + { + os::Printer::log("Could not get mipmap level", ELL_WARNING); + return; + } + D3DSURFACE_DESC mipDesc; + mipSurface->GetDesc(&mipDesc); + D3DLOCKED_RECT miplr; + + // lock mipmap surface + if (FAILED(mipSurface->LockRect(&miplr, NULL, 0))) + { + mipSurface->Release(); + os::Printer::log("Could not lock texture", ELL_WARNING); + return; + } + + memcpy(miplr.pBits, mipmapData, size.getArea()*getPitch()/TextureSize.Width); + mipmapData = (u8*)mipmapData+size.getArea()*getPitch()/TextureSize.Width; + // unlock + mipSurface->UnlockRect(); + // release + mipSurface->Release(); + } while (size.Width != 1 || size.Height != 1); + } + else if (HasMipMaps) + { + // create mip maps. +#ifndef _IRR_USE_D3DXFilterTexture_ + // The D3DXFilterTexture function seems to get linked wrong when + // compiling with both D3D8 and 9, causing it not to work in the D3D9 device. + // So mipmapgeneration is replaced with my own bad generation in d3d 8 when + // compiling with both D3D 8 and 9. + HRESULT hr = D3DXFilterTexture(Texture, NULL, D3DX_DEFAULT , D3DX_DEFAULT ); + if (FAILED(hr)) +#endif createMipMaps(); + } } diff --git a/source/Irrlicht/CD3D8Texture.h b/source/Irrlicht/CD3D8Texture.h index f1b3751c..25ae8eeb 100644 --- a/source/Irrlicht/CD3D8Texture.h +++ b/source/Irrlicht/CD3D8Texture.h @@ -29,7 +29,7 @@ public: //! constructor CD3D8Texture(IImage* image, CD3D8Driver* driver, - u32 flags, const io::path& name); + u32 flags, const io::path& name, void* mipmapData=0); //! rendertarget constructor CD3D8Texture(CD3D8Driver* driver, const core::dimension2d& size, const io::path& name); @@ -38,7 +38,7 @@ public: virtual ~CD3D8Texture(); //! lock function - virtual void* lock(bool readOnly = false); + virtual void* lock(bool readOnly = false, u32 mipmapLevel=0); //! unlock function virtual void unlock(); @@ -66,7 +66,7 @@ public: //! Regenerates the mip map levels of the texture. Useful after locking and //! modifying the texture - virtual void regenerateMipMapLevels(); + virtual void regenerateMipMapLevels(void* mipmapData=0); //! returns if it is a render target virtual bool isRenderTarget() const; @@ -80,7 +80,7 @@ private: void createRenderTarget(); //! creates the hardware texture - bool createTexture(IImage* Image, u32 flags); + bool createTexture(u32 flags, IImage* Image); //! copies the image to the texture bool copyTexture(IImage* Image); @@ -103,7 +103,9 @@ private: core::dimension2d TextureSize; core::dimension2d ImageSize; s32 Pitch; + u32 MipLevelLocked; ECOLOR_FORMAT ColorFormat; + bool HasMipMaps; bool IsRenderTarget; }; diff --git a/source/Irrlicht/CD3D9Driver.cpp b/source/Irrlicht/CD3D9Driver.cpp index c4d090b8..89ef9713 100644 --- a/source/Irrlicht/CD3D9Driver.cpp +++ b/source/Irrlicht/CD3D9Driver.cpp @@ -475,10 +475,10 @@ bool CD3D9Driver::initDriver(const core::dimension2d& screenSize, //! applications must call this method before performing any rendering. returns false if failed. bool CD3D9Driver::beginScene(bool backBuffer, bool zBuffer, SColor color, - void* windowId, core::rect* sourceRect) + const SExposedVideoData& videoData, core::rect* sourceRect) { - CNullDriver::beginScene(backBuffer, zBuffer, color, windowId, sourceRect); - WindowId = windowId; + CNullDriver::beginScene(backBuffer, zBuffer, color, videoData, sourceRect); + WindowId = (HWND)videoData.D3D9.HWnd; SceneSourceRect = sourceRect; if (!pID3DDevice) @@ -552,7 +552,7 @@ bool CD3D9Driver::endScene() sourceRectData.bottom = SceneSourceRect->LowerRightCorner.Y; } - hr = pID3DDevice->Present(srcRct, NULL, (HWND)WindowId, NULL); + hr = pID3DDevice->Present(srcRct, NULL, WindowId, NULL); if (SUCCEEDED(hr)) return true; @@ -720,9 +720,9 @@ void CD3D9Driver::setMaterial(const SMaterial& material) //! returns a device dependent texture from a software surface (IImage) -video::ITexture* CD3D9Driver::createDeviceDependentTexture(IImage* surface,const io::path& name) +video::ITexture* CD3D9Driver::createDeviceDependentTexture(IImage* surface,const io::path& name, void* mipmapData) { - return new CD3D9Texture(surface, this, TextureCreationFlags, name); + return new CD3D9Texture(surface, this, TextureCreationFlags, name, mipmapData); } @@ -2344,6 +2344,15 @@ void CD3D9Driver::setRenderStatesStencilFillMode(bool alpha) } +//! Enable the 2d override material +void CD3D9Driver::enableMaterial2D(bool enable) +{ + if (!enable) + CurrentRenderMode = ERM_NONE; + CNullDriver::enableMaterial2D(enable); +} + + //! sets the needed renderstates void CD3D9Driver::setRenderStates2DMode(bool alpha, bool texture, bool alphaChannel) { @@ -2353,17 +2362,17 @@ void CD3D9Driver::setRenderStates2DMode(bool alpha, bool texture, bool alphaChan if (CurrentRenderMode != ERM_2D || Transformation3DChanged) { // unset last 3d material - if (CurrentRenderMode != ERM_2D) + if (CurrentRenderMode == ERM_3D) { if (static_cast(LastMaterial.MaterialType) < MaterialRenderers.size()) MaterialRenderers[LastMaterial.MaterialType].Renderer->OnUnsetMaterial(); - SMaterial mat; - mat.ZBuffer=ECFN_NEVER; - mat.Lighting=false; - mat.AntiAliasing=video::EAAM_OFF; - mat.TextureLayer[0].BilinearFilter=false; - setBasicRenderStates(mat, mat, true); - // fix everything that is wrongly set by SMaterial default + } + if (!OverrideMaterial2DEnabled) + { + setBasicRenderStates(InitMaterial2D, LastMaterial, true); + LastMaterial=InitMaterial2D; + + // fix everything that is wrongly set by InitMaterial2D default pID3DDevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE); pID3DDevice->SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_DISABLE); pID3DDevice->SetTextureStageState(2, D3DTSS_COLOROP, D3DTOP_DISABLE); @@ -2372,11 +2381,7 @@ void CD3D9Driver::setRenderStates2DMode(bool alpha, bool texture, bool alphaChan pID3DDevice->SetTextureStageState(3, D3DTSS_ALPHAOP, D3DTOP_DISABLE); pID3DDevice->SetRenderState( D3DRS_STENCILENABLE, FALSE ); - - setTransform(ETS_TEXTURE_0, core::IdentityMatrix); - pID3DDevice->SetTextureStageState( 0, D3DTSS_TEXCOORDINDEX, 0); } - pID3DDevice->SetTransform(D3DTS_WORLD, &UnitMatrixD3D9); core::matrix4 m; @@ -2390,6 +2395,14 @@ void CD3D9Driver::setRenderStates2DMode(bool alpha, bool texture, bool alphaChan Transformation3DChanged = false; } + if (OverrideMaterial2DEnabled) + { + OverrideMaterial2D.Lighting=false; + OverrideMaterial2D.ZBuffer=ECFN_NEVER; + OverrideMaterial2D.ZWriteEnable=false; + setBasicRenderStates(OverrideMaterial2D, LastMaterial, false); + LastMaterial = OverrideMaterial2D; + } u32 current2DSignature = 0; current2DSignature |= alpha ? EC2D_ALPHA : 0; @@ -2400,6 +2413,7 @@ void CD3D9Driver::setRenderStates2DMode(bool alpha, bool texture, bool alphaChan { if (texture) { + setTransform(ETS_TEXTURE_0, core::IdentityMatrix); if (alphaChannel) { pID3DDevice->SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_MODULATE ); @@ -2884,13 +2898,6 @@ bool CD3D9Driver::setPixelShaderConstant(const c8* name, const f32* floats, int } -//! Returns pointer to the IGPUProgrammingServices interface. -IGPUProgrammingServices* CD3D9Driver::getGPUProgrammingServices() -{ - return this; -} - - //! Adds a new material renderer to the VideoDriver, using pixel and/or //! vertex shaders to render geometry. s32 CD3D9Driver::addShaderMaterial(const c8* vertexShaderProgram, @@ -2917,6 +2924,11 @@ s32 CD3D9Driver::addHighLevelShaderMaterial( const c8* pixelShaderProgram, const c8* pixelShaderEntryPointName, E_PIXEL_SHADER_TYPE psCompileTarget, + const c8* geometryShaderProgram, + const c8* geometryShaderEntryPointName, + E_GEOMETRY_SHADER_TYPE gsCompileTarget, + scene::E_PRIMITIVE_TYPE inType, scene::E_PRIMITIVE_TYPE outType, + u32 verticesOut, IShaderConstantSetCallBack* callback, E_MATERIAL_TYPE baseMaterial, s32 userData) { diff --git a/source/Irrlicht/CD3D9Driver.h b/source/Irrlicht/CD3D9Driver.h index fe71b608..98b7725e 100644 --- a/source/Irrlicht/CD3D9Driver.h +++ b/source/Irrlicht/CD3D9Driver.h @@ -56,7 +56,7 @@ namespace video //! applications must call this method before performing any rendering. returns false if failed. virtual bool beginScene(bool backBuffer=true, bool zBuffer=true, SColor color=SColor(255,0,0,0), - void* windowId=0, + const SExposedVideoData& videoData=SExposedVideoData(), core::rect* sourceRect=0); //! applications must call this method after performing any rendering. returns false if failed. @@ -241,9 +241,6 @@ namespace video //! Sets a constant for the pixel shader based on a name. virtual bool setPixelShaderConstant(const c8* name, const f32* floats, int count); - //! Returns pointer to the IGPUProgrammingServices interface. - virtual IGPUProgrammingServices* getGPUProgrammingServices(); - //! Returns a pointer to the IVideoDriver interface. (Implementation for //! IMaterialRendererServices) virtual IVideoDriver* getVideoDriver(); @@ -267,6 +264,9 @@ namespace video //! Returns the graphics card vendor name. virtual core::stringc getVendorInfo() {return VendorName;} + //! Enable the 2d override material + virtual void enableMaterial2D(bool enable=true); + //! Check if the driver was recently reset. virtual bool checkDriverReset() {return DriverWasReset;} @@ -326,7 +326,7 @@ namespace video //! returns a device dependent texture from a software surface (IImage) //! THIS METHOD HAS TO BE OVERRIDDEN BY DERIVED DRIVERS WITH OWN TEXTURES - virtual video::ITexture* createDeviceDependentTexture(IImage* surface, const io::path& name); + virtual video::ITexture* createDeviceDependentTexture(IImage* surface, const io::path& name, void* mipmapData=0); //! returns the current size of the screen or rendertarget virtual const core::dimension2d& getCurrentRenderTargetSize() const; @@ -349,6 +349,12 @@ namespace video const c8* pixelShaderProgram = 0, const c8* pixelShaderEntryPointName = "main", E_PIXEL_SHADER_TYPE psCompileTarget = EPST_PS_1_1, + const c8* geometryShaderProgram = 0, + const c8* geometryShaderEntryPointName = "main", + E_GEOMETRY_SHADER_TYPE gsCompileTarget = EGST_GS_4_0, + scene::E_PRIMITIVE_TYPE inType = scene::EPT_TRIANGLES, + scene::E_PRIMITIVE_TYPE outType = scene::EPT_TRIANGLE_STRIP, + u32 verticesOut = 0, IShaderConstantSetCallBack* callback = 0, E_MATERIAL_TYPE baseMaterial = video::EMT_SOLID, s32 userData=0); @@ -393,7 +399,7 @@ namespace video core::dimension2d CurrentRendertargetSize; core::dimension2d CurrentDepthBufferSize; - void* WindowId; + HWND WindowId; core::rect* SceneSourceRect; D3DCAPS9 Caps; diff --git a/source/Irrlicht/CD3D9HLSLMaterialRenderer.cpp b/source/Irrlicht/CD3D9HLSLMaterialRenderer.cpp index a55c1b65..bb8ea807 100644 --- a/source/Irrlicht/CD3D9HLSLMaterialRenderer.cpp +++ b/source/Irrlicht/CD3D9HLSLMaterialRenderer.cpp @@ -178,7 +178,7 @@ bool CD3D9HLSLMaterialRenderer::createHLSLPixelShader(const char* pixelShaderPro #ifdef D3DXSHADER_ENABLE_BACKWARDS_COMPATIBILITY if (Driver->queryFeature(video::EVDF_VERTEX_SHADER_2_0) || Driver->queryFeature(video::EVDF_VERTEX_SHADER_3_0)) // this one's for newer DX SDKs which don't support ps_1_x anymore - // instead they'll siliently compile 1_x as 2_x when using this flag + // instead they'll silently compile 1_x as 2_x when using this flag flags |= D3DXSHADER_ENABLE_BACKWARDS_COMPATIBILITY; #endif #if defined(_IRR_D3D_USE_LEGACY_HLSL_COMPILER) && defined(D3DXSHADER_USE_LEGACY_D3DX9_31_DLL) @@ -341,4 +341,3 @@ void CD3D9HLSLMaterialRenderer::printHLSLVariables(LPD3DXCONSTANTTABLE table) } // end namespace irr #endif // _IRR_COMPILE_WITH_DIRECT3D_9_ - diff --git a/source/Irrlicht/CD3D9Texture.cpp b/source/Irrlicht/CD3D9Texture.cpp index d6debc36..d05ee62d 100644 --- a/source/Irrlicht/CD3D9Texture.cpp +++ b/source/Irrlicht/CD3D9Texture.cpp @@ -50,7 +50,7 @@ CD3D9Texture::CD3D9Texture(CD3D9Driver* driver, const core::dimension2d& si //! constructor CD3D9Texture::CD3D9Texture(IImage* image, CD3D9Driver* driver, - u32 flags, const io::path& name) + u32 flags, const io::path& name, void* mipmapData) : ITexture(name), Texture(0), RTTSurface(0), Driver(driver), DepthSurface(0), TextureSize(0,0), ImageSize(0,0), Pitch(0), ColorFormat(ECF_UNKNOWN), HasMipMaps(false), HardwareMipMaps(false), IsRenderTarget(false) @@ -59,7 +59,7 @@ CD3D9Texture::CD3D9Texture(IImage* image, CD3D9Driver* driver, setDebugName("CD3D9Texture"); #endif - const bool generateMipLevels = Driver->getTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS); + HasMipMaps = Driver->getTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS); Device=driver->getExposedVideoData().D3D9.D3DDev9; if (Device) @@ -69,22 +69,9 @@ CD3D9Texture::CD3D9Texture(IImage* image, CD3D9Driver* driver, { if (createTexture(flags, image)) { - if (copyTexture(image) && generateMipLevels) + if (copyTexture(image)) { - // create mip maps. - #ifdef _IRR_USE_D3DXFilterTexture_ - // The D3DXFilterTexture function seems to get linked wrong when - // compiling with both D3D8 and 9, causing it not to work in the D3D9 device. - // So mipmapgeneration is replaced with my own bad generation - HRESULT hr = D3DXFilterTexture(Texture, NULL, D3DX_DEFAULT, D3DX_DEFAULT); - if (FAILED(hr)) - os::Printer::log("Could not create direct3d mip map levels.", ELL_WARNING); - else - HasMipMaps = true; - #else - createMipMaps(); - HasMipMaps = true; - #endif + regenerateMipMapLevels(mipmapData); } } else @@ -188,8 +175,8 @@ bool CD3D9Texture::createMipMaps(u32 level) Texture->GenerateMipSubLevels(); return true; } - // os::Printer::log("manual mipmap"); + // manual mipmap generation IDirect3DSurface9* upperSurface = 0; IDirect3DSurface9* lowerSurface = 0; @@ -396,30 +383,30 @@ bool CD3D9Texture::copyTexture(IImage * image) //! lock function -void* CD3D9Texture::lock(bool readOnly) +void* CD3D9Texture::lock(bool readOnly, u32 mipmapLevel) { if (!Texture) return 0; + MipLevelLocked=mipmapLevel; HRESULT hr; D3DLOCKED_RECT rect; if(!IsRenderTarget) { - hr = Texture->LockRect(0, &rect, 0, readOnly?D3DLOCK_READONLY:0); + hr = Texture->LockRect(mipmapLevel, &rect, 0, readOnly?D3DLOCK_READONLY:0); if (FAILED(hr)) { os::Printer::log("Could not lock DIRECT3D9 Texture.", ELL_ERROR); return 0; } - - return rect.pBits; } else { - D3DSURFACE_DESC desc; - Texture->GetLevelDesc(0, &desc); if (!RTTSurface) { + // Make RTT surface large enough for all miplevels (including 0) + D3DSURFACE_DESC desc; + Texture->GetLevelDesc(0, &desc); hr = Device->CreateOffscreenPlainSurface(desc.Width, desc.Height, desc.Format, D3DPOOL_SYSTEMMEM, &RTTSurface, 0); if (FAILED(hr)) { @@ -429,7 +416,7 @@ void* CD3D9Texture::lock(bool readOnly) } IDirect3DSurface9 *surface = 0; - hr = Texture->GetSurfaceLevel(0, &surface); + hr = Texture->GetSurfaceLevel(mipmapLevel, &surface); if (FAILED(hr)) { os::Printer::log("Could not lock DIRECT3D9 Texture", "Could not get surface.", ELL_ERROR); @@ -448,8 +435,8 @@ void* CD3D9Texture::lock(bool readOnly) os::Printer::log("Could not lock DIRECT3D9 Texture", "LockRect failed.", ELL_ERROR); return 0; } - return rect.pBits; } + return rect.pBits; } @@ -460,7 +447,7 @@ void CD3D9Texture::unlock() return; if (!IsRenderTarget) - Texture->UnlockRect(0); + Texture->UnlockRect(MipLevelLocked); else if (RTTSurface) RTTSurface->UnlockRect(); } @@ -602,10 +589,58 @@ void CD3D9Texture::copy32BitMipMap(char* src, char* tgt, //! Regenerates the mip map levels of the texture. Useful after locking and //! modifying the texture -void CD3D9Texture::regenerateMipMapLevels() +void CD3D9Texture::regenerateMipMapLevels(void* mipmapData) { - if (HasMipMaps) + if (mipmapData) + { + core::dimension2du size = TextureSize; + u32 level=0; + do + { + if (size.Width>1) + size.Width /=2; + if (size.Height>1) + size.Height /=2; + ++level; + IDirect3DSurface9* mipSurface = 0; + HRESULT hr = Texture->GetSurfaceLevel(level, &mipSurface); + if (FAILED(hr) || !mipSurface) + { + os::Printer::log("Could not get mipmap level", ELL_WARNING); + return; + } + D3DSURFACE_DESC mipDesc; + mipSurface->GetDesc(&mipDesc); + D3DLOCKED_RECT miplr; + + // lock mipmap surface + if (FAILED(mipSurface->LockRect(&miplr, NULL, 0))) + { + mipSurface->Release(); + os::Printer::log("Could not lock texture", ELL_WARNING); + return; + } + + memcpy(miplr.pBits, mipmapData, size.getArea()*getPitch()/TextureSize.Width); + mipmapData = (u8*)mipmapData+size.getArea()*getPitch()/TextureSize.Width; + // unlock + mipSurface->UnlockRect(); + // release + mipSurface->Release(); + } while (size.Width != 1 || size.Height != 1); + } + else if (HasMipMaps) + { + // create mip maps. +#ifdef _IRR_USE_D3DXFilterTexture_ + // The D3DXFilterTexture function seems to get linked wrong when + // compiling with both D3D8 and 9, causing it not to work in the D3D9 device. + // So mipmapgeneration is replaced with my own bad generation + HRESULT hr = D3DXFilterTexture(Texture, NULL, D3DX_DEFAULT, D3DX_DEFAULT); + if (FAILED(hr)) +#endif createMipMaps(); + } } @@ -662,5 +697,3 @@ void CD3D9Texture::setPitch(D3DFORMAT d3dformat) } // end namespace irr #endif // _IRR_COMPILE_WITH_DIRECT3D_9_ - - diff --git a/source/Irrlicht/CD3D9Texture.h b/source/Irrlicht/CD3D9Texture.h index a9588907..efc2a856 100644 --- a/source/Irrlicht/CD3D9Texture.h +++ b/source/Irrlicht/CD3D9Texture.h @@ -29,7 +29,7 @@ public: //! constructor CD3D9Texture(IImage* image, CD3D9Driver* driver, - u32 flags, const io::path& name); + u32 flags, const io::path& name, void* mipmapData=0); //! rendertarget constructor CD3D9Texture(CD3D9Driver* driver, const core::dimension2d& size, const io::path& name, @@ -39,7 +39,7 @@ public: virtual ~CD3D9Texture(); //! lock function - virtual void* lock(bool readOnly = false); + virtual void* lock(bool readOnly = false, u32 mipmapLevel=0); //! unlock function virtual void unlock(); @@ -67,7 +67,7 @@ public: //! Regenerates the mip map levels of the texture. Useful after locking and //! modifying the texture - virtual void regenerateMipMapLevels(); + virtual void regenerateMipMapLevels(void* mipmapData=0); //! returns if it is a render target virtual bool isRenderTarget() const; @@ -108,6 +108,7 @@ private: core::dimension2d TextureSize; core::dimension2d ImageSize; s32 Pitch; + u32 MipLevelLocked; ECOLOR_FORMAT ColorFormat; bool HasMipMaps; diff --git a/source/Irrlicht/CDMFLoader.cpp b/source/Irrlicht/CDMFLoader.cpp index b7979dd7..260befc9 100644 --- a/source/Irrlicht/CDMFLoader.cpp +++ b/source/Irrlicht/CDMFLoader.cpp @@ -216,8 +216,8 @@ IAnimatedMesh* CDMFLoader::createMesh(io::IReadFile* file) } } - delete verts; - delete faces; + delete [] verts; + delete [] faces; } // delete all buffers without geometry in it. diff --git a/source/Irrlicht/CDefaultSceneNodeFactory.cpp b/source/Irrlicht/CDefaultSceneNodeFactory.cpp index c4b943ec..48256f21 100644 --- a/source/Irrlicht/CDefaultSceneNodeFactory.cpp +++ b/source/Irrlicht/CDefaultSceneNodeFactory.cpp @@ -38,7 +38,9 @@ CDefaultSceneNodeFactory::CDefaultSceneNodeFactory(ISceneManager* mgr) SupportedSceneNodeTypes.push_back(SSceneNodeTypePair(ESNT_SKY_BOX, "skyBox")); SupportedSceneNodeTypes.push_back(SSceneNodeTypePair(ESNT_SKY_DOME, "skyDome")); SupportedSceneNodeTypes.push_back(SSceneNodeTypePair(ESNT_SHADOW_VOLUME, "shadowVolume")); - SupportedSceneNodeTypes.push_back(SSceneNodeTypePair(ESNT_OCT_TREE, "octTree")); + SupportedSceneNodeTypes.push_back(SSceneNodeTypePair(ESNT_OCTREE, "octree")); + // Legacy support + SupportedSceneNodeTypes.push_back(SSceneNodeTypePair(ESNT_OCTREE, "octTree")); SupportedSceneNodeTypes.push_back(SSceneNodeTypePair(ESNT_MESH, "mesh")); SupportedSceneNodeTypes.push_back(SSceneNodeTypePair(ESNT_LIGHT, "light")); SupportedSceneNodeTypes.push_back(SSceneNodeTypePair(ESNT_EMPTY, "empty")); @@ -82,8 +84,8 @@ ISceneNode* CDefaultSceneNodeFactory::addSceneNode(ESCENE_NODE_TYPE type, IScene return Manager->addSkyDomeSceneNode(0, 16, 8, 0.9f, 2.0f, 1000.0f, parent); case ESNT_SHADOW_VOLUME: return 0; - case ESNT_OCT_TREE: - return Manager->addOctTreeSceneNode((IMesh*)0, parent, -1, 128, true); + case ESNT_OCTREE: + return Manager->addOctreeSceneNode((IMesh*)0, parent, -1, 128, true); case ESNT_MESH: return Manager->addMeshSceneNode(0, parent, -1, core::vector3df(), core::vector3df(), core::vector3df(1,1,1), true); diff --git a/source/Irrlicht/CFileSystem.cpp b/source/Irrlicht/CFileSystem.cpp index a5ff83db..709ffd49 100644 --- a/source/Irrlicht/CFileSystem.cpp +++ b/source/Irrlicht/CFileSystem.cpp @@ -190,7 +190,8 @@ bool CFileSystem::moveFileArchive(u32 sourceIndex, s32 relative) //! Adds an archive to the file system. bool CFileSystem::addFileArchive(const io::path& filename, bool ignoreCase, - bool ignorePaths, E_FILE_ARCHIVE_TYPE archiveType) + bool ignorePaths, E_FILE_ARCHIVE_TYPE archiveType, + const core::stringc& password) { IFileArchive* archive = 0; bool ret = false; @@ -200,7 +201,11 @@ bool CFileSystem::addFileArchive(const io::path& filename, bool ignoreCase, for (i = 0; i < FileArchives.size(); ++i) { if (getAbsolutePath(filename) == FileArchives[i]->getFileList()->getPath()) + { + if (password.size()) + FileArchives[i]->Password=password; return true; + } } // do we know what type it should be? @@ -281,6 +286,8 @@ bool CFileSystem::addFileArchive(const io::path& filename, bool ignoreCase, if (archive) { FileArchives.push_back(archive); + if (password.size()) + archive->Password=password; ret = true; } else @@ -346,23 +353,25 @@ const io::path& CFileSystem::getWorkingDirectory() else { #if defined(_IRR_WINDOWS_CE_PLATFORM_) - + // does not need this #elif defined(_IRR_WINDOWS_API_) + fschar_t tmp[_MAX_PATH]; #if defined(_IRR_WCHAR_FILESYSTEM ) - wchar_t tmp[_MAX_PATH]; _wgetcwd(tmp, _MAX_PATH); + WorkingDirectory[FILESYSTEM_NATIVE] = tmp; + WorkingDirectory[FILESYSTEM_NATIVE].replace(L'\\', L'/'); #else - c8 tmp[_MAX_PATH]; _getcwd(tmp, _MAX_PATH); + WorkingDirectory[FILESYSTEM_NATIVE] = tmp; + WorkingDirectory[FILESYSTEM_NATIVE].replace('\\', '/'); #endif - WorkingDirectory[FILESYSTEM_NATIVE] = tmp; #endif #if (defined(_IRR_POSIX_API_) || defined(_IRR_OSX_PLATFORM_)) - //! getting the CWD is rather complex as we do not know the size - //! so try it until the call was successful - //! Note that neither the first nor the second parameter may be 0 according to POSIX + // getting the CWD is rather complex as we do not know the size + // so try it until the call was successful + // Note that neither the first nor the second parameter may be 0 according to POSIX #if defined(_IRR_WCHAR_FILESYSTEM ) u32 pathSize=256; @@ -436,42 +445,44 @@ bool CFileSystem::changeWorkingDirectoryTo(const io::path& newDirectory) io::path CFileSystem::getAbsolutePath(const io::path& filename) const { - fschar_t *p=0; - #if defined(_IRR_WINDOWS_CE_PLATFORM_) return filename; #elif defined(_IRR_WINDOWS_API_) - + fschar_t *p=0; + fschar_t fpath[_MAX_PATH]; #if defined(_IRR_WCHAR_FILESYSTEM ) - wchar_t fpath[_MAX_PATH]; p = _wfullpath(fpath, filename.c_str(), _MAX_PATH); + core::stringw tmp(p); + tmp.replace(L'\\', L'/'); #else - c8 fpath[_MAX_PATH]; p = _fullpath(fpath, filename.c_str(), _MAX_PATH); + core::stringc tmp(p); + tmp.replace('\\', '/'); #endif - + return tmp; #elif (defined(_IRR_POSIX_API_) || defined(_IRR_OSX_PLATFORM_)) + c8* p=0; c8 fpath[4096]; fpath[0]=0; p = realpath(filename.c_str(), fpath); if (!p) { - // content in fpath is undefined at this point - if (!fpath[0]) // seems like fpath wasn't altered + // content in fpath is unclear at this point + if (!fpath[0]) // seems like fpath wasn't altered, use our best guess { - // at least remove a ./ prefix - if ('.'==filename[0] && '/'==filename[1]) - return filename.subString(2, filename.size()-2); - else - return filename; + io::path tmp(filename); + return flattenFilename(tmp); } else return io::path(fpath); } - + if (filename[filename.size()-1]=='/') + return io::path(p)+"/"; + else + return io::path(p); +#else + return io::path(filename); #endif - - return io::path(p); } @@ -523,7 +534,7 @@ io::path CFileSystem::getFileBasename(const io::path& filename, bool keepExtensi } -//! flaten a path and file name for example: "/you/me/../." becomes "/you" +//! flatten a path and file name for example: "/you/me/../." becomes "/you" io::path& CFileSystem::flattenFilename(io::path& directory, const io::path& root) const { directory.replace('\\', '/'); @@ -535,6 +546,7 @@ io::path& CFileSystem::flattenFilename(io::path& directory, const io::path& root s32 lastpos = 0; s32 pos = 0; + bool lastWasRealDir=false; while ((pos = directory.findNext('/', lastpos)) >= 0) { @@ -542,7 +554,16 @@ io::path& CFileSystem::flattenFilename(io::path& directory, const io::path& root if (subdir == "../") { - deletePathFromPath(dir, 2); + if (lastWasRealDir) + { + deletePathFromPath(dir, 2); + lastWasRealDir=(dir.size()!=0); + } + else + { + dir.append(subdir); + lastWasRealDir=false; + } } else if (subdir == "/") { @@ -551,6 +572,7 @@ io::path& CFileSystem::flattenFilename(io::path& directory, const io::path& root else if (subdir != "./" ) { dir.append(subdir); + lastWasRealDir=true; } lastpos = pos + 1; diff --git a/source/Irrlicht/CFileSystem.h b/source/Irrlicht/CFileSystem.h index 79e25809..1c5fe480 100644 --- a/source/Irrlicht/CFileSystem.h +++ b/source/Irrlicht/CFileSystem.h @@ -46,8 +46,10 @@ public: virtual IWriteFile* createAndWriteFile(const io::path& filename, bool append=false); //! Adds an archive to the file system. - virtual bool addFileArchive(const io::path& filename, bool ignoreCase = true, - bool ignorePaths = true, E_FILE_ARCHIVE_TYPE archiveType = EFAT_UNKNOWN); + virtual bool addFileArchive(const io::path& filename, + bool ignoreCase = true, bool ignorePaths = true, + E_FILE_ARCHIVE_TYPE archiveType = EFAT_UNKNOWN, + const core::stringc& password=""); //! move the hirarchy of the filesystem. moves sourceIndex relative up or down virtual bool moveFileArchive( u32 sourceIndex, s32 relative ); diff --git a/source/Irrlicht/CGUIColorSelectDialog.cpp b/source/Irrlicht/CGUIColorSelectDialog.cpp index e8cb0f46..bfd2ce91 100644 --- a/source/Irrlicht/CGUIColorSelectDialog.cpp +++ b/source/Irrlicht/CGUIColorSelectDialog.cpp @@ -15,7 +15,6 @@ #include "IGUISpriteBank.h" #include "IFileList.h" #include "os.h" -#include "SoftwareDriver2_helper.h" #include "CImage.h" namespace irr diff --git a/source/Irrlicht/CGUIComboBox.cpp b/source/Irrlicht/CGUIComboBox.cpp index c57228f5..c8dd1fdb 100644 --- a/source/Irrlicht/CGUIComboBox.cpp +++ b/source/Irrlicht/CGUIComboBox.cpp @@ -198,7 +198,9 @@ bool CGUIComboBox::OnEvent(const SEvent& event) if (event.KeyInput.Key == KEY_RETURN || event.KeyInput.Key == KEY_SPACE) { if (!event.KeyInput.PressedDown) + { openCloseMenu(); + } ListButton->setPressed(ListBox == 0); @@ -251,8 +253,7 @@ bool CGUIComboBox::OnEvent(const SEvent& event) if (ListBox && (Environment->hasFocus(ListBox) || ListBox->isMyChild(event.GUIEvent.Caller) ) && event.GUIEvent.Element != this && - event.GUIEvent.Element != ListButton && - event.GUIEvent.Element != ListBox && + !isMyChild(event.GUIEvent.Element) && !ListBox->isMyChild(event.GUIEvent.Element)) { openCloseMenu(); @@ -303,7 +304,9 @@ bool CGUIComboBox::OnEvent(const SEvent& event) if (!(ListBox && ListBox->getAbsolutePosition().isPointInside(p) && ListBox->OnEvent(event))) + { openCloseMenu(); + } return true; } case EMIE_MOUSE_WHEEL: diff --git a/source/Irrlicht/CGUIEditBox.cpp b/source/Irrlicht/CGUIEditBox.cpp index 4976df26..c96700bf 100644 --- a/source/Irrlicht/CGUIEditBox.cpp +++ b/source/Irrlicht/CGUIEditBox.cpp @@ -807,9 +807,9 @@ void CGUIEditBox::draw() mbegin = font->getDimension(s.c_str()).Width; // deal with kerning - mbegin += font->getKerningWidth( - &((*txtLine)[realmbgn - startPos]), - realmbgn - startPos > 0 ? &((*txtLine)[realmbgn - startPos - 1]) : 0); + mbegin += font->getKerningWidth( + &((*txtLine)[realmbgn - startPos]), + realmbgn - startPos > 0 ? &((*txtLine)[realmbgn - startPos - 1]) : 0); lineStartPos = realmbgn - startPos; } @@ -854,7 +854,7 @@ void CGUIEditBox::draw() startPos = BrokenTextPositions[cursorLine]; } s = txtLine->subString(0,CursorPos-startPos); - charcursorpos = font->getDimension(s.c_str()).Width + + charcursorpos = font->getDimension(s.c_str()).Width + font->getKerningWidth(L"_", CursorPos-startPos > 0 ? &((*txtLine)[CursorPos-startPos-1]) : 0); if (focus && (os::Timer::getTime() - BlinkStartTime) % 700 < 350) @@ -877,7 +877,8 @@ void CGUIEditBox::draw() void CGUIEditBox::setText(const wchar_t* text) { Text = text; - CursorPos = 0; + if (u32(CursorPos) > Text.size()) + CursorPos = Text.size(); HScrollPos = 0; breakText(); } diff --git a/source/Irrlicht/CGUIEnvironment.cpp b/source/Irrlicht/CGUIEnvironment.cpp index 97e43b92..7a743bb9 100644 --- a/source/Irrlicht/CGUIEnvironment.cpp +++ b/source/Irrlicht/CGUIEnvironment.cpp @@ -172,7 +172,7 @@ void CGUIEnvironment::loadBuiltInFont() } SFont f; - f.Filename = filename; + f.NamedPath.setPath(filename); f.Font = font; Fonts.push_back(f); @@ -389,13 +389,18 @@ bool CGUIEnvironment::OnEvent(const SEvent& event) void CGUIEnvironment::OnPostRender( u32 time ) { // check tooltip + IGUIElement * hoveredNonSub = Hovered; + while ( hoveredNonSub && hoveredNonSub->isSubElement() ) + { + hoveredNonSub = hoveredNonSub->getParent(); + } // launch tooltip if ( time - ToolTip.LastTime >= ToolTip.LaunchTime && - Hovered && Hovered != this && + hoveredNonSub && hoveredNonSub != this && ToolTip.Element == 0 && - Hovered != ToolTip.Element && - Hovered->getToolTipText().size() && + hoveredNonSub != ToolTip.Element && + hoveredNonSub->getToolTipText().size() && getSkin() && getSkin()->getFont(EGDF_TOOLTIP) ) @@ -403,7 +408,7 @@ void CGUIEnvironment::OnPostRender( u32 time ) core::rect pos; pos.UpperLeftCorner = LastHoveredMousePos; - core::dimension2du dim = getSkin()->getFont(EGDF_TOOLTIP)->getDimension(Hovered->getToolTipText().c_str()); + core::dimension2du dim = getSkin()->getFont(EGDF_TOOLTIP)->getDimension(hoveredNonSub->getToolTipText().c_str()); dim.Width += getSkin()->getSize(EGDS_TEXT_DISTANCE_X)*2; dim.Height += getSkin()->getSize(EGDS_TEXT_DISTANCE_Y)*2; @@ -413,7 +418,7 @@ void CGUIEnvironment::OnPostRender( u32 time ) pos.constrainTo(getAbsolutePosition()); - ToolTip.Element = addStaticText(Hovered->getToolTipText().c_str(), pos, true, true, this, -1, true); + ToolTip.Element = addStaticText(hoveredNonSub->getToolTipText().c_str(), pos, true, true, this, -1, true); ToolTip.Element->setOverrideColor(getSkin()->getColor(EGDC_TOOLTIP)); ToolTip.Element->setBackgroundColor(getSkin()->getColor(EGDC_TOOLTIP_BACKGROUND)); ToolTip.Element->setOverrideFont(getSkin()->getFont(EGDF_TOOLTIP)); @@ -441,7 +446,7 @@ void CGUIEnvironment::updateHoveredElement(core::position2d mousePos) if (Hovered) { - u32 now = os::Timer::getTime (); + u32 now = os::Timer::getTime(); if (Hovered != this) Hovered->grab(); @@ -458,7 +463,7 @@ void CGUIEnvironment::updateHoveredElement(core::position2d mousePos) lastHovered->OnEvent(event); } - if ( ToolTip.Element ) + if (ToolTip.Element) { ToolTip.Element->remove(); ToolTip.Element->drop(); @@ -479,7 +484,8 @@ void CGUIEnvironment::updateHoveredElement(core::position2d mousePos) } - event.GUIEvent.Caller = Hovered; + event.GUIEvent.Caller = Hovered; + event.GUIEvent.Element = Hovered; event.GUIEvent.EventType = EGET_ELEMENT_HOVERED; Hovered->OnEvent(event); } @@ -949,17 +955,20 @@ IGUIWindow* CGUIEnvironment::addWindow(const core::rect& rectangle, bool mo { parent = parent ? parent : this; - if (modal) - { - parent = new CGUIModalScreen(this, parent, -1); - parent->drop(); - } - IGUIWindow* win = new CGUIWindow(this, parent, id, rectangle); if (text) win->setText(text); win->drop(); + if (modal) + { + // Careful, don't just set the modal as parent above. That will mess up the focus (and is hard to change because we have to be very + // careful not to get virtual function call, like OnEvent, in the window. + CGUIModalScreen * modalScreen = new CGUIModalScreen(this, parent, -1); + modalScreen->drop(); + modalScreen->addChild(win); + } + return win; } @@ -998,16 +1007,20 @@ IGUIWindow* CGUIEnvironment::addMessageBox(const wchar_t* caption, const wchar_t rect.LowerRightCorner.X = rect.UpperLeftCorner.X + msgBoxDim.Width; rect.LowerRightCorner.Y = rect.UpperLeftCorner.Y + msgBoxDim.Height; - if (modal) - { - parent = new CGUIModalScreen(this, parent, -1); - parent->drop(); - } - IGUIWindow* win = new CGUIMessageBox(this, caption, text, flag, parent, id, rect, image); - win->drop(); + + if (modal) + { + // Careful, don't just set the modal as parent above. That will mess up the focus (and is hard to change because we have to be very + // careful not to get virtual function call, like OnEvent, in the CGUIMessageBox. + CGUIModalScreen * modalScreen = new CGUIModalScreen(this, parent, -1); + modalScreen->drop(); + modalScreen->addChild( win ); + } + + return win; } @@ -1136,15 +1149,18 @@ IGUIFileOpenDialog* CGUIEnvironment::addFileOpenDialog(const wchar_t* title, { parent = parent ? parent : this; + IGUIFileOpenDialog* d = new CGUIFileOpenDialog(title, this, parent, id); + d->drop(); + if (modal) { - parent = new CGUIModalScreen(this, parent, -1); - parent->drop(); + // Careful, don't just set the modal as parent above. That will mess up the focus (and is hard to change because we have to be very + // careful not to get virtual function call, like OnEvent, in the window. + CGUIModalScreen * modalScreen = new CGUIModalScreen(this, parent, -1); + modalScreen->drop(); + modalScreen->addChild(d); } - IGUIFileOpenDialog* d = new CGUIFileOpenDialog(title, this, parent, id); - - d->drop(); return d; } @@ -1155,16 +1171,19 @@ IGUIColorSelectDialog* CGUIEnvironment::addColorSelectDialog(const wchar_t* titl { parent = parent ? parent : this; - if (modal) - { - parent = new CGUIModalScreen(this, parent, -1); - parent->drop(); - } - IGUIColorSelectDialog* d = new CGUIColorSelectDialog( title, this, parent, id); - d->drop(); + + if (modal) + { + // Careful, don't just set the modal as parent above. That will mess up the focus (and is hard to change because we have to be very + // careful not to get virtual function call, like OnEvent, in the window. + CGUIModalScreen * modalScreen = new CGUIModalScreen(this, parent, -1); + modalScreen->drop(); + modalScreen->addChild(d); + } + return d; } @@ -1303,17 +1322,13 @@ IGUIComboBox* CGUIEnvironment::addComboBox(const core::rect& rectangle, } - //! returns the font IGUIFont* CGUIEnvironment::getFont(const io::path& filename) { // search existing font SFont f; - IGUIFont* ifont=0; - f.Filename = filename; - - f.Filename.make_lower(); + f.NamedPath.setPath(filename); s32 index = Fonts.binary_search(f); if (index != -1) @@ -1325,10 +1340,11 @@ IGUIFont* CGUIEnvironment::getFont(const io::path& filename) if (!FileSystem->existFile(filename)) { - os::Printer::log("Could not load font because the file does not exist", f.Filename, ELL_ERROR); + os::Printer::log("Could not load font because the file does not exist", f.NamedPath.getPath(), ELL_ERROR); return 0; } + IGUIFont* ifont=0; io::IXMLReader *xml = FileSystem->createXMLReader(filename ); if (xml) { @@ -1363,7 +1379,7 @@ IGUIFont* CGUIEnvironment::getFont(const io::path& filename) ifont = (IGUIFont*)font; // change working directory, for loading textures io::path workingDir = FileSystem->getWorkingDirectory(); - FileSystem->changeWorkingDirectoryTo(FileSystem->getFileDir(f.Filename)); + FileSystem->changeWorkingDirectoryTo(FileSystem->getFileDir(f.NamedPath.getPath())); // load the font if (!font->load(xml)) @@ -1378,7 +1394,7 @@ IGUIFont* CGUIEnvironment::getFont(const io::path& filename) else if (t==EGFT_VECTOR) { // todo: vector fonts - os::Printer::log("Unable to load font, XML vector fonts are not supported yet", f.Filename.c_str(), ELL_ERROR); + os::Printer::log("Unable to load font, XML vector fonts are not supported yet", f.NamedPath, ELL_ERROR); //CGUIFontVector* font = new CGUIFontVector(Driver); //ifont = (IGUIFont*)font; @@ -1391,9 +1407,9 @@ IGUIFont* CGUIEnvironment::getFont(const io::path& filename) if (!ifont) { - CGUIFont* font = new CGUIFont(this, f.Filename ); + CGUIFont* font = new CGUIFont(this, f.NamedPath.getPath() ); ifont = (IGUIFont*)font; - if (!font->load(f.Filename)) + if (!font->load(f.NamedPath.getPath())) { font->drop(); return 0; @@ -1409,13 +1425,40 @@ IGUIFont* CGUIEnvironment::getFont(const io::path& filename) } +//! add an externally loaded font +IGUIFont* CGUIEnvironment::addFont(const io::path& name, IGUIFont* font) +{ + if (font) + { + SFont f; + f.NamedPath.setPath(name); + s32 index = Fonts.binary_search(f); + if (index != -1) + return Fonts[index].Font; + f.Font = font; + Fonts.push_back(f); + font->grab(); + } + return font; +} + + +//! returns default font +IGUIFont* CGUIEnvironment::getBuiltInFont() const +{ + if (Fonts.empty()) + return 0; + + return Fonts[0].Font; +} + + IGUISpriteBank* CGUIEnvironment::getSpriteBank(const io::path& filename) { // search for the file name SSpriteBank b; - b.Filename = filename; - b.Filename.make_lower(); + b.NamedPath.setPath(filename); s32 index = Banks.binary_search(b); if (index != -1) @@ -1423,9 +1466,9 @@ IGUISpriteBank* CGUIEnvironment::getSpriteBank(const io::path& filename) // we don't have this sprite bank, we should load it - if (!FileSystem->existFile(b.Filename)) + if (!FileSystem->existFile(b.NamedPath.getPath())) { - os::Printer::log("Could not load sprite bank because the file does not exist", filename, ELL_ERROR); + os::Printer::log("Could not load sprite bank because the file does not exist", b.NamedPath.getPath(), ELL_ERROR); return 0; } @@ -1440,8 +1483,7 @@ IGUISpriteBank* CGUIEnvironment::addEmptySpriteBank(const io::path& name) // no duplicate names allowed SSpriteBank b; - b.Filename = name; - b.Filename.make_lower(); + b.NamedPath.setPath(name); const s32 index = Banks.binary_search(b); if (index != -1) @@ -1456,15 +1498,6 @@ IGUISpriteBank* CGUIEnvironment::addEmptySpriteBank(const io::path& name) } -//! returns default font -IGUIFont* CGUIEnvironment::getBuiltInFont() const -{ - if (Fonts.empty()) - return 0; - - return Fonts[0].Font; -} - //! Creates the image list from the given texture. IGUIImageList* CGUIEnvironment::createImageList( video::ITexture* texture, core::dimension2d imageSize, bool useAlphaChannel ) diff --git a/source/Irrlicht/CGUIEnvironment.h b/source/Irrlicht/CGUIEnvironment.h index c307ac98..10919a8e 100644 --- a/source/Irrlicht/CGUIEnvironment.h +++ b/source/Irrlicht/CGUIEnvironment.h @@ -77,6 +77,11 @@ public: //! returns the font virtual IGUIFont* getFont(const io::path& filename); + //! add an externally loaded font + virtual IGUIFont* addFont(const io::path& name, IGUIFont* font); + + //! returns default font + virtual IGUIFont* getBuiltInFont() const; //! returns the sprite bank virtual IGUISpriteBank* getSpriteBank(const io::path& filename); @@ -182,9 +187,6 @@ public: //! Returns the element with the focus virtual IGUIElement* getFocus() const; - //! returns default font - virtual IGUIFont* getBuiltInFont() const; - //! Adds an element for fading in or out. virtual IGUIInOutFader* addInOutFader(const core::rect* rectangle=0, IGUIElement* parent=0, s32 id=-1); @@ -256,23 +258,23 @@ private: struct SFont { - io::path Filename; + io::SNamedPath NamedPath; IGUIFont* Font; bool operator < (const SFont& other) const { - return (Filename < other.Filename); + return (NamedPath < other.NamedPath); } }; struct SSpriteBank { - core::stringc Filename; + io::SNamedPath NamedPath; IGUISpriteBank* Bank; bool operator < (const SSpriteBank& other) const { - return (Filename < other.Filename); + return (NamedPath < other.NamedPath); } }; diff --git a/source/Irrlicht/CGUIFileOpenDialog.cpp b/source/Irrlicht/CGUIFileOpenDialog.cpp index 38f33ff3..8f6894ec 100644 --- a/source/Irrlicht/CGUIFileOpenDialog.cpp +++ b/source/Irrlicht/CGUIFileOpenDialog.cpp @@ -357,7 +357,7 @@ void CGUIFileOpenDialog::fillListBox() int len = mbstowcs(ws,cs,strlen(cs)); ws[len] = 0; s = ws; - delete ws; + delete [] ws; #else s = FileSystem->getWorkingDirectory(); #endif diff --git a/source/Irrlicht/CGUIFont.cpp b/source/Irrlicht/CGUIFont.cpp index 6a279f15..4919bddb 100644 --- a/source/Irrlicht/CGUIFont.cpp +++ b/source/Irrlicht/CGUIFont.cpp @@ -241,14 +241,16 @@ bool CGUIFont::loadTexture(video::IImage* image, const io::path& name) switch(image->getColorFormat()) { case video::ECF_R5G6B5: - tmpImage = new video::CImage(video::ECF_A1R5G5B5,image); + tmpImage = new video::CImage(video::ECF_A1R5G5B5,image->getDimension()); + image->copyTo(tmpImage); deleteTmpImage=true; break; case video::ECF_A1R5G5B5: case video::ECF_A8R8G8B8: break; case video::ECF_R8G8B8: - tmpImage = new video::CImage(video::ECF_A8R8G8B8,image); + tmpImage = new video::CImage(video::ECF_A8R8G8B8,image->getDimension()); + image->copyTo(tmpImage); deleteTmpImage=true; break; } @@ -468,7 +470,7 @@ void CGUIFont::draw(const core::stringw& text, const core::rect& position, if (!Driver) return; - core::dimension2d textDimension; + core::dimension2d textDimension; // NOTE: don't make this u32 or the >> later on can fail when the dimension widht is < position width core::position2d offset = position.UpperLeftCorner; if (hcenter || vcenter || clip) @@ -514,8 +516,7 @@ void CGUIFont::draw(const core::stringw& text, const core::rect& position, if ( hcenter ) { - core::dimension2d lineDim = getDimension(text.c_str()); - offset.X += (position.getWidth() - lineDim.Width) >> 1; + offset.X += (position.getWidth() - textDimension.Width) >> 1; } continue; } diff --git a/source/Irrlicht/CGUIMenu.cpp b/source/Irrlicht/CGUIMenu.cpp index 8533b6d2..76c37268 100644 --- a/source/Irrlicht/CGUIMenu.cpp +++ b/source/Irrlicht/CGUIMenu.cpp @@ -9,6 +9,7 @@ #include "IGUIEnvironment.h" #include "IVideoDriver.h" #include "IGUIFont.h" +#include "IGUIWindow.h" #include "os.h" @@ -184,28 +185,41 @@ bool CGUIMenu::OnEvent(const SEvent& event) return IGUIElement::OnEvent(event); } - void CGUIMenu::recalculateSize() { + core::rect clientRect; // client rect of parent + if ( Parent && Parent->hasType(EGUIET_WINDOW) ) + { + clientRect = static_cast(Parent)->getClientRect(); + } + else if ( Parent ) + { + clientRect = core::rect(0,0, Parent->getAbsolutePosition().getWidth(), + Parent->getAbsolutePosition().getHeight()); + } + else + { + clientRect = RelativeRect; + } + + IGUISkin* skin = Environment->getSkin(); IGUIFont* font = skin->getFont(EGDF_MENU); if (!font) { if (Parent && skin) - RelativeRect = core::rect(0,0, - Parent->getAbsolutePosition().LowerRightCorner.X, - skin->getSize(EGDS_MENU_HEIGHT)); + RelativeRect = core::rect(clientRect.UpperLeftCorner.X, clientRect.UpperLeftCorner.Y, + clientRect.LowerRightCorner.X, clientRect.UpperLeftCorner.Y+skin->getSize(EGDS_MENU_HEIGHT)); return; } core::rect rect; - rect.UpperLeftCorner.X = 0; - rect.UpperLeftCorner.Y = 0; + rect.UpperLeftCorner = clientRect.UpperLeftCorner; s32 height = font->getDimension(L"A").Height + 5; //if (skin && height < skin->getSize ( EGDS_MENU_HEIGHT )) // height = skin->getSize(EGDS_MENU_HEIGHT); - s32 width = 0; + s32 width = rect.UpperLeftCorner.X; s32 i; for (i=0; i<(s32)Items.size(); ++i) @@ -225,11 +239,10 @@ void CGUIMenu::recalculateSize() width += Items[i].Dim.Width; } - if (Parent) - width = Parent->getAbsolutePosition().getWidth(); + width = clientRect.getWidth(); - rect.LowerRightCorner.X = width; - rect.LowerRightCorner.Y = height; + rect.LowerRightCorner.X = rect.UpperLeftCorner.X + width; + rect.LowerRightCorner.Y = rect.UpperLeftCorner.Y + height; setRelativePosition(rect); diff --git a/source/Irrlicht/CGUIModalScreen.cpp b/source/Irrlicht/CGUIModalScreen.cpp index cc1cece2..0b204cf3 100644 --- a/source/Irrlicht/CGUIModalScreen.cpp +++ b/source/Irrlicht/CGUIModalScreen.cpp @@ -17,7 +17,7 @@ namespace gui //! constructor CGUIModalScreen::CGUIModalScreen(IGUIEnvironment* environment, IGUIElement* parent, s32 id) -: IGUIElement(EGUIET_MODAL_SCREEN, environment, parent, id, parent->getAbsolutePosition()), +: IGUIElement(EGUIET_MODAL_SCREEN, environment, parent, id, core::recti(0, 0, parent->getAbsolutePosition().getWidth(), parent->getAbsolutePosition().getHeight()) ), MouseDownTime(0) { #ifdef _DEBUG @@ -90,6 +90,7 @@ bool CGUIModalScreen::OnEvent(const SEvent& event) { Environment->setFocus(this); } + IGUIElement::OnEvent(event); return false; case EGET_ELEMENT_FOCUS_LOST: if ( !canTakeFocus(event.GUIEvent.Element)) diff --git a/source/Irrlicht/CGUISkin.cpp b/source/Irrlicht/CGUISkin.cpp index 38ae97de..3fd8e73f 100644 --- a/source/Irrlicht/CGUISkin.cpp +++ b/source/Irrlicht/CGUISkin.cpp @@ -9,7 +9,6 @@ #include "IGUISpriteBank.h" #include "IVideoDriver.h" #include "IAttributes.h" -#include "SoftwareDriver2_helper.h" namespace irr { @@ -465,90 +464,136 @@ implementations to find out how to draw the part exactly. core::rect CGUISkin::draw3DWindowBackground(IGUIElement* element, bool drawTitleBar, video::SColor titleBarColor, const core::rect& r, - const core::rect* cl) + const core::rect* cl, + core::rect* checkClientArea) { if (!Driver) + { + if ( checkClientArea ) + { + *checkClientArea = r; + } return r; + } core::rect rect = r; + // top border rect.LowerRightCorner.Y = rect.UpperLeftCorner.Y + 1; - Driver->draw2DRectangle(getColor(EGDC_3D_HIGH_LIGHT), rect, cl); + if ( !checkClientArea ) + { + Driver->draw2DRectangle(getColor(EGDC_3D_HIGH_LIGHT), rect, cl); + } + // left border rect.LowerRightCorner.Y = r.LowerRightCorner.Y; rect.LowerRightCorner.X = rect.UpperLeftCorner.X + 1; - Driver->draw2DRectangle(getColor(EGDC_3D_HIGH_LIGHT), rect, cl); + if ( !checkClientArea ) + { + Driver->draw2DRectangle(getColor(EGDC_3D_HIGH_LIGHT), rect, cl); + } + // right border dark outer line rect.UpperLeftCorner.X = r.LowerRightCorner.X - 1; rect.LowerRightCorner.X = r.LowerRightCorner.X; rect.UpperLeftCorner.Y = r.UpperLeftCorner.Y; rect.LowerRightCorner.Y = r.LowerRightCorner.Y; - Driver->draw2DRectangle(getColor(EGDC_3D_DARK_SHADOW), rect, cl); + if ( !checkClientArea ) + { + Driver->draw2DRectangle(getColor(EGDC_3D_DARK_SHADOW), rect, cl); + } + // right border bright innner line rect.UpperLeftCorner.X -= 1; rect.LowerRightCorner.X -= 1; rect.UpperLeftCorner.Y += 1; rect.LowerRightCorner.Y -= 1; - Driver->draw2DRectangle(getColor(EGDC_3D_SHADOW), rect, cl); + if ( !checkClientArea ) + { + Driver->draw2DRectangle(getColor(EGDC_3D_SHADOW), rect, cl); + } + // bottom border dark outer line rect.UpperLeftCorner.X = r.UpperLeftCorner.X; rect.UpperLeftCorner.Y = r.LowerRightCorner.Y - 1; rect.LowerRightCorner.Y = r.LowerRightCorner.Y; rect.LowerRightCorner.X = r.LowerRightCorner.X; - Driver->draw2DRectangle(getColor(EGDC_3D_DARK_SHADOW), rect, cl); + if ( !checkClientArea ) + { + Driver->draw2DRectangle(getColor(EGDC_3D_DARK_SHADOW), rect, cl); + } + // bottom border bright inner line rect.UpperLeftCorner.X += 1; rect.LowerRightCorner.X -= 1; rect.UpperLeftCorner.Y -= 1; rect.LowerRightCorner.Y -= 1; - Driver->draw2DRectangle(getColor(EGDC_3D_SHADOW), rect, cl); + if ( !checkClientArea ) + { + Driver->draw2DRectangle(getColor(EGDC_3D_SHADOW), rect, cl); + } + // client area for background rect = r; rect.UpperLeftCorner.X +=1; rect.UpperLeftCorner.Y +=1; rect.LowerRightCorner.X -= 2; rect.LowerRightCorner.Y -= 2; - - if (!UseGradient) + if (checkClientArea) { - Driver->draw2DRectangle(getColor(EGDC_3D_FACE), rect, cl); - } - else - if ( Type == EGST_BURNING_SKIN ) - { - const video::SColor c1 = getColor(EGDC_WINDOW).getInterpolated ( 0xFFFFFFFF, 0.9f ); - const video::SColor c2 = getColor(EGDC_WINDOW).getInterpolated ( 0xFFFFFFFF, 0.8f ); - - Driver->draw2DRectangle(rect, c1, c1, c2, c2, cl); - } - else - { - const video::SColor c2 = getColor(EGDC_3D_SHADOW); - const video::SColor c1 = getColor(EGDC_3D_FACE); - Driver->draw2DRectangle(rect, c1, c1, c1, c2, cl); + *checkClientArea = rect; } + if ( !checkClientArea ) + { + if (!UseGradient) + { + Driver->draw2DRectangle(getColor(EGDC_3D_FACE), rect, cl); + } + else if ( Type == EGST_BURNING_SKIN ) + { + const video::SColor c1 = getColor(EGDC_WINDOW).getInterpolated ( 0xFFFFFFFF, 0.9f ); + const video::SColor c2 = getColor(EGDC_WINDOW).getInterpolated ( 0xFFFFFFFF, 0.8f ); + + Driver->draw2DRectangle(rect, c1, c1, c2, c2, cl); + } + else + { + const video::SColor c2 = getColor(EGDC_3D_SHADOW); + const video::SColor c1 = getColor(EGDC_3D_FACE); + Driver->draw2DRectangle(rect, c1, c1, c1, c2, cl); + } + } + + // title bar rect = r; rect.UpperLeftCorner.X += 2; rect.UpperLeftCorner.Y += 2; rect.LowerRightCorner.X -= 2; rect.LowerRightCorner.Y = rect.UpperLeftCorner.Y + getSize(EGDS_WINDOW_BUTTON_WIDTH) + 2; - if (drawTitleBar) + if (drawTitleBar ) { - // draw title bar - //if (!UseGradient) - // Driver->draw2DRectangle(titleBarColor, rect, cl); - //else - if ( Type == EGST_BURNING_SKIN ) + if (checkClientArea) { - const video::SColor c = titleBarColor.getInterpolated( 0xffffffff, 0.8f); - Driver->draw2DRectangle(rect, titleBarColor, titleBarColor, c, c, cl); + (*checkClientArea).UpperLeftCorner.Y = rect.LowerRightCorner.Y; } else { - const video::SColor c = titleBarColor.getInterpolated(video::SColor(255,0,0,0), 0.2f); - Driver->draw2DRectangle(rect, titleBarColor, c, titleBarColor, c, cl); + // draw title bar + //if (!UseGradient) + // Driver->draw2DRectangle(titleBarColor, rect, cl); + //else + if ( Type == EGST_BURNING_SKIN ) + { + const video::SColor c = titleBarColor.getInterpolated( 0xffffffff, 0.8f); + Driver->draw2DRectangle(rect, titleBarColor, titleBarColor, c, c, cl); + } + else + { + const video::SColor c = titleBarColor.getInterpolated(video::SColor(255,0,0,0), 0.2f); + Driver->draw2DRectangle(rect, titleBarColor, c, titleBarColor, c, cl); + } } } diff --git a/source/Irrlicht/CGUISkin.h b/source/Irrlicht/CGUISkin.h index 8ac2c208..7921fa8e 100644 --- a/source/Irrlicht/CGUISkin.h +++ b/source/Irrlicht/CGUISkin.h @@ -125,11 +125,16 @@ namespace gui \param drawTitleBar: True to enable title drawing. \param rect: Defining area where to draw. \param clip: Clip area. - \return Returns rect where to draw title bar text. */ + \param checkClientArea: When set to non-null the function will not draw anything, + but will instead return the clientArea which can be used for drawing by the calling window. + That is the area without borders and without titlebar. + \return Returns rect where it would be good to draw title bar text. This will + work even when checkClientArea is set to a non-null value.*/ virtual core::rect draw3DWindowBackground(IGUIElement* element, bool drawTitleBar, video::SColor titleBarColor, const core::rect& rect, - const core::rect* clip=0); + const core::rect* clip, + core::rect* checkClientArea); //! draws a standard 3d menu pane /** Used for drawing for menus and context menus. diff --git a/source/Irrlicht/CGUISpinBox.cpp b/source/Irrlicht/CGUISpinBox.cpp index 866ea1e2..560f9851 100644 --- a/source/Irrlicht/CGUISpinBox.cpp +++ b/source/Irrlicht/CGUISpinBox.cpp @@ -236,9 +236,9 @@ bool CGUISpinBox::OnEvent(const SEvent& event) void CGUISpinBox::verifyValueRange() { f32 val = getValue(); - if ( val < RangeMin ) + if ( val+core::ROUNDING_ERROR_f32 < RangeMin ) val = RangeMin; - else if ( val > RangeMax ) + else if ( val-core::ROUNDING_ERROR_f32 > RangeMax ) val = RangeMax; else return; diff --git a/source/Irrlicht/CGUISpriteBank.cpp b/source/Irrlicht/CGUISpriteBank.cpp index 713e1a88..c6f3819c 100644 --- a/source/Irrlicht/CGUISpriteBank.cpp +++ b/source/Irrlicht/CGUISpriteBank.cpp @@ -94,6 +94,43 @@ void CGUISpriteBank::setTexture(u32 index, video::ITexture* texture) } +//! clear everything +void CGUISpriteBank::clear() +{ + // drop textures + for (u32 i=0; idrop(); + Textures.clear(); + Sprites.clear(); + Rectangles.clear(); +} + +//! Add the texture and use it for a single non-animated sprite. +s32 CGUISpriteBank::addTextureAsSprite(video::ITexture* texture) +{ + if ( !texture ) + return -1; + + addTexture(texture); + u32 textureIndex = getTextureCount() - 1; + + u32 rectangleIndex = Rectangles.size(); + Rectangles.push_back( core::rect(0,0, texture->getOriginalSize().Width, texture->getOriginalSize().Height) ); + + SGUISprite sprite; + sprite.frameTime = 0; + + SGUISpriteFrame frame; + frame.textureNumber = textureIndex; + frame.rectNumber = rectangleIndex; + sprite.Frames.push_back( frame ); + + Sprites.push_back( sprite ); + + return Sprites.size() - 1; +} + //! draws a sprite in 2d with scale and color void CGUISpriteBank::draw2DSprite(u32 index, const core::position2di& pos, const core::rect* clip, const video::SColor& color, diff --git a/source/Irrlicht/CGUISpriteBank.h b/source/Irrlicht/CGUISpriteBank.h index 30253b0f..a0b4d225 100644 --- a/source/Irrlicht/CGUISpriteBank.h +++ b/source/Irrlicht/CGUISpriteBank.h @@ -40,6 +40,12 @@ public: virtual void addTexture(video::ITexture* texture); virtual void setTexture(u32 index, video::ITexture* texture); + //! Add the texture and use it for a single non-animated sprite. + virtual s32 addTextureAsSprite(video::ITexture* texture); + + //! clears sprites, rectangles and textures + virtual void clear(); + //! Draws a sprite in 2d with position and color virtual void draw2DSprite(u32 index, const core::position2di& pos, const core::rect* clip=0, const video::SColor& color= video::SColor(255,255,255,255), diff --git a/source/Irrlicht/CGUITabControl.cpp b/source/Irrlicht/CGUITabControl.cpp index ae2c1966..f29fddce 100644 --- a/source/Irrlicht/CGUITabControl.cpp +++ b/source/Irrlicht/CGUITabControl.cpp @@ -688,6 +688,7 @@ void CGUITabControl::setTabHeight( s32 height ) TabHeight = height; + recalculateScrollButtonPlacement(); recalculateScrollBar(); } @@ -758,8 +759,17 @@ void CGUITabControl::setTabVerticalAlignment( EGUI_ALIGNMENT alignment ) { VerticalAlignment = alignment; + recalculateScrollButtonPlacement(); + recalculateScrollBar(); +} + +void CGUITabControl::recalculateScrollButtonPlacement() +{ IGUISkin* skin = Environment->getSkin(); s32 ButtonSize = 16; + s32 ButtonHeight = TabHeight - 2; + if ( ButtonHeight < 0 ) + ButtonHeight = TabHeight; if (skin) { ButtonSize = skin->getSize(EGDS_WINDOW_BUTTON_WIDTH); @@ -772,25 +782,22 @@ void CGUITabControl::setTabVerticalAlignment( EGUI_ALIGNMENT alignment ) if (VerticalAlignment == EGUIA_UPPERLEFT) { - ButtonY = (TabHeight / 2) - (ButtonSize / 2); + ButtonY = 2 + (TabHeight / 2) - (ButtonHeight / 2); UpButton->setAlignment(EGUIA_LOWERRIGHT, EGUIA_LOWERRIGHT, EGUIA_UPPERLEFT, EGUIA_UPPERLEFT); DownButton->setAlignment(EGUIA_LOWERRIGHT, EGUIA_LOWERRIGHT, EGUIA_UPPERLEFT, EGUIA_UPPERLEFT); } else { - ButtonY = RelativeRect.getHeight() - (TabHeight / 2) - (ButtonSize / 2); + ButtonY = RelativeRect.getHeight() - (TabHeight / 2) - (ButtonHeight / 2) - 2; UpButton->setAlignment(EGUIA_LOWERRIGHT, EGUIA_LOWERRIGHT, EGUIA_LOWERRIGHT, EGUIA_LOWERRIGHT); DownButton->setAlignment(EGUIA_LOWERRIGHT, EGUIA_LOWERRIGHT, EGUIA_LOWERRIGHT, EGUIA_LOWERRIGHT); } - UpButton->setRelativePosition(core::rect(ButtonX, ButtonY, ButtonX+ButtonSize, ButtonY+ButtonSize)); + UpButton->setRelativePosition(core::rect(ButtonX, ButtonY, ButtonX+ButtonSize, ButtonY+ButtonHeight)); ButtonX += ButtonSize + 1; - DownButton->setRelativePosition(core::rect(ButtonX, ButtonY, ButtonX+ButtonSize, ButtonY+ButtonSize)); - - recalculateScrollBar(); + DownButton->setRelativePosition(core::rect(ButtonX, ButtonY, ButtonX+ButtonSize, ButtonY+ButtonHeight)); } - //! Get the alignment of the tabs EGUI_ALIGNMENT CGUITabControl::getTabVerticalAlignment() const { diff --git a/source/Irrlicht/CGUITabControl.h b/source/Irrlicht/CGUITabControl.h index 5e24cc9a..2fe95382 100644 --- a/source/Irrlicht/CGUITabControl.h +++ b/source/Irrlicht/CGUITabControl.h @@ -159,6 +159,7 @@ namespace gui bool needScrollControl( s32 startIndex=0, bool withScrollControl=false ); s32 calcTabWidth(s32 pos, IGUIFont* font, const wchar_t* text, bool withScrollControl ); + void recalculateScrollButtonPlacement(); void recalculateScrollBar(); core::array Tabs; diff --git a/source/Irrlicht/CGUIWindow.cpp b/source/Irrlicht/CGUIWindow.cpp index 080a8a3a..fb5880ed 100644 --- a/source/Irrlicht/CGUIWindow.cpp +++ b/source/Irrlicht/CGUIWindow.cpp @@ -89,6 +89,8 @@ CGUIWindow::CGUIWindow(IGUIEnvironment* environment, IGUIElement* parent, s32 id setTabGroup(true); setTabStop(true); setTabOrder(-1); + + updateClientRect(); } @@ -221,12 +223,15 @@ void CGUIWindow::draw() { IGUISkin* skin = Environment->getSkin(); + // update each time because the skin is allowed to change this always. + updateClientRect(); + core::rect rect = AbsoluteRect; // draw body fast if ( DrawBackground ) { - rect = skin->draw3DWindowBackground(this, DrawTitlebar, + rect = skin->draw3DWindowBackground(this, DrawTitlebar, skin->getColor(IsActive ? EGDC_ACTIVE_BORDER : EGDC_INACTIVE_BORDER), AbsoluteRect, &AbsoluteClippingRect); @@ -240,7 +245,7 @@ void CGUIWindow::draw() if (font) { font->draw(Text.c_str(), rect, - skin->getColor(IsActive ? EGDC_ACTIVE_CAPTION:EGDC_INACTIVE_CAPTION), + skin->getColor(IsActive ? EGDC_ACTIVE_CAPTION:EGDC_INACTIVE_CAPTION), false, true, &AbsoluteClippingRect); } } @@ -310,6 +315,27 @@ bool CGUIWindow::getDrawTitlebar() const return DrawTitlebar; } +void CGUIWindow::updateClientRect() +{ + if (! DrawBackground ) + { + ClientRect = core::rect(0,0, AbsoluteRect.getWidth(), AbsoluteRect.getHeight()); + return; + } + IGUISkin* skin = Environment->getSkin(); + skin->draw3DWindowBackground(this, + DrawTitlebar, + skin->getColor(IsActive ? EGDC_ACTIVE_BORDER : EGDC_INACTIVE_BORDER), + AbsoluteRect, &AbsoluteClippingRect, &ClientRect); + ClientRect -= AbsoluteRect.UpperLeftCorner; +} + +//! Returns the rectangle of the drawable area (without border, without titlebar and without scrollbars) +core::rect CGUIWindow::getClientRect() const +{ + return ClientRect; +} + //! Writes attributes of the element. void CGUIWindow::serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options=0) const { @@ -345,6 +371,8 @@ void CGUIWindow::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWr CloseButton->setVisible( in->getAttributeAsBool("IsCloseVisible") ); MinButton->setVisible( in->getAttributeAsBool("IsMinVisible") ); RestoreButton->setVisible( in->getAttributeAsBool("IsRestoreVisible") ); + + updateClientRect(); } } // end namespace gui diff --git a/source/Irrlicht/CGUIWindow.h b/source/Irrlicht/CGUIWindow.h index 95f2afec..0d6a8755 100644 --- a/source/Irrlicht/CGUIWindow.h +++ b/source/Irrlicht/CGUIWindow.h @@ -63,6 +63,9 @@ namespace gui //! Get if the window titlebar will be drawn virtual bool getDrawTitlebar() const; + //! Returns the rectangle of the drawable area (without border and without titlebar) + virtual core::rect getClientRect() const; + //! Writes attributes of the element. virtual void serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options) const; @@ -71,9 +74,12 @@ namespace gui protected: + void updateClientRect(); + IGUIButton* CloseButton; IGUIButton* MinButton; IGUIButton* RestoreButton; + core::rect ClientRect; core::position2d DragStart; bool Dragging, IsDraggable; diff --git a/source/Irrlicht/CGeometryCreator.cpp b/source/Irrlicht/CGeometryCreator.cpp index f8c40ae5..5843df5b 100644 --- a/source/Irrlicht/CGeometryCreator.cpp +++ b/source/Irrlicht/CGeometryCreator.cpp @@ -110,7 +110,7 @@ IMesh* CGeometryCreator::createHillPlaneMesh( vtx.Pos.set(sx - center.X, 0, sy - center.Y); vtx.TCoords.set(tsx, 1.0f - tsy); - if (hillHeight != 0.0f) + if (core::isnotzero(hillHeight)) vtx.Pos.Y = sinf(vtx.Pos.X * countHills.Width * core::PI / center.X) * cosf(vtx.Pos.Z * countHills.Height * core::PI / center.Y) * hillHeight; @@ -158,6 +158,7 @@ IMesh* CGeometryCreator::createHillPlaneMesh( buffer->Material = *material; buffer->recalculateBoundingBox(); + buffer->setHardwareMappingHint(EHM_STATIC); SMesh* mesh = new SMesh(); mesh->addMeshBuffer(buffer); @@ -264,9 +265,10 @@ IMesh* CGeometryCreator::createTerrainMesh(video::IImage* texture, { c8 textureName[64]; // create texture for this block - video::IImage* img = new video::CImage(texture, + video::IImage* img = new video::CImage(texture->getColorFormat(), texture->getDimension()); + texture->copyTo(img, core::position2di(0,0), core::recti( core::position2d(core::floor32(processed.X*thRel.X), core::floor32(processed.Y*thRel.Y)), - core::dimension2d(core::floor32(blockSize.Width*thRel.X), core::floor32(blockSize.Height*thRel.Y))); + core::dimension2d(core::floor32(blockSize.Width*thRel.X), core::floor32(blockSize.Height*thRel.Y))), 0); sprintf(textureName, "terrain%u_%u", tm, mesh->getMeshBufferCount()); @@ -326,9 +328,11 @@ IMesh* CGeometryCreator::createArrowMesh(const u32 tesselationCylinder, scene::IMeshBuffer* buffer = mesh2->getMeshBuffer(i); for (u32 j=0; jgetVertexCount(); ++j) buffer->getPosition(j).Y += cylinderHeight; + buffer->setDirty(EBT_VERTEX); mesh->addMeshBuffer(buffer); } mesh2->drop(); + mesh->setHardwareMappingHint(EHM_STATIC); return mesh; } @@ -493,6 +497,7 @@ IMesh* CGeometryCreator::createSphereMesh(f32 radius, u32 polyCountX, u32 polyCo mesh->addMeshBuffer(buffer); buffer->drop(); + mesh->setHardwareMappingHint(EHM_STATIC); mesh->recalculateBoundingBox(); return mesh; } @@ -500,8 +505,8 @@ IMesh* CGeometryCreator::createSphereMesh(f32 radius, u32 polyCountX, u32 polyCo /* A cylinder with proper normals and texture coords */ IMesh* CGeometryCreator::createCylinderMesh(f32 radius, f32 length, - u32 tesselation, const video::SColor& color, - bool closeTop, f32 oblique) const + u32 tesselation, const video::SColor& color, + bool closeTop, f32 oblique) const { SMeshBuffer* buffer = new SMeshBuffer(); @@ -513,10 +518,10 @@ IMesh* CGeometryCreator::createCylinderMesh(f32 radius, f32 length, u32 i; video::S3DVertex v; v.Color = color; - buffer->Vertices.reallocate(tesselation*4+(closeTop?2:1)); - buffer->Indices.reallocate((tesselation*2)*(closeTop?12:9)); + buffer->Vertices.reallocate(tesselation*4+4+(closeTop?2:1)); + buffer->Indices.reallocate((tesselation*2+1)*(closeTop?12:9)); f32 tcx = 0.f; - for ( i = 0; i != tesselation; ++i ) + for ( i = 0; i <= tesselation; ++i ) { const f32 angle = angleStep * i; v.Pos.X = radius * cosf(angle); @@ -553,8 +558,9 @@ IMesh* CGeometryCreator::createCylinderMesh(f32 radius, f32 length, tcx += recTesselation; } - const u32 nonWrappedSize = ( tesselation* 4 ) - 2; - for ( i = 0; i != nonWrappedSize; i += 2 ) + // indices for the main hull part + const u32 nonWrappedSize = tesselation* 4; + for (i=0; i != nonWrappedSize; i += 2) { buffer->Indices.push_back(i + 2); buffer->Indices.push_back(i + 0); @@ -565,6 +571,7 @@ IMesh* CGeometryCreator::createCylinderMesh(f32 radius, f32 length, buffer->Indices.push_back(i + 3); } + // two closing quads between end and start buffer->Indices.push_back(0); buffer->Indices.push_back(i + 0); buffer->Indices.push_back(i + 1); @@ -627,6 +634,7 @@ IMesh* CGeometryCreator::createCylinderMesh(f32 radius, f32 length, buffer->recalculateBoundingBox(); SMesh* mesh = new SMesh(); mesh->addMeshBuffer(buffer); + mesh->setHardwareMappingHint(EHM_STATIC); mesh->recalculateBoundingBox(); buffer->drop(); return mesh; @@ -634,9 +642,10 @@ IMesh* CGeometryCreator::createCylinderMesh(f32 radius, f32 length, /* A cone with proper normals and texture coords */ -IMesh* CGeometryCreator::createConeMesh(f32 radius, f32 length, u32 tesselation, - const video::SColor& colorTop, - const video::SColor& colorBottom, f32 oblique) const +IMesh* CGeometryCreator::createConeMesh(f32 radius, f32 length, u32 tesselation, + const video::SColor& colorTop, + const video::SColor& colorBottom, + f32 oblique) const { SMeshBuffer* buffer = new SMeshBuffer(); @@ -718,6 +727,7 @@ IMesh* CGeometryCreator::createConeMesh(f32 radius, f32 length, u32 tesselation, mesh->addMeshBuffer(buffer); buffer->drop(); + mesh->setHardwareMappingHint(EHM_STATIC); mesh->recalculateBoundingBox(); return mesh; } diff --git a/source/Irrlicht/CImage.cpp b/source/Irrlicht/CImage.cpp index 6f1103c4..ee8845da 100644 --- a/source/Irrlicht/CImage.cpp +++ b/source/Irrlicht/CImage.cpp @@ -40,39 +40,6 @@ CImage::CImage(ECOLOR_FORMAT format, const core::dimension2d& size, void* d } -//! Constructor from other image, with color conversion -CImage::CImage(ECOLOR_FORMAT format, IImage* imageToCopy) -: Data(0), Format(format), DeleteMemory(true) -{ - if (!imageToCopy) - return; - - Size = imageToCopy->getDimension(); - initData(); - - // now copy data from other image - Blit ( BLITTER_TEXTURE, this, 0, 0, imageToCopy, 0,0 ); -} - - -//! Constructor from other image, partially -CImage::CImage(IImage* imageToCopy, const core::position2d& pos, - const core::dimension2d& size) - : Data(0), Size(0,0), DeleteMemory(true) -{ - if (!imageToCopy) - return; - - Format = imageToCopy->getColorFormat(); - Size = size; - - initData(); - - core::rect sClip( pos.X, pos.Y, pos.X + size.Width,pos.Y + size.Height ); - Blit (BLITTER_TEXTURE, this, 0, 0, imageToCopy, &sClip, 0); -} - - //! assumes format and size has been set and creates the rest void CImage::initData() { diff --git a/source/Irrlicht/CImage.h b/source/Irrlicht/CImage.h index f611e1fe..7382ec1a 100644 --- a/source/Irrlicht/CImage.h +++ b/source/Irrlicht/CImage.h @@ -19,23 +19,16 @@ class CImage : public IImage { public: - //! constructor from another image with format change - CImage(ECOLOR_FORMAT format, IImage* imageToCopy); - //! constructor from raw image data - //! \param useForeignMemory: If true, the image will use the data pointer - //! directly and own it from now on, which means it will also try to delete [] the - //! data when the image will be destructed. If false, the memory will by copied. + /** \param useForeignMemory: If true, the image will use the data pointer + directly and own it from now on, which means it will also try to delete [] the + data when the image will be destructed. If false, the memory will by copied. */ CImage(ECOLOR_FORMAT format, const core::dimension2d& size, void* data, bool ownForeignMemory=true, bool deleteMemory = true); //! constructor for empty image CImage(ECOLOR_FORMAT format, const core::dimension2d& size); - //! constructor using a part from another image - CImage(IImage* imageToCopy, - const core::position2d& pos, const core::dimension2d& size); - //! destructor virtual ~CImage(); diff --git a/source/Irrlicht/CIrrDeviceFB.cpp b/source/Irrlicht/CIrrDeviceFB.cpp new file mode 100644 index 00000000..87a73d07 --- /dev/null +++ b/source/Irrlicht/CIrrDeviceFB.cpp @@ -0,0 +1,405 @@ +// Copyright (C) 2002-2007 Nikolaus Gebhardt +// Copyright (C) 2007-2009 Christian Stehno +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#include "CIrrDeviceFB.h" + +#ifdef _IRR_COMPILE_WITH_FB_DEVICE_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "IEventReceiver.h" +#include "os.h" +#include "CTimer.h" +#include "irrString.h" +#include "Keycodes.h" +#include "COSOperator.h" +#include "CColorConverter.h" +#include "SIrrCreationParameters.h" + +#include + +namespace irr +{ + +//! constructor +CIrrDeviceFB::CIrrDeviceFB(const SIrrlichtCreationParameters& params) + : CIrrDeviceStub(params), Framebuffer(-1), EventDevice(-1), SoftwareImage(0), + Pitch(0), FBColorFormat(video::ECF_A8R8G8B8), Close(false) +{ + #ifdef _DEBUG + setDebugName("CIrrDeviceFB"); + #endif + + // print version, distribution etc. + // thx to LynxLuna for pointing me to the uname function + core::stringc linuxversion; + struct utsname FBInfo; + uname(&FBInfo); + + linuxversion += FBInfo.sysname; + linuxversion += " "; + linuxversion += FBInfo.release; + linuxversion += " "; + linuxversion += FBInfo.version; + linuxversion += " "; + linuxversion += FBInfo.machine; + + Operator = new COSOperator(linuxversion.c_str()); + os::Printer::log(linuxversion.c_str(), ELL_INFORMATION); + + // create window + if (params.DriverType != video::EDT_NULL) + { + // create the window, only if we do not use the null device + if (!createWindow(params.WindowSize, params.Bits)) + return; + } + + // create cursor control + CursorControl = new CCursorControl(this, params.DriverType == video::EDT_NULL); + + // create driver + createDriver(); + + if (!VideoDriver) + return; + + createGUIAndScene(); +} + + + +//! destructor +CIrrDeviceFB::~CIrrDeviceFB() +{ + if (SoftwareImage) + munmap(SoftwareImage, CreationParams.WindowSize.Height*Pitch); + // go back to previous format + if (ioctl(Framebuffer, FBIOPUT_VSCREENINFO, &oldscreeninfo) <0) + perror("Restoring old fb mode"); + + if (KeyboardDevice != -1) + if (ioctl(KeyboardDevice, KDSETMODE, &KeyboardMode) <0) + perror("Restoring keyboard mode"); + if (EventDevice != -1) + close(EventDevice); + if (KeyboardDevice != -1) + close(KeyboardDevice); + if (Framebuffer != -1) + close(Framebuffer); +} + + +bool CIrrDeviceFB::createWindow(const core::dimension2d& windowSize, u32 bits) +{ + char buf[256]; + CreationParams.WindowSize.Width = windowSize.Width; + CreationParams.WindowSize.Height = windowSize.Height; + + KeyboardDevice = open("/dev/tty", O_RDWR); + if (KeyboardDevice == -1) + perror("Open keyboard"); + if (ioctl(KeyboardDevice, KDGETMODE, &KeyboardMode) <0) + perror("Read keyboard mode"); + if (ioctl(KeyboardDevice, KDSETMODE, KD_GRAPHICS) <0) + perror("Set keyboard mode"); + + Framebuffer=open("/dev/fb/0", O_RDWR); + if (Framebuffer == -1) + { + Framebuffer=open("/dev/fb0", O_RDWR); + if (Framebuffer == -1) + { + perror("Open framebuffer"); + return false; + } + } + EventDevice = open("/dev/input/event0", O_RDONLY | O_NONBLOCK); + if (EventDevice == -1) + perror("Open event device"); + + // make format settings + ioctl(Framebuffer, FBIOGET_FSCREENINFO, &fbfixscreeninfo); + ioctl(Framebuffer, FBIOGET_VSCREENINFO, &oldscreeninfo); +snprintf(buf, 256, "Original resolution: %d x %d\nARGB%d%d%d%d\n",oldscreeninfo.xres,oldscreeninfo.yres, + oldscreeninfo.transp.length,oldscreeninfo.red.length,oldscreeninfo.green.length,oldscreeninfo.blue.length); + os::Printer::log(buf); + memcpy(&fbscreeninfo, &oldscreeninfo, sizeof(struct fb_var_screeninfo)); + if (CreationParams.DriverType != video::EDT_NULL) + { + fbscreeninfo.xres = fbscreeninfo.xres_virtual = CreationParams.WindowSize.Width; + fbscreeninfo.yres = fbscreeninfo.yres_virtual = CreationParams.WindowSize.Height; + fbscreeninfo.bits_per_pixel = 16; + fbscreeninfo.red.offset = 10; + fbscreeninfo.red.length = 5; + fbscreeninfo.green.offset = 5; + fbscreeninfo.green.length = 5; + fbscreeninfo.blue.offset = 0; + fbscreeninfo.blue.length = 5; + fbscreeninfo.transp.offset = 15; + fbscreeninfo.transp.length = 1; + ioctl(Framebuffer, FBIOPUT_VSCREENINFO, &fbscreeninfo); + ioctl(Framebuffer, FBIOGET_VSCREENINFO, &fbscreeninfo); + +snprintf(buf, 256, "New resolution: %d x %d (%d x %d)\nARGB%d%d%d%d\n",fbscreeninfo.xres,fbscreeninfo.yres,fbscreeninfo.xres_virtual,fbscreeninfo.yres_virtual, + fbscreeninfo.transp.length,fbscreeninfo.red.length,fbscreeninfo.green.length,fbscreeninfo.blue.length); + os::Printer::log(buf); + + CreationParams.WindowSize.Width = fbscreeninfo.xres; + CreationParams.WindowSize.Height = fbscreeninfo.yres; + CreationParams.Bits = fbscreeninfo.bits_per_pixel; + Pitch = fbfixscreeninfo.line_length; + if (fbscreeninfo.bits_per_pixel == 16) + { + if (fbscreeninfo.transp.length == 0) + FBColorFormat = video::ECF_R5G6B5; + else + FBColorFormat = video::ECF_A1R5G5B5; + } + else + { + if (fbscreeninfo.transp.length == 0) + FBColorFormat = video::ECF_R8G8B8; + else + FBColorFormat = video::ECF_A8R8G8B8; + } + if (MAP_FAILED==(SoftwareImage=(u8*)mmap(0, CreationParams.WindowSize.Height*Pitch, PROT_READ|PROT_WRITE, MAP_SHARED, Framebuffer, 0))) + { + perror("mmap render target"); + return false; + } + } + return true; +} + + +//! create the driver +void CIrrDeviceFB::createDriver() +{ + switch(CreationParams.DriverType) + { + case video::EDT_SOFTWARE: + #ifdef _IRR_COMPILE_WITH_SOFTWARE_ + VideoDriver = video::createSoftwareDriver(CreationParams.WindowSize, CreationParams.Fullscreen, FileSystem, this); + #else + os::Printer::log("No Software driver support compiled in.", ELL_WARNING); + #endif + break; + + case video::EDT_BURNINGSVIDEO: + #ifdef _IRR_COMPILE_WITH_BURNINGSVIDEO_ + VideoDriver = video::createSoftwareDriver2(CreationParams.WindowSize, CreationParams.Fullscreen, FileSystem, this); + #else + os::Printer::log("Burning's video driver was not compiled in.", ELL_WARNING); + #endif + break; + + case video::EDT_OPENGL: + case video::EDT_DIRECT3D8: + case video::EDT_DIRECT3D9: + os::Printer::log("This driver is not available in FB. Try Software renderer.", + ELL_WARNING); + break; + + default: + VideoDriver = video::createNullDriver(FileSystem, CreationParams.WindowSize); + break; + } +} + + +//! runs the device. Returns false if device wants to be deleted +bool CIrrDeviceFB::run() +{ + os::Timer::tick(); + + struct input_event ev; + if (EventDevice>=0) + { + if ((read(EventDevice, &ev, sizeof(input_event)) < 0) && + errno != EAGAIN) + perror("Read input event"); + if (ev.type == EV_KEY) + { + irr::SEvent irrevent; + irrevent.EventType = irr::EET_KEY_INPUT_EVENT; + irrevent.KeyInput.PressedDown = true; + + switch (ev.code) + { + case KEY_RIGHTCTRL: + case KEY_LEFTCTRL: + irrevent.KeyInput.Control = true; + break; + case KEY_RIGHTSHIFT: + case KEY_LEFTSHIFT: + irrevent.KeyInput.Shift = true; + break; + case KEY_ESC: + irrevent.KeyInput.Key = (EKEY_CODE)0x1B; + break; + case KEY_SPACE: + irrevent.KeyInput.Key = (EKEY_CODE)0x20; + break; + case KEY_UP: + irrevent.KeyInput.Key = (EKEY_CODE)0x26; + break; + case KEY_LEFT: + irrevent.KeyInput.Key = (EKEY_CODE)0x25; + break; + case KEY_RIGHT: + irrevent.KeyInput.Key = (EKEY_CODE)0x27; + break; + case KEY_DOWN: + irrevent.KeyInput.Key = (EKEY_CODE)0x28; + break; + default: + irrevent.KeyInput.Key = (EKEY_CODE)0; + break; + } + postEventFromUser(irrevent); + } + } + + return !Close; +} + + +//! Pause the current process for the minimum time allowed only to allow other processes to execute +void CIrrDeviceFB::yield() +{ + struct timespec ts = {0,0}; + nanosleep(&ts, NULL); +} + + +//! Pause execution and let other processes to run for a specified amount of time. +void CIrrDeviceFB::sleep(u32 timeMs, bool pauseTimer=false) +{ + bool wasStopped = Timer ? Timer->isStopped() : true; + + struct timespec ts; + ts.tv_sec = (time_t) (timeMs / 1000); + ts.tv_nsec = (long) (timeMs % 1000) * 1000000; + + if (pauseTimer && !wasStopped) + Timer->stop(); + + nanosleep(&ts, NULL); + + if (pauseTimer && !wasStopped) + Timer->start(); +} + + +//! presents a surface in the client area +bool CIrrDeviceFB::present(video::IImage* image, void* windowId, core::rect* src ) +{ + // this is only necessary for software drivers. + if (CreationParams.DriverType != video::EDT_SOFTWARE && CreationParams.DriverType != video::EDT_BURNINGSVIDEO) + return false; + + if (!SoftwareImage) + return false; + + u8* destData = SoftwareImage; + u32 srcwidth = (u32)image->getDimension().Width; + u32 srcheight = (u32)image->getDimension().Height; + // clip images + srcheight = core::min_(srcheight, CreationParams.WindowSize.Height); + srcwidth = core::min_(srcwidth, CreationParams.WindowSize.Width); + + u8* srcdata = (u8*)image->lock(); + for (u32 y=0; ygetColorFormat(), srcwidth, destData, FBColorFormat); + srcdata+=image->getPitch(); + destData+=Pitch; + } + image->unlock(); + msync(SoftwareImage,CreationParams.WindowSize.Width*CreationParams.WindowSize.Height,MS_ASYNC); + return true; +} + + +//! notifies the device that it should close itself +void CIrrDeviceFB::closeDevice() +{ + Close = true; +} + + +//! returns if window is active. if not, nothing need to be drawn +bool CIrrDeviceFB::isWindowActive() const +{ + return true; +} + + +//! returns if window has focus +bool CIrrDeviceFB::isWindowFocused() const +{ + return true; +} + + +//! returns if window is minimized +bool CIrrDeviceFB::isWindowMinimized() const +{ + return false; +} + + +//! sets the caption of the window +void CIrrDeviceFB::setWindowCaption(const wchar_t* text) +{ +} + + +//! Sets if the window should be resizeable in windowed mode. +void CIrrDeviceFB::setResizable(bool resize) +{ +} + + +//! Minimizes window +void CIrrDeviceFB::minimizeWindow() +{ +} + + +//! Maximizes window +void CIrrDeviceFB::maximizeWindow() +{ +} + + +//! Restores original window size +void CIrrDeviceFB::restoreWindow() +{ +} + + +//! Returns the type of this device +E_DEVICE_TYPE CIrrDeviceFB::getType() const +{ + return EIDT_FRAMEBUFFER; +} + + +} // end namespace irr + +#endif // _IRR_USE_FB_DEVICE_ + diff --git a/source/Irrlicht/CIrrDeviceFB.h b/source/Irrlicht/CIrrDeviceFB.h new file mode 100644 index 00000000..c04f6ac6 --- /dev/null +++ b/source/Irrlicht/CIrrDeviceFB.h @@ -0,0 +1,207 @@ +// Copyright (C) 2002-2007 Nikolaus Gebhardt +// Copyright (C) 2007-2009 Christian Stehno +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#ifndef __C_IRR_DEVICE_FB_H_INCLUDED__ +#define __C_IRR_DEVICE_FB_H_INCLUDED__ + +#include "IrrCompileConfig.h" + +#ifdef _IRR_COMPILE_WITH_FB_DEVICE_ + +#include "CIrrDeviceStub.h" +#include "SIrrCreationParameters.h" +#include "IrrlichtDevice.h" +#include "IImagePresenter.h" +#include "ICursorControl.h" + +#define KeySym s32 +#include +#include + +namespace irr +{ + class CIrrDeviceFB : public CIrrDeviceStub, public video::IImagePresenter + { + public: + + //! constructor + CIrrDeviceFB(const SIrrlichtCreationParameters& params); + + //! destructor + virtual ~CIrrDeviceFB(); + + //! 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; + + //! Minimizes window + virtual void minimizeWindow(); + + //! Maximizes window + virtual void maximizeWindow(); + + //! Restores original window size + virtual void restoreWindow(); + + //! presents a surface in the client area + virtual bool present(video::IImage* surface, void* windowId = 0, core::rect* src=0 ); + + //! notifies the device that it should close itself + virtual void closeDevice(); + + //! Sets if the window should be resizeable in windowed mode. + virtual void setResizable(bool resize=false); + + //! Returns the type of this device + virtual E_DEVICE_TYPE getType() const; + + private: + + //! create the driver + void createDriver(); + + bool createWindow(const core::dimension2d& windowSize, u32 bits); + + //! Implementation of the cursor control + class CCursorControl : public gui::ICursorControl + { + public: + + CCursorControl(CIrrDeviceFB* dev, bool null) + : Device(dev), IsVisible(true), Null(null) + { + Device->grab(); + } + + ~CCursorControl() + { + Device->drop(); + } + + //! 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 + { + return IsVisible; + } + + //! Sets the new position of the cursor. + virtual void setPosition(const core::position2d &pos) + { + setPosition(pos.X, pos.Y); + } + + //! Sets the new position of the cursor. + virtual void setPosition(f32 x, f32 y) + { + setPosition((s32)(x*Device->CreationParams.WindowSize.Width), (s32)(y*Device->CreationParams.WindowSize.Height)); + } + + //! Sets the new position of the cursor. + virtual void setPosition(const core::position2d &pos) + { + setPosition(pos.X, pos.Y); + } + + //! Sets the new position of the cursor. + virtual void setPosition(s32 x, s32 y) + { + } + + //! Returns the current position of the mouse cursor. + virtual const core::position2d& getPosition() + { + updateCursorPos(); + return CursorPos; + } + + //! Returns the current position of the mouse cursor. + virtual core::position2d getRelativePosition() + { + updateCursorPos(); + return core::position2d(CursorPos.X / (f32)Device->CreationParams.WindowSize.Width, + CursorPos.Y / (f32)Device->CreationParams.WindowSize.Height); + } + + virtual void setReferenceRect(core::rect* rect=0) + { + } + + private: + + void updateCursorPos() + { + } + + core::position2d CursorPos; + CIrrDeviceFB* Device; + bool IsVisible; + bool Null; + }; + + friend class CCursorControl; + + int Framebuffer; + int EventDevice; + int KeyboardDevice; + struct fb_fix_screeninfo fbfixscreeninfo; + struct fb_var_screeninfo fbscreeninfo; + struct fb_var_screeninfo oldscreeninfo; + long KeyboardMode; + u8* SoftwareImage; + + u32 Pitch; + video::ECOLOR_FORMAT FBColorFormat; + bool Close; + + struct SKeyMap + { + SKeyMap() {} + SKeyMap(s32 x11, s32 win32) + : X11Key(x11), Win32Key(win32) + { + } + + KeySym X11Key; + s32 Win32Key; + + bool operator<(const SKeyMap& o) const + { + return X11Key KeyMap; + }; + + +} // end namespace irr + +#endif // _IRR_USE_FB_DEVICE_ +#endif // __C_IRR_DEVICE_FB_H_INCLUDED__ + diff --git a/source/Irrlicht/CIrrDeviceLinux.cpp b/source/Irrlicht/CIrrDeviceLinux.cpp index fce6493c..b4286c4f 100644 --- a/source/Irrlicht/CIrrDeviceLinux.cpp +++ b/source/Irrlicht/CIrrDeviceLinux.cpp @@ -305,6 +305,37 @@ bool CIrrDeviceLinux::switchToFullscreen(bool reset) } +#if defined(_IRR_COMPILE_WITH_X11_) +void IrrPrintXGrabError(int grabResult, const c8 * grabCommand ) +{ + if ( grabResult == GrabSuccess ) + { +// os::Printer::log(grabCommand, ": GrabSuccess", ELL_INFORMATION); + return; + } + + switch ( grabResult ) + { + case AlreadyGrabbed: + os::Printer::log(grabCommand, ": AlreadyGrabbed", ELL_WARNING); + break; + case GrabNotViewable: + os::Printer::log(grabCommand, ": GrabNotViewable", ELL_WARNING); + break; + case GrabFrozen: + os::Printer::log(grabCommand, ": GrabFrozen", ELL_WARNING); + break; + case GrabInvalidTime: + os::Printer::log(grabCommand, ": GrabInvalidTime", ELL_WARNING); + break; + default: + os::Printer::log(grabCommand, ": grab failed with unknown problem", ELL_WARNING); + break; + } +} +#endif + + bool CIrrDeviceLinux::createWindow() { #ifdef _IRR_COMPILE_WITH_X11_ @@ -340,7 +371,7 @@ bool CIrrDeviceLinux::createWindow() { #ifdef GLX_VERSION_1_3 typedef GLXFBConfig * ( * PFNGLXCHOOSEFBCONFIGPROC) (Display *dpy, int screen, const int *attrib_list, int *nelements); - + #ifdef _IRR_OPENGL_USE_EXTPOINTER_ PFNGLXCHOOSEFBCONFIGPROC glxChooseFBConfig = (PFNGLXCHOOSEFBCONFIGPROC)glXGetProcAddress(reinterpret_cast("glXChooseFBConfig")); #else @@ -606,10 +637,13 @@ bool CIrrDeviceLinux::createWindow() XSetWMProtocols(display, window, &wmDelete, 1); if (CreationParams.Fullscreen) { - XGrabKeyboard(display, window, True, GrabModeAsync, + XSetInputFocus(display, window, RevertToParent, CurrentTime); + int grabKb = XGrabKeyboard(display, window, True, GrabModeAsync, GrabModeAsync, CurrentTime); - XGrabPointer(display, window, True, ButtonPressMask, + IrrPrintXGrabError(grabKb, "XGrabKeyboard"); + int grabPointer = XGrabPointer(display, window, True, ButtonPressMask, GrabModeAsync, GrabModeAsync, window, None, CurrentTime); + IrrPrintXGrabError(grabPointer, "XGrabPointer"); XWarpPointer(display, None, window, 0, 0, 0, 0, 0, 0); } } @@ -695,6 +729,9 @@ bool CIrrDeviceLinux::createWindow() XGetGeometry(display, window, &tmp, &x, &y, &Width, &Height, &borderWidth, &bits); CreationParams.Bits = bits; + CreationParams.WindowSize.Width = Width; + CreationParams.WindowSize.Height = Height; + StdHints = XAllocSizeHints(); long num; XGetWMNormalHints(display, window, StdHints, &num); @@ -909,13 +946,19 @@ bool CIrrDeviceLinux::run() break; case Button4: - irrevent.MouseInput.Event = EMIE_MOUSE_WHEEL; - irrevent.MouseInput.Wheel = 1.0f; + if (event.type == ButtonPress) + { + irrevent.MouseInput.Event = EMIE_MOUSE_WHEEL; + irrevent.MouseInput.Wheel = 1.0f; + } break; case Button5: - irrevent.MouseInput.Event = EMIE_MOUSE_WHEEL; - irrevent.MouseInput.Wheel = -1.0f; + if (event.type == ButtonPress) + { + irrevent.MouseInput.Event = EMIE_MOUSE_WHEEL; + irrevent.MouseInput.Wheel = -1.0f; + } break; } @@ -923,17 +966,17 @@ bool CIrrDeviceLinux::run() { postEventFromUser(irrevent); - if ( irrevent.MouseInput.Event == EMIE_LMOUSE_PRESSED_DOWN ) + if ( irrevent.MouseInput.Event >= EMIE_LMOUSE_PRESSED_DOWN && irrevent.MouseInput.Event <= EMIE_MMOUSE_PRESSED_DOWN ) { - u32 clicks = checkSuccessiveClicks(irrevent.MouseInput.X, irrevent.MouseInput.Y); + u32 clicks = checkSuccessiveClicks(irrevent.MouseInput.X, irrevent.MouseInput.Y, irrevent.MouseInput.Event); if ( clicks == 2 ) { - irrevent.MouseInput.Event = EMIE_MOUSE_DOUBLE_CLICK; + irrevent.MouseInput.Event = (EMOUSE_INPUT_EVENT)(EMIE_LMOUSE_DOUBLE_CLICK + irrevent.MouseInput.Event-EMIE_LMOUSE_PRESSED_DOWN); postEventFromUser(irrevent); } else if ( clicks == 3 ) { - irrevent.MouseInput.Event = EMIE_MOUSE_TRIPLE_CLICK; + irrevent.MouseInput.Event = (EMOUSE_INPUT_EVENT)(EMIE_LMOUSE_TRIPLE_CLICK + irrevent.MouseInput.Event-EMIE_LMOUSE_PRESSED_DOWN); postEventFromUser(irrevent); } } @@ -1826,6 +1869,40 @@ void CIrrDeviceLinux::copyToClipboard(const c8* text) const #endif } +#ifdef _IRR_COMPILE_WITH_X11_ +// return true if the passed event has the type passed in parameter arg +Bool PredicateIsEventType(Display *display, XEvent *event, XPointer arg) +{ + if ( event && event->type == *(int*)arg ) + { +// os::Printer::log("remove event:", core::stringc((int)arg).c_str(), ELL_INFORMATION); + return True; + } + return False; +} +#endif //_IRR_COMPILE_WITH_X11_ + +//! Remove all messages pending in the system message loop +void CIrrDeviceLinux::clearSystemMessages() +{ +#ifdef _IRR_COMPILE_WITH_X11_ + if (CreationParams.DriverType != video::EDT_NULL) + { + XEvent event; + int usrArg = ButtonPress; + while ( XCheckIfEvent(display, &event, PredicateIsEventType, XPointer(&usrArg)) == True ) {} + usrArg = ButtonRelease; + while ( XCheckIfEvent(display, &event, PredicateIsEventType, XPointer(&usrArg)) == True ) {} + usrArg = MotionNotify; + while ( XCheckIfEvent(display, &event, PredicateIsEventType, XPointer(&usrArg)) == True ) {} + usrArg = KeyRelease; + while ( XCheckIfEvent(display, &event, PredicateIsEventType, XPointer(&usrArg)) == True ) {} + usrArg = KeyPress; + while ( XCheckIfEvent(display, &event, PredicateIsEventType, XPointer(&usrArg)) == True ) {} + } +#endif //_IRR_COMPILE_WITH_X11_ +} + void CIrrDeviceLinux::initXAtoms() { #ifdef _IRR_COMPILE_WITH_X11_ diff --git a/source/Irrlicht/CIrrDeviceLinux.h b/source/Irrlicht/CIrrDeviceLinux.h index 2900ad01..169e4101 100644 --- a/source/Irrlicht/CIrrDeviceLinux.h +++ b/source/Irrlicht/CIrrDeviceLinux.h @@ -116,6 +116,9 @@ namespace irr //! This sets the clipboard selection and _not_ the primary selection which you have on X on the middle mouse button. virtual void copyToClipboard(const c8* text) const; + //! Remove all messages pending in the system message loop + virtual void clearSystemMessages(); + //! Get the device type virtual E_DEVICE_TYPE getType() const { diff --git a/source/Irrlicht/CIrrDeviceSDL.cpp b/source/Irrlicht/CIrrDeviceSDL.cpp index 2ffab63f..b4f8e5cf 100644 --- a/source/Irrlicht/CIrrDeviceSDL.cpp +++ b/source/Irrlicht/CIrrDeviceSDL.cpp @@ -380,17 +380,17 @@ bool CIrrDeviceSDL::run() { postEventFromUser(irrevent); - if ( irrevent.MouseInput.Event == EMIE_LMOUSE_PRESSED_DOWN ) + if ( irrevent.MouseInput.Event >= EMIE_LMOUSE_PRESSED_DOWN && irrevent.MouseInput.Event <= EMIE_MMOUSE_PRESSED_DOWN ) { - u32 clicks = checkSuccessiveClicks(irrevent.MouseInput.X, irrevent.MouseInput.Y); + u32 clicks = checkSuccessiveClicks(irrevent.MouseInput.X, irrevent.MouseInput.Y, irrevent.MouseInput.Event); if ( clicks == 2 ) { - irrevent.MouseInput.Event = EMIE_MOUSE_DOUBLE_CLICK; + irrevent.MouseInput.Event = (EMOUSE_INPUT_EVENT)(EMIE_LMOUSE_DOUBLE_CLICK + irrevent.MouseInput.Event-EMIE_LMOUSE_PRESSED_DOWN); postEventFromUser(irrevent); } else if ( clicks == 3 ) { - irrevent.MouseInput.Event = EMIE_MOUSE_TRIPLE_CLICK; + irrevent.MouseInput.Event = (EMOUSE_INPUT_EVENT)(EMIE_LMOUSE_TRIPLE_CLICK + irrevent.MouseInput.Event-EMIE_LMOUSE_PRESSED_DOWN); postEventFromUser(irrevent); } } diff --git a/source/Irrlicht/CIrrDeviceStub.cpp b/source/Irrlicht/CIrrDeviceStub.cpp index 89630f6e..c7c16eaf 100644 --- a/source/Irrlicht/CIrrDeviceStub.cpp +++ b/source/Irrlicht/CIrrDeviceStub.cpp @@ -34,6 +34,7 @@ CIrrDeviceStub::CIrrDeviceStub(const SIrrlichtCreationParameters& params) Logger = new CLogger(UserReceiver); os::Printer::Logger = Logger; } + Logger->setLogLevel( CreationParams.LoggingLevel ); os::Printer::Logger = Logger; @@ -172,7 +173,7 @@ bool CIrrDeviceStub::checkVersion(const char* version) //! Compares to the last call of this function to return double and triple clicks. -u32 CIrrDeviceStub::checkSuccessiveClicks(s32 mouseX, s32 mouseY) +u32 CIrrDeviceStub::checkSuccessiveClicks(s32 mouseX, s32 mouseY, EMOUSE_INPUT_EVENT inputEvent ) { const s32 MAX_MOUSEMOVE = 3; @@ -181,7 +182,9 @@ u32 CIrrDeviceStub::checkSuccessiveClicks(s32 mouseX, s32 mouseY) if ( (clickTime-MouseMultiClicks.LastClickTime) < MouseMultiClicks.DoubleClickTime && core::abs_(MouseMultiClicks.LastClick.X - mouseX ) <= MAX_MOUSEMOVE && core::abs_(MouseMultiClicks.LastClick.Y - mouseY ) <= MAX_MOUSEMOVE - && MouseMultiClicks.CountSuccessiveClicks < 3 ) + && MouseMultiClicks.CountSuccessiveClicks < 3 + && MouseMultiClicks.LastMouseInputEvent == inputEvent + ) { ++MouseMultiClicks.CountSuccessiveClicks; } @@ -190,6 +193,7 @@ u32 CIrrDeviceStub::checkSuccessiveClicks(s32 mouseX, s32 mouseY) MouseMultiClicks.CountSuccessiveClicks = 1; } + MouseMultiClicks.LastMouseInputEvent = inputEvent; MouseMultiClicks.LastClickTime = clickTime; MouseMultiClicks.LastClick.X = mouseX; MouseMultiClicks.LastClick.Y = mouseY; @@ -349,6 +353,12 @@ u32 CIrrDeviceStub::getDoubleClickTime() const return MouseMultiClicks.DoubleClickTime; } +//! Remove all messages pending in the system message loop +void CIrrDeviceStub::clearSystemMessages() +{ +} + + } // end namespace irr diff --git a/source/Irrlicht/CIrrDeviceStub.h b/source/Irrlicht/CIrrDeviceStub.h index 47a54161..2167fc4b 100644 --- a/source/Irrlicht/CIrrDeviceStub.h +++ b/source/Irrlicht/CIrrDeviceStub.h @@ -123,6 +123,10 @@ namespace irr //! Get the maximal elapsed time between 2 clicks to generate double- and tripleclicks for the mouse. virtual u32 getDoubleClickTime() const; + //! Remove all messages pending in the system message loop + virtual void clearSystemMessages(); + + protected: void createGUIAndScene(); @@ -132,7 +136,7 @@ namespace irr //! Compares to the last call of this function to return double and triple clicks. //! \return Returns only 1,2 or 3. A 4th click will start with 1 again. - virtual u32 checkSuccessiveClicks(s32 mouseX, s32 mouseY); + virtual u32 checkSuccessiveClicks(s32 mouseX, s32 mouseY, EMOUSE_INPUT_EVENT inputEvent ); void calculateGammaRamp ( u16 *ramp, f32 gamma, f32 relativebrightness, f32 relativecontrast ); void calculateGammaFromRamp ( f32 &gamma, const u16 *ramp ); @@ -151,13 +155,14 @@ namespace irr struct SMouseMultiClicks { SMouseMultiClicks() - : DoubleClickTime(500), CountSuccessiveClicks(0), LastClickTime(0) + : DoubleClickTime(500), CountSuccessiveClicks(0), LastClickTime(0), LastMouseInputEvent(EMIE_COUNT) {} u32 DoubleClickTime; u32 CountSuccessiveClicks; u32 LastClickTime; core::position2di LastClick; + EMOUSE_INPUT_EVENT LastMouseInputEvent; }; SMouseMultiClicks MouseMultiClicks; video::CVideoModeList VideoModeList; diff --git a/source/Irrlicht/CIrrDeviceWin32.cpp b/source/Irrlicht/CIrrDeviceWin32.cpp index 0a3dede0..2c566fb5 100644 --- a/source/Irrlicht/CIrrDeviceWin32.cpp +++ b/source/Irrlicht/CIrrDeviceWin32.cpp @@ -35,7 +35,7 @@ namespace irr #endif #ifdef _IRR_COMPILE_WITH_OPENGL_ - IVideoDriver* createOpenGLDriver(const SIrrlichtCreationParameters& params, + IVideoDriver* createOpenGLDriver(const irr::SIrrlichtCreationParameters& params, io::IFileSystem* io, CIrrDeviceWin32* device); #endif @@ -45,14 +45,178 @@ namespace irr } } // end namespace irr - -struct SEnvMapper +// Get the codepage from the locale language id +// Based on the table from http://www.science.co.il/Language/Locale-Codes.asp?s=decimal +static unsigned int LocaleIdToCodepage(unsigned int lcid) { - HWND hWnd; - irr::CIrrDeviceWin32* irrDev; -}; + switch ( lcid ) + { + case 1098: // Telugu + case 1095: // Gujarati + case 1094: // Punjabi + case 1103: // Sanskrit + case 1111: // Konkani + case 1114: // Syriac + case 1099: // Kannada + case 1102: // Marathi + case 1125: // Divehi + case 1067: // Armenian + case 1081: // Hindi + case 1079: // Georgian + case 1097: // Tamil + return 0; + case 1054: // Thai + return 874; + case 1041: // Japanese + return 932; + case 2052: // Chinese (PRC) + case 4100: // Chinese (Singapore) + return 936; + case 1042: // Korean + return 949; + case 5124: // Chinese (Macau S.A.R.) + case 3076: // Chinese (Hong Kong S.A.R.) + case 1028: // Chinese (Taiwan) + return 950; + case 1048: // Romanian + case 1060: // Slovenian + case 1038: // Hungarian + case 1051: // Slovak + case 1045: // Polish + case 1052: // Albanian + case 2074: // Serbian (Latin) + case 1050: // Croatian + case 1029: // Czech + return 1250; + case 1104: // Mongolian (Cyrillic) + case 1071: // FYRO Macedonian + case 2115: // Uzbek (Cyrillic) + case 1058: // Ukrainian + case 2092: // Azeri (Cyrillic) + case 1092: // Tatar + case 1087: // Kazakh + case 1059: // Belarusian + case 1088: // Kyrgyz (Cyrillic) + case 1026: // Bulgarian + case 3098: // Serbian (Cyrillic) + case 1049: // Russian + return 1251; + case 8201: // English (Jamaica) + case 3084: // French (Canada) + case 1036: // French (France) + case 5132: // French (Luxembourg) + case 5129: // English (New Zealand) + case 6153: // English (Ireland) + case 1043: // Dutch (Netherlands) + case 9225: // English (Caribbean) + case 4108: // French (Switzerland) + case 4105: // English (Canada) + case 1110: // Galician + case 10249: // English (Belize) + case 3079: // German (Austria) + case 6156: // French (Monaco) + case 12297: // English (Zimbabwe) + case 1069: // Basque + case 2067: // Dutch (Belgium) + case 2060: // French (Belgium) + case 1035: // Finnish + case 1080: // Faroese + case 1031: // German (Germany) + case 3081: // English (Australia) + case 1033: // English (United States) + case 2057: // English (United Kingdom) + case 1027: // Catalan + case 11273: // English (Trinidad) + case 7177: // English (South Africa) + case 1030: // Danish + case 13321: // English (Philippines) + case 15370: // Spanish (Paraguay) + case 9226: // Spanish (Colombia) + case 5130: // Spanish (Costa Rica) + case 7178: // Spanish (Dominican Republic) + case 12298: // Spanish (Ecuador) + case 17418: // Spanish (El Salvador) + case 4106: // Spanish (Guatemala) + case 18442: // Spanish (Honduras) + case 3082: // Spanish (International Sort) + case 13322: // Spanish (Chile) + case 19466: // Spanish (Nicaragua) + case 2058: // Spanish (Mexico) + case 10250: // Spanish (Peru) + case 20490: // Spanish (Puerto Rico) + case 1034: // Spanish (Traditional Sort) + case 14346: // Spanish (Uruguay) + case 8202: // Spanish (Venezuela) + case 1089: // Swahili + case 1053: // Swedish + case 2077: // Swedish (Finland) + case 5127: // German (Liechtenstein) + case 1078: // Afrikaans + case 6154: // Spanish (Panama) + case 4103: // German (Luxembourg) + case 16394: // Spanish (Bolivia) + case 2055: // German (Switzerland) + case 1039: // Icelandic + case 1057: // Indonesian + case 1040: // Italian (Italy) + case 2064: // Italian (Switzerland) + case 2068: // Norwegian (Nynorsk) + case 11274: // Spanish (Argentina) + case 1046: // Portuguese (Brazil) + case 1044: // Norwegian (Bokmal) + case 1086: // Malay (Malaysia) + case 2110: // Malay (Brunei Darussalam) + case 2070: // Portuguese (Portugal) + return 1252; + case 1032: // Greek + return 1253; + case 1091: // Uzbek (Latin) + case 1068: // Azeri (Latin) + case 1055: // Turkish + return 1254; + case 1037: // Hebrew + return 1255; + case 5121: // Arabic (Algeria) + case 15361: // Arabic (Bahrain) + case 9217: // Arabic (Yemen) + case 3073: // Arabic (Egypt) + case 2049: // Arabic (Iraq) + case 11265: // Arabic (Jordan) + case 13313: // Arabic (Kuwait) + case 12289: // Arabic (Lebanon) + case 4097: // Arabic (Libya) + case 6145: // Arabic (Morocco) + case 8193: // Arabic (Oman) + case 16385: // Arabic (Qatar) + case 1025: // Arabic (Saudi Arabia) + case 10241: // Arabic (Syria) + case 14337: // Arabic (U.A.E.) + case 1065: // Farsi + case 1056: // Urdu + case 7169: // Arabic (Tunisia) + return 1256; + case 1061: // Estonian + case 1062: // Latvian + case 1063: // Lithuanian + return 1257; + case 1066: // Vietnamese + return 1258; + } + return 65001; // utf-8 +} -irr::core::list EnvMap; +namespace +{ + struct SEnvMapper + { + HWND hWnd; + irr::CIrrDeviceWin32* irrDev; + }; + irr::core::list EnvMap; + + HKL KEYBOARD_INPUT_HKL=0; + unsigned int KEYBOARD_INPUT_CODEPAGE = 1252; +}; SEnvMapper* getEnvMapperFromHWnd(HWND hWnd) { @@ -171,17 +335,17 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { dev->postEventFromUser(event); - if ( event.MouseInput.Event == irr::EMIE_LMOUSE_PRESSED_DOWN ) + if ( event.MouseInput.Event >= irr::EMIE_LMOUSE_PRESSED_DOWN && event.MouseInput.Event <= irr::EMIE_MMOUSE_PRESSED_DOWN ) { - irr::u32 clicks = dev->checkSuccessiveClicks(event.MouseInput.X, event.MouseInput.Y); + irr::u32 clicks = dev->checkSuccessiveClicks(event.MouseInput.X, event.MouseInput.Y, event.MouseInput.Event); if ( clicks == 2 ) { - event.MouseInput.Event = irr::EMIE_MOUSE_DOUBLE_CLICK; + event.MouseInput.Event = (irr::EMOUSE_INPUT_EVENT)(irr::EMIE_LMOUSE_DOUBLE_CLICK + event.MouseInput.Event-irr::EMIE_LMOUSE_PRESSED_DOWN); dev->postEventFromUser(event); } else if ( clicks == 3 ) { - event.MouseInput.Event = irr::EMIE_MOUSE_TRIPLE_CLICK; + event.MouseInput.Event = (irr::EMOUSE_INPUT_EVENT)(irr::EMIE_LMOUSE_TRIPLE_CLICK + event.MouseInput.Event-irr::EMIE_LMOUSE_PRESSED_DOWN); dev->postEventFromUser(event); } } @@ -223,23 +387,44 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { event.KeyInput.Key = (irr::EKEY_CODE)MapVirtualKey( ((lParam>>16) & 255), MY_MAPVK_VSC_TO_VK_EX ); // some keyboards will just return LEFT for both - left and right keys. So also check extend bit. - if (lParam & 0x1000000) + if (lParam & 0x1000000) event.KeyInput.Key = irr::KEY_RCONTROL; } if ( event.KeyInput.Key == irr::KEY_MENU ) { event.KeyInput.Key = (irr::EKEY_CODE)MapVirtualKey( ((lParam>>16) & 255), MY_MAPVK_VSC_TO_VK_EX ); - if (lParam & 0x1000000) + if (lParam & 0x1000000) event.KeyInput.Key = irr::KEY_RMENU; } - - WORD KeyAsc=0; + GetKeyboardState(allKeys); - ToAscii((UINT)wParam,(UINT)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; + + // Handle unicode and deadkeys in a way that works since Windows 95 and nt4.0 + // Using ToUnicode instead would be shorter, but would to my knowledge not run on 95 and 98. + WORD keyChars[2]; + UINT scanCode = HIWORD(lParam); + int conversionResult = ToAsciiEx(wParam,scanCode,allKeys,keyChars,0,KEYBOARD_INPUT_HKL); + if (conversionResult == 1) + { + WORD unicodeChar; + MultiByteToWideChar( + KEYBOARD_INPUT_CODEPAGE, + MB_PRECOMPOSED, // default + (LPCSTR)keyChars, + sizeof(keyChars), + (WCHAR*)&unicodeChar, + 1 ); + event.KeyInput.Char = unicodeChar; + } + else + event.KeyInput.Char = 0; + + // allow composing characters like '@' with Alt Gr on non-US keyboards + if ((allKeys[VK_MENU] & 0x80) != 0) + event.KeyInput.Control = 0; dev = getDeviceFromHWnd(hWnd); if (dev) @@ -293,6 +478,19 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) dev->postEventFromUser(event); return 0; + + case WM_SETCURSOR: + // because Windows forgot about that in the meantime + dev = getDeviceFromHWnd(hWnd); + if (dev) + dev->getCursorControl()->setVisible( dev->getCursorControl()->isVisible() ); + break; + + case WM_INPUTLANGCHANGE: + // get the new codepage used for keyboard input + KEYBOARD_INPUT_HKL = GetKeyboardLayout(0); + KEYBOARD_INPUT_CODEPAGE = LocaleIdToCodepage( LOWORD(KEYBOARD_INPUT_HKL) ); + return 0; } return DefWindowProc(hWnd, message, wParam, lParam); } @@ -366,6 +564,11 @@ CIrrDeviceWin32::CIrrDeviceWin32(const SIrrlichtCreationParameters& params) s32 windowLeft = (GetSystemMetrics(SM_CXSCREEN) - realWidth) / 2; s32 windowTop = (GetSystemMetrics(SM_CYSCREEN) - realHeight) / 2; + if ( windowLeft < 0 ) + windowLeft = 0; + if ( windowTop < 0 ) + windowTop = 0; // make sure window menus are in screen on creation + if (CreationParams.Fullscreen) { windowLeft = 0; @@ -383,6 +586,9 @@ CIrrDeviceWin32::CIrrDeviceWin32(const SIrrlichtCreationParameters& params) // fix ugly ATI driver bugs. Thanks to ariaci MoveWindow(HWnd, windowLeft, windowTop, realWidth, realHeight, TRUE); + + // make sure everything gets updated to the real sizes + Resized = true; } else if (CreationParams.WindowId) { @@ -421,6 +627,10 @@ CIrrDeviceWin32::CIrrDeviceWin32(const SIrrlichtCreationParameters& params) // set this as active window SetActiveWindow(HWnd); SetForegroundWindow(HWnd); + + // get the codepage used for keyboard input + KEYBOARD_INPUT_HKL = GetKeyboardLayout(0); + KEYBOARD_INPUT_CODEPAGE = LocaleIdToCodepage( LOWORD(KEYBOARD_INPUT_HKL) ); } @@ -563,7 +773,8 @@ bool CIrrDeviceWin32::run() while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { - TranslateMessage(&msg); + // No message translation because we don't use WM_CHAR and it would conflict with our + // deadkey handling. if (ExternalWindow && msg.hwnd == HWnd) WndProc(HWnd, msg.message, msg.wParam, msg.lParam); @@ -640,7 +851,7 @@ void CIrrDeviceWin32::setWindowCaption(const wchar_t* text) if (IsNonNTWindows) { const core::stringc s = text; -#ifdef WIN64 +#if defined(_WIN64) || defined(WIN64) SetWindowTextA(HWnd, s.c_str()); #else SendMessageTimeout(HWnd, WM_SETTEXT, 0, @@ -650,7 +861,7 @@ void CIrrDeviceWin32::setWindowCaption(const wchar_t* text) } else { -#ifdef WIN64 +#if defined(_WIN64) || defined(WIN64) SetWindowTextW(HWnd, text); #else SendMessageTimeoutW(HWnd, WM_SETTEXT, 0, @@ -1014,6 +1225,8 @@ void CIrrDeviceWin32::setResizable(bool resize) SetWindowPos(HWnd, HWND_TOP, windowLeft, windowTop, realWidth, realHeight, SWP_FRAMECHANGED | SWP_NOMOVE | SWP_SHOWWINDOW); + + static_cast(CursorControl)->updateBorderSize(CreationParams.Fullscreen, resize); } @@ -1113,21 +1326,28 @@ void CIrrDeviceWin32::pollJoysticks() u32 joystick; JOYINFOEX info; - info.dwSize = sizeof(info); - info.dwFlags = JOY_RETURNALL; for(joystick = 0; joystick < ActiveJoysticks.size(); ++joystick) { + // needs to be reset for each joystick + // request ALL values and POV as continuous if possible + info.dwSize = sizeof(info); + info.dwFlags = JOY_RETURNALL|JOY_RETURNPOVCTS; + const JOYCAPS & caps = ActiveJoysticks[joystick].Caps; + // if no POV is available don't ask for POV values + if (!(caps.wCaps & JOYCAPS_HASPOV)) + info.dwFlags &= ~(JOY_RETURNPOV|JOY_RETURNPOVCTS); if(JOYERR_NOERROR == joyGetPosEx(ActiveJoysticks[joystick].Index, &info)) { SEvent event; - const JOYCAPS & caps = ActiveJoysticks[joystick].Caps; event.EventType = irr::EET_JOYSTICK_INPUT_EVENT; event.JoystickEvent.Joystick = (u8)joystick; - + event.JoystickEvent.POV = (u16)info.dwPOV; - if(event.JoystickEvent.POV > 35900) + // set to undefined if no POV value was returned or the value + // is out of range + if (!(info.dwFlags & JOY_RETURNPOV) || (event.JoystickEvent.POV > 35900)) event.JoystickEvent.POV = 65535; for(int axis = 0; axis < SEvent::SJoystickEvent::NUMBER_OF_AXES; ++axis) @@ -1209,7 +1429,53 @@ bool CIrrDeviceWin32::getGammaRamp( f32 &red, f32 &green, f32 &blue, f32 &bright } +//! Remove all messages pending in the system message loop +void CIrrDeviceWin32::clearSystemMessages() +{ + MSG msg; + while (PeekMessage(&msg, NULL, WM_KEYFIRST, WM_KEYLAST, PM_REMOVE)) + {} + while (PeekMessage(&msg, NULL, WM_MOUSEFIRST, WM_MOUSELAST, PM_REMOVE)) + {} +} + +// shows last error in a messagebox to help internal debugging. +void CIrrDeviceWin32::ReportLastWinApiError() +{ + // (based on code from ovidiucucu from http://www.codeguru.com/forum/showthread.php?t=318721) + LPCTSTR pszCaption = __TEXT("Windows SDK Error Report"); + DWORD dwError = GetLastError(); + + if(NOERROR == dwError) + { + MessageBox(NULL, __TEXT("No error"), pszCaption, MB_OK); + } + else + { + const DWORD dwFormatControl = FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_IGNORE_INSERTS | + FORMAT_MESSAGE_FROM_SYSTEM; + + LPVOID pTextBuffer = NULL; + DWORD dwCount = FormatMessage(dwFormatControl, + NULL, + dwError, + 0, + (LPTSTR) &pTextBuffer, + 0, + NULL); + if(0 != dwCount) + { + MessageBox(NULL, (LPCTSTR)pTextBuffer, pszCaption, MB_OK|MB_ICONERROR); + LocalFree(pTextBuffer); + } + else + { + MessageBox(NULL, __TEXT("Unknown error"), pszCaption, MB_OK|MB_ICONERROR); + } + } +} + } // end namespace #endif // _IRR_COMPILE_WITH_WINDOWS_DEVICE_ - diff --git a/source/Irrlicht/CIrrDeviceWin32.h b/source/Irrlicht/CIrrDeviceWin32.h index 7b69856f..8e694a9f 100644 --- a/source/Irrlicht/CIrrDeviceWin32.h +++ b/source/Irrlicht/CIrrDeviceWin32.h @@ -87,6 +87,9 @@ namespace irr //! Get the current Gamma Value for the Display virtual bool getGammaRamp( f32 &red, f32 &green, f32 &blue, f32 &brightness, f32 &contrast ); + //! Remove all messages pending in the system message loop + virtual void clearSystemMessages(); + //! Get the device type virtual E_DEVICE_TYPE getType() const { @@ -95,15 +98,19 @@ namespace irr //! Compares to the last call of this function to return double and triple clicks. //! \return Returns only 1,2 or 3. A 4th click will start with 1 again. - virtual u32 checkSuccessiveClicks(s32 mouseX, s32 mouseY) + virtual u32 checkSuccessiveClicks(s32 mouseX, s32 mouseY, EMOUSE_INPUT_EVENT inputEvent ) { // we just have to make it public - return CIrrDeviceStub::checkSuccessiveClicks(mouseX, mouseY); + return CIrrDeviceStub::checkSuccessiveClicks(mouseX, mouseY, inputEvent ); } //! switchs to fullscreen bool switchToFullScreen(bool reset=false); + //! Check for and show last Windows API error to help internal debugging. + //! Does call GetLastError and on errors formats the errortext and displays it in a messagebox. + static void ReportLastWinApiError(); + //! Implementation of the win32 cursor control class CCursorControl : public gui::ICursorControl { @@ -120,11 +127,7 @@ namespace irr if (WindowSize.Height!=0) InvWindowSize.Height = 1.0f / WindowSize.Height; - if (!fullscreen) - { - BorderX = GetSystemMetrics(SM_CXDLGFRAME); - BorderY = GetSystemMetrics(SM_CYCAPTION) + GetSystemMetrics(SM_CYDLGFRAME); - } + updateBorderSize(fullscreen, false); } //! Changes the visible state of the mouse cursor. @@ -132,31 +135,23 @@ namespace irr { CURSORINFO info; info.cbSize = sizeof(CURSORINFO); - - if ( visible ) + BOOL gotCursorInfo = GetCursorInfo(&info); + while ( gotCursorInfo ) { - while ( GetCursorInfo(&info) ) + if ( (visible && info.flags == CURSOR_SHOWING) // visible + || (!visible && info.flags == 0 ) ) // hidden { - if ( info.flags == CURSOR_SHOWING ) - { - IsVisible = visible; - break; - } - ShowCursor(true); // this only increases an internal display counter in windows, so it might have to be called some more + break; } - } - else - { - while ( GetCursorInfo(&info) ) + int showResult = ShowCursor(visible); // this only increases an internal display counter in windows, so it might have to be called some more + if ( showResult < 0 ) { - if ( info.flags == 0 ) // cursor hidden - { - IsVisible = visible; - break; - } - ShowCursor(false); // this only decreases an internal display counter in windows, so it might have to be called some more + break; } + info.cbSize = sizeof(CURSORINFO); // yes, it really must be set each time + gotCursorInfo = GetCursorInfo(&info); } + IsVisible = visible; } //! Returns if the cursor is currently visible. @@ -254,7 +249,7 @@ namespace irr WindowSize = size; if (size.Width!=0) InvWindowSize.Width = 1.0f / size.Width; - else + else InvWindowSize.Width = 0.f; if (size.Height!=0) @@ -263,6 +258,28 @@ namespace irr InvWindowSize.Height = 0.f; } + /** Used to notify the cursor that the window resizable settings changed. */ + void updateBorderSize(bool fullscreen, bool resizable) + { + if (!fullscreen) + { + if (resizable) + { + BorderX = GetSystemMetrics(SM_CXSIZEFRAME); + BorderY = GetSystemMetrics(SM_CYCAPTION) + GetSystemMetrics(SM_CYSIZEFRAME); + } + else + { + BorderX = GetSystemMetrics(SM_CXDLGFRAME); + BorderY = GetSystemMetrics(SM_CYCAPTION) + GetSystemMetrics(SM_CYDLGFRAME); + } + } + else + { + BorderX = BorderY = 0; + } + } + private: //! Updates the internal cursor position @@ -274,7 +291,7 @@ namespace irr DWORD xy = GetMessagePos(); p.x = GET_X_LPARAM(xy); p.y = GET_Y_LPARAM(xy); - } + } if (UseReferenceRect) { diff --git a/source/Irrlicht/CMeshCache.cpp b/source/Irrlicht/CMeshCache.cpp index fca2d5dc..b197c366 100644 --- a/source/Irrlicht/CMeshCache.cpp +++ b/source/Irrlicht/CMeshCache.cpp @@ -11,7 +11,7 @@ namespace irr namespace scene { -static const io::path emptyPath = ""; +static const io::SNamedPath emptyNamedPath; CMeshCache::~CMeshCache() @@ -108,81 +108,74 @@ IAnimatedMesh* CMeshCache::getMeshByIndex(u32 number) } -//! Returns a mesh based on its file name. -IAnimatedMesh* CMeshCache::getMeshByFilename(const io::path& filename) +//! Returns a mesh based on its name. +IAnimatedMesh* CMeshCache::getMeshByName(const io::path& name) { - MeshEntry e ( filename ); + MeshEntry e ( name ); s32 id = Meshes.binary_search(e); return (id != -1) ? Meshes[id].Mesh : 0; } - -//! Returns name of a mesh based on its index number -const io::path& CMeshCache::getMeshFilename(u32 number) const +//! Get the name of a loaded mesh, based on its index. +const io::SNamedPath& CMeshCache::getMeshName(u32 index) const { - if (number >= Meshes.size()) - return emptyPath; + if (index >= Meshes.size()) + return emptyNamedPath; - return Meshes[number].Name; + return Meshes[index].NamedPath; } - - -//! Returns the filename of a loaded mesh, if there is any. -const io::path& CMeshCache::getMeshFilename(const IAnimatedMesh* const mesh) const +//! Get the name of a loaded mesh, if there is any. +const io::SNamedPath& CMeshCache::getMeshName(const IAnimatedMesh* const mesh) const { if(!mesh) - return emptyPath; + return emptyNamedPath; for (u32 i=0; igetMesh(0) == mesh)) - return Meshes[i].Name; + return Meshes[i].NamedPath; } - return emptyPath; + return emptyNamedPath; } - - -//! Renames a loaded mesh, if possible. -bool CMeshCache::setMeshFilename(u32 index, const io::path& filename) +//! Renames a loaded mesh. +bool CMeshCache::renameMesh(u32 index, const io::path& name) { if (index >= Meshes.size()) return false; - Meshes[index].Name = filename; + Meshes[index].NamedPath.setPath(name); Meshes.sort(); return true; } - -//! Renames a loaded mesh, if possible. -bool CMeshCache::setMeshFilename(const IAnimatedMesh* const mesh, const io::path& filename) +//! Renames a loaded mesh. +bool CMeshCache::renameMesh(const IAnimatedMesh* const mesh, const io::path& name) { for (u32 i=0; igetMesh(0) == mesh) { - Meshes[i].Name = filename; + Meshes[i].NamedPath.setPath(name); Meshes.sort(); return true; } @@ -210,9 +202,9 @@ bool CMeshCache::setMeshFilename(const IMesh* const mesh, const io::path& filena //! returns if a mesh already was loaded -bool CMeshCache::isMeshLoaded(const io::path& filename) +bool CMeshCache::isMeshLoaded(const io::path& name) { - return getMeshByFilename(filename) != 0; + return getMeshByName(name) != 0; } diff --git a/source/Irrlicht/CMeshCache.h b/source/Irrlicht/CMeshCache.h index f95ccbbe..74161f29 100644 --- a/source/Irrlicht/CMeshCache.h +++ b/source/Irrlicht/CMeshCache.h @@ -60,34 +60,55 @@ namespace scene \return Returns pointer to the mesh or 0 if there is none with this number. */ virtual IAnimatedMesh* getMeshByIndex(u32 index); - //! Returns a mesh based on its file name. - /** \return Returns pointer to the mesh or 0 if there is none with this number. */ - virtual IAnimatedMesh* getMeshByFilename(const io::path& filename); + //! Returns a mesh based on its name. + /** \param name Name of the mesh. Usually a filename. + \return Pointer to the mesh or 0 if there is none with this number. */ + virtual IAnimatedMesh* getMeshByName(const io::path& name); - //! Returns name of a mesh based on its index number. + //! Get the name of a loaded mesh, based on its index. /** \param index: Index of the mesh, number between 0 and getMeshCount()-1. - Note that this is only valid until a new mesh is loaded */ - virtual const io::path& getMeshFilename(u32 index) const; + \return The name if mesh was found and has a name, else the path is empty. */ + virtual const io::SNamedPath& getMeshName(u32 index) const; - //! Returns the filename of a loaded mesh, if there is any. - /** Returns an empty path if there is none. */ - virtual const io::path& getMeshFilename(const IAnimatedMesh* const mesh) const; + //! Get the name of a loaded mesh, if there is any. + /** \param mesh Pointer to mesh to query. + \return The name if mesh was found and has a name, else the path is empty. */ + virtual const io::SNamedPath& getMeshName(const IAnimatedMesh* const mesh) const; - //! Returns the filename of a loaded mesh, if there is any. - /** Returns an empty path if there is none.*/ - virtual const io::path& getMeshFilename(const IMesh* const mesh) const; + //! Get the name of a loaded mesh, if there is any. + /** \param mesh Pointer to mesh to query. + \return The name if mesh was found and has a name, else the path is empty. */ + virtual const io::SNamedPath& getMeshName(const IMesh* const mesh) const; - //! Renames a loaded mesh, if possible. - virtual bool setMeshFilename(u32 index, const io::path& filename); + //! Renames a loaded mesh. + /** Note that renaming meshes might change the ordering of the + meshes, and so the index of the meshes as returned by + getMeshIndex() or taken by some methods will change. + \param index The index of the mesh in the cache. + \param name New name for the mesh. + \return True if mesh was renamed. */ + virtual bool renameMesh(u32 index, const io::path& name); - //! Renames a loaded mesh, if possible. - virtual bool setMeshFilename(const IAnimatedMesh* const mesh, const io::path& filename); + //! Renames a loaded mesh. + /** Note that renaming meshes might change the ordering of the + meshes, and so the index of the meshes as returned by + getMeshIndex() or taken by some methods will change. + \param mesh Mesh to be renamed. + \param name New name for the mesh. + \return True if mesh was renamed. */ + virtual bool renameMesh(const IAnimatedMesh* const mesh, const io::path& name); - //! Renames a loaded mesh, if possible. - virtual bool setMeshFilename(const IMesh* const mesh, const io::path& filename); + //! Renames a loaded mesh. + /** Note that renaming meshes might change the ordering of the + meshes, and so the index of the meshes as returned by + getMeshIndex() or taken by some methods will change. + \param mesh Mesh to be renamed. + \param name New name for the mesh. + \return True if mesh was renamed. */ + virtual bool renameMesh(const IMesh* const mesh, const io::path& name); //! returns if a mesh already was loaded - virtual bool isMeshLoaded(const io::path& filename); + virtual bool isMeshLoaded(const io::path& name); //! Clears the whole mesh cache, removing all meshes. virtual void clear(); @@ -99,17 +120,16 @@ namespace scene struct MeshEntry { - MeshEntry ( const io::path name ) - : Name ( name ) + MeshEntry ( const io::path& name ) + : NamedPath ( name ) { - Name.make_lower (); } - io::path Name; + io::SNamedPath NamedPath; IAnimatedMesh* Mesh; bool operator < (const MeshEntry& other) const { - return (Name < other.Name); + return (NamedPath < other.NamedPath); } }; diff --git a/source/Irrlicht/CMeshSceneNode.cpp b/source/Irrlicht/CMeshSceneNode.cpp index 45bcbee5..559e1c92 100644 --- a/source/Irrlicht/CMeshSceneNode.cpp +++ b/source/Irrlicht/CMeshSceneNode.cpp @@ -318,14 +318,14 @@ void CMeshSceneNode::serializeAttributes(io::IAttributes* out, io::SAttributeRea { IMeshSceneNode::serializeAttributes(out, options); - out->addString("Mesh", SceneManager->getMeshCache()->getMeshFilename(Mesh).c_str()); + out->addString("Mesh", SceneManager->getMeshCache()->getMeshName(Mesh).getPath().c_str()); out->addBool("ReadOnlyMaterials", ReadOnlyMaterials); } //! Reads attributes of the scene node. void CMeshSceneNode::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options) { - io::path oldMeshStr = SceneManager->getMeshCache()->getMeshFilename(Mesh); + io::path oldMeshStr = SceneManager->getMeshCache()->getMeshName(Mesh); io::path newMeshStr = in->getAttributeAsString("Mesh"); ReadOnlyMaterials = in->getAttributeAsBool("ReadOnlyMaterials"); diff --git a/source/Irrlicht/CNullDriver.cpp b/source/Irrlicht/CNullDriver.cpp index 1ce1db9d..3a2e72eb 100644 --- a/source/Irrlicht/CNullDriver.cpp +++ b/source/Irrlicht/CNullDriver.cpp @@ -74,7 +74,7 @@ IImageWriter* createImageWriterPPM(); CNullDriver::CNullDriver(io::IFileSystem* io, const core::dimension2d& screenSize) : FileSystem(io), MeshManipulator(0), ViewPort(0,0,0,0), ScreenSize(screenSize), PrimitivesDrawn(0), MinVertexCountForVBO(500), TextureCreationFlags(0), - AllowZWriteOnTransparent(false) + OverrideMaterial2DEnabled(false), AllowZWriteOnTransparent(false) { #ifdef _DEBUG setDebugName("CNullDriver"); @@ -150,6 +150,18 @@ CNullDriver::CNullDriver(io::IFileSystem* io, const core::dimension2d& scre memset(&ExposedData, 0, sizeof(ExposedData)); for (u32 i=0; i* sourceRect) + const SExposedVideoData& videoData, core::rect* sourceRect) { core::clearFPUException(); PrimitivesDrawn = 0; @@ -350,8 +362,8 @@ void CNullDriver::renameTexture(ITexture* texture, const io::path& newName) // is just readonly to prevent the user changing the texture name without invoking // this method, because the textures will need resorting afterwards - io::path& name = const_cast(texture->getName()); - name = newName; + io::SNamedPath& name = const_cast(texture->getName()); + name.setPath(newName); Textures.sort(); } @@ -383,6 +395,14 @@ ITexture* CNullDriver::getTexture(const io::path& filename) if (file) { + // Re-check name for actual archive names + texture = findTexture(file->getFileName()); + if (texture) + { + file->drop(); + return texture; + } + texture = loadTextureFromFile(file); file->drop(); @@ -486,12 +506,12 @@ video::ITexture* CNullDriver::findTexture(const io::path& filename) //! Creates a texture from a loaded IImage. -ITexture* CNullDriver::addTexture(const io::path& name, IImage* image) +ITexture* CNullDriver::addTexture(const io::path& name, IImage* image, void* mipmapData) { if ( 0 == name.size() || !image) return 0; - ITexture* t = createDeviceDependentTexture(image, name); + ITexture* t = createDeviceDependentTexture(image, name, mipmapData); if (t) { addTexture(t); @@ -529,7 +549,7 @@ ITexture* CNullDriver::addTexture(const core::dimension2d& size, //! returns a device dependent texture from a software surface (IImage) //! THIS METHOD HAS TO BE OVERRIDDEN BY DERIVED DRIVERS WITH OWN TEXTURES -ITexture* CNullDriver::createDeviceDependentTexture(IImage* surface, const io::path& name) +ITexture* CNullDriver::createDeviceDependentTexture(IImage* surface, const io::path& name, void* mipmapData) { return new SDummyTexture(name); } @@ -1347,20 +1367,26 @@ IImage* CNullDriver::createImage(ECOLOR_FORMAT format, const core::dimension2dgetDimension()); + imageToCopy->copyTo(tmp); + return tmp; } //! Creates a software image from part of another image. IImage* CNullDriver::createImage(IImage* imageToCopy, const core::position2d& pos, const core::dimension2d& size) { - return new CImage(imageToCopy, pos, size); + os::Printer::log("Deprecated method, please create an empty image instead and use copyTo().", ELL_WARNING); + CImage* tmp = new CImage(imageToCopy->getColorFormat(), imageToCopy->getDimension()); + imageToCopy->copyTo(tmp, core::position2di(0,0), core::recti(pos,size)); + return tmp; } @@ -1775,12 +1801,11 @@ const char* CNullDriver::getMaterialRendererName(u32 idx) const //! Returns pointer to the IGPUProgrammingServices interface. IGPUProgrammingServices* CNullDriver::getGPUProgrammingServices() { - return 0; + return this; } -//! Adds a new material renderer to the VideoDriver, based on a high level shading -//! language. Currently only HLSL in D3D9 is supported. +//! Adds a new material renderer to the VideoDriver, based on a high level shading language. s32 CNullDriver::addHighLevelShaderMaterial( const c8* vertexShaderProgram, const c8* vertexShaderEntryPointName, @@ -1788,6 +1813,11 @@ s32 CNullDriver::addHighLevelShaderMaterial( const c8* pixelShaderProgram, const c8* pixelShaderEntryPointName, E_PIXEL_SHADER_TYPE psCompileTarget, + const c8* geometryShaderProgram, + const c8* geometryShaderEntryPointName, + E_GEOMETRY_SHADER_TYPE gsCompileTarget, + scene::E_PRIMITIVE_TYPE inType, scene::E_PRIMITIVE_TYPE outType, + u32 verticesOut, IShaderConstantSetCallBack* callback, E_MATERIAL_TYPE baseMaterial, s32 userData) @@ -1800,46 +1830,60 @@ s32 CNullDriver::addHighLevelShaderMaterial( //! Like IGPUProgrammingServices::addShaderMaterial() (look there for a detailed description), //! but tries to load the programs from files. s32 CNullDriver::addHighLevelShaderMaterialFromFiles( - const io::path& vertexShaderProgram, - const c8* vertexShaderEntryPointName, - E_VERTEX_SHADER_TYPE vsCompileTarget, - const io::path& pixelShaderProgram, - const c8* pixelShaderEntryPointName, - E_PIXEL_SHADER_TYPE psCompileTarget, - IShaderConstantSetCallBack* callback, - E_MATERIAL_TYPE baseMaterial, - s32 userData) + const io::path& vertexShaderProgramFileName, + const c8* vertexShaderEntryPointName, + E_VERTEX_SHADER_TYPE vsCompileTarget, + const io::path& pixelShaderProgramFileName, + const c8* pixelShaderEntryPointName, + E_PIXEL_SHADER_TYPE psCompileTarget, + const io::path& geometryShaderProgramFileName, + const c8* geometryShaderEntryPointName, + E_GEOMETRY_SHADER_TYPE gsCompileTarget, + scene::E_PRIMITIVE_TYPE inType, scene::E_PRIMITIVE_TYPE outType, + u32 verticesOut, + IShaderConstantSetCallBack* callback, + E_MATERIAL_TYPE baseMaterial, + s32 userData) { io::IReadFile* vsfile = 0; io::IReadFile* psfile = 0; + io::IReadFile* gsfile = 0; - if (vertexShaderProgram.size() ) + if (vertexShaderProgramFileName.size() ) { - vsfile = FileSystem->createAndOpenFile(vertexShaderProgram); + vsfile = FileSystem->createAndOpenFile(vertexShaderProgramFileName); if (!vsfile) { os::Printer::log("Could not open vertex shader program file", - vertexShaderProgram, ELL_WARNING); - return -1; + vertexShaderProgramFileName, ELL_WARNING); } } - if (pixelShaderProgram.size() ) + if (pixelShaderProgramFileName.size() ) { - psfile = FileSystem->createAndOpenFile(pixelShaderProgram); + psfile = FileSystem->createAndOpenFile(pixelShaderProgramFileName); if (!psfile) { os::Printer::log("Could not open pixel shader program file", - pixelShaderProgram, ELL_WARNING); - if (vsfile) - vsfile->drop(); - return -1; + pixelShaderProgramFileName, ELL_WARNING); + } + } + + if (geometryShaderProgramFileName.size() ) + { + gsfile = FileSystem->createAndOpenFile(geometryShaderProgramFileName); + if (!gsfile) + { + os::Printer::log("Could not open geometry shader program file", + geometryShaderProgramFileName, ELL_WARNING); } } s32 result = addHighLevelShaderMaterialFromFiles( vsfile, vertexShaderEntryPointName, vsCompileTarget, psfile, pixelShaderEntryPointName, psCompileTarget, + gsfile, geometryShaderEntryPointName, gsCompileTarget, + inType, outType, verticesOut, callback, baseMaterial, userData); if (psfile) @@ -1848,6 +1892,9 @@ s32 CNullDriver::addHighLevelShaderMaterialFromFiles( if (vsfile) vsfile->drop(); + if (gsfile) + gsfile->drop(); + return result; } @@ -1855,18 +1902,24 @@ s32 CNullDriver::addHighLevelShaderMaterialFromFiles( //! Like IGPUProgrammingServices::addShaderMaterial() (look there for a detailed description), //! but tries to load the programs from files. s32 CNullDriver::addHighLevelShaderMaterialFromFiles( - io::IReadFile* vertexShaderProgram, - const c8* vertexShaderEntryPointName, - E_VERTEX_SHADER_TYPE vsCompileTarget, - io::IReadFile* pixelShaderProgram, - const c8* pixelShaderEntryPointName, - E_PIXEL_SHADER_TYPE psCompileTarget, - IShaderConstantSetCallBack* callback, - E_MATERIAL_TYPE baseMaterial, - s32 userData) + io::IReadFile* vertexShaderProgram, + const c8* vertexShaderEntryPointName, + E_VERTEX_SHADER_TYPE vsCompileTarget, + io::IReadFile* pixelShaderProgram, + const c8* pixelShaderEntryPointName, + E_PIXEL_SHADER_TYPE psCompileTarget, + io::IReadFile* geometryShaderProgram, + const c8* geometryShaderEntryPointName, + E_GEOMETRY_SHADER_TYPE gsCompileTarget, + scene::E_PRIMITIVE_TYPE inType, scene::E_PRIMITIVE_TYPE outType, + u32 verticesOut, + IShaderConstantSetCallBack* callback, + E_MATERIAL_TYPE baseMaterial, + s32 userData) { c8* vs = 0; c8* ps = 0; + c8* gs = 0; if (vertexShaderProgram) { @@ -1893,13 +1946,31 @@ s32 CNullDriver::addHighLevelShaderMaterialFromFiles( } } + if (geometryShaderProgram) + { + const long size = geometryShaderProgram->getSize(); + if (size) + { + // if both handles are the same we must reset the file + if ((geometryShaderProgram==vertexShaderProgram) || + (geometryShaderProgram==pixelShaderProgram)) + geometryShaderProgram->seek(0); + gs = new c8[size+1]; + geometryShaderProgram->read(gs, size); + gs[size] = 0; + } + } + s32 result = this->addHighLevelShaderMaterial( vs, vertexShaderEntryPointName, vsCompileTarget, ps, pixelShaderEntryPointName, psCompileTarget, + gs, geometryShaderEntryPointName, gsCompileTarget, + inType, outType, verticesOut, callback, baseMaterial, userData); delete [] vs; delete [] ps; + delete [] gs; return result; } @@ -2102,6 +2173,20 @@ SOverrideMaterial& CNullDriver::getOverrideMaterial() } +//! Get the 2d override material for altering its values +SMaterial& CNullDriver::getMaterial2D() +{ + return OverrideMaterial2D; +} + + +//! Enable the 2d override material +void CNullDriver::enableMaterial2D(bool enable) +{ + OverrideMaterial2DEnabled=enable; +} + + core::dimension2du CNullDriver::getMaxTextureSize() const { return core::dimension2du(0x10000,0x10000); // maybe large enough diff --git a/source/Irrlicht/CNullDriver.h b/source/Irrlicht/CNullDriver.h index 72dd47c2..de2bcd42 100644 --- a/source/Irrlicht/CNullDriver.h +++ b/source/Irrlicht/CNullDriver.h @@ -43,7 +43,8 @@ namespace video virtual ~CNullDriver(); virtual bool beginScene(bool backBuffer=true, bool zBuffer=true, - SColor color=SColor(255,0,0,0), void* windowId=0, + SColor color=SColor(255,0,0,0), + const SExposedVideoData& videoData=SExposedVideoData(), core::rect* sourceRect=0); virtual bool endScene(); @@ -478,6 +479,12 @@ namespace video const c8* pixelShaderProgram = 0, const c8* pixelShaderEntryPointName = 0, E_PIXEL_SHADER_TYPE psCompileTarget = EPST_PS_1_1, + const c8* geometryShaderProgram = 0, + const c8* geometryShaderEntryPointName = "main", + E_GEOMETRY_SHADER_TYPE gsCompileTarget = EGST_GS_4_0, + scene::E_PRIMITIVE_TYPE inType = scene::EPT_TRIANGLES, + scene::E_PRIMITIVE_TYPE outType = scene::EPT_TRIANGLE_STRIP, + u32 verticesOut = 0, IShaderConstantSetCallBack* callback = 0, E_MATERIAL_TYPE baseMaterial = video::EMT_SOLID, s32 userData=0); @@ -491,6 +498,12 @@ namespace video const io::path& pixelShaderProgramFile = "", const c8* pixelShaderEntryPointName = "main", E_PIXEL_SHADER_TYPE psCompileTarget = EPST_PS_1_1, + const io::path& geometryShaderProgramFileName="", + const c8* geometryShaderEntryPointName = "main", + E_GEOMETRY_SHADER_TYPE gsCompileTarget = EGST_GS_4_0, + scene::E_PRIMITIVE_TYPE inType = scene::EPT_TRIANGLES, + scene::E_PRIMITIVE_TYPE outType = scene::EPT_TRIANGLE_STRIP, + u32 verticesOut = 0, IShaderConstantSetCallBack* callback = 0, E_MATERIAL_TYPE baseMaterial = video::EMT_SOLID, s32 userData=0); @@ -504,6 +517,12 @@ namespace video io::IReadFile* pixelShaderProgram = 0, const c8* pixelShaderEntryPointName = "main", E_PIXEL_SHADER_TYPE psCompileTarget = EPST_PS_1_1, + io::IReadFile* geometryShaderProgram= 0, + const c8* geometryShaderEntryPointName = "main", + E_GEOMETRY_SHADER_TYPE gsCompileTarget = EGST_GS_4_0, + scene::E_PRIMITIVE_TYPE inType = scene::EPT_TRIANGLES, + scene::E_PRIMITIVE_TYPE outType = scene::EPT_TRIANGLE_STRIP, + u32 verticesOut = 0, IShaderConstantSetCallBack* callback = 0, E_MATERIAL_TYPE baseMaterial = video::EMT_SOLID, s32 userData=0); @@ -561,6 +580,12 @@ namespace video meshbuffer being rendered. */ virtual SOverrideMaterial& getOverrideMaterial(); + //! Get the 2d override material for altering its values + virtual SMaterial& getMaterial2D(); + + //! Enable the 2d override material + virtual void enableMaterial2D(bool enable=true); + //! Only used by the engine internally. virtual void setAllowZWriteOnTransparent(bool flag) { AllowZWriteOnTransparent=flag; } @@ -585,11 +610,11 @@ namespace video void addTexture(video::ITexture* surface); //! Creates a texture from a loaded IImage. - virtual ITexture* addTexture(const io::path& name, IImage* image); + virtual ITexture* addTexture(const io::path& name, IImage* image, void* mipmapData=0); //! returns a device dependent texture from a software surface (IImage) //! THIS METHOD HAS TO BE OVERRIDDEN BY DERIVED DRIVERS WITH OWN TEXTURES - virtual video::ITexture* createDeviceDependentTexture(IImage* surface, const io::path& name); + virtual video::ITexture* createDeviceDependentTexture(IImage* surface, const io::path& name, void* mipmapData=0); //! checks triangle count and print warning if wrong bool checkPrimitiveCount(u32 prmcnt) const; @@ -640,19 +665,17 @@ namespace video { SDummyTexture(const io::path& name) : ITexture(name), size(0,0) {}; - virtual void* lock(bool readOnly = false) { return 0; }; + virtual void* lock(bool readOnly = false, u32 mipmapLevel=0) { return 0; }; virtual void unlock(){} virtual const core::dimension2d& getOriginalSize() const { return size; } virtual const core::dimension2d& getSize() const { return size; } virtual E_DRIVER_TYPE getDriverType() const { return video::EDT_NULL; } virtual ECOLOR_FORMAT getColorFormat() const { return video::ECF_A1R5G5B5; }; virtual u32 getPitch() const { return 0; } - virtual void regenerateMipMapLevels() {}; + virtual void regenerateMipMapLevels(void* mipmapData=0) {}; core::dimension2d size; }; - - core::array Textures; core::array SurfaceLoader; core::array SurfaceWriter; @@ -685,6 +708,9 @@ namespace video SExposedVideoData ExposedData; SOverrideMaterial OverrideMaterial; + SMaterial OverrideMaterial2D; + SMaterial InitMaterial2D; + bool OverrideMaterial2DEnabled; E_FOG_TYPE FogType; bool PixelFog; @@ -699,6 +725,3 @@ namespace video #endif - - - diff --git a/source/Irrlicht/COBJMeshFileLoader.cpp b/source/Irrlicht/COBJMeshFileLoader.cpp index b98aaf30..54ca465e 100644 --- a/source/Irrlicht/COBJMeshFileLoader.cpp +++ b/source/Irrlicht/COBJMeshFileLoader.cpp @@ -426,7 +426,15 @@ const c8* COBJMeshFileLoader::readTextures(const c8* bufPtr, const c8* const buf bool newTexture=false; if (texname.size()) { - if (FileSystem->existFile(texname)) + 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); diff --git a/source/Irrlicht/COBJMeshWriter.cpp b/source/Irrlicht/COBJMeshWriter.cpp index 3df96f95..607c3d3b 100644 --- a/source/Irrlicht/COBJMeshWriter.cpp +++ b/source/Irrlicht/COBJMeshWriter.cpp @@ -2,7 +2,7 @@ // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h -#include "IrrCompileConfig.h" +#include "IrrCompileConfig.h" #ifdef _IRR_COMPILE_WITH_OBJ_WRITER_ @@ -64,14 +64,14 @@ bool COBJMeshWriter::writeMesh(io::IWriteFile* file, scene::IMesh* mesh, s32 fla // write OBJ MESH header - const core::stringc name(FileSystem->getFileBasename(SceneManager->getMeshCache()->getMeshFilename(mesh), false)+".mtl"); + 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 mat; u32 allVertexCount=1; // count vertices over the whole file @@ -192,7 +192,7 @@ bool COBJMeshWriter::writeMesh(io::IWriteFile* file, scene::IMesh* mesh, s32 fla if (mat[i]->getTexture(0)) { file->write("map_Kd ", 7); - file->write(mat[i]->getTexture(0)->getName().c_str(), mat[i]->getTexture(0)->getName().size()); + 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); diff --git a/source/Irrlicht/COCTLoader.h b/source/Irrlicht/COCTLoader.h index d5c38033..5620e7df 100644 --- a/source/Irrlicht/COCTLoader.h +++ b/source/Irrlicht/COCTLoader.h @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2009 Nikolaus Gebhardt +// Copyright (C) 2002-2009 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h // diff --git a/source/Irrlicht/COSOperator.cpp b/source/Irrlicht/COSOperator.cpp index 9fb1d4d0..33ea328f 100644 --- a/source/Irrlicht/COSOperator.cpp +++ b/source/Irrlicht/COSOperator.cpp @@ -5,17 +5,13 @@ #include "COSOperator.h" #ifdef _IRR_WINDOWS_API_ -#ifdef _IRR_XBOX_PLATFORM_ -#else +#ifndef _IRR_XBOX_PLATFORM_ #include #endif #else #include #include -#ifdef _IRR_COMPILE_WITH_OSX_DEVICE_ -#include "MacOSX/OSXClipboard.h" -#endif -#ifdef _IRR_OSX_PLATFORM_ +#ifndef _IRR_SOLARIS_PLATFORM_ #include #include #endif @@ -24,6 +20,9 @@ #if defined(_IRR_COMPILE_WITH_X11_DEVICE_) #include "CIrrDeviceLinux.h" #endif +#ifdef _IRR_COMPILE_WITH_OSX_DEVICE_ +#include "MacOSX/OSXClipboard.h" +#endif namespace irr { @@ -184,7 +183,7 @@ bool COSOperator::getSystemMemory(u32* Total, u32* Avail) const _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; return true; -#elif defined(_IRR_POSIX_API_) +#elif defined(_IRR_POSIX_API_) && !defined(__FreeBSD__) #if defined(_SC_PHYS_PAGES) && defined(_SC_AVPHYS_PAGES) long ps = sysconf(_SC_PAGESIZE); long pp = sysconf(_SC_PHYS_PAGES); diff --git a/source/Irrlicht/COctTreeSceneNode.cpp b/source/Irrlicht/COctreeSceneNode.cpp similarity index 67% rename from source/Irrlicht/COctTreeSceneNode.cpp rename to source/Irrlicht/COctreeSceneNode.cpp index e77800b5..fbf4cfd3 100644 --- a/source/Irrlicht/COctTreeSceneNode.cpp +++ b/source/Irrlicht/COctreeSceneNode.cpp @@ -2,8 +2,8 @@ // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h -#include "COctTreeSceneNode.h" -#include "OctTree.h" +#include "COctreeSceneNode.h" +#include "Octree.h" #include "ISceneManager.h" #include "IVideoDriver.h" #include "ICameraSceneNode.h" @@ -20,27 +20,28 @@ namespace scene //! constructor -COctTreeSceneNode::COctTreeSceneNode(ISceneNode* parent, ISceneManager* mgr, +COctreeSceneNode::COctreeSceneNode(ISceneNode* parent, ISceneManager* mgr, s32 id, s32 minimalPolysPerNode) -: IMeshSceneNode(parent, mgr, id), StdOctTree(0), LightMapOctTree(0), TangentsOctTree(0), - MinimalPolysPerNode(minimalPolysPerNode), Mesh(0) + : IMeshSceneNode(parent, mgr, id), StdOctree(0), LightMapOctree(0), + TangentsOctree(0), VertexType((video::E_VERTEX_TYPE)-1), + MinimalPolysPerNode(minimalPolysPerNode), Mesh(0), + UseVBOs(OCTREE_USE_HARDWARE), UseVisibilityAndVBOs(OCTREE_USE_VISIBILITY), + BoxBased(OCTREE_BOX_BASED) { #ifdef _DEBUG - setDebugName("COctTreeSceneNode"); + setDebugName("COctreeSceneNode"); #endif - - vertexType = (video::E_VERTEX_TYPE)-1; } //! destructor -COctTreeSceneNode::~COctTreeSceneNode() +COctreeSceneNode::~COctreeSceneNode() { deleteTree(); } -void COctTreeSceneNode::OnRegisterSceneNode() +void COctreeSceneNode::OnRegisterSceneNode() { if (IsVisible) { @@ -84,11 +85,11 @@ void COctTreeSceneNode::OnRegisterSceneNode() //! renders the node. -void COctTreeSceneNode::render() +void COctreeSceneNode::render() { video::IVideoDriver* driver = SceneManager->getVideoDriver(); - if (vertexType == -1 || !driver) + if (VertexType == -1 || !driver) return; ICameraSceneNode* camera = SceneManager->getActiveCamera(); @@ -110,21 +111,18 @@ void COctTreeSceneNode::render() frust.transform(invTrans); } -#if defined ( OCTTREE_BOX_BASED ) const core::aabbox3d &box = frust.getBoundingBox(); -#endif - switch(vertexType) + switch (VertexType) { case video::EVT_STANDARD: { -#if defined ( OCTTREE_BOX_BASED ) - StdOctTree->calculatePolys(box); -#else - StdOctTree->calculatePolys(frust); -#endif + if (BoxBased) + StdOctree->calculatePolys(box); + else + StdOctree->calculatePolys(frust); - const OctTree::SIndexData* d = StdOctTree->getIndexData(); + const Octree::SIndexData* d = StdOctree->getIndexData(); for (u32 i=0; isetMaterial(m); if ( DebugDataVisible & scene::EDS_BBOX_BUFFERS ) { - StdOctTree->getBoundingBoxes(box, boxes); + StdOctree->getBoundingBoxes(box, boxes); for (u32 b=0; b!=boxes.size(); ++b) driver->draw3DBox(*boxes[b]); } @@ -167,12 +165,12 @@ void COctTreeSceneNode::render() break; case video::EVT_2TCOORDS: { -#if defined ( OCTTREE_BOX_BASED ) - LightMapOctTree->calculatePolys(box); -#else - LightMapOctTree->calculatePolys(frust); -#endif - const OctTree::SIndexData* d = LightMapOctTree->getIndexData(); + if (BoxBased) + LightMapOctree->calculatePolys(box); + else + LightMapOctree->calculatePolys(frust); + + const Octree::SIndexData* d = LightMapOctree->getIndexData(); for (u32 i=0; isetMaterial(Materials[i]); -#if defined (OCTTREE_USE_HARDWARE) - driver->drawMeshBuffer ( &LightMapMeshes[i] ); - -#else - driver->drawIndexedTriangleList( - &LightMapMeshes[i].Vertices[0], LightMapMeshes[i].Vertices.size(), - d[i].Indices, d[i].CurrentSize / 3); -#endif + if (UseVBOs) + { + if (UseVisibilityAndVBOs) + { + u16* oldPointer = LightMapMeshes[i].Indices.pointer(); + const u32 oldSize = LightMapMeshes[i].Indices.size(); + LightMapMeshes[i].Indices.set_free_when_destroyed(false); + LightMapMeshes[i].Indices.set_pointer(d[i].Indices, d[i].CurrentSize, false, false); + LightMapMeshes[i].setDirty(scene::EBT_INDEX); + driver->drawMeshBuffer ( &LightMapMeshes[i] ); + LightMapMeshes[i].Indices.set_pointer(oldPointer, oldSize); + LightMapMeshes[i].setDirty(scene::EBT_INDEX); + } + else + driver->drawMeshBuffer ( &LightMapMeshes[i] ); + } + else + driver->drawIndexedTriangleList( + &LightMapMeshes[i].Vertices[0], + LightMapMeshes[i].Vertices.size(), + d[i].Indices, d[i].CurrentSize / 3); } } @@ -208,7 +219,7 @@ void COctTreeSceneNode::render() driver->setMaterial(m); if ( DebugDataVisible & scene::EDS_BBOX_BUFFERS ) { - LightMapOctTree->getBoundingBoxes(box, boxes); + LightMapOctree->getBoundingBoxes(box, boxes); for (u32 b=0; bdraw3DBox(*boxes[b]); } @@ -220,13 +231,12 @@ void COctTreeSceneNode::render() break; case video::EVT_TANGENTS: { -#if defined ( OCTTREE_BOX_BASED ) - TangentsOctTree->calculatePolys(box); -#else - TangentsOctTree->calculatePolys(frust); -#endif + if (BoxBased) + TangentsOctree->calculatePolys(box); + else + TangentsOctree->calculatePolys(frust); - const OctTree::SIndexData* d = TangentsOctTree->getIndexData(); + const Octree::SIndexData* d = TangentsOctree->getIndexData(); for (u32 i=0; isetMaterial(m); if ( DebugDataVisible & scene::EDS_BBOX_BUFFERS ) { - TangentsOctTree->getBoundingBoxes(box, boxes); + TangentsOctree->getBoundingBoxes(box, boxes); for (u32 b=0; bdraw3DBox(*boxes[b]); } @@ -272,19 +282,19 @@ void COctTreeSceneNode::render() //! returns the axis aligned bounding box of this node -const core::aabbox3d& COctTreeSceneNode::getBoundingBox() const +const core::aabbox3d& COctreeSceneNode::getBoundingBox() const { return Box; } //! creates the tree -bool COctTreeSceneNode::createTree(IMesh* mesh) +bool COctreeSceneNode::createTree(IMesh* mesh) { if (!mesh) return false; - MeshName = SceneManager->getMeshCache()->getMeshFilename( mesh ); + MeshName = SceneManager->getMeshCache()->getMeshName(mesh); mesh->grab(); deleteTree(); @@ -301,9 +311,9 @@ bool COctTreeSceneNode::createTree(IMesh* mesh) if (mesh->getMeshBufferCount()) { - vertexType = mesh->getMeshBuffer(0)->getVertexType(); + VertexType = mesh->getMeshBuffer(0)->getVertexType(); - switch(vertexType) + switch(VertexType) { case video::EVT_STANDARD: { @@ -315,8 +325,8 @@ bool COctTreeSceneNode::createTree(IMesh* mesh) { Materials.push_back(b->getMaterial()); - StdMeshes.push_back(OctTree::SMeshChunk()); - OctTree::SMeshChunk &nchunk = StdMeshes.getLast(); + StdMeshes.push_back(Octree::SMeshChunk()); + Octree::SMeshChunk &nchunk = StdMeshes.getLast(); nchunk.MaterialId = Materials.size() - 1; u32 v; @@ -332,8 +342,8 @@ bool COctTreeSceneNode::createTree(IMesh* mesh) } } - StdOctTree = new OctTree(StdMeshes, MinimalPolysPerNode); - nodeCount = StdOctTree->getNodeCount(); + StdOctree = new Octree(StdMeshes, MinimalPolysPerNode); + nodeCount = StdOctree->getNodeCount(); } break; case video::EVT_2TCOORDS: @@ -358,13 +368,17 @@ bool COctTreeSceneNode::createTree(IMesh* mesh) if (b->getVertexCount() && b->getIndexCount()) { Materials.push_back(b->getMaterial()); - LightMapMeshes.push_back(OctTree::SMeshChunk()); - OctTree::SMeshChunk& nchunk = LightMapMeshes.getLast(); + LightMapMeshes.push_back(Octree::SMeshChunk()); + Octree::SMeshChunk& nchunk = LightMapMeshes.getLast(); nchunk.MaterialId = Materials.size() - 1; -#if defined (OCTTREE_USE_HARDWARE) - nchunk.setHardwareMappingHint ( b->getHardwareMappingHint_Vertex() ); -#endif + if (UseVisibilityAndVBOs) + { + nchunk.setHardwareMappingHint(scene::EHM_STATIC, scene::EBT_VERTEX); + nchunk.setHardwareMappingHint(scene::EHM_DYNAMIC, scene::EBT_INDEX); + } + else + nchunk.setHardwareMappingHint(scene::EHM_STATIC); u32 v; nchunk.Vertices.reallocate(b->getVertexCount()); @@ -378,8 +392,8 @@ bool COctTreeSceneNode::createTree(IMesh* mesh) } } - LightMapOctTree = new OctTree(LightMapMeshes, MinimalPolysPerNode); - nodeCount = LightMapOctTree->getNodeCount(); + LightMapOctree = new Octree(LightMapMeshes, MinimalPolysPerNode); + nodeCount = LightMapOctree->getNodeCount(); } break; case video::EVT_TANGENTS: @@ -391,8 +405,8 @@ bool COctTreeSceneNode::createTree(IMesh* mesh) if (b->getVertexCount() && b->getIndexCount()) { Materials.push_back(b->getMaterial()); - TangentsMeshes.push_back(OctTree::SMeshChunk()); - OctTree::SMeshChunk& nchunk = TangentsMeshes.getLast(); + TangentsMeshes.push_back(Octree::SMeshChunk()); + Octree::SMeshChunk& nchunk = TangentsMeshes.getLast(); nchunk.MaterialId = Materials.size() - 1; u32 v; @@ -407,8 +421,8 @@ bool COctTreeSceneNode::createTree(IMesh* mesh) } } - TangentsOctTree = new OctTree(TangentsMeshes, MinimalPolysPerNode); - nodeCount = TangentsOctTree->getNodeCount(); + TangentsOctree = new Octree(TangentsMeshes, MinimalPolysPerNode); + nodeCount = TangentsOctree->getNodeCount(); } break; } @@ -416,7 +430,7 @@ bool COctTreeSceneNode::createTree(IMesh* mesh) u32 endTime = os::Timer::getRealTime(); c8 tmp[255]; - sprintf(tmp, "Needed %ums to create OctTree SceneNode.(%u nodes, %u polys)", + sprintf(tmp, "Needed %ums to create Octree SceneNode.(%u nodes, %u polys)", endTime - beginTime, nodeCount, polyCount/3); os::Printer::log(tmp, ELL_INFORMATION); @@ -429,7 +443,7 @@ bool COctTreeSceneNode::createTree(IMesh* mesh) //! This function is needed for inserting the node into the scene hirachy on a //! optimal position for minimizing renderstate changes, but can also be used //! to directly modify the material of a scene node. -video::SMaterial& COctTreeSceneNode::getMaterial(u32 i) +video::SMaterial& COctreeSceneNode::getMaterial(u32 i) { if ( i >= Materials.size() ) return ISceneNode::getMaterial(i); @@ -439,14 +453,14 @@ video::SMaterial& COctTreeSceneNode::getMaterial(u32 i) //! returns amount of materials used by this scene node. -u32 COctTreeSceneNode::getMaterialCount() const +u32 COctreeSceneNode::getMaterialCount() const { return Materials.size(); } //! Writes attributes of the scene node. -void COctTreeSceneNode::serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options) const +void COctreeSceneNode::serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options) const { ISceneNode::serializeAttributes(out, options); @@ -456,7 +470,7 @@ void COctTreeSceneNode::serializeAttributes(io::IAttributes* out, io::SAttribute //! Reads attributes of the scene node. -void COctTreeSceneNode::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options) +void COctreeSceneNode::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options) { const s32 oldMinimal = MinimalPolysPerNode; @@ -483,18 +497,18 @@ void COctTreeSceneNode::deserializeAttributes(io::IAttributes* in, io::SAttribut } -void COctTreeSceneNode::deleteTree() +void COctreeSceneNode::deleteTree() { - delete StdOctTree; - StdOctTree = 0; + delete StdOctree; + StdOctree = 0; StdMeshes.clear(); - delete LightMapOctTree; - LightMapOctTree = 0; + delete LightMapOctree; + LightMapOctree = 0; LightMapMeshes.clear(); - delete TangentsOctTree; - TangentsOctTree = 0; + delete TangentsOctree; + TangentsOctree = 0; TangentsMeshes.clear(); Materials.clear(); @@ -503,22 +517,22 @@ void COctTreeSceneNode::deleteTree() Mesh->drop(); } -void COctTreeSceneNode::setMesh(IMesh* mesh) +void COctreeSceneNode::setMesh(IMesh* mesh) { createTree(mesh); } -IMesh* COctTreeSceneNode::getMesh(void) +IMesh* COctreeSceneNode::getMesh(void) { return Mesh; } -void COctTreeSceneNode::setReadOnlyMaterials(bool readonly) +void COctreeSceneNode::setReadOnlyMaterials(bool readonly) { // Do nothing } -bool COctTreeSceneNode::isReadOnlyMaterials() const +bool COctreeSceneNode::isReadOnlyMaterials() const { return false; } diff --git a/source/Irrlicht/COctTreeSceneNode.h b/source/Irrlicht/COctreeSceneNode.h similarity index 67% rename from source/Irrlicht/COctTreeSceneNode.h rename to source/Irrlicht/COctreeSceneNode.h index 076a617e..8b64d2a1 100644 --- a/source/Irrlicht/COctTreeSceneNode.h +++ b/source/Irrlicht/COctreeSceneNode.h @@ -2,27 +2,27 @@ // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h -#ifndef __C_OCT_TREE_SCENE_NODE_H_INCLUDED__ -#define __C_OCT_TREE_SCENE_NODE_H_INCLUDED__ +#ifndef __C_OCTREE_SCENE_NODE_H_INCLUDED__ +#define __C_OCTREE_SCENE_NODE_H_INCLUDED__ #include "IMeshSceneNode.h" -#include "OctTree.h" +#include "Octree.h" namespace irr { namespace scene { //! implementation of the IBspTreeSceneNode - class COctTreeSceneNode : public IMeshSceneNode + class COctreeSceneNode : public IMeshSceneNode { public: //! constructor - COctTreeSceneNode(ISceneNode* parent, ISceneManager* mgr, s32 id, + COctreeSceneNode(ISceneNode* parent, ISceneManager* mgr, s32 id, s32 minimalPolysPerNode=512); //! destructor - virtual ~COctTreeSceneNode(); + virtual ~COctreeSceneNode(); virtual void OnRegisterSceneNode(); @@ -41,7 +41,7 @@ namespace scene //! optimal position for minimizing renderstate changes, but can also be used //! to directly modify the material of a scene node. virtual video::SMaterial& getMaterial(u32 i); - + //! returns amount of materials used by this scene node. virtual u32 getMaterialCount() const; @@ -52,7 +52,7 @@ namespace scene virtual void deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options=0); //! Returns type of the scene node - virtual ESCENE_NODE_TYPE getType() const { return ESNT_OCT_TREE; } + virtual ESCENE_NODE_TYPE getType() const { return ESNT_OCTREE; } //! Sets a new mesh to display virtual void setMesh(IMesh* mesh); @@ -72,16 +72,16 @@ namespace scene core::aabbox3d Box; - OctTree* StdOctTree; - core::array< OctTree::SMeshChunk > StdMeshes; + Octree* StdOctree; + core::array< Octree::SMeshChunk > StdMeshes; - OctTree* LightMapOctTree; - core::array< OctTree::SMeshChunk > LightMapMeshes; + Octree* LightMapOctree; + core::array< Octree::SMeshChunk > LightMapMeshes; - OctTree* TangentsOctTree; - core::array< OctTree::SMeshChunk > TangentsMeshes; + Octree* TangentsOctree; + core::array< Octree::SMeshChunk > TangentsMeshes; - video::E_VERTEX_TYPE vertexType; + video::E_VERTEX_TYPE VertexType; core::array< video::SMaterial > Materials; core::stringc MeshName; @@ -89,6 +89,12 @@ namespace scene s32 PassCount; IMesh * Mesh; + //! use VBOs for rendering where possible + bool UseVBOs; + //! use visibility information together with VBOs + bool UseVisibilityAndVBOs; + //! use bounding box or frustum for calculate polys + bool BoxBased; }; } // end namespace scene diff --git a/source/Irrlicht/COctTreeTriangleSelector.cpp b/source/Irrlicht/COctreeTriangleSelector.cpp similarity index 78% rename from source/Irrlicht/COctTreeTriangleSelector.cpp rename to source/Irrlicht/COctreeTriangleSelector.cpp index 342a9daa..fcc0c0bd 100644 --- a/source/Irrlicht/COctTreeTriangleSelector.cpp +++ b/source/Irrlicht/COctreeTriangleSelector.cpp @@ -2,7 +2,7 @@ // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h -#include "COctTreeTriangleSelector.h" +#include "COctreeTriangleSelector.h" #include "ISceneNode.h" #include "os.h" @@ -13,26 +13,26 @@ namespace scene { //! constructor -COctTreeTriangleSelector::COctTreeTriangleSelector(const IMesh* mesh, +COctreeTriangleSelector::COctreeTriangleSelector(const IMesh* mesh, const ISceneNode* node, s32 minimalPolysPerNode) : CTriangleSelector(mesh, node), Root(0), NodeCount(0), MinimalPolysPerNode(minimalPolysPerNode) { #ifdef _DEBUG - setDebugName("COctTreeTriangleSelector"); + setDebugName("COctreeTriangleSelector"); #endif - + if (!Triangles.empty()) { const u32 start = os::Timer::getRealTime(); - // create the triangle octtree - Root = new SOctTreeNode(); + // create the triangle octree + Root = new SOctreeNode(); Root->Triangles = Triangles; - constructOctTree(Root); + constructOctree(Root); c8 tmp[256]; - sprintf(tmp, "Needed %ums to create OctTreeTriangleSelector.(%d nodes, %u polys)", + sprintf(tmp, "Needed %ums to create OctreeTriangleSelector.(%d nodes, %u polys)", os::Timer::getRealTime() - start, NodeCount, Triangles.size()); os::Printer::log(tmp, ELL_INFORMATION); } @@ -40,13 +40,13 @@ COctTreeTriangleSelector::COctTreeTriangleSelector(const IMesh* mesh, //! destructor -COctTreeTriangleSelector::~COctTreeTriangleSelector() +COctreeTriangleSelector::~COctreeTriangleSelector() { delete Root; } -void COctTreeTriangleSelector::constructOctTree(SOctTreeNode* node) +void COctreeTriangleSelector::constructOctree(SOctreeNode* node) { ++NodeCount; @@ -75,7 +75,7 @@ void COctTreeTriangleSelector::constructOctTree(SOctTreeNode* node) { box.reset(middle); box.addInternalPoint(edges[ch]); - node->Child[ch] = new SOctTreeNode(); + node->Child[ch] = new SOctreeNode(); for (s32 i=0; i<(s32)node->Triangles.size(); ++i) { @@ -102,13 +102,13 @@ void COctTreeTriangleSelector::constructOctTree(SOctTreeNode* node) node->Child[ch] = 0; } else - constructOctTree(node->Child[ch]); + constructOctree(node->Child[ch]); } } //! Gets all triangles which lie within a specific bounding box. -void COctTreeTriangleSelector::getTriangles(core::triangle3df* triangles, +void COctreeTriangleSelector::getTriangles(core::triangle3df* triangles, s32 arraySize, s32& outTriangleCount, const core::aabbox3d& box, const core::matrix4* transform) const @@ -138,15 +138,15 @@ void COctTreeTriangleSelector::getTriangles(core::triangle3df* triangles, s32 trianglesWritten = 0; if (Root) - getTrianglesFromOctTree(Root, trianglesWritten, + getTrianglesFromOctree(Root, trianglesWritten, arraySize, invbox, &mat, triangles); outTriangleCount = trianglesWritten; } -void COctTreeTriangleSelector::getTrianglesFromOctTree( - SOctTreeNode* node, s32& trianglesWritten, +void COctreeTriangleSelector::getTrianglesFromOctree( + SOctreeNode* node, s32& trianglesWritten, s32 maximumSize, const core::aabbox3d& box, const core::matrix4* mat, core::triangle3df* triangles) const { @@ -158,7 +158,7 @@ void COctTreeTriangleSelector::getTrianglesFromOctTree( cnt -= cnt + trianglesWritten - maximumSize; s32 i; - + for (i=0; itransformVect(triangles[trianglesWritten].pointA, node->Triangles[i].pointA ); @@ -169,14 +169,14 @@ void COctTreeTriangleSelector::getTrianglesFromOctTree( for (i=0; i<8; ++i) if (node->Child[i]) - getTrianglesFromOctTree(node->Child[i], trianglesWritten, + getTrianglesFromOctree(node->Child[i], trianglesWritten, maximumSize, box, mat, triangles); } //! Gets all triangles which have or may have contact with a 3d line. // new version: from user Piraaate -void COctTreeTriangleSelector::getTriangles(core::triangle3df* triangles, s32 arraySize, +void COctreeTriangleSelector::getTriangles(core::triangle3df* triangles, s32 arraySize, s32& outTriangleCount, const core::line3d& line, const core::matrix4* transform) const { @@ -185,7 +185,7 @@ void COctTreeTriangleSelector::getTriangles(core::triangle3df* triangles, s32 ar box.addInternalPoint(line.end); // TODO: Could be optimized for line a little bit more. - COctTreeTriangleSelector::getTriangles(triangles, arraySize, outTriangleCount, + COctreeTriangleSelector::getTriangles(triangles, arraySize, outTriangleCount, box, transform); #else @@ -212,13 +212,13 @@ void COctTreeTriangleSelector::getTriangles(core::triangle3df* triangles, s32 ar s32 trianglesWritten = 0; if (Root) - getTrianglesFromOctTree(Root, trianglesWritten, arraySize, invline, &mat, triangles); + getTrianglesFromOctree(Root, trianglesWritten, arraySize, invline, &mat, triangles); outTriangleCount = trianglesWritten; #endif } -void COctTreeTriangleSelector::getTrianglesFromOctTree(SOctTreeNode* node, +void COctreeTriangleSelector::getTrianglesFromOctree(SOctreeNode* node, s32& trianglesWritten, s32 maximumSize, const core::line3d& line, const core::matrix4* transform, core::triangle3df* triangles) const { @@ -253,7 +253,7 @@ void COctTreeTriangleSelector::getTrianglesFromOctTree(SOctTreeNode* node, for (i=0; i<8; ++i) if (node->Child[i]) - getTrianglesFromOctTree(node->Child[i], trianglesWritten, + getTrianglesFromOctree(node->Child[i], trianglesWritten, maximumSize, line, transform, triangles); } diff --git a/source/Irrlicht/COctTreeTriangleSelector.h b/source/Irrlicht/COctreeTriangleSelector.h similarity index 62% rename from source/Irrlicht/COctTreeTriangleSelector.h rename to source/Irrlicht/COctreeTriangleSelector.h index dea7b7e4..ae03fd90 100644 --- a/source/Irrlicht/COctTreeTriangleSelector.h +++ b/source/Irrlicht/COctreeTriangleSelector.h @@ -2,8 +2,8 @@ // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h -#ifndef __C_OCT_TREE_TRIANGLE_SELECTOR_H_INCLUDED__ -#define __C_OCT_TREE_TRIANGLE_SELECTOR_H_INCLUDED__ +#ifndef __C_OCTREE_TRIANGLE_SELECTOR_H_INCLUDED__ +#define __C_OCTREE_TRIANGLE_SELECTOR_H_INCLUDED__ #include "CTriangleSelector.h" @@ -15,59 +15,59 @@ namespace scene class ISceneNode; //! Stupid triangle selector without optimization -class COctTreeTriangleSelector : public CTriangleSelector +class COctreeTriangleSelector : public CTriangleSelector { public: //! Constructs a selector based on a mesh - COctTreeTriangleSelector(const IMesh* mesh, const ISceneNode* node, s32 minimalPolysPerNode); + COctreeTriangleSelector(const IMesh* mesh, const ISceneNode* node, s32 minimalPolysPerNode); - virtual ~COctTreeTriangleSelector(); + virtual ~COctreeTriangleSelector(); //! Gets all triangles which lie within a specific bounding box. - virtual void getTriangles(core::triangle3df* triangles, s32 arraySize, s32& outTriangleCount, + virtual void getTriangles(core::triangle3df* triangles, s32 arraySize, s32& outTriangleCount, const core::aabbox3d& box, const core::matrix4* transform=0) const; //! Gets all triangles which have or may have contact with a 3d line. virtual void getTriangles(core::triangle3df* triangles, s32 arraySize, - s32& outTriangleCount, const core::line3d& line, + s32& outTriangleCount, const core::line3d& line, const core::matrix4* transform=0) const; private: - struct SOctTreeNode + struct SOctreeNode { - SOctTreeNode() + SOctreeNode() { for (u32 i=0; i!=8; ++i) Child[i] = 0; } - ~SOctTreeNode() + ~SOctreeNode() { for (u32 i=0; i!=8; ++i) delete Child[i]; } core::array Triangles; - SOctTreeNode* Child[8]; + SOctreeNode* Child[8]; core::aabbox3d Box; }; - void constructOctTree(SOctTreeNode* node); - void deleteEmptyNodes(SOctTreeNode* node); - void getTrianglesFromOctTree(SOctTreeNode* node, s32& trianglesWritten, + void constructOctree(SOctreeNode* node); + void deleteEmptyNodes(SOctreeNode* node); + void getTrianglesFromOctree(SOctreeNode* node, s32& trianglesWritten, s32 maximumSize, const core::aabbox3d& box, const core::matrix4* transform, core::triangle3df* triangles) const; - void getTrianglesFromOctTree(SOctTreeNode* node, s32& trianglesWritten, + void getTrianglesFromOctree(SOctreeNode* node, s32& trianglesWritten, s32 maximumSize, const core::line3d& line, const core::matrix4* transform, core::triangle3df* triangles) const; - SOctTreeNode* Root; + SOctreeNode* Root; s32 NodeCount; s32 MinimalPolysPerNode; }; diff --git a/source/Irrlicht/COgreMeshFileLoader.cpp b/source/Irrlicht/COgreMeshFileLoader.cpp index dcd5f135..540308bc 100644 --- a/source/Irrlicht/COgreMeshFileLoader.cpp +++ b/source/Irrlicht/COgreMeshFileLoader.cpp @@ -121,7 +121,7 @@ IAnimatedMesh* COgreMeshFileLoader::createMesh(io::IReadFile* file) return 0; ChunkData data; readString(file, data, Version); - if ((Version != "[MeshSerializer_v1.30]") && (Version != "[MeshSerializer_v1.40]")) + if ((Version != "[MeshSerializer_v1.30]") && (Version != "[MeshSerializer_v1.40]") && (Version != "[MeshSerializer_v1.41]")) return 0; clearMeshes(); @@ -212,9 +212,7 @@ bool COgreMeshFileLoader::readObjectChunk(io::IReadFile* file, ChunkData& parent switch(data.header.id) { case COGRE_GEOMETRY: - { readGeometry(file, data, mesh.Geometry); - } break; case COGRE_SUBMESH: mesh.SubMeshes.push_back(OgreSubMesh()); @@ -252,7 +250,14 @@ bool COgreMeshFileLoader::readObjectChunk(io::IReadFile* file, ChunkData& parent case COGRE_MESH_LOD: case COGRE_MESH_SUBMESH_NAME_TABLE: case COGRE_MESH_EDGE_LISTS: + // ignore chunk + file->seek(data.header.length-data.read, true); + data.read += data.header.length-data.read; + break; default: +#ifdef IRR_OGRE_LOADER_DEBUG + os::Printer::log("Skipping", core::stringc(data.header.id)); +#endif // ignore chunk file->seek(data.header.length-data.read, true); data.read += data.header.length-data.read; @@ -287,6 +292,9 @@ bool COgreMeshFileLoader::readGeometry(io::IReadFile* file, ChunkData& parent, O break; default: // ignore chunk +#ifdef IRR_OGRE_LOADER_DEBUG + os::Printer::log("Skipping", core::stringc(data.header.id)); +#endif file->seek(data.header.length-data.read, true); data.read += data.header.length-data.read; } @@ -366,6 +374,9 @@ bool COgreMeshFileLoader::readSubMesh(io::IReadFile* file, ChunkData& parent, Og os::Printer::log("Read Submesh"); #endif readString(file, parent, subMesh.Material); +#ifdef IRR_OGRE_LOADER_DEBUG + os::Printer::log("using material", subMesh.Material); +#endif readBool(file, parent, subMesh.SharedVertices); s32 numIndices; @@ -377,23 +388,13 @@ bool COgreMeshFileLoader::readSubMesh(io::IReadFile* file, ChunkData& parent, Og if (subMesh.Indices32Bit) readInt(file, parent, subMesh.Indices.pointer(), numIndices); else + { for (s32 i=0; iseek(-(long)sizeof(ChunkHeader), true); return true; @@ -781,47 +788,28 @@ void COgreMeshFileLoader::composeObject(void) } } -#if 0 - // currently not working correctly for (u32 i=0; iaddPositionKey(m->getAllJoints()[Skeleton.Animations[i].Keyframes[j].BoneID]); - poskey->frame=Skeleton.Animations[i].Keyframes[j].Time; - poskey->position=Skeleton.Animations[i].Keyframes[j].Position; - ISkinnedMesh::SRotationKey* rotkey = m->addRotationKey(m->getAllJoints()[Skeleton.Animations[i].Keyframes[j].BoneID]); - rotkey->frame=Skeleton.Animations[i].Keyframes[j].Time; - rotkey->rotation=Skeleton.Animations[i].Keyframes[j].Orientation; - ISkinnedMesh::SScaleKey* scalekey = m->addScaleKey(m->getAllJoints()[Skeleton.Animations[i].Keyframes[j].BoneID]); - scalekey->frame=Skeleton.Animations[i].Keyframes[j].Time; - scalekey->scale=Skeleton.Animations[i].Keyframes[j].Scale; + OgreKeyframe& frame = Skeleton.Animations[i].Keyframes[j]; + ISkinnedMesh::SJoint* keyjoint = m->getAllJoints()[frame.BoneID]; + ISkinnedMesh::SPositionKey* poskey = m->addPositionKey(keyjoint); + poskey->frame=frame.Time*25; + poskey->position=keyjoint->LocalMatrix.getTranslation()+frame.Position; + ISkinnedMesh::SRotationKey* rotkey = m->addRotationKey(keyjoint); + rotkey->frame=frame.Time*25; + rotkey->rotation=core::quaternion(keyjoint->LocalMatrix)*frame.Orientation; + ISkinnedMesh::SScaleKey* scalekey = m->addScaleKey(keyjoint); + scalekey->frame=frame.Time*25; + scalekey->scale=frame.Scale; } } -#endif m->finalize(); } } -core::stringc COgreMeshFileLoader::getTextureFileName(const core::stringc& texture, - core::stringc& model) -{ - s32 idx = -1; - idx = model.findLast('/'); - - if (idx == -1) - idx = model.findLast('\\'); - - if (idx == -1) - return core::stringc(); - - core::stringc p = model.subString(0, idx+1); - p.append(texture); - return p; -} - - void COgreMeshFileLoader::getMaterialToken(io::IReadFile* file, core::stringc& token, bool noNewLine) { bool parseString=false; @@ -1166,7 +1154,13 @@ void COgreMeshFileLoader::readPass(io::IReadFile* file, OgreTechnique& technique { getMaterialToken(file, token); } while (token != "}"); - getMaterialToken(file, token); + } + else if (token=="shadow_caster_vertex_program_ref") + { + do + { + getMaterialToken(file, token); + } while (token != "}"); } else if (token=="vertex_program_ref") { @@ -1174,7 +1168,6 @@ void COgreMeshFileLoader::readPass(io::IReadFile* file, OgreTechnique& technique { getMaterialToken(file, token); } while (token != "}"); - getMaterialToken(file, token); } //fog_override, iteration, point_size_attenuation //not considered yet! @@ -1366,8 +1359,8 @@ bool COgreMeshFileLoader::loadSkeleton(io::IReadFile* meshFile, const core::stri readQuaternion(file, data, bone.Orientation); #ifdef IRR_OGRE_LOADER_DEBUG os::Printer::log("Bone", bone.Name+" ("+core::stringc(bone.Handle)+")"); -// os::Printer::log("Position", core::stringc(bone.Position.X)+" "+core::stringc(bone.Position.Y)+" "+core::stringc(bone.Position.Z)); -// os::Printer::log("Rotation quat", core::stringc(bone.Orientation.W)+" "+core::stringc(bone.Orientation.X)+" "+core::stringc(bone.Orientation.Y)+" "+core::stringc(bone.Orientation.Z)); + os::Printer::log("Position", core::stringc(bone.Position.X)+" "+core::stringc(bone.Position.Y)+" "+core::stringc(bone.Position.Z)); + os::Printer::log("Rotation quat", core::stringc(bone.Orientation.W)+" "+core::stringc(bone.Orientation.X)+" "+core::stringc(bone.Orientation.Y)+" "+core::stringc(bone.Orientation.Z)); // core::vector3df rot; // bone.Orientation.toEuler(rot); // rot *= core::RADTODEG; @@ -1408,7 +1401,7 @@ bool COgreMeshFileLoader::loadSkeleton(io::IReadFile* meshFile, const core::stri break; case COGRE_ANIMATION_TRACK: #ifdef IRR_OGRE_LOADER_DEBUG -// os::Printer::log("for Bone ", core::stringc(bone)); + os::Printer::log("for Bone ", core::stringc(bone)); #endif readShort(file, data, &bone); // store current bone break; @@ -1418,8 +1411,8 @@ bool COgreMeshFileLoader::loadSkeleton(io::IReadFile* meshFile, const core::stri OgreKeyframe& keyframe = Skeleton.Animations.getLast().Keyframes.getLast(); readFloat(file, data, &keyframe.Time); keyframe.Time+=animationTotal; - readVector(file, data, keyframe.Position); readQuaternion(file, data, keyframe.Orientation); + readVector(file, data, keyframe.Position); if (data.readread(out, sizeof(int)); + file->read(out, sizeof(int)*num); if (SwapEndian) { for (u32 i=0; i(params.WindowId)), HRc(0), DeviceType(EIDT_WIN32) + HDc(0), Device(device), Window(static_cast(params.WindowId)), + DeviceType(EIDT_WIN32) { #ifdef _DEBUG setDebugName("COpenGLDriver"); #endif } + +bool COpenGLDriver::changeRenderContext(const SExposedVideoData& videoData, CIrrDeviceWin32* device) +{ + if (videoData.OpenGLWin32.HWnd && videoData.OpenGLWin32.HDc && videoData.OpenGLWin32.HRc) + { + if (!wglMakeCurrent((HDC)videoData.OpenGLWin32.HDc, (HGLRC)videoData.OpenGLWin32.HRc)) + { + os::Printer::log("Render Context switch failed."); + return false; + } + else + { + HDc = (HDC)videoData.OpenGLWin32.HDc; + } + } + // set back to main context + else if (HDc != ExposedData.OpenGLWin32.HDc) + { + if (!wglMakeCurrent((HDC)ExposedData.OpenGLWin32.HDc, (HGLRC)ExposedData.OpenGLWin32.HRc)) + { + os::Printer::log("Render Context switch failed."); + return false; + } + else + { + HDc = (HDC)ExposedData.OpenGLWin32.HDc; + } + } + return true; +} + + //! inits the open gl driver bool COpenGLDriver::initDriver(irr::SIrrlichtCreationParameters params, CIrrDeviceWin32* device) { + // Create a window to test antialiasing support + const fschar_t* ClassName = __TEXT("GLCIrrDeviceWin32"); + HINSTANCE lhInstance = GetModuleHandle(0); + + // Register Class + WNDCLASSEX wcex; + wcex.cbSize = sizeof(WNDCLASSEX); + wcex.style = CS_HREDRAW | CS_VREDRAW; + wcex.lpfnWndProc = (WNDPROC)DefWindowProc; + wcex.cbClsExtra = 0; + wcex.cbWndExtra = 0; + wcex.hInstance = lhInstance; + wcex.hIcon = NULL; + wcex.hCursor = LoadCursor(NULL, IDC_ARROW); + wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); + wcex.lpszMenuName = 0; + wcex.lpszClassName = ClassName; + wcex.hIconSm = 0; + wcex.hIcon = 0; + RegisterClassEx(&wcex); + + RECT clientSize; + clientSize.top = 0; + clientSize.left = 0; + clientSize.right = params.WindowSize.Width; + clientSize.bottom = params.WindowSize.Height; + + DWORD style = WS_POPUP; + if (!params.Fullscreen) + style = WS_SYSMENU | WS_BORDER | WS_CAPTION | WS_CLIPCHILDREN | WS_CLIPSIBLINGS; + + AdjustWindowRect(&clientSize, style, FALSE); + + 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; + + HWND temporary_wnd=CreateWindow(ClassName, __TEXT(""), style, windowLeft, + windowTop, realWidth, realHeight, NULL, NULL, lhInstance, NULL); + + if (!temporary_wnd) + { + os::Printer::log("Cannot create a temporary window.", ELL_ERROR); + return false; + } + + HDc = GetDC(temporary_wnd); + // Set up pixel format descriptor with desired parameters PIXELFORMATDESCRIPTOR pfd = { sizeof(PIXELFORMATDESCRIPTOR), // Size Of This Pixel Format Descriptor @@ -74,57 +157,6 @@ bool COpenGLDriver::initDriver(irr::SIrrlichtCreationParameters params, CIrrDevi GLuint PixelFormat; - // Create a window to test antialiasing support - const fschar_t* ClassName = __TEXT("GLCIrrDeviceWin32"); - HINSTANCE lhInstance = GetModuleHandle(0); - - // Register Class - WNDCLASSEX wcex; - wcex.cbSize = sizeof(WNDCLASSEX); - wcex.style = CS_HREDRAW | CS_VREDRAW; - wcex.lpfnWndProc = (WNDPROC)DefWindowProc; - wcex.cbClsExtra = 0; - wcex.cbWndExtra = 0; - wcex.hInstance = lhInstance; - wcex.hIcon = NULL; - wcex.hCursor = LoadCursor(NULL, IDC_ARROW); - wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); - wcex.lpszMenuName = 0; - wcex.lpszClassName = ClassName; - wcex.hIconSm = 0; - wcex.hIcon = 0; - - RegisterClassEx(&wcex); - RECT clientSize; - clientSize.top = 0; - clientSize.left = 0; - clientSize.right = params.WindowSize.Width; - clientSize.bottom = params.WindowSize.Height; - - DWORD style = WS_POPUP; - - if (!params.Fullscreen) - style = WS_SYSMENU | WS_BORDER | WS_CAPTION | WS_CLIPCHILDREN | WS_CLIPSIBLINGS; - - AdjustWindowRect(&clientSize, style, FALSE); - - 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; - - HWND temporary_wnd=CreateWindow(ClassName, __TEXT(""), style, windowLeft, windowTop, - realWidth, realHeight, NULL, NULL, lhInstance, NULL); - - if (!temporary_wnd) - { - os::Printer::log("Cannot create a temporary window.", ELL_ERROR); - return false; - } - - HDc = GetDC(temporary_wnd); - for (u32 i=0; i<5; ++i) { if (i == 1) @@ -175,8 +207,8 @@ bool COpenGLDriver::initDriver(irr::SIrrlichtCreationParameters params, CIrrDevi } SetPixelFormat(HDc, PixelFormat, &pfd); - HRc=wglCreateContext(HDc); - if (!HRc) + HGLRC hrc=wglCreateContext(HDc); + if (!hrc) { os::Printer::log("Cannot create a temporary GL rendering context.", ELL_ERROR); ReleaseDC(temporary_wnd, HDc); @@ -184,10 +216,16 @@ bool COpenGLDriver::initDriver(irr::SIrrlichtCreationParameters params, CIrrDevi return false; } - if (!wglMakeCurrent(HDc, HRc)) + SExposedVideoData data; + data.OpenGLWin32.HDc = HDc; + data.OpenGLWin32.HRc = hrc; + data.OpenGLWin32.HWnd = temporary_wnd; + + + if (!changeRenderContext(data, device)) { os::Printer::log("Cannot activate a temporary GL rendering context.", ELL_ERROR); - wglDeleteContext(HRc); + wglDeleteContext(hrc); ReleaseDC(temporary_wnd, HDc); DestroyWindow(temporary_wnd); return false; @@ -277,7 +315,7 @@ bool COpenGLDriver::initDriver(irr::SIrrlichtCreationParameters params, CIrrDevi AntiAlias=0; wglMakeCurrent(HDc, NULL); - wglDeleteContext(HRc); + wglDeleteContext(hrc); ReleaseDC(temporary_wnd, HDc); DestroyWindow(temporary_wnd); @@ -349,23 +387,29 @@ bool COpenGLDriver::initDriver(irr::SIrrlichtCreationParameters params, CIrrDevi WGL_CONTEXT_MINOR_VERSION_ARB, 1, 0 }; - HRc=wglCreateContextAttribs_ARB(HDc, 0, iAttribs); + hrc=wglCreateContextAttribs_ARB(HDc, 0, iAttribs); } else #endif - HRc=wglCreateContext(HDc); + hrc=wglCreateContext(HDc); - if (!HRc) + if (!hrc) { os::Printer::log("Cannot create a GL rendering context.", ELL_ERROR); return false; } + // set exposed data + ExposedData.OpenGLWin32.HDc = HDc; + ExposedData.OpenGLWin32.HRc = hrc; + ExposedData.OpenGLWin32.HWnd = Window; + // activate rendering context - if (!wglMakeCurrent(HDc, HRc)) + + if (!changeRenderContext(ExposedData, device)) { os::Printer::log("Cannot activate GL rendering context", ELL_ERROR); - wglDeleteContext(HRc); + wglDeleteContext(hrc); return false; } @@ -396,12 +440,6 @@ bool COpenGLDriver::initDriver(irr::SIrrlichtCreationParameters params, CIrrDevi if (wglSwapIntervalEXT) wglSwapIntervalEXT(params.Vsync ? 1 : 0); #endif - - // set exposed data - ExposedData.OpenGLWin32.HDc = HDc; - ExposedData.OpenGLWin32.HRc = HRc; - ExposedData.OpenGLWin32.HWnd = Window; - return true; } @@ -420,7 +458,7 @@ COpenGLDriver::COpenGLDriver(const SIrrlichtCreationParameters& params, CurrentRendertargetSize(0,0), ColorFormat(ECF_R8G8B8), CurrentTarget(ERT_FRAME_BUFFER), Doublebuffer(params.Doublebuffer), Stereo(params.Stereobuffer), - _device(device), DeviceType(EIDT_OSX) + Device(device), DeviceType(EIDT_OSX) { #ifdef _DEBUG setDebugName("COpenGLDriver"); @@ -442,13 +480,48 @@ COpenGLDriver::COpenGLDriver(const SIrrlichtCreationParameters& params, Transformation3DChanged(true), AntiAlias(params.AntiAlias), RenderTargetTexture(0), CurrentRendertargetSize(0,0), ColorFormat(ECF_R8G8B8), CurrentTarget(ERT_FRAME_BUFFER), - Doublebuffer(params.Doublebuffer), Stereo(params.Stereobuffer), DeviceType(EIDT_X11) + Doublebuffer(params.Doublebuffer), Stereo(params.Stereobuffer), + Device(device), DeviceType(EIDT_X11) { #ifdef _DEBUG setDebugName("COpenGLDriver"); #endif } + +bool COpenGLDriver::changeRenderContext(const SExposedVideoData& videoData, CIrrDeviceLinux* device) +{ + if (videoData.OpenGLLinux.X11Display && videoData.OpenGLLinux.X11Window && videoData.OpenGLLinux.X11Context) + { + if (!glXMakeCurrent((Display*)videoData.OpenGLLinux.X11Display, videoData.OpenGLLinux.X11Window, (GLXContext)videoData.OpenGLLinux.X11Context)) + { + os::Printer::log("Render Context switch failed."); + return false; + } + else + { + Drawable = videoData.OpenGLLinux.X11Window; + X11Display = (Display*)videoData.OpenGLLinux.X11Display; + } + } + // set back to main context + else if (X11Display != ExposedData.OpenGLLinux.X11Display) + { + if (!glXMakeCurrent((Display*)ExposedData.OpenGLLinux.X11Display, ExposedData.OpenGLLinux.X11Window, (GLXContext)ExposedData.OpenGLLinux.X11Context)) + { + os::Printer::log("Render Context switch failed."); + return false; + } + else + { + Drawable = ExposedData.OpenGLLinux.X11Window; + X11Display = (Display*)ExposedData.OpenGLLinux.X11Display; + } + } + return true; +} + + //! inits the open gl driver bool COpenGLDriver::initDriver(irr::SIrrlichtCreationParameters params, CIrrDeviceLinux* device) { @@ -456,6 +529,7 @@ bool COpenGLDriver::initDriver(irr::SIrrlichtCreationParameters params, CIrrDevi ExposedData.OpenGLLinux.X11Display = glXGetCurrentDisplay(); ExposedData.OpenGLLinux.X11Window = (unsigned long)params.WindowId; Drawable = glXGetCurrentDrawable(); + X11Display = (Display*)ExposedData.OpenGLLinux.X11Display; genericDriverInit(params.WindowSize, params.Stencilbuffer); @@ -488,7 +562,8 @@ COpenGLDriver::COpenGLDriver(const SIrrlichtCreationParameters& params, Transformation3DChanged(true), AntiAlias(params.AntiAlias), RenderTargetTexture(0), CurrentRendertargetSize(0,0), ColorFormat(ECF_R8G8B8), CurrentTarget(ERT_FRAME_BUFFER), - Doublebuffer(params.Doublebuffer), Stereo(params.Stereobuffer), DeviceType(EIDT_SDL) + Doublebuffer(params.Doublebuffer), Stereo(params.Stereobuffer), + Device(device), DeviceType(EIDT_SDL) { #ifdef _DEBUG setDebugName("COpenGLDriver"); @@ -516,12 +591,12 @@ COpenGLDriver::~COpenGLDriver() if (DeviceType == EIDT_WIN32) { - if (HRc) + if (ExposedData.OpenGLWin32.HRc) { if (!wglMakeCurrent(0, 0)) os::Printer::log("Release of dc and rc failed.", ELL_WARNING); - if (!wglDeleteContext(HRc)) + if (!wglDeleteContext((HGLRC)ExposedData.OpenGLWin32.HRc)) os::Printer::log("Release of rendering context failed.", ELL_WARNING); } @@ -690,7 +765,7 @@ bool COpenGLDriver::endScene() #ifdef _IRR_COMPILE_WITH_X11_DEVICE_ if (DeviceType == EIDT_X11) { - glXSwapBuffers((Display*)ExposedData.OpenGLLinux.X11Display, Drawable); + glXSwapBuffers(X11Display, Drawable); return true; } #endif @@ -698,7 +773,7 @@ bool COpenGLDriver::endScene() #ifdef _IRR_COMPILE_WITH_OSX_DEVICE_ if (DeviceType == EIDT_OSX) { - _device->flush(); + Device->flush(); return true; } #endif @@ -746,9 +821,11 @@ void COpenGLDriver::clearBuffers(bool backBuffer, bool zBuffer, bool stencilBuff //! init call for rendering start bool COpenGLDriver::beginScene(bool backBuffer, bool zBuffer, SColor color, - void* windowId, core::rect* sourceRect) + const SExposedVideoData& videoData, core::rect* sourceRect) { - CNullDriver::beginScene(backBuffer, zBuffer, color, windowId, sourceRect); + CNullDriver::beginScene(backBuffer, zBuffer, color, videoData, sourceRect); + + changeRenderContext(videoData, Device); #if defined(_IRR_COMPILE_WITH_SDL_DEVICE_) if (DeviceType == EIDT_SDL) @@ -1559,6 +1636,144 @@ void COpenGLDriver::draw2DVertexPrimitiveList(const void* vertices, u32 vertexCo } +//! draws a set of 2d images, using a color and the alpha channel of the +//! texture if desired. +void COpenGLDriver::draw2DImageBatch(const video::ITexture* texture, + const core::array >& positions, + const core::array >& sourceRects, + const core::rect* clipRect, + SColor color, + bool useAlphaChannelOfTexture) +{ + if (!texture) + return; + + const u32 drawCount = core::min_(positions.size(), sourceRects.size()); + + // texcoords need to be flipped horizontally for RTTs + const bool isRTT = texture->isRenderTarget(); + const core::dimension2d& ss = texture->getOriginalSize(); + const f32 invW = 1.f / static_cast(ss.Width); + const f32 invH = 1.f / static_cast(ss.Height); + const core::dimension2d& renderTargetSize = getCurrentRenderTargetSize(); + + disableTextures(1); + if (!setActiveTexture(0, texture)) + return; + setRenderStates2DMode(color.getAlpha()<255, true, useAlphaChannelOfTexture); + + glColor4ub(color.getRed(), color.getGreen(), color.getBlue(), color.getAlpha()); + glBegin(GL_QUADS); + + for (u32 i=0; i targetPos(positions[i]); + core::position2d sourcePos(sourceRects[i].UpperLeftCorner); + // This needs to be signed as it may go negative. + core::dimension2d sourceSize(sourceRects[i].getSize()); + if (clipRect) + { + if (targetPos.X < clipRect->UpperLeftCorner.X) + { + sourceSize.Width += targetPos.X - clipRect->UpperLeftCorner.X; + if (sourceSize.Width <= 0) + continue; + + sourcePos.X -= targetPos.X - clipRect->UpperLeftCorner.X; + targetPos.X = clipRect->UpperLeftCorner.X; + } + + if (targetPos.X + sourceSize.Width > clipRect->LowerRightCorner.X) + { + sourceSize.Width -= (targetPos.X + sourceSize.Width) - clipRect->LowerRightCorner.X; + if (sourceSize.Width <= 0) + continue; + } + + if (targetPos.Y < clipRect->UpperLeftCorner.Y) + { + sourceSize.Height += targetPos.Y - clipRect->UpperLeftCorner.Y; + if (sourceSize.Height <= 0) + continue; + + sourcePos.Y -= targetPos.Y - clipRect->UpperLeftCorner.Y; + targetPos.Y = clipRect->UpperLeftCorner.Y; + } + + if (targetPos.Y + sourceSize.Height > clipRect->LowerRightCorner.Y) + { + sourceSize.Height -= (targetPos.Y + sourceSize.Height) - clipRect->LowerRightCorner.Y; + if (sourceSize.Height <= 0) + continue; + } + } + + // clip these coordinates + + if (targetPos.X<0) + { + sourceSize.Width += targetPos.X; + if (sourceSize.Width <= 0) + continue; + + sourcePos.X -= targetPos.X; + targetPos.X = 0; + } + + if (targetPos.X + sourceSize.Width > (s32)renderTargetSize.Width) + { + sourceSize.Width -= (targetPos.X + sourceSize.Width) - renderTargetSize.Width; + if (sourceSize.Width <= 0) + continue; + } + + if (targetPos.Y<0) + { + sourceSize.Height += targetPos.Y; + if (sourceSize.Height <= 0) + continue; + + sourcePos.Y -= targetPos.Y; + targetPos.Y = 0; + } + + if (targetPos.Y + sourceSize.Height > (s32)renderTargetSize.Height) + { + sourceSize.Height -= (targetPos.Y + sourceSize.Height) - renderTargetSize.Height; + if (sourceSize.Height <= 0) + continue; + } + + // ok, we've clipped everything. + // now draw it. + + const core::rect tcoords( + sourcePos.X * invW, + (isRTT?(sourcePos.Y + sourceSize.Height):sourcePos.Y) * invH, + (sourcePos.X + sourceSize.Width) * invW, + (isRTT?sourcePos.Y:(sourcePos.Y + sourceSize.Height)) * invH); + + const core::rect poss(targetPos, sourceSize); + + glTexCoord2f(tcoords.UpperLeftCorner.X, tcoords.UpperLeftCorner.Y); + glVertex2f(GLfloat(poss.UpperLeftCorner.X), GLfloat(poss.UpperLeftCorner.Y)); + + glTexCoord2f(tcoords.LowerRightCorner.X, tcoords.UpperLeftCorner.Y); + glVertex2f(GLfloat(poss.LowerRightCorner.X), GLfloat(poss.UpperLeftCorner.Y)); + + glTexCoord2f(tcoords.LowerRightCorner.X, tcoords.LowerRightCorner.Y); + glVertex2f(GLfloat(poss.LowerRightCorner.X), GLfloat(poss.LowerRightCorner.Y)); + + glTexCoord2f(tcoords.UpperLeftCorner.X, tcoords.LowerRightCorner.Y); + glVertex2f(GLfloat(poss.UpperLeftCorner.X), GLfloat(poss.LowerRightCorner.Y)); + } + glEnd(); +} + + //! draws a 2d image, using a color and the alpha channel of the texture if //! desired. The image is drawn at pos, clipped against clipRect (if != 0). //! Only the subtexture defined by sourceRect is used. @@ -2011,9 +2226,9 @@ inline void COpenGLDriver::createGLTextureMatrix(GLfloat *o, const core::matrix4 //! returns a device dependent texture from a software surface (IImage) -video::ITexture* COpenGLDriver::createDeviceDependentTexture(IImage* surface, const io::path& name) +video::ITexture* COpenGLDriver::createDeviceDependentTexture(IImage* surface, const io::path& name, void* mipmapData) { - return new COpenGLTexture(surface, name, this); + return new COpenGLTexture(surface, name, mipmapData, this); } @@ -2025,6 +2240,7 @@ void COpenGLDriver::setMaterial(const SMaterial& material) for (s32 i = MaxTextureUnits-1; i>= 0; --i) { + setActiveTexture(i, material.getTexture(i)); setTransform ((E_TRANSFORMATION_STATE) (ETS_TEXTURE_0 + i), Material.getTextureMatrix(i)); } @@ -2239,8 +2455,6 @@ void COpenGLDriver::setBasicRenderStates(const SMaterial& material, const SMater if (resetAllRenderStates || lastmaterial.ColorMaterial != material.ColorMaterial) { - if (material.ColorMaterial != ECM_NONE) - glEnable(GL_COLOR_MATERIAL); switch (material.ColorMaterial) { case ECM_NONE: @@ -2262,6 +2476,8 @@ void COpenGLDriver::setBasicRenderStates(const SMaterial& material, const SMater glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE); break; } + if (material.ColorMaterial != ECM_NONE) + glEnable(GL_COLOR_MATERIAL); } if (resetAllRenderStates || @@ -2567,6 +2783,15 @@ void COpenGLDriver::setBasicRenderStates(const SMaterial& material, const SMater } +//! Enable the 2d override material +void COpenGLDriver::enableMaterial2D(bool enable) +{ + if (!enable) + CurrentRenderMode = ERM_NONE; + CNullDriver::enableMaterial2D(enable); +} + + //! sets the needed renderstates void COpenGLDriver::setRenderStates2DMode(bool alpha, bool texture, bool alphaChannel) { @@ -2577,35 +2802,41 @@ void COpenGLDriver::setRenderStates2DMode(bool alpha, bool texture, bool alphaCh { if (static_cast(LastMaterial.MaterialType) < MaterialRenderers.size()) MaterialRenderers[LastMaterial.MaterialType].Renderer->OnUnsetMaterial(); - SMaterial mat; - mat.ZBuffer=ECFN_NEVER; - mat.Lighting=false; - mat.AntiAliasing=video::EAAM_OFF; - mat.TextureLayer[0].BilinearFilter=false; - setBasicRenderStates(mat, mat, true); - LastMaterial = mat; + } + if (Transformation3DChanged) + { + glMatrixMode(GL_PROJECTION); + + const core::dimension2d& renderTargetSize = getCurrentRenderTargetSize(); + core::matrix4 m; + m.buildProjectionMatrixOrthoLH(f32(renderTargetSize.Width), f32(-(s32)(renderTargetSize.Height)), -1.0, 1.0); + m.setTranslation(core::vector3df(-1,1,0)); + glLoadMatrixf(m.pointer()); + + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + glTranslatef(0.375, 0.375, 0.0); + + // Make sure we set first texture matrix + if (MultiTextureExtension) + extGlActiveTexture(GL_TEXTURE0_ARB); + + Transformation3DChanged = false; + } + if (!OverrideMaterial2DEnabled) + { + setBasicRenderStates(InitMaterial2D, LastMaterial, true); + LastMaterial = InitMaterial2D; glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); } - - glMatrixMode(GL_PROJECTION); - - const core::dimension2d& renderTargetSize = getCurrentRenderTargetSize(); - core::matrix4 m; - m.buildProjectionMatrixOrthoLH(f32(renderTargetSize.Width), f32(-(s32)(renderTargetSize.Height)), -1.0, 1.0); - m.setTranslation(core::vector3df(-1,1,0)); - glLoadMatrixf(m.pointer()); - - glMatrixMode(GL_MODELVIEW); - glLoadIdentity(); - glTranslatef(0.375, 0.375, 0.0); - - // Make sure we set first texture matrix - if (MultiTextureExtension) - extGlActiveTexture(GL_TEXTURE0_ARB); - glMatrixMode(GL_TEXTURE); - glLoadIdentity(); - - Transformation3DChanged = false; + } + if (OverrideMaterial2DEnabled) + { + OverrideMaterial2D.Lighting=false; + OverrideMaterial2D.ZBuffer=ECFN_NEVER; + OverrideMaterial2D.ZWriteEnable=false; + setBasicRenderStates(OverrideMaterial2D, LastMaterial, false); + LastMaterial = OverrideMaterial2D; } if (alphaChannel || alpha) @@ -2622,11 +2853,14 @@ void COpenGLDriver::setRenderStates2DMode(bool alpha, bool texture, bool alphaCh if (texture) { - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + if (!OverrideMaterial2DEnabled) + { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + } + setTransform(ETS_TEXTURE_0, core::IdentityMatrix); if (alphaChannel) { @@ -2637,9 +2871,18 @@ void COpenGLDriver::setRenderStates2DMode(bool alpha, bool texture, bool alphaCh } else { -#ifdef GL_ARB_texture_env_combine - if (FeatureAvailable[IRR_ARB_texture_env_combine]) +#if defined(GL_ARB_texture_env_combine) || defined(GL_EXT_texture_env_combine) + if (FeatureAvailable[IRR_ARB_texture_env_combine]||FeatureAvailable[IRR_EXT_texture_env_combine]) { +#ifdef GL_ARB_texture_env_combine + glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB); + glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE); + glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_TEXTURE); + // rgb always modulates + glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE); + glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE); + glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PRIMARY_COLOR_ARB); +#else glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT); glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_EXT, GL_REPLACE); glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT, GL_TEXTURE); @@ -2647,6 +2890,7 @@ void COpenGLDriver::setRenderStates2DMode(bool alpha, bool texture, bool alphaCh glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_MODULATE); glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT, GL_TEXTURE); glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE1_RGB_EXT, GL_PRIMARY_COLOR_EXT); +#endif } else #endif @@ -2657,9 +2901,18 @@ void COpenGLDriver::setRenderStates2DMode(bool alpha, bool texture, bool alphaCh { if (alpha) { -#ifdef GL_ARB_texture_env_combine - if (FeatureAvailable[IRR_ARB_texture_env_combine]) +#if defined(GL_ARB_texture_env_combine) || defined(GL_EXT_texture_env_combine) + if (FeatureAvailable[IRR_ARB_texture_env_combine]||FeatureAvailable[IRR_EXT_texture_env_combine]) { +#ifdef GL_ARB_texture_env_combine + glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB); + glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE); + glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_PRIMARY_COLOR_ARB); + // rgb always modulates + glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE); + glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE); + glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PRIMARY_COLOR_ARB); +#else glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT); glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_EXT, GL_REPLACE); glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT, GL_PRIMARY_COLOR_EXT); @@ -2667,6 +2920,7 @@ void COpenGLDriver::setRenderStates2DMode(bool alpha, bool texture, bool alphaCh glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_MODULATE); glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT, GL_TEXTURE); glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE1_RGB_EXT, GL_PRIMARY_COLOR_EXT); +#endif } else #endif @@ -3234,6 +3488,12 @@ s32 COpenGLDriver::addHighLevelShaderMaterial( const c8* pixelShaderProgram, const c8* pixelShaderEntryPointName, E_PIXEL_SHADER_TYPE psCompileTarget, + const c8* geometryShaderProgram, + const c8* geometryShaderEntryPointName, + E_GEOMETRY_SHADER_TYPE gsCompileTarget, + scene::E_PRIMITIVE_TYPE inType, + scene::E_PRIMITIVE_TYPE outType, + u32 verticesOut, IShaderConstantSetCallBack* callback, E_MATERIAL_TYPE baseMaterial, s32 userData) @@ -3241,14 +3501,17 @@ s32 COpenGLDriver::addHighLevelShaderMaterial( s32 nr = -1; COpenGLSLMaterialRenderer* r = new COpenGLSLMaterialRenderer( - this, nr, vertexShaderProgram, vertexShaderEntryPointName, - vsCompileTarget, pixelShaderProgram, pixelShaderEntryPointName, psCompileTarget, + this, nr, + vertexShaderProgram, vertexShaderEntryPointName, vsCompileTarget, + pixelShaderProgram, pixelShaderEntryPointName, psCompileTarget, + geometryShaderProgram, geometryShaderEntryPointName, gsCompileTarget, + inType, outType, verticesOut, callback,getMaterialRenderer(baseMaterial), userData); - r->drop(); return nr; } + //! Returns a pointer to the IVideoDriver interface. (Implementation for //! IMaterialRendererServices) IVideoDriver* COpenGLDriver::getVideoDriver() @@ -3257,13 +3520,6 @@ IVideoDriver* COpenGLDriver::getVideoDriver() } -//! Returns pointer to the IGPUProgrammingServices interface. -IGPUProgrammingServices* COpenGLDriver::getGPUProgrammingServices() -{ - return this; -} - - ITexture* COpenGLDriver::addRenderTargetTexture(const core::dimension2d& size, const io::path& name, const ECOLOR_FORMAT format) @@ -3409,6 +3665,7 @@ bool COpenGLDriver::setRenderTarget(video::ITexture* texture, bool clearBackBuff RenderTargetTexture = 0; CurrentRendertargetSize = core::dimension2d(0,0); CurrentTarget=ERT_FRAME_BUFFER; + glDrawBuffer(Doublebuffer?GL_BACK_LEFT:GL_FRONT_LEFT); } clearBuffers(clearBackBuffer, clearZBuffer, false, color); @@ -3423,7 +3680,7 @@ bool COpenGLDriver::setRenderTarget(const core::array& tar if (targets.size()==0) return setRenderTarget(0, clearBackBuffer, clearZBuffer, color); - u32 maxMultipleRTTs = core::min_(4u, targets.size()); + u32 maxMultipleRTTs = core::min_(static_cast(MaxMultipleRenderTargets), targets.size()); // determine common size core::dimension2du rttSize = CurrentRendertargetSize; @@ -3478,13 +3735,23 @@ bool COpenGLDriver::setRenderTarget(const core::array& tar return false; } - if (targets[0].TargetType==ERT_RENDER_TEXTURE) - setRenderTarget(targets[0].RenderTexture, false, false, 0x0); - else + // init FBO, if any + for (u32 i=0; i 1) { + CurrentTarget=ERT_MULTI_RENDER_TEXTURES; core::array MRTs; MRTs.set_used(maxMultipleRTTs); for(u32 i = 0; i < maxMultipleRTTs; i++) @@ -3505,7 +3772,7 @@ bool COpenGLDriver::setRenderTarget(const core::array& tar { extGlBlendFuncIndexed(i, targets[i].BlendFuncSrc, targets[i].BlendFuncDst); } - if (targets[0].TargetType==ERT_RENDER_TEXTURE) + if (targets[i].TargetType==ERT_RENDER_TEXTURE) { GLenum attachment = GL_NONE; #ifdef GL_EXT_framebuffer_object @@ -3708,6 +3975,41 @@ core::dimension2du COpenGLDriver::getMaxTextureSize() const return core::dimension2du(MaxTextureSize, MaxTextureSize); } +//! Convert E_PRIMITIVE_TYPE to OpenGL equivalent +GLenum COpenGLDriver::primitiveTypeToGL(scene::E_PRIMITIVE_TYPE type) const +{ + switch (type) + { + case scene::EPT_POINTS: + return GL_POINTS; + case scene::EPT_LINE_STRIP: + return GL_LINE_STRIP; + case scene::EPT_LINE_LOOP: + return GL_LINE_LOOP; + case scene::EPT_LINES: + return GL_LINES; + case scene::EPT_TRIANGLE_STRIP: + return GL_TRIANGLE_STRIP; + case scene::EPT_TRIANGLE_FAN: + return GL_TRIANGLE_FAN; + case scene::EPT_TRIANGLES: + return GL_TRIANGLES; + case scene::EPT_QUAD_STRIP: + return GL_QUAD_STRIP; + case scene::EPT_QUADS: + return GL_QUADS; + case scene::EPT_POLYGON: + return GL_POLYGON; + case scene::EPT_POINT_SPRITES: +#ifdef GL_ARB_point_sprite + return GL_POINT_SPRITE_ARB; +#else + return GL_POINTS; +#endif + } + return GL_TRIANGLES; +} + } // end namespace } // end namespace diff --git a/source/Irrlicht/COpenGLDriver.h b/source/Irrlicht/COpenGLDriver.h index 6e221908..ced21f9e 100644 --- a/source/Irrlicht/COpenGLDriver.h +++ b/source/Irrlicht/COpenGLDriver.h @@ -39,12 +39,14 @@ namespace video COpenGLDriver(const SIrrlichtCreationParameters& params, io::IFileSystem* io, CIrrDeviceWin32* device); //! inits the windows specific parts of the open gl driver bool initDriver(SIrrlichtCreationParameters params, CIrrDeviceWin32* device); + bool changeRenderContext(const SExposedVideoData& videoData, CIrrDeviceWin32* device); #endif #ifdef _IRR_COMPILE_WITH_X11_DEVICE_ COpenGLDriver(const SIrrlichtCreationParameters& params, io::IFileSystem* io, CIrrDeviceLinux* device); //! inits the GLX specific parts of the open gl driver bool initDriver(SIrrlichtCreationParameters params, CIrrDeviceLinux* device); + bool changeRenderContext(const SExposedVideoData& videoData, CIrrDeviceLinux* device); #endif #ifdef _IRR_COMPILE_WITH_SDL_DEVICE_ @@ -55,13 +57,16 @@ namespace video COpenGLDriver(const SIrrlichtCreationParameters& params, io::IFileSystem* io, CIrrDeviceMacOSX *device); #endif + //! generic version which overloads the unimplemented versions + bool changeRenderContext(const SExposedVideoData& videoData, void* device) {return false;} + //! destructor virtual ~COpenGLDriver(); //! clears the zbuffer virtual bool beginScene(bool backBuffer=true, bool zBuffer=true, SColor color=SColor(255,0,0,0), - void* windowId=0, + const SExposedVideoData& videoData=SExposedVideoData(), core::rect* sourceRect=0); //! presents the rendered scene on the screen, returns false if failed @@ -115,6 +120,15 @@ namespace video //! \param material: Material to be used from now on. virtual void setMaterial(const SMaterial& material); + //! draws a set of 2d images, using a color and the alpha channel of the + //! texture if desired. + void draw2DImageBatch(const video::ITexture* texture, + const core::array >& positions, + const core::array >& sourceRects, + const core::rect* clipRect, + SColor color, + bool useAlphaChannelOfTexture); + //! draws an 2d image, using a color (if color is other then Color(255,255,255,255)) and the alpha channel of the texture if wanted. virtual void draw2DImage(const video::ITexture* texture, const core::position2d& destPos, const core::rect& sourceRect, const core::rect* clipRect = 0, @@ -261,13 +275,22 @@ namespace video IShaderConstantSetCallBack* callback, E_MATERIAL_TYPE baseMaterial, s32 userData); //! Adds a new material renderer to the VideoDriver, using GLSL to render geometry. - virtual s32 addHighLevelShaderMaterial(const c8* vertexShaderProgram, const c8* vertexShaderEntryPointName, - E_VERTEX_SHADER_TYPE vsCompileTarget, const c8* pixelShaderProgram, const c8* pixelShaderEntryPointName, - E_PIXEL_SHADER_TYPE psCompileTarget, IShaderConstantSetCallBack* callback, E_MATERIAL_TYPE baseMaterial, - s32 userData); - - //! Returns pointer to the IGPUProgrammingServices interface. - virtual IGPUProgrammingServices* getGPUProgrammingServices(); + virtual s32 addHighLevelShaderMaterial( + const c8* vertexShaderProgram, + const c8* vertexShaderEntryPointName = "main", + E_VERTEX_SHADER_TYPE vsCompileTarget = EVST_VS_1_1, + const c8* pixelShaderProgram = 0, + const c8* pixelShaderEntryPointName = "main", + E_PIXEL_SHADER_TYPE psCompileTarget = EPST_PS_1_1, + const c8* geometryShaderProgram = 0, + const c8* geometryShaderEntryPointName = "main", + E_GEOMETRY_SHADER_TYPE gsCompileTarget = EGST_GS_4_0, + scene::E_PRIMITIVE_TYPE inType = scene::EPT_TRIANGLES, + scene::E_PRIMITIVE_TYPE outType = scene::EPT_TRIANGLE_STRIP, + u32 verticesOut = 0, + IShaderConstantSetCallBack* callback = 0, + E_MATERIAL_TYPE baseMaterial = video::EMT_SOLID, + s32 userData = 0); //! Returns a pointer to the IVideoDriver interface. (Implementation for //! IMaterialRendererServices) @@ -316,6 +339,9 @@ namespace video //! \param enable: If true, enable the clipping plane else disable it. virtual void enableClipPlane(u32 index, bool enable); + //! Enable the 2d override material + virtual void enableMaterial2D(bool enable=true); + //! Returns the graphics card vendor name. virtual core::stringc getVendorInfo() {return VendorName;} @@ -325,6 +351,9 @@ namespace video ITexture* createDepthTexture(ITexture* texture, bool shared=true); void removeDepthTexture(ITexture* texture); + //! Convert E_PRIMITIVE_TYPE to OpenGL equivalent + GLenum primitiveTypeToGL(scene::E_PRIMITIVE_TYPE type) const; + private: //! clears the zbuffer and color buffer @@ -338,7 +367,7 @@ namespace video //! inits the parts of the open gl driver used on all platforms bool genericDriverInit(const core::dimension2d& screenSize, bool stencilBuffer); //! returns a device dependent texture from a software surface (IImage) - virtual video::ITexture* createDeviceDependentTexture(IImage* surface, const io::path& name); + virtual video::ITexture* createDeviceDependentTexture(IImage* surface, const io::path& name, void* mipmapData); //! creates a transposed matrix in supplied GLfloat array to pass to OpenGL inline void createGLMatrix(GLfloat gl_matrix[16], const core::matrix4& m); @@ -434,13 +463,20 @@ namespace video #ifdef _IRR_WINDOWS_API_ HDC HDc; // Private GDI Device Context HWND Window; - HGLRC HRc; // Permanent Rendering Context + #ifdef _IRR_COMPILE_WITH_WINDOWS_DEVICE_ + CIrrDeviceWin32 *Device; + #endif #endif #ifdef _IRR_COMPILE_WITH_X11_DEVICE_ GLXDrawable Drawable; + Display* X11Display; + CIrrDeviceLinux *Device; #endif #ifdef _IRR_COMPILE_WITH_OSX_DEVICE_ - CIrrDeviceMacOSX *_device; + CIrrDeviceMacOSX *Device; + #endif + #ifdef _IRR_COMPILE_WITH_SDL_DEVICE_ + CIrrDeviceSDL *Device; #endif E_DEVICE_TYPE DeviceType; diff --git a/source/Irrlicht/COpenGLExtensionHandler.cpp b/source/Irrlicht/COpenGLExtensionHandler.cpp index 585cefbf..970d414a 100644 --- a/source/Irrlicht/COpenGLExtensionHandler.cpp +++ b/source/Irrlicht/COpenGLExtensionHandler.cpp @@ -19,13 +19,18 @@ namespace video COpenGLExtensionHandler::COpenGLExtensionHandler() : StencilBuffer(false), MultiTextureExtension(false), TextureCompressionExtension(false), - MaxTextureUnits(1), MaxLights(1), MaxAnisotropy(1), MaxUserClipPlanes(0), - MaxAuxBuffers(0), MaxIndices(65535), MaxTextureSize(1), MaxTextureLODBias(0.f), - MaxMultipleRenderTargets(1), Version(0), ShaderLanguageVersion(0) + MaxTextureUnits(1), MaxLights(1), MaxAnisotropy(1), + MaxUserClipPlanes(0), MaxAuxBuffers(0), + MaxMultipleRenderTargets(1), MaxIndices(65535), + MaxTextureSize(1), MaxGeometryVerticesOut(0), + MaxTextureLODBias(0.f), Version(0), ShaderLanguageVersion(0) #ifdef _IRR_OPENGL_USE_EXTPOINTER_ ,pGlActiveTextureARB(0), pGlClientActiveTextureARB(0), - pGlGenProgramsARB(0), pGlBindProgramARB(0), pGlProgramStringARB(0), - pGlDeleteProgramsARB(0), pGlProgramLocalParameter4fvARB(0), + pGlGenProgramsARB(0), pGlGenProgramsNV(0), + pGlBindProgramARB(0), pGlBindProgramNV(0), + pGlDeleteProgramsARB(0), pGlDeleteProgramsNV(0), + pGlProgramStringARB(0), pGlLoadProgramNV(0), + pGlProgramLocalParameter4fvARB(0), pGlCreateShaderObjectARB(0), pGlShaderSourceARB(0), pGlCompileShaderARB(0), pGlCreateProgramObjectARB(0), pGlAttachObjectARB(0), pGlLinkProgramARB(0), pGlUseProgramObjectARB(0), pGlDeleteObjectARB(0), @@ -48,7 +53,8 @@ COpenGLExtensionHandler::COpenGLExtensionHandler() : pGlIsBufferARB(0), pGlGetBufferParameterivARB(0), pGlGetBufferPointervARB(0), pGlProvokingVertexARB(0), pGlProvokingVertexEXT(0), pGlColorMaskIndexedEXT(0), pGlEnableIndexedEXT(0), pGlDisableIndexedEXT(0), - pGlBlendFuncIndexedAMD(0), pGlBlendFunciARB(0) + pGlBlendFuncIndexedAMD(0), pGlBlendFunciARB(0), + pGlProgramParameteriARB(0), pGlProgramParameteriEXT(0) #endif // _IRR_OPENGL_USE_EXTPOINTER_ { for (u32 i=0; i("glGenProgramsARB")); + pGlGenProgramsNV = (PFNGLGENPROGRAMSNVPROC) + IRR_OGL_LOAD_EXTENSION(reinterpret_cast("glGenProgramsNV")); + pGlBindProgramARB = (PFNGLBINDPROGRAMARBPROC) IRR_OGL_LOAD_EXTENSION(reinterpret_cast("glBindProgramARB")); + pGlBindProgramNV = (PFNGLBINDPROGRAMNVPROC) + IRR_OGL_LOAD_EXTENSION(reinterpret_cast("glBindProgramNV")); + + pGlDeleteProgramsARB = (PFNGLDELETEPROGRAMSARBPROC) + IRR_OGL_LOAD_EXTENSION(reinterpret_cast("glDeleteProgramsARB")); + + pGlDeleteProgramsNV = (PFNGLDELETEPROGRAMSNVPROC) + IRR_OGL_LOAD_EXTENSION(reinterpret_cast("glDeleteProgramsNV")); + pGlProgramStringARB = (PFNGLPROGRAMSTRINGARBPROC) IRR_OGL_LOAD_EXTENSION(reinterpret_cast("glProgramStringARB")); - pGlDeleteProgramsARB = (PFNGLDELETEPROGRAMSNVPROC) - IRR_OGL_LOAD_EXTENSION(reinterpret_cast("glDeleteProgramsARB")); + pGlLoadProgramNV = (PFNGLLOADPROGRAMNVPROC) + IRR_OGL_LOAD_EXTENSION(reinterpret_cast("glLoadProgramNV")); pGlProgramLocalParameter4fvARB = (PFNGLPROGRAMLOCALPARAMETER4FVARBPROC) IRR_OGL_LOAD_EXTENSION(reinterpret_cast("glProgramLocalParameter4fvARB")); @@ -421,6 +445,10 @@ void COpenGLExtensionHandler::initExtensions(bool stencilBuffer) IRR_OGL_LOAD_EXTENSION(reinterpret_cast("glBlendFuncIndexedAMD")); pGlBlendFunciARB= (PFNGLBLENDFUNCIPROC) IRR_OGL_LOAD_EXTENSION(reinterpret_cast("glBlendFunciARB")); + pGlProgramParameteriARB = (PFNGLPROGRAMPARAMETERIARBPROC) + IRR_OGL_LOAD_EXTENSION(reinterpret_cast("glProgramParameteriARB")); + pGlProgramParameteriEXT = (PFNGLPROGRAMPARAMETERIEXTPROC) + IRR_OGL_LOAD_EXTENSION(reinterpret_cast("glProgramParameteriEXT")); #endif // _IRR_OPENGL_USE_EXTPOINTER_ #endif // _IRR_WINDOWS_API_ @@ -438,8 +466,10 @@ void COpenGLExtensionHandler::initExtensions(bool stencilBuffer) MaxLights=static_cast(num); #ifdef GL_EXT_texture_filter_anisotropic if (FeatureAvailable[IRR_EXT_texture_filter_anisotropic]) + { glGetIntegerv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &num); - MaxAnisotropy=static_cast(num); + MaxAnisotropy=static_cast(num); + } #endif #ifdef GL_VERSION_1_2 if (Version>101) @@ -450,7 +480,17 @@ void COpenGLExtensionHandler::initExtensions(bool stencilBuffer) #endif glGetIntegerv(GL_MAX_TEXTURE_SIZE, &num); MaxTextureSize=static_cast(num); -#ifdef EXT_texture_lod_bias + if (queryFeature(EVDF_GEOMETRY_SHADER)) + { +#if defined(GL_ARB_geometry_shader4) || defined(GL_EXT_geometry_shader4) || defined(GL_NV_geometry_shader4) + glGetIntegerv(GL_MAX_GEOMETRY_OUTPUT_VERTICES_EXT, &num); + MaxGeometryVerticesOut=static_cast(num); +#elif defined(GL_NV_geometry_program4) + extGlGetProgramiv(GEOMETRY_PROGRAM_NV, GL_MAX_PROGRAM_OUTPUT_VERTICES_NV, &num); + MaxGeometryVerticesOut=static_cast(num); +#endif + } +#ifdef GL_EXT_texture_lod_bias if (FeatureAvailable[IRR_EXT_texture_lod_bias]) glGetFloatv(GL_MAX_TEXTURE_LOD_BIAS_EXT, &MaxTextureLODBias); #endif @@ -458,17 +498,17 @@ void COpenGLExtensionHandler::initExtensions(bool stencilBuffer) MaxUserClipPlanes=static_cast(num); glGetIntegerv(GL_AUX_BUFFERS, &num); MaxAuxBuffers=static_cast(num); -#ifdef ARB_draw_buffers +#ifdef GL_ARB_draw_buffers if (FeatureAvailable[IRR_ARB_draw_buffers]) { - glGetIntegerv(GL_MAX_DRAW_BUFFERS_ARB, reinterpret_cast(&MaxUserClipPlanes)); - MaxMultipleRenderTargets = static_cast(MaxUserClipPlanes); + glGetIntegerv(GL_MAX_DRAW_BUFFERS_ARB, &num); + MaxMultipleRenderTargets = static_cast(num); } -#elif defined(ATI_draw_buffers) +#elif defined(GL_ATI_draw_buffers) if (FeatureAvailable[IRR_ATI_draw_buffers]) { - glGetIntegerv(GL_MAX_DRAW_BUFFERS_ATI, reinterpret_cast(&MaxUserClipPlanes)); - MaxMultipleRenderTargets = static_cast(MaxUserClipPlanes); + glGetIntegerv(GL_MAX_DRAW_BUFFERS_ATI, &num); + MaxMultipleRenderTargets = static_cast(num); } #endif glGetFloatv(GL_ALIASED_LINE_WIDTH_RANGE, DimAliasedLine); @@ -529,10 +569,15 @@ bool COpenGLExtensionHandler::queryFeature(E_VIDEO_DRIVER_FEATURE feature) const return FeatureAvailable[IRR_SGIS_generate_mipmap]; case EVDF_STENCIL_BUFFER: return StencilBuffer; + case EVDF_VERTEX_SHADER_1_1: case EVDF_ARB_VERTEX_PROGRAM_1: - return FeatureAvailable[IRR_ARB_vertex_program]; + return FeatureAvailable[IRR_ARB_vertex_program] || FeatureAvailable[IRR_NV_vertex_program1_1]; + case EVDF_PIXEL_SHADER_1_1: + case EVDF_PIXEL_SHADER_1_2: case EVDF_ARB_FRAGMENT_PROGRAM_1: - return FeatureAvailable[IRR_ARB_fragment_program]; + return FeatureAvailable[IRR_ARB_fragment_program] || FeatureAvailable[IRR_NV_fragment_program]; + case EVDF_PIXEL_SHADER_2_0: + case EVDF_VERTEX_SHADER_2_0: case EVDF_ARB_GLSL: return (FeatureAvailable[IRR_ARB_shading_language_100]||Version>=200); case EVDF_TEXTURE_NSQUARE: diff --git a/source/Irrlicht/COpenGLExtensionHandler.h b/source/Irrlicht/COpenGLExtensionHandler.h index 9de6a4dc..aabbeebb 100644 --- a/source/Irrlicht/COpenGLExtensionHandler.h +++ b/source/Irrlicht/COpenGLExtensionHandler.h @@ -812,14 +812,16 @@ class COpenGLExtensionHandler u8 MaxUserClipPlanes; //! Number of auxiliary buffers u8 MaxAuxBuffers; + //! Number of rendertargets available as MRTs + u8 MaxMultipleRenderTargets; //! Optimal number of indices per meshbuffer u32 MaxIndices; //! Maximal texture dimension u32 MaxTextureSize; + //! Maximal vertices handled by geometry shaders + u32 MaxGeometryVerticesOut; //! Maximal LOD Bias f32 MaxTextureLODBias; - //! Number of rendertargets available as MRTs - u8 MaxMultipleRenderTargets; //! Minimal and maximal supported thickness for lines without smoothing GLfloat DimAliasedLine[2]; //! Minimal and maximal supported thickness for points without smoothing @@ -850,6 +852,7 @@ class COpenGLExtensionHandler void extGlGenPrograms(GLsizei n, GLuint *programs); void extGlBindProgram(GLenum target, GLuint program); void extGlProgramString(GLenum target, GLenum format, GLsizei len, const GLvoid *string); + void extGlLoadProgram(GLenum target, GLuint id, GLsizei len, const GLubyte *string); void extGlDeletePrograms(GLsizei n, const GLuint *programs); void extGlProgramLocalParameter4fv(GLenum, GLuint, const GLfloat *); GLhandleARB extGlCreateShaderObject(GLenum shaderType); @@ -904,6 +907,7 @@ class COpenGLExtensionHandler void extGlEnableIndexed(GLenum target, GLuint index); void extGlDisableIndexed(GLenum target, GLuint index); void extGlBlendFuncIndexed(GLuint buf, GLenum src, GLenum dst); + void extGlProgramParameteri(GLhandleARB program, GLenum pname, GLint value); protected: @@ -914,9 +918,13 @@ class COpenGLExtensionHandler PFNGLACTIVETEXTUREARBPROC pGlActiveTextureARB; PFNGLCLIENTACTIVETEXTUREARBPROC pGlClientActiveTextureARB; PFNGLGENPROGRAMSARBPROC pGlGenProgramsARB; + PFNGLGENPROGRAMSNVPROC pGlGenProgramsNV; PFNGLBINDPROGRAMARBPROC pGlBindProgramARB; + PFNGLBINDPROGRAMNVPROC pGlBindProgramNV; + PFNGLDELETEPROGRAMSARBPROC pGlDeleteProgramsARB; + PFNGLDELETEPROGRAMSNVPROC pGlDeleteProgramsNV; PFNGLPROGRAMSTRINGARBPROC pGlProgramStringARB; - PFNGLDELETEPROGRAMSNVPROC pGlDeleteProgramsARB; + PFNGLLOADPROGRAMNVPROC pGlLoadProgramNV; PFNGLPROGRAMLOCALPARAMETER4FVARBPROC pGlProgramLocalParameter4fvARB; PFNGLCREATESHADEROBJECTARBPROC pGlCreateShaderObjectARB; PFNGLSHADERSOURCEARBPROC pGlShaderSourceARB; @@ -979,6 +987,8 @@ class COpenGLExtensionHandler PFNGLDISABLEINDEXEDEXTPROC pGlDisableIndexedEXT; PFNGLBLENDFUNCINDEXEDAMDPROC pGlBlendFuncIndexedAMD; PFNGLBLENDFUNCIPROC pGlBlendFunciARB; + PFNGLPROGRAMPARAMETERIARBPROC pGlProgramParameteriARB; + PFNGLPROGRAMPARAMETERIEXTPROC pGlProgramParameteriEXT; #endif }; @@ -1013,8 +1023,12 @@ inline void COpenGLExtensionHandler::extGlGenPrograms(GLsizei n, GLuint *program #ifdef _IRR_OPENGL_USE_EXTPOINTER_ if (pGlGenProgramsARB) pGlGenProgramsARB(n, programs); -#elif defined(GL_ARB_vertex_program) + else if (pGlGenProgramsNV) + pGlGenProgramsNV(n, programs); +#elif defined(GL_ARB_vertex_program) || defined(GL_ARB_fragment_program) glGenProgramsARB(n,programs); +#elif defined(GL_NV_vertex_program) || defined(GL_NV_fragment_program) + glGenProgramsNV(n,programs); #else os::Printer::log("glGenPrograms not supported", ELL_ERROR); #endif @@ -1025,8 +1039,12 @@ inline void COpenGLExtensionHandler::extGlBindProgram(GLenum target, GLuint prog #ifdef _IRR_OPENGL_USE_EXTPOINTER_ if (pGlBindProgramARB) pGlBindProgramARB(target, program); -#elif defined(GL_ARB_vertex_program) + else if (pGlBindProgramNV) + pGlBindProgramNV(target, program); +#elif defined(GL_ARB_vertex_program) || defined(GL_ARB_fragment_program) glBindProgramARB(target, program); +#elif defined(GL_NV_vertex_program) || defined(GL_NV_fragment_program) + glBindProgramNV(target, program); #else os::Printer::log("glBindProgram not supported", ELL_ERROR); #endif @@ -1037,20 +1055,36 @@ inline void COpenGLExtensionHandler::extGlProgramString(GLenum target, GLenum fo #ifdef _IRR_OPENGL_USE_EXTPOINTER_ if (pGlProgramStringARB) pGlProgramStringARB(target, format, len, string); -#elif defined(GL_ARB_vertex_program) +#elif defined(GL_ARB_vertex_program) || defined(GL_ARB_fragment_program) glProgramStringARB(target,format,len,string); #else os::Printer::log("glProgramString not supported", ELL_ERROR); #endif } +inline void COpenGLExtensionHandler::extGlLoadProgram(GLenum target, GLuint id, GLsizei len, const GLubyte *string) +{ +#ifdef _IRR_OPENGL_USE_EXTPOINTER_ + if (pGlLoadProgramNV) + pGlLoadProgramNV(target, id, len, string); +#elif defined(GL_NV_vertex_program) || defined(GL_NV_fragment_program) + glLoadProgramNV(target,id,len,string); +#else + os::Printer::log("glLoadProgram not supported", ELL_ERROR); +#endif +} + inline void COpenGLExtensionHandler::extGlDeletePrograms(GLsizei n, const GLuint *programs) { #ifdef _IRR_OPENGL_USE_EXTPOINTER_ if (pGlDeleteProgramsARB) pGlDeleteProgramsARB(n, programs); -#elif defined(GL_ARB_vertex_program) + else if (pGlDeleteProgramsNV) + pGlDeleteProgramsNV(n, programs); +#elif defined(GL_ARB_vertex_program) || defined(GL_ARB_fragment_program) glDeleteProgramsARB(n,programs); +#elif defined(GL_NV_vertex_program) || defined(GL_NV_fragment_program) + glDeleteProgramsNV(n,programs); #else os::Printer::log("glDeletePrograms not supported", ELL_ERROR); #endif @@ -1061,7 +1095,7 @@ inline void COpenGLExtensionHandler::extGlProgramLocalParameter4fv(GLenum n, GLu #ifdef _IRR_OPENGL_USE_EXTPOINTER_ if (pGlProgramLocalParameter4fvARB) pGlProgramLocalParameter4fvARB(n,i,f); -#elif defined(GL_ARB_vertex_program) +#elif defined(GL_ARB_vertex_program) || defined(GL_ARB_fragment_program) glProgramLocalParameter4fvARB(n,i,f); #else os::Printer::log("glProgramLocalParameter4fv not supported", ELL_ERROR); @@ -1746,6 +1780,28 @@ inline void COpenGLExtensionHandler::extGlBlendFuncIndexed(GLuint buf, GLenum sr } +inline void COpenGLExtensionHandler::extGlProgramParameteri(GLhandleARB program, GLenum pname, GLint value) +{ +#if defined(_IRR_OPENGL_USE_EXTPOINTER_) + if (queryFeature(EVDF_GEOMETRY_SHADER)) + { + if (pGlProgramParameteriARB) + pGlProgramParameteriARB(program, pname, value); + else if (pGlProgramParameteriEXT) + pGlProgramParameteriEXT(program, pname, value); + } +#elif defined(GL_ARB_geometry_shader4) + glProgramParameteriARB(program, pname, value); +#elif defined(GL_EXT_geometry_shader4) + glProgramParameteriEXT(program, pname, value); +#elif defined(GL_NV_geometry_program4) || defined(GL_NV_geometry_shader4) + glProgramParameteriNV(program, pname, value); +#else + os::Printer::log("glProgramParameteri not supported", ELL_ERROR); +#endif +} + + } } diff --git a/source/Irrlicht/COpenGLMaterialRenderer.h b/source/Irrlicht/COpenGLMaterialRenderer.h index 59db13aa..f8d2f0d5 100644 --- a/source/Irrlicht/COpenGLMaterialRenderer.h +++ b/source/Irrlicht/COpenGLMaterialRenderer.h @@ -10,49 +10,6 @@ #include "COpenGLDriver.h" #include "IMaterialRenderer.h" -#if defined(_IRR_OSX_PLATFORM_) - #define GL_COMBINE_EXT 0x8570 - #define GL_COMBINE_RGB_EXT 0x8571 - #define GL_COMBINE_ALPHA_EXT 0x8572 - #define GL_RGB_SCALE_EXT 0x8573 - #define GL_ADD_SIGNED_EXT 0x8574 - #define GL_INTERPOLATE_EXT 0x8575 - #define GL_CONSTANT_EXT 0x8576 - #define GL_PRIMARY_COLOR_EXT 0x8577 - #define GL_PREVIOUS_EXT 0x8578 - #define GL_SOURCE0_RGB_EXT 0x8580 - #define GL_SOURCE1_RGB_EXT 0x8581 - #define GL_SOURCE2_RGB_EXT 0x8582 - #define GL_SOURCE3_RGB_EXT 0x8583 - #define GL_SOURCE4_RGB_EXT 0x8584 - #define GL_SOURCE5_RGB_EXT 0x8585 - #define GL_SOURCE6_RGB_EXT 0x8586 - #define GL_SOURCE7_RGB_EXT 0x8587 - #define GL_SOURCE0_ALPHA_EXT 0x8588 - #define GL_SOURCE1_ALPHA_EXT 0x8589 - #define GL_SOURCE2_ALPHA_EXT 0x858A - #define GL_SOURCE3_ALPHA_EXT 0x858B - #define GL_SOURCE4_ALPHA_EXT 0x858C - #define GL_SOURCE5_ALPHA_EXT 0x858D - #define GL_SOURCE6_ALPHA_EXT 0x858E - #define GL_SOURCE7_ALPHA_EXT 0x858F - #define GL_OPERAND0_RGB_EXT 0x8590 - #define GL_OPERAND1_RGB_EXT 0x8591 - #define GL_OPERAND2_RGB_EXT 0x8592 - #define GL_OPERAND3_RGB_EXT 0x8593 - #define GL_OPERAND4_RGB_EXT 0x8594 - #define GL_OPERAND5_RGB_EXT 0x8595 - #define GL_OPERAND6_RGB_EXT 0x8596 - #define GL_OPERAND7_RGB_EXT 0x8597 - #define GL_OPERAND0_ALPHA_EXT 0x8598 - #define GL_OPERAND1_ALPHA_EXT 0x8599 - #define GL_OPERAND2_ALPHA_EXT 0x859A - #define GL_OPERAND3_ALPHA_EXT 0x859B - #define GL_OPERAND4_ALPHA_EXT 0x859C - #define GL_OPERAND5_ALPHA_EXT 0x859D - #define GL_OPERAND6_ALPHA_EXT 0x859E - #define GL_OPERAND7_ALPHA_EXT 0x859F -#endif namespace irr { @@ -87,7 +44,6 @@ public: bool resetAllRenderstates, IMaterialRendererServices* services) { Driver->disableTextures(1); - Driver->setActiveTexture(0, material.getTexture(0)); Driver->setBasicRenderStates(material, lastMaterial, resetAllRenderstates); if (resetAllRenderstates || (material.MaterialType != lastMaterial.MaterialType)) @@ -112,7 +68,6 @@ public: bool resetAllRenderstates, IMaterialRendererServices* services) { Driver->disableTextures(1); - Driver->setActiveTexture(0, material.getTexture(0)); Driver->setBasicRenderStates(material, lastMaterial, resetAllRenderstates); // if (material.MaterialType != lastMaterial.MaterialType || @@ -124,12 +79,19 @@ public: u32 alphaSource; unpack_texureBlendFunc ( srcFact, dstFact, modulate, alphaSource, material.MaterialTypeParam ); +#ifdef GL_ARB_texture_env_combine + glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB); + glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE); + glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE); + glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PREVIOUS_ARB); + glTexEnvf(GL_TEXTURE_ENV, GL_RGB_SCALE_ARB, (f32) modulate ); +#else glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT); glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_MODULATE); glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT, GL_TEXTURE); - glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE1_RGB_EXT, GL_PREVIOUS_EXT); - + glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE1_RGB_EXT, GL_PREVIOUS_EXT); glTexEnvf(GL_TEXTURE_ENV, GL_RGB_SCALE_EXT, (f32) modulate ); +#endif glBlendFunc( getGLBlend(srcFact), getGLBlend(dstFact) ); glEnable(GL_ALPHA_TEST); @@ -140,22 +102,42 @@ public: { if (alphaSource==EAS_VERTEX_COLOR) { +#ifdef GL_ARB_texture_env_combine + glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE); + glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_PRIMARY_COLOR_ARB); +#else glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_EXT, GL_REPLACE); glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT, GL_PRIMARY_COLOR_EXT); +#endif } else if (alphaSource==EAS_TEXTURE) { +#ifdef GL_ARB_texture_env_combine + glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE); + glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_TEXTURE); +#else glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_EXT, GL_REPLACE); glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT, GL_TEXTURE); +#endif } else { +#ifdef GL_ARB_texture_env_combine + glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_MODULATE); + glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_TEXTURE); + glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA_ARB, GL_PRIMARY_COLOR_ARB); +#else glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_EXT, GL_MODULATE); glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT, GL_TEXTURE); glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA_EXT, GL_PRIMARY_COLOR_EXT); +#endif } +#ifdef GL_ARB_texture_env_combine + glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PRIMARY_COLOR_ARB); +#else glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE1_RGB_EXT, GL_PRIMARY_COLOR_EXT); +#endif } } } @@ -163,9 +145,15 @@ public: virtual void OnUnsetMaterial() { glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); +#ifdef GL_ARB_texture_env_combine + glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_MODULATE); + glTexEnvf(GL_TEXTURE_ENV, GL_RGB_SCALE_ARB, 1.f ); + glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PREVIOUS_ARB); +#else glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_EXT, GL_MODULATE); glTexEnvf(GL_TEXTURE_ENV, GL_RGB_SCALE_EXT, 1.f ); glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE1_RGB_EXT, GL_PREVIOUS_EXT); +#endif glDisable(GL_BLEND); glDisable(GL_ALPHA_TEST); @@ -215,8 +203,6 @@ public: bool resetAllRenderstates, IMaterialRendererServices* services) { Driver->disableTextures(2); - Driver->setActiveTexture(1, material.getTexture(1)); - Driver->setActiveTexture(0, material.getTexture(0)); Driver->setBasicRenderStates(material, lastMaterial, resetAllRenderstates); if (material.MaterialType != lastMaterial.MaterialType || resetAllRenderstates) @@ -224,6 +210,16 @@ public: if (Driver->queryFeature(EVDF_MULTITEXTURE)) { Driver->extGlActiveTexture(GL_TEXTURE1_ARB); +#ifdef GL_ARB_texture_env_combine + glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB); + glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE); + glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_PRIMARY_COLOR_ARB); + glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_INTERPOLATE); + glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_PREVIOUS_ARB); + glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_TEXTURE); + glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE2_RGB_ARB, GL_PRIMARY_COLOR); + glTexEnvf(GL_TEXTURE_ENV, GL_OPERAND2_RGB_ARB, GL_SRC_ALPHA); +#else glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT); glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_EXT, GL_REPLACE); glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT, GL_PRIMARY_COLOR_EXT); @@ -232,6 +228,7 @@ public: glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE1_RGB_EXT, GL_TEXTURE); glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE2_RGB_EXT, GL_PRIMARY_COLOR); glTexEnvf(GL_TEXTURE_ENV, GL_OPERAND2_RGB_EXT, GL_SRC_ALPHA); +#endif } } } @@ -242,7 +239,11 @@ public: { Driver->extGlActiveTexture(GL_TEXTURE1_ARB); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); +#ifdef GL_ARB_texture_env_combine + glTexEnvf(GL_TEXTURE_ENV, GL_OPERAND2_RGB_ARB, GL_SRC_COLOR); +#else glTexEnvf(GL_TEXTURE_ENV, GL_OPERAND2_RGB_EXT, GL_SRC_COLOR); +#endif Driver->extGlActiveTexture(GL_TEXTURE0_ARB); } } @@ -261,7 +262,6 @@ public: bool resetAllRenderstates, IMaterialRendererServices* services) { Driver->disableTextures(1); - Driver->setActiveTexture(0, material.getTexture(0)); Driver->setBasicRenderStates(material, lastMaterial, resetAllRenderstates); if ((material.MaterialType != lastMaterial.MaterialType) || resetAllRenderstates) @@ -297,20 +297,25 @@ public: bool resetAllRenderstates, IMaterialRendererServices* services) { Driver->disableTextures(1); - Driver->setActiveTexture(0, material.getTexture(0)); Driver->setBasicRenderStates(material, lastMaterial, resetAllRenderstates); if (material.MaterialType != lastMaterial.MaterialType || resetAllRenderstates) { +#ifdef GL_ARB_texture_env_combine + glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB); + glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE); + glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_PRIMARY_COLOR_ARB); + glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE); + glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_PREVIOUS_ARB); + glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_TEXTURE); +#else glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT); - glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_EXT, GL_REPLACE); glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT, GL_PRIMARY_COLOR_EXT ); - glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_MODULATE); glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT, GL_PREVIOUS_EXT); glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE1_RGB_EXT, GL_TEXTURE); - +#endif glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); glEnable(GL_BLEND); } @@ -320,8 +325,13 @@ public: { // default values glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); +#ifdef GL_ARB_texture_env_combine + glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_MODULATE ); + glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_TEXTURE ); +#else glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_EXT, GL_MODULATE ); glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT, GL_TEXTURE ); +#endif glDisable(GL_BLEND); } @@ -345,20 +355,26 @@ public: bool resetAllRenderstates, IMaterialRendererServices* services) { Driver->disableTextures(1); - Driver->setActiveTexture(0, material.getTexture(0)); Driver->setBasicRenderStates(material, lastMaterial, resetAllRenderstates); if (material.MaterialType != lastMaterial.MaterialType || resetAllRenderstates || material.MaterialTypeParam != lastMaterial.MaterialTypeParam ) { +#ifdef GL_ARB_texture_env_combine + glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB); + glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE); + glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE); + glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PREVIOUS_ARB); + glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE); + glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_TEXTURE); +#else glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT); glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_MODULATE); glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT, GL_TEXTURE); glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE1_RGB_EXT, GL_PREVIOUS_EXT); - glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_EXT, GL_REPLACE); glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT, GL_TEXTURE); - +#endif glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glEnable(GL_BLEND); glEnable(GL_ALPHA_TEST); @@ -370,7 +386,11 @@ public: virtual void OnUnsetMaterial() { glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); +#ifdef GL_ARB_texture_env_combine + glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_MODULATE ); +#else glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_EXT, GL_MODULATE ); +#endif glDisable(GL_ALPHA_TEST); glDisable(GL_BLEND); } @@ -395,7 +415,6 @@ public: bool resetAllRenderstates, IMaterialRendererServices* services) { Driver->disableTextures(1); - Driver->setActiveTexture(0, material.getTexture(0)); Driver->setBasicRenderStates(material, lastMaterial, resetAllRenderstates); if (material.MaterialType != lastMaterial.MaterialType || resetAllRenderstates) @@ -431,8 +450,6 @@ public: bool resetAllRenderstates, IMaterialRendererServices* services) { Driver->disableTextures(2); - Driver->setActiveTexture(1, material.getTexture(1)); - Driver->setActiveTexture(0, material.getTexture(0)); Driver->setBasicRenderStates(material, lastMaterial, resetAllRenderstates); if (material.MaterialType != lastMaterial.MaterialType || resetAllRenderstates) @@ -460,32 +477,58 @@ public: // lightmap Driver->extGlActiveTexture(GL_TEXTURE1_ARB); - glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT); +#ifdef GL_ARB_texture_env_combine + glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB); + if (material.MaterialType == EMT_LIGHTMAP_ADD) + glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_ADD); + else + glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE); + + glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_PREVIOUS_ARB); + glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_TEXTURE); + glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_MODULATE); + glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_PREVIOUS_ARB); + glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA_ARB, GL_PREVIOUS_ARB); +#else + glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT); + if (material.MaterialType == EMT_LIGHTMAP_ADD) glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_ADD); else glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_MODULATE); - + glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT, GL_PREVIOUS_EXT); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_EXT, GL_TEXTURE); - glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_EXT, GL_MODULATE); - glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT, GL_PREVIOUS_ARB); - glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA_EXT, GL_PREVIOUS_ARB); + glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT, GL_PREVIOUS_EXT); + glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA_EXT, GL_PREVIOUS_EXT); +#endif switch (material.MaterialType) { case EMT_LIGHTMAP_M4: case EMT_LIGHTMAP_LIGHTING_M4: +#ifdef GL_ARB_texture_env_combine + glTexEnvf(GL_TEXTURE_ENV, GL_RGB_SCALE_ARB, 4.0f); +#else glTexEnvf(GL_TEXTURE_ENV, GL_RGB_SCALE_EXT, 4.0f); +#endif break; case EMT_LIGHTMAP_M2: case EMT_LIGHTMAP_LIGHTING_M2: +#ifdef GL_ARB_texture_env_combine + glTexEnvf(GL_TEXTURE_ENV, GL_RGB_SCALE_ARB, 2.0f); +#else glTexEnvf(GL_TEXTURE_ENV, GL_RGB_SCALE_EXT, 2.0f); +#endif break; default: +#ifdef GL_ARB_texture_env_combine + glTexEnvf(GL_TEXTURE_ENV, GL_RGB_SCALE_ARB, 1.0f); +#else glTexEnvf(GL_TEXTURE_ENV, GL_RGB_SCALE_EXT, 1.0f); +#endif } Driver->extGlActiveTexture(GL_TEXTURE0_ARB); } @@ -497,7 +540,11 @@ public: if (Driver->queryFeature(EVDF_MULTITEXTURE)) { Driver->extGlActiveTexture(GL_TEXTURE1_ARB); +#ifdef GL_ARB_texture_env_combine + glTexEnvf(GL_TEXTURE_ENV, GL_RGB_SCALE_ARB, 1.f ); +#else glTexEnvf(GL_TEXTURE_ENV, GL_RGB_SCALE_EXT, 1.f ); +#endif glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); Driver->extGlActiveTexture(GL_TEXTURE0_ARB); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); @@ -519,8 +566,6 @@ public: bool resetAllRenderstates, IMaterialRendererServices* services) { Driver->disableTextures(2); - Driver->setActiveTexture(1, material.getTexture(1)); - Driver->setActiveTexture(0, material.getTexture(0)); Driver->setBasicRenderStates(material, lastMaterial, resetAllRenderstates); if (material.MaterialType != lastMaterial.MaterialType || resetAllRenderstates) @@ -531,10 +576,17 @@ public: if (Driver->queryFeature(EVDF_MULTITEXTURE)) { Driver->extGlActiveTexture(GL_TEXTURE1_ARB); +#ifdef GL_ARB_texture_env_combine + glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB); + glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_ADD_SIGNED_ARB); + glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_PREVIOUS_ARB); + glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_TEXTURE); +#else glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT); glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_ADD_SIGNED_EXT); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT, GL_PREVIOUS_EXT); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_EXT, GL_TEXTURE); +#endif } } } @@ -563,7 +615,6 @@ public: bool resetAllRenderstates, IMaterialRendererServices* services) { Driver->disableTextures(1); - Driver->setActiveTexture(0, material.getTexture(0)); // texture needs to be flipped for OpenGL core::matrix4 tmp = Driver->getTransform(ETS_TEXTURE_0); tmp[5]*=-1; @@ -600,8 +651,6 @@ public: bool resetAllRenderstates, IMaterialRendererServices* services) { Driver->disableTextures(2); - Driver->setActiveTexture(1, material.getTexture(1)); - Driver->setActiveTexture(0, material.getTexture(0)); Driver->setBasicRenderStates(material, lastMaterial, resetAllRenderstates); if (material.MaterialType != lastMaterial.MaterialType || resetAllRenderstates) @@ -609,10 +658,17 @@ public: if (Driver->queryFeature(EVDF_MULTITEXTURE)) { Driver->extGlActiveTexture(GL_TEXTURE1_ARB); +#ifdef GL_ARB_texture_env_combine + glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB); + glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE); + glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_PREVIOUS_ARB); + glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_TEXTURE); +#else glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT); glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_MODULATE); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT, GL_PREVIOUS_EXT); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_EXT, GL_TEXTURE); +#endif } glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP); glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP); @@ -650,8 +706,6 @@ public: bool resetAllRenderstates, IMaterialRendererServices* services) { Driver->disableTextures(2); - Driver->setActiveTexture(1, material.getTexture(1)); - Driver->setActiveTexture(0, material.getTexture(0)); Driver->setBasicRenderStates(material, lastMaterial, resetAllRenderstates); if (material.MaterialType != lastMaterial.MaterialType || resetAllRenderstates) @@ -659,10 +713,17 @@ public: if (Driver->queryFeature(EVDF_MULTITEXTURE)) { Driver->extGlActiveTexture(GL_TEXTURE1_ARB); +#ifdef GL_ARB_texture_env_combine + glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB); + glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE); + glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_PREVIOUS_ARB); + glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_TEXTURE); +#else glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT); glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_MODULATE); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT, GL_PREVIOUS_EXT); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_EXT, GL_TEXTURE); +#endif } glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP); glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP); diff --git a/source/Irrlicht/COpenGLSLMaterialRenderer.cpp b/source/Irrlicht/COpenGLSLMaterialRenderer.cpp index da64802e..a97e6817 100644 --- a/source/Irrlicht/COpenGLSLMaterialRenderer.cpp +++ b/source/Irrlicht/COpenGLSLMaterialRenderer.cpp @@ -35,6 +35,11 @@ COpenGLSLMaterialRenderer::COpenGLSLMaterialRenderer(video::COpenGLDriver* drive const c8* pixelShaderProgram, const c8* pixelShaderEntryPointName, E_PIXEL_SHADER_TYPE psCompileTarget, + const c8* geometryShaderProgram, + const c8* geometryShaderEntryPointName, + E_GEOMETRY_SHADER_TYPE gsCompileTarget, + scene::E_PRIMITIVE_TYPE inType, scene::E_PRIMITIVE_TYPE outType, + u32 verticesOut, IShaderConstantSetCallBack* callback, video::IMaterialRenderer* baseMaterial, s32 userData) @@ -58,7 +63,7 @@ COpenGLSLMaterialRenderer::COpenGLSLMaterialRenderer(video::COpenGLDriver* drive if (!Driver->queryFeature(EVDF_ARB_GLSL)) return; - init(outMaterialTypeNr, vertexShaderProgram, pixelShaderProgram); + init(outMaterialTypeNr, vertexShaderProgram, pixelShaderProgram, geometryShaderProgram); } @@ -96,9 +101,13 @@ COpenGLSLMaterialRenderer::~COpenGLSLMaterialRenderer() BaseMaterial->drop(); } + void COpenGLSLMaterialRenderer::init(s32& outMaterialTypeNr, - const c8* vertexShaderProgram, - const c8* pixelShaderProgram) + const c8* vertexShaderProgram, + const c8* pixelShaderProgram, + const c8* geometryShaderProgram, + scene::E_PRIMITIVE_TYPE inType, scene::E_PRIMITIVE_TYPE outType, + u32 verticesOut) { outMaterialTypeNr = -1; @@ -110,12 +119,32 @@ void COpenGLSLMaterialRenderer::init(s32& outMaterialTypeNr, if (!createShader(GL_VERTEX_SHADER_ARB, vertexShaderProgram)) return; - if (pixelShaderProgram) if (!createShader(GL_FRAGMENT_SHADER_ARB, pixelShaderProgram)) return; #endif +#if defined(GL_ARB_geometry_shader4) || defined(GL_EXT_geometry_shader4) || defined(GL_NV_geometry_program4) || defined(GL_NV_geometry_shader4) + if (geometryShaderProgram && Driver->queryFeature(EVDF_GEOMETRY_SHADER)) + { + if (!createShader(GL_GEOMETRY_SHADER_EXT, geometryShaderProgram)) + return; +#if defined(GL_ARB_geometry_shader4) || defined(GL_EXT_geometry_shader4) || defined(GL_NV_geometry_shader4) + Driver->extGlProgramParameteri(Program, GL_GEOMETRY_INPUT_TYPE_EXT, Driver->primitiveTypeToGL(inType)); + Driver->extGlProgramParameteri(Program, GL_GEOMETRY_OUTPUT_TYPE_EXT, Driver->primitiveTypeToGL(outType)); + if (verticesOut==0) + Driver->extGlProgramParameteri(Program, GL_GEOMETRY_VERTICES_OUT_EXT, Driver->MaxGeometryVerticesOut); + else + Driver->extGlProgramParameteri(Program, GL_GEOMETRY_VERTICES_OUT_EXT, core::min_(verticesOut, Driver->MaxGeometryVerticesOut)); +#elif defined(GL_NV_geometry_program4) + if (verticesOut==0) + Driver->extGlProgramVertexLimit(GL_GEOMETRY_PROGRAM_NV, Driver->MaxGeometryVerticesOut); + else + Driver->extGlProgramVertexLimit(GL_GEOMETRY_PROGRAM_NV, core::min_(verticesOut, Driver->MaxGeometryVerticesOut)); +#endif + } +#endif + if (!linkProgram()) return; @@ -128,7 +157,7 @@ bool COpenGLSLMaterialRenderer::OnRender(IMaterialRendererServices* service, E_VERTEX_TYPE vtxtype) { // call callback to set shader constants - if (CallBack && (Program)) + if (CallBack && Program) CallBack->OnSetConstants(this, UserData); return true; @@ -167,18 +196,21 @@ void COpenGLSLMaterialRenderer::OnUnsetMaterial() BaseMaterial->OnUnsetMaterial(); } + //! Returns if the material is transparent. bool COpenGLSLMaterialRenderer::isTransparent() const { return BaseMaterial ? BaseMaterial->isTransparent() : false; } + bool COpenGLSLMaterialRenderer::createProgram() { Program = Driver->extGlCreateProgramObject(); return true; } + bool COpenGLSLMaterialRenderer::createShader(GLenum shaderType, const char* shader) { GLhandleARB shaderHandle = Driver->extGlCreateShaderObject(shaderType); @@ -268,6 +300,8 @@ bool COpenGLSLMaterialRenderer::linkProgram() return false; } + // seems that some implementations use an extra null terminator + ++maxlen; c8 *buf = new c8[maxlen]; UniformInfo.clear(); diff --git a/source/Irrlicht/COpenGLSLMaterialRenderer.h b/source/Irrlicht/COpenGLSLMaterialRenderer.h index 4cffbefb..e857e4ce 100644 --- a/source/Irrlicht/COpenGLSLMaterialRenderer.h +++ b/source/Irrlicht/COpenGLSLMaterialRenderer.h @@ -54,15 +54,21 @@ public: COpenGLSLMaterialRenderer( COpenGLDriver* driver, s32& outMaterialTypeNr, - const c8* vertexShaderProgram, - const c8* vertexShaderEntryPointName, - E_VERTEX_SHADER_TYPE vsCompileTarget, - const c8* pixelShaderProgram, - const c8* pixelShaderEntryPointName, - E_PIXEL_SHADER_TYPE psCompileTarget, - IShaderConstantSetCallBack* callback, - IMaterialRenderer* baseMaterial, - s32 userData); + const c8* vertexShaderProgram = 0, + const c8* vertexShaderEntryPointName = 0, + E_VERTEX_SHADER_TYPE vsCompileTarget = video::EVST_VS_1_1, + const c8* pixelShaderProgram = 0, + const c8* pixelShaderEntryPointName = 0, + E_PIXEL_SHADER_TYPE psCompileTarget = video::EPST_PS_1_1, + const c8* geometryShaderProgram = 0, + const c8* geometryShaderEntryPointName = "main", + E_GEOMETRY_SHADER_TYPE gsCompileTarget = EGST_GS_4_0, + scene::E_PRIMITIVE_TYPE inType = scene::EPT_TRIANGLES, + scene::E_PRIMITIVE_TYPE outType = scene::EPT_TRIANGLE_STRIP, + u32 verticesOut = 0, + IShaderConstantSetCallBack* callback = 0, + IMaterialRenderer* baseMaterial = 0, + s32 userData = 0); //! Destructor virtual ~COpenGLSLMaterialRenderer(); @@ -96,7 +102,11 @@ protected: void init(s32& outMaterialTypeNr, const c8* vertexShaderProgram, - const c8* pixelShaderProgram); + const c8* pixelShaderProgram, + const c8* geometryShaderProgram, + scene::E_PRIMITIVE_TYPE inType=scene::EPT_TRIANGLES, + scene::E_PRIMITIVE_TYPE outType=scene::EPT_TRIANGLE_STRIP, + u32 verticesOut=0); bool createProgram(); bool createShader(GLenum shaderType, const char* shader); diff --git a/source/Irrlicht/COpenGLShaderMaterialRenderer.cpp b/source/Irrlicht/COpenGLShaderMaterialRenderer.cpp index aa776792..279642b7 100644 --- a/source/Irrlicht/COpenGLShaderMaterialRenderer.cpp +++ b/source/Irrlicht/COpenGLShaderMaterialRenderer.cpp @@ -85,8 +85,9 @@ COpenGLShaderMaterialRenderer::~COpenGLShaderMaterialRenderer() } -void COpenGLShaderMaterialRenderer::init(s32& outMaterialTypeNr, const c8* vertexShaderProgram, - const c8* pixelShaderProgram, E_VERTEX_TYPE type) +void COpenGLShaderMaterialRenderer::init(s32& outMaterialTypeNr, + const c8* vertexShaderProgram, const c8* pixelShaderProgram, + E_VERTEX_TYPE type) { outMaterialTypeNr = -1; @@ -119,41 +120,43 @@ void COpenGLShaderMaterialRenderer::OnSetMaterial(const video::SMaterial& materi { if (material.MaterialType != lastMaterial.MaterialType || resetAllRenderstates) { -#ifdef GL_ARB_vertex_program if (VertexShader) { // set new vertex shader +#ifdef GL_ARB_vertex_program Driver->extGlBindProgram(GL_VERTEX_PROGRAM_ARB, VertexShader); glEnable(GL_VERTEX_PROGRAM_ARB); - } +#elif defined(GL_NV_vertex_program) + Driver->extGlBindProgram(GL_VERTEX_PROGRAM_NV, VertexShader); + glEnable(GL_VERTEX_PROGRAM_NV); #endif + } // set new pixel shader -#ifdef GL_ARB_fragment_program if (PixelShader[0]) { - if (!material.FogEnable) - { - Driver->extGlBindProgram(GL_FRAGMENT_PROGRAM_ARB, PixelShader[0]); - } - else + GLuint nextShader=PixelShader[0]; + if (material.FogEnable) { GLint curFogMode; glGetIntegerv(GL_FOG_MODE, &curFogMode); // if (Driver->LinearFog && PixelShader[1]) if (curFogMode==GL_LINEAR && PixelShader[1]) - Driver->extGlBindProgram(GL_FRAGMENT_PROGRAM_ARB, PixelShader[1]); + nextShader=PixelShader[1]; // else if (!Driver->LinearFog && PixelShader[2]) else if (curFogMode==GL_EXP && PixelShader[2]) - Driver->extGlBindProgram(GL_FRAGMENT_PROGRAM_ARB, PixelShader[2]); + nextShader=PixelShader[2]; else if (curFogMode==GL_EXP2 && PixelShader[3]) - Driver->extGlBindProgram(GL_FRAGMENT_PROGRAM_ARB, PixelShader[3]); - else - Driver->extGlBindProgram(GL_FRAGMENT_PROGRAM_ARB, PixelShader[0]); + nextShader=PixelShader[3]; } +#ifdef GL_ARB_fragment_program + Driver->extGlBindProgram(GL_FRAGMENT_PROGRAM_ARB, nextShader); glEnable(GL_FRAGMENT_PROGRAM_ARB); - } +#elif defined(GL_NV_fragment_program) + Driver->extGlBindProgram(GL_FRAGMENT_PROGRAM_NV, nextShader); + glEnable(GL_FRAGMENT_PROGRAM_NV); #endif + } if (BaseMaterial) BaseMaterial->OnSetMaterial(material, material, true, services); @@ -175,11 +178,17 @@ void COpenGLShaderMaterialRenderer::OnUnsetMaterial() #ifdef GL_ARB_vertex_program if (VertexShader) glDisable(GL_VERTEX_PROGRAM_ARB); +#elif defined(GL_NV_vertex_program) + if (VertexShader) + glDisable(GL_VERTEX_PROGRAM_NV); #endif #ifdef GL_ARB_fragment_program if (PixelShader[0]) glDisable(GL_FRAGMENT_PROGRAM_ARB); +#elif defined(GL_NV_fragment_program) + if (PixelShader[0]) + glDisable(GL_FRAGMENT_PROGRAM_NV); #endif if (BaseMaterial) @@ -197,24 +206,33 @@ bool COpenGLShaderMaterialRenderer::isTransparent() const // This method needs a properly cleaned error state before the checked instruction is called bool COpenGLShaderMaterialRenderer::checkError(const irr::c8* type) { -#ifdef GL_ARB_vertex_program +#if defined(GL_ARB_vertex_program) || defined(GL_NV_vertex_program) || defined(GL_ARB_fragment_program) || defined(GL_NV_fragment_program) GLenum g = glGetError(); - if (g != GL_NO_ERROR) - { - GLint errPos; - glGetIntegerv( GL_PROGRAM_ERROR_POSITION_ARB, &errPos ); + if (g == GL_NO_ERROR) + return false; - core::stringc errString = type; - errString += " compilation failed at position "; - errString += core::stringc(s32(errPos)); - errString += ":\n"; - errString += reinterpret_cast(glGetString(GL_PROGRAM_ERROR_STRING_ARB)); + core::stringc errString = type; + errString += " compilation failed"; - os::Printer::log(errString.c_str(), ELL_ERROR); - return true; - } + errString += " at position "; + GLint errPos=-1; +#if defined(GL_ARB_vertex_program) || defined(GL_ARB_fragment_program) + glGetIntegerv( GL_PROGRAM_ERROR_POSITION_ARB, &errPos ); +#else + glGetIntegerv( GL_PROGRAM_ERROR_POSITION_NV, &errPos ); #endif - return false; + errString += core::stringc(s32(errPos)); + errString += ":\n"; +#if defined(GL_ARB_vertex_program) || defined(GL_ARB_fragment_program) + errString += reinterpret_cast(glGetString(GL_PROGRAM_ERROR_STRING_ARB)); +#else + errString += reinterpret_cast(glGetString(GL_PROGRAM_ERROR_STRING_NV)); +#endif +#else + core::stringc errString("Shaders not supported."); +#endif + os::Printer::log(errString.c_str(), ELL_ERROR); + return true; } @@ -244,17 +262,25 @@ bool COpenGLShaderMaterialRenderer::createPixelShader(const c8* pxsh) } shdr += inshdr.subString(pos+16, inshdr.size()-pos-16); } -#ifdef GL_ARB_fragment_program Driver->extGlGenPrograms(1, &PixelShader[i]); +#ifdef GL_ARB_fragment_program Driver->extGlBindProgram(GL_FRAGMENT_PROGRAM_ARB, PixelShader[i]); +#elif defined GL_NV_fragment_program + Driver->extGlBindProgram(GL_FRAGMENT_PROGRAM_NV, PixelShader[i]); +#endif // clear error buffer while(glGetError() != GL_NO_ERROR) {} +#ifdef GL_ARB_fragment_program // compile Driver->extGlProgramString(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, - shdr.size(), shdr.c_str()); + shdr.size(), shdr.c_str()); +#elif defined GL_NV_fragment_program + Driver->extGlLoadProgram(GL_FRAGMENT_PROGRAM_NV, PixelShader[i], + shdr.size(), shdr.c_str()); +#endif if (checkError("Pixel shader")) { @@ -263,9 +289,6 @@ bool COpenGLShaderMaterialRenderer::createPixelShader(const c8* pxsh) return false; } -#else - return false; -#endif } return true; @@ -277,17 +300,25 @@ bool COpenGLShaderMaterialRenderer::createVertexShader(const c8* vtxsh) if (!vtxsh) return true; -#ifdef GL_ARB_vertex_program Driver->extGlGenPrograms(1, &VertexShader); +#ifdef GL_ARB_vertex_program Driver->extGlBindProgram(GL_VERTEX_PROGRAM_ARB, VertexShader); +#elif defined GL_NV_vertex_program + Driver->extGlBindProgram(GL_VERTEX_PROGRAM_NV, VertexShader); +#endif // clear error buffer while(glGetError() != GL_NO_ERROR) {} // compile +#ifdef GL_ARB_vertex_program Driver->extGlProgramString(GL_VERTEX_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, - (GLsizei)strlen(vtxsh), vtxsh); + (GLsizei)strlen(vtxsh), vtxsh); +#elif defined GL_NV_vertex_program + Driver->extGlLoadProgram(GL_VERTEX_PROGRAM_NV, VertexShader, + (GLsizei)strlen(vtxsh), vtxsh); +#endif if (checkError("Vertex shader")) { @@ -296,9 +327,6 @@ bool COpenGLShaderMaterialRenderer::createVertexShader(const c8* vtxsh) return false; } -#else - return false; -#endif return true; } @@ -307,5 +335,5 @@ bool COpenGLShaderMaterialRenderer::createVertexShader(const c8* vtxsh) } // end namespace video } // end namespace irr - #endif + diff --git a/source/Irrlicht/COpenGLTexture.cpp b/source/Irrlicht/COpenGLTexture.cpp index 9c045aa4..a713fd4d 100644 --- a/source/Irrlicht/COpenGLTexture.cpp +++ b/source/Irrlicht/COpenGLTexture.cpp @@ -21,8 +21,8 @@ namespace video { //! constructor for usual textures -COpenGLTexture::COpenGLTexture(IImage* origImage, const io::path& name, COpenGLDriver* driver) - : ITexture(name), ColorFormat(ECF_A8R8G8B8), Driver(driver), Image(0), +COpenGLTexture::COpenGLTexture(IImage* origImage, const io::path& name, void* mipmapData, COpenGLDriver* driver) + : ITexture(name), ColorFormat(ECF_A8R8G8B8), Driver(driver), Image(0), MipImage(0), TextureName(0), InternalFormat(GL_RGBA), PixelFormat(GL_BGRA_EXT), PixelType(GL_UNSIGNED_BYTE), IsRenderTarget(false), AutomaticMipmapUpdate(false), @@ -33,19 +33,22 @@ COpenGLTexture::COpenGLTexture(IImage* origImage, const io::path& name, COpenGLD #endif HasMipMaps = Driver->getTextureCreationFlag(ETCF_CREATE_MIP_MAPS); - getImageData(origImage); + getImageValues(origImage); glGenTextures(1, &TextureName); if (ImageSize==TextureSize) - Image = new CImage(ColorFormat, origImage); + { + Image = new CImage(ColorFormat, ImageSize); + origImage->copyTo(Image); + } else { Image = new CImage(ColorFormat, TextureSize); // scale texture origImage->copyToScaling(Image); } - copyTexture(); + uploadTexture(true, mipmapData); if (!KeepImage) { Image->drop(); @@ -53,9 +56,10 @@ COpenGLTexture::COpenGLTexture(IImage* origImage, const io::path& name, COpenGLD } } + //! constructor for basic setup (only for derived classes) COpenGLTexture::COpenGLTexture(const io::path& name, COpenGLDriver* driver) - : ITexture(name), ColorFormat(ECF_A8R8G8B8), Driver(driver), Image(0), + : ITexture(name), ColorFormat(ECF_A8R8G8B8), Driver(driver), Image(0), MipImage(0), TextureName(0), InternalFormat(GL_RGBA), PixelFormat(GL_BGRA_EXT), PixelType(GL_UNSIGNED_BYTE), HasMipMaps(true), IsRenderTarget(false), AutomaticMipmapUpdate(false), @@ -77,6 +81,7 @@ COpenGLTexture::~COpenGLTexture() } +//! Choose best matching color format, based on texture creation flags ECOLOR_FORMAT COpenGLTexture::getBestColorFormat(ECOLOR_FORMAT format) { ECOLOR_FORMAT destFormat = ECF_A8R8G8B8; @@ -120,6 +125,7 @@ ECOLOR_FORMAT COpenGLTexture::getBestColorFormat(ECOLOR_FORMAT format) } +//! Get opengl values for the GPU texture storage GLint COpenGLTexture::getOpenGLFormatAndParametersFromColorFormat(ECOLOR_FORMAT format, GLint& filtering, GLenum& colorformat, @@ -231,7 +237,8 @@ GLint COpenGLTexture::getOpenGLFormatAndParametersFromColorFormat(ECOLOR_FORMAT } -void COpenGLTexture::getImageData(IImage* image) +// prepare values ImageSize, TextureSize, and ColorFormat based on image +void COpenGLTexture::getImageValues(IImage* image) { if (!image) { @@ -265,25 +272,35 @@ void COpenGLTexture::getImageData(IImage* image) //! copies the the texture into an open gl texture. -void COpenGLTexture::copyTexture(bool newTexture) +void COpenGLTexture::uploadTexture(bool newTexture, void* mipmapData, u32 level) { - if (!Image) + // check which image needs to be uploaded + IImage* image = level?MipImage:Image; + if (!image) { os::Printer::log("No image for OpenGL texture to upload", ELL_ERROR); return; } + // get correct opengl color data values + GLenum oldInternalFormat = InternalFormat; GLint filtering; InternalFormat = getOpenGLFormatAndParametersFromColorFormat(ColorFormat, filtering, PixelFormat, PixelType); + // make sure we don't change the internal format of existing images + if (!newTexture) + InternalFormat=oldInternalFormat; + Driver->setActiveTexture(0, this); if (Driver->testGLError()) os::Printer::log("Could not bind Texture", ELL_ERROR); - if (newTexture) + // mipmap handling for main texture + if (!level && newTexture) { #ifndef DISABLE_MIPMAPPING #ifdef GL_SGIS_generate_mipmap - if (HasMipMaps && Driver->queryFeature(EVDF_MIP_MAP_AUTO_UPDATE)) + // auto generate if possible and no mipmap data is given + if (HasMipMaps && !mipmapData && Driver->queryFeature(EVDF_MIP_MAP_AUTO_UPDATE)) { if (Driver->getTextureCreationFlag(ETCF_OPTIMIZED_FOR_SPEED)) glHint(GL_GENERATE_MIPMAP_HINT_SGIS, GL_FASTEST); @@ -298,8 +315,10 @@ void COpenGLTexture::copyTexture(bool newTexture) else #endif { + // Either generate manually due to missing capability + // or use predefined mipmap data AutomaticMipmapUpdate=false; - regenerateMipMapLevels(); + regenerateMipMapLevels(mipmapData); } if (HasMipMaps) // might have changed in regenerateMipMapLevels { @@ -308,10 +327,10 @@ void COpenGLTexture::copyTexture(bool newTexture) glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); } else - #else +#else HasMipMaps=false; - os::Printer::log("Did not create OpenGL texture mip maps.", ELL_ERROR); - #endif + os::Printer::log("Did not create OpenGL texture mip maps.", ELL_INFORMATION); +#endif { // enable bilinear filter without mipmaps glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); @@ -319,14 +338,15 @@ void COpenGLTexture::copyTexture(bool newTexture) } } - void* source = Image->lock(); + // now get image data and upload to GPU + void* source = image->lock(); if (newTexture) - glTexImage2D(GL_TEXTURE_2D, 0, InternalFormat, Image->getDimension().Width, - Image->getDimension().Height, 0, PixelFormat, PixelType, source); + glTexImage2D(GL_TEXTURE_2D, level, InternalFormat, image->getDimension().Width, + image->getDimension().Height, 0, PixelFormat, PixelType, source); else - glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, Image->getDimension().Width, - Image->getDimension().Height, PixelFormat, PixelType, source); - Image->unlock(); + glTexSubImage2D(GL_TEXTURE_2D, level, 0, 0, image->getDimension().Width, + image->getDimension().Height, PixelFormat, PixelType, source); + image->unlock(); if (Driver->testGLError()) os::Printer::log("Could not glTexImage2D", ELL_ERROR); @@ -334,24 +354,47 @@ void COpenGLTexture::copyTexture(bool newTexture) //! lock function -void* COpenGLTexture::lock(bool readOnly) +void* COpenGLTexture::lock(bool readOnly, u32 mipmapLevel) { + // store info about which image is locked + IImage* image = (mipmapLevel==0)?Image:MipImage; ReadOnlyLock |= readOnly; + MipLevelStored = mipmapLevel; - if (!Image || IsRenderTarget) + // if data not available or might have changed on GPU download it + if (!image || IsRenderTarget) { // prepare the data storage if necessary - if (!Image) - Image = new CImage(ECF_A8R8G8B8, ImageSize); - if (!Image) + if (!image) + { + if (mipmapLevel) + { + u32 i=0; + u32 width = TextureSize.Width; + u32 height = TextureSize.Height; + do + { + if (width>1) + width>>=1; + if (height>1) + height>>=1; + ++i; + } + while (i != mipmapLevel); + image = new CImage(ECF_A8R8G8B8, core::dimension2du(width,height)); + } + else + image = new CImage(ECF_A8R8G8B8, ImageSize); + ColorFormat = ECF_A8R8G8B8; + } + if (!image) return 0; - u8* pPixels = static_cast(Image->lock()); - if (!pPixels) - { + u8* pixels = static_cast(image->lock()); + if (!pixels) return 0; - } - // we need to keep the correct texture bound... + + // we need to keep the correct texture bound later on GLint tmpTexture; glGetIntegerv(GL_TEXTURE_BINDING_2D, &tmpTexture); glBindTexture(GL_TEXTURE_2D, TextureName); @@ -362,7 +405,8 @@ void* COpenGLTexture::lock(bool readOnly) glPixelStorei(GL_PACK_INVERT_MESA, GL_TRUE); #endif - glGetTexImage(GL_TEXTURE_2D, 0, GL_BGRA_EXT, GL_UNSIGNED_BYTE, pPixels); + // download GPU data as ARGB8 to pixels; + glGetTexImage(GL_TEXTURE_2D, mipmapLevel, GL_BGRA_EXT, GL_UNSIGNED_BYTE, pixels); #ifdef GL_MESA_pack_invert if (Driver->queryOpenGLFeature(COpenGLExtensionHandler::IRR_MESA_pack_invert)) @@ -371,42 +415,57 @@ void* COpenGLTexture::lock(bool readOnly) #endif { // opengl images are horizontally flipped, so we have to fix that here. - const s32 pitch=Image->getPitch(); - u8* p2 = pPixels + (ImageSize.Height - 1) * pitch; + const s32 pitch=image->getPitch(); + u8* p2 = pixels + (image->getDimension().Height - 1) * pitch; u8* tmpBuffer = new u8[pitch]; - for (u32 i=0; i < ImageSize.Height; i += 2) + for (u32 i=0; i < image->getDimension().Height; i += 2) { - memcpy(tmpBuffer, pPixels, pitch); - memcpy(pPixels, p2, pitch); + memcpy(tmpBuffer, pixels, pitch); + memcpy(pixels, p2, pitch); memcpy(p2, tmpBuffer, pitch); - pPixels += pitch; + pixels += pitch; p2 -= pitch; } delete [] tmpBuffer; } - Image->unlock(); + image->unlock(); //reset old bound texture glBindTexture(GL_TEXTURE_2D, tmpTexture); } - return Image->lock(); + return image->lock(); } //! unlock function void COpenGLTexture::unlock() { - if (!Image) + // test if miplevel or main texture was locked + IImage* image = MipImage?MipImage:Image; + if (!image) return; - Image->unlock(); + // unlock image to see changes + image->unlock(); + // copy texture data to GPU if (!ReadOnlyLock) - copyTexture(false); + uploadTexture(false, 0, MipLevelStored); ReadOnlyLock = false; - if (!KeepImage) + // cleanup local image + if (MipImage) + { + MipImage->drop(); + MipImage=0; + } + else if (!KeepImage) { Image->drop(); Image=0; } + // update information + if (Image) + ColorFormat=Image->getColorFormat(); + else + ColorFormat=ECF_A8R8G8B8; } @@ -456,7 +515,6 @@ GLuint COpenGLTexture::getOpenGLTextureName() const //! Returns whether this texture has mipmaps -//! return true if texture has mipmaps bool COpenGLTexture::hasMipMaps() const { return HasMipMaps; @@ -465,18 +523,18 @@ bool COpenGLTexture::hasMipMaps() const //! Regenerates the mip map levels of the texture. Useful after locking and //! modifying the texture -void COpenGLTexture::regenerateMipMapLevels() +void COpenGLTexture::regenerateMipMapLevels(void* mipmapData) { if (AutomaticMipmapUpdate || !HasMipMaps || !Image) return; if ((Image->getDimension().Width==1) && (Image->getDimension().Height==1)) return; - // Manually create mipmaps + // Manually create mipmaps or use prepared version u32 width=Image->getDimension().Width; u32 height=Image->getDimension().Height; u32 i=0; - u8* target = new u8[Image->getImageDataSizeInBytes()]; + u8* target = static_cast(mipmapData); do { if (width>1) @@ -484,13 +542,24 @@ void COpenGLTexture::regenerateMipMapLevels() if (height>1) height>>=1; ++i; - Image->copyToScaling(target, width, height, Image->getColorFormat()); + if (!target) + target = new u8[width*height*Image->getBytesPerPixel()]; + // create scaled version if no mipdata available + if (!mipmapData) + Image->copyToScaling(target, width, height, Image->getColorFormat()); glTexImage2D(GL_TEXTURE_2D, i, InternalFormat, width, height, 0, PixelFormat, PixelType, target); + // get next prepared mipmap data if available + if (mipmapData) + { + mipmapData = static_cast(mipmapData)+width*height*Image->getBytesPerPixel(); + target = static_cast(mipmapData); + } } while (width!=1 || height!=1); - delete [] target; - Image->unlock(); + // cleanup + if (!mipmapData) + delete [] target; } diff --git a/source/Irrlicht/COpenGLTexture.h b/source/Irrlicht/COpenGLTexture.h index 498b173e..47ac6481 100644 --- a/source/Irrlicht/COpenGLTexture.h +++ b/source/Irrlicht/COpenGLTexture.h @@ -51,13 +51,13 @@ class COpenGLTexture : public ITexture public: //! constructor - COpenGLTexture(IImage* surface, const io::path& name, COpenGLDriver* driver=0); + COpenGLTexture(IImage* surface, const io::path& name, void* mipmapData=0, COpenGLDriver* driver=0); //! destructor virtual ~COpenGLTexture(); //! lock function - virtual void* lock(bool readOnly = false); + virtual void* lock(bool readOnly=false, u32 mipmapLevel=0); //! unlock function virtual void unlock(); @@ -83,9 +83,10 @@ public: //! return whether this texture has mipmaps virtual bool hasMipMaps() const; - //! Regenerates the mip map levels of the texture. Useful after - //! locking and modifying the texture - virtual void regenerateMipMapLevels(); + //! Regenerates the mip map levels of the texture. + /** Useful after locking and modifying the texture + \param mipmapData Pointer to raw mipmap data, including all necessary mip levels, in the same format as the main texture image. If not set the mipmaps are derived from the main image. */ + virtual void regenerateMipMapLevels(void* mipmapData=0); //! Is it a render target? virtual bool isRenderTarget() const; @@ -114,24 +115,28 @@ protected: GLint getOpenGLFormatAndParametersFromColorFormat( ECOLOR_FORMAT format, GLint& filtering, GLenum& colorformat, GLenum& type); - //! convert the image into an internal image with better properties for this driver. - void getImageData(IImage* image); + //! get important numbers of the image and hw texture + void getImageValues(IImage* image); //! copies the texture into an OpenGL texture. - //! \param: newTexture is true if method is called from a newly created texture for the first time. Otherwise call with false to improve memory handling. - void copyTexture(bool newTexture=true); + /** \param newTexture True if method is called for a newly created texture for the first time. Otherwise call with false to improve memory handling. + \param mipmapData Pointer to raw mipmap data, including all necessary mip levels, in the same format as the main texture image. + \param mipLevel If set to non-zero, only that specific miplevel is updated, using the MipImage member. */ + void uploadTexture(bool newTexture=false, void* mipmapData=0, u32 mipLevel=0); core::dimension2d ImageSize; core::dimension2d TextureSize; ECOLOR_FORMAT ColorFormat; COpenGLDriver* Driver; IImage* Image; + IImage* MipImage; GLuint TextureName; GLint InternalFormat; GLenum PixelFormat; GLenum PixelType; + u8 MipLevelStored; bool HasMipMaps; bool IsRenderTarget; bool AutomaticMipmapUpdate; diff --git a/source/Irrlicht/CParticleSystemSceneNode.cpp b/source/Irrlicht/CParticleSystemSceneNode.cpp index 24ad0f16..069c5473 100644 --- a/source/Irrlicht/CParticleSystemSceneNode.cpp +++ b/source/Irrlicht/CParticleSystemSceneNode.cpp @@ -450,6 +450,7 @@ void CParticleSystemSceneNode::doParticleSystem(u32 time) for (u32 i=0; i Particles[i].endTime) Particles.erase(i); else diff --git a/source/Irrlicht/CQ3LevelMesh.cpp b/source/Irrlicht/CQ3LevelMesh.cpp index 082da350..4b0f41e8 100644 --- a/source/Irrlicht/CQ3LevelMesh.cpp +++ b/source/Irrlicht/CQ3LevelMesh.cpp @@ -115,7 +115,6 @@ bool CQ3LevelMesh::loadFile(io::IReadFile* file) // now read lumps file->read(&Lumps[0], sizeof(tBSPLump)*kMaxLumps); - s32 i; if ( LoadParam.swapHeader ) { @@ -151,14 +150,13 @@ bool CQ3LevelMesh::loadFile(io::IReadFile* file) loadLeafBrushes(&Lumps[kLeafBrushes], file); // load the brushes of the leaf loadFogs(&Lumps[kFogs], file ); // load the fogs - loadTextures(); constructMesh(); - solveTJunction (); + solveTJunction(); cleanMeshes(); calcBoundingBoxes(); - cleanLoader (); + cleanLoader(); return true; } @@ -178,8 +176,8 @@ void CQ3LevelMesh::cleanLoader () delete [] MeshVerts; MeshVerts = 0; delete [] Brushes; Brushes = 0; - Lightmap.clear (); - Tex.clear (); + Lightmap.clear(); + Tex.clear(); } //! returns the amount of frames in milliseconds. If the amount is 1, it is a static (=non animated) mesh. @@ -1026,9 +1024,6 @@ void CQ3LevelMesh::constructMesh() } - - - void CQ3LevelMesh::S3DVertex2TCoords_64::copy( video::S3DVertex2TCoords &dest ) const { #if defined (TJUNCTION_SOLVER_ROUND) @@ -1198,7 +1193,6 @@ void CQ3LevelMesh::SBezier::tesselate( s32 level ) Patch->Indices.push_back( inx + 0 ); Patch->Indices.push_back( inx + (level + 1 ) + 1 ); Patch->Indices.push_back( inx + 1 ); - } } } @@ -1764,9 +1758,7 @@ void CQ3LevelMesh::cleanMeshes() ); os::Printer::log(buf, ELL_INFORMATION); } - } - } @@ -1786,7 +1778,6 @@ void CQ3LevelMesh::calcBoundingBoxes() ); os::Printer::log(buf, ELL_INFORMATION); } - } // create bounding box @@ -1798,6 +1789,9 @@ void CQ3LevelMesh::calcBoundingBoxes() } Mesh[g]->recalculateBoundingBox(); + // Mesh[0] is the main bbox + if (g!=0) + Mesh[0]->BoundingBox.addInternalBox(Mesh[g]->getBoundingBox()); } if ( LoadParam.verbose > 0 ) @@ -1812,7 +1806,6 @@ void CQ3LevelMesh::calcBoundingBoxes() ); os::Printer::log( buf, ELL_INFORMATION); } - } @@ -1835,7 +1828,6 @@ void CQ3LevelMesh::loadTextures() ); os::Printer::log( buf, ELL_INFORMATION); } - } c8 lightmapname[255]; @@ -1857,13 +1849,11 @@ void CQ3LevelMesh::loadTextures() // lightmap is a CTexture::R8G8B8 format lmapImg = Driver->createImageFromData( - video::ECF_R8G8B8, - lmapsize, + video::ECF_R8G8B8, lmapsize, LightMaps[t].imageBits, false, true ); Lightmap[t] = Driver->addTexture( lightmapname, lmapImg ); lmapImg->drop(); - } // Driver->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, oldMipMapState); @@ -1871,10 +1861,10 @@ void CQ3LevelMesh::loadTextures() // load textures Tex.set_used( NumTextures+1 ); - const IShader * shader; + const IShader* shader; core::stringc list; - core::stringc check; + io::path check; tTexArray textureArray; // pre-load shaders @@ -1940,20 +1930,19 @@ void CQ3LevelMesh::loadTextures() ); os::Printer::log( buf, ELL_INFORMATION); } - } //! Returns an axis aligned bounding box of the mesh. -//! \return A bounding box of this mesh is returned. const core::aabbox3d& CQ3LevelMesh::getBoundingBox() const { return Mesh[0]->getBoundingBox(); } -void CQ3LevelMesh::setBoundingBox( const core::aabbox3df& box) + +void CQ3LevelMesh::setBoundingBox(const core::aabbox3df& box) { - Mesh[0]->setBoundingBox(box); //? + Mesh[0]->setBoundingBox(box); } diff --git a/source/Irrlicht/CQuake3ShaderSceneNode.cpp b/source/Irrlicht/CQuake3ShaderSceneNode.cpp index 5e466f93..10e4999e 100644 --- a/source/Irrlicht/CQuake3ShaderSceneNode.cpp +++ b/source/Irrlicht/CQuake3ShaderSceneNode.cpp @@ -27,7 +27,7 @@ using namespace quake3; */ CQuake3ShaderSceneNode::CQuake3ShaderSceneNode( scene::ISceneNode* parent, scene::ISceneManager* mgr,s32 id, - io::IFileSystem *fileSystem, scene::IMeshBuffer *original, + io::IFileSystem *fileSystem, const scene::IMeshBuffer *original, const IShader * shader) : scene::IMeshSceneNode(parent, mgr, id, core::vector3df(0.f, 0.f, 0.f), @@ -53,21 +53,20 @@ CQuake3ShaderSceneNode::CQuake3ShaderSceneNode( MeshBuffer->drop (); //Original = new SMeshBufferLightMap(); - Original = (scene::SMeshBufferLightMap*) original; + Original = (const scene::SMeshBufferLightMap*) original; Original->grab(); // clone meshbuffer to modifiable buffer - cloneBuffer( MeshBuffer, (scene::SMeshBufferLightMap*) original, - original->getMaterial().ColorMask != 0 - ); + cloneBuffer(MeshBuffer, Original, + Original->getMaterial().ColorMask != 0); // load all Textures in all stages loadTextures( fileSystem ); setAutomaticCulling( scene::EAC_OFF ); - } + /*! */ CQuake3ShaderSceneNode::~CQuake3ShaderSceneNode() @@ -84,7 +83,7 @@ CQuake3ShaderSceneNode::~CQuake3ShaderSceneNode() /* create single copies */ -void CQuake3ShaderSceneNode::cloneBuffer( scene::SMeshBuffer *dest, scene::SMeshBufferLightMap * buffer, bool translateCenter ) +void CQuake3ShaderSceneNode::cloneBuffer( scene::SMeshBuffer *dest, const scene::SMeshBufferLightMap * buffer, bool translateCenter ) { dest->Material = buffer->Material; dest->Indices = buffer->Indices; @@ -120,7 +119,6 @@ void CQuake3ShaderSceneNode::cloneBuffer( scene::SMeshBuffer *dest, scene::SMesh m.setTranslation( -MeshOffset ); SceneManager->getMeshManipulator()->transform( dest, m ); } - // No Texture!. Use Shader-Pointer for sorting dest->Material.setTexture(0, (video::ITexture*) Shader); @@ -719,7 +717,7 @@ void CQuake3ShaderSceneNode::deformvertexes_autosprite( f32 dt, SModifierFunctio const core::vector3df& camPos = SceneManager->getActiveCamera()->getPosition(); video::S3DVertex * dv = MeshBuffer->Vertices.pointer(); - const video::S3DVertex2TCoords * vin = Original->Vertices.pointer(); + const video::S3DVertex2TCoords * vin = Original->Vertices.const_pointer(); core::matrix4 lookat ( core::matrix4::EM4CONST_NOTHING ); core::quaternion q; @@ -769,7 +767,7 @@ void CQuake3ShaderSceneNode::deformvertexes_autosprite2( f32 dt, SModifierFuncti const core::vector3df camPos = SceneManager->getActiveCamera()->getAbsolutePosition(); video::S3DVertex * dv = MeshBuffer->Vertices.pointer(); - const video::S3DVertex2TCoords * vin = Original->Vertices.pointer(); + const video::S3DVertex2TCoords * vin = Original->Vertices.const_pointer(); core::matrix4 lookat ( core::matrix4::EM4CONST_NOTHING ); diff --git a/source/Irrlicht/CQuake3ShaderSceneNode.h b/source/Irrlicht/CQuake3ShaderSceneNode.h index fde277a7..83089d9a 100644 --- a/source/Irrlicht/CQuake3ShaderSceneNode.h +++ b/source/Irrlicht/CQuake3ShaderSceneNode.h @@ -24,9 +24,9 @@ class CQuake3ShaderSceneNode : public scene::IMeshSceneNode public: CQuake3ShaderSceneNode( ISceneNode* parent, ISceneManager* mgr, s32 id, - io::IFileSystem *fileSystem, - IMeshBuffer *original, - const quake3::IShader * shader + io::IFileSystem* fileSystem, + const IMeshBuffer* original, + const quake3::IShader* shader ); virtual ~CQuake3ShaderSceneNode(); @@ -50,7 +50,7 @@ public: private: const quake3::IShader* Shader; SMesh *Mesh; - SMeshBufferLightMap* Original; + const SMeshBufferLightMap* Original; SMeshBuffer* MeshBuffer; core::vector3df MeshOffset; @@ -75,7 +75,7 @@ private: void loadTextures ( io::IFileSystem * fileSystem ); void addBuffer ( scene::SMeshBufferLightMap * buffer ); - void cloneBuffer ( scene::SMeshBuffer *dest, scene::SMeshBufferLightMap * buffer, bool translateCenter ); + 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 ); diff --git a/source/Irrlicht/CSTLMeshWriter.cpp b/source/Irrlicht/CSTLMeshWriter.cpp index 647aa6aa..f705cc1c 100644 --- a/source/Irrlicht/CSTLMeshWriter.cpp +++ b/source/Irrlicht/CSTLMeshWriter.cpp @@ -2,7 +2,7 @@ // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h -#include "IrrCompileConfig.h" +#include "IrrCompileConfig.h" #ifdef _IRR_COMPILE_WITH_STL_WRITER_ @@ -66,7 +66,7 @@ bool CSTLMeshWriter::writeMeshBinary(io::IWriteFile* file, scene::IMesh* mesh, s // write STL MESH header file->write("binary ",7); - const core::stringc name(SceneManager->getMeshCache()->getMeshFilename(mesh)); + 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); @@ -115,12 +115,12 @@ bool CSTLMeshWriter::writeMeshASCII(io::IWriteFile* file, scene::IMesh* mesh, s3 // write STL MESH header file->write("solid ",6); - const core::stringc name(SceneManager->getMeshCache()->getMeshFilename(mesh)); + 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; igetMeshBufferCount(); ++i) { IMeshBuffer* buffer = mesh->getMeshBuffer(i); diff --git a/source/Irrlicht/CSceneCollisionManager.cpp b/source/Irrlicht/CSceneCollisionManager.cpp index 4bbeeb93..baac48d2 100644 --- a/source/Irrlicht/CSceneCollisionManager.cpp +++ b/source/Irrlicht/CSceneCollisionManager.cpp @@ -10,7 +10,6 @@ #include "os.h" #include "irrMath.h" -#include // For FLT_MAX namespace irr { @@ -41,21 +40,22 @@ CSceneCollisionManager::~CSceneCollisionManager() //! Returns the scene node, which is currently visible at the given //! screen coordinates, viewed from the currently active camera. ISceneNode* CSceneCollisionManager::getSceneNodeFromScreenCoordinatesBB( - const core::position2d& pos, s32 idBitMask, bool bNoDebugObjects, scene::ISceneNode* root) + const core::position2d& pos, s32 idBitMask, bool noDebugObjects, scene::ISceneNode* root) { const core::line3d ln = getRayFromScreenCoordinates(pos, 0); if ( ln.start == ln.end ) return 0; - return getSceneNodeFromRayBB(ln, idBitMask, bNoDebugObjects, root); + return getSceneNodeFromRayBB(ln, idBitMask, noDebugObjects, root); } //! Returns the nearest scene node which collides with a 3d ray and //! which id matches a bitmask. -ISceneNode* CSceneCollisionManager::getSceneNodeFromRayBB(const core::line3d& ray, - s32 idBitMask, bool bNoDebugObjects, scene::ISceneNode* root) +ISceneNode* CSceneCollisionManager::getSceneNodeFromRayBB( + const core::line3d& ray, + s32 idBitMask, bool noDebugObjects, scene::ISceneNode* root) { ISceneNode* best = 0; f32 dist = FLT_MAX; @@ -63,7 +63,7 @@ ISceneNode* CSceneCollisionManager::getSceneNodeFromRayBB(const core::line3d truncatableRay(ray); getPickedNodeBB((root==0)?SceneManager->getRootSceneNode():root, truncatableRay, - idBitMask, bNoDebugObjects, dist, best); + idBitMask, noDebugObjects, dist, best); return best; } @@ -71,7 +71,7 @@ ISceneNode* CSceneCollisionManager::getSceneNodeFromRayBB(const core::line3dgetChildren(); @@ -84,7 +84,7 @@ void CSceneCollisionManager::getPickedNodeBB(ISceneNode* root, if (current->isVisible()) { - if((bNoDebugObjects ? !current->isDebugObject() : true) && + if((noDebugObjects ? !current->isDebugObject() : true) && (bits==0 || (bits != 0 && (current->getID() & bits)))) { // get world to object space transform @@ -103,10 +103,20 @@ void CSceneCollisionManager::getPickedNodeBB(ISceneNode* root, // object space box test is more accurate. if(objectBox.isPointInside(objectRay.start)) { - // If the line starts inside the box, then consider the distance as being - // to the centre of the box. - const f32 toIntersectionSq = objectRay.start.getDistanceFromSQ(objectBox.getCenter()); - if(toIntersectionSq < outbestdistance) + // use fast bbox intersection to find distance to hitpoint + // algorithm from Kay et al., code from gamedev.net + const core::vector3df dir = (objectRay.end-objectRay.start).normalize(); + const core::vector3df minDist = (objectBox.MinEdge - objectRay.start)/dir; + const core::vector3df maxDist = (objectBox.MaxEdge - objectRay.start)/dir; + const core::vector3df realMin(core::min_(minDist.X, maxDist.X),core::min_(minDist.Y, maxDist.Y),core::min_(minDist.Z, maxDist.Z)); + const core::vector3df realMax(core::max_(minDist.X, maxDist.X),core::max_(minDist.Y, maxDist.Y),core::max_(minDist.Z, maxDist.Z)); + + const f32 minmax = core::min_(realMax.X, realMax.Y, realMax.Z); + // nearest distance to intersection + const f32 maxmin = core::max_(realMin.X, realMin.Y, realMin.Z); + + const f32 toIntersectionSq = (maxmin>0?maxmin*maxmin:minmax*minmax); + if (toIntersectionSq < outbestdistance) { outbestdistance = toIntersectionSq; outbestnode = current; @@ -115,7 +125,8 @@ void CSceneCollisionManager::getPickedNodeBB(ISceneNode* root, ray.end = ray.start + (rayVector * sqrtf(toIntersectionSq)); } } - else if (objectBox.intersectsWithLine(objectRay)) + else + if (objectBox.intersectsWithLine(objectRay)) { // Now transform into world space, since we need to use world space // scales and distances. @@ -174,7 +185,7 @@ void CSceneCollisionManager::getPickedNodeBB(ISceneNode* root, // on the box, so need to go back to object space again. worldToObject.transformVect(intersection); - // find the closes point on the box borders. Have to do this as exact checks will fail due to floating point problems. + // find the closest point on the box borders. Have to do this as exact checks will fail due to floating point problems. f32 distToBorder = core::max_ ( core::min_ (core::abs_(objectBox.MinEdge.X-intersection.X), core::abs_(objectBox.MaxEdge.X-intersection.X)), core::min_ (core::abs_(objectBox.MinEdge.Y-intersection.Y), core::abs_(objectBox.MaxEdge.Y-intersection.Y)), core::min_ (core::abs_(objectBox.MinEdge.Z-intersection.Z), core::abs_(objectBox.MaxEdge.Z-intersection.Z)) ); @@ -188,7 +199,7 @@ void CSceneCollisionManager::getPickedNodeBB(ISceneNode* root, // If the ray could be entering through the first face of a pair, then it can't // also be entering through the opposite face, and so we can skip that face. - if(0 == (face % 2)) + if (!(face & 0x01)) ++face; } @@ -204,7 +215,7 @@ void CSceneCollisionManager::getPickedNodeBB(ISceneNode* root, } // Only check the children if this node is visible. - getPickedNodeBB(current, ray, bits, bNoDebugObjects, outbestdistance, outbestnode); + getPickedNodeBB(current, ray, bits, noDebugObjects, outbestdistance, outbestnode); } } } @@ -256,7 +267,7 @@ ISceneNode* CSceneCollisionManager::getSceneNodeAndCollisionPointFromRay( void CSceneCollisionManager::getPickedNodeFromBBAndSelector( ISceneNode * root, - const core::line3df & ray, + core::line3df & ray, s32 bits, bool noDebugObjects, f32 & outBestDistanceSquared, @@ -304,6 +315,8 @@ void CSceneCollisionManager::getPickedNodeFromBBAndSelector( outBestNode = current; outBestCollisionPoint = candidateCollisionPoint; outBestTriangle = candidateTriangle; + const core::vector3df rayVector = ray.getVector().normalize(); + ray.end = ray.start + (rayVector * sqrtf(distanceSquared)); } } } @@ -318,7 +331,7 @@ void CSceneCollisionManager::getPickedNodeFromBBAndSelector( //! Returns the scene node, at which the overgiven camera is looking at and //! which id matches the bitmask. ISceneNode* CSceneCollisionManager::getSceneNodeFromCameraBB( - ICameraSceneNode* camera, s32 idBitMask, bool bNoDebugObjects) + ICameraSceneNode* camera, s32 idBitMask, bool noDebugObjects) { if (!camera) return 0; @@ -328,7 +341,7 @@ ISceneNode* CSceneCollisionManager::getSceneNodeFromCameraBB( end = start + ((end - start).normalize() * camera->getFarValue()); - return getSceneNodeFromRayBB(core::line3d(start, end), idBitMask, bNoDebugObjects); + return getSceneNodeFromRayBB(core::line3d(start, end), idBitMask, noDebugObjects); } diff --git a/source/Irrlicht/CSceneCollisionManager.h b/source/Irrlicht/CSceneCollisionManager.h index 2cc7710b..7b13c8b9 100644 --- a/source/Irrlicht/CSceneCollisionManager.h +++ b/source/Irrlicht/CSceneCollisionManager.h @@ -89,7 +89,7 @@ namespace scene //! recursive method for going through all scene nodes void getPickedNodeFromBBAndSelector(ISceneNode * root, - const core::line3df & ray, + core::line3df & ray, s32 bits, bool noDebugObjects, f32 & outBestDistanceSquared, diff --git a/source/Irrlicht/CSceneManager.cpp b/source/Irrlicht/CSceneManager.cpp index da384784..03c0bac0 100644 --- a/source/Irrlicht/CSceneManager.cpp +++ b/source/Irrlicht/CSceneManager.cpp @@ -116,7 +116,7 @@ #include "CCubeSceneNode.h" #include "CSphereSceneNode.h" #include "CAnimatedMeshSceneNode.h" -#include "COctTreeSceneNode.h" +#include "COctreeSceneNode.h" #include "CCameraSceneNode.h" #include "CLightSceneNode.h" @@ -134,7 +134,7 @@ #include "CSceneCollisionManager.h" #include "CTriangleSelector.h" -#include "COctTreeTriangleSelector.h" +#include "COctreeTriangleSelector.h" #include "CTriangleBBSelector.h" #include "CMetaTriangleSelector.h" #include "CTerrainTriangleSelector.h" @@ -340,7 +340,7 @@ CSceneManager::~CSceneManager() //! gets an animateable mesh. loads it if needed. returned pointer must not be dropped. IAnimatedMesh* CSceneManager::getMesh(const io::path& filename) { - IAnimatedMesh* msh = MeshCache->getMeshByFilename(filename); + IAnimatedMesh* msh = MeshCache->getMeshByName(filename); if (msh) return msh; @@ -386,11 +386,10 @@ IAnimatedMesh* CSceneManager::getMesh(io::IReadFile* file) return 0; io::path name = file->getFileName(); - IAnimatedMesh* msh = MeshCache->getMeshByFilename(file->getFileName()); + IAnimatedMesh* msh = MeshCache->getMeshByName(file->getFileName()); if (msh) return msh; - name.make_lower(); s32 count = MeshLoaderList.size(); for (s32 i=count-1; i>=0; --i) { @@ -486,7 +485,7 @@ IBillboardTextSceneNode* CSceneManager::addBillboardTextSceneNode(gui::IGUIFont* //! Adds a scene node, which can render a quake3 shader -IMeshSceneNode* CSceneManager::addQuake3SceneNode(IMeshBuffer* meshBuffer, +IMeshSceneNode* CSceneManager::addQuake3SceneNode(const IMeshBuffer* meshBuffer, const quake3::IShader * shader, ISceneNode* parent, s32 id ) { @@ -616,25 +615,25 @@ IAnimatedMeshSceneNode* CSceneManager::addAnimatedMeshSceneNode(IAnimatedMesh* m } -//! Adds a scene node for rendering using a octtree to the scene graph. This a good method for rendering +//! Adds a scene node for rendering using a octree to the scene graph. This a good method for rendering //! scenes with lots of geometry. The Octree is built on the fly from the mesh, much //! faster then a bsp tree. -IMeshSceneNode* CSceneManager::addOctTreeSceneNode(IAnimatedMesh* mesh, ISceneNode* parent, +IMeshSceneNode* CSceneManager::addOctreeSceneNode(IAnimatedMesh* mesh, ISceneNode* parent, s32 id, s32 minimalPolysPerNode, bool alsoAddIfMeshPointerZero) { if (!alsoAddIfMeshPointerZero && (!mesh || !mesh->getFrameCount())) return 0; - return addOctTreeSceneNode(mesh ? mesh->getMesh(0) : 0, + return addOctreeSceneNode(mesh ? mesh->getMesh(0) : 0, parent, id, minimalPolysPerNode, alsoAddIfMeshPointerZero); } -//! Adds a scene node for rendering using a octtree. This a good method for rendering +//! Adds a scene node for rendering using a octree. This a good method for rendering //! scenes with lots of geometry. The Octree is built on the fly from the mesh, much //! faster then a bsp tree. -IMeshSceneNode* CSceneManager::addOctTreeSceneNode(IMesh* mesh, ISceneNode* parent, +IMeshSceneNode* CSceneManager::addOctreeSceneNode(IMesh* mesh, ISceneNode* parent, s32 id, s32 minimalPolysPerNode, bool alsoAddIfMeshPointerZero) { if (!alsoAddIfMeshPointerZero && !mesh) @@ -643,7 +642,7 @@ IMeshSceneNode* CSceneManager::addOctTreeSceneNode(IMesh* mesh, ISceneNode* pare if (!parent) parent = this; - COctTreeSceneNode* node = new COctTreeSceneNode(parent, this, id, minimalPolysPerNode); + COctreeSceneNode* node = new COctreeSceneNode(parent, this, id, minimalPolysPerNode); if (node) { @@ -921,7 +920,7 @@ IAnimatedMesh* CSceneManager::addHillPlaneMesh(const io::path& name, const core::dimension2d& textureRepeatCount) { if (MeshCache->isMeshLoaded(name)) - return MeshCache->getMeshByFilename(name); + return MeshCache->getMeshByName(name); IMesh* mesh = GeometryCreator->createHillPlaneMesh(tileSize, tileCount, material, hillHeight, countHills, @@ -955,7 +954,7 @@ IAnimatedMesh* CSceneManager::addTerrainMesh(const io::path& name, const core::dimension2d& defaultVertexBlockSize) { if (MeshCache->isMeshLoaded(name)) - return MeshCache->getMeshByFilename(name); + return MeshCache->getMeshByName(name); IMesh* mesh = GeometryCreator->createTerrainMesh(texture, heightmap, stretchSize, maxHeight, getVideoDriver(), @@ -988,7 +987,7 @@ IAnimatedMesh* CSceneManager::addArrowMesh(const io::path& name, f32 cylinderHeight, f32 width0,f32 width1) { if (MeshCache->isMeshLoaded(name)) - return MeshCache->getMeshByFilename(name); + return MeshCache->getMeshByName(name); IMesh* mesh = GeometryCreator->createArrowMesh( tesselationCylinder, tesselationCone, height, cylinderHeight, width0,width1, @@ -1019,7 +1018,7 @@ IAnimatedMesh* CSceneManager::addSphereMesh(const io::path& name, f32 radius, u32 polyCountX, u32 polyCountY) { if (MeshCache->isMeshLoaded(name)) - return MeshCache->getMeshByFilename(name); + return MeshCache->getMeshByName(name); IMesh* mesh = GeometryCreator->createSphereMesh(radius, polyCountX, polyCountY); if (!mesh) @@ -1050,7 +1049,7 @@ IAnimatedMesh* CSceneManager::addVolumeLightMesh(const io::path& name, const video::SColor FootColor, const video::SColor TailColor) { if (MeshCache->isMeshLoaded(name)) - return MeshCache->getMeshByFilename(name); + return MeshCache->getMeshByName(name); IMesh* mesh = GeometryCreator->createVolumeLightMesh(SubdivideU, SubdivideV, FootColor, TailColor); if (!mesh) @@ -1191,11 +1190,11 @@ bool CSceneManager::isCulled(const ISceneNode* node) const //! registers a node for rendering it at a specific time. -u32 CSceneManager::registerNodeForRendering(ISceneNode* node, E_SCENE_NODE_RENDER_PASS time) +u32 CSceneManager::registerNodeForRendering(ISceneNode* node, E_SCENE_NODE_RENDER_PASS pass) { u32 taken = 0; - switch(time) + switch(pass) { // take camera if it is not already registered case ESNRP_CAMERA: @@ -1254,7 +1253,7 @@ u32 CSceneManager::registerNodeForRendering(ISceneNode* node, E_SCENE_NODE_RENDE case ESNRP_AUTOMATIC: if (!isCulled(node)) { - u32 count = node->getMaterialCount(); + const u32 count = node->getMaterialCount(); taken = 0; for (u32 i=0; i& points, - f32 speed, f32 tightness) + f32 speed, f32 tightness, bool loop, bool pingpong) { ISceneNodeAnimator* a = new CSceneNodeAnimatorFollowSpline(startTime, points, - speed, tightness); + speed, tightness, loop, pingpong); return a; } @@ -1750,14 +1749,14 @@ ITriangleSelector* CSceneManager::createTriangleSelectorFromBoundingBox(ISceneNo //! Creates a simple ITriangleSelector, based on a mesh. -ITriangleSelector* CSceneManager::createOctTreeTriangleSelector(IMesh* mesh, +ITriangleSelector* CSceneManager::createOctreeTriangleSelector(IMesh* mesh, ISceneNode* node, s32 minimalPolysPerNode) { if (!mesh) return 0; - return new COctTreeTriangleSelector(mesh, node, minimalPolysPerNode); + return new COctreeTriangleSelector(mesh, node, minimalPolysPerNode); } diff --git a/source/Irrlicht/CSceneManager.h b/source/Irrlicht/CSceneManager.h index 77f1b1c8..cd85d269 100644 --- a/source/Irrlicht/CSceneManager.h +++ b/source/Irrlicht/CSceneManager.h @@ -113,16 +113,16 @@ namespace scene //! draws all scene nodes virtual void drawAll(); - //! Adds a scene node for rendering using a octtree to the scene graph. This a good method for rendering + //! Adds a scene node for rendering using a octree to the scene graph. This a good method for rendering //! scenes with lots of geometry. The Octree is built on the fly from the mesh, much //! faster then a bsp tree. - virtual IMeshSceneNode* addOctTreeSceneNode(IAnimatedMesh* mesh, ISceneNode* parent=0, + virtual IMeshSceneNode* addOctreeSceneNode(IAnimatedMesh* mesh, ISceneNode* parent=0, s32 id=-1, s32 minimalPolysPerNode=512, bool alsoAddIfMeshPointerZero=false); - //! Adss a scene node for rendering using a octtree. This a good method for rendering + //! Adss a scene node for rendering using a octree. This a good method for rendering //! scenes with lots of geometry. The Octree is built on the fly from the mesh, much //! faster then a bsp tree. - virtual IMeshSceneNode* addOctTreeSceneNode(IMesh* mesh, ISceneNode* parent=0, + virtual IMeshSceneNode* addOctreeSceneNode(IMesh* mesh, ISceneNode* parent=0, s32 id=-1, s32 minimalPolysPerNode=128, bool alsoAddIfMeshPointerZero=false); //! Adds a camera scene node to the tree and sets it as active camera. @@ -196,7 +196,7 @@ namespace scene video::SColor colorTop = 0xFFFFFFFF, video::SColor colorBottom = 0xFFFFFFFF); //! Adds a scene node, which can render a quake3 shader - virtual IMeshSceneNode* addQuake3SceneNode(IMeshBuffer* meshBuffer, const quake3::IShader * shader, + virtual IMeshSceneNode* addQuake3SceneNode(const IMeshBuffer* meshBuffer, const quake3::IShader * shader, ISceneNode* parent=0, s32 id=-1 ); @@ -337,7 +337,7 @@ namespace scene //! Creates a follow spline animator. virtual ISceneNodeAnimator* createFollowSplineAnimator(s32 startTime, const core::array< core::vector3df >& points, - f32 speed = 1.0f, f32 tightness = 0.5f); + f32 speed, f32 tightness, bool loop, bool pingpong); //! Creates a simple ITriangleSelector, based on a mesh. @@ -351,7 +351,7 @@ namespace scene virtual ITriangleSelector* createTriangleSelector(IAnimatedMeshSceneNode* node); //! Creates a simple ITriangleSelector, based on a mesh. - virtual ITriangleSelector* createOctTreeTriangleSelector(IMesh* mesh, + virtual ITriangleSelector* createOctreeTriangleSelector(IMesh* mesh, ISceneNode* node, s32 minimalPolysPerNode); //! Creates a simple dynamic ITriangleSelector, based on a axis aligned bounding box. diff --git a/source/Irrlicht/CSceneNodeAnimatorCameraMaya.cpp b/source/Irrlicht/CSceneNodeAnimatorCameraMaya.cpp index a2d34e16..d00c4282 100644 --- a/source/Irrlicht/CSceneNodeAnimatorCameraMaya.cpp +++ b/source/Irrlicht/CSceneNodeAnimatorCameraMaya.cpp @@ -75,8 +75,12 @@ bool CSceneNodeAnimatorCameraMaya::OnEvent(const SEvent& event) MousePos = CursorControl->getRelativePosition(); break; case EMIE_MOUSE_WHEEL: - case EMIE_MOUSE_DOUBLE_CLICK: - case EMIE_MOUSE_TRIPLE_CLICK: + case EMIE_LMOUSE_DOUBLE_CLICK: + case EMIE_RMOUSE_DOUBLE_CLICK: + case EMIE_MMOUSE_DOUBLE_CLICK: + case EMIE_LMOUSE_TRIPLE_CLICK: + case EMIE_RMOUSE_TRIPLE_CLICK: + case EMIE_MMOUSE_TRIPLE_CLICK: case EMIE_COUNT: return false; } diff --git a/source/Irrlicht/CSceneNodeAnimatorFlyStraight.cpp b/source/Irrlicht/CSceneNodeAnimatorFlyStraight.cpp index e120b4ba..79b74344 100644 --- a/source/Irrlicht/CSceneNodeAnimatorFlyStraight.cpp +++ b/source/Irrlicht/CSceneNodeAnimatorFlyStraight.cpp @@ -42,21 +42,27 @@ void CSceneNodeAnimatorFlyStraight::animateNode(ISceneNode* node, u32 timeMs) u32 t = (timeMs-StartTime); - core::vector3df pos = Start; + core::vector3df pos; - if (!Loop && t >= TimeForWay) + if (!Loop && !PingPong && t >= TimeForWay) { pos = End; HasFinished = true; } + else if (!Loop && PingPong && t >= TimeForWay * 2.f ) + { + pos = Start; + HasFinished = true; + } else { f32 phase = fmodf( (f32) t, (f32) TimeForWay ); core::vector3df rel = Vector * phase * TimeFactor; + const bool pong = PingPong && fmodf( (f32) t, (f32) TimeForWay*2.f ) >= TimeForWay; - if ( !PingPong || phase < TimeForWay * 0.5f ) + if ( !pong ) { - pos += rel; + pos += Start + rel; } else { diff --git a/source/Irrlicht/CSceneNodeAnimatorFollowSpline.cpp b/source/Irrlicht/CSceneNodeAnimatorFollowSpline.cpp index adbb9c26..59ad26b0 100644 --- a/source/Irrlicht/CSceneNodeAnimatorFollowSpline.cpp +++ b/source/Irrlicht/CSceneNodeAnimatorFollowSpline.cpp @@ -13,8 +13,9 @@ namespace scene //! constructor CSceneNodeAnimatorFollowSpline::CSceneNodeAnimatorFollowSpline(u32 time, const core::array& points, f32 speed, - f32 tightness) -: Points(points), Speed(speed), Tightness(tightness), StartTime(time) + f32 tightness, bool loop, bool pingpong) +: ISceneNodeAnimatorFinishing(0), Points(points), Speed(speed), Tightness(tightness), StartTime(time) +, Loop(loop), PingPong(pingpong) { #ifdef _DEBUG setDebugName("CSceneNodeAnimatorFollowSpline"); @@ -36,18 +37,37 @@ void CSceneNodeAnimatorFollowSpline::animateNode(ISceneNode* node, u32 timeMs) const u32 pSize = Points.size(); if (pSize==0) + { + if ( !Loop ) + HasFinished = true; return; + } if (pSize==1) { - node->setPosition(Points[0]); + if ( timeMs > StartTime ) + { + node->setPosition(Points[0]); + if ( !Loop ) + HasFinished = true; + } return; } const f32 dt = ( (timeMs-StartTime) * Speed * 0.001f ); - const f32 u = core::fract ( dt ); - const s32 idx = core::floor32( dt ) % pSize; + const s32 unwrappedIdx = core::floor32( dt ); + if ( !Loop && unwrappedIdx >= (s32)pSize-1 ) + { + node->setPosition(Points[pSize-1]); + HasFinished = true; + return; + } + const bool pong = PingPong && (unwrappedIdx/(pSize-1))%2; + const f32 u = pong ? 1.f-core::fract ( dt ) : core::fract ( dt ); + const s32 idx = pong ? (pSize-2) - (unwrappedIdx % (pSize-1)) + : (PingPong ? unwrappedIdx % (pSize-1) + : unwrappedIdx % pSize); //const f32 u = 0.001f * fmodf( dt, 1000.0f ); - + const core::vector3df& p0 = Points[ clamp( idx - 1, pSize ) ]; const core::vector3df& p1 = Points[ clamp( idx + 0, pSize ) ]; // starting point const core::vector3df& p2 = Points[ clamp( idx + 1, pSize ) ]; // end point @@ -73,6 +93,8 @@ void CSceneNodeAnimatorFollowSpline::serializeAttributes(io::IAttributes* out, i { out->addFloat("Speed", Speed); out->addFloat("Tightness", Tightness); + out->addBool("Loop", Loop); + out->addBool("PingPong", PingPong); u32 count = Points.size(); @@ -98,6 +120,8 @@ void CSceneNodeAnimatorFollowSpline::deserializeAttributes(io::IAttributes* in, { Speed = in->getAttributeAsFloat("Speed"); Tightness = in->getAttributeAsFloat("Tightness"); + Loop = in->getAttributeAsBool("Loop"); + PingPong = in->getAttributeAsBool("PingPong"); Points.clear(); for(u32 i=1; true; ++i) @@ -125,7 +149,7 @@ void CSceneNodeAnimatorFollowSpline::deserializeAttributes(io::IAttributes* in, ISceneNodeAnimator* CSceneNodeAnimatorFollowSpline::createClone(ISceneNode* node, ISceneManager* newManager) { - CSceneNodeAnimatorFollowSpline * newAnimator = + CSceneNodeAnimatorFollowSpline * newAnimator = new CSceneNodeAnimatorFollowSpline(StartTime, Points, Speed, Tightness); return newAnimator; diff --git a/source/Irrlicht/CSceneNodeAnimatorFollowSpline.h b/source/Irrlicht/CSceneNodeAnimatorFollowSpline.h index ce108738..a2de040f 100644 --- a/source/Irrlicht/CSceneNodeAnimatorFollowSpline.h +++ b/source/Irrlicht/CSceneNodeAnimatorFollowSpline.h @@ -7,21 +7,22 @@ #include "ISceneNode.h" #include "irrArray.h" +#include "ISceneNodeAnimatorFinishing.h" namespace irr { namespace scene { - //! Scene node animator based free code Matthias Gall wrote and sent in. (Most of + //! Scene node animator based free code Matthias Gall wrote and sent in. (Most of //! this code is written by him, I only modified bits.) - class CSceneNodeAnimatorFollowSpline : public ISceneNodeAnimator + class CSceneNodeAnimatorFollowSpline : public ISceneNodeAnimatorFinishing { public: - + //! constructor - CSceneNodeAnimatorFollowSpline(u32 startTime, + CSceneNodeAnimatorFollowSpline(u32 startTime, const core::array< core::vector3df >& points, - f32 speed = 1.0f, f32 tightness = 0.5f); + f32 speed = 1.0f, f32 tightness = 0.5f, bool loop=true, bool pingpong=false); //! animates a scene node virtual void animateNode(ISceneNode* node, u32 timeMs); @@ -34,7 +35,7 @@ namespace scene //! Returns type of the scene node animator virtual ESCENE_NODE_ANIMATOR_TYPE getType() const { return ESNAT_FOLLOW_SPLINE; } - + //! Creates a clone of this animator. /** Please note that you will have to drop (IReferenceCounted::drop()) the returned pointer after calling @@ -50,6 +51,8 @@ namespace scene f32 Speed; f32 Tightness; u32 StartTime; + bool Loop; + bool PingPong; }; diff --git a/source/Irrlicht/CSkinnedMesh.cpp b/source/Irrlicht/CSkinnedMesh.cpp index 514c97ee..e6a28f49 100644 --- a/source/Irrlicht/CSkinnedMesh.cpp +++ b/source/Irrlicht/CSkinnedMesh.cpp @@ -1254,17 +1254,13 @@ void CSkinnedMesh::recoverJointsFromMesh(core::array &JointChil SJoint *joint=AllJoints[i]; node->setPosition( joint->LocalAnimatedMatrix.getTranslation() ); node->setRotation( joint->LocalAnimatedMatrix.getRotationDegrees() ); - - //node->setScale( joint->LocalAnimatedMatrix.getScale() ); + node->setScale( joint->LocalAnimatedMatrix.getScale() ); node->positionHint=joint->positionHint; node->scaleHint=joint->scaleHint; node->rotationHint=joint->rotationHint; - //node->setAbsoluteTransformation(joint->GlobalMatrix); //not going to work - - //Note: This updateAbsolutePosition will not work well if joints are not nested like b3d - //node->updateAbsolutePosition(); + node->updateAbsolutePosition(); } } @@ -1276,19 +1272,15 @@ void CSkinnedMesh::transferJointsToMesh(const core::array &Join const IBoneSceneNode* const node=JointChildSceneNodes[i]; SJoint *joint=AllJoints[i]; - joint->LocalAnimatedMatrix.setTranslation(node->getPosition()); joint->LocalAnimatedMatrix.setRotationDegrees(node->getRotation()); - - //joint->LocalAnimatedMatrix.setScale( node->getScale() ); + joint->LocalAnimatedMatrix.setTranslation(node->getPosition()); + joint->LocalAnimatedMatrix *= core::matrix4().setScale(node->getScale()); joint->positionHint=node->positionHint; joint->scaleHint=node->scaleHint; joint->rotationHint=node->rotationHint; - if (node->getSkinningSpace()==EBSS_GLOBAL) - joint->GlobalSkinningSpace=true; - else - joint->GlobalSkinningSpace=false; + joint->GlobalSkinningSpace=(node->getSkinningSpace()==EBSS_GLOBAL); } //Remove cache, temp... LastAnimatedFrame=-1; diff --git a/source/Irrlicht/CSkinnedMesh.h b/source/Irrlicht/CSkinnedMesh.h index b636cd71..4db1d35b 100644 --- a/source/Irrlicht/CSkinnedMesh.h +++ b/source/Irrlicht/CSkinnedMesh.h @@ -134,14 +134,20 @@ namespace scene //! loaders should call this after populating the mesh virtual void finalize(); + //! Adds a new meshbuffer to the mesh, access it as last one virtual SSkinMeshBuffer *addMeshBuffer(); + //! Adds a new joint to the mesh, access it as last one virtual SJoint *addJoint(SJoint *parent=0); + //! Adds a new position key to the mesh, access it as last one virtual SPositionKey *addPositionKey(SJoint *joint); + //! Adds a new rotation key to the mesh, access it as last one virtual SRotationKey *addRotationKey(SJoint *joint); + //! Adds a new scale key to the mesh, access it as last one virtual SScaleKey *addScaleKey(SJoint *joint); + //! Adds a new weight to the mesh, access it as last one virtual SWeight *addWeight(SJoint *joint); virtual void updateBoundingBox(void); diff --git a/source/Irrlicht/CSkyDomeSceneNode.cpp b/source/Irrlicht/CSkyDomeSceneNode.cpp index 4c8941a5..82b1f83c 100644 --- a/source/Irrlicht/CSkyDomeSceneNode.cpp +++ b/source/Irrlicht/CSkyDomeSceneNode.cpp @@ -126,6 +126,7 @@ void CSkyDomeSceneNode::generateMesh() Buffer->Indices.push_back(0 + (VerticalResolution + 1)*k + j); } } + Buffer->setHardwareMappingHint(scene::EHM_STATIC); } @@ -288,4 +289,3 @@ ISceneNode* CSkyDomeSceneNode::clone(ISceneNode* newParent, ISceneManager* newMa } // namespace scene } // namespace irr - diff --git a/source/Irrlicht/CSoftwareDriver.cpp b/source/Irrlicht/CSoftwareDriver.cpp index c5531b40..bc8e270e 100644 --- a/source/Irrlicht/CSoftwareDriver.cpp +++ b/source/Irrlicht/CSoftwareDriver.cpp @@ -214,10 +214,10 @@ void CSoftwareDriver::setMaterial(const SMaterial& material) //! clears the zbuffer bool CSoftwareDriver::beginScene(bool backBuffer, bool zBuffer, SColor color, - void* windowId, core::rect* sourceRect) + const SExposedVideoData& videoData, core::rect* sourceRect) { - CNullDriver::beginScene(backBuffer, zBuffer, color, windowId, sourceRect); - WindowId=windowId; + CNullDriver::beginScene(backBuffer, zBuffer, color, videoData, sourceRect); + WindowId=videoData.D3D9.HWnd; SceneSourceRect = sourceRect; if (backBuffer && BackBuffer) @@ -241,9 +241,9 @@ bool CSoftwareDriver::endScene() //! returns a device dependent texture from a software surface (IImage) //! THIS METHOD HAS TO BE OVERRIDDEN BY DERIVED DRIVERS WITH OWN TEXTURES -ITexture* CSoftwareDriver::createDeviceDependentTexture(IImage* surface, const io::path& name) +ITexture* CSoftwareDriver::createDeviceDependentTexture(IImage* surface, const io::path& name, void* mipmapData) { - return new CSoftwareTexture(surface, name); + return new CSoftwareTexture(surface, name, false, mipmapData); } @@ -919,7 +919,11 @@ void CSoftwareDriver::clearZBuffer() IImage* CSoftwareDriver::createScreenShot() { if (BackBuffer) - return new CImage(BackBuffer->getColorFormat(), BackBuffer); + { + CImage* tmp = new CImage(BackBuffer->getColorFormat(), BackBuffer->getDimension()); + BackBuffer->copyTo(tmp); + return tmp; + } else return 0; } diff --git a/source/Irrlicht/CSoftwareDriver.h b/source/Irrlicht/CSoftwareDriver.h index 82eb3b81..2a55af2a 100644 --- a/source/Irrlicht/CSoftwareDriver.h +++ b/source/Irrlicht/CSoftwareDriver.h @@ -42,7 +42,7 @@ namespace video //! clears the zbuffer virtual bool beginScene(bool backBuffer=true, bool zBuffer=true, SColor color=SColor(255,0,0,0), - void* windowId=0, + const SExposedVideoData& videoData=SExposedVideoData(), core::rect* sourceRect=0); //! presents the rendered scene on the screen, returns false if failed @@ -101,7 +101,7 @@ namespace video //! returns a device dependent texture from a software surface (IImage) //! THIS METHOD HAS TO BE OVERRIDDEN BY DERIVED DRIVERS WITH OWN TEXTURES - virtual video::ITexture* createDeviceDependentTexture(IImage* surface, const io::path& name); + virtual video::ITexture* createDeviceDependentTexture(IImage* surface, const io::path& name, void* mipmapData=0); //! Creates a render target texture. virtual ITexture* addRenderTargetTexture(const core::dimension2d& size, diff --git a/source/Irrlicht/CSoftwareDriver2.cpp b/source/Irrlicht/CSoftwareDriver2.cpp index 4909ead4..07fb4d56 100644 --- a/source/Irrlicht/CSoftwareDriver2.cpp +++ b/source/Irrlicht/CSoftwareDriver2.cpp @@ -343,10 +343,11 @@ void CBurningVideoDriver::setTransform(E_TRANSFORMATION_STATE state, const core: //! clears the zbuffer bool CBurningVideoDriver::beginScene(bool backBuffer, bool zBuffer, - SColor color, void* windowId, core::rect* sourceRect) + SColor color, const SExposedVideoData& videoData, + core::rect* sourceRect) { - CNullDriver::beginScene(backBuffer, zBuffer, color, windowId, sourceRect); - WindowId = windowId; + CNullDriver::beginScene(backBuffer, zBuffer, color, videoData, sourceRect); + WindowId = videoData.D3D9.HWnd; SceneSourceRect = sourceRect; if (backBuffer && BackBuffer) @@ -2049,7 +2050,11 @@ void CBurningVideoDriver::clearZBuffer() IImage* CBurningVideoDriver::createScreenShot() { if (BackBuffer) - return new CImage(BackBuffer->getColorFormat(), BackBuffer); + { + CImage* tmp = new CImage(BackBuffer->getColorFormat(), BackBuffer->getDimension()); + BackBuffer->copyTo(tmp); + return tmp; + } else return 0; @@ -2058,13 +2063,12 @@ IImage* CBurningVideoDriver::createScreenShot() //! returns a device dependent texture from a software surface (IImage) //! THIS METHOD HAS TO BE OVERRIDDEN BY DERIVED DRIVERS WITH OWN TEXTURES -ITexture* CBurningVideoDriver::createDeviceDependentTexture(IImage* surface, const io::path& name) +ITexture* CBurningVideoDriver::createDeviceDependentTexture(IImage* surface, const io::path& name, void* mipmapData) { return new CSoftwareTexture2( surface, name, (getTextureCreationFlag(ETCF_CREATE_MIP_MAPS) ? CSoftwareTexture2::GEN_MIPMAP : 0 ) | - (getTextureCreationFlag(ETCF_ALLOW_NON_POWER_2) ? 0 : CSoftwareTexture2::NP2_SIZE ) - ); + (getTextureCreationFlag(ETCF_ALLOW_NON_POWER_2) ? 0 : CSoftwareTexture2::NP2_SIZE ), mipmapData); } diff --git a/source/Irrlicht/CSoftwareDriver2.h b/source/Irrlicht/CSoftwareDriver2.h index 09679b01..1a23332f 100644 --- a/source/Irrlicht/CSoftwareDriver2.h +++ b/source/Irrlicht/CSoftwareDriver2.h @@ -44,7 +44,7 @@ namespace video //! clears the zbuffer virtual bool beginScene(bool backBuffer=true, bool zBuffer=true, SColor color=SColor(255,0,0,0), - void* windowId=0, + const SExposedVideoData& videoData=SExposedVideoData(), core::rect* sourceRect=0); //! presents the rendered scene on the screen, returns false if failed @@ -168,7 +168,7 @@ namespace video //! returns a device dependent texture from a software surface (IImage) //! THIS METHOD HAS TO BE OVERRIDDEN BY DERIVED DRIVERS WITH OWN TEXTURES - virtual video::ITexture* createDeviceDependentTexture(IImage* surface, const io::path& name); + virtual video::ITexture* createDeviceDependentTexture(IImage* surface, const io::path& name, void* mipmapData=0); video::CImage* BackBuffer; video::IImagePresenter* Presenter; diff --git a/source/Irrlicht/CSoftwareTexture.cpp b/source/Irrlicht/CSoftwareTexture.cpp index 4f4e56cf..4273b29a 100644 --- a/source/Irrlicht/CSoftwareTexture.cpp +++ b/source/Irrlicht/CSoftwareTexture.cpp @@ -14,7 +14,8 @@ namespace video { //! constructor -CSoftwareTexture::CSoftwareTexture(IImage* image, const io::path& name, bool renderTarget) +CSoftwareTexture::CSoftwareTexture(IImage* image, const io::path& name, + bool renderTarget, void* mipmapData) : ITexture(name), Texture(0), IsRenderTarget(renderTarget) { #ifdef _DEBUG @@ -26,7 +27,8 @@ CSoftwareTexture::CSoftwareTexture(IImage* image, const io::path& name, bool ren OrigSize = image->getDimension(); core::dimension2d optSize=OrigSize.getOptimalSize(); - Image = new CImage(ECF_A1R5G5B5, image); + Image = new CImage(ECF_A1R5G5B5, OrigSize); + image->copyTo(Image); if (optSize == OrigSize) { @@ -56,7 +58,7 @@ CSoftwareTexture::~CSoftwareTexture() //! lock function -void* CSoftwareTexture::lock(bool readOnly) +void* CSoftwareTexture::lock(bool readOnly, u32 mipmapLevel) { return Image->lock(); } @@ -131,7 +133,7 @@ u32 CSoftwareTexture::getPitch() const //! Regenerates the mip map levels of the texture. Useful after locking and //! modifying the texture -void CSoftwareTexture::regenerateMipMapLevels() +void CSoftwareTexture::regenerateMipMapLevels(void* mipmapData) { // our software textures don't have mip maps } diff --git a/source/Irrlicht/CSoftwareTexture.h b/source/Irrlicht/CSoftwareTexture.h index d3784068..f5cdd10e 100644 --- a/source/Irrlicht/CSoftwareTexture.h +++ b/source/Irrlicht/CSoftwareTexture.h @@ -21,13 +21,14 @@ class CSoftwareTexture : public ITexture public: //! constructor - CSoftwareTexture(IImage* surface, const io::path& name, bool renderTarget=false); + CSoftwareTexture(IImage* surface, const io::path& name, + bool renderTarget=false, void* mipmapData=0); //! destructor virtual ~CSoftwareTexture(); //! lock function - virtual void* lock(bool readOnly = false); + virtual void* lock(bool readOnly = false, u32 mipmapLevel=0); //! unlock function virtual void unlock(); @@ -55,7 +56,7 @@ public: //! Regenerates the mip map levels of the texture. Useful after locking and //! modifying the texture - virtual void regenerateMipMapLevels(); + virtual void regenerateMipMapLevels(void* mipmapData=0); //! is it a render target? virtual bool isRenderTarget() const; diff --git a/source/Irrlicht/CSoftwareTexture2.cpp b/source/Irrlicht/CSoftwareTexture2.cpp index fd2db088..520ba69e 100644 --- a/source/Irrlicht/CSoftwareTexture2.cpp +++ b/source/Irrlicht/CSoftwareTexture2.cpp @@ -16,8 +16,9 @@ namespace video { //! constructor -CSoftwareTexture2::CSoftwareTexture2(IImage* image, const io::path& name, u32 flags ) -: ITexture(name), MipMapLOD(0), Flags ( flags ) +CSoftwareTexture2::CSoftwareTexture2(IImage* image, const io::path& name, + u32 flags, void* mipmapData) + : ITexture(name), MipMapLOD(0), Flags ( flags ), OriginalFormat(video::ECF_UNKNOWN) { #ifdef _DEBUG setDebugName("CSoftwareTexture2"); @@ -32,12 +33,12 @@ CSoftwareTexture2::CSoftwareTexture2(IImage* image, const io::path& name, u32 fl if (image) { OrigSize = image->getDimension(); + OriginalFormat = image->getColorFormat(); - core::setbit_cond ( Flags, - image->getColorFormat () == video::ECF_A8R8G8B8 || - image->getColorFormat () == video::ECF_A1R5G5B5, - HAS_ALPHA - ); + core::setbit_cond(Flags, + image->getColorFormat () == video::ECF_A8R8G8B8 || + image->getColorFormat () == video::ECF_A1R5G5B5, + HAS_ALPHA); core::dimension2d optSize( OrigSize.getOptimalSize( 0 != ( Flags & NP2_SIZE ), @@ -47,7 +48,8 @@ CSoftwareTexture2::CSoftwareTexture2(IImage* image, const io::path& name, u32 fl if ( OrigSize == optSize ) { - MipMap[0] = new CImage(BURNINGSHADER_COLOR_FORMAT, image); + MipMap[0] = new CImage(BURNINGSHADER_COLOR_FORMAT, image->getDimension()); + image->copyTo(MipMap[0]); } else { @@ -62,19 +64,11 @@ CSoftwareTexture2::CSoftwareTexture2(IImage* image, const io::path& name, u32 fl OrigSize = optSize; os::Printer::log ( buf, ELL_WARNING ); MipMap[0] = new CImage(BURNINGSHADER_COLOR_FORMAT, optSize); - MipMap[0]->fill ( 0 ); - - - // temporary CImage needed - CImage * temp = new CImage ( BURNINGSHADER_COLOR_FORMAT, image ); - temp->copyToScalingBoxFilter ( MipMap[0],0, false ); - //temp->copyToScaling(MipMap[0]); - temp->drop (); + image->copyToScalingBoxFilter ( MipMap[0],0, false ); } } - regenerateMipMapLevels(); - setCurrentMipMapLOD(0); + regenerateMipMapLevels(mipmapData); } @@ -91,7 +85,7 @@ CSoftwareTexture2::~CSoftwareTexture2() //! Regenerates the mip map levels of the texture. Useful after locking and //! modifying the texture -void CSoftwareTexture2::regenerateMipMapLevels() +void CSoftwareTexture2::regenerateMipMapLevels(void* mipmapData) { if ( !hasMipMaps () ) return; @@ -106,21 +100,48 @@ void CSoftwareTexture2::regenerateMipMapLevels() } core::dimension2d newSize; - core::dimension2d currentSize; + core::dimension2d origSize=OrigSize; - i = 1; - CImage * c = MipMap[0]; - while ( i < SOFTWARE_DRIVER_2_MIPMAPPING_MAX ) + for (i=1; i < SOFTWARE_DRIVER_2_MIPMAPPING_MAX; ++i) { - currentSize = c->getDimension(); - newSize.Width = core::s32_max ( 1, currentSize.Width >> SOFTWARE_DRIVER_2_MIPMAPPING_SCALE ); - newSize.Height = core::s32_max ( 1, currentSize.Height >> SOFTWARE_DRIVER_2_MIPMAPPING_SCALE ); + newSize = MipMap[i-1]->getDimension(); + newSize.Width = core::s32_max ( 1, newSize.Width >> SOFTWARE_DRIVER_2_MIPMAPPING_SCALE ); + newSize.Height = core::s32_max ( 1, newSize.Height >> SOFTWARE_DRIVER_2_MIPMAPPING_SCALE ); + origSize.Width = core::s32_max(1, origSize.Width >> 1); + origSize.Height = core::s32_max(1, origSize.Height >> 1); - MipMap[i] = new CImage(BURNINGSHADER_COLOR_FORMAT, newSize); - MipMap[i]->fill ( 0 ); - MipMap[0]->copyToScalingBoxFilter( MipMap[i], 0, false ); - c = MipMap[i]; - ++i; + if (mipmapData) + { + if (OriginalFormat != BURNINGSHADER_COLOR_FORMAT) + { + IImage* tmpImage = new CImage(OriginalFormat, origSize, mipmapData, true, false); + MipMap[i] = new CImage(BURNINGSHADER_COLOR_FORMAT, newSize); + if (origSize==newSize) + tmpImage->copyTo(MipMap[i]); + else + tmpImage->copyToScalingBoxFilter(MipMap[i]); + tmpImage->drop(); + } + else + { + if (origSize==newSize) + MipMap[i] = new CImage(BURNINGSHADER_COLOR_FORMAT, newSize, mipmapData, false); + else + { + MipMap[i] = new CImage(BURNINGSHADER_COLOR_FORMAT, newSize); + IImage* tmpImage = new CImage(BURNINGSHADER_COLOR_FORMAT, origSize, mipmapData, true, false); + tmpImage->copyToScalingBoxFilter(MipMap[i]); + tmpImage->drop(); + } + } + mipmapData = (u8*)mipmapData+origSize.getArea()*IImage::getBitsPerPixelFromFormat(OriginalFormat)/8; + } + else + { + MipMap[i] = new CImage(BURNINGSHADER_COLOR_FORMAT, newSize); + MipMap[i]->fill ( 0 ); + MipMap[0]->copyToScalingBoxFilter( MipMap[i], 0, false ); + } } } @@ -129,4 +150,3 @@ void CSoftwareTexture2::regenerateMipMapLevels() } // end namespace irr #endif // _IRR_COMPILE_WITH_BURNINGSVIDEO_ - diff --git a/source/Irrlicht/CSoftwareTexture2.h b/source/Irrlicht/CSoftwareTexture2.h index 36a77ea1..c117d9dc 100644 --- a/source/Irrlicht/CSoftwareTexture2.h +++ b/source/Irrlicht/CSoftwareTexture2.h @@ -25,19 +25,21 @@ public: //! constructor enum eTex2Flags { - GEN_MIPMAP = 1, + GEN_MIPMAP = 1, IS_RENDERTARGET = 2, - NP2_SIZE = 4, - HAS_ALPHA = 8 + NP2_SIZE = 4, + HAS_ALPHA = 8 }; - CSoftwareTexture2( IImage* surface, const io::path& name, u32 flags ); + CSoftwareTexture2(IImage* surface, const io::path& name, u32 flags, void* mipmapData=0); //! destructor virtual ~CSoftwareTexture2(); //! lock function - virtual void* lock(bool readOnly = false) + virtual void* lock(bool readOnly = false, u32 mipmapLevel=0) { + if (Flags & GEN_MIPMAP) + MipMapLOD=mipmapLevel; return MipMap[MipMapLOD]->lock(); } @@ -99,14 +101,7 @@ public: //! Regenerates the mip map levels of the texture. Useful after locking and //! modifying the texture - virtual void regenerateMipMapLevels(); - - //! Select a Mipmap Level - virtual void setCurrentMipMapLOD ( s32 lod ) - { - if ( Flags & GEN_MIPMAP ) - MipMapLOD = lod; - } + virtual void regenerateMipMapLevels(void* mipmapData=0); //! support mipmaps virtual bool hasMipMaps() const @@ -131,8 +126,9 @@ private: CImage * MipMap[SOFTWARE_DRIVER_2_MIPMAPPING_MAX]; - s32 MipMapLOD; + u32 MipMapLOD; u32 Flags; + ECOLOR_FORMAT OriginalFormat; }; diff --git a/source/Irrlicht/CTerrainSceneNode.cpp b/source/Irrlicht/CTerrainSceneNode.cpp index a7f77089..11c1ef66 100644 --- a/source/Irrlicht/CTerrainSceneNode.cpp +++ b/source/Irrlicht/CTerrainSceneNode.cpp @@ -12,7 +12,6 @@ #include "IVideoDriver.h" #include "ISceneManager.h" #include "ICameraSceneNode.h" -#include "SMeshBufferLightMap.h" #include "SViewFrustum.h" #include "irrMath.h" #include "os.h" @@ -21,6 +20,8 @@ #include "IReadFile.h" #include "ITextSceneNode.h" #include "IAnimatedMesh.h" +#include "SMesh.h" +#include "CDynamicMeshBuffer.h" namespace irr { @@ -47,6 +48,7 @@ namespace scene setDebugName("CTerrainSceneNode"); #endif + Mesh = new SMesh(); RenderBuffer = new CDynamicMeshBuffer(video::EVT_2TCOORDS, video::EIT_16BIT); RenderBuffer->setHardwareMappingHint(scene::EHM_STATIC, scene::EBT_VERTEX); RenderBuffer->setHardwareMappingHint(scene::EHM_DYNAMIC, scene::EBT_INDEX); @@ -66,6 +68,9 @@ namespace scene if (FileSystem) FileSystem->drop(); + if (Mesh) + Mesh->drop(); + if (RenderBuffer) RenderBuffer->drop(); } @@ -78,7 +83,7 @@ namespace scene if (!file) return false; - Mesh.MeshBuffers.clear(); + Mesh->MeshBuffers.clear(); const u32 startTime = os::Timer::getRealTime(); video::IImage* heightMap = SceneManager->getVideoDriver()->createImageFromFile(file); @@ -129,8 +134,6 @@ namespace scene // --- Generate vertex data from heightmap ---- // resize the vertex array for the mesh buffer one time (makes loading faster) - //SMeshBufferLightMap* mb = new SMeshBufferLightMap(); - scene::CDynamicMeshBuffer *mb=0; const u32 numVertices = TerrainData.Size * TerrainData.Size; @@ -187,7 +190,7 @@ namespace scene calculateNormals(mb); // add the MeshBuffer to the mesh - Mesh.addMeshBuffer(mb); + Mesh->addMeshBuffer(mb); // We copy the data to the renderBuffer, after the normals have been calculated. RenderBuffer->getVertexBuffer().set_used(numVertices); @@ -247,7 +250,7 @@ namespace scene // start reading const u32 startTime = os::Timer::getTime(); - Mesh.MeshBuffers.clear(); + Mesh->MeshBuffers.clear(); const s32 bytesPerPixel = bitsPerPixel / 8; @@ -425,7 +428,7 @@ namespace scene calculateNormals(mb); // add the MeshBuffer to the mesh - Mesh.addMeshBuffer(mb); + Mesh->addMeshBuffer(mb); const u32 vertexCount = mb->getVertexCount(); // We copy the data to the renderBuffer, after the normals have been calculated. @@ -470,12 +473,31 @@ namespace scene } + //! Returns the mesh + IMesh* CTerrainSceneNode::getMesh() { return Mesh; } + + + //! Returns the material based on the zero based index i. + video::SMaterial& CTerrainSceneNode::getMaterial(u32 i) + { + return Mesh->getMeshBuffer(i)->getMaterial(); + } + + + //! Returns amount of materials used by this scene node ( always 1 ) + u32 CTerrainSceneNode::getMaterialCount() const + { + return Mesh->getMeshBufferCount(); + } + + //! Sets the scale of the scene node. //! \param scale: New scale of the node void CTerrainSceneNode::setScale(const core::vector3df& scale) { TerrainData.Scale = scale; applyTransformation(); + calculateNormals(RenderBuffer); ForceRecalculation = true; } @@ -514,17 +536,17 @@ namespace scene //! Apply transformation changes(scale, position, rotation) void CTerrainSceneNode::applyTransformation() { - if (!Mesh.getMeshBufferCount()) + if (!Mesh->getMeshBufferCount()) return; TerrainData.Position = TerrainData.Position; - s32 vtxCount = Mesh.getMeshBuffer(0)->getVertexCount(); + s32 vtxCount = Mesh->getMeshBuffer(0)->getVertexCount(); core::matrix4 rotMatrix; rotMatrix.setRotationDegrees(TerrainData.Rotation); for (s32 i = 0; i < vtxCount; ++i) { - RenderBuffer->getVertexBuffer()[i].Pos = Mesh.getMeshBuffer(0)->getPosition(i) * TerrainData.Scale + TerrainData.Position; + RenderBuffer->getVertexBuffer()[i].Pos = Mesh->getMeshBuffer(0)->getPosition(i) * TerrainData.Scale + TerrainData.Position; RenderBuffer->getVertexBuffer()[i].Pos -= TerrainData.RotationPivot; rotMatrix.inverseRotateVect(RenderBuffer->getVertexBuffer()[i].Pos); @@ -698,13 +720,13 @@ namespace scene if (!IsVisible || !SceneManager->getActiveCamera()) return; - if (!Mesh.getMeshBufferCount()) + if (!Mesh->getMeshBufferCount()) return; video::IVideoDriver* driver = SceneManager->getVideoDriver(); driver->setTransform (video::ETS_WORLD, core::IdentityMatrix); - driver->setMaterial(Mesh.getMeshBuffer(0)->getMaterial()); + driver->setMaterial(Mesh->getMeshBuffer(0)->getMaterial()); RenderBuffer->getIndexBuffer().set_used(IndicesToRender); @@ -810,14 +832,14 @@ namespace scene //! \param LOD: The Level Of Detail you want the indices from. void CTerrainSceneNode::getMeshBufferForLOD(IDynamicMeshBuffer& mb, s32 LOD ) const { - if (!Mesh.getMeshBufferCount()) + if (!Mesh->getMeshBufferCount()) return; LOD = core::clamp(LOD, 0, TerrainData.MaxLOD - 1); - const u32 numVertices = Mesh.getMeshBuffer(0)->getVertexCount(); + const u32 numVertices = Mesh->getMeshBuffer(0)->getVertexCount(); mb.getVertexBuffer().reallocate(numVertices); - video::S3DVertex2TCoords* vertices = (video::S3DVertex2TCoords*)Mesh.getMeshBuffer(0)->getVertices(); + video::S3DVertex2TCoords* vertices = (video::S3DVertex2TCoords*)Mesh->getMeshBuffer(0)->getVertices(); for (u32 n=0; ngetMeshBufferCount()) return 0; f32 height = -999999.9f; @@ -1371,7 +1393,7 @@ namespace scene if (X >= 0 && X < TerrainData.Size-1 && Z >= 0 && Z < TerrainData.Size-1) { - const video::S3DVertex2TCoords* Vertices = (const video::S3DVertex2TCoords*)Mesh.getMeshBuffer(0)->getVertices(); + const video::S3DVertex2TCoords* Vertices = (const video::S3DVertex2TCoords*)Mesh->getMeshBuffer(0)->getVertices(); const core::vector3df& a = Vertices[X * TerrainData.Size + Z].Pos; const core::vector3df& b = Vertices[(X + 1) * TerrainData.Size + Z].Pos; const core::vector3df& c = Vertices[X * TerrainData.Size + (Z + 1)].Pos; @@ -1478,18 +1500,18 @@ namespace scene // copy materials - for (unsigned int m = 0; mgetMeshBufferCount(); ++m) { - if (nb->Mesh.getMeshBufferCount()>m && - nb->Mesh.getMeshBuffer(m) && - Mesh.getMeshBuffer(m)) + if (nb->Mesh->getMeshBufferCount()>m && + nb->Mesh->getMeshBuffer(m) && + Mesh->getMeshBuffer(m)) { - nb->Mesh.getMeshBuffer(m)->getMaterial() = - Mesh.getMeshBuffer(m)->getMaterial(); + nb->Mesh->getMeshBuffer(m)->getMaterial() = + Mesh->getMeshBuffer(m)->getMaterial(); } } - nb->RenderBuffer->Material = RenderBuffer->Material; + nb->RenderBuffer->getMaterial() = RenderBuffer->getMaterial(); // finish diff --git a/source/Irrlicht/CTerrainSceneNode.h b/source/Irrlicht/CTerrainSceneNode.h index 66705ef3..f5843d15 100644 --- a/source/Irrlicht/CTerrainSceneNode.h +++ b/source/Irrlicht/CTerrainSceneNode.h @@ -10,8 +10,7 @@ #define __C_TERRAIN_SCENE_NODE_H__ #include "ITerrainSceneNode.h" -#include "SMesh.h" -#include "CDynamicMeshBuffer.h" +#include "IDynamicMeshBuffer.h" #include "path.h" namespace irr @@ -23,6 +22,7 @@ namespace io } namespace scene { + struct SMesh; class ITextSceneNode; //! A scene node for displaying terrain using the geo mip map algorithm. @@ -62,17 +62,11 @@ namespace scene //! 1 material. //! \param i: Zero based index i. UNUSED, left in for virtual purposes. //! \return Returns the single material this scene node uses. - virtual video::SMaterial& getMaterial ( u32 i ) - { - return Mesh.getMeshBuffer(i)->getMaterial(); - } + virtual video::SMaterial& getMaterial(u32 i); //! Returns amount of materials used by this scene node ( always 1 ) //! \return Returns current count of materials used by this scene node ( always 1 ) - virtual u32 getMaterialCount() const - { - return Mesh.getMeshBufferCount(); - } + virtual u32 getMaterialCount() const; //! Gets the last scaling factor applied to the scene node. This value only represents the //! last scaling factor presented to the node. For instance, if you make create the node @@ -136,7 +130,7 @@ namespace scene virtual u32 getIndexCount() const { return IndicesToRender; } //! Returns the mesh - virtual IMesh* getMesh() { return &Mesh; } + virtual IMesh* getMesh(); //! Returns a pointer to the buffer used by the terrain (most users will not need this) virtual IMeshBuffer* getRenderBuffer() { return RenderBuffer; } @@ -283,10 +277,10 @@ namespace scene u32 getIndex(const s32 PatchX, const s32 PatchZ, const s32 PatchIndex, u32 vX, u32 vZ) const; //! smooth the terrain - void smoothTerrain(CDynamicMeshBuffer* mb, s32 smoothFactor); + void smoothTerrain(IDynamicMeshBuffer* mb, s32 smoothFactor); //! calculate smooth normals - void calculateNormals(CDynamicMeshBuffer* mb); + void calculateNormals(IDynamicMeshBuffer* mb); //! create patches, stuff that needs to only be done once for patches goes here. void createPatches(); @@ -307,9 +301,9 @@ namespace scene void applyTransformation(); STerrainData TerrainData; - SMesh Mesh; + SMesh* Mesh; - CDynamicMeshBuffer *RenderBuffer; + IDynamicMeshBuffer *RenderBuffer; u32 VerticesToRender; u32 IndicesToRender; diff --git a/source/Irrlicht/CWaterSurfaceSceneNode.cpp b/source/Irrlicht/CWaterSurfaceSceneNode.cpp index 14a0ab4c..317de214 100644 --- a/source/Irrlicht/CWaterSurfaceSceneNode.cpp +++ b/source/Irrlicht/CWaterSurfaceSceneNode.cpp @@ -100,7 +100,7 @@ void CWaterSurfaceSceneNode::serializeAttributes(io::IAttributes* out, io::SAttr CMeshSceneNode::serializeAttributes(out, options); // serialize original mesh - out->setAttribute("Mesh", SceneManager->getMeshCache()->getMeshFilename(OriginalMesh).c_str()); + out->setAttribute("Mesh", SceneManager->getMeshCache()->getMeshName(OriginalMesh).getPath().c_str()); } diff --git a/source/Irrlicht/CZipReader.cpp b/source/Irrlicht/CZipReader.cpp index d7b70659..2834af17 100644 --- a/source/Irrlicht/CZipReader.cpp +++ b/source/Irrlicht/CZipReader.cpp @@ -15,10 +15,32 @@ #ifdef _IRR_COMPILE_WITH_ZLIB_ #ifndef _IRR_USE_NON_SYSTEM_ZLIB_ #include // use system lib - #else // _IRR_USE_NON_SYSTEM_ZLIB_ + #else #include "zlib/zlib.h" - #endif // _IRR_USE_NON_SYSTEM_ZLIB_ -#endif // _IRR_COMPILE_WITH_ZLIB_ + #endif + + #ifdef _IRR_COMPILE_WITH_ZIP_ENCRYPTION_ + #include "aesGladman/fileenc.h" + #endif + #ifdef _IRR_COMPILE_WITH_BZIP2_ + #ifndef _IRR_USE_NON_SYSTEM_BZLIB_ + #include + #else + #include "bzip2/bzlib.h" + #endif + #endif + #ifdef _IRR_COMPILE_WITH_LZMA_ + #include "lzma/LzmaDec.h" + #endif +#endif + +#ifdef BZ_NO_STDIO +// This method is used for error output from bzip2. +extern "C" void bz_internal_error(int errorCode) +{ + irr::os::Printer::log("Error in bzip2 handling", irr::core::stringc(errorCode), irr::ELL_ERROR); +} +#endif namespace irr { @@ -341,7 +363,7 @@ bool CZipReader::scanGZipHeader() os::Byteswap::byteswap(entry.header.DataDescriptor.UncompressedSize); #endif - //! now we've filled all the fields, this is just a standard deflate block + // now we've filled all the fields, this is just a standard deflate block addItem(ZipFileName, entry.header.DataDescriptor.UncompressedSize, false, 0); FileInfo.push_back(entry); } @@ -386,8 +408,46 @@ bool CZipReader::scanZipHeader() delete [] tmp; } +#ifdef _IRR_COMPILE_WITH_ZIP_ENCRYPTION_ + // AES encryption + if ((entry.header.GeneralBitFlag & ZIP_FILE_ENCRYPTED) && (entry.header.CompressionMethod == 99)) + { + s16 restSize = entry.header.ExtraFieldLength; + SZipFileExtraHeader extraHeader; + while (restSize) + { + File->read(&extraHeader, sizeof(extraHeader)); +#ifdef __BIG_ENDIAN__ + extraHeader.ID = os::Byteswap::byteswap(extraHeader.ID); + extraHeader.Size = os::Byteswap::byteswap(extraHeader.Size); +#endif + restSize -= sizeof(extraHeader); + if (extraHeader.ID==(s16)0x9901) + { + SZipFileAESExtraData data; + File->read(&data, sizeof(data)); +#ifdef __BIG_ENDIAN__ + data.Version = os::Byteswap::byteswap(data.Version); + data.CompressionMode = os::Byteswap::byteswap(data.CompressionMode); +#endif + restSize -= sizeof(data); + if (data.Vendor[0]=='A' && data.Vendor[1]=='E') + { + // encode values into Sig + // AE-Version | Strength | ActualMode + entry.header.Sig = + ((data.Version & 0xff) << 24) | + (data.EncryptionStrength << 16) | + (data.CompressionMode); + File->seek(restSize, true); + break; + } + } + } + } // move forward length of extra field. - + else +#endif if (entry.header.ExtraFieldLength) File->seek(entry.header.ExtraFieldLength, true); @@ -430,11 +490,20 @@ IReadFile* CZipReader::createAndOpenFile(const io::path& filename) return 0; } +#ifdef _IRR_COMPILE_WITH_LZMA_ +//! Used for LZMA decompression. The lib has no default memory management +namespace +{ + void *SzAlloc(void *p, size_t size) { p = p; return malloc(size); } + void SzFree(void *p, void *address) { p = p; free(address); } + ISzAlloc lzmaAlloc = { SzAlloc, SzFree }; +} +#endif //! opens a file by index IReadFile* CZipReader::createAndOpenFile(u32 index) { - + // Irrlicht supports 0, 8, 12, 14, 99 //0 - The file is stored (no compression) //1 - The file is Shrunk //2 - The file is Reduced with compression factor 1 @@ -446,49 +515,143 @@ IReadFile* CZipReader::createAndOpenFile(u32 index) //8 - The file is Deflated //9 - Reserved for enhanced Deflating //10 - PKWARE Date Compression Library Imploding + //12 - bzip2 - Compression Method from libbz2, WinZip 10 + //14 - LZMA - Compression Method, WinZip 12 + //96 - Jpeg compression - Compression Method, WinZip 12 + //97 - WavPack - Compression Method, WinZip 11 + //98 - PPMd - Compression Method, WinZip 10 + //99 - AES encryption, WinZip 9 const SZipFileEntry &e = FileInfo[Files[index].ID]; wchar_t buf[64]; - switch(e.header.CompressionMethod) + s16 actualCompressionMethod=e.header.CompressionMethod; + IReadFile* decrypted=0; + u8* decryptedBuf=0; + u32 decryptedSize=e.header.DataDescriptor.CompressedSize; +#ifdef _IRR_COMPILE_WITH_ZIP_ENCRYPTION_ + if ((e.header.GeneralBitFlag & ZIP_FILE_ENCRYPTED) && (e.header.CompressionMethod == 99)) + { + os::Printer::log("Reading encrypted file."); + u8 salt[16]={0}; + const u16 saltSize = (((e.header.Sig & 0x00ff0000) >>16)+1)*4; + File->seek(e.Offset); + File->read(salt, saltSize); + char pwVerification[2]; + char pwVerificationFile[2]; + File->read(pwVerification, 2); + fcrypt_ctx zctx; // the encryption context + int rc = fcrypt_init( + (e.header.Sig & 0x00ff0000) >>16, + (const unsigned char*)Password.c_str(), // the password + Password.size(), // number of bytes in password + salt, // the salt + (unsigned char*)pwVerificationFile, // on return contains password verifier + &zctx); // encryption context + if (strncmp(pwVerificationFile, pwVerification, 2)) + { + os::Printer::log("Wrong password"); + return 0; + } + decryptedSize= e.header.DataDescriptor.CompressedSize-saltSize-12; + decryptedBuf= new u8[decryptedSize]; + u32 c = 0; + while ((c+32768)<=decryptedSize) + { + File->read(decryptedBuf+c, 32768); + fcrypt_decrypt( + decryptedBuf+c, // pointer to the data to decrypt + 32768, // how many bytes to decrypt + &zctx); // decryption context + c+=32768; + } + File->read(decryptedBuf+c, decryptedSize-c); + fcrypt_decrypt( + decryptedBuf+c, // pointer to the data to decrypt + decryptedSize-c, // how many bytes to decrypt + &zctx); // decryption context + + char fileMAC[10]; + char resMAC[10]; + rc = fcrypt_end( + (unsigned char*)resMAC, // on return contains the authentication code + &zctx); // encryption context + if (rc != 10) + { + os::Printer::log("Error on encryption closing"); + delete [] decryptedBuf; + return 0; + } + File->read(fileMAC, 10); + if (strncmp(fileMAC, resMAC, 10)) + { + os::Printer::log("Error on encryption check"); + delete [] decryptedBuf; + return 0; + } + decrypted = io::createMemoryReadFile(decryptedBuf, decryptedSize, Files[index].FullName, true); + actualCompressionMethod = (e.header.Sig & 0xffff); +#if 0 + if ((e.header.Sig & 0xff000000)==0x01000000) + { + } + else if ((e.header.Sig & 0xff000000)==0x02000000) + { + } + else + { + os::Printer::log("Unknown encryption method"); + return 0; + } +#endif + } +#endif + switch(actualCompressionMethod) { case 0: // no compression { - return createLimitReadFile(Files[index].FullName, File, e.Offset, e.header.DataDescriptor.CompressedSize); + if (decrypted) + return decrypted; + else + return createLimitReadFile(Files[index].FullName, File, e.Offset, decryptedSize); } case 8: { #ifdef _IRR_COMPILE_WITH_ZLIB_ const u32 uncompressedSize = e.header.DataDescriptor.UncompressedSize; - const u32 compressedSize = e.header.DataDescriptor.CompressedSize; - - void* pBuf = new c8[ uncompressedSize ]; + c8* pBuf = new c8[ uncompressedSize ]; if (!pBuf) { swprintf ( buf, 64, L"Not enough memory for decompressing %s", Files[index].FullName.c_str() ); os::Printer::log( buf, ELL_ERROR); + if (decrypted) + decrypted->drop(); return 0; } - c8 *pcData = new c8[ compressedSize ]; + u8 *pcData = decryptedBuf; if (!pcData) { - swprintf ( buf, 64, L"Not enough memory for decompressing %s", Files[index].FullName.c_str() ); - os::Printer::log( buf, ELL_ERROR); - delete [] (c8*)pBuf; - return 0; - } + pcData = new u8[decryptedSize]; + if (!pcData) + { + swprintf ( buf, 64, L"Not enough memory for decompressing %s", Files[index].FullName.c_str() ); + os::Printer::log( buf, ELL_ERROR); + delete [] pBuf; + return 0; + } - //memset(pcData, 0, compressedSize ); - File->seek(e.Offset); - File->read(pcData, compressedSize ); + //memset(pcData, 0, decryptedSize); + File->seek(e.Offset); + File->read(pcData, decryptedSize); + } // Setup the inflate stream. z_stream stream; s32 err; stream.next_in = (Bytef*)pcData; - stream.avail_in = (uInt)compressedSize; + stream.avail_in = (uInt)decryptedSize; stream.next_out = (Bytef*)pBuf; stream.avail_out = uncompressedSize; stream.zalloc = (alloc_func)0; @@ -506,13 +669,16 @@ IReadFile* CZipReader::createAndOpenFile(u32 index) inflateEnd(&stream); } - delete[] pcData; + if (decrypted) + decrypted->drop(); + else + delete[] pcData; if (err != Z_OK) { swprintf ( buf, 64, L"Error decompressing %s", Files[index].FullName.c_str() ); os::Printer::log( buf, ELL_ERROR); - delete [] (c8*)pBuf; + delete [] pBuf; return 0; } else @@ -522,6 +688,143 @@ IReadFile* CZipReader::createAndOpenFile(u32 index) return 0; // zlib not compiled, we cannot decompress the data. #endif } + case 12: + { + #ifdef _IRR_COMPILE_WITH_BZIP2_ + + const u32 uncompressedSize = e.header.DataDescriptor.UncompressedSize; + c8* pBuf = new c8[ uncompressedSize ]; + if (!pBuf) + { + swprintf ( buf, 64, L"Not enough memory for decompressing %s", Files[index].FullName.c_str() ); + os::Printer::log( buf, ELL_ERROR); + if (decrypted) + decrypted->drop(); + return 0; + } + + u8 *pcData = decryptedBuf; + if (!pcData) + { + pcData = new u8[decryptedSize]; + if (!pcData) + { + swprintf ( buf, 64, L"Not enough memory for decompressing %s", Files[index].FullName.c_str() ); + os::Printer::log( buf, ELL_ERROR); + delete [] pBuf; + return 0; + } + + //memset(pcData, 0, decryptedSize); + File->seek(e.Offset); + File->read(pcData, decryptedSize); + } + + bz_stream bz_ctx={0}; + /* use BZIP2's default memory allocation + bz_ctx->bzalloc = NULL; + bz_ctx->bzfree = NULL; + bz_ctx->opaque = NULL; + */ + int err = BZ2_bzDecompressInit(&bz_ctx, 0, 0); /* decompression */ + if(err != BZ_OK) + { + os::Printer::log("bzip2 decompression failed. File cannot be read.", ELL_ERROR); + return 0; + } + bz_ctx.next_in = (char*)pcData; + bz_ctx.avail_in = decryptedSize; + /* pass all input to decompressor */ + bz_ctx.next_out = pBuf; + bz_ctx.avail_out = uncompressedSize; + err = BZ2_bzDecompress(&bz_ctx); + err = BZ2_bzDecompressEnd(&bz_ctx); + + if (decrypted) + decrypted->drop(); + else + delete[] pcData; + + if (err != BZ_OK) + { + swprintf ( buf, 64, L"Error decompressing %s", Files[index].FullName.c_str() ); + os::Printer::log( buf, ELL_ERROR); + delete [] pBuf; + return 0; + } + else + return io::createMemoryReadFile(pBuf, uncompressedSize, Files[index].FullName, true); + + #else + os::Printer::log("bzip2 decompression not supported. File cannot be read.", ELL_ERROR); + return 0; + #endif + } + case 14: + { + #ifdef _IRR_COMPILE_WITH_LZMA_ + + u32 uncompressedSize = e.header.DataDescriptor.UncompressedSize; + c8* pBuf = new c8[ uncompressedSize ]; + if (!pBuf) + { + swprintf ( buf, 64, L"Not enough memory for decompressing %s", Files[index].FullName.c_str() ); + os::Printer::log( buf, ELL_ERROR); + if (decrypted) + decrypted->drop(); + return 0; + } + + u8 *pcData = decryptedBuf; + if (!pcData) + { + pcData = new u8[decryptedSize]; + if (!pcData) + { + swprintf ( buf, 64, L"Not enough memory for decompressing %s", Files[index].FullName.c_str() ); + os::Printer::log( buf, ELL_ERROR); + delete [] pBuf; + return 0; + } + + //memset(pcData, 0, decryptedSize); + File->seek(e.Offset); + File->read(pcData, decryptedSize); + } + + ELzmaStatus status; + SizeT tmpDstSize = uncompressedSize; + SizeT tmpSrcSize = decryptedSize; + + int err = LzmaDecode((Byte*)pBuf, &tmpDstSize, + pcData, &tmpSrcSize, + 0, 0, LZMA_FINISH_END, &status, &lzmaAlloc); + uncompressedSize = tmpDstSize; // may be different to expected value + + if (decrypted) + decrypted->drop(); + else + delete[] pcData; + + if (err != SZ_OK) + { + swprintf ( buf, 64, L"Error decompressing %s", Files[index].FullName.c_str() ); + os::Printer::log( buf, ELL_ERROR); + delete [] pBuf; + return 0; + } + else + return io::createMemoryReadFile(pBuf, uncompressedSize, Files[index].FullName, true); + + #else + os::Printer::log("lzma decompression not supported. File cannot be read.", ELL_ERROR); + return 0; + #endif + } + case 99: + // If we come here with an encrypted file, decryption support is missing + os::Printer::log("Decryption support not enabled. File cannot be read.", ELL_ERROR); + return 0; default: swprintf ( buf, 64, L"file has unsupported compression method. %s", Files[index].FullName.c_str() ); os::Printer::log( buf, ELL_ERROR); diff --git a/source/Irrlicht/CZipReader.h b/source/Irrlicht/CZipReader.h index 85ab459d..cedb6658 100644 --- a/source/Irrlicht/CZipReader.h +++ b/source/Irrlicht/CZipReader.h @@ -97,6 +97,20 @@ namespace io // zipfile comment (variable size) } PACK_STRUCT; + struct SZipFileExtraHeader + { + s16 ID; + s16 Size; + } PACK_STRUCT; + + struct SZipFileAESExtraData + { + s16 Version; + u8 Vendor[2]; + u8 EncryptionStrength; + s16 CompressionMode; + } PACK_STRUCT; + enum E_GZIP_FLAGS { EGZF_TEXT_DAT = 1, @@ -217,3 +231,4 @@ namespace io #endif // __IRR_COMPILE_WITH_ZIP_ARCHIVE_LOADER_ #endif // __C_ZIP_READER_H_INCLUDED__ + diff --git a/source/Irrlicht/IAttribute.h b/source/Irrlicht/IAttribute.h new file mode 100644 index 00000000..0a62c5da --- /dev/null +++ b/source/Irrlicht/IAttribute.h @@ -0,0 +1,106 @@ +// Copyright (C) 2002-2009 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#ifndef __I_ATTRIBUTE_H_INCLUDED__ +#define __I_ATTRIBUTE_H_INCLUDED__ + +#include "IReferenceCounted.h" +#include "SColor.h" +#include "vector3d.h" +#include "vector2d.h" +#include "line2d.h" +#include "line3d.h" +#include "triangle3d.h" +#include "position2d.h" +#include "rect.h" +#include "matrix4.h" +#include "quaternion.h" +#include "plane3d.h" +#include "triangle3d.h" +#include "line2d.h" +#include "line3d.h" +#include "irrString.h" +#include "irrArray.h" +#include "EAttributes.h" + + +namespace irr +{ +namespace io +{ + +class IAttribute : public virtual IReferenceCounted +{ +public: + + virtual ~IAttribute() {}; + + virtual s32 getInt() { return 0; } + virtual f32 getFloat() { return 0; } + virtual video::SColorf getColorf() { return video::SColorf(1.0f,1.0f,1.0f,1.0f); } + virtual video::SColor getColor() { return video::SColor(255,255,255,255); } + virtual core::stringc getString() { return core::stringc(getStringW().c_str()); } + virtual core::stringw getStringW() { return core::stringw(); } + virtual core::array getArray() { return core::array(); }; + virtual bool getBool() { return false; } + virtual void getBinary(void* outdata, s32 maxLength) {}; + virtual core::vector3df getVector() { return core::vector3df(); } + virtual core::position2di getPosition() { return core::position2di(); } + virtual core::rect getRect() { return core::rect(); } + virtual core::quaternion getQuaternion(){ return core::quaternion(); } + virtual core::matrix4 getMatrix() { return core::matrix4(); } + virtual core::triangle3df getTriangle() { return core::triangle3df(); } + virtual core::vector2df getVector2d() { return core::vector2df(); } + virtual core::vector2di getVector2di() { return core::vector2di(); } + virtual core::line2df getLine2d() { return core::line2df(); } + virtual core::line2di getLine2di() { return core::line2di(); } + virtual core::line3df getLine3d() { return core::line3df(); } + virtual core::line3di getLine3di() { return core::line3di(); } + virtual core::dimension2du getDimension2d() { return core::dimension2du(); } + virtual core::aabbox3d getBBox() { return core::aabbox3d(); } + virtual core::plane3df getPlane() { return core::plane3df(); } + + virtual video::ITexture* getTexture() { return 0; } + virtual const char* getEnum() { return 0; } + virtual void* getUserPointer() { return 0; } + + virtual void setInt(s32 intValue) {}; + virtual void setFloat(f32 floatValue) {}; + virtual void setString(const char* text) {}; + virtual void setString(const wchar_t* text){ setString(core::stringc(text).c_str()); }; + virtual void setArray(const core::array& arr ) {}; + virtual void setColor(video::SColorf color) {}; + virtual void setColor(video::SColor color) {}; + virtual void setBool(bool boolValue) {}; + virtual void setBinary(void* data, s32 maxLenght) {}; + virtual void setVector(core::vector3df v) {}; + virtual void setPosition(core::position2di v) {}; + virtual void setRect(core::rect v) {}; + virtual void setQuaternion(core::quaternion v) {}; + virtual void setMatrix(core::matrix4 v) {}; + virtual void setTriangle(core::triangle3df v) {}; + virtual void setVector2d(core::vector2df v) {}; + virtual void setVector2d(core::vector2di v) {}; + virtual void setLine2d(core::line2df v) {}; + virtual void setLine2d(core::line2di v) {}; + virtual void setLine3d(core::line3df v) {}; + virtual void setLine3d(core::line3di v) {}; + virtual void setDimension2d(core::dimension2du v) {}; + virtual void setBBox(core::aabbox3d v) {}; + virtual void setPlane(core::plane3df v) {}; + virtual void setUserPointer(void* v) {}; + + virtual void setEnum(const char* enumValue, const char* const* enumerationLiterals) {}; + virtual void setTexture(video::ITexture*) {}; + + core::stringc Name; + + virtual E_ATTRIBUTE_TYPE getType() const = 0; + virtual const wchar_t* getTypeString() const = 0; +}; + +} // end namespace io +} // end namespace irr + +#endif diff --git a/source/Irrlicht/IBurningShader.cpp b/source/Irrlicht/IBurningShader.cpp index bb2e99c6..6e180a99 100644 --- a/source/Irrlicht/IBurningShader.cpp +++ b/source/Irrlicht/IBurningShader.cpp @@ -10,11 +10,10 @@ namespace irr { - namespace video { - const tFixPointu IBurningShader::dithermask[ 4 * 4] = + const tFixPointu IBurningShader::dithermask[] = { 0x00,0x80,0x20,0xa0, 0xc0,0x40,0xe0,0x60, @@ -23,7 +22,7 @@ namespace video }; IBurningShader::IBurningShader(IDepthBuffer* zbuffer) - :RenderTarget(0),DepthBuffer(zbuffer) + : RenderTarget(0),DepthBuffer(zbuffer) { #ifdef _DEBUG setDebugName("IBurningShader"); @@ -70,7 +69,6 @@ namespace video //(tVideoSample*)RenderTarget->lock() = (tVideoSample*)RenderTarget->lock(); //(fp24*) DepthBuffer->lock() = DepthBuffer->lock(); } - } @@ -91,9 +89,8 @@ namespace video // select mignify and magnify ( lodLevel ) //SOFTWARE_DRIVER_2_MIPMAPPING_LOD_BIAS it->lodLevel = lodLevel; - it->Texture->setCurrentMipMapLOD ( - core::s32_clamp ( lodLevel + SOFTWARE_DRIVER_2_MIPMAPPING_LOD_BIAS, 0, SOFTWARE_DRIVER_2_MIPMAPPING_MAX - 1 ) - ); + it->data = (tVideoSample*) it->Texture->lock(true, + core::s32_clamp ( lodLevel + SOFTWARE_DRIVER_2_MIPMAPPING_LOD_BIAS, 0, SOFTWARE_DRIVER_2_MIPMAPPING_MAX - 1 )); // prepare for optimal fixpoint it->pitchlog2 = s32_log2_s32 ( it->Texture->getPitch() ); @@ -101,12 +98,10 @@ namespace video const core::dimension2d &dim = it->Texture->getSize(); it->textureXMask = s32_to_fixPoint ( dim.Width - 1 ) & FIX_POINT_UNSIGNED_MASK; it->textureYMask = s32_to_fixPoint ( dim.Height - 1 ) & FIX_POINT_UNSIGNED_MASK; - it->data = (tVideoSample*) it->Texture->lock(); } } - } // end namespace video } // end namespace irr diff --git a/source/Irrlicht/Irrlicht-gcc.cbp b/source/Irrlicht/Irrlicht-gcc.cbp index fed23ccb..9c334b42 100644 --- a/source/Irrlicht/Irrlicht-gcc.cbp +++ b/source/Irrlicht/Irrlicht-gcc.cbp @@ -423,6 +423,7 @@ + @@ -447,7 +448,7 @@ - + @@ -469,6 +470,7 @@ + @@ -499,7 +501,6 @@ - @@ -771,6 +772,8 @@ + + @@ -781,10 +784,10 @@ - - - - + + + + @@ -808,8 +811,6 @@ - - @@ -941,6 +942,7 @@ + @@ -950,21 +952,67 @@ - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -997,9 +1045,6 @@ - - @@ -1015,6 +1060,9 @@ + + @@ -1050,9 +1098,6 @@ - - @@ -1084,9 +1129,6 @@ - -