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
This commit is contained in:
cutealien 2022-09-22 21:55:03 +00:00
parent ddc14ea87e
commit 07f17647d2
46 changed files with 589 additions and 463 deletions

View File

@ -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) 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. - 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). - 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 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 Changes in 1.8.6
- Avoid warning about stringop-overflow in string<T>::subString when compiling in release with newer gcc
- Update library zlib to 1.2.11 (from 1.2.8) - Update library zlib to 1.2.11 (from 1.2.8)
- Update library bzip2 to 1.0.8 (from 1.0.6) - 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) - Security: Fix buffer overflow caused by malformed md2 files. Thanks @procfs for reporting (https://irrlicht.sourceforge.io/forum/viewtopic.php?f=7&t=52785)

View File

@ -25,6 +25,7 @@ all: all_linux
# target specific settings # target specific settings
all_linux all_win32 static_win32: LDFLAGS += -L$(IrrlichtHome)/lib/$(SYSTEM) -lIrrlicht 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 += -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_linux clean_linux: SYSTEM=Linux
all_win32 clean_win32 static_win32: SYSTEM=Win32-gcc all_win32 clean_win32 static_win32: SYSTEM=Win32-gcc
all_win32 clean_win32 static_win32: SUF=.exe all_win32 clean_win32 static_win32: SUF=.exe

View File

@ -42,7 +42,7 @@ public:
/* /*
Always return false by default. If you return true you tell the engine Always return false by default. If you return true you tell the engine
that you handled this event completely and the Irrlicht should not 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 EET_KEY_INPUT_EVENT events then Irrlicht would not pass on key-events
to it's GUI system. to it's GUI system.
*/ */
@ -54,7 +54,7 @@ public:
{ {
return KeyIsDown[keyCode]; return KeyIsDown[keyCode];
} }
MyEventReceiver() MyEventReceiver()
{ {
for (u32 i=0; i<KEY_KEY_CODES_COUNT; ++i) for (u32 i=0; i<KEY_KEY_CODES_COUNT; ++i)
@ -71,7 +71,7 @@ private:
The event receiver for keeping the pressed keys is ready, the actual responses The event receiver for keeping the pressed keys is ready, the actual responses
will be made inside the render loop, right before drawing the scene. So lets will be made inside the render loop, right before drawing the scene. So lets
create an irr::IrrlichtDevice and the scene node we want to move. We also create an irr::IrrlichtDevice and the scene node we want to move. We also
create some additional scene nodes to show different possibilities to move and create some additional scene nodes to show different possibilities to move and
animate scene nodes. animate scene nodes.
*/ */
int main() int main()
@ -82,7 +82,7 @@ int main()
return 1; return 1;
/* /*
Create the event receiver. Take care that the pointer to it has to Create the event receiver. Take care that the pointer to it has to
stay valid as long as the IrrlichtDevice uses it. Event receivers are not stay valid as long as the IrrlichtDevice uses it. Event receivers are not
reference counted. reference counted.
*/ */
@ -139,7 +139,7 @@ int main()
} }
/* /*
The last scene node we add is a b3d model of a walking ninja. Is shows the The last scene node we add is a b3d model of a walking ninja. Is shows the
use of a 'fly straight' animator to move the node between two points. use of a 'fly straight' animator to move the node between two points.
*/ */
scene::IAnimatedMeshSceneNode* ninjaNode = scene::IAnimatedMeshSceneNode* ninjaNode =
@ -196,7 +196,7 @@ int main()
core::position2d<s32>(10,20)); core::position2d<s32>(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. name of the driver to the caption of the window.
*/ */
int lastFPS = -1; int lastFPS = -1;
@ -259,7 +259,7 @@ int main()
In the end, delete the Irrlicht device. In the end, delete the Irrlicht device.
*/ */
device->drop(); device->drop();
return 0; return 0;
} }

View File

@ -25,6 +25,7 @@ all: all_linux
# target specific settings # target specific settings
all_linux all_win32 static_win32: LDFLAGS += -L$(IrrlichtHome)/lib/$(SYSTEM) -lIrrlicht 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 += -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_linux clean_linux: SYSTEM=Linux
all_win32 clean_win32 static_win32: SYSTEM=Win32-gcc all_win32 clean_win32 static_win32: SYSTEM=Win32-gcc
all_win32 clean_win32 static_win32: SUF=.exe all_win32 clean_win32 static_win32: SUF=.exe

View File

@ -35,8 +35,6 @@ of the objects and camera.
*/ */
#ifdef _MSC_VER #ifdef _MSC_VER
// We'll also define this to stop MSVC complaining about sprintf().
#define _CRT_SECURE_NO_WARNINGS
#pragma comment(lib, "Irrlicht.lib") #pragma comment(lib, "Irrlicht.lib")
#endif #endif
@ -150,6 +148,7 @@ int main()
*/ */
smgr->addCameraSceneNode(); smgr->addCameraSceneNode();
int lastFPS = -1; int lastFPS = -1;
u32 lastPrimitives = 0;
u32 timeNow = device->getTimer()->getTime(); u32 timeNow = device->getTimer()->getTime();
bool nodeVisible=true; bool nodeVisible=true;
@ -190,16 +189,20 @@ int main()
driver->endScene(); driver->endScene();
int fps = driver->getFPS(); int fps = driver->getFPS();
u32 numPrimitives = driver->getPrimitiveCountDrawn();
if (lastFPS != fps) if (lastFPS != fps || lastPrimitives != numPrimitives)
{ {
core::stringw tmp(L"OcclusionQuery Example ["); core::stringw tmp(L"OcclusionQuery Example [");
tmp += driver->getName(); tmp += driver->getName();
tmp += L"] fps: "; tmp += L"] fps: ";
tmp += fps; tmp += fps;
tmp += L" polygons: ";
tmp += numPrimitives;
device->setWindowCaption(tmp.c_str()); device->setWindowCaption(tmp.c_str());
lastFPS = fps; lastFPS = fps;
lastPrimitives = numPrimitives;
} }
} }

View File

