Merging r6288 through r6336 from trunk to ogl-es branch

git-svn-id: svn://svn.code.sf.net/p/irrlicht/code/branches/ogl-es@6337 dfc29bdd-3216-0410-991c-e03cc46cb475
This commit is contained in:
cutealien 2022-04-15 18:51:09 +00:00
parent 67469c8899
commit 2d63fdba3d
115 changed files with 1828 additions and 1154 deletions

@ -9,6 +9,18 @@ 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)
- Add IMeshBufffer::clone function to create buffer copies. CMeshManipulator::createMeshCopy uses that now and works now with all types of meshbuffers.
- obj writer can now write 32 bit buffers
- obj meshloader can now load 32 bit buffers when setPreferredIndexType is set to EIT_32BIT.
It's 16 bit meshes use now also an IDynamicMeshbuffer instead of an SMeshBuffer.
- Add IMeshLoader::setPreferredIndexType and getPreferredIndexType to allow setting hints for the loaders if users prefer 16 or 32 bit meshbuffers.
- Add IMeshBuffer::getType to allow finding out which class type a meshbuffer has (similar to ISceneNode::getType).
- Add IGUIImage::flip to flip/mirror images
- IBillboardSceneNode got functions to access meshbuffers. So uv-coordinates can now be modified directly (previously only possible via texture matrix).
- vector3d scalar operator/ and operator/= no longer multiply by the inverse but use the expected division.
Costs some speed, but fixes floating point troubles caused by this optimization (like x/x no longer being 1.0).
- Bugfix: XML reader dropped last character in strings if there was a special character replacement for the second-last character.
- Avoid allocating more than 16k on stack in OCT loader. Also avoid potential heap overwrites in there.
- obj file loader now allows using mtl files with spaces in the filename. - obj file loader now allows using mtl files with spaces in the filename.
Note that this means it no longer handles obj files which have multiple mtl files behind the mtllib command. Note that this means it no longer handles obj files which have multiple mtl files behind the mtllib command.
But Irrlicht ignored all but the first name anyway and this way of handling mtllib commands seems to be more common. But Irrlicht ignored all but the first name anyway and this way of handling mtllib commands seems to be more common.

@ -12,7 +12,7 @@ IrrlichtHome := ../..
BinPath = ../../bin/$(SYSTEM) BinPath = ../../bin/$(SYSTEM)
# general compiler settings (might need to be set when compiling the lib, too) # general compiler settings (might need to be set when compiling the lib, too)
CPPFLAGS += -I$(IrrlichtHome)/include -I/usr/X11R6/include CPPFLAGS += -I$(IrrlichtHome)/include
ifndef NDEBUG ifndef NDEBUG
CXXFLAGS += -g -Wall CXXFLAGS += -g -Wall
else else

@ -12,7 +12,7 @@ IrrlichtHome := ../..
BinPath = ../../bin/$(SYSTEM) BinPath = ../../bin/$(SYSTEM)
# general compiler settings (might need to be set when compiling the lib, too) # general compiler settings (might need to be set when compiling the lib, too)
CPPFLAGS += -I$(IrrlichtHome)/include -I/usr/X11R6/include CPPFLAGS += -I$(IrrlichtHome)/include
ifndef NDEBUG ifndef NDEBUG
CXXFLAGS += -g -Wall CXXFLAGS += -g -Wall
else else

@ -12,7 +12,7 @@ IrrlichtHome := ../..
BinPath = ../../bin/$(SYSTEM) BinPath = ../../bin/$(SYSTEM)
# general compiler settings (might need to be set when compiling the lib, too) # general compiler settings (might need to be set when compiling the lib, too)
CPPFLAGS += -I$(IrrlichtHome)/include -I/usr/X11R6/include CPPFLAGS += -I$(IrrlichtHome)/include
ifndef NDEBUG ifndef NDEBUG
CXXFLAGS += -g -Wall CXXFLAGS += -g -Wall
else else

@ -12,7 +12,7 @@ IrrlichtHome := ../..
BinPath = ../../bin/$(SYSTEM) BinPath = ../../bin/$(SYSTEM)
# general compiler settings (might need to be set when compiling the lib, too) # general compiler settings (might need to be set when compiling the lib, too)
CPPFLAGS += -I$(IrrlichtHome)/include -I/usr/X11R6/include CPPFLAGS += -I$(IrrlichtHome)/include
ifndef NDEBUG ifndef NDEBUG
CXXFLAGS += -g -Wall CXXFLAGS += -g -Wall
else else

@ -215,6 +215,8 @@ int main()
const f32 frameDeltaTime = (f32)(now - then) / 1000.f; // Time in seconds const f32 frameDeltaTime = (f32)(now - then) / 1000.f; // Time in seconds
then = now; then = now;
if ( sphereNode )
{
/* Check if keys W, S, A or D are being held down, and move the /* Check if keys W, S, A or D are being held down, and move the
sphere node around respectively. */ sphere node around respectively. */
core::vector3df nodePosition = sphereNode->getPosition(); core::vector3df nodePosition = sphereNode->getPosition();
@ -230,6 +232,7 @@ int main()
nodePosition.X += MOVEMENT_SPEED * frameDeltaTime; nodePosition.X += MOVEMENT_SPEED * frameDeltaTime;
sphereNode->setPosition(nodePosition); sphereNode->setPosition(nodePosition);
}
driver->beginScene(video::ECBF_COLOR | video::ECBF_DEPTH, video::SColor(255,113,113,133)); driver->beginScene(video::ECBF_COLOR | video::ECBF_DEPTH, video::SColor(255,113,113,133));

@ -12,7 +12,7 @@ IrrlichtHome := ../..
BinPath = ../../bin/$(SYSTEM) BinPath = ../../bin/$(SYSTEM)
# general compiler settings (might need to be set when compiling the lib, too) # general compiler settings (might need to be set when compiling the lib, too)
CPPFLAGS += -I$(IrrlichtHome)/include -I/usr/X11R6/include CPPFLAGS += -I$(IrrlichtHome)/include
ifndef NDEBUG ifndef NDEBUG
CXXFLAGS += -g -Wall CXXFLAGS += -g -Wall
else else

@ -12,7 +12,7 @@ IrrlichtHome := ../..
BinPath = ../../bin/$(SYSTEM) BinPath = ../../bin/$(SYSTEM)
# general compiler settings (might need to be set when compiling the lib, too) # general compiler settings (might need to be set when compiling the lib, too)
CPPFLAGS += -I$(IrrlichtHome)/include -I/usr/X11R6/include CPPFLAGS += -I$(IrrlichtHome)/include
ifndef NDEBUG ifndef NDEBUG
CXXFLAGS += -g -Wall CXXFLAGS += -g -Wall
else else

@ -12,7 +12,7 @@ IrrlichtHome := ../..
BinPath = ../../bin/$(SYSTEM) BinPath = ../../bin/$(SYSTEM)
# general compiler settings (might need to be set when compiling the lib, too) # general compiler settings (might need to be set when compiling the lib, too)
CPPFLAGS += -I$(IrrlichtHome)/include -I/usr/X11R6/include CPPFLAGS += -I$(IrrlichtHome)/include
ifndef NDEBUG ifndef NDEBUG
CXXFLAGS += -g -Wall CXXFLAGS += -g -Wall
else else

@ -12,7 +12,7 @@ IrrlichtHome := ../..
BinPath = ../../bin/$(SYSTEM) BinPath = ../../bin/$(SYSTEM)
# general compiler settings (might need to be set when compiling the lib, too) # general compiler settings (might need to be set when compiling the lib, too)
CPPFLAGS += -I$(IrrlichtHome)/include -I/usr/X11R6/include CPPFLAGS += -I$(IrrlichtHome)/include
ifndef NDEBUG ifndef NDEBUG
CXXFLAGS += -g -Wall CXXFLAGS += -g -Wall
else else

@ -12,7 +12,7 @@ IrrlichtHome := ../..
BinPath = ../../bin/$(SYSTEM) BinPath = ../../bin/$(SYSTEM)
# general compiler settings (might need to be set when compiling the lib, too) # general compiler settings (might need to be set when compiling the lib, too)
CPPFLAGS += -I$(IrrlichtHome)/include -I/usr/X11R6/include CPPFLAGS += -I$(IrrlichtHome)/include
ifndef NDEBUG ifndef NDEBUG
CXXFLAGS += -g -Wall CXXFLAGS += -g -Wall
else else

@ -12,7 +12,7 @@ IrrlichtHome := ../..
BinPath = ../../bin/$(SYSTEM) BinPath = ../../bin/$(SYSTEM)
# general compiler settings (might need to be set when compiling the lib, too) # general compiler settings (might need to be set when compiling the lib, too)
CPPFLAGS += -I$(IrrlichtHome)/include -I/usr/X11R6/include CPPFLAGS += -I$(IrrlichtHome)/include
ifndef NDEBUG ifndef NDEBUG
CXXFLAGS += -g -Wall CXXFLAGS += -g -Wall
else else

@ -12,7 +12,7 @@ IrrlichtHome := ../..
BinPath = ../../bin/$(SYSTEM) BinPath = ../../bin/$(SYSTEM)
# general compiler settings (might need to be set when compiling the lib, too) # general compiler settings (might need to be set when compiling the lib, too)
CPPFLAGS += -I$(IrrlichtHome)/include -I/usr/X11R6/include CPPFLAGS += -I$(IrrlichtHome)/include
ifndef NDEBUG ifndef NDEBUG
CXXFLAGS += -g -Wall CXXFLAGS += -g -Wall
else else

@ -12,7 +12,7 @@ IrrlichtHome := ../..
BinPath = ../../bin/$(SYSTEM) BinPath = ../../bin/$(SYSTEM)
# general compiler settings (might need to be set when compiling the lib, too) # general compiler settings (might need to be set when compiling the lib, too)
CPPFLAGS += -I$(IrrlichtHome)/include -I/usr/X11R6/include CPPFLAGS += -I$(IrrlichtHome)/include
ifndef NDEBUG ifndef NDEBUG
CXXFLAGS += -g -Wall CXXFLAGS += -g -Wall
else else

@ -12,7 +12,7 @@ IrrlichtHome := ../..
BinPath = ../../bin/$(SYSTEM) BinPath = ../../bin/$(SYSTEM)
# general compiler settings (might need to be set when compiling the lib, too) # general compiler settings (might need to be set when compiling the lib, too)
CPPFLAGS += -I$(IrrlichtHome)/include -I/usr/X11R6/include CPPFLAGS += -I$(IrrlichtHome)/include
ifndef NDEBUG ifndef NDEBUG
CXXFLAGS += -g -Wall CXXFLAGS += -g -Wall
else else

@ -12,7 +12,7 @@ IrrlichtHome := ../..
BinPath = ../../bin/$(SYSTEM) BinPath = ../../bin/$(SYSTEM)
# general compiler settings (might need to be set when compiling the lib, too) # general compiler settings (might need to be set when compiling the lib, too)
CPPFLAGS += -I$(IrrlichtHome)/include -I/usr/X11R6/include CPPFLAGS += -I$(IrrlichtHome)/include
ifndef NDEBUG ifndef NDEBUG
CXXFLAGS += -g -Wall CXXFLAGS += -g -Wall
else else

@ -1,19 +1,15 @@
/** Example 014 Win32 Window /** Example 014 Win32 Window
This example only runs under MS Windows and demonstrates that Irrlicht can This example runs only under MS Windows and demonstrates how Irrlicht can
render inside a win32 window. MFC and .NET Windows.Forms windows are possible, render inside a win32 window. MFC and .NET Windows.Forms windows are possible,
too. too.*/
In the beginning, we create a windows window using the windows API. I'm not
going to explain this code, because it is windows specific. See the MSDN or a
windows book for details.
*/
#include <irrlicht.h> #include <irrlicht.h>
#ifndef _IRR_WINDOWS_ #ifndef _IRR_WINDOWS_
#error Windows only example #error Windows only example
#else #else
#include <windows.h> // this example only runs with windows #include <windows.h> // this example only runs with Windows
#include <iostream> #include <iostream>
#include "driverChoice.h" #include "driverChoice.h"
#include "exampleHelper.h" #include "exampleHelper.h"
@ -24,9 +20,11 @@ using namespace irr;
#pragma comment(lib, "irrlicht.lib") #pragma comment(lib, "irrlicht.lib")
#endif #endif
HWND hOKButton; HWND hOKButton = 0;
HWND hWnd;
/*
Windows message handler
*/
static LRESULT CALLBACK CustomWndProc(HWND hWnd, UINT message, static LRESULT CALLBACK CustomWndProc(HWND hWnd, UINT message,
WPARAM wParam, LPARAM lParam) WPARAM wParam, LPARAM lParam)
{ {
@ -54,13 +52,11 @@ static LRESULT CALLBACK CustomWndProc(HWND hWnd, UINT message,
return DefWindowProc(hWnd, message, wParam, lParam); return DefWindowProc(hWnd, message, wParam, lParam);
} }
/*
Now ask for the driver and create the Windows specific window.
*/
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;
@ -76,9 +72,13 @@ int main()
if (key != 'a' && key != 'b' && key != 'c') if (key != 'a' && key != 'b' && key != 'c')
return 1; return 1;
HINSTANCE hInstance = 0; /*
// create dialog Create the Windows specific window using the Windows API.
Not further explained here, please see the MSDN or a Windows book
for details about doing that.
*/
HINSTANCE hInstance = 0;
const fschar_t* Win32ClassName = __TEXT("CIrrlichtWindowsTestDialog"); const fschar_t* Win32ClassName = __TEXT("CIrrlichtWindowsTestDialog");
WNDCLASSEX wcex; WNDCLASSEX wcex;
@ -103,7 +103,7 @@ int main()
int windowWidth = 440; int windowWidth = 440;
int windowHeight = 380; int windowHeight = 380;
hWnd = CreateWindow( Win32ClassName, __TEXT("Irrlicht Win32 window example"), HWND hWnd = CreateWindow( Win32ClassName, __TEXT("Irrlicht Win32 window example"),
style, 100, 100, windowWidth, windowHeight, style, 100, 100, windowWidth, windowHeight,
NULL, NULL, hInstance, NULL); NULL, NULL, hInstance, NULL);
@ -112,45 +112,54 @@ int main()
windowWidth = clientRect.right; windowWidth = clientRect.right;
windowHeight = clientRect.bottom; windowHeight = clientRect.bottom;
// create ok button // Create OK button
hOKButton = CreateWindow(__TEXT("BUTTON"), __TEXT("OK - Close"), WS_CHILD | WS_VISIBLE | BS_TEXT, hOKButton = CreateWindow(__TEXT("BUTTON"), __TEXT("OK - Close"), WS_CHILD | WS_VISIBLE | BS_TEXT,
windowWidth - 160, windowHeight - 40, 150, 30, hWnd, NULL, hInstance, NULL); windowWidth - 160, windowHeight - 40, 150, 30, hWnd, NULL, hInstance, NULL);
// create some text // Create some text
CreateWindow(__TEXT("STATIC"), __TEXT("This is Irrlicht running inside a standard Win32 window.\n")\ CreateWindow(__TEXT("STATIC"), __TEXT("This is Irrlicht running inside a standard Win32 window.\n")\
__TEXT("Also mixing with MFC and .NET Windows.Forms is possible."), __TEXT("Also mixing with MFC and .NET Windows.Forms is possible."),
WS_CHILD | WS_VISIBLE, 20, 20, 400, 40, hWnd, NULL, hInstance, NULL); WS_CHILD | WS_VISIBLE, 20, 20, 400, 40, hWnd, NULL, hInstance, NULL);
// create window to put irrlicht in // Create a window to put Irrlicht in
HWND hIrrlichtWindow = CreateWindow(__TEXT("BUTTON"), __TEXT(""), HWND hIrrlichtWindow = CreateWindow(__TEXT("BUTTON"), __TEXT(""),
WS_CHILD | WS_VISIBLE | BS_OWNERDRAW, WS_CHILD | WS_VISIBLE | BS_OWNERDRAW,
50, 80, 320, 220, hWnd, NULL, hInstance, NULL); 50, 80, 320, 220, hWnd, NULL, hInstance, NULL);
video::SExposedVideoData videodata((key=='b')?hIrrlichtWindow:0);
/* /*
So now that we have some window, we can create an Irrlicht device So now that we have some Windows window, we can use it with Irrlicht.
inside of it. We use Irrlicht createEx() function for this. We only There's several options.
need the handle (HWND) to that window, set it as windowsID parameter
and start up the engine as usual. That's it.
*/ */
// create irrlicht device in the button window
irr::SIrrlichtCreationParameters param; irr::SIrrlichtCreationParameters param;
param.DriverType = driverType; param.DriverType = driverType;
/* First option: We create an Irrlicht device inside of the Windows window.
We use Irrlicht createEx() function for this. We do need the
handle (HWND) for that window, set it as windowsID parameter
and start up the engine as usual. That's it.
*/
if (key=='a') if (key=='a')
param.WindowId = reinterpret_cast<void*>(hIrrlichtWindow); param.WindowId = reinterpret_cast<void*>(hIrrlichtWindow);
irr::IrrlichtDevice* device = irr::createDeviceEx(param); irr::IrrlichtDevice* device = irr::createDeviceEx(param);
// setup a simple 3d scene
irr::scene::ISceneManager* smgr = device->getSceneManager(); irr::scene::ISceneManager* smgr = device->getSceneManager();
video::IVideoDriver* driver = device->getVideoDriver(); video::IVideoDriver* driver = device->getVideoDriver();
if (driverType==video::EDT_OPENGL) /*
Second option: We create a typical Irrlicht device, but render to the Window window.
For rendering into another Window than the one used for creating the Irrlicht device
we have to pass some changed SExposedVideoData to beginScene which contains the
HWND of the Windows window.
*/
video::SExposedVideoData videodata((key=='b')?hIrrlichtWindow:0);
/*
OpenGL needs a bit more setup.
Also not yet working as well (haven't figured out yet how to render into the Irrlicht window as well)
*/
if (key == 'b' && driverType==video::EDT_OPENGL)
{ {
HDC HDc=GetDC(hIrrlichtWindow); HDC HDc=GetDC(hIrrlichtWindow);
PIXELFORMATDESCRIPTOR pfd={0}; PIXELFORMATDESCRIPTOR pfd={0};
@ -165,6 +174,10 @@ int main()
videodata.OpenGLWin32.HRc=wglCreateContext(HDc); videodata.OpenGLWin32.HRc=wglCreateContext(HDc);
wglShareLists((HGLRC)driver->getExposedVideoData().OpenGLWin32.HRc, (HGLRC)videodata.OpenGLWin32.HRc); wglShareLists((HGLRC)driver->getExposedVideoData().OpenGLWin32.HRc, (HGLRC)videodata.OpenGLWin32.HRc);
} }
/*
Setup a simple 3d scene
*/
scene::ICameraSceneNode* cam = smgr->addCameraSceneNode(); scene::ICameraSceneNode* cam = smgr->addCameraSceneNode();
cam->setTarget(core::vector3df(0,0,0)); cam->setTarget(core::vector3df(0,0,0));
@ -191,32 +204,36 @@ int main()
driver->getTexture(mediaPath + "irrlicht2_bk.jpg")); driver->getTexture(mediaPath + "irrlicht2_bk.jpg"));
// This shows that we can render to multiple windows within one application // This shows that we can render to multiple windows within one application
// TODO: Currently not working with OpenGL
device->getGUIEnvironment()->addStaticText(core::stringw("Second screen render").c_str(),core::recti(0,0,200,200)); device->getGUIEnvironment()->addStaticText(core::stringw("Second screen render").c_str(),core::recti(0,0,200,200));
// show and execute dialog // show and execute the Windows dialog
ShowWindow(hWnd , SW_SHOW); ShowWindow(hWnd , SW_SHOW);
UpdateWindow(hWnd); UpdateWindow(hWnd);
// do message queue // do message queue
#if 1 // Irrlicht does the message handling with device->run()
/* /*
Now the only thing missing is the drawing loop using Now the only thing missing is the drawing loop using
IrrlichtDevice::run(). We do this as usual. But instead of this, there IrrlichtDevice::run(). We do this as usual. But instead of this, there
is another possibility: You can also simply use your own message loop is another possibility: You can also use your own message loop
using GetMessage, DispatchMessage and whatever. Calling using GetMessage, DispatchMessage and whatever. Calling
Device->run() will cause Irrlicht to dispatch messages internally too. device->run() will cause Irrlicht to dispatch messages internally too.
You need not call Device->run() if you want to do your own message You need not call device->run() if you want to do your own message
dispatching loop, but Irrlicht will not be able to fetch user input dispatching loop, but Irrlicht will not be able to fetch user input
then and you have to do it on your own using the window messages, then and you have to do it on your own using the window messages,
DirectInput, or whatever. DirectInput, or whatever.
*/ */
while (device->run()) while (device->run())
{ {
// draw 3d scene
driver->beginScene(video::ECBF_COLOR | video::ECBF_DEPTH, video::SColor(0), 1.f, 0, videodata); driver->beginScene(video::ECBF_COLOR | video::ECBF_DEPTH, video::SColor(0), 1.f, 0, videodata);
smgr->drawAll(); smgr->drawAll();
driver->endScene(); driver->endScene();
// draw gui into second window
if (key=='b') if (key=='b')
{ {
driver->beginScene(video::ECBF_COLOR | video::ECBF_DEPTH, video::SColor(0xbbbbbbbb)); driver->beginScene(video::ECBF_COLOR | video::ECBF_DEPTH, video::SColor(0xbbbbbbbb));
@ -225,12 +242,13 @@ int main()
} }
} }
#else // Windows API does the message handling
/* /*
The alternative, own message dispatching loop without Device->run() The alternative, own message dispatching loop without Device->run()
would look like this: would look like this:
*/ */
/*MSG msg; MSG msg;
while (true) while (true)
{ {
if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
@ -245,11 +263,20 @@ int main()
// advance virtual time // advance virtual time
device->getTimer()->tick(); device->getTimer()->tick();
// draw engine picture // draw 3d scene
driver->beginScene(true, true, 0, (key=='c')?hIrrlichtWindow:0); driver->beginScene(true, true, 0, videodata);
smgr->drawAll(); smgr->drawAll();
driver->endScene(); driver->endScene();
}*/
// draw gui into second window
if (key=='b')
{
driver->beginScene(video::ECBF_COLOR | video::ECBF_DEPTH, video::SColor(0xbbbbbbbb));
device->getGUIEnvironment()->drawAll();
driver->endScene();
}
}
#endif
device->closeDevice(); device->closeDevice();
device->drop(); device->drop();
@ -259,5 +286,5 @@ int main()
#endif // if windows #endif // if windows
/* /*
That's it, Irrlicht now runs in your own windows window. That's it, Irrlicht now uses a Windows window.
**/ **/

@ -12,7 +12,7 @@ IrrlichtHome := ../..
BinPath = ../../bin/$(SYSTEM) BinPath = ../../bin/$(SYSTEM)
# general compiler settings (might need to be set when compiling the lib, too) # general compiler settings (might need to be set when compiling the lib, too)
CPPFLAGS += -I$(IrrlichtHome)/include -I/usr/X11R6/include CPPFLAGS += -I$(IrrlichtHome)/include
ifndef NDEBUG ifndef NDEBUG
CXXFLAGS += -g -Wall CXXFLAGS += -g -Wall
else else

@ -12,7 +12,7 @@ IrrlichtHome := ../..
BinPath = ../../bin/$(SYSTEM) BinPath = ../../bin/$(SYSTEM)
# general compiler settings (might need to be set when compiling the lib, too) # general compiler settings (might need to be set when compiling the lib, too)
CPPFLAGS += -I$(IrrlichtHome)/include -I/usr/X11R6/include CPPFLAGS += -I$(IrrlichtHome)/include
ifndef NDEBUG ifndef NDEBUG
CXXFLAGS += -g -Wall CXXFLAGS += -g -Wall
else else

