diff --git a/changes.txt b/changes.txt index d84e595..e1d71be 100644 --- a/changes.txt +++ b/changes.txt @@ -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) +- 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. 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. diff --git a/examples/01.HelloWorld/Makefile b/examples/01.HelloWorld/Makefile index 6b6d16f..d046430 100644 --- a/examples/01.HelloWorld/Makefile +++ b/examples/01.HelloWorld/Makefile @@ -12,7 +12,7 @@ IrrlichtHome := ../.. BinPath = ../../bin/$(SYSTEM) # 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 CXXFLAGS += -g -Wall else diff --git a/examples/02.Quake3Map/Makefile b/examples/02.Quake3Map/Makefile index 10f2fcd..80ae387 100644 --- a/examples/02.Quake3Map/Makefile +++ b/examples/02.Quake3Map/Makefile @@ -12,7 +12,7 @@ IrrlichtHome := ../.. BinPath = ../../bin/$(SYSTEM) # 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 CXXFLAGS += -g -Wall else diff --git a/examples/03.CustomSceneNode/Makefile b/examples/03.CustomSceneNode/Makefile index 7daed21..11ad9fc 100644 --- a/examples/03.CustomSceneNode/Makefile +++ b/examples/03.CustomSceneNode/Makefile @@ -12,7 +12,7 @@ IrrlichtHome := ../.. BinPath = ../../bin/$(SYSTEM) # 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 CXXFLAGS += -g -Wall else diff --git a/examples/04.Movement/Makefile b/examples/04.Movement/Makefile index c5d50c9..bd156b3 100644 --- a/examples/04.Movement/Makefile +++ b/examples/04.Movement/Makefile @@ -12,7 +12,7 @@ IrrlichtHome := ../.. BinPath = ../../bin/$(SYSTEM) # 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 CXXFLAGS += -g -Wall else diff --git a/examples/04.Movement/main.cpp b/examples/04.Movement/main.cpp index dcbcc30..e7d3777 100644 --- a/examples/04.Movement/main.cpp +++ b/examples/04.Movement/main.cpp @@ -201,7 +201,7 @@ int main() */ int lastFPS = -1; - // In order to do framerate independent movement, we have to know + // In order to do frame rate independent movement, we have to know // how long it was since the last frame u32 then = device->getTimer()->getTime(); @@ -215,21 +215,24 @@ int main() const f32 frameDeltaTime = (f32)(now - then) / 1000.f; // Time in seconds then = now; - /* Check if keys W, S, A or D are being held down, and move the - sphere node around respectively. */ - core::vector3df nodePosition = sphereNode->getPosition(); + if ( sphereNode ) + { + /* Check if keys W, S, A or D are being held down, and move the + sphere node around respectively. */ + core::vector3df nodePosition = sphereNode->getPosition(); - if(receiver.IsKeyDown(irr::KEY_KEY_W)) - nodePosition.Y += MOVEMENT_SPEED * frameDeltaTime; - else if(receiver.IsKeyDown(irr::KEY_KEY_S)) - nodePosition.Y -= MOVEMENT_SPEED * frameDeltaTime; + if(receiver.IsKeyDown(irr::KEY_KEY_W)) + nodePosition.Y += MOVEMENT_SPEED * frameDeltaTime; + else if(receiver.IsKeyDown(irr::KEY_KEY_S)) + nodePosition.Y -= MOVEMENT_SPEED * frameDeltaTime; - if(receiver.IsKeyDown(irr::KEY_KEY_A)) - nodePosition.X -= MOVEMENT_SPEED * frameDeltaTime; - else if(receiver.IsKeyDown(irr::KEY_KEY_D)) - nodePosition.X += MOVEMENT_SPEED * frameDeltaTime; + if(receiver.IsKeyDown(irr::KEY_KEY_A)) + nodePosition.X -= MOVEMENT_SPEED * frameDeltaTime; + else if(receiver.IsKeyDown(irr::KEY_KEY_D)) + 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)); diff --git a/examples/05.UserInterface/Makefile b/examples/05.UserInterface/Makefile index fb91974..cba2100 100644 --- a/examples/05.UserInterface/Makefile +++ b/examples/05.UserInterface/Makefile @@ -12,7 +12,7 @@ IrrlichtHome := ../.. BinPath = ../../bin/$(SYSTEM) # 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 CXXFLAGS += -g -Wall else diff --git a/examples/06.2DGraphics/Makefile b/examples/06.2DGraphics/Makefile index 84cb831..bf4d05e 100644 --- a/examples/06.2DGraphics/Makefile +++ b/examples/06.2DGraphics/Makefile @@ -12,7 +12,7 @@ IrrlichtHome := ../.. BinPath = ../../bin/$(SYSTEM) # 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 CXXFLAGS += -g -Wall else diff --git a/examples/07.Collision/Makefile b/examples/07.Collision/Makefile index 25efc23..5e34ae9 100644 --- a/examples/07.Collision/Makefile +++ b/examples/07.Collision/Makefile @@ -12,7 +12,7 @@ IrrlichtHome := ../.. BinPath = ../../bin/$(SYSTEM) # 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 CXXFLAGS += -g -Wall else diff --git a/examples/08.SpecialFX/Makefile b/examples/08.SpecialFX/Makefile index 2a382f3..06f3999 100644 --- a/examples/08.SpecialFX/Makefile +++ b/examples/08.SpecialFX/Makefile @@ -12,7 +12,7 @@ IrrlichtHome := ../.. BinPath = ../../bin/$(SYSTEM) # 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 CXXFLAGS += -g -Wall else diff --git a/examples/09.Meshviewer/Makefile b/examples/09.Meshviewer/Makefile index e90ab52..64daf26 100644 --- a/examples/09.Meshviewer/Makefile +++ b/examples/09.Meshviewer/Makefile @@ -12,7 +12,7 @@ IrrlichtHome := ../.. BinPath = ../../bin/$(SYSTEM) # 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 CXXFLAGS += -g -Wall else diff --git a/examples/10.Shaders/Makefile b/examples/10.Shaders/Makefile index fc57b65..9c6abf6 100644 --- a/examples/10.Shaders/Makefile +++ b/examples/10.Shaders/Makefile @@ -12,7 +12,7 @@ IrrlichtHome := ../.. BinPath = ../../bin/$(SYSTEM) # 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 CXXFLAGS += -g -Wall else diff --git a/examples/11.PerPixelLighting/Makefile b/examples/11.PerPixelLighting/Makefile index fddcd34..73c67ba 100644 --- a/examples/11.PerPixelLighting/Makefile +++ b/examples/11.PerPixelLighting/Makefile @@ -12,7 +12,7 @@ IrrlichtHome := ../.. BinPath = ../../bin/$(SYSTEM) # 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 CXXFLAGS += -g -Wall else diff --git a/examples/12.TerrainRendering/Makefile b/examples/12.TerrainRendering/Makefile index 362bf06..4081961 100644 --- a/examples/12.TerrainRendering/Makefile +++ b/examples/12.TerrainRendering/Makefile @@ -12,7 +12,7 @@ IrrlichtHome := ../.. BinPath = ../../bin/$(SYSTEM) # 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 CXXFLAGS += -g -Wall else diff --git a/examples/13.RenderToTexture/Makefile b/examples/13.RenderToTexture/Makefile index 1022075..2096227 100644 --- a/examples/13.RenderToTexture/Makefile +++ b/examples/13.RenderToTexture/Makefile @@ -12,7 +12,7 @@ IrrlichtHome := ../.. BinPath = ../../bin/$(SYSTEM) # 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 CXXFLAGS += -g -Wall else diff --git a/examples/14.Win32Window/Makefile b/examples/14.Win32Window/Makefile index 5813ca0..9770668 100644 --- a/examples/14.Win32Window/Makefile +++ b/examples/14.Win32Window/Makefile @@ -12,7 +12,7 @@ IrrlichtHome := ../.. BinPath = ../../bin/$(SYSTEM) # 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 CXXFLAGS += -g -Wall else diff --git a/examples/14.Win32Window/main.cpp b/examples/14.Win32Window/main.cpp index 183381b..00289a6 100644 --- a/examples/14.Win32Window/main.cpp +++ b/examples/14.Win32Window/main.cpp @@ -1,19 +1,15 @@ /** 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, -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 #ifndef _IRR_WINDOWS_ #error Windows only example #else -#include // this example only runs with windows +#include // this example only runs with Windows #include #include "driverChoice.h" #include "exampleHelper.h" @@ -24,9 +20,11 @@ using namespace irr; #pragma comment(lib, "irrlicht.lib") #endif -HWND hOKButton; -HWND hWnd; +HWND hOKButton = 0; +/* + Windows message handler +*/ static LRESULT CALLBACK CustomWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { @@ -54,13 +52,11 @@ static LRESULT CALLBACK CustomWndProc(HWND hWnd, UINT message, return DefWindowProc(hWnd, message, wParam, lParam); } - -/* - Now ask for the driver and create the Windows specific window. -*/ int main() { - // ask user for driver + /* + Ask user for driver + */ video::E_DRIVER_TYPE driverType=driverChoiceConsole(); if (driverType==video::EDT_COUNT) return 1; @@ -76,9 +72,13 @@ int main() if (key != 'a' && key != 'b' && key != 'c') 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"); WNDCLASSEX wcex; @@ -103,7 +103,7 @@ int main() int windowWidth = 440; 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, NULL, NULL, hInstance, NULL); @@ -112,45 +112,54 @@ int main() windowWidth = clientRect.right; windowHeight = clientRect.bottom; - // create ok button - + // Create OK button hOKButton = CreateWindow(__TEXT("BUTTON"), __TEXT("OK - Close"), WS_CHILD | WS_VISIBLE | BS_TEXT, 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")\ __TEXT("Also mixing with MFC and .NET Windows.Forms is possible."), 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(""), WS_CHILD | WS_VISIBLE | BS_OWNERDRAW, 50, 80, 320, 220, hWnd, NULL, hInstance, NULL); - video::SExposedVideoData videodata((key=='b')?hIrrlichtWindow:0); /* - So now that we have some window, we can create an Irrlicht device - inside of it. We use Irrlicht createEx() function for this. We only - need the handle (HWND) to that window, set it as windowsID parameter - and start up the engine as usual. That's it. + So now that we have some Windows window, we can use it with Irrlicht. + There's several options. */ - // create irrlicht device in the button window - + irr::SIrrlichtCreationParameters param; 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') param.WindowId = reinterpret_cast(hIrrlichtWindow); irr::IrrlichtDevice* device = irr::createDeviceEx(param); - - // setup a simple 3d scene - irr::scene::ISceneManager* smgr = device->getSceneManager(); 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); PIXELFORMATDESCRIPTOR pfd={0}; @@ -165,6 +174,10 @@ int main() videodata.OpenGLWin32.HRc=wglCreateContext(HDc); wglShareLists((HGLRC)driver->getExposedVideoData().OpenGLWin32.HRc, (HGLRC)videodata.OpenGLWin32.HRc); } + + /* + Setup a simple 3d scene + */ scene::ICameraSceneNode* cam = smgr->addCameraSceneNode(); cam->setTarget(core::vector3df(0,0,0)); @@ -191,32 +204,36 @@ int main() driver->getTexture(mediaPath + "irrlicht2_bk.jpg")); // 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)); - // show and execute dialog - + // show and execute the Windows dialog ShowWindow(hWnd , SW_SHOW); UpdateWindow(hWnd); // do message queue +#if 1 // Irrlicht does the message handling with device->run() + /* Now the only thing missing is the drawing loop using 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 - Device->run() will cause Irrlicht to dispatch messages internally too. - You need not call Device->run() if you want to do your own message + device->run() will cause Irrlicht to dispatch messages internally too. + 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 then and you have to do it on your own using the window messages, DirectInput, or whatever. */ - while (device->run()) { + // draw 3d scene driver->beginScene(video::ECBF_COLOR | video::ECBF_DEPTH, video::SColor(0), 1.f, 0, videodata); smgr->drawAll(); driver->endScene(); + + // draw gui into second window if (key=='b') { 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() would look like this: */ - /*MSG msg; + MSG msg; while (true) { if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) @@ -245,11 +263,20 @@ int main() // advance virtual time device->getTimer()->tick(); - // draw engine picture - driver->beginScene(true, true, 0, (key=='c')?hIrrlichtWindow:0); + // draw 3d scene + driver->beginScene(true, true, 0, videodata); smgr->drawAll(); 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->drop(); @@ -259,5 +286,5 @@ int main() #endif // if windows /* -That's it, Irrlicht now runs in your own windows window. +That's it, Irrlicht now uses a Windows window. **/ diff --git a/examples/15.LoadIrrFile/Makefile b/examples/15.LoadIrrFile/Makefile index 5fde118..2383b87 100644 --- a/examples/15.LoadIrrFile/Makefile +++ b/examples/15.LoadIrrFile/Makefile @@ -12,7 +12,7 @@ IrrlichtHome := ../.. BinPath = ../../bin/$(SYSTEM) # 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 CXXFLAGS += -g -Wall else diff --git a/examples/16.Quake3MapShader/Makefile b/examples/16.Quake3MapShader/Makefile index e4d5fb1..c9b197d 100644 --- a/examples/16.Quake3MapShader/Makefile +++ b/examples/16.Quake3MapShader/Makefile @@ -12,7 +12,7 @@ IrrlichtHome := ../.. BinPath = ../../bin/$(SYSTEM) # 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 CXXFLAGS += -g -Wall else diff --git a/examples/16.Quake3MapShader/main.cpp b/examples/16.Quake3MapShader/main.cpp index 38062c5..356a060 100644 --- a/examples/16.Quake3MapShader/main.cpp +++ b/examples/16.Quake3MapShader/main.cpp @@ -41,7 +41,7 @@ using namespace irr; 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 to make it easy, we use a pragma comment lib: */ @@ -66,25 +66,25 @@ public: bool OnEvent(const SEvent& event) { - // check if user presses the key F9 if ((event.EventType == EET_KEY_INPUT_EVENT) && event.KeyInput.PressedDown) { + // check if user presses the key F9 for making a screenshot if (event.KeyInput.Key == KEY_F9) { video::IImage* image = Device->getVideoDriver()->createScreenShot(); if (image) { c8 buf[256]; - snprintf_irr(buf, 256, "%s_shot%04d.jpg", + snprintf_irr(buf, 256, "%s_shot%04u.jpg", FilenameTemplate.c_str(), ++Number); Device->getVideoDriver()->writeImageToFile(image, buf, 85 ); image->drop(); } } - else - if (event.KeyInput.Key == KEY_F8) + // Check for F8 - enabling/disabling display of bounding box for the map + else if (event.KeyInput.Key == KEY_F8) { if (Node->isDebugDataVisible()) 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 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 this decision possible too. */ @@ -130,6 +130,7 @@ int IRRCALLCONV main(int argc, char* argv[]) if (device == 0) return 1; // could not create selected driver. + // We allow passing a map name as command line parameter const char* mapname=0; if (argc>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 - 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 attached. Hence the IAnimated mesh consists of only one frame, 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); /* - now construct SceneNodes for each Shader - The Objects are stored in the quake mesh scene::E_Q3_MESH_ITEMS - and the Shader ID is stored in the MaterialParameters + now construct SceneNodes for each shader + The objects are stored in the quake mesh scene::E_Q3_MESH_ITEMS + and the shader ID is stored in the MaterialParameters mostly dark looking skulls and moving lava.. or green flashing tubes? */ 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 - 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 button pressed, Zoom with both buttons pressed, translate with right mouse button pressed. This could be created with @@ -266,8 +267,8 @@ int IRRCALLCONV main(int argc, char* argv[]) scene::ICameraSceneNode* camera = smgr->addCameraSceneNodeFPS(); /* - so we need a good starting Position in the level. - we can ask the Quake3 Loader for all entities with class_name + 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 choose a random launch */ @@ -356,6 +357,8 @@ int IRRCALLCONV main(int argc, char* argv[]) gui->drawAll(); driver->endScene(); + // Display some info + // Setting window caption can be rather slow, so usually shouldn't be done each frame. int fps = driver->getFPS(); if (1 || lastFPS != fps) { @@ -376,7 +379,7 @@ int IRRCALLCONV main(int argc, char* argv[]) str += "/"; str += attr->getAttributeAsInt("drawn_transparent_effect"); #endif - device->setWindowCaption(str.c_str()); + device->setWindowCaption(str.c_str()); lastFPS = fps; } } diff --git a/examples/17.HelloWorld_Mobile/Makefile b/examples/17.HelloWorld_Mobile/Makefile index a29ccaa..c90e93c 100644 --- a/examples/17.HelloWorld_Mobile/Makefile +++ b/examples/17.HelloWorld_Mobile/Makefile @@ -5,7 +5,7 @@ Target = 17.HelloWorld_Mobile Sources = main.cpp # general compiler settings -CPPFLAGS = -I../../include -I/usr/X11R6/include +CPPFLAGS = -I../../include CXXFLAGS = -O3 -ffast-math #CXXFLAGS = -g -Wall diff --git a/examples/18.SplitScreen/Makefile b/examples/18.SplitScreen/Makefile index fd41401..b24b181 100644 --- a/examples/18.SplitScreen/Makefile +++ b/examples/18.SplitScreen/Makefile @@ -12,7 +12,7 @@ IrrlichtHome := ../.. BinPath = ../../bin/$(SYSTEM) # 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 CXXFLAGS += -g -Wall else diff --git a/examples/18.SplitScreen/main.cpp b/examples/18.SplitScreen/main.cpp index 85aa403..9b768ec 100644 --- a/examples/18.SplitScreen/main.cpp +++ b/examples/18.SplitScreen/main.cpp @@ -2,11 +2,11 @@ A tutorial by Max Winkel. -In this tutorial we'll learn how to use splitscreen (e.g. for racing-games) -with Irrlicht. We'll create a viewport divided -into 4 parts, with 3 fixed cameras and one user-controlled. +In this tutorial we'll learn how to use split screen (e.g. for racing-games) +with Irrlicht. We'll create a viewport divided into 4 parts, with 3 fixed +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) */ @@ -23,55 +23,62 @@ using namespace irr; using namespace core; using namespace video; using namespace scene; +using namespace gui; /* Now we'll define the resolution in a constant for use in -initializing the device and setting up the viewport. In addition -we set up a global variable saying splitscreen is active or not. +initializing the device and setting up the viewport. */ + //Resolution const int ResX=800; const int ResY=600; -const bool fullScreen=false; //Use SplitScreen? 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, -whenever the user press the S-key. All other events are sent -to the FPS camera. +whenever the user press the S-key. +We also allow quitting the application with ESC. */ - class MyEventReceiver : public IEventReceiver { public: virtual bool OnEvent(const SEvent& event) { //Key S enables/disables SplitScreen - if (event.EventType == irr::EET_KEY_INPUT_EVENT && - event.KeyInput.Key == KEY_KEY_S && event.KeyInput.PressedDown) + if (event.EventType == irr::EET_KEY_INPUT_EVENT && event.KeyInput.PressedDown ) { - SplitScreen = !SplitScreen; - return true; + if ( event.KeyInput.Key == KEY_KEY_S ) + { + SplitScreen = !SplitScreen; + return true; + } + if (event.KeyInput.Key == KEY_ESCAPE ) + { + Quit = true; + return true; + } } - //Send all other events to camera4 - if (camera[3]) - return camera[3]->OnEvent(event); + return false; } }; /* -Ok, now the main-function: -First, we initialize the device, get the SourceManager and -VideoDriver, load an animated mesh from .md2 and a map from -.pk3. Because that's old stuff, I won't explain every step. +The main-function: +First, we initialize the device, get some useful variables, +load an animated mesh from .md2 and a map from .pk3. +Because that's old stuff, I won't explain every step. Just take care of the maps position. */ int main() @@ -84,7 +91,8 @@ int main() //Instance of the EventReceiver MyEventReceiver receiver; - //Initialise the engine + //Initialize the engine + const bool fullScreen=false; IrrlichtDevice *device = createDevice(driverType, dimension2du(ResX,ResY), 32, fullScreen, false, false, &receiver); @@ -93,6 +101,7 @@ int main() ISceneManager *smgr = device->getSceneManager(); IVideoDriver *driver = device->getVideoDriver(); + IGUIEnvironment* guienv = device->getGUIEnvironment(); const io::path mediaPath = getExampleMediaPath(); @@ -121,6 +130,9 @@ int main() 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" to switch split screen.\n to quit", recti(5,5, 100, 30), false, true, 0, -1, true); + /* 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 @@ -129,19 +141,19 @@ user. */ // Create 3 fixed and one user-controlled cameras //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 - 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 - 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 - camera[3] = smgr->addCameraSceneNodeFPS(); - // don't start at sydney's position - if (camera[3]) - camera[3]->setPosition(core::vector3df(-50,0,-50)); + Camera[3] = smgr->addCameraSceneNodeFPS(); + // don't start at Sydney's position + if (Camera[3]) + 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 device->getCursorControl()->setVisible(false); @@ -150,12 +162,12 @@ Create a variable for counting the fps and hide the mouse: /* There wasn't much new stuff - till now! -Only by defining four cameras, the game won't be splitscreen. -To do this you need several steps: +The game won't be split the screen just by defining four cameras. +To do this several steps are needed: - Set the viewport to the whole screen - Begin a new scene (Clear screen) - - The following 3 steps are repeated for every viewport in the splitscreen + - The following 3 steps are repeated for every viewport in the split screen - Set the viewport to the area you wish - Activate the camera which should be "linked" with the viewport - Render all objects @@ -168,31 +180,31 @@ To do this you need several steps: 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 - camera[3]->setInputReceiverEnabled(device->isWindowActive()); + Camera[3]->setInputReceiverEnabled(device->isWindowActive()); //Set the viewpoint to the whole screen and begin scene driver->setViewPort(rect(0,0,ResX,ResY)); driver->beginScene(video::ECBF_COLOR | video::ECBF_DEPTH, SColor(255,100,100,100)); - //If SplitScreen is used + //If split screen is used if (SplitScreen) { //Activate camera1 - smgr->setActiveCamera(camera[0]); + smgr->setActiveCamera(Camera[0]); //Set viewpoint to the first quarter (left top) driver->setViewPort(rect(0,0,ResX/2,ResY/2)); //Draw scene smgr->drawAll(); //Activate camera2 - smgr->setActiveCamera(camera[1]); + smgr->setActiveCamera(Camera[1]); //Set viewpoint to the second quarter (right top) driver->setViewPort(rect(ResX/2,0,ResX,ResY/2)); //Draw scene smgr->drawAll(); //Activate camera3 - smgr->setActiveCamera(camera[2]); + smgr->setActiveCamera(Camera[2]); //Set viewpoint to the third quarter (left bottom) driver->setViewPort(rect(0,ResY/2,ResX/2,ResY)); //Draw scene @@ -201,15 +213,21 @@ Sounds a little complicated, but you'll see it isn't: driver->setViewPort(rect(ResX/2,ResY/2,ResX,ResY)); } //Activate camera4 - smgr->setActiveCamera(camera[3]); + smgr->setActiveCamera(Camera[3]); //Draw scene smgr->drawAll(); + + // Back to whole screen for the UI + if (SplitScreen) + driver->setViewPort(rect(0,0,ResX,ResY)); + guienv->drawAll(); + driver->endScene(); /* As you can probably see, the image is rendered for every 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 easy: In the rect-function you define 4 coordinates: - 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 to check out what happens. - Now we just view the current fps and shut down the engine, - when the user wants to: + Last we show the current fps. */ - //Get and show fps if (driver->getFPS() != lastFPS) { 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. -Note: With the S-Key you can switch between using splitscreen -and not. **/ - diff --git a/examples/19.MouseAndJoystick/Makefile b/examples/19.MouseAndJoystick/Makefile index 90d08fb..26b936d 100644 --- a/examples/19.MouseAndJoystick/Makefile +++ b/examples/19.MouseAndJoystick/Makefile @@ -12,7 +12,7 @@ IrrlichtHome := ../.. BinPath = ../../bin/$(SYSTEM) # 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 CXXFLAGS += -g -Wall else diff --git a/examples/19.MouseAndJoystick/main.cpp b/examples/19.MouseAndJoystick/main.cpp index faa6305..fc1995e 100644 --- a/examples/19.MouseAndJoystick/main.cpp +++ b/examples/19.MouseAndJoystick/main.cpp @@ -3,13 +3,11 @@ This tutorial builds on example 04.Movement which showed how to handle keyboard events in Irrlicht. Here we'll handle mouse events and joystick events, if you have a joystick connected and a device -that supports joysticks. These are currently Windows, Linux and SDL +that supports joysticks. These are currently Windows, Linux and SDL devices. */ #ifdef _MSC_VER -// We'll define this to stop MSVC complaining about sprintf(). -#define _CRT_SECURE_NO_WARNINGS #pragma comment(lib, "Irrlicht.lib") #endif @@ -19,8 +17,21 @@ devices. 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. + +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 { @@ -30,7 +41,8 @@ public: { core::position2di Position; bool LeftButtonDown; - SMouseState() : LeftButtonDown(false) { } + bool WasMouseMoved; + SMouseState() : LeftButtonDown(false), WasMouseMoved(false) { } } MouseState; // This is the one method that we have to implement @@ -52,6 +64,7 @@ public: case EMIE_MOUSE_MOVED: MouseState.Position.X = event.MouseInput.X; MouseState.Position.Y = event.MouseInput.Y; + MouseState.WasMouseMoved = true; break; default: @@ -63,7 +76,6 @@ public: // The state of each connected joystick is sent to us // once every run() of the Irrlicht device. Store the // 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 && event.JoystickEvent.Joystick == 0) { @@ -83,9 +95,9 @@ public: return MouseState; } - - MyEventReceiver() + void ResetMouseMoved() { + MouseState.WasMouseMoved = false; } 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 -just create an irr::IrrlichtDevice and the scene node we want to move. We also -create some other additional scene nodes, to show that there are also some -different possibilities to move and animate scene nodes. +just create an irr::IrrlichtDevice and the scene node we want to move. */ int main() { @@ -117,6 +127,11 @@ int main() 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 joystickInfo; if(device->activateJoysticks(joystickInfo)) { @@ -153,6 +168,7 @@ int main() std::cout << "Joystick support is not enabled." << std::endl; } + // Set some window caption text core::stringw tmp = L"Irrlicht Joystick Example ("; tmp += joystickInfo.size(); tmp += " joysticks)"; @@ -179,20 +195,24 @@ int main() camera->setPosition(core::vector3df(0, 0, -10)); // 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; + // Ignore all events which happened until now. + // Like mouse events triggered while we chose our driver. + device->clearSystemMessages(); + while(device->run()) { // 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 then = now; bool movedWithJoystick = false; 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 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.Y += MOVEMENT_SPEED * frameDeltaTime * moveVertical; 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(!movedWithJoystick) + if (!movedWithJoystick && receiver.GetMouseState().WasMouseMoved) { // Create a ray through the mouse cursor. core::line3df ray = smgr->getSceneCollisionManager()->getRayFromScreenCoordinates( @@ -257,9 +280,13 @@ int main() const f32 availableMovement = MOVEMENT_SPEED * frameDeltaTime; if(toMousePosition.getLength() <= availableMovement) + { nodePosition = mousePosition; // Jump to the final position + } else + { nodePosition += toMousePosition.normalize() * availableMovement; // Move towards it + } } } diff --git a/examples/20.ManagedLights/Makefile b/examples/20.ManagedLights/Makefile index 6fe4245..c9828bb 100644 --- a/examples/20.ManagedLights/Makefile +++ b/examples/20.ManagedLights/Makefile @@ -12,7 +12,7 @@ IrrlichtHome := ../.. BinPath = ../../bin/$(SYSTEM) # 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 CXXFLAGS += -g -Wall else diff --git a/examples/21.Quake3Explorer/Makefile b/examples/21.Quake3Explorer/Makefile index 9b33360..3e32723 100644 --- a/examples/21.Quake3Explorer/Makefile +++ b/examples/21.Quake3Explorer/Makefile @@ -12,7 +12,7 @@ IrrlichtHome := ../.. BinPath = ../../bin/$(SYSTEM) # 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 CXXFLAGS += -g -Wall else diff --git a/examples/21.Quake3Explorer/main.cpp b/examples/21.Quake3Explorer/main.cpp index 7b14c92..ecb98b5 100644 --- a/examples/21.Quake3Explorer/main.cpp +++ b/examples/21.Quake3Explorer/main.cpp @@ -3,13 +3,13 @@ This tutorial shows how to load different Quake 3 maps. Features: - - Load BSP Archives at Runtime from the menu - - Load a Map from the menu. Showing with Screenshot + - Load BSP archives at runtime from the menu + - Load a map from the menu. Showing with screenshot - Set the VideoDriver at runtime from menu - Adjust GammaLevel at runtime - - Create SceneNodes for the Shaders - - Load EntityList and create Entity SceneNodes - - Create Players with Weapons and with Collision Response + - Create SceneNodes for the shaders + - Load EntityList and create entity SceneNodes + - Create players with weapons and with collision response - Play music You can download the Quake III Arena demo ( copyright id software ) @@ -26,7 +26,7 @@ Copyright 2006-2011 Burningwater, Thomas Alten #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 { @@ -100,7 +100,7 @@ void GameData::setDefault () loadParam.mergeShaderBuffer = 1; // merge meshbuffers with same material loadParam.cleanUnResolvedMeshes = 1; // should unresolved meshes be cleaned. otherwise blue texture 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; 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 ) { - return 0; + return 0; // TODO: Anyone knows why it just returns? if (!Device) return 0; c8 buf[128]; u32 i; - // Store current Archive for restart + // Store current archive for restart CurrentArchiveList.clear(); IFileSystem *fs = Device->getFileSystem(); 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() ); } - // Store Player Position and Rotation + // Store player position and rotation ICameraSceneNode * camera = Device->getSceneManager()->getActiveCamera (); if ( camera ) { @@ -279,7 +279,7 @@ void Q3Player::create ( IrrlichtDevice *device, IQ3LevelMesh* mesh, ISceneNode * if (!device) return; - // load FPS weapon to Camera + // load FPS weapon to camera Device = device; Mesh = mesh; MapParent = mapNode; @@ -377,8 +377,8 @@ void Q3Player::create ( IrrlichtDevice *device, IQ3LevelMesh* mesh, ISceneNode * /* - 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" + 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" */ 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 ) { @@ -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 ) { @@ -446,7 +446,7 @@ void Q3Player::OnAnimationEnd(IAnimatedMeshSceneNode* node) -/* GUI Elements +/* GUI elements */ struct GUI { @@ -560,13 +560,13 @@ CQuake3EventHandler::CQuake3EventHandler( GameData *game ) BulletParent(0), FogParent(0), SkyNode(0), Meta(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 ) { 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); // create internal textures @@ -599,21 +599,10 @@ void CQuake3EventHandler::createTextures() video::IImage* image; u32 i; - u32 x; - u32 y; - u32 * data; for ( i = 0; i != 8; ++i ) { image = driver->createImage ( video::ECF_A8R8G8B8, dim); - data = (u32*) image->getData (); - for ( y = 0; y != dim.Height; ++y ) - { - for ( x = 0; x != dim.Width; ++x ) - { - data [x] = 0xFFFFFFFF; - } - data = (u32*) ( (u8*) data + image->getPitch() ); - } + image->fill(SColor(0xFFFFFFFF)); snprintf_irr ( buf, 64, "smoke_%02d", i ); driver->addTexture( buf, image ); image->drop (); @@ -623,15 +612,7 @@ void CQuake3EventHandler::createTextures() for ( i = 0; i != 1; ++i ) { image = driver->createImage ( video::ECF_A8R8G8B8, dim); - data = (u32*) image->getData (); - for ( y = 0; y != dim.Height; ++y ) - { - for ( x = 0; x != dim.Width; ++x ) - { - data [x] = 0xFFFFFFFF; - } - data = (u32*) ( (u8*) data + image->getPitch() ); - } + image->fill(SColor(0xFFFFFFFF)); snprintf_irr ( buf, 64, "fog_%02d", i ); driver->addTexture( buf, image ); image->drop (); @@ -644,7 +625,6 @@ void CQuake3EventHandler::createTextures() */ void CQuake3EventHandler::CreateGUI() { - IGUIEnvironment *env = Game->Device->getGUIEnvironment(); IVideoDriver * driver = Game->Device->getVideoDriver(); @@ -663,15 +643,6 @@ void CQuake3EventHandler::CreateGUI() // minimal gui size 800x600 dimension2d dim ( 800, 600 ); - dimension2d vdim ( Game->Device->getVideoDriver()->getScreenSize() ); - - if ( vdim.Height >= dim.Height && vdim.Width >= dim.Width ) - { - //dim = vdim; - } - else - { - } gui.Window = env->addWindow ( rect ( 0, 0, dim.Width, dim.Height ), false, L"Quake3 Explorer" ); 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 - // show the attached Archive in proper order + // show the attached archive in proper order if ( gui.ArchiveList ) { 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 () { @@ -1113,9 +1084,9 @@ void CQuake3EventHandler::LoadMap ( const stringw &mapName, s32 collision ) BulletParent->setName ( "Bullet Container" ); /* - now construct SceneNodes for each Shader - The Objects are stored in the quake mesh E_Q3_MESH_ITEMS - and the Shader ID is stored in the MaterialParameters + now construct SceneNodes for each shader + The objects are stored in the quake mesh E_Q3_MESH_ITEMS + and the shader ID is stored in the MaterialParameters mostly dark looking skulls and moving lava.. or green flashing tubes? */ 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 ); /* - Now construct Models from Entity List + Now construct models from entity list */ 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) { @@ -1169,7 +1140,7 @@ void CQuake3EventHandler::addSceneTreeItem( ISceneNode * parent, IGUITreeViewNod node = nodeParent->addChildBack( msg, 0, imageIndex ); - // Add all Animators + // Add all animators list::ConstIterator ait = (*it)->getAnimators().begin(); for (; ait != (*it)->getAnimators().end(); ++ait) { @@ -1753,7 +1724,7 @@ void CQuake3EventHandler::useItem( Q3Player * player) } else { - // doesnt collide with wall + // doesn't collide with wall vector3df start = camera->getPosition(); if ( player->WeaponNode ) { @@ -2104,7 +2075,7 @@ void runGame ( GameData *game ) 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 () ) { eventHandler->LoadMap ( game->CurrentMapName, 1 ); diff --git a/examples/21.Quake3Explorer/q3factory.cpp b/examples/21.Quake3Explorer/q3factory.cpp index 476a2ed..c3bdb24 100644 --- a/examples/21.Quake3Explorer/q3factory.cpp +++ b/examples/21.Quake3Explorer/q3factory.cpp @@ -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 */ void Q3ShaderFactory ( Q3LevelLoadParameter &loadParam, @@ -399,7 +399,7 @@ void Q3ShaderFactory ( Q3LevelLoadParameter &loadParam, sceneNodeID += 1; } - // show Debug Shader Name + // show debug shader name if ( showShaderName && node ) { swprintf_irr ( (wchar_t*) buf, 64, L"%hs:%d", node->getName(),node->getID() ); @@ -413,7 +413,7 @@ void Q3ShaderFactory ( Q3LevelLoadParameter &loadParam, sceneNodeID += 1; } - // create Portal Rendertargets + // create portal rendertargets if ( shader ) { 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, IrrlichtDevice *device, @@ -513,7 +513,7 @@ void Q3ModelFactory ( Q3LevelLoadParameter &loadParam, char buf[128]; - const SVarGroup *group; + const SVarGroup *group = 0; IEntity search; s32 index; s32 lastIndex; @@ -531,12 +531,12 @@ void Q3ModelFactory ( Q3LevelLoadParameter &loadParam, } fclose ( f ); */ - IAnimatedMeshMD3* model; - SMD3Mesh * mesh; - const SMD3MeshBuffer *meshBuffer; - IMeshSceneNode* node; - ISceneNodeAnimator* anim; - const IShader *shader; + IAnimatedMeshMD3* model = 0; + SMD3Mesh * mesh = 0; + const SMD3MeshBuffer *meshBuffer = 0; + IMeshSceneNode* node = 0; + ISceneNodeAnimator* anim = 0; + const IShader *shader = 0; u32 pos; vector3df p; u32 nodeCount = 0; @@ -546,7 +546,7 @@ void Q3ModelFactory ( Q3LevelLoadParameter &loadParam, if ( showShaderName ) font = device->getGUIEnvironment()->getFont("fontlucida.png"); - const SItemElement *itemElement; + const SItemElement *itemElement = 0; // walk list for ( index = 0; (u32) index < entity.size(); ++index ) @@ -706,7 +706,7 @@ s32 Q3StartPosition ( IQ3LevelMesh* mesh, u32 parsepos; - const SVarGroup *group; + const SVarGroup *group = 0; group = entityList[ index ].getGroup(1); parsepos = 0; @@ -802,7 +802,7 @@ ISceneNodeAnimatorCollisionResponse* camCollisionResponse( IrrlichtDevice * devi } -//! internal Animation +//! internal animation void setTimeFire ( TimeFire *t, u32 delta, u32 flags ) { t->flags = flags; diff --git a/examples/21.Quake3Explorer/q3factory.h b/examples/21.Quake3Explorer/q3factory.h index d9606ed..51b727e 100644 --- a/examples/21.Quake3Explorer/q3factory.h +++ b/examples/21.Quake3Explorer/q3factory.h @@ -46,7 +46,7 @@ enum eItemSubGroup CHAINGUN, }; -//! aplly a special effect to the shader +//! apply a special effect to the shader enum eItemSpecialEffect { SPECIAL_SFX_NONE = 0, @@ -55,7 +55,7 @@ enum eItemSpecialEffect SPECIAL_SFX_ROTATE_1 = 4, }; -// a List for defining a model +// a list for defining a model struct SItemElement { 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 ); -//! internal Animation +//! internal animation enum eTimeFireFlag { FIRED = 1, diff --git a/examples/22.MaterialViewer/Makefile b/examples/22.MaterialViewer/Makefile index fcbdc22..1c24d09 100644 --- a/examples/22.MaterialViewer/Makefile +++ b/examples/22.MaterialViewer/Makefile @@ -12,7 +12,7 @@ IrrlichtHome := ../.. BinPath = ../../bin/$(SYSTEM) # 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 CXXFLAGS += -g -Wall else diff --git a/examples/22.MaterialViewer/main.cpp b/examples/22.MaterialViewer/main.cpp index 358ce02..d814d4f 100755 --- a/examples/22.MaterialViewer/main.cpp +++ b/examples/22.MaterialViewer/main.cpp @@ -1,6 +1,6 @@ /** 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. 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. -// For now just change the defaultMaterial in CApp::init for the rest. -// TODO: Allow users to switch between a sphere and a box mesh. +// For now just change the defaultMaterial in CApp::setActiveMeshNodeType for the rest. #include #include "driverChoice.h" @@ -127,9 +126,8 @@ video::E_VERTEX_TYPE getVertexTypeForMaterialType(video::E_MATERIAL_TYPE materia } /* - Custom GUI-control to edit colorvalues. + Custom GUI-control to edit color values. */ -// Constructor CColorControl::CColorControl(gui::IGUIEnvironment* guiEnv, const core::position2d & pos, const wchar_t *text, IGUIElement* parent, s32 id) : gui::IGUIElement(gui::EGUIET_ELEMENT, guiEnv, parent,id, core::rect< s32 >(pos, pos+core::dimension2d(80, 75))) , 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); groupElement->setNotClipped(true); - guiEnv->addStaticText (text, core::rect(0,0,80,15), false, false, groupElement, -1, false); + s32 border=guiEnv->getSkin()->getSize(EGDS_TEXT_DISTANCE_X); + guiEnv->addStaticText(text, core::rect(border,border,80,15), false, false, groupElement, -1, true); - EditAlpha = addEditForNumbers(guiEnv, core::position2d(0,15), L"a", -1, groupElement ); - EditRed = addEditForNumbers(guiEnv, core::position2d(0,30), L"r", -1, groupElement ); - EditGreen = addEditForNumbers(guiEnv, core::position2d(0,45), L"g", -1, groupElement ); - EditBlue = addEditForNumbers(guiEnv, core::position2d(0,60), L"b", -1, groupElement ); + EditAlpha = addEditForNumbers(guiEnv, core::position2d(border,15), L"a", -1, groupElement ); + EditRed = addEditForNumbers(guiEnv, core::position2d(border,30), L"r", -1, groupElement ); + EditGreen = addEditForNumbers(guiEnv, core::position2d(border,45), L"g", -1, groupElement ); + EditBlue = addEditForNumbers(guiEnv, core::position2d(border,60), L"b", -1, groupElement ); ColorStatic = guiEnv->addStaticText (L"", core::rect(60,15,80,75), true, false, groupElement, -1, true); @@ -163,10 +162,9 @@ CColorControl::CColorControl(gui::IGUIEnvironment* guiEnv, const core::position2 // event receiver bool CColorControl::OnEvent(const SEvent &event) { - if ( event.EventType != EET_GUI_EVENT ) - return false; - - if ( event.GUIEvent.Caller->getID() == ButtonSetId && event.GUIEvent.EventType == gui::EGET_BUTTON_CLICKED ) + if ( event.EventType == EET_GUI_EVENT + && event.GUIEvent.Caller->getID() == ButtonSetId + && event.GUIEvent.EventType == gui::EGET_BUTTON_CLICKED ) { Color = getColorFromEdits(); setEditsFromColor(Color); @@ -183,60 +181,52 @@ void CColorControl::setColor(const video::SColor& col) 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 & pos, const wchar_t *text, s32 id, gui::IGUIElement * parent) { using namespace gui; - core::rect< s32 > rect(pos, pos+core::dimension2d(10, 15)); - guiEnv->addStaticText (text, rect, false, false, parent, -1, false); + core::recti rect(pos, pos+core::dimension2d(10, 15)); + guiEnv->addStaticText(text, rect, false, false, parent, -1, false); rect += core::position2d( 20, 0 ); rect.LowerRightCorner.X += 20; gui::IGUIEditBox* edit = guiEnv->addEditBox(L"0", rect, true, parent, id); return edit; } -// Get the color value from the editfields +// Get the color value from the editboxes video::SColor CColorControl::getColorFromEdits() const { video::SColor col; if (EditAlpha) { - u32 alpha = core::strtoul10(core::stringc(EditAlpha->getText()).c_str()); - if (alpha > 255) - alpha = 255; + u32 alpha = core::min_(core::strtoul10(core::stringc(EditAlpha->getText()).c_str()), 255u); col.setAlpha(alpha); } if (EditRed) { - u32 red = core::strtoul10(core::stringc(EditRed->getText()).c_str()); - if (red > 255) - red = 255; + u32 red = core::min_(core::strtoul10(core::stringc(EditRed->getText()).c_str()), 255u); col.setRed(red); } if (EditGreen) { - u32 green = core::strtoul10(core::stringc(EditGreen->getText()).c_str()); - if (green > 255) - green = 255; + u32 green = core::min_(core::strtoul10(core::stringc(EditGreen->getText()).c_str()), 255u); col.setGreen(green); } if (EditBlue) { - u32 blue = core::strtoul10(core::stringc(EditBlue->getText()).c_str()); - if (blue > 255) - blue = 255; + u32 blue = core::min_(core::strtoul10(core::stringc(EditBlue->getText()).c_str()), 255u); col.setBlue(blue); } 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) { DirtyFlag = true; @@ -345,10 +335,9 @@ CTextureControl::CTextureControl(gui::IGUIEnvironment* guiEnv, video::IVideoDriv bool CTextureControl::OnEvent(const SEvent &event) { - if ( event.EventType != EET_GUI_EVENT ) - return false; - - if ( event.GUIEvent.Caller == ComboTexture && event.GUIEvent.EventType == gui::EGET_COMBO_BOX_CHANGED ) + if ( event.EventType == EET_GUI_EVENT + && event.GUIEvent.Caller == ComboTexture + && event.GUIEvent.EventType == gui::EGET_COMBO_BOX_CHANGED ) { DirtyFlag = true; } @@ -392,13 +381,15 @@ void CTextureControl::selectTextureByName(const irr::core::stringw& name) void CTextureControl::updateTextures(video::IVideoDriver * driver) { s32 oldSelected = ComboTexture->getSelected(); - s32 selectNew = -1; core::stringw oldTextureName; if ( oldSelected >= 0 ) { oldTextureName = ComboTexture->getItem(oldSelected); } + ComboTexture->clear(); + + s32 selectNew = -1; for ( u32 i=0; i < driver->getTextureCount(); ++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 */ -void CMaterialControl::init(scene::IMeshSceneNode* node, IrrlichtDevice * device, const core::position2d & pos, const wchar_t * description) +void CMaterialControl::init(IrrlichtDevice * device, const core::position2d & 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; Driver = device->getVideoDriver (); gui::IGUIEnvironment* guiEnv = device->getGUIEnvironment(); - //scene::ISceneManager* smgr = device->getSceneManager(); - const video::SMaterial & material = node->getMaterial(0); s32 top = pos.Y; // Description - guiEnv->addStaticText(description, core::rect(pos.X, top, pos.X+60, top+15), false, false, 0, -1, false); + guiEnv->addStaticText(description, core::rect(pos.X, top, pos.X+150, top+15), true, false, 0, -1, true); top += 15; // Control for material type - core::rect rectCombo(pos.X, top, 150, top+15); + core::rect rectCombo(pos.X, top, pos.X+150, top+15); top += 15; ComboMaterial = guiEnv->addComboBox (rectCombo); for ( int i=0; i <= (int)video::EMT_ONETEXTURE_BLEND; ++i ) { ComboMaterial->addItem( core::stringw(video::sBuiltInMaterialTypeNames[i]).c_str() ); } - ComboMaterial->setSelected( (s32)material.MaterialType ); + ComboMaterial->setSelected(0); // Control to enable/disabling material lighting core::rect rectBtn(core::position2d(pos.X, top), core::dimension2d(100, 15)); top += 15; ButtonLighting = guiEnv->addButton (rectBtn, 0, -1, L"Lighting"); ButtonLighting->setIsPushButton(true); - ButtonLighting->setPressed(material.Lighting); - core::rect rectInfo( rectBtn.LowerRightCorner.X, rectBtn.UpperLeftCorner.Y, rectBtn.LowerRightCorner.X+40, rectBtn.UpperLeftCorner.Y+15 ); + core::rect rectInfo( rectBtn.LowerRightCorner.X, rectBtn.UpperLeftCorner.Y, rectBtn.LowerRightCorner.X+50, rectBtn.UpperLeftCorner.Y+15 ); InfoLighting = guiEnv->addStaticText(L"", rectInfo, true, false ); InfoLighting->setTextAlignment(gui::EGUIA_CENTER, gui::EGUIA_CENTER ); // Controls for colors TypicalColorsControl = new CTypicalColorsControl(guiEnv, core::position2d(pos.X, top), true, guiEnv->getRootGUIElement()); top += 300; - TypicalColorsControl->setColorsToMaterialColors(material); // Controls for selecting the material textures - guiEnv->addStaticText(L"Textures", core::rect(pos.X, top, pos.X+60, top+15), false, false, 0, -1, false); + guiEnv->addStaticText(L"Textures", core::rect(pos.X, top, pos.X+150, top+15), true, false, 0, -1, true); top += 15; - for (irr::u32 i=0; igetRootGUIElement()); + TextureControls.push_back(new CTextureControl(guiEnv, Driver, core::position2di(pos.X, top), guiEnv->getRootGUIElement())); top += 15; } 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; isetDirty(); +} + void CMaterialControl::update(scene::IMeshSceneNode* sceneNode, scene::IMeshSceneNode* sceneNode2T, scene::IMeshSceneNode* sceneNodeTangents) { if ( !Initialized ) @@ -525,19 +526,19 @@ void CMaterialControl::update(scene::IMeshSceneNode* sceneNode, scene::IMeshScen TypicalColorsControl->resetDirty(); - for (irr::u32 i=0; iresetDirty(); } void CMaterialControl::updateTextures() { - for (irr::u32 i=0; iupdateTextures(Driver); } void CMaterialControl::selectTextures(const irr::core::stringw& name) { - for (irr::u32 i=0; iselectTextureByName(name); } @@ -550,11 +551,11 @@ void CMaterialControl::updateMaterial(video::SMaterial & material) { TypicalColorsControl->updateMaterialColors(material); material.Lighting = ButtonLighting->isPressed(); - for (irr::u32 i=0; iisDirty() ) { - 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 return; - guiEnv->addStaticText(description, core::rect(pos.X, pos.Y, pos.X+70, pos.Y+15), false, false, 0, -1, false); + gui::IGUIStaticText* st = guiEnv->addStaticText(description, core::rect(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(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(); TypicalColorsControl->setColorsToLightDataColors(lightData); Initialized = true; @@ -588,9 +591,7 @@ void CLightNodeControl::update(scene::ILightSceneNode* node) Main application class */ -/* - Event handler -*/ +// Event handler bool CApp::OnEvent(const SEvent &event) { if (event.EventType == EET_GUI_EVENT) @@ -618,13 +619,33 @@ bool CApp::OnEvent(const SEvent &event) 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*)event.GUIEvent.Caller; loadTexture(io::path(dialog->getFileName()).c_str()); } 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: break; } @@ -702,44 +723,33 @@ bool CApp::init(int argc, char *argv[]) subMenuFile->addItem(L"Quit", GUI_ID_QUIT); // a static camera - Camera = smgr->addCameraSceneNode (0, core::vector3df(0, 40, -40), - core::vector3df(0, 10, 0), + Camera = smgr->addCameraSceneNode (0, core::vector3df(0, 30, -50), + core::vector3df(0, 0, 0), -1); - // default material - 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; + setActiveMeshNodeType(ENT_CUBE); const s32 controlsTop = 20; MeshMaterialControl = new CMaterialControl(); - MeshMaterialControl->init( SceneNode, Device, core::position2d(10,controlsTop), L"Material" ); + MeshMaterialControl->init( Device, core::position2d(10,controlsTop), L"Material"); + MeshMaterialControl->setMaterial(SceneNode->getMaterial(0)); 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 - 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), - 35.0f); + lightRadius); LightControl = new CLightNodeControl(); LightControl->init(NodeLight, guiEnv, core::position2d(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. scene::IMeshSceneNode* backgroundCube = smgr->addCubeSceneNode (200.0f, 0, -1, core::vector3df(0, 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 - // Add a the mesh vertex color control - guiEnv->addStaticText(L"Mesh", core::rect(200, controlsTop, 270, controlsTop+15), false, false, 0, -1, false); - ControlVertexColors = new CColorControl( guiEnv, core::position2d(200, controlsTop+15), L"Vertex colors", guiEnv->getRootGUIElement()); - video::S3DVertex * vertices = (video::S3DVertex *)SceneNode->getMesh()->getMeshBuffer(0)->getVertices(); - if ( vertices ) - { - ControlVertexColors->setColor(vertices[0].Color); - } + // Add a the mesh UI controls + gui::IGUIStaticText* stMesh = guiEnv->addStaticText(L"Mesh", core::rect(440, controlsTop, 520, controlsTop+15), true, false, 0, -1, true); + stMesh->setAlignment(irr::gui::EGUIA_LOWERRIGHT, irr::gui::EGUIA_LOWERRIGHT, irr::gui::EGUIA_UPPERLEFT, irr::gui::EGUIA_UPPERLEFT); + ComboMeshType = guiEnv->addComboBox(core::rect(440, controlsTop+16, 520, controlsTop+30), 0, -1); + ComboMeshType->setAlignment(irr::gui::EGUIA_LOWERRIGHT, irr::gui::EGUIA_LOWERRIGHT, irr::gui::EGUIA_UPPERLEFT, irr::gui::EGUIA_UPPERLEFT); + ComboMeshType->addItem(L"cube"); + ComboMeshType->addItem(L"sphere"); + ControlVertexColors = new CColorControl( guiEnv, core::position2d(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 GlobalAmbient = new CColorControl( guiEnv, core::position2d(550, 300), L"Global ambient", guiEnv->getRootGUIElement()); 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; } @@ -769,15 +782,12 @@ bool CApp::init(int argc, char *argv[]) */ bool CApp::update() { - using namespace irr; - video::IVideoDriver* videoDriver = Device->getVideoDriver(); if ( !Device->run() ) return false; // Figure out delta time since last frame - ITimer * timer = Device->getTimer(); - u32 newTick = timer->getRealTime(); + u32 newTick = Device->getTimer()->getRealTime(); f32 deltaTime = RealTimeTick > 0 ? f32(newTick-RealTimeTick)/1000.f : 0.f; // in seconds RealTimeTick = newTick; @@ -807,22 +817,30 @@ bool CApp::update() GlobalAmbient->resetDirty(); } - // Let the user move the light around const float zoomSpeed = 10.f * deltaTime; const float rotationSpeed = 100.f * deltaTime; - if ( KeysPressed[KEY_PLUS] || KeysPressed[KEY_ADD]) - ZoomOut(NodeLight, zoomSpeed); - if ( KeysPressed[KEY_MINUS] || KeysPressed[KEY_SUBTRACT]) - ZoomOut(NodeLight, -zoomSpeed); - if ( KeysPressed[KEY_RIGHT]) - RotateHorizontal(NodeLight, rotationSpeed); - if ( KeysPressed[KEY_LEFT]) - RotateHorizontal(NodeLight, -rotationSpeed); - UpdateRotationAxis(NodeLight, LightRotationAxis); - if ( KeysPressed[KEY_UP]) - RotateAroundAxis(NodeLight, rotationSpeed, LightRotationAxis); - if ( KeysPressed[KEY_DOWN]) - RotateAroundAxis(NodeLight, -rotationSpeed, LightRotationAxis); + + // 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]) + ZoomOut(NodeLight, zoomSpeed); + if ( KeysPressed[KEY_MINUS] || KeysPressed[KEY_SUBTRACT]) + ZoomOut(NodeLight, -zoomSpeed); + if ( KeysPressed[KEY_RIGHT]) + RotateHorizontal(NodeLight, rotationSpeed); + if ( KeysPressed[KEY_LEFT]) + RotateHorizontal(NodeLight, -rotationSpeed); + UpdateRotationAxis(NodeLight, LightRotationAxis); + if ( KeysPressed[KEY_UP]) + RotateAroundAxis(NodeLight, rotationSpeed, LightRotationAxis); + if ( KeysPressed[KEY_DOWN]) + RotateAroundAxis(NodeLight, -rotationSpeed, LightRotationAxis); + } // Let the user move the camera around if (MousePressed) @@ -957,7 +975,7 @@ void CApp::createDefaultTextures(video::IVideoDriver * driver) 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) { Device->getVideoDriver()->getTexture(name); @@ -1004,7 +1022,7 @@ void CApp::ZoomOut(irr::scene::ISceneNode* node, irr::f32 units) void CApp::UpdateRotationAxis(irr::scene::ISceneNode* node, irr::core::vector3df& axis) { // Find a perpendicular axis to the x,z vector. If none found (vector straight up/down) continue to use the existing one. - core::vector3df pos(node->getPosition()); + core::vector3df pos(node->getPosition()); if ( !core::equals(pos.X, 0.f) || !core::equals(pos.Z, 0.f) ) { axis.X = -pos.Z; @@ -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. */ diff --git a/examples/22.MaterialViewer/main.h b/examples/22.MaterialViewer/main.h index 8fabc01..dc121cd 100644 --- a/examples/22.MaterialViewer/main.h +++ b/examples/22.MaterialViewer/main.h @@ -110,6 +110,12 @@ public: // Change active selectionbased on the texture name void selectTextureByName(const irr::core::stringw& name); + // Set dirty flag (node will update texture) + void setDirty() + { + DirtyFlag = true; + } + // Reset the dirty flag void resetDirty() { @@ -140,15 +146,12 @@ public: CMaterialControl() : Initialized(false), Driver(0) , TypicalColorsControl(0), ButtonLighting(0), InfoLighting(0), ComboMaterial(0) - { - for (irr::u32 i=0; idrop(); @@ -157,7 +160,9 @@ public: TypicalColorsControl->drop(); } - void init(irr::scene::IMeshSceneNode* node, irr::IrrlichtDevice * device, const irr::core::position2d & pos, const wchar_t * description); + void init(irr::IrrlichtDevice * device, const irr::core::position2d & 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); @@ -177,7 +182,7 @@ protected: irr::gui::IGUIButton * ButtonLighting; irr::gui::IGUIStaticText* InfoLighting; irr::gui::IGUIComboBox * ComboMaterial; - CTextureControl* TextureControls[irr::video::MATERIAL_MAX_TEXTURES]; + irr::core::array TextureControls; }; /* @@ -242,6 +247,7 @@ public: , LightRotationAxis(irr::core::vector3df(1,0,0)) , MeshMaterialControl(0) , LightControl(0) + , ComboMeshType(0) , ControlVertexColors(0) , GlobalAmbient(0) , MousePressed(false) @@ -293,6 +299,14 @@ protected: void ZoomOut(irr::scene::ISceneNode* node, irr::f32 units); 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: SConfig Config; @@ -309,6 +323,7 @@ private: irr::core::vector3df LightRotationAxis; CMaterialControl* MeshMaterialControl; CLightNodeControl* LightControl; + irr::gui::IGUIComboBox* ComboMeshType; CColorControl* ControlVertexColors; CColorControl* GlobalAmbient; bool KeysPressed[irr::KEY_KEY_CODES_COUNT]; diff --git a/examples/23.SMeshHandling/Makefile b/examples/23.SMeshHandling/Makefile index 3c7710b..01df5b8 100644 --- a/examples/23.SMeshHandling/Makefile +++ b/examples/23.SMeshHandling/Makefile @@ -12,7 +12,7 @@ IrrlichtHome := ../.. BinPath = ../../bin/$(SYSTEM) # 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 CXXFLAGS += -g -Wall else diff --git a/examples/24.CursorControl/Makefile b/examples/24.CursorControl/Makefile index f30f370..351347f 100644 --- a/examples/24.CursorControl/Makefile +++ b/examples/24.CursorControl/Makefile @@ -12,7 +12,7 @@ IrrlichtHome := ../.. BinPath = ../../bin/$(SYSTEM) # 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 CXXFLAGS += -g -Wall else diff --git a/examples/24.CursorControl/main.cpp b/examples/24.CursorControl/main.cpp index 22c22cb..d313866 100644 --- a/examples/24.CursorControl/main.cpp +++ b/examples/24.CursorControl/main.cpp @@ -1,6 +1,6 @@ /** 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. */ @@ -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) { @@ -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; } @@ -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. 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 Return sprite index on success or -1 on failure */ @@ -433,8 +444,6 @@ int main() video::IVideoDriver* driver = device->getVideoDriver(); IGUIEnvironment* env = device->getGUIEnvironment(); - gui::IGUISpriteBank * SpriteBankIcons; - SAppContext context; context.Device = device; @@ -443,23 +452,24 @@ int main() rectInfoStatic.UpperLeftCorner += dimension2di(0, 15); context.InfoStatic = env->addStaticText (L"", rectInfoStatic, true, true); 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); context.EventBox = env->addListBox(rectEventBox); 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); context.CursorBox = env->addListBox(rectCursorBox); 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); context.SpriteBox = env->addListBox(rectSpriteBox); - context.ButtonSetVisible = env->addButton( rect( 410, 20, 560, 40 ), 0, -1, L"set visible (delayed)" ); - context.ButtonSetInvisible = env->addButton( rect( 410, 50, 560, 70 ), 0, -1, L"set invisible (delayed)" ); - context.ButtonSimulateBadFps = env->addButton( rect( 410, 80, 560, 100 ), 0, -1, L"simulate bad FPS" ); + context.ButtonSetVisible = env->addButton( rect( 410, 20, 560, 40 ), 0, -1, L"Set visible (delayed)" ); + context.ButtonSetInvisible = env->addButton( rect( 410, 50, 560, 70 ), 0, -1, L"Set invisible (delayed)" ); + context.ButtonSimulateBadFps = env->addButton( rect( 410, 80, 560, 100 ), 0, -1, L"Simulate bad FPS" ); context.ButtonSimulateBadFps->setIsPushButton(true); - context.ButtonChangeIcon = env->addButton( rect( 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( 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 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. */ - SpriteBankIcons = env->addEmptySpriteBank(io::path("cursor_icons")); + gui::IGUISpriteBank * SpriteBankIcons = env->addEmptySpriteBank(io::path("cursor_icons")); context.SpriteBox->setSpriteBank(SpriteBankIcons); const io::path mediaPath = getExampleMediaPath(); @@ -546,7 +556,8 @@ int main() 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 ) { device->sleep(500); // 2 fps diff --git a/examples/25.XmlHandling/Makefile b/examples/25.XmlHandling/Makefile index 359b8f0..6d366dc 100644 --- a/examples/25.XmlHandling/Makefile +++ b/examples/25.XmlHandling/Makefile @@ -12,7 +12,7 @@ IrrlichtHome := ../.. BinPath = ../../bin/$(SYSTEM) # 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 CXXFLAGS += -g -Wall else diff --git a/examples/25.XmlHandling/main.cpp b/examples/25.XmlHandling/main.cpp index c12afe2..b8f99d3 100644 --- a/examples/25.XmlHandling/main.cpp +++ b/examples/25.XmlHandling/main.cpp @@ -224,7 +224,7 @@ public: // Get setting as string 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 //the map node has the function getValue and getKey, as we already know the key, we return node->getValue() map::Node* n = SettingMap.find(key); @@ -263,7 +263,7 @@ private: map SettingMap; //current config - stringw SettingsFile; // location of the xml, usually the + stringw SettingsFile; // filename of the xml irr::IrrlichtDevice* NullDevice; }; @@ -338,7 +338,7 @@ public: 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 @@ -375,7 +375,7 @@ void createSettingsDialog(SAppContext& app) 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(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); @@ -434,7 +434,7 @@ int main() param.WindowSize.set(640,480); // 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 app.Settings = new SettingManager(getExampleMediaPath() + "settings.xml"); if ( !app.Settings->load() ) @@ -448,7 +448,7 @@ int main() //settings xml loaded from disk, //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 //see DriverOptions in the settingmanager class for details map::Node* driver = app.Settings->DriverOptions.find( app.Settings->getSetting("driver") ); diff --git a/examples/26.OcclusionQuery/Makefile b/examples/26.OcclusionQuery/Makefile index b01efd3..6a18b24 100644 --- a/examples/26.OcclusionQuery/Makefile +++ b/examples/26.OcclusionQuery/Makefile @@ -12,7 +12,7 @@ IrrlichtHome := ../.. BinPath = ../../bin/$(SYSTEM) # 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 CXXFLAGS += -g -Wall else diff --git a/examples/27.PostProcessing/Makefile b/examples/27.PostProcessing/Makefile index c590500..ecf44d8 100644 --- a/examples/27.PostProcessing/Makefile +++ b/examples/27.PostProcessing/Makefile @@ -5,7 +5,7 @@ Target = 27.PostProcessing Sources = main.cpp # general compiler settings -CPPFLAGS = -I../../include -I/usr/X11R6/include +CPPFLAGS = -I../../include CXXFLAGS = -O3 -ffast-math #CXXFLAGS = -g -Wall diff --git a/examples/28.CubeMapping/Makefile b/examples/28.CubeMapping/Makefile index 22514c2..627c9ea 100644 --- a/examples/28.CubeMapping/Makefile +++ b/examples/28.CubeMapping/Makefile @@ -5,7 +5,7 @@ Target = 28.CubeMapping Sources = main.cpp # general compiler settings -CPPFLAGS = -I../../include -I/usr/X11R6/include +CPPFLAGS = -I../../include CXXFLAGS = -O3 -ffast-math #CXXFLAGS = -g -Wall diff --git a/examples/30.Profiling/Makefile b/examples/30.Profiling/Makefile index fa113d4..e34e171 100644 --- a/examples/30.Profiling/Makefile +++ b/examples/30.Profiling/Makefile @@ -12,7 +12,7 @@ IrrlichtHome := ../.. BinPath = ../../bin/$(SYSTEM) # 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 CXXFLAGS += -g -Wall else diff --git a/examples/Demo/Makefile b/examples/Demo/Makefile index 706ce7c..a6c6db0 100644 --- a/examples/Demo/Makefile +++ b/examples/Demo/Makefile @@ -12,7 +12,7 @@ IrrlichtHome := ../.. BinPath = ../../bin/$(SYSTEM) # 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 CXXFLAGS += -g -Wall else diff --git a/include/CDynamicMeshBuffer.h b/include/CDynamicMeshBuffer.h index cb776d2..2eed836 100644 --- a/include/CDynamicMeshBuffer.h +++ b/include/CDynamicMeshBuffer.h @@ -14,7 +14,7 @@ namespace irr { 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 { public: @@ -114,6 +114,46 @@ namespace scene 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; iVertexBuffer->push_back((*VertexBuffer)[i]); + } + clone->BoundingBox = BoundingBox; + } + + if (cloneFlags & ECF_INDICES) + { + const u32 numIndices = IndexBuffer->size(); + clone->IndexBuffer->reallocate(numIndices); + for ( u32 i=0; iIndexBuffer->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; core::aabbox3d BoundingBox; //! Primitive type used for rendering (triangles, lines, ...) diff --git a/include/CMeshBuffer.h b/include/CMeshBuffer.h index b5cbcb2..bc66df7 100644 --- a/include/CMeshBuffer.h +++ b/include/CMeshBuffer.h @@ -12,7 +12,7 @@ namespace irr { namespace scene { - //! Template implementation of the IMeshBuffer interface + //! Template implementation of the IMeshBuffer interface for 16-bit buffers template class CMeshBuffer : public IMeshBuffer { @@ -193,8 +193,8 @@ namespace scene Vertices.reallocate(vertexCount+numVertices); for (i=0; i(vertices)[i]); - BoundingBox.addInternalPoint(reinterpret_cast(vertices)[i].Pos); + Vertices.push_back(static_cast(vertices)[i]); + BoundingBox.addInternalPoint(static_cast(vertices)[i].Pos); } Indices.reallocate(getIndexCount()+numIndices); @@ -286,6 +286,41 @@ namespace scene /** This shouldn't be used for anything outside the VideoDriver. */ 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 * clone = new CMeshBuffer(); + + 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_Index; @@ -311,6 +346,25 @@ namespace scene typedef CMeshBuffer SMeshBufferLightMap; //! Meshbuffer with vertices having tangents stored, e.g. for normal mapping typedef CMeshBuffer SMeshBufferTangents; + + //! partial specialization to return types + template <> + inline EMESH_BUFFER_TYPE CMeshBuffer::getTypeT() const + { + return EMBT_STANDARD; + } + template <> + inline EMESH_BUFFER_TYPE CMeshBuffer::getTypeT() const + { + return EMBT_LIGHTMAP; + } + template <> + inline EMESH_BUFFER_TYPE CMeshBuffer::getTypeT() const + { + return EMBT_TANGENTS; + } + + } // end namespace scene } // end namespace irr diff --git a/include/EMaterialTypes.h b/include/EMaterialTypes.h index 26b5f9e..2d38a3d 100644 --- a/include/EMaterialTypes.h +++ b/include/EMaterialTypes.h @@ -73,7 +73,7 @@ namespace video EMT_SPHERE_MAP, //! 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, //! A transparent material. diff --git a/include/EMeshBufferTypes.h b/include/EMeshBufferTypes.h new file mode 100644 index 0000000..8a30240 --- /dev/null +++ b/include/EMeshBufferTypes.h @@ -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 diff --git a/include/IBillboardSceneNode.h b/include/IBillboardSceneNode.h index ee7a332..0d6fcc9 100644 --- a/include/IBillboardSceneNode.h +++ b/include/IBillboardSceneNode.h @@ -12,6 +12,7 @@ namespace irr namespace scene { class ICameraSceneNode; + class IMeshBuffer; //! A billboard scene node. /** 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 to contain the billboard. While this function can return the real one. */ virtual const core::aabbox3d& 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 diff --git a/include/IGeometryCreator.h b/include/IGeometryCreator.h index 7a4bdf8..b987147 100644 --- a/include/IGeometryCreator.h +++ b/include/IGeometryCreator.h @@ -24,15 +24,31 @@ namespace scene { //! 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 + //! 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, //! 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 - // as this mesh sets them to 0,1 values. We can't do that when creating the mesh as it - // depends on texture resolution which we don't know at that point. - ECMT_6BUF_4VTX_NP + //! You can use this one if you need different texture on each cube side + 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. /** You can get an instance of this class through ISceneManager::getGeometryCreator() */ class IGeometryCreator : public IReferenceCounted @@ -44,6 +60,9 @@ public: \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. \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; diff --git a/include/IImage.h b/include/IImage.h index 81cd24a..450b3e4 100644 --- a/include/IImage.h +++ b/include/IImage.h @@ -74,7 +74,6 @@ public: //! Returns bits per pixel. u32 getBitsPerPixel() const { - return getBitsPerPixelFromFormat(Format); } @@ -359,6 +358,11 @@ public: /** NOTE: mipmaps are ignored */ 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 virtual void fill(const SColor &color) =0; diff --git a/include/IMeshBuffer.h b/include/IMeshBuffer.h index 8b14177..6ecbb76 100644 --- a/include/IMeshBuffer.h +++ b/include/IMeshBuffer.h @@ -12,6 +12,7 @@ #include "SVertexIndex.h" #include "EHardwareBufferFlags.h" #include "EPrimitiveTypes.h" +#include "EMeshBufferTypes.h" namespace irr { @@ -71,11 +72,17 @@ namespace scene virtual video::E_INDEX_TYPE getIndexType() const =0; //! 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; //! 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; //! Get amount of indices in this meshbuffer. @@ -176,6 +183,24 @@ namespace scene 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 diff --git a/include/IMeshLoader.h b/include/IMeshLoader.h index 25df3ef..065d76e 100644 --- a/include/IMeshLoader.h +++ b/include/IMeshLoader.h @@ -8,6 +8,7 @@ #include "IReferenceCounted.h" #include "path.h" #include "IMeshTextureLoader.h" +#include "SVertexIndex.h" namespace irr { @@ -29,7 +30,7 @@ class IMeshLoader : public virtual IReferenceCounted public: //! Constructor - IMeshLoader() : TextureLoader(0) {} + IMeshLoader() : TextureLoader(0), PreferredIndexType(video::EIT_16BIT) {} //! Destructor virtual ~IMeshLoader() @@ -78,8 +79,30 @@ public: 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: IMeshTextureLoader* TextureLoader; + irr::video::E_INDEX_TYPE PreferredIndexType; }; diff --git a/include/IMeshManipulator.h b/include/IMeshManipulator.h index f53a651..1b30730 100644 --- a/include/IMeshManipulator.h +++ b/include/IMeshManipulator.h @@ -229,9 +229,7 @@ namespace scene u8 axis, const core::vector3df& offset) const=0; //! Clones a static IMesh into a modifiable SMesh. - /** All meshbuffers in the returned SMesh - are of type SMeshBuffer or SMeshBufferLightMap. - \param mesh Mesh to copy. + /** \param mesh Mesh to copy. \return Cloned mesh. If you no longer need the cloned mesh, you should call SMesh::drop(). See IReferenceCounted::drop() for more information. */ diff --git a/include/ISceneManager.h b/include/ISceneManager.h index 3df4678..8c4cd32 100644 --- a/include/ISceneManager.h +++ b/include/ISceneManager.h @@ -453,13 +453,15 @@ namespace scene where the scene node will be placed. \param rotation: Initial rotation 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 pointer should not be dropped. See IReferenceCounted::drop() for more information. */ 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& 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 /** \param radius: Radius of the sphere. diff --git a/include/IVertexBuffer.h b/include/IVertexBuffer.h index 5c51354..1a8c6fb 100644 --- a/include/IVertexBuffer.h +++ b/include/IVertexBuffer.h @@ -18,17 +18,27 @@ namespace scene class IVertexBuffer : public virtual IReferenceCounted { public: + //! Pointer to first element of vertex data virtual void* getData() =0; + virtual video::E_VERTEX_TYPE getType() const =0; virtual void setType(video::E_VERTEX_TYPE vertexType) =0; + + //! Number of bytes per element virtual u32 stride() const =0; + + //! Number of elements 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 video::S3DVertex& operator [](const u32 index) const =0; virtual video::S3DVertex& getLast() =0; virtual void set_used(u32 usedNow) =0; virtual void reallocate(u32 new_size) =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; //! get the current hardware mapping hint diff --git a/include/IVideoDriver.h b/include/IVideoDriver.h index 30395d0..f67b998 100644 --- a/include/IVideoDriver.h +++ b/include/IVideoDriver.h @@ -801,7 +801,7 @@ namespace video \param texture Texture to be drawn. \param destPos Upper left 2d destination position where the 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 image is clipped to. If this pointer is NULL the image is not clipped. @@ -823,7 +823,7 @@ namespace video \param texture Texture to be drawn. \param pos Upper left 2d destination position where the image 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 rectangle used each time. \param kerningWidth Offset to Position on X @@ -851,7 +851,7 @@ namespace video \param texture Texture to be drawn. \param positions Array of upper left 2d destinations where the 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 images are clipped to. If this pointer is 0 then the image is not clipped. @@ -871,7 +871,7 @@ namespace video /** Suggested and first implemented by zola. \param texture The texture to draw from \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 colors Array of 4 colors denoting the color values of the corners of the destRect @@ -1343,7 +1343,7 @@ namespace video E_MATERIAL_TYPE enum or a value which was returned by addMaterialRenderer(). \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 IMaterialRenderers responsible for rendering specific diff --git a/include/SSharedMeshBuffer.h b/include/SSharedMeshBuffer.h index 0a171be..aac563d 100644 --- a/include/SSharedMeshBuffer.h +++ b/include/SSharedMeshBuffer.h @@ -172,9 +172,16 @@ namespace scene } //! 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 - 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 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. */ 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 video::SMaterial Material; diff --git a/include/SSkinMeshBuffer.h b/include/SSkinMeshBuffer.h index 726deff..52d480c 100644 --- a/include/SSkinMeshBuffer.h +++ b/include/SSkinMeshBuffer.h @@ -383,6 +383,41 @@ struct SSkinMeshBuffer : public IMeshBuffer 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. void boundingBoxNeedsRecalculated(void) { BoundingBoxNeedsRecalculated = true; } diff --git a/include/irrArray.h b/include/irrArray.h index 3572e62..1e358fd 100644 --- a/include/irrArray.h +++ b/include/irrArray.h @@ -234,9 +234,10 @@ public: //! Set (copy) data from given memory block /** \param newData data to set, must have newSize elements \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 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) { @@ -299,22 +300,27 @@ public: return *this; strategy = other.strategy; + // (TODO: we could probably avoid re-allocations of data when (allocated < other.allocated) + if (data) clear(); - //if (allocated < other.allocated) - if (other.allocated == 0) - data = 0; - else - data = allocator.allocate(other.allocated); // new T[other.allocated]; - used = other.used; free_when_destroyed = true; is_sorted = other.is_sorted; allocated = other.allocated; - for (u32 i=0; i 1.f) + if(uA < 0.0 || uA > 1.0) return false; // Outside the line segment - const f32 uB = numeratorB / commonDenominator; - if(uB < 0.f || uB > 1.f) + const f64 uB = numeratorB / commonDenominator; + if(uB < 0.0 || uB > 1.0) return false; // Outside the line segment } diff --git a/include/matrix4.h b/include/matrix4.h index 90d13ad..f39de7d 100644 --- a/include/matrix4.h +++ b/include/matrix4.h @@ -1155,10 +1155,10 @@ namespace core template inline void CMatrix4::rotateVect( vector3df& vect ) const { - vector3df tmp = vect; - vect.X = 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.Z = tmp.X*M[2] + tmp.Y*M[6] + tmp.Z*M[10]; + vector3d tmp(static_cast(vect.X), static_cast(vect.Y), static_cast(vect.Z)); + vect.X = static_cast(tmp.X*M[0] + tmp.Y*M[4] + tmp.Z*M[8]); + vect.Y = static_cast(tmp.X*M[1] + tmp.Y*M[5] + tmp.Z*M[9]); + vect.Z = static_cast(tmp.X*M[2] + tmp.Y*M[6] + tmp.Z*M[10]); } //! An alternate transform vector method, writing into a second vector @@ -1182,24 +1182,24 @@ namespace core template inline void CMatrix4::inverseRotateVect( vector3df& vect ) const { - vector3df tmp = vect; - vect.X = 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.Z = tmp.X*M[8] + tmp.Y*M[9] + tmp.Z*M[10]; + vector3d tmp(static_cast(vect.X), static_cast(vect.Y), static_cast(vect.Z)); + vect.X = static_cast(tmp.X*M[0] + tmp.Y*M[1] + tmp.Z*M[2]); + vect.Y = static_cast(tmp.X*M[4] + tmp.Y*M[5] + tmp.Z*M[6]); + vect.Z = static_cast(tmp.X*M[8] + tmp.Y*M[9] + tmp.Z*M[10]); } template inline void CMatrix4::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[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]; - vect.X = vector[0]; - vect.Y = vector[1]; - vect.Z = vector[2]; + vect.X = static_cast(vector[0]); + vect.Y = static_cast(vector[1]); + vect.Z = static_cast(vector[2]); } template diff --git a/include/vector3d.h b/include/vector3d.h index c348cd7..ebea7c4 100644 --- a/include/vector3d.h +++ b/include/vector3d.h @@ -54,8 +54,8 @@ namespace core vector3d operator/(const vector3d& other) const { return vector3d(X / other.X, Y / other.Y, Z / other.Z); } vector3d& operator/=(const vector3d& other) { X/=other.X; Y/=other.Y; Z/=other.Z; return *this; } - vector3d operator/(const T v) const { T i=(T)1.0/v; return vector3d(X * i, Y * i, Z * i); } - vector3d& operator/=(const T v) { T i=(T)1.0/v; X*=i; Y*=i; Z*=i; return *this; } + vector3d operator/(const T v) const { return vector3d(X/v, Y/v, Z/v); } + vector3d& operator/=(const T v) { X/=v; Y/=v; Z/=v; return *this; } T& operator [](u32 index) { diff --git a/media/cubeMapReflection.frag b/media/cubeMapReflection.frag index f1a4a1f..7e7e718 100644 --- a/media/cubeMapReflection.frag +++ b/media/cubeMapReflection.frag @@ -1,3 +1,4 @@ +#version 130 uniform samplerCube cubeTex; uniform float Roughness; diff --git a/source/Irrlicht/CAnimatedMeshSceneNode.cpp b/source/Irrlicht/CAnimatedMeshSceneNode.cpp index de96749..e5c7f80 100644 --- a/source/Irrlicht/CAnimatedMeshSceneNode.cpp +++ b/source/Irrlicht/CAnimatedMeshSceneNode.cpp @@ -206,7 +206,7 @@ IMesh * CAnimatedMeshSceneNode::getMeshForCurrentFrame() // 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. - CSkinnedMesh* skinnedMesh = reinterpret_cast(Mesh); + CSkinnedMesh* skinnedMesh = static_cast(Mesh); if (JointMode == EJUOR_CONTROL)//write to mesh skinnedMesh->transferJointsToMesh(JointChildSceneNodes); @@ -949,7 +949,7 @@ void CAnimatedMeshSceneNode::animateJoints(bool CalculateAbsolutePositions) checkJoints(); const f32 frame = getFrameNr(); //old? - CSkinnedMesh* skinnedMesh=reinterpret_cast(Mesh); + CSkinnedMesh* skinnedMesh=static_cast(Mesh); skinnedMesh->transferOnlyJointsHintsToMesh( JointChildSceneNodes ); skinnedMesh->animateMesh(frame, 1.0f); diff --git a/source/Irrlicht/CBillboardSceneNode.h b/source/Irrlicht/CBillboardSceneNode.h index 2bb6cbe..2e7379e 100644 --- a/source/Irrlicht/CBillboardSceneNode.h +++ b/source/Irrlicht/CBillboardSceneNode.h @@ -72,6 +72,20 @@ public: //! Get the real boundingbox used by the billboard (which depends on the active camera) virtual const core::aabbox3d& 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. virtual void serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options=0) const IRR_OVERRIDE; diff --git a/source/Irrlicht/CCubeSceneNode.cpp b/source/Irrlicht/CCubeSceneNode.cpp index 0400c11..1e882ea 100644 --- a/source/Irrlicht/CCubeSceneNode.cpp +++ b/source/Irrlicht/CCubeSceneNode.cpp @@ -37,9 +37,10 @@ namespace scene //! constructor CCubeSceneNode::CCubeSceneNode(f32 size, ISceneNode* parent, ISceneManager* mgr, 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), - Mesh(0), Shadow(0), Size(size) + Mesh(0), Shadow(0), Size(size), MeshType(type) { #ifdef _DEBUG setDebugName("CCubeSceneNode"); @@ -62,7 +63,7 @@ void CCubeSceneNode::setSize() { if (Mesh) Mesh->drop(); - Mesh = SceneManager->getGeometryCreator()->createCubeMesh(core::vector3df(Size)); + Mesh = SceneManager->getGeometryCreator()->createCubeMesh(core::vector3df(Size), MeshType); } @@ -135,7 +136,7 @@ const core::aabbox3d& CCubeSceneNode::getBoundingBox() const //! Removes a child from this scene node. //! Implemented here, to be able to remove the shadow properly, if there is one, -//! or to remove attached childs. +//! or to remove attached child. bool CCubeSceneNode::removeChild(ISceneNode* child) { if (child && Shadow == child) @@ -199,17 +200,20 @@ void CCubeSceneNode::serializeAttributes(io::IAttributes* out, io::SAttributeRea ISceneNode::serializeAttributes(out, options); out->addFloat("Size", Size); + out->addEnum("MeshType", (irr::s32)MeshType, CubeMeshTypeNames); } //! Reads attributes of the scene node. 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); - if (newSize != Size) + if (newSize != Size || newMeshType != MeshType) { Size = newSize; + MeshType = newMeshType; setSize(); } @@ -226,7 +230,7 @@ ISceneNode* CCubeSceneNode::clone(ISceneNode* newParent, ISceneManager* newManag newManager = SceneManager; CCubeSceneNode* nb = new CCubeSceneNode(Size, newParent, - newManager, ID, RelativeTranslation); + newManager, ID, RelativeTranslation, RelativeRotation, RelativeScale, MeshType); nb->cloneMembers(this, newManager); nb->getMaterial(0) = getMaterial(0); diff --git a/source/Irrlicht/CCubeSceneNode.h b/source/Irrlicht/CCubeSceneNode.h index d1719e2..fc276c2 100644 --- a/source/Irrlicht/CCubeSceneNode.h +++ b/source/Irrlicht/CCubeSceneNode.h @@ -7,6 +7,7 @@ #include "IMeshSceneNode.h" #include "SMesh.h" +#include "IGeometryCreator.h" namespace irr { @@ -20,7 +21,8 @@ namespace scene CCubeSceneNode(f32 size, ISceneNode* parent, ISceneManager* mgr, s32 id, const core::vector3df& position = core::vector3df(0,0,0), const core::vector3df& rotation = core::vector3df(0,0,0), - const core::vector3df& scale = core::vector3df(1.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(); @@ -84,6 +86,7 @@ namespace scene IMesh* Mesh; IShadowVolumeSceneNode* Shadow; f32 Size; + ECUBE_MESH_TYPE MeshType; }; } // end namespace scene diff --git a/source/Irrlicht/CD3D9Driver.cpp b/source/Irrlicht/CD3D9Driver.cpp index d606bc2..838b39e 100644 --- a/source/Irrlicht/CD3D9Driver.cpp +++ b/source/Irrlicht/CD3D9Driver.cpp @@ -1192,7 +1192,7 @@ void CD3D9Driver::removeOcclusionQuery(scene::ISceneNode* node) if (index != -1) { if (OcclusionQueries[index].PID != 0) - reinterpret_cast(OcclusionQueries[index].PID)->Release(); + static_cast(OcclusionQueries[index].PID)->Release(); CNullDriver::removeOcclusionQuery(node); } } @@ -1210,10 +1210,10 @@ void CD3D9Driver::runOcclusionQuery(scene::ISceneNode* node, bool visible) if (index != -1) { if (OcclusionQueries[index].PID) - reinterpret_cast(OcclusionQueries[index].PID)->Issue(D3DISSUE_BEGIN); + static_cast(OcclusionQueries[index].PID)->Issue(D3DISSUE_BEGIN); CNullDriver::runOcclusionQuery(node,visible); if (OcclusionQueries[index].PID) - reinterpret_cast(OcclusionQueries[index].PID)->Issue(D3DISSUE_END); + static_cast(OcclusionQueries[index].PID)->Issue(D3DISSUE_END); } } @@ -1232,12 +1232,12 @@ void CD3D9Driver::updateOcclusionQuery(scene::ISceneNode* node, bool block) bool available = block?true:false; int tmp=0; if (!block) - available=(reinterpret_cast(OcclusionQueries[index].PID)->GetData(&tmp, sizeof(DWORD), 0)==S_OK); + available=(static_cast(OcclusionQueries[index].PID)->GetData(&tmp, sizeof(DWORD), 0)==S_OK); else { do { - HRESULT hr = reinterpret_cast(OcclusionQueries[index].PID)->GetData(&tmp, sizeof(DWORD), D3DGETDATA_FLUSH); + HRESULT hr = static_cast(OcclusionQueries[index].PID)->GetData(&tmp, sizeof(DWORD), D3DGETDATA_FLUSH); available = (hr == S_OK); if (hr!=S_FALSE) break; @@ -2946,7 +2946,7 @@ bool CD3D9Driver::reset() { if (OcclusionQueries[i].PID) { - reinterpret_cast(OcclusionQueries[i].PID)->Release(); + static_cast(OcclusionQueries[i].PID)->Release(); OcclusionQueries[i].PID=0; } } diff --git a/source/Irrlicht/CGeometryCreator.cpp b/source/Irrlicht/CGeometryCreator.cpp index 235163d..989d24e 100644 --- a/source/Irrlicht/CGeometryCreator.cpp +++ b/source/Irrlicht/CGeometryCreator.cpp @@ -140,6 +140,69 @@ IMesh* CGeometryCreator::createCubeMesh(const core::vector3df& size, ECUBE_MESH_ 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(); return mesh; diff --git a/source/Irrlicht/CImage.cpp b/source/Irrlicht/CImage.cpp index 753262b..182623d 100644 --- a/source/Irrlicht/CImage.cpp +++ b/source/Irrlicht/CImage.cpp @@ -347,6 +347,60 @@ void CImage::fill(const SColor &color) 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(windowId); + hwnd = static_cast(windowId); HDC dc = GetDC(hwnd); diff --git a/source/Irrlicht/CMeshManipulator.cpp b/source/Irrlicht/CMeshManipulator.cpp index f177fc2..093ad23 100644 --- a/source/Irrlicht/CMeshManipulator.cpp +++ b/source/Irrlicht/CMeshManipulator.cpp @@ -577,8 +577,7 @@ void CMeshManipulator::makePlanarTextureMapping(scene::IMesh* mesh, f32 resoluti } -//! Clones a static IMesh into a modifyable SMesh. -// not yet 32bit +//! Clones a static IMesh into a modifiable SMesh. SMesh* CMeshManipulator::createMeshCopy(scene::IMesh* mesh) const { if (!mesh) @@ -590,66 +589,10 @@ SMesh* CMeshManipulator::createMeshCopy(scene::IMesh* mesh) const for ( u32 b=0; bgetMeshBuffer(b); - switch(mb->getVertexType()) - { - 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 + IMeshBuffer* bufferClone = mesh->getMeshBuffer(b)->createClone(); + clone->addMeshBuffer(bufferClone); + bufferClone->drop(); + } clone->BoundingBox = mesh->getBoundingBox(); return clone; diff --git a/source/Irrlicht/CNullDriver.cpp b/source/Irrlicht/CNullDriver.cpp index b679ebe..e2c3e72 100644 --- a/source/Irrlicht/CNullDriver.cpp +++ b/source/Irrlicht/CNullDriver.cpp @@ -441,10 +441,7 @@ ITexture* CNullDriver::addTexture(const core::dimension2d& size, const io:: IImage* image = new CImage(format, size); ITexture* t = 0; - core::array imageArray(1); - imageArray.push_back(image); - - if (checkImage(imageArray)) + if (checkImage(image->getColorFormat(), image->getDimension())) { t = createDeviceDependentTexture(name, image); } @@ -473,18 +470,14 @@ ITexture* CNullDriver::addTexture(const io::path& name, IImage* image) ITexture* t = 0; - core::array imageArray(1); - imageArray.push_back(image); - - if (checkImage(imageArray)) + if (checkImage(image->getColorFormat(), image->getDimension())) { t = createDeviceDependentTexture(name, image); - } - - if (t) - { - addTexture(t); - t->drop(); + if (t) + { + addTexture(t); + t->drop(); + } } return t; @@ -509,12 +502,11 @@ ITexture* CNullDriver::addTextureCubemap(const io::path& name, IImage* imagePosX if (checkImage(imageArray)) { t = createDeviceDependentTextureCubemap(name, imageArray); - } - - if (t) - { - addTexture(t); - t->drop(); + if (t) + { + addTexture(t); + t->drop(); + } } return t; @@ -1434,88 +1426,91 @@ bool CNullDriver::checkPrimitiveCount(u32 prmCount) const bool CNullDriver::checkImage(const core::array& image) const { - bool status = true; - if (image.size() > 0) { ECOLOR_FORMAT lastFormat = image[0]->getColorFormat(); core::dimension2d 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(); core::dimension2d size = image[i]->getDimension(); - switch (format) - { - case ECF_DXT1: - case ECF_DXT2: - case ECF_DXT3: - case ECF_DXT4: - case ECF_DXT5: - if (!queryFeature(EVDF_TEXTURE_COMPRESSED_DXT)) - { - os::Printer::log("DXT texture compression not available.", ELL_ERROR); - status = false; - } - 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); - status = false; - } - break; - case ECF_PVRTC_RGB2: - case ECF_PVRTC_ARGB2: - case ECF_PVRTC_RGB4: - case ECF_PVRTC_ARGB4: - if (!queryFeature(EVDF_TEXTURE_COMPRESSED_PVRTC)) - { - os::Printer::log("PVRTC texture compression not available.", ELL_ERROR); - status = false; - } - 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); - status = false; - } - break; - case ECF_PVRTC2_ARGB2: - case ECF_PVRTC2_ARGB4: - if (!queryFeature(EVDF_TEXTURE_COMPRESSED_PVRTC2)) - { - os::Printer::log("PVRTC2 texture compression not available.", ELL_ERROR); - status = false; - } - break; - case ECF_ETC1: - if (!queryFeature(EVDF_TEXTURE_COMPRESSED_ETC1)) - { - os::Printer::log("ETC1 texture compression not available.", ELL_ERROR); - status = false; - } - break; - case ECF_ETC2_RGB: - case ECF_ETC2_ARGB: - if (!queryFeature(EVDF_TEXTURE_COMPRESSED_ETC2)) - { - os::Printer::log("ETC2 texture compression not available.", ELL_ERROR); - status = false; - } - break; - default: - break; - } - if (format != lastFormat || size != lastSize) - status = false; + return false; + + if ( !checkImage(format, size) ) + return false; } + + return true; } - else + return false; +} + +bool CNullDriver::checkImage(ECOLOR_FORMAT format, const core::dimension2du& size) const +{ + switch (format) { - status = false; + case ECF_DXT1: + case ECF_DXT2: + case ECF_DXT3: + case ECF_DXT4: + case ECF_DXT5: + if (!queryFeature(EVDF_TEXTURE_COMPRESSED_DXT)) + { + os::Printer::log("DXT texture compression not available.", ELL_ERROR); + return false; + } + 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); + return false; + } + break; + case ECF_PVRTC_RGB2: + case ECF_PVRTC_ARGB2: + case ECF_PVRTC_RGB4: + case ECF_PVRTC_ARGB4: + if (!queryFeature(EVDF_TEXTURE_COMPRESSED_PVRTC)) + { + os::Printer::log("PVRTC texture compression not available.", ELL_ERROR); + return false; + } + 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); + return false; + } + break; + case ECF_PVRTC2_ARGB2: + case ECF_PVRTC2_ARGB4: + if (!queryFeature(EVDF_TEXTURE_COMPRESSED_PVRTC2)) + { + os::Printer::log("PVRTC2 texture compression not available.", ELL_ERROR); + return false; + } + break; + case ECF_ETC1: + if (!queryFeature(EVDF_TEXTURE_COMPRESSED_ETC1)) + { + os::Printer::log("ETC1 texture compression not available.", ELL_ERROR); + return false; + } + break; + case ECF_ETC2_RGB: + case ECF_ETC2_ARGB: + if (!queryFeature(EVDF_TEXTURE_COMPRESSED_ETC2)) + { + os::Printer::log("ETC2 texture compression not available.", ELL_ERROR); + return false; + } + break; + default: + break; } - return status; + return true; } //! 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. -void CNullDriver::setMaterialRendererName(s32 idx, const char* name) +void CNullDriver::setMaterialRendererName(u32 idx, const char* name) { - if (idx < s32(sizeof(sBuiltInMaterialTypeNames) / sizeof(char*))-1 || - idx >= (s32)MaterialRenderers.size()) + if (idx < (sizeof(sBuiltInMaterialTypeNames) / sizeof(char*))-1 || + idx >= MaterialRenderers.size()) return; MaterialRenderers[idx].Name = name; diff --git a/source/Irrlicht/CNullDriver.h b/source/Irrlicht/CNullDriver.h index a03b217..2647b4d 100644 --- a/source/Irrlicht/CNullDriver.h +++ b/source/Irrlicht/CNullDriver.h @@ -616,7 +616,7 @@ namespace video virtual bool writeImageToFile(IImage* image, io::IWriteFile * file, u32 param = 0) IRR_OVERRIDE; //! 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 virtual void swapMaterialRenderers(u32 idx1, u32 idx2, bool swapNames) IRR_OVERRIDE; @@ -710,6 +710,7 @@ namespace video bool checkPrimitiveCount(u32 prmcnt) const; bool checkImage(const core::array& 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 s32 addAndDropMaterialRenderer(IMaterialRenderer* m); diff --git a/source/Irrlicht/COBJMeshFileLoader.cpp b/source/Irrlicht/COBJMeshFileLoader.cpp index 2efe70d..2249716 100644 --- a/source/Irrlicht/COBJMeshFileLoader.cpp +++ b/source/Irrlicht/COBJMeshFileLoader.cpp @@ -82,7 +82,7 @@ IAnimatedMesh* COBJMeshFileLoader::createMesh(io::IReadFile* file) core::array > normalsBuffer(1000); core::array > textureCoordBuffer(1000); - SObjMtl * currMtl = new SObjMtl(); + SObjMtl * currMtl = new SObjMtl(PreferredIndexType); Materials.push_back(currMtl); u32 smoothingGroup=0; @@ -224,6 +224,8 @@ IAnimatedMesh* COBJMeshFileLoader::createMesh(io::IReadFile* file) v.Color = currMtl->Meshbuffer->Material.DiffuseColor; // 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 c8* linePtr = wordBuffer.c_str(); const c8* const endPtr = linePtr+wordBuffer.size(); @@ -272,8 +274,8 @@ IAnimatedMesh* COBJMeshFileLoader::createMesh(io::IReadFile* file) } else { - currMtl->Meshbuffer->Vertices.push_back(v); - vertLocation = currMtl->Meshbuffer->Vertices.size() -1; + mbVertexBuffer.push_back(v); + vertLocation = mbVertexBuffer.size() -1; currMtl->VertMap.insert(v, vertLocation); } @@ -292,9 +294,9 @@ IAnimatedMesh* COBJMeshFileLoader::createMesh(io::IReadFile* file) 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. { - currMtl->Meshbuffer->Indices.push_back(a); - currMtl->Meshbuffer->Indices.push_back(b); - currMtl->Meshbuffer->Indices.push_back(c); + mbIndexBuffer.push_back(a); + mbIndexBuffer.push_back(b); + mbIndexBuffer.push_back(c); } else { @@ -577,7 +579,7 @@ void COBJMeshFileLoader::readMTL(const c8* fileName, const io::path& relPath) c8 mtlNameBuf[WORD_BUFFER_LENGTH]; bufPtr = goAndCopyNextWord(mtlNameBuf, bufPtr, WORD_BUFFER_LENGTH, bufEnd); - currMaterial = new SObjMtl; + currMaterial = new SObjMtl(PreferredIndexType); currMaterial->Name = mtlNameBuf; } break; diff --git a/source/Irrlicht/COBJMeshFileLoader.h b/source/Irrlicht/COBJMeshFileLoader.h index e7c9fbf..2954056 100644 --- a/source/Irrlicht/COBJMeshFileLoader.h +++ b/source/Irrlicht/COBJMeshFileLoader.h @@ -9,7 +9,7 @@ #include "IFileSystem.h" #include "ISceneManager.h" #include "irrString.h" -#include "SMeshBuffer.h" +#include "CDynamicMeshBuffer.h" #include "irrMap.h" namespace irr @@ -42,10 +42,10 @@ private: 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) { - Meshbuffer = new SMeshBuffer(); + Meshbuffer = new CDynamicMeshBuffer(irr::video::EVT_STANDARD, IndexType); Meshbuffer->Material.Shininess = 0.0f; Meshbuffer->Material.AmbientColor = video::SColorf(0.2f, 0.2f, 0.2f, 1.0f).toSColor(); Meshbuffer->Material.DiffuseColor = video::SColorf(0.8f, 0.8f, 0.8f, 1.0f).toSColor(); @@ -53,16 +53,17 @@ private: } 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), RecalculateNormals(false) { - Meshbuffer = new SMeshBuffer(); + Meshbuffer = new CDynamicMeshBuffer(irr::video::EVT_STANDARD, IndexType); Meshbuffer->Material = o.Meshbuffer->Material; } core::map VertMap; - scene::SMeshBuffer *Meshbuffer; + irr::video::E_INDEX_TYPE IndexType; + scene::CDynamicMeshBuffer *Meshbuffer; core::stringc Name; core::stringc Group; f32 Bumpiness; diff --git a/source/Irrlicht/COBJMeshWriter.cpp b/source/Irrlicht/COBJMeshWriter.cpp index 372b9c2..7c1232e 100644 --- a/source/Irrlicht/COBJMeshWriter.cpp +++ b/source/Irrlicht/COBJMeshWriter.cpp @@ -127,11 +127,26 @@ bool COBJMeshWriter::writeMesh(io::IWriteFile* file, scene::IMesh* mesh, s32 fla file->write(num.c_str(), num.size()); file->write("\n",1); + unsigned int idx2=0, idx1=0, idx0 = 0; const u32 indexCount = buffer->getIndexCount(); for (j=0; jgetIndexType()) + { + 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); - num = core::stringc(buffer->getIndices()[j+2]+allVertexCount); + num = core::stringc(idx2); file->write(num.c_str(), num.size()); file->write("/",1); 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(" ",1); - num = core::stringc(buffer->getIndices()[j+1]+allVertexCount); + num = core::stringc(idx1); file->write(num.c_str(), num.size()); file->write("/",1); 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(" ",1); - num = core::stringc(buffer->getIndices()[j+0]+allVertexCount); + num = core::stringc(idx0); file->write(num.c_str(), num.size()); file->write("/",1); file->write(num.c_str(), num.size()); diff --git a/source/Irrlicht/COCTLoader.cpp b/source/Irrlicht/COCTLoader.cpp index fb7025f..c09120e 100644 --- a/source/Irrlicht/COCTLoader.cpp +++ b/source/Irrlicht/COCTLoader.cpp @@ -102,18 +102,29 @@ IAnimatedMesh* COCTLoader::createMesh(io::IReadFile* file) file->read(verts, sizeof(octVert) * header.numVerts); file->read(faces, sizeof(octFace) * header.numFaces); - //TODO: Make sure id is in the legal range for Textures and Lightmaps u32 i; - for (i = 0; i < header.numTextures; i++) { - octTexture t; - file->read(&t, sizeof(octTexture)); - textures[t.id] = t; + for (i = 0; i < header.numTextures; i++) + { + u32 id; + file->read(&id, sizeof(id)); + if ( id >= header.numTextures ) + { + os::Printer::log("COCTLoader: Invalid texture id", irr::ELL_WARNING); + id = i; + } + file->read(&textures[id], sizeof(octTexture)); } - for (i = 0; i < header.numLightmaps; i++) { - octLightmap t; - file->read(&t, sizeof(octLightmap)); - lightmaps[t.id] = t; + for (i = 0; i < header.numLightmaps; i++) + { + 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); diff --git a/source/Irrlicht/COCTLoader.h b/source/Irrlicht/COCTLoader.h index 75c6ff1..98acdcb 100644 --- a/source/Irrlicht/COCTLoader.h +++ b/source/Irrlicht/COCTLoader.h @@ -115,12 +115,10 @@ namespace scene }; struct octTexture { - u32 id; char fileName[64]; }; struct octLightmap { - u32 id; u8 data[128][128][3]; }; diff --git a/source/Irrlicht/COGLES2Driver.cpp b/source/Irrlicht/COGLES2Driver.cpp index 8417e1b..8a6b3c1 100644 --- a/source/Irrlicht/COGLES2Driver.cpp +++ b/source/Irrlicht/COGLES2Driver.cpp @@ -1099,7 +1099,7 @@ COGLES2Driver::~COGLES2Driver() 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) return; diff --git a/source/Irrlicht/COGLES2Driver.h b/source/Irrlicht/COGLES2Driver.h index 24fc9e4..cb8b181 100644 --- a/source/Irrlicht/COGLES2Driver.h +++ b/source/Irrlicht/COGLES2Driver.h @@ -118,7 +118,7 @@ namespace video const video::SColor* const colors = 0, bool useAlphaChannelOfTexture = false) IRR_OVERRIDE; // 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 virtual void draw2DImageBatch(const video::ITexture* texture, diff --git a/source/Irrlicht/COGLESDriver.cpp b/source/Irrlicht/COGLESDriver.cpp index ef4edb4..e70d858 100644 --- a/source/Irrlicht/COGLESDriver.cpp +++ b/source/Irrlicht/COGLESDriver.cpp @@ -1032,7 +1032,7 @@ void COGLES1Driver::draw2DImage(const video::ITexture* texture, const core::rect 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)) return; diff --git a/source/Irrlicht/COGLESDriver.h b/source/Irrlicht/COGLESDriver.h index 4d21ff0..88832ca 100644 --- a/source/Irrlicht/COGLESDriver.h +++ b/source/Irrlicht/COGLESDriver.h @@ -109,7 +109,8 @@ namespace video const core::rect& sourceRect, const core::rect* clipRect = 0, 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 virtual void draw2DImageBatch(const video::ITexture* texture, diff --git a/source/Irrlicht/COSOperator.cpp b/source/Irrlicht/COSOperator.cpp index 6cef827..1f98425 100644 --- a/source/Irrlicht/COSOperator.cpp +++ b/source/Irrlicht/COSOperator.cpp @@ -73,12 +73,16 @@ void COSOperator::copyToClipboard(const c8* text) const char * buffer; clipbuffer = GlobalAlloc(GMEM_DDESHARE, strlen(text)+1); - buffer = (char*)GlobalLock(clipbuffer); - - strcpy(buffer, text); - - GlobalUnlock(clipbuffer); - SetClipboardData(CF_TEXT, clipbuffer); + if ( clipbuffer ) + { + buffer = (char*)GlobalLock(clipbuffer); + if ( buffer ) + { + strcpy(buffer, text); + } + GlobalUnlock(clipbuffer); + SetClipboardData(CF_TEXT, clipbuffer); + } CloseClipboard(); #elif defined(_IRR_COMPILE_WITH_OSX_DEVICE_) diff --git a/source/Irrlicht/COpenGLCoreTexture.h b/source/Irrlicht/COpenGLCoreTexture.h index ec3d39f..17712f0 100644 --- a/source/Irrlicht/COpenGLCoreTexture.h +++ b/source/Irrlicht/COpenGLCoreTexture.h @@ -328,7 +328,7 @@ public: glClear(GL_COLOR_BUFFER_BIT); - Driver->draw2DImage(this, layer, true); + Driver->draw2DImageQuad(this, layer, true); IImage* tmpImage = Driver->createImage(ECF_A8R8G8B8, Size); glReadPixels(0, 0, Size.Width, Size.Height, GL_RGBA, GL_UNSIGNED_BYTE, tmpImage->getData()); diff --git a/source/Irrlicht/COpenGLDriver.cpp b/source/Irrlicht/COpenGLDriver.cpp index 5dcbfba..815b58e 100644 --- a/source/Irrlicht/COpenGLDriver.cpp +++ b/source/Irrlicht/COpenGLDriver.cpp @@ -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)) return; @@ -3971,7 +3971,7 @@ IImage* COpenGLDriver::createScreenShot(video::ECOLOR_FORMAT format, video::E_RE if (format==video::ECF_UNKNOWN) format=getColorFormat(); - // TODO: Maybe we could support more formats (floating point and some of those beyond ECF_R8), didn't really try yet + // TODO: Maybe we could support more formats (floating point and some of those beyond ECF_R8), didn't really try yet if (IImage::isCompressedFormat(format) || IImage::isDepthFormat(format) || IImage::isFloatingPointFormat(format) || format >= ECF_R8) return 0; diff --git a/source/Irrlicht/COpenGLDriver.h b/source/Irrlicht/COpenGLDriver.h index c43c1fa..6f2bd7a 100644 --- a/source/Irrlicht/COpenGLDriver.h +++ b/source/Irrlicht/COpenGLDriver.h @@ -148,7 +148,10 @@ namespace video const core::rect& sourceRect, const core::rect* clipRect = 0, 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 //! texture if desired. diff --git a/source/Irrlicht/CSceneManager.cpp b/source/Irrlicht/CSceneManager.cpp index 8f727c1..b860182 100644 --- a/source/Irrlicht/CSceneManager.cpp +++ b/source/Irrlicht/CSceneManager.cpp @@ -609,13 +609,14 @@ IVolumeLightSceneNode* CSceneManager::addVolumeLightSceneNode( //! the returned pointer must not be dropped. IMeshSceneNode* CSceneManager::addCubeSceneNode(f32 size, ISceneNode* parent, 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_ if (!parent) 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(); return node; diff --git a/source/Irrlicht/CSceneManager.h b/source/Irrlicht/CSceneManager.h index ab9c975..5051ecc 100644 --- a/source/Irrlicht/CSceneManager.h +++ b/source/Irrlicht/CSceneManager.h @@ -73,7 +73,8 @@ namespace scene 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& 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. virtual IMeshSceneNode* addSphereSceneNode(f32 radius=5.0f, s32 polyCount=16, ISceneNode* parent=0, s32 id=-1, diff --git a/source/Irrlicht/CSoftwareDriver2.cpp b/source/Irrlicht/CSoftwareDriver2.cpp index 5962fcd..e6a9a03 100644 --- a/source/Irrlicht/CSoftwareDriver2.cpp +++ b/source/Irrlicht/CSoftwareDriver2.cpp @@ -947,14 +947,14 @@ REALINLINE size_t clipToFrustumTest(const s4DVertex* v) { size_t flag = 0; - flag |= v->Pos.z <= v->Pos.w ? 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_NEAR : 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 ? VERTEX4D_CLIP_RIGHT : 0; + flag |= v->Pos.x <= v->Pos.w ? (size_t)VERTEX4D_CLIP_LEFT : 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 ? VERTEX4D_CLIP_TOP : 0; + flag |= v->Pos.y <= v->Pos.w ? (size_t)VERTEX4D_CLIP_BOTTOM : 0; + flag |= -v->Pos.y <= v->Pos.w ? (size_t)VERTEX4D_CLIP_TOP : 0; /* diff --git a/source/Irrlicht/CTextSceneNode.h b/source/Irrlicht/CTextSceneNode.h index 2d2c71e..2afd8c9 100644 --- a/source/Irrlicht/CTextSceneNode.h +++ b/source/Irrlicht/CTextSceneNode.h @@ -145,6 +145,18 @@ namespace scene virtual const core::aabbox3d& 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: void updateMesh(const irr::scene::ICameraSceneNode* camera); diff --git a/source/Irrlicht/CWebGL1Driver.cpp b/source/Irrlicht/CWebGL1Driver.cpp index 1f0acb1..fe765f8 100644 --- a/source/Irrlicht/CWebGL1Driver.cpp +++ b/source/Irrlicht/CWebGL1Driver.cpp @@ -290,7 +290,7 @@ void CWebGL1Driver::draw2DImage(const video::ITexture* texture, const core::rect 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 ) return; diff --git a/source/Irrlicht/CWebGL1Driver.h b/source/Irrlicht/CWebGL1Driver.h index 8816136..19e8a7e 100644 --- a/source/Irrlicht/CWebGL1Driver.h +++ b/source/Irrlicht/CWebGL1Driver.h @@ -64,7 +64,7 @@ namespace video const video::SColor* const colors = 0, bool useAlphaChannelOfTexture = false) IRR_OVERRIDE; // 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 virtual void draw2DImageBatch(const video::ITexture* texture, diff --git a/source/Irrlicht/CXMLReaderImpl.h b/source/Irrlicht/CXMLReaderImpl.h index 8fb87e1..d2b041b 100644 --- a/source/Irrlicht/CXMLReaderImpl.h +++ b/source/Irrlicht/CXMLReaderImpl.h @@ -549,7 +549,7 @@ private: pos = origstr.findNext(L'&', pos); } - if (oldPos < (int)origstr.size()-1) + if (oldPos < (int)origstr.size()) newstr.append(origstr.subString(oldPos, origstr.size()-oldPos)); return newstr; diff --git a/source/Irrlicht/Irrlicht10.0.vcxproj b/source/Irrlicht/Irrlicht10.0.vcxproj index 84d8bc3..44ef1e2 100644 --- a/source/Irrlicht/Irrlicht10.0.vcxproj +++ b/source/Irrlicht/Irrlicht10.0.vcxproj @@ -844,6 +844,7 @@ + @@ -859,8 +860,8 @@ - - + + @@ -869,7 +870,7 @@ - + @@ -1035,7 +1036,7 @@ - + @@ -1207,7 +1208,7 @@ - + @@ -1484,7 +1485,7 @@ - + diff --git a/source/Irrlicht/Irrlicht10.0.vcxproj.filters b/source/Irrlicht/Irrlicht10.0.vcxproj.filters index 5eb92b0..47dd740 100644 --- a/source/Irrlicht/Irrlicht10.0.vcxproj.filters +++ b/source/Irrlicht/Irrlicht10.0.vcxproj.filters @@ -137,13 +137,13 @@ include - + include include - + include @@ -1416,7 +1416,7 @@ Irrlicht\video\Null - + include\core @@ -1483,6 +1483,9 @@ include + + include\scene + diff --git a/source/Irrlicht/dmfsupport.h b/source/Irrlicht/dmfsupport.h index 721f703..dc65e5b 100644 --- a/source/Irrlicht/dmfsupport.h +++ b/source/Irrlicht/dmfsupport.h @@ -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 /**& materials/**= 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& materials/**= 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 -*/ - -/* - * From rfc3629, the UTF-8 spec: - * http://www.ietf.org/rfc/rfc3629.txt - * - * Char. number range | UTF-8 octet sequence - * (hexadecimal) | (binary) - * --------------------+--------------------------------------------- - * 0000 0000-0000 007F | 0xxxxxxx - * 0000 0080-0000 07FF | 110xxxxx 10xxxxxx - * 0000 0800-0000 FFFF | 1110xxxx 10xxxxxx 10xxxxxx - * 0001 0000-0010 FFFF | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx - */ - - -/* - * This may not be the best value, but it's one that isn't represented - * in Unicode (0x10FFFF is the largest codepoint value). We return this - * value from utf8codepoint() if there's bogus bits in the - * stream. utf8codepoint() will turn this value into something - * reasonable (like a question mark), for text that wants to try to recover, - * whereas utf8valid() will use the value to determine if a string has bad - * bits. - */ -#define UNICODE_BOGUS_CHAR_VALUE 0xFFFFFFFF - -/* - * This is the codepoint we currently return when there was bogus bits in a - * UTF-8 string. May not fly in Asian locales? - */ -#define UNICODE_BOGUS_CHAR_CODEPOINT '?' - -static u32 utf8codepoint(const char **_str) -{ - const char *str = *_str; - u32 retval = 0; - u32 octet = (u32) ((u8) *str); - u32 octet2, octet3, octet4; - - if (octet == 0) /* null terminator, end of string. */ - return 0; - - else if (octet < 128) /* one octet char: 0 to 127 */ - { - (*_str)++; /* skip to next possible start of codepoint. */ - return(octet); - } /* else if */ - - else if ((octet > 127) && (octet < 192)) /* bad (starts with 10xxxxxx). */ - { - /* - * Apparently each of these is supposed to be flagged as a bogus - * char, instead of just resyncing to the next valid codepoint. - */ - (*_str)++; /* skip to next possible start of codepoint. */ - return UNICODE_BOGUS_CHAR_VALUE; - } /* else if */ - - else if (octet < 224) /* two octets */ - { - octet -= (128+64); - octet2 = (u32) ((u8) *(++str)); - if ((octet2 & (128+64)) != 128) /* Format isn't 10xxxxxx? */ - return UNICODE_BOGUS_CHAR_VALUE; - - *_str += 2; /* skip to next possible start of codepoint. */ - retval = ((octet << 6) | (octet2 - 128)); - if ((retval >= 0x80) && (retval <= 0x7FF)) - return retval; - } /* else if */ - - else if (octet < 240) /* three octets */ - { - octet -= (128+64+32); - octet2 = (u32) ((u8) *(++str)); - if ((octet2 & (128+64)) != 128) /* Format isn't 10xxxxxx? */ - return UNICODE_BOGUS_CHAR_VALUE; - - octet3 = (u32) ((u8) *(++str)); - if ((octet3 & (128+64)) != 128) /* Format isn't 10xxxxxx? */ - return UNICODE_BOGUS_CHAR_VALUE; - - *_str += 3; /* skip to next possible start of codepoint. */ - retval = ( ((octet << 12)) | ((octet2-128) << 6) | ((octet3-128)) ); - - /* There are seven "UTF-16 surrogates" that are illegal in UTF-8. */ - switch (retval) - { - case 0xD800: - case 0xDB7F: - case 0xDB80: - case 0xDBFF: - case 0xDC00: - case 0xDF80: - case 0xDFFF: - return UNICODE_BOGUS_CHAR_VALUE; - } /* switch */ - - /* 0xFFFE and 0xFFFF are illegal, too, so we check them at the edge. */ - if ((retval >= 0x800) && (retval <= 0xFFFD)) - return retval; - } /* else if */ - - else if (octet < 248) /* four octets */ - { - octet -= (128+64+32+16); - octet2 = (u32) ((u8) *(++str)); - if ((octet2 & (128+64)) != 128) /* Format isn't 10xxxxxx? */ - return UNICODE_BOGUS_CHAR_VALUE; - - octet3 = (u32) ((u8) *(++str)); - if ((octet3 & (128+64)) != 128) /* Format isn't 10xxxxxx? */ - return UNICODE_BOGUS_CHAR_VALUE; - - octet4 = (u32) ((u8) *(++str)); - if ((octet4 & (128+64)) != 128) /* Format isn't 10xxxxxx? */ - return UNICODE_BOGUS_CHAR_VALUE; - - *_str += 4; /* skip to next possible start of codepoint. */ - retval = ( ((octet << 18)) | ((octet2 - 128) << 12) | - ((octet3 - 128) << 6) | ((octet4 - 128)) ); - if ((retval >= 0x10000) && (retval <= 0x10FFFF)) - return retval; - } /* else if */ - - /* - * Five and six octet sequences became illegal in rfc3629. - * We throw the codepoint away, but parse them to make sure we move - * ahead the right number of bytes and don't overflow the buffer. - */ - - else if (octet < 252) /* five octets */ - { - octet = (u32) ((u8) *(++str)); - if ((octet & (128+64)) != 128) /* Format isn't 10xxxxxx? */ - return UNICODE_BOGUS_CHAR_VALUE; - - octet = (u32) ((u8) *(++str)); - if ((octet & (128+64)) != 128) /* Format isn't 10xxxxxx? */ - return UNICODE_BOGUS_CHAR_VALUE; - - octet = (u32) ((u8) *(++str)); - if ((octet & (128+64)) != 128) /* Format isn't 10xxxxxx? */ - return UNICODE_BOGUS_CHAR_VALUE; - - octet = (u32) ((u8) *(++str)); - if ((octet & (128+64)) != 128) /* Format isn't 10xxxxxx? */ - return UNICODE_BOGUS_CHAR_VALUE; - - *_str += 5; /* skip to next possible start of codepoint. */ - return UNICODE_BOGUS_CHAR_VALUE; - } /* else if */ - - else /* six octets */ - { - octet = (u32) ((u8) *(++str)); - if ((octet & (128+64)) != 128) /* Format isn't 10xxxxxx? */ - return UNICODE_BOGUS_CHAR_VALUE; - - octet = (u32) ((u8) *(++str)); - if ((octet & (128+64)) != 128) /* Format isn't 10xxxxxx? */ - return UNICODE_BOGUS_CHAR_VALUE; - - octet = (u32) ((u8) *(++str)); - if ((octet & (128+64)) != 128) /* Format isn't 10xxxxxx? */ - return UNICODE_BOGUS_CHAR_VALUE; - - octet = (u32) ((u8) *(++str)); - if ((octet & (128+64)) != 128) /* Format isn't 10xxxxxx? */ - return UNICODE_BOGUS_CHAR_VALUE; - - octet = (u32) ((u8) *(++str)); - if ((octet & (128+64)) != 128) /* Format isn't 10xxxxxx? */ - return UNICODE_BOGUS_CHAR_VALUE; - - *_str += 6; /* skip to next possible start of codepoint. */ - return UNICODE_BOGUS_CHAR_VALUE; - } /* else if */ - - return UNICODE_BOGUS_CHAR_VALUE; -} /* utf8codepoint */ - - -static void PHYSFS_utf8ToUcs4(const char *src, u32 *dst, u64 len) -{ - len -= sizeof (u32); /* save room for null char. */ - while (len >= sizeof (u32)) - { - u32 cp = utf8codepoint(&src); - if (cp == 0) - break; - else if (cp == UNICODE_BOGUS_CHAR_VALUE) - cp = UNICODE_BOGUS_CHAR_CODEPOINT; - *(dst++) = cp; - len -= sizeof (u32); - } /* while */ - - *dst = 0; -} /* PHYSFS_utf8ToUcs4 */ - - -static void PHYSFS_utf8ToUcs2(const char *src, u16 *dst, u64 len) -{ - len -= sizeof (u16); /* save room for null char. */ - while (len >= sizeof (u16)) - { - u32 cp = utf8codepoint(&src); - if (cp == 0) - break; - else if (cp == UNICODE_BOGUS_CHAR_VALUE) - cp = UNICODE_BOGUS_CHAR_CODEPOINT; - - /* !!! BLUESKY: UTF-16 surrogates? */ - if (cp > 0xFFFF) - cp = UNICODE_BOGUS_CHAR_CODEPOINT; - - *(dst++) = cp; - len -= sizeof (u16); - } /* while */ - - *dst = 0; -} /* PHYSFS_utf8ToUcs2 */ - -static void utf8fromcodepoint(u32 cp, char **_dst, u64 *_len) -{ - char *dst = *_dst; - u64 len = *_len; - - if (len == 0) - return; - - if (cp > 0x10FFFF) - cp = UNICODE_BOGUS_CHAR_CODEPOINT; - else if ((cp == 0xFFFE) || (cp == 0xFFFF)) /* illegal values. */ - cp = UNICODE_BOGUS_CHAR_CODEPOINT; - else - { - /* There are seven "UTF-16 surrogates" that are illegal in UTF-8. */ - switch (cp) - { - case 0xD800: - case 0xDB7F: - case 0xDB80: - case 0xDBFF: - case 0xDC00: - case 0xDF80: - case 0xDFFF: - cp = UNICODE_BOGUS_CHAR_CODEPOINT; - } /* switch */ - } /* else */ - - /* Do the encoding... */ - if (cp < 0x80) - { - *(dst++) = (char) cp; - len--; - } /* if */ - - else if (cp < 0x800) - { - if (len < 2) - len = 0; - else - { - *(dst++) = (char) ((cp >> 6) | 128 | 64); - *(dst++) = (char) (cp & 0x3F) | 128; - len -= 2; - } /* else */ - } /* else if */ - - else if (cp < 0x10000) - { - if (len < 3) - len = 0; - else - { - *(dst++) = (char) ((cp >> 12) | 128 | 64 | 32); - *(dst++) = (char) ((cp >> 6) & 0x3F) | 128; - *(dst++) = (char) (cp & 0x3F) | 128; - len -= 3; - } /* else */ - } /* else if */ - - else - { - if (len < 4) - len = 0; - else - { - *(dst++) = (char) ((cp >> 18) | 128 | 64 | 32 | 16); - *(dst++) = (char) ((cp >> 12) & 0x3F) | 128; - *(dst++) = (char) ((cp >> 6) & 0x3F) | 128; - *(dst++) = (char) (cp & 0x3F) | 128; - len -= 4; - } /* else if */ - } /* else */ - - *_dst = dst; - *_len = len; -} /* utf8fromcodepoint */ - -#define UTF8FROMTYPE(typ, src, dst, len) \ - if (len == 0) return; \ - len--; \ - while (len) \ - { \ - const u32 cp = (u32) ((typ) (*(src++))); \ - if (cp == 0) break; \ - utf8fromcodepoint(cp, &dst, &len); \ - } \ - *dst = '\0'; \ - -static void PHYSFS_utf8FromUcs4(const u32 *src, char *dst, u64 len) -{ - UTF8FROMTYPE(u32, src, dst, len); -} /* PHYSFS_utf8FromUcs4 */ - -static void PHYSFS_utf8FromUcs2(const u16 *src, char *dst, u64 len) -{ - UTF8FROMTYPE(u64, src, dst, len); -} /* PHYSFS_utf8FromUcs4 */ - -#undef UTF8FROMTYPE - -void utf8ToWchar(const char *in, wchar_t *out, const u64 len) -{ -#ifdef _WIN32 - PHYSFS_utf8ToUcs2(in, (u16 *) out, len); -#else - PHYSFS_utf8ToUcs4(in, (u32 *) out, len); -#endif -} - -void wcharToUtf8(const wchar_t *in, char *out, const u64 len) -{ -#ifdef _WIN32 - PHYSFS_utf8FromUcs2((const u16 *) in, out, len); -#else - PHYSFS_utf8FromUcs4((const u32 *) in, out, len); -#endif -} - -} // end namespace core -} // end namespace irr - +// Copyright (C) 2014 Lauri Kasanen +// This file is part of the "Irrlicht Engine". The UTF-8 functions are from physfs, +// under the zlib license, reproduced below. + +#include "irrTypes.h" +#include "irrString.h" + +namespace irr +{ +namespace core +{ + +/* + Copyright (c) 2001-2011 Ryan C. Gordon and others. + + This software is provided 'as-is', without any express or implied warranty. + In no event will the authors be held liable for any damages arising from + the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software in a + product, an acknowledgment in the product documentation would be + appreciated but is not required. + + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + + 3. This notice may not be removed or altered from any source distribution. + + Ryan C. Gordon +*/ + +/* + * From rfc3629, the UTF-8 spec: + * http://www.ietf.org/rfc/rfc3629.txt + * + * Char. number range | UTF-8 octet sequence + * (hexadecimal) | (binary) + * --------------------+--------------------------------------------- + * 0000 0000-0000 007F | 0xxxxxxx + * 0000 0080-0000 07FF | 110xxxxx 10xxxxxx + * 0000 0800-0000 FFFF | 1110xxxx 10xxxxxx 10xxxxxx + * 0001 0000-0010 FFFF | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx + */ + + +/* + * This may not be the best value, but it's one that isn't represented + * in Unicode (0x10FFFF is the largest codepoint value). We return this + * value from utf8codepoint() if there's bogus bits in the + * stream. utf8codepoint() will turn this value into something + * reasonable (like a question mark), for text that wants to try to recover, + * whereas utf8valid() will use the value to determine if a string has bad + * bits. + */ +#define UNICODE_BOGUS_CHAR_VALUE 0xFFFFFFFF + +/* + * This is the codepoint we currently return when there was bogus bits in a + * UTF-8 string. May not fly in Asian locales? + */ +#define UNICODE_BOGUS_CHAR_CODEPOINT '?' + +static u32 utf8codepoint(const char **_str) +{ + const char *str = *_str; + u32 retval = 0; + u32 octet = (u32) ((u8) *str); + u32 octet2, octet3, octet4; + + if (octet == 0) /* null terminator, end of string. */ + return 0; + + else if (octet < 128) /* one octet char: 0 to 127 */ + { + (*_str)++; /* skip to next possible start of codepoint. */ + return(octet); + } /* else if */ + + else if ((octet > 127) && (octet < 192)) /* bad (starts with 10xxxxxx). */ + { + /* + * Apparently each of these is supposed to be flagged as a bogus + * char, instead of just resyncing to the next valid codepoint. + */ + (*_str)++; /* skip to next possible start of codepoint. */ + return UNICODE_BOGUS_CHAR_VALUE; + } /* else if */ + + else if (octet < 224) /* two octets */ + { + octet -= (128+64); + octet2 = (u32) ((u8) *(++str)); + if ((octet2 & (128+64)) != 128) /* Format isn't 10xxxxxx? */ + return UNICODE_BOGUS_CHAR_VALUE; + + *_str += 2; /* skip to next possible start of codepoint. */ + retval = ((octet << 6) | (octet2 - 128)); + if ((retval >= 0x80) && (retval <= 0x7FF)) + return retval; + } /* else if */ + + else if (octet < 240) /* three octets */ + { + octet -= (128+64+32); + octet2 = (u32) ((u8) *(++str)); + if ((octet2 & (128+64)) != 128) /* Format isn't 10xxxxxx? */ + return UNICODE_BOGUS_CHAR_VALUE; + + octet3 = (u32) ((u8) *(++str)); + if ((octet3 & (128+64)) != 128) /* Format isn't 10xxxxxx? */ + return UNICODE_BOGUS_CHAR_VALUE; + + *_str += 3; /* skip to next possible start of codepoint. */ + retval = ( ((octet << 12)) | ((octet2-128) << 6) | ((octet3-128)) ); + + /* There are seven "UTF-16 surrogates" that are illegal in UTF-8. */ + switch (retval) + { + case 0xD800: + case 0xDB7F: + case 0xDB80: + case 0xDBFF: + case 0xDC00: + case 0xDF80: + case 0xDFFF: + return UNICODE_BOGUS_CHAR_VALUE; + } /* switch */ + + /* 0xFFFE and 0xFFFF are illegal, too, so we check them at the edge. */ + if ((retval >= 0x800) && (retval <= 0xFFFD)) + return retval; + } /* else if */ + + else if (octet < 248) /* four octets */ + { + octet -= (128+64+32+16); + octet2 = (u32) ((u8) *(++str)); + if ((octet2 & (128+64)) != 128) /* Format isn't 10xxxxxx? */ + return UNICODE_BOGUS_CHAR_VALUE; + + octet3 = (u32) ((u8) *(++str)); + if ((octet3 & (128+64)) != 128) /* Format isn't 10xxxxxx? */ + return UNICODE_BOGUS_CHAR_VALUE; + + octet4 = (u32) ((u8) *(++str)); + if ((octet4 & (128+64)) != 128) /* Format isn't 10xxxxxx? */ + return UNICODE_BOGUS_CHAR_VALUE; + + *_str += 4; /* skip to next possible start of codepoint. */ + retval = ( ((octet << 18)) | ((octet2 - 128) << 12) | + ((octet3 - 128) << 6) | ((octet4 - 128)) ); + if ((retval >= 0x10000) && (retval <= 0x10FFFF)) + return retval; + } /* else if */ + + /* + * Five and six octet sequences became illegal in rfc3629. + * We throw the codepoint away, but parse them to make sure we move + * ahead the right number of bytes and don't overflow the buffer. + */ + + else if (octet < 252) /* five octets */ + { + octet = (u32) ((u8) *(++str)); + if ((octet & (128+64)) != 128) /* Format isn't 10xxxxxx? */ + return UNICODE_BOGUS_CHAR_VALUE; + + octet = (u32) ((u8) *(++str)); + if ((octet & (128+64)) != 128) /* Format isn't 10xxxxxx? */ + return UNICODE_BOGUS_CHAR_VALUE; + + octet = (u32) ((u8) *(++str)); + if ((octet & (128+64)) != 128) /* Format isn't 10xxxxxx? */ + return UNICODE_BOGUS_CHAR_VALUE; + + octet = (u32) ((u8) *(++str)); + if ((octet & (128+64)) != 128) /* Format isn't 10xxxxxx? */ + return UNICODE_BOGUS_CHAR_VALUE; + + *_str += 5; /* skip to next possible start of codepoint. */ + return UNICODE_BOGUS_CHAR_VALUE; + } /* else if */ + + else /* six octets */ + { + octet = (u32) ((u8) *(++str)); + if ((octet & (128+64)) != 128) /* Format isn't 10xxxxxx? */ + return UNICODE_BOGUS_CHAR_VALUE; + + octet = (u32) ((u8) *(++str)); + if ((octet & (128+64)) != 128) /* Format isn't 10xxxxxx? */ + return UNICODE_BOGUS_CHAR_VALUE; + + octet = (u32) ((u8) *(++str)); + if ((octet & (128+64)) != 128) /* Format isn't 10xxxxxx? */ + return UNICODE_BOGUS_CHAR_VALUE; + + octet = (u32) ((u8) *(++str)); + if ((octet & (128+64)) != 128) /* Format isn't 10xxxxxx? */ + return UNICODE_BOGUS_CHAR_VALUE; + + octet = (u32) ((u8) *(++str)); + if ((octet & (128+64)) != 128) /* Format isn't 10xxxxxx? */ + return UNICODE_BOGUS_CHAR_VALUE; + + *_str += 6; /* skip to next possible start of codepoint. */ + return UNICODE_BOGUS_CHAR_VALUE; + } /* else if */ + + return UNICODE_BOGUS_CHAR_VALUE; +} /* utf8codepoint */ + + +static void PHYSFS_utf8ToUcs4(const char *src, u32 *dst, u64 len) +{ + len -= sizeof (u32); /* save room for null char. */ + while (len >= sizeof (u32)) + { + u32 cp = utf8codepoint(&src); + if (cp == 0) + break; + else if (cp == UNICODE_BOGUS_CHAR_VALUE) + cp = UNICODE_BOGUS_CHAR_CODEPOINT; + *(dst++) = cp; + len -= sizeof (u32); + } /* while */ + + *dst = 0; +} /* PHYSFS_utf8ToUcs4 */ + + +static void PHYSFS_utf8ToUcs2(const char *src, u16 *dst, u64 len) +{ + len -= sizeof (u16); /* save room for null char. */ + while (len >= sizeof (u16)) + { + u32 cp = utf8codepoint(&src); + if (cp == 0) + break; + else if (cp == UNICODE_BOGUS_CHAR_VALUE) + cp = UNICODE_BOGUS_CHAR_CODEPOINT; + + /* !!! BLUESKY: UTF-16 surrogates? */ + if (cp > 0xFFFF) + cp = UNICODE_BOGUS_CHAR_CODEPOINT; + + *(dst++) = cp; + len -= sizeof (u16); + } /* while */ + + *dst = 0; +} /* PHYSFS_utf8ToUcs2 */ + +static void utf8fromcodepoint(u32 cp, char **_dst, u64 *_len) +{ + char *dst = *_dst; + u64 len = *_len; + + if (len == 0) + return; + + if (cp > 0x10FFFF) + cp = UNICODE_BOGUS_CHAR_CODEPOINT; + else if ((cp == 0xFFFE) || (cp == 0xFFFF)) /* illegal values. */ + cp = UNICODE_BOGUS_CHAR_CODEPOINT; + else + { + /* There are seven "UTF-16 surrogates" that are illegal in UTF-8. */ + switch (cp) + { + case 0xD800: + case 0xDB7F: + case 0xDB80: + case 0xDBFF: + case 0xDC00: + case 0xDF80: + case 0xDFFF: + cp = UNICODE_BOGUS_CHAR_CODEPOINT; + } /* switch */ + } /* else */ + + /* Do the encoding... */ + if (cp < 0x80) + { + *(dst++) = (char) cp; + len--; + } /* if */ + + else if (cp < 0x800) + { + if (len < 2) + len = 0; + else + { + *(dst++) = (char) ((cp >> 6) | 128 | 64); + *(dst++) = (char) (cp & 0x3F) | 128; + len -= 2; + } /* else */ + } /* else if */ + + else if (cp < 0x10000) + { + if (len < 3) + len = 0; + else + { + *(dst++) = (char) ((cp >> 12) | 128 | 64 | 32); + *(dst++) = (char) ((cp >> 6) & 0x3F) | 128; + *(dst++) = (char) (cp & 0x3F) | 128; + len -= 3; + } /* else */ + } /* else if */ + + else + { + if (len < 4) + len = 0; + else + { + *(dst++) = (char) ((cp >> 18) | 128 | 64 | 32 | 16); + *(dst++) = (char) ((cp >> 12) & 0x3F) | 128; + *(dst++) = (char) ((cp >> 6) & 0x3F) | 128; + *(dst++) = (char) (cp & 0x3F) | 128; + len -= 4; + } /* else if */ + } /* else */ + + *_dst = dst; + *_len = len; +} /* utf8fromcodepoint */ + +#define UTF8FROMTYPE(typ, src, dst, len) \ + if (len == 0) return; \ + len--; \ + while (len) \ + { \ + const u32 cp = (u32) ((typ) (*(src++))); \ + if (cp == 0) break; \ + utf8fromcodepoint(cp, &dst, &len); \ + } \ + *dst = '\0'; \ + +static void PHYSFS_utf8FromUcs4(const u32 *src, char *dst, u64 len) +{ + UTF8FROMTYPE(u32, src, dst, len); +} /* PHYSFS_utf8FromUcs4 */ + +static void PHYSFS_utf8FromUcs2(const u16 *src, char *dst, u64 len) +{ + UTF8FROMTYPE(u64, src, dst, len); +} /* PHYSFS_utf8FromUcs4 */ + +#undef UTF8FROMTYPE + +void utf8ToWchar(const char *in, wchar_t *out, const u64 len) +{ + switch ( sizeof(wchar_t) ) + { + case 2: PHYSFS_utf8ToUcs2(in, (u16 *) out, len); break; + case 4: PHYSFS_utf8ToUcs4(in, (u32 *) out, len); break; + } +} + +void wcharToUtf8(const wchar_t *in, char *out, const u64 len) +{ + switch ( sizeof(wchar_t) ) + { + case 2: PHYSFS_utf8FromUcs2((const u16 *) in, out, len); break; + case 4: PHYSFS_utf8FromUcs4((const u32 *) in, out, len); break; + } +} + +} // end namespace core +} // end namespace irr diff --git a/tests/Makefile b/tests/Makefile index 83b4b26..7dff010 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -18,7 +18,7 @@ all: all_linux # target specific settings 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: LDFLAGS = -L../lib/$(SYSTEM) -lIrrlicht -lopengl32 -lm diff --git a/tests/makeColorKeyTexture.cpp b/tests/makeColorKeyTexture.cpp index 288a426..f5816e6 100644 --- a/tests/makeColorKeyTexture.cpp +++ b/tests/makeColorKeyTexture.cpp @@ -27,12 +27,12 @@ static bool doTestWith(E_DRIVER_TYPE driverType, cube->setMaterialTexture(0, driver->getTexture("../media/wall.bmp")); cube->setMaterialFlag(video::EMF_LIGHTING, false); - ITexture * Texture = device->getVideoDriver()->getTexture("../media/portal2.bmp"); + ITexture * texture = device->getVideoDriver()->getTexture("../media/portal2.bmp"); - device->getVideoDriver()->makeColorKeyTexture(Texture, + device->getVideoDriver()->makeColorKeyTexture(texture, position2d(64,64), zeroTexels); - device->getVideoDriver()->makeColorKeyTexture(Texture, + device->getVideoDriver()->makeColorKeyTexture(texture, position2d(64,64), zeroTexels); (void)smgr->addCameraSceneNode(); @@ -40,9 +40,9 @@ static bool doTestWith(E_DRIVER_TYPE driverType, driver->beginScene(video::ECBF_COLOR | video::ECBF_DEPTH, SColor(255,100,101,140)); smgr->drawAll(); - driver->draw2DImage(Texture, + driver->draw2DImage(texture, position2di(40, 40), - rect(0, 0, Texture->getSize().Width, Texture->getSize().Height), + recti(texture->getOriginalSize()), 0, SColor(255,255,255,255), true); diff --git a/tests/media/Burning's Video-shotsInShots0.png b/tests/media/Burning's Video-shotsInShots0.png new file mode 100644 index 0000000..7bf1d55 Binary files /dev/null and b/tests/media/Burning's Video-shotsInShots0.png differ diff --git a/tests/media/Burning's Video-shotsInShots2.png b/tests/media/Burning's Video-shotsInShots2.png new file mode 100644 index 0000000..7bf1d55 Binary files /dev/null and b/tests/media/Burning's Video-shotsInShots2.png differ diff --git a/tests/media/Direct3D 9.0-shotsInShots0.png b/tests/media/Direct3D 9.0-shotsInShots0.png new file mode 100644 index 0000000..b118965 Binary files /dev/null and b/tests/media/Direct3D 9.0-shotsInShots0.png differ diff --git a/tests/media/Direct3D 9.0-shotsInShots2.png b/tests/media/Direct3D 9.0-shotsInShots2.png new file mode 100644 index 0000000..b118965 Binary files /dev/null and b/tests/media/Direct3D 9.0-shotsInShots2.png differ diff --git a/tests/media/Irrlicht Software Driver 1.0-shotsInShots0.png b/tests/media/Irrlicht Software Driver 1.0-shotsInShots0.png new file mode 100644 index 0000000..70d2d49 Binary files /dev/null and b/tests/media/Irrlicht Software Driver 1.0-shotsInShots0.png differ diff --git a/tests/media/Irrlicht Software Driver 1.0-shotsInShots2.png b/tests/media/Irrlicht Software Driver 1.0-shotsInShots2.png new file mode 100644 index 0000000..70d2d49 Binary files /dev/null and b/tests/media/Irrlicht Software Driver 1.0-shotsInShots2.png differ diff --git a/tests/media/OpenGL-shotsInShots0.png b/tests/media/OpenGL-shotsInShots0.png new file mode 100644 index 0000000..e833935 Binary files /dev/null and b/tests/media/OpenGL-shotsInShots0.png differ diff --git a/tests/media/OpenGL-shotsInShots2.png b/tests/media/OpenGL-shotsInShots2.png new file mode 100644 index 0000000..e833935 Binary files /dev/null and b/tests/media/OpenGL-shotsInShots2.png differ diff --git a/tests/orthoCam.cpp b/tests/orthoCam.cpp index deb08bc..11e3786 100644 --- a/tests/orthoCam.cpp +++ b/tests/orthoCam.cpp @@ -96,7 +96,7 @@ bool orthoCam(void) // passed &= testOrthoCam(video::EDT_SOFTWARE); passed &= testOrthoCam(video::EDT_BURNINGSVIDEO); passed &= testOrthoCam(video::EDT_DIRECT3D9); - + SLOW_SWITCH; // TODO: not sure if burnings could work? Currently it doesn't. passed &= testOrthoStencil(video::EDT_OPENGL); passed &= testOrthoStencil(video::EDT_DIRECT3D9); diff --git a/tests/renderTargetTexture.cpp b/tests/renderTargetTexture.cpp index 24d15d0..140e9a5 100644 --- a/tests/renderTargetTexture.cpp +++ b/tests/renderTargetTexture.cpp @@ -45,14 +45,13 @@ static bool testWith2DImage(video::E_DRIVER_TYPE driverType) //draw the image : driver->beginScene(video::ECBF_COLOR | video::ECBF_DEPTH, video::SColor (255, 200, 200, 200)); driver->draw2DImage (image, - core::rect < s32 > - (64 - image->getSize ().Width / 2, - 64 - image->getSize ().Height / 2, - 64 + image->getSize ().Width / 2, - 64 + image->getSize ().Height / 2), - core::rect < s32 > (0, 0, image->getSize ().Width, - image->getSize ().Height), 0, colors, - true); + core::recti( + 64 - image->getOriginalSize().Width / 2, + 64 - image->getOriginalSize().Height / 2, + 64 + image->getOriginalSize().Width / 2, + 64 + image->getOriginalSize().Height / 2), + core::recti(image->getOriginalSize()), + 0, colors, true); driver->endScene (); //then create a model and apply to it the RTT Texture @@ -76,14 +75,13 @@ static bool testWith2DImage(video::E_DRIVER_TYPE driverType) //draw img driver->draw2DImage (image, - core::rect < s32 > - (64 - image->getSize ().Width / 2, - 64 - image->getSize ().Height / 2, - 64 + image->getSize ().Width / 2, - 64 + image->getSize ().Height / 2), - core::rect < s32 > (0, 0, image->getSize ().Width, - image->getSize ().Height), 0, - colors, true); + core::recti( + 64 - image->getOriginalSize().Width / 2, + 64 - image->getOriginalSize().Height / 2, + 64 + image->getOriginalSize().Width / 2, + 64 + image->getOriginalSize().Height / 2), + core::recti(image->getOriginalSize()), + 0, colors, true); //call this is important : //if not called, the bug won't appear @@ -243,7 +241,7 @@ bool rttAndText(video::E_DRIVER_TYPE driverType) driver->beginScene(0, video::SColor(255,255, 255, 255)); driver->setRenderTargetEx(renderTarget, video::ECBF_COLOR | video::ECBF_DEPTH, video::SColor(255,255,0,255)); - driver->draw2DImage(driver->getTexture("../media/fireball.bmp"), core::recti(0, 0, renderTargetTex->getSize().Width, renderTargetTex->getSize().Height), core::recti(0, 0, 64, 64)); + driver->draw2DImage(driver->getTexture("../media/fireball.bmp"), core::recti(renderTargetTex->getOriginalSize()), core::recti(0, 0, 64, 64)); guienv->getBuiltInFont()->draw(L"OMGGG =!", core::rect(120, 100, 256, 256), video::SColor(255, 0, 0, 255)); driver->setRenderTargetEx(0, 0, 0); driver->endScene(); diff --git a/tests/screenshot.cpp b/tests/screenshot.cpp index 51f3148..3900959 100644 --- a/tests/screenshot.cpp +++ b/tests/screenshot.cpp @@ -5,10 +5,10 @@ using namespace irr; - +static irr::u8 aa = 0; // AntiAlias used in testShotsInShots // Tests screenshots features -bool testShots(video::E_DRIVER_TYPE type) +static bool testShots(video::E_DRIVER_TYPE type) { IrrlichtDevice *device = createDevice(type, core::dimension2d(160, 120), 32); if (!device) @@ -75,9 +75,82 @@ bool testShots(video::E_DRIVER_TYPE type) return true; } +// render some recognizable stuff +static void drawSomeStuff(video::IVideoDriver* driver) +{ + driver->draw2DRectangle(core::recti(5,5,155,115), + video::SColor(255, 100, 0, 0), + video::SColor(255, 0, 200, 0), + video::SColor(255, 0, 0, 200), + video::SColor(255, 20, 150, 150)); + driver->draw2DLine(core::position2di(10,10), core::position2di(150,110), video::SColor(255,250,50,0)); + driver->draw2DLine(core::position2di(0,120), core::position2di(80,60), video::SColor(255,50,50,250)); +} + +// Make a screenshot, then draw it again (scaled down) together with the stuff the screenshot was made from +static bool testShotsOfShots(video::E_DRIVER_TYPE type) +{ + SIrrlichtCreationParameters params; + params.AntiAlias = aa; + params.WindowSize = core::dimension2du(160, 120); + params.DriverType = type; + + IrrlichtDevice *device = createDeviceEx(params); + + if (!device) + return true; // in case the driver type does not exist + + video::IVideoDriver* driver = device->getVideoDriver(); + logTestString("Testing driver %ls\n", driver->getName()); + stabilizeScreenBackground(driver); + + device->run(); + driver->beginScene(video::ECBF_COLOR | video::ECBF_DEPTH, video::SColor(255,100,101,140)); + drawSomeStuff(driver); + driver->endScene(); + video::IImage* img = driver->createScreenShot(); + + bool result = true; + if ( img ) + { + video::ITexture * screenshot = driver->addTexture(io::path("firstScreenshot"), img); + + driver->beginScene(video::ECBF_COLOR | video::ECBF_DEPTH, video::SColor(255,100,101,140)); + drawSomeStuff(driver); + driver->draw2DImage(screenshot, core::recti(0, 30, 80, 90), core::recti(screenshot->getOriginalSize()), 0, 0, 0); + driver->endScene(); + img->drop(); + + irr::core::stringc name("-shotsInShots"); + name += irr::core::stringc((int)aa); + name += ".png"; + result = takeScreenshotAndCompareAgainstReference(driver, name.c_str()); + if ( !result ) + { + logTestString("driver color format: %s\n", video::ColorFormatNames[driver->getColorFormat()]); + } + } + else + { + logTestString("Failed to create a screenshot"); + result = false; + } + + + device->closeDevice(); + device->run(); + device->drop(); + + return result; +} + bool screenshot() { bool result = true; TestWithAllHWDrivers(testShots); + aa = 0; + TestWithAllDrivers(testShotsOfShots); + aa = 2; // testing something that might cause troubles with Nouveau on some systems + TestWithAllDrivers(testShotsOfShots); return result; } diff --git a/tests/testGeometryCreator.cpp b/tests/testGeometryCreator.cpp index cbf48dd..6ef4654 100644 --- a/tests/testGeometryCreator.cpp +++ b/tests/testGeometryCreator.cpp @@ -77,7 +77,7 @@ bool testGeometryCreator(void) { smgr->drawAll(); driver->endScene(); - result = takeScreenshotAndCompareAgainstReference(driver, "-testGeometryCreator.png", 99.994f); + result = takeScreenshotAndCompareAgainstReference(driver, "-testGeometryCreator.png", 99.989f); } smgr->clear(); diff --git a/tests/tests-last-passed-at.txt b/tests/tests-last-passed-at.txt index 97e8e82..b2e7b88 100644 --- a/tests/tests-last-passed-at.txt +++ b/tests/tests-last-passed-at.txt @@ -1,4 +1,4 @@ -Tests finished. 72 tests of 72 passed. -Compiled as DEBUG -Test suite pass at GMT Thu Jan 6 13:59:44 2022 - +Tests finished. 72 tests of 72 passed. +Compiled as DEBUG +Test suite pass at GMT Thu Apr 14 16:41:11 2022 + diff --git a/tests/tests.cbp b/tests/tests.cbp index f5d2dd1..f0a90b5 100644 --- a/tests/tests.cbp +++ b/tests/tests.cbp @@ -107,7 +107,7 @@ - + @@ -117,6 +117,7 @@ + @@ -127,6 +128,7 @@ + @@ -150,10 +152,6 @@ - - - - - +