@ -1,16 +1,16 @@
/** Example 027 Post Processing /** 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 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 to render target. With the help of screen quad, the render target texture
is then drawn on the quad with shader-defined effects applied. 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 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. 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. written in HLSL and GLSL.
@author Boshen Guan @author Boshen Guan
@ -29,46 +29,42 @@ using namespace irr;
/* /*
We write a class derived from IShaderConstantSetCallBack class and implement 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. 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 shader. Therefore, we set texture size in OnSetConstants callback using
setVertexShaderConstant function. setVertexShaderConstant function.
*/ */
IrrlichtDevice* device = 0;
video::ITexture* rt = 0;
class QuadShaderCallBack : public video::IShaderConstantSetCallBack class QuadShaderCallBack : public video::IShaderConstantSetCallBack
{ {
public: public:
QuadShaderCallBack() : FirstUpdate(true), TextureSizeID(-1), TextureSamplerID(-1) QuadShaderCallBack() : FirstUpdate(true), TextureSizeID(-1), TextureSamplerID(-1)
{ } { }
virtual void OnSetConstants(video::IMaterialRendererServices* services, virtual void OnSetConstants(video::IMaterialRendererServices* services,
s32 userData) s32 userData)
{ {
core::dimension2d<u32> size = rt->getSize();
// get texture size array
f32 textureSize[] =
{
(f32)size.Width, (f32)size.Height
};
if ( FirstUpdate ) if ( FirstUpdate )
{ {
FirstUpdate = false;
TextureSizeID = services->getVertexShaderConstantID("TextureSize"); TextureSizeID = services->getVertexShaderConstantID("TextureSize");
TextureSamplerID = services->getPixelShaderConstantID("TextureSampler"); TextureSamplerID = services->getPixelShaderConstantID("TextureSampler");
} }
// set texture size to vertex shader // get texture size array (for our simple example HLSL just needs that to calculate pixel centers)
services->setVertexShaderConstant(TextureSizeID, reinterpret_cast<f32*>(textureSize), 2); core::dimension2d<u32> size = services->getVideoDriver()->getCurrentRenderTargetSize();
f32 textureSize[2];
// set texture for an OpenGL driver textureSize[0] = (f32)size.Width;
s32 textureLayer = 0; textureSize[1] = (f32)size.Height;
services->setPixelShaderConstant(TextureSamplerID, &textureLayer, 1);
} // 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: private:
bool FirstUpdate; bool FirstUpdate;
@ -80,102 +76,91 @@ class ScreenQuad : public IReferenceCounted
{ {
public: public:
ScreenQuad(video::IVideoDriver* driver) ScreenQuad(video::IVideoDriver* driver)
: Driver(driver) : Driver(driver)
{ {
// --------------------------------> u // --------------------------------> u
// |[1](-1, 1)----------[2](1, 1) // |[1](-1, 1)----------[2](1, 1)
// | | ( 0, 0) / | (1, 0) // | | ( 0, 0) / | (1, 0)
// | | / | // | | / |
// | | / | // | | / |
// | | / | // | | / |
// | | / | // | | / |
// | | / | // | | / |
// | | / | // | | / |
// | | / | // | | / |
// | | / | // | | / |
// |[0](-1, -1)---------[3](1, -1) // |[0](-1, -1)---------[3](1, -1)
// | ( 0, 1) (1, 1) // | ( 0, 1) (1, 1)
// V // V
// v // v
/* /*
A screen quad is composed of two adjacent triangles with 4 vertices. A screen quad is composed of two adjacent triangles with 4 vertices.
Vertex [0], [1] and [2] create the first triangle and Vertex [0], 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 [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 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. 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[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[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[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[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[0] = 0;
Indices[1] = 1; Indices[1] = 1;
Indices[2] = 2; Indices[2] = 2;
Indices[3] = 0; Indices[3] = 0;
Indices[4] = 2; Indices[4] = 2;
Indices[5] = 3; Indices[5] = 3;
// turn off lighting as default // turn off lighting as default
Material.setFlag(video::EMF_LIGHTING, false); Material.setFlag(video::EMF_LIGHTING, false);
// set texture warp settings to clamp to edge pixel // set texture warp settings to clamp to edge pixel
for (u32 i = 0; i < video::MATERIAL_MAX_TEXTURES; i++) for (u32 i = 0; i < video::MATERIAL_MAX_TEXTURES; i++)
{ {
Material.TextureLayer[i].TextureWrapU = video::ETC_CLAMP_TO_EDGE; Material.TextureLayer[i].TextureWrapU = video::ETC_CLAMP_TO_EDGE;
Material.TextureLayer[i].TextureWrapV = video::ETC_CLAMP_TO_EDGE; Material.TextureLayer[i].TextureWrapV = video::ETC_CLAMP_TO_EDGE;
} }
} }
virtual ~ScreenQuad() {} virtual ~ScreenQuad() {}
//! render the screen quad //! render the screen quad
virtual void render() virtual void render()
{ {
// set the material of screen quad // set the material of screen quad
Driver->setMaterial(Material); Driver->setMaterial(Material);
// set matrices to fit the quad to full viewport // set world matrix to fit the quad to full viewport
Driver->setTransform(video::ETS_WORLD, core::IdentityMatrix); Driver->setTransform(video::ETS_WORLD, core::IdentityMatrix);
Driver->setTransform(video::ETS_VIEW, core::IdentityMatrix); // view & projection not used in shader, but matter to burnings driver
Driver->setTransform(video::ETS_PROJECTION, core::IdentityMatrix); Driver->setTransform(video::ETS_VIEW, core::IdentityMatrix);
Driver->setTransform(video::ETS_PROJECTION, core::IdentityMatrix);
// draw screen quad // draw screen quad
Driver->drawVertexPrimitiveList(Vertices, 4, Indices, 2); Driver->drawVertexPrimitiveList(Vertices, 4, Indices, 2);
} }
//! sets a flag of material to a new value //! Access the material
virtual void setMaterialFlag(video::E_MATERIAL_FLAG flag, bool newvalue) virtual video::SMaterial& getMaterial()
{ {
Material.setFlag(flag, newvalue); return Material;
} }
//! 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;
}
private: private:
video::IVideoDriver *Driver; video::IVideoDriver *Driver;
video::S3DVertex Vertices[4]; video::S3DVertex Vertices[4];
u16 Indices[6]; u16 Indices[6];
video::SMaterial Material; video::SMaterial Material;
}; };
/* /*
@ -184,233 +169,237 @@ according to the driver type.
*/ */
int main() int main()
{ {
// ask user for driver // ask user for driver
video::E_DRIVER_TYPE driverType=driverChoiceConsole(); video::E_DRIVER_TYPE driverType=driverChoiceConsole();
if (driverType==video::EDT_COUNT) if (driverType==video::EDT_COUNT)
return 1; return 1;
// create device // create device
device = createDevice(driverType, core::dimension2d<u32>(640, 480)); IrrlichtDevice* device = createDevice(driverType, core::dimension2d<u32>(640, 480));
if (device == 0) if (device == 0)
return 1; // could not create selected driver. return 1; // could not create selected driver.
video::IVideoDriver* driver = device->getVideoDriver(); video::IVideoDriver* driver = device->getVideoDriver();
scene::ISceneManager* smgr = device->getSceneManager(); scene::ISceneManager* smgr = device->getSceneManager();
/* /*
In this example, high level post processing shaders are loaded for both In this example, high level post processing shaders are loaded for both
Direct3D and OpenGL drivers. Direct3D and OpenGL drivers.
File pp_d3d9.hlsl is for Direct3D 9, and pp_opengl.frag/pp_opengl.vert File pp_d3d9.hlsl is for Direct3D 9, and pp_opengl.frag/pp_opengl.vert
are for OpenGL. are for OpenGL.
*/ */
const io::path mediaPath = getExampleMediaPath(); const io::path mediaPath = getExampleMediaPath();
io::path vsFileName; // filename for the vertex shader io::path vsFileName; // filename for the vertex shader
io::path psFileName; // filename for the pixel shader io::path psFileName; // filename for the pixel shader
switch(driverType) switch(driverType)
{ {
case video::EDT_DIRECT3D9: case video::EDT_DIRECT3D9:
psFileName = mediaPath + "pp_d3d9.hlsl"; psFileName = mediaPath + "pp_d3d9.hlsl";
vsFileName = psFileName; // both shaders are in the same file vsFileName = psFileName; // both shaders are in the same file
break; break;
case video::EDT_OPENGL: case video::EDT_OPENGL:
case video::EDT_BURNINGSVIDEO: case video::EDT_BURNINGSVIDEO:
psFileName = mediaPath + "pp_opengl.frag"; psFileName = mediaPath + "pp_opengl.frag";
vsFileName = mediaPath + "pp_opengl.vert"; vsFileName = mediaPath + "pp_opengl.vert";
break; break;
} }
/* /*
Check for hardware capability of executing the corresponding shaders Check for hardware capability of executing the corresponding shaders
on selected renderer. This is not necessary though. on selected renderer. This is not necessary though.
*/ */
if (!driver->queryFeature(video::EVDF_PIXEL_SHADER_1_1) && if (!driver->queryFeature(video::EVDF_PIXEL_SHADER_1_1) &&
!driver->queryFeature(video::EVDF_ARB_FRAGMENT_PROGRAM_1)) !driver->queryFeature(video::EVDF_ARB_FRAGMENT_PROGRAM_1))
{ {
device->getLogger()->log("WARNING: Pixel shaders disabled "\ device->getLogger()->log("WARNING: Pixel shaders disabled "\
"because of missing driver/hardware support."); "because of missing driver/hardware support.");
psFileName = ""; psFileName = "";
} }
if (!driver->queryFeature(video::EVDF_VERTEX_SHADER_1_1) && if (!driver->queryFeature(video::EVDF_VERTEX_SHADER_1_1) &&
!driver->queryFeature(video::EVDF_ARB_VERTEX_PROGRAM_1)) !driver->queryFeature(video::EVDF_ARB_VERTEX_PROGRAM_1))
{ {
device->getLogger()->log("WARNING: Vertex shaders disabled "\ device->getLogger()->log("WARNING: Vertex shaders disabled "\
"because of missing driver/hardware support."); "because of missing driver/hardware support.");
vsFileName = ""; vsFileName = "";
} }
/* /*
An animated mesh is loaded to be displayed. As in most examples, An animated mesh is loaded to be displayed. As in most examples,
we'll take the fairy md2 model. we'll take the fairy md2 model.
*/ */
// load and display animated fairy mesh // load and display animated fairy mesh
scene::IAnimatedMeshSceneNode* fairy = smgr->addAnimatedMeshSceneNode( scene::IAnimatedMeshSceneNode* fairy = smgr->addAnimatedMeshSceneNode(
smgr->getMesh(mediaPath + "faerie.md2")); smgr->getMesh(mediaPath + "faerie.md2"));
if (fairy) if (fairy)
{ {
fairy->setMaterialTexture(0, fairy->setMaterialTexture(0,
driver->getTexture(mediaPath + "faerie2.bmp")); // set diffuse texture driver->getTexture(mediaPath + "faerie2.bmp")); // set diffuse texture
fairy->setMaterialFlag(video::EMF_LIGHTING, false); // disable dynamic lighting fairy->setMaterialFlag(video::EMF_LIGHTING, false); // disable dynamic lighting
fairy->setPosition(core::vector3df(-10,0,-100)); fairy->setPosition(core::vector3df(-10,0,-100));
fairy->setMD2Animation ( scene::EMAT_STAND ); fairy->setMD2Animation ( scene::EMAT_STAND );
} }
// add scene camera // add scene camera
smgr->addCameraSceneNode(0, core::vector3df(10,10,-80), smgr->addCameraSceneNode(0, core::vector3df(10,10,-80),
core::vector3df(-10,10,-100)); core::vector3df(-10,10,-100));
/* /*
We create a render target texture (RTT) with the same size as 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 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. 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 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 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 result of rendering directly to the frame buffer. Therefore, the size of
RTT keeps the same with frame buffer. 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<u32>(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)) /*
{ Post processing is achieved by rendering a screen quad with this RTT (with
rt = driver->addRenderTargetTexture(core::dimension2d<u32>(640, 480), "RTT1"); previously rendered result) as a texture on the quad. A screen quad is
} geometry of flat plane composed of two adjacent triangles covering the
else 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
device->getLogger()->log("Your hardware or this renderer is not able to use the "\ take control of this rendering process by applying various shader-defined
"render to texture feature. RTT Disabled."); 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
Post processing is achieved by rendering a screen quad with this RTT (with ScreenQuad *screenQuad = new ScreenQuad(driver);
previously rendered result) as a texture on the quad. A screen quad is video::SMaterial& screenQuadMaterial = screenQuad->getMaterial();
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 // turn off mip maps and bilinear filter since we do not want interpolated results
ScreenQuad *screenQuad = new ScreenQuad(driver); 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 // turn off depth buffer, because our full screen 2D overlay doesn't process depth
screenQuad->setMaterialFlag(video::EMF_USE_MIP_MAPS, false); screenQuadMaterial.setFlag(video::EMF_ZBUFFER, false);
screenQuad->setMaterialFlag(video::EMF_BILINEAR_FILTER, false);
// set quad texture to RTT we just create // set quad texture to RTT we just create
screenQuad->setMaterialTexture(0, rt); screenQuadMaterial.setTexture(0, rt);
/* /*
Let's create material for the quad. Like in other example, we create material Let's create material for the quad. Like in other example, we create material
using IGPUProgrammingServices and call addShaderMaterialFromFiles, which using IGPUProgrammingServices and call addShaderMaterialFromFiles, which
returns a material type identifier. returns a material type identifier.
*/ */
// create materials // create materials
video::IGPUProgrammingServices* gpu = driver->getGPUProgrammingServices(); video::IGPUProgrammingServices* gpu = driver->getGPUProgrammingServices();
s32 ppMaterialType = 0; s32 ppMaterialType = 0;
if (gpu) if (gpu)
{ {
// We write a QuadShaderCallBack class that implements OnSetConstants // We write a QuadShaderCallBack class that implements OnSetConstants
// callback of IShaderConstantSetCallBack class at the beginning of // callback of IShaderConstantSetCallBack class at the beginning of
// this tutorial. We set shader constants in this callback. // this tutorial. We set shader constants in this callback.
// create an instance of callback class
QuadShaderCallBack* mc = new QuadShaderCallBack(); // create an instance of callback class
// create material from post processing shaders QuadShaderCallBack* mc = new QuadShaderCallBack();
ppMaterialType = gpu->addHighLevelShaderMaterialFromFiles( // create material from post processing shaders
vsFileName, "vertexMain", video::EVST_VS_1_1,
psFileName, "pixelMain", video::EPST_PS_1_1, mc);
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 mc->drop();
screenQuad->setMaterialType((video::E_MATERIAL_TYPE)ppMaterialType); }
/* // set post processing material type to the quad
Now draw everything. That's all. screenQuadMaterial.MaterialType = (video::E_MATERIAL_TYPE)ppMaterialType;
*/
int lastFPS = -1; /*
Now draw everything. That's all.
*/
while(device->run()) int lastFPS = -1;
{
if (device->isWindowActive())
{
driver->beginScene(true, true, video::SColor(255,0,0,0));
if (rt) while(device->run())
{ {
// draw scene into render target if (device->isWindowActive())
{
driver->beginScene(true, true, video::SColor(255,0,0,0));
// set render target to RTT if (rt)
driver->setRenderTarget(rt, true, true, video::SColor(255,0,0,0)); {
// draw scene into render target
// draw scene to RTT just like normal rendering // set render target to RTT
smgr->drawAll(); driver->setRenderTarget(rt, true, true, video::SColor(255,0,0,0));
// after rendering to RTT, we change render target back // draw scene to RTT just like normal rendering
driver->setRenderTarget(0, true, true, video::SColor(255,0,0,0)); smgr->drawAll();
// render screen quad to apply post processing // after rendering to RTT, we change render target back
screenQuad->render(); driver->setRenderTarget(0, true, true, video::SColor(255,0,0,0));
}
else
{
// draw scene normally
smgr->drawAll();
}
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) int fps = driver->getFPS();
{
core::stringw str = L"Irrlicht Engine - Post processing example [";
str += driver->getName();
str += "] FPS:";
str += fps;
device->setWindowCaption(str.c_str()); if (lastFPS != fps)
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;
} }
/* /*

View File

@ -316,7 +316,7 @@ private:
Irrlicht internally uses textures with left-top origin and then corrects the texture-matrices in the fixed-function pipeline. 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. 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 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 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. 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. 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. 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: 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. 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. 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. /* 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 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. */ textures. While the cubemap uses a single texture created from 6 images. */
eventReceiver.BackgroundSkybox = smgr->addSkyBoxSceneNode( eventReceiver.BackgroundSkybox = smgr->addSkyBoxSceneNode(
@ -639,7 +639,7 @@ int main()
#endif #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); scene::IMeshSceneNode * movingNode = smgr->addCubeSceneNode(30.f);
movingNode->getMaterial(0).Lighting = false; movingNode->getMaterial(0).Lighting = false;
@ -692,7 +692,7 @@ int main()
driver->beginScene(true, true, video::SColor(255, 127, 127, 255)); driver->beginScene(true, true, video::SColor(255, 127, 127, 255));
/* Check if we want to update the environment maps. /* 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. or maybe updating an environment map once in a while.
*/ */
int updateCubemaps = eventReceiver.checkCubemapUpdate(); int updateCubemaps = eventReceiver.checkCubemapUpdate();
@ -704,7 +704,7 @@ int main()
{ {
/* /*
Flipping projection matrix flips front/backface culling. 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); smgr->getSceneNodesFromType(scene::ESNT_ANY, allNodes);
flipCullingFlags(allNodes); flipCullingFlags(allNodes);

View File

@ -176,6 +176,17 @@ namespace scene
return Vertices[i].TCoords; 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 //! Append the vertices and indices to the current buffer
/** Only works for compatible types, i.e. either the same type /** Only works for compatible types, i.e. either the same type

View File

@ -121,19 +121,23 @@ namespace scene
virtual f32 getFOV() const =0; virtual f32 getFOV() const =0;
//! Sets the value of the near clipping plane. (default: 1.0f) //! 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; virtual void setNearValue(f32 zn) =0;
//! Sets the value of the far clipping plane (default: 2000.0f) //! 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; virtual void setFarValue(f32 zf) =0;
//! Sets the aspect ratio (default: 4.0f / 3.0f) //! 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; virtual void setAspectRatio(f32 aspect) =0;
//! Sets the field of view (Default: PI / 2.5f) //! 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; virtual void setFOV(f32 fovy) =0;
//! Get the view frustum. //! Get the view frustum.
@ -165,7 +169,10 @@ namespace scene
@see getTargetAndRotationBinding() */ @see getTargetAndRotationBinding() */
virtual void bindTargetAndRotation(bool bound) =0; 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; virtual void updateMatrices() = 0;
//! Queries if the camera scene node's rotation and its target position are bound together. //! Queries if the camera scene node's rotation and its target position are bound together.

View File

@ -166,6 +166,18 @@ namespace scene
{ {
return getVertexBuffer()[i].Normal; 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;
}
}; };

View File

@ -22,7 +22,10 @@ namespace scene
before or after each scene node is rendered. It is assumed that the before or after each scene node is rendered. It is assumed that the
ILightManager implementation will store any data that it wishes to ILightManager implementation will store any data that it wishes to
retain, i.e. the ISceneManager to which it is assigned, the lightList, 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 class ILightManager : public IReferenceCounted
{ {
public: public:
@ -35,27 +38,27 @@ namespace scene
the light manager may modify. This reference will remain valid the light manager may modify. This reference will remain valid
until OnPostRender(). until OnPostRender().
*/ */
virtual void OnPreRender(core::array<ISceneNode*> & lightList) = 0; virtual void OnPreRender(core::array<ISceneNode*> & lightList) {};
//! Called after the last scene node is rendered. //! Called after the last scene node is rendered.
/** After this call returns, the lightList passed to OnPreRender() becomes invalid. */ /** 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 //! Called before a render pass begins
/** \param renderPass: the render pass that's about to begin */ /** \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 //! Called after the render pass specified in OnRenderPassPreRender() ends
/** \param[in] renderPass: the render pass that has finished */ /** \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 //! Called before the given scene node is rendered
/** \param[in] node: the scene node that's about to be 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 //! Called after the the node specified in OnNodePreRender() has been rendered
/** \param[in] node: the scene node that has just 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 scene
} // end namespace irr } // end namespace irr

View File

@ -119,6 +119,12 @@ namespace scene
//! returns texture coord of vertex i //! returns texture coord of vertex i
virtual core::vector2df& getTCoords(u32 i) = 0; 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 //! Append the vertices and indices to the current buffer
/** Only works for compatible vertex types /** Only works for compatible vertex types
and not implemented for most buffers for now. and not implemented for most buffers for now.

View File

@ -103,7 +103,9 @@ namespace scene
bool angleWeighted=false) const=0; bool angleWeighted=false) const=0;
//! Scales the actual mesh, not a scene node. //! 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. */ \param factor Scale factor for each axis. */
void scale(IMesh* mesh, const core::vector3df& factor) const void scale(IMesh* mesh, const core::vector3df& factor) const
{ {
@ -111,7 +113,9 @@ namespace scene
} }
//! Scales the actual meshbuffer, not a scene node. //! 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. */ \param factor Scale factor for each axis. */
void scale(IMeshBuffer* buffer, const core::vector3df& factor) const 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 mesh Mesh on which the operation is performed.
\param m transformation matrix. \param m transformation matrix.
\param normalsUpdate When 0 - don't update normals. \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); apply(SVertexPositionTransformManipulator(m), mesh, true);
@ -158,18 +165,25 @@ namespace scene
if ( m.getInverse(invT) ) if ( m.getInverse(invT) )
{ {
invT = invT.getTransposed(); 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 //! Applies a transformation to a meshbuffer
/** \param buffer Meshbuffer on which the operation is performed. /** \param buffer Meshbuffer on which the operation is performed.
\param m transformation matrix. \param m transformation matrix.
\param normalsUpdate When 0 - don't update normals. \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); apply(SVertexPositionTransformManipulator(m), buffer, true);
@ -179,9 +193,13 @@ namespace scene
if ( m.getInverse(invT) ) if ( m.getInverse(invT) )
{ {
invT = invT.getTransposed(); 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 //! Applies a transformation to a mesh
@ -239,6 +257,7 @@ namespace scene
/** This is useful if you want to draw tangent space normal /** This is useful if you want to draw tangent space normal
mapped geometry because it calculates the tangent and binormal mapped geometry because it calculates the tangent and binormal
data which is needed there. data which is needed there.
Note: Only 16-bit meshbuffers supported so far
\param mesh Input mesh \param mesh Input mesh
\param recalculateNormals The normals are recalculated if set, \param recalculateNormals The normals are recalculated if set,
otherwise the original ones are kept. Note that keeping the otherwise the original ones are kept. Note that keeping the
@ -257,7 +276,8 @@ namespace scene
bool angleWeighted=false, bool recalculateTangents=true) const=0; bool angleWeighted=false, bool recalculateTangents=true) const=0;
//! Creates a copy of the mesh, which will only consist of S3DVertex2TCoord vertices. //! 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 \return Mesh consisting only of S3DVertex2TCoord vertices. If
you no longer need the cloned mesh, you should call you no longer need the cloned mesh, you should call
IMesh::drop(). See IReferenceCounted::drop() for more IMesh::drop(). See IReferenceCounted::drop() for more
@ -265,7 +285,8 @@ namespace scene
virtual IMesh* createMeshWith2TCoords(IMesh* mesh) const = 0; virtual IMesh* createMeshWith2TCoords(IMesh* mesh) const = 0;
//! Creates a copy of the mesh, which will only consist of S3DVertex vertices. //! 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 \return Mesh consisting only of S3DVertex vertices. If
you no longer need the cloned mesh, you should call you no longer need the cloned mesh, you should call
IMesh::drop(). See IReferenceCounted::drop() for more IMesh::drop(). See IReferenceCounted::drop() for more
@ -273,15 +294,17 @@ namespace scene
virtual IMesh* createMeshWith1TCoords(IMesh* mesh) const = 0; virtual IMesh* createMeshWith1TCoords(IMesh* mesh) const = 0;
//! Creates a copy of a mesh with all vertices unwelded //! 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 \return Mesh consisting only of unique faces. All vertices
which were previously shared are now duplicated. If you no which were previously shared are now duplicated. If you no
longer need the cloned mesh, you should call IMesh::drop(). See longer need the cloned mesh, you should call IMesh::drop(). See
IReferenceCounted::drop() for more information. */ IReferenceCounted::drop() for more information. */
virtual IMesh* createMeshUniquePrimitives(IMesh* mesh) const = 0; virtual IMesh* createMeshUniquePrimitives(IMesh* mesh) const = 0;
//! Creates a copy of a mesh with vertices welded //! Creates a copy of a mesh with vertices welded
/** \param mesh Input mesh /** Note: Only 16-bit meshbuffers supported so far, 32-bit buffer are cloned
\param mesh Input mesh
\param tolerance The threshold for vertex comparisons. \param tolerance The threshold for vertex comparisons.
\return Mesh without redundant vertices. If you no longer need \return Mesh without redundant vertices. If you no longer need
the cloned mesh, you should call IMesh::drop(). See the cloned mesh, you should call IMesh::drop(). See

View File

@ -171,6 +171,21 @@ namespace scene
return (*Vertices)[Indices[i]].TCoords; 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 //! 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 virtual void append(const void* const vertices, u32 numVertices, const u16* const indices, u32 numIndices) IRR_OVERRIDE
{ {

View File

@ -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 //! 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 {} virtual void append(const void* const vertices, u32 numVertices, const u16* const indices, u32 numIndices) IRR_OVERRIDE {}

View File

@ -277,6 +277,32 @@ namespace scene
core::matrix4 Transformation; 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 <typename VType>
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 <typename VType>
void operator()(VType& vertex) const
{
vertex.Normal.normalize();
}
};
//! Vertex manipulator which scales the TCoords of the vertex //! Vertex manipulator which scales the TCoords of the vertex
class SVertexTCoordsScaleManipulator : public IVertexManipulator class SVertexTCoordsScaleManipulator : public IVertexManipulator
{ {

View File

@ -947,13 +947,13 @@ public:
\param make_lower copy only lower case */ \param make_lower copy only lower case */
string<T> subString(u32 begin, s32 length, bool make_lower = false ) const string<T> 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 // if start after string
// or no proper substring length // or no proper substring length
if ((length <= 0) || (begin>=size())) if ((length <= 0) || (begin>=size()))
return string<T>(""); return string<T>("");
// clamp length to maximal value
if ((length+begin) > size())
length = size()-begin;
string<T> o; string<T> o;
o.reserve(length+1); o.reserve(length+1);

View File

@ -221,10 +221,10 @@ namespace core
//! Translate a vector by the inverse of the translation part of this matrix. //! Translate a vector by the inverse of the translation part of this matrix.
void inverseTranslateVect( vector3df& vect ) const; 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; 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; void rotateVect( vector3df& vect ) const;
//! An alternate transform vector method, writing into a second vector //! An alternate transform vector method, writing into a second vector

View File

@ -28,16 +28,16 @@ CCameraSceneNode::CCameraSceneNode(ISceneNode* parent, ISceneManager* mgr, s32 i
// set default projection // set default projection
Fovy = core::PI / 2.5f; // Field of view, in radians. 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; const video::IVideoDriver* const d = mgr?mgr->getVideoDriver():0;
if (d) if (d)
{ {
Aspect = (f32)d->getCurrentRenderTargetSize().Width / if ( d->getCurrentRenderTargetSize().Height )
(f32)d->getCurrentRenderTargetSize().Height; Aspect = (f32)d->getCurrentRenderTargetSize().Width /
(f32)d->getCurrentRenderTargetSize().Height;
HasD3DStyleProjectionMatrix = d->getDriverType() != video::EDT_OPENGL; HasD3DStyleProjectionMatrix = d->getDriverType() != video::EDT_OPENGL;
} }
else
Aspect = 4.0f / 3.0f; // Aspect ratio.
ViewArea.setFarNearDistance(ZFar - ZNear); ViewArea.setFarNearDistance(ZFar - ZNear);
recalculateProjectionMatrix(); recalculateProjectionMatrix();
@ -252,6 +252,7 @@ void CCameraSceneNode::OnRegisterSceneNode()
//! render //! render
void CCameraSceneNode::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(); updateMatrices();
video::IVideoDriver* driver = SceneManager->getVideoDriver(); video::IVideoDriver* driver = SceneManager->getVideoDriver();

View File

@ -1827,7 +1827,7 @@ void CColladaMeshWriter::writeMeshGeometry(const irr::core::stringc& meshname, s
if ( buffer->getPrimitiveType() != EPT_TRIANGLES ) 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; continue;
} }
@ -1865,12 +1865,16 @@ void CColladaMeshWriter::writeMeshGeometry(const irr::core::stringc& meshname, s
Writer->writeElement("p", false); 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; core::stringc strP;
strP.reserve(100); strP.reserve(100);
for (u32 p=0; p<polyCount; ++p) for (u32 p=0; p<polyCount; ++p)
{ {
// Irrlicht uses clockwise, Collada uses counter-clockwise to define front-face // Irrlicht uses clockwise, Collada uses counter-clockwise to define front-face
u32 irrIdx = buffer->getIndices()[(p*3) + 2]; u32 irrIdx = iType == video::EIT_16BIT ? idx16[p*3 + 2] : idx32[p*3 + 2];
strP = ""; strP = "";
strP += irrIdx + posIdx; strP += irrIdx + posIdx;
strP += " "; strP += " ";
@ -1884,7 +1888,7 @@ void CColladaMeshWriter::writeMeshGeometry(const irr::core::stringc& meshname, s
strP += " "; strP += " ";
} }
irrIdx = buffer->getIndices()[(p*3) + 1]; irrIdx = iType == video::EIT_16BIT ? idx16[p*3 + 1] : idx32[p*3 + 1];
strP += irrIdx + posIdx; strP += irrIdx + posIdx;
strP += " "; strP += " ";
strP += irrIdx + tCoordIdx; strP += irrIdx + tCoordIdx;
@ -1897,7 +1901,7 @@ void CColladaMeshWriter::writeMeshGeometry(const irr::core::stringc& meshname, s
strP += " "; strP += " ";
} }
irrIdx = buffer->getIndices()[(p*3) + 0]; irrIdx = iType == video::EIT_16BIT ? idx16[p*3] : idx32[p*3];
strP += irrIdx + posIdx; strP += irrIdx + posIdx;
strP += " "; strP += " ";
strP += irrIdx + tCoordIdx; strP += irrIdx + tCoordIdx;

View File

@ -3001,7 +3001,7 @@ bool CD3D9Driver::reset()
} }
else 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; return false;
} }

View File

@ -339,7 +339,7 @@ bool CGUIContextMenu::OnEvent(const SEvent& event)
case EMIE_MOUSE_MOVED: case EMIE_MOUSE_MOVED:
if (Environment->hasFocus(this)) if (Environment->hasFocus(this))
highlight(core::position2d<s32>(event.MouseInput.X, event.MouseInput.Y), true); highlight(core::position2d<s32>(event.MouseInput.X, event.MouseInput.Y), true);
return true; break;
default: default:
break; break;
} }
@ -423,7 +423,7 @@ u32 CGUIContextMenu::sendClick(const core::position2d<s32>& p)
} }
//! returns true, if an element was highligted //! returns true, if an element was highlighted
bool CGUIContextMenu::highlight(const core::position2d<s32>& p, bool canOpenSubMenu) bool CGUIContextMenu::highlight(const core::position2d<s32>& p, bool canOpenSubMenu)
{ {
if (!isEnabled()) if (!isEnabled())

View File

@ -810,7 +810,7 @@ bool CGUIEnvironment::loadGUI(const io::path& filename, IGUIElement* parent)
io::IReadFile* read = FileSystem->createAndOpenFile(filename); io::IReadFile* read = FileSystem->createAndOpenFile(filename);
if (!read) 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; return false;
} }

View File

@ -137,7 +137,7 @@ bool CImageLoaderJPG::isALoadableFileFormat(io::IReadFile* file) const
IImage* CImageLoaderJPG::loadImage(io::IReadFile* file) const IImage* CImageLoaderJPG::loadImage(io::IReadFile* file) const
{ {
#ifndef _IRR_COMPILE_WITH_LIBJPEG_ #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; return 0;
#else #else

View File

@ -99,14 +99,14 @@ IImage* CImageLoaderPng::loadImage(io::IReadFile* file) const
// Read the first few bytes of the PNG file // Read the first few bytes of the PNG file
if( file->read(buffer, 8) != 8 ) 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; return 0;
} }
// Check if it really is a PNG file // Check if it really is a PNG file
if( png_sig_cmp(buffer, 0, 8) ) 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; 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); NULL, (png_error_ptr)png_cpexcept_error, (png_error_ptr)png_cpexcept_warn);
if (!png_ptr) 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; return 0;
} }
@ -123,7 +123,7 @@ IImage* CImageLoaderPng::loadImage(io::IReadFile* file) const
png_infop info_ptr = png_create_info_struct(png_ptr); png_infop info_ptr = png_create_info_struct(png_ptr);
if (!info_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); png_destroy_read_struct(&png_ptr, NULL, NULL);
return 0; 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 png_read_info(png_ptr, info_ptr); // Read the info section of the png file
u32 Width; u32 Width=0;
u32 Height; u32 Height=0;
s32 BitDepth; s32 BitDepth=0;
s32 ColorType; s32 ColorType=0;
{ {
// Use temporary variables to avoid passing cast pointers // Use temporary variables to avoid passing cast pointers
png_uint_32 w,h; png_uint_32 w,h;
@ -158,9 +158,6 @@ IImage* CImageLoaderPng::loadImage(io::IReadFile* file) const
Height=h; 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 // Convert palette color to true color
if (ColorType==PNG_COLOR_TYPE_PALETTE) if (ColorType==PNG_COLOR_TYPE_PALETTE)
png_set_palette_to_rgb(png_ptr); png_set_palette_to_rgb(png_ptr);
@ -223,15 +220,16 @@ IImage* CImageLoaderPng::loadImage(io::IReadFile* file) const
#endif #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 // Create the image structure to be filled by png data
video::IImage* image = 0; video::IImage* image = new CImage(colorFormat, core::dimension2du(Width, Height));
if (ColorType==PNG_COLOR_TYPE_RGB_ALPHA)
image = new CImage(ECF_A8R8G8B8, core::dimension2d<u32>(Width, Height));
else
image = new CImage(ECF_R8G8B8, core::dimension2d<u32>(Width, Height));
if (!image) 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); png_destroy_read_struct(&png_ptr, NULL, NULL);
return 0; return 0;
} }
@ -240,7 +238,7 @@ IImage* CImageLoaderPng::loadImage(io::IReadFile* file) const
RowPointers = new png_bytep[Height]; RowPointers = new png_bytep[Height];
if (!RowPointers) 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); png_destroy_read_struct(&png_ptr, NULL, NULL);
delete image; delete image;
return 0; return 0;

View File

@ -80,7 +80,7 @@ IImage* CImageLoaderPSD::loadImage(io::IReadFile* file) const
if (header.mode != 3 || header.depth != 8) 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; return 0;
} }
@ -93,7 +93,7 @@ IImage* CImageLoaderPSD::loadImage(io::IReadFile* file) const
#endif #endif
if (!file->seek(l, true)) 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; return 0;
} }
@ -105,7 +105,7 @@ IImage* CImageLoaderPSD::loadImage(io::IReadFile* file) const
#endif #endif
if (!file->seek(l, true)) 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; return 0;
} }
@ -117,7 +117,7 @@ IImage* CImageLoaderPSD::loadImage(io::IReadFile* file) const
#endif #endif
if (!file->seek(l, true)) 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; return 0;
} }
@ -131,7 +131,7 @@ IImage* CImageLoaderPSD::loadImage(io::IReadFile* file) const
if (compressionType != 1 && compressionType != 0) 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; 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)) 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; break;
} }
@ -247,7 +247,7 @@ bool CImageLoaderPSD::readRLEImageData(io::IReadFile* file, const PsdHeader& hea
{ {
delete [] tmpData; delete [] tmpData;
delete [] rleCount; 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; return false;
} }
@ -263,7 +263,7 @@ bool CImageLoaderPSD::readRLEImageData(io::IReadFile* file, const PsdHeader& hea
delete [] rleCount; delete [] rleCount;
delete [] buf; delete [] buf;
delete [] tmpData; 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; return false;
} }

