From 07f17647d2cd3544fb39ea2af7ad59066c554b36 Mon Sep 17 00:00:00 2001 From: cutealien Date: Thu, 22 Sep 2022 21:55:03 +0000 Subject: [PATCH] Merging r6405 through r6424 from trunk to ogl-es branch git-svn-id: svn://svn.code.sf.net/p/irrlicht/code/branches/ogl-es@6425 dfc29bdd-3216-0410-991c-e03cc46cb475 --- changes.txt | 3 + examples/02.Quake3Map/Makefile | 1 + examples/04.Movement/main.cpp | 14 +- examples/09.Meshviewer/Makefile | 1 + examples/26.OcclusionQuery/main.cpp | 9 +- examples/27.PostProcessing/main.cpp | 561 +++++++++--------- examples/28.CubeMapping/main.cpp | 12 +- include/CMeshBuffer.h | 11 + include/ICameraSceneNode.h | 17 +- include/IDynamicMeshBuffer.h | 12 + include/ILightManager.h | 17 +- include/IMeshBuffer.h | 6 + include/IMeshManipulator.h | 49 +- include/SSharedMeshBuffer.h | 15 + include/SSkinMeshBuffer.h | 28 + include/SVertexManipulator.h | 26 + include/irrString.h | 6 +- include/matrix4.h | 4 +- source/Irrlicht/CCameraSceneNode.cpp | 9 +- source/Irrlicht/CColladaMeshWriter.cpp | 12 +- source/Irrlicht/CD3D9Driver.cpp | 2 +- source/Irrlicht/CGUIContextMenu.cpp | 4 +- source/Irrlicht/CGUIEnvironment.cpp | 2 +- source/Irrlicht/CImageLoaderJPG.cpp | 2 +- source/Irrlicht/CImageLoaderPNG.cpp | 34 +- source/Irrlicht/CImageLoaderPSD.cpp | 16 +- source/Irrlicht/CImageLoaderTGA.cpp | 2 +- source/Irrlicht/CImageWriterPNG.cpp | 8 +- source/Irrlicht/CIrrDeviceLinux.cpp | 24 +- source/Irrlicht/CIrrDeviceSDL.cpp | 8 +- source/Irrlicht/CIrrDeviceSDL.h | 11 +- source/Irrlicht/CIrrMeshFileLoader.cpp | 2 +- source/Irrlicht/CLWOMeshFileLoader.cpp | 2 +- source/Irrlicht/CMD2MeshFileLoader.cpp | 4 +- source/Irrlicht/CMS3DMeshFileLoader.cpp | 20 +- source/Irrlicht/CMeshManipulator.cpp | 58 +- source/Irrlicht/COBJMeshFileLoader.cpp | 2 +- source/Irrlicht/CQ3LevelMesh.cpp | 2 +- source/Irrlicht/CSceneManager.cpp | 4 +- .../Irrlicht/CSceneNodeAnimatorCameraFPS.cpp | 2 +- source/Irrlicht/CSkinnedMesh.cpp | 12 +- source/Irrlicht/CTerrainSceneNode.cpp | 2 +- source/Irrlicht/CWGLManager.cpp | 2 +- source/Irrlicht/CXMeshFileLoader.cpp | 4 +- source/Irrlicht/os.h | 2 + tests/tests-last-passed-at.txt | 8 +- 46 files changed, 589 insertions(+), 463 deletions(-) diff --git a/changes.txt b/changes.txt index 03b0f884..dd53ea2a 100644 --- a/changes.txt +++ b/changes.txt @@ -11,6 +11,8 @@ Changes in ogl-es (not yet released - will be merged with trunk at some point) -------------------------- Changes in 1.9 (not yet released) +- Fix MouseButtonStates for mouse events in CIrrDeviceSDL when middle or right button are released. +- CGUIContextMenu no longer marks EMIE_MOUSE_MOVED as handled - core::array::linear_search and linear_reverse_search can now work with any types as long as corresponding operator== is implemented. - Add checks for sane image sizes in some image loaders (so far: bmp, jpg, tga, png). Thanks @sfan5 for the original patch (got modified a bit): https://github.com/minetest/irrlicht/commit/dbd39120e7ed8c0c97e48e2df62347627f3c1d42 @@ -383,6 +385,7 @@ Changes in 1.9 (not yet released) -------------------------- Changes in 1.8.6 +- Avoid warning about stringop-overflow in string::subString when compiling in release with newer gcc - Update library zlib to 1.2.11 (from 1.2.8) - Update library bzip2 to 1.0.8 (from 1.0.6) - Security: Fix buffer overflow caused by malformed md2 files. Thanks @procfs for reporting (https://irrlicht.sourceforge.io/forum/viewtopic.php?f=7&t=52785) diff --git a/examples/02.Quake3Map/Makefile b/examples/02.Quake3Map/Makefile index 80ae3876..6f17a8bb 100644 --- a/examples/02.Quake3Map/Makefile +++ b/examples/02.Quake3Map/Makefile @@ -25,6 +25,7 @@ all: all_linux # target specific settings all_linux all_win32 static_win32: LDFLAGS += -L$(IrrlichtHome)/lib/$(SYSTEM) -lIrrlicht all_linux: LDFLAGS += -L/usr/X11R6/lib$(LIBSELECT) -lGL -lEGL -lGLESv1_CM -lGLESv2 -lXxf86vm -lXext -lX11 -lXcursor +#all_linux: LDFLAGS += `sdl-config --libs` all_linux clean_linux: SYSTEM=Linux all_win32 clean_win32 static_win32: SYSTEM=Win32-gcc all_win32 clean_win32 static_win32: SUF=.exe diff --git a/examples/04.Movement/main.cpp b/examples/04.Movement/main.cpp index e7d37776..6a3c94b0 100644 --- a/examples/04.Movement/main.cpp +++ b/examples/04.Movement/main.cpp @@ -42,7 +42,7 @@ public: /* Always return false by default. If you return true you tell the engine that you handled this event completely and the Irrlicht should not - process it any further. So for example if you return true for all + process it any further. So for example if you return true for all EET_KEY_INPUT_EVENT events then Irrlicht would not pass on key-events to it's GUI system. */ @@ -54,7 +54,7 @@ public: { return KeyIsDown[keyCode]; } - + MyEventReceiver() { for (u32 i=0; i(10,20)); /* - Lets draw the scene and also write the current frames per second and the + Lets draw the scene and also write the current frames per second and the name of the driver to the caption of the window. */ int lastFPS = -1; @@ -259,7 +259,7 @@ int main() In the end, delete the Irrlicht device. */ device->drop(); - + return 0; } diff --git a/examples/09.Meshviewer/Makefile b/examples/09.Meshviewer/Makefile index 64daf261..cffb4294 100644 --- a/examples/09.Meshviewer/Makefile +++ b/examples/09.Meshviewer/Makefile @@ -25,6 +25,7 @@ all: all_linux # target specific settings all_linux all_win32 static_win32: LDFLAGS += -L$(IrrlichtHome)/lib/$(SYSTEM) -lIrrlicht all_linux: LDFLAGS += -L/usr/X11R6/lib$(LIBSELECT) -lGL -lEGL -lGLESv1_CM -lGLESv2 -lXxf86vm -lXext -lX11 -lXcursor +#all_linux: LDFLAGS += `sdl-config --libs` all_linux clean_linux: SYSTEM=Linux all_win32 clean_win32 static_win32: SYSTEM=Win32-gcc all_win32 clean_win32 static_win32: SUF=.exe diff --git a/examples/26.OcclusionQuery/main.cpp b/examples/26.OcclusionQuery/main.cpp index 6aea63cb..d078a680 100644 --- a/examples/26.OcclusionQuery/main.cpp +++ b/examples/26.OcclusionQuery/main.cpp @@ -35,8 +35,6 @@ of the objects and camera. */ #ifdef _MSC_VER -// We'll also define this to stop MSVC complaining about sprintf(). -#define _CRT_SECURE_NO_WARNINGS #pragma comment(lib, "Irrlicht.lib") #endif @@ -150,6 +148,7 @@ int main() */ smgr->addCameraSceneNode(); int lastFPS = -1; + u32 lastPrimitives = 0; u32 timeNow = device->getTimer()->getTime(); bool nodeVisible=true; @@ -190,16 +189,20 @@ int main() driver->endScene(); int fps = driver->getFPS(); + u32 numPrimitives = driver->getPrimitiveCountDrawn(); - if (lastFPS != fps) + if (lastFPS != fps || lastPrimitives != numPrimitives) { core::stringw tmp(L"OcclusionQuery Example ["); tmp += driver->getName(); tmp += L"] fps: "; tmp += fps; + tmp += L" polygons: "; + tmp += numPrimitives; device->setWindowCaption(tmp.c_str()); lastFPS = fps; + lastPrimitives = numPrimitives; } } diff --git a/examples/27.PostProcessing/main.cpp b/examples/27.PostProcessing/main.cpp index 1c9df3f5..67739dd6 100644 --- a/examples/27.PostProcessing/main.cpp +++ b/examples/27.PostProcessing/main.cpp @@ -1,16 +1,16 @@ /** Example 027 Post Processing -This tutorial shows how to implement post processing for D3D9 and OpenGL with +This tutorial shows how to implement post processing for D3D9 and OpenGL with the engine. In order to do post processing, scene objects are firstly rendered to render target. With the help of screen quad, the render target texture is then drawn on the quad with shader-defined effects applied. -This tutorial shows how to create a screen quad. It also shows how to create a +This tutorial shows how to create a screen quad. It also shows how to create a render target texture and associate it with the quad. Effects are defined as -shaders which are applied during rendering the quad with the render target +shaders which are applied during rendering the quad with the render target texture attached to it. -A simple color inverse example is presented in this tutorial. The effect is +A simple color inverse example is presented in this tutorial. The effect is written in HLSL and GLSL. @author Boshen Guan @@ -29,46 +29,42 @@ using namespace irr; /* We write a class derived from IShaderConstantSetCallBack class and implement -OnSetConstants callback interface. In this callback, we will set constants +OnSetConstants callback interface. In this callback, we will set constants used by the shader. -In this example, our HLSL shader needs texture size as input in its vertex +In this example, our HLSL shader needs texture size as input in its vertex shader. Therefore, we set texture size in OnSetConstants callback using setVertexShaderConstant function. */ -IrrlichtDevice* device = 0; -video::ITexture* rt = 0; - class QuadShaderCallBack : public video::IShaderConstantSetCallBack { public: QuadShaderCallBack() : FirstUpdate(true), TextureSizeID(-1), TextureSamplerID(-1) { } - virtual void OnSetConstants(video::IMaterialRendererServices* services, - s32 userData) - { - core::dimension2d size = rt->getSize(); - - // get texture size array - f32 textureSize[] = - { - (f32)size.Width, (f32)size.Height - }; - + virtual void OnSetConstants(video::IMaterialRendererServices* services, + s32 userData) + { if ( FirstUpdate ) { + FirstUpdate = false; TextureSizeID = services->getVertexShaderConstantID("TextureSize"); TextureSamplerID = services->getPixelShaderConstantID("TextureSampler"); } - // set texture size to vertex shader - services->setVertexShaderConstant(TextureSizeID, reinterpret_cast(textureSize), 2); - - // set texture for an OpenGL driver - s32 textureLayer = 0; - services->setPixelShaderConstant(TextureSamplerID, &textureLayer, 1); - } + // get texture size array (for our simple example HLSL just needs that to calculate pixel centers) + core::dimension2d size = services->getVideoDriver()->getCurrentRenderTargetSize(); + f32 textureSize[2]; + textureSize[0] = (f32)size.Width; + textureSize[1] = (f32)size.Height; + + // set texture size to vertex shader + services->setVertexShaderConstant(TextureSizeID, textureSize, 2); + + // set texture for an OpenGL driver + s32 textureLayer = 0; + services->setPixelShaderConstant(TextureSamplerID, &textureLayer, 1); + } private: bool FirstUpdate; @@ -80,102 +76,91 @@ class ScreenQuad : public IReferenceCounted { public: - ScreenQuad(video::IVideoDriver* driver) - : Driver(driver) - { - // --------------------------------> u - // |[1](-1, 1)----------[2](1, 1) - // | | ( 0, 0) / | (1, 0) - // | | / | - // | | / | - // | | / | - // | | / | - // | | / | - // | | / | - // | | / | - // | | / | - // |[0](-1, -1)---------[3](1, -1) - // | ( 0, 1) (1, 1) - // V - // v + ScreenQuad(video::IVideoDriver* driver) + : Driver(driver) + { + // --------------------------------> u + // |[1](-1, 1)----------[2](1, 1) + // | | ( 0, 0) / | (1, 0) + // | | / | + // | | / | + // | | / | + // | | / | + // | | / | + // | | / | + // | | / | + // | | / | + // |[0](-1, -1)---------[3](1, -1) + // | ( 0, 1) (1, 1) + // V + // v - /* - A screen quad is composed of two adjacent triangles with 4 vertices. - Vertex [0], [1] and [2] create the first triangle and Vertex [0], - [2] and [3] create the second one. To map texture on the quad, UV - coordinates are assigned to the vertices. The origin of UV coordinate - locates on the top-left corner. And the value of UVs range from 0 to 1. - */ + /* + A screen quad is composed of two adjacent triangles with 4 vertices. + Vertex [0], [1] and [2] create the first triangle and Vertex [0], + [2] and [3] create the second one. To map texture on the quad, UV + coordinates are assigned to the vertices. The origin of UV coordinate + locates on the top-left corner. And the value of UVs range from 0 to 1. + */ - // define vertices array + // define vertices array - Vertices[0] = irr::video::S3DVertex(-1.0f, -1.0f, 0.0f, 1, 1, 0, irr::video::SColor(0,255,255,255), 0.0f, 1.0f); - Vertices[1] = irr::video::S3DVertex(-1.0f, 1.0f, 0.0f, 1, 1, 0, irr::video::SColor(0,255,255,255), 0.0f, 0.0f); - Vertices[2] = irr::video::S3DVertex( 1.0f, 1.0f, 0.0f, 1, 1, 0, irr::video::SColor(0,255,255,255), 1.0f, 0.0f); - Vertices[3] = irr::video::S3DVertex( 1.0f, -1.0f, 0.0f, 1, 1, 0, irr::video::SColor(0,255,255,255), 1.0f, 1.0f); + Vertices[0] = irr::video::S3DVertex(-1.0f, -1.0f, 0.0f, 1, 1, 0, irr::video::SColor(0,255,255,255), 0.0f, 1.0f); + Vertices[1] = irr::video::S3DVertex(-1.0f, 1.0f, 0.0f, 1, 1, 0, irr::video::SColor(0,255,255,255), 0.0f, 0.0f); + Vertices[2] = irr::video::S3DVertex( 1.0f, 1.0f, 0.0f, 1, 1, 0, irr::video::SColor(0,255,255,255), 1.0f, 0.0f); + Vertices[3] = irr::video::S3DVertex( 1.0f, -1.0f, 0.0f, 1, 1, 0, irr::video::SColor(0,255,255,255), 1.0f, 1.0f); - // define indices for triangles + // define indices for triangles - Indices[0] = 0; - Indices[1] = 1; - Indices[2] = 2; - Indices[3] = 0; - Indices[4] = 2; - Indices[5] = 3; + Indices[0] = 0; + Indices[1] = 1; + Indices[2] = 2; + Indices[3] = 0; + Indices[4] = 2; + Indices[5] = 3; - // turn off lighting as default - Material.setFlag(video::EMF_LIGHTING, false); + // turn off lighting as default + Material.setFlag(video::EMF_LIGHTING, false); - // set texture warp settings to clamp to edge pixel - for (u32 i = 0; i < video::MATERIAL_MAX_TEXTURES; i++) - { - Material.TextureLayer[i].TextureWrapU = video::ETC_CLAMP_TO_EDGE; - Material.TextureLayer[i].TextureWrapV = video::ETC_CLAMP_TO_EDGE; - } - } + // set texture warp settings to clamp to edge pixel + for (u32 i = 0; i < video::MATERIAL_MAX_TEXTURES; i++) + { + Material.TextureLayer[i].TextureWrapU = video::ETC_CLAMP_TO_EDGE; + Material.TextureLayer[i].TextureWrapV = video::ETC_CLAMP_TO_EDGE; + } + } - virtual ~ScreenQuad() {} + virtual ~ScreenQuad() {} - //! render the screen quad - virtual void render() - { - // set the material of screen quad - Driver->setMaterial(Material); + //! render the screen quad + virtual void render() + { + // set the material of screen quad + Driver->setMaterial(Material); - // set matrices to fit the quad to full viewport - Driver->setTransform(video::ETS_WORLD, core::IdentityMatrix); - Driver->setTransform(video::ETS_VIEW, core::IdentityMatrix); - Driver->setTransform(video::ETS_PROJECTION, core::IdentityMatrix); + // set world matrix to fit the quad to full viewport + Driver->setTransform(video::ETS_WORLD, core::IdentityMatrix); + // view & projection not used in shader, but matter to burnings driver + Driver->setTransform(video::ETS_VIEW, core::IdentityMatrix); + Driver->setTransform(video::ETS_PROJECTION, core::IdentityMatrix); - // draw screen quad - Driver->drawVertexPrimitiveList(Vertices, 4, Indices, 2); - } + // draw screen quad + Driver->drawVertexPrimitiveList(Vertices, 4, Indices, 2); + } - //! sets a flag of material to a new value - virtual void setMaterialFlag(video::E_MATERIAL_FLAG flag, bool newvalue) - { - Material.setFlag(flag, newvalue); - } - - //! sets the texture of the specified layer in material to the new texture. - void setMaterialTexture(u32 textureLayer, video::ITexture* texture) - { - Material.setTexture(textureLayer, texture); - } - - //! sets the material type to a new material type. - virtual void setMaterialType(video::E_MATERIAL_TYPE newType) - { - Material.MaterialType = newType; - } + //! Access the material + virtual video::SMaterial& getMaterial() + { + return Material; + } private: - video::IVideoDriver *Driver; - video::S3DVertex Vertices[4]; - u16 Indices[6]; - video::SMaterial Material; + video::IVideoDriver *Driver; + video::S3DVertex Vertices[4]; + u16 Indices[6]; + video::SMaterial Material; }; /* @@ -184,233 +169,237 @@ according to the driver type. */ int main() { - // ask user for driver - video::E_DRIVER_TYPE driverType=driverChoiceConsole(); - if (driverType==video::EDT_COUNT) - return 1; + // ask user for driver + video::E_DRIVER_TYPE driverType=driverChoiceConsole(); + if (driverType==video::EDT_COUNT) + return 1; - // create device - device = createDevice(driverType, core::dimension2d(640, 480)); + // create device + IrrlichtDevice* device = createDevice(driverType, core::dimension2d(640, 480)); - if (device == 0) - return 1; // could not create selected driver. + if (device == 0) + return 1; // could not create selected driver. - video::IVideoDriver* driver = device->getVideoDriver(); - scene::ISceneManager* smgr = device->getSceneManager(); + video::IVideoDriver* driver = device->getVideoDriver(); + scene::ISceneManager* smgr = device->getSceneManager(); - /* - In this example, high level post processing shaders are loaded for both - Direct3D and OpenGL drivers. - File pp_d3d9.hlsl is for Direct3D 9, and pp_opengl.frag/pp_opengl.vert - are for OpenGL. - */ + /* + In this example, high level post processing shaders are loaded for both + Direct3D and OpenGL drivers. + File pp_d3d9.hlsl is for Direct3D 9, and pp_opengl.frag/pp_opengl.vert + are for OpenGL. + */ const io::path mediaPath = getExampleMediaPath(); - io::path vsFileName; // filename for the vertex shader - io::path psFileName; // filename for the pixel shader + io::path vsFileName; // filename for the vertex shader + io::path psFileName; // filename for the pixel shader - switch(driverType) - { - case video::EDT_DIRECT3D9: - psFileName = mediaPath + "pp_d3d9.hlsl"; - vsFileName = psFileName; // both shaders are in the same file - break; + switch(driverType) + { + case video::EDT_DIRECT3D9: + psFileName = mediaPath + "pp_d3d9.hlsl"; + vsFileName = psFileName; // both shaders are in the same file + break; - case video::EDT_OPENGL: - case video::EDT_BURNINGSVIDEO: - psFileName = mediaPath + "pp_opengl.frag"; - vsFileName = mediaPath + "pp_opengl.vert"; - break; - } + case video::EDT_OPENGL: + case video::EDT_BURNINGSVIDEO: + psFileName = mediaPath + "pp_opengl.frag"; + vsFileName = mediaPath + "pp_opengl.vert"; + break; + } - /* - Check for hardware capability of executing the corresponding shaders - on selected renderer. This is not necessary though. - */ + /* + Check for hardware capability of executing the corresponding shaders + on selected renderer. This is not necessary though. + */ - if (!driver->queryFeature(video::EVDF_PIXEL_SHADER_1_1) && - !driver->queryFeature(video::EVDF_ARB_FRAGMENT_PROGRAM_1)) - { - device->getLogger()->log("WARNING: Pixel shaders disabled "\ - "because of missing driver/hardware support."); - psFileName = ""; - } + if (!driver->queryFeature(video::EVDF_PIXEL_SHADER_1_1) && + !driver->queryFeature(video::EVDF_ARB_FRAGMENT_PROGRAM_1)) + { + device->getLogger()->log("WARNING: Pixel shaders disabled "\ + "because of missing driver/hardware support."); + psFileName = ""; + } - if (!driver->queryFeature(video::EVDF_VERTEX_SHADER_1_1) && - !driver->queryFeature(video::EVDF_ARB_VERTEX_PROGRAM_1)) - { - device->getLogger()->log("WARNING: Vertex shaders disabled "\ - "because of missing driver/hardware support."); - vsFileName = ""; - } + if (!driver->queryFeature(video::EVDF_VERTEX_SHADER_1_1) && + !driver->queryFeature(video::EVDF_ARB_VERTEX_PROGRAM_1)) + { + device->getLogger()->log("WARNING: Vertex shaders disabled "\ + "because of missing driver/hardware support."); + vsFileName = ""; + } - /* - An animated mesh is loaded to be displayed. As in most examples, - we'll take the fairy md2 model. - */ + /* + An animated mesh is loaded to be displayed. As in most examples, + we'll take the fairy md2 model. + */ - // load and display animated fairy mesh + // load and display animated fairy mesh - scene::IAnimatedMeshSceneNode* fairy = smgr->addAnimatedMeshSceneNode( - smgr->getMesh(mediaPath + "faerie.md2")); + scene::IAnimatedMeshSceneNode* fairy = smgr->addAnimatedMeshSceneNode( + smgr->getMesh(mediaPath + "faerie.md2")); - if (fairy) - { - fairy->setMaterialTexture(0, - driver->getTexture(mediaPath + "faerie2.bmp")); // set diffuse texture - fairy->setMaterialFlag(video::EMF_LIGHTING, false); // disable dynamic lighting - fairy->setPosition(core::vector3df(-10,0,-100)); - fairy->setMD2Animation ( scene::EMAT_STAND ); - } + if (fairy) + { + fairy->setMaterialTexture(0, + driver->getTexture(mediaPath + "faerie2.bmp")); // set diffuse texture + fairy->setMaterialFlag(video::EMF_LIGHTING, false); // disable dynamic lighting + fairy->setPosition(core::vector3df(-10,0,-100)); + fairy->setMD2Animation ( scene::EMAT_STAND ); + } - // add scene camera - smgr->addCameraSceneNode(0, core::vector3df(10,10,-80), - core::vector3df(-10,10,-100)); + // add scene camera + smgr->addCameraSceneNode(0, core::vector3df(10,10,-80), + core::vector3df(-10,10,-100)); - /* - We create a render target texture (RTT) with the same size as frame buffer. - Instead of rendering the scene directly to the frame buffer, we firstly - render it to this RTT. Post processing is then applied based on this RTT. - RTT size needs not to be the same with frame buffer though. However in this - example, we expect the result of rendering to RTT to be consistent with the - result of rendering directly to the frame buffer. Therefore, the size of - RTT keeps the same with frame buffer. - */ + /* + We create a render target texture (RTT) with the same size as frame buffer. + Instead of rendering the scene directly to the frame buffer, we firstly + render it to this RTT. Post processing is then applied based on this RTT. + RTT size needs not to be the same with frame buffer though. However in this + example, we expect the result of rendering to RTT to be consistent with the + result of rendering directly to the frame buffer. Therefore, the size of + RTT keeps the same with frame buffer. + */ - // create render target + // create render target + video::ITexture* rt = 0; + if (driver->queryFeature(video::EVDF_RENDER_TO_TARGET)) + { + rt = driver->addRenderTargetTexture(core::dimension2d(640, 480), "RTT1"); + } + else + { + device->getLogger()->log("Your hardware or this renderer is not able to use the "\ + "render to texture feature. RTT Disabled."); + } - if (driver->queryFeature(video::EVDF_RENDER_TO_TARGET)) - { - rt = driver->addRenderTargetTexture(core::dimension2d(640, 480), "RTT1"); - } - else - { - device->getLogger()->log("Your hardware or this renderer is not able to use the "\ - "render to texture feature. RTT Disabled."); - } + /* + Post processing is achieved by rendering a screen quad with this RTT (with + previously rendered result) as a texture on the quad. A screen quad is + geometry of flat plane composed of two adjacent triangles covering the + entire area of viewport. In this pass of rendering, RTT works just like + a normal texture and is drawn on the quad during rendering. We can then + take control of this rendering process by applying various shader-defined + materials to the quad. In other words, we can achieve different effect by + writing different shaders. + This process is called post processing because it normally does not rely + on scene geometry. The inputs of this process are just textures, or in + other words, just images. With the help of screen quad, we can draw these + images on the screen with different effects. For example, we can adjust + contrast, make grayscale, add noise, do more fancy effect such as blur, + bloom, ghost, or just like in this example, we invert the color to produce + negative image. + Note that post processing is not limited to use only one texture. It can + take multiple textures as shader inputs to provide desired result. In + addition, post processing can also be chained to produce compound result. + */ - /* - Post processing is achieved by rendering a screen quad with this RTT (with - previously rendered result) as a texture on the quad. A screen quad is - geometry of flat plane composed of two adjacent triangles covering the - entire area of viewport. In this pass of rendering, RTT works just like - a normal texture and is drawn on the quad during rendering. We can then - take control of this rendering process by applying various shader-defined - materials to the quad. In other words, we can achieve different effect by - writing different shaders. - This process is called post processing because it normally does not rely - on scene geometry. The inputs of this process are just textures, or in - other words, just images. With the help of screen quad, we can draw these - images on the screen with different effects. For example, we can adjust - contrast, make grayscale, add noise, do more fancy effect such as blur, - bloom, ghost, or just like in this example, we invert the color to produce - negative image. - Note that post processing is not limited to use only one texture. It can - take multiple textures as shader inputs to provide desired result. In - addition, post processing can also be chained to produce compound result. - */ + // we create a screen quad + ScreenQuad *screenQuad = new ScreenQuad(driver); + video::SMaterial& screenQuadMaterial = screenQuad->getMaterial(); - // we create a screen quad - ScreenQuad *screenQuad = new ScreenQuad(driver); + // turn off mip maps and bilinear filter since we do not want interpolated results + screenQuadMaterial.setFlag(video::EMF_USE_MIP_MAPS, false); + screenQuadMaterial.setFlag(video::EMF_BILINEAR_FILTER, false); - // turn off mip maps and bilinear filter since we do not want interpolated result - screenQuad->setMaterialFlag(video::EMF_USE_MIP_MAPS, false); - screenQuad->setMaterialFlag(video::EMF_BILINEAR_FILTER, false); + // turn off depth buffer, because our full screen 2D overlay doesn't process depth + screenQuadMaterial.setFlag(video::EMF_ZBUFFER, false); - // set quad texture to RTT we just create - screenQuad->setMaterialTexture(0, rt); + // set quad texture to RTT we just create + screenQuadMaterial.setTexture(0, rt); - /* - Let's create material for the quad. Like in other example, we create material - using IGPUProgrammingServices and call addShaderMaterialFromFiles, which - returns a material type identifier. - */ + /* + Let's create material for the quad. Like in other example, we create material + using IGPUProgrammingServices and call addShaderMaterialFromFiles, which + returns a material type identifier. + */ - // create materials + // create materials - video::IGPUProgrammingServices* gpu = driver->getGPUProgrammingServices(); - s32 ppMaterialType = 0; + video::IGPUProgrammingServices* gpu = driver->getGPUProgrammingServices(); + s32 ppMaterialType = 0; - if (gpu) - { - // We write a QuadShaderCallBack class that implements OnSetConstants - // callback of IShaderConstantSetCallBack class at the beginning of - // this tutorial. We set shader constants in this callback. - - // create an instance of callback class + if (gpu) + { + // We write a QuadShaderCallBack class that implements OnSetConstants + // callback of IShaderConstantSetCallBack class at the beginning of + // this tutorial. We set shader constants in this callback. - QuadShaderCallBack* mc = new QuadShaderCallBack(); + // create an instance of callback class - // create material from post processing shaders + QuadShaderCallBack* mc = new QuadShaderCallBack(); - ppMaterialType = gpu->addHighLevelShaderMaterialFromFiles( - vsFileName, "vertexMain", video::EVST_VS_1_1, - psFileName, "pixelMain", video::EPST_PS_1_1, mc); + // create material from post processing shaders - mc->drop(); - } + ppMaterialType = gpu->addHighLevelShaderMaterialFromFiles( + vsFileName, "vertexMain", video::EVST_VS_1_1, + psFileName, "pixelMain", video::EPST_PS_1_1, mc); - // set post processing material type to the quad - screenQuad->setMaterialType((video::E_MATERIAL_TYPE)ppMaterialType); + mc->drop(); + } - /* - Now draw everything. That's all. - */ + // set post processing material type to the quad + screenQuadMaterial.MaterialType = (video::E_MATERIAL_TYPE)ppMaterialType; - int lastFPS = -1; + /* + Now draw everything. That's all. + */ - while(device->run()) - { - if (device->isWindowActive()) - { - driver->beginScene(true, true, video::SColor(255,0,0,0)); + int lastFPS = -1; - if (rt) - { - // draw scene into render target + while(device->run()) + { + if (device->isWindowActive()) + { + driver->beginScene(true, true, video::SColor(255,0,0,0)); - // set render target to RTT - driver->setRenderTarget(rt, true, true, video::SColor(255,0,0,0)); + if (rt) + { + // draw scene into render target - // draw scene to RTT just like normal rendering - smgr->drawAll(); + // set render target to RTT + driver->setRenderTarget(rt, true, true, video::SColor(255,0,0,0)); - // after rendering to RTT, we change render target back - driver->setRenderTarget(0, true, true, video::SColor(255,0,0,0)); + // draw scene to RTT just like normal rendering + smgr->drawAll(); - // render screen quad to apply post processing - screenQuad->render(); - } - else - { - // draw scene normally - smgr->drawAll(); - } + // after rendering to RTT, we change render target back + driver->setRenderTarget(0, true, true, video::SColor(255,0,0,0)); - driver->endScene(); + // render screen quad to apply post processing + screenQuad->render(); + } + else + { + // draw scene normally + smgr->drawAll(); + } - int fps = driver->getFPS(); + driver->endScene(); - if (lastFPS != fps) - { - core::stringw str = L"Irrlicht Engine - Post processing example ["; - str += driver->getName(); - str += "] FPS:"; - str += fps; + int fps = driver->getFPS(); - device->setWindowCaption(str.c_str()); - lastFPS = fps; - } - } - } + if (lastFPS != fps) + { + core::stringw str = L"Irrlicht Engine - Post processing example ["; + str += driver->getName(); + str += "] FPS:"; + str += fps; - // do not forget to manually drop the screen quad + device->setWindowCaption(str.c_str()); + lastFPS = fps; + } + } + } - screenQuad->drop(); + // do not forget to manually drop the screen quad - device->drop(); + screenQuad->drop(); - return 0; + device->drop(); + + return 0; } /* diff --git a/examples/28.CubeMapping/main.cpp b/examples/28.CubeMapping/main.cpp index b831d318..cbbdbb69 100644 --- a/examples/28.CubeMapping/main.cpp +++ b/examples/28.CubeMapping/main.cpp @@ -316,7 +316,7 @@ private: Irrlicht internally uses textures with left-top origin and then corrects the texture-matrices in the fixed-function pipeline. For shader materials it's left to the users to handle those UV-flips for the texture-matrix. Render target textures (RTT's) in OpenGL are rendered with left-bottom origin and Irrlicht can't change that, so all RTT textures - in memory are upside-down (unlike all other Irrlicht textures). + in memory are upside-down (compared to other Irrlicht textures). In the fixed function pipeline Irrlicht handles this by flipping the RTT's texture matrix once more and for shaders it's again left to the users to handle it. Cubemap textures are different from other textures in OpenGL. Each cube side has left-top as the origin. So not flipping Irrlicht textures for those would be fine. @@ -325,7 +325,7 @@ private: So... the following 2 defines are two different workarounds I found. Both are ugly, which one is better in reality depends probably on the scene. Only use one of those: - CUBEMAP_UPSIDE_DOWN_GL_PROJECTION is relatively fast as it just changes the project matrix. The problem is that changing the projection matrix + CUBEMAP_UPSIDE_DOWN_GL_PROJECTION is relatively fast as it just changes the projection matrix. The problem is that changing the projection matrix means changing front/backside culling. So every node rendered has to flip the material flags for those. CUBEMAP_USPIDE_DOWN_RTT will change the texture memory itself and flip the image upside-down. @@ -591,7 +591,7 @@ int main() } /* Add some background which will show up in the environment maps. - For first one we use the same textures as used in the spheres. + For the first background we use the same textures as used in the spheres. Note the difference between a skybox and a cubemap is that the skybox really uses 6 different textures. While the cubemap uses a single texture created from 6 images. */ eventReceiver.BackgroundSkybox = smgr->addSkyBoxSceneNode( @@ -639,7 +639,7 @@ int main() #endif /* - Add some moving node to show the difference between static/dynamic environment maps + Add a moving node to show the difference between static/dynamic environment maps */ scene::IMeshSceneNode * movingNode = smgr->addCubeSceneNode(30.f); movingNode->getMaterial(0).Lighting = false; @@ -692,7 +692,7 @@ int main() driver->beginScene(true, true, video::SColor(255, 127, 127, 255)); /* Check if we want to update the environment maps. - Usually not something you'll do every frame, but either once at the star + Usually not something you'll do every frame, but either once at the start or maybe updating an environment map once in a while. */ int updateCubemaps = eventReceiver.checkCubemapUpdate(); @@ -704,7 +704,7 @@ int main() { /* Flipping projection matrix flips front/backface culling. - We only have a skybox so in this case this still would be fast, with more objects it's getting more ugly. + We only have a skybox so in this case it's fast, with more objects it's getting more ugly. */ smgr->getSceneNodesFromType(scene::ESNT_ANY, allNodes); flipCullingFlags(allNodes); diff --git a/include/CMeshBuffer.h b/include/CMeshBuffer.h index bc66df7c..6f1ff368 100644 --- a/include/CMeshBuffer.h +++ b/include/CMeshBuffer.h @@ -176,6 +176,17 @@ namespace scene return Vertices[i].TCoords; } + //! returns color of vertex i + virtual video::SColor& getColor(u32 i) IRR_OVERRIDE + { + return Vertices[i].Color; + } + + //! returns color of vertex i + virtual const video::SColor& getColor(u32 i) const IRR_OVERRIDE + { + return Vertices[i].Color; + } //! Append the vertices and indices to the current buffer /** Only works for compatible types, i.e. either the same type diff --git a/include/ICameraSceneNode.h b/include/ICameraSceneNode.h index feb3cefc..101c756f 100644 --- a/include/ICameraSceneNode.h +++ b/include/ICameraSceneNode.h @@ -121,19 +121,23 @@ namespace scene virtual f32 getFOV() const =0; //! Sets the value of the near clipping plane. (default: 1.0f) - /** \param zn: New z near value. */ + /** Also changes projection matrix and resets IsOrthogonal flag. + \param zn: New z near value. */ virtual void setNearValue(f32 zn) =0; //! Sets the value of the far clipping plane (default: 2000.0f) - /** \param zf: New z far value. */ + /** Also changes projection matrix and resets IsOrthogonal flag. + \param zf: New z far value. */ virtual void setFarValue(f32 zf) =0; //! Sets the aspect ratio (default: 4.0f / 3.0f) - /** \param aspect: New aspect ratio. */ + /** Also changes projection matrix and resets IsOrthogonal flag. + \param aspect: New aspect ratio. */ virtual void setAspectRatio(f32 aspect) =0; //! Sets the field of view (Default: PI / 2.5f) - /** \param fovy: New field of view in radians. */ + /** Also changes projection matrix and resets IsOrthogonal flag. + \param fovy: New field of view in radians. */ virtual void setFOV(f32 fovy) =0; //! Get the view frustum. @@ -165,7 +169,10 @@ namespace scene @see getTargetAndRotationBinding() */ virtual void bindTargetAndRotation(bool bound) =0; - //! Updates the matrices without uploading them to the driver + //! Updates the view matrix and frustum without uploading the matrix to the driver. + /** You need this when you want an up-to-date camera view matrix & frustum before the render() call. + Usually you should call updateAbsolutePosition() before calling this. + Despite it's function name, the projection matrix is not touched. */ virtual void updateMatrices() = 0; //! Queries if the camera scene node's rotation and its target position are bound together. diff --git a/include/IDynamicMeshBuffer.h b/include/IDynamicMeshBuffer.h index 3aed1265..8317f175 100644 --- a/include/IDynamicMeshBuffer.h +++ b/include/IDynamicMeshBuffer.h @@ -166,6 +166,18 @@ namespace scene { return getVertexBuffer()[i].Normal; } + + //! returns color of vertex i + virtual video::SColor& getColor(u32 i) IRR_OVERRIDE + { + return getVertexBuffer()[i].Color; + } + + //! returns color of vertex i + virtual const video::SColor& getColor(u32 i) const IRR_OVERRIDE + { + return getVertexBuffer()[i].Color; + } }; diff --git a/include/ILightManager.h b/include/ILightManager.h index ad8988c8..b156e708 100644 --- a/include/ILightManager.h +++ b/include/ILightManager.h @@ -22,7 +22,10 @@ namespace scene before or after each scene node is rendered. It is assumed that the ILightManager implementation will store any data that it wishes to retain, i.e. the ISceneManager to which it is assigned, the lightList, - the current render pass, and the current scene node. */ + the current render pass, and the current scene node. + + It can also be useful for shaders as it allows finding out the currently rendered SceneNode. + */ class ILightManager : public IReferenceCounted { public: @@ -35,27 +38,27 @@ namespace scene the light manager may modify. This reference will remain valid until OnPostRender(). */ - virtual void OnPreRender(core::array & lightList) = 0; + virtual void OnPreRender(core::array & lightList) {}; //! Called after the last scene node is rendered. /** After this call returns, the lightList passed to OnPreRender() becomes invalid. */ - virtual void OnPostRender(void) = 0; + virtual void OnPostRender(void) {}; //! Called before a render pass begins /** \param renderPass: the render pass that's about to begin */ - virtual void OnRenderPassPreRender(E_SCENE_NODE_RENDER_PASS renderPass) = 0; + virtual void OnRenderPassPreRender(E_SCENE_NODE_RENDER_PASS renderPass) {}; //! Called after the render pass specified in OnRenderPassPreRender() ends /** \param[in] renderPass: the render pass that has finished */ - virtual void OnRenderPassPostRender(E_SCENE_NODE_RENDER_PASS renderPass) = 0; + virtual void OnRenderPassPostRender(E_SCENE_NODE_RENDER_PASS renderPass) {}; //! Called before the given scene node is rendered /** \param[in] node: the scene node that's about to be rendered */ - virtual void OnNodePreRender(ISceneNode* node) = 0; + virtual void OnNodePreRender(ISceneNode* node) {}; //! Called after the the node specified in OnNodePreRender() has been rendered /** \param[in] node: the scene node that has just been rendered */ - virtual void OnNodePostRender(ISceneNode* node) = 0; + virtual void OnNodePostRender(ISceneNode* node) {}; }; } // end namespace scene } // end namespace irr diff --git a/include/IMeshBuffer.h b/include/IMeshBuffer.h index 77ce995d..253d2712 100644 --- a/include/IMeshBuffer.h +++ b/include/IMeshBuffer.h @@ -119,6 +119,12 @@ namespace scene //! returns texture coord of vertex i virtual core::vector2df& getTCoords(u32 i) = 0; + //! returns color of vertex i + virtual video::SColor& getColor(u32 i) = 0; + + //! returns color of vertex i + virtual const video::SColor& getColor(u32 i) const = 0; + //! Append the vertices and indices to the current buffer /** Only works for compatible vertex types and not implemented for most buffers for now. diff --git a/include/IMeshManipulator.h b/include/IMeshManipulator.h index 1b307301..b2a0b46a 100644 --- a/include/IMeshManipulator.h +++ b/include/IMeshManipulator.h @@ -103,7 +103,9 @@ namespace scene bool angleWeighted=false) const=0; //! Scales the actual mesh, not a scene node. - /** \param mesh Mesh on which the operation is performed. + /** Note: When your scale are not uniform then + prefer the transform function to have correct normals. + \param mesh Mesh on which the operation is performed. \param factor Scale factor for each axis. */ void scale(IMesh* mesh, const core::vector3df& factor) const { @@ -111,7 +113,9 @@ namespace scene } //! Scales the actual meshbuffer, not a scene node. - /** \param buffer Meshbuffer on which the operation is performed. + /** Note: When your scale are not uniform then + prefer the transform function to have correct normals. + \param buffer Meshbuffer on which the operation is performed. \param factor Scale factor for each axis. */ void scale(IMeshBuffer* buffer, const core::vector3df& factor) const { @@ -146,9 +150,12 @@ namespace scene /** \param mesh Mesh on which the operation is performed. \param m transformation matrix. \param normalsUpdate When 0 - don't update normals. - When 1 - update normals with inverse transposed of the transformation matrix + When 1 - update normals with inner 3x3 matrix of the inverse transposed of the transformation matrix + should be set when the matrix has rotation or non-uniform scaling + \param normalizeNormals When true it normalizes all normals again. + Recommended to set this when normalsUpdate is 1 and there is any scaling */ - void transform(IMesh* mesh, const core::matrix4& m, u32 normalsUpdate = 0) const + void transform(IMesh* mesh, const core::matrix4& m, u32 normalsUpdate = 0, bool normalizeNormals=false) const { apply(SVertexPositionTransformManipulator(m), mesh, true); @@ -158,18 +165,25 @@ namespace scene if ( m.getInverse(invT) ) { invT = invT.getTransposed(); - apply(SVertexNormalTransformManipulator(invT), mesh, false); + apply(SVertexNormalRotateScaleManipulator(invT), mesh, false); } } + if ( normalizeNormals ) + { + apply(SVertexNormalizeNormalManipulator(), mesh, false); + } } //! Applies a transformation to a meshbuffer /** \param buffer Meshbuffer on which the operation is performed. \param m transformation matrix. \param normalsUpdate When 0 - don't update normals. - When 1 - update normals with inverse transposed of the transformation matrix + When 1 - update normals with inner 3x3 matrix of the inverse transposed of the transformation matrix + should be set when the matrix has rotation or non-uniform scaling + \param normalizeNormals When true it normalizes all normals again. + Recommended to set this when normalsUpdate is 1 and there is any scaling */ - void transform(IMeshBuffer* buffer, const core::matrix4& m, u32 normalsUpdate = 0) const + void transform(IMeshBuffer* buffer, const core::matrix4& m, u32 normalsUpdate = 0, bool normalizeNormals=false) const { apply(SVertexPositionTransformManipulator(m), buffer, true); @@ -179,9 +193,13 @@ namespace scene if ( m.getInverse(invT) ) { invT = invT.getTransposed(); - apply(SVertexNormalTransformManipulator(invT), buffer, false); + apply(SVertexNormalRotateScaleManipulator(invT), buffer, false); } } + if ( normalizeNormals ) + { + apply(SVertexNormalizeNormalManipulator(), buffer, false); + } } //! Applies a transformation to a mesh @@ -239,6 +257,7 @@ namespace scene /** This is useful if you want to draw tangent space normal mapped geometry because it calculates the tangent and binormal data which is needed there. + Note: Only 16-bit meshbuffers supported so far \param mesh Input mesh \param recalculateNormals The normals are recalculated if set, otherwise the original ones are kept. Note that keeping the @@ -257,7 +276,8 @@ namespace scene bool angleWeighted=false, bool recalculateTangents=true) const=0; //! Creates a copy of the mesh, which will only consist of S3DVertex2TCoord vertices. - /** \param mesh Input mesh + /** Note: Only 16-bit meshbuffers supported so far + \param mesh Input mesh \return Mesh consisting only of S3DVertex2TCoord vertices. If you no longer need the cloned mesh, you should call IMesh::drop(). See IReferenceCounted::drop() for more @@ -265,7 +285,8 @@ namespace scene virtual IMesh* createMeshWith2TCoords(IMesh* mesh) const = 0; //! Creates a copy of the mesh, which will only consist of S3DVertex vertices. - /** \param mesh Input mesh + /** Note: Only 16-bit meshbuffers supported so far + \param mesh Input mesh \return Mesh consisting only of S3DVertex vertices. If you no longer need the cloned mesh, you should call IMesh::drop(). See IReferenceCounted::drop() for more @@ -273,15 +294,17 @@ namespace scene virtual IMesh* createMeshWith1TCoords(IMesh* mesh) const = 0; //! Creates a copy of a mesh with all vertices unwelded - /** \param mesh Input mesh + /** Note: Only 16-bit meshbuffers supported so far + \param mesh Input mesh \return Mesh consisting only of unique faces. All vertices which were previously shared are now duplicated. If you no longer need the cloned mesh, you should call IMesh::drop(). See IReferenceCounted::drop() for more information. */ virtual IMesh* createMeshUniquePrimitives(IMesh* mesh) const = 0; - //! Creates a copy of a mesh with vertices welded - /** \param mesh Input mesh + //! Creates a copy of a mesh with vertices welded + /** Note: Only 16-bit meshbuffers supported so far, 32-bit buffer are cloned + \param mesh Input mesh \param tolerance The threshold for vertex comparisons. \return Mesh without redundant vertices. If you no longer need the cloned mesh, you should call IMesh::drop(). See diff --git a/include/SSharedMeshBuffer.h b/include/SSharedMeshBuffer.h index aac563d8..f894625b 100644 --- a/include/SSharedMeshBuffer.h +++ b/include/SSharedMeshBuffer.h @@ -171,6 +171,21 @@ namespace scene return (*Vertices)[Indices[i]].TCoords; } + //! returns color of vertex i + virtual video::SColor& getColor(u32 i) IRR_OVERRIDE + { + IRR_DEBUG_BREAK_IF(!Vertices); + return (*Vertices)[Indices[i]].Color; + } + + //! returns color of vertex i + virtual const video::SColor& getColor(u32 i) const IRR_OVERRIDE + { + IRR_DEBUG_BREAK_IF(!Vertices); + return (*Vertices)[Indices[i]].Color; + } + + //! append the vertices and indices to the current buffer virtual void append(const void* const vertices, u32 numVertices, const u16* const indices, u32 numIndices) IRR_OVERRIDE { diff --git a/include/SSkinMeshBuffer.h b/include/SSkinMeshBuffer.h index 52d480ce..b2b812b4 100644 --- a/include/SSkinMeshBuffer.h +++ b/include/SSkinMeshBuffer.h @@ -326,6 +326,34 @@ struct SSkinMeshBuffer : public IMeshBuffer } } + //! returns color of vertex i + virtual video::SColor& getColor(u32 i) IRR_OVERRIDE + { + switch (VertexType) + { + case video::EVT_2TCOORDS: + return Vertices_2TCoords[i].Color; + case video::EVT_TANGENTS: + return Vertices_Tangents[i].Color; + default: + return Vertices_Standard[i].Color; + } + } + + //! returns color of vertex i + virtual const video::SColor& getColor(u32 i) const IRR_OVERRIDE + { + switch (VertexType) + { + case video::EVT_2TCOORDS: + return Vertices_2TCoords[i].Color; + case video::EVT_TANGENTS: + return Vertices_Tangents[i].Color; + default: + return Vertices_Standard[i].Color; + } + } + //! append the vertices and indices to the current buffer virtual void append(const void* const vertices, u32 numVertices, const u16* const indices, u32 numIndices) IRR_OVERRIDE {} diff --git a/include/SVertexManipulator.h b/include/SVertexManipulator.h index 1c32d4c9..0fcc31db 100644 --- a/include/SVertexManipulator.h +++ b/include/SVertexManipulator.h @@ -277,6 +277,32 @@ namespace scene core::matrix4 Transformation; }; + //! Vertex manipulator which transforms the normal of the vertex with the rotate/scale part of the given matrix (inner 3x3) + class SVertexNormalRotateScaleManipulator : public IVertexManipulator + { + public: + SVertexNormalRotateScaleManipulator(const core::matrix4& m) : Transformation(m) {} + template + void operator()(VType& vertex) const + { + Transformation.rotateVect(vertex.Normal); + } + private: + core::matrix4 Transformation; + }; + + //! Vertex manipulator which normalizes the normal of the vertex + class SVertexNormalizeNormalManipulator : public IVertexManipulator + { + public: + SVertexNormalizeNormalManipulator() {} + template + void operator()(VType& vertex) const + { + vertex.Normal.normalize(); + } + }; + //! Vertex manipulator which scales the TCoords of the vertex class SVertexTCoordsScaleManipulator : public IVertexManipulator { diff --git a/include/irrString.h b/include/irrString.h index 021086f6..bc7a6a23 100644 --- a/include/irrString.h +++ b/include/irrString.h @@ -947,13 +947,13 @@ public: \param make_lower copy only lower case */ string subString(u32 begin, s32 length, bool make_lower = false ) const { + // clamp length to maximal value + if ((length+begin) > size()) + length = size()-begin; // if start after string // or no proper substring length if ((length <= 0) || (begin>=size())) return string(""); - // clamp length to maximal value - if ((length+begin) > size()) - length = size()-begin; string o; o.reserve(length+1); diff --git a/include/matrix4.h b/include/matrix4.h index 26a3306b..b561fdcd 100644 --- a/include/matrix4.h +++ b/include/matrix4.h @@ -221,10 +221,10 @@ namespace core //! Translate a vector by the inverse of the translation part of this matrix. void inverseTranslateVect( vector3df& vect ) const; - //! Rotate a vector by the inverse of the rotation part of this matrix. + //! Tranform (rotate/scale) a vector by the inverse of the rotation part this matrix void inverseRotateVect( vector3df& vect ) const; - //! Rotate a vector by the rotation part of this matrix. + //! Transform (rotate/scale) a vector by the rotation part of this matrix. void rotateVect( vector3df& vect ) const; //! An alternate transform vector method, writing into a second vector diff --git a/source/Irrlicht/CCameraSceneNode.cpp b/source/Irrlicht/CCameraSceneNode.cpp index 34c66895..3c97ee55 100644 --- a/source/Irrlicht/CCameraSceneNode.cpp +++ b/source/Irrlicht/CCameraSceneNode.cpp @@ -28,16 +28,16 @@ CCameraSceneNode::CCameraSceneNode(ISceneNode* parent, ISceneManager* mgr, s32 i // set default projection Fovy = core::PI / 2.5f; // Field of view, in radians. + Aspect = 4.0f / 3.0f; // Aspect ratio. const video::IVideoDriver* const d = mgr?mgr->getVideoDriver():0; if (d) { - Aspect = (f32)d->getCurrentRenderTargetSize().Width / - (f32)d->getCurrentRenderTargetSize().Height; + if ( d->getCurrentRenderTargetSize().Height ) + Aspect = (f32)d->getCurrentRenderTargetSize().Width / + (f32)d->getCurrentRenderTargetSize().Height; HasD3DStyleProjectionMatrix = d->getDriverType() != video::EDT_OPENGL; } - else - Aspect = 4.0f / 3.0f; // Aspect ratio. ViewArea.setFarNearDistance(ZFar - ZNear); recalculateProjectionMatrix(); @@ -252,6 +252,7 @@ void CCameraSceneNode::OnRegisterSceneNode() //! render void CCameraSceneNode::render() { + updateAbsolutePosition(); // depending on that call in onAnimate is risky (might not be in SceneManager or it or it's parent might be invisible and still should render) updateMatrices(); video::IVideoDriver* driver = SceneManager->getVideoDriver(); diff --git a/source/Irrlicht/CColladaMeshWriter.cpp b/source/Irrlicht/CColladaMeshWriter.cpp index c9805d5a..91a0a235 100644 --- a/source/Irrlicht/CColladaMeshWriter.cpp +++ b/source/Irrlicht/CColladaMeshWriter.cpp @@ -1827,7 +1827,7 @@ void CColladaMeshWriter::writeMeshGeometry(const irr::core::stringc& meshname, s if ( buffer->getPrimitiveType() != EPT_TRIANGLES ) { - os::Printer::log("Collada writer does not support non-triangle meshbuffers. Mesh: ", meshname.c_str(), ELL_WARNING); + os::Printer::log("Collada writer does not support non-triangle meshbuffers. Mesh", meshname.c_str(), ELL_WARNING); continue; } @@ -1865,12 +1865,16 @@ void CColladaMeshWriter::writeMeshGeometry(const irr::core::stringc& meshname, s Writer->writeElement("p", false); + const video::E_INDEX_TYPE iType = buffer->getIndexType(); + const u16* idx16 = buffer->getIndices(); + const u32* idx32 = (u32*)buffer->getIndices(); + core::stringc strP; strP.reserve(100); for (u32 p=0; pgetIndices()[(p*3) + 2]; + u32 irrIdx = iType == video::EIT_16BIT ? idx16[p*3 + 2] : idx32[p*3 + 2]; strP = ""; strP += irrIdx + posIdx; strP += " "; @@ -1884,7 +1888,7 @@ void CColladaMeshWriter::writeMeshGeometry(const irr::core::stringc& meshname, s strP += " "; } - irrIdx = buffer->getIndices()[(p*3) + 1]; + irrIdx = iType == video::EIT_16BIT ? idx16[p*3 + 1] : idx32[p*3 + 1]; strP += irrIdx + posIdx; strP += " "; strP += irrIdx + tCoordIdx; @@ -1897,7 +1901,7 @@ void CColladaMeshWriter::writeMeshGeometry(const irr::core::stringc& meshname, s strP += " "; } - irrIdx = buffer->getIndices()[(p*3) + 0]; + irrIdx = iType == video::EIT_16BIT ? idx16[p*3] : idx32[p*3]; strP += irrIdx + posIdx; strP += " "; strP += irrIdx + tCoordIdx; diff --git a/source/Irrlicht/CD3D9Driver.cpp b/source/Irrlicht/CD3D9Driver.cpp index 8a98dceb..4bbee26d 100644 --- a/source/Irrlicht/CD3D9Driver.cpp +++ b/source/Irrlicht/CD3D9Driver.cpp @@ -3001,7 +3001,7 @@ bool CD3D9Driver::reset() } else { - os::Printer::log("Resetting failed due to unknown reason.", core::stringc((int)hr).c_str(), ELL_WARNING); + os::Printer::log("Resetting failed due to unknown reason", core::stringc((int)hr).c_str(), ELL_WARNING); } return false; } diff --git a/source/Irrlicht/CGUIContextMenu.cpp b/source/Irrlicht/CGUIContextMenu.cpp index d38ceeda..fb866dc7 100644 --- a/source/Irrlicht/CGUIContextMenu.cpp +++ b/source/Irrlicht/CGUIContextMenu.cpp @@ -339,7 +339,7 @@ bool CGUIContextMenu::OnEvent(const SEvent& event) case EMIE_MOUSE_MOVED: if (Environment->hasFocus(this)) highlight(core::position2d(event.MouseInput.X, event.MouseInput.Y), true); - return true; + break; default: break; } @@ -423,7 +423,7 @@ u32 CGUIContextMenu::sendClick(const core::position2d& p) } -//! returns true, if an element was highligted +//! returns true, if an element was highlighted bool CGUIContextMenu::highlight(const core::position2d& p, bool canOpenSubMenu) { if (!isEnabled()) diff --git a/source/Irrlicht/CGUIEnvironment.cpp b/source/Irrlicht/CGUIEnvironment.cpp index 5d2a5f02..2ab30e7b 100644 --- a/source/Irrlicht/CGUIEnvironment.cpp +++ b/source/Irrlicht/CGUIEnvironment.cpp @@ -810,7 +810,7 @@ bool CGUIEnvironment::loadGUI(const io::path& filename, IGUIElement* parent) io::IReadFile* read = FileSystem->createAndOpenFile(filename); if (!read) { - os::Printer::log("Unable to open gui file", filename, ELL_ERROR); + os::Printer::log("Unable to open GUI file", filename, ELL_ERROR); return false; } diff --git a/source/Irrlicht/CImageLoaderJPG.cpp b/source/Irrlicht/CImageLoaderJPG.cpp index 0cd6a353..48c8997d 100644 --- a/source/Irrlicht/CImageLoaderJPG.cpp +++ b/source/Irrlicht/CImageLoaderJPG.cpp @@ -137,7 +137,7 @@ bool CImageLoaderJPG::isALoadableFileFormat(io::IReadFile* file) const IImage* CImageLoaderJPG::loadImage(io::IReadFile* file) const { #ifndef _IRR_COMPILE_WITH_LIBJPEG_ - os::Printer::log("Can't load as not compiled with _IRR_COMPILE_WITH_LIBJPEG_:", file->getFileName(), ELL_DEBUG); + os::Printer::log("Can't load as not compiled with _IRR_COMPILE_WITH_LIBJPEG_", file->getFileName(), ELL_DEBUG); return 0; #else diff --git a/source/Irrlicht/CImageLoaderPNG.cpp b/source/Irrlicht/CImageLoaderPNG.cpp index 08fc7201..076871f3 100644 --- a/source/Irrlicht/CImageLoaderPNG.cpp +++ b/source/Irrlicht/CImageLoaderPNG.cpp @@ -99,14 +99,14 @@ IImage* CImageLoaderPng::loadImage(io::IReadFile* file) const // Read the first few bytes of the PNG file if( file->read(buffer, 8) != 8 ) { - os::Printer::log("LOAD PNG: can't read file\n", file->getFileName(), ELL_ERROR); + os::Printer::log("LOAD PNG: can't read file (filesize < 8)", file->getFileName(), ELL_ERROR); return 0; } // Check if it really is a PNG file if( png_sig_cmp(buffer, 0, 8) ) { - os::Printer::log("LOAD PNG: not really a png\n", file->getFileName(), ELL_ERROR); + os::Printer::log("LOAD PNG: not really a png (wrong signature)", file->getFileName(), ELL_ERROR); return 0; } @@ -115,7 +115,7 @@ IImage* CImageLoaderPng::loadImage(io::IReadFile* file) const NULL, (png_error_ptr)png_cpexcept_error, (png_error_ptr)png_cpexcept_warn); if (!png_ptr) { - os::Printer::log("LOAD PNG: Internal PNG create read struct failure\n", file->getFileName(), ELL_ERROR); + os::Printer::log("LOAD PNG: Internal PNG create read struct failure", file->getFileName(), ELL_ERROR); return 0; } @@ -123,7 +123,7 @@ IImage* CImageLoaderPng::loadImage(io::IReadFile* file) const png_infop info_ptr = png_create_info_struct(png_ptr); if (!info_ptr) { - os::Printer::log("LOAD PNG: Internal PNG create info struct failure\n", file->getFileName(), ELL_ERROR); + os::Printer::log("LOAD PNG: Internal PNG create info struct failure", file->getFileName(), ELL_ERROR); png_destroy_read_struct(&png_ptr, NULL, NULL); return 0; } @@ -143,10 +143,10 @@ IImage* CImageLoaderPng::loadImage(io::IReadFile* file) const png_read_info(png_ptr, info_ptr); // Read the info section of the png file - u32 Width; - u32 Height; - s32 BitDepth; - s32 ColorType; + u32 Width=0; + u32 Height=0; + s32 BitDepth=0; + s32 ColorType=0; { // Use temporary variables to avoid passing cast pointers png_uint_32 w,h; @@ -158,9 +158,6 @@ IImage* CImageLoaderPng::loadImage(io::IReadFile* file) const Height=h; } - if (!IImage::checkDataSizeLimit((size_t)Width* Height * (BitDepth/8))) - png_cpexcept_error(png_ptr, "Image dimensions too large"); - // Convert palette color to true color if (ColorType==PNG_COLOR_TYPE_PALETTE) png_set_palette_to_rgb(png_ptr); @@ -223,15 +220,16 @@ IImage* CImageLoaderPng::loadImage(io::IReadFile* file) const #endif } + ECOLOR_FORMAT colorFormat = ColorType==PNG_COLOR_TYPE_RGB_ALPHA ? ECF_A8R8G8B8 : ECF_R8G8B8; + + if (!IImage::checkDataSizeLimit(IImage::getDataSizeFromFormat(colorFormat, Width, Height))) + png_cpexcept_error(png_ptr, "Image dimensions too large"); + // Create the image structure to be filled by png data - video::IImage* image = 0; - if (ColorType==PNG_COLOR_TYPE_RGB_ALPHA) - image = new CImage(ECF_A8R8G8B8, core::dimension2d(Width, Height)); - else - image = new CImage(ECF_R8G8B8, core::dimension2d(Width, Height)); + video::IImage* image = new CImage(colorFormat, core::dimension2du(Width, Height)); if (!image) { - os::Printer::log("LOAD PNG: Internal PNG create image struct failure\n", file->getFileName(), ELL_ERROR); + os::Printer::log("LOAD PNG: Internal PNG create image struct failure", file->getFileName(), ELL_ERROR); png_destroy_read_struct(&png_ptr, NULL, NULL); return 0; } @@ -240,7 +238,7 @@ IImage* CImageLoaderPng::loadImage(io::IReadFile* file) const RowPointers = new png_bytep[Height]; if (!RowPointers) { - os::Printer::log("LOAD PNG: Internal PNG create row pointers failure\n", file->getFileName(), ELL_ERROR); + os::Printer::log("LOAD PNG: Internal PNG create row pointers failure", file->getFileName(), ELL_ERROR); png_destroy_read_struct(&png_ptr, NULL, NULL); delete image; return 0; diff --git a/source/Irrlicht/CImageLoaderPSD.cpp b/source/Irrlicht/CImageLoaderPSD.cpp index 3eb5c3b8..00aadd69 100644 --- a/source/Irrlicht/CImageLoaderPSD.cpp +++ b/source/Irrlicht/CImageLoaderPSD.cpp @@ -80,7 +80,7 @@ IImage* CImageLoaderPSD::loadImage(io::IReadFile* file) const if (header.mode != 3 || header.depth != 8) { - os::Printer::log("Unsupported PSD color mode or depth.\n", file->getFileName(), ELL_ERROR); + os::Printer::log("Unsupported PSD color mode or depth", file->getFileName(), ELL_ERROR); return 0; } @@ -93,7 +93,7 @@ IImage* CImageLoaderPSD::loadImage(io::IReadFile* file) const #endif if (!file->seek(l, true)) { - os::Printer::log("Error seeking file pos to image resources.\n", file->getFileName(), ELL_ERROR); + os::Printer::log("Error seeking file pos to image resources", file->getFileName(), ELL_ERROR); return 0; } @@ -105,7 +105,7 @@ IImage* CImageLoaderPSD::loadImage(io::IReadFile* file) const #endif if (!file->seek(l, true)) { - os::Printer::log("Error seeking file pos to layer and mask.\n", file->getFileName(), ELL_ERROR); + os::Printer::log("Error seeking file pos to layer and mask", file->getFileName(), ELL_ERROR); return 0; } @@ -117,7 +117,7 @@ IImage* CImageLoaderPSD::loadImage(io::IReadFile* file) const #endif if (!file->seek(l, true)) { - os::Printer::log("Error seeking file pos to image data section.\n", file->getFileName(), ELL_ERROR); + os::Printer::log("Error seeking file pos to image data section", file->getFileName(), ELL_ERROR); return 0; } @@ -131,7 +131,7 @@ IImage* CImageLoaderPSD::loadImage(io::IReadFile* file) const if (compressionType != 1 && compressionType != 0) { - os::Printer::log("Unsupported psd compression mode.\n", file->getFileName(), ELL_ERROR); + os::Printer::log("Unsupported psd compression mode", file->getFileName(), ELL_ERROR); return 0; } @@ -171,7 +171,7 @@ bool CImageLoaderPSD::readRawImageData(io::IReadFile* file, const PsdHeader& hea { if (!file->read(tmpData, sizeof(c8) * header.width * header.height)) { - os::Printer::log("Error reading color channel\n", file->getFileName(), ELL_ERROR); + os::Printer::log("Error reading color channel", file->getFileName(), ELL_ERROR); break; } @@ -247,7 +247,7 @@ bool CImageLoaderPSD::readRLEImageData(io::IReadFile* file, const PsdHeader& hea { delete [] tmpData; delete [] rleCount; - os::Printer::log("Error reading rle rows\n", file->getFileName(), ELL_ERROR); + os::Printer::log("Error reading rle rows", file->getFileName(), ELL_ERROR); return false; } @@ -263,7 +263,7 @@ bool CImageLoaderPSD::readRLEImageData(io::IReadFile* file, const PsdHeader& hea delete [] rleCount; delete [] buf; delete [] tmpData; - os::Printer::log("Error reading rle rows\n", file->getFileName(), ELL_ERROR); + os::Printer::log("Error reading rle rows", file->getFileName(), ELL_ERROR); return false; } diff --git a/source/Irrlicht/CImageLoaderTGA.cpp b/source/Irrlicht/CImageLoaderTGA.cpp index 667f40d6..8d91bd08 100644 --- a/source/Irrlicht/CImageLoaderTGA.cpp +++ b/source/Irrlicht/CImageLoaderTGA.cpp @@ -108,7 +108,7 @@ IImage* CImageLoaderTGA::loadImage(io::IReadFile* file) const if (!IImage::checkDataSizeLimit((size_t)header.ImageWidth* header.ImageHeight * (header.PixelDepth/8))) { - os::Printer::log("Image dimensions too large in file.", file->getFileName(), ELL_ERROR); + os::Printer::log("Image dimensions too large in file", file->getFileName(), ELL_ERROR); return 0; } diff --git a/source/Irrlicht/CImageWriterPNG.cpp b/source/Irrlicht/CImageWriterPNG.cpp index 3da43453..c08100f2 100644 --- a/source/Irrlicht/CImageWriterPNG.cpp +++ b/source/Irrlicht/CImageWriterPNG.cpp @@ -84,7 +84,7 @@ bool CImageWriterPNG::writeImage(io::IWriteFile* file, IImage* image,u32 param) NULL, (png_error_ptr)png_cpexcept_error, (png_error_ptr)png_cpexcept_warning); if (!png_ptr) { - os::Printer::log("PNGWriter: Internal PNG create write struct failure\n", file->getFileName(), ELL_ERROR); + os::Printer::log("PNGWriter: Internal PNG create write struct failure", file->getFileName(), ELL_ERROR); return false; } @@ -92,7 +92,7 @@ bool CImageWriterPNG::writeImage(io::IWriteFile* file, IImage* image,u32 param) png_infop info_ptr = png_create_info_struct(png_ptr); if (!info_ptr) { - os::Printer::log("PNGWriter: Internal PNG create info struct failure\n", file->getFileName(), ELL_ERROR); + os::Printer::log("PNGWriter: Internal PNG create info struct failure", file->getFileName(), ELL_ERROR); png_destroy_write_struct(&png_ptr, NULL); return false; } @@ -141,7 +141,7 @@ bool CImageWriterPNG::writeImage(io::IWriteFile* file, IImage* image,u32 param) u8* tmpImage = new u8[image->getDimension().Height*lineWidth]; if (!tmpImage) { - os::Printer::log("PNGWriter: Internal PNG create image failure\n", file->getFileName(), ELL_ERROR); + os::Printer::log("PNGWriter: Internal PNG create image failure", file->getFileName(), ELL_ERROR); png_destroy_write_struct(&png_ptr, &info_ptr); return false; } @@ -175,7 +175,7 @@ bool CImageWriterPNG::writeImage(io::IWriteFile* file, IImage* image,u32 param) u8** RowPointers = new png_bytep[image->getDimension().Height]; if (!RowPointers) { - os::Printer::log("PNGWriter: Internal PNG create row pointers failure\n", file->getFileName(), ELL_ERROR); + os::Printer::log("PNGWriter: Internal PNG create row pointers failure", file->getFileName(), ELL_ERROR); png_destroy_write_struct(&png_ptr, &info_ptr); delete [] tmpImage; return false; diff --git a/source/Irrlicht/CIrrDeviceLinux.cpp b/source/Irrlicht/CIrrDeviceLinux.cpp index 3e05766a..cb18e2ef 100644 --- a/source/Irrlicht/CIrrDeviceLinux.cpp +++ b/source/Irrlicht/CIrrDeviceLinux.cpp @@ -306,8 +306,8 @@ bool CIrrDeviceLinux::switchToFullscreen(bool reset) if (bestMode != -1) { os::Printer::log("Starting vidmode fullscreen mode...", ELL_INFORMATION); - os::Printer::log("hdisplay: ", core::stringc(modes[bestMode]->hdisplay).c_str(), ELL_INFORMATION); - os::Printer::log("vdisplay: ", core::stringc(modes[bestMode]->vdisplay).c_str(), ELL_INFORMATION); + os::Printer::log("hdisplay", core::stringc(modes[bestMode]->hdisplay).c_str(), ELL_INFORMATION); + os::Printer::log("vdisplay", core::stringc(modes[bestMode]->vdisplay).c_str(), ELL_INFORMATION); XF86VidModeSwitchToMode(XDisplay, Screennr, modes[bestMode]); XF86VidModeSetViewPort(XDisplay, Screennr, 0, 0); @@ -343,8 +343,8 @@ bool CIrrDeviceLinux::switchToFullscreen(bool reset) if (bestMode != -1) { os::Printer::log("Starting randr fullscreen mode...", ELL_INFORMATION); - os::Printer::log("width: ", core::stringc(modes[bestMode].width).c_str(), ELL_INFORMATION); - os::Printer::log("height: ", core::stringc(modes[bestMode].height).c_str(), ELL_INFORMATION); + os::Printer::log("width", core::stringc(modes[bestMode].width).c_str(), ELL_INFORMATION); + os::Printer::log("height", core::stringc(modes[bestMode].height).c_str(), ELL_INFORMATION); XRRSetScreenConfig(XDisplay,config,DefaultRootWindow(XDisplay),bestMode,OldRandrRotation,CurrentTime); UseXRandR=true; @@ -367,26 +367,26 @@ void IrrPrintXGrabError(int grabResult, const c8 * grabCommand ) { if ( grabResult == GrabSuccess ) { -// os::Printer::log(grabCommand, ": GrabSuccess", ELL_INFORMATION); +// os::Printer::log(grabCommand, "GrabSuccess", ELL_INFORMATION); return; } switch ( grabResult ) { case AlreadyGrabbed: - os::Printer::log(grabCommand, ": AlreadyGrabbed", ELL_WARNING); + os::Printer::log(grabCommand, "AlreadyGrabbed", ELL_WARNING); break; case GrabNotViewable: - os::Printer::log(grabCommand, ": GrabNotViewable", ELL_WARNING); + os::Printer::log(grabCommand, "GrabNotViewable", ELL_WARNING); break; case GrabFrozen: - os::Printer::log(grabCommand, ": GrabFrozen", ELL_WARNING); + os::Printer::log(grabCommand, "GrabFrozen", ELL_WARNING); break; case GrabInvalidTime: - os::Printer::log(grabCommand, ": GrabInvalidTime", ELL_WARNING); + os::Printer::log(grabCommand, "GrabInvalidTime", ELL_WARNING); break; default: - os::Printer::log(grabCommand, ": grab failed with unknown problem", ELL_WARNING); + os::Printer::log(grabCommand, "grab failed with unknown problem", ELL_WARNING); break; } } @@ -455,7 +455,7 @@ bool CIrrDeviceLinux::createWindow() } #ifdef _DEBUG else - os::Printer::log("Visual chosen: ", core::stringc(static_cast(VisualInfo->visualid)).c_str(), ELL_DEBUG); + os::Printer::log("Visual chosen", core::stringc(static_cast(VisualInfo->visualid)).c_str(), ELL_DEBUG); #endif // create color map @@ -1993,7 +1993,7 @@ 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); +// os::Printer::log("remove event", core::stringc((int)arg).c_str(), ELL_INFORMATION); return True; } return False; diff --git a/source/Irrlicht/CIrrDeviceSDL.cpp b/source/Irrlicht/CIrrDeviceSDL.cpp index e3e7713e..2c1e59e7 100644 --- a/source/Irrlicht/CIrrDeviceSDL.cpp +++ b/source/Irrlicht/CIrrDeviceSDL.cpp @@ -203,7 +203,7 @@ CIrrDeviceSDL::CIrrDeviceSDL(const SIrrlichtCreationParameters& param) #endif SDL_INIT_NOPARACHUTE ) < 0) { - os::Printer::log( "Unable to initialize SDL!", SDL_GetError()); + os::Printer::log("Unable to initialize SDL!", SDL_GetError()); Close = true; } else @@ -429,7 +429,7 @@ bool CIrrDeviceSDL::createWindow() } if ( !Screen ) { - os::Printer::log( "Could not initialize display!" ); + os::Printer::log("Could not initialize display!" ); return false; } @@ -618,7 +618,7 @@ bool CIrrDeviceSDL::run() else { irrevent.MouseInput.Event = irr::EMIE_RMOUSE_LEFT_UP; - MouseButtonStates &= !irr::EMBSM_RIGHT; + MouseButtonStates &= ~irr::EMBSM_RIGHT; } break; @@ -631,7 +631,7 @@ bool CIrrDeviceSDL::run() else { irrevent.MouseInput.Event = irr::EMIE_MMOUSE_LEFT_UP; - MouseButtonStates &= !irr::EMBSM_MIDDLE; + MouseButtonStates &= ~irr::EMBSM_MIDDLE; } break; diff --git a/source/Irrlicht/CIrrDeviceSDL.h b/source/Irrlicht/CIrrDeviceSDL.h index 3ba4ebf3..9d2afe86 100644 --- a/source/Irrlicht/CIrrDeviceSDL.h +++ b/source/Irrlicht/CIrrDeviceSDL.h @@ -153,6 +153,8 @@ namespace irr virtual void setPosition(s32 x, s32 y) IRR_OVERRIDE { SDL_WarpMouse( x, y ); + CursorPos.X = x; + CursorPos.Y = y; } //! Returns the current position of the mouse cursor. @@ -200,15 +202,6 @@ namespace irr #else CursorPos.X = Device->MouseX; CursorPos.Y = Device->MouseY; - - if (CursorPos.X < 0) - CursorPos.X = 0; - if (CursorPos.X > (s32)Device->Width) - CursorPos.X = Device->Width; - if (CursorPos.Y < 0) - CursorPos.Y = 0; - if (CursorPos.Y > (s32)Device->Height) - CursorPos.Y = Device->Height; #endif } diff --git a/source/Irrlicht/CIrrMeshFileLoader.cpp b/source/Irrlicht/CIrrMeshFileLoader.cpp index e24d7a5d..84754eae 100644 --- a/source/Irrlicht/CIrrMeshFileLoader.cpp +++ b/source/Irrlicht/CIrrMeshFileLoader.cpp @@ -458,7 +458,7 @@ void CIrrMeshFileLoader::skipSection(io::IXMLReader* reader, bool reportSkipping { #ifdef _DEBUG if (reportSkipping) - os::Printer::log("irrMesh unknown element:", core::stringc(reader->getNodeName()).c_str()); + os::Printer::log("irrMesh unknown element", core::stringc(reader->getNodeName()).c_str()); #endif ++tagCounter; diff --git a/source/Irrlicht/CLWOMeshFileLoader.cpp b/source/Irrlicht/CLWOMeshFileLoader.cpp index ce158440..d30a6ebc 100644 --- a/source/Irrlicht/CLWOMeshFileLoader.cpp +++ b/source/Irrlicht/CLWOMeshFileLoader.cpp @@ -1945,7 +1945,7 @@ void CLWOMeshFileLoader::readMat(u32 size) default: { #ifdef LWO_READER_DEBUG - os::Printer::log("LWO loader: skipping ", core::stringc((char*)&uiType, 4)); + os::Printer::log("LWO loader: skipping", core::stringc((char*)&uiType, 4)); #endif File->seek(subsize, true); size -= subsize; diff --git a/source/Irrlicht/CMD2MeshFileLoader.cpp b/source/Irrlicht/CMD2MeshFileLoader.cpp index 5aa16c88..78136e75 100644 --- a/source/Irrlicht/CMD2MeshFileLoader.cpp +++ b/source/Irrlicht/CMD2MeshFileLoader.cpp @@ -199,7 +199,7 @@ bool CMD2MeshFileLoader::loadFile(io::IReadFile* file, CAnimatedMeshMD2* mesh) if (!file->read(textureCoords, sizeof(SMD2TextureCoordinate)*header.numTexcoords)) { delete[] textureCoords; - os::Printer::log("MD2 Loader: Error reading TextureCoords.", file->getFileName(), ELL_ERROR); + os::Printer::log("MD2 Loader: Error reading TextureCoords", file->getFileName(), ELL_ERROR); return false; } @@ -221,7 +221,7 @@ bool CMD2MeshFileLoader::loadFile(io::IReadFile* file, CAnimatedMeshMD2* mesh) delete[] triangles; delete[] textureCoords; - os::Printer::log("MD2 Loader: Error reading triangles.", file->getFileName(), ELL_ERROR); + os::Printer::log("MD2 Loader: Error reading triangles", file->getFileName(), ELL_ERROR); return false; } diff --git a/source/Irrlicht/CMS3DMeshFileLoader.cpp b/source/Irrlicht/CMS3DMeshFileLoader.cpp index 4ad18aa2..77ef21cc 100644 --- a/source/Irrlicht/CMS3DMeshFileLoader.cpp +++ b/source/Irrlicht/CMS3DMeshFileLoader.cpp @@ -242,7 +242,7 @@ bool CMS3DMeshFileLoader::load(io::IReadFile* file) if (pPtr + ((sizeof(MS3DVertex) - MS3DVERTEX_NUM_PAD_BYTES) * numVertices) > buffer+fileSize) { delete [] buffer; - os::Printer::log("Loading failed. Corrupted data found.", file->getFileName(), ELL_ERROR); + os::Printer::log("Loading failed. Corrupted data found", file->getFileName(), ELL_ERROR); return false; } for (u16 tmp=0; tmp buffer+fileSize) { delete [] buffer; - os::Printer::log("Loading failed. Corrupted data found.", file->getFileName(), ELL_ERROR); + os::Printer::log("Loading failed. Corrupted data found", file->getFileName(), ELL_ERROR); return false; } for (u16 tmp=0; tmp buffer+fileSize) { delete [] buffer; - os::Printer::log("Loading failed. Corrupted data found.", file->getFileName(), ELL_ERROR); + os::Printer::log("Loading failed. Corrupted data found", file->getFileName(), ELL_ERROR); return false; } } @@ -390,7 +390,7 @@ bool CMS3DMeshFileLoader::load(io::IReadFile* file) if (pPtr > buffer+fileSize) { delete [] buffer; - os::Printer::log("Loading failed. Corrupted data found.", file->getFileName(), ELL_ERROR); + os::Printer::log("Loading failed. Corrupted data found", file->getFileName(), ELL_ERROR); return false; } @@ -452,7 +452,7 @@ bool CMS3DMeshFileLoader::load(io::IReadFile* file) if (pPtr > buffer+fileSize) { delete [] buffer; - os::Printer::log("Loading failed. Corrupted data found.", file->getFileName(), ELL_ERROR); + os::Printer::log("Loading failed. Corrupted data found", file->getFileName(), ELL_ERROR); return false; } @@ -479,7 +479,7 @@ bool CMS3DMeshFileLoader::load(io::IReadFile* file) if (pPtr > buffer+fileSize) { delete [] buffer; - os::Printer::log("Loading failed. Corrupted data found.", file->getFileName(), ELL_ERROR); + os::Printer::log("Loading failed. Corrupted data found", file->getFileName(), ELL_ERROR); return false; } @@ -529,7 +529,7 @@ bool CMS3DMeshFileLoader::load(io::IReadFile* file) if (pPtr > buffer+fileSize) { delete [] buffer; - os::Printer::log("Loading failed. Corrupted data found.", file->getFileName(), ELL_ERROR); + os::Printer::log("Loading failed. Corrupted data found", file->getFileName(), ELL_ERROR); return false; } @@ -569,7 +569,7 @@ bool CMS3DMeshFileLoader::load(io::IReadFile* file) if (pPtr > buffer+fileSize) { delete [] buffer; - os::Printer::log("Loading failed. Corrupted data found.", file->getFileName(), ELL_ERROR); + os::Printer::log("Loading failed. Corrupted data found", file->getFileName(), ELL_ERROR); return false; } @@ -625,7 +625,7 @@ bool CMS3DMeshFileLoader::load(io::IReadFile* file) if (pPtr > buffer+fileSize) { delete [] buffer; - os::Printer::log("Loading failed. Corrupted data found.", file->getFileName(), ELL_ERROR); + os::Printer::log("Loading failed. Corrupted data found", file->getFileName(), ELL_ERROR); return false; } } @@ -657,7 +657,7 @@ bool CMS3DMeshFileLoader::load(io::IReadFile* file) if (pPtr > buffer+fileSize) { delete [] buffer; - os::Printer::log("Loading failed. Corrupted data found.", file->getFileName(), ELL_ERROR); + os::Printer::log("Loading failed. Corrupted data found", file->getFileName(), ELL_ERROR); return false; } } diff --git a/source/Irrlicht/CMeshManipulator.cpp b/source/Irrlicht/CMeshManipulator.cpp index 093ad239..bc02c391 100644 --- a/source/Irrlicht/CMeshManipulator.cpp +++ b/source/Irrlicht/CMeshManipulator.cpp @@ -708,38 +708,45 @@ IMesh* CMeshManipulator::createMeshUniquePrimitives(IMesh* mesh) const // not yet 32bit IMesh* CMeshManipulator::createMeshWelded(IMesh *mesh, f32 tolerance) const { - SMesh* clone = new SMesh(); - clone->BoundingBox = mesh->getBoundingBox(); + SMesh* meshClone = new SMesh(); + meshClone->BoundingBox = mesh->getBoundingBox(); core::array redirects; for (u32 b=0; bgetMeshBufferCount(); ++b) { const IMeshBuffer* const mb = mesh->getMeshBuffer(b); + const u32 vertexCount = mb->getVertexCount(); // reset redirect list - redirects.set_used(mb->getVertexCount()); + redirects.set_used(vertexCount); - const u16* indices = 0; - u32 indexCount = 0; + const video::E_INDEX_TYPE indexType = mb->getIndexType(); + const u16* indices = mb->getIndices(); + const u32 indexCount = mb->getIndexCount(); core::array* outIdx = 0; + if ( indexType == video::EIT_32BIT ) + { + IMeshBuffer* buffer = mb->createClone(); + buffer->setBoundingBox(mb->getBoundingBox()); + buffer->getMaterial() = mb->getMaterial(); + meshClone->addMeshBuffer(buffer); + buffer->drop(); + continue; // TODO: handle 32-bit buffers beside copying them + } + switch(mb->getVertexType()) { case video::EVT_STANDARD: { SMeshBuffer* buffer = new SMeshBuffer(); - buffer->BoundingBox = mb->getBoundingBox(); + buffer->setBoundingBox(mb->getBoundingBox()); buffer->Material = mb->getMaterial(); - clone->addMeshBuffer(buffer); + meshClone->addMeshBuffer(buffer); buffer->drop(); - video::S3DVertex* v = - (video::S3DVertex*)mb->getVertices(); + video::S3DVertex* v = (video::S3DVertex*)mb->getVertices(); - u32 vertexCount = mb->getVertexCount(); - - indices = mb->getIndices(); - indexCount = mb->getIndexCount(); outIdx = &buffer->Indices; buffer->Vertices.reallocate(vertexCount); @@ -771,18 +778,14 @@ IMesh* CMeshManipulator::createMeshWelded(IMesh *mesh, f32 tolerance) const case video::EVT_2TCOORDS: { SMeshBufferLightMap* buffer = new SMeshBufferLightMap(); - buffer->BoundingBox = mb->getBoundingBox(); + buffer->setBoundingBox(mb->getBoundingBox()); buffer->Material = mb->getMaterial(); - clone->addMeshBuffer(buffer); + meshClone->addMeshBuffer(buffer); buffer->drop(); video::S3DVertex2TCoords* v = (video::S3DVertex2TCoords*)mb->getVertices(); - u32 vertexCount = mb->getVertexCount(); - - indices = mb->getIndices(); - indexCount = mb->getIndexCount(); outIdx = &buffer->Indices; buffer->Vertices.reallocate(vertexCount); @@ -814,18 +817,13 @@ IMesh* CMeshManipulator::createMeshWelded(IMesh *mesh, f32 tolerance) const case video::EVT_TANGENTS: { SMeshBufferTangents* buffer = new SMeshBufferTangents(); - buffer->BoundingBox = mb->getBoundingBox(); + buffer->setBoundingBox(mb->getBoundingBox()); buffer->Material = mb->getMaterial(); - clone->addMeshBuffer(buffer); + meshClone->addMeshBuffer(buffer); buffer->drop(); - video::S3DVertexTangents* v = - (video::S3DVertexTangents*)mb->getVertices(); + video::S3DVertexTangents* v = (video::S3DVertexTangents*)mb->getVertices(); - u32 vertexCount = mb->getVertexCount(); - - indices = mb->getIndices(); - indexCount = mb->getIndexCount(); outIdx = &buffer->Indices; buffer->Vertices.reallocate(vertexCount); @@ -860,7 +858,7 @@ IMesh* CMeshManipulator::createMeshWelded(IMesh *mesh, f32 tolerance) const break; } - // Clean up any degenerate tris + // set indices for new buffer core::array &Indices = *outIdx; Indices.clear(); Indices.reallocate(indexCount); @@ -873,6 +871,7 @@ IMesh* CMeshManipulator::createMeshWelded(IMesh *mesh, f32 tolerance) const bool drop = false; + // Clean up any degenerate tris if (a == b || b == c || a == c) drop = true; @@ -885,8 +884,9 @@ IMesh* CMeshManipulator::createMeshWelded(IMesh *mesh, f32 tolerance) const Indices.push_back(c); } } + // indexCount-Indices.size() vertices got welded for this meshbuffer } - return clone; + return meshClone; } diff --git a/source/Irrlicht/COBJMeshFileLoader.cpp b/source/Irrlicht/COBJMeshFileLoader.cpp index 9fe99b01..dfca89ae 100644 --- a/source/Irrlicht/COBJMeshFileLoader.cpp +++ b/source/Irrlicht/COBJMeshFileLoader.cpp @@ -250,7 +250,7 @@ IAnimatedMesh* COBJMeshFileLoader::createMesh(io::IReadFile* file) v.Pos = vertexBuffer[Idx[0]]; else { - os::Printer::log("Invalid vertex index in this line:", wordBuffer.c_str(), ELL_ERROR); + os::Printer::log("Invalid vertex index in this line", wordBuffer.c_str(), ELL_ERROR); delete [] buf; return 0; } diff --git a/source/Irrlicht/CQ3LevelMesh.cpp b/source/Irrlicht/CQ3LevelMesh.cpp index b2f9060e..53b1dffd 100644 --- a/source/Irrlicht/CQ3LevelMesh.cpp +++ b/source/Irrlicht/CQ3LevelMesh.cpp @@ -112,7 +112,7 @@ bool CQ3LevelMesh::loadFile(io::IReadFile* file) ( header.strID != 0x50534252 || header.version != 1 ) // RBSP, starwars jedi, sof ) { - os::Printer::log("Could not load .bsp file, unknown header.", file->getFileName(), ELL_ERROR); + os::Printer::log("Could not load .bsp file, unknown header", file->getFileName(), ELL_ERROR); return false; } diff --git a/source/Irrlicht/CSceneManager.cpp b/source/Irrlicht/CSceneManager.cpp index 4302cfa4..42bf9b53 100644 --- a/source/Irrlicht/CSceneManager.cpp +++ b/source/Irrlicht/CSceneManager.cpp @@ -438,7 +438,7 @@ IAnimatedMesh* CSceneManager::getMesh(const io::path& filename, const io::path& io::IReadFile* file = FileSystem->createAndOpenFile(filename); if (!file) { - os::Printer::log("Could not load mesh, because file could not be opened: ", filename, ELL_ERROR); + os::Printer::log("Could not load mesh, because file could not be opened", filename, ELL_ERROR); return 0; } @@ -2377,7 +2377,7 @@ bool CSceneManager::loadScene(io::IReadFile* file, ISceneUserDataSerializer* use ret = SceneLoaderList[i]->loadScene(file, userDataSerializer, rootNode); if (!ret) - os::Printer::log("Could not load scene file, perhaps the format is unsupported: ", file->getFileName().c_str(), ELL_ERROR); + os::Printer::log("Could not load scene file, perhaps the format is unsupported", file->getFileName().c_str(), ELL_ERROR); return ret; } diff --git a/source/Irrlicht/CSceneNodeAnimatorCameraFPS.cpp b/source/Irrlicht/CSceneNodeAnimatorCameraFPS.cpp index a5f71b4f..591dce51 100644 --- a/source/Irrlicht/CSceneNodeAnimatorCameraFPS.cpp +++ b/source/Irrlicht/CSceneNodeAnimatorCameraFPS.cpp @@ -117,7 +117,6 @@ void CSceneNodeAnimatorCameraFPS::animateNode(ISceneNode* node, u32 timeMs) if (firstUpdate) { - camera->updateAbsolutePosition(); if (CursorControl ) { CursorControl->setPosition(0.5f, 0.5f); @@ -151,6 +150,7 @@ void CSceneNodeAnimatorCameraFPS::animateNode(ISceneNode* node, u32 timeMs) LastAnimationTime = timeMs; // Update rotation + camera->updateAbsolutePosition(); core::vector3df target = (camera->getTarget() - camera->getAbsolutePosition()); core::vector3df relativeRotation = target.getHorizontalAngle(); diff --git a/source/Irrlicht/CSkinnedMesh.cpp b/source/Irrlicht/CSkinnedMesh.cpp index bc94759f..d53bf1b2 100644 --- a/source/Irrlicht/CSkinnedMesh.cpp +++ b/source/Irrlicht/CSkinnedMesh.cpp @@ -1104,27 +1104,27 @@ void CSkinnedMesh::finalize() if ( redundantPosKeys > 0 ) { - os::Printer::log("Skinned Mesh - redundant position frames kicked:", core::stringc(redundantPosKeys).c_str(), ELL_DEBUG); + os::Printer::log("Skinned Mesh - redundant position frames kicked", core::stringc(redundantPosKeys).c_str(), ELL_DEBUG); } if ( unorderedPosKeys > 0 ) { - irr::os::Printer::log("Skinned Mesh - unsorted position frames kicked:", irr::core::stringc(unorderedPosKeys).c_str(), irr::ELL_DEBUG); + irr::os::Printer::log("Skinned Mesh - unsorted position frames kicked", irr::core::stringc(unorderedPosKeys).c_str(), irr::ELL_DEBUG); } if ( redundantScaleKeys > 0 ) { - os::Printer::log("Skinned Mesh - redundant scale frames kicked:", core::stringc(redundantScaleKeys).c_str(), ELL_DEBUG); + os::Printer::log("Skinned Mesh - redundant scale frames kicked", core::stringc(redundantScaleKeys).c_str(), ELL_DEBUG); } if ( unorderedScaleKeys > 0 ) { - irr::os::Printer::log("Skinned Mesh - unsorted scale frames kicked:", irr::core::stringc(unorderedScaleKeys).c_str(), irr::ELL_DEBUG); + irr::os::Printer::log("Skinned Mesh - unsorted scale frames kicked", irr::core::stringc(unorderedScaleKeys).c_str(), irr::ELL_DEBUG); } if ( redundantRotationKeys > 0 ) { - os::Printer::log("Skinned Mesh - redundant rotation frames kicked:", core::stringc(redundantRotationKeys).c_str(), ELL_DEBUG); + os::Printer::log("Skinned Mesh - redundant rotation frames kicked", core::stringc(redundantRotationKeys).c_str(), ELL_DEBUG); } if ( unorderedRotationKeys > 0 ) { - irr::os::Printer::log("Skinned Mesh - unsorted rotation frames kicked:", irr::core::stringc(unorderedRotationKeys).c_str(), irr::ELL_DEBUG); + irr::os::Printer::log("Skinned Mesh - unsorted rotation frames kicked", irr::core::stringc(unorderedRotationKeys).c_str(), irr::ELL_DEBUG); } } diff --git a/source/Irrlicht/CTerrainSceneNode.cpp b/source/Irrlicht/CTerrainSceneNode.cpp index 395a45da..0dbb96a9 100644 --- a/source/Irrlicht/CTerrainSceneNode.cpp +++ b/source/Irrlicht/CTerrainSceneNode.cpp @@ -265,7 +265,7 @@ namespace scene { if ((filesize-file->getPos())/bytesPerPixel>(size_t)(width*width)) { - os::Printer::log("Error reading heightmap RAW file", "File is too small."); + os::Printer::log("Error reading heightmap RAW file: File is too small."); return false; } TerrainData.Size = width; diff --git a/source/Irrlicht/CWGLManager.cpp b/source/Irrlicht/CWGLManager.cpp index da9fb1a3..1368c3d7 100644 --- a/source/Irrlicht/CWGLManager.cpp +++ b/source/Irrlicht/CWGLManager.cpp @@ -463,7 +463,7 @@ bool CWGLManager::activateContext(const SExposedVideoData& videoData, bool resto { if (!wglMakeCurrent((HDC)PrimaryContext.OpenGLWin32.HDc, (HGLRC)PrimaryContext.OpenGLWin32.HRc)) { - os::Printer::log("Render Context switch failed."); + os::Printer::log("Render Context switch (back to main) failed."); return false; } CurrentContext=PrimaryContext; diff --git a/source/Irrlicht/CXMeshFileLoader.cpp b/source/Irrlicht/CXMeshFileLoader.cpp index 4678c854..db72b218 100644 --- a/source/Irrlicht/CXMeshFileLoader.cpp +++ b/source/Irrlicht/CXMeshFileLoader.cpp @@ -491,7 +491,7 @@ bool CXMeshFileLoader::parseDataObject() // parse specific object #ifdef _XREADER_DEBUG - os::Printer::log("debug DataObject:", objectName.c_str(), ELL_DEBUG); + os::Printer::log("debug DataObject", objectName.c_str(), ELL_DEBUG); #endif if (objectName == "template") @@ -848,7 +848,7 @@ bool CXMeshFileLoader::parseDataObjectMesh(SXMesh &mesh) } #ifdef _XREADER_DEBUG - os::Printer::log("debug DataObject in mesh:", objectName.c_str(), ELL_DEBUG); + os::Printer::log("debug DataObject in mesh", objectName.c_str(), ELL_DEBUG); #endif if (objectName == "MeshNormals") diff --git a/source/Irrlicht/os.h b/source/Irrlicht/os.h index ca2bbf14..ae524c8b 100644 --- a/source/Irrlicht/os.h +++ b/source/Irrlicht/os.h @@ -39,6 +39,8 @@ namespace os static void print(const c8* message, ELOG_LEVEL ll = ELL_INFORMATION); static void log(const c8* message, ELOG_LEVEL ll = ELL_INFORMATION); static void log(const wchar_t* message, ELOG_LEVEL ll = ELL_INFORMATION); + + // The string ": " is added between message and hint static void log(const c8* message, const c8* hint, ELOG_LEVEL ll = ELL_INFORMATION); static void log(const c8* message, const io::path& hint, ELOG_LEVEL ll = ELL_INFORMATION); static ILogger* Logger; diff --git a/tests/tests-last-passed-at.txt b/tests/tests-last-passed-at.txt index 3cde178b..fde0c2e8 100644 --- a/tests/tests-last-passed-at.txt +++ b/tests/tests-last-passed-at.txt @@ -1,4 +1,4 @@ -Tests finished. 72 tests of 72 passed. -Compiled as DEBUG -Test suite pass at GMT Sat May 14 18:16:57 2022 - +Tests finished. 72 tests of 72 passed. +Compiled as DEBUG +Test suite pass at GMT Thu Sep 15 20:10:06 2022 +