@ -41,7 +41,7 @@ using namespace irr;
using namespace scene; using namespace scene;
/* /*
Again, to be able to use the Irrlicht.DLL file, we need to link with the Again, to be able to use the Irrlicht.dll on Windows, we link with the
Irrlicht.lib. We could set this option in the project settings, but Irrlicht.lib. We could set this option in the project settings, but
to make it easy, we use a pragma comment lib: to make it easy, we use a pragma comment lib:
*/ */
@ -66,25 +66,25 @@ public:
bool OnEvent(const SEvent& event) bool OnEvent(const SEvent& event)
{ {
// check if user presses the key F9
if ((event.EventType == EET_KEY_INPUT_EVENT) && if ((event.EventType == EET_KEY_INPUT_EVENT) &&
event.KeyInput.PressedDown) event.KeyInput.PressedDown)
{ {
// check if user presses the key F9 for making a screenshot
if (event.KeyInput.Key == KEY_F9) if (event.KeyInput.Key == KEY_F9)
{ {
video::IImage* image = Device->getVideoDriver()->createScreenShot(); video::IImage* image = Device->getVideoDriver()->createScreenShot();
if (image) if (image)
{ {
c8 buf[256]; c8 buf[256];
snprintf_irr(buf, 256, "%s_shot%04d.jpg", snprintf_irr(buf, 256, "%s_shot%04u.jpg",
FilenameTemplate.c_str(), FilenameTemplate.c_str(),
++Number); ++Number);
Device->getVideoDriver()->writeImageToFile(image, buf, 85 ); Device->getVideoDriver()->writeImageToFile(image, buf, 85 );
image->drop(); image->drop();
} }
} }
else // Check for F8 - enabling/disabling display of bounding box for the map
if (event.KeyInput.Key == KEY_F8) else if (event.KeyInput.Key == KEY_F8)
{ {
if (Node->isDebugDataVisible()) if (Node->isDebugDataVisible())
Node->setDebugDataVisible(scene::EDS_OFF); Node->setDebugDataVisible(scene::EDS_OFF);
@ -112,7 +112,7 @@ int IRRCALLCONV main(int argc, char* argv[])
/* /*
Like in the HelloWorld example, we create an IrrlichtDevice with Like in the HelloWorld example, we create an IrrlichtDevice with
createDevice(). The difference now is that we ask the user to select createDevice(). The difference now is that we ask the user to select
which hardware accelerated driver to use. The Software device would be which hardware accelerated driver to use. The Software device might be
too slow to draw a huge Quake 3 map, but just for the fun of it, we make too slow to draw a huge Quake 3 map, but just for the fun of it, we make
this decision possible too. this decision possible too.
*/ */
@ -130,6 +130,7 @@ int IRRCALLCONV main(int argc, char* argv[])
if (device == 0) if (device == 0)
return 1; // could not create selected driver. return 1; // could not create selected driver.
// We allow passing a map name as command line parameter
const char* mapname=0; const char* mapname=0;
if (argc>2) if (argc>2)
mapname = argv[2]; mapname = argv[2];
@ -170,7 +171,7 @@ int IRRCALLCONV main(int argc, char* argv[])
/* /*
Now we can load the mesh by calling getMesh(). We get a pointer returned Now we can load the mesh by calling getMesh(). We get a pointer returned
to a IAnimatedMesh. As you know, Quake 3 maps are not really animated, to an IAnimatedMesh. As you know, Quake 3 maps are not really animated,
they are only a huge chunk of static geometry with some materials they are only a huge chunk of static geometry with some materials
attached. Hence the IAnimated mesh consists of only one frame, attached. Hence the IAnimated mesh consists of only one frame,
so we get the "first frame" of the "animation", which is our quake level so we get the "first frame" of the "animation", which is our quake level
@ -203,9 +204,9 @@ int IRRCALLCONV main(int argc, char* argv[])
device->setEventReceiver(&screenshotFactory); device->setEventReceiver(&screenshotFactory);
/* /*
now construct SceneNodes for each Shader now construct SceneNodes for each shader
The Objects are stored in the quake mesh scene::E_Q3_MESH_ITEMS The objects are stored in the quake mesh scene::E_Q3_MESH_ITEMS
and the Shader ID is stored in the MaterialParameters and the shader ID is stored in the MaterialParameters
mostly dark looking skulls and moving lava.. or green flashing tubes? mostly dark looking skulls and moving lava.. or green flashing tubes?
*/ */
if ( mesh ) if ( mesh )
@ -253,9 +254,9 @@ int IRRCALLCONV main(int argc, char* argv[])
} }
/* /*
Now we only need a Camera to look at the Quake 3 map. And we want to Now we only need a camera to look at the Quake 3 map. And we want to
create a user controlled camera. There are some different cameras create a user controlled camera. There are some different cameras
available in the Irrlicht engine. For example the Maya Camera which can available in the Irrlicht engine. For example the Maya camera which can
be controlled comparable to the camera in Maya: Rotate with left mouse be controlled comparable to the camera in Maya: Rotate with left mouse
button pressed, Zoom with both buttons pressed, translate with right button pressed, Zoom with both buttons pressed, translate with right
mouse button pressed. This could be created with mouse button pressed. This could be created with
@ -266,8 +267,8 @@ int IRRCALLCONV main(int argc, char* argv[])
scene::ICameraSceneNode* camera = smgr->addCameraSceneNodeFPS(); scene::ICameraSceneNode* camera = smgr->addCameraSceneNodeFPS();
/* /*
so we need a good starting Position in the level. so we need a good starting position in the level.
we can ask the Quake3 Loader for all entities with class_name we can ask the Quake3 loader for all entities with class_name
"info_player_deathmatch" "info_player_deathmatch"
we choose a random launch we choose a random launch
*/ */
@ -356,6 +357,8 @@ int IRRCALLCONV main(int argc, char* argv[])
gui->drawAll(); gui->drawAll();
driver->endScene(); driver->endScene();
// Display some info
// Setting window caption can be rather slow, so usually shouldn't be done each frame.
int fps = driver->getFPS(); int fps = driver->getFPS();
if (1 || lastFPS != fps) if (1 || lastFPS != fps)
{ {

@ -5,7 +5,7 @@ Target = 17.HelloWorld_Mobile
Sources = main.cpp Sources = main.cpp
# general compiler settings # general compiler settings
CPPFLAGS = -I../../include -I/usr/X11R6/include CPPFLAGS = -I../../include
CXXFLAGS = -O3 -ffast-math CXXFLAGS = -O3 -ffast-math
#CXXFLAGS = -g -Wall #CXXFLAGS = -g -Wall

@ -12,7 +12,7 @@ IrrlichtHome := ../..
BinPath = ../../bin/$(SYSTEM) BinPath = ../../bin/$(SYSTEM)
# general compiler settings (might need to be set when compiling the lib, too) # general compiler settings (might need to be set when compiling the lib, too)
CPPFLAGS += -I$(IrrlichtHome)/include -I/usr/X11R6/include CPPFLAGS += -I$(IrrlichtHome)/include
ifndef NDEBUG ifndef NDEBUG
CXXFLAGS += -g -Wall CXXFLAGS += -g -Wall
else else

@ -3,10 +3,10 @@
A tutorial by Max Winkel. A tutorial by Max Winkel.
In this tutorial we'll learn how to use split screen (e.g. for racing-games) In this tutorial we'll learn how to use split screen (e.g. for racing-games)
with Irrlicht. We'll create a viewport divided with Irrlicht. We'll create a viewport divided into 4 parts, with 3 fixed
into 4 parts, with 3 fixed cameras and one user-controlled. cameras and one user-controlled.
Ok, let's start with the headers (I think there's OK, let's start with the headers (I think there's
nothing to say about it) nothing to say about it)
*/ */
@ -23,55 +23,62 @@ using namespace irr;
using namespace core; using namespace core;
using namespace video; using namespace video;
using namespace scene; using namespace scene;
using namespace gui;
/* /*
Now we'll define the resolution in a constant for use in Now we'll define the resolution in a constant for use in
initializing the device and setting up the viewport. In addition initializing the device and setting up the viewport.
we set up a global variable saying splitscreen is active or not.
*/ */
//Resolution //Resolution
const int ResX=800; const int ResX=800;
const int ResY=600; const int ResY=600;
const bool fullScreen=false;
//Use SplitScreen? //Use SplitScreen?
bool SplitScreen=true; bool SplitScreen=true;
// We allow quitting the with the ESC key
bool Quit = false;
/* /*
Now we need four pointers to our cameras which are created later: We need four pointers to our cameras which are created later:
*/ */
//cameras ICameraSceneNode *Camera[4]={0,0,0,0};
ICameraSceneNode *camera[4]={0,0,0,0};
/* /*
In our event-receiver we switch the SplitScreen-variable, In our event-receiver we switch the SplitScreen-variable,
whenever the user press the S-key. All other events are sent whenever the user press the S-key.
to the FPS camera. We also allow quitting the application with ESC.
*/ */
class MyEventReceiver : public IEventReceiver class MyEventReceiver : public IEventReceiver
{ {
public: public:
virtual bool OnEvent(const SEvent& event) virtual bool OnEvent(const SEvent& event)
{ {
//Key S enables/disables SplitScreen //Key S enables/disables SplitScreen
if (event.EventType == irr::EET_KEY_INPUT_EVENT && if (event.EventType == irr::EET_KEY_INPUT_EVENT && event.KeyInput.PressedDown )
event.KeyInput.Key == KEY_KEY_S && event.KeyInput.PressedDown) {
if ( event.KeyInput.Key == KEY_KEY_S )
{ {
SplitScreen = !SplitScreen; SplitScreen = !SplitScreen;
return true; return true;
} }
//Send all other events to camera4 if (event.KeyInput.Key == KEY_ESCAPE )
if (camera[3]) {
return camera[3]->OnEvent(event); Quit = true;
return true;
}
}
return false; return false;
} }
}; };
/* /*
Ok, now the main-function: The main-function:
First, we initialize the device, get the SourceManager and First, we initialize the device, get some useful variables,
VideoDriver, load an animated mesh from .md2 and a map from load an animated mesh from .md2 and a map from .pk3.
.pk3. Because that's old stuff, I won't explain every step. Because that's old stuff, I won't explain every step.
Just take care of the maps position. Just take care of the maps position.
*/ */
int main() int main()
@ -84,7 +91,8 @@ int main()
//Instance of the EventReceiver //Instance of the EventReceiver
MyEventReceiver receiver; MyEventReceiver receiver;
//Initialise the engine //Initialize the engine
const bool fullScreen=false;
IrrlichtDevice *device = createDevice(driverType, IrrlichtDevice *device = createDevice(driverType,
dimension2du(ResX,ResY), 32, fullScreen, dimension2du(ResX,ResY), 32, fullScreen,
false, false, &receiver); false, false, &receiver);
@ -93,6 +101,7 @@ int main()
ISceneManager *smgr = device->getSceneManager(); ISceneManager *smgr = device->getSceneManager();
IVideoDriver *driver = device->getVideoDriver(); IVideoDriver *driver = device->getVideoDriver();
IGUIEnvironment* guienv = device->getGUIEnvironment();
const io::path mediaPath = getExampleMediaPath(); const io::path mediaPath = getExampleMediaPath();
@ -121,6 +130,9 @@ int main()
map_node->setPosition(vector3df(-850,-220,-850)); map_node->setPosition(vector3df(-850,-220,-850));
} }
// Add some static text gui element, to give users information and how to show how using the UI works.
guienv->addStaticText(L"<S> to switch split screen.\n<ESC> to quit", recti(5,5, 100, 30), false, true, 0, -1, true);
/* /*
Now we create our four cameras. One is looking at the model Now we create our four cameras. One is looking at the model
from the front, one from the top and one from the side. In from the front, one from the top and one from the side. In
@ -129,19 +141,19 @@ user.
*/ */
// Create 3 fixed and one user-controlled cameras // Create 3 fixed and one user-controlled cameras
//Front //Front
camera[0] = smgr->addCameraSceneNode(0, vector3df(50,0,0), vector3df(0,0,0)); Camera[0] = smgr->addCameraSceneNode(0, vector3df(50,0,0), vector3df(0,0,0));
//Top //Top
camera[1] = smgr->addCameraSceneNode(0, vector3df(0,50,0), vector3df(0,0,0)); Camera[1] = smgr->addCameraSceneNode(0, vector3df(0,50,0), vector3df(0,0,0));
//Left //Left
camera[2] = smgr->addCameraSceneNode(0, vector3df(0,0,50), vector3df(0,0,0)); Camera[2] = smgr->addCameraSceneNode(0, vector3df(0,0,50), vector3df(0,0,0));
//User-controlled //User-controlled
camera[3] = smgr->addCameraSceneNodeFPS(); Camera[3] = smgr->addCameraSceneNodeFPS();
// don't start at sydney's position // don't start at Sydney's position
if (camera[3]) if (Camera[3])
camera[3]->setPosition(core::vector3df(-50,0,-50)); Camera[3]->setPosition(core::vector3df(-50,0,-50));
/* /*
Create a variable for counting the fps and hide the mouse: Hide the mouse and create a variable for counting the fps:
*/ */
//Hide mouse //Hide mouse
device->getCursorControl()->setVisible(false); device->getCursorControl()->setVisible(false);
@ -150,8 +162,8 @@ Create a variable for counting the fps and hide the mouse:
/* /*
There wasn't much new stuff - till now! There wasn't much new stuff - till now!
Only by defining four cameras, the game won't be splitscreen. The game won't be split the screen just by defining four cameras.
To do this you need several steps: To do this several steps are needed:
- Set the viewport to the whole screen - Set the viewport to the whole screen
- Begin a new scene (Clear screen) - Begin a new scene (Clear screen)
@ -168,31 +180,31 @@ To do this you need several steps:
Sounds a little complicated, but you'll see it isn't: Sounds a little complicated, but you'll see it isn't:
*/ */
while(device->run()) while(!Quit && device->run())
{ {
// Don't reset mouse cursor when window is not active // Don't reset mouse cursor when window is not active
camera[3]->setInputReceiverEnabled(device->isWindowActive()); Camera[3]->setInputReceiverEnabled(device->isWindowActive());
//Set the viewpoint to the whole screen and begin scene //Set the viewpoint to the whole screen and begin scene
driver->setViewPort(rect<s32>(0,0,ResX,ResY)); driver->setViewPort(rect<s32>(0,0,ResX,ResY));
driver->beginScene(video::ECBF_COLOR | video::ECBF_DEPTH, SColor(255,100,100,100)); driver->beginScene(video::ECBF_COLOR | video::ECBF_DEPTH, SColor(255,100,100,100));
//If SplitScreen is used //If split screen is used
if (SplitScreen) if (SplitScreen)
{ {
//Activate camera1 //Activate camera1
smgr->setActiveCamera(camera[0]); smgr->setActiveCamera(Camera[0]);
//Set viewpoint to the first quarter (left top) //Set viewpoint to the first quarter (left top)
driver->setViewPort(rect<s32>(0,0,ResX/2,ResY/2)); driver->setViewPort(rect<s32>(0,0,ResX/2,ResY/2));
//Draw scene //Draw scene
smgr->drawAll(); smgr->drawAll();
//Activate camera2 //Activate camera2
smgr->setActiveCamera(camera[1]); smgr->setActiveCamera(Camera[1]);
//Set viewpoint to the second quarter (right top) //Set viewpoint to the second quarter (right top)
driver->setViewPort(rect<s32>(ResX/2,0,ResX,ResY/2)); driver->setViewPort(rect<s32>(ResX/2,0,ResX,ResY/2));
//Draw scene //Draw scene
smgr->drawAll(); smgr->drawAll();
//Activate camera3 //Activate camera3
smgr->setActiveCamera(camera[2]); smgr->setActiveCamera(Camera[2]);
//Set viewpoint to the third quarter (left bottom) //Set viewpoint to the third quarter (left bottom)
driver->setViewPort(rect<s32>(0,ResY/2,ResX/2,ResY)); driver->setViewPort(rect<s32>(0,ResY/2,ResX/2,ResY));
//Draw scene //Draw scene
@ -201,15 +213,21 @@ Sounds a little complicated, but you'll see it isn't:
driver->setViewPort(rect<s32>(ResX/2,ResY/2,ResX,ResY)); driver->setViewPort(rect<s32>(ResX/2,ResY/2,ResX,ResY));
} }
//Activate camera4 //Activate camera4
smgr->setActiveCamera(camera[3]); smgr->setActiveCamera(Camera[3]);
//Draw scene //Draw scene
smgr->drawAll(); smgr->drawAll();
// Back to whole screen for the UI
if (SplitScreen)
driver->setViewPort(rect<s32>(0,0,ResX,ResY));
guienv->drawAll();
driver->endScene(); driver->endScene();
/* /*
As you can probably see, the image is rendered for every As you can probably see, the image is rendered for every
viewport separately. That means, that you'll loose much performance. viewport separately. That means, that you'll loose much performance.
Ok, if you're asking "How do I have to set the viewport OK, if you're asking "How do I have to set the viewport
to get this or that screen?", don't panic. It's really to get this or that screen?", don't panic. It's really
easy: In the rect-function you define 4 coordinates: easy: In the rect-function you define 4 coordinates:
- X-coordinate of the corner left top - X-coordinate of the corner left top
@ -225,10 +243,8 @@ Sounds a little complicated, but you'll see it isn't:
If you didn't fully understand, just play around with the example If you didn't fully understand, just play around with the example
to check out what happens. to check out what happens.
Now we just view the current fps and shut down the engine, Last we show the current fps.
when the user wants to:
*/ */
//Get and show fps
if (driver->getFPS() != lastFPS) if (driver->getFPS() != lastFPS)
{ {
lastFPS = driver->getFPS(); lastFPS = driver->getFPS();
@ -244,7 +260,4 @@ Sounds a little complicated, but you'll see it isn't:
} }
/* /*
That's it! Just compile and play around with the program. That's it! Just compile and play around with the program.
Note: With the S-Key you can switch between using splitscreen
and not.
**/ **/

@ -12,7 +12,7 @@ IrrlichtHome := ../..
BinPath = ../../bin/$(SYSTEM) BinPath = ../../bin/$(SYSTEM)
# general compiler settings (might need to be set when compiling the lib, too) # general compiler settings (might need to be set when compiling the lib, too)
CPPFLAGS += -I$(IrrlichtHome)/include -I/usr/X11R6/include CPPFLAGS += -I$(IrrlichtHome)/include
ifndef NDEBUG ifndef NDEBUG
CXXFLAGS += -g -Wall CXXFLAGS += -g -Wall
else else

@ -8,8 +8,6 @@ devices.
*/ */
#ifdef _MSC_VER #ifdef _MSC_VER
// We'll 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
@ -19,8 +17,21 @@ devices.
using namespace irr; using namespace irr;
/* /*
Just as we did in example 04.Movement, we'll store the latest state of the Just as we did in example 04.Movement with keys, we'll store the latest state of the
mouse and the first joystick, updating them as we receive events. mouse and the first joystick, updating them as we receive events.
Note that instead of working with events we could work with CursorControl, aka
device->getCursorControl(), to get the current mouse state.
With events you get every mouse movement since the last device->run(),
while CursorControl will always return the current state at the moment you check it.
CursorControl will be able to get cursor positions even if the mouse is outside the
active Window, while the behavior of mouse-events for this is a bit system dependent
and also can be influenced by system calls for mouse-grabbing.
Events tend to work on more devices (especially mobile devices) where CursorControl might
not be available. Also on some systems (X11) checking the mouse position with CursorControl
can be rather slow compared to events.
Often it depends a bit on the type of game which solution is preferable, just be aware
that you have some choice for this.
*/ */
class MyEventReceiver : public IEventReceiver class MyEventReceiver : public IEventReceiver
{ {
@ -30,7 +41,8 @@ public:
{ {
core::position2di Position; core::position2di Position;
bool LeftButtonDown; bool LeftButtonDown;
SMouseState() : LeftButtonDown(false) { } bool WasMouseMoved;
SMouseState() : LeftButtonDown(false), WasMouseMoved(false) { }
} MouseState; } MouseState;
// This is the one method that we have to implement // This is the one method that we have to implement
@ -52,6 +64,7 @@ public:
case EMIE_MOUSE_MOVED: case EMIE_MOUSE_MOVED:
MouseState.Position.X = event.MouseInput.X; MouseState.Position.X = event.MouseInput.X;
MouseState.Position.Y = event.MouseInput.Y; MouseState.Position.Y = event.MouseInput.Y;
MouseState.WasMouseMoved = true;
break; break;
default: default:
@ -63,7 +76,6 @@ public:
// The state of each connected joystick is sent to us // The state of each connected joystick is sent to us
// once every run() of the Irrlicht device. Store the // once every run() of the Irrlicht device. Store the
// state of the first joystick, ignoring other joysticks. // state of the first joystick, ignoring other joysticks.
// This is currently only supported on Windows and Linux.
if (event.EventType == irr::EET_JOYSTICK_INPUT_EVENT if (event.EventType == irr::EET_JOYSTICK_INPUT_EVENT
&& event.JoystickEvent.Joystick == 0) && event.JoystickEvent.Joystick == 0)
{ {
@ -83,9 +95,9 @@ public:
return MouseState; return MouseState;
} }
void ResetMouseMoved()
MyEventReceiver()
{ {
MouseState.WasMouseMoved = false;
} }
private: private:
@ -94,11 +106,9 @@ private:
/* /*
The event receiver for keeping the pressed keys is ready, the actual responses The event receiver for remembering the events 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
just create an irr::IrrlichtDevice and the scene node we want to move. We also just create an irr::IrrlichtDevice and the scene node we want to move.
create some other additional scene nodes, to show that there are also some
different possibilities to move and animate scene nodes.
*/ */
int main() int main()
{ {
@ -117,6 +127,11 @@ int main()
return 1; // could not create selected driver. return 1; // could not create selected driver.
/*
Joysticks have to be activated to generate events.
So lets's do that and also print out some info to the console
about all the joysticks we found and can use.
*/
core::array<SJoystickInfo> joystickInfo; core::array<SJoystickInfo> joystickInfo;
if(device->activateJoysticks(joystickInfo)) if(device->activateJoysticks(joystickInfo))
{ {
@ -153,6 +168,7 @@ int main()
std::cout << "Joystick support is not enabled." << std::endl; std::cout << "Joystick support is not enabled." << std::endl;
} }
// Set some window caption text
core::stringw tmp = L"Irrlicht Joystick Example ("; core::stringw tmp = L"Irrlicht Joystick Example (";
tmp += joystickInfo.size(); tmp += joystickInfo.size();
tmp += " joysticks)"; tmp += " joysticks)";
@ -179,20 +195,24 @@ int main()
camera->setPosition(core::vector3df(0, 0, -10)); camera->setPosition(core::vector3df(0, 0, -10));
// As in example 04, we'll use framerate independent movement. // As in example 04, we'll use framerate independent movement.
u32 then = device->getTimer()->getTime(); u32 then = device->getTimer()->getRealTime();
const f32 MOVEMENT_SPEED = 5.f; const f32 MOVEMENT_SPEED = 5.f;
// Ignore all events which happened until now.
// Like mouse events triggered while we chose our driver.
device->clearSystemMessages();
while(device->run()) while(device->run())
{ {
// Work out a frame delta time. // Work out a frame delta time.
const u32 now = device->getTimer()->getTime(); const u32 now = device->getTimer()->getRealTime();
const f32 frameDeltaTime = (f32)(now - then) / 1000.f; // Time in seconds const f32 frameDeltaTime = (f32)(now - then) / 1000.f; // Time in seconds
then = now; then = now;
bool movedWithJoystick = false; bool movedWithJoystick = false;
core::vector3df nodePosition = node->getPosition(); core::vector3df nodePosition = node->getPosition();
if(joystickInfo.size() > 0) if(joystickInfo.size() > 0) // if we have at least one joystick
{ {
f32 moveHorizontal = 0.f; // Range is -1.f for full left to +1.f for full right f32 moveHorizontal = 0.f; // Range is -1.f for full left to +1.f for full right
f32 moveVertical = 0.f; // -1.f for full down to +1.f for full up. f32 moveVertical = 0.f; // -1.f for full down to +1.f for full up.
@ -237,11 +257,14 @@ int main()
nodePosition.X += MOVEMENT_SPEED * frameDeltaTime * moveHorizontal; nodePosition.X += MOVEMENT_SPEED * frameDeltaTime * moveHorizontal;
nodePosition.Y += MOVEMENT_SPEED * frameDeltaTime * moveVertical; nodePosition.Y += MOVEMENT_SPEED * frameDeltaTime * moveVertical;
movedWithJoystick = true; movedWithJoystick = true;
// We only go back to following mouse when it moves again
receiver.ResetMouseMoved();
} }
} }
// If the arrow node isn't being moved with the joystick, then have it follow the mouse cursor. // If the arrow node isn't being moved with the joystick, then have it follow the mouse cursor.
if(!movedWithJoystick) if (!movedWithJoystick && receiver.GetMouseState().WasMouseMoved)
{ {
// Create a ray through the mouse cursor. // Create a ray through the mouse cursor.
core::line3df ray = smgr->getSceneCollisionManager()->getRayFromScreenCoordinates( core::line3df ray = smgr->getSceneCollisionManager()->getRayFromScreenCoordinates(
@ -257,11 +280,15 @@ int main()
const f32 availableMovement = MOVEMENT_SPEED * frameDeltaTime; const f32 availableMovement = MOVEMENT_SPEED * frameDeltaTime;
if(toMousePosition.getLength() <= availableMovement) if(toMousePosition.getLength() <= availableMovement)
{
nodePosition = mousePosition; // Jump to the final position nodePosition = mousePosition; // Jump to the final position
}
else else
{
nodePosition += toMousePosition.normalize() * availableMovement; // Move towards it nodePosition += toMousePosition.normalize() * availableMovement; // Move towards it
} }
} }
}
node->setPosition(nodePosition); node->setPosition(nodePosition);

@ -12,7 +12,7 @@ IrrlichtHome := ../..
BinPath = ../../bin/$(SYSTEM) BinPath = ../../bin/$(SYSTEM)
# general compiler settings (might need to be set when compiling the lib, too) # general compiler settings (might need to be set when compiling the lib, too)
CPPFLAGS += -I$(IrrlichtHome)/include -I/usr/X11R6/include CPPFLAGS += -I$(IrrlichtHome)/include
ifndef NDEBUG ifndef NDEBUG
CXXFLAGS += -g -Wall CXXFLAGS += -g -Wall
else else

@ -12,7 +12,7 @@ IrrlichtHome := ../..
BinPath = ../../bin/$(SYSTEM) BinPath = ../../bin/$(SYSTEM)
# general compiler settings (might need to be set when compiling the lib, too) # general compiler settings (might need to be set when compiling the lib, too)
CPPFLAGS += -I$(IrrlichtHome)/include -I/usr/X11R6/include CPPFLAGS += -I$(IrrlichtHome)/include
ifndef NDEBUG ifndef NDEBUG
CXXFLAGS += -g -Wall CXXFLAGS += -g -Wall
else else

@ -3,13 +3,13 @@
This tutorial shows how to load different Quake 3 maps. This tutorial shows how to load different Quake 3 maps.
Features: Features:
- Load BSP Archives at Runtime from the menu - Load BSP archives at runtime from the menu
- Load a Map from the menu. Showing with Screenshot - Load a map from the menu. Showing with screenshot
- Set the VideoDriver at runtime from menu - Set the VideoDriver at runtime from menu
- Adjust GammaLevel at runtime - Adjust GammaLevel at runtime
- Create SceneNodes for the Shaders - Create SceneNodes for the shaders
- Load EntityList and create Entity SceneNodes - Load EntityList and create entity SceneNodes
- Create Players with Weapons and with Collision Response - Create players with weapons and with collision response
- Play music - Play music
You can download the Quake III Arena demo ( copyright id software ) You can download the Quake III Arena demo ( copyright id software )
@ -26,7 +26,7 @@ Copyright 2006-2011 Burningwater, Thomas Alten
#include "sound.h" #include "sound.h"
/* /*
Game Data is used to hold Data which is needed to drive the game GameData is used to hold data which is needed to drive the game
*/ */
struct GameData struct GameData
{ {
@ -100,7 +100,7 @@ void GameData::setDefault ()
loadParam.mergeShaderBuffer = 1; // merge meshbuffers with same material loadParam.mergeShaderBuffer = 1; // merge meshbuffers with same material
loadParam.cleanUnResolvedMeshes = 1; // should unresolved meshes be cleaned. otherwise blue texture loadParam.cleanUnResolvedMeshes = 1; // should unresolved meshes be cleaned. otherwise blue texture
loadParam.loadAllShaders = 1; // load all scripts in the script directory loadParam.loadAllShaders = 1; // load all scripts in the script directory
loadParam.loadSkyShader = 0; // load sky Shader loadParam.loadSkyShader = 0; // load sky shader
loadParam.alpharef = 1; loadParam.alpharef = 1;
sound = 0; sound = 0;
@ -168,18 +168,18 @@ s32 GameData::load ( const path &filename )
} }
/* /*
Store the current game State in a quake3 configuration file Store the current game state in a quake3 configuration file
*/ */
s32 GameData::save ( const path &filename ) s32 GameData::save ( const path &filename )
{ {
return 0; return 0; // TODO: Anyone knows why it just returns?
if (!Device) if (!Device)
return 0; return 0;
c8 buf[128]; c8 buf[128];
u32 i; u32 i;
// Store current Archive for restart // Store current archive for restart
CurrentArchiveList.clear(); CurrentArchiveList.clear();
IFileSystem *fs = Device->getFileSystem(); IFileSystem *fs = Device->getFileSystem();
for ( i = 0; i != fs->getFileArchiveCount(); ++i ) for ( i = 0; i != fs->getFileArchiveCount(); ++i )
@ -187,7 +187,7 @@ s32 GameData::save ( const path &filename )
CurrentArchiveList.push_back ( fs->getFileArchive(i)->getFileList()->getPath() ); CurrentArchiveList.push_back ( fs->getFileArchive(i)->getFileList()->getPath() );
} }
// Store Player Position and Rotation // Store player position and rotation
ICameraSceneNode * camera = Device->getSceneManager()->getActiveCamera (); ICameraSceneNode * camera = Device->getSceneManager()->getActiveCamera ();
if ( camera ) if ( camera )
{ {
@ -279,7 +279,7 @@ void Q3Player::create ( IrrlichtDevice *device, IQ3LevelMesh* mesh, ISceneNode *
if (!device) if (!device)
return; return;
// load FPS weapon to Camera // load FPS weapon to camera
Device = device; Device = device;
Mesh = mesh; Mesh = mesh;
MapParent = mapNode; MapParent = mapNode;
@ -377,8 +377,8 @@ void Q3Player::create ( IrrlichtDevice *device, IQ3LevelMesh* mesh, ISceneNode *
/* /*
so we need a good starting Position in the level. So we need a good starting position in the level.
we can ask the Quake3 Loader for all entities with class_name "info_player_deathmatch" We can ask the Quake3 loader for all entities with class_name "info_player_deathmatch"
*/ */
void Q3Player::respawn () void Q3Player::respawn ()
{ {
@ -396,7 +396,7 @@ void Q3Player::respawn ()
} }
/* /*
set Player position from saved coordinates set player position from saved coordinates
*/ */
void Q3Player::setpos ( const vector3df &pos, const vector3df &rotation ) void Q3Player::setpos ( const vector3df &pos, const vector3df &rotation )
{ {
@ -414,7 +414,7 @@ void Q3Player::setpos ( const vector3df &pos, const vector3df &rotation )
} }
} }
/* set the Animation of the player and weapon /* set the animation of the player and weapon
*/ */
void Q3Player::setAnim ( const c8 *name ) void Q3Player::setAnim ( const c8 *name )
{ {
@ -446,7 +446,7 @@ void Q3Player::OnAnimationEnd(IAnimatedMeshSceneNode* node)
/* GUI Elements /* GUI elements
*/ */
struct GUI struct GUI
{ {
@ -560,13 +560,13 @@ CQuake3EventHandler::CQuake3EventHandler( GameData *game )
BulletParent(0), FogParent(0), SkyNode(0), Meta(0) BulletParent(0), FogParent(0), SkyNode(0), Meta(0)
{ {
buf[0]=0; buf[0]=0;
// Also use 16 Bit Textures for 16 Bit RenderDevice // Also use 16 bit textures for 16 bit RenderDevice
if ( Game->deviceParam.Bits == 16 ) if ( Game->deviceParam.Bits == 16 )
{ {
game->Device->getVideoDriver()->setTextureCreationFlag(ETCF_ALWAYS_16_BIT, true); game->Device->getVideoDriver()->setTextureCreationFlag(ETCF_ALWAYS_16_BIT, true);
} }
// Quake3 Shader controls Z-Writing // Quake3 shader controls Z-writing
game->Device->getSceneManager()->getParameters()->setAttribute(scene::ALLOW_ZWRITE_ON_TRANSPARENT, true); game->Device->getSceneManager()->getParameters()->setAttribute(scene::ALLOW_ZWRITE_ON_TRANSPARENT, true);
// create internal textures // create internal textures
@ -599,21 +599,10 @@ void CQuake3EventHandler::createTextures()
video::IImage* image; video::IImage* image;
u32 i; u32 i;
u32 x;
u32 y;
u32 * data;
for ( i = 0; i != 8; ++i ) for ( i = 0; i != 8; ++i )
{ {
image = driver->createImage ( video::ECF_A8R8G8B8, dim); image = driver->createImage ( video::ECF_A8R8G8B8, dim);
data = (u32*) image->getData (); image->fill(SColor(0xFFFFFFFF));
for ( y = 0; y != dim.Height; ++y )
{
for ( x = 0; x != dim.Width; ++x )
{
data [x] = 0xFFFFFFFF;
}
data = (u32*) ( (u8*) data + image->getPitch() );
}
snprintf_irr ( buf, 64, "smoke_%02d", i ); snprintf_irr ( buf, 64, "smoke_%02d", i );
driver->addTexture( buf, image ); driver->addTexture( buf, image );
image->drop (); image->drop ();
@ -623,15 +612,7 @@ void CQuake3EventHandler::createTextures()
for ( i = 0; i != 1; ++i ) for ( i = 0; i != 1; ++i )
{ {
image = driver->createImage ( video::ECF_A8R8G8B8, dim); image = driver->createImage ( video::ECF_A8R8G8B8, dim);
data = (u32*) image->getData (); image->fill(SColor(0xFFFFFFFF));
for ( y = 0; y != dim.Height; ++y )
{
for ( x = 0; x != dim.Width; ++x )
{
data [x] = 0xFFFFFFFF;
}
data = (u32*) ( (u8*) data + image->getPitch() );
}
snprintf_irr ( buf, 64, "fog_%02d", i ); snprintf_irr ( buf, 64, "fog_%02d", i );
driver->addTexture( buf, image ); driver->addTexture( buf, image );
image->drop (); image->drop ();
@ -644,7 +625,6 @@ void CQuake3EventHandler::createTextures()
*/ */
void CQuake3EventHandler::CreateGUI() void CQuake3EventHandler::CreateGUI()
{ {
IGUIEnvironment *env = Game->Device->getGUIEnvironment(); IGUIEnvironment *env = Game->Device->getGUIEnvironment();
IVideoDriver * driver = Game->Device->getVideoDriver(); IVideoDriver * driver = Game->Device->getVideoDriver();
@ -663,15 +643,6 @@ void CQuake3EventHandler::CreateGUI()
// minimal gui size 800x600 // minimal gui size 800x600
dimension2d<u32> dim ( 800, 600 ); dimension2d<u32> dim ( 800, 600 );
dimension2d<u32> vdim ( Game->Device->getVideoDriver()->getScreenSize() );
if ( vdim.Height >= dim.Height && vdim.Width >= dim.Width )
{
//dim = vdim;
}
else
{
}
gui.Window = env->addWindow ( rect<s32> ( 0, 0, dim.Width, dim.Height ), false, L"Quake3 Explorer" ); gui.Window = env->addWindow ( rect<s32> ( 0, 0, dim.Width, dim.Height ), false, L"Quake3 Explorer" );
gui.Window->setToolTipText ( L"Quake3Explorer. Loads and show various BSP File Format and Shaders." ); gui.Window->setToolTipText ( L"Quake3Explorer. Loads and show various BSP File Format and Shaders." );
@ -860,7 +831,7 @@ void CQuake3EventHandler::AddArchive ( const path& archiveName )
} }
// store the current archives in game data // store the current archives in game data
// show the attached Archive in proper order // show the attached archive in proper order
if ( gui.ArchiveList ) if ( gui.ArchiveList )
{ {
gui.ArchiveList->clearRows(); gui.ArchiveList->clearRows();
@ -998,7 +969,7 @@ void CQuake3EventHandler::AddArchive ( const path& archiveName )
} }
/* /*
clears the Map in Memory clears the map in memory
*/ */
void CQuake3EventHandler::dropMap () void CQuake3EventHandler::dropMap ()
{ {
@ -1113,9 +1084,9 @@ void CQuake3EventHandler::LoadMap ( const stringw &mapName, s32 collision )
BulletParent->setName ( "Bullet Container" ); BulletParent->setName ( "Bullet Container" );
/* /*
now construct SceneNodes for each Shader now construct SceneNodes for each shader
The Objects are stored in the quake mesh E_Q3_MESH_ITEMS The objects are stored in the quake mesh E_Q3_MESH_ITEMS
and the Shader ID is stored in the MaterialParameters and the shader ID is stored in the MaterialParameters
mostly dark looking skulls and moving lava.. or green flashing tubes? mostly dark looking skulls and moving lava.. or green flashing tubes?
*/ */
Q3ShaderFactory ( Game->loadParam, Game->Device, Mesh, E_Q3_MESH_ITEMS,ShaderParent, Meta, false ); Q3ShaderFactory ( Game->loadParam, Game->Device, Mesh, E_Q3_MESH_ITEMS,ShaderParent, Meta, false );
@ -1123,13 +1094,13 @@ void CQuake3EventHandler::LoadMap ( const stringw &mapName, s32 collision )
Q3ShaderFactory ( Game->loadParam, Game->Device, Mesh, E_Q3_MESH_UNRESOLVED,UnresolvedParent, Meta, true ); Q3ShaderFactory ( Game->loadParam, Game->Device, Mesh, E_Q3_MESH_UNRESOLVED,UnresolvedParent, Meta, true );
/* /*
Now construct Models from Entity List Now construct models from entity list
*/ */
Q3ModelFactory ( Game->loadParam, Game->Device, Mesh, ItemParent, false ); Q3ModelFactory ( Game->loadParam, Game->Device, Mesh, ItemParent, false );
} }
/* /*
Adds a SceneNode with an icon to the Scene Tree Adds a SceneNode with an icon to the scene tree
*/ */
void CQuake3EventHandler::addSceneTreeItem( ISceneNode * parent, IGUITreeViewNode* nodeParent) void CQuake3EventHandler::addSceneTreeItem( ISceneNode * parent, IGUITreeViewNode* nodeParent)
{ {
@ -1169,7 +1140,7 @@ void CQuake3EventHandler::addSceneTreeItem( ISceneNode * parent, IGUITreeViewNod
node = nodeParent->addChildBack( msg, 0, imageIndex ); node = nodeParent->addChildBack( msg, 0, imageIndex );
// Add all Animators // Add all animators
list<ISceneNodeAnimator*>::ConstIterator ait = (*it)->getAnimators().begin(); list<ISceneNodeAnimator*>::ConstIterator ait = (*it)->getAnimators().begin();
for (; ait != (*it)->getAnimators().end(); ++ait) for (; ait != (*it)->getAnimators().end(); ++ait)
{ {
@ -1753,7 +1724,7 @@ void CQuake3EventHandler::useItem( Q3Player * player)
} }
else else
{ {
// doesnt collide with wall // doesn't collide with wall
vector3df start = camera->getPosition(); vector3df start = camera->getPosition();
if ( player->WeaponNode ) if ( player->WeaponNode )
{ {
@ -2104,7 +2075,7 @@ void runGame ( GameData *game )
eventHandler->AddArchive ( game->CurrentArchiveList[i] ); eventHandler->AddArchive ( game->CurrentArchiveList[i] );
} }
// Load a Map or startup to the GUI // Load a map or startup to the GUI
if ( game->CurrentMapName.size () ) if ( game->CurrentMapName.size () )
{ {
eventHandler->LoadMap ( game->CurrentMapName, 1 ); eventHandler->LoadMap ( game->CurrentMapName, 1 );

@ -301,7 +301,7 @@ const SItemElement * getItemElement ( const stringc& key )
} }
/*! /*!
Quake3 Model Factory. Quake3 model factory.
Takes the mesh buffers and creates scenenodes for their associated shaders Takes the mesh buffers and creates scenenodes for their associated shaders
*/ */
void Q3ShaderFactory ( Q3LevelLoadParameter &loadParam, void Q3ShaderFactory ( Q3LevelLoadParameter &loadParam,
@ -399,7 +399,7 @@ void Q3ShaderFactory ( Q3LevelLoadParameter &loadParam,
sceneNodeID += 1; sceneNodeID += 1;
} }
// show Debug Shader Name // show debug shader name
if ( showShaderName && node ) if ( showShaderName && node )
{ {
swprintf_irr ( (wchar_t*) buf, 64, L"%hs:%d", node->getName(),node->getID() ); swprintf_irr ( (wchar_t*) buf, 64, L"%hs:%d", node->getName(),node->getID() );
@ -413,7 +413,7 @@ void Q3ShaderFactory ( Q3LevelLoadParameter &loadParam,
sceneNodeID += 1; sceneNodeID += 1;
} }
// create Portal Rendertargets // create portal rendertargets
if ( shader ) if ( shader )
{ {
const SVarGroup *group = shader->getGroup(1); const SVarGroup *group = shader->getGroup(1);
@ -496,7 +496,7 @@ void Q3ShaderFactory ( Q3LevelLoadParameter &loadParam,
/*! /*!
create Items from Entity create items from entity
*/ */
void Q3ModelFactory ( Q3LevelLoadParameter &loadParam, void Q3ModelFactory ( Q3LevelLoadParameter &loadParam,
IrrlichtDevice *device, IrrlichtDevice *device,
@ -513,7 +513,7 @@ void Q3ModelFactory ( Q3LevelLoadParameter &loadParam,
char buf[128]; char buf[128];
const SVarGroup *group; const SVarGroup *group = 0;
IEntity search; IEntity search;
s32 index; s32 index;
s32 lastIndex; s32 lastIndex;
@ -531,12 +531,12 @@ void Q3ModelFactory ( Q3LevelLoadParameter &loadParam,
} }
fclose ( f ); fclose ( f );
*/ */
IAnimatedMeshMD3* model; IAnimatedMeshMD3* model = 0;
SMD3Mesh * mesh; SMD3Mesh * mesh = 0;
const SMD3MeshBuffer *meshBuffer; const SMD3MeshBuffer *meshBuffer = 0;
IMeshSceneNode* node; IMeshSceneNode* node = 0;
ISceneNodeAnimator* anim; ISceneNodeAnimator* anim = 0;
const IShader *shader; const IShader *shader = 0;
u32 pos; u32 pos;
vector3df p; vector3df p;
u32 nodeCount = 0; u32 nodeCount = 0;
@ -546,7 +546,7 @@ void Q3ModelFactory ( Q3LevelLoadParameter &loadParam,
if ( showShaderName ) if ( showShaderName )
font = device->getGUIEnvironment()->getFont("fontlucida.png"); font = device->getGUIEnvironment()->getFont("fontlucida.png");
const SItemElement *itemElement; const SItemElement *itemElement = 0;
// walk list // walk list
for ( index = 0; (u32) index < entity.size(); ++index ) for ( index = 0; (u32) index < entity.size(); ++index )
@ -706,7 +706,7 @@ s32 Q3StartPosition ( IQ3LevelMesh* mesh,
u32 parsepos; u32 parsepos;
const SVarGroup *group; const SVarGroup *group = 0;
group = entityList[ index ].getGroup(1); group = entityList[ index ].getGroup(1);
parsepos = 0; parsepos = 0;
@ -802,7 +802,7 @@ ISceneNodeAnimatorCollisionResponse* camCollisionResponse( IrrlichtDevice * devi
} }
//! internal Animation //! internal animation
void setTimeFire ( TimeFire *t, u32 delta, u32 flags ) void setTimeFire ( TimeFire *t, u32 delta, u32 flags )
{ {
t->flags = flags; t->flags = flags;

@ -46,7 +46,7 @@ enum eItemSubGroup
CHAINGUN, CHAINGUN,
}; };
//! aplly a special effect to the shader //! apply a special effect to the shader
enum eItemSpecialEffect enum eItemSpecialEffect
{ {
SPECIAL_SFX_NONE = 0, SPECIAL_SFX_NONE = 0,
@ -55,7 +55,7 @@ enum eItemSpecialEffect
SPECIAL_SFX_ROTATE_1 = 4, SPECIAL_SFX_ROTATE_1 = 4,
}; };
// a List for defining a model // a list for defining a model
struct SItemElement struct SItemElement
{ {
const c8 *key; const c8 *key;
@ -124,11 +124,11 @@ funcptr_createDeviceEx load_createDeviceEx ( const c8 * filename);
/* /*
get the current collision respone camera animator get the current collision response camera animator
*/ */
ISceneNodeAnimatorCollisionResponse* camCollisionResponse( IrrlichtDevice * device ); ISceneNodeAnimatorCollisionResponse* camCollisionResponse( IrrlichtDevice * device );
//! internal Animation //! internal animation
enum eTimeFireFlag enum eTimeFireFlag
{ {
FIRED = 1, FIRED = 1,

@ -12,7 +12,7 @@ IrrlichtHome := ../..
BinPath = ../../bin/$(SYSTEM) BinPath = ../../bin/$(SYSTEM)
# general compiler settings (might need to be set when compiling the lib, too) # general compiler settings (might need to be set when compiling the lib, too)
CPPFLAGS += -I$(IrrlichtHome)/include -I/usr/X11R6/include CPPFLAGS += -I$(IrrlichtHome)/include
ifndef NDEBUG ifndef NDEBUG
CXXFLAGS += -g -Wall CXXFLAGS += -g -Wall
else else

@ -1,6 +1,6 @@
/** Example 022 Material Viewer /** Example 022 Material Viewer
This example can be used to play around with material settings and watch the results. This example can be used to experiment with material settings and watch the results.
Only the default non-shader materials are used in here. Only the default non-shader materials are used in here.
You have a node with a mesh, one dynamic light and global ambient light to play around with. You have a node with a mesh, one dynamic light and global ambient light to play around with.
@ -9,8 +9,7 @@ You can move the camera while left-mouse button is clicked.
*/ */
// TODO: Should be possible to set all material values by the GUI. // TODO: Should be possible to set all material values by the GUI.
// For now just change the defaultMaterial in CApp::init for the rest. // For now just change the defaultMaterial in CApp::setActiveMeshNodeType for the rest.
// TODO: Allow users to switch between a sphere and a box mesh.
#include <irrlicht.h> #include <irrlicht.h>
#include "driverChoice.h" #include "driverChoice.h"
@ -129,7 +128,6 @@ video::E_VERTEX_TYPE getVertexTypeForMaterialType(video::E_MATERIAL_TYPE materia
/* /*
Custom GUI-control to edit color values. Custom GUI-control to edit color values.
*/ */
// Constructor
CColorControl::CColorControl(gui::IGUIEnvironment* guiEnv, const core::position2d<s32> & pos, const wchar_t *text, IGUIElement* parent, s32 id) CColorControl::CColorControl(gui::IGUIEnvironment* guiEnv, const core::position2d<s32> & pos, const wchar_t *text, IGUIElement* parent, s32 id)
: gui::IGUIElement(gui::EGUIET_ELEMENT, guiEnv, parent,id, core::rect< s32 >(pos, pos+core::dimension2d<s32>(80, 75))) : gui::IGUIElement(gui::EGUIET_ELEMENT, guiEnv, parent,id, core::rect< s32 >(pos, pos+core::dimension2d<s32>(80, 75)))
, DirtyFlag(true) , DirtyFlag(true)
@ -147,12 +145,13 @@ CColorControl::CColorControl(gui::IGUIEnvironment* guiEnv, const core::position2
IGUIStaticText * groupElement = guiEnv->addStaticText (L"", rectControls, true, false, this, -1, false); IGUIStaticText * groupElement = guiEnv->addStaticText (L"", rectControls, true, false, this, -1, false);
groupElement->setNotClipped(true); groupElement->setNotClipped(true);
guiEnv->addStaticText (text, core::rect<s32>(0,0,80,15), false, false, groupElement, -1, false); s32 border=guiEnv->getSkin()->getSize(EGDS_TEXT_DISTANCE_X);
guiEnv->addStaticText(text, core::rect<s32>(border,border,80,15), false, false, groupElement, -1, true);
EditAlpha = addEditForNumbers(guiEnv, core::position2d<s32>(0,15), L"a", -1, groupElement ); EditAlpha = addEditForNumbers(guiEnv, core::position2d<s32>(border,15), L"a", -1, groupElement );
EditRed = addEditForNumbers(guiEnv, core::position2d<s32>(0,30), L"r", -1, groupElement ); EditRed = addEditForNumbers(guiEnv, core::position2d<s32>(border,30), L"r", -1, groupElement );
EditGreen = addEditForNumbers(guiEnv, core::position2d<s32>(0,45), L"g", -1, groupElement ); EditGreen = addEditForNumbers(guiEnv, core::position2d<s32>(border,45), L"g", -1, groupElement );
EditBlue = addEditForNumbers(guiEnv, core::position2d<s32>(0,60), L"b", -1, groupElement ); EditBlue = addEditForNumbers(guiEnv, core::position2d<s32>(border,60), L"b", -1, groupElement );
ColorStatic = guiEnv->addStaticText (L"", core::rect<s32>(60,15,80,75), true, false, groupElement, -1, true); ColorStatic = guiEnv->addStaticText (L"", core::rect<s32>(60,15,80,75), true, false, groupElement, -1, true);
@ -163,10 +162,9 @@ CColorControl::CColorControl(gui::IGUIEnvironment* guiEnv, const core::position2
// event receiver // event receiver
bool CColorControl::OnEvent(const SEvent &event) bool CColorControl::OnEvent(const SEvent &event)
{ {
if ( event.EventType != EET_GUI_EVENT ) if ( event.EventType == EET_GUI_EVENT
return false; && event.GUIEvent.Caller->getID() == ButtonSetId
&& event.GUIEvent.EventType == gui::EGET_BUTTON_CLICKED )
if ( event.GUIEvent.Caller->getID() == ButtonSetId && event.GUIEvent.EventType == gui::EGET_BUTTON_CLICKED )
{ {
Color = getColorFromEdits(); Color = getColorFromEdits();
setEditsFromColor(Color); setEditsFromColor(Color);
@ -183,12 +181,12 @@ void CColorControl::setColor(const video::SColor& col)
setEditsFromColor(Color); setEditsFromColor(Color);
} }
// Add a staticbox for a description + an editbox so users can enter numbers // Add a statictext for a description + an editbox so users can enter numbers
gui::IGUIEditBox* CColorControl::addEditForNumbers(gui::IGUIEnvironment* guiEnv, const core::position2d<s32> & pos, const wchar_t *text, s32 id, gui::IGUIElement * parent) gui::IGUIEditBox* CColorControl::addEditForNumbers(gui::IGUIEnvironment* guiEnv, const core::position2d<s32> & pos, const wchar_t *text, s32 id, gui::IGUIElement * parent)
{ {
using namespace gui; using namespace gui;
core::rect< s32 > rect(pos, pos+core::dimension2d<s32>(10, 15)); core::recti rect(pos, pos+core::dimension2d<s32>(10, 15));
guiEnv->addStaticText(text, rect, false, false, parent, -1, false); guiEnv->addStaticText(text, rect, false, false, parent, -1, false);
rect += core::position2d<s32>( 20, 0 ); rect += core::position2d<s32>( 20, 0 );
rect.LowerRightCorner.X += 20; rect.LowerRightCorner.X += 20;
@ -196,47 +194,39 @@ gui::IGUIEditBox* CColorControl::addEditForNumbers(gui::IGUIEnvironment* guiEnv,
return edit; return edit;
} }
// Get the color value from the editfields // Get the color value from the editboxes
video::SColor CColorControl::getColorFromEdits() const video::SColor CColorControl::getColorFromEdits() const
{ {
video::SColor col; video::SColor col;
if (EditAlpha) if (EditAlpha)
{ {
u32 alpha = core::strtoul10(core::stringc(EditAlpha->getText()).c_str()); u32 alpha = core::min_(core::strtoul10(core::stringc(EditAlpha->getText()).c_str()), 255u);
if (alpha > 255)
alpha = 255;
col.setAlpha(alpha); col.setAlpha(alpha);
} }
if (EditRed) if (EditRed)
{ {
u32 red = core::strtoul10(core::stringc(EditRed->getText()).c_str()); u32 red = core::min_(core::strtoul10(core::stringc(EditRed->getText()).c_str()), 255u);
if (red > 255)
red = 255;
col.setRed(red); col.setRed(red);
} }
if (EditGreen) if (EditGreen)
{ {
u32 green = core::strtoul10(core::stringc(EditGreen->getText()).c_str()); u32 green = core::min_(core::strtoul10(core::stringc(EditGreen->getText()).c_str()), 255u);
if (green > 255)
green = 255;
col.setGreen(green); col.setGreen(green);
} }
if (EditBlue) if (EditBlue)
{ {
u32 blue = core::strtoul10(core::stringc(EditBlue->getText()).c_str()); u32 blue = core::min_(core::strtoul10(core::stringc(EditBlue->getText()).c_str()), 255u);
if (blue > 255)
blue = 255;
col.setBlue(blue); col.setBlue(blue);
} }
return col; return col;
} }
// Fill the editfields with the value for the given color // Fill the editboxes with a color value
void CColorControl::setEditsFromColor(video::SColor col) void CColorControl::setEditsFromColor(video::SColor col)
{ {
DirtyFlag = true; DirtyFlag = true;
@ -345,10 +335,9 @@ CTextureControl::CTextureControl(gui::IGUIEnvironment* guiEnv, video::IVideoDriv
bool CTextureControl::OnEvent(const SEvent &event) bool CTextureControl::OnEvent(const SEvent &event)
{ {
if ( event.EventType != EET_GUI_EVENT ) if ( event.EventType == EET_GUI_EVENT
return false; && event.GUIEvent.Caller == ComboTexture
&& event.GUIEvent.EventType == gui::EGET_COMBO_BOX_CHANGED )
if ( event.GUIEvent.Caller == ComboTexture && event.GUIEvent.EventType == gui::EGET_COMBO_BOX_CHANGED )
{ {
DirtyFlag = true; DirtyFlag = true;
} }
@ -392,13 +381,15 @@ void CTextureControl::selectTextureByName(const irr::core::stringw& name)
void CTextureControl::updateTextures(video::IVideoDriver * driver) void CTextureControl::updateTextures(video::IVideoDriver * driver)
{ {
s32 oldSelected = ComboTexture->getSelected(); s32 oldSelected = ComboTexture->getSelected();
s32 selectNew = -1;
core::stringw oldTextureName; core::stringw oldTextureName;
if ( oldSelected >= 0 ) if ( oldSelected >= 0 )
{ {
oldTextureName = ComboTexture->getItem(oldSelected); oldTextureName = ComboTexture->getItem(oldSelected);
} }
ComboTexture->clear(); ComboTexture->clear();
s32 selectNew = -1;
for ( u32 i=0; i < driver->getTextureCount(); ++i ) for ( u32 i=0; i < driver->getTextureCount(); ++i )
{ {
video::ITexture * texture = driver->getTextureByIndex(i); video::ITexture * texture = driver->getTextureByIndex(i);
@ -422,60 +413,70 @@ void CTextureControl::updateTextures(video::IVideoDriver * driver)
/* /*
Control which allows setting some of the material values for a meshscenenode Control which allows setting some of the material values for a meshscenenode
*/ */
void CMaterialControl::init(scene::IMeshSceneNode* node, IrrlichtDevice * device, const core::position2d<s32> & pos, const wchar_t * description) void CMaterialControl::init(IrrlichtDevice * device, const core::position2d<s32> & pos, const wchar_t * description)
{ {
if ( Initialized || !node || !device) // initializing twice or with invalid data not allowed if ( Initialized || !device) // initializing twice or with invalid data not allowed
return; return;
Driver = device->getVideoDriver (); Driver = device->getVideoDriver ();
gui::IGUIEnvironment* guiEnv = device->getGUIEnvironment(); gui::IGUIEnvironment* guiEnv = device->getGUIEnvironment();
//scene::ISceneManager* smgr = device->getSceneManager();
const video::SMaterial & material = node->getMaterial(0);
s32 top = pos.Y; s32 top = pos.Y;
// Description // Description
guiEnv->addStaticText(description, core::rect<s32>(pos.X, top, pos.X+60, top+15), false, false, 0, -1, false); guiEnv->addStaticText(description, core::rect<s32>(pos.X, top, pos.X+150, top+15), true, false, 0, -1, true);
top += 15; top += 15;
// Control for material type // Control for material type
core::rect<s32> rectCombo(pos.X, top, 150, top+15); core::rect<s32> rectCombo(pos.X, top, pos.X+150, top+15);
top += 15; top += 15;
ComboMaterial = guiEnv->addComboBox (rectCombo); ComboMaterial = guiEnv->addComboBox (rectCombo);
for ( int i=0; i <= (int)video::EMT_ONETEXTURE_BLEND; ++i ) for ( int i=0; i <= (int)video::EMT_ONETEXTURE_BLEND; ++i )
{ {
ComboMaterial->addItem( core::stringw(video::sBuiltInMaterialTypeNames[i]).c_str() ); ComboMaterial->addItem( core::stringw(video::sBuiltInMaterialTypeNames[i]).c_str() );
} }
ComboMaterial->setSelected( (s32)material.MaterialType ); ComboMaterial->setSelected(0);
// Control to enable/disabling material lighting // Control to enable/disabling material lighting
core::rect<s32> rectBtn(core::position2d<s32>(pos.X, top), core::dimension2d<s32>(100, 15)); core::rect<s32> rectBtn(core::position2d<s32>(pos.X, top), core::dimension2d<s32>(100, 15));
top += 15; top += 15;
ButtonLighting = guiEnv->addButton (rectBtn, 0, -1, L"Lighting"); ButtonLighting = guiEnv->addButton (rectBtn, 0, -1, L"Lighting");
ButtonLighting->setIsPushButton(true); ButtonLighting->setIsPushButton(true);
ButtonLighting->setPressed(material.Lighting); core::rect<s32> rectInfo( rectBtn.LowerRightCorner.X, rectBtn.UpperLeftCorner.Y, rectBtn.LowerRightCorner.X+50, rectBtn.UpperLeftCorner.Y+15 );
core::rect<s32> rectInfo( rectBtn.LowerRightCorner.X, rectBtn.UpperLeftCorner.Y, rectBtn.LowerRightCorner.X+40, rectBtn.UpperLeftCorner.Y+15 );
InfoLighting = guiEnv->addStaticText(L"", rectInfo, true, false ); InfoLighting = guiEnv->addStaticText(L"", rectInfo, true, false );
InfoLighting->setTextAlignment(gui::EGUIA_CENTER, gui::EGUIA_CENTER ); InfoLighting->setTextAlignment(gui::EGUIA_CENTER, gui::EGUIA_CENTER );
// Controls for colors // Controls for colors
TypicalColorsControl = new CTypicalColorsControl(guiEnv, core::position2d<s32>(pos.X, top), true, guiEnv->getRootGUIElement()); TypicalColorsControl = new CTypicalColorsControl(guiEnv, core::position2d<s32>(pos.X, top), true, guiEnv->getRootGUIElement());
top += 300; top += 300;
TypicalColorsControl->setColorsToMaterialColors(material);
// Controls for selecting the material textures // Controls for selecting the material textures
guiEnv->addStaticText(L"Textures", core::rect<s32>(pos.X, top, pos.X+60, top+15), false, false, 0, -1, false); guiEnv->addStaticText(L"Textures", core::rect<s32>(pos.X, top, pos.X+150, top+15), true, false, 0, -1, true);
top += 15; top += 15;
for (irr::u32 i=0; i<irr::video::MATERIAL_MAX_TEXTURES; ++i) // The default material types only use first 2 textures
irr::u32 maxTextures = core::min_(2u, irr::video::MATERIAL_MAX_TEXTURES);
for (irr::u32 i=0; i<maxTextures; ++i)
{ {
TextureControls[i] = new CTextureControl(guiEnv, Driver, core::position2di(pos.X, top), guiEnv->getRootGUIElement()); TextureControls.push_back(new CTextureControl(guiEnv, Driver, core::position2di(pos.X, top), guiEnv->getRootGUIElement()));
top += 15; top += 15;
} }
Initialized = true; Initialized = true;
} }
void CMaterialControl::setMaterial(const irr::video::SMaterial & material)
{
if (ComboMaterial)
ComboMaterial->setSelected( (s32)material.MaterialType );
if (ButtonLighting)
ButtonLighting->setPressed(material.Lighting);
if (TypicalColorsControl)
TypicalColorsControl->setColorsToMaterialColors(material);
for (irr::u32 i=0; i<TextureControls.size(); ++i)
TextureControls[i]->setDirty();
}
void CMaterialControl::update(scene::IMeshSceneNode* sceneNode, scene::IMeshSceneNode* sceneNode2T, scene::IMeshSceneNode* sceneNodeTangents) void CMaterialControl::update(scene::IMeshSceneNode* sceneNode, scene::IMeshSceneNode* sceneNode2T, scene::IMeshSceneNode* sceneNodeTangents)
{ {
if ( !Initialized ) if ( !Initialized )
@ -525,19 +526,19 @@ void CMaterialControl::update(scene::IMeshSceneNode* sceneNode, scene::IMeshScen
TypicalColorsControl->resetDirty(); TypicalColorsControl->resetDirty();
for (irr::u32 i=0; i<irr::video::MATERIAL_MAX_TEXTURES; ++i) for (irr::u32 i=0; i<TextureControls.size(); ++i)
TextureControls[i]->resetDirty(); TextureControls[i]->resetDirty();
} }
void CMaterialControl::updateTextures() void CMaterialControl::updateTextures()
{ {
for (irr::u32 i=0; i<irr::video::MATERIAL_MAX_TEXTURES; ++i) for (irr::u32 i=0; i<TextureControls.size(); ++i)
TextureControls[i]->updateTextures(Driver); TextureControls[i]->updateTextures(Driver);
} }
void CMaterialControl::selectTextures(const irr::core::stringw& name) void CMaterialControl::selectTextures(const irr::core::stringw& name)
{ {
for (irr::u32 i=0; i<irr::video::MATERIAL_MAX_TEXTURES; ++i) for (irr::u32 i=0; i<TextureControls.size(); ++i)
TextureControls[i]->selectTextureByName(name); TextureControls[i]->selectTextureByName(name);
} }
@ -550,11 +551,11 @@ void CMaterialControl::updateMaterial(video::SMaterial & material)
{ {
TypicalColorsControl->updateMaterialColors(material); TypicalColorsControl->updateMaterialColors(material);
material.Lighting = ButtonLighting->isPressed(); material.Lighting = ButtonLighting->isPressed();
for (irr::u32 i=0; i<irr::video::MATERIAL_MAX_TEXTURES; ++i) for (irr::u32 i=0; i<TextureControls.size(); ++i)
{ {
if ( TextureControls[i]->isDirty() ) if ( TextureControls[i]->isDirty() )
{ {
material.TextureLayer[i].Texture = Driver->getTexture( io::path(TextureControls[i]->getSelectedTextureName()) ); material.TextureLayer[i].Texture = Driver->findTexture( io::path(TextureControls[i]->getSelectedTextureName()) );
} }
} }
} }
@ -568,8 +569,10 @@ void CLightNodeControl::init(scene::ILightSceneNode* node, gui::IGUIEnvironment*
if ( Initialized || !node || !guiEnv) // initializing twice or with invalid data not allowed if ( Initialized || !node || !guiEnv) // initializing twice or with invalid data not allowed
return; return;
guiEnv->addStaticText(description, core::rect<s32>(pos.X, pos.Y, pos.X+70, pos.Y+15), false, false, 0, -1, false); gui::IGUIStaticText* st = guiEnv->addStaticText(description, core::rect<s32>(pos.X, pos.Y, pos.X+80, pos.Y+15), true, false, 0, -1, true);
st->setAlignment(irr::gui::EGUIA_LOWERRIGHT, irr::gui::EGUIA_LOWERRIGHT, irr::gui::EGUIA_UPPERLEFT, irr::gui::EGUIA_UPPERLEFT);
TypicalColorsControl = new CTypicalColorsControl(guiEnv, core::position2d<s32>(pos.X, pos.Y+15), false, guiEnv->getRootGUIElement()); TypicalColorsControl = new CTypicalColorsControl(guiEnv, core::position2d<s32>(pos.X, pos.Y+15), false, guiEnv->getRootGUIElement());
TypicalColorsControl->setAlignment(irr::gui::EGUIA_LOWERRIGHT, irr::gui::EGUIA_LOWERRIGHT, irr::gui::EGUIA_UPPERLEFT, irr::gui::EGUIA_UPPERLEFT);
const video::SLight & lightData = node->getLightData(); const video::SLight & lightData = node->getLightData();
TypicalColorsControl->setColorsToLightDataColors(lightData); TypicalColorsControl->setColorsToLightDataColors(lightData);
Initialized = true; Initialized = true;
@ -588,9 +591,7 @@ void CLightNodeControl::update(scene::ILightSceneNode* node)
Main application class Main application class
*/ */
/* // Event handler
Event handler
*/
bool CApp::OnEvent(const SEvent &event) bool CApp::OnEvent(const SEvent &event)
{ {
if (event.EventType == EET_GUI_EVENT) if (event.EventType == EET_GUI_EVENT)
@ -618,13 +619,33 @@ bool CApp::OnEvent(const SEvent &event)
case gui::EGET_FILE_SELECTED: case gui::EGET_FILE_SELECTED:
{ {
// load the model file, selected in the file open dialog // load the texture file, selected in the file open dialog
gui::IGUIFileOpenDialog* dialog = gui::IGUIFileOpenDialog* dialog =
(gui::IGUIFileOpenDialog*)event.GUIEvent.Caller; (gui::IGUIFileOpenDialog*)event.GUIEvent.Caller;
loadTexture(io::path(dialog->getFileName()).c_str()); loadTexture(io::path(dialog->getFileName()).c_str());
} }
break; break;
case gui::EGET_COMBO_BOX_CHANGED:
if (event.GUIEvent.Caller == ComboMeshType )
{
irr::scene::IMeshSceneNode* currentNode = getVisibleMeshNode();
if (currentNode)
{
// ensure next mesh will get same color and material settings
if ( ControlVertexColors )
{
video::S3DVertex * vertices = (video::S3DVertex *)currentNode->getMesh()->getMeshBuffer(0)->getVertices();
ControlVertexColors->setColor(vertices[0].Color);
}
if ( MeshMaterialControl )
MeshMaterialControl->setMaterial(currentNode->getMaterial(0));
}
setActiveMeshNodeType((ENodeType)ComboMeshType->getSelected());
return true;
}
break;
default: default:
break; break;
} }
@ -702,44 +723,33 @@ bool CApp::init(int argc, char *argv[])
subMenuFile->addItem(L"Quit", GUI_ID_QUIT); subMenuFile->addItem(L"Quit", GUI_ID_QUIT);
// a static camera // a static camera
Camera = smgr->addCameraSceneNode (0, core::vector3df(0, 40, -40), Camera = smgr->addCameraSceneNode (0, core::vector3df(0, 30, -50),
core::vector3df(0, 10, 0), core::vector3df(0, 0, 0),
-1); -1);
// default material setActiveMeshNodeType(ENT_CUBE);
video::SMaterial defaultMaterial;
defaultMaterial.Shininess = 20.f;
// add the nodes which are used to show the materials
SceneNode = smgr->addCubeSceneNode (30.0f, 0, -1,
core::vector3df(0, 0, 0),
core::vector3df(0.f, 45.f, 0.f),
core::vector3df(1.0f, 1.0f, 1.0f));
SceneNode->getMaterial(0) = defaultMaterial;
const s32 controlsTop = 20; const s32 controlsTop = 20;
MeshMaterialControl = new CMaterialControl(); MeshMaterialControl = new CMaterialControl();
MeshMaterialControl->init( SceneNode, Device, core::position2d<s32>(10,controlsTop), L"Material" ); MeshMaterialControl->init( Device, core::position2d<s32>(10,controlsTop), L"Material");
MeshMaterialControl->setMaterial(SceneNode->getMaterial(0));
MeshMaterialControl->selectTextures(core::stringw("CARO_A8R8G8B8")); // set a useful default texture MeshMaterialControl->selectTextures(core::stringw("CARO_A8R8G8B8")); // set a useful default texture
// create nodes with other vertex types
scene::IMesh * mesh2T = MeshManipulator->createMeshWith2TCoords(SceneNode->getMesh());
SceneNode2T = smgr->addMeshSceneNode(mesh2T, 0, -1, SceneNode->getPosition(), SceneNode->getRotation(), SceneNode->getScale() );
mesh2T->drop();
scene::IMesh * meshTangents = MeshManipulator->createMeshWithTangents(SceneNode->getMesh(), false, false, false);
SceneNodeTangents = smgr->addMeshSceneNode(meshTangents, 0, -1
, SceneNode->getPosition(), SceneNode->getRotation(), SceneNode->getScale() );
meshTangents->drop();
// add one light // add one light
NodeLight = smgr->addLightSceneNode(0, core::vector3df(0, 0, -40), const f32 lightRadius = 80.f;
NodeLight = smgr->addLightSceneNode(0, core::vector3df(0, 30, -70),
video::SColorf(1.0f, 1.0f, 1.0f), video::SColorf(1.0f, 1.0f, 1.0f),
35.0f); lightRadius);
LightControl = new CLightNodeControl(); LightControl = new CLightNodeControl();
LightControl->init(NodeLight, guiEnv, core::position2d<s32>(550,controlsTop), L"Dynamic light" ); LightControl->init(NodeLight, guiEnv, core::position2d<s32>(550,controlsTop), L"Dynamic light" );
#if 0 // enable to have some visual feedback for the light size
scene::IMeshSceneNode* lightRadiusNode = smgr->addSphereSceneNode(lightRadius, 64, NodeLight);
lightRadiusNode->getMaterial(0).Lighting = false;
lightRadiusNode->getMaterial(0).Wireframe = true;
#endif
// one large cube around everything. That's mainly to make the light more obvious. // one large cube around everything. That's mainly to make the light more obvious.
scene::IMeshSceneNode* backgroundCube = smgr->addCubeSceneNode (200.0f, 0, -1, core::vector3df(0, 0, 0), scene::IMeshSceneNode* backgroundCube = smgr->addCubeSceneNode (200.0f, 0, -1, core::vector3df(0, 0, 0),
core::vector3df(45, 0, 0), core::vector3df(45, 0, 0),
@ -748,18 +758,21 @@ bool CApp::init(int argc, char *argv[])
backgroundCube->getMaterial(0).EmissiveColor.set(255,50,50,50); // we keep some self lighting to keep texts visible backgroundCube->getMaterial(0).EmissiveColor.set(255,50,50,50); // we keep some self lighting to keep texts visible
// Add a the mesh vertex color control // Add a the mesh UI controls
guiEnv->addStaticText(L"Mesh", core::rect<s32>(200, controlsTop, 270, controlsTop+15), false, false, 0, -1, false); gui::IGUIStaticText* stMesh = guiEnv->addStaticText(L"Mesh", core::rect<s32>(440, controlsTop, 520, controlsTop+15), true, false, 0, -1, true);
ControlVertexColors = new CColorControl( guiEnv, core::position2d<s32>(200, controlsTop+15), L"Vertex colors", guiEnv->getRootGUIElement()); stMesh->setAlignment(irr::gui::EGUIA_LOWERRIGHT, irr::gui::EGUIA_LOWERRIGHT, irr::gui::EGUIA_UPPERLEFT, irr::gui::EGUIA_UPPERLEFT);
video::S3DVertex * vertices = (video::S3DVertex *)SceneNode->getMesh()->getMeshBuffer(0)->getVertices(); ComboMeshType = guiEnv->addComboBox(core::rect<s32>(440, controlsTop+16, 520, controlsTop+30), 0, -1);
if ( vertices ) ComboMeshType->setAlignment(irr::gui::EGUIA_LOWERRIGHT, irr::gui::EGUIA_LOWERRIGHT, irr::gui::EGUIA_UPPERLEFT, irr::gui::EGUIA_UPPERLEFT);
{ ComboMeshType->addItem(L"cube");
ControlVertexColors->setColor(vertices[0].Color); ComboMeshType->addItem(L"sphere");
} ControlVertexColors = new CColorControl( guiEnv, core::position2d<s32>(440, controlsTop+30), L"Vertex colors", guiEnv->getRootGUIElement());
ControlVertexColors->setAlignment(irr::gui::EGUIA_LOWERRIGHT, irr::gui::EGUIA_LOWERRIGHT, irr::gui::EGUIA_UPPERLEFT, irr::gui::EGUIA_UPPERLEFT);
ControlVertexColors->setColor(irr::video::SColor(255,255,255,255));
// Add a control for ambient light // Add a control for ambient light
GlobalAmbient = new CColorControl( guiEnv, core::position2d<s32>(550, 300), L"Global ambient", guiEnv->getRootGUIElement()); GlobalAmbient = new CColorControl( guiEnv, core::position2d<s32>(550, 300), L"Global ambient", guiEnv->getRootGUIElement());
GlobalAmbient->setColor( smgr->getAmbientLight().toSColor() ); GlobalAmbient->setColor( smgr->getAmbientLight().toSColor() );
GlobalAmbient->setAlignment(irr::gui::EGUIA_LOWERRIGHT, irr::gui::EGUIA_LOWERRIGHT, irr::gui::EGUIA_UPPERLEFT, irr::gui::EGUIA_UPPERLEFT);
return true; return true;
} }
@ -769,15 +782,12 @@ bool CApp::init(int argc, char *argv[])
*/ */
bool CApp::update() bool CApp::update()
{ {
using namespace irr;
video::IVideoDriver* videoDriver = Device->getVideoDriver(); video::IVideoDriver* videoDriver = Device->getVideoDriver();
if ( !Device->run() ) if ( !Device->run() )
return false; return false;
// Figure out delta time since last frame // Figure out delta time since last frame
ITimer * timer = Device->getTimer(); u32 newTick = Device->getTimer()->getRealTime();
u32 newTick = timer->getRealTime();
f32 deltaTime = RealTimeTick > 0 ? f32(newTick-RealTimeTick)/1000.f : 0.f; // in seconds f32 deltaTime = RealTimeTick > 0 ? f32(newTick-RealTimeTick)/1000.f : 0.f; // in seconds
RealTimeTick = newTick; RealTimeTick = newTick;
@ -807,9 +817,16 @@ bool CApp::update()
GlobalAmbient->resetDirty(); GlobalAmbient->resetDirty();
} }
// Let the user move the light around
const float zoomSpeed = 10.f * deltaTime; const float zoomSpeed = 10.f * deltaTime;
const float rotationSpeed = 100.f * deltaTime; const float rotationSpeed = 100.f * deltaTime;
// Let the user move the light around
irr::gui::IGUIElement* focus=guiEnv->getFocus(); // some checks to prevent interfering with UI input
if ( !focus || focus == guiEnv->getRootGUIElement()
|| focus->getType() == irr::gui::EGUIET_STATIC_TEXT
|| focus->getType() == irr::gui::EGUIET_BUTTON
)
{
if ( KeysPressed[KEY_PLUS] || KeysPressed[KEY_ADD]) if ( KeysPressed[KEY_PLUS] || KeysPressed[KEY_ADD])
ZoomOut(NodeLight, zoomSpeed); ZoomOut(NodeLight, zoomSpeed);
if ( KeysPressed[KEY_MINUS] || KeysPressed[KEY_SUBTRACT]) if ( KeysPressed[KEY_MINUS] || KeysPressed[KEY_SUBTRACT])
@ -823,6 +840,7 @@ bool CApp::update()
RotateAroundAxis(NodeLight, rotationSpeed, LightRotationAxis); RotateAroundAxis(NodeLight, rotationSpeed, LightRotationAxis);
if ( KeysPressed[KEY_DOWN]) if ( KeysPressed[KEY_DOWN])
RotateAroundAxis(NodeLight, -rotationSpeed, LightRotationAxis); RotateAroundAxis(NodeLight, -rotationSpeed, LightRotationAxis);
}
// Let the user move the camera around // Let the user move the camera around
if (MousePressed) if (MousePressed)
@ -957,7 +975,7 @@ void CApp::createDefaultTextures(video::IVideoDriver * driver)
imageA8R8G8B8->drop(); imageA8R8G8B8->drop();
} }
// Load a texture and make sure nodes know it when more textures are available. // Load a texture and make sure UI knows it when more textures are available.
void CApp::loadTexture(const io::path &name) void CApp::loadTexture(const io::path &name)
{ {
Device->getVideoDriver()->getTexture(name); Device->getVideoDriver()->getTexture(name);
@ -1013,6 +1031,69 @@ void CApp::UpdateRotationAxis(irr::scene::ISceneNode* node, irr::core::vector3df
} }
} }
void CApp::setActiveMeshNodeType(ENodeType nodeType)
{
scene::ISceneManager* smgr = Device->getSceneManager();
if ( SceneNode )
smgr->addToDeletionQueue(SceneNode);
SceneNode = nullptr;
if ( SceneNode2T )
smgr->addToDeletionQueue(SceneNode2T);
SceneNode2T = nullptr;
if ( SceneNodeTangents )
smgr->addToDeletionQueue(SceneNodeTangents);
SceneNodeTangents = nullptr;
// default material
video::SMaterial defaultMaterial;
defaultMaterial.Shininess = 20.f;
// add the nodes which are used to show the materials
const irr::f32 size = 35.f;
if ( nodeType == ENT_CUBE)
{
SceneNode = smgr->addCubeSceneNode (size, 0, -1,
core::vector3df(0, 0, 0),
core::vector3df(0.f, 45.f, 0.f),
core::vector3df(1.0f, 1.0f, 1.0f),
scene::ECMT_1BUF_24VTX_NP);
// avoid wrong colored lines at cube-borders (uv's go from 0-1 currently, which does not work well with interpolation)
for ( u32 i=0; i < irr::video::MATERIAL_MAX_TEXTURES_USED; ++i)
{
defaultMaterial.TextureLayer[i].TextureWrapU = irr::video::ETC_CLAMP_TO_EDGE;
defaultMaterial.TextureLayer[i].TextureWrapV = irr::video::ETC_CLAMP_TO_EDGE;
}
}
else
{
SceneNode = smgr->addSphereSceneNode(size*0.5f);
}
SceneNode->getMaterial(0) = defaultMaterial;
// SceneNode->setDebugDataVisible(scene::EDS_NORMALS); // showing normals can sometimes be useful to understand what's going on
// create nodes with other vertex types
scene::IMesh * mesh2T = MeshManipulator->createMeshWith2TCoords(SceneNode->getMesh());
SceneNode2T = smgr->addMeshSceneNode(mesh2T, 0, -1, SceneNode->getPosition(), SceneNode->getRotation(), SceneNode->getScale() );
mesh2T->drop();
scene::IMesh * meshTangents = MeshManipulator->createMeshWithTangents(SceneNode->getMesh(), false, false, false);
SceneNodeTangents = smgr->addMeshSceneNode(meshTangents, 0, -1
, SceneNode->getPosition(), SceneNode->getRotation(), SceneNode->getScale() );
meshTangents->drop();
}
irr::scene::IMeshSceneNode* CApp::getVisibleMeshNode() const
{
if ( SceneNode && SceneNode->isVisible() )
return SceneNode;
if ( SceneNode2T && SceneNode2T->isVisible() )
return SceneNode2T;
if ( SceneNodeTangents && SceneNodeTangents->isVisible() )
return SceneNodeTangents;
return nullptr;
}
/* /*
Short main as most is done in classes. Short main as most is done in classes.
*/ */

@ -110,6 +110,12 @@ public:
// Change active selectionbased on the texture name // Change active selectionbased on the texture name
void selectTextureByName(const irr::core::stringw& name); void selectTextureByName(const irr::core::stringw& name);
// Set dirty flag (node will update texture)
void setDirty()
{
DirtyFlag = true;
}
// Reset the dirty flag // Reset the dirty flag
void resetDirty() void resetDirty()
{ {
@ -140,15 +146,12 @@ public:
CMaterialControl() CMaterialControl()
: Initialized(false), Driver(0) : Initialized(false), Driver(0)
, TypicalColorsControl(0), ButtonLighting(0), InfoLighting(0), ComboMaterial(0) , TypicalColorsControl(0), ButtonLighting(0), InfoLighting(0), ComboMaterial(0)
{ {}
for (irr::u32 i=0; i<irr::video::MATERIAL_MAX_TEXTURES; ++i)
TextureControls[i] = 0;
}
// Destructor // Destructor
~CMaterialControl() ~CMaterialControl()
{ {
for (irr::u32 i=0; i<irr::video::MATERIAL_MAX_TEXTURES; ++i) for (irr::u32 i=0; i<TextureControls.size(); ++i)
{ {
if (TextureControls[i] ) if (TextureControls[i] )
TextureControls[i]->drop(); TextureControls[i]->drop();
@ -157,7 +160,9 @@ public:
TypicalColorsControl->drop(); TypicalColorsControl->drop();
} }
void init(irr::scene::IMeshSceneNode* node, irr::IrrlichtDevice * device, const irr::core::position2d<irr::s32> & pos, const wchar_t * description); void init(irr::IrrlichtDevice * device, const irr::core::position2d<irr::s32> & pos, const wchar_t * description);
void setMaterial(const irr::video::SMaterial & material);
void update(irr::scene::IMeshSceneNode* sceneNode, irr::scene::IMeshSceneNode* sceneNode2T, irr::scene::IMeshSceneNode* sceneNodeTangents); void update(irr::scene::IMeshSceneNode* sceneNode, irr::scene::IMeshSceneNode* sceneNode2T, irr::scene::IMeshSceneNode* sceneNodeTangents);
@ -177,7 +182,7 @@ protected:
irr::gui::IGUIButton * ButtonLighting; irr::gui::IGUIButton * ButtonLighting;
irr::gui::IGUIStaticText* InfoLighting; irr::gui::IGUIStaticText* InfoLighting;
irr::gui::IGUIComboBox * ComboMaterial; irr::gui::IGUIComboBox * ComboMaterial;
CTextureControl* TextureControls[irr::video::MATERIAL_MAX_TEXTURES]; irr::core::array<CTextureControl*> TextureControls;
}; };
/* /*
@ -242,6 +247,7 @@ public:
, LightRotationAxis(irr::core::vector3df(1,0,0)) , LightRotationAxis(irr::core::vector3df(1,0,0))
, MeshMaterialControl(0) , MeshMaterialControl(0)
, LightControl(0) , LightControl(0)
, ComboMeshType(0)
, ControlVertexColors(0) , ControlVertexColors(0)
, GlobalAmbient(0) , GlobalAmbient(0)
, MousePressed(false) , MousePressed(false)
@ -293,6 +299,14 @@ protected:
void ZoomOut(irr::scene::ISceneNode* node, irr::f32 units); void ZoomOut(irr::scene::ISceneNode* node, irr::f32 units);
void UpdateRotationAxis(irr::scene::ISceneNode* node, irr::core::vector3df& axis); void UpdateRotationAxis(irr::scene::ISceneNode* node, irr::core::vector3df& axis);
enum ENodeType
{
ENT_CUBE,
ENT_SPHERE
};
void setActiveMeshNodeType(ENodeType nodeType);
irr::scene::IMeshSceneNode* getVisibleMeshNode() const;
private: private:
SConfig Config; SConfig Config;
@ -309,6 +323,7 @@ private:
irr::core::vector3df LightRotationAxis; irr::core::vector3df LightRotationAxis;
CMaterialControl* MeshMaterialControl; CMaterialControl* MeshMaterialControl;
CLightNodeControl* LightControl; CLightNodeControl* LightControl;
irr::gui::IGUIComboBox* ComboMeshType;
CColorControl* ControlVertexColors; CColorControl* ControlVertexColors;
CColorControl* GlobalAmbient; CColorControl* GlobalAmbient;
bool KeysPressed[irr::KEY_KEY_CODES_COUNT]; bool KeysPressed[irr::KEY_KEY_CODES_COUNT];

@ -12,7 +12,7 @@ IrrlichtHome := ../..
BinPath = ../../bin/$(SYSTEM) BinPath = ../../bin/$(SYSTEM)
# general compiler settings (might need to be set when compiling the lib, too) # general compiler settings (might need to be set when compiling the lib, too)
CPPFLAGS += -I$(IrrlichtHome)/include -I/usr/X11R6/include CPPFLAGS += -I$(IrrlichtHome)/include
ifndef NDEBUG ifndef NDEBUG
CXXFLAGS += -g -Wall CXXFLAGS += -g -Wall
else else

@ -12,7 +12,7 @@ IrrlichtHome := ../..
BinPath = ../../bin/$(SYSTEM) BinPath = ../../bin/$(SYSTEM)
# general compiler settings (might need to be set when compiling the lib, too) # general compiler settings (might need to be set when compiling the lib, too)
CPPFLAGS += -I$(IrrlichtHome)/include -I/usr/X11R6/include CPPFLAGS += -I$(IrrlichtHome)/include
ifndef NDEBUG ifndef NDEBUG
CXXFLAGS += -g -Wall CXXFLAGS += -g -Wall
else else

@ -1,6 +1,6 @@
/** Example 024 CursorControl /** Example 024 CursorControl
Show how to modify cursors and offer some useful tool-functions for creating cursors. Show how to modify cursors and offer some useful tool functions for creating cursors.
It can also be used for experiments with the mouse in general. It can also be used for experiments with the mouse in general.
*/ */
@ -142,7 +142,7 @@ void PrintMouseEventName(const SEvent& event, stringw &result)
} }
/* /*
Helper function to print all the state information which get from a mouse-event into a stringw Helper function to print all the state information from a mouse event into a stringw
*/ */
void PrintMouseState(const SEvent& event, stringw &result) void PrintMouseState(const SEvent& event, stringw &result)
{ {
@ -295,6 +295,17 @@ public:
} }
} }
if ( event.EventType == EET_KEY_INPUT_EVENT)
{
// Allow invisible cursor to show up again when users presses ESC
if ( !event.KeyInput.PressedDown && event.KeyInput.Key == irr::KEY_ESCAPE )
{
TimerAction action;
action.Action = ETA_MOUSE_VISIBLE;
Context.runTimerAction(action);
}
}
return false; return false;
} }
@ -303,7 +314,7 @@ private:
}; };
/* /*
Use several imagefiles as animation frames for a sprite which can be used as cursor icon. Use several image files as animation frames for a sprite which can then be used as a cursor icon.
The images in those files all need to have the same size. The images in those files all need to have the same size.
Return sprite index on success or -1 on failure Return sprite index on success or -1 on failure
*/ */
@ -345,7 +356,7 @@ s32 AddAnimatedIconToSpriteBank( gui::IGUISpriteBank * spriteBank, video::IVideo
} }
/* /*
Use several images within one imagefile as animation frames for a sprite which can be used as cursor icon Use several images within one image file as animation frames for a sprite which can then be used as a cursor icon
The sizes of the icons within that file all need to have the same size The sizes of the icons within that file all need to have the same size
Return sprite index on success or -1 on failure Return sprite index on success or -1 on failure
*/ */
@ -433,8 +444,6 @@ int main()
video::IVideoDriver* driver = device->getVideoDriver(); video::IVideoDriver* driver = device->getVideoDriver();
IGUIEnvironment* env = device->getGUIEnvironment(); IGUIEnvironment* env = device->getGUIEnvironment();
gui::IGUISpriteBank * SpriteBankIcons;
SAppContext context; SAppContext context;
context.Device = device; context.Device = device;
@ -443,23 +452,24 @@ int main()
rectInfoStatic.UpperLeftCorner += dimension2di(0, 15); rectInfoStatic.UpperLeftCorner += dimension2di(0, 15);
context.InfoStatic = env->addStaticText (L"", rectInfoStatic, true, true); context.InfoStatic = env->addStaticText (L"", rectInfoStatic, true, true);
rect< s32 > rectEventBox(10,210, 200, 400); rect< s32 > rectEventBox(10,210, 200, 400);
env->addStaticText (L"click events (new on top)", rectEventBox, true, true); env->addStaticText (L"Click events (new on top)", rectEventBox, true, true);
rectEventBox.UpperLeftCorner += dimension2di(0, 15); rectEventBox.UpperLeftCorner += dimension2di(0, 15);
context.EventBox = env->addListBox(rectEventBox); context.EventBox = env->addListBox(rectEventBox);
rect< s32 > rectCursorBox(210,10, 400, 250); rect< s32 > rectCursorBox(210,10, 400, 250);
env->addStaticText (L"cursors, click to set the active one", rectCursorBox, true, true); env->addStaticText (L"Cursors, click to set the active one", rectCursorBox, true, true);
rectCursorBox.UpperLeftCorner += dimension2di(0, 15); rectCursorBox.UpperLeftCorner += dimension2di(0, 15);
context.CursorBox = env->addListBox(rectCursorBox); context.CursorBox = env->addListBox(rectCursorBox);
rect< s32 > rectSpriteBox(210,260, 400, 400); rect< s32 > rectSpriteBox(210,260, 400, 400);
env->addStaticText (L"sprites", rectSpriteBox, true, true); env->addStaticText (L"Sprites", rectSpriteBox, true, true);
rectSpriteBox.UpperLeftCorner += dimension2di(0, 15); rectSpriteBox.UpperLeftCorner += dimension2di(0, 15);
context.SpriteBox = env->addListBox(rectSpriteBox); context.SpriteBox = env->addListBox(rectSpriteBox);
context.ButtonSetVisible = env->addButton( rect<s32>( 410, 20, 560, 40 ), 0, -1, L"set visible (delayed)" ); context.ButtonSetVisible = env->addButton( rect<s32>( 410, 20, 560, 40 ), 0, -1, L"Set visible (delayed)" );
context.ButtonSetInvisible = env->addButton( rect<s32>( 410, 50, 560, 70 ), 0, -1, L"set invisible (delayed)" ); context.ButtonSetInvisible = env->addButton( rect<s32>( 410, 50, 560, 70 ), 0, -1, L"Set invisible (delayed)" );
context.ButtonSimulateBadFps = env->addButton( rect<s32>( 410, 80, 560, 100 ), 0, -1, L"simulate bad FPS" ); context.ButtonSimulateBadFps = env->addButton( rect<s32>( 410, 80, 560, 100 ), 0, -1, L"Simulate bad FPS" );
context.ButtonSimulateBadFps->setIsPushButton(true); context.ButtonSimulateBadFps->setIsPushButton(true);
context.ButtonChangeIcon = env->addButton( rect<s32>( 410, 140, 560, 160 ), 0, -1, L"replace cursor icon\n(cursor+sprite must be selected)" ); s32 t = context.SpriteBox->getAbsolutePosition().UpperLeftCorner.Y;
context.ButtonChangeIcon = env->addButton( rect<s32>( 410, t, 560, t+20), 0, -1, L"Replace cursor icon\n(cursor+sprite must be selected)" );
// set the names for all the system cursors // set the names for all the system cursors
for ( int i=0; i < (int)gui::ECI_COUNT; ++i ) for ( int i=0; i < (int)gui::ECI_COUNT; ++i )
@ -470,7 +480,7 @@ int main()
/* /*
Create sprites which then can be used as cursor icons. Create sprites which then can be used as cursor icons.
*/ */
SpriteBankIcons = env->addEmptySpriteBank(io::path("cursor_icons")); gui::IGUISpriteBank * SpriteBankIcons = env->addEmptySpriteBank(io::path("cursor_icons"));
context.SpriteBox->setSpriteBank(SpriteBankIcons); context.SpriteBox->setSpriteBank(SpriteBankIcons);
const io::path mediaPath = getExampleMediaPath(); const io::path mediaPath = getExampleMediaPath();
@ -546,7 +556,8 @@ int main()
driver->endScene(); driver->endScene();
} }
// By simulating bad fps we can find out if hardware-support for cursors works or not. If it works the cursor will move as usual,while it otherwise will just update with 2 fps now. // By simulating a bad frame rate we can find out if hardware support for cursors works or not.
// If it works the cursor will move as usual, otherwise it will update with only 2 fps when SimulateBadFps is true.
if ( context.SimulateBadFps ) if ( context.SimulateBadFps )
{ {
device->sleep(500); // 2 fps device->sleep(500); // 2 fps

@ -12,7 +12,7 @@ IrrlichtHome := ../..
BinPath = ../../bin/$(SYSTEM) BinPath = ../../bin/$(SYSTEM)
# general compiler settings (might need to be set when compiling the lib, too) # general compiler settings (might need to be set when compiling the lib, too)
CPPFLAGS += -I$(IrrlichtHome)/include -I/usr/X11R6/include CPPFLAGS += -I$(IrrlichtHome)/include
ifndef NDEBUG ifndef NDEBUG
CXXFLAGS += -g -Wall CXXFLAGS += -g -Wall
else else

@ -224,7 +224,7 @@ public:
// Get setting as string // Get setting as string
stringw getSetting(const stringw& key) const stringw getSetting(const stringw& key) const
{ {
//the find function or irrmap returns a pointer to a map Node //the find function of irr::map returns a pointer to a map::Node
//if the key can be found, otherwise it returns null //if the key can be found, otherwise it returns null
//the map node has the function getValue and getKey, as we already know the key, we return node->getValue() //the map node has the function getValue and getKey, as we already know the key, we return node->getValue()
map<stringw, stringw>::Node* n = SettingMap.find(key); map<stringw, stringw>::Node* n = SettingMap.find(key);
@ -263,7 +263,7 @@ private:
map<stringw, stringw> SettingMap; //current config map<stringw, stringw> SettingMap; //current config
stringw SettingsFile; // location of the xml, usually the stringw SettingsFile; // filename of the xml
irr::IrrlichtDevice* NullDevice; irr::IrrlichtDevice* NullDevice;
}; };
@ -338,7 +338,7 @@ public:
if (App.Settings->save()) if (App.Settings->save())
{ {
App.Gui->addMessageBox(L"settings save",L"settings saved, please restart for settings to change effect","",true); App.Gui->addMessageBox(L"Settings saved",L"Settings saved, please restart for settings to change effect","",true);
} }
} }
// cancel/exit button clicked, tell the application to exit // cancel/exit button clicked, tell the application to exit
@ -375,7 +375,7 @@ void createSettingsDialog(SAppContext& app)
app.Gui->getSkin()->setColor((irr::gui::EGUI_DEFAULT_COLOR)i, col); app.Gui->getSkin()->setColor((irr::gui::EGUI_DEFAULT_COLOR)i, col);
} }
//create video settings windows //create video settings window
gui::IGUIWindow* windowSettings = app.Gui->addWindow(rect<s32>(10,10,400,400),true,L"Videosettings"); gui::IGUIWindow* windowSettings = app.Gui->addWindow(rect<s32>(10,10,400,400),true,L"Videosettings");
app.Gui->addStaticText (L"Select your desired video settings", rect< s32 >(10,20, 200, 40), false, true, windowSettings); app.Gui->addStaticText (L"Select your desired video settings", rect< s32 >(10,20, 200, 40), false, true, windowSettings);
@ -434,7 +434,7 @@ int main()
param.WindowSize.set(640,480); param.WindowSize.set(640,480);
// Try to load config. // Try to load config.
// I leave it as an exercise of the reader to store the configuration in the local application data folder, // I leave it as an exercise for the reader to store the configuration in the local application data folder,
// the only logical place to store config data for games. For all other operating systems I redirect to your manuals // the only logical place to store config data for games. For all other operating systems I redirect to your manuals
app.Settings = new SettingManager(getExampleMediaPath() + "settings.xml"); app.Settings = new SettingManager(getExampleMediaPath() + "settings.xml");
if ( !app.Settings->load() ) if ( !app.Settings->load() )
@ -448,7 +448,7 @@ int main()
//settings xml loaded from disk, //settings xml loaded from disk,
//map driversetting to driver type and test if the setting is valid //map driversetting to driver type and test if the setting is valid
//the DriverOptions map contains string representations mapped to to irrlicht E_DRIVER_TYPE enum //the DriverOptions map contains string representations mapped to to Irrlicht E_DRIVER_TYPE enum
//e.g "direct3d9" will become 4 //e.g "direct3d9" will become 4
//see DriverOptions in the settingmanager class for details //see DriverOptions in the settingmanager class for details
map<stringw, s32>::Node* driver = app.Settings->DriverOptions.find( app.Settings->getSetting("driver") ); map<stringw, s32>::Node* driver = app.Settings->DriverOptions.find( app.Settings->getSetting("driver") );

@ -12,7 +12,7 @@ IrrlichtHome := ../..
BinPath = ../../bin/$(SYSTEM) BinPath = ../../bin/$(SYSTEM)
# general compiler settings (might need to be set when compiling the lib, too) # general compiler settings (might need to be set when compiling the lib, too)
CPPFLAGS += -I$(IrrlichtHome)/include -I/usr/X11R6/include CPPFLAGS += -I$(IrrlichtHome)/include
ifndef NDEBUG ifndef NDEBUG
CXXFLAGS += -g -Wall CXXFLAGS += -g -Wall
else else

@ -5,7 +5,7 @@ Target = 27.PostProcessing
Sources = main.cpp Sources = main.cpp
# general compiler settings # general compiler settings
CPPFLAGS = -I../../include -I/usr/X11R6/include CPPFLAGS = -I../../include
CXXFLAGS = -O3 -ffast-math CXXFLAGS = -O3 -ffast-math
#CXXFLAGS = -g -Wall #CXXFLAGS = -g -Wall

@ -5,7 +5,7 @@ Target = 28.CubeMapping
Sources = main.cpp Sources = main.cpp
# general compiler settings # general compiler settings
CPPFLAGS = -I../../include -I/usr/X11R6/include CPPFLAGS = -I../../include
CXXFLAGS = -O3 -ffast-math CXXFLAGS = -O3 -ffast-math
#CXXFLAGS = -g -Wall #CXXFLAGS = -g -Wall

@ -12,7 +12,7 @@ IrrlichtHome := ../..
BinPath = ../../bin/$(SYSTEM) BinPath = ../../bin/$(SYSTEM)
# general compiler settings (might need to be set when compiling the lib, too) # general compiler settings (might need to be set when compiling the lib, too)
CPPFLAGS += -I$(IrrlichtHome)/include -I/usr/X11R6/include CPPFLAGS += -I$(IrrlichtHome)/include
ifndef NDEBUG ifndef NDEBUG
CXXFLAGS += -g -Wall CXXFLAGS += -g -Wall
else else

@ -12,7 +12,7 @@ IrrlichtHome := ../..
BinPath = ../../bin/$(SYSTEM) BinPath = ../../bin/$(SYSTEM)
# general compiler settings (might need to be set when compiling the lib, too) # general compiler settings (might need to be set when compiling the lib, too)
CPPFLAGS += -I$(IrrlichtHome)/include -I/usr/X11R6/include CPPFLAGS += -I$(IrrlichtHome)/include
ifndef NDEBUG ifndef NDEBUG
CXXFLAGS += -g -Wall CXXFLAGS += -g -Wall
else else

@ -14,7 +14,7 @@ namespace irr
{ {
namespace scene namespace scene
{ {
//! Implementation of the IMeshBuffer interface for which can work with 16 and 32 bit indices as well as different vertex types
class CDynamicMeshBuffer: public IDynamicMeshBuffer class CDynamicMeshBuffer: public IDynamicMeshBuffer
{ {
public: public:
@ -114,6 +114,46 @@ namespace scene
return PrimitiveType; return PrimitiveType;
} }
//! Returns type of the class implementing the IMeshBuffer
virtual EMESH_BUFFER_TYPE getType() const IRR_OVERRIDE
{
return EMBT_DYNAMIC;
}
//! Create copy of the meshbuffer
virtual IMeshBuffer* createClone(int cloneFlags) const IRR_OVERRIDE
{
CDynamicMeshBuffer* clone = new CDynamicMeshBuffer(VertexBuffer->getType(), IndexBuffer->getType());
if (cloneFlags & ECF_VERTICES)
{
const u32 numVertices = VertexBuffer->size();
clone->VertexBuffer->reallocate(numVertices);
for ( u32 i=0; i<numVertices; ++i )
{
clone->VertexBuffer->push_back((*VertexBuffer)[i]);
}
clone->BoundingBox = BoundingBox;
}
if (cloneFlags & ECF_INDICES)
{
const u32 numIndices = IndexBuffer->size();
clone->IndexBuffer->reallocate(numIndices);
for ( u32 i=0; i<numIndices; ++i )
{
clone->IndexBuffer->push_back((*IndexBuffer)[i]);
}
}
clone->VertexBuffer->setHardwareMappingHint(VertexBuffer->getHardwareMappingHint());
clone->IndexBuffer->setHardwareMappingHint(clone->IndexBuffer->getHardwareMappingHint());
clone->Material = Material;
clone->PrimitiveType = PrimitiveType;
return clone;
}
video::SMaterial Material; video::SMaterial Material;
core::aabbox3d<f32> BoundingBox; core::aabbox3d<f32> BoundingBox;
//! Primitive type used for rendering (triangles, lines, ...) //! Primitive type used for rendering (triangles, lines, ...)

@ -12,7 +12,7 @@ namespace irr
{ {
namespace scene namespace scene
{ {
//! Template implementation of the IMeshBuffer interface //! Template implementation of the IMeshBuffer interface for 16-bit buffers
template <class T> template <class T>
class CMeshBuffer : public IMeshBuffer class CMeshBuffer : public IMeshBuffer
{ {
@ -193,8 +193,8 @@ namespace scene
Vertices.reallocate(vertexCount+numVertices); Vertices.reallocate(vertexCount+numVertices);
for (i=0; i<numVertices; ++i) for (i=0; i<numVertices; ++i)
{ {
Vertices.push_back(reinterpret_cast<const T*>(vertices)[i]); Vertices.push_back(static_cast<const T*>(vertices)[i]);
BoundingBox.addInternalPoint(reinterpret_cast<const T*>(vertices)[i].Pos); BoundingBox.addInternalPoint(static_cast<const T*>(vertices)[i].Pos);
} }
Indices.reallocate(getIndexCount()+numIndices); Indices.reallocate(getIndexCount()+numIndices);
@ -286,6 +286,41 @@ namespace scene
/** This shouldn't be used for anything outside the VideoDriver. */ /** This shouldn't be used for anything outside the VideoDriver. */
virtual u32 getChangedID_Index() const IRR_OVERRIDE {return ChangedID_Index;} virtual u32 getChangedID_Index() const IRR_OVERRIDE {return ChangedID_Index;}
//! Returns type of the class implementing the IMeshBuffer
virtual EMESH_BUFFER_TYPE getType() const IRR_OVERRIDE
{
return getTypeT();
}
//! Create copy of the meshbuffer
virtual IMeshBuffer* createClone(int cloneFlags) const IRR_OVERRIDE
{
CMeshBuffer<T> * clone = new CMeshBuffer<T>();
if (cloneFlags & ECF_VERTICES)
{
clone->Vertices = Vertices;
clone->BoundingBox = BoundingBox;
}
if (cloneFlags & ECF_INDICES)
{
clone->Indices = Indices;
}
clone->PrimitiveType = PrimitiveType;
clone->Material = getMaterial();
clone->MappingHint_Vertex = MappingHint_Vertex;
clone->MappingHint_Index = MappingHint_Index;
return clone;
}
//! Returns type of the class implementing the IMeshBuffer for template specialization
// Minor note: Some compilers (VS) allow directly specializing the virtual function,
// but this will fail on other compilers (GCC). So using a helper function.
EMESH_BUFFER_TYPE getTypeT() const;
u32 ChangedID_Vertex; u32 ChangedID_Vertex;
u32 ChangedID_Index; u32 ChangedID_Index;
@ -311,6 +346,25 @@ namespace scene
typedef CMeshBuffer<video::S3DVertex2TCoords> SMeshBufferLightMap; typedef CMeshBuffer<video::S3DVertex2TCoords> SMeshBufferLightMap;
//! Meshbuffer with vertices having tangents stored, e.g. for normal mapping //! Meshbuffer with vertices having tangents stored, e.g. for normal mapping
typedef CMeshBuffer<video::S3DVertexTangents> SMeshBufferTangents; typedef CMeshBuffer<video::S3DVertexTangents> SMeshBufferTangents;
//! partial specialization to return types
template <>
inline EMESH_BUFFER_TYPE CMeshBuffer<video::S3DVertex>::getTypeT() const
{
return EMBT_STANDARD;
}
template <>
inline EMESH_BUFFER_TYPE CMeshBuffer<video::S3DVertex2TCoords>::getTypeT() const
{
return EMBT_LIGHTMAP;
}
template <>
inline EMESH_BUFFER_TYPE CMeshBuffer<video::S3DVertexTangents>::getTypeT() const
{
return EMBT_TANGENTS;
}
} // end namespace scene } // end namespace scene
} // end namespace irr } // end namespace irr

@ -73,7 +73,7 @@ namespace video
EMT_SPHERE_MAP, EMT_SPHERE_MAP,
//! A reflecting material with an optional non reflecting texture layer. //! A reflecting material with an optional non reflecting texture layer.
/** The reflection map should be set as first texture. */ /** The reflection map should be set as second texture. */
EMT_REFLECTION_2_LAYER, EMT_REFLECTION_2_LAYER,
//! A transparent material. //! A transparent material.

@ -0,0 +1,44 @@
// This file is part of the "Irrlicht Engine".
// For conditions of distribution and use, see copyright notice in irrlicht.h
#ifndef IRR_E_MESH_BUFFER_TYPES_H_INCLUDED
#define IRR_E_MESH_BUFFER_TYPES_H_INCLUDED
#include "irrTypes.h"
namespace irr
{
namespace scene
{
//! An enumeration for all types of built-in mesh buffers
/** Types are represented by a four character code instead
of simple numbers (easier to add external classes). */
enum EMESH_BUFFER_TYPE
{
//! SMeshBuffer (16 bit buffers)
EMBT_STANDARD = MAKE_IRR_ID('s','t','a','n'),
//! SMeshBufferLightMap (16 bit buffers)
EMBT_LIGHTMAP = MAKE_IRR_ID('l','i','g','h'),
//! SMeshBufferTangents (16 bit buffers)
EMBT_TANGENTS = MAKE_IRR_ID('t','a','n','g'),
//! CDynamicMeshBuffer (16 or 32 bit buffers)
EMBT_DYNAMIC = MAKE_IRR_ID('d','y','n','a'),
// SSharedMeshBuffer
EMBT_SHARED = MAKE_IRR_ID('s','h','a','r'),
// SSkinMeshBuffer
EMBT_SKIN = MAKE_IRR_ID('s','k','i','n'),
//! Unknown class type
EMBT_UNKNOWN = MAKE_IRR_ID('u','n','k','n')
};
} // end namespace scene
} // end namespace irr
#endif

@ -12,6 +12,7 @@ namespace irr
namespace scene namespace scene
{ {
class ICameraSceneNode; class ICameraSceneNode;
class IMeshBuffer;
//! A billboard scene node. //! A billboard scene node.
/** A billboard is like a 3d sprite: A 2d element, /** A billboard is like a 3d sprite: A 2d element,
@ -74,6 +75,17 @@ public:
That is why the usual getBoundingBox will return a "safe" boundingbox which is guaranteed That is why the usual getBoundingBox will return a "safe" boundingbox which is guaranteed
to contain the billboard. While this function can return the real one. */ to contain the billboard. While this function can return the real one. */
virtual const core::aabbox3d<f32>& getTransformedBillboardBoundingBox(const irr::scene::ICameraSceneNode* camera) = 0; virtual const core::aabbox3d<f32>& getTransformedBillboardBoundingBox(const irr::scene::ICameraSceneNode* camera) = 0;
//! Get the amount of mesh buffers.
/** \return Amount of mesh buffers (IMeshBuffer) in this mesh. */
virtual u32 getMeshBufferCount() const = 0;
//! Get pointer to a mesh buffer.
/** NOTE: Positions and normals of this meshbuffers are re-calculated before rendering.
So this is mainly useful to access/modify the uv-coordinates.
\param nr: Zero based index of the mesh buffer.
\return Pointer to the mesh buffer or 0 if there is no such mesh buffer. */
virtual IMeshBuffer* getMeshBuffer(u32 nr) const = 0;
}; };
} // end namespace scene } // end namespace scene

@ -24,15 +24,31 @@ namespace scene
{ {
//! Single buffer with 12 different vertices, normals are average of adjacent planes //! Single buffer with 12 different vertices, normals are average of adjacent planes
//! Order for outgoing (front-face) normals of planes would be: NEG_Z, POS_X, POS_Z, NEG_X, POS_Y, NEG_Y //! Order for outgoing (front-face) normals of planes would be: NEG_Z, POS_X, POS_Z, NEG_X, POS_Y, NEG_Y
//! This was the only available type before Irrlicht 1.9, so it's still the default in some functions.
//! It has the least vertices, but is pretty much unusable if you have dynamic light
ECMT_1BUF_12VTX_NA, ECMT_1BUF_12VTX_NA,
//! One buffer per side, each with 4 vertices, normals are perpendicular to sides //! One buffer per side, each with 4 vertices, normals are perpendicular to sides
//! Note: You probably will have to scale down your texture uv's to avoid white lines at borders //! You can use this one if you need different texture on each cube side
// as this mesh sets them to 0,1 values. We can't do that when creating the mesh as it ECMT_6BUF_4VTX_NP,
// depends on texture resolution which we don't know at that point.
ECMT_6BUF_4VTX_NP //! Single buffer with 24 different vertices, normals are perpendicular to sides
ECMT_1BUF_24VTX_NP,
//! not used, counts the number of enumerated types
ECMT_COUNT
}; };
//! Names for ECUBE_MESH_TYPE
const c8* const CubeMeshTypeNames[ECMT_COUNT+1] =
{
"1BUF_12VTX_NA",
"ECMT_6BUF_4VTX_NP",
"1BUF_24VTX_NP",
0
};
//! Helper class for creating geometry on the fly. //! Helper class for creating geometry on the fly.
/** You can get an instance of this class through ISceneManager::getGeometryCreator() */ /** You can get an instance of this class through ISceneManager::getGeometryCreator() */
class IGeometryCreator : public IReferenceCounted class IGeometryCreator : public IReferenceCounted
@ -44,6 +60,9 @@ public:
\param size Dimensions of the cube. \param size Dimensions of the cube.
\param type One of ECUBE_MESH_TYPE. So you can chose between cubes with single material or independent materials per side. \param type One of ECUBE_MESH_TYPE. So you can chose between cubes with single material or independent materials per side.
\return Generated mesh. \return Generated mesh.
Note: UV's go always from 0 to 1. Which can produce wrong colors at edges with texture filtering.
Fixing UV's depends on texture-size (have to be moved half a pixel towards the inside, so 0.5f/texure_size as then the pixel center is exactly on the border)
Easier solution is usually to set TextureWrapU and TextureWrapV to ETC_CLAMP_TO_EDGE in the Material.
*/ */
virtual IMesh* createCubeMesh(const core::vector3df& size=core::vector3df(5.f,5.f,5.f), ECUBE_MESH_TYPE type = ECMT_1BUF_12VTX_NA) const =0; virtual IMesh* createCubeMesh(const core::vector3df& size=core::vector3df(5.f,5.f,5.f), ECUBE_MESH_TYPE type = ECMT_1BUF_12VTX_NA) const =0;

@ -74,7 +74,6 @@ public:
//! Returns bits per pixel. //! Returns bits per pixel.
u32 getBitsPerPixel() const u32 getBitsPerPixel() const
{ {
return getBitsPerPixelFromFormat(Format); return getBitsPerPixelFromFormat(Format);
} }
@ -359,6 +358,11 @@ public:
/** NOTE: mipmaps are ignored */ /** NOTE: mipmaps are ignored */
virtual void copyToScalingBoxFilter(IImage* target, s32 bias = 0, bool blend = false) = 0; virtual void copyToScalingBoxFilter(IImage* target, s32 bias = 0, bool blend = false) = 0;
//! Flips (mirrors) the image in one or two directions
/** \param topBottom Flip around central x-axis (vertical flipping)
\param leftRight Flip around central y-axis (typical mirror, horizontal flipping) */
virtual void flip(bool topBottom, bool leftRight) = 0;
//! fills the surface with given color //! fills the surface with given color
virtual void fill(const SColor &color) =0; virtual void fill(const SColor &color) =0;

@ -12,6 +12,7 @@
#include "SVertexIndex.h" #include "SVertexIndex.h"
#include "EHardwareBufferFlags.h" #include "EHardwareBufferFlags.h"
#include "EPrimitiveTypes.h" #include "EPrimitiveTypes.h"
#include "EMeshBufferTypes.h"
namespace irr namespace irr
{ {
@ -71,11 +72,17 @@ namespace scene
virtual video::E_INDEX_TYPE getIndexType() const =0; virtual video::E_INDEX_TYPE getIndexType() const =0;
//! Get access to indices. //! Get access to indices.
/** \return Pointer to indices array. */ /** Note: For historical reasons data pointer is of type u16*, but
for an index type of EIT_32BIT the index data is using an u32 array
and therefore needs a cast to u32*.
\return Pointer to indices array. */
virtual const u16* getIndices() const = 0; virtual const u16* getIndices() const = 0;
//! Get access to indices. //! Get access to indices.
/** \return Pointer to indices array. */ /** Note: For historical reasons data pointer is of type u16*, but
for an index type of EIT_32BIT the index data is using an u32 array
and therefore needs a cast to u32*.
\return Pointer to indices array. */
virtual u16* getIndices() = 0; virtual u16* getIndices() = 0;
//! Get amount of indices in this meshbuffer. //! Get amount of indices in this meshbuffer.
@ -176,6 +183,24 @@ namespace scene
return 0; return 0;
} }
//! Returns type of the class implementing the IMeshBuffer
/** \return The class type of this meshbuffer. */
virtual EMESH_BUFFER_TYPE getType() const
{
return EMBT_UNKNOWN;
}
//! Bitflags with options for cloning
enum ECloneFlags
{
ECF_VERTICES = 1, //! clone the vertices (or copy pointer for SSharedMeshBuffer)
ECF_INDICES = 2 //! clone the indices
};
//! Create a new object with a copy of the meshbuffer
//\param cloneFlags A combination of ECloneFlags
virtual IMeshBuffer* createClone(int cloneFlags=ECF_VERTICES|ECF_INDICES) const = 0;
}; };
} // end namespace scene } // end namespace scene

@ -8,6 +8,7 @@
#include "IReferenceCounted.h" #include "IReferenceCounted.h"
#include "path.h" #include "path.h"
#include "IMeshTextureLoader.h" #include "IMeshTextureLoader.h"
#include "SVertexIndex.h"
namespace irr namespace irr
{ {
@ -29,7 +30,7 @@ class IMeshLoader : public virtual IReferenceCounted
public: public:
//! Constructor //! Constructor
IMeshLoader() : TextureLoader(0) {} IMeshLoader() : TextureLoader(0), PreferredIndexType(video::EIT_16BIT) {}
//! Destructor //! Destructor
virtual ~IMeshLoader() virtual ~IMeshLoader()
@ -78,8 +79,30 @@ public:
return TextureLoader; return TextureLoader;
} }
//! Give loader a hint if you would prefer 16 or 32 bit meshbuffers.
/**
Generally Irrlicht works with 16-bit meshbuffers so far.
Rendering 32-bit meshbuffers works, other functions like
mesh-writing and mesh manipulation might not work yet.
NOTE: Most loaders will ignore this hint so far, but hopefully
will care about it in the future.
*/
void setPreferredIndexType(irr::video::E_INDEX_TYPE typeHint)
{
PreferredIndexType = typeHint;
}
//! Return current preference user has for the index-size of meshbuffers
/** Note that this is _not_ necessarily the type used by the meshloader */
irr::video::E_INDEX_TYPE getPreferredIndexType() const
{
return PreferredIndexType;
}
protected: protected:
IMeshTextureLoader* TextureLoader; IMeshTextureLoader* TextureLoader;
irr::video::E_INDEX_TYPE PreferredIndexType;
}; };

@ -229,9 +229,7 @@ namespace scene
u8 axis, const core::vector3df& offset) const=0; u8 axis, const core::vector3df& offset) const=0;
//! Clones a static IMesh into a modifiable SMesh. //! Clones a static IMesh into a modifiable SMesh.
/** All meshbuffers in the returned SMesh /** \param mesh Mesh to copy.
are of type SMeshBuffer or SMeshBufferLightMap.
\param mesh Mesh to copy.
\return Cloned mesh. If you no longer need the \return Cloned mesh. If you no longer need the
cloned mesh, you should call SMesh::drop(). See cloned mesh, you should call SMesh::drop(). See
IReferenceCounted::drop() for more information. */ IReferenceCounted::drop() for more information. */

@ -453,13 +453,15 @@ namespace scene
where the scene node will be placed. where the scene node will be placed.
\param rotation: Initial rotation of the scene node. \param rotation: Initial rotation of the scene node.
\param scale: Initial scale of the scene node. \param scale: Initial scale of the scene node.
\param type: Type of cube-mesh to create. Check ECUBE_MESH_TYPE documentation for more info
\return Pointer to the created test scene node. This \return Pointer to the created test scene node. This
pointer should not be dropped. See IReferenceCounted::drop() pointer should not be dropped. See IReferenceCounted::drop()
for more information. */ for more information. */
virtual IMeshSceneNode* addCubeSceneNode(f32 size=10.0f, ISceneNode* parent=0, s32 id=-1, virtual IMeshSceneNode* addCubeSceneNode(f32 size=10.0f, ISceneNode* parent=0, s32 id=-1,
const core::vector3df& position = core::vector3df(0,0,0), const core::vector3df& position = core::vector3df(0,0,0),
const core::vector3df& rotation = core::vector3df(0,0,0), const core::vector3df& rotation = core::vector3df(0,0,0),
const core::vector3df& scale = core::vector3df(1.0f, 1.0f, 1.0f)) = 0; const core::vector3df& scale = core::vector3df(1.0f, 1.0f, 1.0f),
ECUBE_MESH_TYPE type=ECMT_1BUF_12VTX_NA) = 0;
//! Adds a sphere scene node of the given radius and detail //! Adds a sphere scene node of the given radius and detail
/** \param radius: Radius of the sphere. /** \param radius: Radius of the sphere.

@ -18,17 +18,27 @@ namespace scene
class IVertexBuffer : public virtual IReferenceCounted class IVertexBuffer : public virtual IReferenceCounted
{ {
public: public:
//! Pointer to first element of vertex data
virtual void* getData() =0; virtual void* getData() =0;
virtual video::E_VERTEX_TYPE getType() const =0; virtual video::E_VERTEX_TYPE getType() const =0;
virtual void setType(video::E_VERTEX_TYPE vertexType) =0; virtual void setType(video::E_VERTEX_TYPE vertexType) =0;
//! Number of bytes per element
virtual u32 stride() const =0; virtual u32 stride() const =0;
//! Number of elements
virtual u32 size() const =0; virtual u32 size() const =0;
//! Add vertex to end. Note that depending on vertex type this will be one of the types derived from video::S3DVertex.
virtual void push_back(const video::S3DVertex &element) =0; virtual void push_back(const video::S3DVertex &element) =0;
virtual video::S3DVertex& operator [](const u32 index) const =0; virtual video::S3DVertex& operator [](const u32 index) const =0;
virtual video::S3DVertex& getLast() =0; virtual video::S3DVertex& getLast() =0;
virtual void set_used(u32 usedNow) =0; virtual void set_used(u32 usedNow) =0;
virtual void reallocate(u32 new_size) =0; virtual void reallocate(u32 new_size) =0;
virtual u32 allocated_size() const =0; virtual u32 allocated_size() const =0;
//! Same as getData() - not sure why we got 2, should probably deprecate (and we don't always have video::S3DVertex*, so just confusing)
virtual video::S3DVertex* pointer() =0; virtual video::S3DVertex* pointer() =0;
//! get the current hardware mapping hint //! get the current hardware mapping hint

@ -801,7 +801,7 @@ namespace video
\param texture Texture to be drawn. \param texture Texture to be drawn.
\param destPos Upper left 2d destination position where the \param destPos Upper left 2d destination position where the
image will be drawn. image will be drawn.
\param sourceRect Source rectangle in the image. \param sourceRect Source rectangle in the texture (based on it's OriginalSize)
\param clipRect Pointer to rectangle on the screen where the \param clipRect Pointer to rectangle on the screen where the
image is clipped to. image is clipped to.
If this pointer is NULL the image is not clipped. If this pointer is NULL the image is not clipped.
@ -823,7 +823,7 @@ namespace video
\param texture Texture to be drawn. \param texture Texture to be drawn.
\param pos Upper left 2d destination position where the image \param pos Upper left 2d destination position where the image
will be drawn. will be drawn.
\param sourceRects Source rectangles of the image. \param sourceRects Source rectangles of the texture (based on it's OriginalSize)
\param indices List of indices which choose the actual \param indices List of indices which choose the actual
rectangle used each time. rectangle used each time.
\param kerningWidth Offset to Position on X \param kerningWidth Offset to Position on X
@ -851,7 +851,7 @@ namespace video
\param texture Texture to be drawn. \param texture Texture to be drawn.
\param positions Array of upper left 2d destinations where the \param positions Array of upper left 2d destinations where the
images will be drawn. images will be drawn.
\param sourceRects Source rectangles of the image. \param sourceRects Source rectangles of the texture (based on it's OriginalSize)
\param clipRect Pointer to rectangle on the screen where the \param clipRect Pointer to rectangle on the screen where the
images are clipped to. images are clipped to.
If this pointer is 0 then the image is not clipped. If this pointer is 0 then the image is not clipped.
@ -871,7 +871,7 @@ namespace video
/** Suggested and first implemented by zola. /** Suggested and first implemented by zola.
\param texture The texture to draw from \param texture The texture to draw from
\param destRect The rectangle to draw into \param destRect The rectangle to draw into
\param sourceRect The rectangle denoting a part of the texture \param sourceRect The rectangle denoting a part of the texture (based on it's OriginalSize)
\param clipRect Clips the destination rectangle (may be 0) \param clipRect Clips the destination rectangle (may be 0)
\param colors Array of 4 colors denoting the color values of \param colors Array of 4 colors denoting the color values of
the corners of the destRect the corners of the destRect
@ -1343,7 +1343,7 @@ namespace video
E_MATERIAL_TYPE enum or a value which was returned by E_MATERIAL_TYPE enum or a value which was returned by
addMaterialRenderer(). addMaterialRenderer().
\param name: New name of the material renderer. */ \param name: New name of the material renderer. */
virtual void setMaterialRendererName(s32 idx, const c8* name) =0; virtual void setMaterialRendererName(u32 idx, const c8* name) =0;
//! Swap the material renderers used for certain id's //! Swap the material renderers used for certain id's
/** Swap the IMaterialRenderers responsible for rendering specific /** Swap the IMaterialRenderers responsible for rendering specific

@ -172,9 +172,16 @@ namespace scene
} }
//! 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
{
// can't do that as it doesn't own the vertex memory
}
//! append the meshbuffer to the current buffer //! append the meshbuffer to the current buffer
virtual void append(const IMeshBuffer* const other) IRR_OVERRIDE {} virtual void append(const IMeshBuffer* const other) IRR_OVERRIDE
{
// can't do that as it doesn't own the vertex memory
}
//! get the current hardware mapping hint //! get the current hardware mapping hint
virtual E_HARDWARE_MAPPING getHardwareMappingHint_Vertex() const IRR_OVERRIDE virtual E_HARDWARE_MAPPING getHardwareMappingHint_Vertex() const IRR_OVERRIDE
@ -226,6 +233,36 @@ namespace scene
/** This shouldn't be used for anything outside the VideoDriver. */ /** This shouldn't be used for anything outside the VideoDriver. */
virtual u32 getChangedID_Index() const IRR_OVERRIDE {return ChangedID_Index;} virtual u32 getChangedID_Index() const IRR_OVERRIDE {return ChangedID_Index;}
//! Returns type of the class implementing the IMeshBuffer
virtual EMESH_BUFFER_TYPE getType() const IRR_OVERRIDE
{
return EMBT_SHARED;
}
//! Create copy of the meshbuffer
virtual IMeshBuffer* createClone(int cloneFlags) const IRR_OVERRIDE
{
SSharedMeshBuffer * clone = new SSharedMeshBuffer();
if (cloneFlags & ECF_VERTICES)
{
clone->Vertices = Vertices;
clone->BoundingBox = BoundingBox;
}
if (cloneFlags & ECF_INDICES)
{
clone->Indices = Indices;
}
clone->Material = Material;
clone->MappingHintVertex = MappingHintVertex;
clone->MappingHintIndex = MappingHintIndex;
clone->PrimitiveType = PrimitiveType;
return clone;
}
//! Material of this meshBuffer //! Material of this meshBuffer
video::SMaterial Material; video::SMaterial Material;

@ -383,6 +383,41 @@ struct SSkinMeshBuffer : public IMeshBuffer
virtual u32 getChangedID_Index() const IRR_OVERRIDE {return ChangedID_Index;} virtual u32 getChangedID_Index() const IRR_OVERRIDE {return ChangedID_Index;}
//! Returns type of the class implementing the IMeshBuffer
virtual EMESH_BUFFER_TYPE getType() const IRR_OVERRIDE
{
return EMBT_SKIN;
}
//! Create copy of the meshbuffer
virtual IMeshBuffer* createClone(int cloneFlags) const IRR_OVERRIDE
{
SSkinMeshBuffer* clone = new SSkinMeshBuffer(VertexType);
if (cloneFlags & ECF_VERTICES)
{
clone->Vertices_Tangents = Vertices_Tangents;
clone->Vertices_2TCoords = Vertices_2TCoords;
clone->Vertices_Standard = Vertices_Standard;
clone->BoundingBox = BoundingBox;
clone->BoundingBoxNeedsRecalculated = BoundingBoxNeedsRecalculated;
}
if (cloneFlags & ECF_INDICES)
{
clone->Indices = Indices;
}
clone->Transformation = Transformation;
clone->Material = getMaterial();
clone->PrimitiveType = PrimitiveType;
clone->MappingHint_Vertex = MappingHint_Vertex;
clone->MappingHint_Index = MappingHint_Index;
return clone;
}
//! Call this after changing the positions of any vertex. //! Call this after changing the positions of any vertex.
void boundingBoxNeedsRecalculated(void) { BoundingBoxNeedsRecalculated = true; } void boundingBoxNeedsRecalculated(void) { BoundingBoxNeedsRecalculated = true; }

@ -234,9 +234,10 @@ public:
//! Set (copy) data from given memory block //! Set (copy) data from given memory block
/** \param newData data to set, must have newSize elements /** \param newData data to set, must have newSize elements
\param newSize Amount of elements in newData \param newSize Amount of elements in newData
\param canShrink When true we reallocate the array even it can shrink.
May reduce memory usage, but call is more whenever size changes.
\param newDataIsSorted Info if you pass sorted/unsorted data \param newDataIsSorted Info if you pass sorted/unsorted data
\param canShrink Specifies whether the array is reallocated even if
enough space is available. Setting this flag to false can speed up
array usage, but may use more memory than required by the data.
*/ */
void set_data(const T* newData, u32 newSize, bool newDataIsSorted=false, bool canShrink=false) void set_data(const T* newData, u32 newSize, bool newDataIsSorted=false, bool canShrink=false)
{ {
@ -299,22 +300,27 @@ public:
return *this; return *this;
strategy = other.strategy; strategy = other.strategy;
// (TODO: we could probably avoid re-allocations of data when (allocated < other.allocated)
if (data) if (data)
clear(); clear();
//if (allocated < other.allocated)
if (other.allocated == 0)
data = 0;
else
data = allocator.allocate(other.allocated); // new T[other.allocated];
used = other.used; used = other.used;
free_when_destroyed = true; free_when_destroyed = true;
is_sorted = other.is_sorted; is_sorted = other.is_sorted;
allocated = other.allocated; allocated = other.allocated;
if (other.allocated == 0)
{
data = 0;
}
else
{
data = allocator.allocate(other.allocated); // new T[other.allocated];
for (u32 i=0; i<other.used; ++i) for (u32 i=0; i<other.used; ++i)
allocator.construct(&data[i], other.data[i]); // data[i] = other.data[i]; allocator.construct(&data[i], other.data[i]); // data[i] = other.data[i];
}
return *this; return *this;
} }

@ -159,20 +159,20 @@ class line2d
{ {
// Uses the method given at: // Uses the method given at:
// http://local.wasp.uwa.edu.au/~pbourke/geometry/lineline2d/ // http://local.wasp.uwa.edu.au/~pbourke/geometry/lineline2d/
const f32 commonDenominator = (f32)((l.end.Y - l.start.Y)*(end.X - start.X) - const f64 commonDenominator = (f64)((l.end.Y - l.start.Y)*(end.X - start.X) -
(l.end.X - l.start.X)*(end.Y - start.Y)); (l.end.X - l.start.X)*(end.Y - start.Y));
const f32 numeratorA = (f32)((l.end.X - l.start.X)*(start.Y - l.start.Y) - const f64 numeratorA = (f64)((l.end.X - l.start.X)*(start.Y - l.start.Y) -
(l.end.Y - l.start.Y)*(start.X -l.start.X)); (l.end.Y - l.start.Y)*(start.X -l.start.X));
const f32 numeratorB = (f32)((end.X - start.X)*(start.Y - l.start.Y) - const f64 numeratorB = (f64)((end.X - start.X)*(start.Y - l.start.Y) -
(end.Y - start.Y)*(start.X -l.start.X)); (end.Y - start.Y)*(start.X -l.start.X));
if(equals(commonDenominator, 0.f)) if(equals(commonDenominator, 0.0))
{ {
// The lines are either coincident or parallel // The lines are either coincident or parallel
// if both numerators are 0, the lines are coincident // if both numerators are 0, the lines are coincident
if(!ignoreCoincidentLines && equals(numeratorA, 0.f) && equals(numeratorB, 0.f)) if(!ignoreCoincidentLines && equals(numeratorA, 0.0) && equals(numeratorB, 0.0))
{ {
// Try and find a common endpoint // Try and find a common endpoint
if(l.start == start || l.end == start) if(l.start == start || l.end == start)
@ -235,14 +235,14 @@ class line2d
// Get the point of intersection on this line, checking that // Get the point of intersection on this line, checking that
// it is within the line segment. // it is within the line segment.
const f32 uA = numeratorA / commonDenominator; const f64 uA = numeratorA / commonDenominator;
if (checkOnlySegments) if (checkOnlySegments)
{ {
if(uA < 0.f || uA > 1.f) if(uA < 0.0 || uA > 1.0)
return false; // Outside the line segment return false; // Outside the line segment
const f32 uB = numeratorB / commonDenominator; const f64 uB = numeratorB / commonDenominator;
if(uB < 0.f || uB > 1.f) if(uB < 0.0 || uB > 1.0)
return false; // Outside the line segment return false; // Outside the line segment
} }

@ -1155,10 +1155,10 @@ namespace core
template <class T> template <class T>
inline void CMatrix4<T>::rotateVect( vector3df& vect ) const inline void CMatrix4<T>::rotateVect( vector3df& vect ) const
{ {
vector3df tmp = vect; vector3d<T> tmp(static_cast<T>(vect.X), static_cast<T>(vect.Y), static_cast<T>(vect.Z));
vect.X = tmp.X*M[0] + tmp.Y*M[4] + tmp.Z*M[8]; vect.X = static_cast<f32>(tmp.X*M[0] + tmp.Y*M[4] + tmp.Z*M[8]);
vect.Y = tmp.X*M[1] + tmp.Y*M[5] + tmp.Z*M[9]; vect.Y = static_cast<f32>(tmp.X*M[1] + tmp.Y*M[5] + tmp.Z*M[9]);
vect.Z = tmp.X*M[2] + tmp.Y*M[6] + tmp.Z*M[10]; vect.Z = static_cast<f32>(tmp.X*M[2] + tmp.Y*M[6] + tmp.Z*M[10]);
} }
//! An alternate transform vector method, writing into a second vector //! An alternate transform vector method, writing into a second vector
@ -1182,24 +1182,24 @@ namespace core
template <class T> template <class T>
inline void CMatrix4<T>::inverseRotateVect( vector3df& vect ) const inline void CMatrix4<T>::inverseRotateVect( vector3df& vect ) const
{ {
vector3df tmp = vect; vector3d<T> tmp(static_cast<T>(vect.X), static_cast<T>(vect.Y), static_cast<T>(vect.Z));
vect.X = tmp.X*M[0] + tmp.Y*M[1] + tmp.Z*M[2]; vect.X = static_cast<f32>(tmp.X*M[0] + tmp.Y*M[1] + tmp.Z*M[2]);
vect.Y = tmp.X*M[4] + tmp.Y*M[5] + tmp.Z*M[6]; vect.Y = static_cast<f32>(tmp.X*M[4] + tmp.Y*M[5] + tmp.Z*M[6]);
vect.Z = tmp.X*M[8] + tmp.Y*M[9] + tmp.Z*M[10]; vect.Z = static_cast<f32>(tmp.X*M[8] + tmp.Y*M[9] + tmp.Z*M[10]);
} }
template <class T> template <class T>
inline void CMatrix4<T>::transformVect( vector3df& vect) const inline void CMatrix4<T>::transformVect( vector3df& vect) const
{ {
f32 vector[3]; T vector[3];
vector[0] = vect.X*M[0] + vect.Y*M[4] + vect.Z*M[8] + M[12]; vector[0] = vect.X*M[0] + vect.Y*M[4] + vect.Z*M[8] + M[12];
vector[1] = vect.X*M[1] + vect.Y*M[5] + vect.Z*M[9] + M[13]; vector[1] = vect.X*M[1] + vect.Y*M[5] + vect.Z*M[9] + M[13];
vector[2] = vect.X*M[2] + vect.Y*M[6] + vect.Z*M[10] + M[14]; vector[2] = vect.X*M[2] + vect.Y*M[6] + vect.Z*M[10] + M[14];
vect.X = vector[0]; vect.X = static_cast<f32>(vector[0]);
vect.Y = vector[1]; vect.Y = static_cast<f32>(vector[1]);
vect.Z = vector[2]; vect.Z = static_cast<f32>(vector[2]);
} }
template <class T> template <class T>

@ -54,8 +54,8 @@ namespace core
vector3d<T> operator/(const vector3d<T>& other) const { return vector3d<T>(X / other.X, Y / other.Y, Z / other.Z); } vector3d<T> operator/(const vector3d<T>& other) const { return vector3d<T>(X / other.X, Y / other.Y, Z / other.Z); }
vector3d<T>& operator/=(const vector3d<T>& other) { X/=other.X; Y/=other.Y; Z/=other.Z; return *this; } vector3d<T>& operator/=(const vector3d<T>& other) { X/=other.X; Y/=other.Y; Z/=other.Z; return *this; }
vector3d<T> operator/(const T v) const { T i=(T)1.0/v; return vector3d<T>(X * i, Y * i, Z * i); } vector3d<T> operator/(const T v) const { return vector3d<T>(X/v, Y/v, Z/v); }
vector3d<T>& operator/=(const T v) { T i=(T)1.0/v; X*=i; Y*=i; Z*=i; return *this; } vector3d<T>& operator/=(const T v) { X/=v; Y/=v; Z/=v; return *this; }
T& operator [](u32 index) T& operator [](u32 index)
{ {

@ -1,3 +1,4 @@
#version 130
uniform samplerCube cubeTex; uniform samplerCube cubeTex;
uniform float Roughness; uniform float Roughness;

@ -206,7 +206,7 @@ IMesh * CAnimatedMeshSceneNode::getMeshForCurrentFrame()
// As multiple scene nodes may be sharing the same skinned mesh, we have to // As multiple scene nodes may be sharing the same skinned mesh, we have to
// re-animate it every frame to ensure that this node gets the mesh that it needs. // re-animate it every frame to ensure that this node gets the mesh that it needs.
CSkinnedMesh* skinnedMesh = reinterpret_cast<CSkinnedMesh*>(Mesh); CSkinnedMesh* skinnedMesh = static_cast<CSkinnedMesh*>(Mesh);
if (JointMode == EJUOR_CONTROL)//write to mesh if (JointMode == EJUOR_CONTROL)//write to mesh
skinnedMesh->transferJointsToMesh(JointChildSceneNodes); skinnedMesh->transferJointsToMesh(JointChildSceneNodes);
@ -949,7 +949,7 @@ void CAnimatedMeshSceneNode::animateJoints(bool CalculateAbsolutePositions)
checkJoints(); checkJoints();
const f32 frame = getFrameNr(); //old? const f32 frame = getFrameNr(); //old?
CSkinnedMesh* skinnedMesh=reinterpret_cast<CSkinnedMesh*>(Mesh); CSkinnedMesh* skinnedMesh=static_cast<CSkinnedMesh*>(Mesh);
skinnedMesh->transferOnlyJointsHintsToMesh( JointChildSceneNodes ); skinnedMesh->transferOnlyJointsHintsToMesh( JointChildSceneNodes );
skinnedMesh->animateMesh(frame, 1.0f); skinnedMesh->animateMesh(frame, 1.0f);

@ -72,6 +72,20 @@ public:
//! Get the real boundingbox used by the billboard (which depends on the active camera) //! Get the real boundingbox used by the billboard (which depends on the active camera)
virtual const core::aabbox3d<f32>& getTransformedBillboardBoundingBox(const irr::scene::ICameraSceneNode* camera) IRR_OVERRIDE; virtual const core::aabbox3d<f32>& getTransformedBillboardBoundingBox(const irr::scene::ICameraSceneNode* camera) IRR_OVERRIDE;
//! Get the amount of mesh buffers.
virtual u32 getMeshBufferCount() const IRR_OVERRIDE
{
return Buffer ? 1 : 0;
}
//! Get pointer to the mesh buffer.
virtual IMeshBuffer* getMeshBuffer(u32 nr) const IRR_OVERRIDE
{
if ( nr == 0 )
return Buffer;
return 0;
}
//! Writes attributes of the scene node. //! Writes attributes of the scene node.
virtual void serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options=0) const IRR_OVERRIDE; virtual void serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options=0) const IRR_OVERRIDE;

@ -37,9 +37,10 @@ namespace scene
//! constructor //! constructor
CCubeSceneNode::CCubeSceneNode(f32 size, ISceneNode* parent, ISceneManager* mgr, CCubeSceneNode::CCubeSceneNode(f32 size, ISceneNode* parent, ISceneManager* mgr,
s32 id, const core::vector3df& position, s32 id, const core::vector3df& position,
const core::vector3df& rotation, const core::vector3df& scale) const core::vector3df& rotation, const core::vector3df& scale,
ECUBE_MESH_TYPE type)
: IMeshSceneNode(parent, mgr, id, position, rotation, scale), : IMeshSceneNode(parent, mgr, id, position, rotation, scale),
Mesh(0), Shadow(0), Size(size) Mesh(0), Shadow(0), Size(size), MeshType(type)
{ {
#ifdef _DEBUG #ifdef _DEBUG
setDebugName("CCubeSceneNode"); setDebugName("CCubeSceneNode");
@ -62,7 +63,7 @@ void CCubeSceneNode::setSize()
{ {
if (Mesh) if (Mesh)
Mesh->drop(); Mesh->drop();
Mesh = SceneManager->getGeometryCreator()->createCubeMesh(core::vector3df(Size)); Mesh = SceneManager->getGeometryCreator()->createCubeMesh(core::vector3df(Size), MeshType);
} }
@ -135,7 +136,7 @@ const core::aabbox3d<f32>& CCubeSceneNode::getBoundingBox() const
//! Removes a child from this scene node. //! Removes a child from this scene node.
//! Implemented here, to be able to remove the shadow properly, if there is one, //! Implemented here, to be able to remove the shadow properly, if there is one,
//! or to remove attached childs. //! or to remove attached child.
bool CCubeSceneNode::removeChild(ISceneNode* child) bool CCubeSceneNode::removeChild(ISceneNode* child)
{ {
if (child && Shadow == child) if (child && Shadow == child)
@ -199,17 +200,20 @@ void CCubeSceneNode::serializeAttributes(io::IAttributes* out, io::SAttributeRea
ISceneNode::serializeAttributes(out, options); ISceneNode::serializeAttributes(out, options);
out->addFloat("Size", Size); out->addFloat("Size", Size);
out->addEnum("MeshType", (irr::s32)MeshType, CubeMeshTypeNames);
} }
//! Reads attributes of the scene node. //! Reads attributes of the scene node.
void CCubeSceneNode::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options) void CCubeSceneNode::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options)
{ {
f32 newSize = in->getAttributeAsFloat("Size"); f32 newSize = in->getAttributeAsFloat("Size", Size);
ECUBE_MESH_TYPE newMeshType = (ECUBE_MESH_TYPE)in->getAttributeAsEnumeration("MeshType", CubeMeshTypeNames, (irr::s32)MeshType);
newSize = core::max_(newSize, 0.0001f); newSize = core::max_(newSize, 0.0001f);
if (newSize != Size) if (newSize != Size || newMeshType != MeshType)
{ {
Size = newSize; Size = newSize;
MeshType = newMeshType;
setSize(); setSize();
} }
@ -226,7 +230,7 @@ ISceneNode* CCubeSceneNode::clone(ISceneNode* newParent, ISceneManager* newManag
newManager = SceneManager; newManager = SceneManager;
CCubeSceneNode* nb = new CCubeSceneNode(Size, newParent, CCubeSceneNode* nb = new CCubeSceneNode(Size, newParent,
newManager, ID, RelativeTranslation); newManager, ID, RelativeTranslation, RelativeRotation, RelativeScale, MeshType);
nb->cloneMembers(this, newManager); nb->cloneMembers(this, newManager);
nb->getMaterial(0) = getMaterial(0); nb->getMaterial(0) = getMaterial(0);

@ -7,6 +7,7 @@
#include "IMeshSceneNode.h" #include "IMeshSceneNode.h"
#include "SMesh.h" #include "SMesh.h"
#include "IGeometryCreator.h"
namespace irr namespace irr
{ {
@ -20,7 +21,8 @@ namespace scene
CCubeSceneNode(f32 size, ISceneNode* parent, ISceneManager* mgr, s32 id, CCubeSceneNode(f32 size, ISceneNode* parent, ISceneManager* mgr, s32 id,
const core::vector3df& position = core::vector3df(0,0,0), const core::vector3df& position = core::vector3df(0,0,0),
const core::vector3df& rotation = core::vector3df(0,0,0), const core::vector3df& rotation = core::vector3df(0,0,0),
const core::vector3df& scale = core::vector3df(1.0f, 1.0f, 1.0f)); const core::vector3df& scale = core::vector3df(1.0f, 1.0f, 1.0f),
ECUBE_MESH_TYPE type=ECMT_1BUF_12VTX_NA);
virtual ~CCubeSceneNode(); virtual ~CCubeSceneNode();
@ -84,6 +86,7 @@ namespace scene
IMesh* Mesh; IMesh* Mesh;
IShadowVolumeSceneNode* Shadow; IShadowVolumeSceneNode* Shadow;
f32 Size; f32 Size;
ECUBE_MESH_TYPE MeshType;
}; };
} // end namespace scene } // end namespace scene

@ -1192,7 +1192,7 @@ void CD3D9Driver::removeOcclusionQuery(scene::ISceneNode* node)
if (index != -1) if (index != -1)
{ {
if (OcclusionQueries[index].PID != 0) if (OcclusionQueries[index].PID != 0)
reinterpret_cast<IDirect3DQuery9*>(OcclusionQueries[index].PID)->Release(); static_cast<IDirect3DQuery9*>(OcclusionQueries[index].PID)->Release();
CNullDriver::removeOcclusionQuery(node); CNullDriver::removeOcclusionQuery(node);
} }
} }
@ -1210,10 +1210,10 @@ void CD3D9Driver::runOcclusionQuery(scene::ISceneNode* node, bool visible)
if (index != -1) if (index != -1)
{ {
if (OcclusionQueries[index].PID) if (OcclusionQueries[index].PID)
reinterpret_cast<IDirect3DQuery9*>(OcclusionQueries[index].PID)->Issue(D3DISSUE_BEGIN); static_cast<IDirect3DQuery9*>(OcclusionQueries[index].PID)->Issue(D3DISSUE_BEGIN);
CNullDriver::runOcclusionQuery(node,visible); CNullDriver::runOcclusionQuery(node,visible);
if (OcclusionQueries[index].PID) if (OcclusionQueries[index].PID)
reinterpret_cast<IDirect3DQuery9*>(OcclusionQueries[index].PID)->Issue(D3DISSUE_END); static_cast<IDirect3DQuery9*>(OcclusionQueries[index].PID)->Issue(D3DISSUE_END);
} }
} }
@ -1232,12 +1232,12 @@ void CD3D9Driver::updateOcclusionQuery(scene::ISceneNode* node, bool block)
bool available = block?true:false; bool available = block?true:false;
int tmp=0; int tmp=0;
if (!block) if (!block)
available=(reinterpret_cast<IDirect3DQuery9*>(OcclusionQueries[index].PID)->GetData(&tmp, sizeof(DWORD), 0)==S_OK); available=(static_cast<IDirect3DQuery9*>(OcclusionQueries[index].PID)->GetData(&tmp, sizeof(DWORD), 0)==S_OK);
else else
{ {
do do
{ {
HRESULT hr = reinterpret_cast<IDirect3DQuery9*>(OcclusionQueries[index].PID)->GetData(&tmp, sizeof(DWORD), D3DGETDATA_FLUSH); HRESULT hr = static_cast<IDirect3DQuery9*>(OcclusionQueries[index].PID)->GetData(&tmp, sizeof(DWORD), D3DGETDATA_FLUSH);
available = (hr == S_OK); available = (hr == S_OK);
if (hr!=S_FALSE) if (hr!=S_FALSE)
break; break;
@ -2946,7 +2946,7 @@ bool CD3D9Driver::reset()
{ {
if (OcclusionQueries[i].PID) if (OcclusionQueries[i].PID)
{ {
reinterpret_cast<IDirect3DQuery9*>(OcclusionQueries[i].PID)->Release(); static_cast<IDirect3DQuery9*>(OcclusionQueries[i].PID)->Release();
OcclusionQueries[i].PID=0; OcclusionQueries[i].PID=0;
} }
} }

@ -140,6 +140,69 @@ IMesh* CGeometryCreator::createCubeMesh(const core::vector3df& size, ECUBE_MESH_
buffer->drop(); buffer->drop();
} }
} }
else if ( type == ECMT_1BUF_24VTX_NP )
{
SMeshBuffer* buffer = new SMeshBuffer();
// Create indices (pos, neg describes normal direction of front-face)
const u16 u[36] = { 0,2,1, 0,3,2, // NEG_Z
4,7,6, 4,5,7, // POS_X
8,10,11, 8,9,10, // POS_Z
15,13,12, 15,14,13, // NEG_X
19,17,16, 19,18,17, // POS_Y
20,23,22, 20,22,21}; // NEG_Y
buffer->Indices.set_used(36);
for (u32 i=0; i<36; ++i)
buffer->Indices[i] = u[i];
// Create vertices
buffer->Vertices.reallocate(24);
buffer->Vertices.push_back(video::S3DVertex(0,0,0, 0, 0,-1, clr, 0, 1)); // 0
buffer->Vertices.push_back(video::S3DVertex(1,0,0, 0, 0,-1, clr, 1, 1)); // 1
buffer->Vertices.push_back(video::S3DVertex(1,1,0, 0, 0,-1, clr, 1, 0)); // 2
buffer->Vertices.push_back(video::S3DVertex(0,1,0, 0, 0,-1, clr, 0, 0)); // 3
buffer->Vertices.push_back(video::S3DVertex(1,0,0, 1, 0, 0, clr, 1, 1)); // 4 (1)
buffer->Vertices.push_back(video::S3DVertex(1,1,0, 1, 0, 0, clr, 1, 0)); // 5 (2)
buffer->Vertices.push_back(video::S3DVertex(1,0,1, 1, 0, 0, clr, 0, 1)); // 6 (4)
buffer->Vertices.push_back(video::S3DVertex(1,1,1, 1, 0, 0, clr, 0, 0)); // 7 (5)
buffer->Vertices.push_back(video::S3DVertex(1,0,1, 0, 0, 1, clr, 0, 1)); // 8 (4)
buffer->Vertices.push_back(video::S3DVertex(1,1,1, 0, 0, 1, clr, 0, 0)); // 9 (5)
buffer->Vertices.push_back(video::S3DVertex(0,1,1, 0, 0, 1, clr, 1, 0)); // 10 (6)
buffer->Vertices.push_back(video::S3DVertex(0,0,1, 0, 0, 1, clr, 1, 1)); // 11 (7)
buffer->Vertices.push_back(video::S3DVertex(0,0,0, -1, 0, 0, clr, 0, 1)); // 12 (0)
buffer->Vertices.push_back(video::S3DVertex(0,1,0, -1, 0, 0, clr, 0, 0)); // 13 (3)
buffer->Vertices.push_back(video::S3DVertex(0,1,1, -1, 0, 0, clr, 1, 0)); // 14 (6)
buffer->Vertices.push_back(video::S3DVertex(0,0,1, -1, 0, 0, clr, 1, 1)); // 15 (7)
buffer->Vertices.push_back(video::S3DVertex(1,1,0, 0, 1, 0, clr, 1, 0)); // 16 (2)
buffer->Vertices.push_back(video::S3DVertex(1,1,1, 0, 1, 0, clr, 0, 0)); // 17 (5)
buffer->Vertices.push_back(video::S3DVertex(0,1,1, 0, 1, 0, clr, 0, 1)); // 18 (8)
buffer->Vertices.push_back(video::S3DVertex(0,1,0, 0, 1, 0, clr, 1, 1)); // 19 (9)
buffer->Vertices.push_back(video::S3DVertex(0,0,0, 0,-1, 0, clr, 0, 1)); // 20 (0)
buffer->Vertices.push_back(video::S3DVertex(0,0,1, 0,-1, 0, clr, 1, 1)); // 21 (7)
buffer->Vertices.push_back(video::S3DVertex(1,0,1, 0,-1, 0, clr, 1, 0)); // 22 (10)
buffer->Vertices.push_back(video::S3DVertex(1,0,0, 0,-1, 0, clr, 0, 0)); // 23 (11)
// Recalculate bounding box and set cube size
buffer->BoundingBox.reset(0,0,0);
for (u32 i=0; i<24; ++i)
{
buffer->Vertices[i].Pos -= core::vector3df(0.5f, 0.5f, 0.5f);
buffer->Vertices[i].Pos *= size;
buffer->BoundingBox.addInternalPoint(buffer->Vertices[i].Pos);
}
mesh->addMeshBuffer(buffer);
buffer->drop();
}
mesh->recalculateBoundingBox(); mesh->recalculateBoundingBox();
return mesh; return mesh;

@ -347,6 +347,60 @@ void CImage::fill(const SColor &color)
memset32( Data, c, getImageDataSizeInBytes() ); memset32( Data, c, getImageDataSizeInBytes() );
} }
void CImage::flip(bool topBottom, bool leftRight)
{
if ( !topBottom && !leftRight)
return;
const core::dimension2du dim(getDimension());
if ( dim.Width == 0 || dim.Height == 0 )
return;
u8* data = (u8*)getData();
if (!data)
return;
const u32 bpp = getBytesPerPixel();
const u32 pitch = getPitch();
if ( topBottom )
{
for ( u32 i=0; i<dim.Height/2; ++i)
{
// Reverse bottom/top lines
u8* l1 = data+i*pitch;
u8* l2 = data+(dim.Height-1-i)*pitch;
for ( u32 b=0; b<pitch; ++b)
{
irr::u8 dummy = *l1;
*l1 = *l2;
*l2 = dummy;
++l1;
++l2;
}
}
}
if ( leftRight )
{
for ( u32 i=0; i<dim.Height; ++i)
{
// Reverse left/right for each line
u8* l1 = data+i*pitch;
u8* l2 = l1+(dim.Width-1)*bpp;
for ( u32 p=0; p<dim.Width/2; ++p)
{
for ( u32 b=0; b<bpp; ++b)
{
irr::u8 dummy = l1[b];
l1[b] = l2[b];
l2[b] = dummy;
}
l1 += bpp;
l2 -= bpp;
}
}
}
}
//! get a filtered pixel //! get a filtered pixel
inline SColor CImage::getPixelBox( s32 x, s32 y, s32 fx, s32 fy, s32 bias ) const inline SColor CImage::getPixelBox( s32 x, s32 y, s32 fx, s32 fy, s32 bias ) const

@ -55,6 +55,9 @@ public:
//! copies this surface into another, scaling it to fit, applying a box filter //! copies this surface into another, scaling it to fit, applying a box filter
virtual void copyToScalingBoxFilter(IImage* target, s32 bias = 0, bool blend = false) IRR_OVERRIDE; virtual void copyToScalingBoxFilter(IImage* target, s32 bias = 0, bool blend = false) IRR_OVERRIDE;
//! Flips (mirrors) the image in one or two directions
virtual void flip(bool topBottom, bool leftRight) IRR_OVERRIDE;
//! fills the surface with given color //! fills the surface with given color
virtual void fill(const SColor &color) IRR_OVERRIDE; virtual void fill(const SColor &color) IRR_OVERRIDE;

@ -1354,7 +1354,7 @@ bool CIrrDeviceWin32::present(video::IImage* image, void* windowId, core::rect<s
{ {
HWND hwnd = HWnd; HWND hwnd = HWnd;
if ( windowId ) if ( windowId )
hwnd = reinterpret_cast<HWND>(windowId); hwnd = static_cast<HWND>(windowId);
HDC dc = GetDC(hwnd); HDC dc = GetDC(hwnd);

@ -577,8 +577,7 @@ void CMeshManipulator::makePlanarTextureMapping(scene::IMesh* mesh, f32 resoluti
} }
//! Clones a static IMesh into a modifyable SMesh. //! Clones a static IMesh into a modifiable SMesh.
// not yet 32bit
SMesh* CMeshManipulator::createMeshCopy(scene::IMesh* mesh) const SMesh* CMeshManipulator::createMeshCopy(scene::IMesh* mesh) const
{ {
if (!mesh) if (!mesh)
@ -590,66 +589,10 @@ SMesh* CMeshManipulator::createMeshCopy(scene::IMesh* mesh) const
for ( u32 b=0; b<meshBufferCount; ++b) for ( u32 b=0; b<meshBufferCount; ++b)
{ {
const IMeshBuffer* const mb = mesh->getMeshBuffer(b); IMeshBuffer* bufferClone = mesh->getMeshBuffer(b)->createClone();
switch(mb->getVertexType()) clone->addMeshBuffer(bufferClone);
{ bufferClone->drop();
case video::EVT_STANDARD:
{
SMeshBuffer* buffer = new SMeshBuffer();
buffer->Material = mb->getMaterial();
const u32 vcount = mb->getVertexCount();
buffer->Vertices.reallocate(vcount);
video::S3DVertex* vertices = (video::S3DVertex*)mb->getVertices();
for (u32 i=0; i < vcount; ++i)
buffer->Vertices.push_back(vertices[i]);
const u32 icount = mb->getIndexCount();
buffer->Indices.reallocate(icount);
const u16* indices = mb->getIndices();
for (u32 i=0; i < icount; ++i)
buffer->Indices.push_back(indices[i]);
clone->addMeshBuffer(buffer);
buffer->drop();
} }
break;
case video::EVT_2TCOORDS:
{
SMeshBufferLightMap* buffer = new SMeshBufferLightMap();
buffer->Material = mb->getMaterial();
const u32 vcount = mb->getVertexCount();
buffer->Vertices.reallocate(vcount);
video::S3DVertex2TCoords* vertices = (video::S3DVertex2TCoords*)mb->getVertices();
for (u32 i=0; i < vcount; ++i)
buffer->Vertices.push_back(vertices[i]);
const u32 icount = mb->getIndexCount();
buffer->Indices.reallocate(icount);
const u16* indices = mb->getIndices();
for (u32 i=0; i < icount; ++i)
buffer->Indices.push_back(indices[i]);
clone->addMeshBuffer(buffer);
buffer->drop();
}
break;
case video::EVT_TANGENTS:
{
SMeshBufferTangents* buffer = new SMeshBufferTangents();
buffer->Material = mb->getMaterial();
const u32 vcount = mb->getVertexCount();
buffer->Vertices.reallocate(vcount);
video::S3DVertexTangents* vertices = (video::S3DVertexTangents*)mb->getVertices();
for (u32 i=0; i < vcount; ++i)
buffer->Vertices.push_back(vertices[i]);
const u32 icount = mb->getIndexCount();
buffer->Indices.reallocate(icount);
const u16* indices = mb->getIndices();
for (u32 i=0; i < icount; ++i)
buffer->Indices.push_back(indices[i]);
clone->addMeshBuffer(buffer);
buffer->drop();
}
break;
}// end switch
}// end for all mesh buffers
clone->BoundingBox = mesh->getBoundingBox(); clone->BoundingBox = mesh->getBoundingBox();
return clone; return clone;

@ -441,10 +441,7 @@ ITexture* CNullDriver::addTexture(const core::dimension2d<u32>& size, const io::
IImage* image = new CImage(format, size); IImage* image = new CImage(format, size);
ITexture* t = 0; ITexture* t = 0;
core::array<IImage*> imageArray(1); if (checkImage(image->getColorFormat(), image->getDimension()))
imageArray.push_back(image);
if (checkImage(imageArray))
{ {
t = createDeviceDependentTexture(name, image); t = createDeviceDependentTexture(name, image);
} }
@ -473,19 +470,15 @@ ITexture* CNullDriver::addTexture(const io::path& name, IImage* image)
ITexture* t = 0; ITexture* t = 0;
core::array<IImage*> imageArray(1); if (checkImage(image->getColorFormat(), image->getDimension()))
imageArray.push_back(image);
if (checkImage(imageArray))
{ {
t = createDeviceDependentTexture(name, image); t = createDeviceDependentTexture(name, image);
}
if (t) if (t)
{ {
addTexture(t); addTexture(t);
t->drop(); t->drop();
} }
}
return t; return t;
} }
@ -509,13 +502,12 @@ ITexture* CNullDriver::addTextureCubemap(const io::path& name, IImage* imagePosX
if (checkImage(imageArray)) if (checkImage(imageArray))
{ {
t = createDeviceDependentTextureCubemap(name, imageArray); t = createDeviceDependentTextureCubemap(name, imageArray);
}
if (t) if (t)
{ {
addTexture(t); addTexture(t);
t->drop(); t->drop();
} }
}
return t; return t;
} }
@ -1434,18 +1426,30 @@ bool CNullDriver::checkPrimitiveCount(u32 prmCount) const
bool CNullDriver::checkImage(const core::array<IImage*>& image) const bool CNullDriver::checkImage(const core::array<IImage*>& image) const
{ {
bool status = true;
if (image.size() > 0) if (image.size() > 0)
{ {
ECOLOR_FORMAT lastFormat = image[0]->getColorFormat(); ECOLOR_FORMAT lastFormat = image[0]->getColorFormat();
core::dimension2d<u32> lastSize = image[0]->getDimension(); core::dimension2d<u32> lastSize = image[0]->getDimension();
for (u32 i = 0; i < image.size() && status; ++i) for (u32 i = 0; i < image.size(); ++i)
{ {
ECOLOR_FORMAT format = image[i]->getColorFormat(); ECOLOR_FORMAT format = image[i]->getColorFormat();
core::dimension2d<u32> size = image[i]->getDimension(); core::dimension2d<u32> size = image[i]->getDimension();
if (format != lastFormat || size != lastSize)
return false;
if ( !checkImage(format, size) )
return false;
}
return true;
}
return false;
}
bool CNullDriver::checkImage(ECOLOR_FORMAT format, const core::dimension2du& size) const
{
switch (format) switch (format)
{ {
case ECF_DXT1: case ECF_DXT1:
@ -1456,12 +1460,12 @@ bool CNullDriver::checkImage(const core::array<IImage*>& image) const
if (!queryFeature(EVDF_TEXTURE_COMPRESSED_DXT)) if (!queryFeature(EVDF_TEXTURE_COMPRESSED_DXT))
{ {
os::Printer::log("DXT texture compression not available.", ELL_ERROR); os::Printer::log("DXT texture compression not available.", ELL_ERROR);
status = false; return false;
} }
else if (size.getOptimalSize(true, false) != size) else if (size.getOptimalSize(true, false) != size)
{ {
os::Printer::log("Invalid size of image for DXT texture, size of image must be power of two.", ELL_ERROR); os::Printer::log("Invalid size of image for DXT texture, size of image must be power of two.", ELL_ERROR);
status = false; return false;
} }
break; break;
case ECF_PVRTC_RGB2: case ECF_PVRTC_RGB2:
@ -1471,12 +1475,12 @@ bool CNullDriver::checkImage(const core::array<IImage*>& image) const
if (!queryFeature(EVDF_TEXTURE_COMPRESSED_PVRTC)) if (!queryFeature(EVDF_TEXTURE_COMPRESSED_PVRTC))
{ {
os::Printer::log("PVRTC texture compression not available.", ELL_ERROR); os::Printer::log("PVRTC texture compression not available.", ELL_ERROR);
status = false; return false;
} }
else if (size.getOptimalSize(true, false) != size) else if (size.getOptimalSize(true, false) != size)
{ {
os::Printer::log("Invalid size of image for PVRTC compressed texture, size of image must be power of two and squared.", ELL_ERROR); os::Printer::log("Invalid size of image for PVRTC compressed texture, size of image must be power of two and squared.", ELL_ERROR);
status = false; return false;
} }
break; break;
case ECF_PVRTC2_ARGB2: case ECF_PVRTC2_ARGB2:
@ -1484,14 +1488,14 @@ bool CNullDriver::checkImage(const core::array<IImage*>& image) const
if (!queryFeature(EVDF_TEXTURE_COMPRESSED_PVRTC2)) if (!queryFeature(EVDF_TEXTURE_COMPRESSED_PVRTC2))
{ {
os::Printer::log("PVRTC2 texture compression not available.", ELL_ERROR); os::Printer::log("PVRTC2 texture compression not available.", ELL_ERROR);
status = false; return false;
} }
break; break;
case ECF_ETC1: case ECF_ETC1:
if (!queryFeature(EVDF_TEXTURE_COMPRESSED_ETC1)) if (!queryFeature(EVDF_TEXTURE_COMPRESSED_ETC1))
{ {
os::Printer::log("ETC1 texture compression not available.", ELL_ERROR); os::Printer::log("ETC1 texture compression not available.", ELL_ERROR);
status = false; return false;
} }
break; break;
case ECF_ETC2_RGB: case ECF_ETC2_RGB:
@ -1499,23 +1503,14 @@ bool CNullDriver::checkImage(const core::array<IImage*>& image) const
if (!queryFeature(EVDF_TEXTURE_COMPRESSED_ETC2)) if (!queryFeature(EVDF_TEXTURE_COMPRESSED_ETC2))
{ {
os::Printer::log("ETC2 texture compression not available.", ELL_ERROR); os::Printer::log("ETC2 texture compression not available.", ELL_ERROR);
status = false; return false;
} }
break; break;
default: default:
break; break;
} }
if (format != lastFormat || size != lastSize) return true;
status = false;
}
}
else
{
status = false;
}
return status;
} }
//! Enables or disables a texture creation flag. //! Enables or disables a texture creation flag.
@ -2097,10 +2092,10 @@ s32 CNullDriver::addMaterialRenderer(IMaterialRenderer* renderer, const char* na
//! Sets the name of a material renderer. //! Sets the name of a material renderer.
void CNullDriver::setMaterialRendererName(s32 idx, const char* name) void CNullDriver::setMaterialRendererName(u32 idx, const char* name)
{ {
if (idx < s32(sizeof(sBuiltInMaterialTypeNames) / sizeof(char*))-1 || if (idx < (sizeof(sBuiltInMaterialTypeNames) / sizeof(char*))-1 ||
idx >= (s32)MaterialRenderers.size()) idx >= MaterialRenderers.size())
return; return;
MaterialRenderers[idx].Name = name; MaterialRenderers[idx].Name = name;

@ -616,7 +616,7 @@ namespace video
virtual bool writeImageToFile(IImage* image, io::IWriteFile * file, u32 param = 0) IRR_OVERRIDE; virtual bool writeImageToFile(IImage* image, io::IWriteFile * file, u32 param = 0) IRR_OVERRIDE;
//! Sets the name of a material renderer. //! Sets the name of a material renderer.
virtual void setMaterialRendererName(s32 idx, const char* name) IRR_OVERRIDE; virtual void setMaterialRendererName(u32 idx, const char* name) IRR_OVERRIDE;
//! Swap the material renderers used for certain id's //! Swap the material renderers used for certain id's
virtual void swapMaterialRenderers(u32 idx1, u32 idx2, bool swapNames) IRR_OVERRIDE; virtual void swapMaterialRenderers(u32 idx1, u32 idx2, bool swapNames) IRR_OVERRIDE;
@ -710,6 +710,7 @@ namespace video
bool checkPrimitiveCount(u32 prmcnt) const; bool checkPrimitiveCount(u32 prmcnt) const;
bool checkImage(const core::array<IImage*>& image) const; bool checkImage(const core::array<IImage*>& image) const;
bool checkImage(ECOLOR_FORMAT format, const core::dimension2du& size) const;
// adds a material renderer and drops it afterwards. To be used for internal creation // adds a material renderer and drops it afterwards. To be used for internal creation
s32 addAndDropMaterialRenderer(IMaterialRenderer* m); s32 addAndDropMaterialRenderer(IMaterialRenderer* m);

@ -82,7 +82,7 @@ IAnimatedMesh* COBJMeshFileLoader::createMesh(io::IReadFile* file)
core::array<core::vector3df, core::irrAllocatorFast<core::vector3df> > normalsBuffer(1000); core::array<core::vector3df, core::irrAllocatorFast<core::vector3df> > normalsBuffer(1000);
core::array<core::vector2df, core::irrAllocatorFast<core::vector2df> > textureCoordBuffer(1000); core::array<core::vector2df, core::irrAllocatorFast<core::vector2df> > textureCoordBuffer(1000);
SObjMtl * currMtl = new SObjMtl(); SObjMtl * currMtl = new SObjMtl(PreferredIndexType);
Materials.push_back(currMtl); Materials.push_back(currMtl);
u32 smoothingGroup=0; u32 smoothingGroup=0;
@ -224,6 +224,8 @@ IAnimatedMesh* COBJMeshFileLoader::createMesh(io::IReadFile* file)
v.Color = currMtl->Meshbuffer->Material.DiffuseColor; v.Color = currMtl->Meshbuffer->Material.DiffuseColor;
// get all vertices data in this face (current line of obj file) // get all vertices data in this face (current line of obj file)
IVertexBuffer& mbVertexBuffer = currMtl->Meshbuffer->getVertexBuffer();
IIndexBuffer& mbIndexBuffer = currMtl->Meshbuffer->getIndexBuffer();
const core::stringc wordBuffer = copyLine(bufPtr, bufEnd); const core::stringc wordBuffer = copyLine(bufPtr, bufEnd);
const c8* linePtr = wordBuffer.c_str(); const c8* linePtr = wordBuffer.c_str();
const c8* const endPtr = linePtr+wordBuffer.size(); const c8* const endPtr = linePtr+wordBuffer.size();
@ -272,8 +274,8 @@ IAnimatedMesh* COBJMeshFileLoader::createMesh(io::IReadFile* file)
} }
else else
{ {
currMtl->Meshbuffer->Vertices.push_back(v); mbVertexBuffer.push_back(v);
vertLocation = currMtl->Meshbuffer->Vertices.size() -1; vertLocation = mbVertexBuffer.size() -1;
currMtl->VertMap.insert(v, vertLocation); currMtl->VertMap.insert(v, vertLocation);
} }
@ -292,9 +294,9 @@ IAnimatedMesh* COBJMeshFileLoader::createMesh(io::IReadFile* file)
const int b = faceCorners[i]; const int b = faceCorners[i];
if (a != b && a != c && b != c) // ignore degenerated faces. We can get them when we merge vertices above in the VertMap. if (a != b && a != c && b != c) // ignore degenerated faces. We can get them when we merge vertices above in the VertMap.
{ {
currMtl->Meshbuffer->Indices.push_back(a); mbIndexBuffer.push_back(a);
currMtl->Meshbuffer->Indices.push_back(b); mbIndexBuffer.push_back(b);
currMtl->Meshbuffer->Indices.push_back(c); mbIndexBuffer.push_back(c);
} }
else else
{ {
@ -577,7 +579,7 @@ void COBJMeshFileLoader::readMTL(const c8* fileName, const io::path& relPath)
c8 mtlNameBuf[WORD_BUFFER_LENGTH]; c8 mtlNameBuf[WORD_BUFFER_LENGTH];
bufPtr = goAndCopyNextWord(mtlNameBuf, bufPtr, WORD_BUFFER_LENGTH, bufEnd); bufPtr = goAndCopyNextWord(mtlNameBuf, bufPtr, WORD_BUFFER_LENGTH, bufEnd);
currMaterial = new SObjMtl; currMaterial = new SObjMtl(PreferredIndexType);
currMaterial->Name = mtlNameBuf; currMaterial->Name = mtlNameBuf;
} }
break; break;

@ -9,7 +9,7 @@
#include "IFileSystem.h" #include "IFileSystem.h"
#include "ISceneManager.h" #include "ISceneManager.h"
#include "irrString.h" #include "irrString.h"
#include "SMeshBuffer.h" #include "CDynamicMeshBuffer.h"
#include "irrMap.h" #include "irrMap.h"
namespace irr namespace irr
@ -42,10 +42,10 @@ private:
struct SObjMtl struct SObjMtl
{ {
SObjMtl() : Meshbuffer(0), Bumpiness (1.0f), Illumination(0), SObjMtl(irr::video::E_INDEX_TYPE indexType) : IndexType(indexType), Meshbuffer(0), Bumpiness (1.0f), Illumination(0),
RecalculateNormals(false) RecalculateNormals(false)
{ {
Meshbuffer = new SMeshBuffer(); Meshbuffer = new CDynamicMeshBuffer(irr::video::EVT_STANDARD, IndexType);
Meshbuffer->Material.Shininess = 0.0f; Meshbuffer->Material.Shininess = 0.0f;
Meshbuffer->Material.AmbientColor = video::SColorf(0.2f, 0.2f, 0.2f, 1.0f).toSColor(); Meshbuffer->Material.AmbientColor = video::SColorf(0.2f, 0.2f, 0.2f, 1.0f).toSColor();
Meshbuffer->Material.DiffuseColor = video::SColorf(0.8f, 0.8f, 0.8f, 1.0f).toSColor(); Meshbuffer->Material.DiffuseColor = video::SColorf(0.8f, 0.8f, 0.8f, 1.0f).toSColor();
@ -53,16 +53,17 @@ private:
} }
SObjMtl(const SObjMtl& o) SObjMtl(const SObjMtl& o)
: Name(o.Name), Group(o.Group), : IndexType(o.IndexType), Name(o.Name), Group(o.Group),
Bumpiness(o.Bumpiness), Illumination(o.Illumination), Bumpiness(o.Bumpiness), Illumination(o.Illumination),
RecalculateNormals(false) RecalculateNormals(false)
{ {
Meshbuffer = new SMeshBuffer(); Meshbuffer = new CDynamicMeshBuffer(irr::video::EVT_STANDARD, IndexType);
Meshbuffer->Material = o.Meshbuffer->Material; Meshbuffer->Material = o.Meshbuffer->Material;
} }
core::map<video::S3DVertex, int> VertMap; core::map<video::S3DVertex, int> VertMap;
scene::SMeshBuffer *Meshbuffer; irr::video::E_INDEX_TYPE IndexType;
scene::CDynamicMeshBuffer *Meshbuffer;
core::stringc Name; core::stringc Name;
core::stringc Group; core::stringc Group;
f32 Bumpiness; f32 Bumpiness;

@ -127,11 +127,26 @@ bool COBJMeshWriter::writeMesh(io::IWriteFile* file, scene::IMesh* mesh, s32 fla
file->write(num.c_str(), num.size()); file->write(num.c_str(), num.size());
file->write("\n",1); file->write("\n",1);
unsigned int idx2=0, idx1=0, idx0 = 0;
const u32 indexCount = buffer->getIndexCount(); const u32 indexCount = buffer->getIndexCount();
for (j=0; j<indexCount; j+=3) for (j=0; j<indexCount; j+=3)
{ {
switch(buffer->getIndexType())
{
case video::EIT_16BIT:
idx2 = buffer->getIndices()[j+2]+allVertexCount;
idx1 = buffer->getIndices()[j+1]+allVertexCount;
idx0 = buffer->getIndices()[j+0]+allVertexCount;
break;
case video::EIT_32BIT:
idx2 = ((u32*)buffer->getIndices())[j+2]+allVertexCount;
idx1 = ((u32*)buffer->getIndices())[j+1]+allVertexCount;
idx0 = ((u32*)buffer->getIndices())[j+0]+allVertexCount;
break;
}
file->write("f ",2); file->write("f ",2);
num = core::stringc(buffer->getIndices()[j+2]+allVertexCount); num = core::stringc(idx2);
file->write(num.c_str(), num.size()); file->write(num.c_str(), num.size());
file->write("/",1); file->write("/",1);
file->write(num.c_str(), num.size()); file->write(num.c_str(), num.size());
@ -139,7 +154,7 @@ bool COBJMeshWriter::writeMesh(io::IWriteFile* file, scene::IMesh* mesh, s32 fla
file->write(num.c_str(), num.size()); file->write(num.c_str(), num.size());
file->write(" ",1); file->write(" ",1);
num = core::stringc(buffer->getIndices()[j+1]+allVertexCount); num = core::stringc(idx1);
file->write(num.c_str(), num.size()); file->write(num.c_str(), num.size());
file->write("/",1); file->write("/",1);
file->write(num.c_str(), num.size()); file->write(num.c_str(), num.size());
@ -147,7 +162,7 @@ bool COBJMeshWriter::writeMesh(io::IWriteFile* file, scene::IMesh* mesh, s32 fla
file->write(num.c_str(), num.size()); file->write(num.c_str(), num.size());
file->write(" ",1); file->write(" ",1);
num = core::stringc(buffer->getIndices()[j+0]+allVertexCount); num = core::stringc(idx0);
file->write(num.c_str(), num.size()); file->write(num.c_str(), num.size());
file->write("/",1); file->write("/",1);
file->write(num.c_str(), num.size()); file->write(num.c_str(), num.size());

@ -102,18 +102,29 @@ IAnimatedMesh* COCTLoader::createMesh(io::IReadFile* file)
file->read(verts, sizeof(octVert) * header.numVerts); file->read(verts, sizeof(octVert) * header.numVerts);
file->read(faces, sizeof(octFace) * header.numFaces); file->read(faces, sizeof(octFace) * header.numFaces);
//TODO: Make sure id is in the legal range for Textures and Lightmaps
u32 i; u32 i;
for (i = 0; i < header.numTextures; i++) { for (i = 0; i < header.numTextures; i++)
octTexture t; {
file->read(&t, sizeof(octTexture)); u32 id;
textures[t.id] = t; file->read(&id, sizeof(id));
if ( id >= header.numTextures )
{
os::Printer::log("COCTLoader: Invalid texture id", irr::ELL_WARNING);
id = i;
} }
for (i = 0; i < header.numLightmaps; i++) { file->read(&textures[id], sizeof(octTexture));
octLightmap t; }
file->read(&t, sizeof(octLightmap)); for (i = 0; i < header.numLightmaps; i++)
lightmaps[t.id] = t; {
u32 id;
file->read(&id, sizeof(id));
if ( id >= header.numLightmaps )
{
os::Printer::log("COCTLoader: Invalid lightmap id", irr::ELL_WARNING);
id = i;
}
file->read(&lightmaps[id], sizeof(octLightmap));
} }
file->read(lights, sizeof(octLight) * header.numLights); file->read(lights, sizeof(octLight) * header.numLights);

@ -115,12 +115,10 @@ namespace scene
}; };
struct octTexture { struct octTexture {
u32 id;
char fileName[64]; char fileName[64];
}; };
struct octLightmap { struct octLightmap {
u32 id;
u8 data[128][128][3]; u8 data[128][128][3];
}; };

@ -1099,7 +1099,7 @@ COGLES2Driver::~COGLES2Driver()
testGLError(__LINE__); testGLError(__LINE__);
} }
void COGLES2Driver::draw2DImage(const video::ITexture* texture, u32 layer, bool flip) void COGLES2Driver::draw2DImageQuad(const video::ITexture* texture, u32 layer, bool flip)
{ {
if (!texture) if (!texture)
return; return;

@ -118,7 +118,7 @@ namespace video
const video::SColor* const colors = 0, bool useAlphaChannelOfTexture = false) IRR_OVERRIDE; const video::SColor* const colors = 0, bool useAlphaChannelOfTexture = false) IRR_OVERRIDE;
// internally used // internally used
virtual void draw2DImage(const video::ITexture* texture, u32 layer, bool flip); virtual void draw2DImageQuad(const video::ITexture* texture, u32 layer, bool flip);
//! draws a set of 2d images //! draws a set of 2d images
virtual void draw2DImageBatch(const video::ITexture* texture, virtual void draw2DImageBatch(const video::ITexture* texture,

@ -1032,7 +1032,7 @@ void COGLES1Driver::draw2DImage(const video::ITexture* texture, const core::rect
glDisable(GL_SCISSOR_TEST); glDisable(GL_SCISSOR_TEST);
} }
void COGLES1Driver::draw2DImage(const video::ITexture* texture, u32 layer, bool flip) void COGLES1Driver::draw2DImageQuad(const video::ITexture* texture, u32 layer, bool flip)
{ {
if (!texture || !CacheHandler->getTextureCache().set(0, texture)) if (!texture || !CacheHandler->getTextureCache().set(0, texture))
return; return;

@ -109,7 +109,8 @@ namespace video
const core::rect<s32>& sourceRect, const core::rect<s32>* clipRect = 0, const core::rect<s32>& sourceRect, const core::rect<s32>* clipRect = 0,
const video::SColor* const colors = 0, bool useAlphaChannelOfTexture = false) IRR_OVERRIDE; const video::SColor* const colors = 0, bool useAlphaChannelOfTexture = false) IRR_OVERRIDE;
virtual void draw2DImage(const video::ITexture* texture, u32 layer, bool flip); // internally used
virtual void draw2DImageQuad(const video::ITexture* texture, u32 layer, bool flip);
//! draws a set of 2d images //! draws a set of 2d images
virtual void draw2DImageBatch(const video::ITexture* texture, virtual void draw2DImageBatch(const video::ITexture* texture,

@ -73,12 +73,16 @@ void COSOperator::copyToClipboard(const c8* text) const
char * buffer; char * buffer;
clipbuffer = GlobalAlloc(GMEM_DDESHARE, strlen(text)+1); clipbuffer = GlobalAlloc(GMEM_DDESHARE, strlen(text)+1);
if ( clipbuffer )
{
buffer = (char*)GlobalLock(clipbuffer); buffer = (char*)GlobalLock(clipbuffer);
if ( buffer )
{
strcpy(buffer, text); strcpy(buffer, text);
}
GlobalUnlock(clipbuffer); GlobalUnlock(clipbuffer);
SetClipboardData(CF_TEXT, clipbuffer); SetClipboardData(CF_TEXT, clipbuffer);
}
CloseClipboard(); CloseClipboard();
#elif defined(_IRR_COMPILE_WITH_OSX_DEVICE_) #elif defined(_IRR_COMPILE_WITH_OSX_DEVICE_)

@ -328,7 +328,7 @@ public:
glClear(GL_COLOR_BUFFER_BIT); glClear(GL_COLOR_BUFFER_BIT);
Driver->draw2DImage(this, layer, true); Driver->draw2DImageQuad(this, layer, true);
IImage* tmpImage = Driver->createImage(ECF_A8R8G8B8, Size); IImage* tmpImage = Driver->createImage(ECF_A8R8G8B8, Size);
glReadPixels(0, 0, Size.Width, Size.Height, GL_RGBA, GL_UNSIGNED_BYTE, tmpImage->getData()); glReadPixels(0, 0, Size.Width, Size.Height, GL_RGBA, GL_UNSIGNED_BYTE, tmpImage->getData());

@ -1446,7 +1446,7 @@ void COpenGLDriver::draw2DImage(const video::ITexture* texture, const core::rect
} }
void COpenGLDriver::draw2DImage(const video::ITexture* texture, u32 layer, bool flip) void COpenGLDriver::draw2DImageQuad(const video::ITexture* texture, u32 layer, bool flip)
{ {
if (!texture || !CacheHandler->getTextureCache().set(0, texture)) if (!texture || !CacheHandler->getTextureCache().set(0, texture))
return; return;

@ -148,7 +148,10 @@ namespace video
const core::rect<s32>& sourceRect, const core::rect<s32>* clipRect = 0, const core::rect<s32>& sourceRect, const core::rect<s32>* clipRect = 0,
const video::SColor* const colors = 0, bool useAlphaChannelOfTexture = false) IRR_OVERRIDE; const video::SColor* const colors = 0, bool useAlphaChannelOfTexture = false) IRR_OVERRIDE;
virtual void draw2DImage(const video::ITexture* texture, u32 layer, bool flip); // Was some helper function used in previous texture locking. Currently not accessible for users
// and also no longer needed internally (unless we switch back to old texture lock code).
// It seems to draw the texture to a fullscreen quad. Also allows drawing one side of a cubemap texture.
void draw2DImageQuad(const video::ITexture* texture, u32 layer, bool flip);
//! draws a set of 2d images, using a color and the alpha channel of the //! draws a set of 2d images, using a color and the alpha channel of the
//! texture if desired. //! texture if desired.

@ -609,13 +609,14 @@ IVolumeLightSceneNode* CSceneManager::addVolumeLightSceneNode(
//! the returned pointer must not be dropped. //! the returned pointer must not be dropped.
IMeshSceneNode* CSceneManager::addCubeSceneNode(f32 size, ISceneNode* parent, IMeshSceneNode* CSceneManager::addCubeSceneNode(f32 size, ISceneNode* parent,
s32 id, const core::vector3df& position, s32 id, const core::vector3df& position,
const core::vector3df& rotation, const core::vector3df& scale) const core::vector3df& rotation, const core::vector3df& scale,
ECUBE_MESH_TYPE type)
{ {
#ifdef _IRR_COMPILE_WITH_CUBE_SCENENODE_ #ifdef _IRR_COMPILE_WITH_CUBE_SCENENODE_
if (!parent) if (!parent)
parent = this; parent = this;
IMeshSceneNode* node = new CCubeSceneNode(size, parent, this, id, position, rotation, scale); IMeshSceneNode* node = new CCubeSceneNode(size, parent, this, id, position, rotation, scale, type);
node->drop(); node->drop();
return node; return node;

@ -73,7 +73,8 @@ namespace scene
virtual IMeshSceneNode* addCubeSceneNode(f32 size=10.0f, ISceneNode* parent=0, s32 id=-1, virtual IMeshSceneNode* addCubeSceneNode(f32 size=10.0f, ISceneNode* parent=0, s32 id=-1,
const core::vector3df& position = core::vector3df(0,0,0), const core::vector3df& position = core::vector3df(0,0,0),
const core::vector3df& rotation = core::vector3df(0,0,0), const core::vector3df& rotation = core::vector3df(0,0,0),
const core::vector3df& scale = core::vector3df(1.0f, 1.0f, 1.0f)) IRR_OVERRIDE; const core::vector3df& scale = core::vector3df(1.0f, 1.0f, 1.0f),
ECUBE_MESH_TYPE type=ECMT_1BUF_12VTX_NA) IRR_OVERRIDE;
//! Adds a sphere scene node to the scene. //! Adds a sphere scene node to the scene.
virtual IMeshSceneNode* addSphereSceneNode(f32 radius=5.0f, s32 polyCount=16, ISceneNode* parent=0, s32 id=-1, virtual IMeshSceneNode* addSphereSceneNode(f32 radius=5.0f, s32 polyCount=16, ISceneNode* parent=0, s32 id=-1,

@ -947,14 +947,14 @@ REALINLINE size_t clipToFrustumTest(const s4DVertex* v)
{ {
size_t flag = 0; size_t flag = 0;
flag |= v->Pos.z <= v->Pos.w ? VERTEX4D_CLIP_NEAR : 0; flag |= v->Pos.z <= v->Pos.w ? (size_t)VERTEX4D_CLIP_NEAR : 0;
flag |= -v->Pos.z <= v->Pos.w ? VERTEX4D_CLIP_FAR : 0; flag |= -v->Pos.z <= v->Pos.w ? (size_t)VERTEX4D_CLIP_FAR : 0;
flag |= v->Pos.x <= v->Pos.w ? VERTEX4D_CLIP_LEFT : 0; flag |= v->Pos.x <= v->Pos.w ? (size_t)VERTEX4D_CLIP_LEFT : 0;
flag |= -v->Pos.x <= v->Pos.w ? VERTEX4D_CLIP_RIGHT : 0; flag |= -v->Pos.x <= v->Pos.w ? (size_t)VERTEX4D_CLIP_RIGHT : 0;
flag |= v->Pos.y <= v->Pos.w ? VERTEX4D_CLIP_BOTTOM : 0; flag |= v->Pos.y <= v->Pos.w ? (size_t)VERTEX4D_CLIP_BOTTOM : 0;
flag |= -v->Pos.y <= v->Pos.w ? VERTEX4D_CLIP_TOP : 0; flag |= -v->Pos.y <= v->Pos.w ? (size_t)VERTEX4D_CLIP_TOP : 0;
/* /*

@ -145,6 +145,18 @@ namespace scene
virtual const core::aabbox3d<f32>& getTransformedBillboardBoundingBox(const irr::scene::ICameraSceneNode* camera) IRR_OVERRIDE; virtual const core::aabbox3d<f32>& getTransformedBillboardBoundingBox(const irr::scene::ICameraSceneNode* camera) IRR_OVERRIDE;
//! Get the amount of mesh buffers.
virtual u32 getMeshBufferCount() const IRR_OVERRIDE
{
return Mesh ? Mesh->getMeshBufferCount() : 0;
}
//! Get pointer to the mesh buffer.
virtual IMeshBuffer* getMeshBuffer(u32 nr) const IRR_OVERRIDE
{
return Mesh ? Mesh->getMeshBuffer(nr) : 0;
}
protected: protected:
void updateMesh(const irr::scene::ICameraSceneNode* camera); void updateMesh(const irr::scene::ICameraSceneNode* camera);

@ -290,7 +290,7 @@ void CWebGL1Driver::draw2DImage(const video::ITexture* texture, const core::rect
testGLError(); testGLError();
} }
void CWebGL1Driver::draw2DImage(const video::ITexture* texture, u32 layer, bool flip) void CWebGL1Driver::draw2DImageQuad(const video::ITexture* texture, u32 layer, bool flip)
{ {
if (!texture ) if (!texture )
return; return;

@ -64,7 +64,7 @@ namespace video
const video::SColor* const colors = 0, bool useAlphaChannelOfTexture = false) IRR_OVERRIDE; const video::SColor* const colors = 0, bool useAlphaChannelOfTexture = false) IRR_OVERRIDE;
// internally used // internally used
virtual void draw2DImage(const video::ITexture* texture, u32 layer, bool flip) IRR_OVERRIDE; virtual void draw2DImageQuad(const video::ITexture* texture, u32 layer, bool flip) IRR_OVERRIDE;
//! draws a set of 2d images //! draws a set of 2d images
virtual void draw2DImageBatch(const video::ITexture* texture, virtual void draw2DImageBatch(const video::ITexture* texture,

@ -549,7 +549,7 @@ private:
pos = origstr.findNext(L'&', pos); pos = origstr.findNext(L'&', pos);
} }
if (oldPos < (int)origstr.size()-1) if (oldPos < (int)origstr.size())
newstr.append(origstr.subString(oldPos, origstr.size()-oldPos)); newstr.append(origstr.subString(oldPos, origstr.size()-oldPos));
return newstr; return newstr;

@ -844,6 +844,7 @@
<ClInclude Include="..\..\include\EHardwareBufferFlags.h" /> <ClInclude Include="..\..\include\EHardwareBufferFlags.h" />
<ClInclude Include="..\..\include\EMaterialFlags.h" /> <ClInclude Include="..\..\include\EMaterialFlags.h" />
<ClInclude Include="..\..\include\EMaterialTypes.h" /> <ClInclude Include="..\..\include\EMaterialTypes.h" />
<ClInclude Include="..\..\include\EMeshBufferTypes.h" />
<ClInclude Include="..\..\include\EReadFileType.h" /> <ClInclude Include="..\..\include\EReadFileType.h" />
<ClInclude Include="..\..\include\EShaderTypes.h" /> <ClInclude Include="..\..\include\EShaderTypes.h" />
<ClInclude Include="..\..\include\fast_atof.h" /> <ClInclude Include="..\..\include\fast_atof.h" />

@ -1483,6 +1483,9 @@
<ClInclude Include="..\..\include\EDeviceTypes.h"> <ClInclude Include="..\..\include\EDeviceTypes.h">
<Filter>include</Filter> <Filter>include</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="..\..\include\EMeshBufferTypes.h">
<Filter>include\scene</Filter>
</ClInclude>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Include="..\..\changes.txt"> <None Include="..\..\changes.txt">

@ -356,67 +356,6 @@ bool GetDMFMaterials(const StringList& RawFile,
} }
/**This function extract an array of dmfMaterial from a DMF file considering 1st an 2nd layer for water plains.
You must give in input a StringList representing a DMF file loaded with LoadFromFile.
\return true if function succeed or false on fail.*/
bool GetDMFWaterMaterials(const StringList& RawFile /**<StringList representing a DMF file.*/,
core::array<dmfMaterial>& materials/**<Materials returned.*/,
int num_material/**<Number of materials contained in DMF file.*/
)
{
int offs=4;
StringList temp;
StringList temp1;
StringList temp2;
//Checking if this is a DeleD map File of version >= 0.91
temp=SubdivideString(RawFile[0],";");//file info
if ( temp[0] != "DeleD Map File" )
return false;//not a deled file
temp.clear();
temp=SubdivideString(RawFile[1]," ");//get version
temp1=SubdivideString(temp[1],";");
if (atof(temp1[0].c_str()) < 0.91)
return false;//not correct version
//end checking
temp.clear();
temp1.clear();
for(int i=0;i<num_material;i++)
{
temp = SubdivideString(RawFile[offs+i],";");
materials[i].materialID=i;
temp1 = SubdivideString(temp[5],",");
materials[i].textureFlag=atoi(temp1[0].c_str());
temp2 = SubdivideString(temp1[1],"\\");
materials[i].textureName=temp2.getLast();
temp1.clear();
temp2.clear();
int a=temp.size();
if(a==7)
{
temp1=SubdivideString(temp[6],",");
materials[i].lightmapFlag=atoi(temp1[0].c_str());
temp2=SubdivideString(temp1[1],"\\");
materials[i].lightmapName=temp2.getLast();
}
else
{
materials[i].lightmapFlag=1;
materials[i].lightmapName="FFFFFFFF";
}
temp1.clear();
temp2.clear();
}
return true;
}
/**This function extract an array of dmfVert and dmfFace from a DMF file. /**This function extract an array of dmfVert and dmfFace from a DMF file.
You must give in input a StringList representing a DMF file loaded with LoadFromFile and two arrays long enough. You must give in input a StringList representing a DMF file loaded with LoadFromFile and two arrays long enough.
Please use GetDMFHeader() before this function to know number of vertices and faces. Please use GetDMFHeader() before this function to know number of vertices and faces.
@ -501,6 +440,66 @@ bool GetDMFVerticesFaces(const StringList& RawFile/**<StringList representing a
return true; return true;
} }
#if 0 // functions unused and compiler gives us warnings about it. Keeping them in case anyone ever wants to improve support for this.
/**This function extract an array of dmfMaterial from a DMF file considering 1st an 2nd layer for water plains.
You must give in input a StringList representing a DMF file loaded with LoadFromFile.
\return true if function succeed or false on fail.*/
bool GetDMFWaterMaterials(const StringList& RawFile /**<StringList representing a DMF file.*/,
core::array<dmfMaterial>& materials/**<Materials returned.*/,
int num_material/**<Number of materials contained in DMF file.*/
)
{
int offs=4;
StringList temp;
StringList temp1;
StringList temp2;
//Checking if this is a DeleD map File of version >= 0.91
temp=SubdivideString(RawFile[0],";");//file info
if ( temp[0] != "DeleD Map File" )
return false;//not a deled file
temp.clear();
temp=SubdivideString(RawFile[1]," ");//get version
temp1=SubdivideString(temp[1],";");
if (atof(temp1[0].c_str()) < 0.91)
return false;//not correct version
//end checking
temp.clear();
temp1.clear();
for(int i=0;i<num_material;i++)
{
temp = SubdivideString(RawFile[offs+i],";");
materials[i].materialID=i;
temp1 = SubdivideString(temp[5],",");
materials[i].textureFlag=atoi(temp1[0].c_str());
temp2 = SubdivideString(temp1[1],"\\");
materials[i].textureName=temp2.getLast();
temp1.clear();
temp2.clear();
int a=temp.size();
if(a==7)
{
temp1=SubdivideString(temp[6],",");
materials[i].lightmapFlag=atoi(temp1[0].c_str());
temp2=SubdivideString(temp1[1],"\\");
materials[i].lightmapName=temp2.getLast();
}
else
{
materials[i].lightmapFlag=1;
materials[i].lightmapName="FFFFFFFF";
}
temp1.clear();
temp2.clear();
}
return true;
}
/**This function extract an array of dmfLights from a DMF file. /**This function extract an array of dmfLights from a DMF file.
You must give in input a StringList representing a DMF file loaded with You must give in input a StringList representing a DMF file loaded with
@ -723,6 +722,7 @@ bool GetDMFWaterPlanes(const StringList& RawFile/**<StringList representing a DM
return true; return true;
} }
#endif
} // end namespace } // end namespace
} // end namespace scene } // end namespace scene

@ -359,22 +359,21 @@ static void PHYSFS_utf8FromUcs2(const u16 *src, char *dst, u64 len)
void utf8ToWchar(const char *in, wchar_t *out, const u64 len) void utf8ToWchar(const char *in, wchar_t *out, const u64 len)
{ {
#ifdef _WIN32 switch ( sizeof(wchar_t) )
PHYSFS_utf8ToUcs2(in, (u16 *) out, len); {
#else case 2: PHYSFS_utf8ToUcs2(in, (u16 *) out, len); break;
PHYSFS_utf8ToUcs4(in, (u32 *) out, len); case 4: PHYSFS_utf8ToUcs4(in, (u32 *) out, len); break;
#endif }
} }
void wcharToUtf8(const wchar_t *in, char *out, const u64 len) void wcharToUtf8(const wchar_t *in, char *out, const u64 len)
{ {
#ifdef _WIN32 switch ( sizeof(wchar_t) )
PHYSFS_utf8FromUcs2((const u16 *) in, out, len); {
#else case 2: PHYSFS_utf8FromUcs2((const u16 *) in, out, len); break;
PHYSFS_utf8FromUcs4((const u32 *) in, out, len); case 4: PHYSFS_utf8FromUcs4((const u32 *) in, out, len); break;
#endif }
} }
} // end namespace core } // end namespace core
} // end namespace irr } // end namespace irr

@ -18,7 +18,7 @@ all: all_linux
# target specific settings # target specific settings
all_linux: SYSTEM=Linux all_linux: SYSTEM=Linux
all_linux: LDFLAGS = -L/usr/X11R6/lib$(LIBSELECT) -L../lib/$(SYSTEM) -lIrrlicht -lGL -lXxf86vm -lXext -lX11 -lXcursor all_linux: LDFLAGS = -L/usr/X11R6/lib$(LIBSELECT) -L../lib/$(SYSTEM) -lIrrlicht -lGL -lXxf86vm -lX11
all_win32 clean_win32: SYSTEM=Win32-gcc all_win32 clean_win32: SYSTEM=Win32-gcc
all_win32: LDFLAGS = -L../lib/$(SYSTEM) -lIrrlicht -lopengl32 -lm all_win32: LDFLAGS = -L../lib/$(SYSTEM) -lIrrlicht -lopengl32 -lm

Some files were not shown because too many files have changed in this diff Show More