View File

@ -108,7 +108,7 @@ IImage* CImageLoaderTGA::loadImage(io::IReadFile* file) const
if (!IImage::checkDataSizeLimit((size_t)header.ImageWidth* header.ImageHeight * (header.PixelDepth/8))) 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; return 0;
} }

View File

@ -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); NULL, (png_error_ptr)png_cpexcept_error, (png_error_ptr)png_cpexcept_warning);
if (!png_ptr) 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; 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); png_infop info_ptr = png_create_info_struct(png_ptr);
if (!info_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); png_destroy_write_struct(&png_ptr, NULL);
return false; return false;
} }
@ -141,7 +141,7 @@ bool CImageWriterPNG::writeImage(io::IWriteFile* file, IImage* image,u32 param)
u8* tmpImage = new u8[image->getDimension().Height*lineWidth]; u8* tmpImage = new u8[image->getDimension().Height*lineWidth];
if (!tmpImage) 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); png_destroy_write_struct(&png_ptr, &info_ptr);
return false; return false;
} }
@ -175,7 +175,7 @@ bool CImageWriterPNG::writeImage(io::IWriteFile* file, IImage* image,u32 param)
u8** RowPointers = new png_bytep[image->getDimension().Height]; u8** RowPointers = new png_bytep[image->getDimension().Height];
if (!RowPointers) 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); png_destroy_write_struct(&png_ptr, &info_ptr);
delete [] tmpImage; delete [] tmpImage;
return false; return false;

View File

@ -306,8 +306,8 @@ bool CIrrDeviceLinux::switchToFullscreen(bool reset)
if (bestMode != -1) if (bestMode != -1)
{ {
os::Printer::log("Starting vidmode fullscreen mode...", ELL_INFORMATION); 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("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("vdisplay", core::stringc(modes[bestMode]->vdisplay).c_str(), ELL_INFORMATION);
XF86VidModeSwitchToMode(XDisplay, Screennr, modes[bestMode]); XF86VidModeSwitchToMode(XDisplay, Screennr, modes[bestMode]);
XF86VidModeSetViewPort(XDisplay, Screennr, 0, 0); XF86VidModeSetViewPort(XDisplay, Screennr, 0, 0);
@ -343,8 +343,8 @@ bool CIrrDeviceLinux::switchToFullscreen(bool reset)
if (bestMode != -1) if (bestMode != -1)
{ {
os::Printer::log("Starting randr fullscreen mode...", ELL_INFORMATION); 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("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("height", core::stringc(modes[bestMode].height).c_str(), ELL_INFORMATION);
XRRSetScreenConfig(XDisplay,config,DefaultRootWindow(XDisplay),bestMode,OldRandrRotation,CurrentTime); XRRSetScreenConfig(XDisplay,config,DefaultRootWindow(XDisplay),bestMode,OldRandrRotation,CurrentTime);
UseXRandR=true; UseXRandR=true;
@ -367,26 +367,26 @@ void IrrPrintXGrabError(int grabResult, const c8 * grabCommand )
{ {
if ( grabResult == GrabSuccess ) if ( grabResult == GrabSuccess )
{ {
// os::Printer::log(grabCommand, ": GrabSuccess", ELL_INFORMATION); // os::Printer::log(grabCommand, "GrabSuccess", ELL_INFORMATION);
return; return;
} }
switch ( grabResult ) switch ( grabResult )
{ {
case AlreadyGrabbed: case AlreadyGrabbed:
os::Printer::log(grabCommand, ": AlreadyGrabbed", ELL_WARNING); os::Printer::log(grabCommand, "AlreadyGrabbed", ELL_WARNING);
break; break;
case GrabNotViewable: case GrabNotViewable:
os::Printer::log(grabCommand, ": GrabNotViewable", ELL_WARNING); os::Printer::log(grabCommand, "GrabNotViewable", ELL_WARNING);
break; break;
case GrabFrozen: case GrabFrozen:
os::Printer::log(grabCommand, ": GrabFrozen", ELL_WARNING); os::Printer::log(grabCommand, "GrabFrozen", ELL_WARNING);
break; break;
case GrabInvalidTime: case GrabInvalidTime:
os::Printer::log(grabCommand, ": GrabInvalidTime", ELL_WARNING); os::Printer::log(grabCommand, "GrabInvalidTime", ELL_WARNING);
break; break;
default: default:
os::Printer::log(grabCommand, ": grab failed with unknown problem", ELL_WARNING); os::Printer::log(grabCommand, "grab failed with unknown problem", ELL_WARNING);
break; break;
} }
} }
@ -455,7 +455,7 @@ bool CIrrDeviceLinux::createWindow()
} }
#ifdef _DEBUG #ifdef _DEBUG
else else
os::Printer::log("Visual chosen: ", core::stringc(static_cast<u32>(VisualInfo->visualid)).c_str(), ELL_DEBUG); os::Printer::log("Visual chosen", core::stringc(static_cast<u32>(VisualInfo->visualid)).c_str(), ELL_DEBUG);
#endif #endif
// create color map // create color map
@ -1993,7 +1993,7 @@ Bool PredicateIsEventType(Display *display, XEvent *event, XPointer arg)
{ {
if ( event && event->type == *(int*)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 True;
} }
return False; return False;

View File

@ -203,7 +203,7 @@ CIrrDeviceSDL::CIrrDeviceSDL(const SIrrlichtCreationParameters& param)
#endif #endif
SDL_INIT_NOPARACHUTE ) < 0) SDL_INIT_NOPARACHUTE ) < 0)
{ {
os::Printer::log( "Unable to initialize SDL!", SDL_GetError()); os::Printer::log("Unable to initialize SDL!", SDL_GetError());
Close = true; Close = true;
} }
else else
@ -429,7 +429,7 @@ bool CIrrDeviceSDL::createWindow()
} }
if ( !Screen ) if ( !Screen )
{ {
os::Printer::log( "Could not initialize display!" ); os::Printer::log("Could not initialize display!" );
return false; return false;
} }
@ -618,7 +618,7 @@ bool CIrrDeviceSDL::run()
else else
{ {
irrevent.MouseInput.Event = irr::EMIE_RMOUSE_LEFT_UP; irrevent.MouseInput.Event = irr::EMIE_RMOUSE_LEFT_UP;
MouseButtonStates &= !irr::EMBSM_RIGHT; MouseButtonStates &= ~irr::EMBSM_RIGHT;
} }
break; break;
@ -631,7 +631,7 @@ bool CIrrDeviceSDL::run()
else else
{ {
irrevent.MouseInput.Event = irr::EMIE_MMOUSE_LEFT_UP; irrevent.MouseInput.Event = irr::EMIE_MMOUSE_LEFT_UP;
MouseButtonStates &= !irr::EMBSM_MIDDLE; MouseButtonStates &= ~irr::EMBSM_MIDDLE;
} }
break; break;

View File

@ -153,6 +153,8 @@ namespace irr
virtual void setPosition(s32 x, s32 y) IRR_OVERRIDE virtual void setPosition(s32 x, s32 y) IRR_OVERRIDE
{ {
SDL_WarpMouse( x, y ); SDL_WarpMouse( x, y );
CursorPos.X = x;
CursorPos.Y = y;
} }
//! Returns the current position of the mouse cursor. //! Returns the current position of the mouse cursor.
@ -200,15 +202,6 @@ namespace irr
#else #else
CursorPos.X = Device->MouseX; CursorPos.X = Device->MouseX;
CursorPos.Y = Device->MouseY; 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 #endif
} }

View File

@ -458,7 +458,7 @@ void CIrrMeshFileLoader::skipSection(io::IXMLReader* reader, bool reportSkipping
{ {
#ifdef _DEBUG #ifdef _DEBUG
if (reportSkipping) 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 #endif
++tagCounter; ++tagCounter;

View File

@ -1945,7 +1945,7 @@ void CLWOMeshFileLoader::readMat(u32 size)
default: default:
{ {
#ifdef LWO_READER_DEBUG #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 #endif
File->seek(subsize, true); File->seek(subsize, true);
size -= subsize; size -= subsize;

View File

@ -199,7 +199,7 @@ bool CMD2MeshFileLoader::loadFile(io::IReadFile* file, CAnimatedMeshMD2* mesh)
if (!file->read(textureCoords, sizeof(SMD2TextureCoordinate)*header.numTexcoords)) if (!file->read(textureCoords, sizeof(SMD2TextureCoordinate)*header.numTexcoords))
{ {
delete[] textureCoords; 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; return false;
} }
@ -221,7 +221,7 @@ bool CMD2MeshFileLoader::loadFile(io::IReadFile* file, CAnimatedMeshMD2* mesh)
delete[] triangles; delete[] triangles;
delete[] textureCoords; 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; return false;
} }

View File

@ -242,7 +242,7 @@ bool CMS3DMeshFileLoader::load(io::IReadFile* file)
if (pPtr + ((sizeof(MS3DVertex) - MS3DVERTEX_NUM_PAD_BYTES) * numVertices) > buffer+fileSize) if (pPtr + ((sizeof(MS3DVertex) - MS3DVERTEX_NUM_PAD_BYTES) * numVertices) > buffer+fileSize)
{ {
delete [] buffer; 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; return false;
} }
for (u16 tmp=0; tmp<numVertices; ++tmp) for (u16 tmp=0; tmp<numVertices; ++tmp)
@ -273,7 +273,7 @@ bool CMS3DMeshFileLoader::load(io::IReadFile* file)
if (pPtr + ((sizeof(MS3DTriangle) - MS3DTRIANGLE_NUM_PAD_BYTES) * numTriangles) > buffer+fileSize) if (pPtr + ((sizeof(MS3DTriangle) - MS3DTRIANGLE_NUM_PAD_BYTES) * numTriangles) > buffer+fileSize)
{ {
delete [] buffer; 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; return false;
} }
for (u16 tmp=0; tmp<numTriangles; ++tmp) for (u16 tmp=0; tmp<numTriangles; ++tmp)
@ -349,7 +349,7 @@ bool CMS3DMeshFileLoader::load(io::IReadFile* file)
if (pPtr > buffer+fileSize) if (pPtr > buffer+fileSize)
{ {
delete [] buffer; 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; return false;
} }
} }
@ -390,7 +390,7 @@ bool CMS3DMeshFileLoader::load(io::IReadFile* file)
if (pPtr > buffer+fileSize) if (pPtr > buffer+fileSize)
{ {
delete [] buffer; 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; return false;
} }
@ -452,7 +452,7 @@ bool CMS3DMeshFileLoader::load(io::IReadFile* file)
if (pPtr > buffer+fileSize) if (pPtr > buffer+fileSize)
{ {
delete [] buffer; 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; return false;
} }
@ -479,7 +479,7 @@ bool CMS3DMeshFileLoader::load(io::IReadFile* file)
if (pPtr > buffer+fileSize) if (pPtr > buffer+fileSize)
{ {
delete [] buffer; 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; return false;
} }
@ -529,7 +529,7 @@ bool CMS3DMeshFileLoader::load(io::IReadFile* file)
if (pPtr > buffer+fileSize) if (pPtr > buffer+fileSize)
{ {
delete [] buffer; 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; return false;
} }
@ -569,7 +569,7 @@ bool CMS3DMeshFileLoader::load(io::IReadFile* file)
if (pPtr > buffer+fileSize) if (pPtr > buffer+fileSize)
{ {
delete [] buffer; 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; return false;
} }
@ -625,7 +625,7 @@ bool CMS3DMeshFileLoader::load(io::IReadFile* file)
if (pPtr > buffer+fileSize) if (pPtr > buffer+fileSize)
{ {
delete [] buffer; 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; return false;
} }
} }
@ -657,7 +657,7 @@ bool CMS3DMeshFileLoader::load(io::IReadFile* file)
if (pPtr > buffer+fileSize) if (pPtr > buffer+fileSize)
{ {
delete [] buffer; 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; return false;
} }
} }

View File

@ -708,38 +708,45 @@ IMesh* CMeshManipulator::createMeshUniquePrimitives(IMesh* mesh) const
// not yet 32bit // not yet 32bit
IMesh* CMeshManipulator::createMeshWelded(IMesh *mesh, f32 tolerance) const IMesh* CMeshManipulator::createMeshWelded(IMesh *mesh, f32 tolerance) const
{ {
SMesh* clone = new SMesh(); SMesh* meshClone = new SMesh();
clone->BoundingBox = mesh->getBoundingBox(); meshClone->BoundingBox = mesh->getBoundingBox();
core::array<u16> redirects; core::array<u16> redirects;
for (u32 b=0; b<mesh->getMeshBufferCount(); ++b) for (u32 b=0; b<mesh->getMeshBufferCount(); ++b)
{ {
const IMeshBuffer* const mb = mesh->getMeshBuffer(b); const IMeshBuffer* const mb = mesh->getMeshBuffer(b);
const u32 vertexCount = mb->getVertexCount();
// reset redirect list // reset redirect list
redirects.set_used(mb->getVertexCount()); redirects.set_used(vertexCount);
const u16* indices = 0; const video::E_INDEX_TYPE indexType = mb->getIndexType();
u32 indexCount = 0; const u16* indices = mb->getIndices();
const u32 indexCount = mb->getIndexCount();
core::array<u16>* outIdx = 0; core::array<u16>* 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()) switch(mb->getVertexType())
{ {
case video::EVT_STANDARD: case video::EVT_STANDARD:
{ {
SMeshBuffer* buffer = new SMeshBuffer(); SMeshBuffer* buffer = new SMeshBuffer();
buffer->BoundingBox = mb->getBoundingBox(); buffer->setBoundingBox(mb->getBoundingBox());
buffer->Material = mb->getMaterial(); buffer->Material = mb->getMaterial();
clone->addMeshBuffer(buffer); meshClone->addMeshBuffer(buffer);
buffer->drop(); buffer->drop();
video::S3DVertex* v = video::S3DVertex* v = (video::S3DVertex*)mb->getVertices();
(video::S3DVertex*)mb->getVertices();
u32 vertexCount = mb->getVertexCount();
indices = mb->getIndices();
indexCount = mb->getIndexCount();
outIdx = &buffer->Indices; outIdx = &buffer->Indices;
buffer->Vertices.reallocate(vertexCount); buffer->Vertices.reallocate(vertexCount);
@ -771,18 +778,14 @@ IMesh* CMeshManipulator::createMeshWelded(IMesh *mesh, f32 tolerance) const
case video::EVT_2TCOORDS: case video::EVT_2TCOORDS:
{ {
SMeshBufferLightMap* buffer = new SMeshBufferLightMap(); SMeshBufferLightMap* buffer = new SMeshBufferLightMap();
buffer->BoundingBox = mb->getBoundingBox(); buffer->setBoundingBox(mb->getBoundingBox());
buffer->Material = mb->getMaterial(); buffer->Material = mb->getMaterial();
clone->addMeshBuffer(buffer); meshClone->addMeshBuffer(buffer);
buffer->drop(); buffer->drop();
video::S3DVertex2TCoords* v = video::S3DVertex2TCoords* v =
(video::S3DVertex2TCoords*)mb->getVertices(); (video::S3DVertex2TCoords*)mb->getVertices();
u32 vertexCount = mb->getVertexCount();
indices = mb->getIndices();
indexCount = mb->getIndexCount();
outIdx = &buffer->Indices; outIdx = &buffer->Indices;
buffer->Vertices.reallocate(vertexCount); buffer->Vertices.reallocate(vertexCount);
@ -814,18 +817,13 @@ IMesh* CMeshManipulator::createMeshWelded(IMesh *mesh, f32 tolerance) const
case video::EVT_TANGENTS: case video::EVT_TANGENTS:
{ {
SMeshBufferTangents* buffer = new SMeshBufferTangents(); SMeshBufferTangents* buffer = new SMeshBufferTangents();
buffer->BoundingBox = mb->getBoundingBox(); buffer->setBoundingBox(mb->getBoundingBox());
buffer->Material = mb->getMaterial(); buffer->Material = mb->getMaterial();
clone->addMeshBuffer(buffer); meshClone->addMeshBuffer(buffer);
buffer->drop(); buffer->drop();
video::S3DVertexTangents* v = video::S3DVertexTangents* v = (video::S3DVertexTangents*)mb->getVertices();
(video::S3DVertexTangents*)mb->getVertices();
u32 vertexCount = mb->getVertexCount();
indices = mb->getIndices();
indexCount = mb->getIndexCount();
outIdx = &buffer->Indices; outIdx = &buffer->Indices;
buffer->Vertices.reallocate(vertexCount); buffer->Vertices.reallocate(vertexCount);
@ -860,7 +858,7 @@ IMesh* CMeshManipulator::createMeshWelded(IMesh *mesh, f32 tolerance) const
break; break;
} }
// Clean up any degenerate tris // set indices for new buffer
core::array<u16> &Indices = *outIdx; core::array<u16> &Indices = *outIdx;
Indices.clear(); Indices.clear();
Indices.reallocate(indexCount); Indices.reallocate(indexCount);
@ -873,6 +871,7 @@ IMesh* CMeshManipulator::createMeshWelded(IMesh *mesh, f32 tolerance) const
bool drop = false; bool drop = false;
// Clean up any degenerate tris
if (a == b || b == c || a == c) if (a == b || b == c || a == c)
drop = true; drop = true;
@ -885,8 +884,9 @@ IMesh* CMeshManipulator::createMeshWelded(IMesh *mesh, f32 tolerance) const
Indices.push_back(c); Indices.push_back(c);
} }
} }
// indexCount-Indices.size() vertices got welded for this meshbuffer
} }
return clone; return meshClone;
} }

View File

@ -250,7 +250,7 @@ IAnimatedMesh* COBJMeshFileLoader::createMesh(io::IReadFile* file)
v.Pos = vertexBuffer[Idx[0]]; v.Pos = vertexBuffer[Idx[0]];
else 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; delete [] buf;
return 0; return 0;
} }

View File

@ -112,7 +112,7 @@ bool CQ3LevelMesh::loadFile(io::IReadFile* file)
( header.strID != 0x50534252 || header.version != 1 ) // RBSP, starwars jedi, sof ( 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; return false;
} }

View File

@ -438,7 +438,7 @@ IAnimatedMesh* CSceneManager::getMesh(const io::path& filename, const io::path&
io::IReadFile* file = FileSystem->createAndOpenFile(filename); io::IReadFile* file = FileSystem->createAndOpenFile(filename);
if (!file) 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; return 0;
} }
@ -2377,7 +2377,7 @@ bool CSceneManager::loadScene(io::IReadFile* file, ISceneUserDataSerializer* use
ret = SceneLoaderList[i]->loadScene(file, userDataSerializer, rootNode); ret = SceneLoaderList[i]->loadScene(file, userDataSerializer, rootNode);
if (!ret) 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; return ret;
} }

View File

@ -117,7 +117,6 @@ void CSceneNodeAnimatorCameraFPS::animateNode(ISceneNode* node, u32 timeMs)
if (firstUpdate) if (firstUpdate)
{ {
camera->updateAbsolutePosition();
if (CursorControl ) if (CursorControl )
{ {
CursorControl->setPosition(0.5f, 0.5f); CursorControl->setPosition(0.5f, 0.5f);
@ -151,6 +150,7 @@ void CSceneNodeAnimatorCameraFPS::animateNode(ISceneNode* node, u32 timeMs)
LastAnimationTime = timeMs; LastAnimationTime = timeMs;
// Update rotation // Update rotation
camera->updateAbsolutePosition();
core::vector3df target = (camera->getTarget() - camera->getAbsolutePosition()); core::vector3df target = (camera->getTarget() - camera->getAbsolutePosition());
core::vector3df relativeRotation = target.getHorizontalAngle(); core::vector3df relativeRotation = target.getHorizontalAngle();

View File

@ -1104,27 +1104,27 @@ void CSkinnedMesh::finalize()
if ( redundantPosKeys > 0 ) 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 ) 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 ) 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 ) 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 ) 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 ) 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);
} }
} }

View File

@ -265,7 +265,7 @@ namespace scene
{ {
if ((filesize-file->getPos())/bytesPerPixel>(size_t)(width*width)) 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; return false;
} }
TerrainData.Size = width; TerrainData.Size = width;

View File

@ -463,7 +463,7 @@ bool CWGLManager::activateContext(const SExposedVideoData& videoData, bool resto
{ {
if (!wglMakeCurrent((HDC)PrimaryContext.OpenGLWin32.HDc, (HGLRC)PrimaryContext.OpenGLWin32.HRc)) 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; return false;
} }
CurrentContext=PrimaryContext; CurrentContext=PrimaryContext;

View File

@ -491,7 +491,7 @@ bool CXMeshFileLoader::parseDataObject()
// parse specific object // parse specific object
#ifdef _XREADER_DEBUG #ifdef _XREADER_DEBUG
os::Printer::log("debug DataObject:", objectName.c_str(), ELL_DEBUG); os::Printer::log("debug DataObject", objectName.c_str(), ELL_DEBUG);
#endif #endif
if (objectName == "template") if (objectName == "template")
@ -848,7 +848,7 @@ bool CXMeshFileLoader::parseDataObjectMesh(SXMesh &mesh)
} }
#ifdef _XREADER_DEBUG #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 #endif
if (objectName == "MeshNormals") if (objectName == "MeshNormals")

View File

@ -39,6 +39,8 @@ namespace os
static void print(const c8* message, ELOG_LEVEL ll = ELL_INFORMATION); 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 c8* message, ELOG_LEVEL ll = ELL_INFORMATION);
static void log(const wchar_t* 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 c8* hint, ELOG_LEVEL ll = ELL_INFORMATION);
static void log(const c8* message, const io::path& hint, ELOG_LEVEL ll = ELL_INFORMATION); static void log(const c8* message, const io::path& hint, ELOG_LEVEL ll = ELL_INFORMATION);
static ILogger* Logger; static ILogger* Logger;

View File

@ -1,4 +1,4 @@
Tests finished. 72 tests of 72 passed. Tests finished. 72 tests of 72 passed.
Compiled as DEBUG Compiled as DEBUG
Test suite pass at GMT Sat May 14 18:16:57 2022 Test suite pass at GMT Thu Sep 15 20:10:06 2022