diff --git a/changes.txt b/changes.txt index 31a2a8d8..08d65fc3 100644 --- a/changes.txt +++ b/changes.txt @@ -1,3 +1,466 @@ +Changes in version 1.6, TA + +- FileSystem 2.0 SUPER MASTER MAJOR API CHANGE !!! + + The FileSystem is know build internally like for e.q the texture-, and the meshloaders. + There exists a known list of ArchiveLoader, which know how to produce a Archive. + The Loaders and the Archive can be attached/detached on runtime. + + The FileNames are now stored as core::string. where c16 is toggled between char/wchar + with the #define flag _IRR_WCHAR_FILESYSTEM, to supported unicode backends (default:off) + I replaced all (const c8* filename) to string references. + + Basically the FileSystem is divided into two regions. Native and Virtual. + Native means using the backend OS. + Virtual means only use currently attach IArchives. + + Browsing + each FileSystem has it's own workdirectory and it's own methods to + - create a FileTree + - add/remove files & directory ( to be done ) + Hint: store a savegame in a zip archive... + + basic browsing for all archives is implemented. + Example 21. Quake3Explorer shows this + + TODO: + - a file filter should be implemented. + - The IArchive should have a function to create a filetree + for now CFileList is used. + + Class Hiarchy: + + IArchiveLoader: is able to produce a IFileArchive + - ZipLoader + - PakLoader + - MountPointReader ( formaly known as CUnzipReader ) + + IFileArchive: + -ZipArchive + -PakArchive + -MountPoint (known as FolderFile) + + IFileSystem + - addArchiveLoader + + - changed implementation of isALoadableFileExtension in all loaders + to have consistent behavior + - added a parameter to IFileList * createFileList + setFileListSystem + allows to query files in any of the game archives + standard behavior listtype = SYSTEM ( default) + + - CLimitReadFile + added multiple file random-access support. + solved problems with mixed compressed & uncompressed files in a zip + + TODO: + - Big Big Testing!! + - Linux Version ( minor ) + - remove all double loader interfaces where only the filename differs + (IReadFile/const char *filename). This blows up the the interface + - many loaders use their own private filesearching + we should rework this + - there are a lot of helper function ( getAbsolutePath, getFileDir ) + which should be adapted to the virtual filesystem + +- IrrlichtDevice + added: + virtual bool setGammaRamp( f32 red, f32 green, f32 blue, f32 brightness, f32 contrast ) = 0; + virtual bool getGammaRamp( f32 &red, f32 &green, f32 &blue ) = 0; + + and calculating methods to DeviceStub. + implemented in Win32, TODO: other Devices + + - irrlicht.h + changed exported irrlicht.dll routines createDevice, createDeviceEx, IdentityMatrix + to extern "C" name mangling. + + for easier dynamically loading the irrlicht library and different versions + + - ParticleSystem + removed the private (old?,wrong?) interface from the ParticleEffectors + to match the parent class irr::io::IAttributeExchangingObject::deserializeAttributes + TODO: + please test if the serialization works! + +- Generic + - vector3d& normalize() + #if 0 + f32 length = (f32)(X*X + Y*Y + Z*Z); + if (core::equals(length, 0.f)) + return *this; + length = core::reciprocal_squareroot ( (f32)length ); + #else + const T length = core::reciprocal_squareroot ( (X*X + Y*Y + Z*Z) ); + #endif + + Weak checking on zero?!?! just to avoid a sqrt?. mhm, maybe not;-) + added reciprocal_squareroot for f64 + + - dimension2d + added operator dimension2d& operator=(const dimension2d& other) + to cast between different types + - vector2d + bugfix: + vector2d& operator+=(const dimension2d& other) { X += other.Width; Y += other.Width; return *this; } + to + vector2d& operator+=(const dimension2d& other) { X += other.Width; Y += other.Height; return *this; } + + - C3DMeshLoader renamed chunks const u16 to a enum + removing "variable declared but never used warning" + - added a global const identity Material + changed all references *((video::SMaterial*)0) to point to IdentityMaterial + removed warning: "a NULL reference is not allowed" + + - modified IRRLICHT_MATH to not support reciprocal stuff + but to use faster float-to-int conversion. + gcc troubles may they are. i'm using intel-compiler..;-) + - core::matrix4 + USE_MATRIX_TEST + + i tried to optimize the identity-check ( in means of performance) + i didn't succeed so well, so i made a define for the matrix isIdentity -check + for now it's sometimes faster to always calculate versus identity-check + but if there are a lot of scenenodes/ particles one can profit from the + fast_inverse matrix, when no scaling is used. further approvement could + be done on inverse for just tranlastion! ( many static scenenodes are not rotated, + they are just placed somewhere in the world) + one thing to take in account is that sizeof(matrix) is 64 byte and + with the additional bool/u32 makes it 66 byte which is not really cache-friendly.. + + - added buildRotateFromTo + Builds a matrix that rotates from one vector to another + + - irr::array. changed allocating routine in push_back + + okt, 2008. it's only allowed to alloc one element, if + default constructor has to be called. + + removes existing crashes. ( MD3 Mesh ) and possible others ones. + + A new list template should be made. + one with constructor/destructor calls ( safe_array ) and + one without. like the array since the beginning of irrlicht. + currently the array/string is extremly slow.. + + also a hint for the user has to be done, so that a struct T of + array must have a copy constructor of type T ( const T&other ). + + i needed hours to track that down... + + added a new method setAllocStrategy, + safe ( used + 1 ), double ( used * 2 + 1) + + better default strategies will be implemented + + - removed binary_search_const + i added it quite a long time ago, but it doesnt make real sense + a call to a sort method should happen always. i just wanted to safe + a few cycles.. + - added binary_search_multi + searches for a multi-set ( more than 1 entry in the sorted array) + returns start and end-index + + - changed some identity matrix settings to use core::IdentityMatrix + - added deletePathFromFilename to generic string functions in coreutil.h and + removed from CZipReader and CPakReader + + - s32 deserializeAttributes used instead of virtual void deserializeAttributes in + ParticleSystem ( wrong virtual was used) + +- strings & Locale + - started to add locale support + - added verify to string + - added some helper functions + + +- XBOX + i have access to a XBOX development machine now. I started to compile + for the XBOX. Question: Who did the previous implementation?. There + is no XBOX-Device inhere. maybe it's forbidden because of using the offical + Microsoft XDK. I will implement a native or sdl device based on opendk. + irrlicht compiles without errors on the xbox but can't be used. + + TODO: + - native XBOX Device +- Windows Mobile + reworked a little. added the mobile example to the windows solution for + cross development. + added maximal 128x128 texture size for windows mobile ( memory issues ) +- Collision Speed Up + + The Collision Speed Up greatly improves with many small static child-nodes + + - added COctTreeTriangleSelector::getTriangles for 3dline from user Piraaate + - modified createOctTreeTriangleSelector and createTriangleSelector + to allow node == 0, to be added to a meta selector + - CSceneNodeAnimatorCollisionResponse has the same problem as CSceneNodeAnimatorFPS + on first update: + Problem. you start setting the map. (setWorld). First update cames 4000 ms later. + The Animator applies the missing force... big problem... + changed to react on first update like camera. + + - add Variable FirstUpdate. if set to true ( on all changes ) + then position, lasttime, and falling are initialized + + -added #define OCTTREE_USE_HARDWARE in Octree.h + + if defined octtree uses internally a derived scene::MeshBuffer which has + the possibility to use the Hardware Vertex Buffer for static vertices and + dirty indices;-) + + if defined OCTTREE_USE_HARDWARE octree uses internally a derived scene::CMeshBuffer + so it's not just a replacement inside the octree. It also in the OctTreeSceneNode. + #if defined (OCTTREE_USE_HARDWARE) + driver->drawMeshBuffer ( &LightMapMeshes[i] ); + #else + driver->drawIndexedTriangleList( &LightMapMeshes[i].Vertices[0], LightMapMeshes[i].Vertices.size(), + d[i].Indices, d[i].CurrentSize / 3); + #endif + #define OCTTREE_PARENTTEST is also used. It's skip testing on fully outside and takes everything on fully inside + + + - virtual void ISceneNode::updateAbsolutePosition() + - changed + inline CMatrix4 CMatrix4::operator*(const CMatrix4& m2) const + + all two matrices have to be checked by isIdentity() + to let the isIdentity work always + + -changed inline bool CMatrix4::isIdentity() const + + on full identityCheck-> + to look first on Translation, because this is the most challenging element + which will likely not to be identity.. + + - virtual core::matrix4 getRelativeTransformation() const + + Hiarchy on Identity-Check + 1) ->getRelativeTransform -> 9 floating point checks to be passed as Identity + 2) ->isIdentity () -> 16 floating point checks to be passed as Identity + + - inline void CMatrix4::transformBoxEx(core::aabbox3d& box) const + added isIdentity() check + + +- changed CSceneNodeAnimatorCollisionResponse + - added CSceneNodeAnimatorCollisionResponse::setGravity + needed to set the differents Forces for the Animator. for eq. water.. + - added CSceneNodeAnimatorCollisionResponse::setAnimateTarget + - added CSceneNodeAnimatorCollisionResponse::getAnimateTarget + - changed CSceneNodeAnimatorCollisionResponse::animateNode to react on FirstUpdate + - changad Gravity to + - TODO: set Gravity to Physically frame independent values.. + current response uses an frame depdended acceleration vector. + ~9.81 m/s^2 was achieved at around 50 fps with a setting of -0.03 + may effect existing application.. + +- SceneNodes + - CSkyDomeSceneNode + moved radius ( default 1000 ) to constructor + added Normals + added DebugInfo + added Material.ZBuffer, added SceneMaanager + + - CVolumeLightSceneNode: + changed default blending OneTextureBlendgl_src_color gl_src_alpha to + EMT_TRANSPARENT_ADD_COLOR ( gl_src_color gl_one ) + which gives the same effect on non-transparent-materials. + Following the unspoken guide-line, lowest effect as default + - added LensFlareSceneNode (from forum user gammaray, modified to work ) + showing in example special fx + - changed SceneNode Skydome f64 to f32, + - AnimatedMesh + -Debug Data: + mesh normals didn't rotate with the scenenode fixed ( matrix-multiplication order) + - Camera SceneNode setPosition + Camera now finally allow to change position and target and updates all + effected animators.. + + a call to OnAnimate ( ) lastime < time or OnAnimate ( 0 ) will reset the + camera and fr. the collision animator to a new position + +- Device: + added the current mousebutton state to the Mouse Event + so i need to get the current mouse state from the OS + + -a dded to CIrrDeviceWin32 + TODO: + - Linux and SDL Device +- GUI + + - CGUIFont: + - added virtual void setInvisibleCharacters( const wchar_t *s ) = 0; + + define which characters should not be drawn ( send to driver) by the font. + for example " " would not draw any space which is usually blank in most fonts + and saves rendering of ususally full blank alpha-sprites. + This saves a lot of rendering... + + default: + setInvisibleCharacters ( L" " ); + + - added MultiLine rendering + should avoid to us CStaticText breaking text in future + - CGUIListBox + - changed Scrollbar LargeStepSize to ItemHeight + which easy enables to scroll line by line + + - CGUIScrollBar + bug: + Create a Window and inside a listbox with a scrollbar or + a windowed irrlicht application + + Click & hold Scrollbar Slider. move outside it's region. + Release Mouse. Go Back to Scrollbar.. it's moving always... + + it's generally missing the event PRESSED_MOVED, which + leads to problem when an element is dragging, has a focus, or position loose + and gets focus back again. ( think of a drunken mouse sliding left&right during tracking ) + + so added the mouse Input Buttonstates on every mouse event + IrrDeviceWin32: + added event.MouseInput.ButtonStates = wParam & ( MK_LBUTTON | MK_RBUTTON | MK_MBUTTON ); + TODO: + Linux & SDL + + so now i can do this + case irr::EMIE_MOUSE_MOVED: + if ( !event.MouseInput.isLeftPressed () ) + { + Dragging = false; + } + + - bug: + Scrollbar notifyListBox notify when the scrollbar is clicked. + + - changed timed event in draw to OnPostRender + Why the hell is a gui element firing a timed event + in a draw routine!!!!!. This should be corrected for all gui-elements. + + + - added GUI Image List from Reinhard Ostermeier, modified to work + added GUI Tree View from Reinhard Ostermeier, modified to work + shown in the Quake3MapShader Example + TODO: Spritebanks + + + - FileOpenDialog + changed the static text for the filename to an edit box. + - changed the interface for addEditBox to match with addStaticText + - changed the interface for addSpinBox to match with addEditBox + - added MouseWheel to Spinbox + - changed CGUITable CLICK_AREA from 3 to 12 to enable clicking on the visible marker + - CGUISpritebank + removed some crashes with empty Sprite banks + - IGUIScrollBar + added SetMin before min was always 0 + changed ScrollWheel Direction on horizontal to move right on wheel up, left on wheel down + + - IComboBox + -added ItemData + - removed IsVisbile check in IGUIElement::draw + + +- Image Loaders + - added TGA file type 2 ( grayscale uncompressed ) + - added TGA file type (1) 8 Bit indexed color uncompressed + + ColorConverter: + - added convert_B8G8R8toA8R8G8B8 + - added convert_B8G8R8A8toA8R8G8B8 + +- Media Files + - added missing shaders and textures to map-20kdm2. + Taken from free implementation + - ball.wav. adjusted DC-Offset, amplified to -4dB, trim cross-zero + - impact.wav clip-restoration, trim cross-zero + - added gun.md2, gun.pcx to media-files + copyright issues!. i don't know from where this file came from... + i hope this is not from original quake2.. + - added new irrlicht logo irrlicht3.png + i've taken the new layout. i should ask niko to use it. + - added Skydome picture to media files (skydome2.jpg) half/sphere + +- OctTree + -added + #define OCTTREE_PARENTTEST ( default: disabled ) + used to leave-out children test if the parent passed a complete frustum. + plus: leaves out children test + minus: all edges have to be checked + - added MesBuffer Hardware Hint Vertex to octtree + +- CQuake3ShaderSceneNode: + - removed function releaseMesh + Shader doesn't copy the original mesh anymore ( saving memory ) + so therefore this (for others often misleading ) function was removed + - changed constructor to take a (shared) destination meshbuffer for rendering + reducing vertex-memory to a half + - don't copy the original vertices anymore + - added deformvertexes autosprite + - added deformvertexes move + - added support for RTCW and Raven BSPs ( qmap2 ) + - added polygonoffset (TODO: not perfect) + - added added nomipmaps + - added rgbgen const + - added alphagen + - added MesBuffer Hardware Hint Vertex/Index to Quake3: static geometry, dynamic indices + - added Quake3Explorer examples + - added wave noise + - added tcmod transform + - added whiteimage + - added collision to Quake3Explorer + - renamed SMD3QuaterionTag* to SMD3QuaternionTag* ( typo ) + - updated quake3:blendfunc + - added crouch to Quake3Explorer + (modifying the ellipsiodRadius of the camera animator ) + added crouch to CSceneNodeAnimatorCameraFPS + still problems with stand up and collision + - Quake3MapLoader + modified memory allocation for faster loading + - Quake3LoadParam + added Parameter to the Mesh-Loader + - added + The still existing missing caulking of curved surfaces. + using round in the coordinates doesn't solve the problem. + but for the demo bsp mesh it solves the problem... (luck) + so for now it's switchable. + TJUNCTION_SOLVER_ROUND + default:off + +- BurningVideo + - pushed BurningsVideo to 0.40 + - added blendfunc gl_one_minus_dst_alpha gl_one + - added blendfunc gl_dst_color gl_zero + - added blendfunc gl_dst_color src_alpha + - modified AlphaChannel_Ref renderer to support alpha test lessequal + - addded 32 Bit Index Buffer + - added sourceRect/destRect check to 2D-Blitter ( slower, but resolves crash ) + - added setTextureCreationFlag video::ETCF_ALLOW_NON_POWER_2 + Burning checks this flag and when set, it bypasses the power2 size check, + which is necessary on 3D but can be avoided on 2D. + used on fonts automatically. + - added Support for Destination Alpha + +- OpenGL + - Fixed a bug in COpenGLExtensenionHandler where a glint was downcasted to u8!!!!!! + MaxTextureSize=static_cast(num); + + - TODO: COpenGLMaterialRenderer_ONETEXTURE_BLEND to work as expected + +- Direct3D8 + - compile and links again + - added 32 Bit Index Buffer + - D3DSAMP_MIPMAPLODBIAS doesnt compile!. it is d3d9 i think. + - compile for XBOX +- Direc3D9 + - fixed crash on RTT Textures DepthBuffer freed twice. + added deleteAllTextures to destuctor +- NullDriver + - removeallTextures. added setMaterial ( SMaterial() ) to clean pointers for freed textures +------------------------------------------------------------------------------- + Changes in version 1.6 - New scene parameter B3D_LOADER_IGNORE_MIPMAP_FLAG to ignore the often missing mipmap flag in b3d files. If this parameter is true, the old pre Irrlicht-1.5 behavior is restored. diff --git a/examples/01.HelloWorld/main.cpp b/examples/01.HelloWorld/main.cpp index fddb223d..e669244b 100644 --- a/examples/01.HelloWorld/main.cpp +++ b/examples/01.HelloWorld/main.cpp @@ -171,7 +171,10 @@ int main() */ IAnimatedMesh* mesh = smgr->getMesh("../../media/sydney.md2"); if (!mesh) + { + device->drop(); return 1; + } IAnimatedMeshSceneNode* node = smgr->addAnimatedMeshSceneNode( mesh ); /* diff --git a/examples/04.Movement/main.cpp b/examples/04.Movement/main.cpp index bf6684c7..4bf9912d 100644 --- a/examples/04.Movement/main.cpp +++ b/examples/04.Movement/main.cpp @@ -191,7 +191,7 @@ int main() To be able to look at and move around in this scene, we create a first person shooter style camera and make the mouse cursor invisible. */ - smgr->addCameraSceneNodeFPS(0, 100.0f, .1f); + smgr->addCameraSceneNodeFPS(); device->getCursorControl()->setVisible(false); /* diff --git a/examples/08.SpecialFX/main.cpp b/examples/08.SpecialFX/main.cpp index 0a7d0d93..c6d48aa9 100644 --- a/examples/08.SpecialFX/main.cpp +++ b/examples/08.SpecialFX/main.cpp @@ -104,7 +104,7 @@ int main() want to. */ - mesh = smgr->addHillPlaneMesh("myHill", + mesh = smgr->addHillPlaneMesh( "myHill", core::dimension2d(20,20), core::dimension2d(40,40), 0, 0, core::dimension2d(0,0), diff --git a/examples/09.Meshviewer/main.cpp b/examples/09.Meshviewer/main.cpp index e1630d76..89831df4 100644 --- a/examples/09.Meshviewer/main.cpp +++ b/examples/09.Meshviewer/main.cpp @@ -133,18 +133,18 @@ void loadModel(const c8* fn) extension == ".bmp" || extension == ".wal") { video::ITexture * texture = - Device->getVideoDriver()->getTexture( filename.c_str() ); + Device->getVideoDriver()->getTexture( filename ); if ( texture && Model ) { // always reload texture Device->getVideoDriver()->removeTexture(texture); - texture = Device->getVideoDriver()->getTexture( filename.c_str() ); + texture = Device->getVideoDriver()->getTexture( filename ); Model->setMaterialTexture(0, texture); } return; } - // if a archive is loaded add it to the FileSystems.. + // if a archive is loaded add it to the FileArchive.. else if (extension == ".pk3" || extension == ".zip") { Device->getFileSystem()->addZipFileArchive(filename.c_str()); @@ -614,7 +614,7 @@ int main(int argc, char* argv[]) // read configuration from xml file - io::IXMLReader* xml = Device->getFileSystem()->createXMLReader("config.xml"); + io::IXMLReader* xml = Device->getFileSystem()->createXMLReader( L"config.xml"); while(xml && xml->read()) { diff --git a/examples/10.Shaders/main.cpp b/examples/10.Shaders/main.cpp index 6a3872c4..a487149f 100644 --- a/examples/10.Shaders/main.cpp +++ b/examples/10.Shaders/main.cpp @@ -171,8 +171,8 @@ int main() addShaderMaterial() instead of addShaderMaterialFromFiles(). */ - const c8* vsFileName = 0; // filename for the vertex shader - const c8* psFileName = 0; // filename for the pixel shader + core::string vsFileName; // filename for the vertex shader + core::string psFileName; // filename for the pixel shader switch(driverType) { @@ -225,7 +225,7 @@ int main() { device->getLogger()->log("WARNING: Pixel shaders disabled "\ "because of missing driver/hardware support."); - psFileName = 0; + psFileName = ""; } if (!driver->queryFeature(video::EVDF_VERTEX_SHADER_1_1) && @@ -233,7 +233,7 @@ int main() { device->getLogger()->log("WARNING: Vertex shaders disabled "\ "because of missing driver/hardware support."); - vsFileName = 0; + vsFileName = ""; } /* @@ -380,7 +380,7 @@ int main() // add a camera and disable the mouse cursor - scene::ICameraSceneNode* cam = smgr->addCameraSceneNodeFPS(0, 100.0f, .1f); + scene::ICameraSceneNode* cam = smgr->addCameraSceneNodeFPS(); cam->setPosition(core::vector3df(-100,50,100)); cam->setTarget(core::vector3df(0,0,0)); device->getCursorControl()->setVisible(false); diff --git a/examples/11.PerPixelLighting/main.cpp b/examples/11.PerPixelLighting/main.cpp index 69d7255f..b60eb833 100644 --- a/examples/11.PerPixelLighting/main.cpp +++ b/examples/11.PerPixelLighting/main.cpp @@ -207,8 +207,7 @@ int main() core::position2d(10,10)); // add camera - scene::ICameraSceneNode* camera = - smgr->addCameraSceneNodeFPS(0, 100.0f, .3f); + scene::ICameraSceneNode* camera = smgr->addCameraSceneNodeFPS(); camera->setPosition(core::vector3df(-200,200,-200)); // disable mouse cursor diff --git a/examples/15.LoadIrrFile/main.cpp b/examples/15.LoadIrrFile/main.cpp index 9de0c9fe..81ee8ef5 100644 --- a/examples/15.LoadIrrFile/main.cpp +++ b/examples/15.LoadIrrFile/main.cpp @@ -68,7 +68,7 @@ int main() */ // load the scene - smgr->loadScene("../../media/example.irr"); + smgr->loadScene( "../../media/example.irr"); /* Now we'll create a camera, and give it a collision response animator diff --git a/examples/16.Quake3MapShader/main.cpp b/examples/16.Quake3MapShader/main.cpp index 7fb77bbf..075091ef 100644 --- a/examples/16.Quake3MapShader/main.cpp +++ b/examples/16.Quake3MapShader/main.cpp @@ -191,6 +191,9 @@ int IRRCALLCONV main(int argc, char* argv[]) + // Quake3 Shader controls Z-Writing + smgr->getParameters()->setAttribute(scene::ALLOW_ZWRITE_ON_TRANSPARENT, true); + /* 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, @@ -251,7 +254,7 @@ int IRRCALLCONV main(int argc, char* argv[]) s32 shaderIndex = (s32) material.MaterialTypeParam2; // the meshbuffer can be rendered without additional support, or it has no shader - const quake3::SShader *shader = mesh->getShader ( shaderIndex ); + const quake3::IShader *shader = mesh->getShader ( shaderIndex ); if ( 0 == shader ) { continue; @@ -294,8 +297,6 @@ int IRRCALLCONV main(int argc, char* argv[]) } - // original mesh is not needed anymore - mesh->releaseMesh ( quake3::E_Q3_MESH_ITEMS ); } /* @@ -422,6 +423,12 @@ int IRRCALLCONV main(int argc, char* argv[]) str += calls; str += "/"; str += culled; + str += " Draw: "; + str += attr->getAttributeAsInt ( "drawn_solid" ); + str += "/"; + str += attr->getAttributeAsInt ( "drawn_transparent" ); + str += "/"; + str += attr->getAttributeAsInt ( "drawn_transparent_effect" ); device->setWindowCaption(str.c_str()); lastFPS = fps; diff --git a/examples/17.HelloWorld_Mobile/HelloWorld_mobile.sln b/examples/17.HelloWorld_Mobile/HelloWorld_mobile.sln index becce35f..31932b79 100644 --- a/examples/17.HelloWorld_Mobile/HelloWorld_mobile.sln +++ b/examples/17.HelloWorld_Mobile/HelloWorld_mobile.sln @@ -2,6 +2,9 @@ Microsoft Visual Studio Solution File, Format Version 9.00 # Visual Studio 2005 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "17.HelloWorld_mobile", "HelloWorld_mobile.vcproj", "{AD95D5D7-91D2-4030-B28D-23A6FE5C0359}" + ProjectSection(ProjectDependencies) = postProject + {E08E042A-6C45-411B-92BE-3CC31331019F} = {E08E042A-6C45-411B-92BE-3CC31331019F} + EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Irrlicht", "..\..\source\Irrlicht\Irrlicht_mobile6.vcproj", "{E08E042A-6C45-411B-92BE-3CC31331019F}" EndProject diff --git a/examples/17.HelloWorld_Mobile/HelloWorld_mobile.vcproj b/examples/17.HelloWorld_Mobile/HelloWorld_mobile.vcproj index cf4a025f..dcaca9ef 100644 --- a/examples/17.HelloWorld_Mobile/HelloWorld_mobile.vcproj +++ b/examples/17.HelloWorld_Mobile/HelloWorld_mobile.vcproj @@ -94,7 +94,7 @@ ForceDirty="-1" RemoteDirectory="%CSIDL_PROGRAM_FILES%\irrlicht\bin\wince-visualstudio" RegisterOutput="0" - AdditionalFiles="sydney.md2|$(InputDir)..\..\media|%CSIDL_PROGRAM_FILES%\irrlicht\media|0;sydney.bmp|$(InputDir)..\..\media|%CSIDL_PROGRAM_FILES%\irrlicht\media|0;irrlicht.dll|$(InputDir)$(OutDir)|%CSIDL_PROGRAM_FILES%\irrlicht\bin\wince-visualstudio|0" + AdditionalFiles="sydney.md2|$(InputDir)..\..\media|%CSIDL_PROGRAM_FILES%\irrlicht\media|0;sydney.bmp|$(InputDir)..\..\media|%CSIDL_PROGRAM_FILES%\irrlicht\media|0;ninja.b3d|$(InputDir)..\..\media|%CSIDL_PROGRAM_FILES%\irrlicht\media|0;nskinbl.jpg|$(InputDir)..\..\media|%CSIDL_PROGRAM_FILES%\irrlicht\media|0;irrlichtlogo3.png|$(InputDir)..\..\media|%CSIDL_PROGRAM_FILES%\irrlicht\media|0;terrain-heightmap.bmp|$(InputDir)..\..\media|%CSIDL_PROGRAM_FILES%\irrlicht\media|0;terrain-texture.jpg|$(InputDir)..\..\media|%CSIDL_PROGRAM_FILES%\irrlicht\media|0;detailmap3.jpg|$(InputDir)..\..\media|%CSIDL_PROGRAM_FILES%\irrlicht\media|0;irrlicht2_up.jpg|$(InputDir)..\..\media|%CSIDL_PROGRAM_FILES%\irrlicht\media|0;irrlicht2_dn.jpg|$(InputDir)..\..\media|%CSIDL_PROGRAM_FILES%\irrlicht\media|0;irrlicht2_lf.jpg|$(InputDir)..\..\media|%CSIDL_PROGRAM_FILES%\irrlicht\media|0;irrlicht2_rt.jpg|$(InputDir)..\..\media|%CSIDL_PROGRAM_FILES%\irrlicht\media|0;irrlicht2_ft.jpg|$(InputDir)..\..\media|%CSIDL_PROGRAM_FILES%\irrlicht\media|0;irrlicht2_bk.jpg|$(InputDir)..\..\media|%CSIDL_PROGRAM_FILES%\irrlicht\media|0;skydome.jpg|$(InputDir)..\..\media|%CSIDL_PROGRAM_FILES%\irrlicht\media|0;irrlicht.dll|$(InputDir)$(OutDir)|%CSIDL_PROGRAM_FILES%\irrlicht\bin\wince-visualstudio|0" /> @@ -130,7 +130,7 @@ RuntimeLibrary="0" UsePrecompiledHeader="0" WarningLevel="3" - DebugInformationFormat="3" + DebugInformationFormat="0" EnableFloatingPointEmulation="true" /> diff --git a/examples/17.HelloWorld_Mobile/main.cpp b/examples/17.HelloWorld_Mobile/main.cpp index e781f700..782ce79b 100644 --- a/examples/17.HelloWorld_Mobile/main.cpp +++ b/examples/17.HelloWorld_Mobile/main.cpp @@ -1,12 +1,14 @@ /** Example 017 Helloworld mobile - -This example show Hello World for Windows mobile + This example show Hello World for Windows mobile. + It compiles on other platform too. The only differences between the original + examples are. You need a GUI, because otherwise you can't quit the application. + You need a Filesystem, which is relative based to your executable. */ #include -#ifdef _IRR_USE_WINDOWS_CE_DEVICE_ -#include +#if defined ( _IRR_WINDOWS_ ) + #include #endif using namespace irr; @@ -18,12 +20,12 @@ using namespace gui; #pragma comment(lib, "Irrlicht.lib") -class MyEventReceiver : public IEventReceiver +class EventReceiver_basic : public IEventReceiver { private: IrrlichtDevice *Device; public: - MyEventReceiver ( IrrlichtDevice *device ): Device ( device ) {} + EventReceiver_basic ( IrrlichtDevice *device ): Device ( device ) {} virtual bool OnEvent(const SEvent& event) { @@ -101,49 +103,98 @@ public: } }; - -#if defined(_WIN32_WCE) -int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, - int nCmdShow ) -#else -int main() -#endif +/*! + Startup a Windows Mobile Device +*/ +IrrlichtDevice *startup() { - E_DRIVER_TYPE driverType = EDT_BURNINGSVIDEO; + // both software and burnings video can be used + E_DRIVER_TYPE driverType = EDT_SOFTWARE; // EDT_BURNINGSVIDEO; // create device + IrrlichtDevice *device = 0; - IrrlichtDevice *device = - createDevice(driverType, dimension2d(240, 320), 16, true ); - - if (device == 0) - return 1; // could not create selected driver. - - // create engine and camera - MyEventReceiver receiver(device); - device->setEventReceiver(&receiver); - device->setWindowCaption(L"Irrlicht CE Demo"); +#if defined (_IRR_USE_WINDOWS_CE_DEVICE_) + // set to standard mobile fullscreen 240x320 + device = createDevice(driverType, dimension2d(240, 320), 16, true ); +#else + // on PC. use window mode + device = createDevice(driverType, dimension2d(240, 320), 16, false ); +#endif + if ( 0 == device ) + return 0; IVideoDriver* driver = device->getVideoDriver(); ISceneManager* smgr = device->getSceneManager(); IGUIEnvironment* guienv = device->getGUIEnvironment(); // set the filesystem relative to the executable +#if defined (_IRR_WINDOWS_) { wchar_t buf[255]; GetModuleFileNameW ( 0, buf, 255 ); - stringc base = buf; - base = base.subString ( 0, base.findLast ( '\\' ) ); - device->getFileSystem()->addFolderFileArchive ( base.c_str() ); + string base = buf; + base = base.subString ( 0, base.findLast ( '\\' ) + 1 ); + device->getFileSystem()->registerFileArchive ( base ); + } +#endif + + IGUIStaticText *text = guienv->addStaticText(L"FPS: 25", + rect(140,15,200,30), false, false, 0, 100 ); + + guienv->addButton(core::rect(200,10,238,30), 0, 2, L"Quit"); + + // add irrlicht logo + guienv->addImage(driver->getTexture("../../media/irrlichtlogo3.png"), + core::position2d(0,-2)); + return device; +} + +/*! +*/ +int run ( IrrlichtDevice *device ) +{ + while(device->run()) + if (device->isWindowActive()) + { + device->getVideoDriver()->beginScene(true, true, SColor(0,100,100,100)); + device->getSceneManager()->drawAll(); + device->getGUIEnvironment()->drawAll(); + device->getVideoDriver()->endScene (); + + IGUIElement *stat = device->getGUIEnvironment()-> + getRootGUIElement()->getElementFromId ( 100 ); + if ( stat ) + { + stringw str = L"FPS: "; + str += (s32)device->getVideoDriver()->getFPS(); + + stat->setText ( str.c_str() ); + } } + device->drop(); + return 0; +} - IGUIStaticText *text = - guienv->addStaticText(L"FPS: 25", - rect(60,5,200,20), false ); +/*! +*/ +int example_customscenenode() +{ + // create device + IrrlichtDevice *device = startup(); + if (device == 0) + return 1; // could not create selected driver. + + // create engine and camera + EventReceiver_basic receiver(device); + device->setEventReceiver(&receiver); + + IVideoDriver* driver = device->getVideoDriver(); + ISceneManager* smgr = device->getSceneManager(); + IGUIEnvironment* guienv = device->getGUIEnvironment(); - guienv->addButton(core::rect(10,5,50,20), 0, 2, L"Quit"); smgr->addCameraSceneNode(0, vector3df(0,-40,0), vector3df(0,0,0)); @@ -163,27 +214,289 @@ int main() myNode->drop(); myNode = 0; // As I shouldn't refer to it again, ensure that I can't - u32 frames=0; - while(device->run()) + return run ( device ); +} + +class EventReceiver_terrain : public IEventReceiver +{ +public: + + EventReceiver_terrain(IrrlichtDevice *device, scene::ISceneNode* terrain, scene::ISceneNode* skybox, scene::ISceneNode* skydome) : + Device ( device ), Terrain(terrain), Skybox(skybox), Skydome(skydome), showBox(true) { - driver->beginScene(true, true, SColor(0,100,100,100)); - smgr->drawAll(); - guienv->drawAll(); - driver->endScene(); - - if (++frames==10) - { - stringw str = L"FPS: "; - str += (s32)driver->getFPS(); - - text->setText ( str.c_str() ); - frames=0; - } + Skybox->setVisible(true); + Skydome->setVisible(false); } - device->drop(); + bool OnEvent(const SEvent& event) + { + if (event.EventType == EET_GUI_EVENT) + { + s32 id = event.GUIEvent.Caller->getID(); + + switch(event.GUIEvent.EventType) + { + case EGET_BUTTON_CLICKED: + if (id == 2) + { + Device->closeDevice(); + return true; + } break; + } + } + + // check if user presses the key 'W' or 'D' + if (event.EventType == irr::EET_KEY_INPUT_EVENT && !event.KeyInput.PressedDown) + { + switch (event.KeyInput.Key) + { + case irr::KEY_KEY_W: // switch wire frame mode + Terrain->setMaterialFlag(video::EMF_WIREFRAME, + !Terrain->getMaterial(0).Wireframe); + Terrain->setMaterialFlag(video::EMF_POINTCLOUD, false); + return true; + case irr::KEY_KEY_P: // switch wire frame mode + Terrain->setMaterialFlag(video::EMF_POINTCLOUD, + !Terrain->getMaterial(0).PointCloud); + Terrain->setMaterialFlag(video::EMF_WIREFRAME, false); + return true; + case irr::KEY_KEY_D: // toggle detail map + Terrain->setMaterialType( + Terrain->getMaterial(0).MaterialType == video::EMT_SOLID ? + video::EMT_DETAIL_MAP : video::EMT_SOLID); + return true; + case irr::KEY_KEY_S: // toggle skies + showBox=!showBox; + Skybox->setVisible(showBox); + Skydome->setVisible(!showBox); + return true; + default: + break; + } + } + + return false; + } + +private: + IrrlichtDevice *Device; + scene::ISceneNode* Terrain; + scene::ISceneNode* Skybox; + scene::ISceneNode* Skydome; + bool showBox; +}; + + +/* +The start of the main function starts like in most other example. We ask the user +for the desired renderer and start it up. This time with the advanced parameter handling. +*/ +int example_terrain() +{ + // create device + IrrlichtDevice *device = startup(); + if (device == 0) + return 1; // could not create selected driver. - return 0; + /* + First, we add standard stuff to the scene: A nice irrlicht engine + logo, a small help text, a user controlled camera, and we disable + the mouse cursor. + */ + + video::IVideoDriver* driver = device->getVideoDriver(); + scene::ISceneManager* smgr = device->getSceneManager(); + gui::IGUIEnvironment* env = device->getGUIEnvironment(); + + + //set other font + //env->getSkin()->setFont(env->getFont("../../media/fontlucida.png")); + + // add some help text + env->addStaticText( + L"Press 'W' to change wireframe mode\nPress 'D' to toggle detail map\nPress 'S' to toggle skybox/skydome", + core::rect(5,250,235,320), true, true, 0, -1, true); + + // add camera + scene::ICameraSceneNode* camera = + smgr->addCameraSceneNodeFPS(0,100.0f,1.2f); + + camera->setPosition(core::vector3df(2700*2,255*2,2600*2)); + camera->setTarget(core::vector3df(2397*2,343*2,2700*2)); + camera->setFarValue(42000.0f); + + // disable mouse cursor + device->getCursorControl()->setVisible(false); + + /* + Here comes the terrain renderer scene node: We add it just like any + other scene node to the scene using + ISceneManager::addTerrainSceneNode(). The only parameter we use is a + file name to the heightmap we use. A heightmap is simply a gray scale + texture. The terrain renderer loads it and creates the 3D terrain from + it. + + To make the terrain look more big, we change the scale factor of + it to (40, 4.4, 40). Because we don't have any dynamic lights in the + scene, we switch off the lighting, and we set the file + terrain-texture.jpg as texture for the terrain and detailmap3.jpg as + second texture, called detail map. At last, we set the scale values for + the texture: The first texture will be repeated only one time over the + whole terrain, and the second one (detail map) 20 times. + */ + + // add terrain scene node + scene::ITerrainSceneNode* terrain = smgr->addTerrainSceneNode( + "../../media/terrain-heightmap.bmp", + 0, // parent node + -1, // node id + core::vector3df(0.f, 0.f, 0.f), // position + core::vector3df(0.f, 0.f, 0.f), // rotation + core::vector3df(40.f, 4.4f, 40.f), // scale + video::SColor ( 255, 255, 255, 255 ), // vertexColor + 5, // maxLOD + scene::ETPS_17, // patchSize + 4 // smoothFactor + ); + + if ( terrain ) + { + terrain->setMaterialFlag(video::EMF_LIGHTING, false); + + terrain->setMaterialTexture(0, + driver->getTexture("../../media/terrain-texture.jpg")); + terrain->setMaterialTexture(1, + driver->getTexture("../../media/detailmap3.jpg")); + + terrain->setMaterialType(video::EMT_DETAIL_MAP); + + terrain->scaleTexture(1.0f, 20.0f); + //terrain->setDebugDataVisible ( true ); + + /* + To be able to do collision with the terrain, we create a triangle selector. + If you want to know what triangle selectors do, just take a look into the + collision tutorial. The terrain triangle selector works together with the + terrain. To demonstrate this, we create a collision response animator + and attach it to the camera, so that the camera will not be able to fly + through the terrain. + */ + + // create triangle selector for the terrain + scene::ITriangleSelector* selector + = smgr->createTerrainTriangleSelector(terrain, 0); + terrain->setTriangleSelector(selector); + + // create collision response animator and attach it to the camera + scene::ISceneNodeAnimator* anim = smgr->createCollisionResponseAnimator( + selector, camera, core::vector3df(60,100,60), + core::vector3df(0,0,0), + core::vector3df(0,50,0)); + selector->drop(); + camera->addAnimator(anim); + anim->drop(); + + /* If you need access to the terrain data you can also do this directly via the following code fragment. + */ + scene::CDynamicMeshBuffer* buffer = new scene::CDynamicMeshBuffer(video::EVT_2TCOORDS, video::EIT_16BIT); + terrain->getMeshBufferForLOD(*buffer, 0); + video::S3DVertex2TCoords* data = (video::S3DVertex2TCoords*)buffer->getVertexBuffer().getData(); + // Work on data or get the IndexBuffer with a similar call. + buffer->drop(); // When done drop the buffer again. + } + + /* + To make the user be able to switch between normal and wireframe mode, + we create an instance of the event reciever from above and let Irrlicht + know about it. In addition, we add the skybox which we already used in + lots of Irrlicht examples and a skydome, which is shown mutually + exclusive with the skybox by pressing 'S'. + */ + + // create skybox and skydome + driver->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, false); + + scene::ISceneNode* skybox=smgr->addSkyBoxSceneNode( + driver->getTexture("../../media/irrlicht2_up.jpg"), + driver->getTexture("../../media/irrlicht2_dn.jpg"), + driver->getTexture("../../media/irrlicht2_lf.jpg"), + driver->getTexture("../../media/irrlicht2_rt.jpg"), + driver->getTexture("../../media/irrlicht2_ft.jpg"), + driver->getTexture("../../media/irrlicht2_bk.jpg")); + scene::ISceneNode* skydome=smgr->addSkyDomeSceneNode(driver->getTexture("../../media/skydome.jpg"),16,8,0.95f,2.0f); + + driver->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, true); + + // create event receiver + EventReceiver_terrain receiver( device, terrain, skybox, skydome); + device->setEventReceiver(&receiver); + + return run ( device ); +} + +/* +*/ +int example_helloworld() +{ + // create device + IrrlichtDevice *device = startup(); + if (device == 0) + return 1; // could not create selected driver. + + IVideoDriver* driver = device->getVideoDriver(); + ISceneManager* smgr = device->getSceneManager(); + IGUIEnvironment* guienv = device->getGUIEnvironment(); + + IAnimatedMesh* mesh = smgr->getMesh("../../media/sydney.md2"); + if (!mesh) + { + device->drop(); + return 1; + } + IAnimatedMeshSceneNode* node = smgr->addAnimatedMeshSceneNode( mesh ); + + /* + To let the mesh look a little bit nicer, we change its material. We + disable lighting because we do not have a dynamic light in here, and + the mesh would be totally black otherwise. Then we set the frame loop, + such that the predefined STAND animation is used. And last, we apply a + texture to the mesh. Without it the mesh would be drawn using only a + color. + */ + if (node) + { + node->setMaterialFlag(EMF_LIGHTING, false); + node->setMD2Animation(scene::EMAT_STAND); + node->setMaterialTexture( 0, driver->getTexture("../../media/sydney.bmp") ); + } + + /* + To look at the mesh, we place a camera into 3d space at the position + (0, 30, -40). The camera looks from there to (0,5,0), which is + approximately the place where our md2 model is. + */ + smgr->addCameraSceneNode(0, vector3df(0,30,-40), vector3df(0,5,0)); + + EventReceiver_basic receiver(device); + device->setEventReceiver(&receiver); + + return run ( device ); + +} + +#if defined (_IRR_USE_WINDOWS_CE_DEVICE_) + #pragma comment(linker, "/subsystem:WINDOWSCE /ENTRY:main") +#elif defined (_IRR_WINDOWS_) + #pragma comment(linker, "/subsystem:windows /ENTRY:mainCRTStartup") +#endif + +/* +*/ +int main() +{ + example_helloworld (); + example_customscenenode(); + //example_terrain(); } /* diff --git a/examples/19.MouseAndJoystick/main.cpp b/examples/19.MouseAndJoystick/main.cpp index 03adf3b5..b8a05413 100644 --- a/examples/19.MouseAndJoystick/main.cpp +++ b/examples/19.MouseAndJoystick/main.cpp @@ -182,7 +182,15 @@ int main() /* We'll create an arrow mesh and move it around either with the joystick axis/hat, or make it follow the mouse pointer. */ - scene::ISceneNode * node = smgr->addMeshSceneNode(smgr->addArrowMesh("Arrow", video::SColor(255, 255, 0, 0), video::SColor(255, 0, 255, 0))); + scene::ISceneNode * node = smgr->addMeshSceneNode( + smgr->addArrowMesh( "Arrow", + video::SColor(255, 255, 0, 0), + video::SColor(255, 0, 255, 0), + 16,16, + 2.f, 1.3f, + 0.1f, 0.6f + ) + ); node->setMaterialFlag(video::EMF_LIGHTING, false); scene::ICameraSceneNode * camera = smgr->addCameraSceneNode(); diff --git a/examples/20.ManagedLights/ManagedLights_vc8.vcproj b/examples/20.ManagedLights/ManagedLights_vc8.vcproj index 57dfcf46..2f37f63f 100644 --- a/examples/20.ManagedLights/ManagedLights_vc8.vcproj +++ b/examples/20.ManagedLights/ManagedLights_vc8.vcproj @@ -1,7 +1,7 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/21.Quake3Explorer/Quake3Explorer_vc7.vcproj b/examples/21.Quake3Explorer/Quake3Explorer_vc7.vcproj new file mode 100644 index 00000000..12a7b656 --- /dev/null +++ b/examples/21.Quake3Explorer/Quake3Explorer_vc7.vcproj @@ -0,0 +1,132 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/21.Quake3Explorer/Quake3Explorer_vc8.vcproj b/examples/21.Quake3Explorer/Quake3Explorer_vc8.vcproj new file mode 100644 index 00000000..90450273 --- /dev/null +++ b/examples/21.Quake3Explorer/Quake3Explorer_vc8.vcproj @@ -0,0 +1,210 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/21.Quake3Explorer/Quake3Explorer_vc9.vcproj b/examples/21.Quake3Explorer/Quake3Explorer_vc9.vcproj new file mode 100644 index 00000000..27046a43 --- /dev/null +++ b/examples/21.Quake3Explorer/Quake3Explorer_vc9.vcproj @@ -0,0 +1,188 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/21.Quake3Explorer/example.dev b/examples/21.Quake3Explorer/example.dev new file mode 100644 index 00000000..14ebb420 --- /dev/null +++ b/examples/21.Quake3Explorer/example.dev @@ -0,0 +1,59 @@ +[Project] +FileName=example.dev +Name=Irrlicht Example 16 Quake3 Map Shader +UnitCount=1 +Type=1 +Ver=1 +ObjFiles= +Includes=..\..\include +Libs= +PrivateResource= +ResourceIncludes= +MakeIncludes= +Compiler= +CppCompiler= +Linker=../../lib/Win32-gcc/libIrrlicht.a_@@_ +IsCpp=1 +Icon= +ExeOutput=../../bin/Win32-gcc +ObjectOutput=obj +OverrideOutput=1 +OverrideOutputName=16.Quake3MapShader.exe +HostApplication= +Folders= +CommandLine= +IncludeVersionInfo=0 +SupportXPThemes=0 +CompilerSet=0 +CompilerSettings=0000000000000000000000 +UseCustomMakefile=0 +CustomMakefile= + +[Unit1] +FileName=main.cpp +CompileCpp=1 +Folder=Projekt1 +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[VersionInfo] +Major=0 +Minor=1 +Release=1 +Build=1 +LanguageID=1033 +CharsetID=1252 +CompanyName= +FileVersion= +FileDescription=Irrlicht Engine example compiled using DevCpp and gcc +InternalName= +LegalCopyright= +LegalTrademarks= +OriginalFilename= +ProductName= +ProductVersion= +AutoIncBuildNr=0 + diff --git a/examples/21.Quake3Explorer/main.cpp b/examples/21.Quake3Explorer/main.cpp new file mode 100644 index 00000000..b1a49c55 --- /dev/null +++ b/examples/21.Quake3Explorer/main.cpp @@ -0,0 +1,1932 @@ +/** Example 021 Quake3 Explorer + +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 + - 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 Collison Respsone + - Play music + +You can download the Quake III Arena demo ( copyright id software ) +at the following location: +ftp://ftp.idsoftware.com/idstuff/quake3/win32/q3ademo.exe + +Copyright 2006-2009 Burningwater, Thomas Alten +*/ + +#include "q3factory.h" +#include "sound.h" +#include + +/*! + Game Data is used to hold Data which is needed to drive the game +*/ +struct GameData +{ + GameData ( const string &startupDir) + { + retVal = 0; + createExDevice = 0; + Device = 0; + StartupDir = startupDir; + setDefault (); + } + + void setDefault () + { + debugState = EDS_OFF; + gravityState = 1; + flyTroughState = 0; + wireFrame = 0; + guiActive = 1; + guiInputActive = 0; + GammaValue = 1.f; + + // default deviceParam; + deviceParam.DriverType = EDT_DIRECT3D9; + deviceParam.WindowSize.Width = 800; + deviceParam.WindowSize.Height = 600; + deviceParam.Fullscreen = false; + deviceParam.Bits = 32; + deviceParam.ZBufferBits = 32; + deviceParam.Vsync = false; + deviceParam.AntiAlias = false; + + // default Quake3 loadParam + loadParam.defaultLightMapMaterial = EMT_LIGHTMAP; + loadParam.defaultModulate = EMFN_MODULATE_1X; + loadParam.verbose = 1; + loadParam.mergeShaderBuffer = 1; + 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.alpharef = 1; + + sound = 0; + + CurrentMapName = ""; + CurrentArchiveList.clear (); + CurrentArchiveList.push_back ( StartupDir + "../../media/" ); + CurrentArchiveList.push_back ( StartupDir + "../../media/map-20kdm2.pk3" ); + } + + s32 debugState; + s32 gravityState; + s32 flyTroughState; + s32 wireFrame; + s32 guiActive; + s32 guiInputActive; + f32 GammaValue; + s32 retVal; + s32 sound; + + core::string StartupDir; + stringw CurrentMapName; + array < core::string > CurrentArchiveList; + + Q3LevelLoadParameter loadParam; + SIrrlichtCreationParameters deviceParam; + funcptr_createDeviceEx createExDevice; + IrrlichtDevice *Device; +}; + + +/*! + Representing a player +*/ +struct Q3Player : public IAnimationEndCallBack +{ + Q3Player () + : WeaponNode ( 0 ), StartPositionCurrent ( 0 ), Mesh ( 0 ), Device ( 0 ) + { + animation[0] = 0; + } + + void create ( IrrlichtDevice *device, + IQ3LevelMesh* mesh, + ISceneNode *mapNode, + IMetaTriangleSelector *meta + ); + void shutdown (); + void setAnim ( const c8 *name ); + void respawn (); + virtual void OnAnimationEnd(IAnimatedMeshSceneNode* node); + + ISceneNodeAnimatorCollisionResponse * cam() { return camCollisionResponse ( Device ); } + + IrrlichtDevice *Device; + ISceneNode* MapParent; + IQ3LevelMesh* Mesh; + IAnimatedMeshSceneNode* WeaponNode; + c8 animation[64]; + s32 StartPositionCurrent; + c8 buf[64]; + + TimeFire Anim[4]; + +}; + + +/*! +*/ +void Q3Player::shutdown () +{ + setAnim ( 0 ); + + dropElement (WeaponNode); + + if ( Device ) + { + ICameraSceneNode* camera = Device->getSceneManager()->getActiveCamera(); + dropElement ( camera ); + Device = 0; + } + + MapParent = 0; + Mesh = 0; +} + + +/*! +*/ +void Q3Player::create ( IrrlichtDevice *device, IQ3LevelMesh* mesh, ISceneNode *mapNode, IMetaTriangleSelector *meta ) +{ + setTimeFire ( Anim + 0, 200, FIRED ); + setTimeFire ( Anim + 1, 5000 ); + + // load FPS weapon to Camera + Device = device; + Mesh = mesh; + MapParent = mapNode; + + ISceneManager *smgr = device->getSceneManager (); + IVideoDriver * driver = device->getVideoDriver(); + + ICameraSceneNode* camera = 0; + + SKeyMap keyMap[10]; + keyMap[0].Action = EKA_MOVE_FORWARD; + keyMap[0].KeyCode = KEY_UP; + keyMap[1].Action = EKA_MOVE_FORWARD; + keyMap[1].KeyCode = KEY_KEY_W; + + keyMap[2].Action = EKA_MOVE_BACKWARD; + keyMap[2].KeyCode = KEY_DOWN; + keyMap[3].Action = EKA_MOVE_BACKWARD; + keyMap[3].KeyCode = KEY_KEY_S; + + keyMap[4].Action = EKA_STRAFE_LEFT; + keyMap[4].KeyCode = KEY_LEFT; + keyMap[5].Action = EKA_STRAFE_LEFT; + keyMap[5].KeyCode = KEY_KEY_A; + + keyMap[6].Action = EKA_STRAFE_RIGHT; + keyMap[6].KeyCode = KEY_RIGHT; + keyMap[7].Action = EKA_STRAFE_RIGHT; + keyMap[7].KeyCode = KEY_KEY_D; + + keyMap[8].Action = EKA_JUMP_UP; + keyMap[8].KeyCode = KEY_KEY_J; + + keyMap[9].Action = EKA_CROUCH; + keyMap[9].KeyCode = KEY_KEY_C; + + camera = smgr->addCameraSceneNodeFPS(0, 100.0f, 0.6f, -1, keyMap, 10, false, 0.6f); + camera->setName ( "First Person Camera" ); + //camera->setFOV ( 100.f * core::DEGTORAD ); + camera->setFarValue( 20000.f ); + + IAnimatedMeshMD2* weaponMesh = (IAnimatedMeshMD2*) smgr->getMesh("gun.md2"); + if ( 0 == weaponMesh ) + return; + + if ( weaponMesh->getMeshType() == EAMT_MD2 ) + { + s32 count = weaponMesh->getAnimationCount(); + for ( s32 i = 0; i != count; ++i ) + { + snprintf ( buf, 64, "Animation: %s", weaponMesh->getAnimationName(i) ); + device->getLogger()->log(buf, ELL_INFORMATION); + } + } + + WeaponNode = smgr->addAnimatedMeshSceneNode( + weaponMesh, + smgr->getActiveCamera(), + 10, + vector3df( 0, 0, 0), + vector3df(-90,-90,90) + ); + WeaponNode->setMaterialFlag(EMF_LIGHTING, false); + WeaponNode->setMaterialTexture(0, driver->getTexture( "gun.jpg")); + WeaponNode->setLoopMode ( false ); + WeaponNode->setName ( "tommi the gun man" ); + + //create a collision auto response animator + ISceneNodeAnimator* anim = + smgr->createCollisionResponseAnimator( meta, camera, + vector3df(30,45,30), + getGravity ( "earth" ), + vector3df(0,40,0), + 0.0005f + ); + + camera->addAnimator( anim ); + anim->drop(); + + if ( meta ) + { + meta->drop (); + } + + respawn (); + setAnim ( "idle" ); +} + + +/*! + 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 () +{ + ICameraSceneNode* camera = Device->getSceneManager()->getActiveCamera(); + + Device->getLogger()->log( "respawn" ); + + if ( StartPositionCurrent >= Q3StartPosition ( + Mesh, camera,StartPositionCurrent++, + cam ()->getEllipsoidTranslation() ) + ) + { + StartPositionCurrent = 0; + } +} + + +/*! +*/ +void Q3Player::setAnim ( const c8 *name ) +{ + if ( name ) + { + snprintf ( animation, 64, "%s", name ); + if ( WeaponNode ) + { + WeaponNode->setAnimationEndCallback ( this ); + WeaponNode->setMD2Animation ( animation ); + } + } + else + { + animation[0] = 0; + if ( WeaponNode ) + { + WeaponNode->setAnimationEndCallback ( 0 ); + } + } +} + + +/*! +*/ +void Q3Player::OnAnimationEnd(IAnimatedMeshSceneNode* node) +{ + setAnim ( 0 ); +} + + + +//! GUIElements +struct GUI +{ + GUI () + { + Window = 0; + SetVideoMode = 0; + Bit32 = 0; + MultiSample = 0; + FullScreen = 0; + VideoMode = 0; + VideoDriver = 0; + StatusLine = 0; + SceneTree = 0; + Tesselation = 0; + Gamma = 0; + Collision = 0; + Visible_Map = 0; + Visible_Shader = 0; + Visible_Fog = 0; + Visible_Unresolved = 0; + Respawn = 0; + MapList = 0; + Logo = 0; + ArchiveList = 0; + ArchiveAdd = 0; + ArchiveRemove = 0; + ArchiveFileOpen = 0; + } + + void drop() + { + dropElement ( Window ); + dropElement ( Logo ); + } + + IGUIComboBox* VideoDriver; + IGUIComboBox* VideoMode; + IGUICheckBox* FullScreen; + IGUICheckBox* Bit32; + IGUIScrollBar* MultiSample; + IGUIButton *SetVideoMode; + + IGUIScrollBar* Tesselation; + IGUIScrollBar* Gamma; + IGUICheckBox* Collision; + IGUICheckBox * Visible_Map; + IGUICheckBox * Visible_Shader; + IGUICheckBox * Visible_Fog; + IGUICheckBox * Visible_Unresolved; + IGUIButton * Respawn; + + IGUITable* ArchiveList; + IGUIButton* ArchiveAdd; + IGUIButton* ArchiveRemove; + IGUIFileOpenDialog* ArchiveFileOpen; + + IGUIListBox *MapList; + IGUITreeView* SceneTree; + IGUIStaticText* StatusLine; + IGUIImage * Logo; + IGUIWindow * Window; + +}; + + +/*! + CQuake3EventHandler controls the game +*/ +class CQuake3EventHandler : public IEventReceiver +{ +public: + + CQuake3EventHandler( GameData *gameData ); + virtual ~CQuake3EventHandler (); + + void Animate(); + void Render(); + + void AddArchive ( const core::string& archiveName ); + void LoadMap ( const stringw& mapName, s32 collision ); + void CreatePlayers(); + void AddSky( u32 dome, const c8 *texture ); + + void CreateGUI(); + void SetGUIActive( s32 command); + + bool OnEvent(const SEvent& eve); + + +private: + + GameData *Game; + + IQ3LevelMesh* Mesh; + ISceneNode* MapParent; + ISceneNode* ShaderParent; + ISceneNode* ItemParent; + ISceneNode* UnresolvedParent; + ISceneNode* BulletParent; + ISceneNode* FogParent; + ISceneNode * SkyNode; + IMetaTriangleSelector *Meta; + + c8 buf[256]; + + Q3Player Player[2]; + + + struct SParticleImpact + { + u32 when; + vector3df pos; + vector3df outVector; + }; + array Impacts; + void useItem( Q3Player * player); + void createParticleImpacts( u32 now ); + + void createTextures (); + void addSceneTreeItem( ISceneNode * parent, IGUITreeViewNode* nodeParent); + + GUI gui; + void dropMap (); +}; + +/*! +*/ +CQuake3EventHandler::CQuake3EventHandler( GameData *game ) +: Game ( game ) +{ + MapParent = 0; + ShaderParent = 0; + ItemParent = 0; + UnresolvedParent = 0; + FogParent = 0; + BulletParent = 0; + Meta = 0; + Mesh = 0; + SkyNode = 0; + + + //! 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 + game->Device->getSceneManager()->getParameters()->setAttribute(scene::ALLOW_ZWRITE_ON_TRANSPARENT, true); + + // create internal textures + createTextures (); + + sound_init ( game->Device ); + + Game->Device->setEventReceiver ( this ); +} + + +CQuake3EventHandler::~CQuake3EventHandler () +{ + Player[0].shutdown (); + sound_shutdown (); + + Game->Device->drop(); +} + + +//! create runtime textures smog, fog +void CQuake3EventHandler::createTextures () +{ + IVideoDriver * driver = Game->Device->getVideoDriver(); + + dimension2du dim ( 64, 64 ); + + video::ITexture* texture; + video::IImage* image; + u32 i; + s32 x; + s32 y; + u32 * data; + for ( i = 0; i != 8; ++i ) + { + image = driver->createImage ( video::ECF_A8R8G8B8, dim); + data = (u32*) image->lock (); + for ( y = 0; y != dim.Height; ++y ) + { + for ( x = 0; x != dim.Width; ++x ) + { + data [x] = 0xFFFFFFFF; + } + data = (u32*) ( (u8*) data + image->getPitch() ); + } + image->unlock(); + snprintf ( buf, 64, "smoke_%02d", i ); + texture = driver->addTexture( buf, image ); + image->drop (); + } + + // fog + for ( i = 0; i != 1; ++i ) + { + image = driver->createImage ( video::ECF_A8R8G8B8, dim); + data = (u32*) image->lock (); + for ( y = 0; y != dim.Height; ++y ) + { + for ( x = 0; x != dim.Width; ++x ) + { + data [x] = 0xFFFFFFFF; + } + data = (u32*) ( (u8*) data + image->getPitch() ); + } + image->unlock(); + snprintf ( buf, 64, "fog_%02d", i ); + texture = driver->addTexture( buf, image ); + image->drop (); + } + +} + + +/*! + create the GUI +*/ +void CQuake3EventHandler::CreateGUI() +{ + + IGUIEnvironment *env = Game->Device->getGUIEnvironment(); + ISceneManager *smgr = Game->Device->getSceneManager (); + IVideoDriver * driver = Game->Device->getVideoDriver(); + + gui.drop(); + + // set skin font + env->getSkin()->setFont(env->getFont("fontlucida.png")); + env->getSkin()->setColor ( EGDC_BUTTON_TEXT, video::SColor(240,0xAA,0xAA,0xAA) ); + env->getSkin()->setColor ( EGDC_3D_HIGH_LIGHT, video::SColor(240,0x22,0x22,0x22) ); + env->getSkin()->setColor ( EGDC_3D_FACE, video::SColor(240,0x44,0x44,0x44) ); + env->getSkin()->setColor ( EGDC_WINDOW, video::SColor(240,0x66,0x66,0x66) ); + + // 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." ); + gui.Window->getCloseButton()->setToolTipText ( L"Quit Quake3 Explorer" ); + + // add a status line help text + gui.StatusLine = env->addStaticText( 0, rect( 5,dim.Height - 30,dim.Width - 5,dim.Height - 10), + false, false, gui.Window, -1, true + ); + + + env->addStaticText ( L"VideoDriver:", rect( dim.Width - 400, 24, dim.Width - 310, 40 ),false, false, gui.Window, -1, false ); + gui.VideoDriver = env->addComboBox(rect( dim.Width - 300, 24, dim.Width - 10, 40 ),gui.Window); + gui.VideoDriver->addItem(L"Direct3D 9.0c", EDT_DIRECT3D9 ); + gui.VideoDriver->addItem(L"Direct3D 8.1", EDT_DIRECT3D8 ); + gui.VideoDriver->addItem(L"OpenGL 1.5", EDT_OPENGL); + gui.VideoDriver->addItem(L"Software Renderer", EDT_SOFTWARE); + gui.VideoDriver->addItem(L"Burning's Video (TM) Thomas Alten", EDT_BURNINGSVIDEO); + gui.VideoDriver->setSelected ( gui.VideoDriver->getIndexForItemData ( Game->deviceParam.DriverType ) ); + gui.VideoDriver->setToolTipText ( L"Use a VideoDriver" ); + + env->addStaticText ( L"VideoMode:", rect( dim.Width - 400, 44, dim.Width - 310, 60 ),false, false, gui.Window, -1, false ); + gui.VideoMode = env->addComboBox(rect( dim.Width - 300, 44, dim.Width - 10, 60 ),gui.Window); + gui.VideoMode->setToolTipText ( L"Supported Screenmodes" ); + IVideoModeList *modeList = Game->Device->getVideoModeList(); + if ( modeList ) + { + s32 i; + for ( i = 0; i != modeList->getVideoModeCount (); ++i ) + { + u16 d = modeList->getVideoModeDepth ( i ); + if ( d < 16 ) + continue; + + u16 w = modeList->getVideoModeResolution ( i ).Width; + u16 h = modeList->getVideoModeResolution ( i ).Height; + u32 val = w << 16 | h; + + if ( gui.VideoMode->getIndexForItemData ( val ) >= 0 ) + continue; + + f32 aspect = (f32) w / (f32) h; + const c8 *a = ""; + if ( core::equals ( aspect, 1.3333333333f ) ) a = "4:3"; + else if ( core::equals ( aspect, 1.6666666f ) ) a = "15:9 widescreen"; + else if ( core::equals ( aspect, 1.7777777f ) ) a = "16:9 widescreen"; + else if ( core::equals ( aspect, 1.6f ) ) a = "16:10 widescreen"; + else if ( core::equals ( aspect, 2.133333f ) ) a = "20:9 widescreen"; + + snprintf ( buf, sizeof ( buf ), "%d x %d, %s",w, h, a ); + gui.VideoMode->addItem ( stringw ( buf ).c_str(), val ); + } + } + gui.VideoMode->setSelected ( gui.VideoMode->getIndexForItemData ( + Game->deviceParam.WindowSize.Width << 16 | + Game->deviceParam.WindowSize.Height ) ); + + gui.FullScreen = env->addCheckBox ( Game->deviceParam.Fullscreen, rect( dim.Width - 400, 64, dim.Width - 300, 80 ), gui.Window,-1, L"Fullscreen" ); + gui.FullScreen->setToolTipText ( L"Set Fullscreen or Window Mode" ); + + gui.Bit32 = env->addCheckBox ( Game->deviceParam.Bits == 32, rect( dim.Width - 300, 64, dim.Width - 240, 80 ), gui.Window,-1, L"32Bit" ); + gui.Bit32->setToolTipText ( L"Use 16 or 32 Bit" ); + + env->addStaticText ( L"MultiSample:", rect( dim.Width - 235, 64, dim.Width - 150, 80 ),false, false, gui.Window, -1, false ); + gui.MultiSample = env->addScrollBar( true, rect( dim.Width - 150, 64, dim.Width - 70, 80 ), gui.Window,-1 ); + gui.MultiSample->setMin ( 0 ); + gui.MultiSample->setMax ( 8 ); + gui.MultiSample->setSmallStep ( 1 ); + gui.MultiSample->setLargeStep ( 1 ); + gui.MultiSample->setPos ( Game->deviceParam.AntiAlias ); + gui.MultiSample->setToolTipText ( L"Set the MultiSample (disable, 1x, 2x, 4x, 8x )" ); + + gui.SetVideoMode = env->addButton (rect( dim.Width - 60, 64, dim.Width - 10, 80 ), gui.Window, -1,L"set" ); + gui.SetVideoMode->setToolTipText ( L"Set Video Mode with current values" ); + + env->addStaticText ( L"Gamma:", rect( dim.Width - 400, 104, dim.Width - 310, 120 ),false, false, gui.Window, -1, false ); + gui.Gamma = env->addScrollBar( true, rect( dim.Width - 300, 104, dim.Width - 10, 120 ), gui.Window,-1 ); + gui.Gamma->setMin ( 50 ); + gui.Gamma->setMax ( 350 ); + gui.Gamma->setSmallStep ( 1 ); + gui.Gamma->setLargeStep ( 10 ); + gui.Gamma->setPos ( core::floor32 ( Game->GammaValue * 100.f ) ); + gui.Gamma->setToolTipText ( L"Adjust Gamma Ramp ( 0.5 - 3.5)" ); + Game->Device->setGammaRamp ( Game->GammaValue, Game->GammaValue, Game->GammaValue, 0.f, 0.f ); + + + env->addStaticText ( L"Tesselation:", rect( dim.Width - 400, 124, dim.Width - 310, 140 ),false, false, gui.Window, -1, false ); + gui.Tesselation = env->addScrollBar( true, rect( dim.Width - 300, 124, dim.Width - 10, 140 ), gui.Window,-1 ); + gui.Tesselation->setMin ( 2 ); + gui.Tesselation->setMax ( 12 ); + gui.Tesselation->setSmallStep ( 1 ); + gui.Tesselation->setLargeStep ( 1 ); + gui.Tesselation->setPos ( Game->loadParam.patchTesselation ); + gui.Tesselation->setToolTipText ( L"How smooth should curved surfaces be rendered" ); + + gui.Collision = env->addCheckBox ( true, rect( dim.Width - 400, 150, dim.Width - 300, 166 ), gui.Window,-1, L"Collision" ); + gui.Collision->setToolTipText ( L"Set collision on or off ( flythrough ). \nPress F7 on your Keyboard" ); + gui.Visible_Map = env->addCheckBox ( true, rect( dim.Width - 300, 150, dim.Width - 240, 166 ), gui.Window,-1, L"Map" ); + gui.Visible_Map->setToolTipText ( L"Show or not show the static part the Level. \nPress F3 on your Keyboard" ); + gui.Visible_Shader = env->addCheckBox ( true, rect( dim.Width - 240, 150, dim.Width - 170, 166 ), gui.Window,-1, L"Shader" ); + gui.Visible_Shader->setToolTipText ( L"Show or not show the Shader Nodes. \nPress F4 on your Keyboard" ); + gui.Visible_Fog = env->addCheckBox ( true, rect( dim.Width - 170, 150, dim.Width - 110, 166 ), gui.Window,-1, L"Fog" ); + gui.Visible_Fog->setToolTipText ( L"Show or not show the Fog Nodes. \nPress F5 on your Keyboard" ); + gui.Visible_Unresolved = env->addCheckBox ( true, rect( dim.Width - 110, 150, dim.Width - 10, 166 ), gui.Window,-1, L"Unresolved" ); + gui.Visible_Unresolved->setToolTipText ( L"Show the or not show the Nodes the Engine can't handle. \nPress F6 on your Keyboard" ); + + //Respawn = env->addButton ( rect( dim.Width - 260, 90, dim.Width - 10, 106 ), 0,-1, L"Respawn" ); + + env->addStaticText ( L"Archives:", rect( 5, dim.Height - 530, dim.Width - 600,dim.Height - 514 ),false, false, gui.Window, -1, false ); + gui.ArchiveAdd = env->addButton ( rect( dim.Width - 700, dim.Height - 530, dim.Width - 620, dim.Height - 514 ), gui.Window,-1, L"add" ); + gui.ArchiveAdd->setToolTipText ( L"Add an archive, usally packed zip-archives (*.pk3) to the Filesystem" ); + gui.ArchiveRemove = env->addButton ( rect( dim.Width - 600, dim.Height - 530, dim.Width - 520, dim.Height - 514 ), gui.Window,-1, L"del" ); + gui.ArchiveRemove->setToolTipText ( L"Remove the selected archive from the FileSystem." ); + + + gui.ArchiveList = env->addTable ( rect( 5,dim.Height - 510, dim.Width - 450,dim.Height - 410 ), gui.Window ); + gui.ArchiveList->addColumn ( L"Type", 0 ); + gui.ArchiveList->addColumn ( L"Real File Path", 1 ); + gui.ArchiveList->setColumnWidth ( 0, 60 ); + gui.ArchiveList->setColumnWidth ( 1, 284 ); + gui.ArchiveList->setToolTipText ( L"Show the attached Archives" ); + + + env->addStaticText ( L"Maps:", rect( 5, dim.Height - 400, dim.Width - 450,dim.Height - 380 ),false, false, gui.Window, -1, false ); + gui.MapList = env->addListBox ( rect( 5,dim.Height - 380, dim.Width - 450,dim.Height - 40 ), gui.Window, -1, true ); + gui.MapList->setToolTipText ( L"Show the current Maps in all Archives.\n Double-Click the Map to start the level" ); + + + // create a visible Scene Tree + env->addStaticText ( L"Scenegraph:", rect( dim.Width - 400, dim.Height - 400, dim.Width - 5,dim.Height - 380 ),false, false, gui.Window, -1, false ); + gui.SceneTree = env->addTreeView( rect( dim.Width - 400, dim.Height - 380, dim.Width - 5, dim.Height - 40 ), + gui.Window, -1, true, true, false ); + gui.SceneTree->setToolTipText ( L"Show the current Scenegraph" ); + gui.SceneTree->getRoot()->clearChilds(); + addSceneTreeItem ( Game->Device->getSceneManager()->getRootSceneNode(), gui.SceneTree->getRoot() ); + + + IGUIImageList* imageList = env->createImageList( driver->getTexture ( "iconlist.png" ), + dimension2d( 32, 32 ), true ); + + if ( imageList ) + { + gui.SceneTree->setImageList( imageList ); + imageList->drop (); + } + + + // load the engine logo + gui.Logo = env->addImage( driver->getTexture("irrlichtlogo3.png"), position2d(5, 16 ), true, 0 ); + gui.Logo->setToolTipText ( L"The great Irrlicht Engine" ); + + AddArchive ( "" ); +} + + + +/*! + Add an Archive to the FileSystems und updates the GUI +*/ +void CQuake3EventHandler::AddArchive ( const core::string& archiveName ) +{ + io::IFileSystem *fs = Game->Device->getFileSystem(); + u32 i; + + if ( archiveName.size () ) + { + bool exists = false; + for ( i = 0; i != fs->getFileArchiveCount(); ++i ) + { + if ( fs->getFileArchive ( i )->getArchiveName() == archiveName ) + { + exists = true; + break; + } + } + + if ( !exists ) + { + fs->registerFileArchive ( archiveName, true, false ); + Game->CurrentMapName = ""; + } + } + + // show the attached Archive in proper order + if ( gui.ArchiveList ) + { + gui.ArchiveList->clearRows(); + + for ( i = 0; i != fs->getFileArchiveCount(); ++i ) + { + io::IFileArchive * archive = fs->getFileArchive ( i ); + + u32 index = gui.ArchiveList->addRow ( -1 ); + + gui.ArchiveList->setCellText ( index, 0, archive->getArchiveType () ); + gui.ArchiveList->setCellText ( index, 1, archive->getArchiveName () ); + + } + + } + + + // browse the archives for maps + if ( gui.MapList ) + { + gui.MapList->clear (); + + IGUISpriteBank *bank = Game->Device->getGUIEnvironment()->getSpriteBank ( "sprite_q3map" ); + if ( 0 == bank ) + bank = Game->Device->getGUIEnvironment()->addEmptySpriteBank ( "sprite_q3map" ); + + SGUISprite sprite; + SGUISpriteFrame frame; + core::rect r; + + + bank->getSprites().clear(); + bank->getPositions().clear (); + gui.MapList->setSpriteBank ( bank ); + + u32 g = 0; + core::stringw s; + + //! browse the attached file system + fs->setFileListSystem ( io::FILESYSTEM_VIRTUAL ); + fs->changeWorkingDirectoryTo ( "/maps/" ); + io::IFileList *fileList = fs->createFileList (); + fs->setFileListSystem ( io::FILESYSTEM_NATIVE ); + + + for ( i=0; i< fileList->getFileCount(); ++i) + { + s = fileList->getFullFileName(i); + if ( s.find ( ".bsp" ) >= 0 ) + { + // get level screenshot. reformat texture to 128x128 + string c ( s ); + deletePathFromFilename ( c ); + cutFilenameExtension ( c, c ); + c = string ( "levelshots/" ) + c; + + dimension2du dim ( 128, 128 ); + IVideoDriver * driver = Game->Device->getVideoDriver(); + IImage* image = 0; + ITexture *tex = 0; + string filename; + + filename = c + ".jpg"; + image = driver->createImageFromFile( filename ); + if ( 0 == image ) + { + filename = c + ".tga"; + image = driver->createImageFromFile( filename ); + } + + if ( image ) + { + IImage* filter = driver->createImage ( video::ECF_R8G8B8, dim ); + image->copyToScalingBoxFilter ( filter, 0 ); + image->drop (); + image = filter; + } + + if ( image ) + { + tex = driver->addTexture ( filename, image ); + image->drop (); + } + + + bank->setTexture ( g, tex ); + + r.LowerRightCorner.X = dim.Width; + r.LowerRightCorner.Y = dim.Height; + gui.MapList->setItemHeight ( r.LowerRightCorner.Y + 4 ); + frame.rectNumber = bank->getPositions().size(); + frame.textureNumber = g; + + bank->getPositions().push_back(r); + + sprite.Frames.set_used ( 0 ); + sprite.Frames.push_back(frame); + sprite.frameTime = 0; + bank->getSprites().push_back(sprite); + + gui.MapList->addItem ( s.c_str (), g ); + g += 1; + } + } + fileList->drop (); + + gui.MapList->setSelected ( -1 ); + IGUIScrollBar * bar = (IGUIScrollBar*)gui.MapList->getElementFromId( 0 ); + if ( bar ) + bar->setPos ( 0 ); + + } + +} + +/*! + clears the Map in Memory +*/ +void CQuake3EventHandler::dropMap () +{ + IVideoDriver * driver = Game->Device->getVideoDriver(); + + driver->removeAllHardwareBuffers (); + driver->removeAllTextures (); + + Player[0].shutdown (); + + + dropElement ( ItemParent ); + dropElement ( ShaderParent ); + dropElement ( UnresolvedParent ); + dropElement ( FogParent ); + dropElement ( BulletParent ); + + + Impacts.clear(); + + if ( Meta ) + { + Meta = 0; + } + + dropElement ( MapParent ); + dropElement ( SkyNode ); + + if ( Mesh ) + { + Game->Device->getSceneManager ()->getMeshCache()->removeMesh ( Mesh ); + Mesh = 0; + } +} + +/*! +*/ +void CQuake3EventHandler::LoadMap ( const stringw &mapName, s32 collision ) +{ + if ( 0 == mapName.size() ) + return; + + dropMap (); + + io::IFileSystem *fs = Game->Device->getFileSystem(); + ISceneManager *smgr = Game->Device->getSceneManager (); + + io::IReadFile* file = fs->createMemoryReadFile ( &Game->loadParam, sizeof ( Game->loadParam ), + L"levelparameter.cfg", false); + + smgr->getMesh( file ); + file->drop (); + + Mesh = (IQ3LevelMesh*) smgr->getMesh(mapName); + if ( 0 == Mesh ) + return; + + /* + add the geometry mesh to the Scene ( polygon & patches ) + The Geometry mesh is optimised for faster drawing + */ + + IMesh *geometry = Mesh->getMesh(E_Q3_MESH_GEOMETRY); + if ( 0 == geometry || geometry->getMeshBufferCount() == 0) + return; + + Game->CurrentMapName = mapName; + + IMeshBuffer *b0 = geometry->getMeshBuffer(0); + + //create a collision list + Meta = 0; + + ITriangleSelector * selector = 0; + if (collision) + Meta = smgr->createMetaTriangleSelector(); + + //s32 minimalNodes = b0 ? core::s32_max ( 2048, b0->getVertexCount() / 32 ) : 2048; + s32 minimalNodes = 2048; + + MapParent = smgr->addMeshSceneNode( geometry ); + //MapParent = smgr->addOctTreeSceneNode(geometry, 0, -1, minimalNodes); + MapParent->setName ( mapName ); + if ( Meta ) + { + selector = smgr->createOctTreeTriangleSelector( geometry,MapParent, minimalNodes); + //selector = smgr->createTriangleSelector ( geometry, MapParent ); + Meta->addTriangleSelector( selector); + selector->drop (); + } + + // logical parent for the items + ItemParent = smgr->addEmptySceneNode(); + if ( ItemParent ) + ItemParent->setName ( "Item Container" ); + + ShaderParent = smgr->addEmptySceneNode(); + if ( ShaderParent ) + ShaderParent->setName ( "Shader Container" ); + + UnresolvedParent = smgr->addEmptySceneNode(); + if ( UnresolvedParent ) + UnresolvedParent->setName ( "Unresolved Container" ); + + FogParent = smgr->addEmptySceneNode(); + if ( FogParent ) + FogParent->setName ( "Fog Container" ); + + // logical parent for the bullets + BulletParent = smgr->addEmptySceneNode(); + if ( BulletParent ) + 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 + mostly dark looking skulls and moving lava.. or green flashing tubes? + */ + Q3ShaderFactory ( Game->loadParam, Game->Device, Mesh, E_Q3_MESH_ITEMS,ShaderParent, Meta, false ); + Q3ShaderFactory ( Game->loadParam, Game->Device, Mesh, E_Q3_MESH_FOG,FogParent, 0, false ); + Q3ShaderFactory ( Game->loadParam, Game->Device, Mesh, E_Q3_MESH_UNRESOLVED,UnresolvedParent, 0, true ); + + + /* + Now construct Models from Entity List + */ + Q3ModelFactory ( Game->loadParam, Game->Device, Mesh, ItemParent ); + +} + +/* +**/ + +/*! + Adds a SceneNode with an icon to the Scene Tree +*/ +void CQuake3EventHandler::addSceneTreeItem( ISceneNode * parent, IGUITreeViewNode* nodeParent) +{ + IGUITreeViewNode* node; + wchar_t *msg = (wchar_t*) buf; + + s32 imageIndex; + list::ConstIterator it = parent->getChildren().begin(); + for (; it != parent->getChildren().end(); ++it) + { + switch ( (*it)->getType () ) + { + case ESNT_Q3SHADER_SCENE_NODE: imageIndex = 0; break; + case ESNT_CAMERA: imageIndex = 1; break; + case ESNT_EMPTY: imageIndex = 2; break; + case ESNT_MESH: imageIndex = 3; break; + case ESNT_OCT_TREE: imageIndex = 3; break; + case ESNT_ANIMATED_MESH: imageIndex = 4; break; + case ESNT_SKY_BOX: imageIndex = 5; break; + case ESNT_BILLBOARD: imageIndex = 6; break; + case ESNT_PARTICLE_SYSTEM: imageIndex = 7; break; + case ESNT_TEXT: imageIndex = 8; break; + default:imageIndex = -1; break; + } + + if ( imageIndex < 0 ) + { + swprintf ( msg, 128, L"%hs,%hs", + Game->Device->getSceneManager ()->getSceneNodeTypeName ( (*it)->getType () ), + (*it)->getName() + ); + } + else + { + swprintf ( msg, 128, L"%hs",(*it)->getName() ); + } + + + node = nodeParent->addChildBack( msg, 0, imageIndex ); + addSceneTreeItem ( *it, node ); + } + +} + + +//! Adds life! +void CQuake3EventHandler::CreatePlayers() +{ + Player[0].create ( Game->Device, Mesh, MapParent, Meta ); +} + +//! Adds a skydome to the scene +void CQuake3EventHandler::AddSky( u32 dome, const c8 *texture) +{ + ISceneManager *smgr = Game->Device->getSceneManager (); + IVideoDriver * driver = Game->Device->getVideoDriver(); + + bool oldMipMapState = driver->getTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS); + driver->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, false); + + if ( 0 == dome ) + { + // irrlicht order + //static const c8*p[] = { "ft", "lf", "bk", "rt", "up", "dn" }; + // quake3 order + static const c8*p[] = { "ft", "rt", "bk", "lf", "up", "dn" }; + + u32 i = 0; + snprintf ( buf, 64, "%s_%s.jpg", texture, p[i] ); + SkyNode = smgr->addSkyBoxSceneNode( driver->getTexture ( buf ), 0, 0, 0, 0, 0 ); + + for ( i = 0; i < 6; ++i ) + { + snprintf ( buf, 64, "%s_%s.jpg", texture, p[i] ); + SkyNode->getMaterial(i).setTexture ( 0, driver->getTexture ( buf ) ); + } + } + else + if ( 1 == dome ) + { + snprintf ( buf, 64, "%s.jpg", texture ); + SkyNode = smgr->addSkyDomeSceneNode( + driver->getTexture( buf ), + 32,32, + 1.f, + 1.f, + 1000.f, + 0, + 11 + ); + } + else + if ( 2 == dome ) + { + snprintf ( buf, 64, "%s.jpg", texture ); + SkyNode = smgr->addSkyDomeSceneNode( + driver->getTexture( buf ), + 16,8, + 0.95f, + 2.f, + 1000.f, + 0, + 11 + ); + } + + SkyNode->setName ( "Skydome" ); + //SkyNode->getMaterial(0).ZBuffer = video::EMDF_DEPTH_LESS_EQUAL; + + driver->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, oldMipMapState); + +} + + +/*! +*/ +void CQuake3EventHandler::SetGUIActive( s32 command) +{ + bool inputState = false; + + ICameraSceneNode * camera = Game->Device->getSceneManager()->getActiveCamera (); + + switch ( command ) + { + case 0: Game->guiActive = 0; inputState = !Game->guiActive; break; + case 1: Game->guiActive = 1; inputState = !Game->guiActive;;break; + case 2: Game->guiActive ^= 1; inputState = !Game->guiActive;break; + case 3: + if ( camera ) + inputState = !camera->isInputReceiverEnabled(); + break; + } + + if ( camera ) + { + camera->setInputReceiverEnabled ( inputState ); + Game->Device->getCursorControl()->setVisible( !inputState ); + } + + if ( gui.Window ) + { + gui.Window->setVisible ( Game->guiActive != 0 ); + } + + if ( Game->guiActive && + gui.SceneTree && Game->Device->getGUIEnvironment()->getFocus() != gui.SceneTree + ) + { + gui.SceneTree->getRoot()->clearChilds(); + addSceneTreeItem ( Game->Device->getSceneManager()->getRootSceneNode(), gui.SceneTree->getRoot() ); + } + + Game->Device->getGUIEnvironment()->setFocus ( Game->guiActive ? gui.Window: 0 ); +} + + + +/*! + Handle game input +*/ +bool CQuake3EventHandler::OnEvent(const SEvent& eve) +{ + if ( eve.EventType == EET_LOG_TEXT_EVENT ) + { + return false; + } + + if ( Game->guiActive && eve.EventType == EET_GUI_EVENT ) + { + if ( eve.GUIEvent.Caller == gui.MapList && eve.GUIEvent.EventType == gui::EGET_LISTBOX_SELECTED_AGAIN ) + { + s32 selected = gui.MapList->getSelected(); + if ( selected >= 0 ) + { + stringw loadMap = gui.MapList->getListItem ( selected ); + if ( 0 == MapParent || loadMap != Game->CurrentMapName ) + { + printf ( "Loading map %ls\n", loadMap.c_str() ); + LoadMap ( loadMap , 1 ); + if ( 0 == Game->loadParam.loadSkyShader ) + AddSky ( 1, "skydome2" ); + //AddSky ( 0, "env/ssky" ); + CreatePlayers (); + CreateGUI (); + SetGUIActive ( 0 ); + return true; + } + } + } + else + if ( eve.GUIEvent.Caller == gui.ArchiveRemove && eve.GUIEvent.EventType == gui::EGET_BUTTON_CLICKED ) + { + Game->Device->getFileSystem()->unregisterFileArchive ( gui.ArchiveList->getSelected () ); + Game->CurrentMapName = ""; + AddArchive ( "" ); + } + else + if ( eve.GUIEvent.Caller == gui.ArchiveAdd && eve.GUIEvent.EventType == gui::EGET_BUTTON_CLICKED ) + { + if ( 0 == gui.ArchiveFileOpen ) + { + Game->Device->getFileSystem()->setFileListSystem ( io::FILESYSTEM_NATIVE ); + gui.ArchiveFileOpen = Game->Device->getGUIEnvironment()->addFileOpenDialog ( L"Add Game Archive" , false,gui.Window ); + } + } + else + if ( eve.GUIEvent.Caller == gui.ArchiveFileOpen && eve.GUIEvent.EventType == gui::EGET_FILE_SELECTED ) + { + AddArchive ( gui.ArchiveFileOpen->getFileName() ); + gui.ArchiveFileOpen = 0; + } + else + if ( eve.GUIEvent.Caller == gui.ArchiveFileOpen && eve.GUIEvent.EventType == gui::EGET_DIRECTORY_SELECTED ) + { + AddArchive ( gui.ArchiveFileOpen->getDirectoryName() ); + } + else + if ( eve.GUIEvent.Caller == gui.ArchiveFileOpen && eve.GUIEvent.EventType == gui::EGET_FILE_CHOOSE_DIALOG_CANCELLED ) + { + gui.ArchiveFileOpen = 0; + } + else + if ( eve.GUIEvent.Caller == gui.VideoDriver && eve.GUIEvent.EventType == gui::EGET_COMBO_BOX_CHANGED ) + { + Game->deviceParam.DriverType = (E_DRIVER_TYPE) gui.VideoDriver->getItemData ( gui.VideoDriver->getSelected() ); + } + else + if ( eve.GUIEvent.Caller == gui.VideoMode && eve.GUIEvent.EventType == gui::EGET_COMBO_BOX_CHANGED ) + { + u32 val = gui.VideoMode->getItemData ( gui.VideoMode->getSelected() ); + Game->deviceParam.WindowSize.Width = val >> 16; + Game->deviceParam.WindowSize.Height = val & 0xFFFF; + } + else + if ( eve.GUIEvent.Caller == gui.FullScreen && eve.GUIEvent.EventType == gui::EGET_CHECKBOX_CHANGED ) + { + Game->deviceParam.Fullscreen = gui.FullScreen->isChecked(); + } + else + if ( eve.GUIEvent.Caller == gui.Bit32 && eve.GUIEvent.EventType == gui::EGET_CHECKBOX_CHANGED ) + { + Game->deviceParam.Bits = gui.Bit32->isChecked() ? 32 : 16; + } + else + if ( eve.GUIEvent.Caller == gui.MultiSample && eve.GUIEvent.EventType == gui::EGET_SCROLL_BAR_CHANGED ) + { + Game->deviceParam.AntiAlias = gui.MultiSample->getPos(); + } + else + if ( eve.GUIEvent.Caller == gui.Tesselation && eve.GUIEvent.EventType == gui::EGET_SCROLL_BAR_CHANGED ) + { + Game->loadParam.patchTesselation = gui.Tesselation->getPos (); + } + else + if ( eve.GUIEvent.Caller == gui.Gamma && eve.GUIEvent.EventType == gui::EGET_SCROLL_BAR_CHANGED ) + { + Game->GammaValue = gui.Gamma->getPos () * 0.01f; + Game->Device->setGammaRamp ( Game->GammaValue, Game->GammaValue, Game->GammaValue, 0.f, 0.f ); + } + else + if ( eve.GUIEvent.Caller == gui.SetVideoMode && eve.GUIEvent.EventType == gui::EGET_BUTTON_CLICKED ) + { + Game->retVal = 2; + Game->Device->closeDevice(); + } + else + if ( eve.GUIEvent.Caller == gui.Window && eve.GUIEvent.EventType == gui::EGET_ELEMENT_CLOSED ) + { + Game->Device->closeDevice(); + } + else + if ( eve.GUIEvent.Caller == gui.Collision && eve.GUIEvent.EventType == gui::EGET_CHECKBOX_CHANGED ) + { + // set fly through active + Game->flyTroughState ^= 1; + Player[0].cam()->setAnimateTarget ( Game->flyTroughState == 0 ); + + printf ( "collision %d\n", Game->flyTroughState == 0 ); + } + else + if ( eve.GUIEvent.Caller == gui.Visible_Map && eve.GUIEvent.EventType == gui::EGET_CHECKBOX_CHANGED ) + { + bool v = gui.Visible_Map->isChecked(); + + if ( MapParent ) + { + printf ( "static node set visible %d\n",v ); + MapParent->setVisible ( v ); + } + } + else + if ( eve.GUIEvent.Caller == gui.Visible_Shader && eve.GUIEvent.EventType == gui::EGET_CHECKBOX_CHANGED ) + { + bool v = gui.Visible_Shader->isChecked(); + + if ( ShaderParent ) + { + printf ( "shader node set visible %d\n",v ); + ShaderParent->setVisible ( v ); + } + } + else + if ( eve.GUIEvent.Caller == gui.Respawn && eve.GUIEvent.EventType == gui::EGET_BUTTON_CLICKED ) + { + Player[0].respawn (); + } + + return false; + } + + // fire + if ((eve.EventType == EET_KEY_INPUT_EVENT && eve.KeyInput.Key == KEY_SPACE && + eve.KeyInput.PressedDown == false) || + (eve.EventType == EET_MOUSE_INPUT_EVENT && eve.MouseInput.Event == EMIE_LMOUSE_LEFT_UP) + ) + { + ICameraSceneNode * camera = Game->Device->getSceneManager()->getActiveCamera (); + if ( camera && camera->isInputReceiverEnabled () ) + { + useItem( Player + 0 ); + } + } + + // gui active + if ((eve.EventType == EET_KEY_INPUT_EVENT && eve.KeyInput.Key == KEY_F1 && + eve.KeyInput.PressedDown == false) || + (eve.EventType == EET_MOUSE_INPUT_EVENT && eve.MouseInput.Event == EMIE_RMOUSE_LEFT_UP) + ) + { + SetGUIActive ( 2 ); + } + + // check if user presses the key + if ( eve.EventType == EET_KEY_INPUT_EVENT && eve.KeyInput.PressedDown == false) + { + // Escape toggles camera Input + if ( eve.KeyInput.Key == irr::KEY_ESCAPE ) + { + SetGUIActive ( 3 ); + } + else + if (eve.KeyInput.Key == KEY_F11) + { + //! screenshot are taken without gamma! + IImage* image = Game->Device->getVideoDriver()->createScreenShot(); + if (image) + { + core::vector3df pos; + core::vector3df rot; + ICameraSceneNode * cam = Game->Device->getSceneManager()->getActiveCamera (); + if ( cam ) + { + pos = cam->getPosition (); + rot = cam->getRotation (); + } + + static const c8 *dName[] = { "null", "software", "burning", + "d3d8", "d3d9", "opengl" }; + + snprintf(buf, 256, "%s_%ls_%.0f_%.0f_%.0f_%.0f_%.0f_%.0f.jpg", + dName[Game->Device->getVideoDriver()->getDriverType()], + Game->CurrentMapName.c_str(), + pos.X, pos.Y, pos.Z, + rot.X, rot.Y, rot.Z + ); + core::string filename ( buf ); + filename.replace ( '/', '_' ); + printf ( "screenshot : %s\n", filename.c_str() ); + Game->Device->getVideoDriver()->writeImageToFile(image, filename, 100 ); + image->drop(); + } + } + else + if (eve.KeyInput.Key == KEY_F9) + { + s32 value = EDS_OFF; + + Game->debugState = ( Game->debugState + 1 ) & 3; + + switch ( Game->debugState ) + { + case 1: value = EDS_NORMALS | EDS_MESH_WIRE_OVERLAY | EDS_BBOX_ALL; break; + case 2: value = EDS_NORMALS | EDS_MESH_WIRE_OVERLAY | EDS_SKELETON; break; + } +/* + // set debug map data on/off + debugState = debugState == EDS_OFF ? + EDS_NORMALS | EDS_MESH_WIRE_OVERLAY | EDS_BBOX_ALL: + EDS_OFF; +*/ + if ( ShaderParent ) + { + list::ConstIterator it = ShaderParent->getChildren().begin(); + for (; it != ShaderParent->getChildren().end(); ++it) + { + (*it)->setDebugDataVisible ( value ); + } + } + + if ( UnresolvedParent ) + { + list::ConstIterator it = UnresolvedParent->getChildren().begin(); + for (; it != UnresolvedParent->getChildren().end(); ++it) + { + (*it)->setDebugDataVisible ( value ); + } + } + + if ( FogParent ) + { + list::ConstIterator it = FogParent->getChildren().begin(); + for (; it != FogParent->getChildren().end(); ++it) + { + (*it)->setDebugDataVisible ( value ); + } + } + + if ( SkyNode ) + { + SkyNode->setDebugDataVisible ( value ); + } + + } + else + if (eve.KeyInput.Key == KEY_F8) + { + // set gravity on/off + Game->gravityState ^= 1; + Player[0].cam()->setGravity ( getGravity ( Game->gravityState ? "earth" : "none" ) ); + printf ( "gravity %s\n", Game->gravityState ? "earth" : "none" ); + } + else + if (eve.KeyInput.Key == KEY_F7) + { + // set fly through active + Game->flyTroughState ^= 1; + Player[0].cam()->setAnimateTarget ( Game->flyTroughState == 0 ); + if ( gui.Collision ) + gui.Collision->setChecked ( Game->flyTroughState == 0 ); + + printf ( "collision %d\n", Game->flyTroughState == 0 ); + } + else + if (eve.KeyInput.Key == KEY_F2) + { + Player[0].respawn (); + } + else + if (eve.KeyInput.Key == KEY_F3) + { + if ( MapParent ) + { + bool v = !MapParent->isVisible (); + printf ( "static node set visible %d\n",v ); + MapParent->setVisible ( v ); + if ( gui.Visible_Map ) + gui.Visible_Map->setChecked ( v ); + } + } + else + if (eve.KeyInput.Key == KEY_F4) + { + if ( ShaderParent ) + { + bool v = !ShaderParent->isVisible (); + printf ( "shader node set visible %d\n",v ); + ShaderParent->setVisible ( v ); + if ( gui.Visible_Shader ) + gui.Visible_Shader->setChecked ( v ); + } + } + else + if (eve.KeyInput.Key == KEY_F5) + { + if ( FogParent ) + { + bool v = !FogParent->isVisible (); + printf ( "fog node set visible %d\n",v ); + FogParent->setVisible ( v ); + if ( gui.Visible_Fog ) + gui.Visible_Fog->setChecked ( v ); + } + + } + else + if (eve.KeyInput.Key == KEY_F6) + { + if ( UnresolvedParent ) + { + bool v = !UnresolvedParent->isVisible (); + printf ( "unresolved node set visible %d\n",v ); + UnresolvedParent->setVisible ( v ); + if ( gui.Visible_Unresolved ) + gui.Visible_Unresolved->setChecked ( v ); + } + } +/* + else + if (eve.KeyInput.Key == KEY_KEY_P) + { + ICameraSceneNode* camera = Device->getSceneManager()->getActiveCamera(); + const core::vector3df &p = camera->getPosition(); + const core::vector3df &r = camera->getRotation(); + printf ( "core::vector3df (%ff,%ff,%ff)\ncore::vector3df (%ff,%ff,%ff)\n", p.X, p.Y, p.Z, r.X, r.Y, r.Z ); + } + else + if (eve.KeyInput.Key == KEY_KEY_G) + { + ICameraSceneNode* camera = Device->getSceneManager()->getActiveCamera(); + + camera->setPosition ( core::vector3df ( 635.673767f,79.271515f,159.270813f ) ); + camera->setRotation ( core::vector3df ( 349.166565f,126.624962f,0.000000f ) ); + camera->OnAnimate ( 0 ); + } +*/ + } + + // check if user presses the key C ( for crouch) + if ( eve.EventType == EET_KEY_INPUT_EVENT && eve.KeyInput.Key == KEY_KEY_C ) + { + // crouch + ISceneNodeAnimatorCollisionResponse *anim = Player[0].cam (); + if ( anim && 0 == Game->flyTroughState ) + { + if ( false == eve.KeyInput.PressedDown ) + { + // stand up + anim->setEllipsoidRadius ( vector3df(30,45,30) ); + anim->setEllipsoidTranslation ( vector3df(0,40,0)); + + } + else + { + // on your knees + anim->setEllipsoidRadius ( vector3df(30,20,30) ); + anim->setEllipsoidTranslation ( vector3df(0,20,0)); + } + return true; + } + } + return false; +} + + + +/* + useItem +*/ +void CQuake3EventHandler::useItem( Q3Player * player) +{ + ISceneManager* smgr = Game->Device->getSceneManager(); + ICameraSceneNode* camera = smgr->getActiveCamera(); + + if (!camera) + return; + + SParticleImpact imp; + imp.when = 0; + + // get line of camera + + vector3df start = camera->getPosition(); + + if ( player->WeaponNode ) + { + start.X += 0.f; + start.Y += 0.f; + start.Z += 0.f; + } + + vector3df end = (camera->getTarget() - start); + end.normalize(); + start += end*20.0f; + + end = start + (end * camera->getFarValue()); + + triangle3df triangle; + line3d line(start, end); + + // get intersection point with map + const scene::ISceneNode* hitNode; + if (smgr->getSceneCollisionManager()->getCollisionPoint( + line, Meta, end, triangle,hitNode)) + { + // collides with wall + vector3df out = triangle.getNormal(); + out.setLength(0.03f); + + imp.when = 1; + imp.outVector = out; + imp.pos = end; + + player->setAnim ( "pow" ); + player->Anim[1].next += player->Anim[1].delta; + } + else + { + // doesnt collide with wall + vector3df start = camera->getPosition(); + if ( player->WeaponNode ) + { + //start.X += 10.f; + //start.Y += -5.f; + //start.Z += 1.f; + } + + vector3df end = (camera->getTarget() - start); + end.normalize(); + start += end*20.0f; + end = start + (end * camera->getFarValue()); + } + + // create fire ball + ISceneNode* node = 0; + node = smgr->addBillboardSceneNode( BulletParent,dimension2d(10,10), start); + + node->setMaterialFlag(EMF_LIGHTING, false); + node->setMaterialTexture(0, Game->Device->getVideoDriver()->getTexture("fireball.bmp")); + node->setMaterialType(EMT_TRANSPARENT_ADD_COLOR); + + f32 length = (f32)(end - start).getLength(); + const f32 speed = 5.8f; + u32 time = (u32)(length / speed); + + ISceneNodeAnimator* anim = 0; + + // set flight line + + anim = smgr->createFlyStraightAnimator(start, end, time); + node->addAnimator(anim); + anim->drop(); + + snprintf ( buf, 64, "bullet: %s on %.1f,%1.f,%1.f", + imp.when ? "hit" : "nohit", end.X, end.Y, end.Z ); + node->setName ( buf ); + + + anim = smgr->createDeleteAnimator(time); + node->addAnimator(anim); + anim->drop(); + + if (imp.when) + { + // create impact note + imp.when = Game->Device->getTimer()->getTime() + + (time + (s32) ( ( 1.f + Noiser::get() ) * 250.f )); + Impacts.push_back(imp); + } + + // play sound +} + +/*! +*/ +void CQuake3EventHandler::createParticleImpacts( u32 now ) +{ + ISceneManager* sm = Game->Device->getSceneManager(); + + struct smokeLayer + { + const c8 * texture; + f32 scale; + f32 minparticleSize; + f32 maxparticleSize; + f32 boxSize; + u32 minParticle; + u32 maxParticle; + u32 fadeout; + u32 lifetime; + }; + + smokeLayer smoke[] = + { + { "smoke2.jpg", 0.4f, 1.5f, 18.f, 20.f, 20, 50, 2000, 10000 }, + { "smoke3.jpg", 0.2f, 1.2f, 15.f, 20.f, 10, 30, 1000, 12000 } + }; + + + u32 i; + u32 g; + s32 factor = 1; + for ( g = 0; g != 2; ++g ) + { + smoke[g].minParticle *= factor; + smoke[g].maxParticle *= factor; + smoke[g].lifetime *= factor; + smoke[g].boxSize *= Noiser::get() * 0.5f; + } + + for ( i=0; i < Impacts.size(); ++i) + { + if (now < Impacts[i].when) + continue; + + // create smoke particle system + IParticleSystemSceneNode* pas = 0; + + for ( g = 0; g != 2; ++g ) + { + pas = sm->addParticleSystemSceneNode(false, BulletParent, -1, Impacts[i].pos); + + snprintf ( buf, 64, "bullet impact smoke at %.1f,%.1f,%1.f", + Impacts[i].pos.X,Impacts[i].pos.Y,Impacts[i].pos.Z); + pas->setName ( buf ); + + // create a flat smoke + vector3df direction = Impacts[i].outVector; + direction *= smoke[g].scale; + IParticleEmitter* em = pas->createBoxEmitter( + aabbox3d(-4.f,0.f,-4.f,20.f,smoke[g].minparticleSize,20.f), + direction,smoke[g].minParticle, smoke[g].maxParticle, + video::SColor(0,0,0,0),video::SColor(0,128,128,128), + 250,4000, 60); + + em->setMinStartSize (dimension2d( smoke[g].minparticleSize, smoke[g].minparticleSize)); + em->setMaxStartSize (dimension2d( smoke[g].maxparticleSize, smoke[g].maxparticleSize)); + + pas->setEmitter(em); + em->drop(); + + // particles get invisible + IParticleAffector* paf = pas->createFadeOutParticleAffector( + video::SColor ( 0, 0, 0, 0 ), smoke[g].fadeout); + pas->addAffector(paf); + paf->drop(); + + // particle system life time + ISceneNodeAnimator* anim = sm->createDeleteAnimator( smoke[g].lifetime); + pas->addAnimator(anim); + anim->drop(); + + pas->setMaterialFlag(video::EMF_LIGHTING, false); + pas->setMaterialType(video::EMT_TRANSPARENT_VERTEX_ALPHA ); + pas->setMaterialTexture(0, Game->Device->getVideoDriver()->getTexture( smoke[g].texture )); + } + + + // play impact sound + #ifdef USE_IRRKLANG +/* + if (irrKlang) + { + audio::ISound* sound = + irrKlang->play3D(impactSound, Impacts[i].pos, false, false, true); + + if (sound) + { + // adjust max value a bit to make to sound of an impact louder + sound->setMinDistance(400); + sound->drop(); + } + } +*/ + #endif + + + // delete entry + Impacts.erase(i); + i--; + } +} + +/* + render +*/ +void CQuake3EventHandler::Render() +{ + IVideoDriver * driver = Game->Device->getVideoDriver(); + if ( 0 == driver ) + return; + + driver->beginScene(true, true, SColor(0,0,0,0)); + Game->Device->getSceneManager ()->drawAll(); + Game->Device->getGUIEnvironment()->drawAll(); + driver->endScene(); +} + +/* + update the generic scene node +*/ +void CQuake3EventHandler::Animate() +{ + u32 now = Game->Device->getTimer()->getTime(); + + + Q3Player * player = Player + 0; + + checkTimeFire ( player->Anim, 4, now ); + + // Query Scene Manager attributes + if ( player->Anim[0].flags & FIRED ) + { + ISceneManager *smgr = Game->Device->getSceneManager (); + wchar_t *msg = (wchar_t*) buf; + IVideoDriver * driver = Game->Device->getVideoDriver(); + + io::IAttributes * attr = smgr->getParameters(); + swprintf ( msg, 128, + L"Q3 %s [%s], FPS:%03d Tri:%.03fm Cull %d/%d nodes (%d,%d,%d)", + Game->CurrentMapName.c_str(), + driver->getName(), + driver->getFPS (), + (f32) driver->getPrimitiveCountDrawn( 0 ) * ( 1.f / 1000000.f ), + attr->getAttributeAsInt ( "culled" ), + attr->getAttributeAsInt ( "calls" ), + attr->getAttributeAsInt ( "drawn_solid" ), + attr->getAttributeAsInt ( "drawn_transparent" ), + attr->getAttributeAsInt ( "drawn_transparent_effect" ) + ); + Game->Device->setWindowCaption( msg ); + + swprintf ( msg, 128, + L"%03d fps, F1 GUI on/off, F2 respawn, F3-F6 toggle Nodes, F7 Collision on/off" + L", F8 Gravity on/off, Right Mouse Toggle GUI", + Game->Device->getVideoDriver()->getFPS () + ); + if ( gui.StatusLine ) + gui.StatusLine->setText ( msg ); + player->Anim[0].flags &= ~FIRED; + } + + // idle.. + if ( player->Anim[1].flags & FIRED ) + { + if ( strcmp ( player->animation, "idle" ) ) + player->setAnim ( "idle" ); + + player->Anim[1].flags &= ~FIRED; + } + + createParticleImpacts ( now ); + +} + + +/*! +*/ +void runGame ( GameData *game ) +{ + if ( game->retVal >= 3 ) + return; + + game->Device = (*game->createExDevice) ( game->deviceParam ); + if ( 0 == game->Device) + { + // could not create selected driver. + game->retVal = 0; + return; + } + + // these files are needed to run the explorer + io::IFileSystem *fs = game->Device->getFileSystem(); + + // create an event receiver based on current game data + CQuake3EventHandler *eventHandler = new CQuake3EventHandler( game ); + + //! add our media directory and archive to the file system + for ( u32 i = 0; i < game->CurrentArchiveList.size(); ++i ) + { + eventHandler->AddArchive ( game->CurrentArchiveList[i] ); + } + + eventHandler->AddSky ( 1, "skydome2" ); + eventHandler->CreatePlayers (); + eventHandler->CreateGUI (); + eventHandler->SetGUIActive ( 1 ); + background_music ( "IrrlichtTheme.ogg" ); + + game->retVal = 3; + while( game->Device->run() ) + { + eventHandler->Animate (); + eventHandler->Render (); + if (! game->Device->isWindowActive()) + game->Device->yield(); + } + + game->Device->setGammaRamp ( 1.f, 1.f, 1.f, 0.f, 0.f ); + delete eventHandler; +} + +#if defined (_IRR_WINDOWS_) && 0 + #pragma comment(linker, "/subsystem:windows /ENTRY:mainCRTStartup") +#endif + +/*! +*/ +s32 IRRCALLCONV main(int argc, char* argv[]) +{ + GameData game ( deletePathFromPath ( core::string (argv[0]), 1 ) ); + + // dynamically load irrlicht + const c8 * dllName = argc > 1 ? argv[1] : "irrlicht.dll"; + game.createExDevice = load_createDeviceEx ( dllName ); + if ( 0 == game.createExDevice ) + { + game.retVal = 3; + printf ( "Could not load %s.\n", dllName ); + return game.retVal; // could not load dll + } + + // start without asking for driver + game.retVal = 1; + do + { + // if driver could not created, ask for another driver + if ( game.retVal == 0 ) + { + game.setDefault (); + printf("Please select the driver you want for this example:\n"\ + " (a) Direct3D 9.0c\n (b) Direct3D 8.1\n (c) OpenGL 1.5\n"\ + " (d) Software Renderer\n (e) Burning's Video (TM) Thomas Alten\n"\ + " (otherKey) exit\n\n"); + + char i = 'a'; + std::cin >> i; + + switch(i) + { + case 'a': game.deviceParam.DriverType = EDT_DIRECT3D9;break; + case 'b': game.deviceParam.DriverType = EDT_DIRECT3D8;break; + case 'c': game.deviceParam.DriverType = EDT_OPENGL; break; + case 'd': game.deviceParam.DriverType = EDT_SOFTWARE; break; + case 'e': game.deviceParam.DriverType = EDT_BURNINGSVIDEO;break; + default: game.retVal = 3; break; + } + } + runGame ( &game ); + } while ( game.retVal < 3 ); + + return game.retVal; +} + +/* +**/ + + diff --git a/examples/21.Quake3Explorer/q3factory.cpp b/examples/21.Quake3Explorer/q3factory.cpp new file mode 100644 index 00000000..be3e102c --- /dev/null +++ b/examples/21.Quake3Explorer/q3factory.cpp @@ -0,0 +1,739 @@ +/*! + Model Factory. + create the additional scenenodes for ( bullets, health... ) + + Defines the Entities for Quake3 +*/ + +#include "q3factory.h" +#include "sound.h" + +using namespace irr; +using namespace scene; +using namespace gui; +using namespace video; +using namespace core; +using namespace quake3; + +//! This list is based on the original quake3. +static const SItemElement Quake3ItemElement [] = { +{ "item_health", + "models/powerups/health/medium_cross.md3", + "models/powerups/health/medium_sphere.md3", + "sound/items/n_health.wav", + "icons/iconh_yellow", + "25 Health", + 25, + HEALTH, + SUB_NONE +}, +{ "item_health_large", + "models/powerups/health/large_cross.md3", + "models/powerups/health/large_sphere.md3", + "sound/items/l_health.wav", + "icons/iconh_red", + "50 Health", + 50, + HEALTH, + SUB_NONE +}, +{ + "item_health_mega", + "models/powerups/health/mega_cross.md3", + "models/powerups/health/mega_sphere.md3", + "sound/items/m_health.wav", + "icons/iconh_mega", + "Mega Health", + 100, + HEALTH, + SUB_NONE, +}, +{ + "item_health_small", + "models/powerups/health/small_cross.md3", + "models/powerups/health/small_sphere.md3", + "sound/items/s_health.wav", + "icons/iconh_green", + "5 Health", + 5, + HEALTH, + SUB_NONE, +}, +{ "ammo_bullets", + "models/powerups/ammo/machinegunam.md3", + "", + "sound/misc/am_pkup.wav", + "icons/icona_machinegun", + "Bullets", + 50, + AMMO, + MACHINEGUN +}, +{ + "ammo_cells", + "models/powerups/ammo/plasmaam.md3", + "", + "sound/misc/am_pkup.wav", + "icons/icona_plasma", + "Cells", + 30, + AMMO, + PLASMAGUN, +}, +{ "ammo_rockets", + "models/powerups/ammo/rocketam.md3", + "", + "", + "icons/icona_rocket", + "Rockets", + 5, + AMMO, + ROCKET_LAUNCHER, +}, +{ + "ammo_shells", + "models/powerups/ammo/shotgunam.md3", + "", + "sound/misc/am_pkup.wav", + "icons/icona_shotgun", + "Shells", + 10, + AMMO, + SHOTGUN, +}, +{ + "ammo_slugs", + "models/powerups/ammo/railgunam.md3", + "", + "sound/misc/am_pkup.wav", + "icons/icona_railgun", + "Slugs", + 10, + AMMO, + RAILGUN, +}, +{ + "item_armor_body", + "models/powerups/armor/armor_red.md3", + "", + "sound/misc/ar2_pkup.wav", + "icons/iconr_red", + "Heavy Armor", + 100, + ARMOR, + SUB_NONE, +}, +{ + "item_armor_combat", + "models/powerups/armor/armor_yel.md3", + "", + "sound/misc/ar2_pkup.wav", + "icons/iconr_yellow", + "Armor", + 50, + ARMOR, + SUB_NONE, +}, +{ + "item_armor_shard", + "models/powerups/armor/shard.md3", + "", + "sound/misc/ar1_pkup.wav", + "icons/iconr_shard", + "Armor Shard", + 5, + ARMOR, + SUB_NONE, +}, +{ + "weapon_gauntlet", + "models/weapons2/gauntlet/gauntlet.md3", + "", + "sound/misc/w_pkup.wav", + "icons/iconw_gauntlet", + "Gauntlet", + 0, + WEAPON, + GAUNTLET, +}, +{ + "weapon_shotgun", + "models/weapons2/shotgun/shotgun.md3", + "", + "sound/misc/w_pkup.wav", + "icons/iconw_shotgun", + "Shotgun", + 10, + WEAPON, + SHOTGUN, +}, +{ + "weapon_machinegun", + "models/weapons2/machinegun/machinegun.md3", + "", + "sound/misc/w_pkup.wav", + "icons/iconw_machinegun", + "Machinegun", + 40, + WEAPON, + MACHINEGUN, +}, +{ + "weapon_grenadelauncher", + "models/weapons2/grenadel/grenadel.md3", + "", + "sound/misc/w_pkup.wav", + "icons/iconw_grenade", + "Grenade Launcher", + 10, + WEAPON, + GRENADE_LAUNCHER, +}, +{ + "weapon_rocketlauncher", + "models/weapons2/rocketl/rocketl.md3", + "", + "sound/misc/w_pkup.wav", + "icons/iconw_rocket", + "Rocket Launcher", + 10, + WEAPON, + ROCKET_LAUNCHER, +}, +{ + "weapon_lightning", + "models/weapons2/lightning/lightning.md3", + "", + "sound/misc/w_pkup.wav", + "icons/iconw_lightning", + "Lightning Gun", + 100, + WEAPON, + LIGHTNING, +}, +{ + "weapon_railgun", + "models/weapons2/railgun/railgun.md3", + "", + "sound/misc/w_pkup.wav", + "icons/iconw_railgun", + "Railgun", + 10, + WEAPON, + RAILGUN, +}, +{ + "weapon_plasmagun", + "models/weapons2/plasma/plasma.md3", + "", + "sound/misc/w_pkup.wav", + "icons/iconw_plasma", + "Plasma Gun", + 50, + WEAPON, + PLASMAGUN, +}, +{ + "weapon_bfg", + "models/weapons2/bfg/bfg.md3", + "", + "sound/misc/w_pkup.wav", + "icons/iconw_bfg", + "BFG10K", + 20, + WEAPON, + BFG, +}, +{ + "weapon_grapplinghook", + "models/weapons2/grapple/grapple.md3", + "", + "sound/misc/w_pkup.wav", + "icons/iconw_grapple", + "Grappling Hook", + 0, + WEAPON, + GRAPPLING_HOOK, +}, +{ + "" +} + +}; + +/*! +*/ +const SItemElement * getItemElement ( const stringc& key ) +{ + const SItemElement *item = Quake3ItemElement; + + while ( item->key[0] ) + { + if ( 0 == strcmp ( key.c_str(), item->key ) ) + return item; + item += 1; + } + return 0; +} + +/*! + Quake3 Model Factory. + Takes the mesh buffers and creates scenenodes for their associated shaders +*/ +void Q3ShaderFactory ( Q3LevelLoadParameter &loadParam, + IrrlichtDevice *device, + IQ3LevelMesh* mesh, + eQ3MeshIndex meshIndex, + ISceneNode *parent, + IMetaTriangleSelector *meta, + bool showShaderName ) +{ + if ( 0 == mesh || 0 == device ) + return; + + IMeshSceneNode* node = 0; + ISceneManager* smgr = device->getSceneManager(); + ITriangleSelector * selector = 0; + + // the additional mesh can be quite huge and is unoptimized + // Save to cast to SMesh + SMesh * additional_mesh = (SMesh*) mesh->getMesh ( meshIndex ); + if ( 0 == additional_mesh || additional_mesh->getMeshBufferCount() == 0) + return; + + char buf[128]; + if ( loadParam.verbose > 0 ) + { + loadParam.startTime = device->getTimer()->getRealTime(); + if ( loadParam.verbose > 1 ) + { + snprintf(buf, 128, "q3shaderfactory start" ); + device->getLogger()->log( buf, ELL_INFORMATION); + } + } + + IGUIFont *font = 0; + if ( showShaderName ) + font = device->getGUIEnvironment()->getFont("fontlucida.png"); + + IVideoDriver *driver = device->getVideoDriver(); + + // create helper textures + if ( 1 ) + { + tTexArray tex; + u32 pos = 0; + getTextures ( tex, "$redimage $blueimage $whiteimage $checkerimage", pos, + device->getFileSystem(), driver ); + } + + s32 sceneNodeID = 0; + for ( u32 i = 0; i!= additional_mesh->getMeshBufferCount (); ++i ) + { + IMeshBuffer *meshBuffer = additional_mesh->getMeshBuffer ( i ); + const SMaterial &material = meshBuffer->getMaterial(); + + //! The ShaderIndex is stored in the second material parameter + s32 shaderIndex = (s32) material.MaterialTypeParam2; + + // the meshbuffer can be rendered without additional support, or it has no shader + IShader *shader = (IShader *) mesh->getShader ( shaderIndex ); + + // no shader, or mapped to existing material + if ( 0 == shader ) + { + +#if 1 + // clone mesh + SMesh * m = new SMesh (); + m->addMeshBuffer ( meshBuffer ); + SMaterial &mat = m->getMeshBuffer( 0 )->getMaterial(); + if ( mat.getTexture( 0 ) == 0 ) + mat.setTexture ( 0, driver->getTexture ( "$blueimage" ) ); + if ( mat.getTexture( 1 ) == 0 ) + mat.setTexture ( 1, driver->getTexture ( "$redimage" ) ); + + IMesh * store = smgr->getMeshManipulator ()->createMeshWith2TCoords ( m ); + m->drop(); + + node = smgr->addMeshSceneNode ( store, parent, sceneNodeID ); + node->setAutomaticCulling ( scene::EAC_OFF ); + store->drop (); + sceneNodeID += 1; +#endif + } + else if ( 1 ) + { +/* + stringc s; + dumpShader ( s, shader ); + printf ( s.c_str () ); +*/ + // create sceneNode + node = smgr->addQuake3SceneNode ( meshBuffer, shader, parent, sceneNodeID ); + node->setAutomaticCulling ( scene::EAC_FRUSTUM_BOX ); + sceneNodeID += 1; + } + + // show Debug Shader Name + if ( showShaderName && node ) + { + IBillboardTextSceneNode* node2 = 0; + swprintf ( (wchar_t*) buf, 64, L"%hs:%d", node->getName(),node->getID() ); + node2 = smgr->addBillboardTextSceneNode( + font, + (wchar_t*) buf, + node, + dimension2d(80.0f, 8.0f), + vector3df(0, 10, 0), + sceneNodeID + ); + snprintf ( buf, 64, "%hs:%d", node->getName(),node->getID() ); + //node2->setName ( buf ); + sceneNodeID += 1; + } + + // create Portal Rendertargets + if ( shader ) + { + const SVarGroup *group = shader->getGroup(1); + if ( group->isDefined( "surfaceparm", "portal" ) ) + { + } + + } + + + // add collision + // find out if shader is marked als nonsolid + u8 doCreate = meta !=0 ; + + if ( shader ) + { + const SVarGroup *group = shader->getGroup(1); + if ( group->isDefined( "surfaceparm", "trans" ) + // || group->isDefined( "surfaceparm", "sky" ) + // || group->isDefined( "surfaceparm", "nonsolid" ) + ) + { + if ( !group->isDefined( "surfaceparm", "metalsteps" ) ) + { + doCreate = 0; + } + } + } + + if ( doCreate ) + { + IMesh *m = 0; + + //! controls if triangles are modified by the scenenode during runtime + bool takeOriginal = true; + + if ( takeOriginal ) + { + m = new SMesh; + ((SMesh*) m )->addMeshBuffer (meshBuffer); + } + else + { + m = node->getMesh(); + } + + //selector = smgr->createOctTreeTriangleSelector ( m, 0, 128 ); + selector = smgr->createTriangleSelector ( m, 0 ); + meta->addTriangleSelector ( selector ); + selector->drop (); + + if ( takeOriginal ) + { + delete m; + } + } + + } + +#if 0 + if ( meta ) + { + selector = smgr->createOctTreeTriangleSelector ( additional_mesh, 0 ); + meta->addTriangleSelector ( selector ); + selector->drop (); + } +#endif + + if ( loadParam.verbose > 0 ) + { + loadParam.endTime = device->getTimer()->getRealTime (); + snprintf(buf, 128, "q3shaderfactory needed %04d ms to create %d shader nodes", + loadParam.endTime - loadParam.startTime, + sceneNodeID + ); + device->getLogger()->log(buf, ELL_INFORMATION); + } + +} + + +/*! +*/ +void Q3ModelFactory ( Q3LevelLoadParameter &loadParam, + IrrlichtDevice *device, + IQ3LevelMesh* masterMesh, + ISceneNode *parent + ) +{ + if ( 0 == masterMesh ) + return; + + tQ3EntityList &entity = masterMesh->getEntityList (); + ISceneManager* smgr = device->getSceneManager(); + + + char buf[128]; + const SVarGroup *group; + SEntity search; + s32 index; + s32 lastIndex; + +/* + stringc s; + FILE *f = 0; + f = fopen ( "entity.txt", "wb" ); + for ( index = 0; (u32) index < entityList.size (); ++index ) + { + const SEntity *entity = &entityList[ index ]; + s = entity->name; + dumpShader ( s, entity ); + fwrite ( s.c_str(), 1, s.size(), f ); + } + fclose ( f ); +*/ + IAnimatedMeshMD3* model; + SMD3Mesh * mesh; + const SMD3MeshBuffer *meshBuffer; + IMeshSceneNode* node; + const IShader *shader; + u32 pos; + vector3df p; + + + const SItemElement *itemElement; + + // walk list + for ( index = 0; (u32) index < entity.size(); ++index ) + { + itemElement = getItemElement ( entity[index].name ); + if ( 0 == itemElement ) + continue; + + pos = 0; + p = getAsVector3df ( entity[index].getGroup(1)->get ( "origin" ), pos ); + + for ( u32 g = 0; g < 2; ++g ) + { + if ( 0 == itemElement->model[g] || itemElement->model[g][0] == 0 ) + continue; + model = (IAnimatedMeshMD3*) smgr->getMesh( itemElement->model[g] ); + if ( 0 == model ) + continue; + + mesh = model->getOriginalMesh(); + for ( u32 j = 0; j != mesh->Buffer.size (); ++j ) + { + meshBuffer = mesh->Buffer[j]; + if ( 0 == meshBuffer ) + continue; + + shader = masterMesh->getShader ( meshBuffer->Shader, false ); + if ( 0 == shader ) + { + snprintf ( buf, 128, "q3ModelFactory shader %s failed", meshBuffer->Shader.c_str() ); + device->getLogger()->log ( buf ); + continue; + } + + node = smgr->addQuake3SceneNode ( model->getMesh(0)->getMeshBuffer(j), shader, parent ); + if ( 0 == node ) + continue; + + node->setName ( shader->name.c_str () ); + node->setPosition ( p ); + } + } + } + + // music + search.name = "worldspawn"; + index = entity.binary_search_multi ( search, lastIndex ); + + if ( index >= 0 ) + { + group = entity[ index ].getGroup(1); + background_music ( group->get ( "music" ).c_str () ); + } + + // music + search.name = "worldspawn"; + index = entity.binary_search_multi ( search, lastIndex ); + + if ( index >= 0 ) + { + group = entity[ index ].getGroup(1); + background_music ( group->get ( "music" ).c_str () ); + } + + //IAnimatedMesh* mesh = smgr->getMesh("../../media/sydney.md2"); + //IAnimatedMeshSceneNode* node = smgr->addAnimatedMeshSceneNode( mesh ); + +} + +/*! + 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" +*/ +s32 Q3StartPosition ( IQ3LevelMesh* mesh, + ICameraSceneNode* camera, + s32 startposIndex, + const vector3df &translation + ) +{ + if ( 0 == mesh ) + return 0; + + tQ3EntityList &entityList = mesh->getEntityList (); + + SEntity search; + search.name = "info_player_start"; // "info_player_deathmatch"; + + // find all entities in the multi-list + s32 lastIndex; + s32 index = entityList.binary_search_multi ( search, lastIndex ); + + if ( index < 0 ) + { + search.name = "info_player_deathmatch"; + index = entityList.binary_search_multi ( search, lastIndex ); + } + + if ( index < 0 ) + return 0; + + index += core::clamp ( startposIndex, 0, lastIndex - index ); + + u32 parsepos; + + const SVarGroup *group; + group = entityList[ index ].getGroup(1); + + parsepos = 0; + vector3df pos = getAsVector3df ( group->get ( "origin" ), parsepos ); + pos += translation; + + parsepos = 0; + f32 angle = getAsFloat ( group->get ( "angle"), parsepos ); + + vector3df target ( 0.f, 0.f, 1.f ); + target.rotateXZBy ( angle - 90.f, vector3df () ); + + if ( camera ) + { + camera->setPosition ( pos ); + camera->setTarget ( pos + target ); + //! New. FPSCamera and animators catches reset on animate 0 + camera->OnAnimate ( 0 ); + } + return lastIndex - index + 1; +} + + +/*! + gets a accumulated force on a given surface +*/ +vector3df getGravity ( const c8 * surface ) +{ + if ( 0 == strcmp ( surface, "earth" ) ) return vector3df ( 0.f, -90.f, 0.f ); + if ( 0 == strcmp ( surface, "moon" ) ) return vector3df ( 0.f, -6.f / 100.f, 0.f ); + if ( 0 == strcmp ( surface, "water" ) ) return vector3df ( 0.1f / 100.f, -2.f / 100.f, 0.f ); + if ( 0 == strcmp ( surface, "ice" ) ) return vector3df ( 0.2f / 100.f, -9.f / 100.f, 0.3f / 100.f ); + + return vector3df ( 0.f, 0.f, 0.f ); +} + + + +/* + Dynamically load the Irrlicht Library +*/ + +#if defined(_IRR_WINDOWS_API_) && 1 +#include + +funcptr_createDevice load_createDevice ( const c8 * filename) +{ + return (funcptr_createDevice) GetProcAddress ( LoadLibrary ( filename ), "createDevice" ); +} + +funcptr_createDeviceEx load_createDeviceEx ( const c8 * filename) +{ + return (funcptr_createDeviceEx) GetProcAddress ( LoadLibrary ( filename ), "createDeviceEx" ); +} + +#else + +// TODO: Dynamic Loading for other os +#pragma comment(lib, "Irrlicht.lib") + +funcptr_createDevice load_createDevice ( const c8 * filename) +{ + return createDevice; +} + +funcptr_createDeviceEx load_createDeviceEx ( const c8 * filename) +{ + return createDeviceEx; +} + +#endif + +/* + get the current collision respone camera animator +*/ +ISceneNodeAnimatorCollisionResponse* camCollisionResponse( IrrlichtDevice * device ) +{ + ICameraSceneNode *camera = device->getSceneManager()->getActiveCamera(); + ISceneNodeAnimatorCollisionResponse *a = 0; + + list::ConstIterator it = camera->getAnimators().begin(); + for (; it != camera->getAnimators().end(); ++it) + { + a = (ISceneNodeAnimatorCollisionResponse*) (*it); + if ( a->getType() == ESNAT_COLLISION_RESPONSE ) + return a; + } + + return 0; +} + + +//! internal Animation +void setTimeFire ( TimeFire *t, u32 delta, u32 flags ) +{ + t->flags = flags; + t->next = 0; + t->delta = delta; +} + + +void checkTimeFire ( TimeFire *t, u32 listSize, u32 now ) +{ + u32 i; + for ( i = 0; i < listSize; ++i ) + { + if ( now < t[i].next ) + continue; + + t[i].next = core::max_ ( now + t[i].delta, t[i].next + t[i].delta ); + t[i].flags |= FIRED; + } +} diff --git a/examples/21.Quake3Explorer/q3factory.h b/examples/21.Quake3Explorer/q3factory.h new file mode 100644 index 00000000..b4db3e77 --- /dev/null +++ b/examples/21.Quake3Explorer/q3factory.h @@ -0,0 +1,142 @@ +/*! + Model Factory. + create the additional scenenodes for ( bullets, health... ) + + Defines the Entities for Quake3 +*/ +#ifndef __QUAKE3_FACTORY__H_INCLUDED__ +#define __QUAKE3_FACTORY__H_INCLUDED__ + +#include + + +using namespace irr; +using namespace scene; +using namespace gui; +using namespace video; +using namespace core; +using namespace quake3; + + + +//! Defines to which group the entities belong +enum eItemGroup +{ + WEAPON, + AMMO, + ARMOR, + HEALTH, + POWERUP +}; + +//! define a supgroup for the item. for e.q the Weapons +enum eItemSubGroup +{ + SUB_NONE = 0, + GAUNTLET, + MACHINEGUN, + SHOTGUN, + GRENADE_LAUNCHER, + ROCKET_LAUNCHER, + LIGHTNING, + RAILGUN, + PLASMAGUN, + BFG, + GRAPPLING_HOOK, + NAILGUN, + PROX_LAUNCHER, + CHAINGUN, +}; + +// a List for defining a model +struct SItemElement +{ + const c8 *key; + const c8 *model[2]; + const c8 *sound; + const c8 *icon; + const c8 *pickup; + s32 value; + eItemGroup group; + eItemSubGroup sub; +}; + + +/*! + Get's an entity based on it's key +*/ +const SItemElement * getItemElement ( const stringc& key ); + +/*! + Quake3 Model Factory. + Takes the mesh buffers and creates scenenodes for their associated shaders +*/ +void Q3ShaderFactory ( Q3LevelLoadParameter &loadParam, + IrrlichtDevice *device, + IQ3LevelMesh* mesh, + eQ3MeshIndex meshIndex, + ISceneNode *parent, + IMetaTriangleSelector *meta, + bool showShaderName + ); + + +/*! + Creates Model based on the entity list +*/ +void Q3ModelFactory ( Q3LevelLoadParameter &loadParam, + IrrlichtDevice *device, + IQ3LevelMesh* masterMesh, + ISceneNode *parent + ); + +/*! + 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" +*/ +s32 Q3StartPosition ( IQ3LevelMesh* mesh, + ICameraSceneNode* camera, + s32 startposIndex, + const vector3df &translation + ); +/*! + gets a accumulated force on a given surface +*/ +vector3df getGravity ( const c8 * surface ); + + +/* + Dynamically load the Irrlicht Library +*/ +funcptr_createDevice load_createDevice ( const c8 * filename); +funcptr_createDeviceEx load_createDeviceEx ( const c8 * filename); + + +//! Macro for save Dropping an Element +#define dropElement(x) if (x) { x->remove(); x = 0; } + + +/* + get the current collision respone camera animator +*/ +ISceneNodeAnimatorCollisionResponse* camCollisionResponse( IrrlichtDevice * device ); + +//! internal Animation +enum eTimeFireFlag +{ + FIRED = 1, +}; + +struct TimeFire +{ + u32 flags; + u32 next; + u32 delta; +}; + +void setTimeFire ( TimeFire *t, u32 delta, u32 flags = 0 ); +void checkTimeFire ( TimeFire *t, u32 listSize, u32 now ); + +#endif // __QUAKE3_FACTORY__H_INCLUDED__ + + diff --git a/examples/21.Quake3Explorer/sound.cpp b/examples/21.Quake3Explorer/sound.cpp new file mode 100644 index 00000000..75615c1d --- /dev/null +++ b/examples/21.Quake3Explorer/sound.cpp @@ -0,0 +1,98 @@ +/*! + Sound Factory. + provides a sound interface + +*/ + +#include "sound.h" + + +//#define USE_IRRKLANG + +#ifdef USE_IRRKLANG + +#include +#ifdef _IRR_WINDOWS_ + #pragma comment (lib, "irrKlang.lib") +#endif + +using namespace irrklang; + +struct soundfile: public IFileReader +{ + soundfile ( io::IReadFile* f ): file (f ) {} + virtual ~soundfile () { file->drop (); } + + virtual ik_s32 read(void* buffer, ik_u32 sizeToRead) { return file->read ( buffer, sizeToRead ); } + virtual bool seek(ik_s32 finalPos, bool relativeMovement = false) { return file->seek ( finalPos, relativeMovement ); } + virtual ik_s32 getSize(){ return file->getSize (); } + virtual ik_s32 getPos() {return file->getPos (); } + virtual const ik_c8* getFileName() { return file->getFileName (); } + io::IReadFile* file; +}; + +struct klangFactory : public irrklang::IFileFactory +{ + klangFactory ( IrrlichtDevice *device ) { Device = device; } + + virtual irrklang::IFileReader* createFileReader(const ik_c8* filename) + { + io::IReadFile* file = Device->getFileSystem()->createAndOpenFile(filename); + if ( 0 == file ) + return 0; + + return new soundfile ( file ); + } + + IrrlichtDevice *Device; +}; + +ISoundEngine *engine = 0; +ISound *backMusic = 0; + +void sound_init ( IrrlichtDevice *device ) +{ + engine = createIrrKlangDevice (); + if ( 0 == engine ) + return; + + klangFactory *f = new klangFactory ( device ); + engine->addFileFactory ( f ); +} + +void sound_shutdown () +{ + if ( backMusic ) + backMusic->drop (); + + if ( engine ) + engine->drop (); +} + +void background_music ( const c8 * file ) +{ + if ( 0 == engine ) + return; + + if ( backMusic ) + { + backMusic->stop (); + backMusic->drop (); + } + + backMusic = engine->play2D ( file, true, false, true ); + + if ( backMusic ) + { + backMusic->setVolume ( 0.5f ); + } +} + +#else + +void sound_init ( IrrlichtDevice *device ) {} +void sound_shutdown () {} +void background_music ( const c8 * file ) {} + +#endif + diff --git a/examples/21.Quake3Explorer/sound.h b/examples/21.Quake3Explorer/sound.h new file mode 100644 index 00000000..033e9bb6 --- /dev/null +++ b/examples/21.Quake3Explorer/sound.h @@ -0,0 +1,18 @@ +/*! + Sound Factory. + provides a sound interface + +*/ +#ifndef __QUAKE3_SOUND__H_INCLUDED__ +#define __QUAKE3_SOUND__H_INCLUDED__ + +#include + +using namespace irr; + +void sound_init ( IrrlichtDevice *device ); +void sound_shutdown (); +void background_music ( const c8 * file ); + + +#endif // __QUAKE3_SOUND__H_INCLUDED__ diff --git a/examples/BuildAllExamples_v7.sln b/examples/BuildAllExamples_v7.sln index bb9897ae..8cacce69 100644 --- a/examples/BuildAllExamples_v7.sln +++ b/examples/BuildAllExamples_v7.sln @@ -75,8 +75,17 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "16.Quake3MapShader", "16.Qu EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "19.MouseAndJoystick", "19.MouseAndJoystick\MouseAndJoystick.vcproj", "{1AB9413E-4F53-42A3-8CB2-CB4BE22336D0}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "20.ManagedLights_vc8", "20.ManagedLights\ManagedLights_vc8.vcproj", "{16007FE2-142B-47F8-93E1-519BA3F39E71}" +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "20.ManagedLights", "20.ManagedLights\ManagedLights_vc7.vcproj", "{16007FE2-142B-47F8-93E1-519BA3F39E71}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "21.Quake3Explorer", "21.Quake3Explorer\Quake3Explorer_vc7.vcproj", "{CDC4AAA9-72E1-4FFA-A04D-7EF59D8B97CD}" + ProjectSection(ProjectDependencies) = postProject + {E08E042A-6C45-411B-92BE-3CC31331019F} = {E08E042A-6C45-411B-92BE-3CC31331019F} + EndProjectSection EndProject Global GlobalSection(SolutionConfiguration) = preSolution @@ -156,6 +165,16 @@ Global {EB3B38EA-5CE7-4983-845B-880661E69D09}.Debug.Build.0 = Debug|Win32 {EB3B38EA-5CE7-4983-845B-880661E69D09}.Release.ActiveCfg = Release|Win32 {EB3B38EA-5CE7-4983-845B-880661E69D09}.Release.Build.0 = Release|Win32 + {1AB9413E-4F53-42A3-8CB2-CB4BE22336D0}.Debug.ActiveCfg = Debug|Win32 + {1AB9413E-4F53-42A3-8CB2-CB4BE22336D0}.Release.ActiveCfg = Release|Win32 + {16007FE2-142B-47F8-93E1-519BA3F39E71}.Debug.ActiveCfg = Debug|Win32 + {16007FE2-142B-47F8-93E1-519BA3F39E71}.Debug.Build.0 = Debug|Win32 + {16007FE2-142B-47F8-93E1-519BA3F39E71}.Release.ActiveCfg = Release|Win32 + {16007FE2-142B-47F8-93E1-519BA3F39E71}.Release.Build.0 = Release|Win32 + {CDC4AAA9-72E1-4FFA-A04D-7EF59D8B97CD}.Debug.ActiveCfg = Debug|Win32 + {CDC4AAA9-72E1-4FFA-A04D-7EF59D8B97CD}.Debug.Build.0 = Debug|Win32 + {CDC4AAA9-72E1-4FFA-A04D-7EF59D8B97CD}.Release.ActiveCfg = Release|Win32 + {CDC4AAA9-72E1-4FFA-A04D-7EF59D8B97CD}.Release.Build.0 = Release|Win32 EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution EndGlobalSection diff --git a/examples/BuildAllExamples_v8.sln b/examples/BuildAllExamples_v8.sln index 44dd83c7..ea977559 100644 --- a/examples/BuildAllExamples_v8.sln +++ b/examples/BuildAllExamples_v8.sln @@ -6,6 +6,9 @@ EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "02.Quake3Map_vc8", "02.Quake3Map\Quake3Map_vc8.vcproj", "{D1A464A2-D479-458C-98A2-60965D823CD1}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "03.CustomSceneNode_vc8", "03.CustomSceneNode\CustomSceneNode_vc8.vcproj", "{171CCDFA-C140-4956-8EB7-F0168F4521D3}" + ProjectSection(ProjectDependencies) = postProject + {E08E042A-6C45-411B-92BE-3CC31331019F} = {E08E042A-6C45-411B-92BE-3CC31331019F} + EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "04.Movement_vc8", "04.Movement\Movement_vc8.vcproj", "{7BDBB7E8-E0C9-4A0D-83C1-D389D6140FEF}" EndProject @@ -43,6 +46,16 @@ EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "19.MouseAndJoystick_vc8", "19.MouseAndJoystick\MouseAndJoystick_vc8.vcproj", "{1AB9413E-4F53-42A3-8CB2-CB4BE22336D0}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "20.ManagedLights_vc8", "20.ManagedLights\ManagedLights_vc8.vcproj", "{16007FE2-142B-47F8-93E1-519BA3F39E71}" + ProjectSection(ProjectDependencies) = postProject + {E08E042A-6C45-411B-92BE-3CC31331019F} = {E08E042A-6C45-411B-92BE-3CC31331019F} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "21.Quake3Explorer_vc8", "21.Quake3Explorer\Quake3Explorer_vc8.vcproj", "{CDC4AAA9-72E1-4FFA-A04D-7EF59D8B97CD}" + ProjectSection(ProjectDependencies) = postProject + {E08E042A-6C45-411B-92BE-3CC31331019F} = {E08E042A-6C45-411B-92BE-3CC31331019F} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "17. HelloWorld for Windows Mobile on PC", "17.HelloWorld_Mobile\17. HelloWorld for Windows Mobile on PC_v8.vcproj", "{2A29B6B1-AFC4-46C7-9944-7052AAE66F7B}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -112,8 +125,8 @@ Global {78C9F424-523C-49AC-94B7-823AA4A26BF9}.Release|Win32.Build.0 = Release|Win32 {E08E042A-6C45-411B-92BE-3CC31331019F}.Debug|Win32.ActiveCfg = Debug|Win32 {E08E042A-6C45-411B-92BE-3CC31331019F}.Debug|Win32.Build.0 = Debug|Win32 - {E08E042A-6C45-411B-92BE-3CC31331019F}.Release|Win32.ActiveCfg = Release - Fast FPU|Win32 - {E08E042A-6C45-411B-92BE-3CC31331019F}.Release|Win32.Build.0 = Release - Fast FPU|Win32 + {E08E042A-6C45-411B-92BE-3CC31331019F}.Release|Win32.ActiveCfg = Release|Win32 + {E08E042A-6C45-411B-92BE-3CC31331019F}.Release|Win32.Build.0 = Release|Win32 {6F076455-D955-45D4-9C68-4AD4E45F2D47}.Debug|Win32.ActiveCfg = Debug|Win32 {6F076455-D955-45D4-9C68-4AD4E45F2D47}.Debug|Win32.Build.0 = Debug|Win32 {6F076455-D955-45D4-9C68-4AD4E45F2D47}.Release|Win32.ActiveCfg = Release|Win32 @@ -130,6 +143,14 @@ Global {16007FE2-142B-47F8-93E1-519BA3F39E71}.Debug|Win32.Build.0 = Debug|Win32 {16007FE2-142B-47F8-93E1-519BA3F39E71}.Release|Win32.ActiveCfg = Release|Win32 {16007FE2-142B-47F8-93E1-519BA3F39E71}.Release|Win32.Build.0 = Release|Win32 + {CDC4AAA9-72E1-4FFA-A04D-7EF59D8B97CD}.Debug|Win32.ActiveCfg = Debug|Win32 + {CDC4AAA9-72E1-4FFA-A04D-7EF59D8B97CD}.Debug|Win32.Build.0 = Debug|Win32 + {CDC4AAA9-72E1-4FFA-A04D-7EF59D8B97CD}.Release|Win32.ActiveCfg = Release|Win32 + {CDC4AAA9-72E1-4FFA-A04D-7EF59D8B97CD}.Release|Win32.Build.0 = Release|Win32 + {2A29B6B1-AFC4-46C7-9944-7052AAE66F7B}.Debug|Win32.ActiveCfg = Debug|Win32 + {2A29B6B1-AFC4-46C7-9944-7052AAE66F7B}.Debug|Win32.Build.0 = Debug|Win32 + {2A29B6B1-AFC4-46C7-9944-7052AAE66F7B}.Release|Win32.ActiveCfg = Release|Win32 + {2A29B6B1-AFC4-46C7-9944-7052AAE66F7B}.Release|Win32.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/examples/Demo/CDemo.cpp b/examples/Demo/CDemo.cpp index a9325b03..75e1b4c7 100644 --- a/examples/Demo/CDemo.cpp +++ b/examples/Demo/CDemo.cpp @@ -351,6 +351,9 @@ void CDemo::loadSceneData() video::IVideoDriver* driver = device->getVideoDriver(); scene::ISceneManager* sm = device->getSceneManager(); + // Quake3 Shader controls Z-Writing + sm->getParameters()->setAttribute(scene::ALLOW_ZWRITE_ON_TRANSPARENT, true); + quakeLevelMesh = (scene::IQ3LevelMesh*) sm->getMesh("maps/20kdm2.bsp"); if (quakeLevelMesh) @@ -399,7 +402,7 @@ void CDemo::loadSceneData() s32 shaderIndex = (s32) material.MaterialTypeParam2; // the meshbuffer can be rendered without additional support, or it has no shader - const scene::quake3::SShader *shader = quakeLevelMesh->getShader ( shaderIndex ); + const scene::quake3::IShader *shader = quakeLevelMesh->getShader ( shaderIndex ); if ( 0 == shader ) { continue; @@ -408,9 +411,6 @@ void CDemo::loadSceneData() sm->addQuake3SceneNode ( meshBuffer, shader ); } - // original mesh is not needed anymore - quakeLevelMesh->releaseMesh ( scene::quake3::E_Q3_MESH_ITEMS ); - } // load sydney model and create 2 instances @@ -482,7 +482,7 @@ void CDemo::loadSceneData() core::stringc tmp("../../media/portal"); tmp += g; tmp += ".bmp"; - video::ITexture* t = driver->getTexture( tmp.c_str () ); + video::ITexture* t = driver->getTexture( tmp ); textures.push_back(t); } diff --git a/examples/Demo/CMainMenu.cpp b/examples/Demo/CMainMenu.cpp index efbef0d4..a84b33fe 100644 --- a/examples/Demo/CMainMenu.cpp +++ b/examples/Demo/CMainMenu.cpp @@ -1,4 +1,4 @@ -// This is a Demo of the Irrlicht Engine (c) 2005-2009 by N.Gebhardt. +// This is a Demo of the Irrlicht Engine (c) 2005-2008 by N.Gebhardt. // This file is not documented. #include "CMainMenu.h" @@ -116,7 +116,7 @@ bool CMainMenu::run(bool& outFullscreen, bool& outMusic, bool& outShadows, box->addItem(L"OpenGL 1.5"); box->addItem(L"Direct3D 8.1"); box->addItem(L"Direct3D 9.0c"); - box->addItem(L"Burning's Video 0.39"); + box->addItem(L"Burning's Video 0.40"); box->addItem(L"Irrlicht Software Renderer 1.0"); box->setSelected(selected); diff --git a/include/EGUIElementTypes.h b/include/EGUIElementTypes.h index 30306d40..60d2316f 100644 --- a/include/EGUIElementTypes.h +++ b/include/EGUIElementTypes.h @@ -82,6 +82,9 @@ enum EGUI_ELEMENT_TYPE //! A window EGUIET_WINDOW, + //! A Tree View + EGUIET_TREE_VIEW, + //! Not an element, amount of elements in there EGUIET_COUNT, diff --git a/include/ESceneNodeTypes.h b/include/ESceneNodeTypes.h index a7148cd4..f76a8cea 100644 --- a/include/ESceneNodeTypes.h +++ b/include/ESceneNodeTypes.h @@ -66,6 +66,9 @@ namespace scene //! Particle System Scene Node ESNT_PARTICLE_SYSTEM = MAKE_IRR_ID('p','t','c','l'), + //! Quake3 Shader Scene Node + ESNT_Q3SHADER_SCENE_NODE = MAKE_IRR_ID('q','3','s','h'), + //! Quake3 Model Scene Node ( has tag to link to ) ESNT_MD3_SCENE_NODE = MAKE_IRR_ID('m','d','3','_'), diff --git a/include/IAnimatedMeshMD3.h b/include/IAnimatedMeshMD3.h index a260e102..9a81bf46 100644 --- a/include/IAnimatedMeshMD3.h +++ b/include/IAnimatedMeshMD3.h @@ -89,15 +89,15 @@ namespace scene struct SMD3Header { c8 headerID[4]; //id of file, always "IDP3" - s32 Version; //this is a version number, always 15 + s32 Version; //this is a version number, always 15 s8 fileName[68]; //sometimes left Blank... 65 chars, 32bit aligned == 68 chars - s32 numFrames; //number of KeyFrames - s32 numTags; //number of 'tags' per frame - s32 numMeshes; //number of meshes/skins - s32 numMaxSkins; //maximum number of unique skins used in md3 file - s32 headerSize; //always equal to the length of this header - s32 tagStart; //starting position of tag-structures - s32 tagEnd; //ending position of tag-structures/starting position of mesh-structures + s32 numFrames; //number of KeyFrames + s32 numTags; //number of 'tags' per frame + s32 numMeshes; //number of meshes/skins + s32 numMaxSkins; //maximum number of unique skins used in md3 file. artefact md2 + s32 frameStart; //starting position of frame-structur + s32 tagStart; //starting position of tag-structures + s32 tagEnd; //ending position of tag-structures/starting position of mesh-structures s32 fileSize; }; @@ -151,9 +151,10 @@ namespace scene //! Holding Frame Data for a Mesh struct SMD3MeshBuffer : public IReferenceCounted { + virtual ~SMD3MeshBuffer () {} SMD3MeshHeader MeshHeader; - core::array < core::stringc > Shader; + core::stringc Shader; core::array < s32 > Indices; core::array < SMD3Vertex > Vertices; core::array < SMD3TexCoord > Tex; @@ -161,44 +162,74 @@ namespace scene //! hold a tag info for connecting meshes /** Basically its an alternate way to describe a transformation. */ - struct SMD3QuaterionTag + struct SMD3QuaternionTag { - SMD3QuaterionTag() {} + virtual ~SMD3QuaternionTag() + { + position.X = 0.f; + } - SMD3QuaterionTag( const core::stringc& name ) + // construct copy constructor + SMD3QuaternionTag( const SMD3QuaternionTag & copyMe ) + { + *this = copyMe; + } + + // construct for searching + SMD3QuaternionTag( const core::stringc& name ) : Name ( name ) {} // construct from a matrix - SMD3QuaterionTag ( const core::stringc& name, const core::matrix4 &m ) : Name(name), position(m.getTranslation()), rotation(m) - { } + SMD3QuaternionTag ( const core::stringc& name, const core::matrix4 &m ) + : Name(name), position(m.getTranslation()), rotation(m) {} // construct from a position and euler angles in degrees - SMD3QuaterionTag ( const core::vector3df &pos, const core::vector3df &angle ) : position(pos), rotation(angle * core::DEGTORAD) - { } + SMD3QuaternionTag ( const core::vector3df &pos, const core::vector3df &angle ) + : position(pos), rotation(angle * core::DEGTORAD) {} // set to matrix void setto ( core::matrix4 &m ) { - rotation.getMatrix ( m ); - m.setTranslation ( position ); + rotation.getMatrix ( m, position ); } - bool operator == ( const SMD3QuaterionTag &other ) const + bool operator == ( const SMD3QuaternionTag &other ) const { return Name == other.Name; } + SMD3QuaternionTag & operator=( const SMD3QuaternionTag & copyMe ) + { + Name = copyMe.Name; + position = copyMe.position; + rotation = copyMe.rotation; + return *this; + } + core::stringc Name; core::vector3df position; core::quaternion rotation; }; //! holds a associative list of named quaternions - struct SMD3QuaterionTagList : public virtual IReferenceCounted + struct SMD3QuaternionTagList { - SMD3QuaterionTag* get ( const core::stringc& name ) + SMD3QuaternionTagList () { - SMD3QuaterionTag search ( name ); + Container.setAllocStrategy ( core::ALLOC_STRATEGY_SAFE ); + } + + // construct copy constructor + SMD3QuaternionTagList( const SMD3QuaternionTagList & copyMe ) + { + *this = copyMe; + } + + virtual ~SMD3QuaternionTagList () {} + + SMD3QuaternionTag* get ( const core::stringc& name ) + { + SMD3QuaternionTag search ( name ); s32 index = Container.linear_search ( search ); if ( index >= 0 ) return &Container[index]; @@ -210,39 +241,61 @@ namespace scene return Container.size(); } - const SMD3QuaterionTag& operator[](u32 index) const + void set_used ( u32 new_size) + { + s32 diff = (s32) new_size - (s32) Container.allocated_size (); + if ( diff > 0 ) + { + SMD3QuaternionTag e ( "" ); + for ( s32 i = 0; i < diff; ++i ) + Container.push_back ( e ); + } + } + + const SMD3QuaternionTag& operator[](u32 index) const { return Container[index]; } - SMD3QuaterionTag& operator[](u32 index) + SMD3QuaternionTag& operator[](u32 index) { return Container[index]; } - SMD3QuaterionTagList & operator = (const SMD3QuaterionTagList & copyMe) + void push_back ( const SMD3QuaternionTag& other ) + { + Container.push_back ( other ); + } + + SMD3QuaternionTagList& operator = (const SMD3QuaternionTagList & copyMe) { Container = copyMe.Container; return *this; } - core::array < SMD3QuaterionTag > Container; + private: + core::array < SMD3QuaternionTag > Container; }; //! Holding Frames Buffers and Tag Infos struct SMD3Mesh: public IReferenceCounted { - ~SMD3Mesh() + SMD3Mesh () + { + MD3Header.numFrames = 0; + } + + virtual ~SMD3Mesh() { for (u32 i=0; idrop(); } - SMD3Header MD3Header; core::stringc Name; core::array < SMD3MeshBuffer * > Buffer; - SMD3QuaterionTagList TagList; + SMD3QuaternionTagList TagList; + SMD3Header MD3Header; }; @@ -255,7 +308,7 @@ namespace scene virtual void setInterpolationShift ( u32 shift, u32 loopMode ) = 0; //! get the tag list of the mesh. - virtual SMD3QuaterionTagList *getTagList(s32 frame, s32 detailLevel, s32 startFrameLoop, s32 endFrameLoop) = 0; + virtual SMD3QuaternionTagList *getTagList(s32 frame, s32 detailLevel, s32 startFrameLoop, s32 endFrameLoop) = 0; //! get the original md3 mesh. virtual SMD3Mesh * getOriginalMesh () = 0; diff --git a/include/IAnimatedMeshSceneNode.h b/include/IAnimatedMeshSceneNode.h index 2d0cba16..a1e024ad 100644 --- a/include/IAnimatedMeshSceneNode.h +++ b/include/IAnimatedMeshSceneNode.h @@ -193,7 +193,7 @@ namespace scene virtual IAnimatedMesh* getMesh(void) = 0; //! Get the absolute transformation for a special MD3 Tag if the mesh is a md3 mesh, or the absolutetransformation if it's a normal scenenode - virtual const SMD3QuaterionTag& getMD3TagTransformation( const core::stringc & tagname) = 0; + virtual const SMD3QuaternionTag* getMD3TagTransformation( const core::stringc & tagname) = 0; //! Set how the joints should be updated on render virtual void setJointMode(E_JOINT_UPDATE_ON_RENDER mode)=0; diff --git a/include/IEventReceiver.h b/include/IEventReceiver.h index 3eb15473..285fd123 100644 --- a/include/IEventReceiver.h +++ b/include/IEventReceiver.h @@ -149,6 +149,9 @@ namespace irr //! A file has been selected in the file dialog EGET_FILE_SELECTED, + //! A directory has been selected in the file dialog + EGET_DIRECTORY_SELECTED, + //! A file open dialog has been closed without choosing a file EGET_FILE_CHOOSE_DIALOG_CANCELLED, @@ -181,7 +184,19 @@ namespace irr //! A table has changed EGET_TABLE_CHANGED, EGET_TABLE_HEADER_CHANGED, - EGET_TABLE_SELECTED_AGAIN + EGET_TABLE_SELECTED_AGAIN, + + //! A tree view node lost selection. See IGUITreeView::getLastEventNode(). + EGET_TREEVIEW_NODE_DESELECT, + + //! A tree view node was selected. See IGUITreeView::getLastEventNode(). + EGET_TREEVIEW_NODE_SELECT, + + //! A tree view node was expanded. See IGUITreeView::getLastEventNode(). + EGET_TREEVIEW_NODE_EXPAND, + + //! A tree view node was collapsed. See IGUITreeView::getLastEventNode(). + EGET_TREEVIEW_NODE_COLLAPS, }; } // end namespace gui @@ -217,6 +232,13 @@ struct SEvent /** Only valid if event was EMIE_MOUSE_WHEEL */ f32 Wheel; + //! A bitmap of button states. You can use IsButtonPressed() to + /** Only valid if event was EMIE_MOUSE_MOVED */ + u32 ButtonStates; + bool isLeftPressed () const { return 0 != ( ButtonStates & 0x0001 ); } + bool isRightPressed () const { return 0 != ( ButtonStates & 0x0002 ); } + bool isMiddlePressed () const { return 0 != ( ButtonStates & 0x0010 ); } + //! Type of mouse event EMOUSE_INPUT_EVENT Event; }; diff --git a/include/IFileList.h b/include/IFileList.h index 8a06f816..ced46288 100644 --- a/include/IFileList.h +++ b/include/IFileList.h @@ -6,6 +6,7 @@ #define __I_FILE_LIST_H_INCLUDED__ #include "IReferenceCounted.h" +#include "irrString.h" namespace irr { @@ -25,13 +26,13 @@ public: \param index is the zero based index of the file which name should be returned. The index has to be smaller than the amount getFileCount() returns. \return File name of the file. Returns 0, if an error occured. */ - virtual const c8* getFileName(u32 index) const = 0; + virtual const core::string& getFileName(u32 index) const = 0; //! Gets the full name of a file in the list, path included, based on an index. /** \param index is the zero based index of the file which name should be returned. The index has to be smaller than the amount getFileCount() returns. \return File name of the file. Returns 0, if an error occured. */ - virtual const c8* getFullFileName(u32 index) = 0; + virtual const core::string& getFullFileName(u32 index) = 0; //! Check if the file is a directory /** \param index The zero based index of the file whose name shall diff --git a/include/IFileSystem.h b/include/IFileSystem.h index 253ce7bc..d25defc9 100644 --- a/include/IFileSystem.h +++ b/include/IFileSystem.h @@ -7,7 +7,7 @@ #include "IReferenceCounted.h" #include "IXMLReader.h" -#include "irrString.h" +#include "IFileArchive.h" namespace irr { @@ -24,6 +24,7 @@ class IFileList; class IXMLWriter; class IAttributes; + //! The FileSystem manages files and archives and provides access to them. /** It manages where files are, so that modules which use the the IO do not need to know where every file is located. A file could be in a .zip-Archive or @@ -37,7 +38,7 @@ public: \return Returns a pointer to the created file interface. The returned pointer should be dropped when no longer needed. See IReferenceCounted::drop() for more information. */ - virtual IReadFile* createAndOpenFile(const c8* filename) = 0; + virtual IReadFile* createAndOpenFile(const core::string& filename) = 0; //! Creates an IReadFile interface for accessing memory like a file. /** This allows you to use a pointer to memory where an IReadFile is requested. @@ -50,7 +51,7 @@ public: The returned pointer should be dropped when no longer needed. See IReferenceCounted::drop() for more information. */ - virtual IReadFile* createMemoryReadFile(void* memory, s32 len, const c8* fileName, bool deleteMemoryWhenDropped=false) = 0; + virtual IReadFile* createMemoryReadFile(void* memory, s32 len, const core::string& fileName, bool deleteMemoryWhenDropped=false) = 0; //! Creates an IWriteFile interface for accessing memory like a file. /** This allows you to use a pointer to memory where an IWriteFile is requested. @@ -64,7 +65,7 @@ public: The returned pointer should be dropped when no longer needed. See IReferenceCounted::drop() for more information. */ - virtual IWriteFile* createMemoryWriteFile(void* memory, s32 len, const c8* fileName, bool deleteMemoryWhenDropped=false) = 0; + virtual IWriteFile* createMemoryWriteFile(void* memory, s32 len, const core::string& fileName, bool deleteMemoryWhenDropped=false) = 0; //! Opens a file for write access. @@ -75,7 +76,28 @@ public: file could not created or opened for writing. The returned pointer should be dropped when no longer needed. See IReferenceCounted::drop() for more information. */ - virtual IWriteFile* createAndWriteFile(const c8* filename, bool append=false) = 0; + virtual IWriteFile* createAndWriteFile(const core::string& filename, bool append=false) = 0; + + //! Adds an archive to the file system. + /** After calling this, the Irrlicht Engine will search and open files directly from this archive too. + This is useful for hiding data from the end user, speeding up file access and making it possible to + access for example Quake3 .pk3 files, which are nothing different than .zip files. + \param filename: Filename of the zip archive to add to the file system. + \param ignoreCase: If set to true, files in the archive can be accessed without + writing all letters in the right case. + \param ignorePaths: If set to true, files in the added archive can be accessed + without its complete path. + \return Returns true if the archive was added successful, false if not. */ + virtual bool registerFileArchive( const core::string& filename, bool ignoreCase = true, bool ignorePaths = true, s32 index = -1) = 0; + + //! Adds an external archive loader to the engine. + virtual void addArchiveLoader(IArchiveLoader* loader) = 0; + //! return the amount of currently attached Archives + virtual u32 getFileArchiveCount() = 0; + //! removes an archive from the file system. + virtual bool unregisterFileArchive( u32 index ) = 0; + //! get the Archive number index + virtual IFileArchive* getFileArchive( u32 index ) = 0; //! Adds an zip archive to the file system. /** After calling this, the Irrlicht Engine will search and open files directly from this archive too. @@ -87,7 +109,11 @@ public: \param ignorePaths: If set to true, files in the added archive can be accessed without its complete path. \return Returns true if the archive was added successful, false if not. */ - virtual bool addZipFileArchive(const c8* filename, bool ignoreCase = true, bool ignorePaths = true) = 0; + virtual bool addZipFileArchive(const c8* filename, bool ignoreCase = true, bool ignorePaths = true) + { + return registerFileArchive ( filename, ignoreCase, ignorePaths ); + } + //! Adds an unzipped archive ( or basedirectory with subdirectories..) to the file system. /** Useful for handling data which will be in a zip file @@ -97,7 +123,10 @@ public: \param ignorePaths: If set to true, files in the added archive can be accessed without its complete path. \return Returns true if the archive was added successful, false if not. */ - virtual bool addFolderFileArchive(const c8* filename, bool ignoreCase = true, bool ignorePaths = true) = 0; + virtual bool addFolderFileArchive(const c8* filename, bool ignoreCase = true, bool ignorePaths = true) + { + return registerFileArchive ( filename, ignoreCase, ignorePaths ); + } //! Adds an pak archive to the file system. /** After calling this, the Irrlicht Engine will search and open files directly from this archive too. @@ -109,51 +138,53 @@ public: \param ignorePaths: If set to true, files in the added archive can be accessed without its complete path.(should not use with Quake2 paks \return Returns true if the archive was added successful, false if not. */ - virtual bool addPakFileArchive(const c8* filename, bool ignoreCase = true, bool ignorePaths = true) = 0; + virtual bool addPakFileArchive(const c8* filename, bool ignoreCase = true, bool ignorePaths = true) + { + return registerFileArchive ( filename, ignoreCase, ignorePaths ); + } //! Get the current working directory. /** \return Current working directory as a string. */ - virtual const c8* getWorkingDirectory() = 0; + virtual const core::string& getWorkingDirectory() = 0; //! Changes the current working directory. /** \param newDirectory: A string specifying the new working directory. The string is operating system dependent. Under Windows it has the form ":\\\<..>". An example would be: "C:\Windows\" \return True if successful, otherwise false. */ - virtual bool changeWorkingDirectoryTo(const c8* newDirectory) = 0; + virtual bool changeWorkingDirectoryTo(const core::string& newDirectory) = 0; //! Converts a relative path to an absolute (unique) path, resolving symbolic links if required /** \param filename Possibly relative filename begin queried. \result Absolute filename which points to the same file. */ - virtual core::stringc getAbsolutePath(const core::stringc& filename) const = 0; + virtual core::string getAbsolutePath(const core::string& filename) const = 0; //! Returns the directory a file is located in. /** \param filename: The file to get the directory from. \return String containing the directory of the file. */ - virtual core::stringc getFileDir(const core::stringc& filename) const = 0; + virtual core::string getFileDir(const core::string& filename) const = 0; //! Returns the base part of a filename, i.e. the name without the directory //! part. If no directory is prefixed, the full name is returned. /** \param filename: The file to get the basename from \param keepExtension True if filename with extension is returned otherwise everything after the final '.' is removed as well. */ - virtual core::stringc getFileBasename(const core::stringc& filename, bool keepExtension=true) const = 0; + virtual core::string getFileBasename(const core::string& filename, bool keepExtension=true) const = 0; + + //! flaten a path and file name for example: "/you/me/../." becomes "/you" + virtual core::string& flatenFilename( core::string& directory, const core::string& root = "/" ) const = 0; //! Creates a list of files and directories in the current working directory and returns it. /** \return a Pointer to the created IFileList is returned. After the list has been used it has to be deleted using its IFileList::drop() method. See IReferenceCounted::drop() for more information. */ - virtual IFileList* createFileList() const = 0; + virtual eFileSystemType setFileListSystem( eFileSystemType listType) = 0; + virtual IFileList* createFileList() = 0; //! Determines if a file exists and could be opened. /** \param filename is the string identifying the file which should be tested for existence. \return Returns true if file exists, and false if it does not exist or an error occured. */ - virtual bool existFile(const c8* filename) const = 0; - - //! Determines if a file exists and could be opened. - /** \param filename is the string identifying the file which should be tested for existence. - \return Returns true if file exists, and false if it does not exist or an error occured. */ - virtual bool existFile(const core::stringc& filename) const = 0; + virtual bool existFile(const core::string& filename) const = 0; //! Creates a XML Reader from a file which returns all parsed strings as wide characters (wchar_t*). /** Use createXMLReaderUTF8() if you prefer char* instead of wchar_t*. See IIrrXMLReader for @@ -162,7 +193,7 @@ public: IXMLReader is returned. After use, the reader has to be deleted using its IXMLReader::drop() method. See IReferenceCounted::drop() for more information. */ - virtual IXMLReader* createXMLReader(const c8* filename) = 0; + virtual IXMLReader* createXMLReader(const core::string& filename) = 0; //! Creates a XML Reader from a file which returns all parsed strings as wide characters (wchar_t*). /** Use createXMLReaderUTF8() if you prefer char* instead of wchar_t*. See IIrrXMLReader for @@ -180,7 +211,7 @@ public: IXMLReader is returned. After use, the reader has to be deleted using its IXMLReaderUTF8::drop() method. See IReferenceCounted::drop() for more information. */ - virtual IXMLReaderUTF8* createXMLReaderUTF8(const c8* filename) = 0; + virtual IXMLReaderUTF8* createXMLReaderUTF8(const core::string& filename) = 0; //! Creates a XML Reader from a file which returns all parsed strings as ASCII/UTF-8 characters (char*). /** Use createXMLReader() if you prefer wchar_t* instead of char*. See IIrrXMLReader for @@ -196,7 +227,7 @@ public: IXMLWriter is returned. After use, the reader has to be deleted using its IXMLWriter::drop() method. See IReferenceCounted::drop() for more information. */ - virtual IXMLWriter* createXMLWriter(const c8* filename) = 0; + virtual IXMLWriter* createXMLWriter(const core::string& filename) = 0; //! Creates a XML Writer from a file. /** \return 0, if file could not be opened, otherwise a pointer to the created diff --git a/include/IGPUProgrammingServices.h b/include/IGPUProgrammingServices.h index da866334..18b78c07 100644 --- a/include/IGPUProgrammingServices.h +++ b/include/IGPUProgrammingServices.h @@ -156,10 +156,10 @@ public: then printed to the error log and can be catched with a custom event receiver. */ virtual s32 addHighLevelShaderMaterialFromFiles( - const c8* vertexShaderProgram, + const core::string& vertexShaderProgramFileName, const c8* vertexShaderEntryPointName = "main", E_VERTEX_SHADER_TYPE vsCompileTarget = EVST_VS_1_1, - const c8* pixelShaderProgram = 0, + const core::string& pixelShaderProgramFileName = "", const c8* pixelShaderEntryPointName = "main", E_PIXEL_SHADER_TYPE psCompileTarget = EPST_PS_1_1, IShaderConstantSetCallBack* callback = 0, @@ -293,8 +293,8 @@ public: error occured. -1 is returned for example if a vertex or pixel shader program could not be compiled, the error strings are then printed out into the error log, and can be catched with a custom event receiver. */ - virtual s32 addShaderMaterialFromFiles(const c8* vertexShaderProgramFileName, - const c8* pixelShaderProgramFileName, + virtual s32 addShaderMaterialFromFiles(const core::string& vertexShaderProgramFileName, + const core::string& pixelShaderProgramFileName, IShaderConstantSetCallBack* callback = 0, E_MATERIAL_TYPE baseMaterial = video::EMT_SOLID, s32 userData = 0) = 0; diff --git a/include/IGUIComboBox.h b/include/IGUIComboBox.h index 1eba9758..57af3c4a 100644 --- a/include/IGUIComboBox.h +++ b/include/IGUIComboBox.h @@ -27,8 +27,14 @@ namespace gui //! Returns string of an item. the idx may be a value from 0 to itemCount-1 virtual const wchar_t* getItem(u32 idx) const = 0; + //! Returns item data of an item. the idx may be a value from 0 to itemCount-1 + virtual u32 getItemData(u32 idx) const = 0; + + //! Returns index based on item data + virtual s32 getIndexForItemData(u32 data ) const = 0; + //! Adds an item and returns the index of it - virtual u32 addItem(const wchar_t* text) = 0; + virtual u32 addItem(const wchar_t* text, u32 data = 0) = 0; //! Removes an item from the combo box. /** Warning. This will change the index of all following items */ diff --git a/include/IGUIElement.h b/include/IGUIElement.h index c4f38b5e..66fbbb80 100644 --- a/include/IGUIElement.h +++ b/include/IGUIElement.h @@ -432,24 +432,24 @@ public: //! Draws the element and its children. virtual void draw() { - if (!IsVisible) - return; - - core::list::Iterator it = Children.begin(); - for (; it != Children.end(); ++it) - (*it)->draw(); + if ( IsVisible ) + { + core::list::Iterator it = Children.begin(); + for (; it != Children.end(); ++it) + (*it)->draw(); + } } //! animate the element and its children. virtual void OnPostRender(u32 timeMs) { - if (!IsVisible) - return; - - core::list::Iterator it = Children.begin(); - for (; it != Children.end(); ++it) - (*it)->OnPostRender( timeMs ); + if ( IsVisible ) + { + core::list::Iterator it = Children.begin(); + for (; it != Children.end(); ++it) + (*it)->OnPostRender( timeMs ); + } } diff --git a/include/IGUIEnvironment.h b/include/IGUIEnvironment.h index a8e40e03..9f26279b 100644 --- a/include/IGUIEnvironment.h +++ b/include/IGUIEnvironment.h @@ -41,6 +41,8 @@ class IGUIImage; class IGUIMeshViewer; class IGUICheckBox; class IGUIListBox; +class IGUITreeView; +class IGUIImageList; class IGUIFileOpenDialog; class IGUIColorSelectDialog; class IGUIInOutFader; @@ -144,13 +146,23 @@ public: See IReferenceCounted::drop() for more information. */ virtual IGUISkin* createSkin(EGUI_SKIN_TYPE type) = 0; + + //! Creates the image list from the given texture. + /** Loads the font if it was not loaded before. + \param filename Filename of the Font. + \return Pointer to the font. Returns 0 if the font could not be loaded. + This pointer should not be dropped. See IReferenceCounted::drop() for + more information. */ + virtual IGUIImageList* createImageList( video::ITexture* texture, + core::dimension2d imageSize, bool useAlphaChannel ) = 0; + //! Returns pointer to the font with the specified filename. /** Loads the font if it was not loaded before. \param filename Filename of the Font. \return Pointer to the font. Returns 0 if the font could not be loaded. This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ - virtual IGUIFont* getFont(const c8* filename) = 0; + virtual IGUIFont* getFont(const core::string& filename) = 0; //! Returns the default built-in font. /** \return Pointer to the default built-in font. @@ -163,13 +175,13 @@ public: \param filename Filename of the sprite bank's origin. \return Pointer to the sprite bank. Returns 0 if it could not be loaded. This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ - virtual IGUISpriteBank* getSpriteBank(const c8* filename) = 0; + virtual IGUISpriteBank* getSpriteBank(const core::string& filename) = 0; //! Adds an empty sprite bank to the manager /** \param name Name of the new sprite bank. \return Pointer to the sprite bank. This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ - virtual IGUISpriteBank* addEmptySpriteBank(const c8 *name) = 0; + virtual IGUISpriteBank* addEmptySpriteBank(const core::string& name) = 0; //! Returns the root gui element. /** This is the first gui element, the (direct or indirect) parent of all @@ -295,6 +307,18 @@ public: virtual IGUIListBox* addListBox(const core::rect& rectangle, IGUIElement* parent=0, s32 id=-1, bool drawBackground=false) = 0; + //! Adds a tree view element. + /** \param rectangle Position and dimension of list box. + \param parent Parent gui element of the list box. + \param id Id to identify the gui element. + \param drawBackground Flag whether the background should be drawn. + \return Pointer to the created list box. Returns 0 if an error occured. + This pointer should not be dropped. See IReferenceCounted::drop() for + more information. */ + virtual IGUITreeView* addTreeView(const core::rect& rectangle, + IGUIElement* parent=0, s32 id=-1, bool drawBackground=false, + bool scrollBarVertical = true, bool scrollBarHorizontal = false) = 0; + //! Adds a mesh viewer. Not 100% implemented yet. /** \param rectangle Position and dimension of mesh viewer. \param parent Parent gui element of the mesh viewer. @@ -377,7 +401,7 @@ public: This pointer should not be dropped. See IReferenceCounted::drop() for more information. */ virtual IGUISpinBox* addSpinBox(const wchar_t* text, const core::rect& rectangle, - IGUIElement* parent=0, s32 id=-1) = 0; + bool border=true,IGUIElement* parent=0, s32 id=-1) = 0; //! Adds an element for fading in or out. /* \param rectangle Rectangle specifying the borders of the element. @@ -503,7 +527,7 @@ public: //! Saves the current gui into a file. /** \param filename Name of the file. \param start The GUIElement to start with. Root if 0. */ - virtual bool saveGUI(const c8* filename, IGUIElement* start=0) = 0; + virtual bool saveGUI(const core::string& filename, IGUIElement* start=0) = 0; //! Saves the current gui into a file. /** \param file The file to write to. @@ -513,7 +537,7 @@ public: //! Loads the gui. Note that the current gui is not cleared before. /** \param filename Name of the file. \param parent Parent for the loaded GUI, root if 0. */ - virtual bool loadGUI(const c8* filename, IGUIElement* parent=0) = 0; + virtual bool loadGUI(const c16* filename, IGUIElement* parent=0) = 0; //! Loads the gui. Note that the current gui is not cleared before. /** \param file The file to load from. diff --git a/include/IGUIFileOpenDialog.h b/include/IGUIFileOpenDialog.h index 5b7270b7..df65b393 100644 --- a/include/IGUIFileOpenDialog.h +++ b/include/IGUIFileOpenDialog.h @@ -23,6 +23,10 @@ namespace gui //! Returns the filename of the selected file. Returns NULL, if no file was selected. virtual const wchar_t* getFileName() const = 0; + + //! Returns the directory of the selected file. Returns NULL, if no directory was selected. + virtual const core::string& getDirectoryName() = 0; + }; diff --git a/include/IGUIFont.h b/include/IGUIFont.h index 21383207..f2f3b352 100644 --- a/include/IGUIFont.h +++ b/include/IGUIFont.h @@ -85,6 +85,13 @@ public: //! Returns the distance between letters virtual s32 getKerningHeight() const = 0; + + //! define which characters should not be drawn by the font. for example " " would + // not draw any space which is usually blank in most fonts. + /** + \param invisible: string of symbols, which are not send down to the videodriver + */ + virtual void setInvisibleCharacters( const wchar_t *s ) = 0; }; } // end namespace gui diff --git a/include/IGUIScrollBar.h b/include/IGUIScrollBar.h index 9b60e1f0..2348df21 100644 --- a/include/IGUIScrollBar.h +++ b/include/IGUIScrollBar.h @@ -21,11 +21,15 @@ namespace gui IGUIScrollBar(IGUIEnvironment* environment, IGUIElement* parent, s32 id, core::rect rectangle) : IGUIElement(EGUIET_SCROLL_BAR, environment, parent, id, rectangle) {} + //! sets the maximum value of the scrollbar. + virtual void setMax(s32 max) = 0; //! gets the maximum value of the scrollbar. virtual s32 getMax() const = 0; //! sets the maximum value of the scrollbar. - virtual void setMax(s32 max) = 0; + virtual void setMin(s32 max) = 0; + //! gets the maximum value of the scrollbar. + virtual s32 getMin() const = 0; //! gets the small step value virtual s32 getSmallStep() const = 0; diff --git a/include/IGUITable.h b/include/IGUITable.h index fb7f81c5..2e802d5e 100644 --- a/include/IGUITable.h +++ b/include/IGUITable.h @@ -136,8 +136,9 @@ namespace gui will be placed after it. If the row is larger than the actual number of row by more than one, it won't be created. Note that if you create a row that's not at the end, there might be - performance issues. */ - virtual void addRow(u32 rowIndex) = 0; + performance issues. + \returns: index of inteserted row*/ + virtual u32 addRow(u32 rowIndex) = 0; //! Remove a row from the table virtual void removeRow(u32 rowIndex) = 0; @@ -158,10 +159,10 @@ namespace gui virtual void orderRows(s32 columnIndex=-1, EGUI_ORDERING_MODE mode=EGOM_NONE) = 0; //! Set the text of a cell - virtual void setCellText(u32 rowIndex, u32 columnIndex, const wchar_t* text) = 0; + virtual void setCellText(u32 rowIndex, u32 columnIndex, const core::stringw& text) = 0; //! Set the text of a cell, and set a color of this cell. - virtual void setCellText(u32 rowIndex, u32 columnIndex, const wchar_t* text, video::SColor color) = 0; + virtual void setCellText(u32 rowIndex, u32 columnIndex, const core::stringw& text, video::SColor color) = 0; //! Set the data of a cell virtual void setCellData(u32 rowIndex, u32 columnIndex, void *data) = 0; diff --git a/include/IGUIWindow.h b/include/IGUIWindow.h index b23aca0d..55eef4a0 100644 --- a/include/IGUIWindow.h +++ b/include/IGUIWindow.h @@ -31,6 +31,7 @@ namespace gui //! Returns pointer to the maximize button virtual IGUIButton* getMaximizeButton() const = 0; + }; diff --git a/include/IImage.h b/include/IImage.h index c24c9405..478c26f9 100644 --- a/include/IImage.h +++ b/include/IImage.h @@ -113,6 +113,9 @@ public: const core::rect& sourceRect, const SColor &color, const core::rect* clipRect = 0) =0; + //! copies this surface into another, scaling it to fit, appyling a box filter + virtual void copyToScalingBoxFilter(IImage* target, s32 bias = 0) = 0; + //! fills the surface with black or white virtual void fill(const SColor &color) =0; diff --git a/include/IImageLoader.h b/include/IImageLoader.h index f252776b..ae1254f9 100644 --- a/include/IImageLoader.h +++ b/include/IImageLoader.h @@ -7,6 +7,7 @@ #include "IReferenceCounted.h" #include "IImage.h" +#include "irrString.h" namespace irr { @@ -30,7 +31,7 @@ public: /** Check is based on the file extension (e.g. ".tga") \param fileName Name of file to check. \return True if file seems to be loadable. */ - virtual bool isALoadableFileExtension(const c8* fileName) const = 0; + virtual bool isALoadableFileExtension(const core::string& filename) const = 0; //! Check if the file might be loaded by this class /** Check might look into the file. diff --git a/include/IImageWriter.h b/include/IImageWriter.h index bf622012..cc059c69 100644 --- a/include/IImageWriter.h +++ b/include/IImageWriter.h @@ -6,6 +6,8 @@ #define _I_IMAGE_WRITER_H_INCLUDED__ #include "IReferenceCounted.h" +#include "irrString.h" +#include "coreutil.h" namespace irr { @@ -26,7 +28,7 @@ public: //! Check if this writer can write a file with the given extension /** \param fileName Name of the file to check. \return True if file extension specifies a writable type. */ - virtual bool isAWriteableFileExtension(const c8* fileName) const = 0; + virtual bool isAWriteableFileExtension(const core::string& filename) const = 0; //! Write image to file /** \param file File handle to write to. diff --git a/include/ILogger.h b/include/ILogger.h index bedfa8af..fabdacbc 100644 --- a/include/ILogger.h +++ b/include/ILogger.h @@ -66,6 +66,7 @@ public: filtered with these levels. If you want to be a text displayed, independent on what level filter is set, use ELL_NONE. */ virtual void log(const c8* text, const c8* hint, ELOG_LEVEL ll=ELL_INFORMATION) = 0; + virtual void log(const c8* text, const wchar_t* hint, ELOG_LEVEL ll=ELL_INFORMATION) = 0; //! Prints out a text into the log /** \param text: Text to print out. diff --git a/include/IMeshCache.h b/include/IMeshCache.h index 4c6837bd..25054dc2 100644 --- a/include/IMeshCache.h +++ b/include/IMeshCache.h @@ -47,7 +47,7 @@ namespace scene set by this method. \param mesh Pointer to a mesh which will now be referenced by this name. */ - virtual void addMesh(const c8* filename, IAnimatedMesh* mesh) = 0; + virtual void addMesh(const core::string& filename, IAnimatedMesh* mesh) = 0; //! Removes a mesh from the cache. /** After loading a mesh with getMesh(), the mesh can be @@ -93,25 +93,25 @@ namespace scene //! Returns a mesh based on its filename. /** \param filename Name of the mesh. \return Pointer to the mesh or 0 if there is none with this number. */ - virtual IAnimatedMesh* getMeshByFilename(const c8* filename) = 0; + virtual IAnimatedMesh* getMeshByFilename(const core::string& filename) = 0; //! Get the filename of a loaded mesh, based on its index. /** \param index: Index of the mesh, number between 0 and getMeshCount()-1. \return String with name if mesh was found and has a name, else 0. */ - virtual const c8* getMeshFilename(u32 index) const = 0; + virtual const c16* getMeshFilename(u32 index) const = 0; //! Get the filename of a loaded mesh, if there is any. /** \param mesh Pointer to mesh to query. \return String with name if mesh was found and has a name, else 0. */ - virtual const c8* getMeshFilename(const IAnimatedMesh* const mesh) const = 0; + virtual const c16* getMeshFilename(const IAnimatedMesh* const mesh) const = 0; //! Get the filename of a loaded mesh, if there is any. /** \param mesh Pointer to mesh to query. \return String with name if mesh was found and has a name, else 0. */ - virtual const c8* getMeshFilename(const IMesh* const mesh) const = 0; + virtual const c16* getMeshFilename(const IMesh* const mesh) const = 0; //! Renames a loaded mesh. /** Note that renaming meshes might change the ordering of the @@ -120,7 +120,7 @@ namespace scene \param index The index of the mesh in the cache. \param filename New name for the mesh. \return True if mesh was renamed. */ - virtual bool setMeshFilename(u32 index, const c8* filename) = 0; + virtual bool setMeshFilename(u32 index, const c16* filename) = 0; //! Renames a loaded mesh. /** Note that renaming meshes might change the ordering of the @@ -129,7 +129,7 @@ namespace scene \param mesh Mesh to be renamed. \param filename New name for the mesh. \return True if mesh was renamed. */ - virtual bool setMeshFilename(const IAnimatedMesh* const mesh, const c8* filename) = 0; + virtual bool setMeshFilename(const IAnimatedMesh* const mesh, const c16* filename) = 0; //! Renames a loaded mesh. /** Note that renaming meshes might change the ordering of the @@ -138,12 +138,12 @@ namespace scene \param mesh Mesh to be renamed. \param filename New name for the mesh. \return True if mesh was renamed. */ - virtual bool setMeshFilename(const IMesh* const mesh, const c8* filename) = 0; + virtual bool setMeshFilename(const IMesh* const mesh, const c16* filename) = 0; //! Check if a mesh was already loaded. /** \param filename Name of the mesh. \return True if the mesh has been loaded, else false. */ - virtual bool isMeshLoaded(const c8* filename) = 0; + virtual bool isMeshLoaded(const core::string& filename) = 0; //! Clears the whole mesh cache, removing all meshes. /** All meshes will be reloaded completely when using ISceneManager::getMesh() diff --git a/include/IMeshLoader.h b/include/IMeshLoader.h index 5b26358a..5b292c97 100644 --- a/include/IMeshLoader.h +++ b/include/IMeshLoader.h @@ -6,6 +6,7 @@ #define __I_MESH_LOADER_H_INCLUDED__ #include "IReferenceCounted.h" +#include "irrString.h" namespace irr { @@ -34,7 +35,7 @@ public: only. \param fileName Name of the file to test. \return True if the file might be loaded by this class. */ - virtual bool isALoadableFileExtension(const c8* fileName) const = 0; + virtual bool isALoadableFileExtension(const core::string& filename) const = 0; //! Creates/loads an animated mesh from the file. /** \param file File handler to load the file from. diff --git a/include/IParticleAffector.h b/include/IParticleAffector.h index 7843c91f..f3d742cb 100644 --- a/include/IParticleAffector.h +++ b/include/IParticleAffector.h @@ -57,20 +57,6 @@ public: //! Gets whether or not the affector is currently enabled. virtual bool getEnabled() const { return Enabled; } - //! Writes attributes of the object. - /** Implement this to expose the attributes of your scene node animator for - scripting languages, editors, debuggers or xml serialization purposes. */ - virtual void serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options=0) const {} - - //! Reads attributes of the object. - /** Implement this to set the attributes of your scene node animator for - scripting languages, editors, debuggers or xml deserialization purposes. - \param startIndex start index where to start reading attributes. - \param in The attributes to work with. - \param options Additional options. - \return Last index of an attribute read by this affector */ - virtual s32 deserializeAttributes(s32 startIndex, io::IAttributes* in, io::SAttributeReadWriteOptions* options=0) { return 0; } - //! Get emitter type virtual E_PARTICLE_AFFECTOR_TYPE getType() const = 0; diff --git a/include/IParticleEmitter.h b/include/IParticleEmitter.h index 02c8698d..03c4c6e0 100644 --- a/include/IParticleEmitter.h +++ b/include/IParticleEmitter.h @@ -96,21 +96,6 @@ public: //! Get the minimum starting size for particles virtual const core::dimension2df& getMinStartSize() const = 0; - //! Writes attributes of the object. - /** Implement this to expose the attributes of your scene node animator for - scripting languages, editors, debuggers or xml serialization purposes. */ - virtual void serializeAttributes(io::IAttributes* out, - io::SAttributeReadWriteOptions* options=0) const {} - - //! Reads attributes of the object. - /** Implement this to set the attributes of your scene node animator for - scripting languages, editors, debuggers or xml deserialization purposes. - \param startIndex start index where to start reading attributes. - \param in The attributes to work with. - \param options Additional options. - \return Last index of an attribute read by this affector */ - virtual s32 deserializeAttributes(s32 startIndex, io::IAttributes* in, - io::SAttributeReadWriteOptions* options=0) { return 0; } //! Get emitter type virtual E_PARTICLE_EMITTER_TYPE getType() const { return EPET_POINT; } diff --git a/include/IQ3LevelMesh.h b/include/IQ3LevelMesh.h index 2f5948c5..6dd980ea 100644 --- a/include/IQ3LevelMesh.h +++ b/include/IQ3LevelMesh.h @@ -20,19 +20,21 @@ namespace scene { public: - //! releases a Mesh from the Q3 Loader - virtual void releaseMesh(s32 index) = 0; - //! loads the shader definition from file /** \param filename Name of the shaderfile, defaults to /scripts if fileNameIsValid is false. \param fileNameIsValid Specifies whether the filename is valid in the current situation. */ - virtual const quake3::SShader* getShader( const c8* filename, bool fileNameIsValid=true ) = 0; + virtual const quake3::IShader* getShader( const c8* filename, bool fileNameIsValid=true ) = 0; + + virtual const quake3::IShader* getShader( const core::string& filename,bool fileNameIsValid=true ) + { + return getShader ( core::stringc ( filename ).c_str(), fileNameIsValid ); + } //! returns a already loaded Shader - virtual const quake3::SShader* getShader(u32 index) const = 0; + virtual const quake3::IShader* getShader(u32 index) const = 0; //! get's an interface to the entities - virtual const quake3::tQ3EntityList& getEntityList() = 0; + virtual quake3::tQ3EntityList& getEntityList( const c8 * filename = 0) = 0; }; } // end namespace scene diff --git a/include/IReadFile.h b/include/IReadFile.h index 78d76700..96dbc03d 100644 --- a/include/IReadFile.h +++ b/include/IReadFile.h @@ -6,6 +6,7 @@ #define __I_READ_FILE_H_INCLUDED__ #include "IReferenceCounted.h" +#include "coreutil.h" namespace irr { @@ -40,15 +41,15 @@ namespace io //! Get name of file. /** \return File name as zero terminated character string. */ - virtual const c8* getFileName() const = 0; + virtual const core::string& getFileName() const = 0; }; //! Internal function, please do not use. - IReadFile* createReadFile(const c8* fileName); + IReadFile* createReadFile(const core::string& fileName); //! Internal function, please do not use. - IReadFile* createLimitReadFile(const c8* fileName, IReadFile* alreadyOpenedFile, long areaSize); + IReadFile* createLimitReadFile(const core::string& fileName, IReadFile* alreadyOpenedFile, long pos, long areaSize); //! Internal function, please do not use. - IReadFile* createMemoryReadFile(void* memory, long size, const c8* fileName, bool deleteMemoryWhenDropped); + IReadFile* createMemoryReadFile(void* memory, long size, const core::string& fileName, bool deleteMemoryWhenDropped); } // end namespace io } // end namespace irr diff --git a/include/ISceneNode.h b/include/ISceneNode.h index 1e3b258c..9dce9697 100644 --- a/include/ISceneNode.h +++ b/include/ISceneNode.h @@ -373,7 +373,7 @@ namespace scene \return The material at that index. */ virtual video::SMaterial& getMaterial(u32 num) { - return *((video::SMaterial*)0); + return video::IdentityMaterial; } diff --git a/include/ISceneNodeAnimatorCollisionResponse.h b/include/ISceneNodeAnimatorCollisionResponse.h index 5e30d11c..f946dd44 100644 --- a/include/ISceneNodeAnimatorCollisionResponse.h +++ b/include/ISceneNodeAnimatorCollisionResponse.h @@ -97,6 +97,10 @@ namespace scene to this animator's gravity vector. */ virtual void jump(f32 jumpSpeed) = 0; + //! Should the Target react on collision ( default = true ) + virtual void setAnimateTarget ( bool enable ) = 0; + virtual bool getAnimateTarget () const = 0; + //! Set translation of the collision ellipsoid. /** By default, the ellipsoid for collision detection is created around the center of the scene node, which means that diff --git a/include/ITexture.h b/include/ITexture.h index ef7580f7..93af6562 100644 --- a/include/ITexture.h +++ b/include/ITexture.h @@ -62,6 +62,10 @@ enum E_TEXTURE_CREATION_FLAG //! Discard any alpha layer and use non-alpha color format. ETCF_NO_ALPHA_CHANNEL = 0x00000020, + //! Allow the Driver to use Non-Power-2-Textures + //! BurningVideo can handle Non-Power-2 Textures in 2D (GUI), but not it 3D + ETCF_ALLOW_NON_POWER_2 = 0x00000040, + //! This flag is never used, it only forces the compiler to //! compile these enumeration values to 32 bit. ETCF_FORCE_32_BIT_DO_NOT_USE = 0x7fffffff @@ -99,7 +103,7 @@ class ITexture : public virtual IReferenceCounted public: //! constructor - ITexture(const c8* name) : Name(name) + ITexture(const core::string& name) : Name(name) { Name.make_lower(); } @@ -167,11 +171,11 @@ public: virtual bool isRenderTarget() const { return false; } //! Returns name of texture (in most cases this is the filename) - const core::stringc& getName() const { return Name; } + const core::string& getName() const { return Name; } protected: - core::stringc Name; + core::string Name; }; diff --git a/include/IWriteFile.h b/include/IWriteFile.h index 4f1a694b..24df5fe5 100644 --- a/include/IWriteFile.h +++ b/include/IWriteFile.h @@ -6,6 +6,7 @@ #define __I_WRITE_FILE_H_INCLUDED__ #include "IReferenceCounted.h" +#include "irrString.h" namespace irr { @@ -36,11 +37,11 @@ namespace io //! Get name of file. /** \return File name as zero terminated character string. */ - virtual const c8* getFileName() const = 0; + virtual const core::string& getFileName() const = 0; }; //! Internal function, please do not use. - IWriteFile* createWriteFile(const c8* fileName, bool append); + IWriteFile* createWriteFile(const core::string& fileName, bool append); } // end namespace io } // end namespace irr diff --git a/include/IrrCompileConfig.h b/include/IrrCompileConfig.h index 333048cd..9370abed 100644 --- a/include/IrrCompileConfig.h +++ b/include/IrrCompileConfig.h @@ -42,9 +42,12 @@ // XBox only suppots the native Window stuff #if defined(_XBOX) -#define _IRR_XBOX_PLATFORM_ -#define _IRR_WINDOWS_API_ -#define _IRR_USE_WINDOWS_DEVICE_ + #undef _IRR_WINDOWS_ + #define _IRR_XBOX_PLATFORM_ + #define _IRR_WINDOWS_API_ + //#define _IRR_USE_WINDOWS_DEVICE_ + #undef _IRR_USE_WINDOWS_DEVICE_ + //#define _IRR_USE_SDL_DEVICE_ #endif #if defined(__APPLE__) || defined(MACOSX) @@ -85,7 +88,7 @@ to the compiler settings: -DIRR_COMPILE_WITH_DX9_DEV_PACK and this to the linker settings: -ld3dx9 -ld3dx8 **/ #if defined(_IRR_WINDOWS_API_) && (!defined(__GNUC__) || defined(IRR_COMPILE_WITH_DX9_DEV_PACK)) -//#define _IRR_COMPILE_WITH_DIRECT3D_8_ +#define _IRR_COMPILE_WITH_DIRECT3D_8_ #define _IRR_COMPILE_WITH_DIRECT3D_9_ #endif @@ -129,6 +132,13 @@ define out. */ you will not be able to use anything provided by the GUI Environment, including loading fonts. */ #define _IRR_COMPILE_WITH_GUI_ + +//! Define _IRR_WCHAR_FILESYSTEM to enable unicode filesystem support for the engine. +/** This enables the engine to read/write from unicode filesystem. If you +disable this feature, the engine behave as before ( ansi) +ones. */ +//#define _IRR_WCHAR_FILESYSTEM + //! Define _IRR_COMPILE_WITH_ZLIB_ to enable compiling the engine using zlib. /** This enables the engine to read from compressed .zip archives. If you disable this feature, the engine can still read archives, but only uncompressed @@ -201,7 +211,7 @@ tool . */ #define BURNINGVIDEO_RENDERER_BEAUTIFUL //#define BURNINGVIDEO_RENDERER_FAST //#define BURNINGVIDEO_RENDERER_ULTRA_FAST - +//#define BURNINGVIDEO_RENDERER_CE //! Define _IRR_COMPILE_WITH_SKINNED_MESH_SUPPORT_ if you want to use bone based /** animated meshes. If you compile without this, you will be unable to load @@ -341,24 +351,64 @@ precision will be lower but speed higher. currently X86 only // XBox does not have OpenGL or DirectX9 #if defined(_IRR_XBOX_PLATFORM_) -#undef _IRR_COMPILE_WITH_OPENGL_ -#undef _IRR_COMPILE_WITH_DIRECT3D_9_ + #undef _IRR_COMPILE_WITH_OPENGL_ + #undef _IRR_COMPILE_WITH_DIRECT3D_9_ #endif -// WinCE does not have OpenGL or DirectX9 +//! WinCE does not have OpenGL or DirectX9. use minimal loaders #if defined(_WIN32_WCE) #undef _IRR_COMPILE_WITH_OPENGL_ #undef _IRR_COMPILE_WITH_DIRECT3D_8_ #undef _IRR_COMPILE_WITH_DIRECT3D_9_ - #undef _IRR_COMPILE_WITH_SOFTWARE_ + #undef BURNINGVIDEO_RENDERER_BEAUTIFUL + #undef BURNINGVIDEO_RENDERER_FAST + #undef BURNINGVIDEO_RENDERER_ULTRA_FAST + #define BURNINGVIDEO_RENDERER_CE + #undef _IRR_USE_WINDOWS_DEVICE_ #define _IRR_USE_WINDOWS_CE_DEVICE_ - #define BURNINGVIDEO_RENDERER_CE + //#define _IRR_WCHAR_FILESYSTEM + + #undef _IRR_COMPILE_WITH_IRR_MESH_LOADER_ + //#undef _IRR_COMPILE_WITH_MD2_LOADER_ + #undef _IRR_COMPILE_WITH_MD3_LOADER_ + #undef _IRR_COMPILE_WITH_3DS_LOADER_ + #undef _IRR_COMPILE_WITH_COLLADA_LOADER_ + #undef _IRR_COMPILE_WITH_CSM_LOADER_ + #undef _IRR_COMPILE_WITH_BSP_LOADER_ + #undef _IRR_COMPILE_WITH_DMF_LOADER_ + #undef _IRR_COMPILE_WITH_LMTS_LOADER_ + #undef _IRR_COMPILE_WITH_MY3D_LOADER_ + #undef _IRR_COMPILE_WITH_OBJ_LOADER_ + #undef _IRR_COMPILE_WITH_OCT_LOADER_ + #undef _IRR_COMPILE_WITH_OGRE_LOADER_ + #undef _IRR_COMPILE_WITH_LWO_LOADER_ + #undef _IRR_COMPILE_WITH_STL_LOADER_ + #undef _IRR_COMPILE_WITH_IRR_WRITER_ + #undef _IRR_COMPILE_WITH_COLLADA_WRITER_ + #undef _IRR_COMPILE_WITH_STL_WRITER_ + #undef _IRR_COMPILE_WITH_OBJ_WRITER_ + //#undef _IRR_COMPILE_WITH_BMP_LOADER_ + //#undef _IRR_COMPILE_WITH_JPG_LOADER_ + #undef _IRR_COMPILE_WITH_PCX_LOADER_ + //#undef _IRR_COMPILE_WITH_PNG_LOADER_ + #undef _IRR_COMPILE_WITH_PPM_LOADER_ + #undef _IRR_COMPILE_WITH_PSD_LOADER_ + //#undef _IRR_COMPILE_WITH_TGA_LOADER_ + #undef _IRR_COMPILE_WITH_WAL_LOADER_ + #undef _IRR_COMPILE_WITH_BMP_WRITER_ + #undef _IRR_COMPILE_WITH_JPG_WRITER_ + #undef _IRR_COMPILE_WITH_PCX_WRITER_ + #undef _IRR_COMPILE_WITH_PNG_WRITER_ + #undef _IRR_COMPILE_WITH_PPM_WRITER_ + #undef _IRR_COMPILE_WITH_PSD_WRITER_ + #undef _IRR_COMPILE_WITH_TGA_WRITER_ + #endif #if defined(_IRR_SOLARIS_PLATFORM_) -#undef _IRR_COMPILE_WITH_JOYSTICK_EVENTS_ + #undef _IRR_COMPILE_WITH_JOYSTICK_EVENTS_ #endif #endif // __IRR_COMPILE_CONFIG_H_INCLUDED__ diff --git a/include/IrrlichtDevice.h b/include/IrrlichtDevice.h index ef7bad1d..a682d108 100644 --- a/include/IrrlichtDevice.h +++ b/include/IrrlichtDevice.h @@ -217,6 +217,17 @@ namespace irr is defined, false if joysticks are not supported or support is compiled out. */ virtual bool activateJoysticks(core::array & joystickInfo) = 0; + + //! Set the current Gamma Value for the Display + /** Gamma in + */ + virtual bool setGammaRamp( f32 red, f32 green, f32 blue, + f32 relativebrightness, f32 relativecontrast ) = 0; + + //! Get the current Gamma Value for the Display + virtual bool getGammaRamp( f32 &red, f32 &green, f32 &blue, + f32 &brightness, f32 &contrast ) = 0; + }; } // end namespace irr diff --git a/include/SKeyMap.h b/include/SKeyMap.h index 1836b5c5..e6dd929b 100644 --- a/include/SKeyMap.h +++ b/include/SKeyMap.h @@ -18,6 +18,7 @@ namespace irr EKA_STRAFE_LEFT, EKA_STRAFE_RIGHT, EKA_JUMP_UP, + EKA_CROUCH, EKA_COUNT, //! This value is not used. It only forces this enumeration to compile in 32 bit. diff --git a/include/SMaterial.h b/include/SMaterial.h index 1bcc5e0f..05dfaee7 100644 --- a/include/SMaterial.h +++ b/include/SMaterial.h @@ -98,6 +98,18 @@ namespace video dstFact = E_BLEND_FACTOR ( ( state & 0x000000FF ) ); } + //! These flags are used to specify the DebthBuffer Function for the Material + /** Usally this is set to less equal + */ + //! DebthBuffer Function + enum E_DEPTHBUFFER_FUNC + { + EMDF_DEPTH_OFF = 0, + EMDF_DEPTH_LESS_EQUAL = 1, + EMDF_DEPTH_EQUAL = 2, + EMDF_DEPTH_GREATER_EQUAL = 3 + }; + //! These flags are used to specify the anti-aliasing and smoothing modes /** Techniques supported are multisampling, geometry smoothing, and alpha to coverage. @@ -518,6 +530,9 @@ namespace video } }; + //! global const identity Material + IRRLICHT_API extern SMaterial IdentityMaterial; + } // end namespace video } // end namespace irr diff --git a/include/SSharedMeshBuffer.h b/include/SSharedMeshBuffer.h index fc7ea0e3..1ffd7c45 100644 --- a/include/SSharedMeshBuffer.h +++ b/include/SSharedMeshBuffer.h @@ -133,11 +133,12 @@ namespace scene } //! set the hardware mapping hint, for driver - virtual void setHardwareMappingHint( E_HARDWARE_MAPPING NewMappingHint ) + virtual void setHardwareMappingHint( E_HARDWARE_MAPPING NewMappingHint, E_BUFFER_TYPE buffer=EBT_VERTEX_AND_INDEX ) { MappingHint=NewMappingHint; } + //! flags the mesh as changed, reloads hardware buffers virtual void setDirty(E_BUFFER_TYPE Buffer=EBT_VERTEX_AND_INDEX) { diff --git a/include/coreutil.h b/include/coreutil.h index e69bbddd..cf410f19 100644 --- a/include/coreutil.h +++ b/include/coreutil.h @@ -18,7 +18,35 @@ namespace core // ----------- some basic quite often used string functions ----------------- -//! cut the filename extension from a string +//! search if a filename has a proper extension +inline s32 isFileExtension ( const core::string& filename, + const core::string& ext0, + const core::string& ext1, + const core::string& ext2 + ) +{ + s32 extPos = filename.findLast ( '.' ); + if ( extPos < 0 ) + return 0; + + extPos += 1; + if ( filename.equals_substring_ignore_case ( ext0, extPos ) ) return 1; + if ( filename.equals_substring_ignore_case ( ext1, extPos ) ) return 2; + if ( filename.equals_substring_ignore_case ( ext2, extPos ) ) return 3; + return 0; +} + +//! search if a filename has a proper extension +inline bool hasFileExtension ( const core::string& filename, + const core::string& ext0, + const core::string& ext1 = "", + const core::string& ext2 = "" + ) +{ + return isFileExtension ( filename, ext0, ext1, ext2 ) > 0; +} + +//! cut the filename extension from a source string and stores in the dest string inline stringc& cutFilenameExtension ( stringc &dest, const stringc &source ) { s32 endPos = source.findLast ( '.' ); @@ -26,6 +54,14 @@ inline stringc& cutFilenameExtension ( stringc &dest, const stringc &source ) return dest; } +//! cut the filename extension from a source string and stores in the dest string +inline stringw& cutFilenameExtension ( stringw &dest, const stringw &source ) +{ + s32 endPos = source.findLast ( '.' ); + dest = source.subString ( 0, endPos < 0 ? source.size () : endPos ); + return dest; +} + //! get the filename extension from a string inline stringc& getFileNameExtension ( stringc &dest, const stringc &source ) { @@ -37,6 +73,104 @@ inline stringc& getFileNameExtension ( stringc &dest, const stringc &source ) return dest; } +//! delete path from filename +inline core::stringw& deletePathFromFilename(core::stringw& filename) +{ + // delete path from filename + const wchar_t *s = filename.c_str(); + const wchar_t* p = s + filename.size(); + + // search for path separator or beginning + while ( *p != '/' && *p != '\\' && p != s ) + p--; + + if ( p != s ) + { + ++p; + filename = p; + } + return filename; +} + +//! delete path from filename +inline core::stringc& deletePathFromFilename(core::stringc& filename) +{ + // delete path from filename + const c8 *s = filename.c_str(); + const c8* p = s + filename.size(); + + // search for path separator or beginning + while ( *p != '/' && *p != '\\' && p != s ) + p--; + + if ( p != s ) + { + ++p; + filename = p; + } + return filename; +} + +//! trim paths +inline core::string& deletePathFromPath(core::string& filename, s32 pathCount) +{ + // delete path from filename + s32 i = filename.size(); + + // search for path separator or beginning + while ( i ) + { + if ( filename[i] == '/' || filename[i] == '\\' ) + { + if ( --pathCount <= 0 ) + break; + } + i -= 1; + } + + if ( i ) + { + filename [ i + 1 ] = 0; + filename.verify(); + } + return filename; +} + +//! gets the last char of a string or null +inline c16 lastChar( const core::string& s) +{ + return s.size() ? s [ s.size() - 1 ] : 0; +} + +//! looks if file is in the same directory of path. returns offset of directory. +//! 0 means in same directory. 1 means file is direct child of path +inline s32 isInSameDirectory ( const core::string& path, const core::string& file ) +{ + s32 subA = 0; + s32 subB = 0; + s32 pos; + + if ( path.size() && !path.equalsn ( file, path.size() ) ) + return -1; + + pos = 0; + while ( (pos = path.findNext ( '/', pos )) >= 0 ) + { + subA += 1; + pos += 1; + } + + pos = 0; + while ( (pos = file.findNext ( '/', pos )) >= 0 ) + { + subB += 1; + pos += 1; + } + + return subB - subA; +} + + //! some standard function ( to remove dependencies ) #undef isdigit #undef isspace diff --git a/include/dimension2d.h b/include/dimension2d.h index 4c3c8862..b7301951 100644 --- a/include/dimension2d.h +++ b/include/dimension2d.h @@ -33,6 +33,15 @@ namespace core explicit dimension2d(const dimension2d& other) : Width((T)other.Width), Height((T)other.Height) { } + template + dimension2d& operator=(const dimension2d& other) + { + Width = (T) other.Width; + Height = (T) other.Height; + return *this; + } + + //! Equality operator bool operator==(const dimension2d& other) const { @@ -118,23 +127,26 @@ namespace core return Width*Height; } - //! Get the optimal size according to some properties - /** This is a function often used for texture dimension - calculations. The function returns the next larger or - smaller dimension which is a power-of-two dimension - (2^n,2^m) and/or square (Width=Height). - \param requirePowerOfTwo Forces the result to use only - powers of two as values. - \param requireSquare Makes width==height in the result - \param larger Choose whether the result is larger or - smaller than the current dimension. If one dimension - need not be changed it is kept with any value of larger. - \return The optimal dimension under the given - constraints. */ + //! Get the optimal size according to some properties + /** This is a function often used for texture dimension + calculations. The function returns the next larger or + smaller dimension which is a power-of-two dimension + (2^n,2^m) and/or square (Width=Height). + \param requirePowerOfTwo Forces the result to use only + powers of two as values. + \param requireSquare Makes width==height in the result + \param larger Choose whether the result is larger or + smaller than the current dimension. If one dimension + need not be changed it is kept with any value of larger. + \param maxValue Maximum texturesize. if value > 0 size is + clamped to maxValue + \return The optimal dimension under the given + constraints. */ dimension2d getOptimalSize( bool requirePowerOfTwo=true, bool requireSquare=false, - bool larger=true) const + bool larger=true, + u32 maxValue = 0) const { u32 i=1; u32 j=1; @@ -162,6 +174,13 @@ namespace core else i=j; } + + if ( maxValue > 0 && i > maxValue) + i = maxValue; + + if ( maxValue > 0 && j > maxValue) + j = maxValue; + return dimension2d((T)i,(T)j); } diff --git a/include/irrAllocator.h b/include/irrAllocator.h index b4bb7611..21e8510d 100644 --- a/include/irrAllocator.h +++ b/include/irrAllocator.h @@ -107,6 +107,14 @@ public: #define DEBUG_CLIENTBLOCK new( _CLIENT_BLOCK, __FILE__, __LINE__) #endif +//! defines an allocation strategy +enum eAllocStrategy +{ + ALLOC_STRATEGY_SAFE = 0, + ALLOC_STRATEGY_DOUBLE = 1, + ALLOC_STRATEGY_SQRT = 2, +}; + } // end namespace core } // end namespace irr diff --git a/include/irrArray.h b/include/irrArray.h index 4904faaa..4c36af7c 100644 --- a/include/irrArray.h +++ b/include/irrArray.h @@ -26,7 +26,7 @@ public: //! Default constructor for empty array. array() : data(0), allocated(0), used(0), - free_when_destroyed(true), is_sorted(true) + free_when_destroyed(true), is_sorted(true),strategy ( ALLOC_STRATEGY_DOUBLE ) { } @@ -34,7 +34,7 @@ public: /** \param start_count Amount of elements to pre-allocate. */ array(u32 start_count) : data(0), allocated(0), used(0), - free_when_destroyed(true), is_sorted(true) + free_when_destroyed(true), is_sorted(true),strategy ( ALLOC_STRATEGY_DOUBLE ) { reallocate(start_count); } @@ -93,6 +93,15 @@ public: } + //! set a new allocation strategy + /** if the maximum size of the array is unknown, you can define how big the + allocation should happen. + \param element: newStratgey to applay to this array. */ + void setAllocStrategy ( eAllocStrategy newStrategy = ALLOC_STRATEGY_DOUBLE ) + { + strategy = newStrategy; + } + //! Adds an element at back of array. /** If the array is too small to add this new element it is made bigger. \param element: Element to add at the back of the array. */ @@ -100,14 +109,31 @@ public: { if (used + 1 > allocated) { - // reallocate(used * 2 +1); // this doesn't work if the element is in the same array. So // we'll copy the element first to be sure we'll get no data // corruption T e(element); - reallocate(used * 2 +1); // increase data block + //reallocate(used * 2 +1); // increase data block + // TA: okt, 2008. it's only allowed to alloc one element, if + // default constructor has to be called + // increase data block + u32 newAlloc; + switch ( strategy ) + { + case ALLOC_STRATEGY_DOUBLE: + newAlloc = used + 1 + (allocated < 500 ? + (allocated < 5 ? 5 : used) : used >> 2); + break; + default: + case ALLOC_STRATEGY_SAFE: + newAlloc = used + 1; + break; + } + reallocate( newAlloc); + // construct new element + // Attention!. in missing default constructors for faster alloc methods allocator.construct(&data[used++], e); // data[used++] = e; // push_back } else @@ -215,6 +241,8 @@ public: //! Assignment operator void operator=(const array& other) { + strategy = other.strategy; + if (data) { for (u32 i=0; i 0 && !(element < data[index - 1]) && !(data[index - 1] < element) ) + { + index -= 1; + } + // look linear up + while ( last < (s32) used - 1 && !(element < data[last + 1]) && !(data[last + 1] < element) ) + { + last += 1; + } + + return index; + } + //! Finds an element in linear time, which is very slow. /** Use binary_search for faster finding. Only works if ==operator is implemented. @@ -501,6 +561,7 @@ public: u32 used; bool free_when_destroyed; bool is_sorted; + eAllocStrategy strategy; TAlloc allocator; }; diff --git a/include/irrMath.h b/include/irrMath.h index 331ad816..395fd7a7 100644 --- a/include/irrMath.h +++ b/include/irrMath.h @@ -22,6 +22,7 @@ #define powf(X,Y) (f32)pow((f64)(X),(f64)(Y)) #define fmodf(X,Y) (f32)fmod((f64)(X),(f64)(Y)) #define fabsf(X) (f32)fabs((f64)(X)) + #define logf(X) (f32)log((f64)(X)) #endif namespace irr @@ -31,20 +32,15 @@ namespace core //! Rounding error constant often used when comparing f32 values. -#ifdef IRRLICHT_FAST_MATH - const f32 ROUNDING_ERROR_32 = 0.00005f; - const f64 ROUNDING_ERROR_64 = 0.000005; -#else const f32 ROUNDING_ERROR_32 = 0.000001f; const f64 ROUNDING_ERROR_64 = 0.00000001; -#endif #ifdef PI // make sure we don't collide with a define #undef PI #endif //! Constant for PI. const f32 PI = 3.14159265359f; - + //! Constant for reciprocal of PI. const f32 RECIPROCAL_PI = 1.0f/PI; @@ -207,6 +203,12 @@ namespace core return fabsf(a) <= tolerance; } + //! returns if a equals not zero, taking rounding errors into account + inline bool isnotzero(const f32 a, const f32 tolerance = ROUNDING_ERROR_32) + { + return fabsf(a) > tolerance; + } + //! returns if a equals zero, taking rounding errors into account inline bool iszero(const s32 a, const s32 tolerance = 0) { @@ -322,6 +324,12 @@ namespace core return ( ( -condition >> 31 ) & ( a ^ b ) ) ^ b; } + //! conditional set based on mask and arithmetic shift + REALINLINE u16 if_c_a_else_b ( const s16 condition, const s16 a, const s16 b ) + { + return ( ( -condition >> 15 ) & ( a ^ b ) ) ^ b; + } + //! conditional set based on mask and arithmetic shift REALINLINE u32 if_c_a_else_0 ( const s32 condition, const u32 a ) { @@ -346,6 +354,7 @@ namespace core REALINLINE void clearFPUException () { #ifdef IRRLICHT_FAST_MATH + return; #ifdef feclearexcept feclearexcept(FE_ALL_EXCEPT); #elif defined(_MSC_VER) @@ -358,55 +367,107 @@ namespace core #endif } - REALINLINE f32 reciprocal_squareroot(const f32 x) + // calculate: 1 / sqrt ( x ) + REALINLINE f64 reciprocal_squareroot(const f64 x) { -#ifdef IRRLICHT_FAST_MATH + return 1.0 / sqrt ( x ); + } + + // calculate: 1 / sqrt ( x ) + REALINLINE f32 reciprocal_squareroot(const f32 f) + { +#if defined ( IRRLICHT_FAST_MATH ) + #if defined(_MSC_VER) + // SSE reciprocal square root estimate, accurate to 12 significant + // bits of the mantissa + f32 recsqrt; + __asm rsqrtss xmm0, f // xmm0 = rsqrtss(f) + __asm movss recsqrt, xmm0 // return xmm0 + return recsqrt; + +/* // comes from Nvidia -#if 1 u32 tmp = (u32(IEEE_1_0 << 1) + IEEE_1_0 - *(u32*)&x) >> 1; f32 y = *(f32*)&tmp; return y * (1.47f - 0.47f * x * y * y); -#elif defined(_MSC_VER) - // an sse2 version - __asm - { - movss xmm0, x - rsqrtss xmm0, xmm0 - movss x, xmm0 - } - return x; -#endif +*/ + #else + return 1.f / sqrtf ( f ); + #endif #else // no fast math - return 1.f / sqrtf ( x ); + return 1.f / sqrtf ( f ); #endif } - - + // calculate: 1 / x REALINLINE f32 reciprocal ( const f32 f ) { -#ifdef IRRLICHT_FAST_MATH +#if defined (IRRLICHT_FAST_MATH) + + // SSE Newton-Raphson reciprocal estimate, accurate to 23 significant + // bi ts of the mantissa + // One Newtown-Raphson Iteration: + // f(i+1) = 2 * rcpss(f) - f * rcpss(f) * rcpss(f) + f32 rec; + __asm rcpss xmm0, f // xmm0 = rcpss(f) + __asm movss xmm1, f // xmm1 = f + __asm mulss xmm1, xmm0 // xmm1 = f * rcpss(f) + __asm mulss xmm1, xmm0 // xmm2 = f * rcpss(f) * rcpss(f) + __asm addss xmm0, xmm0 // xmm0 = 2 * rcpss(f) + __asm subss xmm0, xmm1 // xmm0 = 2 * rcpss(f) + // - f * rcpss(f) * rcpss(f) + __asm movss rec, xmm0 // return xmm0 + return rec; + + //! i do not divide through 0.. (fpu expection) // instead set f to a high value to get a return value near zero.. // -1000000000000.f.. is use minus to stay negative.. // must test's here (plane.normal dot anything ) checks on <= 0.f - return 1.f / f; //u32 x = (-(AIR(f) != 0 ) >> 31 ) & ( IR(f) ^ 0xd368d4a5 ) ^ 0xd368d4a5; //return 1.f / FR ( x ); + #else // no fast math return 1.f / f; #endif } - REALINLINE f32 reciprocal_approxim ( const f32 p ) + // calculate: 1 / x, low precision allowed + REALINLINE f32 reciprocal_approxim ( const f32 f ) { -#ifdef IRRLICHT_FAST_MATH +#if defined( IRRLICHT_FAST_MATH) + + // SSE Newton-Raphson reciprocal estimate, accurate to 23 significant + // bi ts of the mantissa + // One Newtown-Raphson Iteration: + // f(i+1) = 2 * rcpss(f) - f * rcpss(f) * rcpss(f) + f32 rec; + __asm rcpss xmm0, f // xmm0 = rcpss(f) + __asm movss xmm1, f // xmm1 = f + __asm mulss xmm1, xmm0 // xmm1 = f * rcpss(f) + __asm mulss xmm1, xmm0 // xmm2 = f * rcpss(f) * rcpss(f) + __asm addss xmm0, xmm0 // xmm0 = 2 * rcpss(f) + __asm subss xmm0, xmm1 // xmm0 = 2 * rcpss(f) + // - f * rcpss(f) * rcpss(f) + __asm movss rec, xmm0 // return xmm0 + return rec; + + +/* + // SSE reciprocal estimate, accurate to 12 significant bits of + f32 rec; + __asm rcpss xmm0, f // xmm0 = rcpss(f) + __asm movss rec , xmm0 // return xmm0 + return rec; +*/ +/* register u32 x = 0x7F000000 - IR ( p ); const f32 r = FR ( x ); return r * (2.0f - p * r); +*/ #else // no fast math - return 1.f / p; + return 1.f / f; #endif } diff --git a/include/irrString.h b/include/irrString.h index bf31e817..16e1c5d7 100644 --- a/include/irrString.h +++ b/include/irrString.h @@ -27,11 +27,46 @@ This means that c8 strings are treated as ASCII/Latin-1, not UTF-8, and are simply expanded to the equivalent wchar_t, while Unicode/wchar_t characters are truncated to 8-bit ASCII/Latin-1 characters, discarding all other information in the wchar_t. - -Known bugs: -Special characters like umlauts are ignored in the -methods make_upper, make_lower and equals_ignore_case. */ + +enum eLocaleID +{ + IRR_LOCALE_ANSI = 0, + IRR_LOCALE_GERMAN = 1 +}; + +static eLocaleID locale_current = IRR_LOCALE_ANSI; +static inline void locale_set ( eLocaleID id ) +{ + locale_current = id; +} + +//! Returns a character converted to lower case +static inline u32 locale_lower ( u32 x ) +{ + switch ( locale_current ) + { + case IRR_LOCALE_GERMAN: + break; + } + // ansi + return x >= 'A' && x <= 'Z' ? x + 0x20 : x; +} + +//! Returns a character converted to upper case +static inline u32 locale_upper ( u32 x ) +{ + switch ( locale_current ) + { + case IRR_LOCALE_GERMAN: + break; + } + + // ansi + return x >= 'a' && x <= 'z' ? x + ( 'A' - 'a' ) : x; +} + + template > class string { @@ -185,7 +220,7 @@ public: //! Destructor - ~string() + virtual ~string() { allocator.deallocate(array); // delete [] array; } @@ -375,22 +410,15 @@ public: void make_lower() { for (u32 i=0; i=a && array[i]<=z) - array[i] += diff; - } + array[i] = locale_upper ( array[i] ); } @@ -400,12 +428,29 @@ public: bool equals_ignore_case(const string& other) const { for(u32 i=0; array[i] && other[i]; ++i) - if (ansi_lower(array[i]) != ansi_lower(other[i])) + if (locale_lower( array[i]) != locale_lower(other[i])) return false; return used == other.used; } + //! Compares the strings ignoring case. + /** \param other: Other string to compare. + \param sourcePos: where to start to compare in the string + \return True if the strings are equal ignoring case. */ + bool equals_substring_ignore_case(const string&other, const s32 sourcePos = 0 ) const + { + if ( (u32) sourcePos > used ) + return false; + + u32 i; + for( i=0; array[sourcePos + i] && other[i]; ++i) + if (locale_lower( array[sourcePos + i]) != locale_lower(other[i])) + return false; + + return array[sourcePos + i] == 0 && other[i] == 0; + } + //! Compares the strings ignoring case. /** \param other: Other string to compare. @@ -414,7 +459,7 @@ public: { for(u32 i=0; array[i] && other.array[i]; ++i) { - s32 diff = (s32) ansi_lower ( array[i] ) - (s32) ansi_lower ( other.array[i] ); + s32 diff = (s32) locale_lower ( array[i] ) - (s32) locale_lower ( other.array[i] ); if ( diff ) return diff < 0; } @@ -869,22 +914,32 @@ public: --used; } -private: -/* - T toLower(const T& t) const + //! verify the existing string. + void verify() { - if (t>=(T)'A' && t<=(T)'Z') - return t + ((T)'a' - (T)'A'); + // terminate on existing null + for (u32 i=0; i 0 ) + { + used = allocated - 1; + array[used] = 0; + } else - return t; - } -*/ - //! Returns a character converted to lower case - inline T ansi_lower ( u32 x ) const - { - return x >= 'A' && x <= 'Z' ? (T) x + 0x20 : (T) x; + { + used = 0; + } } +private: //! Reallocate the array, make it bigger or smaller void reallocate(u32 new_size) @@ -904,7 +959,6 @@ private: allocator.deallocate(old_array); // delete [] old_array; } - //--- member variables T* array; @@ -920,6 +974,7 @@ typedef string stringc; //! Typedef for wide character strings typedef string stringw; + } // end namespace core } // end namespace irr diff --git a/include/irrTypes.h b/include/irrTypes.h index 01b31f1a..db080e7c 100644 --- a/include/irrTypes.h +++ b/include/irrTypes.h @@ -119,6 +119,15 @@ typedef unsigned short wchar_t; #endif // microsoft compiler #endif // _IRR_WINDOWS_API_ +//! Should the wide character version of the FileSystem be used +#if defined(_IRR_WCHAR_FILESYSTEM) + //! 16 bit character variable. Used for unicode Filesystem and unicode strings + typedef wchar_t c16; +#else + //! 8 bit character variable. Used for ansi Filesystem and non-unicode strings + typedef char c16; +#endif + //! define a break macro for debugging. #if defined(_DEBUG) #if defined(_IRR_WINDOWS_API_) && defined(_MSC_VER) && !defined (_WIN32_WCE) diff --git a/include/irrlicht.h b/include/irrlicht.h index 3a4db604..db264935 100644 --- a/include/irrlicht.h +++ b/include/irrlicht.h @@ -95,6 +95,7 @@ #include "IGUITable.h" #include "IGUIToolbar.h" #include "IGUIWindow.h" +#include "IGUITreeView.h" #include "IImage.h" #include "IImageLoader.h" #include "IImageWriter.h" @@ -315,7 +316,7 @@ namespace irr \return Returns pointer to the created IrrlichtDevice or null if the device could not be created. */ - IRRLICHT_API IrrlichtDevice* IRRCALLCONV createDevice( + extern "C" IRRLICHT_API IrrlichtDevice* IRRCALLCONV createDevice( video::E_DRIVER_TYPE deviceType = video::EDT_SOFTWARE, // parantheses are necessary for some compilers const core::dimension2d& windowSize = (core::dimension2d(640,480)), @@ -325,6 +326,17 @@ namespace irr bool vsync = false, IEventReceiver* receiver = 0); + //! typedef for Function Pointer + typedef IrrlichtDevice* (IRRCALLCONV *funcptr_createDevice )( + video::E_DRIVER_TYPE deviceType, + const core::dimension2d& windowSize, + u32 bits, + bool fullscreen, + bool stencilbuffer, + bool vsync, + IEventReceiver* receiver); + + //! Creates an Irrlicht device with the option to specify advanced parameters. /** Usually you should used createDevice() for creating an Irrlicht Engine device. Use this function only if you wish to specify advanced parameters like a window @@ -333,9 +345,12 @@ namespace irr See irr::SIrrlichtCreationParameters for details. \return Returns pointer to the created IrrlichtDevice or null if the device could not be created. */ - IRRLICHT_API IrrlichtDevice* IRRCALLCONV createDeviceEx( + extern "C" IRRLICHT_API IrrlichtDevice* IRRCALLCONV createDeviceEx( const SIrrlichtCreationParameters& parameters); + //! typedef for Function Pointer + typedef IrrlichtDevice* (IRRCALLCONV *funcptr_createDeviceEx )( const SIrrlichtCreationParameters& parameters ); + // THE FOLLOWING IS AN EMPTY LIST OF ALL SUB NAMESPACES // EXISTING ONLY FOR THE DOCUMENTATION SOFTWARE DOXYGEN. diff --git a/include/matrix4.h b/include/matrix4.h index a1810063..23ac1f79 100644 --- a/include/matrix4.h +++ b/include/matrix4.h @@ -13,6 +13,23 @@ #include "rect.h" #include "irrString.h" +//#define USE_MATRIX_TEST +//#define USE_MATRIX_TEST_DEBUG + +#if defined( USE_MATRIX_TEST_DEBUG ) + #include + + struct MatrixTest + { + MatrixTest () : ID(0), Calls(0) {} + char buf[256]; + int Calls; + int ID; + }; + static MatrixTest MTest; + +#endif + namespace irr { namespace core @@ -45,13 +62,25 @@ namespace core CMatrix4( const CMatrix4& other,eConstructor constructor = EM4CONST_COPY); //! Simple operator for directly accessing every element of the matrix. - T& operator()(const s32 row, const s32 col) { definitelyIdentityMatrix=false; return M[ row * 4 + col ]; } + T& operator()(const s32 row, const s32 col) + { +#if defined ( USE_MATRIX_TEST ) + definitelyIdentityMatrix=false; +#endif + return M[ row * 4 + col ]; + } //! Simple operator for directly accessing every element of the matrix. const T& operator()(const s32 row, const s32 col) const { return M[row * 4 + col]; } //! Simple operator for linearly accessing every element of the matrix. - T& operator[](u32 index) { definitelyIdentityMatrix=false; return M[index]; } + T& operator[](u32 index) + { +#if defined ( USE_MATRIX_TEST ) + definitelyIdentityMatrix=false; +#endif + return M[index]; + } //! Simple operator for linearly accessing every element of the matrix. const T& operator[](u32 index) const { return M[index]; } @@ -64,7 +93,13 @@ namespace core //! Returns pointer to internal array const T* pointer() const { return M; } - T* pointer() { definitelyIdentityMatrix=false; return M; } + T* pointer() + { +#if defined ( USE_MATRIX_TEST ) + definitelyIdentityMatrix=false; +#endif + return M; + } //! Returns true if other matrix is equal to this matrix. bool operator==(const CMatrix4 &other) const; @@ -264,6 +299,32 @@ namespace core //! Gets transposed matrix inline void getTransposed( CMatrix4& dest ) const; + //! Builds a matrix that rotates from one vector to another + /** \param from: vector to rotate from + \param to: vector to rotate to + */ + CMatrix4& buildRotateFromTo(const core::vector3df& from, const core::vector3df& to); + + //! Builds a combined matrix which translate to a center before rotation and translate afterwards + /** \param from: vector to rotate from + \param to: vector to rotate to + */ + void setRotationCenter(const core::vector3df& center, const core::vector3df& translate); + + //! Builds a matrix which rotates a source vector to a look vector over an arbitrary axis + /** \param camPos: viewer position in world coo + \param center: object position in world-coo and rotation pivot + \param translation: object final translation from center + \param axis: axis to rotate about + \param from: source vector to rotate from + */ + void buildAxisAlignedBillboard( const core::vector3df& camPos, + const core::vector3df& center, + const core::vector3df& translation, + const core::vector3df& axis, + const core::vector3df& from + ); + /* construct 2D Texture transformations rotate about center, scale, and transform. @@ -321,13 +382,26 @@ namespace core private: //! Matrix data, stored in row-major order T M[16]; +#if defined ( USE_MATRIX_TEST ) //! Flag is this matrix is identity matrix - mutable bool definitelyIdentityMatrix; + mutable u32 definitelyIdentityMatrix; +#endif +#if defined ( USE_MATRIX_TEST_DEBUG ) + u32 id; + mutable u32 calls; +#endif + }; // Default constructor template - inline CMatrix4::CMatrix4( eConstructor constructor ) : definitelyIdentityMatrix(false) + inline CMatrix4::CMatrix4( eConstructor constructor ) +#if defined ( USE_MATRIX_TEST ) + : definitelyIdentityMatrix(BIT_UNTESTED) +#endif +#if defined ( USE_MATRIX_TEST_DEBUG ) + ,id ( MTest.ID++), calls ( 0 ) +#endif { switch ( constructor ) { @@ -344,7 +418,13 @@ namespace core // Copy constructor template - inline CMatrix4::CMatrix4( const CMatrix4& other, eConstructor constructor) : definitelyIdentityMatrix(false) + inline CMatrix4::CMatrix4( const CMatrix4& other, eConstructor constructor) +#if defined ( USE_MATRIX_TEST ) + : definitelyIdentityMatrix(BIT_UNTESTED) +#endif +#if defined ( USE_MATRIX_TEST_DEBUG ) + ,id ( MTest.ID++), calls ( 0 ) +#endif { switch ( constructor ) { @@ -526,6 +606,7 @@ namespace core template inline CMatrix4& CMatrix4::operator*=(const CMatrix4& other) { +#if defined ( USE_MATRIX_TEST ) // do checks on your own in order to avoid copy creation if ( !other.isIdentity() ) { @@ -540,6 +621,10 @@ namespace core } } return *this; +#else + CMatrix4 temp ( *this ); + return setbyproduct_nocheck( temp, other ); +#endif } //! multiply by another matrix @@ -570,7 +655,9 @@ namespace core M[13] = m1[1]*m2[12] + m1[5]*m2[13] + m1[9]*m2[14] + m1[13]*m2[15]; M[14] = m1[2]*m2[12] + m1[6]*m2[13] + m1[10]*m2[14] + m1[14]*m2[15]; M[15] = m1[3]*m2[12] + m1[7]*m2[13] + m1[11]*m2[14] + m1[15]*m2[15]; +#if defined ( USE_MATRIX_TEST ) definitelyIdentityMatrix=false; +#endif return *this; } @@ -581,6 +668,7 @@ namespace core template inline CMatrix4& CMatrix4::setbyproduct(const CMatrix4& other_a, const CMatrix4& other_b ) { +#if defined ( USE_MATRIX_TEST ) if ( other_a.isIdentity () ) return (*this = other_b); else @@ -588,17 +676,22 @@ namespace core return (*this = other_a); else return setbyproduct_nocheck(other_a,other_b); +#else + return setbyproduct_nocheck(other_a,other_b); +#endif } //! multiply by another matrix template inline CMatrix4 CMatrix4::operator*(const CMatrix4& m2) const { +#if defined ( USE_MATRIX_TEST ) // Testing purpose.. if ( this->isIdentity() ) return m2; if ( m2.isIdentity() ) return *this; +#endif CMatrix4 m3 ( EM4CONST_NOTHING ); @@ -641,7 +734,9 @@ namespace core M[12] = translation.X; M[13] = translation.Y; M[14] = translation.Z; +#if defined ( USE_MATRIX_TEST ) definitelyIdentityMatrix=false; +#endif return *this; } @@ -651,7 +746,9 @@ namespace core M[12] = -translation.X; M[13] = -translation.Y; M[14] = -translation.Z; +#if defined ( USE_MATRIX_TEST ) definitelyIdentityMatrix=false; +#endif return *this; } @@ -661,7 +758,9 @@ namespace core M[0] = scale.X; M[5] = scale.Y; M[10] = scale.Z; +#if defined ( USE_MATRIX_TEST ) definitelyIdentityMatrix=false; +#endif return *this; } @@ -727,7 +826,9 @@ namespace core M[8] = (T)( crsp*cy+sr*sy ); M[9] = (T)( crsp*sy-sr*cy ); M[10] = (T)( cr*cp ); +#if defined ( USE_MATRIX_TEST ) definitelyIdentityMatrix=false; +#endif return *this; } @@ -800,7 +901,9 @@ namespace core M[2] = (T)( crsp*cy+sr*sy ); M[6] = (T)( crsp*sy-sr*cy ); M[10] = (T)( cr*cp ); +#if defined ( USE_MATRIX_TEST ) definitelyIdentityMatrix=false; +#endif return *this; } @@ -812,7 +915,9 @@ namespace core { memset(M, 0, 16*sizeof(T)); M[0] = M[5] = M[10] = M[15] = (T)1; +#if defined ( USE_MATRIX_TEST ) definitelyIdentityMatrix=true; +#endif return *this; } @@ -824,8 +929,10 @@ namespace core template inline bool CMatrix4::isIdentity() const { +#if defined ( USE_MATRIX_TEST ) if (definitelyIdentityMatrix) return true; +#endif if (!equals( M[ 0], (T)1 ) || !equals( M[ 5], (T)1 ) || !equals( M[10], (T)1 ) || @@ -837,7 +944,9 @@ namespace core if ((j != i) && (!iszero((*this)(i,j)))) return false; +#if defined ( USE_MATRIX_TEST ) definitelyIdentityMatrix=true; +#endif return true; } @@ -875,8 +984,10 @@ namespace core template inline bool CMatrix4::isIdentity_integer_base() const { +#if defined ( USE_MATRIX_TEST ) if (definitelyIdentityMatrix) return true; +#endif if(IR(M[0])!=F32_VALUE_1) return false; if(IR(M[1])!=0) return false; if(IR(M[2])!=0) return false; @@ -896,7 +1007,10 @@ namespace core if(IR(M[13])!=0) return false; if(IR(M[13])!=0) return false; if(IR(M[15])!=F32_VALUE_1) return false; + +#if defined ( USE_MATRIX_TEST ) definitelyIdentityMatrix=true; +#endif return true; } @@ -998,8 +1112,10 @@ namespace core template inline void CMatrix4::transformBox(core::aabbox3d& box) const { +#if defined ( USE_MATRIX_TEST ) if (isIdentity()) return; +#endif transformVect(box.MinEdge); transformVect(box.MaxEdge); @@ -1010,6 +1126,11 @@ namespace core template inline void CMatrix4::transformBoxEx(core::aabbox3d& box) const { +#if defined ( USE_MATRIX_TEST ) + if (isIdentity()) + return; +#endif + const f32 Amin[3] = {box.MinEdge.X, box.MinEdge.Y, box.MinEdge.Z}; const f32 Amax[3] = {box.MaxEdge.X, box.MaxEdge.Y, box.MaxEdge.Z}; @@ -1099,12 +1220,13 @@ namespace core /// The inverse is calculated using Cramers rule. /// If no inverse exists then 'false' is returned. +#if defined ( USE_MATRIX_TEST ) if ( this->isIdentity() ) { out=*this; return true; } - +#endif const CMatrix4 &m = *this; f32 d = (m(0, 0) * m(1, 1) - m(0, 1) * m(1, 0)) * (m(2, 2) * m(3, 3) - m(2, 3) * m(3, 2)) - @@ -1167,7 +1289,10 @@ namespace core out(3, 3) = d * (m(0, 0) * (m(1, 1) * m(2, 2) - m(1, 2) * m(2, 1)) + m(0, 1) * (m(1, 2) * m(2, 0) - m(1, 0) * m(2, 2)) + m(0, 2) * (m(1, 0) * m(2, 1) - m(1, 1) * m(2, 0))); + +#if defined ( USE_MATRIX_TEST ) out.definitelyIdentityMatrix = definitelyIdentityMatrix; +#endif return true; } @@ -1196,7 +1321,10 @@ namespace core out.M[13] = (T)-(M[12]*M[4] + M[13]*M[5] + M[14]*M[6]); out.M[14] = (T)-(M[12]*M[8] + M[13]*M[9] + M[14]*M[10]); out.M[15] = 1; + +#if defined ( USE_MATRIX_TEST ) out.definitelyIdentityMatrix = definitelyIdentityMatrix; +#endif return true; } @@ -1205,9 +1333,10 @@ namespace core template inline bool CMatrix4::makeInverse() { +#if defined ( USE_MATRIX_TEST ) if (definitelyIdentityMatrix) return true; - +#endif CMatrix4 temp ( EM4CONST_NOTHING ); if (getInverse(temp)) @@ -1226,7 +1355,9 @@ namespace core if (this==&other) return *this; memcpy(M, other.M, 16*sizeof(T)); +#if defined ( USE_MATRIX_TEST ) definitelyIdentityMatrix=other.definitelyIdentityMatrix; +#endif return *this; } @@ -1236,7 +1367,10 @@ namespace core { for (s32 i = 0; i < 16; ++i) M[i]=scalar; + +#if defined ( USE_MATRIX_TEST ) definitelyIdentityMatrix=false; +#endif return *this; } @@ -1244,8 +1378,10 @@ namespace core template inline bool CMatrix4::operator==(const CMatrix4 &other) const { +#if defined ( USE_MATRIX_TEST ) if (definitelyIdentityMatrix && other.definitelyIdentityMatrix) return true; +#endif for (s32 i = 0; i < 16; ++i) if (M[i] != other.M[i]) return false; @@ -1290,7 +1426,10 @@ namespace core M[14] = (T)(zNear*zFar/(zNear-zFar)); // DirectX version // M[14] = (T)(2.0f*zNear*zFar/(zNear-zFar)); // OpenGL version M[15] = 0; + +#if defined ( USE_MATRIX_TEST ) definitelyIdentityMatrix=false; +#endif return *this; } @@ -1322,7 +1461,10 @@ namespace core M[13] = 0; M[14] = (T)(-zNear*zFar/(zFar-zNear)); M[15] = 0; + +#if defined ( USE_MATRIX_TEST ) definitelyIdentityMatrix=false; +#endif return *this; } @@ -1351,7 +1493,10 @@ namespace core M[13] = 0; M[14] = (T)(zNear/(zNear-zFar)); M[15] = 1; + +#if defined ( USE_MATRIX_TEST ) definitelyIdentityMatrix=false; +#endif return *this; } @@ -1380,7 +1525,10 @@ namespace core M[13] = 0; M[14] = (T)(zNear/(zNear-zFar)); M[15] = -1; + +#if defined ( USE_MATRIX_TEST ) definitelyIdentityMatrix=false; +#endif return *this; } @@ -1409,7 +1557,10 @@ namespace core M[13] = 0; M[14] = (T)(zNear*zFar/(zNear-zFar)); M[15] = 0; + +#if defined ( USE_MATRIX_TEST ) definitelyIdentityMatrix=false; +#endif return *this; } @@ -1438,7 +1589,9 @@ namespace core M[13] = 0; M[14] = (T)(zNear*zFar/(zNear-zFar)); M[15] = 0; +#if defined ( USE_MATRIX_TEST ) definitelyIdentityMatrix=false; +#endif return *this; } @@ -1469,7 +1622,9 @@ namespace core M[13] = (T)(-plane.D * light.Y); M[14] = (T)(-plane.D * light.Z); M[15] = (T)(-plane.D * point + d); +#if defined ( USE_MATRIX_TEST ) definitelyIdentityMatrix=false; +#endif return *this; } @@ -1507,7 +1662,9 @@ namespace core M[13] = (T)-yaxis.dotProduct(position); M[14] = (T)-zaxis.dotProduct(position); M[15] = 1; +#if defined ( USE_MATRIX_TEST ) definitelyIdentityMatrix=false; +#endif return *this; } @@ -1546,7 +1703,9 @@ namespace core M[13] = (T)-yaxis.dotProduct(position); M[14] = (T)-zaxis.dotProduct(position); M[15] = 1; +#if defined ( USE_MATRIX_TEST ) definitelyIdentityMatrix=false; +#endif return *this; } @@ -1601,7 +1760,9 @@ namespace core o[13] = M[ 7]; o[14] = M[11]; o[15] = M[15]; +#if defined ( USE_MATRIX_TEST ) o.definitelyIdentityMatrix=definitelyIdentityMatrix; +#endif } @@ -1621,6 +1782,140 @@ namespace core return setScale(core::vector3d((T)scaleX, (T)scaleY, (T)zScale)); } + //! Builds a matrix that rotates from one vector to another + /** \param from: vector to rotate from + \param to: vector to rotate to + + http://www.euclideanspace.com/maths/geometry/rotations/conversions/angleToMatrix/index.htm + */ + template + inline CMatrix4& CMatrix4::buildRotateFromTo(const core::vector3df& from, const core::vector3df& to) + { + // unit vectors + core::vector3df f ( from ); + core::vector3df t ( to ); + f.normalize (); + t.normalize (); + + // axis multiplication by sin + core::vector3df vs ( t.crossProduct ( f ) ); + + // axis of rotation + core::vector3df v ( vs ); + v.normalize(); + + // cosinus angle + T ca = f.dotProduct ( t ); + + core::vector3df vt ( v * ( (T) 1 - ca ) ); + + M[0] = vt.X * v.X + ca; + M[5] = vt.Y * v.Y + ca; + M[10] = vt.Z * v.Z + ca; + + vt.X *= v.Y; + vt.Z *= v.X; + vt.Y *= v.Z; + + M[1] = vt.X - vs.Z; + M[2] = vt.Z + vs.Y; + M[3] = (T) 0; + + M[4] = vt.X + vs.Z; + M[6] = vt.Y - vs.X; + M[7] = (T) 0; + + M[8] = vt.Z - vs.Y; + M[9] = vt.Y + vs.X; + M[11] = (T) 0; + + M[12] = (T) 0; + M[13] = (T) 0; + M[14] = (T) 0; + M[15] = (T) 1; + + return *this; + } + + //! Builds a matrix which rotates a source vector to a look vector over an arbitrary axis + /** \param camPos: viewer position in world coo + \param center: object position in world-coo and rotation pivot + \param translation: object final translation from center + \param axis: axis to rotate about + \param from: source vector to rotate from + */ + template + inline void CMatrix4::buildAxisAlignedBillboard( const core::vector3df& camPos, + const core::vector3df& center, + const core::vector3df& translation, + const core::vector3df& axis, + const core::vector3df& from + ) + { + // axis of rotation + core::vector3df up = axis; + up.normalize (); + + core::vector3df forward = camPos - center; + forward.normalize(); + + core::vector3df right = up.crossProduct ( forward ); + right.normalize (); + + // correct look vector + core::vector3df look = right.crossProduct ( up ); + + // rotate from to + + // axis multiplication by sin + core::vector3df vs = look.crossProduct ( from ); + + // cosinus angle + f32 ca = from.dotProduct ( look ); + + core::vector3df vt ( up * ( 1.f - ca ) ); + + M[0] = vt.X * up.X + ca; + M[5] = vt.Y * up.Y + ca; + M[10] = vt.Z * up.Z + ca; + + vt.X *= up.Y; + vt.Z *= up.X; + vt.Y *= up.Z; + + M[1] = vt.X - vs.Z; + M[2] = vt.Z + vs.Y; + M[3] = (T) 0; + + M[4] = vt.X + vs.Z; + M[6] = vt.Y - vs.X; + M[7] = (T) 0; + + M[8] = vt.Z - vs.Y; + M[9] = vt.Y + vs.X; + M[11] = (T) 0; + + setRotationCenter ( center, translation ); + + } + + + //! Builds a combined matrix which translate to a center before rotation and translate afterwards + /** \param from: vector to rotate from + \param to: vector to rotate to + */ + template + inline void CMatrix4::setRotationCenter(const core::vector3df& center, const core::vector3df& translation) + { + M[12] = -M[0]*center.X - M[4]*center.Y - M[8]*center.Z + (center.X - translation.X ); + M[13] = -M[1]*center.X - M[5]*center.Y - M[9]*center.Z + (center.Y - translation.Y ); + M[14] = -M[2]*center.X - M[6]*center.Y - M[10]*center.Z + (center.Z - translation.Z ); + M[15] = (T) 1.0; +#if defined ( USE_MATRIX_TEST ) + definitelyIdentityMatrix=false; +#endif + } + /*! Generate texture coordinates as linear functions so that: u = Ux*x + Uy*y + Uz*z + Uw @@ -1661,7 +1956,9 @@ namespace core M[13] = 0; M[14] = 0; M[15] = 1; +#if defined ( USE_MATRIX_TEST ) definitelyIdentityMatrix=false; +#endif return *this; } @@ -1680,7 +1977,10 @@ namespace core M[8] = (T)(0.5f * ( s - c) + 0.5f); M[9] = (T)(-0.5f * ( s + c) + 0.5f); + +#if defined ( USE_MATRIX_TEST ) definitelyIdentityMatrix = definitelyIdentityMatrix && (rotateRad==0.0f); +#endif return *this; } @@ -1690,7 +1990,10 @@ namespace core { M[8] = (T)x; M[9] = (T)y; + +#if defined ( USE_MATRIX_TEST ) definitelyIdentityMatrix = definitelyIdentityMatrix && (x==0.0f) && (y==0.0f); +#endif return *this; } @@ -1700,7 +2003,10 @@ namespace core { M[2] = (T)x; M[6] = (T)y; + +#if defined ( USE_MATRIX_TEST ) definitelyIdentityMatrix = definitelyIdentityMatrix && (x==0.0f) && (y==0.0f) ; +#endif return *this; } @@ -1709,7 +2015,9 @@ namespace core { M[0] = (T)sx; M[5] = (T)sy; +#if defined ( USE_MATRIX_TEST ) definitelyIdentityMatrix = definitelyIdentityMatrix && (sx==1.0f) && (sy==1.0f); +#endif return *this; } @@ -1721,7 +2029,10 @@ namespace core M[5] = (T)sy; M[8] = (T)(0.5f - 0.5f * sx); M[9] = (T)(0.5f - 0.5f * sy); + +#if defined ( USE_MATRIX_TEST ) definitelyIdentityMatrix = definitelyIdentityMatrix && (sx==1.0f) && (sy==1.0f); +#endif return *this; } @@ -1732,7 +2043,9 @@ namespace core { memcpy(M,data, 16*sizeof(T)); - definitelyIdentityMatrix = false; +#if defined ( USE_MATRIX_TEST ) + definitelyIdentityMatrix=false; +#endif return *this; } @@ -1741,7 +2054,9 @@ namespace core template inline void CMatrix4::setDefinitelyIdentityMatrix( bool isDefinitelyIdentityMatrix) { +#if defined ( USE_MATRIX_TEST ) definitelyIdentityMatrix = isDefinitelyIdentityMatrix; +#endif } @@ -1749,7 +2064,11 @@ namespace core template inline bool CMatrix4::getDefinitelyIdentityMatrix() const { +#if defined ( USE_MATRIX_TEST ) return definitelyIdentityMatrix; +#else + return false; +#endif } diff --git a/include/quaternion.h b/include/quaternion.h index a4a9e9a3..568db401 100644 --- a/include/quaternion.h +++ b/include/quaternion.h @@ -83,7 +83,26 @@ class quaternion matrix4 getMatrix() const; //! Creates a matrix from this quaternion - void getMatrix( matrix4 &dest ) const; + void getMatrix( matrix4 &dest, const vector3df &translation ) const; + + /*! + Creates a matrix from this quaternion + Rotate about a center point + shortcut for + core::quaternion q; + q.rotationFromTo ( vin[i].Normal, forward ); + q.getMatrixCenter ( lookat, center, newPos ); + + core::matrix4 m2; + m2.setInverseTranslation ( center ); + lookat *= m2; + + core::matrix4 m3; + m2.setTranslation ( newPos ); + lookat *= m3; + + */ + void getMatrixCenter( matrix4 &dest, const vector3df ¢er, const vector3df &translation ) const; //! Creates a matrix from this quaternion inline void getMatrix_transposed( matrix4 &dest ) const; @@ -275,28 +294,74 @@ inline matrix4 quaternion::getMatrix() const } -// Creates a matrix from this quaternion -inline void quaternion::getMatrix( matrix4 &dest ) const +/*! + Creates a matrix from this quaternion +*/ +inline void quaternion::getMatrix( matrix4 &dest, const core::vector3df ¢er ) const { - dest[0] = 1.0f - 2.0f*Y*Y - 2.0f*Z*Z; - dest[1] = 2.0f*X*Y + 2.0f*Z*W; - dest[2] = 2.0f*X*Z - 2.0f*Y*W; - dest[3] = 0.0f; + f32 * m = dest.pointer(); - dest[4] = 2.0f*X*Y - 2.0f*Z*W; - dest[5] = 1.0f - 2.0f*X*X - 2.0f*Z*Z; - dest[6] = 2.0f*Z*Y + 2.0f*X*W; - dest[7] = 0.0f; + m[0] = 1.0f - 2.0f*Y*Y - 2.0f*Z*Z; + m[1] = 2.0f*X*Y + 2.0f*Z*W; + m[2] = 2.0f*X*Z - 2.0f*Y*W; + m[3] = 0.0f; - dest[8] = 2.0f*X*Z + 2.0f*Y*W; - dest[9] = 2.0f*Z*Y - 2.0f*X*W; - dest[10] = 1.0f - 2.0f*X*X - 2.0f*Y*Y; - dest[11] = 0.0f; + m[4] = 2.0f*X*Y - 2.0f*Z*W; + m[5] = 1.0f - 2.0f*X*X - 2.0f*Z*Z; + m[6] = 2.0f*Z*Y + 2.0f*X*W; + m[7] = 0.0f; - dest[12] = 0.f; - dest[13] = 0.f; - dest[14] = 0.f; - dest[15] = 1.f; + m[8] = 2.0f*X*Z + 2.0f*Y*W; + m[9] = 2.0f*Z*Y - 2.0f*X*W; + m[10] = 1.0f - 2.0f*X*X - 2.0f*Y*Y; + m[11] = 0.0f; + + m[12] = center.X; + m[13] = center.Y; + m[14] = center.Z; + m[15] = 1.f; + + //dest.setDefinitelyIdentityMatrix ( matrix4::BIT_IS_NOT_IDENTITY ); + dest.setDefinitelyIdentityMatrix ( false ); +} + + + +/*! + Creates a matrix from this quaternion + Rotate about a center point + shortcut for + core::quaternion q; + q.rotationFromTo ( vin[i].Normal, forward ); + q.getMatrix ( lookat, center ); + + core::matrix4 m2; + m2.setInverseTranslation ( center ); + lookat *= m2; +*/ +inline void quaternion::getMatrixCenter( matrix4 &dest, + const core::vector3df ¢er, + const core::vector3df &translation + ) const +{ + f32 * m = dest.pointer(); + + m[0] = 1.0f - 2.0f*Y*Y - 2.0f*Z*Z; + m[1] = 2.0f*X*Y + 2.0f*Z*W; + m[2] = 2.0f*X*Z - 2.0f*Y*W; + m[3] = 0.0f; + + m[4] = 2.0f*X*Y - 2.0f*Z*W; + m[5] = 1.0f - 2.0f*X*X - 2.0f*Z*Z; + m[6] = 2.0f*Z*Y + 2.0f*X*W; + m[7] = 0.0f; + + m[8] = 2.0f*X*Z + 2.0f*Y*W; + m[9] = 2.0f*Z*Y - 2.0f*X*W; + m[10] = 1.0f - 2.0f*X*X - 2.0f*Y*Y; + m[11] = 0.0f; + + dest.setRotationCenter ( center, translation ); } // Creates a matrix from this quaternion @@ -321,6 +386,8 @@ inline void quaternion::getMatrix_transposed( matrix4 &dest ) const dest[7] = 0.f; dest[11] = 0.f; dest[15] = 1.f; + //dest.setDefinitelyIdentityMatrix ( matrix4::BIT_IS_NOT_IDENTITY ); + dest.setDefinitelyIdentityMatrix ( false ); } @@ -534,7 +601,6 @@ inline core::quaternion& quaternion::rotationFromTo(const vector3df& from, const const f32 s = sqrtf( (1+d)*2 ); // optimize inv_sqrt const f32 invs = 1.f / s; const vector3df c = v0.crossProduct(v1)*invs; - X = c.X; Y = c.Y; Z = c.Z; diff --git a/include/rect.h b/include/rect.h index bf2ec35d..60db9a0c 100644 --- a/include/rect.h +++ b/include/rect.h @@ -35,7 +35,8 @@ namespace core rect(const position2d& upperLeft, const position2d& lowerRight) : UpperLeftCorner(upperLeft), LowerRightCorner(lowerRight) {} - rect(const position2d& pos, const dimension2d& size) + template + rect(const position2d& pos, const dimension2d& size) : UpperLeftCorner(pos), LowerRightCorner(pos.X + size.Width, pos.Y + size.Height) {} diff --git a/include/vector2d.h b/include/vector2d.h index 83a92de5..8bff9838 100644 --- a/include/vector2d.h +++ b/include/vector2d.h @@ -37,7 +37,8 @@ public: vector2d operator-() const { return vector2d(-X, -Y); } vector2d& operator=(const vector2d& other) { X = other.X; Y = other.Y; return *this; } - vector2d& operator=(const dimension2d& other) { X = other.Width; Y = other.Width; return *this; } + + vector2d& operator=(const dimension2d& other) { X = other.Width; Y = other.Height; return *this; } vector2d operator+(const vector2d& other) const { return vector2d(X + other.X, Y + other.Y); } vector2d operator+(const dimension2d& other) const { return vector2d(X + other.Width, Y + other.Height); } diff --git a/include/vector3d.h b/include/vector3d.h index 0c501934..2db2c0de 100644 --- a/include/vector3d.h +++ b/include/vector3d.h @@ -140,10 +140,15 @@ namespace core \return Reference to this vector after normalization. */ vector3d& normalize() { +#if 0 f32 length = (f32)(X*X + Y*Y + Z*Z); if (core::equals(length, 0.f)) return *this; length = core::reciprocal_squareroot ( (f32)length ); +#else + const T length = core::reciprocal_squareroot ( (X*X + Y*Y + Z*Z) ); +#endif + X = (T)(X * length); Y = (T)(Y * length); Z = (T)(Z * length); diff --git a/media/gun.jpg b/media/gun.jpg new file mode 100644 index 00000000..0e954982 Binary files /dev/null and b/media/gun.jpg differ diff --git a/media/gun.md2 b/media/gun.md2 new file mode 100644 index 00000000..082d07c7 Binary files /dev/null and b/media/gun.md2 differ diff --git a/media/iconlist.png b/media/iconlist.png new file mode 100644 index 00000000..7484df35 Binary files /dev/null and b/media/iconlist.png differ diff --git a/media/map-20kdm2.pk3 b/media/map-20kdm2.pk3 index 50ed50d9..d86083ef 100644 Binary files a/media/map-20kdm2.pk3 and b/media/map-20kdm2.pk3 differ diff --git a/source/Irrlicht/C3DSMeshFileLoader.cpp b/source/Irrlicht/C3DSMeshFileLoader.cpp index cd25ec19..f38efcb7 100644 --- a/source/Irrlicht/C3DSMeshFileLoader.cpp +++ b/source/Irrlicht/C3DSMeshFileLoader.cpp @@ -23,97 +23,103 @@ namespace scene { -// Primary chunk -const u16 C3DS_MAIN3DS = 0x4D4D; +enum e3DSChunk +{ -// Main Chunks -const u16 C3DS_EDIT3DS = 0x3D3D; -const u16 C3DS_KEYF3DS = 0xB000; -const u16 C3DS_VERSION = 0x0002; -const u16 C3DS_MESHVERSION = 0x3D3E; + // Primary chunk + C3DS_MAIN3DS = 0x4D4D, -// sub chunks of C3DS_EDIT3DS -const u16 C3DS_EDIT_MATERIAL = 0xAFFF; -const u16 C3DS_EDIT_OBJECT = 0x4000; + // Main Chunks + C3DS_EDIT3DS = 0x3D3D, + C3DS_KEYF3DS = 0xB000, + C3DS_VERSION = 0x0002, + C3DS_MESHVERSION = 0x3D3E, -// sub chunks of C3DS_EDIT_MATERIAL -const u16 C3DS_MATNAME = 0xA000; -const u16 C3DS_MATAMBIENT = 0xA010; -const u16 C3DS_MATDIFFUSE = 0xA020; -const u16 C3DS_MATSPECULAR = 0xA030; -const u16 C3DS_MATSHININESS = 0xA040; -const u16 C3DS_MATSHIN2PCT = 0xA041; -const u16 C3DS_TRANSPARENCY = 0xA050; -const u16 C3DS_TRANSPARENCY_FALLOFF = 0xA052; -const u16 C3DS_REFL_BLUR = 0xA053; -const u16 C3DS_TWO_SIDE = 0xA081; -const u16 C3DS_WIRE = 0xA085; -const u16 C3DS_SHADING = 0xA100; -const u16 C3DS_MATTEXMAP = 0xA200; -const u16 C3DS_MATSPECMAP = 0xA204; -const u16 C3DS_MATOPACMAP = 0xA210; -const u16 C3DS_MATREFLMAP = 0xA220; -const u16 C3DS_MATBUMPMAP = 0xA230; -const u16 C3DS_MATMAPFILE = 0xA300; -const u16 C3DS_MAT_TEXTILING = 0xA351; -const u16 C3DS_MAT_USCALE = 0xA354; -const u16 C3DS_MAT_VSCALE = 0xA356; -const u16 C3DS_MAT_UOFFSET = 0xA358; -const u16 C3DS_MAT_VOFFSET = 0xA35A; + // sub chunks of C3DS_EDIT3DS + C3DS_EDIT_MATERIAL = 0xAFFF, + C3DS_EDIT_OBJECT = 0x4000, -// subs of C3DS_EDIT_OBJECT -const u16 C3DS_OBJTRIMESH = 0x4100; + // sub chunks of C3DS_EDIT_MATERIAL + C3DS_MATNAME = 0xA000, + C3DS_MATAMBIENT = 0xA010, + C3DS_MATDIFFUSE = 0xA020, + C3DS_MATSPECULAR = 0xA030, + C3DS_MATSHININESS = 0xA040, + C3DS_MATSHIN2PCT = 0xA041, + C3DS_TRANSPARENCY = 0xA050, + C3DS_TRANSPARENCY_FALLOFF = 0xA052, + C3DS_REFL_BLUR = 0xA053, + C3DS_TWO_SIDE = 0xA081, + C3DS_WIRE = 0xA085, + C3DS_SHADING = 0xA100, + C3DS_MATTEXMAP = 0xA200, + C3DS_MATSPECMAP = 0xA204, + C3DS_MATOPACMAP = 0xA210, + C3DS_MATREFLMAP = 0xA220, + C3DS_MATBUMPMAP = 0xA230, + C3DS_MATMAPFILE = 0xA300, + C3DS_MAT_TEXTILING = 0xA351, + C3DS_MAT_USCALE = 0xA354, + C3DS_MAT_VSCALE = 0xA356, + C3DS_MAT_UOFFSET = 0xA358, + C3DS_MAT_VOFFSET = 0xA35A, -// subs of C3DS_OBJTRIMESH -const u16 C3DS_TRIVERT = 0x4110; -const u16 C3DS_POINTFLAGARRAY= 0x4111; -const u16 C3DS_TRIFACE = 0x4120; -const u16 C3DS_TRIFACEMAT = 0x4130; -const u16 C3DS_TRIUV = 0x4140; -const u16 C3DS_TRISMOOTH = 0x4150; -const u16 C3DS_TRIMATRIX = 0x4160; -const u16 C3DS_MESHCOLOR = 0x4165; -const u16 C3DS_DIRECT_LIGHT = 0x4600; -const u16 C3DS_DL_INNER_RANGE= 0x4659; -const u16 C3DS_DL_OUTER_RANGE= 0x465A; -const u16 C3DS_DL_MULTIPLIER = 0x465B; -const u16 C3DS_CAMERA = 0x4700; -const u16 C3DS_CAM_SEE_CONE = 0x4710; -const u16 C3DS_CAM_RANGES = 0x4720; + // subs of C3DS_EDIT_OBJECT + C3DS_OBJTRIMESH = 0x4100, -// subs of C3DS_KEYF3DS -const u16 C3DS_KF_HDR = 0xB00A; -const u16 C3DS_AMBIENT_TAG = 0xB001; -const u16 C3DS_OBJECT_TAG = 0xB002; -const u16 C3DS_CAMERA_TAG = 0xB003; -const u16 C3DS_TARGET_TAG = 0xB004; -const u16 C3DS_LIGHTNODE_TAG = 0xB005; -const u16 C3DS_KF_SEG = 0xB008; -const u16 C3DS_KF_CURTIME = 0xB009; -const u16 C3DS_KF_NODE_HDR = 0xB010; -const u16 C3DS_PIVOTPOINT = 0xB013; -const u16 C3DS_BOUNDBOX = 0xB014; -const u16 C3DS_MORPH_SMOOTH = 0xB015; -const u16 C3DS_POS_TRACK_TAG = 0xB020; -const u16 C3DS_ROT_TRACK_TAG = 0xB021; -const u16 C3DS_SCL_TRACK_TAG = 0xB022; -const u16 C3DS_NODE_ID = 0xB030; + // subs of C3DS_OBJTRIMESH + C3DS_TRIVERT = 0x4110, + C3DS_POINTFLAGARRAY= 0x4111, + C3DS_TRIFACE = 0x4120, + C3DS_TRIFACEMAT = 0x4130, + C3DS_TRIUV = 0x4140, + C3DS_TRISMOOTH = 0x4150, + C3DS_TRIMATRIX = 0x4160, + C3DS_MESHCOLOR = 0x4165, + C3DS_DIRECT_LIGHT = 0x4600, + C3DS_DL_INNER_RANGE= 0x4659, + C3DS_DL_OUTER_RANGE= 0x465A, + C3DS_DL_MULTIPLIER = 0x465B, + C3DS_CAMERA = 0x4700, + C3DS_CAM_SEE_CONE = 0x4710, + C3DS_CAM_RANGES = 0x4720, -// Viewport definitions -const u16 C3DS_VIEWPORT_LAYOUT = 0x7001; -const u16 C3DS_VIEWPORT_DATA = 0x7011; -const u16 C3DS_VIEWPORT_DATA_3 = 0x7012; -const u16 C3DS_VIEWPORT_SIZE = 0x7020; + // subs of C3DS_KEYF3DS + C3DS_KF_HDR = 0xB00A, + C3DS_AMBIENT_TAG = 0xB001, + C3DS_OBJECT_TAG = 0xB002, + C3DS_CAMERA_TAG = 0xB003, + C3DS_TARGET_TAG = 0xB004, + C3DS_LIGHTNODE_TAG = 0xB005, + C3DS_KF_SEG = 0xB008, + C3DS_KF_CURTIME = 0xB009, + C3DS_KF_NODE_HDR = 0xB010, + C3DS_PIVOTPOINT = 0xB013, + C3DS_BOUNDBOX = 0xB014, + C3DS_MORPH_SMOOTH = 0xB015, + C3DS_POS_TRACK_TAG = 0xB020, + C3DS_ROT_TRACK_TAG = 0xB021, + C3DS_SCL_TRACK_TAG = 0xB022, + C3DS_NODE_ID = 0xB030, -// different color chunk types -const u16 C3DS_COL_RGB = 0x0010; -const u16 C3DS_COL_TRU = 0x0011; -const u16 C3DS_COL_LIN_24 = 0x0012; -const u16 C3DS_COL_LIN_F = 0x0013; + // Viewport definitions + C3DS_VIEWPORT_LAYOUT = 0x7001, + C3DS_VIEWPORT_DATA = 0x7011, + C3DS_VIEWPORT_DATA_3 = 0x7012, + C3DS_VIEWPORT_SIZE = 0x7020, -// percentage chunk types -const u16 C3DS_PERCENTAGE_I = 0x0030; -const u16 C3DS_PERCENTAGE_F = 0x0031; + // different color chunk types + C3DS_COL_RGB = 0x0010, + C3DS_COL_TRU = 0x0011, + C3DS_COL_LIN_24 = 0x0012, + C3DS_COL_LIN_F = 0x0013, + + // percentage chunk types + C3DS_PERCENTAGE_I = 0x0030, + C3DS_PERCENTAGE_F = 0x0031, + + C3DS_CHUNK_MAX = 0xFFFF +}; //! Constructor @@ -147,9 +153,9 @@ C3DSMeshFileLoader::~C3DSMeshFileLoader() //! returns true if the file maybe is able to be loaded by this class //! based on the file extension (e.g. ".bsp") -bool C3DSMeshFileLoader::isALoadableFileExtension(const c8* filename) const +bool C3DSMeshFileLoader::isALoadableFileExtension(const core::string& filename) const { - return strstr(filename, ".3ds")!=0; + return core::hasFileExtension ( filename, "3ds" ); } @@ -1133,13 +1139,13 @@ void C3DSMeshFileLoader::loadMaterials(io::IReadFile* file) if (Materials[i].Filename[0].size()) { video::ITexture* texture = 0; - if (FileSystem->existFile(Materials[i].Filename[0].c_str())) - texture = SceneManager->getVideoDriver()->getTexture(Materials[i].Filename[0].c_str()); + if (FileSystem->existFile(Materials[i].Filename[0])) + texture = SceneManager->getVideoDriver()->getTexture(Materials[i].Filename[0]); if (!texture) { const core::stringc fname = FileSystem->getFileDir(modelFilename) + "/" + FileSystem->getFileBasename(Materials[i].Filename[0]); - if (FileSystem->existFile(fname.c_str())) - texture = SceneManager->getVideoDriver()->getTexture(fname.c_str()); + if (FileSystem->existFile(fname)) + texture = SceneManager->getVideoDriver()->getTexture(fname); } if (!texture) os::Printer::log("Could not load a texture for entry in 3ds file", @@ -1151,13 +1157,13 @@ void C3DSMeshFileLoader::loadMaterials(io::IReadFile* file) if (Materials[i].Filename[2].size()) { video::ITexture* texture = 0; - if (FileSystem->existFile(Materials[i].Filename[2].c_str())) - texture = SceneManager->getVideoDriver()->getTexture(Materials[i].Filename[2].c_str()); + if (FileSystem->existFile(Materials[i].Filename[2])) + texture = SceneManager->getVideoDriver()->getTexture(Materials[i].Filename[2]); if (!texture) { const core::stringc fname = FileSystem->getFileDir(modelFilename) + "/" + FileSystem->getFileBasename(Materials[i].Filename[2]); - if (FileSystem->existFile(fname.c_str())) - texture = SceneManager->getVideoDriver()->getTexture(fname.c_str()); + if (FileSystem->existFile(fname)) + texture = SceneManager->getVideoDriver()->getTexture(fname); } if (!texture) { @@ -1174,13 +1180,13 @@ void C3DSMeshFileLoader::loadMaterials(io::IReadFile* file) if (Materials[i].Filename[3].size()) { video::ITexture* texture = 0; - if (FileSystem->existFile(Materials[i].Filename[3].c_str())) - texture = SceneManager->getVideoDriver()->getTexture(Materials[i].Filename[3].c_str()); + if (FileSystem->existFile(Materials[i].Filename[3])) + texture = SceneManager->getVideoDriver()->getTexture(Materials[i].Filename[3]); if (!texture) { const core::stringc fname = FileSystem->getFileDir(modelFilename) + "/" + FileSystem->getFileBasename(Materials[i].Filename[3]); - if (FileSystem->existFile(fname.c_str())) - texture = SceneManager->getVideoDriver()->getTexture(fname.c_str()); + if (FileSystem->existFile(fname)) + texture = SceneManager->getVideoDriver()->getTexture(fname); } if (!texture) @@ -1199,13 +1205,13 @@ void C3DSMeshFileLoader::loadMaterials(io::IReadFile* file) if (Materials[i].Filename[4].size()) { video::ITexture* texture = 0; - if (FileSystem->existFile(Materials[i].Filename[4].c_str())) - texture = SceneManager->getVideoDriver()->getTexture(Materials[i].Filename[4].c_str()); + if (FileSystem->existFile(Materials[i].Filename[4])) + texture = SceneManager->getVideoDriver()->getTexture(Materials[i].Filename[4]); if (!texture) { const core::stringc fname = FileSystem->getFileDir(modelFilename) + "/" + FileSystem->getFileBasename(Materials[i].Filename[4]); - if (FileSystem->existFile(fname.c_str())) - texture = SceneManager->getVideoDriver()->getTexture(fname.c_str()); + if (FileSystem->existFile(fname)) + texture = SceneManager->getVideoDriver()->getTexture(fname); } if (!texture) os::Printer::log("Could not load a texture for entry in 3ds file", diff --git a/source/Irrlicht/C3DSMeshFileLoader.h b/source/Irrlicht/C3DSMeshFileLoader.h index 9add65fb..aeefa9f0 100644 --- a/source/Irrlicht/C3DSMeshFileLoader.h +++ b/source/Irrlicht/C3DSMeshFileLoader.h @@ -30,7 +30,7 @@ public: //! returns true if the file maybe is able to be loaded by this class //! based on the file extension (e.g. ".cob") - virtual bool isALoadableFileExtension(const c8* fileName) const; + virtual bool isALoadableFileExtension(const core::string& filename) const; //! creates/loads an animated mesh from the file. //! \return Pointer to the created mesh. Returns 0 if loading failed. diff --git a/source/Irrlicht/CAnimatedMeshMD3.cpp b/source/Irrlicht/CAnimatedMeshMD3.cpp index 28391fb1..dc2b01eb 100644 --- a/source/Irrlicht/CAnimatedMeshMD3.cpp +++ b/source/Irrlicht/CAnimatedMeshMD3.cpp @@ -25,16 +25,18 @@ namespace scene #endif -struct SMD3Bone +//! General properties of a single animation frame. +struct SMD3Frame { - f32 Mins[3]; // bounding box per frame - f32 Maxs[3]; - f32 Position[3]; // position of bounding box - f32 scale; - c8 creator[16]; + f32 mins[3]; // bounding box per frame + f32 maxs[3]; + f32 position[3]; // position of bounding box + f32 radius; // radius of bounding sphere + c8 creator[16]; // name of frame }; +//! An attachment point for another MD3 model. struct SMD3Tag { c8 Name[64]; //name of 'tag' as it's usually called in the md3 files try to see it as a sub-mesh/seperate mesh-part. @@ -42,9 +44,11 @@ struct SMD3Tag f32 rotationMatrix[9]; //3x3 rotation direction of tag }; -struct SMD3Skin +//!Shader +struct SMD3Shader { - c8 name[68]; // name of skin + c8 name[64]; // name of shader + s32 shaderIndex; }; @@ -67,7 +71,6 @@ CAnimatedMeshMD3::CAnimatedMeshMD3() #endif Mesh = new SMD3Mesh(); - memset( &Mesh->MD3Header, 0, sizeof ( Mesh->MD3Header ) ); setInterpolationShift ( 0, 0 ); } @@ -112,7 +115,7 @@ void CAnimatedMeshMD3::setDirty(E_BUFFER_TYPE buffer) //! Returns the animated tag list based on a detail level. 0 is the lowest, 255 the highest detail. -SMD3QuaterionTagList *CAnimatedMeshMD3::getTagList(s32 frame, s32 detailLevel, s32 startFrameLoop, s32 endFrameLoop) +SMD3QuaternionTagList *CAnimatedMeshMD3::getTagList(s32 frame, s32 detailLevel, s32 startFrameLoop, s32 endFrameLoop) { if ( 0 == Mesh ) return 0; @@ -175,7 +178,7 @@ IMesh* CAnimatedMeshMD3::getMesh(s32 frame, s32 detailLevel, s32 startFrameLoop, { buildVertexArray(frameA, frameB, iPol, Mesh->Buffer[i], - (SMeshBuffer*) MeshIPol.getMeshBuffer(i) + (SMeshBufferLightMap*) MeshIPol.getMeshBuffer(i) ); } MeshIPol.recalculateBoundingBox (); @@ -191,7 +194,7 @@ IMesh* CAnimatedMeshMD3::getMesh(s32 frame, s32 detailLevel, s32 startFrameLoop, //! create a Irrlicht MeshBuffer for a MD3 MeshBuffer IMeshBuffer * CAnimatedMeshMD3::createMeshBuffer(const SMD3MeshBuffer* source) { - SMeshBuffer * dest = new SMeshBuffer(); + SMeshBufferLightMap * dest = new SMeshBufferLightMap(); dest->Vertices.set_used( source->MeshHeader.numVertices ); dest->Indices.set_used( source->Indices.size () ); @@ -208,10 +211,12 @@ IMeshBuffer * CAnimatedMeshMD3::createMeshBuffer(const SMD3MeshBuffer* source) // fill in static vertex info for ( i = 0; i!= (u32)source->MeshHeader.numVertices; ++i ) { - video::S3DVertex &v = dest->Vertices[i]; + video::S3DVertex2TCoords &v = dest->Vertices[i]; v.Color = 0xFFFFFFFF; v.TCoords.X = source->Tex[i].u; v.TCoords.Y = source->Tex[i].v; + v.TCoords2.X = 0.f; + v.TCoords2.Y = 0.f; } return dest; } @@ -220,7 +225,7 @@ IMeshBuffer * CAnimatedMeshMD3::createMeshBuffer(const SMD3MeshBuffer* source) //! build final mesh's vertices from frames frameA and frameB with linear interpolation. void CAnimatedMeshMD3::buildVertexArray ( u32 frameA, u32 frameB, f32 interpolate, const SMD3MeshBuffer * source, - SMeshBuffer * dest + SMeshBufferLightMap * dest ) { const u32 frameOffsetA = frameA * source->MeshHeader.numVertices; @@ -229,7 +234,7 @@ void CAnimatedMeshMD3::buildVertexArray ( u32 frameA, u32 frameB, f32 interpolat for (s32 i = 0; i != source->MeshHeader.numVertices; ++i) { - video::S3DVertex &v = dest->Vertices [ i ]; + video::S3DVertex2TCoords &v = dest->Vertices [ i ]; const SMD3Vertex &vA = source->Vertices [ frameOffsetA + i ]; const SMD3Vertex &vB = source->Vertices [ frameOffsetB + i ]; @@ -240,8 +245,8 @@ void CAnimatedMeshMD3::buildVertexArray ( u32 frameA, u32 frameB, f32 interpolat v.Pos.Z = scale * ( vA.position[1] + interpolate * ( vB.position[1] - vA.position[1] ) ); // normal - const core::vector3df nA(getNormal ( vA.normal[0], vA.normal[1] )); - const core::vector3df nB(getNormal ( vB.normal[0], vB.normal[1] )); + const core::vector3df nA( quake3::getMD3Normal ( vA.normal[0], vA.normal[1] )); + const core::vector3df nB( quake3::getMD3Normal ( vB.normal[0], vB.normal[1] )); v.Normal.X = nA.X + interpolate * ( nB.X - nA.X ); v.Normal.Y = nA.Z + interpolate * ( nB.Z - nA.Z ); @@ -260,10 +265,10 @@ void CAnimatedMeshMD3::buildTagArray ( u32 frameA, u32 frameB, f32 interpolate ) for ( s32 i = 0; i != Mesh->MD3Header.numTags; ++i ) { - SMD3QuaterionTag &d = TagListIPol [ i ]; + SMD3QuaternionTag &d = TagListIPol [ i ]; - const SMD3QuaterionTag &qA = Mesh->TagList.Container[ frameOffsetA + i]; - const SMD3QuaterionTag &qB = Mesh->TagList.Container[ frameOffsetB + i]; + const SMD3QuaternionTag &qA = Mesh->TagList[ frameOffsetA + i]; + const SMD3QuaternionTag &qB = Mesh->TagList[ frameOffsetB + i]; // rotation d.rotation.slerp( qA.rotation, qB.rotation, interpolate ); @@ -298,19 +303,31 @@ bool CAnimatedMeshMD3::loadModelFile( u32 modelIndex, io::IReadFile* file) //! store model name Mesh->Name = file->getFileName(); - //! Bone Frames Data ( ignore ) + u32 i; + + //! Frame Data ( ignore ) +#if 0 + SMD3Frame frameImport; + file->seek ( Mesh->MD3Header.frameStart ); + for (i = 0; i != Mesh->MD3Header.numFrames; ++i ) + { + file->read(&frameImport, sizeof(frameImport) ); + } +#endif + //! Tag Data const u32 totalTags = Mesh->MD3Header.numTags * Mesh->MD3Header.numFrames; SMD3Tag import; - SMD3QuaterionTag exp; - u32 i; file->seek( Mesh->MD3Header.tagStart ); + Mesh->TagList.set_used ( totalTags ); for (i = 0; i != totalTags; ++i ) { file->read(&import, sizeof(import) ); + SMD3QuaternionTag &exp = Mesh->TagList[i]; + //! tag name exp.Name = import.Name; @@ -325,14 +342,11 @@ bool CAnimatedMeshMD3::loadModelFile( u32 modelIndex, io::IReadFile* file) -import.rotationMatrix[6], 1 + import.rotationMatrix[8]); exp.rotation.normalize (); - Mesh->TagList.Container.push_back ( exp ); } //! Meshes u32 offset = Mesh->MD3Header.tagEnd; - SMD3Skin skin; - for (i = 0; i != (u32)Mesh->MD3Header.numMeshes; ++i ) { //! construct a new mesh buffer @@ -350,13 +364,17 @@ bool CAnimatedMeshMD3::loadModelFile( u32 modelIndex, io::IReadFile* file) buf->Indices.set_used ( meshHeader.numTriangles * 3 ); buf->Tex.set_used ( meshHeader.numVertices ); - //! read skins (shaders) + SMD3Shader skin; file->seek( offset + buf->MeshHeader.offset_shaders ); for ( s32 g = 0; g != buf->MeshHeader.numShader; ++g ) { file->read( &skin, sizeof(skin) ); - buf->Shader.push_back ( skin.name ); + + core::stringc name; + cutFilenameExtension ( name, skin.name ); + name.replace ( '\\', '/' ); + buf->Shader = name; } //! read texture coordinates @@ -388,7 +406,7 @@ bool CAnimatedMeshMD3::loadModelFile( u32 modelIndex, io::IReadFile* file) // Init Tag Interpolation for (i = 0; i != (u32)Mesh->MD3Header.numTags; ++i ) { - TagListIPol.Container.push_back ( Mesh->TagList.Container[i] ); + TagListIPol.push_back ( Mesh->TagList[i] ); } return true; diff --git a/source/Irrlicht/CAnimatedMeshMD3.h b/source/Irrlicht/CAnimatedMeshMD3.h index c5c84456..ab6c42dc 100644 --- a/source/Irrlicht/CAnimatedMeshMD3.h +++ b/source/Irrlicht/CAnimatedMeshMD3.h @@ -12,6 +12,7 @@ #include "irrString.h" #include "SMesh.h" #include "SMeshBuffer.h" +#include "IQ3Shader.h" namespace irr { @@ -34,7 +35,7 @@ namespace scene // IAnimatedMeshMD3 virtual void setInterpolationShift ( u32 shift, u32 loopMode ); virtual SMD3Mesh * getOriginalMesh (); - virtual SMD3QuaterionTagList *getTagList(s32 frame, s32 detailLevel, s32 startFrameLoop, s32 endFrameLoop); + virtual SMD3QuaternionTagList *getTagList(s32 frame, s32 detailLevel, s32 startFrameLoop, s32 endFrameLoop); //IAnimatedMesh virtual u32 getFrameCount() const; @@ -116,27 +117,20 @@ namespace scene //! return a Mesh per frame SMesh MeshIPol; - SMD3QuaterionTagList TagListIPol; + SMD3QuaternionTagList TagListIPol; IMeshBuffer * createMeshBuffer ( const SMD3MeshBuffer *source ); void buildVertexArray ( u32 frameA, u32 frameB, f32 interpolate, const SMD3MeshBuffer * source, - SMeshBuffer * dest + SMeshBufferLightMap * dest ); void buildTagArray ( u32 frameA, u32 frameB, f32 interpolate ); - core::vector3df getNormal ( u32 i, u32 j ) - { - const f32 lng = i * 2.0f * core::PI / 255.0f; - const f32 lat = j * 2.0f * core::PI / 255.0f; - return core::vector3df(cosf ( lat ) * sinf ( lng ), - sinf ( lat ) * sinf ( lng ), - cos ( lng )); - } }; + } // end namespace scene } // end namespace irr diff --git a/source/Irrlicht/CAnimatedMeshSceneNode.cpp b/source/Irrlicht/CAnimatedMeshSceneNode.cpp index 6e3d2e31..b31564b3 100644 --- a/source/Irrlicht/CAnimatedMeshSceneNode.cpp +++ b/source/Irrlicht/CAnimatedMeshSceneNode.cpp @@ -36,8 +36,9 @@ CAnimatedMeshSceneNode::CAnimatedMeshSceneNode(IAnimatedMesh* mesh, CurrentFrameNr(0.f), JointMode(EJUOR_NONE), JointsUsed(false), TransitionTime(0), Transiting(0.f), TransitingBlend(0.f), - Looping(true), ReadOnlyMaterials(false), RenderFromIdentity(0), - LoopCallBack(0), PassCount(0), Shadow(0) + Looping(true), ReadOnlyMaterials(false), + LoopCallBack(0), PassCount(0), Shadow(0), RenderFromIdentity(0), + MD3Special ( 0 ) { #ifdef _DEBUG setDebugName("CAnimatedMeshSceneNode"); @@ -53,6 +54,9 @@ CAnimatedMeshSceneNode::CAnimatedMeshSceneNode(IAnimatedMesh* mesh, //! destructor CAnimatedMeshSceneNode::~CAnimatedMeshSceneNode() { + if ( MD3Special ) + MD3Special->drop (); + if (Mesh) Mesh->drop(); @@ -200,7 +204,7 @@ void CAnimatedMeshSceneNode::OnRegisterSceneNode() } } -IMesh * CAnimatedMeshSceneNode::getMeshForCurrentFrame(void) +IMesh * CAnimatedMeshSceneNode::getMeshForCurrentFrame(bool forceRecalcOfControlJoints) { if(Mesh->getMeshType() != EAMT_SKINNED) { @@ -249,6 +253,14 @@ void CAnimatedMeshSceneNode::OnAnimate(u32 timeMs) { CurrentFrameNr = buildFrameNr ( timeMs ); + if ( Mesh ) + { + scene::IMesh * mesh = getMeshForCurrentFrame( true ); + + if ( mesh ) + Box = mesh->getBoundingBox(); + } + IAnimatedMeshSceneNode::OnAnimate ( timeMs ); } @@ -267,7 +279,7 @@ void CAnimatedMeshSceneNode::render() ++PassCount; - scene::IMesh* m = getMeshForCurrentFrame(); + scene::IMesh* m = getMeshForCurrentFrame( false ); if(m) { @@ -302,7 +314,7 @@ void CAnimatedMeshSceneNode::render() mat = Materials[i]; mat.MaterialType = video::EMT_TRANSPARENT_ADD_COLOR; if (RenderFromIdentity) - driver->setTransform(video::ETS_WORLD, core::matrix4() ); + driver->setTransform(video::ETS_WORLD, core::IdentityMatrix ); else if (Mesh->getMeshType() == EAMT_SKINNED) driver->setTransform(video::ETS_WORLD, AbsoluteTransformation * ((SSkinMeshBuffer*)mb)->Transformation); @@ -328,7 +340,7 @@ void CAnimatedMeshSceneNode::render() scene::IMeshBuffer* mb = m->getMeshBuffer(i); if (RenderFromIdentity) - driver->setTransform(video::ETS_WORLD, core::matrix4() ); + driver->setTransform(video::ETS_WORLD, core::IdentityMatrix ); else if (Mesh->getMeshType() == EAMT_SKINNED) driver->setTransform(video::ETS_WORLD, AbsoluteTransformation * ((SSkinMeshBuffer*)mb)->Transformation); @@ -374,15 +386,16 @@ void CAnimatedMeshSceneNode::render() // Align to v->normal core::quaternion quatRot( v->Normal.Z, 0.f, -v->Normal.X, 1 + v->Normal.Y ); quatRot.normalize(); - quatRot.getMatrix ( m2 ); + quatRot.getMatrix ( m2, v->Pos ); - m2.setTranslation(v->Pos); if (Mesh->getMeshType() == EAMT_SKINNED) { m2 = (AbsoluteTransformation * ((SSkinMeshBuffer*)mb)->Transformation) * m2; } else - m2*=AbsoluteTransformation; + { + m2 = AbsoluteTransformation * m2; + } driver->setTransform(video::ETS_WORLD, m2 ); for ( u32 a = 0; a != mesh->getMeshBufferCount(); ++a ) @@ -453,7 +466,7 @@ void CAnimatedMeshSceneNode::render() core::matrix4 matr; - SMD3QuaterionTagList *taglist = ((IAnimatedMeshMD3*)Mesh)->getTagList( + SMD3QuaternionTagList *taglist = ((IAnimatedMeshMD3*)Mesh)->getTagList( (s32)getFrameNr(), 255, getStartFrame(), getEndFrame()); if ( taglist ) @@ -483,7 +496,7 @@ void CAnimatedMeshSceneNode::render() { const IMeshBuffer* mb = m->getMeshBuffer(g); if (RenderFromIdentity) - driver->setTransform(video::ETS_WORLD, core::matrix4() ); + driver->setTransform(video::ETS_WORLD, core::IdentityMatrix ); else if (Mesh->getMeshType() == EAMT_SKINNED) driver->setTransform(video::ETS_WORLD, AbsoluteTransformation * ((SSkinMeshBuffer*)mb)->Transformation); driver->drawMeshBuffer(mb); @@ -787,8 +800,8 @@ void CAnimatedMeshSceneNode::deserializeAttributes(io::IAttributes* in, io::SAtt { IAnimatedMeshSceneNode::deserializeAttributes(in, options); - core::stringc oldMeshStr = SceneManager->getMeshCache()->getMeshFilename(Mesh); - core::stringc newMeshStr = in->getAttributeAsString("Mesh"); + core::string oldMeshStr = SceneManager->getMeshCache()->getMeshFilename(Mesh); + core::string newMeshStr = in->getAttributeAsString("Mesh"); Looping = in->getAttributeAsBool("Looping"); ReadOnlyMaterials = in->getAttributeAsBool("ReadOnlyMaterials"); @@ -847,14 +860,9 @@ void CAnimatedMeshSceneNode::setMesh(IAnimatedMesh* mesh) // returns the absolute transformation for a special MD3 Tag if the mesh is a md3 mesh, // or the absolutetransformation if it's a normal scenenode -const SMD3QuaterionTag& CAnimatedMeshSceneNode::getMD3TagTransformation( const core::stringc & tagname) +const SMD3QuaternionTag* CAnimatedMeshSceneNode::getMD3TagTransformation( const core::stringc & tagname) { - SMD3QuaterionTag * tag = MD3Special.AbsoluteTagList.get ( tagname ); - if ( tag ) - return *tag; - - MD3Special.AbsoluteTagList.Container.push_back ( SMD3QuaterionTag ( tagname, AbsoluteTransformation ) ); - return *MD3Special.AbsoluteTagList.get ( tagname ); + return MD3Special ? MD3Special->AbsoluteTagList.get ( tagname ) : 0; } @@ -866,23 +874,32 @@ void CAnimatedMeshSceneNode::updateAbsolutePosition() if ( 0 == Mesh || Mesh->getMeshType() != EAMT_MD3 ) return; - SMD3QuaterionTag parent; - if ( Parent && Parent->getType () == ESNT_ANIMATED_MESH) - { - parent = ((IAnimatedMeshSceneNode*) Parent)->getMD3TagTransformation ( MD3Special.Tagname ); - } - - SMD3QuaterionTag relative( RelativeTranslation, RelativeRotation ); - - SMD3QuaterionTagList *taglist; + SMD3QuaternionTagList *taglist; taglist = ( (IAnimatedMeshMD3*) Mesh )->getTagList ( (s32)getFrameNr(),255,getStartFrame (),getEndFrame () ); if ( taglist ) { - MD3Special.AbsoluteTagList.Container.set_used ( taglist->size () ); + if ( 0 == MD3Special ) + { + MD3Special = new SMD3Special (); + } + + SMD3QuaternionTag parent ( MD3Special->Tagname ); + if ( Parent && Parent->getType () == ESNT_ANIMATED_MESH) + { + const SMD3QuaternionTag * p = ((IAnimatedMeshSceneNode*) Parent)->getMD3TagTransformation + ( MD3Special->Tagname ); + + if ( p ) + parent = *p; + } + + SMD3QuaternionTag relative( RelativeTranslation, RelativeRotation ); + + MD3Special->AbsoluteTagList.set_used ( taglist->size () ); for ( u32 i=0; i!= taglist->size (); ++i ) { - MD3Special.AbsoluteTagList[i].position = parent.position + (*taglist)[i].position + relative.position; - MD3Special.AbsoluteTagList[i].rotation = parent.rotation * (*taglist)[i].rotation * relative.rotation; + MD3Special->AbsoluteTagList[i].position = parent.position + (*taglist)[i].position + relative.position; + MD3Special->AbsoluteTagList[i].rotation = parent.rotation * (*taglist)[i].rotation * relative.rotation; } } } @@ -1004,6 +1021,8 @@ void CAnimatedMeshSceneNode::animateJoints(bool CalculateAbsolutePositions) } +/*! +*/ void CAnimatedMeshSceneNode::checkJoints() { if (!Mesh || Mesh->getMeshType() != EAMT_SKINNED) @@ -1021,7 +1040,8 @@ void CAnimatedMeshSceneNode::checkJoints() } } - +/*! +*/ void CAnimatedMeshSceneNode::beginTransition() { if (!JointsUsed) @@ -1046,6 +1066,8 @@ void CAnimatedMeshSceneNode::beginTransition() TransitingBlend = 0.f; } +/*! +*/ ISceneNode* CAnimatedMeshSceneNode::clone(ISceneNode* newParent, ISceneManager* newManager) { if (!newParent) newParent = Parent; diff --git a/source/Irrlicht/CAnimatedMeshSceneNode.h b/source/Irrlicht/CAnimatedMeshSceneNode.h index 3d4e864d..1c93e0d9 100644 --- a/source/Irrlicht/CAnimatedMeshSceneNode.h +++ b/source/Irrlicht/CAnimatedMeshSceneNode.h @@ -134,7 +134,7 @@ namespace scene // returns the absolute transformation for a special MD3 Tag if the mesh is a md3 mesh, // or the absolutetransformation if it's a normal scenenode - const SMD3QuaterionTag& getMD3TagTransformation( const core::stringc & tagname); + const SMD3QuaternionTag* getMD3TagTransformation( const core::stringc & tagname); //! updates the absolute position based on the relative and the parents position virtual void updateAbsolutePosition(); @@ -162,7 +162,7 @@ namespace scene private: //! Get a static mesh for the current frame of this animated mesh - IMesh* getMeshForCurrentFrame(void); + IMesh* getMeshForCurrentFrame(bool forceRecalcOfControlJoints); f32 buildFrameNr( u32 timeMs); void checkJoints(); @@ -198,10 +198,14 @@ namespace scene core::array JointChildSceneNodes; core::array PretransitingSave; - struct SMD3Special + // Quake3 Model + struct SMD3Special : public virtual IReferenceCounted { + virtual ~SMD3Special () + { + } core::stringc Tagname; - SMD3QuaterionTagList AbsoluteTagList; + SMD3QuaternionTagList AbsoluteTagList; SMD3Special & operator = (const SMD3Special & copyMe) { @@ -210,7 +214,7 @@ namespace scene return *this; } }; - SMD3Special MD3Special; + SMD3Special *MD3Special; }; } // end namespace scene diff --git a/source/Irrlicht/CAttributeImpl.h b/source/Irrlicht/CAttributeImpl.h index 37b477af..0600daa7 100644 --- a/source/Irrlicht/CAttributeImpl.h +++ b/source/Irrlicht/CAttributeImpl.h @@ -1831,14 +1831,6 @@ public: return Value ? Value->getName() : core::stringc(); } - virtual void getString(char* target) - { - if (Value) - strcpy(target, Value->getName().c_str()); - else - target[0] = 0x0; - } - virtual void setString(const char* text) { if (Driver) @@ -1934,9 +1926,12 @@ public: return (Value != 0); } - virtual void getString(char* target) + virtual core::stringw getStringW() { - sprintf(target, "0x%x", *(int*)(&Value)); + wchar_t buf[32]; + swprintf(buf, 32, L"0x%x", *(int*)(&Value)); + + return core::stringw(buf); } virtual void setString(const char* text) diff --git a/source/Irrlicht/CB3DMeshFileLoader.cpp b/source/Irrlicht/CB3DMeshFileLoader.cpp index c7cc5829..d8e59943 100644 --- a/source/Irrlicht/CB3DMeshFileLoader.cpp +++ b/source/Irrlicht/CB3DMeshFileLoader.cpp @@ -36,9 +36,9 @@ CB3DMeshFileLoader::CB3DMeshFileLoader(scene::ISceneManager* smgr) //! returns true if the file maybe is able to be loaded by this class //! based on the file extension (e.g. ".bsp") -bool CB3DMeshFileLoader::isALoadableFileExtension(const c8* fileName) const +bool CB3DMeshFileLoader::isALoadableFileExtension(const core::string& filename) const { - return strstr(fileName, ".b3d") != 0; + return core::hasFileExtension ( filename, "b3d" ); } @@ -722,9 +722,9 @@ bool CB3DMeshFileLoader::readChunkBRUS() { // This is what blitz basic calls a brush, like a Irrlicht Material - const core::stringc name = readString(); #ifdef _B3D_READER_DEBUG - os::Printer::log("read Material", name.c_str()); + const core::stringc name = readString(); + os::Printer::log("read Material", name.c_str()); #endif Materials.push_back(SB3dMaterial()); SB3dMaterial& B3dMaterial=Materials.getLast(); @@ -909,7 +909,7 @@ void CB3DMeshFileLoader::loadTextures(SB3dMaterial& material) const { if (!SceneManager->getParameters()->getAttributeAsBool(B3D_LOADER_IGNORE_MIPMAP_FLAG)) SceneManager->getVideoDriver()->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, (B3dTexture->Flags & 0x8) ? true:false); - material.Material.setTexture(i, SceneManager->getVideoDriver()->getTexture( B3dTexture->TextureName.c_str() )); + material.Material.setTexture(i, SceneManager->getVideoDriver()->getTexture( B3dTexture->TextureName )); if (material.Textures[i]->Flags & 0x10) // Clamp U material.Material.TextureLayer[i].TextureWrap=video::ETC_CLAMP; if (material.Textures[i]->Flags & 0x20) // Clamp V diff --git a/source/Irrlicht/CB3DMeshFileLoader.h b/source/Irrlicht/CB3DMeshFileLoader.h index 5f9099e7..e053c814 100644 --- a/source/Irrlicht/CB3DMeshFileLoader.h +++ b/source/Irrlicht/CB3DMeshFileLoader.h @@ -32,7 +32,7 @@ public: //! returns true if the file maybe is able to be loaded by this class //! based on the file extension (e.g. ".bsp") - virtual bool isALoadableFileExtension(const c8* fileName) const; + virtual bool isALoadableFileExtension(const core::string& filename) const; //! creates/loads an animated mesh from the file. //! \return Pointer to the created mesh. Returns 0 if loading failed. diff --git a/source/Irrlicht/CBSPMeshFileLoader.cpp b/source/Irrlicht/CBSPMeshFileLoader.cpp index daedbffe..e541f052 100644 --- a/source/Irrlicht/CBSPMeshFileLoader.cpp +++ b/source/Irrlicht/CBSPMeshFileLoader.cpp @@ -38,9 +38,9 @@ CBSPMeshFileLoader::~CBSPMeshFileLoader() //! returns true if the file maybe is able to be loaded by this class //! based on the file extension (e.g. ".bsp") -bool CBSPMeshFileLoader::isALoadableFileExtension(const c8* filename) const +bool CBSPMeshFileLoader::isALoadableFileExtension(const core::string& filename) const { - return strstr(filename, ".bsp") || strstr(filename, ".shader"); + return core::hasFileExtension ( filename, "bsp", "shader", "cfg" ); } @@ -50,27 +50,44 @@ bool CBSPMeshFileLoader::isALoadableFileExtension(const c8* filename) const //! See IReferenceCounted::drop() for more information. IAnimatedMesh* CBSPMeshFileLoader::createMesh(io::IReadFile* file) { - // load quake 3 bsp - if (strstr(file->getFileName(), ".bsp")) + s32 type = core::isFileExtension ( file->getFileName(), "bsp", "shader", "cfg" ); + IQ3LevelMesh* q = 0; + + switch ( type ) { - CQ3LevelMesh* q = new CQ3LevelMesh(FileSystem, SceneManager); + case 1: + q = new CQ3LevelMesh(FileSystem, SceneManager, LoadParam); - q->getShader("scripts/models.shader"); - q->getShader("scripts/liquid.shader"); - //q->getShader("scripts/sky.shader"); + // determine real shaders in LoadParam + if ( 0 == LoadParam.loadAllShaders ) + { + q->getShader("scripts/common.shader"); + q->getShader("scripts/sfx.shader"); + q->getShader("scripts/gfx.shader"); + q->getShader("scripts/liquid.shader"); + q->getShader("scripts/models.shader"); + q->getShader("scripts/walls.shader"); + //q->getShader("scripts/sky.shader"); + } - if ( q->loadFile(file) ) + if ( ((CQ3LevelMesh*)q)->loadFile(file) ) + return q; + + q->drop(); + break; + + case 2: + q = new CQ3LevelMesh(FileSystem, SceneManager,LoadParam); + q->getShader( file->getFileName() ); return q; - - q->drop(); - } - - // load quake 3 shader container - if (strstr(file->getFileName(), ".shader")) - { - CQ3LevelMesh* q = new CQ3LevelMesh(FileSystem, SceneManager); - q->getShader(file->getFileName()); - return q; + break; + case 3: + // load quake 3 loading parameter + if ( file->getFileName() == "levelparameter.cfg" ) + { + file->read ( &LoadParam, sizeof ( LoadParam ) ); + } + break; } return 0; diff --git a/source/Irrlicht/CBSPMeshFileLoader.h b/source/Irrlicht/CBSPMeshFileLoader.h index db17392b..ff4c49ab 100644 --- a/source/Irrlicht/CBSPMeshFileLoader.h +++ b/source/Irrlicht/CBSPMeshFileLoader.h @@ -9,6 +9,7 @@ #include "IFileSystem.h" #include "IVideoDriver.h" #include "ISceneManager.h" +#include "IQ3Shader.h" namespace irr { @@ -28,7 +29,7 @@ public: //! returns true if the file maybe is able to be loaded by this class //! based on the file extension (e.g. ".bsp") - virtual bool isALoadableFileExtension(const c8* fileName) const; + virtual bool isALoadableFileExtension(const core::string& filename) const; //! creates/loads an animated mesh from the file. //! \return Pointer to the created mesh. Returns 0 if loading failed. @@ -40,6 +41,8 @@ private: io::IFileSystem* FileSystem; scene::ISceneManager* SceneManager; + + quake3::Q3LevelLoadParameter LoadParam; }; } // end namespace scene diff --git a/source/Irrlicht/CBurningShader_Raster_Reference.cpp b/source/Irrlicht/CBurningShader_Raster_Reference.cpp index 9abaeda6..b6c459d4 100644 --- a/source/Irrlicht/CBurningShader_Raster_Reference.cpp +++ b/source/Irrlicht/CBurningShader_Raster_Reference.cpp @@ -554,8 +554,8 @@ void CBurningShader_Raster_Reference::pShader_EMT_LIGHTMAP_M4 () f32 inversew = fix_inverse32 ( line.w[0] ); - getSample_texture ( r0, g0, b0, &IT[0], f32_to_fixPoint ( line.t[0][0].x,inversew), f32_to_fixPoint ( line.t[0][0].y,inversew) ); - getSample_texture ( r1, g1, b1, &IT[1], f32_to_fixPoint ( line.t[1][0].x,inversew), f32_to_fixPoint ( line.t[1][0].y,inversew) ); + getSample_texture ( r0, g0, b0, &IT[0], tofix ( line.t[0][0].x,inversew), tofix ( line.t[0][0].y,inversew) ); + getSample_texture ( r1, g1, b1, &IT[1], tofix ( line.t[1][0].x,inversew), tofix ( line.t[1][0].y,inversew) ); pShader.dst[pShader.i] = fix_to_color ( clampfix_maxcolor ( imulFix_tex2 ( r0, r1 ) ), @@ -574,8 +574,8 @@ void CBurningShader_Raster_Reference::pShader_1 () const f32 inversew = fix_inverse32 ( line.w[0] ); - tx0 = f32_to_fixPoint ( line.t[0][0].x, inversew ); - ty0 = f32_to_fixPoint ( line.t[0][0].y, inversew ); + tx0 = tofix ( line.t[0][0].x, inversew ); + ty0 = tofix ( line.t[0][0].y, inversew ); getSample_texture ( r0, g0, b0, &IT[0], tx0, ty0 ); pShader.dst[pShader.i] = fix_to_color ( r0, g0, b0 ); @@ -856,8 +856,8 @@ void CBurningShader_Raster_Reference::drawTriangle ( const s4DVertex *a,const s4 // sort on height, y if ( F32_A_GREATER_B ( a->Pos.y , b->Pos.y ) ) swapVertexPointer(&a, &b); - if ( F32_A_GREATER_B ( a->Pos.y , c->Pos.y ) ) swapVertexPointer(&a, &c); if ( F32_A_GREATER_B ( b->Pos.y , c->Pos.y ) ) swapVertexPointer(&b, &c); + if ( F32_A_GREATER_B ( a->Pos.y , b->Pos.y ) ) swapVertexPointer(&a, &b); // calculate delta y of the edges diff --git a/source/Irrlicht/CCSMLoader.cpp b/source/Irrlicht/CCSMLoader.cpp index 823613b0..c7458f9d 100644 --- a/source/Irrlicht/CCSMLoader.cpp +++ b/source/Irrlicht/CCSMLoader.cpp @@ -372,9 +372,9 @@ namespace scene //! returns true if the file maybe is able to be loaded by this class //! based on the file extension (e.g. ".bsp") - bool CCSMLoader::isALoadableFileExtension(const c8* fileName) const + bool CCSMLoader::isALoadableFileExtension(const core::string& filename) const { - return strstr(fileName, ".csm")!=0; + return core::hasFileExtension ( filename, "csm" ); } //! creates/loads an animated mesh from the file. @@ -409,7 +409,7 @@ namespace scene scene::IMesh* pMesh = createIrrlichtMesh(&csmFile, SceneManager->getParameters()->getAttributeAsString(CSM_TEXTURE_PATH), - file->getFileName()); + core::stringc ( file->getFileName() ).c_str() ); return pMesh; } @@ -453,7 +453,7 @@ namespace scene texName+= "/"; texName+= surface->getTextureName(); - video::ITexture* texture = driver->getTexture(texName.c_str()); + video::ITexture* texture = driver->getTexture(texName); scene::SMeshBufferLightMap *buffer = new scene::SMeshBufferLightMap(); //material @@ -462,7 +462,7 @@ namespace scene lmapName += (int)surface->getLightMapId(); buffer->Material.setTexture(0, texture); - buffer->Material.setTexture(1, driver->getTexture(lmapName.c_str())); + buffer->Material.setTexture(1, driver->getTexture(lmapName)); buffer->Material.Lighting = false; buffer->Material.MaterialType = video::EMT_LIGHTMAP_M4; diff --git a/source/Irrlicht/CCSMLoader.h b/source/Irrlicht/CCSMLoader.h index bfa27353..075070ee 100644 --- a/source/Irrlicht/CCSMLoader.h +++ b/source/Irrlicht/CCSMLoader.h @@ -60,7 +60,7 @@ namespace scene //! returns true if the file maybe is able to be loaded by this class //! based on the file extension (e.g. ".bsp") - virtual bool isALoadableFileExtension(const c8* fileName) const; + virtual bool isALoadableFileExtension(const core::string& filename) const; //! creates/loads an animated mesh from the file. virtual IAnimatedMesh* createMesh(io::IReadFile* file); diff --git a/source/Irrlicht/CColladaFileLoader.cpp b/source/Irrlicht/CColladaFileLoader.cpp index 06d0ab2e..92a3ce38 100644 --- a/source/Irrlicht/CColladaFileLoader.cpp +++ b/source/Irrlicht/CColladaFileLoader.cpp @@ -328,9 +328,9 @@ CColladaFileLoader::~CColladaFileLoader() //! Returns true if the file maybe is able to be loaded by this class. /** This decision should be based only on the file extension (e.g. ".cob") */ -bool CColladaFileLoader::isALoadableFileExtension(const c8* fileName) const +bool CColladaFileLoader::isALoadableFileExtension(const core::string& filename) const { - return strstr(fileName, ".xml") || strstr(fileName, ".dae"); + return core::hasFileExtension ( filename, "xml", "dae" ); } @@ -1774,7 +1774,7 @@ void CColladaFileLoader::readGeometry(io::IXMLReaderUTF8* reader) amesh->recalculateBoundingBox(); // create virtual file name - core::stringc filename = CurrentlyLoadingMesh; + core::string filename = CurrentlyLoadingMesh; filename += '#'; filename += id; @@ -2696,9 +2696,9 @@ video::ITexture* CColladaFileLoader::getTextureFromImage(core::stringc uri) { if (Images[i].Source.size() && Images[i].SourceIsFilename) { - if (FileSystem->existFile(Images[i].Source.c_str())) - return driver->getTexture(Images[i].Source.c_str()); - return driver->getTexture((FileSystem->getFileDir(CurrentlyLoadingMesh)+"/"+Images[i].Source).c_str()); + if (FileSystem->existFile(Images[i].Source)) + return driver->getTexture(Images[i].Source); + return driver->getTexture((FileSystem->getFileDir(CurrentlyLoadingMesh)+"/"+Images[i].Source)); } else if (Images[i].Source.size()) diff --git a/source/Irrlicht/CColladaFileLoader.h b/source/Irrlicht/CColladaFileLoader.h index c253346d..0f4be37e 100644 --- a/source/Irrlicht/CColladaFileLoader.h +++ b/source/Irrlicht/CColladaFileLoader.h @@ -184,7 +184,7 @@ public: //! returns true if the file maybe is able to be loaded by this class //! based on the file extension (e.g. ".cob") - virtual bool isALoadableFileExtension(const c8* fileName) const; + virtual bool isALoadableFileExtension(const core::string& filename) const; //! creates/loads an animated mesh from the file. //! \return Pointer to the created mesh. Returns 0 if loading failed. @@ -337,7 +337,7 @@ private: core::stringc CurrentlyLoadingMesh; scene::IAnimatedMesh* FirstLoadedMesh; - core::stringc FirstLoadedMeshName; + core::string FirstLoadedMeshName; s32 LoadedMeshCount; u32 Version; bool FlipAxis; diff --git a/source/Irrlicht/CColorConverter.cpp b/source/Irrlicht/CColorConverter.cpp index 65e50dd8..4adddb81 100644 --- a/source/Irrlicht/CColorConverter.cpp +++ b/source/Irrlicht/CColorConverter.cpp @@ -415,6 +415,38 @@ void CColorConverter::convert_R8G8B8toA1R5G5B5(const void* sP, s32 sN, void* dP) } } +void CColorConverter::convert_B8G8R8toA8R8G8B8(const void* sP, s32 sN, void* dP) +{ + u8* sB = (u8* )sP; + u32* dB = (u32*)dP; + + for (s32 x = 0; x < sN; ++x) + { + *dB = 0xff000000 | (sB[2]<<16) | (sB[1]<<8) | sB[0]; + + sB += 3; + ++dB; + } +} + +void CColorConverter::convert_B8G8R8A8toA8R8G8B8(const void* sP, s32 sN, void* dP) +{ + u8* sB = (u8*)sP; + u8* dB = (u8*)dP; + + for (s32 x = 0; x < sN; ++x) + { + dB[0] = sB[3]; + dB[1] = sB[2]; + dB[2] = sB[1]; + dB[3] = sB[0]; + + sB += 4; + dB += 4; + } + +} + void CColorConverter::convert_R8G8B8toR5G6B5(const void* sP, s32 sN, void* dP) { u8 * sB = (u8 *)sP; diff --git a/source/Irrlicht/CColorConverter.h b/source/Irrlicht/CColorConverter.h index e7ef5f70..e678c598 100644 --- a/source/Irrlicht/CColorConverter.h +++ b/source/Irrlicht/CColorConverter.h @@ -66,6 +66,8 @@ public: static void convert_R8G8B8toA8R8G8B8(const void* sP, s32 sN, void* dP); static void convert_R8G8B8toA1R5G5B5(const void* sP, s32 sN, void* dP); static void convert_R8G8B8toR5G6B5(const void* sP, s32 sN, void* dP); + static void convert_B8G8R8toA8R8G8B8(const void* sP, s32 sN, void* dP); + static void convert_B8G8R8A8toA8R8G8B8(const void* sP, s32 sN, void* dP); static void convert_R5G6B5toR5G6B5(const void* sP, s32 sN, void* dP); static void convert_R5G6B5toR8G8B8(const void* sP, s32 sN, void* dP); diff --git a/source/Irrlicht/CD3D8Driver.cpp b/source/Irrlicht/CD3D8Driver.cpp index 33f85e70..c9fd0bbf 100644 --- a/source/Irrlicht/CD3D8Driver.cpp +++ b/source/Irrlicht/CD3D8Driver.cpp @@ -147,6 +147,11 @@ bool CD3D8Driver::initDriver(const core::dimension2d& screenSize, bool highPrecisionFPU, bool vsync, u8 antiAlias) { HRESULT hr; + typedef IDirect3D8 * (__stdcall *D3DCREATETYPE)(UINT); + +#if defined( _IRR_XBOX_PLATFORM_) + D3DCREATETYPE d3dCreate = (D3DCREATETYPE) &Direct3DCreate8; +#else D3DLibrary = LoadLibrary( "d3d8.dll" ); if (!D3DLibrary) @@ -155,7 +160,6 @@ bool CD3D8Driver::initDriver(const core::dimension2d& screenSize, return false; } - typedef IDirect3D8 * (__stdcall *D3DCREATETYPE)(UINT); D3DCREATETYPE d3dCreate = (D3DCREATETYPE) GetProcAddress(D3DLibrary, "Direct3DCreate8"); if (!d3dCreate) @@ -163,6 +167,7 @@ bool CD3D8Driver::initDriver(const core::dimension2d& screenSize, os::Printer::log("Error, could not get proc adress of Direct3DCreate8.", ELL_ERROR); return false; } +#endif //just like pID3D = Direct3DCreate8(D3D_SDK_VERSION); pID3D = (*d3dCreate)(D3D_SDK_VERSION); @@ -255,6 +260,7 @@ bool CD3D8Driver::initDriver(const core::dimension2d& screenSize, present.BackBufferFormat, D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_SURFACE, present.AutoDepthStencilFormat))) { +#if !defined( _IRR_XBOX_PLATFORM_) present.AutoDepthStencilFormat = D3DFMT_D24X4S4; if(FAILED(pID3D->CheckDeviceFormat(D3DADAPTER_DEFAULT, devtype, present.BackBufferFormat, D3DUSAGE_DEPTHSTENCIL, @@ -269,6 +275,7 @@ bool CD3D8Driver::initDriver(const core::dimension2d& screenSize, StencilBuffer = false; } } +#endif } else if(FAILED(pID3D->CheckDepthStencilMatch(D3DADAPTER_DEFAULT, devtype, @@ -281,6 +288,7 @@ bool CD3D8Driver::initDriver(const core::dimension2d& screenSize, // do not use else here to cope with flag change in previous block if (!StencilBuffer) { +#if !defined( _IRR_XBOX_PLATFORM_) present.AutoDepthStencilFormat = D3DFMT_D32; if(FAILED(pID3D->CheckDeviceFormat(D3DADAPTER_DEFAULT, devtype, present.BackBufferFormat, D3DUSAGE_DEPTHSTENCIL, @@ -301,11 +309,24 @@ bool CD3D8Driver::initDriver(const core::dimension2d& screenSize, } } } +#else + present.AutoDepthStencilFormat = D3DFMT_D16; + if(FAILED(pID3D->CheckDeviceFormat(D3DADAPTER_DEFAULT, devtype, + present.BackBufferFormat, D3DUSAGE_DEPTHSTENCIL, + D3DRTYPE_SURFACE, present.AutoDepthStencilFormat))) + { + os::Printer::log("Device does not support required depth buffer.", ELL_WARNING); + return false; + } +#endif } // create device - +#if defined( _IRR_XBOX_PLATFORM_) + DWORD fpuPrecision = 0; +#else DWORD fpuPrecision = highPrecisionFPU ? D3DCREATE_FPU_PRESERVE : 0; +#endif if (pureSoftware) { hr = pID3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_REF, hwnd, @@ -392,6 +413,8 @@ bool CD3D8Driver::beginScene(bool backBuffer, bool zBuffer, SColor color, HRESULT hr; if (DeviceLost) { +#if defined( _IRR_XBOX_PLATFORM_) +#else if(FAILED(hr = pID3DDevice->TestCooperativeLevel())) { if (hr == D3DERR_DEVICELOST) @@ -405,6 +428,7 @@ bool CD3D8Driver::beginScene(bool backBuffer, bool zBuffer, SColor color, if ((hr == D3DERR_DEVICENOTRESET) && !reset()) return false; } +#endif } DWORD flags = 0; @@ -650,8 +674,7 @@ void CD3D8Driver::setMaterial(const SMaterial& material) //! returns a device dependent texture from a software surface (IImage) -video::ITexture* CD3D8Driver::createDeviceDependentTexture(IImage* surface, - const char* name) +video::ITexture* CD3D8Driver::createDeviceDependentTexture(IImage* surface,const core::string& name) { return new CD3D8Texture(surface, this, TextureCreationFlags, name); } @@ -769,11 +792,8 @@ bool CD3D8Driver::setRenderTarget(video::ITexture* texture, //! Creates a render target texture. -ITexture* CD3D8Driver::addRenderTargetTexture( - const core::dimension2d& size, const c8* name) +ITexture* CD3D8Driver::addRenderTargetTexture(const core::dimension2d& size, const core::string& name) { - if (!name) - name="rt"; ITexture* tex = new CD3D8Texture(this, size, name); addTexture(tex); tex->drop(); @@ -1472,9 +1492,12 @@ void CD3D8Driver::setBasicRenderStates(const SMaterial& material, const SMateria if (resetAllRenderstates || lastmaterial.TextureLayer[st].LODBias != material.TextureLayer[st].LODBias) { const float tmp = material.TextureLayer[st].LODBias * 0.125f; - pID3DDevice->SetTextureStageState(st, D3DSAMP_MIPMAPLODBIAS, *(DWORD*)(&tmp)); - } + //!TA D3DSAMP_MIPMAPLODBIAS doesn't compile! +/* + pID3DDevice->SetTextureStageState(st, D3DSAMP_MIPMAPLODBIAS, *(DWORD*)(&tmp)); +*/ + } if (resetAllRenderstates || lastmaterial.TextureLayer[st].TextureWrap != material.TextureLayer[st].TextureWrap) { u32 mode = D3DTADDRESS_WRAP; @@ -1991,9 +2014,16 @@ void CD3D8Driver::setFog(SColor color, bool linearFog, f32 start, pID3DDevice->SetRenderState(D3DRS_FOGCOLOR, color.color); +#if defined( _IRR_XBOX_PLATFORM_) + pID3DDevice->SetRenderState( + pixelFog ? D3DRS_FOGTABLEMODE : D3DRS_FOGTABLEMODE, + linearFog ? D3DFOG_LINEAR : D3DFOG_EXP); + +#else pID3DDevice->SetRenderState( pixelFog ? D3DRS_FOGTABLEMODE : D3DRS_FOGVERTEXMODE, linearFog ? D3DFOG_LINEAR : D3DFOG_EXP); +#endif if(linearFog) { @@ -2125,6 +2155,9 @@ void CD3D8Driver::clearZBuffer() //! Returns an image created from the last rendered frame. IImage* CD3D8Driver::createScreenShot() { +#if defined( _IRR_XBOX_PLATFORM_) + return 0; +#else HRESULT hr; // query the screen dimensions of the current adapter @@ -2210,6 +2243,7 @@ IImage* CD3D8Driver::createScreenShot() // return status of save operation to caller return newImage; +#endif } @@ -2226,18 +2260,24 @@ const core::dimension2d& CD3D8Driver::getCurrentRenderTargetSize() const // Set/unset a clipping plane. bool CD3D8Driver::setClipPlane(u32 index, const core::plane3df& plane, bool enable) { +#if defined( _IRR_XBOX_PLATFORM_) + return false; +#else if (index >= MaxUserClipPlanes) return false; - pID3DDevice->SetClipPlane(index, (const float*)&plane); enableClipPlane(index, enable); return true; +#endif } // Enable/disable a clipping plane. void CD3D8Driver::enableClipPlane(u32 index, bool enable) { +#if defined( _IRR_XBOX_PLATFORM_) + return; +#else if (index >= MaxUserClipPlanes) return; DWORD renderstate; @@ -2247,6 +2287,7 @@ void CD3D8Driver::enableClipPlane(u32 index, bool enable) else renderstate &= ~(1 << index); pID3DDevice->SetRenderState(D3DRS_CLIPPLANEENABLE, renderstate); +#endif } diff --git a/source/Irrlicht/CD3D8Driver.h b/source/Irrlicht/CD3D8Driver.h index 11c0f724..0c43cab4 100644 --- a/source/Irrlicht/CD3D8Driver.h +++ b/source/Irrlicht/CD3D8Driver.h @@ -191,7 +191,7 @@ namespace video //! Creates a render target texture. virtual ITexture* addRenderTargetTexture(const core::dimension2d& size, - const c8* name); + const core::string& name); //! Clears the ZBuffer. virtual void clearZBuffer(); @@ -249,7 +249,7 @@ namespace video //! returns a device dependent texture from a software surface (IImage) //! THIS METHOD HAS TO BE OVERRIDDEN BY DERIVED DRIVERS WITH OWN TEXTURES - virtual video::ITexture* createDeviceDependentTexture(IImage* surface, const char* name); + virtual video::ITexture* createDeviceDependentTexture(IImage* surface, const core::string& name); // returns the current size of the screen or rendertarget virtual const core::dimension2d& getCurrentRenderTargetSize() const; diff --git a/source/Irrlicht/CD3D8ParallaxMapRenderer.h b/source/Irrlicht/CD3D8ParallaxMapRenderer.h index 53bd89ac..38f8f52d 100644 --- a/source/Irrlicht/CD3D8ParallaxMapRenderer.h +++ b/source/Irrlicht/CD3D8ParallaxMapRenderer.h @@ -33,9 +33,10 @@ public: //! material renderer should be set. virtual void OnSetConstants(IMaterialRendererServices* services, s32 userData); - bool OnRender(IMaterialRendererServices* service, E_VERTEX_TYPE vtxtype); + virtual bool OnRender(IMaterialRendererServices* service, E_VERTEX_TYPE vtxtype); - void OnSetMaterial(const video::SMaterial& material, + virtual void OnSetMaterial(const SMaterial& material) { } + virtual void OnSetMaterial(const video::SMaterial& material, const video::SMaterial& lastMaterial, bool resetAllRenderstates, video::IMaterialRendererServices* services); diff --git a/source/Irrlicht/CD3D8Texture.cpp b/source/Irrlicht/CD3D8Texture.cpp index 62d25b41..e4e0d62b 100644 --- a/source/Irrlicht/CD3D8Texture.cpp +++ b/source/Irrlicht/CD3D8Texture.cpp @@ -31,7 +31,7 @@ namespace video { //! rendertarget constructor -CD3D8Texture::CD3D8Texture(CD3D8Driver* driver, core::dimension2d size, const char* name) +CD3D8Texture::CD3D8Texture(CD3D8Driver* driver, const core::dimension2d& size, const core::string& name) : ITexture(name), Texture(0), RTTSurface(0), Driver(driver), TextureSize(size), ImageSize(size), Pitch(0), HasMipMaps(false), IsRenderTarget(true) @@ -50,7 +50,7 @@ CD3D8Texture::CD3D8Texture(CD3D8Driver* driver, core::dimension2d size, con //! constructor CD3D8Texture::CD3D8Texture(IImage* image, CD3D8Driver* driver, - u32 flags, const char* name) + u32 flags, const core::string& name) : ITexture(name), Texture(0), RTTSurface(0), Driver(driver), TextureSize(0,0), ImageSize(0,0), Pitch(0), HasMipMaps(false), IsRenderTarget(false) @@ -148,10 +148,17 @@ bool CD3D8Texture::createTexture(video::IImage* image, u32 flags) case ETCF_OPTIMIZED_FOR_SPEED: format = D3DFMT_A1R5G5B5; break; } + if (Driver->getTextureCreationFlag(video::ETCF_NO_ALPHA_CHANNEL)) { if (format == D3DFMT_A8R8G8B8) + +#ifdef _IRR_XBOX_PLATFORM_ + format = D3DFMT_X8R8G8B8; +#else format = D3DFMT_R8G8B8; +#endif + else if (format == D3DFMT_A1R5G5B5) format = D3DFMT_R5G6B5; } @@ -167,8 +174,13 @@ bool CD3D8Texture::createTexture(video::IImage* image, u32 flags) // try brute force 16 bit if (format == D3DFMT_A8R8G8B8) format = D3DFMT_A1R5G5B5; +#ifdef _IRR_XBOX_PLATFORM_ + else if (format == D3DFMT_X8R8G8B8) + format = D3DFMT_R5G6B5; +#else else if (format == D3DFMT_R8G8B8) format = D3DFMT_R5G6B5; +#endif else return false; diff --git a/source/Irrlicht/CD3D8Texture.h b/source/Irrlicht/CD3D8Texture.h index 221dba98..736cc3fd 100644 --- a/source/Irrlicht/CD3D8Texture.h +++ b/source/Irrlicht/CD3D8Texture.h @@ -10,6 +10,10 @@ #include "ITexture.h" #include "IImage.h" + +#ifdef _IRR_XBOX_PLATFORM_ + #include +#endif #include namespace irr @@ -28,10 +32,10 @@ public: //! constructor CD3D8Texture(IImage* image, CD3D8Driver* driver, - u32 flags, const char* name); + u32 flags, const core::string& name); //! rendertarget constructor - CD3D8Texture(CD3D8Driver* driver, core::dimension2d size, const char* name); + CD3D8Texture(CD3D8Driver* driver, const core::dimension2d& size, const core::string& name); //! destructor virtual ~CD3D8Texture(); diff --git a/source/Irrlicht/CD3D9Driver.cpp b/source/Irrlicht/CD3D9Driver.cpp index 24bc4723..78917b1d 100644 --- a/source/Irrlicht/CD3D9Driver.cpp +++ b/source/Irrlicht/CD3D9Driver.cpp @@ -70,6 +70,7 @@ CD3D9Driver::CD3D9Driver(const core::dimension2d& screenSize, HWND window, CD3D9Driver::~CD3D9Driver() { deleteMaterialRenders(); + deleteAllTextures(); // drop the main depth buffer DepthBuffers[0]->drop(); @@ -427,7 +428,7 @@ bool CD3D9Driver::initDriver(const core::dimension2d& screenSize, AlphaToCoverageSupport = (pID3D->CheckDeviceFormat(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8, 0,D3DRTYPE_SURFACE, (D3DFORMAT)MAKEFOURCC('A', 'T', 'O', 'C')) == S_OK); - else if (VendorID=0x1002)//ATI + else if (VendorID==0x1002)//ATI AlphaToCoverageSupport = true; // TODO: Check unknown #if 0 AlphaToCoverageSupport = (pID3D->CheckDeviceFormat(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, @@ -697,8 +698,7 @@ void CD3D9Driver::setMaterial(const SMaterial& material) //! returns a device dependent texture from a software surface (IImage) -video::ITexture* CD3D9Driver::createDeviceDependentTexture(IImage* surface, - const char* name) +video::ITexture* CD3D9Driver::createDeviceDependentTexture(IImage* surface,const core::string& name) { return new CD3D9Texture(surface, this, TextureCreationFlags, name); } @@ -840,12 +840,12 @@ const core::rect& CD3D9Driver::getViewPort() const } -bool CD3D9Driver::updateVertexHardwareBuffer(SHWBufferLink_d3d9 *HWBuffer) +bool CD3D9Driver::updateVertexHardwareBuffer(SHWBufferLink_d3d9 *hwBuffer) { - if (!HWBuffer) + if (!hwBuffer) return false; - const scene::IMeshBuffer* mb = HWBuffer->MeshBuffer; + const scene::IMeshBuffer* mb = hwBuffer->MeshBuffer; const void* vertices=mb->getVertices(); const u32 vertexCount=mb->getVertexCount(); const E_VERTEX_TYPE vType=mb->getVertexType(); @@ -853,7 +853,7 @@ bool CD3D9Driver::updateVertexHardwareBuffer(SHWBufferLink_d3d9 *HWBuffer) void* pLockedBuffer = 0; - if (!HWBuffer->vertexBuffer || vertexSize * vertexCount > HWBuffer->vertexBufferSize) + if (!hwBuffer->vertexBuffer || vertexSize * vertexCount > hwBuffer->vertexBufferSize) { DWORD flags = 0; @@ -880,41 +880,41 @@ bool CD3D9Driver::updateVertexHardwareBuffer(SHWBufferLink_d3d9 *HWBuffer) } flags = D3DUSAGE_WRITEONLY; // SIO2: Default to D3DUSAGE_WRITEONLY - if(HWBuffer->Mapped_Vertex != scene::EHM_STATIC) + if(hwBuffer->Mapped_Vertex != scene::EHM_STATIC) flags |= D3DUSAGE_DYNAMIC; - pID3DDevice->CreateVertexBuffer(vertexCount * vertexSize, flags, FVF, D3DPOOL_DEFAULT, &HWBuffer->vertexBuffer, NULL); + pID3DDevice->CreateVertexBuffer(vertexCount * vertexSize, flags, FVF, D3DPOOL_DEFAULT, &hwBuffer->vertexBuffer, NULL); - if(!HWBuffer->vertexBuffer) + if(!hwBuffer->vertexBuffer) return false; flags = 0; // SIO2: Reset flags before Lock - if(HWBuffer->Mapped_Vertex != scene::EHM_STATIC) + if(hwBuffer->Mapped_Vertex != scene::EHM_STATIC) flags = D3DLOCK_DISCARD; - HWBuffer->vertexBuffer->Lock(0, vertexCount * vertexSize, (void**)&pLockedBuffer, flags); + hwBuffer->vertexBuffer->Lock(0, vertexCount * vertexSize, (void**)&pLockedBuffer, flags); memcpy(pLockedBuffer, vertices, vertexCount * vertexSize); - HWBuffer->vertexBuffer->Unlock(); + hwBuffer->vertexBuffer->Unlock(); - HWBuffer->vertexBufferSize = vertexCount * vertexSize; + hwBuffer->vertexBufferSize = vertexCount * vertexSize; } else { - HWBuffer->vertexBuffer->Lock(0, vertexCount * vertexSize, (void**)&pLockedBuffer, D3DLOCK_DISCARD); + hwBuffer->vertexBuffer->Lock(0, vertexCount * vertexSize, (void**)&pLockedBuffer, D3DLOCK_DISCARD); memcpy(pLockedBuffer, vertices, vertexCount * vertexSize); - HWBuffer->vertexBuffer->Unlock(); + hwBuffer->vertexBuffer->Unlock(); } return true; } -bool CD3D9Driver::updateIndexHardwareBuffer(SHWBufferLink_d3d9 *HWBuffer) +bool CD3D9Driver::updateIndexHardwareBuffer(SHWBufferLink_d3d9 *hwBuffer) { - if (!HWBuffer) + if (!hwBuffer) return false; - const scene::IMeshBuffer* mb = HWBuffer->MeshBuffer; + const scene::IMeshBuffer* mb = hwBuffer->MeshBuffer; const u16* indices=mb->getIndices(); const u32 indexCount=mb->getIndexCount(); u32 indexSize = 2; @@ -935,38 +935,38 @@ bool CD3D9Driver::updateIndexHardwareBuffer(SHWBufferLink_d3d9 *HWBuffer) } } - if (!HWBuffer->indexBuffer || indexSize * indexCount > HWBuffer->indexBufferSize) + if (!hwBuffer->indexBuffer || indexSize * indexCount > hwBuffer->indexBufferSize) { DWORD flags = 0; flags = D3DUSAGE_WRITEONLY; // SIO2: Default to D3DUSAGE_WRITEONLY - if(HWBuffer->Mapped_Index != scene::EHM_STATIC) + if(hwBuffer->Mapped_Index != scene::EHM_STATIC) flags |= D3DUSAGE_DYNAMIC; // SIO2: Add DYNAMIC flag for dynamic buffer data - if(FAILED(pID3DDevice->CreateIndexBuffer( indexCount * indexSize, flags, indexType, D3DPOOL_DEFAULT, &HWBuffer->indexBuffer, NULL))) + if(FAILED(pID3DDevice->CreateIndexBuffer( indexCount * indexSize, flags, indexType, D3DPOOL_DEFAULT, &hwBuffer->indexBuffer, NULL))) return false; void* pIndices = 0; flags = 0; // SIO2: Reset flags before Lock - if(HWBuffer->Mapped_Index != scene::EHM_STATIC) + if(hwBuffer->Mapped_Index != scene::EHM_STATIC) flags = D3DLOCK_DISCARD; - if(FAILED(HWBuffer->indexBuffer->Lock( 0, 0, (void**)&pIndices, flags))) + if(FAILED(hwBuffer->indexBuffer->Lock( 0, 0, (void**)&pIndices, flags))) return false; memcpy(pIndices, indices, indexCount * indexSize); - HWBuffer->indexBuffer->Unlock(); + hwBuffer->indexBuffer->Unlock(); - HWBuffer->indexBufferSize = indexCount * indexSize; + hwBuffer->indexBufferSize = indexCount * indexSize; } else { void* pIndices = 0; - if( SUCCEEDED(HWBuffer->indexBuffer->Lock( 0, 0, (void**)&pIndices, D3DLOCK_DISCARD))) + if( SUCCEEDED(hwBuffer->indexBuffer->Lock( 0, 0, (void**)&pIndices, D3DLOCK_DISCARD))) { memcpy(pIndices, indices, indexCount * indexSize); - HWBuffer->indexBuffer->Unlock(); + hwBuffer->indexBuffer->Unlock(); } } @@ -975,33 +975,33 @@ bool CD3D9Driver::updateIndexHardwareBuffer(SHWBufferLink_d3d9 *HWBuffer) //! updates hardware buffer if needed -bool CD3D9Driver::updateHardwareBuffer(SHWBufferLink *HWBuffer) +bool CD3D9Driver::updateHardwareBuffer(SHWBufferLink *hwBuffer) { - if (!HWBuffer) + if (!hwBuffer) return false; - if (HWBuffer->Mapped_Vertex!=scene::EHM_NEVER) + if (hwBuffer->Mapped_Vertex!=scene::EHM_NEVER) { - if (HWBuffer->ChangedID_Vertex != HWBuffer->MeshBuffer->getChangedID_Vertex() - || !((SHWBufferLink_d3d9*)HWBuffer)->vertexBuffer) + if (hwBuffer->ChangedID_Vertex != hwBuffer->MeshBuffer->getChangedID_Vertex() + || !((SHWBufferLink_d3d9*)hwBuffer)->vertexBuffer) { - HWBuffer->ChangedID_Vertex = HWBuffer->MeshBuffer->getChangedID_Vertex(); + hwBuffer->ChangedID_Vertex = hwBuffer->MeshBuffer->getChangedID_Vertex(); - if (!updateVertexHardwareBuffer((SHWBufferLink_d3d9*)HWBuffer)) + if (!updateVertexHardwareBuffer((SHWBufferLink_d3d9*)hwBuffer)) return false; } } - if (HWBuffer->Mapped_Index!=scene::EHM_NEVER) + if (hwBuffer->Mapped_Index!=scene::EHM_NEVER) { - if (HWBuffer->ChangedID_Index != HWBuffer->MeshBuffer->getChangedID_Index() - || !((SHWBufferLink_d3d9*)HWBuffer)->indexBuffer) + if (hwBuffer->ChangedID_Index != hwBuffer->MeshBuffer->getChangedID_Index() + || !((SHWBufferLink_d3d9*)hwBuffer)->indexBuffer) { - HWBuffer->ChangedID_Index = HWBuffer->MeshBuffer->getChangedID_Index(); + hwBuffer->ChangedID_Index = hwBuffer->MeshBuffer->getChangedID_Index(); - if (!updateIndexHardwareBuffer((SHWBufferLink_d3d9*)HWBuffer)) + if (!updateIndexHardwareBuffer((SHWBufferLink_d3d9*)hwBuffer)) return false; } } @@ -1016,28 +1016,28 @@ CD3D9Driver::SHWBufferLink *CD3D9Driver::createHardwareBuffer(const scene::IMesh if (!mb || (mb->getHardwareMappingHint_Index()==scene::EHM_NEVER && mb->getHardwareMappingHint_Vertex()==scene::EHM_NEVER)) return 0; - SHWBufferLink_d3d9 *HWBuffer=new SHWBufferLink_d3d9(mb); + SHWBufferLink_d3d9 *hwBuffer=new SHWBufferLink_d3d9(mb); //add to map - HWBufferMap.insert(HWBuffer->MeshBuffer, HWBuffer); + HWBufferMap.insert(hwBuffer->MeshBuffer, hwBuffer); - HWBuffer->ChangedID_Vertex=HWBuffer->MeshBuffer->getChangedID_Vertex(); - HWBuffer->ChangedID_Index=HWBuffer->MeshBuffer->getChangedID_Index(); - HWBuffer->Mapped_Vertex=mb->getHardwareMappingHint_Vertex(); - HWBuffer->Mapped_Index=mb->getHardwareMappingHint_Index(); - HWBuffer->LastUsed=0; - HWBuffer->vertexBuffer=0; - HWBuffer->indexBuffer=0; - HWBuffer->vertexBufferSize=0; - HWBuffer->indexBufferSize=0; + hwBuffer->ChangedID_Vertex=hwBuffer->MeshBuffer->getChangedID_Vertex(); + hwBuffer->ChangedID_Index=hwBuffer->MeshBuffer->getChangedID_Index(); + hwBuffer->Mapped_Vertex=mb->getHardwareMappingHint_Vertex(); + hwBuffer->Mapped_Index=mb->getHardwareMappingHint_Index(); + hwBuffer->LastUsed=0; + hwBuffer->vertexBuffer=0; + hwBuffer->indexBuffer=0; + hwBuffer->vertexBufferSize=0; + hwBuffer->indexBufferSize=0; - if (!updateHardwareBuffer(HWBuffer)) + if (!updateHardwareBuffer(hwBuffer)) { - deleteHardwareBuffer(HWBuffer); + deleteHardwareBuffer(hwBuffer); return 0; } - return HWBuffer; + return hwBuffer; } @@ -2619,10 +2619,8 @@ IVideoDriver* CD3D9Driver::getVideoDriver() //! Creates a render target texture. ITexture* CD3D9Driver::addRenderTargetTexture( const core::dimension2d& size, - const c8* name) + const core::string& name) { - if (!name) - name="rt"; ITexture* tex = new CD3D9Texture(this, size, name); if (tex) { diff --git a/source/Irrlicht/CD3D9Driver.h b/source/Irrlicht/CD3D9Driver.h index d77335ca..708d7c67 100644 --- a/source/Irrlicht/CD3D9Driver.h +++ b/source/Irrlicht/CD3D9Driver.h @@ -25,7 +25,7 @@ namespace video struct SDepthSurface : public IReferenceCounted { SDepthSurface() : Surface(0) {} - ~SDepthSurface() + virtual ~SDepthSurface() { if (Surface) Surface->Release(); @@ -77,7 +77,10 @@ namespace video struct SHWBufferLink_d3d9 : public SHWBufferLink { - SHWBufferLink_d3d9(const scene::IMeshBuffer *_MeshBuffer): SHWBufferLink(_MeshBuffer), vertexBuffer(0), indexBuffer(0){} + SHWBufferLink_d3d9(const scene::IMeshBuffer *_MeshBuffer): + SHWBufferLink(_MeshBuffer), + vertexBuffer(0), indexBuffer(0), + vertexBufferSize(0), indexBufferSize(0) {} IDirect3DVertexBuffer9* vertexBuffer; IDirect3DIndexBuffer9* indexBuffer; @@ -220,7 +223,7 @@ namespace video //! Creates a render target texture. virtual ITexture* addRenderTargetTexture(const core::dimension2d& size, - const c8* name); + const core::string& name); //! Clears the ZBuffer. virtual void clearZBuffer(); @@ -293,7 +296,7 @@ namespace video //! returns a device dependent texture from a software surface (IImage) //! THIS METHOD HAS TO BE OVERRIDDEN BY DERIVED DRIVERS WITH OWN TEXTURES - virtual video::ITexture* createDeviceDependentTexture(IImage* surface, const char* name); + virtual video::ITexture* createDeviceDependentTexture(IImage* surface, const core::string& name); //! returns the current size of the screen or rendertarget virtual const core::dimension2d& getCurrentRenderTargetSize() const; diff --git a/source/Irrlicht/CD3D9ParallaxMapRenderer.h b/source/Irrlicht/CD3D9ParallaxMapRenderer.h index 54719e7f..f57a09f3 100644 --- a/source/Irrlicht/CD3D9ParallaxMapRenderer.h +++ b/source/Irrlicht/CD3D9ParallaxMapRenderer.h @@ -40,6 +40,7 @@ public: //! Returns the render capability of the material. virtual s32 getRenderCapability() const; + virtual void OnSetMaterial(const SMaterial& material) { } virtual void OnSetMaterial(const video::SMaterial& material, const video::SMaterial& lastMaterial, bool resetAllRenderstates, video::IMaterialRendererServices* services); diff --git a/source/Irrlicht/CD3D9Texture.cpp b/source/Irrlicht/CD3D9Texture.cpp index ec7bb45e..3e50e471 100644 --- a/source/Irrlicht/CD3D9Texture.cpp +++ b/source/Irrlicht/CD3D9Texture.cpp @@ -30,7 +30,7 @@ namespace video { //! rendertarget constructor -CD3D9Texture::CD3D9Texture(CD3D9Driver* driver, const core::dimension2d& size, const char* name) +CD3D9Texture::CD3D9Texture(CD3D9Driver* driver, const core::dimension2d& size, const core::string& name) : ITexture(name), Texture(0), RTTSurface(0), Driver(driver), DepthSurface(0), TextureSize(size), ImageSize(size), Pitch(0), HasMipMaps(false), HardwareMipMaps(false), IsRenderTarget(true) @@ -49,7 +49,7 @@ CD3D9Texture::CD3D9Texture(CD3D9Driver* driver, const core::dimension2d& si //! constructor CD3D9Texture::CD3D9Texture(IImage* image, CD3D9Driver* driver, - u32 flags, const char* name) + u32 flags, const core::string& name) : ITexture(name), Texture(0), RTTSurface(0), Driver(driver), DepthSurface(0), TextureSize(0,0), ImageSize(0,0), Pitch(0), HasMipMaps(false), HardwareMipMaps(false), IsRenderTarget(false) @@ -105,8 +105,10 @@ CD3D9Texture::~CD3D9Texture() // we can release the surface. We only use the value of the pointer // hence it is safe to use the dropped pointer... if (DepthSurface) + { if (DepthSurface->drop()) Driver->removeDepthSurface(DepthSurface); + } if (Device) Device->Release(); diff --git a/source/Irrlicht/CD3D9Texture.h b/source/Irrlicht/CD3D9Texture.h index ca93389a..84faa2dd 100644 --- a/source/Irrlicht/CD3D9Texture.h +++ b/source/Irrlicht/CD3D9Texture.h @@ -29,10 +29,10 @@ public: //! constructor CD3D9Texture(IImage* image, CD3D9Driver* driver, - u32 flags, const char* name); + u32 flags, const core::string& name); //! rendertarget constructor - CD3D9Texture(CD3D9Driver* driver, const core::dimension2d& size, const char* name); + CD3D9Texture(CD3D9Driver* driver, const core::dimension2d& size, const core::string& name); //! destructor virtual ~CD3D9Texture(); diff --git a/source/Irrlicht/CDMFLoader.cpp b/source/Irrlicht/CDMFLoader.cpp index c95b5095..a2ae1c10 100644 --- a/source/Irrlicht/CDMFLoader.cpp +++ b/source/Irrlicht/CDMFLoader.cpp @@ -196,16 +196,16 @@ IAnimatedMesh* CDMFLoader::createMesh(io::IReadFile* file) if (materiali[i].textureBlend==4) driver->setTextureCreationFlag(ETCF_ALWAYS_32_BIT,true); if (FileSystem->existFile(path+materiali[i].textureName)) - tex = driver->getTexture((path+materiali[i].textureName).c_str()); + tex = driver->getTexture((path+materiali[i].textureName)); else if (FileSystem->existFile(path+FileSystem->getFileBasename(materiali[i].textureName))) - tex = driver->getTexture((path+FileSystem->getFileBasename(materiali[i].textureName)).c_str()); + tex = driver->getTexture((path+FileSystem->getFileBasename(materiali[i].textureName))); else if (FileSystem->existFile(materiali[i].textureName)) tex = driver->getTexture(materiali[i].textureName.c_str()); else if (FileSystem->existFile(FileSystem->getFileBasename(materiali[i].textureName))) - tex = driver->getTexture(FileSystem->getFileBasename(materiali[i].textureName).c_str()); + tex = driver->getTexture(FileSystem->getFileBasename(materiali[i].textureName)); #ifdef _IRR_DMF_DEBUG_ else - os::Printer::log("Could not load texture", materiali[i].textureName.c_str()); + os::Printer::log("Could not load texture", materiali[i].textureName); #endif // _IRR_DMF_DEBUG_ } //Primary texture is just a colour @@ -234,7 +234,7 @@ IAnimatedMesh* CDMFLoader::createMesh(io::IReadFile* file) //Lightmap is present if (materiali[i].lightmapFlag == 0) - lig = driver->getTexture((path+materiali[i].lightmapName).c_str()); + lig = driver->getTexture((path+materiali[i].lightmapName)); else //no lightmap { buffer->Material.MaterialType = video::EMT_SOLID; @@ -377,9 +377,9 @@ IAnimatedMesh* CDMFLoader::createMesh(io::IReadFile* file) /** \brief Tell us if this file is able to be loaded by this class based on the file extension (e.g. ".bsp") \return true if file is loadable.*/ -bool CDMFLoader::isALoadableFileExtension(const c8* filename) const +bool CDMFLoader::isALoadableFileExtension(const core::string& filename) const { - return strstr(filename, ".dmf") != 0; + return core::hasFileExtension ( filename, "dmf" ); } diff --git a/source/Irrlicht/CDMFLoader.h b/source/Irrlicht/CDMFLoader.h index 7d23bd5f..0f95df85 100644 --- a/source/Irrlicht/CDMFLoader.h +++ b/source/Irrlicht/CDMFLoader.h @@ -52,7 +52,7 @@ namespace scene //! returns true if the file maybe is able to be loaded by this class //! based on the file extension (e.g. ".cob") - virtual bool isALoadableFileExtension(const c8* fileName) const; + virtual bool isALoadableFileExtension(const core::string& filename) const; /** creates/loads an animated mesh from the file. \return Pointer to the created mesh. Returns 0 if loading failed. diff --git a/source/Irrlicht/CDefaultGUIElementFactory.cpp b/source/Irrlicht/CDefaultGUIElementFactory.cpp index f0a831da..07cc11d3 100644 --- a/source/Irrlicht/CDefaultGUIElementFactory.cpp +++ b/source/Irrlicht/CDefaultGUIElementFactory.cpp @@ -26,6 +26,7 @@ #include "IGUITable.h" #include "IGUIToolbar.h" #include "IGUIWindow.h" +#include "IGUITreeView.h" namespace irr { @@ -92,7 +93,9 @@ IGUIElement* CDefaultGUIElementFactory::addGUIElement(EGUI_ELEMENT_TYPE type, IG case EGUIET_WINDOW: return Environment->addWindow(core::rect(0,0,100,100),false,0,parent); case EGUIET_SPIN_BOX: - return Environment->addSpinBox(L"0.0", core::rect(0,0,100,100), parent); + return Environment->addSpinBox(L"0.0", core::rect(0,0,100,100), true, parent); + case EGUIET_TREE_VIEW: + return Environment->addTreeView(core::rect(0,0,100,100),parent); default: return 0; } diff --git a/source/Irrlicht/CDefaultSceneNodeFactory.cpp b/source/Irrlicht/CDefaultSceneNodeFactory.cpp index 84364d70..a12c207a 100644 --- a/source/Irrlicht/CDefaultSceneNodeFactory.cpp +++ b/source/Irrlicht/CDefaultSceneNodeFactory.cpp @@ -51,6 +51,7 @@ CDefaultSceneNodeFactory::CDefaultSceneNodeFactory(ISceneManager* mgr) // legacy, for version <= 1.4.x irr files SupportedSceneNodeTypes.push_back(SSceneNodeTypePair(ESNT_CAMERA_MAYA, "cameraMaya")); SupportedSceneNodeTypes.push_back(SSceneNodeTypePair(ESNT_CAMERA_FPS, "cameraFPS")); + SupportedSceneNodeTypes.push_back(SSceneNodeTypePair(ESNT_Q3SHADER_SCENE_NODE, "quake3Shader")); } @@ -68,7 +69,7 @@ ISceneNode* CDefaultSceneNodeFactory::addSceneNode(ESCENE_NODE_TYPE type, IScene case ESNT_WATER_SURFACE: return Manager->addWaterSurfaceSceneNode(0, 2.0f, 300.0f, 10.0f, parent); case ESNT_TERRAIN: - return Manager->addTerrainSceneNode((const char*)0, parent, -1, + return Manager->addTerrainSceneNode((const c16*)0, parent, -1, core::vector3df(0.0f,0.0f,0.0f), core::vector3df(0.0f,0.0f,0.0f), core::vector3df(1.0f,1.0f,1.0f), diff --git a/source/Irrlicht/CFileList.cpp b/source/Irrlicht/CFileList.cpp index 7fee16e4..cfafa5a3 100644 --- a/source/Irrlicht/CFileList.cpp +++ b/source/Irrlicht/CFileList.cpp @@ -5,6 +5,7 @@ #include "CFileList.h" #include "IrrCompileConfig.h" #include "irrArray.h" +#include "coreutil.h" #include #if (defined(_IRR_POSIX_API_) || defined(_IRR_OSX_PLATFORM_)) @@ -29,13 +30,25 @@ namespace irr namespace io { - -CFileList::CFileList() +CFileList::CFileList( const c8 * param) { #ifdef _DEBUG setDebugName("CFileList"); #endif + + if ( 0 == param ) + constructNative (); +} + +CFileList::~CFileList() +{ + Files.clear (); +} + + +void CFileList::constructNative () +{ // -------------------------------------------- // Windows version #ifdef _IRR_WINDOWS_API_ @@ -129,8 +142,8 @@ CFileList::CFileList() #endif // sort the list on all platforms Files.sort(); -} +} u32 CFileList::getFileCount() const { @@ -138,33 +151,35 @@ u32 CFileList::getFileCount() const } -const c8* CFileList::getFileName(u32 index) const +static const core::string emptyFileListEntry; + +const core::string& CFileList::getFileName(u32 index) const { - if (index < Files.size()) - return Files[index].Name.c_str(); - else - return 0; + if (index >= Files.size()) + return emptyFileListEntry; + + return Files[index].Name; } //! Gets the full name of a file in the list, path included, based on an index. -const c8* CFileList::getFullFileName(u32 index) +const core::string& CFileList::getFullFileName(u32 index) { if (index >= Files.size()) - return 0; + return emptyFileListEntry; if (Files[index].FullName.size() < Files[index].Name.size()) { // create full name Files[index].FullName = Path; - - if (Path.size() > 3) + c16 last = lastChar ( Files[index].FullName ); + if ( last != '/' && last != '\\' ) Files[index].FullName.append('/'); Files[index].FullName.append(Files[index].Name); } - return Files[index].FullName.c_str(); + return Files[index].FullName; } diff --git a/source/Irrlicht/CFileList.h b/source/Irrlicht/CFileList.h index 1940ecb3..27213295 100644 --- a/source/Irrlicht/CFileList.h +++ b/source/Irrlicht/CFileList.h @@ -9,11 +9,34 @@ #include "irrString.h" #include "irrArray.h" + namespace irr { namespace io { +/*! + FileSystem, which manages where files are, so that modules which + use the the io do not need to know where every file is located. + local FileEntry +*/ +struct FileEntry +{ + core::string Name; + core::string FullName; + long Size; + bool isDirectory; + + bool operator <(const struct FileEntry& other) const + { + if ( isDirectory ^ other.isDirectory ) + return isDirectory; + + return Name.lower_ignore_case ( other.Name ); + } +}; + + /*! FileSystem, which manages where files are, so that modules which use the the io do not need to know where every file is located. @@ -23,7 +46,9 @@ class CFileList : public IFileList public: //! constructor - CFileList(); + CFileList( const c8 *param = 0); + + virtual ~CFileList(); //! Returns the amount of files in the filelist. /** \return Amount of files and directories in the file list. */ @@ -33,10 +58,10 @@ public: /** \param index is the zero based index of the file which name should be returned. The index has to be smaller than the amount getFileCount() returns. \return The file name of the file. Returns 0, if an error occured. */ - virtual const c8* getFileName(u32 index) const; + virtual const core::string& getFileName(u32 index) const; //! Gets the full name of a file in the list, path included, based on an index. - virtual const c8* getFullFileName(u32 index); + virtual const core::string& getFullFileName(u32 index); //! Returns of the file is a directory /** \param index is the zero based index of the file which name should @@ -44,28 +69,15 @@ public: \return True if the file is a directory, else false. */ virtual bool isDirectory(u32 index) const; -private: +//protected: - struct FileEntry - { - core::stringc Name; - core::stringc FullName; - long Size; - bool isDirectory; - - bool operator <(const struct FileEntry& other) const - { - if ( isDirectory ^ other.isDirectory ) - return isDirectory; - - return Name.lower_ignore_case ( other.Name ); - } - }; - - core::stringc Path; + core::string Path; core::array< FileEntry > Files; + + void constructNative (); }; + } // end namespace irr } // end namespace io diff --git a/source/Irrlicht/CFileSystem.cpp b/source/Irrlicht/CFileSystem.cpp index 495b0363..8497b0ee 100644 --- a/source/Irrlicht/CFileSystem.cpp +++ b/source/Irrlicht/CFileSystem.cpp @@ -2,6 +2,8 @@ // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h +#include "IrrCompileConfig.h" + #include "CFileSystem.h" #include "IReadFile.h" #include "IWriteFile.h" @@ -12,7 +14,6 @@ #include "CXMLWriter.h" #include "stdio.h" #include "os.h" -#include "IrrCompileConfig.h" #include "CAttributes.h" #include "CMemoryFile.h" @@ -32,12 +33,21 @@ namespace io { + + //! constructor CFileSystem::CFileSystem() { #ifdef _DEBUG setDebugName("CFileSystem"); #endif + + setFileListSystem ( FILESYSTEM_NATIVE ); + + addArchiveLoader ( new CArchiveLoaderZIP ( this ) ); + addArchiveLoader ( new CArchiveLoaderMount ( this ) ); + addArchiveLoader ( new CArchiveLoaderPAK ( this ) ); + } @@ -46,53 +56,41 @@ CFileSystem::~CFileSystem() { u32 i; - for ( i=0; idrop(); + for ( i=0; i < FileArchive.size(); ++i) + { + FileArchive[i]->drop (); + } - for ( i=0; idrop(); + for ( i=0; i < ArchiveLoader.size(); ++i) + { + ArchiveLoader[i]->drop (); + } - for ( i= 0; idrop(); } //! opens a file for read access -IReadFile* CFileSystem::createAndOpenFile(const c8* filename) +IReadFile* CFileSystem::createAndOpenFile( const core::string& filename) { IReadFile* file = 0; u32 i; - for ( i=0; iopenFile(filename); - if (file) - return file; - } - - for ( i = 0; iopenFile(filename); - if (file) - return file; - } - - for ( i = 0; iopenFile(filename); + file = FileArchive[i]->openFile(filename); if (file) return file; } // Create the file using an absolute path so that it matches // the scheme used by CNullDriver::getTexture(). - return createReadFile(getAbsolutePath(filename).c_str()); + return createReadFile(getAbsolutePath(filename)); } //! Creates an IReadFile interface for treating memory like a file. IReadFile* CFileSystem::createMemoryReadFile(void* memory, s32 len, - const c8* fileName, bool deleteMemoryWhenDropped) + const core::string& fileName, bool deleteMemoryWhenDropped) { if (!memory) return 0; @@ -102,7 +100,7 @@ IReadFile* CFileSystem::createMemoryReadFile(void* memory, s32 len, //! Creates an IReadFile interface for treating memory like a file. IWriteFile* CFileSystem::createMemoryWriteFile(void* memory, s32 len, - const c8* fileName, bool deleteMemoryWhenDropped) + const core::string& fileName, bool deleteMemoryWhenDropped) { if (!memory) return 0; @@ -112,116 +110,179 @@ IWriteFile* CFileSystem::createMemoryWriteFile(void* memory, s32 len, //! Opens a file for write access. -IWriteFile* CFileSystem::createAndWriteFile(const c8* filename, bool append) +IWriteFile* CFileSystem::createAndWriteFile(const core::string& filename, bool append) { return createWriteFile(filename, append); } -bool CFileSystem::addFolderFileArchive(const c8* filename, bool ignoreCase, bool ignorePaths) -{ - CUnZipReader* zr = new CUnZipReader(this, filename, ignoreCase, ignorePaths); - if (zr) - UnZipFileSystems.push_back(zr); - #ifdef _DEBUG - else - { - os::Printer::log("Could not open file. Folderfile not added", filename, ELL_ERROR); - } - #endif - _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; - return (zr!=0); +//! Adds an external archive loader to the engine. +void CFileSystem::addArchiveLoader(IArchiveLoader* loader) +{ + if (!loader) + return; + + //loader->grab(); + ArchiveLoader.push_back ( loader ); } -//! adds an zip archive to the filesystem -bool CFileSystem::addZipFileArchive(const c8* filename, bool ignoreCase, bool ignorePaths) +//! Adds an archive to the file system. +bool CFileSystem::registerFileArchive( const core::string& filename, bool ignoreCase, bool ignorePaths, s32 index ) { - CZipReader* zr = 0; - IReadFile* file = createAndOpenFile(filename); - if (file) + IFileArchive* archive = 0; + bool ret = false; + u32 i; + + // try to load arhive based on file name + for ( i = 0; i < ArchiveLoader.size(); ++i) { - zr = new CZipReader(file, ignoreCase, ignorePaths); - if (zr) - ZipFileSystems.push_back(zr); - - file->drop(); + if ( ArchiveLoader[i]->isALoadableFileFormat( filename ) ) + { + archive = ArchiveLoader[i]->createArchive( filename, ignoreCase, ignorePaths ); + if (archive) + break; + } } - #ifdef _DEBUG - else - os::Printer::log("Could not open file. Zipfile not added", filename, ELL_ERROR); - #endif - _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; - return (zr != 0); + if ( archive ) + { + if ( index < 0 ) + FileArchive.push_back ( archive ); + else + FileArchive.insert ( archive, index ); + + ret = true; + } + else + { + char buf[256]; + + core::stringw showName ( filename ); + snprintf ( buf, sizeof (buf), "Could not create archive for: %ls\n", showName.c_str() ); + os::Printer::log( buf ,ELL_ERROR); + } + + return ret; + } - -//! adds an pak archive to the filesystem -bool CFileSystem::addPakFileArchive(const c8* filename, bool ignoreCase, bool ignorePaths) +//! removes an archive to the file system. +bool CFileSystem::unregisterFileArchive( u32 index ) { - CPakReader* zr = 0; - IReadFile* file = createAndOpenFile(filename); - if (file) + bool ret = false; + if ( index < FileArchive.size () ) { - zr = new CPakReader(file, ignoreCase, ignorePaths); - if (zr) - PakFileSystems.push_back(zr); - - file->drop(); + FileArchive[index]->drop(); + FileArchive.erase ( index ); + ret = true; } - #ifdef _DEBUG - else - os::Printer::log("Could not open file. Pakfile not added", filename, ELL_ERROR); - #endif + return ret; +} - _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; - return (zr != 0); +//! gets an archive +u32 CFileSystem::getFileArchiveCount() +{ + return FileArchive.size(); +} + +IFileArchive* CFileSystem::getFileArchive( u32 index ) +{ + return index < getFileArchiveCount () ? FileArchive [ index ] : 0; } //! Returns the string of the current working directory -const c8* CFileSystem::getWorkingDirectory() +const core::string& CFileSystem::getWorkingDirectory() { -#ifdef _IRR_WINDOWS_API_ - #if !defined ( _WIN32_WCE ) - _getcwd(WorkingDirectory, FILE_SYSTEM_MAX_PATH); - #endif -#endif + eFileSystemType type = FileSystemType; -#if (defined(_IRR_POSIX_API_) || defined(_IRR_OSX_PLATFORM_)) - getcwd(WorkingDirectory, (size_t)FILE_SYSTEM_MAX_PATH); -#endif - return WorkingDirectory; + if ( type != FILESYSTEM_NATIVE ) + { + type = FILESYSTEM_VIRTUAL; + } + else + { + const s32 FILE_SYSTEM_MAX_PATH = 1024; + WorkingDirectory [ type ].reserve ( FILE_SYSTEM_MAX_PATH ); + c16* r = (c16*) WorkingDirectory [ type ].c_str(); + + #if defined( _IRR_USE_WINDOWS_CE_DEVICE_) + #elif defined( _IRR_WINDOWS_API_) + #if defined ( _IRR_WCHAR_FILESYSTEM ) + _wgetcwd ( r, FILE_SYSTEM_MAX_PATH ); + #else + _getcwd(r, FILE_SYSTEM_MAX_PATH); + #endif + #endif + + #if (defined(_IRR_POSIX_API_) || defined(_IRR_OSX_PLATFORM_)) + + #if defined ( _IRR_WCHAR_FILESYSTEM ) + wgetcwd ( r, FILE_SYSTEM_MAX_PATH ); + #else + getcwd(r, (size_t)FILE_SYSTEM_MAX_PATH); + #endif + #endif + + WorkingDirectory [ type ].verify(); + } + + return WorkingDirectory [ type ]; } //! Changes the current Working Directory to the given string. -bool CFileSystem::changeWorkingDirectoryTo(const c8* newDirectory) +bool CFileSystem::changeWorkingDirectoryTo(const core::string& newDirectory) { bool success=false; -#ifdef _MSC_VER - #if !defined ( _WIN32_WCE ) - success=(_chdir(newDirectory) == 0); + + if ( FileSystemType != FILESYSTEM_NATIVE ) + { + WorkingDirectory [ FILESYSTEM_VIRTUAL ].append ( newDirectory ); + flatenFilename ( WorkingDirectory [ FILESYSTEM_VIRTUAL ], "" ); + success = 1; + } + else + { + WorkingDirectory [ FILESYSTEM_NATIVE ] = newDirectory; + +#if defined( _IRR_USE_WINDOWS_CE_DEVICE_) + success = true; +#elif defined( _MSC_VER) + #if defined ( _IRR_WCHAR_FILESYSTEM ) + success=(_wchdir(newDirectory.c_str()) == 0); + #else + success=(_chdir(newDirectory.c_str()) == 0); #endif #else - success=(chdir(newDirectory) == 0); + success=(chdir(newDirectory.c_str()) == 0); #endif + } + return success; } - -core::stringc CFileSystem::getAbsolutePath(const core::stringc& filename) const +/*! +*/ +core::string CFileSystem::getAbsolutePath(const core::string& filename) const { - c8 *p=0; + c16 *p=0; -#ifdef _IRR_WINDOWS_API_ - #if !defined ( _WIN32_WCE ) - c8 fpath[_MAX_PATH]; - p = _fullpath( fpath, filename.c_str(), _MAX_PATH); +#if defined( _IRR_USE_WINDOWS_CE_DEVICE_) + return filename; +#elif defined( _IRR_WINDOWS_API_) + + #if defined ( _IRR_WCHAR_FILESYSTEM ) + c16 fpath[_MAX_PATH]; + p = _wfullpath( fpath, filename.c_str(), _MAX_PATH); + #else + c8 fpath[_MAX_PATH]; + p = _fullpath( fpath, filename.c_str(), _MAX_PATH); #endif + #elif (defined(_IRR_POSIX_API_) || defined(_IRR_OSX_PLATFORM_)) c8 fpath[4096]; fpath[0]=0; @@ -238,19 +299,19 @@ core::stringc CFileSystem::getAbsolutePath(const core::stringc& filename) const return filename; } else - return core::stringc(fpath); + return core::string(fpath); } #endif - return core::stringc(p); + return core::string(p); } //! returns the directory part of a filename, i.e. all until the first //! slash or backslash, excluding it. If no directory path is prefixed, a '.' //! is returned. -core::stringc CFileSystem::getFileDir(const core::stringc& filename) const +core::string CFileSystem::getFileDir(const core::string& filename) const { // find last forward or backslash s32 lastSlash = filename.findLast('/'); @@ -266,7 +327,7 @@ core::stringc CFileSystem::getFileDir(const core::stringc& filename) const //! returns the base part of a filename, i.e. all except for the directory //! part. If no directory path is prefixed, the full name is returned. -core::stringc CFileSystem::getFileBasename(const core::stringc& filename, bool keepExtension) const +core::string CFileSystem::getFileBasename(const core::string& filename, bool keepExtension) const { // find last forward or backslash s32 lastSlash = filename.findLast('/'); @@ -291,31 +352,171 @@ core::stringc CFileSystem::getFileBasename(const core::stringc& filename, bool k } -//! Creates a list of files and directories in the current working directory -IFileList* CFileSystem::createFileList() const +//! flaten a path and file name for example: "/you/me/../." becomes "/you" +core::string& CFileSystem::flatenFilename( core::string& directory, const core::string& root ) const { - return new CFileList(); + directory.replace ( '\\', '/' ); + if ( lastChar ( directory ) != '/' ) + directory.append ( '/' ); + + core::string dir; + core::string subdir; + + s32 lastpos = 0; + s32 pos = 0; + + while ( ( pos = directory.findNext ( '/', lastpos ) ) >= 0 ) + { + subdir = directory.subString ( lastpos, pos - lastpos + 1 ); + + if ( subdir == "../" ) + { + deletePathFromPath ( dir, 2 ); + } + else + if ( subdir == "/" ) + { + dir = root; + } + else + if ( subdir != "./" ) + { + dir.append ( subdir ); + } + + lastpos = pos + 1; + } + directory = dir; + return directory; +} + +//! Creates a list of files and directories in the current working directory +eFileSystemType CFileSystem::setFileListSystem( eFileSystemType listType) +{ + eFileSystemType current = FileSystemType; + FileSystemType = listType; + return current; +} + + +//! Creates a list of files and directories in the current working directory +IFileList* CFileSystem::createFileList() +{ + FileEntry e2; + FileEntry e3; + + if ( FileSystemType == FILESYSTEM_NATIVE ) + return new CFileList(); + + CFileList* r = new CFileList( "virtual" ); + r->Path = WorkingDirectory [ FILESYSTEM_VIRTUAL ]; + + for ( u32 i = 0; i != FileArchive.size(); ++i) + { + CFileList* flist[2] = { 0, 0 }; + + //! merge relative folder file archives + if ( FileArchive[i]->getArchiveType() == "mount" ) + { + eFileSystemType currentType = setFileListSystem ( FILESYSTEM_NATIVE ); + + core::string save ( getWorkingDirectory () ); + core::string current; + + current = FileArchive[i]->getArchiveName() + WorkingDirectory [ FILESYSTEM_VIRTUAL ]; + flatenFilename ( current ); + + if ( changeWorkingDirectoryTo ( current ) ) + { + flist[0] = new CFileList( "mountpoint" ); + flist[0]->constructNative (); + changeWorkingDirectoryTo ( save ); + } + + setFileListSystem ( currentType ); + } + else + if ( FileArchive[i]->getArchiveType() == "zip" ) + { + flist[0] = new CFileList( "zip" ); + flist[1] = new CFileList( "zip directory" ); + + // add relative navigation + e2.isDirectory = 1; + e2.Name = "."; + e2.FullName = r->Path + e2.Name; + e2.Size = 0; + flist[1]->Files.push_back ( e2 ); + + e2.Name = ".."; + e2.FullName = r->Path + e2.Name; + flist[1]->Files.push_back ( e2 ); + + for ( u32 g = 0; g < FileArchive[i]->getFileCount(); ++g) + { + const SZipFileEntry *e = (SZipFileEntry*) FileArchive[i]->getFileInfo ( g ); + s32 test = isInSameDirectory ( r->Path, e->zipFileName ); + if ( test < 0 || test > 1 ) + continue; + + e2.Size = e->header.DataDescriptor.UncompressedSize; + e2.isDirectory = e2.Size == 0; + + // check missing directories + if ( !e2.isDirectory && test == 1 ) + { + e3.Size = 0; + e3.isDirectory = 1; + e3.FullName = e->path; + e3.Name = e->path.subString ( r->Path.size(), e->path.size() - r->Path.size() - 1 ); + + if ( flist[1]->Files.binary_search ( e3 ) < 0 ) + flist[1]->Files.push_back ( e3 ); + } + else + { + e2.FullName = e->zipFileName; + e2.Name = e->simpleFileName; + + if ( !e2.isDirectory ) + core::deletePathFromFilename ( e2.Name ); + flist[0]->Files.push_back ( e2 ); + } + } + } + + // add file to virtual directory + for ( u32 g = 0; g < 2; ++g ) + { + if ( !flist[g] ) + continue; + for ( u32 j = 0; j != flist[g]->Files.size(); ++j ) + r->Files.push_back ( flist[g]->Files[j] ); + + flist[g]->drop(); + } + } + + r->Files.sort(); + return r; } //! determines if a file exists and would be able to be opened. -bool CFileSystem::existFile(const c8* filename) const +bool CFileSystem::existFile(const core::string& filename) const { u32 i; - for (i=0; ifindFile(filename)!=-1) + for (i=0; i < FileArchive.size(); ++i) + if ( FileArchive[i]->findFile(filename)!=-1) return true; - for (i=0; ifindFile(filename)!=-1) - return true; +#if defined ( _IRR_WCHAR_FILESYSTEM ) + FILE* f = _wfopen(filename.c_str(), L"rb"); +#else + FILE* f = fopen(filename.c_str(), "rb"); +#endif - for (i=0; ifindFile(filename)!=-1) - return true; - - FILE* f = fopen(filename, "rb"); if (f) { fclose(f); @@ -328,7 +529,7 @@ bool CFileSystem::existFile(const c8* filename) const //! Creates a XML Reader from a file. -IXMLReader* CFileSystem::createXMLReader(const c8* filename) +IXMLReader* CFileSystem::createXMLReader(const core::string& filename) { IReadFile* file = createAndOpenFile(filename); if (!file) @@ -351,7 +552,7 @@ IXMLReader* CFileSystem::createXMLReader(IReadFile* file) //! Creates a XML Reader from a file. -IXMLReaderUTF8* CFileSystem::createXMLReaderUTF8(const c8* filename) +IXMLReaderUTF8* CFileSystem::createXMLReaderUTF8(const core::string& filename) { IReadFile* file = createAndOpenFile(filename); if (!file) @@ -374,7 +575,7 @@ IXMLReaderUTF8* CFileSystem::createXMLReaderUTF8(IReadFile* file) //! Creates a XML Writer from a file. -IXMLWriter* CFileSystem::createXMLWriter(const c8* filename) +IXMLWriter* CFileSystem::createXMLWriter(const core::string& filename) { IWriteFile* file = createAndWriteFile(filename); IXMLWriter* writer = createXMLWriter(file); diff --git a/source/Irrlicht/CFileSystem.h b/source/Irrlicht/CFileSystem.h index 645b2259..930f95c9 100644 --- a/source/Irrlicht/CFileSystem.h +++ b/source/Irrlicht/CFileSystem.h @@ -15,8 +15,7 @@ namespace io class CZipReader; class CPakReader; - class CUnZipReader; - const s32 FILE_SYSTEM_MAX_PATH = 1024; + class CMountPointReader; /*! FileSystem which uses normal files and one zipfile @@ -32,71 +31,74 @@ public: virtual ~CFileSystem(); //! opens a file for read access - virtual IReadFile* createAndOpenFile(const c8* filename); + virtual IReadFile* createAndOpenFile(const core::string& filename); //! Creates an IReadFile interface for accessing memory like a file. - virtual IReadFile* createMemoryReadFile(void* memory, s32 len, const c8* fileName, bool deleteMemoryWhenDropped = false); + virtual IReadFile* createMemoryReadFile(void* memory, s32 len, const core::string& fileName, bool deleteMemoryWhenDropped = false); //! Creates an IWriteFile interface for accessing memory like a file. - virtual IWriteFile* createMemoryWriteFile(void* memory, s32 len, const c8* fileName, bool deleteMemoryWhenDropped=false); + virtual IWriteFile* createMemoryWriteFile(void* memory, s32 len, const core::string& fileName, bool deleteMemoryWhenDropped=false); //! Opens a file for write access. - virtual IWriteFile* createAndWriteFile(const c8* filename, bool append=false); + virtual IWriteFile* createAndWriteFile(const core::string& filename, bool append=false); - //! adds an zip archive to the filesystem - virtual bool addZipFileArchive(const c8* filename, bool ignoreCase = true, bool ignorePaths = true); - virtual bool addFolderFileArchive(const c8* filename, bool ignoreCase = true, bool ignorePaths = true); + //! Adds an archive to the file system. + virtual bool registerFileArchive( const core::string& filename, bool ignoreCase = true, bool ignorePaths = true, s32 index = -1); - //! adds an pak archive to the filesystem - virtual bool addPakFileArchive(const c8* filename, bool ignoreCase = true, bool ignorePaths = true); + //! Adds an external archive loader to the engine. + virtual void addArchiveLoader(IArchiveLoader* loader); + + //! gets an archive + virtual u32 getFileArchiveCount(); + virtual IFileArchive* getFileArchive( u32 index ); + //! removes an archive to the file system. + virtual bool unregisterFileArchive( u32 index ); //! Returns the string of the current working directory - virtual const c8* getWorkingDirectory(); + virtual const core::string& getWorkingDirectory(); //! Changes the current Working Directory to the string given. //! The string is operating system dependent. Under Windows it will look //! like this: "drive:\directory\sudirectory\" - virtual bool changeWorkingDirectoryTo(const c8* newDirectory); + virtual bool changeWorkingDirectoryTo(const core::string& newDirectory); //! Converts a relative path to an absolute (unique) path, resolving symbolic links - virtual core::stringc getAbsolutePath(const core::stringc& filename) const; + virtual core::string getAbsolutePath(const core::string& filename) const; //! Returns the directory a file is located in. /** \param filename: The file to get the directory from */ - virtual core::stringc getFileDir(const core::stringc& filename) const; + virtual core::string getFileDir(const core::string& filename) const; //! Returns the base part of a filename, i.e. the name without the directory //! part. If no directory is prefixed, the full name is returned. /** \param filename: The file to get the basename from */ - core::stringc getFileBasename(const core::stringc& filename, bool keepExtension=true) const; + virtual core::string getFileBasename(const core::string& filename, bool keepExtension=true) const; + + //! flaten a path and file name for example: "/you/me/../." becomes "/you" + virtual core::string& flatenFilename( core::string& directory, const core::string& root = "/" ) const; //! Creates a list of files and directories in the current working directory //! and returns it. - virtual IFileList* createFileList() const; + virtual eFileSystemType setFileListSystem( eFileSystemType listType); + virtual IFileList* createFileList(); //! determinates if a file exists and would be able to be opened. - virtual bool existFile(const c8* filename) const; - - //! determines if a file exists and would be able to be opened. - bool existFile(const core::stringc& filename) const - { - return existFile(filename.c_str()); - } + virtual bool existFile(const core::string& filename) const; //! Creates a XML Reader from a file. - virtual IXMLReader* createXMLReader(const c8* filename); + virtual IXMLReader* createXMLReader(const core::string& filename); //! Creates a XML Reader from a file. virtual IXMLReader* createXMLReader(IReadFile* file); //! Creates a XML Reader from a file. - virtual IXMLReaderUTF8* createXMLReaderUTF8(const c8* filename); + virtual IXMLReaderUTF8* createXMLReaderUTF8(const core::string& filename); //! Creates a XML Reader from a file. virtual IXMLReaderUTF8* createXMLReaderUTF8(IReadFile* file); //! Creates a XML Writer from a file. - virtual IXMLWriter* createXMLWriter(const c8* filename); + virtual IXMLWriter* createXMLWriter(const core::string& filename); //! Creates a XML Writer from a file. virtual IXMLWriter* createXMLWriter(IWriteFile* file); @@ -106,10 +108,12 @@ public: private: - core::array ZipFileSystems; - core::array PakFileSystems; - core::array UnZipFileSystems; - c8 WorkingDirectory[FILE_SYSTEM_MAX_PATH]; + eFileSystemType FileSystemType; // Currently used FileSystemType + core::string WorkingDirectory [2]; // WorkingDirectory for Native/Virtual + + core::array< IArchiveLoader* > ArchiveLoader; // currently attached ArchiveLoaders + core::array< IFileArchive*> FileArchive; // currently attached Archives + }; diff --git a/source/Irrlicht/CGUIColorSelectDialog.cpp b/source/Irrlicht/CGUIColorSelectDialog.cpp index ee660898..d1ed240c 100644 --- a/source/Irrlicht/CGUIColorSelectDialog.cpp +++ b/source/Irrlicht/CGUIColorSelectDialog.cpp @@ -307,7 +307,7 @@ void CGUIColorSelectDialog::buildColorRing( const core::dimension2d & dim, bool generateMipLevels = driver->getTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS); driver->setTextureCreationFlag( video::ETCF_CREATE_MIP_MAPS, false); - ColorRing.Texture = driver->addTexture ("#colorring", RawTexture); + ColorRing.Texture = driver->addTexture ( L"#colorring", RawTexture); RawTexture->drop(); driver->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, generateMipLevels); diff --git a/source/Irrlicht/CGUIComboBox.cpp b/source/Irrlicht/CGUIComboBox.cpp index 6f0fd317..ceff0609 100644 --- a/source/Irrlicht/CGUIComboBox.cpp +++ b/source/Irrlicht/CGUIComboBox.cpp @@ -94,7 +94,27 @@ const wchar_t* CGUIComboBox::getItem(u32 idx) const if (idx >= Items.size()) return 0; - return Items[idx].c_str(); + return Items[idx].Name.c_str(); +} + +//! returns string of an item. the idx may be a value from 0 to itemCount-1 +u32 CGUIComboBox::getItemData(u32 idx) const +{ + if (idx >= Items.size()) + return 0; + + return Items[idx].Data; +} + +//! Returns index based on item data +s32 CGUIComboBox::getIndexForItemData(u32 data ) const +{ + for ( u32 i = 0; i < Items.size (); ++i ) + { + if ( Items[i].Data == data ) + return i; + } + return -1; } @@ -119,9 +139,9 @@ const wchar_t* CGUIComboBox::getText() const //! adds an item and returns the index of it -u32 CGUIComboBox::addItem(const wchar_t* text) +u32 CGUIComboBox::addItem(const wchar_t* text, u32 data) { - Items.push_back(core::stringw(text)); + Items.push_back( SComboData ( text, data ) ); if (Selected == -1) setSelected(0); @@ -155,7 +175,7 @@ void CGUIComboBox::setSelected(s32 idx) if (Selected == -1) SelectedText->setText(L""); else - SelectedText->setText(Items[Selected].c_str()); + SelectedText->setText(Items[Selected].Name.c_str()); } @@ -402,7 +422,7 @@ void CGUIComboBox::openCloseMenu() ListBox->drop(); for (s32 i=0; i<(s32)Items.size(); ++i) - ListBox->addItem(Items[i].c_str()); + ListBox->addItem(Items[i].Name.c_str()); ListBox->setSelected(Selected); @@ -427,7 +447,7 @@ void CGUIComboBox::serializeAttributes(io::IAttributes* out, io::SAttributeReadW core::stringc s = "Item"; s += i; s += "Text"; - out->addString(s.c_str(), Items[i].c_str()); + out->addString(s.c_str(), Items[i].Name.c_str()); } } @@ -450,7 +470,7 @@ void CGUIComboBox::deserializeAttributes(io::IAttributes* in, io::SAttributeRead core::stringc s = "Item"; s += i; s += "Text"; - addItem(in->getAttributeAsStringW(s.c_str()).c_str()); + addItem(in->getAttributeAsStringW(s.c_str()).c_str(), 0); } setSelected(in->getAttributeAsInt("Selected")); diff --git a/source/Irrlicht/CGUIComboBox.h b/source/Irrlicht/CGUIComboBox.h index ac8b4aee..f56c552f 100644 --- a/source/Irrlicht/CGUIComboBox.h +++ b/source/Irrlicht/CGUIComboBox.h @@ -35,8 +35,14 @@ namespace gui //! returns string of an item. the idx may be a value from 0 to itemCount-1 virtual const wchar_t* getItem(u32 idx) const; + //! Returns item data of an item. the idx may be a value from 0 to itemCount-1 + virtual u32 getItemData(u32 idx) const; + + //! Returns index based on item data + virtual s32 getIndexForItemData( u32 data ) const; + //! adds an item and returns the index of it - virtual u32 addItem(const wchar_t* text); + virtual u32 addItem(const wchar_t* text, u32 data); //! Removes an item from the combo box. virtual void removeItem(u32 id); @@ -77,7 +83,18 @@ namespace gui IGUIStaticText* SelectedText; IGUIListBox* ListBox; IGUIElement *LastFocus; - core::array< core::stringw > Items; + + + struct SComboData + { + SComboData ( const wchar_t * text, u32 data ) + : Name (text), Data ( data ) {} + + core::stringw Name; + u32 Data; + }; + core::array< SComboData > Items; + s32 Selected; EGUI_ALIGNMENT HAlign, VAlign; bool HasFocus; diff --git a/source/Irrlicht/CGUIEditBox.cpp b/source/Irrlicht/CGUIEditBox.cpp index b542ca13..b6549f8a 100644 --- a/source/Irrlicht/CGUIEditBox.cpp +++ b/source/Irrlicht/CGUIEditBox.cpp @@ -235,6 +235,12 @@ bool CGUIEditBox::processKey(const SEvent& event) if (event.KeyInput.Control) { + // german backlash '\' entered with control + '?' + if ( event.KeyInput.Char == '\\' ) + { + inputChar(event.KeyInput.Char); + } + switch(event.KeyInput.Key) { case KEY_KEY_A: diff --git a/source/Irrlicht/CGUIEnvironment.cpp b/source/Irrlicht/CGUIEnvironment.cpp index f9d05013..7c821131 100644 --- a/source/Irrlicht/CGUIEnvironment.cpp +++ b/source/Irrlicht/CGUIEnvironment.cpp @@ -19,6 +19,8 @@ #include "CGUIMeshViewer.h" #include "CGUICheckBox.h" #include "CGUIListBox.h" +#include "CGUITreeView.h" +#include "CGUIImageList.h" #include "CGUIFileOpenDialog.h" #include "CGUIColorSelectDialog.h" #include "CGUIStaticText.h" @@ -156,10 +158,11 @@ CGUIEnvironment::~CGUIEnvironment() void CGUIEnvironment::loadBuiltInFont() { - const c8* filename = "#DefaultFont"; + core::string filename = "#DefaultFont"; + io::IReadFile* file = io::createMemoryReadFile(BuiltInFontData, BuiltInFontDataSize, filename, false); - CGUIFont* font = new CGUIFont(this, "#DefaultFont"); + CGUIFont* font = new CGUIFont(this, filename ); if (!font->load(file)) { os::Printer::log("Error: Could not load built-in Font. Did you compile without the BMP loader?", ELL_ERROR); @@ -187,8 +190,7 @@ void CGUIEnvironment::drawAll() AbsoluteRect.LowerRightCorner.Y != dim.Height) { // resize gui environment - DesiredRect.LowerRightCorner.X = Driver->getScreenSize().Width; - DesiredRect.LowerRightCorner.Y = Driver->getScreenSize().Height; + DesiredRect.LowerRightCorner = dim; AbsoluteClippingRect = DesiredRect; AbsoluteRect = DesiredRect; updateAbsolutePosition(); @@ -658,7 +660,7 @@ IGUIElement* CGUIEnvironment::addGUIElement(const c8* elementName, IGUIElement* //! Saves the current gui into a file. //! \param filename: Name of the file . -bool CGUIEnvironment::saveGUI(const c8* filename, IGUIElement* start) +bool CGUIEnvironment::saveGUI(const core::string& filename, IGUIElement* start) { io::IWriteFile* file = FileSystem->createAndWriteFile(filename); if (!file) @@ -700,7 +702,7 @@ bool CGUIEnvironment::saveGUI(io::IWriteFile* file, IGUIElement* start) //! Loads the gui. Note that the current gui is not cleared before. //! \param filename: Name of the file. -bool CGUIEnvironment::loadGUI(const c8* filename, IGUIElement* parent) +bool CGUIEnvironment::loadGUI(const c16* filename, IGUIElement* parent) { io::IReadFile* read = FileSystem->createAndOpenFile(filename); if (!read) @@ -1018,7 +1020,7 @@ IGUIScrollBar* CGUIEnvironment::addScrollBar(bool horizontal, const core::rect& rectangle, IGUIElement* parent, s32 id, bool drawBackground) { CGUITable* b = new CGUITable(this, parent ? parent : this, id, rectangle, true, drawBackground, false); @@ -1114,6 +1116,19 @@ IGUIListBox* CGUIEnvironment::addListBox(const core::rect& rectangle, return b; } +//! adds a tree view +IGUITreeView* CGUIEnvironment::addTreeView(const core::rect& rectangle, + IGUIElement* parent, s32 id, + bool drawBackground, + bool scrollBarVertical, bool scrollBarHorizontal) +{ + IGUITreeView* b = new CGUITreeView(this, parent ? parent : this, id, rectangle, + true, drawBackground, scrollBarVertical, scrollBarHorizontal); + + b->setIconFont ( getBuiltInFont () ); + b->drop(); + return b; +} //! adds a file open dialog. The returned pointer must not be dropped. IGUIFileOpenDialog* CGUIEnvironment::addFileOpenDialog(const wchar_t* title, @@ -1185,10 +1200,11 @@ IGUIEditBox* CGUIEnvironment::addEditBox(const wchar_t* text, //! Adds a spin box to the environment IGUISpinBox* CGUIEnvironment::addSpinBox(const wchar_t* text, - const core::rect &rectangle, - IGUIElement* parent, s32 id) + const core::rect &rectangle, + bool border,IGUIElement* parent, s32 id) { - IGUISpinBox* d = new CGUISpinBox(text, this, parent ? parent : this, id, rectangle); + IGUISpinBox* d = new CGUISpinBox(text, border,this, + parent ? parent : this, id, rectangle); d->drop(); return d; @@ -1287,17 +1303,15 @@ IGUIComboBox* CGUIEnvironment::addComboBox(const core::rect& rectangle, } + //! returns the font -IGUIFont* CGUIEnvironment::getFont(const c8* filename) +IGUIFont* CGUIEnvironment::getFont(const core::string& filename) { // search existing font SFont f; IGUIFont* ifont=0; - if (!filename) - f.Filename = ""; - else - f.Filename = filename; + f.Filename = filename; f.Filename.make_lower(); @@ -1311,11 +1325,11 @@ IGUIFont* CGUIEnvironment::getFont(const c8* filename) if (!FileSystem->existFile(filename)) { - os::Printer::log("Could not load font because the file does not exist", f.Filename.c_str(), ELL_ERROR); + os::Printer::log("Could not load font because the file does not exist", f.Filename, ELL_ERROR); return 0; } - io::IXMLReader *xml = FileSystem->createXMLReader(filename); + io::IXMLReader *xml = FileSystem->createXMLReader(filename ); if (xml) { // this is an XML font, but we need to know what type @@ -1348,8 +1362,8 @@ IGUIFont* CGUIEnvironment::getFont(const c8* filename) CGUIFont* font = new CGUIFont(this, filename); ifont = (IGUIFont*)font; // change working directory, for loading textures - core::stringc workingDir = FileSystem->getWorkingDirectory(); - FileSystem->changeWorkingDirectoryTo(FileSystem->getFileDir(f.Filename).c_str()); + core::string workingDir = FileSystem->getWorkingDirectory(); + FileSystem->changeWorkingDirectoryTo(FileSystem->getFileDir(f.Filename)); // load the font if (!font->load(xml)) @@ -1359,7 +1373,7 @@ IGUIFont* CGUIEnvironment::getFont(const c8* filename) ifont = 0; } // change working dir back again - FileSystem->changeWorkingDirectoryTo( workingDir.c_str()); + FileSystem->changeWorkingDirectoryTo( workingDir ); } else if (t==EGFT_VECTOR) { @@ -1377,9 +1391,9 @@ IGUIFont* CGUIEnvironment::getFont(const c8* filename) if (!ifont) { - CGUIFont* font = new CGUIFont(this, f.Filename.c_str()); + CGUIFont* font = new CGUIFont(this, f.Filename ); ifont = (IGUIFont*)font; - if (!font->load(f.Filename.c_str())) + if (!font->load(f.Filename)) { font->drop(); return 0; @@ -1395,16 +1409,12 @@ IGUIFont* CGUIEnvironment::getFont(const c8* filename) } -IGUISpriteBank* CGUIEnvironment::getSpriteBank(const c8* filename) +IGUISpriteBank* CGUIEnvironment::getSpriteBank(const core::string& filename) { // search for the file name SSpriteBank b; - if (!filename) - b.Filename = ""; - else - b.Filename = filename; - + b.Filename = filename; b.Filename.make_lower(); s32 index = Banks.binary_search(b); @@ -1413,7 +1423,7 @@ IGUISpriteBank* CGUIEnvironment::getSpriteBank(const c8* filename) // we don't have this sprite bank, we should load it - if (!FileSystem->existFile(b.Filename.c_str())) + if (!FileSystem->existFile(b.Filename)) { os::Printer::log("Could not load sprite bank because the file does not exist", filename, ELL_ERROR); return 0; @@ -1425,15 +1435,12 @@ IGUISpriteBank* CGUIEnvironment::getSpriteBank(const c8* filename) } -IGUISpriteBank* CGUIEnvironment::addEmptySpriteBank(const c8 *name) +IGUISpriteBank* CGUIEnvironment::addEmptySpriteBank(const core::string& name) { // no duplicate names allowed SSpriteBank b; - if (!name) - b.Filename = ""; - else - b.Filename = name; + b.Filename = name; const s32 index = Banks.binary_search(b); if (index != -1) @@ -1442,7 +1449,6 @@ IGUISpriteBank* CGUIEnvironment::addEmptySpriteBank(const c8 *name) // create a new sprite bank b.Bank = new CGUISpriteBank(this); - Banks.push_back(b); return b.Bank; @@ -1458,8 +1464,21 @@ IGUIFont* CGUIEnvironment::getBuiltInFont() const return Fonts[0].Font; } +//! Creates the image list from the given texture. +IGUIImageList* CGUIEnvironment::createImageList( video::ITexture* texture, + core::dimension2d imageSize, bool useAlphaChannel ) +{ + CGUIImageList* imageList = new CGUIImageList( Driver ); + if( !imageList->createImageList( texture, imageSize, useAlphaChannel ) ) + { + imageList->drop(); + return 0; + } + + return imageList; +} -//! Returns the root gui element. +//! Returns the root gui element. IGUIElement* CGUIEnvironment::getRootGUIElement() { return this; diff --git a/source/Irrlicht/CGUIEnvironment.h b/source/Irrlicht/CGUIEnvironment.h index 8e9c3051..6ec795f6 100644 --- a/source/Irrlicht/CGUIEnvironment.h +++ b/source/Irrlicht/CGUIEnvironment.h @@ -70,14 +70,19 @@ public: See IReferenceCounted::drop() for more information. */ virtual IGUISkin* createSkin(EGUI_SKIN_TYPE type); + //! Creates the image list from the given texture. + virtual IGUIImageList* createImageList( video::ITexture* texture, + core::dimension2d imageSize, bool useAlphaChannel ); + //! returns the font - virtual IGUIFont* getFont(const c8* filename); + virtual IGUIFont* getFont(const core::string& filename); + //! returns the sprite bank - virtual IGUISpriteBank* getSpriteBank(const c8* filename); + virtual IGUISpriteBank* getSpriteBank(const core::string& filename); //! returns the sprite bank - virtual IGUISpriteBank* addEmptySpriteBank(const c8* name); + virtual IGUISpriteBank* addEmptySpriteBank(const core::string& name); //! adds an button. The returned pointer must not be dropped. virtual IGUIButton* addButton(const core::rect& rectangle, IGUIElement* parent=0, s32 id=-1, const wchar_t* text=0,const wchar_t* tooltiptext = 0); @@ -94,7 +99,8 @@ public: bool modal = true, s32 flag = EMBF_OK, IGUIElement* parent=0, s32 id=-1); //! adds a scrollbar. The returned pointer must not be dropped. - virtual IGUIScrollBar* addScrollBar(bool horizontal, const core::rect& rectangle, IGUIElement* parent=0, s32 id=-1); + virtual IGUIScrollBar* addScrollBar(bool horizontal, const core::rect& rectangle, + IGUIElement* parent=0, s32 id=-1); //! Adds an image element. virtual IGUIImage* addImage(video::ITexture* image, core::position2d pos, @@ -111,6 +117,11 @@ public: virtual IGUIListBox* addListBox(const core::rect& rectangle, IGUIElement* parent=0, s32 id=-1, bool drawBackground=false); + //! adds a tree view + virtual IGUITreeView* addTreeView(const core::rect& rectangle, + IGUIElement* parent=0, s32 id=-1, bool drawBackground=false, + bool scrollBarVertical = true, bool scrollBarHorizontal = false); + //! adds an mesh viewer. The returned pointer must not be dropped. virtual IGUIMeshViewer* addMeshViewer(const core::rect& rectangle, IGUIElement* parent=0, s32 id=-1, const wchar_t* text=0); @@ -130,7 +141,7 @@ public: //! Adds a spin box to the environment virtual IGUISpinBox* addSpinBox(const wchar_t* text, const core::rect& rectangle, - IGUIElement* parent=0, s32 id=-1); + bool border=false,IGUIElement* parent=0, s32 id=-1); //! Adds a tab control to the environment. virtual IGUITabControl* addTabControl(const core::rect& rectangle, @@ -203,7 +214,7 @@ public: /** \param filename: Name of the file. \param start: The element to start saving from. if not specified, the root element will be used */ - virtual bool saveGUI(const c8* filename, IGUIElement* start=0); + virtual bool saveGUI( const core::string& filename, IGUIElement* start=0); //! Saves the current gui into a file. /** \param file: The file to save the GUI to. @@ -215,7 +226,7 @@ public: /** \param filename: Name of the file. \param parent: The parent of all loaded GUI elements, if not specified, the root element will be used */ - virtual bool loadGUI(const c8* filename, IGUIElement* parent=0); + virtual bool loadGUI(const c16* filename, IGUIElement* parent=0); //! Loads the gui. Note that the current gui is not cleared before. /** \param file: IReadFile to load the GUI from @@ -245,7 +256,7 @@ private: struct SFont { - core::stringc Filename; + core::string Filename; IGUIFont* Font; bool operator < (const SFont& other) const diff --git a/source/Irrlicht/CGUIFileOpenDialog.cpp b/source/Irrlicht/CGUIFileOpenDialog.cpp index 5b6a41d0..00d2039d 100644 --- a/source/Irrlicht/CGUIFileOpenDialog.cpp +++ b/source/Irrlicht/CGUIFileOpenDialog.cpp @@ -84,7 +84,7 @@ CGUIFileOpenDialog::CGUIFileOpenDialog(const wchar_t* title, FileBox->setAlignment(EGUIA_UPPERLEFT, EGUIA_LOWERRIGHT, EGUIA_UPPERLEFT, EGUIA_LOWERRIGHT); FileBox->grab(); - FileNameText = Environment->addStaticText(0, core::rect(10, 30, RelativeRect.getWidth()-90, 50), true, false, this); + FileNameText = Environment->addEditBox(0, core::rect(10, 30, RelativeRect.getWidth()-90, 50), true, this); FileNameText->setSubElement(true); FileNameText->setAlignment(EGUIA_UPPERLEFT, EGUIA_LOWERRIGHT, EGUIA_UPPERLEFT, EGUIA_UPPERLEFT); FileNameText->grab(); @@ -132,6 +132,13 @@ const wchar_t* CGUIFileOpenDialog::getFileName() const return FileName.c_str(); } +//! Returns the directory of the selected file. Returns NULL, if no directory was selected. +const core::string& CGUIFileOpenDialog::getDirectoryName() +{ + FileSystem->flatenFilename ( FileDirectory ); + return FileDirectory; +} + //! called if an event happened. bool CGUIFileOpenDialog::OnEvent(const SEvent& event) @@ -155,11 +162,18 @@ bool CGUIFileOpenDialog::OnEvent(const SEvent& event) return true; } else - if (event.GUIEvent.Caller == OKButton && FileName != L"") + if (event.GUIEvent.Caller == OKButton ) { - sendSelectedEvent(); - remove(); - return true; + if ( FileDirectory != L"" ) + { + sendSelectedEvent( EGET_DIRECTORY_SELECTED ); + } + if ( FileName != L"" ) + { + sendSelectedEvent( EGET_FILE_SELECTED ); + remove(); + return true; + } } break; @@ -169,9 +183,15 @@ bool CGUIFileOpenDialog::OnEvent(const SEvent& event) if (FileList && FileSystem) { if (FileList->isDirectory(selected)) + { FileName = L""; + FileDirectory = FileList->getFullFileName(selected); + } else + { + FileDirectory = L""; FileName = FileList->getFullFileName(selected); + } } } break; @@ -183,9 +203,10 @@ bool CGUIFileOpenDialog::OnEvent(const SEvent& event) { if (FileList->isDirectory(selected)) { + FileDirectory = FileList->getFullFileName(selected); FileSystem->changeWorkingDirectoryTo(FileList->getFileName(selected)); fillListBox(); - FileName = L""; + FileName = ""; } else { @@ -195,6 +216,18 @@ bool CGUIFileOpenDialog::OnEvent(const SEvent& event) } } break; + case EGET_EDITBOX_ENTER: + if (event.GUIEvent.Caller == FileNameText) + { + core::string dir( FileNameText->getText () ); + if ( FileSystem->changeWorkingDirectoryTo( dir ) ) + { + fillListBox(); + FileName = L""; + } + return true; + } + break; default: break; } @@ -214,6 +247,10 @@ bool CGUIFileOpenDialog::OnEvent(const SEvent& event) Dragging = false; return true; case EMIE_MOUSE_MOVED: + + if ( !event.MouseInput.isLeftPressed () ) + Dragging = false; + if (Dragging) { // gui window should not be dragged outside its parent @@ -297,19 +334,20 @@ void CGUIFileOpenDialog::fillListBox() if (FileNameText) { s = FileSystem->getWorkingDirectory(); + FileDirectory = s; FileNameText->setText(s.c_str()); } } //! sends the event that the file has been selected. -void CGUIFileOpenDialog::sendSelectedEvent() +void CGUIFileOpenDialog::sendSelectedEvent( EGUI_EVENT_TYPE type) { SEvent event; event.EventType = EET_GUI_EVENT; event.GUIEvent.Caller = this; event.GUIEvent.Element = 0; - event.GUIEvent.EventType = EGET_FILE_SELECTED; + event.GUIEvent.EventType = type; Parent->OnEvent(event); } diff --git a/source/Irrlicht/CGUIFileOpenDialog.h b/source/Irrlicht/CGUIFileOpenDialog.h index 43d7a9f2..27f314f2 100644 --- a/source/Irrlicht/CGUIFileOpenDialog.h +++ b/source/Irrlicht/CGUIFileOpenDialog.h @@ -11,6 +11,7 @@ #include "IGUIFileOpenDialog.h" #include "IGUIButton.h" #include "IGUIListBox.h" +#include "IGUIEditBox.h" #include "IFileSystem.h" namespace irr @@ -31,6 +32,9 @@ namespace gui //! returns the filename of the selected file. Returns NULL, if no file was selected. virtual const wchar_t* getFileName() const; + //! Returns the directory of the selected file. Returns NULL, if no directory was selected. + virtual const core::string& getDirectoryName(); + //! called if an event happened. virtual bool OnEvent(const SEvent& event); @@ -43,18 +47,20 @@ namespace gui void fillListBox(); //! sends the event that the file has been selected. - void sendSelectedEvent(); + void sendSelectedEvent( EGUI_EVENT_TYPE type ); //! sends the event that the file choose process has been canceld void sendCancelEvent(); core::position2d DragStart; core::stringw FileName; + core::string FileDirectory; + IGUIButton* CloseButton; IGUIButton* OKButton; IGUIButton* CancelButton; IGUIListBox* FileBox; - IGUIElement* FileNameText; + IGUIEditBox* FileNameText; IGUIElement* EventParent; io::IFileSystem* FileSystem; io::IFileList* FileList; diff --git a/source/Irrlicht/CGUIFont.cpp b/source/Irrlicht/CGUIFont.cpp index 650c862c..4016df19 100644 --- a/source/Irrlicht/CGUIFont.cpp +++ b/source/Irrlicht/CGUIFont.cpp @@ -19,7 +19,7 @@ namespace gui { //! constructor -CGUIFont::CGUIFont(IGUIEnvironment *env, const c8* filename) +CGUIFont::CGUIFont(IGUIEnvironment *env, const core::string& filename) : Driver(0), SpriteBank(0), Environment(env), WrongCharacter(0), MaxHeight(0), GlobalKerningWidth(0), GlobalKerningHeight(0) { @@ -39,6 +39,8 @@ CGUIFont::CGUIFont(IGUIEnvironment *env, const c8* filename) if (Driver) Driver->grab(); + + setInvisibleCharacters ( L" " ); } @@ -78,7 +80,7 @@ bool CGUIFont::load(io::IXMLReader* xml) Driver->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, false); // load texture - SpriteBank->setTexture(i, Driver->getTexture(fn.c_str())); + SpriteBank->setTexture(i, Driver->getTexture(fn)); // set previous mip-map+filter state Driver->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, mipmap); @@ -216,7 +218,7 @@ bool CGUIFont::load(io::IReadFile* file) //! loads a font file, native file needed, for texture parsing -bool CGUIFont::load(const c8* filename) +bool CGUIFont::load(const core::string& filename) { if (!Driver) return false; @@ -226,7 +228,7 @@ bool CGUIFont::load(const c8* filename) //! load & prepare font from ITexture -bool CGUIFont::loadTexture(video::IImage* image, const c8* name) +bool CGUIFont::loadTexture(video::IImage* image, const core::string& name) { if (!image) return false; @@ -265,7 +267,12 @@ bool CGUIFont::loadTexture(video::IImage* image, const c8* name) if ( ret ) { + bool current = Driver->getTextureCreationFlag ( video::ETCF_ALLOW_NON_POWER_2 ); + Driver->setTextureCreationFlag(video::ETCF_ALLOW_NON_POWER_2, true); + SpriteBank->addTexture(Driver->addTexture(name, tmpImage)); + + Driver->setTextureCreationFlag(video::ETCF_ALLOW_NON_POWER_2, current ); } if (deleteTmpImage) tmpImage->drop(); @@ -438,46 +445,6 @@ void CGUIFont::readPositions16bit(video::IImage* image, s32& lowerRightPositions } -//! returns the dimension of text -core::dimension2d CGUIFont::getDimension(const wchar_t* text) const -{ - core::dimension2d dim(0, 0); - core::dimension2d thisLine(0, MaxHeight); - - for (const wchar_t* p = text; *p; ++p) - { - bool lineBreak=false; - if (*p == L'\r') // Mac or Windows breaks - { - lineBreak = true; - if (p[1] == L'\n') // Windows breaks - ++p; - } - else if (*p == L'\n') // Unix breaks - { - lineBreak = true; - } - if (lineBreak) - { - dim.Height += thisLine.Height; - if (dim.Width < thisLine.Width) - dim.Width = thisLine.Width; - thisLine.Width = 0; - continue; - } - - const SFontArea &area = Areas[getAreaFromCharacter(*p)]; - - thisLine.Width += area.underhang; - thisLine.Width += area.width + area.overhang + GlobalKerningWidth; - } - - dim.Height += thisLine.Height; - if (dim.Width < thisLine.Width) - dim.Width = thisLine.Width; - - return dim; -} //! set an Pixel Offset on Drawing ( scale position on width ) @@ -536,81 +503,117 @@ s32 CGUIFont::getAreaFromCharacter(const wchar_t c) const return WrongCharacter; } - -/* -//! draws an text and clips it to the specified rectangle if wanted -void CGUIFont::draw(const wchar_t* text, const core::rect& position, video::SColor color, bool hcenter, bool vcenter, const core::rect* clip) +void CGUIFont::setInvisibleCharacters( const wchar_t *s ) { - if (!Driver) - return; - - core::dimension2d textDimension; - core::position2d offset = position.UpperLeftCorner; - - if (hcenter || vcenter) - { - textDimension = getDimension(text); - - if (hcenter) - offset.X = ((position.getWidth() - textDimension.Width)>>1) + offset.X; - - if (vcenter) - offset.Y = ((position.getHeight() - textDimension.Height)>>1) + offset.Y; - } - - core::array indices; - indices.reallocate(core::stringw(text).size()); - u32 n; - while(*text) - { - n = (*text) - 32; - if ( n > Positions.size()) - n = WrongCharacter; - indices.push_back(n); - ++text; - } - Driver->draw2DImage(Texture, offset, Positions, indices, GlobalKerningWidth, clip, color, true); + Invisible = s; } -*/ +//! returns the dimension of text +core::dimension2d CGUIFont::getDimension(const wchar_t* text) const +{ + core::dimension2d dim(0, 0); + core::dimension2d thisLine(0, MaxHeight); + + for (const wchar_t* p = text; *p; ++p) + { + bool lineBreak=false; + if (*p == L'\r') // Mac or Windows breaks + { + lineBreak = true; + if (p[1] == L'\n') // Windows breaks + ++p; + } + else if (*p == L'\n') // Unix breaks + { + lineBreak = true; + } + if (lineBreak) + { + dim.Height += thisLine.Height; + if (dim.Width < thisLine.Width) + dim.Width = thisLine.Width; + thisLine.Width = 0; + continue; + } + + const SFontArea &area = Areas[getAreaFromCharacter(*p)]; + + thisLine.Width += area.underhang; + thisLine.Width += area.width + area.overhang + GlobalKerningWidth; + } + + dim.Height += thisLine.Height; + if (dim.Width < thisLine.Width) + dim.Width = thisLine.Width; + + return dim; +} + //! draws some text and clips it to the specified rectangle if wanted -void CGUIFont::draw(const wchar_t* text, const core::rect& position, video::SColor color, bool hcenter, bool vcenter, const core::rect* clip) +void CGUIFont::draw(const wchar_t* text, const core::rect& position, + video::SColor color, + bool hcenter, bool vcenter, const core::rect* clip + ) { if (!Driver) return; - core::dimension2d textDimension; + core::dimension2d textDimension; core::position2d offset = position.UpperLeftCorner; if (hcenter || vcenter || clip) textDimension = getDimension(text); if (hcenter) - offset.X = ((position.getWidth() - textDimension.Width)>>1) + offset.X; + offset.X += (position.getWidth() - textDimension.Width) >> 1; if (vcenter) - offset.Y = ((position.getHeight() - textDimension.Height)>>1) + offset.Y; + offset.Y += (position.getHeight() - textDimension.Height) >> 1; if (clip) { - core::rect clippedRect(offset, core::dimension2d(textDimension)); + core::rect clippedRect(offset, textDimension); clippedRect.clipAgainst(*clip); if (!clippedRect.isValid()) return; } - while(*text) + wchar_t c; + while( c = *text++) { - SFontArea& area = Areas[getAreaFromCharacter(*text)]; + bool lineBreak=false; + if ( c == L'\r') // Mac or Windows breaks + { + lineBreak = true; + if ( *text == L'\n') // Windows breaks + ++text; + } + else if ( c == L'\n') // Unix breaks + { + lineBreak = true; + } + + if (lineBreak) + { + offset.Y += MaxHeight; + offset.X = position.UpperLeftCorner.X; + + if ( hcenter ) + { + core::dimension2d lineDim = getDimension(text); + offset.X += (position.getWidth() - lineDim.Width) >> 1; + } + continue; + } + + SFontArea& area = Areas[getAreaFromCharacter(c)]; offset.X += area.underhang; - - SpriteBank->draw2DSprite(area.spriteno, offset, clip, color); - + if ( Invisible.findFirst ( c ) < 0 ) + SpriteBank->draw2DSprite(area.spriteno, offset, clip, color); offset.X += area.width + area.overhang + GlobalKerningWidth; - ++text; } } diff --git a/source/Irrlicht/CGUIFont.h b/source/Irrlicht/CGUIFont.h index cb6abf6a..018e8aee 100644 --- a/source/Irrlicht/CGUIFont.h +++ b/source/Irrlicht/CGUIFont.h @@ -34,13 +34,13 @@ class CGUIFont : public IGUIFontBitmap public: //! constructor - CGUIFont(IGUIEnvironment* env, const c8* filename); + CGUIFont(IGUIEnvironment* env, const core::string& filename); //! destructor virtual ~CGUIFont(); //! loads a font from a texture file - bool load(const c8* filename); + bool load(const core::string& filename); //! loads a font from a texture file bool load(io::IReadFile* file); @@ -76,6 +76,8 @@ public: //! returns the sprite number from a given character virtual u32 getSpriteNoFromChar(const wchar_t *c) const; + virtual void setInvisibleCharacters( const wchar_t *s ); + private: struct SFontArea @@ -88,7 +90,7 @@ private: }; //! load & prepare font from ITexture - bool loadTexture(video::IImage * image, const c8* name); + bool loadTexture(video::IImage * image, const core::string& name); void readPositions16bit(video::IImage* texture, s32& lowerRightPositions); void readPositions32bit(video::IImage* texture, s32& lowerRightPositions); @@ -104,6 +106,8 @@ private: u32 WrongCharacter; s32 MaxHeight; s32 GlobalKerningWidth, GlobalKerningHeight; + + core::stringw Invisible; }; } // end namespace gui diff --git a/source/Irrlicht/CGUIImageList.cpp b/source/Irrlicht/CGUIImageList.cpp new file mode 100644 index 00000000..b9de25be --- /dev/null +++ b/source/Irrlicht/CGUIImageList.cpp @@ -0,0 +1,94 @@ +// This file is part of the "Irrlicht Engine". +// written by Reinhard Ostermeier, reinhard@nospam.r-ostermeier.de +// modified by Thomas Alten + +#include "CGUIImageList.h" + + +namespace irr +{ +namespace gui +{ + +//! constructor +CGUIImageList::CGUIImageList( video::IVideoDriver* driver ) + : Driver( driver ), + Texture( 0 ), + ImageCount( 0 ), + ImageSize( 0, 0 ), + ImagesPerRow( 0 ), + UseAlphaChannel( false ) +{ + #ifdef _DEBUG + setDebugName( "CGUIImageList" ); + #endif + + if( Driver ) + { + Driver->grab(); + } +} + + + +//! destructor +CGUIImageList::~CGUIImageList() +{ + if( Driver ) + { + Driver->drop(); + } + + if( Texture ) + { + Texture->drop(); + } +} + + +//! Creates the image list from texture. +bool CGUIImageList::createImageList( video::ITexture* texture, + core::dimension2d imageSize, + bool useAlphaChannel + ) +{ + if( !texture ) + { + return false; + } + + Texture = texture; + Texture->grab(); + + ImageSize = imageSize; + + ImagesPerRow = Texture->getSize().Width / ImageSize.Width; + ImageCount = ImagesPerRow * Texture->getSize().Height / ImageSize.Height; + + UseAlphaChannel = useAlphaChannel; + + return true; +} + +//! Draws an image and clips it to the specified rectangle if wanted +void CGUIImageList::draw( s32 index, const core::position2d& destPos, + const core::rect* clip /*= 0*/ ) +{ + core::rect sourceRect; + + if( !Driver || index < 0 || index >= ImageCount ) + { + return; + } + + sourceRect.UpperLeftCorner.X = ( index % ImagesPerRow ) * ImageSize.Width; + sourceRect.UpperLeftCorner.Y = ( index / ImagesPerRow ) * ImageSize.Height; + sourceRect.LowerRightCorner.X = sourceRect.UpperLeftCorner.X + ImageSize.Width; + sourceRect.LowerRightCorner.Y = sourceRect.UpperLeftCorner.Y + ImageSize.Height; + + Driver->draw2DImage( Texture, destPos, sourceRect, clip, + video::SColor( 255, 255, 255, 255 ), UseAlphaChannel ); +} + +} // end namespace gui +} // end namespace irr diff --git a/source/Irrlicht/CGUIImageList.h b/source/Irrlicht/CGUIImageList.h new file mode 100644 index 00000000..5b079edd --- /dev/null +++ b/source/Irrlicht/CGUIImageList.h @@ -0,0 +1,68 @@ +// This file is part of the "Irrlicht Engine". +// written by Reinhard Ostermeier, reinhard@nospam.r-ostermeier.de + +#ifndef __C_GUI_IMAGE_LIST_H_INCLUDED__ +#define __C_GUI_IMAGE_LIST_H_INCLUDED__ + +#include "IGUIImageList.h" +#include "IVideoDriver.h" + +namespace irr +{ +namespace gui +{ + +class CGUIImageList : public IGUIImageList +{ +public: + + //! constructor + CGUIImageList( video::IVideoDriver* Driver ); + + //! destructor + virtual ~CGUIImageList(); + + //! Creates the image list from texture. + //! \param texture: The texture to use + //! \param imageSize: Size of a single image + //! \param useAlphaChannel: true if the alpha channel from the texture should be used + //! \return + //! true if the image list was created + bool createImageList( + video::ITexture* texture, + core::dimension2d imageSize, + bool useAlphaChannel ); + + //! Draws an image and clips it to the specified rectangle if wanted + //! \param index: Index of the image + //! \param destPos: Position of the image to draw + //! \param clip: Optional pointer to a rectalgle against which the text will be clipped. + //! If the pointer is null, no clipping will be done. + virtual void draw( s32 index, const core::position2d& destPos, + const core::rect* clip = 0 ); + + //! Returns the count of Images in the list. + //! \return Returns the count of Images in the list. + virtual s32 getImageCount() const + { return ImageCount; } + + //! Returns the size of the images in the list. + //! \return Returns the size of the images in the list. + virtual core::dimension2d getImageSize() const + { return ImageSize; } + +private: + + video::IVideoDriver* Driver; + video::ITexture* Texture; + s32 ImageCount; + core::dimension2d ImageSize; + s32 ImagesPerRow; + bool UseAlphaChannel; +}; + +} // end namespace gui +} // end namespace irr + +#endif + diff --git a/source/Irrlicht/CGUIListBox.cpp b/source/Irrlicht/CGUIListBox.cpp index 61132901..2d3779e9 100644 --- a/source/Irrlicht/CGUIListBox.cpp +++ b/source/Irrlicht/CGUIListBox.cpp @@ -23,7 +23,8 @@ namespace gui CGUIListBox::CGUIListBox(IGUIEnvironment* environment, IGUIElement* parent, s32 id, core::rect rectangle, bool clip, bool drawBack, bool moveOverSelect) -: IGUIListBox(environment, parent, id, rectangle), Selected(-1), ItemHeight(0), +: IGUIListBox(environment, parent, id, rectangle), Selected(-1), + ItemHeight(0),ItemHeightOverride(0), TotalItemHeight(0), ItemsIconWidth(0), Font(0), IconBank(0), ScrollBar(0), selectTime(0), LastKeyTime(0), Selecting(false), DrawBack(drawBack), MoveOverSelect(moveOverSelect), AutoScroll(true), HighlightWhenNotFocused(true) @@ -151,17 +152,22 @@ void CGUIListBox::recalculateItemHeight() Font->drop(); Font = skin->getFont(); - ItemHeight = 0; + if ( 0 == ItemHeightOverride ) + ItemHeight = 0; if (Font) { - ItemHeight = Font->getDimension(L"A").Height + 4; + if ( 0 == ItemHeightOverride ) + ItemHeight = Font->getDimension(L"A").Height + 4; + Font->grab(); } } TotalItemHeight = ItemHeight * Items.size(); ScrollBar->setMax(TotalItemHeight - AbsoluteRect.getHeight()); + ScrollBar->setSmallStep ( 1 ); + ScrollBar->setLargeStep ( ItemHeight ); if ( TotalItemHeight <= AbsoluteRect.getHeight() ) ScrollBar->setVisible(false); @@ -190,6 +196,21 @@ void CGUIListBox::setSelected(s32 id) recalculateScrollPos(); } +//! sets the selected item. Set this to -1 if no item should be selected +void CGUIListBox::setSelected(const wchar_t *item) +{ + s32 index = -1; + + if ( item ) + { + for ( index = 0; index < (s32) Items.size(); ++index ) + { + if ( Items[index].text == item ) + break; + } + } + setSelected ( index ); +} //! called if an event happened. bool CGUIListBox::OnEvent(const SEvent& event) @@ -855,6 +876,13 @@ video::SColor CGUIListBox::getItemDefaultColor(EGUI_LISTBOX_COLOR colorType) con } } +//! set global itemHeight +void CGUIListBox::setItemHeight( s32 height ) +{ + ItemHeight = height; + ItemHeightOverride = 1; +} + } // end namespace gui } // end namespace irr diff --git a/source/Irrlicht/CGUIListBox.h b/source/Irrlicht/CGUIListBox.h index 798e561d..0e8dc3f7 100644 --- a/source/Irrlicht/CGUIListBox.h +++ b/source/Irrlicht/CGUIListBox.h @@ -48,6 +48,9 @@ namespace gui //! sets the selected item. Set this to -1 if no item should be selected virtual void setSelected(s32 id); + //! sets the selected item. Set this to -1 if no item should be selected + virtual void setSelected(const wchar_t *item); + //! called if an event happened. virtual bool OnEvent(const SEvent& event); @@ -119,6 +122,9 @@ namespace gui //! Swap the items at the given indices virtual void swapItems(u32 index1, u32 index2); + //! set global itemHeight + virtual void setItemHeight( s32 height ); + private: struct ListItem @@ -152,6 +158,7 @@ namespace gui core::array< ListItem > Items; s32 Selected; s32 ItemHeight; + s32 ItemHeightOverride; s32 TotalItemHeight; s32 ItemsIconWidth; gui::IGUIFont* Font; diff --git a/source/Irrlicht/CGUIScrollBar.cpp b/source/Irrlicht/CGUIScrollBar.cpp index 09bee5b6..d7b7df22 100644 --- a/source/Irrlicht/CGUIScrollBar.cpp +++ b/source/Irrlicht/CGUIScrollBar.cpp @@ -26,7 +26,7 @@ CGUIScrollBar::CGUIScrollBar(bool horizontal, IGUIEnvironment* environment, : IGUIScrollBar(environment, parent, id, rectangle), UpButton(0), DownButton(0), Dragging(false), Horizontal(horizontal), DraggedBySlider(false), TrayClick(false), Pos(0), DrawPos(0), - DrawHeight(0), Max(100), SmallStep(10), LargeStep(50), DesiredPos(0), + DrawHeight(0), Min(0), Max(100), SmallStep(10), LargeStep(50), DesiredPos(0), LastChange(0) { #ifdef _DEBUG @@ -80,7 +80,7 @@ bool CGUIScrollBar::OnEvent(const SEvent& event) setPos(Pos+SmallStep); break; case KEY_HOME: - setPos(0); + setPos(Min); break; case KEY_PRIOR: setPos(Pos-LargeStep); @@ -134,12 +134,19 @@ bool CGUIScrollBar::OnEvent(const SEvent& event) } break; case EET_MOUSE_INPUT_EVENT: + { + const core::position2di p(event.MouseInput.X, event.MouseInput.Y); + bool isInside = isPointInside ( p ); switch(event.MouseInput.Event) { case EMIE_MOUSE_WHEEL: if (Environment->hasFocus(this)) - { // thanks to a bug report by REAPER - setPos(getPos() + (s32)event.MouseInput.Wheel* -SmallStep); + { + // thanks to a bug report by REAPER + setPos( getPos() + + ( (s32)event.MouseInput.Wheel * SmallStep * (Horizontal ? 1 : -1 ) ) + ); + SEvent newEvent; newEvent.EventType = EET_GUI_EVENT; newEvent.GUIEvent.Caller = this; @@ -151,39 +158,38 @@ bool CGUIScrollBar::OnEvent(const SEvent& event) break; case EMIE_LMOUSE_PRESSED_DOWN: { - if (AbsoluteClippingRect.isPointInside(core::position2di(event.MouseInput.X, event.MouseInput.Y))) + if (isInside) { Dragging = true; - DraggedBySlider = SliderRect.isPointInside(core::position2di(event.MouseInput.X, event.MouseInput.Y)); + DraggedBySlider = SliderRect.isPointInside(p); TrayClick = !DraggedBySlider; - DesiredPos = getPosFromMousePos(event.MouseInput.X, event.MouseInput.Y); + DesiredPos = getPosFromMousePos(p); + Environment->setFocus ( this ); return true; } break; } case EMIE_LMOUSE_LEFT_UP: case EMIE_MOUSE_MOVED: - if (Dragging) + { + if ( !event.MouseInput.isLeftPressed () ) + Dragging = false; + + if ( !Dragging ) + return isInside; + + if ( event.MouseInput.Event == EMIE_LMOUSE_LEFT_UP ) + Dragging = false; + + const s32 newPos = getPosFromMousePos(p); + const s32 oldPos = Pos; + + if (!DraggedBySlider) { - if (event.MouseInput.Event == EMIE_LMOUSE_LEFT_UP) - Dragging = false; - - const s32 newPos = getPosFromMousePos(event.MouseInput.X, event.MouseInput.Y); - const s32 oldPos = Pos; - - if (!DraggedBySlider) + if ( isInside ) { - if (AbsoluteClippingRect.isPointInside(core::position2di(event.MouseInput.X, event.MouseInput.Y))) - { - DraggedBySlider = SliderRect.isPointInside(core::position2di(event.MouseInput.X, event.MouseInput.Y)); - TrayClick = !DraggedBySlider; - } - else - { - TrayClick = false; - if (event.MouseInput.Event == EMIE_MOUSE_MOVED) - return true; - } + DraggedBySlider = SliderRect.isPointInside(p); + TrayClick = !DraggedBySlider; } if (DraggedBySlider) @@ -192,25 +198,37 @@ bool CGUIScrollBar::OnEvent(const SEvent& event) } else { - DesiredPos = newPos; + TrayClick = false; + if (event.MouseInput.Event == EMIE_MOUSE_MOVED) + return isInside; } - - if (Pos != oldPos && Parent) - { - SEvent newEvent; - newEvent.EventType = EET_GUI_EVENT; - newEvent.GUIEvent.Caller = this; - newEvent.GUIEvent.Element = 0; - newEvent.GUIEvent.EventType = EGET_SCROLL_BAR_CHANGED; - Parent->OnEvent(newEvent); - } - return true; } - break; + + if (DraggedBySlider) + { + setPos(newPos); + } + else + { + DesiredPos = newPos; + } + + if (Pos != oldPos && Parent) + { + SEvent newEvent; + newEvent.EventType = EET_GUI_EVENT; + newEvent.GUIEvent.Caller = this; + newEvent.GUIEvent.Element = 0; + newEvent.GUIEvent.EventType = EGET_SCROLL_BAR_CHANGED; + Parent->OnEvent(newEvent); + } + return isInside; + } break; + default: break; } - break; + } break; default: break; } @@ -219,22 +237,11 @@ bool CGUIScrollBar::OnEvent(const SEvent& event) return IGUIElement::OnEvent(event); } - -//! draws the element and its children -void CGUIScrollBar::draw() +void CGUIScrollBar::OnPostRender(u32 timeMs) { - if (!IsVisible) - return; - - IGUISkin* skin = Environment->getSkin(); - if (!skin) - return; - - u32 now = os::Timer::getRealTime(); - - if (Dragging && !DraggedBySlider && TrayClick && now > LastChange + 200) + if (Dragging && !DraggedBySlider && TrayClick && timeMs > LastChange + 200) { - LastChange = now; + LastChange = timeMs; const s32 oldPos = Pos; @@ -258,12 +265,25 @@ void CGUIScrollBar::draw() } } +} + +//! draws the element and its children +void CGUIScrollBar::draw() +{ + if (!IsVisible) + return; + + IGUISkin* skin = Environment->getSkin(); + if (!skin) + return; + + SliderRect = AbsoluteRect; // draws the background skin->draw2DRectangle(this, skin->getColor(EGDC_SCROLLBAR), SliderRect, &AbsoluteClippingRect); - if (Max!=0) + if ( core::isnotzero ( range() ) ) { // recalculate slider rectangle if (Horizontal) @@ -290,66 +310,46 @@ void CGUIScrollBar::updateAbsolutePosition() IGUIElement::updateAbsolutePosition(); // todo: properly resize refreshControls(); - - if (Horizontal) - { - const f32 f = (RelativeRect.getWidth() - ((f32)RelativeRect.getHeight()*3.0f)) / (f32)Max; - DrawPos = (s32)((Pos * f) + ((f32)RelativeRect.getHeight() * 0.5f)); - DrawHeight = RelativeRect.getHeight(); - } - else - { - f32 f = 0.0f; - if (Max != 0) - f = (RelativeRect.getHeight() - ((f32)RelativeRect.getWidth()*3.0f)) / (f32)Max; - - DrawPos = (s32)((Pos * f) + ((f32)RelativeRect.getWidth() * 0.5f)); - DrawHeight = RelativeRect.getWidth(); - } + setPos ( Pos ); } -s32 CGUIScrollBar::getPosFromMousePos(s32 x, s32 y) const +//! +s32 CGUIScrollBar::getPosFromMousePos(const core::position2di &pos) const { + f32 w, p; if (Horizontal) { - const f32 w = RelativeRect.getWidth() - f32(RelativeRect.getHeight())*3.0f; - const f32 p = x - AbsoluteRect.UpperLeftCorner.X - RelativeRect.getHeight()*1.5f; - return s32( p/w * f32(Max) ); + w = RelativeRect.getWidth() - f32(RelativeRect.getHeight())*3.0f; + p = pos.X - AbsoluteRect.UpperLeftCorner.X - RelativeRect.getHeight()*1.5f; } else { - const f32 h = RelativeRect.getHeight() - f32(RelativeRect.getWidth())*3.0f; - const f32 p = y - AbsoluteRect.UpperLeftCorner.Y - RelativeRect.getWidth()*1.5f; - return s32( p/h * f32(Max) ); + w = RelativeRect.getHeight() - f32(RelativeRect.getWidth())*3.0f; + p = pos.Y - AbsoluteRect.UpperLeftCorner.Y - RelativeRect.getWidth()*1.5f; } + return (s32) ( p/w * range() ) + Min; } //! sets the position of the scrollbar void CGUIScrollBar::setPos(s32 pos) { - if (pos < 0) - Pos = 0; - else if (pos > Max) - Pos = Max; - else - Pos = pos; + Pos = core::s32_clamp ( pos, Min, Max ); if (Horizontal) { - const f32 f = (RelativeRect.getWidth() - ((f32)RelativeRect.getHeight()*3.0f)) / (f32)Max; - DrawPos = (s32)((Pos * f) + ((f32)RelativeRect.getHeight() * 0.5f)); + f32 f = (RelativeRect.getWidth() - ((f32)RelativeRect.getHeight()*3.0f)) / range(); + DrawPos = (s32)( ( ( Pos - Min ) * f) + ((f32)RelativeRect.getHeight() * 0.5f)); DrawHeight = RelativeRect.getHeight(); } else { - f32 f = 0.0f; - if (Max != 0) - f = (RelativeRect.getHeight() - ((f32)RelativeRect.getWidth()*3.0f)) / (f32)Max; + f32 f = (RelativeRect.getHeight() - ((f32)RelativeRect.getWidth()*3.0f)) / range(); - DrawPos = (s32)((Pos * f) + ((f32)RelativeRect.getWidth() * 0.5f)); + DrawPos = (s32)( ( ( Pos - Min ) * f) + ((f32)RelativeRect.getWidth() * 0.5f)); DrawHeight = RelativeRect.getWidth(); } + } @@ -397,12 +397,27 @@ s32 CGUIScrollBar::getMax() const //! sets the maximum value of the scrollbar. void CGUIScrollBar::setMax(s32 max) { - if (max > 0) - Max = max; - else - Max = 0; + Max = core::max_ ( max, Min ); - bool enable = (Max != 0); + bool enable = core::isnotzero ( range() ); + UpButton->setEnabled(enable); + DownButton->setEnabled(enable); + setPos(Pos); +} + +//! gets the maximum value of the scrollbar. +s32 CGUIScrollBar::getMin() const +{ + return Min; +} + + +//! sets the minimum value of the scrollbar. +void CGUIScrollBar::setMin(s32 min) +{ + Min = core::min_ ( min, Max ); + + bool enable = core::isnotzero ( range() ); UpButton->setEnabled(enable); DownButton->setEnabled(enable); setPos(Pos); @@ -504,7 +519,8 @@ void CGUIScrollBar::serializeAttributes(io::IAttributes* out, io::SAttributeRead out->addBool("Horizontal", Horizontal); out->addInt ("Value", Pos); - out->addInt ("Max", Max); + out->addInt ("Min", Min); + out->addInt ("Max", Max); out->addInt ("SmallStep", SmallStep); out->addInt ("LargeStep", LargeStep); } @@ -516,6 +532,7 @@ void CGUIScrollBar::deserializeAttributes(io::IAttributes* in, io::SAttributeRea IGUIScrollBar::deserializeAttributes(in,options); Horizontal = in->getAttributeAsBool("Horizontal"); + setMin(in->getAttributeAsInt("Min")); setMax(in->getAttributeAsInt("Max")); setPos(in->getAttributeAsInt("Value")); setSmallStep(in->getAttributeAsInt("SmallStep")); diff --git a/source/Irrlicht/CGUIScrollBar.h b/source/Irrlicht/CGUIScrollBar.h index 258e273c..6077e981 100644 --- a/source/Irrlicht/CGUIScrollBar.h +++ b/source/Irrlicht/CGUIScrollBar.h @@ -34,12 +34,21 @@ namespace gui //! draws the element and its children virtual void draw(); + virtual void OnPostRender(u32 timeMs); + + //! gets the maximum value of the scrollbar. virtual s32 getMax() const; //! sets the maximum value of the scrollbar. virtual void setMax(s32 max); + //! gets the minimum value of the scrollbar. + virtual s32 getMin() const; + + //! sets the minimum value of the scrollbar. + virtual void setMin(s32 max); + //! gets the small step value virtual s32 getSmallStep() const; @@ -70,7 +79,7 @@ namespace gui private: void refreshControls(); - s32 getPosFromMousePos(s32 x, s32 y) const; + s32 getPosFromMousePos(const core::position2di &p) const; IGUIButton* UpButton; IGUIButton* DownButton; @@ -84,11 +93,14 @@ namespace gui s32 Pos; s32 DrawPos; s32 DrawHeight; + s32 Min; s32 Max; s32 SmallStep; s32 LargeStep; s32 DesiredPos; u32 LastChange; + + f32 range () const { return (f32) ( Max - Min ); } }; } // end namespace gui diff --git a/source/Irrlicht/CGUISpinBox.cpp b/source/Irrlicht/CGUISpinBox.cpp index 1aeeadc0..74a5998d 100644 --- a/source/Irrlicht/CGUISpinBox.cpp +++ b/source/Irrlicht/CGUISpinBox.cpp @@ -19,7 +19,7 @@ namespace gui { //! constructor -CGUISpinBox::CGUISpinBox(const wchar_t* text, IGUIEnvironment* environment, +CGUISpinBox::CGUISpinBox(const wchar_t* text, bool border,IGUIEnvironment* environment, IGUIElement* parent, s32 id, const core::rect& rectangle) : IGUISpinBox(environment, parent, id, rectangle), EditBox(0), ButtonSpinUp(0), ButtonSpinDown(0), StepSize(1.f), @@ -66,7 +66,7 @@ CGUISpinBox::CGUISpinBox(const wchar_t* text, IGUIEnvironment* environment, } const core::rect rectEdit(0, 0, rectangle.getWidth() - ButtonWidth - 1, rectangle.getHeight()); - EditBox = Environment->addEditBox(text, rectEdit, true, this, -1); + EditBox = Environment->addEditBox(text, rectEdit, border, this, -1); EditBox->grab(); EditBox->setSubElement(true); EditBox->setAlignment(EGUIA_UPPERLEFT, EGUIA_LOWERRIGHT, EGUIA_UPPERLEFT, EGUIA_LOWERRIGHT); @@ -166,6 +166,19 @@ bool CGUISpinBox::OnEvent(const SEvent& event) bool changeEvent = false; switch(event.EventType) { + case EET_MOUSE_INPUT_EVENT: + switch(event.MouseInput.Event) + { + case EMIE_MOUSE_WHEEL: + { + f32 val = getValue() + (StepSize * event.MouseInput.Wheel); + setValue(val); + changeEvent = true; + } + break; + } + break; + case EET_GUI_EVENT: if (event.GUIEvent.EventType == EGET_BUTTON_CLICKED) { diff --git a/source/Irrlicht/CGUISpinBox.h b/source/Irrlicht/CGUISpinBox.h index 559ff530..c2e328ef 100644 --- a/source/Irrlicht/CGUISpinBox.h +++ b/source/Irrlicht/CGUISpinBox.h @@ -22,7 +22,7 @@ namespace gui public: //! constructor - CGUISpinBox(const wchar_t* text, IGUIEnvironment* environment, + CGUISpinBox(const wchar_t* text, bool border, IGUIEnvironment* environment, IGUIElement* parent, s32 id, const core::rect& rectangle); //! destructor diff --git a/source/Irrlicht/CGUISpriteBank.cpp b/source/Irrlicht/CGUISpriteBank.cpp index 06ffbc53..fca57d00 100644 --- a/source/Irrlicht/CGUISpriteBank.cpp +++ b/source/Irrlicht/CGUISpriteBank.cpp @@ -77,7 +77,7 @@ void CGUISpriteBank::addTexture(video::ITexture* texture) void CGUISpriteBank::setTexture(u32 index, video::ITexture* texture) { - while (index > Textures.size()) + while (index >= Textures.size()) Textures.push_back(0); if (Textures[index]) @@ -95,7 +95,7 @@ void CGUISpriteBank::draw2DSprite(u32 index, const core::position2di& pos, const core::rect* clip, const video::SColor& color, u32 starttime, u32 currenttime, bool loop, bool center) { - if (Sprites[index].Frames.empty() || index >= Sprites.size()) + if (index >= Sprites.size() || Sprites[index].Frames.empty() ) return; // work out frame number diff --git a/source/Irrlicht/CGUIStaticText.cpp b/source/Irrlicht/CGUIStaticText.cpp index 6a4d6240..e0f52a1b 100644 --- a/source/Irrlicht/CGUIStaticText.cpp +++ b/source/Irrlicht/CGUIStaticText.cpp @@ -274,17 +274,17 @@ void CGUIStaticText::breakText() if (c == L'\r') // Mac or Windows breaks { lineBreak = true; - c = ' '; if (Text[i+1] == L'\n') // Windows breaks { Text.erase(i+1); --size; } + c = '\0'; } else if (c == L'\n') // Unix breaks { lineBreak = true; - c = ' '; + c = '\0'; } if (c == L' ' || c == 0 || i == (size-1)) diff --git a/source/Irrlicht/CGUITable.cpp b/source/Irrlicht/CGUITable.cpp index f98d9244..e213142a 100644 --- a/source/Irrlicht/CGUITable.cpp +++ b/source/Irrlicht/CGUITable.cpp @@ -246,10 +246,12 @@ bool CGUITable::hasResizableColumns() const } -void CGUITable::addRow(u32 rowIndex) +u32 CGUITable::addRow(u32 rowIndex) { if ( rowIndex > Rows.size() ) - return; + { + rowIndex = Rows.size(); + } Row row; @@ -265,6 +267,7 @@ void CGUITable::addRow(u32 rowIndex) } recalculateHeights(); + return rowIndex; } @@ -283,7 +286,7 @@ void CGUITable::removeRow(u32 rowIndex) //! adds an list item, returns id of item -void CGUITable::setCellText(u32 rowIndex, u32 columnIndex, const wchar_t* text) +void CGUITable::setCellText(u32 rowIndex, u32 columnIndex, const core::stringw& text) { if ( rowIndex < Rows.size() && columnIndex < Columns.size() ) { @@ -296,8 +299,7 @@ void CGUITable::setCellText(u32 rowIndex, u32 columnIndex, const wchar_t* text) } } - -void CGUITable::setCellText(u32 rowIndex, u32 columnIndex, const wchar_t* text, video::SColor color) +void CGUITable::setCellText(u32 rowIndex, u32 columnIndex, const core::stringw& text, video::SColor color) { if ( rowIndex < Rows.size() && columnIndex < Columns.size() ) { @@ -687,7 +689,7 @@ bool CGUITable::dragColumnStart(s32 xpos, s32 ypos) if ( ypos > ( AbsoluteRect.UpperLeftCorner.Y + ItemHeight ) ) return false; - const s32 CLICK_AREA = 3; // to left and right of line which can be dragged + const s32 CLICK_AREA = 12; // to left and right of line which can be dragged s32 pos = AbsoluteRect.UpperLeftCorner.X+1; if ( HorizontalScrollBar && HorizontalScrollBar->isVisible() ) diff --git a/source/Irrlicht/CGUITable.h b/source/Irrlicht/CGUITable.h index 67684411..bb2d91d9 100644 --- a/source/Irrlicht/CGUITable.h +++ b/source/Irrlicht/CGUITable.h @@ -83,7 +83,7 @@ namespace gui than the actual number of rows by more than one, it won't be created. Note that if you create a row that is not at the end, there might be performance issues*/ - virtual void addRow(u32 rowIndex); + virtual u32 addRow(u32 rowIndex); //! Remove a row from the table virtual void removeRow(u32 rowIndex); @@ -104,10 +104,10 @@ namespace gui //! Set the text of a cell - virtual void setCellText(u32 rowIndex, u32 columnIndex, const wchar_t* text); + virtual void setCellText(u32 rowIndex, u32 columnIndex, const core::stringw& text); //! Set the text of a cell, and set a color of this cell. - virtual void setCellText(u32 rowIndex, u32 columnIndex, const wchar_t* text, video::SColor color); + virtual void setCellText(u32 rowIndex, u32 columnIndex, const core::stringw& text, video::SColor color); //! Set the data of a cell //! data will not be serialized. diff --git a/source/Irrlicht/CGUITreeView.cpp b/source/Irrlicht/CGUITreeView.cpp new file mode 100644 index 00000000..648b967c --- /dev/null +++ b/source/Irrlicht/CGUITreeView.cpp @@ -0,0 +1,1082 @@ +// This file is part of the "Irrlicht Engine". +// written by Reinhard Ostermeier, reinhard@nospam.r-ostermeier.de +// expaned by burningwater + +#include "CGUITreeView.h" +#include "IGUISkin.h" +#include "IGUIEnvironment.h" +#include "IVideoDriver.h" +#include "IGUIFont.h" +#include "CGUIScrollBar.h" +#include "os.h" + +namespace irr +{ +namespace gui +{ + +CGUITreeViewNode::CGUITreeViewNode( CGUITreeView* owner, CGUITreeViewNode* parent ) + : Owner( owner ), + Parent( parent ), + ImageIndex( -1 ), + SelectedImageIndex( -1 ), + Data( 0 ), + Data2( 0 ), + Expanded( false ) +{ +#ifdef _DEBUG + setDebugName( "CGUITreeView" ); +#endif +} + +CGUITreeViewNode::~CGUITreeViewNode() +{ + if( Owner && this == Owner->getSelected() ) + { + setSelected( false ); + } + + clearChilds(); + + if( Data2 ) + { + Data2->drop(); + } +} + +IGUITreeView* CGUITreeViewNode::getOwner() const +{ + return Owner; +} + +IGUITreeViewNode* CGUITreeViewNode::getParent() const +{ + return Parent; +} + +void CGUITreeViewNode::setText( const wchar_t* text ) +{ + Text = text; +} + +void CGUITreeViewNode::setIcon( const wchar_t* icon ) +{ + Icon = icon; +} + +void CGUITreeViewNode::clearChilds() +{ + core::list::Iterator it; + + for( it = Childs.begin(); it != Childs.end(); it++ ) + { + ( *it )->drop(); + } + Childs.clear(); +} + +IGUITreeViewNode* CGUITreeViewNode::addChildBack( + const wchar_t* text, + const wchar_t* icon /*= 0*/, + s32 imageIndex /*= -1*/, + s32 selectedImageIndex /*= -1*/, + void* data /*= 0*/, + IReferenceCounted* data2 /*= 0*/ ) +{ + CGUITreeViewNode* newChild = new CGUITreeViewNode( Owner, this ); + + Childs.push_back( newChild ); + newChild->Text = text; + newChild->Icon = icon; + newChild->ImageIndex = imageIndex; + newChild->SelectedImageIndex = selectedImageIndex; + newChild->Data = data; + newChild->Data2 = data2; + if( data2 ) + { + data2->grab(); + } + return newChild; +} + +IGUITreeViewNode* CGUITreeViewNode::addChildFront( + const wchar_t* text, + const wchar_t* icon /*= 0*/, + s32 imageIndex /*= -1*/, + s32 selectedImageIndex /*= -1*/, + void* data /*= 0*/, + IReferenceCounted* data2 /*= 0*/ ) +{ + CGUITreeViewNode* newChild = new CGUITreeViewNode( Owner, this ); + + Childs.push_front( newChild ); + newChild->Text = text; + newChild->Icon = icon; + newChild->ImageIndex = imageIndex; + newChild->SelectedImageIndex = selectedImageIndex; + newChild->Data = data; + newChild->Data2 = data2; + if( data2 ) + { + data2->grab(); + } + return newChild; +} + +IGUITreeViewNode* CGUITreeViewNode::insertChildAfter( + IGUITreeViewNode* other, + const wchar_t* text, + const wchar_t* icon /*= 0*/, + s32 imageIndex /*= -1*/, + s32 selectedImageIndex /*= -1*/, + void* data /*= 0*/, + IReferenceCounted* data2/* = 0*/ ) +{ + core::list::Iterator itOther; + CGUITreeViewNode* newChild = 0; + + for( itOther = Childs.begin(); itOther != Childs.end(); itOther++ ) + { + if( other == *itOther ) + { + newChild = new CGUITreeViewNode( Owner, this ); + newChild->Text = text; + newChild->Icon = icon; + newChild->ImageIndex = imageIndex; + newChild->SelectedImageIndex = selectedImageIndex; + newChild->Data = data; + newChild->Data2 = data2; + if( data2 ) + { + data2->grab(); + } + Childs.insert_after( itOther, newChild ); + break; + } + } + return newChild; +} + +IGUITreeViewNode* CGUITreeViewNode::insertChildBefore( + IGUITreeViewNode* other, + const wchar_t* text, + const wchar_t* icon /*= 0*/, + s32 imageIndex /*= -1*/, + s32 selectedImageIndex /*= -1*/, + void* data /*= 0*/, + IReferenceCounted* data2/* = 0*/ ) +{ + core::list::Iterator itOther; + CGUITreeViewNode* newChild = 0; + + for( itOther = Childs.begin(); itOther != Childs.end(); itOther++ ) + { + if( other == *itOther ) + { + newChild = new CGUITreeViewNode( Owner, this ); + newChild->Text = text; + newChild->Icon = icon; + newChild->ImageIndex = imageIndex; + newChild->SelectedImageIndex = selectedImageIndex; + newChild->Data = data; + newChild->Data2 = data2; + if( data2 ) + { + data2->grab(); + } + Childs.insert_before( itOther, newChild ); + break; + } + } + return newChild; +} + +IGUITreeViewNode* CGUITreeViewNode::getFirstChild() const +{ + if( Childs.empty() ) + { + return 0; + } + else + { + return *( Childs.begin() ); + } +} + +IGUITreeViewNode* CGUITreeViewNode::getLastChild() const +{ + if( Childs.empty() ) + { + return 0; + } + else + { + return *( Childs.getLast() ); + } +} + +IGUITreeViewNode* CGUITreeViewNode::getPrevSibling() const +{ + core::list::Iterator itThis; + core::list::Iterator itOther; + CGUITreeViewNode* other = 0; + + if( Parent ) + { + for( itThis = Parent->Childs.begin(); itThis != Parent->Childs.end(); itThis++ ) + { + if( this == *itThis ) + { + if( itThis != Parent->Childs.begin() ) + { + other = *itOther; + } + break; + } + itOther = itThis; + } + } + return other; +} + +IGUITreeViewNode* CGUITreeViewNode::getNextSibling() const +{ + core::list::Iterator itThis; + CGUITreeViewNode* other = 0; + + if( Parent ) + { + for( itThis = Parent->Childs.begin(); itThis != Parent->Childs.end(); itThis++ ) + { + if( this == *itThis ) + { + if( itThis != Parent->Childs.getLast() ) + { + other = *( ++itThis ); + } + break; + } + } + } + return other; +} + +IGUITreeViewNode* CGUITreeViewNode::getNextVisible() const +{ + IGUITreeViewNode* next = 0; + IGUITreeViewNode* node = 0; + + node = const_cast( this ); + + if( node->getExpanded() && node->hasChilds() ) + { + next = node->getFirstChild(); + } + else + { + next = node->getNextSibling(); + } + while( !next && node->getParent() ) + { + next = node->getParent()->getNextSibling(); + if( !next ) + { + node = node->getParent(); + } + } + + return next; +} + +bool CGUITreeViewNode::deleteChild( IGUITreeViewNode* child ) +{ + core::list::Iterator itChild; + bool deleted = false; + + for( itChild = Childs.begin(); itChild != Childs.end(); itChild++ ) + { + if( child == *itChild ) + { + child->drop(); + Childs.erase( itChild ); + deleted = true; + break; + } + } + return deleted; +} + +bool CGUITreeViewNode::moveChildUp( IGUITreeViewNode* child ) +{ + core::list::Iterator itChild; + core::list::Iterator itOther; + CGUITreeViewNode* nodeTmp; + bool moved = false; + + for( itChild = Childs.begin(); itChild != Childs.end(); itChild++ ) + { + if( child == *itChild ) + { + if( itChild != Childs.begin() ) + { + nodeTmp = *itChild; + *itChild = *itOther; + *itOther = nodeTmp; + moved = true; + } + break; + } + itOther = itChild; + } + return moved; +} + +bool CGUITreeViewNode::moveChildDown( IGUITreeViewNode* child ) +{ + core::list::Iterator itChild; + core::list::Iterator itOther; + CGUITreeViewNode* nodeTmp; + bool moved = false; + + for( itChild = Childs.begin(); itChild != Childs.end(); itChild++ ) + { + if( child == *itChild ) + { + if( itChild != Childs.getLast() ) + { + itOther = itChild; + ++itOther; + nodeTmp = *itChild; + *itChild = *itOther; + *itOther = nodeTmp; + moved = true; + } + break; + } + } + return moved; +} + +void CGUITreeViewNode::setExpanded( bool expanded ) +{ + Expanded = expanded; +} + +void CGUITreeViewNode::setSelected( bool selected ) +{ + if( Owner ) + { + if( selected ) + { + Owner->Selected = this; + } + else + { + if( Owner->Selected == this ) + { + Owner->Selected = 0; + } + } + } +} + +bool CGUITreeViewNode::getSelected() const +{ + if( Owner ) + { + return Owner->Selected == this; + } + else + { + return false; + } +} + +bool CGUITreeViewNode::isRoot() const +{ + return ( Owner && ( this == Owner->Root ) ); +} + +s32 CGUITreeViewNode::getLevel() const +{ + if( Parent ) + { + return Parent->getLevel() + 1; + } + else + { + return 0; + } +} + +bool CGUITreeViewNode::isVisible() const +{ + if( Parent ) + { + return Parent->getExpanded() && Parent->isVisible(); + } + else + { + return true; + } +} + + +//! constructor +CGUITreeView::CGUITreeView(IGUIEnvironment* environment, IGUIElement* parent, + s32 id, core::rect rectangle, bool clip, + bool drawBack,bool scrollBarVertical, bool scrollBarHorizontal) + : IGUITreeView( environment, parent, id, rectangle ), + Selected( 0 ), + ScrollBarH( 0 ), + ScrollBarV( 0 ), + LinesVisible( true ), + ItemHeight( 0 ), + IndentWidth( 0 ), + TotalItemHeight( 0 ), + TotalItemWidth ( 0 ), + Selecting( false ), + Font( 0 ), + IconFont( 0 ), + ImageList( 0 ), + ImageLeftOfIcon( true ), + LastEventNode( 0 ), + Clip( clip ), + DrawBack( drawBack ) +{ +#ifdef _DEBUG + setDebugName( "CGUITreeView" ); +#endif + + IGUISkin* skin = Environment->getSkin(); + s32 s = skin->getSize( EGDS_SCROLLBAR_SIZE ); + + if ( scrollBarVertical ) + { + ScrollBarV = new CGUIScrollBar( false, Environment, this, 0, + core::rect( RelativeRect.getWidth() - s, + 0, + RelativeRect.getWidth(), + RelativeRect.getHeight() - (scrollBarHorizontal ? s : 0 ) + ), + !clip ); + ScrollBarV->drop(); + + ScrollBarV->setPos( 0 ); + ScrollBarV->grab(); + } + + if ( scrollBarHorizontal ) + { + ScrollBarH = new CGUIScrollBar( true, Environment, this, 1, + core::rect( 0, RelativeRect.getHeight() - s, RelativeRect.getWidth() - s, RelativeRect.getHeight() ), + !clip ); + ScrollBarH->drop(); + + ScrollBarH->setPos( 0 ); + ScrollBarH->grab(); + } + + Root = new CGUITreeViewNode( this, 0 ); + Root->Expanded = true; + + recalculateItemHeight(); +} + + +//! destructor +CGUITreeView::~CGUITreeView() +{ + if( ScrollBarV ) + { + ScrollBarV->drop(); + } + + if( ScrollBarH ) + { + ScrollBarH->drop(); + } + + if( Font ) + { + Font->drop(); + } + + if( IconFont ) + { + IconFont->drop(); + } + + if( ImageList ) + { + ImageList->drop(); + } + + if( Root ) + { + Root->drop(); + } +} + +void CGUITreeView::recalculateItemHeight() +{ + IGUISkin* skin = Environment->getSkin(); + IGUITreeViewNode* node; + + if( Font != skin->getFont() ) + { + if( Font ) + { + Font->drop(); + } + + Font = skin->getFont(); + ItemHeight = 0; + + if( Font ) + { + ItemHeight = Font->getDimension( L"A" ).Height + 4; + Font->grab(); + } + + if( IconFont ) + { + s32 height = IconFont->getDimension( L" " ).Height; + if( height > ItemHeight ) + { + ItemHeight = height; + } + } + if( ImageList ) + { + if( ImageList->getImageSize().Height + 1 > ItemHeight ) + { + ItemHeight = ImageList->getImageSize().Height + 1; + } + } + } + + IndentWidth = ItemHeight; + if( IndentWidth < 9 ) + { + IndentWidth = 9; + } + else if( IndentWidth > 15 ) + { + IndentWidth = 15; + } + else + { + if( ( ( IndentWidth >> 1 ) << 1 ) - IndentWidth == 0 ) + { + --IndentWidth; + } + } + + TotalItemHeight = 0; + TotalItemWidth = AbsoluteRect.getWidth() * 2; + node = Root->getFirstChild(); + while( node ) + { + TotalItemHeight += ItemHeight; + node = node->getNextVisible(); + } + + if ( ScrollBarV ) + ScrollBarV->setMax( TotalItemHeight - AbsoluteRect.getHeight() ); + + if ( ScrollBarH ) + ScrollBarH->setMax( TotalItemWidth - AbsoluteRect.getWidth() ); + +} + +//! called if an event happened. +bool CGUITreeView::OnEvent( const SEvent &event ) +{ + switch( event.EventType ) + { + case EET_GUI_EVENT: + switch( event.GUIEvent.EventType ) + { + case gui::EGET_SCROLL_BAR_CHANGED: + if( event.GUIEvent.Caller == ScrollBarV || event.GUIEvent.Caller == ScrollBarH ) + { + //s32 pos = ( ( gui::IGUIScrollBar* )event.GUIEvent.Caller )->getPos(); + return true; + } + break; + case gui::EGET_ELEMENT_FOCUS_LOST: + { + Selecting = false; + return false; + } + break; + } + break; + case EET_MOUSE_INPUT_EVENT: + { + core::position2d p( event.MouseInput.X, event.MouseInput.Y ); + + switch( event.MouseInput.Event ) + { + case EMIE_MOUSE_WHEEL: + if ( ScrollBarV ) + ScrollBarV->setPos( ScrollBarV->getPos() + (s32)event.MouseInput.Wheel * -10 ); + return true; + break; + + case EMIE_LMOUSE_PRESSED_DOWN: + + if (Environment->hasFocus(this) && !AbsoluteClippingRect.isPointInside(p) ) + { + Environment->removeFocus(this); + return false; + } + + if( Environment->hasFocus( this ) && + ( ( ScrollBarV && ScrollBarV->getAbsolutePosition().isPointInside( p ) && ScrollBarV->OnEvent( event ) ) || + ( ScrollBarH && ScrollBarH->getAbsolutePosition().isPointInside( p ) && ScrollBarH->OnEvent( event ) ) + ) + ) + { + return true; + } + + Selecting = true; + Environment->setFocus( this ); + return true; + break; + + case EMIE_LMOUSE_LEFT_UP: + if( Environment->hasFocus( this ) && + ( ( ScrollBarV && ScrollBarV->getAbsolutePosition().isPointInside( p ) && ScrollBarV->OnEvent( event ) ) || + ( ScrollBarH && ScrollBarH->getAbsolutePosition().isPointInside( p ) && ScrollBarH->OnEvent( event ) ) + ) + ) + { + return true; + } + + Selecting = false; + Environment->removeFocus( this ); + mouseAction( event.MouseInput.X, event.MouseInput.Y ); + return true; + break; + + case EMIE_MOUSE_MOVED: + if( Selecting ) + { + if( getAbsolutePosition().isPointInside( p ) ) + { + mouseAction( event.MouseInput.X, event.MouseInput.Y, true ); + return true; + } + } + } + } + break; + } + + + return Parent ? Parent->OnEvent( event ) : false; +} + +/*! +*/ +void CGUITreeView::mouseAction( s32 xpos, s32 ypos, bool onlyHover /*= false*/ ) +{ + IGUITreeViewNode* oldSelected = Selected; + IGUITreeViewNode* hitNode = 0; + s32 selIdx; + s32 n; + IGUITreeViewNode* node; + SEvent event; + + event.EventType = EET_GUI_EVENT; + event.GUIEvent.Caller = this; + + xpos -= AbsoluteRect.UpperLeftCorner.X; + ypos -= AbsoluteRect.UpperLeftCorner.Y; + + // find new selected item. + if( ItemHeight != 0 && ScrollBarV ) + { + selIdx = ( ( ypos - 1 ) + ScrollBarV->getPos() ) / ItemHeight; + } + + hitNode = 0; + node = Root->getFirstChild(); + n = 0; + while( node ) + { + if( selIdx == n ) + { + hitNode = node; + break; + } + node = node->getNextVisible(); + ++n; + } + + if( hitNode && xpos > hitNode->getLevel() * IndentWidth ) + { + Selected = hitNode; + } + + if( hitNode && !onlyHover + && xpos < hitNode->getLevel() * IndentWidth + && xpos > ( hitNode->getLevel() - 1 ) * IndentWidth + && hitNode->hasChilds() ) + { + hitNode->setExpanded( !hitNode->getExpanded() ); + + // post expand/collaps news + if( hitNode->getExpanded() ) + { + event.GUIEvent.EventType = EGET_TREEVIEW_NODE_EXPAND; + } + else + { + event.GUIEvent.EventType = EGET_TREEVIEW_NODE_COLLAPS; + } + LastEventNode = hitNode; + Parent->OnEvent( event ); + LastEventNode = 0; + } + + if( Selected && !Selected->isVisible() ) + { + Selected = 0; + } + + // post selection news + + if( Parent && !onlyHover && Selected != oldSelected ) + { + if( oldSelected ) + { + event.GUIEvent.EventType = EGET_TREEVIEW_NODE_DESELECT; + LastEventNode = oldSelected; + Parent->OnEvent( event ); + LastEventNode = 0; + } + if( Selected ) + { + event.GUIEvent.EventType = EGET_TREEVIEW_NODE_SELECT; + LastEventNode = Selected; + Parent->OnEvent( event ); + LastEventNode = 0; + } + } +} + + +//! draws the element and its children +void CGUITreeView::draw() +{ + if( !IsVisible ) + { + return; + } + + recalculateItemHeight(); // if the font changed + + IGUISkin* skin = Environment->getSkin(); + irr::video::IVideoDriver* driver = Environment->getVideoDriver(); + + core::rect* clipRect = 0; + if( Clip ) + { + clipRect = &AbsoluteClippingRect; + } + + // draw background + core::rect frameRect( AbsoluteRect ); + + if( DrawBack ) + { + driver->draw2DRectangle( skin->getColor( EGDC_3D_HIGH_LIGHT ), frameRect, + clipRect ); + } + + // draw the border + frameRect.LowerRightCorner.Y = frameRect.UpperLeftCorner.Y + 1; + driver->draw2DRectangle( skin->getColor( EGDC_3D_SHADOW ), frameRect, + clipRect ); + + frameRect.LowerRightCorner.Y = AbsoluteRect.LowerRightCorner.Y; + frameRect.LowerRightCorner.X = frameRect.UpperLeftCorner.X + 1; + driver->draw2DRectangle( skin->getColor( EGDC_3D_SHADOW ), frameRect, + clipRect ); + + frameRect = AbsoluteRect; + frameRect.UpperLeftCorner.X = frameRect.LowerRightCorner.X - 1; + driver->draw2DRectangle( skin->getColor( EGDC_3D_HIGH_LIGHT ), frameRect, + clipRect ); + + frameRect = AbsoluteRect; + frameRect.UpperLeftCorner.Y = AbsoluteRect.LowerRightCorner.Y - 1; + frameRect.LowerRightCorner.Y = AbsoluteRect.LowerRightCorner.Y; + driver->draw2DRectangle( skin->getColor( EGDC_3D_HIGH_LIGHT ), frameRect, + clipRect ); + + + // draw items + + core::rect clientClip( AbsoluteRect ); + clientClip.UpperLeftCorner.Y += 1; + clientClip.UpperLeftCorner.X += 1; + clientClip.LowerRightCorner.X = AbsoluteRect.LowerRightCorner.X; + clientClip.LowerRightCorner.Y -= 1; + + if ( ScrollBarV ) + clientClip.LowerRightCorner.X -= skin->getSize( EGDS_SCROLLBAR_SIZE ); + if ( ScrollBarH ) + clientClip.LowerRightCorner.Y -= skin->getSize( EGDS_SCROLLBAR_SIZE ); + + if( clipRect ) + { + clientClip.clipAgainst( *clipRect ); + } + + frameRect = AbsoluteRect; + frameRect.LowerRightCorner.X = AbsoluteRect.LowerRightCorner.X - skin->getSize( EGDS_SCROLLBAR_SIZE ); + frameRect.LowerRightCorner.Y = AbsoluteRect.UpperLeftCorner.Y + ItemHeight; + + if ( ScrollBarV ) + { + frameRect.UpperLeftCorner.Y -= ScrollBarV->getPos(); + frameRect.LowerRightCorner.Y -= ScrollBarV->getPos(); + } + + if ( ScrollBarH ) + { + frameRect.UpperLeftCorner.X -= ScrollBarH->getPos(); + frameRect.LowerRightCorner.X -= ScrollBarH->getPos(); + } + + IGUITreeViewNode* node = Root->getFirstChild(); + while( node ) + { + frameRect.UpperLeftCorner.X = AbsoluteRect.UpperLeftCorner.X + 1 + node->getLevel() * IndentWidth; + + if( frameRect.LowerRightCorner.Y >= AbsoluteRect.UpperLeftCorner.Y + && frameRect.UpperLeftCorner.Y <= AbsoluteRect.LowerRightCorner.Y ) + { + if( node == Selected ) + { + driver->draw2DRectangle( skin->getColor( EGDC_HIGH_LIGHT ), frameRect, &clientClip ); + } + + if( node->hasChilds() ) + { + core::rect rc; + core::rect expanderRect; + + expanderRect.UpperLeftCorner.X = frameRect.UpperLeftCorner.X - IndentWidth + 2; + expanderRect.UpperLeftCorner.Y = frameRect.UpperLeftCorner.Y + ( ( frameRect.getHeight() - ( IndentWidth - 4 ) ) >> 1 ); + expanderRect.LowerRightCorner.X = expanderRect.UpperLeftCorner.X + IndentWidth - 4; + expanderRect.LowerRightCorner.Y = expanderRect.UpperLeftCorner.Y + IndentWidth - 4; + + // box upper line + rc.UpperLeftCorner.X = expanderRect.UpperLeftCorner.X; + rc.UpperLeftCorner.Y = expanderRect.UpperLeftCorner.Y; + rc.LowerRightCorner.X = expanderRect.LowerRightCorner.X; + rc.LowerRightCorner.Y = rc.UpperLeftCorner.Y + 1; + driver->draw2DRectangle( skin->getColor( EGDC_3D_SHADOW ), rc, + clipRect ); + + // box left line + rc.UpperLeftCorner.X = expanderRect.UpperLeftCorner.X; + rc.UpperLeftCorner.Y = expanderRect.UpperLeftCorner.Y; + rc.LowerRightCorner.X = rc.UpperLeftCorner.X + 1; + rc.LowerRightCorner.Y = expanderRect.LowerRightCorner.Y; + driver->draw2DRectangle( skin->getColor( EGDC_3D_SHADOW ), rc, + clipRect ); + + // box right line + rc.UpperLeftCorner.X = expanderRect.LowerRightCorner.X - 1; + rc.UpperLeftCorner.Y = expanderRect.UpperLeftCorner.Y; + rc.LowerRightCorner.X = rc.UpperLeftCorner.X + 1; + rc.LowerRightCorner.Y = expanderRect.LowerRightCorner.Y; + driver->draw2DRectangle( skin->getColor( EGDC_3D_SHADOW ), rc, + clipRect ); + + // box bottom line + rc.UpperLeftCorner.X = expanderRect.UpperLeftCorner.X; + rc.UpperLeftCorner.Y = expanderRect.LowerRightCorner.Y - 1; + rc.LowerRightCorner.X = expanderRect.LowerRightCorner.X; + rc.LowerRightCorner.Y = rc.UpperLeftCorner.Y + 1; + driver->draw2DRectangle( skin->getColor( EGDC_3D_SHADOW ), rc, + clipRect ); + + // horizontal '-' line + rc.UpperLeftCorner.X = expanderRect.UpperLeftCorner.X + 2; + rc.UpperLeftCorner.Y = expanderRect.UpperLeftCorner.Y + ( expanderRect.getHeight() >> 1 ); + rc.LowerRightCorner.X = rc.UpperLeftCorner.X + expanderRect.getWidth() - 4; + rc.LowerRightCorner.Y = rc.UpperLeftCorner.Y + 1; + driver->draw2DRectangle( skin->getColor( EGDC_BUTTON_TEXT ), rc, + clipRect ); + + if( !node->getExpanded() ) + { + // vertical '+' line + rc.UpperLeftCorner.X = expanderRect.UpperLeftCorner.X + ( expanderRect.getWidth() >> 1 ); + rc.UpperLeftCorner.Y = expanderRect.UpperLeftCorner.Y + 2; + rc.LowerRightCorner.X = rc.UpperLeftCorner.X + 1; + rc.LowerRightCorner.Y = rc.UpperLeftCorner.Y + expanderRect.getHeight() - 4; + driver->draw2DRectangle( skin->getColor( EGDC_BUTTON_TEXT ), rc, + clipRect ); + } + } + + core::rect textRect = frameRect; + + if( Font ) + { + s32 iconWidth = 0; + for( s32 n = 0; n < 2; ++n ) + { + s32 index = node->getImageIndex(); + if( ( ImageList && index >= 0 ) + && ( ( ImageLeftOfIcon && n == 0 ) + || ( !ImageLeftOfIcon && n == 1 ) ) ) + { + index = node->getSelectedImageIndex(); + if( node != Selected || index < 0 ) + { + index = node->getImageIndex(); + } + ImageList->draw( + index, + core::position2d( + textRect.UpperLeftCorner.X, + textRect.UpperLeftCorner.Y + ( ( textRect.getHeight() - ImageList->getImageSize().Height ) >> 1 ) ), + &clientClip ); + iconWidth += ImageList->getImageSize().Width + 3; + textRect.UpperLeftCorner.X += ImageList->getImageSize().Width + 3; + } + else if( ( IconFont && reinterpret_cast( node )->Icon.size() ) + && ( ( ImageLeftOfIcon && n == 1 ) + || ( !ImageLeftOfIcon && n == 0 ) ) ) + { + IconFont->draw( node->getIcon(), textRect, skin->getColor( ( node == Selected ) ? EGDC_HIGH_LIGHT_TEXT : EGDC_BUTTON_TEXT ), false, true, &clientClip ); + iconWidth += IconFont->getDimension( node->getIcon() ).Width + 3; + textRect.UpperLeftCorner.X += IconFont->getDimension( node->getIcon() ).Width + 3; + } + } + + Font->draw( node->getText(), textRect, skin->getColor( ( node == Selected ) ? EGDC_HIGH_LIGHT_TEXT : EGDC_BUTTON_TEXT ), false, true, &clientClip ); + + textRect.UpperLeftCorner.X -= iconWidth; + } + + // draw the lines if neccessary + if( LinesVisible ) + { + core::rect rc; + + // horizontal line + rc.UpperLeftCorner.X = frameRect.UpperLeftCorner.X - IndentWidth - ( IndentWidth >> 1 ) - 1; + rc.UpperLeftCorner.Y = frameRect.UpperLeftCorner.Y + ( ( frameRect.getHeight() ) >> 1 ); + if( node->hasChilds() ) + { + rc.LowerRightCorner.X = frameRect.UpperLeftCorner.X - IndentWidth; + } + else + { + rc.LowerRightCorner.X = frameRect.UpperLeftCorner.X - 2; + } + rc.LowerRightCorner.Y = rc.UpperLeftCorner.Y + 1; + driver->draw2DRectangle( skin->getColor( EGDC_3D_SHADOW ), rc, + clipRect ); + + if( node->getParent() != Root ) + { + // vertical line + if( node == node->getParent()->getFirstChild() ) + { + rc.UpperLeftCorner.Y = frameRect.UpperLeftCorner.Y - ( ( frameRect.getHeight() - IndentWidth ) >> 1 ); + } + else + { + rc.UpperLeftCorner.Y = frameRect.UpperLeftCorner.Y - ( frameRect.getHeight() >> 1 ); + } + rc.LowerRightCorner.X = rc.UpperLeftCorner.X + 1; + driver->draw2DRectangle( skin->getColor( EGDC_3D_SHADOW ), rc, + clipRect ); + + // the vertical lines of all parents + IGUITreeViewNode* nodeTmp = node->getParent(); + rc.UpperLeftCorner.Y = frameRect.UpperLeftCorner.Y - ( frameRect.getHeight() >> 1 ); + for( s32 n = 0; n < node->getLevel() - 2; ++n ) + { + rc.UpperLeftCorner.X -= IndentWidth; + rc.LowerRightCorner.X -= IndentWidth; + if( nodeTmp != nodeTmp->getParent()->getLastChild() ) + { + driver->draw2DRectangle( skin->getColor( EGDC_3D_SHADOW ), rc, + clipRect ); + } + nodeTmp = nodeTmp->getParent(); + } + } + } + } + + frameRect.UpperLeftCorner.Y += ItemHeight; + frameRect.LowerRightCorner.Y += ItemHeight; + + node = node->getNextVisible(); + } + + IGUIElement::draw(); +} + +//! Sets the font which should be used as icon font. This font is set to the Irrlicht engine +//! built-in-font by default. Icons can be displayed in front of every list item. +//! An icon is a string, displayed with the icon font. When using the build-in-font of the +//! Irrlicht engine as icon font, the icon strings defined in GUIIcons.h can be used. +void CGUITreeView::setIconFont( IGUIFont* font ) +{ + s32 height; + + if( IconFont ) + { + IconFont->drop(); + } + + IconFont = font; + if( IconFont ) + { + height = IconFont->getDimension( L" " ).Height; + if( height > ItemHeight ) + { + ItemHeight = height; + } + IconFont->grab(); + } +} + +//! Sets the image list which should be used for the image and selected image of every node. +//! The default is 0 (no images). +void CGUITreeView::setImageList( IGUIImageList* imageList ) +{ + if( ImageList ) + { + ImageList->drop(); + } + + ImageList = imageList; + if( ImageList ) + { + if( ImageList->getImageSize().Height + 1 > ItemHeight ) + { + ItemHeight = ImageList->getImageSize().Height + 1; + } + ImageList->grab(); + } +} + +} // end namespace gui +} // end namespace irr diff --git a/source/Irrlicht/CGUITreeView.h b/source/Irrlicht/CGUITreeView.h new file mode 100644 index 00000000..35d9bc34 --- /dev/null +++ b/source/Irrlicht/CGUITreeView.h @@ -0,0 +1,331 @@ +// This file is part of the "Irrlicht Engine". +// written by Reinhard Ostermeier, reinhard@nospam.r-ostermeier.de + +#ifndef __C_GUI_TREE_VIEW_H_INCLUDED__ +#define __C_GUI_TREE_VIEW_H_INCLUDED__ + +#include "IGUITreeView.h" +#include "irrList.h" + + +namespace irr +{ +namespace gui +{ + // forward declarations + class IGUIFont; + class IGUIScrollBar; + class CGUITreeView; + + //! Node for gui tree view + class CGUITreeViewNode : public IGUITreeViewNode + { + friend class CGUITreeView; + + public: + //! constructor + CGUITreeViewNode( CGUITreeView* owner, CGUITreeViewNode* parent ); + + //! destructor + ~CGUITreeViewNode(); + + //! returns the owner (tree view) of this node + virtual IGUITreeView* getOwner() const; + + //! Returns the parent node of this node. + virtual IGUITreeViewNode* getParent() const; + + //! returns the text of the node + virtual const wchar_t* getText() const + { return Text.c_str(); } + + //! sets the text of the node + virtual void setText( const wchar_t* text ); + + //! returns the icon text of the node + virtual const wchar_t* getIcon() const + { return Icon.c_str(); } + + //! sets the icon text of the node + virtual void setIcon( const wchar_t* icon ); + + //! returns the image index of the node + virtual u32 getImageIndex() const + { return ImageIndex; } + + //! sets the image index of the node + virtual void setImageIndex( u32 imageIndex ) + { ImageIndex = imageIndex; } + + //! returns the image index of the node + virtual u32 getSelectedImageIndex() const + { return SelectedImageIndex; } + + //! sets the image index of the node + virtual void setSelectedImageIndex( u32 imageIndex ) + { SelectedImageIndex = imageIndex; } + + //! returns the user data (void*) of this node + virtual void* getData() const + { return Data; } + + //! sets the user data (void*) of this node + virtual void setData( void* data ) + { Data = data; } + + //! returns the user data2 (IReferenceCounted) of this node + virtual IReferenceCounted* getData2() const + { return Data2; } + + //! sets the user data2 (IReferenceCounted) of this node + virtual void setData2( IReferenceCounted* data ) + { + if( Data2 ) + { + Data2->drop(); + } + Data2 = data; + if( Data2 ) + { + Data2->grab(); + } + } + + //! returns the child item count + virtual u32 getChildCount() const + { return Childs.getSize(); } + + //! removes all childs (recursive) from this node + virtual void clearChilds(); + + //! returns true if this node has child nodes + virtual bool hasChilds() const + { return !Childs.empty(); } + + //! Adds a new node behind the last child node. + //! \param text text of the new node + //! \param icon icon text of the new node + //! \param imageIndex index of the image for the new node (-1 = none) + //! \param selectedImageIndex index of the selected image for the new node (-1 = same as imageIndex) + //! \param data user data (void*) of the new node + //! \param data2 user data2 (IReferenceCounted*) of the new node + //! \return + //! returns the new node + virtual IGUITreeViewNode* addChildBack( + const wchar_t* text, + const wchar_t* icon = 0, + s32 imageIndex = -1, + s32 selectedImageIndex = -1, + void* data = 0, + IReferenceCounted* data2 = 0 ); + + //! Adds a new node before the first child node. + //! \param text text of the new node + //! \param icon icon text of the new node + //! \param imageIndex index of the image for the new node (-1 = none) + //! \param selectedImageIndex index of the selected image for the new node (-1 = same as imageIndex) + //! \param data user data (void*) of the new node + //! \param data2 user data2 (IReferenceCounted*) of the new node + //! \return + //! returns the new node + virtual IGUITreeViewNode* addChildFront( + const wchar_t* text, + const wchar_t* icon = 0, + s32 imageIndex = -1, + s32 selectedImageIndex = -1, + void* data = 0, + IReferenceCounted* data2 = 0 ); + + //! Adds a new node behind the other node. + //! The other node has also te be a child node from this node. + //! \param text text of the new node + //! \param icon icon text of the new node + //! \param imageIndex index of the image for the new node (-1 = none) + //! \param selectedImageIndex index of the selected image for the new node (-1 = same as imageIndex) + //! \param data user data (void*) of the new node + //! \param data2 user data2 (IReferenceCounted*) of the new node + //! \return + //! returns the new node or 0 if other is no child node from this + virtual IGUITreeViewNode* insertChildAfter( + IGUITreeViewNode* other, + const wchar_t* text, + const wchar_t* icon = 0, + s32 imageIndex = -1, + s32 selectedImageIndex = -1, + void* data = 0, + IReferenceCounted* data2 = 0 ); + + //! Adds a new node before the other node. + //! The other node has also te be a child node from this node. + //! \param text text of the new node + //! \param icon icon text of the new node + //! \param imageIndex index of the image for the new node (-1 = none) + //! \param selectedImageIndex index of the selected image for the new node (-1 = same as imageIndex) + //! \param data user data (void*) of the new node + //! \param data2 user data2 (IReferenceCounted*) of the new node + //! \return + //! returns the new node or 0 if other is no child node from this + virtual IGUITreeViewNode* insertChildBefore( + IGUITreeViewNode* other, + const wchar_t* text, + const wchar_t* icon = 0, + s32 imageIndex = -1, + s32 selectedImageIndex = -1, + void* data = 0, + IReferenceCounted* data2 = 0 ); + + //! Return the first child note from this node. + virtual IGUITreeViewNode* getFirstChild() const; + + //! Return the last child note from this node. + virtual IGUITreeViewNode* getLastChild() const; + + //! Returns the preverse sibling node from this node. + virtual IGUITreeViewNode* getPrevSibling() const; + + //! Returns the next sibling node from this node. + virtual IGUITreeViewNode* getNextSibling() const; + + //! Returns the next visible (expanded, may be out of scrolling) node from this node. + virtual IGUITreeViewNode* getNextVisible() const; + + //! Deletes a child node. + virtual bool deleteChild( IGUITreeViewNode* child ); + + //! Moves a child node one position up. + virtual bool moveChildUp( IGUITreeViewNode* child ); + + //! Moves a child node one position down. + virtual bool moveChildDown( IGUITreeViewNode* child ); + + //! Returns true if the node is expanded (childs are visible). + virtual bool getExpanded() const + { return Expanded; } + + //! Sets if the node is expanded. + virtual void setExpanded( bool expanded ); + + //! Returns true if the node is currently selected. + virtual bool getSelected() const; + + //! Sets this node as selected. + virtual void setSelected( bool selected ); + + //! Returns true if this node is the root node. + virtual bool isRoot() const; + + //! Returns the level of this node. + virtual s32 getLevel() const; + + //! Returns true if this node is visible (all parents are expanded). + virtual bool isVisible() const; + + private: + + CGUITreeView* Owner; + CGUITreeViewNode* Parent; + core::stringw Text; + core::stringw Icon; + s32 ImageIndex; + s32 SelectedImageIndex; + void* Data; + IReferenceCounted* Data2; + bool Expanded; + core::list Childs; + }; + + + //! Default tree view GUI element. + class CGUITreeView : public IGUITreeView + { + friend class CGUITreeViewNode; + + public: + //! constructor + CGUITreeView( IGUIEnvironment* environment, IGUIElement* parent, + s32 id, core::rect rectangle, bool clip = true, + bool drawBack = false, bool scrollBarVertical = true, bool scrollBarHorizontal = true ); + + //! destructor + virtual ~CGUITreeView(); + + //! returns the root node (not visible) from the tree. + virtual IGUITreeViewNode* getRoot() const + { return Root; } + + //! returns the selected node of the tree or 0 if none is selected + virtual IGUITreeViewNode* getSelected() const + { return Selected; } + + //! returns true if the tree lines are visible + virtual bool getLinesVisible() const + { return LinesVisible; } + + //! sets if the tree lines are visible + virtual void setLinesVisible( bool visible ) + { LinesVisible = visible; } + + //! called if an event happened. + virtual bool OnEvent( const SEvent &event ); + + //! draws the element and its children + virtual void draw(); + + //! Sets the font which should be used as icon font. This font is set to the Irrlicht engine + //! built-in-font by default. Icons can be displayed in front of every list item. + //! An icon is a string, displayed with the icon font. When using the build-in-font of the + //! Irrlicht engine as icon font, the icon strings defined in GUIIcons.h can be used. + virtual void setIconFont( IGUIFont* font ); + + //! Sets the image list which should be used for the image and selected image of every node. + //! The default is 0 (no images). + virtual void setImageList( IGUIImageList* imageList ); + + //! Returns the image list which is used for the nodes. + virtual IGUIImageList* getImageList() const + { return ImageList; } + + //! Sets if the image is left of the icon. Default is true. + virtual void setImageLeftOfIcon( bool bLeftOf ) + { ImageLeftOfIcon = bLeftOf; } + + //! Returns if the Image is left of the icon. Default is true. + virtual bool getImageLeftOfIcon() const + { return ImageLeftOfIcon; } + + //! Returns the node which is associated to the last event. + virtual IGUITreeViewNode* getLastEventNode() const + { return LastEventNode; } + + private: + //! calculates the heigth of an node and of all visible nodes. + void recalculateItemHeight(); + + //! executes an mouse action (like selectNew of CGUIListBox) + void mouseAction( s32 xpos, s32 ypos, bool onlyHover = false ); + + CGUITreeViewNode* Root; + IGUITreeViewNode* Selected; + bool LinesVisible; + s32 ItemHeight; + s32 IndentWidth; + s32 TotalItemHeight; + s32 TotalItemWidth; + IGUIFont* Font; + IGUIFont* IconFont; + bool Selecting; + IGUIScrollBar* ScrollBarH; + IGUIScrollBar* ScrollBarV; + bool Clip; + bool DrawBack; + IGUIImageList* ImageList; + bool ImageLeftOfIcon; + IGUITreeViewNode* LastEventNode; + }; + + +} // end namespace gui +} // end namespace irr + +#endif + diff --git a/source/Irrlicht/CGUIWindow.cpp b/source/Irrlicht/CGUIWindow.cpp index ae6a6106..4e3a49ed 100644 --- a/source/Irrlicht/CGUIWindow.cpp +++ b/source/Irrlicht/CGUIWindow.cpp @@ -168,6 +168,9 @@ bool CGUIWindow::OnEvent(const SEvent& event) Dragging = false; return true; case EMIE_MOUSE_MOVED: + if ( !event.MouseInput.isLeftPressed () ) + Dragging = false; + if (Dragging) { // gui window should not be dragged outside its parent @@ -206,27 +209,29 @@ void CGUIWindow::updateAbsolutePosition() //! draws the element and its children void CGUIWindow::draw() { - if (!IsVisible) - return; - - IGUISkin* skin = Environment->getSkin(); - - core::rect rect = AbsoluteRect; - core::rect *cl = &AbsoluteClippingRect; - - // draw body fast - rect = skin->draw3DWindowBackground(this, true, skin->getColor(EGDC_ACTIVE_BORDER), - AbsoluteRect, &AbsoluteClippingRect); - - if (Text.size()) + if ( IsVisible ) { - rect.UpperLeftCorner.X += skin->getSize(EGDS_TEXT_DISTANCE_X); - rect.UpperLeftCorner.Y += skin->getSize(EGDS_TEXT_DISTANCE_Y); - rect.LowerRightCorner.X -= skin->getSize(EGDS_WINDOW_BUTTON_WIDTH) + 5; + IGUISkin* skin = Environment->getSkin(); - IGUIFont* font = skin->getFont(EGDF_WINDOW); - if (font) - font->draw(Text.c_str(), rect, skin->getColor(EGDC_ACTIVE_CAPTION), false, true, cl); + core::rect rect = AbsoluteRect; + + // draw body fast + rect = skin->draw3DWindowBackground(this, true, skin->getColor(EGDC_ACTIVE_BORDER), + AbsoluteRect, &AbsoluteClippingRect); + + if (Text.size()) + { + rect.UpperLeftCorner.X += skin->getSize(EGDS_TEXT_DISTANCE_X); + rect.UpperLeftCorner.Y += skin->getSize(EGDS_TEXT_DISTANCE_Y); + rect.LowerRightCorner.X -= skin->getSize(EGDS_WINDOW_BUTTON_WIDTH) + 5; + + IGUIFont* font = skin->getFont(EGDF_WINDOW); + if (font) + { + font->draw(Text.c_str(), rect, + skin->getColor(EGDC_ACTIVE_CAPTION), false, true, &AbsoluteClippingRect); + } + } } IGUIElement::draw(); diff --git a/source/Irrlicht/CImage.cpp b/source/Irrlicht/CImage.cpp index eb971649..a4851ac3 100644 --- a/source/Irrlicht/CImage.cpp +++ b/source/Irrlicht/CImage.cpp @@ -1,865 +1,936 @@ -// Copyright (C) 2002-2009 Nikolaus Gebhardt / Thomas Alten -// This file is part of the "Irrlicht Engine". -// For conditions of distribution and use, see copyright notice in irrlicht.h +// Copyright (C) 2002-2009 Nikolaus Gebhardt / Thomas Alten +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#include "CImage.h" +#include "irrString.h" +#include "SoftwareDriver2_helper.h" +#include "CColorConverter.h" + +namespace irr +{ + + struct SBlitJob + { + AbsRectangle Dest; + AbsRectangle Source; + + u32 argb; + + void * src; + void * dst; + + s32 width; + s32 height; + + u32 srcPitch; + u32 dstPitch; + + u32 srcPixelMul; + u32 dstPixelMul; + }; + + // Blitter Operation + enum eBlitter + { + BLITTER_INVALID = 0, + BLITTER_COLOR, + BLITTER_COLOR_ALPHA, + BLITTER_TEXTURE, + BLITTER_TEXTURE_ALPHA_BLEND, + BLITTER_TEXTURE_ALPHA_COLOR_BLEND + }; + + typedef void (*tExecuteBlit) ( const SBlitJob * job ); + + + // Bitfields Cohen Sutherland + enum eClipCode + { + CLIPCODE_EMPTY = 0, + CLIPCODE_BOTTOM = 1, + CLIPCODE_TOP = 2, + CLIPCODE_LEFT = 4, + CLIPCODE_RIGHT = 8 + }; + +inline u32 GetClipCode( const AbsRectangle &r, const core::position2d &p ) +{ + u32 code = CLIPCODE_EMPTY; + + if ( p.X < r.x0 ) + code = CLIPCODE_LEFT; + else + if ( p.X > r.x1 ) + code = CLIPCODE_RIGHT; + + if ( p.Y < r.y0 ) + code |= CLIPCODE_TOP; + else + if ( p.Y > r.y1 ) + code |= CLIPCODE_BOTTOM; + + return code; +} + + +/*! + Cohen Sutherland clipping + @return: 1 if valid +*/ + +static int ClipLine(const AbsRectangle &clipping, + core::position2d &p0, + core::position2d &p1, + const core::position2d& p0_in, + const core::position2d& p1_in) +{ + u32 code0; + u32 code1; + u32 code; + + p0 = p0_in; + p1 = p1_in; + + code0 = GetClipCode( clipping, p0 ); + code1 = GetClipCode( clipping, p1 ); + + // trivial accepted + while ( code0 | code1 ) + { + s32 x=0; + s32 y=0; + + // trivial reject + if ( code0 & code1 ) + return 0; + + if ( code0 ) + { + // clip first point + code = code0; + } + else + { + // clip last point + code = code1; + } + + if ( (code & CLIPCODE_BOTTOM) == CLIPCODE_BOTTOM ) + { + // clip bottom viewport + y = clipping.y1; + x = p0.X + ( p1.X - p0.X ) * ( y - p0.Y ) / ( p1.Y - p0.Y ); + } + else + if ( (code & CLIPCODE_TOP) == CLIPCODE_TOP ) + { + // clip to viewport + y = clipping.y0; + x = p0.X + ( p1.X - p0.X ) * ( y - p0.Y ) / ( p1.Y - p0.Y ); + } + else + if ( (code & CLIPCODE_RIGHT) == CLIPCODE_RIGHT ) + { + // clip right viewport + x = clipping.x1; + y = p0.Y + ( p1.Y - p0.Y ) * ( x - p0.X ) / ( p1.X - p0.X ); + } + else + if ( (code & CLIPCODE_LEFT) == CLIPCODE_LEFT ) + { + // clip left viewport + x = clipping.x0; + y = p0.Y + ( p1.Y - p0.Y ) * ( x - p0.X ) / ( p1.X - p0.X ); + } + + if ( code == code0 ) + { + // modify first point + p0.X = x; + p0.Y = y; + code0 = GetClipCode( clipping, p0 ); + } + else + { + // modify second point + p1.X = x; + p1.Y = y; + code1 = GetClipCode( clipping, p1 ); + } + } + + return 1; +} + +/* +*/ +inline void GetClip(AbsRectangle &clipping, video::IImage * t) +{ + clipping.x0 = 0; + clipping.y0 = 0; + clipping.x1 = t->getDimension().Width - 1; + clipping.y1 = t->getDimension().Height - 1; +} + +/* +*/ +static void RenderLine32_Decal(video::IImage *t, + const core::position2d &p0, + const core::position2d &p1, + u32 argb ) +{ + s32 dx = p1.X - p0.X; + s32 dy = p1.Y - p0.Y; + + s32 c; + s32 m; + s32 d = 0; + s32 run; + + s32 xInc = 4; + s32 yInc = (s32) t->getPitch(); + + if ( dx < 0 ) + { + xInc = -xInc; + dx = -dx; + } + + if ( dy < 0 ) + { + yInc = -yInc; + dy = -dy; + } + + u32 *dst; + dst = (u32*) ( (u8*) t->lock() + ( p0.Y * t->getPitch() ) + ( p0.X << 2 ) ); + + if ( dy > dx ) + { + s32 tmp; + tmp = dx; + dx = dy; + dy = tmp; + tmp = xInc; + xInc = yInc; + yInc = tmp; + } + + c = dx << 1; + m = dy << 1; + + run = dx; + while ( run ) + { + *dst = argb; + + dst = (u32*) ( (u8*) dst + xInc ); // x += xInc + d += m; + if ( d > dx ) + { + dst = (u32*) ( (u8*) dst + yInc ); // y += yInc + d -= c; + } + run -= 1; + } + + t->unlock(); +} + + +/* +*/ +static void RenderLine32_Blend(video::IImage *t, + const core::position2d &p0, + const core::position2d &p1, + u32 argb, u32 alpha) +{ + s32 dx = p1.X - p0.X; + s32 dy = p1.Y - p0.Y; + + s32 c; + s32 m; + s32 d = 0; + s32 run; + + s32 xInc = 4; + s32 yInc = (s32) t->getPitch(); + + if ( dx < 0 ) + { + xInc = -xInc; + dx = -dx; + } + + if ( dy < 0 ) + { + yInc = -yInc; + dy = -dy; + } + + u32 *dst; + dst = (u32*) ( (u8*) t->lock() + ( p0.Y * t->getPitch() ) + ( p0.X << 2 ) ); + + if ( dy > dx ) + { + s32 tmp; + tmp = dx; + dx = dy; + dy = tmp; + tmp = xInc; + xInc = yInc; + yInc = tmp; + } + + c = dx << 1; + m = dy << 1; + + run = dx; + while ( run ) + { + *dst = PixelBlend32( *dst, argb, alpha ); + + dst = (u32*) ( (u8*) dst + xInc ); // x += xInc + d += m; + if ( d > dx ) + { + dst = (u32*) ( (u8*) dst + yInc ); // y += yInc + d -= c; + } + run -= 1; + } + + t->unlock(); +} + +/* +*/ +static void RenderLine16_Decal(video::IImage *t, + const core::position2d &p0, + const core::position2d &p1, + u32 argb ) +{ + s32 dx = p1.X - p0.X; + s32 dy = p1.Y - p0.Y; + + s32 c; + s32 m; + s32 d = 0; + s32 run; + + s32 xInc = 2; + s32 yInc = (s32) t->getPitch(); + + if ( dx < 0 ) + { + xInc = -xInc; + dx = -dx; + } + + if ( dy < 0 ) + { + yInc = -yInc; + dy = -dy; + } + + u16 *dst; + dst = (u16*) ( (u8*) t->lock() + ( p0.Y * t->getPitch() ) + ( p0.X << 1 ) ); + + if ( dy > dx ) + { + s32 tmp; + tmp = dx; + dx = dy; + dy = tmp; + tmp = xInc; + xInc = yInc; + yInc = tmp; + } + + c = dx << 1; + m = dy << 1; + + run = dx; + while ( run ) + { + *dst = (u16)argb; + + dst = (u16*) ( (u8*) dst + xInc ); // x += xInc + d += m; + if ( d > dx ) + { + dst = (u16*) ( (u8*) dst + yInc ); // y += yInc + d -= c; + } + run -= 1; + } + + t->unlock(); +} + +/* +*/ +static void RenderLine16_Blend(video::IImage *t, + const core::position2d &p0, + const core::position2d &p1, + u32 argb, + u32 alpha) +{ + s32 dx = p1.X - p0.X; + s32 dy = p1.Y - p0.Y; + + s32 c; + s32 m; + s32 d = 0; + s32 run; + + s32 xInc = 2; + s32 yInc = (s32) t->getPitch(); + + if ( dx < 0 ) + { + xInc = -xInc; + dx = -dx; + } + + if ( dy < 0 ) + { + yInc = -yInc; + dy = -dy; + } + + u16 *dst; + dst = (u16*) ( (u8*) t->lock() + ( p0.Y * t->getPitch() ) + ( p0.X << 1 ) ); + + if ( dy > dx ) + { + s32 tmp; + tmp = dx; + dx = dy; + dy = tmp; + tmp = xInc; + xInc = yInc; + yInc = tmp; + } + + c = dx << 1; + m = dy << 1; + + run = dx; + while ( run ) + { + *dst = PixelBlend16( *dst, argb, alpha ); + + dst = (u16*) ( (u8*) dst + xInc ); // x += xInc + d += m; + if ( d > dx ) + { + dst = (u16*) ( (u8*) dst + yInc ); // y += yInc + d -= c; + } + run -= 1; + } + + t->unlock(); +} + + +/*! +*/ +static void executeBlit_TextureCopy_x_to_x( const SBlitJob * job ) +{ + const void *src = (void*) job->src; + void *dst = (void*) job->dst; + + const u32 widthPitch = job->width * job->dstPixelMul; + for ( s32 dy = 0; dy != job->height; ++dy ) + { + memcpy( dst, src, widthPitch ); + + src = (void*) ( (u8*) (src) + job->srcPitch ); + dst = (void*) ( (u8*) (dst) + job->dstPitch ); + } +} + + +/*! +*/ +static void executeBlit_TextureCopy_32_to_16( const SBlitJob * job ) +{ + const u32 *src = static_cast(job->src); + u16 *dst = static_cast(job->dst); + + for ( s32 dy = 0; dy != job->height; ++dy ) + { + for ( s32 dx = 0; dx != job->width; ++dx ) + { + //16 bit Blitter depends on pre-multiplied color + const u32 s = PixelLerp32( src[dx] | 0xFF000000, extractAlpha( src[dx] ) ); + dst[dx] = video::A8R8G8B8toA1R5G5B5( s ); + } + + src = (u32*) ( (u8*) (src) + job->srcPitch ); + dst = (u16*) ( (u8*) (dst) + job->dstPitch ); + } +} + +/*! +*/ +static void executeBlit_TextureCopy_24_to_16( const SBlitJob * job ) +{ + const void *src = (void*) job->src; + u16 *dst = (u16*) job->dst; + + for ( s32 dy = 0; dy != job->height; ++dy ) + { + u8 * s = (u8*) src; + + for ( s32 dx = 0; dx != job->width; ++dx ) + { + dst[dx] = video::RGB16(s[0], s[1], s[2]); + s += 3; + } + + src = (void*) ( (u8*) (src) + job->srcPitch ); + dst = (u16*) ( (u8*) (dst) + job->dstPitch ); + } +} + + +/*! +*/ +static void executeBlit_TextureCopy_16_to_32( const SBlitJob * job ) +{ + const u16 *src = (u16*) job->src; + u32 *dst = (u32*) job->dst; + + for ( s32 dy = 0; dy != job->height; ++dy ) + { + for ( s32 dx = 0; dx != job->width; ++dx ) + { + dst[dx] = video::A1R5G5B5toA8R8G8B8( src[dx] ); + } + + src = (u16*) ( (u8*) (src) + job->srcPitch ); + dst = (u32*) ( (u8*) (dst) + job->dstPitch ); + } +} + +static void executeBlit_TextureCopy_16_to_24( const SBlitJob * job ) +{ + const u16 *src = (u16*) job->src; + u8 *dst = (u8*) job->dst; + + for ( s32 dy = 0; dy != job->height; ++dy ) + { + for ( s32 dx = 0; dx != job->width; ++dx ) + { + u32 colour = video::A1R5G5B5toA8R8G8B8( src[dx] ); + u8 * writeTo = &dst[dx * 3]; + *writeTo++ = (colour >> 16)& 0xFF; + *writeTo++ = (colour >> 8) & 0xFF; + *writeTo++ = colour & 0xFF; + } + + src = (u16*) ( (u8*) (src) + job->srcPitch ); + dst += job->dstPitch; + } +} + + +/*! +*/ +static void executeBlit_TextureCopy_24_to_32( const SBlitJob * job ) +{ + void *src = (void*) job->src; + u32 *dst = (u32*) job->dst; + + for ( s32 dy = 0; dy != job->height; ++dy ) + { + u8 * s = (u8*) src; + + for ( s32 dx = 0; dx != job->width; ++dx ) + { + dst[dx] = 0xFF000000 | s[0] << 16 | s[1] << 8 | s[2]; + s += 3; + } + + src = (void*) ( (u8*) (src) + job->srcPitch ); + dst = (u32*) ( (u8*) (dst) + job->dstPitch ); + } +} + +static void executeBlit_TextureCopy_32_to_24( const SBlitJob * job ) +{ + const u32 * src = (u32*) job->src; + u8 * dst = (u8*) job->dst; + + for ( s32 dy = 0; dy != job->height; ++dy ) + { + for ( s32 dx = 0; dx != job->width; ++dx ) + { + u8 * writeTo = &dst[dx * 3]; + *writeTo++ = (src[dx] >> 16)& 0xFF; + *writeTo++ = (src[dx] >> 8) & 0xFF; + *writeTo++ = src[dx] & 0xFF; + } + + src = (u32*) ( (u8*) (src) + job->srcPitch ); + dst += job->dstPitch ; + } + +} + + +/*! +*/ +static void executeBlit_TextureBlend_16_to_16( const SBlitJob * job ) +{ + u32 dx; + s32 dy; + + u32 *src = (u32*) job->src; + u32 *dst = (u32*) job->dst; + + + const u32 rdx = job->width >> 1; + const u32 off = core::if_c_a_else_b( job->width & 1 ,job->width - 1, 0 ); + + + for ( dy = 0; dy != job->height; ++dy ) + { + for ( dx = 0; dx != rdx; ++dx ) + { + dst[dx] = PixelBlend16_simd( dst[dx], src[dx] ); + } + + if ( off ) + { + ((u16*) dst)[off] = PixelBlend16( ((u16*) dst)[off], ((u16*) src)[off] ); + } + + src = (u32*) ( (u8*) (src) + job->srcPitch ); + dst = (u32*) ( (u8*) (dst) + job->dstPitch ); + } +} + +/*! +*/ +static void executeBlit_TextureBlend_32_to_32( const SBlitJob * job ) +{ + u32 *src = (u32*) job->src; + u32 *dst = (u32*) job->dst; + + for ( s32 dy = 0; dy != job->height; ++dy ) + { + for ( s32 dx = 0; dx != job->width; ++dx ) + { + dst[dx] = PixelBlend32( dst[dx], src[dx] ); + } + src = (u32*) ( (u8*) (src) + job->srcPitch ); + dst = (u32*) ( (u8*) (dst) + job->dstPitch ); + } +} + +/*! +*/ +static void executeBlit_TextureBlendColor_16_to_16( const SBlitJob * job ) +{ + u16 *src = (u16*) job->src; + u16 *dst = (u16*) job->dst; + + u16 blend = video::A8R8G8B8toA1R5G5B5 ( job->argb ); + for ( s32 dy = 0; dy != job->height; ++dy ) + { + for ( s32 dx = 0; dx != job->width; ++dx ) + { + if ( 0 == (src[dx] & 0x8000) ) + continue; + + dst[dx] = PixelMul16_2( src[dx], blend ); + } + src = (u16*) ( (u8*) (src) + job->srcPitch ); + dst = (u16*) ( (u8*) (dst) + job->dstPitch ); + } +} + + +/*! +*/ +static void executeBlit_TextureBlendColor_32_to_32( const SBlitJob * job ) +{ + u32 *src = (u32*) job->src; + u32 *dst = (u32*) job->dst; + + for ( s32 dy = 0; dy != job->height; ++dy ) + { + for ( s32 dx = 0; dx != job->width; ++dx ) + { + dst[dx] = PixelBlend32( dst[dx], PixelMul32_2( src[dx], job->argb ) ); + } + src = (u32*) ( (u8*) (src) + job->srcPitch ); + dst = (u32*) ( (u8*) (dst) + job->dstPitch ); + } +} + +/*! +*/ +static void executeBlit_Color_16_to_16( const SBlitJob * job ) +{ + u16 *dst = (u16*) job->dst; + + u16 c0 = video::A8R8G8B8toA1R5G5B5( job->argb ); + u32 c = c0 | c0 << 16; + + if ( 0 == (job->srcPitch & 3 ) ) + { + for ( s32 dy = 0; dy != job->height; ++dy ) + { + memset32( dst, c, job->srcPitch ); + dst = (u16*) ( (u8*) (dst) + job->dstPitch ); + } + } + else + { + s32 dx = job->width - 1; + + for ( s32 dy = 0; dy != job->height; ++dy ) + { + memset32( dst, c, job->srcPitch ); + dst[dx] = c0; + dst = (u16*) ( (u8*) (dst) + job->dstPitch ); + } + + } +} + +/*! +*/ +static void executeBlit_Color_32_to_32( const SBlitJob * job ) +{ + u32 *dst = (u32*) job->dst; + + for ( s32 dy = 0; dy != job->height; ++dy ) + { + memset32( dst, job->argb, job->srcPitch ); + dst = (u32*) ( (u8*) (dst) + job->dstPitch ); + } +} + +/*! +*/ +static void executeBlit_ColorAlpha_16_to_16( const SBlitJob * job ) +{ + u16 *dst = (u16*) job->dst; + + const u32 alpha = extractAlpha( job->argb ) >> 3; + const u32 src = video::A8R8G8B8toA1R5G5B5( job->argb ); + + for ( s32 dy = 0; dy != job->height; ++dy ) + { + for ( s32 dx = 0; dx != job->width; ++dx ) + { + dst[dx] = PixelBlend16( dst[dx], src, alpha ); + } + dst = (u16*) ( (u8*) (dst) + job->dstPitch ); + } +} + +/*! +*/ +static void executeBlit_ColorAlpha_32_to_32( const SBlitJob * job ) +{ + u32 *dst = (u32*) job->dst; + + const u32 alpha = extractAlpha( job->argb ); + const u32 src = job->argb; + + for ( s32 dy = 0; dy != job->height; ++dy ) + { + for ( s32 dx = 0; dx != job->width; ++dx ) + { + dst[dx] = PixelBlend32( dst[dx], src, alpha ); + } + dst = (u32*) ( (u8*) (dst) + job->dstPitch ); + } +} + +/*! +*/ +struct blitterTable +{ + eBlitter operation; + s32 destFormat; + s32 sourceFormat; + tExecuteBlit func; +}; + +static const blitterTable blitTable[] = +{ + { BLITTER_TEXTURE, -2, -2, executeBlit_TextureCopy_x_to_x }, + { BLITTER_TEXTURE, video::ECF_A1R5G5B5, video::ECF_A8R8G8B8, executeBlit_TextureCopy_32_to_16 }, + { BLITTER_TEXTURE, video::ECF_A1R5G5B5, video::ECF_R8G8B8, executeBlit_TextureCopy_24_to_16 }, + { BLITTER_TEXTURE, video::ECF_A8R8G8B8, video::ECF_A1R5G5B5, executeBlit_TextureCopy_16_to_32 }, + { BLITTER_TEXTURE, video::ECF_A8R8G8B8, video::ECF_R8G8B8, executeBlit_TextureCopy_24_to_32 }, + { BLITTER_TEXTURE, video::ECF_R8G8B8, video::ECF_A1R5G5B5, executeBlit_TextureCopy_16_to_24 }, + { BLITTER_TEXTURE, video::ECF_R8G8B8, video::ECF_A8R8G8B8, executeBlit_TextureCopy_32_to_24 }, + { BLITTER_TEXTURE_ALPHA_BLEND, video::ECF_A1R5G5B5, video::ECF_A1R5G5B5, executeBlit_TextureBlend_16_to_16 }, + { BLITTER_TEXTURE_ALPHA_BLEND, video::ECF_A8R8G8B8, video::ECF_A8R8G8B8, executeBlit_TextureBlend_32_to_32 }, + { BLITTER_TEXTURE_ALPHA_COLOR_BLEND, video::ECF_A1R5G5B5, video::ECF_A1R5G5B5, executeBlit_TextureBlendColor_16_to_16 }, + { BLITTER_TEXTURE_ALPHA_COLOR_BLEND, video::ECF_A8R8G8B8, video::ECF_A8R8G8B8, executeBlit_TextureBlendColor_32_to_32 }, + { BLITTER_COLOR, video::ECF_A1R5G5B5, -1, executeBlit_Color_16_to_16 }, + { BLITTER_COLOR, video::ECF_A8R8G8B8, -1, executeBlit_Color_32_to_32 }, + { BLITTER_COLOR_ALPHA, video::ECF_A1R5G5B5, -1, executeBlit_ColorAlpha_16_to_16 }, + { BLITTER_COLOR_ALPHA, video::ECF_A8R8G8B8, -1, executeBlit_ColorAlpha_32_to_32 }, + { BLITTER_INVALID } +}; + +static inline tExecuteBlit getBlitter2( eBlitter operation,const video::IImage * dest,const video::IImage * source ) +{ + video::ECOLOR_FORMAT sourceFormat = (video::ECOLOR_FORMAT) ( source ? source->getColorFormat() : -1 ); + video::ECOLOR_FORMAT destFormat = (video::ECOLOR_FORMAT) ( dest ? dest->getColorFormat() : -1 ); + + const blitterTable * b = blitTable; + + while ( b->operation != BLITTER_INVALID ) + { + if ( b->operation == operation ) + { + if (( b->destFormat == -1 || b->destFormat == destFormat ) && + ( b->sourceFormat == -1 || b->sourceFormat == sourceFormat ) ) + return b->func; + else + if ( b->destFormat == -2 && ( sourceFormat == destFormat ) ) + return b->func; + } + b += 1; + } + return 0; +} + +#if 0 +static tExecuteBlit getBlitter( eBlitter operation,const video::IImage * dest,const video::IImage * source ) +{ + video::ECOLOR_FORMAT sourceFormat = (video::ECOLOR_FORMAT) -1; + video::ECOLOR_FORMAT destFormat = (video::ECOLOR_FORMAT) -1; + + if ( source ) + sourceFormat = source->getColorFormat (); + + if ( dest ) + destFormat = dest->getColorFormat(); + + switch ( operation ) + { + case BLITTER_TEXTURE: + { + if ( sourceFormat == destFormat ) + return executeBlit_TextureCopy_x_to_x; + + if ( destFormat == video::ECF_A1R5G5B5 && sourceFormat == video::ECF_A8R8G8B8 ) + return executeBlit_TextureCopy_32_to_16; + + if ( destFormat == video::ECF_A1R5G5B5 && sourceFormat == video::ECF_R8G8B8 ) + return executeBlit_TextureCopy_24_to_16; + + if ( destFormat == video::ECF_A8R8G8B8 && sourceFormat == video::ECF_A1R5G5B5 ) + return executeBlit_TextureCopy_16_to_32; + + if ( destFormat == video::ECF_R8G8B8 && sourceFormat == video::ECF_A1R5G5B5 ) + return executeBlit_TextureCopy_16_to_24; + + if ( destFormat == video::ECF_A8R8G8B8 && sourceFormat == video::ECF_R8G8B8 ) + return executeBlit_TextureCopy_24_to_32; + + if ( destFormat == video::ECF_R8G8B8 && sourceFormat == video::ECF_A8R8G8B8 ) + return executeBlit_TextureCopy_32_to_24; + + } break; + + case BLITTER_TEXTURE_ALPHA_BLEND: + { + if ( destFormat == video::ECF_A1R5G5B5 && sourceFormat == video::ECF_A1R5G5B5 ) + return executeBlit_TextureBlend_16_to_16; + + if ( destFormat == video::ECF_A8R8G8B8 && sourceFormat == video::ECF_A8R8G8B8 ) + return executeBlit_TextureBlend_32_to_32; + + } break; + + case BLITTER_TEXTURE_ALPHA_COLOR_BLEND: + { + if ( destFormat == video::ECF_A1R5G5B5 && sourceFormat == video::ECF_A1R5G5B5 ) + return executeBlit_TextureBlendColor_16_to_16; + + if ( destFormat == video::ECF_A8R8G8B8 && sourceFormat == video::ECF_A8R8G8B8 ) + return executeBlit_TextureBlendColor_32_to_32; + } break; + + case BLITTER_COLOR: + { + if ( destFormat == video::ECF_A1R5G5B5 ) + return executeBlit_Color_16_to_16; + + if ( destFormat == video::ECF_A8R8G8B8 ) + return executeBlit_Color_32_to_32; + } break; + + case BLITTER_COLOR_ALPHA: + { + if ( destFormat == video::ECF_A1R5G5B5 ) + return executeBlit_ColorAlpha_16_to_16; + + if ( destFormat == video::ECF_A8R8G8B8 ) + return executeBlit_ColorAlpha_32_to_32; + + } break; + + case BLITTER_INVALID: + break; + } +/* + char buf[64]; + sprintf( buf, "Blit: %d %d->%d unsupported",operation,sourceFormat,destFormat ); + os::Printer::log(buf ); +*/ + return 0; + +} +#endif -#include "CImage.h" -#include "irrString.h" -#include "SoftwareDriver2_helper.h" -#include "CColorConverter.h" - -namespace irr +// bounce clipping to texture +inline void setClip ( AbsRectangle &out, const core::rect *clip, + const video::IImage * tex, s32 passnative ) { - - struct SBlitJob + if ( clip && 0 == tex && passnative ) { - AbsRectangle Dest; - AbsRectangle Source; - - u32 argb; - - void * src; - void * dst; - - s32 width; - s32 height; - - u32 srcPitch; - u32 dstPitch; - - u32 srcPixelMul; - u32 dstPixelMul; - }; - - // Blitter Operation - enum eBlitter - { - BLITTER_INVALID = 0, - BLITTER_COLOR, - BLITTER_COLOR_ALPHA, - BLITTER_TEXTURE, - BLITTER_TEXTURE_ALPHA_BLEND, - BLITTER_TEXTURE_ALPHA_COLOR_BLEND - }; - - typedef void (*tExecuteBlit) ( const SBlitJob * job ); - - - // Bitfields Cohen Sutherland - enum eClipCode - { - CLIPCODE_EMPTY = 0, - CLIPCODE_BOTTOM = 1, - CLIPCODE_TOP = 2, - CLIPCODE_LEFT = 4, - CLIPCODE_RIGHT = 8 - }; - -inline u32 GetClipCode( const AbsRectangle &r, const core::position2d &p ) -{ - u32 code = CLIPCODE_EMPTY; - - if ( p.X < r.x0 ) - code = CLIPCODE_LEFT; - else - if ( p.X > r.x1 ) - code = CLIPCODE_RIGHT; - - if ( p.Y < r.y0 ) - code |= CLIPCODE_TOP; - else - if ( p.Y > r.y1 ) - code |= CLIPCODE_BOTTOM; - - return code; -} - - -/*! - Cohen Sutherland clipping - @return: 1 if valid -*/ - -static int ClipLine(const AbsRectangle &clipping, - core::position2d &p0, - core::position2d &p1, - const core::position2d& p0_in, - const core::position2d& p1_in) -{ - u32 code0; - u32 code1; - u32 code; - - p0 = p0_in; - p1 = p1_in; - - code0 = GetClipCode( clipping, p0 ); - code1 = GetClipCode( clipping, p1 ); - - // trivial accepted - while ( code0 | code1 ) - { - s32 x=0; - s32 y=0; - - // trivial reject - if ( code0 & code1 ) - return 0; - - if ( code0 ) - { - // clip first point - code = code0; - } - else - { - // clip last point - code = code1; - } - - if ( (code & CLIPCODE_BOTTOM) == CLIPCODE_BOTTOM ) - { - // clip bottom viewport - y = clipping.y1; - x = p0.X + ( p1.X - p0.X ) * ( y - p0.Y ) / ( p1.Y - p0.Y ); - } - else - if ( (code & CLIPCODE_TOP) == CLIPCODE_TOP ) - { - // clip to viewport - y = clipping.y0; - x = p0.X + ( p1.X - p0.X ) * ( y - p0.Y ) / ( p1.Y - p0.Y ); - } - else - if ( (code & CLIPCODE_RIGHT) == CLIPCODE_RIGHT ) - { - // clip right viewport - x = clipping.x1; - y = p0.Y + ( p1.Y - p0.Y ) * ( x - p0.X ) / ( p1.X - p0.X ); - } - else - if ( (code & CLIPCODE_LEFT) == CLIPCODE_LEFT ) - { - // clip left viewport - x = clipping.x0; - y = p0.Y + ( p1.Y - p0.Y ) * ( x - p0.X ) / ( p1.X - p0.X ); - } - - if ( code == code0 ) - { - // modify first point - p0.X = x; - p0.Y = y; - code0 = GetClipCode( clipping, p0 ); - } - else - { - // modify second point - p1.X = x; - p1.Y = y; - code1 = GetClipCode( clipping, p1 ); - } + out.x0 = clip->UpperLeftCorner.X; + out.x1 = clip->LowerRightCorner.X; + out.y0 = clip->UpperLeftCorner.Y; + out.y1 = clip->LowerRightCorner.Y; + return; } - return 1; -} - -/* -*/ -inline void GetClip(AbsRectangle &clipping, video::IImage * t) -{ - clipping.x0 = 0; - clipping.y0 = 0; - clipping.x1 = t->getDimension().Width - 1; - clipping.y1 = t->getDimension().Height - 1; -} - -/* -*/ -static void RenderLine32_Decal(video::IImage *t, - const core::position2d &p0, - const core::position2d &p1, - u32 argb ) -{ - s32 dx = p1.X - p0.X; - s32 dy = p1.Y - p0.Y; - - s32 c; - s32 m; - s32 d = 0; - s32 run; - - s32 xInc = 4; - s32 yInc = (s32) t->getPitch(); - - if ( dx < 0 ) + const s32 w = tex ? tex->getDimension().Width : 0; + const s32 h = tex ? tex->getDimension().Height : 0; + if ( clip ) { - xInc = -xInc; - dx = -dx; - } - - if ( dy < 0 ) - { - yInc = -yInc; - dy = -dy; - } - - u32 *dst; - dst = (u32*) ( (u8*) t->lock() + ( p0.Y * t->getPitch() ) + ( p0.X << 2 ) ); - - if ( dy > dx ) - { - s32 tmp; - tmp = dx; - dx = dy; - dy = tmp; - tmp = xInc; - xInc = yInc; - yInc = tmp; - } - - c = dx << 1; - m = dy << 1; - - run = dx; - while ( run ) - { - *dst = argb; - - dst = (u32*) ( (u8*) dst + xInc ); // x += xInc - d += m; - if ( d > dx ) - { - dst = (u32*) ( (u8*) dst + yInc ); // y += yInc - d -= c; - } - run -= 1; - } - - t->unlock(); -} - - -/* -*/ -static void RenderLine32_Blend(video::IImage *t, - const core::position2d &p0, - const core::position2d &p1, - u32 argb, u32 alpha) -{ - s32 dx = p1.X - p0.X; - s32 dy = p1.Y - p0.Y; - - s32 c; - s32 m; - s32 d = 0; - s32 run; - - s32 xInc = 4; - s32 yInc = (s32) t->getPitch(); - - if ( dx < 0 ) - { - xInc = -xInc; - dx = -dx; - } - - if ( dy < 0 ) - { - yInc = -yInc; - dy = -dy; - } - - u32 *dst; - dst = (u32*) ( (u8*) t->lock() + ( p0.Y * t->getPitch() ) + ( p0.X << 2 ) ); - - if ( dy > dx ) - { - s32 tmp; - tmp = dx; - dx = dy; - dy = tmp; - tmp = xInc; - xInc = yInc; - yInc = tmp; - } - - c = dx << 1; - m = dy << 1; - - run = dx; - while ( run ) - { - *dst = PixelBlend32( *dst, argb, alpha ); - - dst = (u32*) ( (u8*) dst + xInc ); // x += xInc - d += m; - if ( d > dx ) - { - dst = (u32*) ( (u8*) dst + yInc ); // y += yInc - d -= c; - } - run -= 1; - } - - t->unlock(); -} - -/* -*/ -static void RenderLine16_Decal(video::IImage *t, - const core::position2d &p0, - const core::position2d &p1, - u32 argb ) -{ - s32 dx = p1.X - p0.X; - s32 dy = p1.Y - p0.Y; - - s32 c; - s32 m; - s32 d = 0; - s32 run; - - s32 xInc = 2; - s32 yInc = (s32) t->getPitch(); - - if ( dx < 0 ) - { - xInc = -xInc; - dx = -dx; - } - - if ( dy < 0 ) - { - yInc = -yInc; - dy = -dy; - } - - u16 *dst; - dst = (u16*) ( (u8*) t->lock() + ( p0.Y * t->getPitch() ) + ( p0.X << 1 ) ); - - if ( dy > dx ) - { - s32 tmp; - tmp = dx; - dx = dy; - dy = tmp; - tmp = xInc; - xInc = yInc; - yInc = tmp; - } - - c = dx << 1; - m = dy << 1; - - run = dx; - while ( run ) - { - *dst = (u16)argb; - - dst = (u16*) ( (u8*) dst + xInc ); // x += xInc - d += m; - if ( d > dx ) - { - dst = (u16*) ( (u8*) dst + yInc ); // y += yInc - d -= c; - } - run -= 1; - } - - t->unlock(); -} - -/* -*/ -static void RenderLine16_Blend(video::IImage *t, - const core::position2d &p0, - const core::position2d &p1, - u32 argb, - u32 alpha) -{ - s32 dx = p1.X - p0.X; - s32 dy = p1.Y - p0.Y; - - s32 c; - s32 m; - s32 d = 0; - s32 run; - - s32 xInc = 2; - s32 yInc = (s32) t->getPitch(); - - if ( dx < 0 ) - { - xInc = -xInc; - dx = -dx; - } - - if ( dy < 0 ) - { - yInc = -yInc; - dy = -dy; - } - - u16 *dst; - dst = (u16*) ( (u8*) t->lock() + ( p0.Y * t->getPitch() ) + ( p0.X << 1 ) ); - - if ( dy > dx ) - { - s32 tmp; - tmp = dx; - dx = dy; - dy = tmp; - tmp = xInc; - xInc = yInc; - yInc = tmp; - } - - c = dx << 1; - m = dy << 1; - - run = dx; - while ( run ) - { - *dst = PixelBlend16( *dst, argb, alpha ); - - dst = (u16*) ( (u8*) dst + xInc ); // x += xInc - d += m; - if ( d > dx ) - { - dst = (u16*) ( (u8*) dst + yInc ); // y += yInc - d -= c; - } - run -= 1; - } - - t->unlock(); -} - - -/*! -*/ -static void executeBlit_TextureCopy_x_to_x( const SBlitJob * job ) -{ - const void *src = (void*) job->src; - void *dst = (void*) job->dst; - - const u32 widthPitch = job->width * job->dstPixelMul; - for ( s32 dy = 0; dy != job->height; ++dy ) - { - memcpy( dst, src, widthPitch ); - - src = (void*) ( (u8*) (src) + job->srcPitch ); - dst = (void*) ( (u8*) (dst) + job->dstPitch ); - } -} - - -/*! -*/ -static void executeBlit_TextureCopy_32_to_16( const SBlitJob * job ) -{ - const u32 *src = static_cast(job->src); - u16 *dst = static_cast(job->dst); - - for ( s32 dy = 0; dy != job->height; ++dy ) - { - for ( s32 dx = 0; dx != job->width; ++dx ) - { - //16 bit Blitter depends on pre-multiplied color - const u32 s = PixelLerp32( src[dx] | 0xFF000000, extractAlpha( src[dx] ) ); - dst[dx] = video::A8R8G8B8toA1R5G5B5( s ); - } - - src = (u32*) ( (u8*) (src) + job->srcPitch ); - dst = (u16*) ( (u8*) (dst) + job->dstPitch ); - } -} - -/*! -*/ -static void executeBlit_TextureCopy_24_to_16( const SBlitJob * job ) -{ - const void *src = (void*) job->src; - u16 *dst = (u16*) job->dst; - - for ( s32 dy = 0; dy != job->height; ++dy ) - { - u8 * s = (u8*) src; - - for ( s32 dx = 0; dx != job->width; ++dx ) - { - dst[dx] = video::RGB16(s[0], s[1], s[2]); - s += 3; - } - - src = (void*) ( (u8*) (src) + job->srcPitch ); - dst = (u16*) ( (u8*) (dst) + job->dstPitch ); - } -} - - -/*! -*/ -static void executeBlit_TextureCopy_16_to_32( const SBlitJob * job ) -{ - const u16 *src = (u16*) job->src; - u32 *dst = (u32*) job->dst; - - for ( s32 dy = 0; dy != job->height; ++dy ) - { - for ( s32 dx = 0; dx != job->width; ++dx ) - { - dst[dx] = video::A1R5G5B5toA8R8G8B8( src[dx] ); - } - - src = (u16*) ( (u8*) (src) + job->srcPitch ); - dst = (u32*) ( (u8*) (dst) + job->dstPitch ); - } -} - -static void executeBlit_TextureCopy_16_to_24( const SBlitJob * job ) -{ - const u16 *src = (u16*) job->src; - u8 *dst = (u8*) job->dst; - - for ( s32 dy = 0; dy != job->height; ++dy ) - { - for ( s32 dx = 0; dx != job->width; ++dx ) - { - u32 colour = video::A1R5G5B5toA8R8G8B8( src[dx] ); - u8 * writeTo = &dst[dx * 3]; - *writeTo++ = (colour >> 16)& 0xFF; - *writeTo++ = (colour >> 8) & 0xFF; - *writeTo++ = colour & 0xFF; - } - - src = (u16*) ( (u8*) (src) + job->srcPitch ); - dst += job->dstPitch; - } -} - - -/*! -*/ -static void executeBlit_TextureCopy_24_to_32( const SBlitJob * job ) -{ - void *src = (void*) job->src; - u32 *dst = (u32*) job->dst; - - for ( s32 dy = 0; dy != job->height; ++dy ) - { - u8 * s = (u8*) src; - - for ( s32 dx = 0; dx != job->width; ++dx ) - { - dst[dx] = 0xFF000000 | s[0] << 16 | s[1] << 8 | s[2]; - s += 3; - } - - src = (void*) ( (u8*) (src) + job->srcPitch ); - dst = (u32*) ( (u8*) (dst) + job->dstPitch ); - } -} - -static void executeBlit_TextureCopy_32_to_24( const SBlitJob * job ) -{ - const u32 * src = (u32*) job->src; - u8 * dst = (u8*) job->dst; - - for ( s32 dy = 0; dy != job->height; ++dy ) - { - for ( s32 dx = 0; dx != job->width; ++dx ) - { - u8 * writeTo = &dst[dx * 3]; - *writeTo++ = (src[dx] >> 16)& 0xFF; - *writeTo++ = (src[dx] >> 8) & 0xFF; - *writeTo++ = src[dx] & 0xFF; - } - - src = (u32*) ( (u8*) (src) + job->srcPitch ); - dst += job->dstPitch ; - } - -} - - -/*! -*/ -static void executeBlit_TextureBlend_16_to_16( const SBlitJob * job ) -{ - u32 dx; - s32 dy; - - u32 *src = (u32*) job->src; - u32 *dst = (u32*) job->dst; - - - const u32 rdx = job->width >> 1; - const u32 off = core::if_c_a_else_b( job->width & 1 ,job->width - 1, 0 ); - - - if ( 0 == off ) - { - for ( dy = 0; dy != job->height; ++dy ) - { - for ( dx = 0; dx != rdx; ++dx ) - { - dst[dx] = PixelBlend16_simd( dst[dx], src[dx] ); - } - - src = (u32*) ( (u8*) (src) + job->srcPitch ); - dst = (u32*) ( (u8*) (dst) + job->dstPitch ); - } - + out.x0 = core::s32_clamp ( clip->UpperLeftCorner.X, 0, w ); + out.x1 = core::s32_clamp ( clip->LowerRightCorner.X, out.x0, w ); + out.y0 = core::s32_clamp ( clip->UpperLeftCorner.Y, 0, h ); + out.y1 = core::s32_clamp ( clip->LowerRightCorner.Y, out.y0, h ); } else { - for ( dy = 0; dy != job->height; ++dy ) - { - for ( dx = 0; dx != rdx; ++dx ) - { - dst[dx] = PixelBlend16_simd( dst[dx], src[dx] ); - } - - ((u16*) dst)[off] = PixelBlend16( ((u16*) dst)[off], ((u16*) src)[off] ); - - src = (u32*) ( (u8*) (src) + job->srcPitch ); - dst = (u32*) ( (u8*) (dst) + job->dstPitch ); - } - + out.x0 = 0; + out.y0 = 0; + out.x1 = w; + out.y1 = h; } -} - -/*! -*/ -static void executeBlit_TextureBlend_32_to_32( const SBlitJob * job ) -{ - u32 *src = (u32*) job->src; - u32 *dst = (u32*) job->dst; - - for ( s32 dy = 0; dy != job->height; ++dy ) - { - for ( s32 dx = 0; dx != job->width; ++dx ) - { - dst[dx] = PixelBlend32( dst[dx], src[dx] ); - } - src = (u32*) ( (u8*) (src) + job->srcPitch ); - dst = (u32*) ( (u8*) (dst) + job->dstPitch ); - } -} - -/*! -*/ -static void executeBlit_TextureBlendColor_16_to_16( const SBlitJob * job ) -{ - u16 *src = (u16*) job->src; - u16 *dst = (u16*) job->dst; - - u16 blend = video::A8R8G8B8toA1R5G5B5 ( job->argb ); - for ( s32 dy = 0; dy != job->height; ++dy ) - { - for ( s32 dx = 0; dx != job->width; ++dx ) - { - dst[dx] = PixelBlend16( dst[dx], PixelMul16_2( src[dx], blend ) ); - } - src = (u16*) ( (u8*) (src) + job->srcPitch ); - dst = (u16*) ( (u8*) (dst) + job->dstPitch ); - } -} - - -/*! -*/ -static void executeBlit_TextureBlendColor_32_to_32( const SBlitJob * job ) -{ - u32 *src = (u32*) job->src; - u32 *dst = (u32*) job->dst; - - for ( s32 dy = 0; dy != job->height; ++dy ) - { - for ( s32 dx = 0; dx != job->width; ++dx ) - { - dst[dx] = PixelBlend32( dst[dx], PixelMul32_2( src[dx], job->argb ) ); - } - src = (u32*) ( (u8*) (src) + job->srcPitch ); - dst = (u32*) ( (u8*) (dst) + job->dstPitch ); - } -} - -/*! -*/ -static void executeBlit_Color_16_to_16( const SBlitJob * job ) -{ - u16 *dst = (u16*) job->dst; - - u16 c0 = video::A8R8G8B8toA1R5G5B5( job->argb ); - u32 c = c0 | c0 << 16; - - if ( 0 == (job->srcPitch & 3 ) ) - { - for ( s32 dy = 0; dy != job->height; ++dy ) - { - memset32( dst, c, job->srcPitch ); - dst = (u16*) ( (u8*) (dst) + job->dstPitch ); - } - } - else - { - s32 dx = job->width - 1; - - for ( s32 dy = 0; dy != job->height; ++dy ) - { - memset32( dst, c, job->srcPitch ); - dst[dx] = c0; - dst = (u16*) ( (u8*) (dst) + job->dstPitch ); - } - - } -} - -/*! -*/ -static void executeBlit_Color_32_to_32( const SBlitJob * job ) -{ - u32 *dst = (u32*) job->dst; - - for ( s32 dy = 0; dy != job->height; ++dy ) - { - memset32( dst, job->argb, job->srcPitch ); - dst = (u32*) ( (u8*) (dst) + job->dstPitch ); - } -} - -/*! -*/ -static void executeBlit_ColorAlpha_16_to_16( const SBlitJob * job ) -{ - u16 *dst = (u16*) job->dst; - - const u32 alpha = extractAlpha( job->argb ) >> 3; - const u32 src = video::A8R8G8B8toA1R5G5B5( job->argb ); - - for ( s32 dy = 0; dy != job->height; ++dy ) - { - for ( s32 dx = 0; dx != job->width; ++dx ) - { - dst[dx] = PixelBlend16( dst[dx], src, alpha ); - } - dst = (u16*) ( (u8*) (dst) + job->dstPitch ); - } -} - -/*! -*/ -static void executeBlit_ColorAlpha_32_to_32( const SBlitJob * job ) -{ - u32 *dst = (u32*) job->dst; - - const u32 alpha = extractAlpha( job->argb ); - const u32 src = job->argb; - - for ( s32 dy = 0; dy != job->height; ++dy ) - { - for ( s32 dx = 0; dx != job->width; ++dx ) - { - dst[dx] = PixelBlend32( dst[dx], src, alpha ); - } - dst = (u32*) ( (u8*) (dst) + job->dstPitch ); - } -} - -/*! -*/ -static tExecuteBlit getBlitter( eBlitter operation,const video::IImage * dest,const video::IImage * source ) -{ - video::ECOLOR_FORMAT sourceFormat = (video::ECOLOR_FORMAT) -1; - video::ECOLOR_FORMAT destFormat = (video::ECOLOR_FORMAT) -1; - - if ( source ) - sourceFormat = source->getColorFormat(); - - if ( dest ) - destFormat = dest->getColorFormat(); - - switch ( operation ) - { - case BLITTER_TEXTURE: - { - if ( sourceFormat == destFormat ) - return executeBlit_TextureCopy_x_to_x; - - if ( destFormat == video::ECF_A1R5G5B5 && sourceFormat == video::ECF_A8R8G8B8 ) - return executeBlit_TextureCopy_32_to_16; - - if ( destFormat == video::ECF_A1R5G5B5 && sourceFormat == video::ECF_R8G8B8 ) - return executeBlit_TextureCopy_24_to_16; - - if ( destFormat == video::ECF_A8R8G8B8 && sourceFormat == video::ECF_A1R5G5B5 ) - return executeBlit_TextureCopy_16_to_32; - - if ( destFormat == video::ECF_R8G8B8 && sourceFormat == video::ECF_A1R5G5B5 ) - return executeBlit_TextureCopy_16_to_24; - - if ( destFormat == video::ECF_A8R8G8B8 && sourceFormat == video::ECF_R8G8B8 ) - return executeBlit_TextureCopy_24_to_32; - - if ( destFormat == video::ECF_R8G8B8 && sourceFormat == video::ECF_A8R8G8B8 ) - return executeBlit_TextureCopy_32_to_24; - - } break; - - case BLITTER_TEXTURE_ALPHA_BLEND: - { - if ( destFormat == video::ECF_A1R5G5B5 && sourceFormat == video::ECF_A1R5G5B5 ) - return executeBlit_TextureBlend_16_to_16; - - if ( destFormat == video::ECF_A8R8G8B8 && sourceFormat == video::ECF_A8R8G8B8 ) - return executeBlit_TextureBlend_32_to_32; - - } break; - - case BLITTER_TEXTURE_ALPHA_COLOR_BLEND: - { - if ( destFormat == video::ECF_A1R5G5B5 && sourceFormat == video::ECF_A1R5G5B5 ) - return executeBlit_TextureBlendColor_16_to_16; - - if ( destFormat == video::ECF_A8R8G8B8 && sourceFormat == video::ECF_A8R8G8B8 ) - return executeBlit_TextureBlendColor_32_to_32; - } break; - - case BLITTER_COLOR: - { - if ( destFormat == video::ECF_A1R5G5B5 ) - return executeBlit_Color_16_to_16; - - if ( destFormat == video::ECF_A8R8G8B8 ) - return executeBlit_Color_32_to_32; - } break; - - case BLITTER_COLOR_ALPHA: - { - if ( destFormat == video::ECF_A1R5G5B5 ) - return executeBlit_ColorAlpha_16_to_16; - - if ( destFormat == video::ECF_A8R8G8B8 ) - return executeBlit_ColorAlpha_32_to_32; - - } break; - - case BLITTER_INVALID: - break; - } -/* - char buf[64]; - sprintf( buf, "Blit: %d %d->%d unsupported",operation,sourceFormat,destFormat ); - os::Printer::log(buf ); -*/ - return 0; } - - /*! a generic 2D Blitter */ @@ -871,7 +942,7 @@ static s32 Blit(eBlitter operation, const core::rect *sourceClipping, u32 argb) { - tExecuteBlit blitter = getBlitter( operation, dest, source ); + tExecuteBlit blitter = getBlitter2( operation, dest, source ); if ( 0 == blitter ) { return 0; @@ -884,43 +955,15 @@ static s32 Blit(eBlitter operation, SBlitJob job; - if ( sourceClipping ) - { - sourceClip.x0 = sourceClipping->UpperLeftCorner.X; - sourceClip.y0 = sourceClipping->UpperLeftCorner.Y; - sourceClip.x1 = sourceClipping->LowerRightCorner.X; - sourceClip.y1 = sourceClipping->LowerRightCorner.Y; - } - else - { - sourceClip.x0 = 0; - sourceClip.y0 = 0; - sourceClip.x1 = source ? source->getDimension().Width : 0; - sourceClip.y1 = source ? source->getDimension().Height : 0; - } - - if ( destClipping ) - { - destClip.x0 = destClipping->UpperLeftCorner.X; - destClip.y0 = destClipping->UpperLeftCorner.Y; - destClip.x1 = destClipping->LowerRightCorner.X; - destClip.y1 = destClipping->LowerRightCorner.Y; - } - else - { - destClip.x0 = 0; - destClip.y0 = 0; - destClip.x1 = dest ? dest->getDimension().Width : 0; - destClip.y1 = dest ? dest->getDimension().Height : 0; - } + setClip ( sourceClip, sourceClipping, source, 1 ); + setClip ( destClip, destClipping, dest, 0 ); v.x0 = destPos ? destPos->X : 0; v.y0 = destPos ? destPos->Y : 0; v.x1 = v.x0 + ( sourceClip.x1 - sourceClip.x0 ); v.y1 = v.y0 + ( sourceClip.y1 - sourceClip.y0 ); - intersect( job.Dest, destClip, v ); - if ( !isValid( job.Dest ) ) + if ( !intersect( job.Dest, destClip, v ) ) return 0; job.width = job.Dest.x1 - job.Dest.x0; @@ -963,525 +1006,524 @@ static s32 Blit(eBlitter operation, } } - -namespace irr -{ -namespace video -{ - -//! constructor -CImage::CImage(ECOLOR_FORMAT format, const core::dimension2d& size) -:Data(0), Size(size), Format(format), DeleteMemory(true) -{ - initData(); -} - - -//! constructor -CImage::CImage(ECOLOR_FORMAT format, const core::dimension2d& size, void* data, - bool ownForeignMemory, bool deleteForeignMemory) -: Data(0), Size(size), Format(format), DeleteMemory(deleteForeignMemory) -{ - if (ownForeignMemory) - { - Data = (void*)0xbadf00d; - initData(); - Data = data; - } - else - { - Data = 0; - initData(); - memcpy(Data, data, Size.Height * Pitch); - } -} - - - -//! constructor -CImage::CImage(ECOLOR_FORMAT format, IImage* imageToCopy) -: Data(0), Format(format), DeleteMemory(true) -{ - if (!imageToCopy) - return; - - Size = imageToCopy->getDimension(); - initData(); - - // now copy data from other image - - Blit ( BLITTER_TEXTURE, this, 0, 0, imageToCopy, 0,0 ); -} - - - -//! constructor -CImage::CImage(IImage* imageToCopy, const core::position2d& pos, - const core::dimension2d& size) - : Data(0), Size(0,0), DeleteMemory(true) -{ - if (!imageToCopy) - return; - - Format = imageToCopy->getColorFormat(); - Size = size; - - initData(); - - core::rect sClip( pos.X, pos.Y, pos.X + size.Width,pos.Y + size.Height ); - Blit (BLITTER_TEXTURE, this, 0, 0, imageToCopy, &sClip, 0); -} - - - -//! assumes format and size has been set and creates the rest -void CImage::initData() -{ - setBitMasks(); - BitsPerPixel = getBitsPerPixelFromFormat(Format); - BytesPerPixel = BitsPerPixel / 8; - - // Pitch should be aligned... - Pitch = BytesPerPixel * Size.Width; - - if (!Data) - Data = new s8[Size.Height * Pitch]; -} - - -//! destructor -CImage::~CImage() -{ - if ( DeleteMemory ) - delete [] (s8*)Data; -} - - -//! Returns width and height of image data. -const core::dimension2d& CImage::getDimension() const -{ - return Size; -} - - - -//! Returns bits per pixel. -u32 CImage::getBitsPerPixel() const -{ - return BitsPerPixel; -} - - -//! Returns bytes per pixel -u32 CImage::getBytesPerPixel() const -{ - return BytesPerPixel; -} - - - -//! Returns image data size in bytes -u32 CImage::getImageDataSizeInBytes() const -{ - return Pitch * Size.Height; -} - - - -//! Returns image data size in pixels -u32 CImage::getImageDataSizeInPixels() const -{ - return Size.Width * Size.Height; -} - - - -//! returns mask for red value of a pixel -u32 CImage::getRedMask() const -{ - return RedMask; -} - - - -//! returns mask for green value of a pixel -u32 CImage::getGreenMask() const -{ - return GreenMask; -} - - - -//! returns mask for blue value of a pixel -u32 CImage::getBlueMask() const -{ - return BlueMask; -} - - - -//! returns mask for alpha value of a pixel -u32 CImage::getAlphaMask() const -{ - return AlphaMask; -} - - -void CImage::setBitMasks() -{ - switch(Format) - { - case ECF_A1R5G5B5: - AlphaMask = 0x1<<15; - RedMask = 0x1F<<10; - GreenMask = 0x1F<<5; - BlueMask = 0x1F; - break; - case ECF_R5G6B5: - AlphaMask = 0x0; - RedMask = 0x1F<<11; - GreenMask = 0x3F<<5; - BlueMask = 0x1F; - break; - case ECF_R8G8B8: - AlphaMask = 0x0; - RedMask = 0x00FF0000; - GreenMask = 0x0000FF00; - BlueMask = 0x000000FF; - break; - case ECF_A8R8G8B8: - AlphaMask = 0xFF000000; - RedMask = 0x00FF0000; - GreenMask = 0x0000FF00; - BlueMask = 0x000000FF; - break; - } -} - - -u32 CImage::getBitsPerPixelFromFormat(ECOLOR_FORMAT format) -{ - switch(format) - { - case ECF_A1R5G5B5: - return 16; - case ECF_R5G6B5: - return 16; - case ECF_R8G8B8: - return 24; - case ECF_A8R8G8B8: - return 32; - } - - return 0; -} - -//! sets a pixel -void CImage::setPixel(u32 x, u32 y, const SColor &color ) -{ - if (x >= (u32)Size.Width || y >= (u32)Size.Height) - return; - - switch(Format) - { - case ECF_A1R5G5B5: - { - u16 * dest = (u16*) ((u8*) Data + ( y * Pitch ) + ( x << 1 )); - *dest = video::A8R8G8B8toA1R5G5B5( color.color ); - } break; - - case ECF_R5G6B5: - { - u16 * dest = (u16*) ((u8*) Data + ( y * Pitch ) + ( x << 1 )); - *dest = video::A8R8G8B8toR5G6B5( color.color ); - } break; - - case ECF_R8G8B8: - { - u8* dest = (u8*) Data + ( y * Pitch ) + ( x * 3 ); - dest[0] = (u8)color.getRed(); - dest[1] = (u8)color.getGreen(); - dest[2] = (u8)color.getBlue(); - } break; - - case ECF_A8R8G8B8: - { - u32 * dest = (u32*) ((u8*) Data + ( y * Pitch ) + ( x << 2 )); - *dest = color.color; - } break; - } -} - - -//! returns a pixel -SColor CImage::getPixel(u32 x, u32 y) const -{ - if (x >= (u32)Size.Width || y >= (u32)Size.Height) - return SColor(0); - - switch(Format) - { - case ECF_A1R5G5B5: - return A1R5G5B5toA8R8G8B8(((u16*)Data)[y*Size.Width + x]); - case ECF_R5G6B5: - return R5G6B5toA8R8G8B8(((u16*)Data)[y*Size.Width + x]); - case ECF_A8R8G8B8: - return ((u32*)Data)[y*Size.Width + x]; - case ECF_R8G8B8: - { - u8* p = &((u8*)Data)[(y*3)*Size.Width + (x*3)]; - return SColor(255,p[0],p[1],p[2]); - } - } - - return SColor(0); -} - - -//! returns the color format -ECOLOR_FORMAT CImage::getColorFormat() const -{ - return Format; -} - - -//! draws a rectangle -void CImage::drawRectangle(const core::rect& rect, const SColor &color) -{ - Blit(color.getAlpha() == 0xFF ? BLITTER_COLOR : BLITTER_COLOR_ALPHA, - this, 0, &rect.UpperLeftCorner, 0, &rect, color.color); -} - - -//! copies this surface into another -void CImage::copyTo(IImage* target, const core::position2d& pos) -{ - Blit(BLITTER_TEXTURE, target, 0, &pos, this, 0, 0); -} - - -//! copies this surface into another -void CImage::copyTo(IImage* target, const core::position2d& pos, const core::rect& sourceRect, const core::rect* clipRect) -{ - Blit(BLITTER_TEXTURE, target, clipRect, &pos, this, &sourceRect, 0); -} - - - -//! copies this surface into another, using the alpha mask, an cliprect and a color to add with -void CImage::copyToWithAlpha(IImage* target, const core::position2d& pos, const core::rect& sourceRect, const SColor &color, const core::rect* clipRect) -{ - // color blend only necessary on not full spectrum aka. color.color != 0xFFFFFFFF - Blit(color.color == 0xFFFFFFFF ? BLITTER_TEXTURE_ALPHA_BLEND: BLITTER_TEXTURE_ALPHA_COLOR_BLEND, - target, clipRect, &pos, this, &sourceRect, color.color); -} - - - -//! draws a line from to with color -void CImage::drawLine(const core::position2d& from, const core::position2d& to, const SColor &color) -{ - AbsRectangle clip; - GetClip( clip, this ); - - core::position2d p[2]; - - if ( ClipLine( clip, p[0], p[1], from, to ) ) - { - u32 alpha = extractAlpha( color.color ); - - switch ( Format ) - { - case ECF_A1R5G5B5: - if ( alpha == 256 ) - { - RenderLine16_Decal( this, p[0], p[1], video::A8R8G8B8toA1R5G5B5( color.color ) ); - } - else - { - RenderLine16_Blend( this, p[0], p[1], video::A8R8G8B8toA1R5G5B5( color.color ), alpha >> 3 ); - } - break; - case ECF_A8R8G8B8: - if ( alpha == 256 ) - { - RenderLine32_Decal( this, p[0], p[1], color.color ); - } - else - { - RenderLine32_Blend( this, p[0], p[1], color.color, alpha ); - } - break; - default: - break; - } - } -} - - - -//! copies this surface into another, scaling it to the target image size -// note: this is very very slow. (i didn't want to write a fast version. -// but hopefully, nobody wants to scale surfaces every frame. -void CImage::copyToScaling(void* target, u32 width, u32 height, ECOLOR_FORMAT format, u32 pitch) -{ - if (!target || !width || !height) - return; - - const u32 bpp=getBitsPerPixelFromFormat(format)/8; - if (0==pitch) - pitch = width*bpp; - - if (Format==format && Size.Width==width && Size.Height==height) - { - if (pitch==Pitch) - { - memcpy(target, Data, height*pitch); - return; - } - else - { - u8* tgtpos = (u8*) target; - u8* dstpos = (u8*) Data; - const u32 bwidth = width*bpp; - for (u32 y=0; y& targetSize = target->getDimension(); - - if (targetSize==Size) - { - copyTo(target); - return; - } - - copyToScaling(target->lock(), targetSize.Width, targetSize.Height, target->getColorFormat()); - target->unlock(); -} - -//! copies this surface into another, scaling it to fit it. -void CImage::copyToScalingBoxFilter(IImage* target, s32 bias) -{ - const core::dimension2d destSize = target->getDimension(); - - const f32 sourceXStep = (f32) Size.Width / (f32) destSize.Width; - const f32 sourceYStep = (f32) Size.Height / (f32) destSize.Height; - - target->lock(); - - s32 fx = core::ceil32( sourceXStep ); - s32 fy = core::ceil32( sourceYStep ); - f32 sx; - f32 sy; - - sy = 0.f; - for ( u32 y = 0; y != destSize.Height; ++y ) - { - sx = 0.f; - for ( u32 x = 0; x != destSize.Width; ++x ) - { - target->setPixel( x, y, getPixelBox( core::floor32(sx), core::floor32(sy), fx, fy, bias ) ); - sx += sourceXStep; - } - sy += sourceYStep; - } - - target->unlock(); -} - - -//! fills the surface with given color -void CImage::fill(const SColor &color) -{ - u32 c; - - switch ( Format ) - { - case ECF_A1R5G5B5: - c = video::A8R8G8B8toA1R5G5B5( color.color ); - c |= c << 16; - break; - case ECF_R5G6B5: - c = video::A8R8G8B8toR5G6B5( color.color ); - c |= c << 16; - break; - case ECF_A8R8G8B8: - c = color.color; - break; - default: -// os::Printer::log("CImage::Format not supported", ELL_ERROR); - return; - } - - memset32( Data, c, getImageDataSizeInBytes() ); -} - - -//! get a filtered pixel -inline SColor CImage::getPixelBox( s32 x, s32 y, s32 fx, s32 fy, s32 bias ) const -{ - SColor c; - s32 a = 0, r = 0, g = 0, b = 0; - - for ( s32 dx = 0; dx != fx; ++dx ) - { - for ( s32 dy = 0; dy != fy; ++dy ) - { - c = getPixel( x + dx , y + dy ); - - a += c.getAlpha(); - r += c.getRed(); - g += c.getGreen(); - b += c.getBlue(); - } - } - - s32 sdiv = s32_log2_s32(fx * fy); - - a = core::s32_clamp( ( a >> sdiv ) + bias, 0, 255 ); - r = core::s32_clamp( ( r >> sdiv ) + bias, 0, 255 ); - g = core::s32_clamp( ( g >> sdiv ) + bias, 0, 255 ); - b = core::s32_clamp( ( b >> sdiv ) + bias, 0, 255 ); - - c.set( a, r, g, b ); - return c; -} - - -} // end namespace video -} // end namespace irr - + +namespace irr +{ +namespace video +{ + +//! constructor +CImage::CImage(ECOLOR_FORMAT format, const core::dimension2d& size) +:Data(0), Size(size), Format(format), DeleteMemory(true) +{ + initData(); +} + + +//! constructor +CImage::CImage(ECOLOR_FORMAT format, const core::dimension2d& size, void* data, + bool ownForeignMemory, bool deleteForeignMemory) +: Data(0), Size(size), Format(format), DeleteMemory(deleteForeignMemory) +{ + if (ownForeignMemory) + { + Data = (void*)0xbadf00d; + initData(); + Data = data; + } + else + { + Data = 0; + initData(); + memcpy(Data, data, Size.Height * Pitch); + } +} + + + +//! constructor +CImage::CImage(ECOLOR_FORMAT format, IImage* imageToCopy) +: Data(0), Format(format), DeleteMemory(true) +{ + if (!imageToCopy) + return; + + Size = imageToCopy->getDimension(); + initData(); + + // now copy data from other image + + Blit ( BLITTER_TEXTURE, this, 0, 0, imageToCopy, 0,0 ); +} + + + +//! constructor +CImage::CImage(IImage* imageToCopy, const core::position2d& pos, + const core::dimension2d& size) + : Data(0), Size(0,0), DeleteMemory(true) +{ + if (!imageToCopy) + return; + + Format = imageToCopy->getColorFormat(); + Size = size; + + initData(); + + core::rect sClip( pos.X, pos.Y, pos.X + size.Width,pos.Y + size.Height ); + Blit (BLITTER_TEXTURE, this, 0, 0, imageToCopy, &sClip, 0); +} + + + +//! assumes format and size has been set and creates the rest +void CImage::initData() +{ + setBitMasks(); + BitsPerPixel = getBitsPerPixelFromFormat(Format); + BytesPerPixel = BitsPerPixel / 8; + + // Pitch should be aligned... + Pitch = BytesPerPixel * Size.Width; + + if (!Data) + Data = new s8[Size.Height * Pitch]; +} + + +//! destructor +CImage::~CImage() +{ + if ( DeleteMemory ) + delete [] (s8*)Data; +} + + +//! Returns width and height of image data. +const core::dimension2d& CImage::getDimension() const +{ + return Size; +} + + + +//! Returns bits per pixel. +u32 CImage::getBitsPerPixel() const +{ + return BitsPerPixel; +} + + +//! Returns bytes per pixel +u32 CImage::getBytesPerPixel() const +{ + return BytesPerPixel; +} + + + +//! Returns image data size in bytes +u32 CImage::getImageDataSizeInBytes() const +{ + return Pitch * Size.Height; +} + + + +//! Returns image data size in pixels +u32 CImage::getImageDataSizeInPixels() const +{ + return Size.Width * Size.Height; +} + + + +//! returns mask for red value of a pixel +u32 CImage::getRedMask() const +{ + return RedMask; +} + + + +//! returns mask for green value of a pixel +u32 CImage::getGreenMask() const +{ + return GreenMask; +} + + + +//! returns mask for blue value of a pixel +u32 CImage::getBlueMask() const +{ + return BlueMask; +} + + + +//! returns mask for alpha value of a pixel +u32 CImage::getAlphaMask() const +{ + return AlphaMask; +} + + +void CImage::setBitMasks() +{ + switch(Format) + { + case ECF_A1R5G5B5: + AlphaMask = 0x1<<15; + RedMask = 0x1F<<10; + GreenMask = 0x1F<<5; + BlueMask = 0x1F; + break; + case ECF_R5G6B5: + AlphaMask = 0x0; + RedMask = 0x1F<<11; + GreenMask = 0x3F<<5; + BlueMask = 0x1F; + break; + case ECF_R8G8B8: + AlphaMask = 0x0; + RedMask = 0x00FF0000; + GreenMask = 0x0000FF00; + BlueMask = 0x000000FF; + break; + case ECF_A8R8G8B8: + AlphaMask = 0xFF000000; + RedMask = 0x00FF0000; + GreenMask = 0x0000FF00; + BlueMask = 0x000000FF; + break; + } +} + + +u32 CImage::getBitsPerPixelFromFormat(ECOLOR_FORMAT format) +{ + switch(format) + { + case ECF_A1R5G5B5: + return 16; + case ECF_R5G6B5: + return 16; + case ECF_R8G8B8: + return 24; + case ECF_A8R8G8B8: + return 32; + } + + return 0; +} + +//! sets a pixel +void CImage::setPixel(u32 x, u32 y, const SColor &color ) +{ + if (x >= (u32)Size.Width || y >= (u32)Size.Height) + return; + + switch(Format) + { + case ECF_A1R5G5B5: + { + u16 * dest = (u16*) ((u8*) Data + ( y * Pitch ) + ( x << 1 )); + *dest = video::A8R8G8B8toA1R5G5B5( color.color ); + } break; + + case ECF_R5G6B5: + { + u16 * dest = (u16*) ((u8*) Data + ( y * Pitch ) + ( x << 1 )); + *dest = video::A8R8G8B8toR5G6B5( color.color ); + } break; + + case ECF_R8G8B8: + { + u8* dest = (u8*) Data + ( y * Pitch ) + ( x * 3 ); + dest[0] = (u8)color.getRed(); + dest[1] = (u8)color.getGreen(); + dest[2] = (u8)color.getBlue(); + } break; + + case ECF_A8R8G8B8: + { + u32 * dest = (u32*) ((u8*) Data + ( y * Pitch ) + ( x << 2 )); + *dest = color.color; + } break; + } +} + + +//! returns a pixel +SColor CImage::getPixel(u32 x, u32 y) const +{ + if (x >= (u32)Size.Width || y >= (u32)Size.Height) + return SColor(0); + + switch(Format) + { + case ECF_A1R5G5B5: + return A1R5G5B5toA8R8G8B8(((u16*)Data)[y*Size.Width + x]); + case ECF_R5G6B5: + return R5G6B5toA8R8G8B8(((u16*)Data)[y*Size.Width + x]); + case ECF_A8R8G8B8: + return ((u32*)Data)[y*Size.Width + x]; + case ECF_R8G8B8: + { + u8* p = &((u8*)Data)[(y*3)*Size.Width + (x*3)]; + return SColor(255,p[0],p[1],p[2]); + } + } + + return SColor(0); +} + + +//! returns the color format +ECOLOR_FORMAT CImage::getColorFormat() const +{ + return Format; +} + + +//! draws a rectangle +void CImage::drawRectangle(const core::rect& rect, const SColor &color) +{ + Blit(color.getAlpha() == 0xFF ? BLITTER_COLOR : BLITTER_COLOR_ALPHA, + this, 0, &rect.UpperLeftCorner, 0, &rect, color.color); +} + + +//! copies this surface into another +void CImage::copyTo(IImage* target, const core::position2d& pos) +{ + Blit(BLITTER_TEXTURE, target, 0, &pos, this, 0, 0); +} + + +//! copies this surface into another +void CImage::copyTo(IImage* target, const core::position2d& pos, const core::rect& sourceRect, const core::rect* clipRect) +{ + Blit(BLITTER_TEXTURE, target, clipRect, &pos, this, &sourceRect, 0); +} + + + +//! copies this surface into another, using the alpha mask, an cliprect and a color to add with +void CImage::copyToWithAlpha(IImage* target, const core::position2d& pos, const core::rect& sourceRect, const SColor &color, const core::rect* clipRect) +{ + // color blend only necessary on not full spectrum aka. color.color != 0xFFFFFFFF + Blit(color.color == 0xFFFFFFFF ? BLITTER_TEXTURE_ALPHA_BLEND: BLITTER_TEXTURE_ALPHA_COLOR_BLEND, + target, clipRect, &pos, this, &sourceRect, color.color); +} + + + +//! draws a line from to with color +void CImage::drawLine(const core::position2d& from, const core::position2d& to, const SColor &color) +{ + AbsRectangle clip; + GetClip( clip, this ); + + core::position2d p[2]; + + if ( ClipLine( clip, p[0], p[1], from, to ) ) + { + u32 alpha = extractAlpha( color.color ); + + switch ( Format ) + { + case ECF_A1R5G5B5: + if ( alpha == 256 ) + { + RenderLine16_Decal( this, p[0], p[1], video::A8R8G8B8toA1R5G5B5( color.color ) ); + } + else + { + RenderLine16_Blend( this, p[0], p[1], video::A8R8G8B8toA1R5G5B5( color.color ), alpha >> 3 ); + } + break; + case ECF_A8R8G8B8: + if ( alpha == 256 ) + { + RenderLine32_Decal( this, p[0], p[1], color.color ); + } + else + { + RenderLine32_Blend( this, p[0], p[1], color.color, alpha ); + } + break; + default: + break; + } + } +} + + + +//! copies this surface into another, scaling it to the target image size +// note: this is very very slow. (i didn't want to write a fast version. +// but hopefully, nobody wants to scale surfaces every frame. +void CImage::copyToScaling(void* target, u32 width, u32 height, ECOLOR_FORMAT format, u32 pitch) +{ + if (!target || !width || !height) + return; + + const u32 bpp=getBitsPerPixelFromFormat(format)/8; + if (0==pitch) + pitch = width*bpp; + + if (Format==format && Size.Width==width && Size.Height==height) + { + if (pitch==Pitch) + { + memcpy(target, Data, height*pitch); + return; + } + else + { + u8* tgtpos = (u8*) target; + u8* dstpos = (u8*) Data; + const u32 bwidth = width*bpp; + for (u32 y=0; y& targetSize = target->getDimension(); + + if (targetSize==Size) + { + copyTo(target); + return; + } + + copyToScaling(target->lock(), targetSize.Width, targetSize.Height, target->getColorFormat()); + target->unlock(); +} + +//! copies this surface into another, scaling it to fit it. +void CImage::copyToScalingBoxFilter(IImage* target, s32 bias) +{ + const core::dimension2d destSize = target->getDimension(); + + const f32 sourceXStep = (f32) Size.Width / (f32) destSize.Width; + const f32 sourceYStep = (f32) Size.Height / (f32) destSize.Height; + + target->lock(); + + s32 fx = core::ceil32( sourceXStep ); + s32 fy = core::ceil32( sourceYStep ); + f32 sx; + f32 sy; + + sy = 0.f; + for ( s32 y = 0; y != destSize.Height; ++y ) + { + sx = 0.f; + for ( s32 x = 0; x != destSize.Width; ++x ) + { + target->setPixel( x, y, getPixelBox( core::floor32(sx), core::floor32(sy), fx, fy, bias ) ); + sx += sourceXStep; + } + sy += sourceYStep; + } + + target->unlock(); +} + + +//! fills the surface with given color +void CImage::fill(const SColor &color) +{ + u32 c; + + switch ( Format ) + { + case ECF_A1R5G5B5: + c = video::A8R8G8B8toA1R5G5B5( color.color ); + c |= c << 16; + break; + case ECF_R5G6B5: + c = video::A8R8G8B8toR5G6B5( color.color ); + c |= c << 16; + break; + case ECF_A8R8G8B8: + c = color.color; + break; + default: +// os::Printer::log("CImage::Format not supported", ELL_ERROR); + return; + } + + memset32( Data, c, getImageDataSizeInBytes() ); +} + + +//! get a filtered pixel +inline SColor CImage::getPixelBox( s32 x, s32 y, s32 fx, s32 fy, s32 bias ) const +{ + SColor c; + s32 a = 0, r = 0, g = 0, b = 0; + + for ( s32 dx = 0; dx != fx; ++dx ) + { + for ( s32 dy = 0; dy != fy; ++dy ) + { + c = getPixel( x + dx , y + dy ); + + a += c.getAlpha(); + r += c.getRed(); + g += c.getGreen(); + b += c.getBlue(); + } + } + + s32 sdiv = s32_log2_s32(fx * fy); + + a = core::s32_clamp( ( a >> sdiv ) + bias, 0, 255 ); + r = core::s32_clamp( ( r >> sdiv ) + bias, 0, 255 ); + g = core::s32_clamp( ( g >> sdiv ) + bias, 0, 255 ); + b = core::s32_clamp( ( b >> sdiv ) + bias, 0, 255 ); + + c.set( a, r, g, b ); + return c; +} + + +} // end namespace video +} // end namespace irr diff --git a/source/Irrlicht/CImage.h b/source/Irrlicht/CImage.h index 67ead229..8645598d 100644 --- a/source/Irrlicht/CImage.h +++ b/source/Irrlicht/CImage.h @@ -105,7 +105,7 @@ public: const core::rect* clipRect = 0); //! copies this surface into another, scaling it to fit, appyling a box filter - void copyToScalingBoxFilter(IImage* target, s32 bias = 0); + virtual void copyToScalingBoxFilter(IImage* target, s32 bias = 0); //! fills the surface with black or white virtual void fill(const SColor &color); diff --git a/source/Irrlicht/CImageLoaderBMP.cpp b/source/Irrlicht/CImageLoaderBMP.cpp index 1224f860..ee2bf0a4 100644 --- a/source/Irrlicht/CImageLoaderBMP.cpp +++ b/source/Irrlicht/CImageLoaderBMP.cpp @@ -30,9 +30,9 @@ CImageLoaderBMP::CImageLoaderBMP() //! returns true if the file maybe is able to be loaded by this class //! based on the file extension (e.g. ".tga") -bool CImageLoaderBMP::isALoadableFileExtension(const c8* fileName) const +bool CImageLoaderBMP::isALoadableFileExtension(const core::string& filename) const { - return strstr(fileName, ".bmp") != 0; + return core::hasFileExtension ( filename, "bmp" ); } @@ -307,36 +307,41 @@ IImage* CImageLoaderBMP::loadImage(io::IReadFile* file) const // create surface + // no default constructor from packed area! ARM problem! + core::dimension2d dim; + dim.Width = header.Width; + dim.Height = header.Height; + IImage* image = 0; switch(header.BPP) { case 1: - image = new CImage(ECF_A1R5G5B5, core::dimension2d(header.Width, header.Height)); + image = new CImage(ECF_A1R5G5B5, dim); if (image) CColorConverter::convert1BitTo16Bit(bmpData, (s16*)image->lock(), header.Width, header.Height, pitch, true); break; case 4: - image = new CImage(ECF_A1R5G5B5, core::dimension2d(header.Width, header.Height)); + image = new CImage(ECF_A1R5G5B5, dim); if (image) CColorConverter::convert4BitTo16Bit(bmpData, (s16*)image->lock(), header.Width, header.Height, paletteData, pitch, true); break; case 8: - image = new CImage(ECF_A1R5G5B5, core::dimension2d(header.Width, header.Height)); + image = new CImage(ECF_A1R5G5B5, dim); if (image) CColorConverter::convert8BitTo16Bit(bmpData, (s16*)image->lock(), header.Width, header.Height, paletteData, pitch, true); break; case 16: - image = new CImage(ECF_A1R5G5B5, core::dimension2d(header.Width, header.Height)); + image = new CImage(ECF_A1R5G5B5, dim); if (image) CColorConverter::convert16BitTo16Bit((s16*)bmpData, (s16*)image->lock(), header.Width, header.Height, pitch, true); break; case 24: - image = new CImage(ECF_R8G8B8, core::dimension2d(header.Width, header.Height)); + image = new CImage(ECF_R8G8B8, dim); if (image) CColorConverter::convert24BitTo24Bit(bmpData, (u8*)image->lock(), header.Width, header.Height, pitch, true, true); break; case 32: // thx to Reinhard Ostermeier - image = new CImage(ECF_A8R8G8B8, core::dimension2d(header.Width, header.Height)); + image = new CImage(ECF_A8R8G8B8, dim); if (image) CColorConverter::convert32BitTo32Bit((s32*)bmpData, (s32*)image->lock(), header.Width, header.Height, pitch, true); break; diff --git a/source/Irrlicht/CImageLoaderBMP.h b/source/Irrlicht/CImageLoaderBMP.h index e7e4076d..6d7db4a3 100644 --- a/source/Irrlicht/CImageLoaderBMP.h +++ b/source/Irrlicht/CImageLoaderBMP.h @@ -85,7 +85,7 @@ public: //! returns true if the file maybe is able to be loaded by this class //! based on the file extension (e.g. ".tga") - virtual bool isALoadableFileExtension(const c8* fileName) const; + virtual bool isALoadableFileExtension(const core::string& filename) const; //! returns true if the file maybe is able to be loaded by this class virtual bool isALoadableFileFormat(io::IReadFile* file) const; diff --git a/source/Irrlicht/CImageLoaderJPG.cpp b/source/Irrlicht/CImageLoaderJPG.cpp index faf9394b..c4d7e8e0 100644 --- a/source/Irrlicht/CImageLoaderJPG.cpp +++ b/source/Irrlicht/CImageLoaderJPG.cpp @@ -35,9 +35,9 @@ CImageLoaderJPG::~CImageLoaderJPG() //! returns true if the file maybe is able to be loaded by this class //! based on the file extension (e.g. ".tga") -bool CImageLoaderJPG::isALoadableFileExtension(const c8* fileName) const +bool CImageLoaderJPG::isALoadableFileExtension(const core::string& filename) const { - return strstr(fileName, ".jpg") != 0; + return core::hasFileExtension ( filename, "jpg", "jpeg" ); } diff --git a/source/Irrlicht/CImageLoaderJPG.h b/source/Irrlicht/CImageLoaderJPG.h index 472c9b26..5a83d6d4 100644 --- a/source/Irrlicht/CImageLoaderJPG.h +++ b/source/Irrlicht/CImageLoaderJPG.h @@ -43,7 +43,7 @@ public: //! returns true if the file maybe is able to be loaded by this class //! based on the file extension (e.g. ".tga") - virtual bool isALoadableFileExtension(const c8* fileName) const; + virtual bool isALoadableFileExtension(const core::string& filename) const; //! returns true if the file maybe is able to be loaded by this class virtual bool isALoadableFileFormat(io::IReadFile* file) const; diff --git a/source/Irrlicht/CImageLoaderPCX.cpp b/source/Irrlicht/CImageLoaderPCX.cpp index f53c7d86..79972662 100644 --- a/source/Irrlicht/CImageLoaderPCX.cpp +++ b/source/Irrlicht/CImageLoaderPCX.cpp @@ -31,9 +31,9 @@ CImageLoaderPCX::CImageLoaderPCX() //! returns true if the file maybe is able to be loaded by this class //! based on the file extension (e.g. ".tga") -bool CImageLoaderPCX::isALoadableFileExtension(const c8* fileName) const +bool CImageLoaderPCX::isALoadableFileExtension(const core::string& filename) const { - return (strstr(fileName, ".PCX") != 0) || (strstr(fileName, ".pcx") != 0); + return core::hasFileExtension ( filename, "pcx" ); } diff --git a/source/Irrlicht/CImageLoaderPCX.h b/source/Irrlicht/CImageLoaderPCX.h index 1024e2c2..7ef0b8c5 100644 --- a/source/Irrlicht/CImageLoaderPCX.h +++ b/source/Irrlicht/CImageLoaderPCX.h @@ -73,7 +73,7 @@ public: //! returns true if the file maybe is able to be loaded by this class //! based on the file extension (e.g. ".tga") - virtual bool isALoadableFileExtension(const c8* fileName) const; + virtual bool isALoadableFileExtension(const core::string& filename) const; //! returns true if the file maybe is able to be loaded by this class virtual bool isALoadableFileFormat(io::IReadFile* file) const; diff --git a/source/Irrlicht/CImageLoaderPNG.cpp b/source/Irrlicht/CImageLoaderPNG.cpp index df432b76..78fcae5e 100644 --- a/source/Irrlicht/CImageLoaderPNG.cpp +++ b/source/Irrlicht/CImageLoaderPNG.cpp @@ -49,14 +49,10 @@ void PNGAPI user_read_data_fcn(png_structp png_ptr, png_bytep data, png_size_t l //! returns true if the file maybe is able to be loaded by this class //! based on the file extension (e.g. ".tga") -bool CImageLoaderPng::isALoadableFileExtension(const c8* fileName) const +bool CImageLoaderPng::isALoadableFileExtension(const core::string& filename) const { #ifdef _IRR_COMPILE_WITH_LIBPNG_ - // added fix for file extension check by jox - const c8* ext = strrchr(fileName, '.'); - if (ext == 0) - return false; - return (strcmp(ext, ".PNG") == 0) || (strcmp(ext, ".png") == 0); + return core::hasFileExtension ( filename, "png" ); #else return false; #endif // _IRR_COMPILE_WITH_LIBPNG_ diff --git a/source/Irrlicht/CImageLoaderPNG.h b/source/Irrlicht/CImageLoaderPNG.h index d10d1e6b..a3213c70 100644 --- a/source/Irrlicht/CImageLoaderPNG.h +++ b/source/Irrlicht/CImageLoaderPNG.h @@ -27,7 +27,7 @@ public: //! returns true if the file maybe is able to be loaded by this class //! based on the file extension (e.g. ".png") - virtual bool isALoadableFileExtension(const c8* fileName) const; + virtual bool isALoadableFileExtension(const core::string& filename) const; //! returns true if the file maybe is able to be loaded by this class virtual bool isALoadableFileFormat(io::IReadFile* file) const; diff --git a/source/Irrlicht/CImageLoaderPPM.cpp b/source/Irrlicht/CImageLoaderPPM.cpp index be7804d9..9ea22176 100644 --- a/source/Irrlicht/CImageLoaderPPM.cpp +++ b/source/Irrlicht/CImageLoaderPPM.cpp @@ -30,9 +30,9 @@ CImageLoaderPPM::CImageLoaderPPM() //! returns true if the file maybe is able to be loaded by this class //! based on the file extension (e.g. ".tga") -bool CImageLoaderPPM::isALoadableFileExtension(const c8* fileName) const +bool CImageLoaderPPM::isALoadableFileExtension(const core::string& filename) const { - return strstr(fileName, ".ppm") || strstr(fileName, ".pgm") || strstr(fileName, ".pbm"); + return core::hasFileExtension ( filename, "ppm", "pgm", "pbm" ); } diff --git a/source/Irrlicht/CImageLoaderPPM.h b/source/Irrlicht/CImageLoaderPPM.h index af71299f..25819dfd 100644 --- a/source/Irrlicht/CImageLoaderPPM.h +++ b/source/Irrlicht/CImageLoaderPPM.h @@ -31,7 +31,7 @@ public: //! returns true if the file maybe is able to be loaded by this class //! based on the file extension (e.g. ".tga") - virtual bool isALoadableFileExtension(const c8* fileName) const; + virtual bool isALoadableFileExtension(const core::string& filename) const; //! returns true if the file maybe is able to be loaded by this class virtual bool isALoadableFileFormat(io::IReadFile* file) const; diff --git a/source/Irrlicht/CImageLoaderPSD.cpp b/source/Irrlicht/CImageLoaderPSD.cpp index 247c3c20..5526eb93 100644 --- a/source/Irrlicht/CImageLoaderPSD.cpp +++ b/source/Irrlicht/CImageLoaderPSD.cpp @@ -29,9 +29,9 @@ CImageLoaderPSD::CImageLoaderPSD() //! returns true if the file maybe is able to be loaded by this class //! based on the file extension (e.g. ".tga") -bool CImageLoaderPSD::isALoadableFileExtension(const c8* fileName) const +bool CImageLoaderPSD::isALoadableFileExtension(const core::string& filename) const { - return strstr(fileName, ".psd") != 0; + return core::hasFileExtension ( filename, "psd" ); } diff --git a/source/Irrlicht/CImageLoaderPSD.h b/source/Irrlicht/CImageLoaderPSD.h index 6b6cad06..4cd36e79 100644 --- a/source/Irrlicht/CImageLoaderPSD.h +++ b/source/Irrlicht/CImageLoaderPSD.h @@ -60,7 +60,7 @@ public: //! returns true if the file maybe is able to be loaded by this class //! based on the file extension (e.g. ".tga") - virtual bool isALoadableFileExtension(const c8* fileName) const; + virtual bool isALoadableFileExtension(const core::string& filename) const; //! returns true if the file maybe is able to be loaded by this class virtual bool isALoadableFileFormat(io::IReadFile* file) const; diff --git a/source/Irrlicht/CImageLoaderTGA.cpp b/source/Irrlicht/CImageLoaderTGA.cpp index bb2193dd..0f006ff8 100644 --- a/source/Irrlicht/CImageLoaderTGA.cpp +++ b/source/Irrlicht/CImageLoaderTGA.cpp @@ -21,9 +21,9 @@ namespace video //! returns true if the file maybe is able to be loaded by this class //! based on the file extension (e.g. ".tga") -bool CImageLoaderTGA::isALoadableFileExtension(const c8* fileName) const +bool CImageLoaderTGA::isALoadableFileExtension(const core::string& filename) const { - return (strstr(fileName, ".tga") != 0) || (strstr(fileName, ".TGA") != 0); + return core::hasFileExtension ( filename, "tga" ); } @@ -96,7 +96,7 @@ bool CImageLoaderTGA::isALoadableFileFormat(io::IReadFile* file) const IImage* CImageLoaderTGA::loadImage(io::IReadFile* file) const { STGAHeader header; - u8* colorMap = 0; + u32 *palette = 0; file->read(&header, sizeof(STGAHeader)); @@ -112,16 +112,37 @@ IImage* CImageLoaderTGA::loadImage(io::IReadFile* file) const if (header.ColorMapType) { + // create 32 bit palette + palette = new u32[ header.ColorMapLength]; + // read color map - colorMap = new u8[header.ColorMapEntrySize/8 * header.ColorMapLength]; + u8 * colorMap = new u8[header.ColorMapEntrySize/8 * header.ColorMapLength]; file->read(colorMap,header.ColorMapEntrySize/8 * header.ColorMapLength); + + // convert to 32-bit palette + switch ( header.ColorMapEntrySize ) + { + case 16: + CColorConverter::convert_A1R5G5B5toA8R8G8B8(colorMap, header.ColorMapLength, palette); + break; + case 24: + CColorConverter::convert_B8G8R8toA8R8G8B8(colorMap, header.ColorMapLength, palette); + break; + case 32: + CColorConverter::convert_B8G8R8A8toA8R8G8B8(colorMap, header.ColorMapLength, palette); + break; + } + delete [] colorMap; } // read image u8* data = 0; - if (header.ImageType == 2) + if ( header.ImageType == 1 || // Uncompressed, color-mapped images. + header.ImageType == 2 || // Uncompressed, RGB images + header.ImageType == 3 // Uncompressed, black and white images + ) { const s32 imageSize = header.ImageHeight * header.ImageWidth * header.PixelDepth/8; data = new u8[imageSize]; @@ -129,12 +150,14 @@ IImage* CImageLoaderTGA::loadImage(io::IReadFile* file) const } else if(header.ImageType == 10) + { + // Runlength encoded RGB images data = loadCompressedImage(file, header); + } else { os::Printer::log("Unsupported TGA file type", file->getFileName(), ELL_ERROR); - if (colorMap) - delete [] colorMap; + delete [] palette; return 0; } @@ -142,32 +165,37 @@ IImage* CImageLoaderTGA::loadImage(io::IReadFile* file) const switch(header.PixelDepth) { + case 8: + image = new CImage(ECF_A1R5G5B5, + core::dimension2d(header.ImageWidth, header.ImageHeight)); + if (image) + CColorConverter::convert8BitTo16Bit((u8*)data, + (s16*)image->lock(), + header.ImageWidth,header.ImageHeight, + header.ImageType == 3 ? 0 : (s32*) palette, + 0, + (header.ImageDescriptor&0x20)==0); + break; case 16: - { - image = new CImage(ECF_A1R5G5B5, - core::dimension2d(header.ImageWidth, header.ImageHeight)); - if (image) - CColorConverter::convert16BitTo16Bit((s16*)data, - (s16*)image->lock(), header.ImageWidth, header.ImageHeight, 0, (header.ImageDescriptor&0x20)==0); - } + image = new CImage(ECF_A1R5G5B5, + core::dimension2d(header.ImageWidth, header.ImageHeight)); + if (image) + CColorConverter::convert16BitTo16Bit((s16*)data, + (s16*)image->lock(), header.ImageWidth, header.ImageHeight, 0, (header.ImageDescriptor&0x20)==0); break; case 24: - { image = new CImage(ECF_R8G8B8, core::dimension2d(header.ImageWidth, header.ImageHeight)); if (image) CColorConverter::convert24BitTo24Bit( (u8*)data, (u8*)image->lock(), header.ImageWidth, header.ImageHeight, 0, (header.ImageDescriptor&0x20)==0, true); - } break; case 32: - { image = new CImage(ECF_A8R8G8B8, core::dimension2d(header.ImageWidth, header.ImageHeight)); if (image) CColorConverter::convert32BitTo32Bit((s32*)data, (s32*)image->lock(), header.ImageWidth, header.ImageHeight, 0, (header.ImageDescriptor&0x20)==0); - } break; default: os::Printer::log("Unsupported TGA format", file->getFileName(), ELL_ERROR); @@ -175,15 +203,14 @@ IImage* CImageLoaderTGA::loadImage(io::IReadFile* file) const } if (image) image->unlock(); + delete [] data; - if (colorMap) - delete [] colorMap; + delete [] palette; return image; } - //! creates a loader which is able to load tgas IImageLoader* createImageLoaderTGA() { diff --git a/source/Irrlicht/CImageLoaderTGA.h b/source/Irrlicht/CImageLoaderTGA.h index 26429d8b..afbd012f 100644 --- a/source/Irrlicht/CImageLoaderTGA.h +++ b/source/Irrlicht/CImageLoaderTGA.h @@ -68,7 +68,7 @@ public: //! returns true if the file maybe is able to be loaded by this class //! based on the file extension (e.g. ".tga") - virtual bool isALoadableFileExtension(const c8* fileName) const; + virtual bool isALoadableFileExtension(const core::string& filename) const; //! returns true if the file maybe is able to be loaded by this class virtual bool isALoadableFileFormat(io::IReadFile* file) const; diff --git a/source/Irrlicht/CImageLoaderWAL.cpp b/source/Irrlicht/CImageLoaderWAL.cpp index 53c9a040..251bcba0 100644 --- a/source/Irrlicht/CImageLoaderWAL.cpp +++ b/source/Irrlicht/CImageLoaderWAL.cpp @@ -51,9 +51,9 @@ s32 CImageLoaderWAL::DefaultPaletteQ2[256] = { }; -bool CImageLoaderWAL::isALoadableFileExtension(const c8* fileName) const +bool CImageLoaderWAL::isALoadableFileExtension(const core::string& filename) const { - return strstr(fileName, ".wal") != 0; + return core::hasFileExtension ( filename, "wal" ); } diff --git a/source/Irrlicht/CImageLoaderWAL.h b/source/Irrlicht/CImageLoaderWAL.h index de6e819d..613acbbc 100644 --- a/source/Irrlicht/CImageLoaderWAL.h +++ b/source/Irrlicht/CImageLoaderWAL.h @@ -52,7 +52,7 @@ namespace video class CImageLoaderWAL : public irr::video::IImageLoader { public: - virtual bool isALoadableFileExtension(const c8* fileName) const; + virtual bool isALoadableFileExtension(const core::string& filename) const; virtual bool isALoadableFileFormat(irr::io::IReadFile* file) const; diff --git a/source/Irrlicht/CImageWriterBMP.cpp b/source/Irrlicht/CImageWriterBMP.cpp index f4c7689b..3c2194e2 100644 --- a/source/Irrlicht/CImageWriterBMP.cpp +++ b/source/Irrlicht/CImageWriterBMP.cpp @@ -28,9 +28,9 @@ CImageWriterBMP::CImageWriterBMP() #endif } -bool CImageWriterBMP::isAWriteableFileExtension(const c8* fileName) const +bool CImageWriterBMP::isAWriteableFileExtension(const core::string& filename) const { - return strstr(fileName, ".bmp") != 0; + return core::hasFileExtension ( filename, "bmp" ); } bool CImageWriterBMP::writeImage(io::IWriteFile* file, IImage* image, u32 param) const diff --git a/source/Irrlicht/CImageWriterBMP.h b/source/Irrlicht/CImageWriterBMP.h index 759c1834..62f34463 100644 --- a/source/Irrlicht/CImageWriterBMP.h +++ b/source/Irrlicht/CImageWriterBMP.h @@ -23,7 +23,7 @@ public: CImageWriterBMP(); //! return true if this writer can write a file with the given extension - virtual bool isAWriteableFileExtension(const c8* fileName) const; + virtual bool isAWriteableFileExtension(const core::string& filename) const; //! write image to file virtual bool writeImage(io::IWriteFile *file, IImage *image, u32 param) const; diff --git a/source/Irrlicht/CImageWriterJPG.cpp b/source/Irrlicht/CImageWriterJPG.cpp index bf285659..c7736f1f 100644 --- a/source/Irrlicht/CImageWriterJPG.cpp +++ b/source/Irrlicht/CImageWriterJPG.cpp @@ -203,10 +203,9 @@ CImageWriterJPG::CImageWriterJPG() } -bool CImageWriterJPG::isAWriteableFileExtension(const c8* fileName) const +bool CImageWriterJPG::isAWriteableFileExtension(const core::string& filename) const { - const char* dot = strrchr (fileName, '.'); - return dot && (!strcmp (dot, ".jpg") || !strcmp (dot, ".jpeg")); + return core::hasFileExtension ( filename, "jpg", "jpeg" ); } diff --git a/source/Irrlicht/CImageWriterJPG.h b/source/Irrlicht/CImageWriterJPG.h index f44cd563..7d1b61ac 100644 --- a/source/Irrlicht/CImageWriterJPG.h +++ b/source/Irrlicht/CImageWriterJPG.h @@ -23,7 +23,7 @@ public: CImageWriterJPG(); //! return true if this writer can write a file with the given extension - virtual bool isAWriteableFileExtension(const c8* fileName) const; + virtual bool isAWriteableFileExtension(const core::string& filename) const; //! write image to file virtual bool writeImage(io::IWriteFile *file, IImage *image, u32 param) const; diff --git a/source/Irrlicht/CImageWriterPCX.cpp b/source/Irrlicht/CImageWriterPCX.cpp index 31f52d42..bea56012 100644 --- a/source/Irrlicht/CImageWriterPCX.cpp +++ b/source/Irrlicht/CImageWriterPCX.cpp @@ -28,9 +28,9 @@ CImageWriterPCX::CImageWriterPCX() #endif } -bool CImageWriterPCX::isAWriteableFileExtension(const c8* fileName) const +bool CImageWriterPCX::isAWriteableFileExtension(const core::string& filename) const { - return strstr(fileName, ".pcx") != 0; + return core::hasFileExtension ( filename, "pcx" ); } bool CImageWriterPCX::writeImage(io::IWriteFile *file, IImage *image,u32 param) const diff --git a/source/Irrlicht/CImageWriterPCX.h b/source/Irrlicht/CImageWriterPCX.h index 7cf09f12..d4698c59 100644 --- a/source/Irrlicht/CImageWriterPCX.h +++ b/source/Irrlicht/CImageWriterPCX.h @@ -23,7 +23,7 @@ public: CImageWriterPCX(); //! return true if this writer can write a file with the given extension - virtual bool isAWriteableFileExtension(const c8* fileName) const; + virtual bool isAWriteableFileExtension(const core::string& filename) const; //! write image to file virtual bool writeImage(io::IWriteFile *file, IImage *image, u32 param) const; diff --git a/source/Irrlicht/CImageWriterPNG.cpp b/source/Irrlicht/CImageWriterPNG.cpp index 75704b89..4ad2e2ff 100644 --- a/source/Irrlicht/CImageWriterPNG.cpp +++ b/source/Irrlicht/CImageWriterPNG.cpp @@ -58,10 +58,10 @@ CImageWriterPNG::CImageWriterPNG() #endif } -bool CImageWriterPNG::isAWriteableFileExtension(const c8* fileName) const +bool CImageWriterPNG::isAWriteableFileExtension(const core::string& filename) const { #ifdef _IRR_COMPILE_WITH_LIBPNG_ - return strstr(fileName, ".png") != 0; + return core::hasFileExtension ( filename, "png" ); #else return false; #endif diff --git a/source/Irrlicht/CImageWriterPNG.h b/source/Irrlicht/CImageWriterPNG.h index 0b45ed80..18abe137 100644 --- a/source/Irrlicht/CImageWriterPNG.h +++ b/source/Irrlicht/CImageWriterPNG.h @@ -23,7 +23,7 @@ public: CImageWriterPNG(); //! return true if this writer can write a file with the given extension - virtual bool isAWriteableFileExtension(const c8* fileName) const; + virtual bool isAWriteableFileExtension(const core::string& filename) const; //! write image to file virtual bool writeImage(io::IWriteFile *file, IImage *image, u32 param) const; diff --git a/source/Irrlicht/CImageWriterPPM.cpp b/source/Irrlicht/CImageWriterPPM.cpp index 9610458f..d4168b0d 100644 --- a/source/Irrlicht/CImageWriterPPM.cpp +++ b/source/Irrlicht/CImageWriterPPM.cpp @@ -31,9 +31,9 @@ CImageWriterPPM::CImageWriterPPM() } -bool CImageWriterPPM::isAWriteableFileExtension(const c8* fileName) const +bool CImageWriterPPM::isAWriteableFileExtension(const core::string& filename) const { - return strstr(fileName, ".ppm") != 0; + return core::hasFileExtension ( filename, "ppm" ); } diff --git a/source/Irrlicht/CImageWriterPPM.h b/source/Irrlicht/CImageWriterPPM.h index 99a68a9e..c29a3963 100644 --- a/source/Irrlicht/CImageWriterPPM.h +++ b/source/Irrlicht/CImageWriterPPM.h @@ -23,7 +23,7 @@ public: CImageWriterPPM(); //! return true if this writer can write a file with the given extension - virtual bool isAWriteableFileExtension(const c8* fileName) const; + virtual bool isAWriteableFileExtension(const core::string& filename) const; //! write image to file virtual bool writeImage(io::IWriteFile *file, IImage *image, u32 param) const; diff --git a/source/Irrlicht/CImageWriterPSD.cpp b/source/Irrlicht/CImageWriterPSD.cpp index 25c4d5b7..91c6ba21 100644 --- a/source/Irrlicht/CImageWriterPSD.cpp +++ b/source/Irrlicht/CImageWriterPSD.cpp @@ -28,9 +28,9 @@ CImageWriterPSD::CImageWriterPSD() #endif } -bool CImageWriterPSD::isAWriteableFileExtension(const c8* fileName) const +bool CImageWriterPSD::isAWriteableFileExtension(const core::string& filename) const { - return strstr(fileName, ".psd") != 0; + return core::hasFileExtension ( filename, "psd" ); } bool CImageWriterPSD::writeImage(io::IWriteFile *file, IImage *image,u32 param) const diff --git a/source/Irrlicht/CImageWriterPSD.h b/source/Irrlicht/CImageWriterPSD.h index bf0be8d1..ec94ace4 100644 --- a/source/Irrlicht/CImageWriterPSD.h +++ b/source/Irrlicht/CImageWriterPSD.h @@ -23,7 +23,7 @@ public: CImageWriterPSD(); //! return true if this writer can write a file with the given extension - virtual bool isAWriteableFileExtension(const c8* fileName) const; + virtual bool isAWriteableFileExtension(const core::string& filename) const; //! write image to file virtual bool writeImage(io::IWriteFile *file, IImage *image,u32 param) const; diff --git a/source/Irrlicht/CImageWriterTGA.cpp b/source/Irrlicht/CImageWriterTGA.cpp index 7016c67c..42ff8926 100644 --- a/source/Irrlicht/CImageWriterTGA.cpp +++ b/source/Irrlicht/CImageWriterTGA.cpp @@ -28,9 +28,9 @@ CImageWriterTGA::CImageWriterTGA() #endif } -bool CImageWriterTGA::isAWriteableFileExtension(const c8* fileName) const +bool CImageWriterTGA::isAWriteableFileExtension(const core::string& filename) const { - return strstr(fileName, ".tga") != 0; + return core::hasFileExtension ( filename, "tga" ); } bool CImageWriterTGA::writeImage(io::IWriteFile *file, IImage *image,u32 param) const diff --git a/source/Irrlicht/CImageWriterTGA.h b/source/Irrlicht/CImageWriterTGA.h index 7f24338f..5aa0da6f 100644 --- a/source/Irrlicht/CImageWriterTGA.h +++ b/source/Irrlicht/CImageWriterTGA.h @@ -23,7 +23,7 @@ public: CImageWriterTGA(); //! return true if this writer can write a file with the given extension - virtual bool isAWriteableFileExtension(const c8* fileName) const; + virtual bool isAWriteableFileExtension(const core::string& filename) const; //! write image to file virtual bool writeImage(io::IWriteFile *file, IImage *image,u32 param) const; diff --git a/source/Irrlicht/CIrrDeviceLinux.cpp b/source/Irrlicht/CIrrDeviceLinux.cpp index 47a10264..354b2785 100644 --- a/source/Irrlicht/CIrrDeviceLinux.cpp +++ b/source/Irrlicht/CIrrDeviceLinux.cpp @@ -722,6 +722,7 @@ bool CIrrDeviceLinux::run() if ((CreationParams.DriverType != video::EDT_NULL) && display) { SEvent irrevent; + irrevent.MouseInput.ButtonStates = -1; while (XPending(display) > 0 && !Close) { diff --git a/source/Irrlicht/CIrrDeviceSDL.cpp b/source/Irrlicht/CIrrDeviceSDL.cpp index 886856db..f5024ca6 100644 --- a/source/Irrlicht/CIrrDeviceSDL.cpp +++ b/source/Irrlicht/CIrrDeviceSDL.cpp @@ -246,6 +246,7 @@ bool CIrrDeviceSDL::run() os::Timer::tick(); SEvent irrevent; + irrevent.MouseInput.ButtonStates = -1; SDL_Event SDL_event; while ( !Close && SDL_PollEvent( &SDL_event ) ) @@ -305,8 +306,8 @@ bool CIrrDeviceSDL::run() irrevent.KeyInput.Char = SDL_event.key.keysym.unicode; irrevent.KeyInput.Key = (EKEY_CODE)KeyMap[idx].Win32Key; irrevent.KeyInput.PressedDown = (SDL_event.type == SDL_KEYDOWN); - irrevent.KeyInput.Shift = SDL_event.key.keysym.mod & KMOD_SHIFT; - irrevent.KeyInput.Control = SDL_event.key.keysym.mod & KMOD_CTRL; + irrevent.KeyInput.Shift = (SDL_event.key.keysym.mod & KMOD_SHIFT) != 0; + irrevent.KeyInput.Control = (SDL_event.key.keysym.mod & KMOD_CTRL ) != 0; postEventFromUser(irrevent); } else @@ -336,7 +337,7 @@ bool CIrrDeviceSDL::run() SDL_FreeSurface(Screen); Screen = SDL_SetVideoMode( Width, Height, CreationParams.Bits, SDL_Flags ); if (VideoDriver) - VideoDriver->OnResize(core::dimension2d(Width, Height)); + VideoDriver->OnResize(core::dimension2d(Width, Height)); } break; @@ -614,7 +615,7 @@ video::IVideoModeList* CIrrDeviceSDL::getVideoModeList() else { for (u32 i=0; modes[i]; ++i) - VideoModeList.addMode(core::dimension2d(modes[i]->w, modes[i]->h), vi->vfmt->BitsPerPixel); + VideoModeList.addMode(core::dimension2d(modes[i]->w, modes[i]->h), vi->vfmt->BitsPerPixel); } } } diff --git a/source/Irrlicht/CIrrDeviceStub.cpp b/source/Irrlicht/CIrrDeviceStub.cpp index 87cd5f12..63df16a1 100644 --- a/source/Irrlicht/CIrrDeviceStub.cpp +++ b/source/Irrlicht/CIrrDeviceStub.cpp @@ -257,5 +257,60 @@ bool CIrrDeviceStub::activateJoysticks(core::array & joystickInfo return false; } +/*! +*/ +void CIrrDeviceStub::calculateGammaRamp ( u16 *ramp, f32 gamma, f32 relativebrightness, f32 relativecontrast ) +{ + s32 i; + s32 value; + s32 rbright = (s32) ( relativebrightness * (65535.f / 4 ) ); + f32 rcontrast = 1.f / (255.f - ( relativecontrast * 127.5f ) ); + + gamma = gamma > 0.f ? 1.0f / gamma : 0.f; + + for ( i = 0; i < 256; ++i ) + { + value = (s32)(powf( rcontrast * i, gamma)*65535.f + 0.5f ); + ramp[i] = (u16) core::s32_clamp ( value + rbright, 0, 65535 ); + } + +} + +void CIrrDeviceStub::calculateGammaFromRamp ( f32 &gamma, const u16 *ramp ) +{ + /* The following is adapted from a post by Garrett Bass on OpenGL + Gamedev list, March 4, 2000. + */ + f32 sum = 0.0; + s32 i, count = 0; + + gamma = 1.0; + for ( i = 1; i < 256; ++i ) { + if ( (ramp[i] != 0) && (ramp[i] != 65535) ) { + f32 B = (f32)i / 256.f; + f32 A = ramp[i] / 65535.f; + sum += (f32) ( logf(A) / logf(B) ); + count++; + } + } + if ( count && sum ) { + gamma = 1.0f / (sum / count); + } + +} + +//! Set the current Gamma Value for the Display +bool CIrrDeviceStub::setGammaRamp( f32 red, f32 green, f32 blue, f32 brightness, f32 contrast ) +{ + return false; +} + +//! Get the current Gamma Value for the Display +bool CIrrDeviceStub::getGammaRamp( f32 &red, f32 &green, f32 &blue, f32 &brightness, f32 &contrast ) +{ + return false; +} + + } // end namespace irr diff --git a/source/Irrlicht/CIrrDeviceStub.h b/source/Irrlicht/CIrrDeviceStub.h index e4b5e046..53cc29b1 100644 --- a/source/Irrlicht/CIrrDeviceStub.h +++ b/source/Irrlicht/CIrrDeviceStub.h @@ -110,6 +110,12 @@ namespace irr //! Activate any joysticks, and generate events for them. virtual bool activateJoysticks(core::array & joystickInfo); + //! Set the current Gamma Value for the Display + virtual bool setGammaRamp( f32 red, f32 green, f32 blue, f32 brightness, f32 contrast ); + + //! Get the current Gamma Value for the Display + virtual bool getGammaRamp( f32 &red, f32 &green, f32 &blue, f32 &brightness, f32 &contrast ); + protected: void createGUIAndScene(); @@ -129,6 +135,10 @@ namespace irr scene::ISceneManager* InputReceivingSceneManager; video::CVideoModeList VideoModeList; SIrrlichtCreationParameters CreationParams; + + void calculateGammaRamp ( u16 *ramp, f32 gamma, f32 relativebrightness, f32 relativecontrast ); + void calculateGammaFromRamp ( f32 &gamma, const u16 *ramp ); + }; } // end namespace irr diff --git a/source/Irrlicht/CIrrDeviceWin32.cpp b/source/Irrlicht/CIrrDeviceWin32.cpp index 6118e5ba..eab9a581 100644 --- a/source/Irrlicht/CIrrDeviceWin32.cpp +++ b/source/Irrlicht/CIrrDeviceWin32.cpp @@ -87,6 +87,74 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) if (GetCapture() != hWnd && ClickCount > 0) ClickCount = 0; + + struct messageMap + { + irr::s32 group; + UINT winMessage; + irr::s32 irrMessage; + }; + + static messageMap mouseMap[] = + { + 0, WM_LBUTTONDOWN,irr::EMIE_LMOUSE_PRESSED_DOWN, + 1, WM_LBUTTONUP,irr::EMIE_LMOUSE_LEFT_UP, + 0, WM_RBUTTONDOWN,irr::EMIE_RMOUSE_PRESSED_DOWN, + 1, WM_RBUTTONUP,irr::EMIE_RMOUSE_LEFT_UP, + 0, WM_MBUTTONDOWN, irr::EMIE_MMOUSE_PRESSED_DOWN, + 1, WM_MBUTTONUP,irr::EMIE_MMOUSE_LEFT_UP, + 2, WM_MOUSEMOVE,irr::EMIE_MOUSE_MOVED, + 3, WM_MOUSEWHEEL,irr::EMIE_MOUSE_WHEEL, + -1,0,0 + }; + + // handle grouped events + messageMap * m = mouseMap; + while ( m->group >=0 && m->winMessage != message ) + m += 1; + + if ( m->group >= 0 ) + { + if ( m->group == 0 ) // down + { + ClickCount++; + SetCapture(hWnd); + } + else + if ( m->group == 1 ) // up + { + ClickCount--; + if (ClickCount<1) + { + ClickCount=0; + ReleaseCapture(); + } + } + + event.EventType = irr::EET_MOUSE_INPUT_EVENT; + event.MouseInput.Event = (irr::EMOUSE_INPUT_EVENT) m->irrMessage; + event.MouseInput.X = (short)LOWORD(lParam); + event.MouseInput.Y = (short)HIWORD(lParam); + event.MouseInput.ButtonStates = wParam & ( MK_LBUTTON | MK_RBUTTON | MK_MBUTTON ); + event.MouseInput.Wheel = 0.f; + + // wheel + if ( m->group == 3 ) + { + POINT p; // fixed by jox + p.x = 0; p.y = 0; + ClientToScreen(hWnd, &p); + event.MouseInput.X -= p.x; + event.MouseInput.Y -= p.y; + event.MouseInput.Wheel = ((irr::f32)((short)HIWORD(wParam))) / (irr::f32)WHEEL_DELTA; + } + + dev = getDeviceFromHWnd(hWnd); + if (dev) + dev->postEventFromUser(event); + return 0; + } + switch (message) { case WM_PAINT: @@ -108,120 +176,7 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) SetCursor(NULL); return 0; } - } - break; - - case WM_MOUSEWHEEL: - event.EventType = irr::EET_MOUSE_INPUT_EVENT; - event.MouseInput.Wheel = ((irr::f32)((short)HIWORD(wParam))) / (irr::f32)WHEEL_DELTA; - event.MouseInput.Event = irr::EMIE_MOUSE_WHEEL; - - POINT p; // fixed by jox - p.x = 0; p.y = 0; - ClientToScreen(hWnd, &p); - event.MouseInput.X = LOWORD(lParam) - p.x; - event.MouseInput.Y = HIWORD(lParam) - p.y; - - dev = getDeviceFromHWnd(hWnd); - if (dev) - dev->postEventFromUser(event); - break; - - case WM_LBUTTONDOWN: - ClickCount++; - SetCapture(hWnd); - event.EventType = irr::EET_MOUSE_INPUT_EVENT; - event.MouseInput.Event = irr::EMIE_LMOUSE_PRESSED_DOWN; - event.MouseInput.X = (short)LOWORD(lParam); - event.MouseInput.Y = (short)HIWORD(lParam); - dev = getDeviceFromHWnd(hWnd); - if (dev) - dev->postEventFromUser(event); - return 0; - - case WM_LBUTTONUP: - ClickCount--; - if (ClickCount<1) - { - ClickCount=0; - ReleaseCapture(); - } - event.EventType = irr::EET_MOUSE_INPUT_EVENT; - event.MouseInput.Event = irr::EMIE_LMOUSE_LEFT_UP; - event.MouseInput.X = (short)LOWORD(lParam); - event.MouseInput.Y = (short)HIWORD(lParam); - dev = getDeviceFromHWnd(hWnd); - if (dev) - dev->postEventFromUser(event); - return 0; - - case WM_RBUTTONDOWN: - ClickCount++; - SetCapture(hWnd); - event.EventType = irr::EET_MOUSE_INPUT_EVENT; - event.MouseInput.Event = irr::EMIE_RMOUSE_PRESSED_DOWN; - event.MouseInput.X = (short)LOWORD(lParam); - event.MouseInput.Y = (short)HIWORD(lParam); - dev = getDeviceFromHWnd(hWnd); - if (dev) - dev->postEventFromUser(event); - return 0; - - case WM_RBUTTONUP: - ClickCount--; - if (ClickCount<1) - { - ClickCount=0; - ReleaseCapture(); - } - event.EventType = irr::EET_MOUSE_INPUT_EVENT; - event.MouseInput.Event = irr::EMIE_RMOUSE_LEFT_UP; - event.MouseInput.X = (short)LOWORD(lParam); - event.MouseInput.Y = (short)HIWORD(lParam); - dev = getDeviceFromHWnd(hWnd); - if (dev) - dev->postEventFromUser(event); - return 0; - - case WM_MBUTTONDOWN: - ClickCount++; - SetCapture(hWnd); - event.EventType = irr::EET_MOUSE_INPUT_EVENT; - event.MouseInput.Event = irr::EMIE_MMOUSE_PRESSED_DOWN; - event.MouseInput.X = (short)LOWORD(lParam); - event.MouseInput.Y = (short)HIWORD(lParam); - dev = getDeviceFromHWnd(hWnd); - if (dev) - dev->postEventFromUser(event); - return 0; - - case WM_MBUTTONUP: - ClickCount--; - if (ClickCount<1) - { - ClickCount=0; - ReleaseCapture(); - } - event.EventType = irr::EET_MOUSE_INPUT_EVENT; - event.MouseInput.Event = irr::EMIE_MMOUSE_LEFT_UP; - event.MouseInput.X = (short)LOWORD(lParam); - event.MouseInput.Y = (short)HIWORD(lParam); - dev = getDeviceFromHWnd(hWnd); - if (dev) - dev->postEventFromUser(event); - return 0; - - case WM_MOUSEMOVE: - event.EventType = irr::EET_MOUSE_INPUT_EVENT; - event.MouseInput.Event = irr::EMIE_MOUSE_MOVED; - event.MouseInput.X = (short)LOWORD(lParam); - event.MouseInput.Y = (short)HIWORD(lParam); - dev = getDeviceFromHWnd(hWnd); - - if (dev) - dev->postEventFromUser(event); - - return 0; + } break; case WM_KEYDOWN: case WM_KEYUP: @@ -1082,6 +1037,46 @@ void CIrrDeviceWin32::pollJoysticks() #endif // _IRR_COMPILE_WITH_JOYSTICK_EVENTS_ } +//! Set the current Gamma Value for the Display +bool CIrrDeviceWin32::setGammaRamp( f32 red, f32 green, f32 blue, f32 brightness, f32 contrast ) +{ + bool r; + u16 ramp[3][256]; + + calculateGammaRamp( ramp[0], red, brightness, contrast ); + calculateGammaRamp( ramp[1], green, brightness, contrast ); + calculateGammaRamp( ramp[2], blue, brightness, contrast ); + + HDC dc = GetDC(0); + r = SetDeviceGammaRamp ( dc, ramp ) == TRUE; + ReleaseDC(HWnd, dc); + return r; +} + +//! Get the current Gamma Value for the Display +bool CIrrDeviceWin32::getGammaRamp( f32 &red, f32 &green, f32 &blue, f32 &brightness, f32 &contrast ) +{ + bool r; + u16 ramp[3][256]; + + HDC dc = GetDC(0); + r = GetDeviceGammaRamp ( dc, ramp ) == TRUE; + ReleaseDC(HWnd, dc); + + if ( r ) + { + calculateGammaFromRamp(red, ramp[0]); + calculateGammaFromRamp(green, ramp[1]); + calculateGammaFromRamp(blue, ramp[2]); + } + + brightness = 0.f; + contrast = 0.f; + + return r; + +} + IRRLICHT_API IrrlichtDevice* IRRCALLCONV createDeviceEx( const SIrrlichtCreationParameters& parameters) { diff --git a/source/Irrlicht/CIrrDeviceWin32.h b/source/Irrlicht/CIrrDeviceWin32.h index f12766d6..69ec2ab3 100644 --- a/source/Irrlicht/CIrrDeviceWin32.h +++ b/source/Irrlicht/CIrrDeviceWin32.h @@ -13,9 +13,10 @@ #include "IImagePresenter.h" #define WIN32_LEAN_AND_MEAN -#include - -#include // For JOYCAPS +#if !defined(_IRR_XBOX_PLATFORM_) + #include + #include // For JOYCAPS +#endif namespace irr @@ -71,6 +72,12 @@ namespace irr //! Activate any joysticks, and generate events for them. virtual bool activateJoysticks(core::array & joystickInfo); + //! Set the current Gamma Value for the Display + virtual bool setGammaRamp( f32 red, f32 green, f32 blue, f32 brightness, f32 contrast ); + + //! Get the current Gamma Value for the Display + virtual bool getGammaRamp( f32 &red, f32 &green, f32 &blue, f32 &brightness, f32 &contrast ); + //! Implementation of the win32 cursor control class CCursorControl : public gui::ICursorControl { @@ -260,12 +267,14 @@ namespace irr bool ExternalWindow; CCursorControl* Win32CursorControl; +#if defined(_IRR_COMPILE_WITH_JOYSTICK_EVENTS_) struct JoystickInfo { u32 Index; JOYCAPS Caps; }; core::array ActiveJoysticks; +#endif }; } // end namespace irr diff --git a/source/Irrlicht/CIrrDeviceWinCE.cpp b/source/Irrlicht/CIrrDeviceWinCE.cpp index 7d8831bf..e1d1ebcc 100644 --- a/source/Irrlicht/CIrrDeviceWinCE.cpp +++ b/source/Irrlicht/CIrrDeviceWinCE.cpp @@ -552,7 +552,7 @@ void CIrrDeviceWinCE::resizeIfNecessary() sprintf(tmp, "Resizing window (%ld %ld)", r.right, r.bottom); os::Printer::log(tmp); - getVideoDriver()->OnResize(irr::core::dimension2d(r.right, r.bottom)); + getVideoDriver()->OnResize(irr::core::dimension2d(r.right, r.bottom)); } Resized = false; @@ -610,7 +610,7 @@ bool CIrrDeviceWinCE::present(video::IImage* image, void* windowId, core::rectgetBitsPerPixel(); bi.bV4Planes = 1; bi.bV4Width = image->getDimension().Width; - bi.bV4Height = -image->getDimension().Height; + bi.bV4Height = 0 - image->getDimension().Height; bi.bV4V4Compression = BI_BITFIELDS; bi.bV4AlphaMask = image->getAlphaMask (); bi.bV4RedMask = image->getRedMask (); @@ -714,14 +714,14 @@ video::IVideoModeList* CIrrDeviceWinCE::getVideoModeList() while (EnumDisplaySettings(NULL, i, &mode)) { - VideoModeList.addMode(core::dimension2d(mode.dmPelsWidth, mode.dmPelsHeight), + VideoModeList.addMode(core::dimension2d(mode.dmPelsWidth, mode.dmPelsHeight), mode.dmBitsPerPel); ++i; } if (EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &mode)) - VideoModeList.setDesktop(mode.dmBitsPerPel, core::dimension2d(mode.dmPelsWidth, mode.dmPelsHeight)); + VideoModeList.setDesktop(mode.dmBitsPerPel, core::dimension2d(mode.dmPelsWidth, mode.dmPelsHeight)); } return &VideoModeList; diff --git a/source/Irrlicht/CIrrDeviceWinCE.h b/source/Irrlicht/CIrrDeviceWinCE.h index 1f4ca919..9fe38685 100644 --- a/source/Irrlicht/CIrrDeviceWinCE.h +++ b/source/Irrlicht/CIrrDeviceWinCE.h @@ -74,7 +74,7 @@ namespace irr { public: - CCursorControl(const core::dimension2d& wsize, HWND hwnd, bool fullscreen) + CCursorControl(const core::dimension2d& wsize, HWND hwnd, bool fullscreen) : WindowSize(wsize), InvWindowSize(0.0f, 0.0f), IsVisible(true), HWnd(hwnd), BorderX(0), BorderY(0), UseReferenceRect(false) { diff --git a/source/Irrlicht/CIrrMeshFileLoader.cpp b/source/Irrlicht/CIrrMeshFileLoader.cpp index 0bba98a3..3ab73fcd 100644 --- a/source/Irrlicht/CIrrMeshFileLoader.cpp +++ b/source/Irrlicht/CIrrMeshFileLoader.cpp @@ -36,10 +36,9 @@ CIrrMeshFileLoader::CIrrMeshFileLoader(scene::ISceneManager* smgr, //! Returns true if the file maybe is able to be loaded by this class. /** This decision should be based only on the file extension (e.g. ".cob") */ -bool CIrrMeshFileLoader::isALoadableFileExtension(const c8* fileName) const +bool CIrrMeshFileLoader::isALoadableFileExtension(const core::string& filename) const { - return strstr(fileName, ".xml") || - strstr(fileName, ".irrmesh"); + return core::hasFileExtension ( filename, "xml", "irrmesh" ); } diff --git a/source/Irrlicht/CIrrMeshFileLoader.h b/source/Irrlicht/CIrrMeshFileLoader.h index abcff377..a5128a7e 100644 --- a/source/Irrlicht/CIrrMeshFileLoader.h +++ b/source/Irrlicht/CIrrMeshFileLoader.h @@ -29,7 +29,7 @@ public: //! returns true if the file maybe is able to be loaded by this class //! based on the file extension (e.g. ".cob") - virtual bool isALoadableFileExtension(const c8* fileName) const; + virtual bool isALoadableFileExtension(const core::string& filename) const; //! creates/loads an animated mesh from the file. //! \return Pointer to the created mesh. Returns 0 if loading failed. diff --git a/source/Irrlicht/CLMTSMeshFileLoader.cpp b/source/Irrlicht/CLMTSMeshFileLoader.cpp index dff5d0b0..3de1ec67 100644 --- a/source/Irrlicht/CLMTSMeshFileLoader.cpp +++ b/source/Irrlicht/CLMTSMeshFileLoader.cpp @@ -123,9 +123,9 @@ void CLMTSMeshFileLoader::cleanup() } -bool CLMTSMeshFileLoader::isALoadableFileExtension(const c8* filename) const +bool CLMTSMeshFileLoader::isALoadableFileExtension(const core::string& filename) const { - return strstr(filename, ".lmts") != 0; + return core::hasFileExtension ( filename, "lmts" ); } diff --git a/source/Irrlicht/CLMTSMeshFileLoader.h b/source/Irrlicht/CLMTSMeshFileLoader.h index 8d17e533..61f92417 100644 --- a/source/Irrlicht/CLMTSMeshFileLoader.h +++ b/source/Irrlicht/CLMTSMeshFileLoader.h @@ -40,7 +40,7 @@ public: virtual ~CLMTSMeshFileLoader(); - virtual bool isALoadableFileExtension(const c8* fileName) const; + virtual bool isALoadableFileExtension(const core::string& filename) const; virtual IAnimatedMesh* createMesh(io::IReadFile* file); diff --git a/source/Irrlicht/CLWOMeshFileLoader.cpp b/source/Irrlicht/CLWOMeshFileLoader.cpp index 988c8dc7..332f4399 100644 --- a/source/Irrlicht/CLWOMeshFileLoader.cpp +++ b/source/Irrlicht/CLWOMeshFileLoader.cpp @@ -133,9 +133,9 @@ CLWOMeshFileLoader::~CLWOMeshFileLoader() //! returns true if the file maybe is able to be loaded by this class //! based on the file extension (e.g. ".bsp") -bool CLWOMeshFileLoader::isALoadableFileExtension(const c8* filename) const +bool CLWOMeshFileLoader::isALoadableFileExtension(const core::string& filename) const { - return strstr(filename, ".lwo")!=0; + return core::hasFileExtension ( filename, "lwo" ); } @@ -1754,8 +1754,8 @@ video::ITexture* CLWOMeshFileLoader::loadTexture(const core::stringc& file) { video::IVideoDriver* driver = SceneManager->getVideoDriver(); - if (FileSystem->existFile(file.c_str())) - return driver->getTexture(file.c_str()); + if (FileSystem->existFile(file)) + return driver->getTexture(file); core::stringc strippedName; s32 stringPos = file.findLast('/'); @@ -1764,8 +1764,8 @@ video::ITexture* CLWOMeshFileLoader::loadTexture(const core::stringc& file) if (stringPos != -1) { strippedName = file.subString(stringPos+1, file.size()-stringPos); - if (FileSystem->existFile(strippedName.c_str())) - return driver->getTexture(strippedName.c_str()); + if (FileSystem->existFile(strippedName)) + return driver->getTexture(strippedName); } else strippedName = file; @@ -1777,8 +1777,8 @@ video::ITexture* CLWOMeshFileLoader::loadTexture(const core::stringc& file) { newpath = newpath.subString(0,stringPos+1); newpath.append(strippedName); - if (FileSystem->existFile(newpath.c_str())) - return driver->getTexture(newpath.c_str()); + if (FileSystem->existFile(newpath)) + return driver->getTexture(newpath); } os::Printer::log("Could not load texture", file.c_str(), ELL_WARNING); diff --git a/source/Irrlicht/CLWOMeshFileLoader.h b/source/Irrlicht/CLWOMeshFileLoader.h index 8751183d..22917edf 100644 --- a/source/Irrlicht/CLWOMeshFileLoader.h +++ b/source/Irrlicht/CLWOMeshFileLoader.h @@ -36,7 +36,7 @@ public: //! returns true if the file maybe is able to be loaded by this class //! based on the file extension (e.g. ".bsp") - virtual bool isALoadableFileExtension(const c8* fileName) const; + virtual bool isALoadableFileExtension(const core::string& filename) const; //! creates/loads an animated mesh from the file. //! \return Pointer to the created mesh. Returns 0 if loading failed. diff --git a/source/Irrlicht/CLimitReadFile.cpp b/source/Irrlicht/CLimitReadFile.cpp index 2127f826..59bdbf28 100644 --- a/source/Irrlicht/CLimitReadFile.cpp +++ b/source/Irrlicht/CLimitReadFile.cpp @@ -11,31 +11,23 @@ namespace io { -CLimitReadFile::CLimitReadFile(IReadFile* alreadyOpenedFile, long areaSize, const c8* name) -: Filename(name), AreaSize(areaSize), AreaStart(0), AreaEnd(0), File(alreadyOpenedFile) +CLimitReadFile::CLimitReadFile(IReadFile* alreadyOpenedFile, long pos, long areaSize, + const core::string& name) +: Filename(name), AreaStart(0), AreaEnd(0), File(alreadyOpenedFile), Pos ( 0 ) { #ifdef _DEBUG setDebugName("CLimitReadFile"); #endif if (File) + { File->grab(); - - init(); + AreaStart = pos; + AreaEnd = AreaStart + areaSize; + } } -void CLimitReadFile::init() -{ - if (!File) - return; - - AreaStart = File->getPos(); - AreaEnd = AreaStart + AreaSize; -} - - - CLimitReadFile::~CLimitReadFile() { if (File) @@ -47,6 +39,19 @@ CLimitReadFile::~CLimitReadFile() //! returns how much was read s32 CLimitReadFile::read(void* buffer, u32 sizeToRead) { +#if 1 + if ( 0 == File ) + return 0; + + s32 r = AreaStart + Pos; + s32 toRead = core::s32_min( AreaEnd, r + sizeToRead ) - core::s32_max( AreaStart, r ); + if ( toRead < 0 ) + return 0; + File->seek ( r ); + r = File->read(buffer, toRead); + Pos += r; + return r; +#else const long pos = File->getPos(); if (pos >= AreaEnd) @@ -56,6 +61,7 @@ s32 CLimitReadFile::read(void* buffer, u32 sizeToRead) sizeToRead = AreaEnd - pos; return File->read(buffer, sizeToRead); +#endif } @@ -65,6 +71,10 @@ s32 CLimitReadFile::read(void* buffer, u32 sizeToRead) //! otherwise from begin of file bool CLimitReadFile::seek(long finalPos, bool relativeMovement) { +#if 1 + Pos = core::s32_clamp ( finalPos + (relativeMovement ? Pos : 0 ), 0, AreaEnd - AreaStart ); + return true; +#else const long pos = File->getPos(); if (relativeMovement) @@ -80,13 +90,14 @@ bool CLimitReadFile::seek(long finalPos, bool relativeMovement) } return File->seek(finalPos, relativeMovement); +#endif } //! returns size of file long CLimitReadFile::getSize() const { - return AreaSize; + return AreaEnd - AreaStart; } @@ -94,21 +105,25 @@ long CLimitReadFile::getSize() const //! returns where in the file we are. long CLimitReadFile::getPos() const { +#if 1 + return Pos; +#else return File->getPos() - AreaStart; +#endif } //! returns name of file -const c8* CLimitReadFile::getFileName() const +const core::string& CLimitReadFile::getFileName() const { - return Filename.c_str(); + return Filename; } -IReadFile* createLimitReadFile(const c8* fileName, IReadFile* alreadyOpenedFile, long areaSize) +IReadFile* createLimitReadFile(const core::string& fileName, IReadFile* alreadyOpenedFile, long pos, long areaSize) { - return new CLimitReadFile(alreadyOpenedFile, areaSize, fileName); + return new CLimitReadFile(alreadyOpenedFile, pos, areaSize, fileName); } diff --git a/source/Irrlicht/CLimitReadFile.h b/source/Irrlicht/CLimitReadFile.h index b5436052..16a36743 100644 --- a/source/Irrlicht/CLimitReadFile.h +++ b/source/Irrlicht/CLimitReadFile.h @@ -25,7 +25,7 @@ namespace io { public: - CLimitReadFile(IReadFile* alreadyOpenedFile, long areaSize, const c8* name); + CLimitReadFile(IReadFile* alreadyOpenedFile, long pos, long areaSize, const core::string& name); virtual ~CLimitReadFile(); @@ -44,16 +44,14 @@ namespace io virtual long getPos() const; //! returns name of file - virtual const c8* getFileName() const; + virtual const core::string& getFileName() const; private: - void init(); - - core::stringc Filename; - long AreaSize; + core::string Filename; long AreaStart; long AreaEnd; + long Pos; IReadFile* File; }; diff --git a/source/Irrlicht/CLogger.cpp b/source/Irrlicht/CLogger.cpp index dafcd3b6..d9f6cfc0 100644 --- a/source/Irrlicht/CLogger.cpp +++ b/source/Irrlicht/CLogger.cpp @@ -81,6 +81,16 @@ namespace irr log(s1.c_str(), s2.c_str(), ll); } + //! Prints out a text into the log + void CLogger::log(const c8* text, const wchar_t* hint, ELOG_LEVEL ll) + { + if (ll < LogLevel) + return; + + core::stringc s2 = hint; + log( text, s2.c_str(), ll); + } + //! Sets a new event receiver void CLogger::setReceiver(IEventReceiver* r) { diff --git a/source/Irrlicht/CLogger.h b/source/Irrlicht/CLogger.h index a311ba83..9dc29604 100644 --- a/source/Irrlicht/CLogger.h +++ b/source/Irrlicht/CLogger.h @@ -35,6 +35,9 @@ public: //! Prints out a text into the log virtual void log(const c8* text, const c8* hint, ELOG_LEVEL ll=ELL_INFORMATION); + //! Prints out a text into the log + virtual void log(const c8* text, const wchar_t* hint, ELOG_LEVEL ll=ELL_INFORMATION); + //! Prints out a text into the log virtual void log(const wchar_t* text, const wchar_t* hint, ELOG_LEVEL ll=ELL_INFORMATION); diff --git a/source/Irrlicht/CMD2MeshFileLoader.cpp b/source/Irrlicht/CMD2MeshFileLoader.cpp index 583ff151..02a2aab1 100644 --- a/source/Irrlicht/CMD2MeshFileLoader.cpp +++ b/source/Irrlicht/CMD2MeshFileLoader.cpp @@ -102,9 +102,9 @@ CMD2MeshFileLoader::CMD2MeshFileLoader() //! returns true if the file maybe is able to be loaded by this class //! based on the file extension (e.g. ".bsp") -bool CMD2MeshFileLoader::isALoadableFileExtension(const c8* filename) const +bool CMD2MeshFileLoader::isALoadableFileExtension(const core::string& filename) const { - return strstr(filename, ".md2")!=0; + return core::hasFileExtension ( filename, "md2" ); } diff --git a/source/Irrlicht/CMD2MeshFileLoader.h b/source/Irrlicht/CMD2MeshFileLoader.h index b6b828a2..fd62d1cf 100644 --- a/source/Irrlicht/CMD2MeshFileLoader.h +++ b/source/Irrlicht/CMD2MeshFileLoader.h @@ -24,7 +24,7 @@ public: //! returns true if the file maybe is able to be loaded by this class //! based on the file extension (e.g. ".bsp") - virtual bool isALoadableFileExtension(const c8* fileName) const; + virtual bool isALoadableFileExtension(const core::string& filename) const; //! creates/loads an animated mesh from the file. //! \return Pointer to the created mesh. Returns 0 if loading failed. diff --git a/source/Irrlicht/CMD3MeshFileLoader.cpp b/source/Irrlicht/CMD3MeshFileLoader.cpp index dc622ac2..aa27fcf1 100644 --- a/source/Irrlicht/CMD3MeshFileLoader.cpp +++ b/source/Irrlicht/CMD3MeshFileLoader.cpp @@ -16,9 +16,9 @@ namespace scene //! returns true if the file maybe is able to be loaded by this class //! based on the file extension (e.g. ".bsp") -bool CMD3MeshFileLoader::isALoadableFileExtension(const c8* filename) const +bool CMD3MeshFileLoader::isALoadableFileExtension(const core::string& filename) const { - return strstr(filename, ".md3") != 0; + return core::hasFileExtension ( filename, "md3" ); } diff --git a/source/Irrlicht/CMD3MeshFileLoader.h b/source/Irrlicht/CMD3MeshFileLoader.h index 25dcec27..f3358d81 100644 --- a/source/Irrlicht/CMD3MeshFileLoader.h +++ b/source/Irrlicht/CMD3MeshFileLoader.h @@ -19,7 +19,7 @@ public: //! returns true if the file maybe is able to be loaded by this class //! based on the file extension (e.g. ".bsp") - virtual bool isALoadableFileExtension(const c8* fileName) const; + virtual bool isALoadableFileExtension(const core::string& filename) const; //! creates/loads an animated mesh from the file. //! \return Pointer to the created mesh. Returns 0 if loading failed. diff --git a/source/Irrlicht/CMS3DMeshFileLoader.cpp b/source/Irrlicht/CMS3DMeshFileLoader.cpp index 22ba58c3..951593f0 100644 --- a/source/Irrlicht/CMS3DMeshFileLoader.cpp +++ b/source/Irrlicht/CMS3DMeshFileLoader.cpp @@ -125,9 +125,9 @@ CMS3DMeshFileLoader::CMS3DMeshFileLoader(video::IVideoDriver *driver) //! returns true if the file maybe is able to be loaded by this class //! based on the file extension (e.g. ".bsp") -bool CMS3DMeshFileLoader::isALoadableFileExtension(const c8* filename) const +bool CMS3DMeshFileLoader::isALoadableFileExtension(const core::string& filename) const { - return strstr(filename, ".ms3d")!=0; + return core::hasFileExtension ( filename, "ms3d" ); } @@ -381,14 +381,14 @@ bool CMS3DMeshFileLoader::load(io::IReadFile* file) if (TexturePath.trim()!="") { TexturePath=stripPathFromString(file->getFileName(),true) + stripPathFromString(TexturePath,false); - tmpBuffer->Material.setTexture(0, Driver->getTexture(TexturePath.c_str()) ); + tmpBuffer->Material.setTexture(0, Driver->getTexture(TexturePath) ); } core::stringc AlphamapPath=(const c8*)material->Alphamap; if (AlphamapPath.trim()!="") { AlphamapPath=stripPathFromString(file->getFileName(),true) + stripPathFromString(AlphamapPath,false); - tmpBuffer->Material.setTexture(2, Driver->getTexture(AlphamapPath.c_str()) ); + tmpBuffer->Material.setTexture(2, Driver->getTexture(AlphamapPath) ); } } diff --git a/source/Irrlicht/CMS3DMeshFileLoader.h b/source/Irrlicht/CMS3DMeshFileLoader.h index a4483f81..8464db55 100644 --- a/source/Irrlicht/CMS3DMeshFileLoader.h +++ b/source/Irrlicht/CMS3DMeshFileLoader.h @@ -24,7 +24,7 @@ public: //! returns true if the file might be loadable by this class //! based on the file extension (e.g. ".bsp") - virtual bool isALoadableFileExtension(const c8* fileName) const; + virtual bool isALoadableFileExtension(const core::string& filename) const; //! creates/loads an animated mesh from the file. //! \return Pointer to the created mesh. Returns 0 if loading failed. diff --git a/source/Irrlicht/CMY3DMeshFileLoader.cpp b/source/Irrlicht/CMY3DMeshFileLoader.cpp index e3c4445d..f21ef98e 100644 --- a/source/Irrlicht/CMY3DMeshFileLoader.cpp +++ b/source/Irrlicht/CMY3DMeshFileLoader.cpp @@ -72,9 +72,9 @@ CMY3DMeshFileLoader::~CMY3DMeshFileLoader() } -bool CMY3DMeshFileLoader::isALoadableFileExtension(const c8* filename) const +bool CMY3DMeshFileLoader::isALoadableFileExtension(const core::string& filename) const { - return strstr(filename, ".my3d") != 0; + return core::hasFileExtension ( filename, "my3d" ); } @@ -195,7 +195,7 @@ IAnimatedMesh* CMY3DMeshFileLoader::createMesh(io::IReadFile* file) me.Texture2FileName.append(name); if (name.size()) - me.Texture2 = SceneManager->getVideoDriver()->getTexture(me.Texture2FileName.c_str()); + me.Texture2 = SceneManager->getVideoDriver()->getTexture(me.Texture2FileName); me.MaterialType = video::EMT_LIGHTMAP_M2; gotLightMap = true; @@ -209,7 +209,7 @@ IAnimatedMesh* CMY3DMeshFileLoader::createMesh(io::IReadFile* file) me.Texture2FileName.append(name); if (name.size()) - me.Texture2 = SceneManager->getVideoDriver()->getTexture(me.Texture2FileName.c_str()); + me.Texture2 = SceneManager->getVideoDriver()->getTexture(me.Texture2FileName); me.MaterialType = video::EMT_REFLECTION_2_LAYER; } @@ -219,7 +219,7 @@ IAnimatedMesh* CMY3DMeshFileLoader::createMesh(io::IReadFile* file) me.Texture1FileName = filepath; me.Texture1FileName.append(name); if (name.size()) - me.Texture1 = SceneManager->getVideoDriver()->getTexture(me.Texture1FileName.c_str()); + me.Texture1 = SceneManager->getVideoDriver()->getTexture(me.Texture1FileName); gotMainMap = true; me.MaterialType = video::EMT_SOLID; diff --git a/source/Irrlicht/CMY3DMeshFileLoader.h b/source/Irrlicht/CMY3DMeshFileLoader.h index ab94d538..ebe0979d 100644 --- a/source/Irrlicht/CMY3DMeshFileLoader.h +++ b/source/Irrlicht/CMY3DMeshFileLoader.h @@ -87,7 +87,7 @@ public: CMY3DMeshFileLoader(ISceneManager *scmgr, io::IFileSystem* fs); virtual ~CMY3DMeshFileLoader(); - virtual bool isALoadableFileExtension(const c8* fileName) const; + virtual bool isALoadableFileExtension(const core::string& filename) const; virtual IAnimatedMesh* createMesh(io::IReadFile* file); diff --git a/source/Irrlicht/CMemoryFile.cpp b/source/Irrlicht/CMemoryFile.cpp index cf8daa7a..330ee3fe 100644 --- a/source/Irrlicht/CMemoryFile.cpp +++ b/source/Irrlicht/CMemoryFile.cpp @@ -11,7 +11,7 @@ namespace io { -CMemoryFile::CMemoryFile(void* memory, long len, const c8* fileName, bool d) +CMemoryFile::CMemoryFile(void* memory, long len, const core::string& fileName, bool d) : Buffer(memory), Len(len), Pos(0), Filename(fileName), deleteMemoryWhenDropped(d) { #ifdef _DEBUG @@ -104,13 +104,13 @@ long CMemoryFile::getPos() const //! returns name of file -const c8* CMemoryFile::getFileName() const +const core::string& CMemoryFile::getFileName() const { - return Filename.c_str(); + return Filename; } -IReadFile* createMemoryReadFile(void* memory, long size, const c8* fileName, bool deleteMemoryWhenDropped) +IReadFile* createMemoryReadFile(void* memory, long size, const core::string& fileName, bool deleteMemoryWhenDropped) { CMemoryFile* file = new CMemoryFile(memory, size, fileName, deleteMemoryWhenDropped); return file; diff --git a/source/Irrlicht/CMemoryFile.h b/source/Irrlicht/CMemoryFile.h index 7495a4b0..189d9a52 100644 --- a/source/Irrlicht/CMemoryFile.h +++ b/source/Irrlicht/CMemoryFile.h @@ -23,7 +23,7 @@ namespace io public: //! Constructor - CMemoryFile(void* memory, long len, const c8* fileName, bool deleteMemoryWhenDropped); + CMemoryFile(void* memory, long len, const core::string& fileName, bool deleteMemoryWhenDropped); //! Destructor virtual ~CMemoryFile(); @@ -44,14 +44,14 @@ namespace io virtual long getPos() const; //! returns name of file - virtual const c8* getFileName() const; + virtual const core::string& getFileName() const; private: void *Buffer; long Len; long Pos; - core::stringc Filename; + core::string Filename; bool deleteMemoryWhenDropped; }; diff --git a/source/Irrlicht/CMeshCache.cpp b/source/Irrlicht/CMeshCache.cpp index 46513987..9755a5f2 100644 --- a/source/Irrlicht/CMeshCache.cpp +++ b/source/Irrlicht/CMeshCache.cpp @@ -19,14 +19,12 @@ CMeshCache::~CMeshCache() //! adds a mesh to the list -void CMeshCache::addMesh(const c8* filename, IAnimatedMesh* mesh) +void CMeshCache::addMesh(const core::string& filename, IAnimatedMesh* mesh) { mesh->grab(); - MeshEntry e; + MeshEntry e ( filename ); e.Mesh = mesh; - e.Name = filename; - e.Name.make_lower(); Meshes.push_back(e); } @@ -109,18 +107,16 @@ IAnimatedMesh* CMeshCache::getMeshByIndex(u32 number) //! Returns a mesh based on its file name. -IAnimatedMesh* CMeshCache::getMeshByFilename(const c8* filename) +IAnimatedMesh* CMeshCache::getMeshByFilename(const core::string& filename) { - MeshEntry e; - e.Name = filename; - e.Name.make_lower(); + MeshEntry e ( filename ); s32 id = Meshes.binary_search(e); return (id != -1) ? Meshes[id].Mesh : 0; } //! Returns name of a mesh based on its index number -const c8* CMeshCache::getMeshFilename(u32 number) const +const c16* CMeshCache::getMeshFilename(u32 number) const { if (number >= Meshes.size()) return 0; @@ -131,7 +127,7 @@ const c8* CMeshCache::getMeshFilename(u32 number) const //! Returns the filename of a loaded mesh, if there is any. Returns 0 if there is none. -const c8* CMeshCache::getMeshFilename(const IAnimatedMesh* const mesh) const +const c16* CMeshCache::getMeshFilename(const IAnimatedMesh* const mesh) const { if(!mesh) return 0; @@ -147,7 +143,7 @@ const c8* CMeshCache::getMeshFilename(const IAnimatedMesh* const mesh) const //! Returns the filename of a loaded mesh, if there is any. Returns 0 if there is none. -const c8* CMeshCache::getMeshFilename(const IMesh* const mesh) const +const c16* CMeshCache::getMeshFilename(const IMesh* const mesh) const { if(!mesh) return 0; @@ -166,7 +162,7 @@ const c8* CMeshCache::getMeshFilename(const IMesh* const mesh) const //! Renames a loaded mesh, if possible. -bool CMeshCache::setMeshFilename(u32 index, const c8* filename) +bool CMeshCache::setMeshFilename(u32 index, const c16* filename) { if (index >= Meshes.size()) return false; @@ -178,7 +174,7 @@ bool CMeshCache::setMeshFilename(u32 index, const c8* filename) //! Renames a loaded mesh, if possible. -bool CMeshCache::setMeshFilename(const IAnimatedMesh* const mesh, const c8* filename) +bool CMeshCache::setMeshFilename(const IAnimatedMesh* const mesh, const c16* filename) { for (u32 i=0; i& filename) { return getMeshByFilename(filename) != 0; } diff --git a/source/Irrlicht/CMeshCache.h b/source/Irrlicht/CMeshCache.h index ff85ca39..b22bf48b 100644 --- a/source/Irrlicht/CMeshCache.h +++ b/source/Irrlicht/CMeshCache.h @@ -30,7 +30,7 @@ namespace scene \param filename: Filename of the mesh. When called ISceneManager::getMesh() with this parameter, the method will return the mesh parameter given with this method. \param mesh: Pointer to a mesh which will now be referenced by this name. */ - virtual void addMesh(const c8* filename, IAnimatedMesh* mesh); + virtual void addMesh(const core::string& filename, IAnimatedMesh* mesh); //! Removes a mesh from the cache. /** After loading a mesh with getMesh(), the mesh can be removed from the cache @@ -62,32 +62,32 @@ namespace scene //! Returns a mesh based on its file name. /** \return Returns pointer to the mesh or 0 if there is none with this number. */ - virtual IAnimatedMesh* getMeshByFilename(const c8* filename); + virtual IAnimatedMesh* getMeshByFilename(const core::string& filename); //! Returns name of a mesh based on its index number. /** \param index: Index of the mesh, number between 0 and getMeshCount()-1. Note that this is only valid until a new mesh is loaded */ - virtual const c8* getMeshFilename(u32 index) const; + virtual const c16* getMeshFilename(u32 index) const; //! Returns the filename of a loaded mesh, if there is any. /** Returns 0 if there is none. */ - virtual const c8* getMeshFilename(const IAnimatedMesh* const mesh) const; + virtual const c16* getMeshFilename(const IAnimatedMesh* const mesh) const; //! Returns the filename of a loaded mesh, if there is any. /* Returns 0 if there is none.*/ - virtual const c8* getMeshFilename(const IMesh* const mesh) const; + virtual const c16* getMeshFilename(const IMesh* const mesh) const; //! Renames a loaded mesh, if possible. - virtual bool setMeshFilename(u32 index, const c8* filename); + virtual bool setMeshFilename(u32 index, const c16* filename); //! Renames a loaded mesh, if possible. - virtual bool setMeshFilename(const IAnimatedMesh* const mesh, const c8* filename); + virtual bool setMeshFilename(const IAnimatedMesh* const mesh, const c16* filename); //! Renames a loaded mesh, if possible. - virtual bool setMeshFilename(const IMesh* const mesh, const c8* filename); + virtual bool setMeshFilename(const IMesh* const mesh, const c16* filename); //! returns if a mesh already was loaded - virtual bool isMeshLoaded(const c8* filename); + virtual bool isMeshLoaded(const core::string& filename); //! Clears the whole mesh cache, removing all meshes. virtual void clear(); @@ -99,7 +99,12 @@ namespace scene struct MeshEntry { - core::stringc Name; + MeshEntry ( const core::string name ) + : Name ( name ) + { + Name.make_lower (); + } + core::string Name; IAnimatedMesh* Mesh; bool operator < (const MeshEntry& other) const diff --git a/source/Irrlicht/CMeshSceneNode.cpp b/source/Irrlicht/CMeshSceneNode.cpp index d99f9f9d..1d303bcf 100644 --- a/source/Irrlicht/CMeshSceneNode.cpp +++ b/source/Irrlicht/CMeshSceneNode.cpp @@ -221,9 +221,8 @@ void CMeshSceneNode::render() // align to v->Normal core::quaternion quatRot(v->Normal.X, 0.f, -v->Normal.X, 1+v->Normal.Y); quatRot.normalize(); - quatRot.getMatrix(m2); + quatRot.getMatrix(m2, v->Pos); - m2.setTranslation(v->Pos); m2*=AbsoluteTransformation; driver->setTransform(video::ETS_WORLD, m2); @@ -339,8 +338,8 @@ void CMeshSceneNode::serializeAttributes(io::IAttributes* out, io::SAttributeRea //! Reads attributes of the scene node. void CMeshSceneNode::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options) { - core::stringc oldMeshStr = SceneManager->getMeshCache()->getMeshFilename(Mesh); - core::stringc newMeshStr = in->getAttributeAsString("Mesh"); + core::string oldMeshStr = SceneManager->getMeshCache()->getMeshFilename(Mesh); + core::string newMeshStr = in->getAttributeAsString("Mesh"); ReadOnlyMaterials = in->getAttributeAsBool("ReadOnlyMaterials"); if (newMeshStr != "" && oldMeshStr != newMeshStr) diff --git a/source/Irrlicht/CNullDriver.cpp b/source/Irrlicht/CNullDriver.cpp index b87d9173..5b452827 100644 --- a/source/Irrlicht/CNullDriver.cpp +++ b/source/Irrlicht/CNullDriver.cpp @@ -281,6 +281,7 @@ void CNullDriver::removeTexture(ITexture* texture) //! memory. void CNullDriver::removeAllTextures() { + setMaterial ( SMaterial() ); deleteAllTextures(); } @@ -303,13 +304,13 @@ u32 CNullDriver::getTextureCount() const //! Renames a texture -void CNullDriver::renameTexture(ITexture* texture, const c8* newName) +void CNullDriver::renameTexture(ITexture* texture, const core::string& newName) { // we can do a const_cast here safely, the name of the ITexture interface // is just readonly to prevent the user changing the texture name without invoking // this method, because the textures will need resorting afterwards - core::stringc& name = const_cast(texture->getName()); + core::string& name = const_cast&>(texture->getName()); name = newName; Textures.sort(); @@ -317,12 +318,12 @@ void CNullDriver::renameTexture(ITexture* texture, const c8* newName) //! loads a Texture -ITexture* CNullDriver::getTexture(const c8* filename) +ITexture* CNullDriver::getTexture(const core::string& filename) { // Identify textures by their absolute filenames if possible. - core::stringc absolutePath = FileSystem->getAbsolutePath(filename); + core::string absolutePath = FileSystem->getAbsolutePath(filename); - ITexture* texture = findTexture(absolutePath.c_str()); + ITexture* texture = findTexture(absolutePath ); if (texture) return texture; @@ -332,7 +333,7 @@ ITexture* CNullDriver::getTexture(const c8* filename) return texture; // Now try to open the file using the complete path. - io::IReadFile* file = FileSystem->createAndOpenFile(absolutePath.c_str()); + io::IReadFile* file = FileSystem->createAndOpenFile(absolutePath ); if(!file) { @@ -391,7 +392,7 @@ ITexture* CNullDriver::getTexture(io::IReadFile* file) //! opens the file and loads it into the surface -video::ITexture* CNullDriver::loadTextureFromFile(io::IReadFile* file, const c8 *hashName ) +video::ITexture* CNullDriver::loadTextureFromFile(io::IReadFile* file, const core::string& hashName ) { ITexture* texture = 0; IImage* image = createImageFromFile(file); @@ -399,7 +400,7 @@ video::ITexture* CNullDriver::loadTextureFromFile(io::IReadFile* file, const c8 if (image) { // create texture from surface - texture = createDeviceDependentTexture(image, hashName ? hashName : file->getFileName() ); + texture = createDeviceDependentTexture(image, hashName.size() ? hashName : file->getFileName() ); os::Printer::log("Loaded texture", file->getFileName()); image->drop(); } @@ -432,11 +433,8 @@ void CNullDriver::addTexture(video::ITexture* texture) //! looks if the image is already loaded -video::ITexture* CNullDriver::findTexture(const c8* filename) +video::ITexture* CNullDriver::findTexture(const core::string& filename) { - if (!filename) - filename = ""; - SSurface s; SDummyTexture dummy(filename); s.Surface = &dummy; @@ -451,9 +449,9 @@ video::ITexture* CNullDriver::findTexture(const c8* filename) //! Creates a texture from a loaded IImage. -ITexture* CNullDriver::addTexture(const c8* name, IImage* image) +ITexture* CNullDriver::addTexture(const core::string& name, IImage* image) { - if (!name || !image) + if ( 0 == name.size() || !image) return 0; ITexture* t = createDeviceDependentTexture(image, name); @@ -469,9 +467,9 @@ ITexture* CNullDriver::addTexture(const c8* name, IImage* image) //! creates a Texture ITexture* CNullDriver::addTexture(const core::dimension2d& size, - const c8* name, ECOLOR_FORMAT format) + const core::string& name, ECOLOR_FORMAT format) { - if (!name) + if ( 0 == name.size () ) return 0; IImage* image = new CImage(format, size); @@ -489,7 +487,7 @@ ITexture* CNullDriver::addTexture(const core::dimension2d& size, //! returns a device dependent texture from a software surface (IImage) //! THIS METHOD HAS TO BE OVERRIDDEN BY DERIVED DRIVERS WITH OWN TEXTURES -ITexture* CNullDriver::createDeviceDependentTexture(IImage* surface, const char* name) +ITexture* CNullDriver::createDeviceDependentTexture(IImage* surface, const core::string& name) { #ifdef _IRR_COMPILE_WITH_SOFTWARE_ return new CSoftwareTexture(surface, name); @@ -1187,9 +1185,9 @@ bool CNullDriver::getTextureCreationFlag(E_TEXTURE_CREATION_FLAG flag) const //! Creates a software image from a file. -IImage* CNullDriver::createImageFromFile(const char* filename) +IImage* CNullDriver::createImageFromFile(const core::string& filename) { - if (!filename) + if (!filename.size()) return 0; IImage* image = 0; @@ -1249,7 +1247,7 @@ IImage* CNullDriver::createImageFromFile(io::IReadFile* file) //! Writes the provided image to disk file -bool CNullDriver::writeImageToFile(IImage* image, const char* filename,u32 param) +bool CNullDriver::writeImageToFile(IImage* image, const core::string& filename,u32 param) { io::IWriteFile* file = FileSystem->createAndWriteFile(filename); if(!file) @@ -1668,10 +1666,10 @@ s32 CNullDriver::addHighLevelShaderMaterial( //! Like IGPUProgrammingServices::addShaderMaterial() (look there for a detailed description), //! but tries to load the programs from files. s32 CNullDriver::addHighLevelShaderMaterialFromFiles( - const c8* vertexShaderProgram, + const core::string& vertexShaderProgram, const c8* vertexShaderEntryPointName, E_VERTEX_SHADER_TYPE vsCompileTarget, - const c8* pixelShaderProgram, + const core::string& pixelShaderProgram, const c8* pixelShaderEntryPointName, E_PIXEL_SHADER_TYPE psCompileTarget, IShaderConstantSetCallBack* callback, @@ -1681,7 +1679,7 @@ s32 CNullDriver::addHighLevelShaderMaterialFromFiles( io::IReadFile* vsfile = 0; io::IReadFile* psfile = 0; - if (vertexShaderProgram) + if (vertexShaderProgram.size() ) { vsfile = FileSystem->createAndOpenFile(vertexShaderProgram); if (!vsfile) @@ -1692,7 +1690,7 @@ s32 CNullDriver::addHighLevelShaderMaterialFromFiles( } } - if (pixelShaderProgram) + if (pixelShaderProgram.size() ) { psfile = FileSystem->createAndOpenFile(pixelShaderProgram); if (!psfile) @@ -1830,8 +1828,8 @@ s32 CNullDriver::addShaderMaterialFromFiles(io::IReadFile* vertexShaderProgram, //! Like IGPUProgrammingServices::addShaderMaterial(), but tries to load the //! programs from files. -s32 CNullDriver::addShaderMaterialFromFiles(const c8* vertexShaderProgramFileName, - const c8* pixelShaderProgramFileName, +s32 CNullDriver::addShaderMaterialFromFiles(const core::string& vertexShaderProgramFileName, + const core::string& pixelShaderProgramFileName, IShaderConstantSetCallBack* callback, E_MATERIAL_TYPE baseMaterial, s32 userData) @@ -1839,7 +1837,7 @@ s32 CNullDriver::addShaderMaterialFromFiles(const c8* vertexShaderProgramFileNam io::IReadFile* vsfile = 0; io::IReadFile* psfile = 0; - if (vertexShaderProgramFileName) + if (vertexShaderProgramFileName.size()) { vsfile = FileSystem->createAndOpenFile(vertexShaderProgramFileName); if (!vsfile) @@ -1850,7 +1848,7 @@ s32 CNullDriver::addShaderMaterialFromFiles(const c8* vertexShaderProgramFileNam } } - if (pixelShaderProgramFileName) + if (pixelShaderProgramFileName.size()) { psfile = FileSystem->createAndOpenFile(pixelShaderProgramFileName); if (!psfile) @@ -1878,7 +1876,7 @@ s32 CNullDriver::addShaderMaterialFromFiles(const c8* vertexShaderProgramFileNam //! Creates a render target texture. ITexture* CNullDriver::addRenderTargetTexture(const core::dimension2d& size, - const c8* name) + const core::string&name) { return 0; } diff --git a/source/Irrlicht/CNullDriver.h b/source/Irrlicht/CNullDriver.h index 8845db01..e60a40f5 100644 --- a/source/Irrlicht/CNullDriver.h +++ b/source/Irrlicht/CNullDriver.h @@ -64,11 +64,7 @@ namespace video virtual void setMaterial(const SMaterial& material); //! loads a Texture - virtual ITexture* getTexture(const c8* filename); - - //! loads a Texture - virtual ITexture* getTexture(const core::stringc& filename) - { return getTexture(filename.c_str()); } + virtual ITexture* getTexture(const core::string& filename); //! loads a Texture virtual ITexture* getTexture(io::IReadFile* file); @@ -80,10 +76,10 @@ namespace video virtual u32 getTextureCount() const; //! Renames a texture - virtual void renameTexture(ITexture* texture, const c8* newName); + virtual void renameTexture(ITexture* texture, const core::string& newName); //! creates a Texture - virtual ITexture* addTexture(const core::dimension2d& size, const c8* name, ECOLOR_FORMAT format = ECF_A8R8G8B8); + virtual ITexture* addTexture(const core::dimension2d& size, const core::string& name, ECOLOR_FORMAT format = ECF_A8R8G8B8); //! sets a render target virtual bool setRenderTarget(video::ITexture* texture, bool clearBackBuffer, @@ -285,7 +281,7 @@ namespace video //! Creates a render target texture. virtual ITexture* addRenderTargetTexture(const core::dimension2d& size, - const c8* name); + const core::string& name); //! Creates an 1bit alpha channel of the texture based of an color key. virtual void makeColorKeyTexture(video::ITexture* texture, video::SColor color, bool zeroTexels) const; @@ -309,7 +305,7 @@ namespace video virtual bool getTextureCreationFlag(E_TEXTURE_CREATION_FLAG flag) const; //! Creates a software image from a file. - virtual IImage* createImageFromFile(const char* filename); + virtual IImage* createImageFromFile(const core::string& filename); //! Creates a software image from a file. virtual IImage* createImageFromFile(io::IReadFile* file); @@ -340,7 +336,10 @@ namespace video protected: struct SHWBufferLink { - SHWBufferLink(const scene::IMeshBuffer *_MeshBuffer):MeshBuffer(_MeshBuffer),ChangedID_Vertex(0),ChangedID_Index(0),LastUsed(0),Mapped_Vertex(scene::EHM_NEVER),Mapped_Index(scene::EHM_NEVER) + SHWBufferLink(const scene::IMeshBuffer *_MeshBuffer) + :MeshBuffer(_MeshBuffer), + ChangedID_Vertex(0),ChangedID_Index(0),LastUsed(0), + Mapped_Vertex(scene::EHM_NEVER),Mapped_Index(scene::EHM_NEVER) { if (MeshBuffer) MeshBuffer->grab(); @@ -426,8 +425,8 @@ namespace video //! Like IGPUProgrammingServices::addShaderMaterial(), but tries to load the //! programs from files. - virtual s32 addShaderMaterialFromFiles(const c8* vertexShaderProgramFileName = 0, - const c8* pixelShaderProgramFileName = 0, + virtual s32 addShaderMaterialFromFiles(const core::string& vertexShaderProgramFileName, + const core::string& pixelShaderProgramFileName, IShaderConstantSetCallBack* callback = 0, E_MATERIAL_TYPE baseMaterial = video::EMT_SOLID, s32 userData=0); @@ -457,10 +456,10 @@ namespace video //! Like IGPUProgrammingServices::addShaderMaterial() (look there for a detailed description), //! but tries to load the programs from files. virtual s32 addHighLevelShaderMaterialFromFiles( - const c8* vertexShaderProgram, + const core::string& vertexShaderProgramFile, const c8* vertexShaderEntryPointName = "main", E_VERTEX_SHADER_TYPE vsCompileTarget = EVST_VS_1_1, - const c8* pixelShaderProgram = 0, + const core::string& pixelShaderProgramFile = "", const c8* pixelShaderEntryPointName = "main", E_PIXEL_SHADER_TYPE psCompileTarget = EPST_PS_1_1, IShaderConstantSetCallBack* callback = 0, @@ -490,7 +489,7 @@ namespace video virtual IImage* createScreenShot(); //! Writes the provided image to disk file - virtual bool writeImageToFile(IImage* image, const char* filename, u32 param = 0); + virtual bool writeImageToFile(IImage* image, const core::string& filename, u32 param = 0); //! Writes the provided image to a file. virtual bool writeImageToFile(IImage* image, io::IWriteFile * file, u32 param = 0); @@ -505,7 +504,7 @@ namespace video virtual void fillMaterialStructureFromAttributes(video::SMaterial& outMaterial, io::IAttributes* attributes); //! looks if the image is already loaded - virtual video::ITexture* findTexture(const c8* filename); + virtual video::ITexture* findTexture(const core::string& filename); //! Set/unset a clipping plane. //! There are at least 6 clipping planes available for the user to set at will. @@ -542,17 +541,17 @@ namespace video void deleteAllTextures(); //! opens the file and loads it into the surface - video::ITexture* loadTextureFromFile(io::IReadFile* file, const c8* hashName = 0); + video::ITexture* loadTextureFromFile(io::IReadFile* file, const core::string& hashName = ""); //! adds a surface, not loaded or created by the Irrlicht Engine void addTexture(video::ITexture* surface); //! Creates a texture from a loaded IImage. - virtual ITexture* addTexture(const c8* name, IImage* image); + virtual ITexture* addTexture(const core::string& name, IImage* image); //! returns a device dependent texture from a software surface (IImage) //! THIS METHOD HAS TO BE OVERRIDDEN BY DERIVED DRIVERS WITH OWN TEXTURES - virtual video::ITexture* createDeviceDependentTexture(IImage* surface, const char* name); + virtual video::ITexture* createDeviceDependentTexture(IImage* surface, const core::string& name); //! checks triangle count and print warning if wrong bool checkPrimitiveCount(u32 prmcnt) const; @@ -601,7 +600,7 @@ namespace video struct SDummyTexture : public ITexture { - SDummyTexture(const char* name) : ITexture(name), size(0,0) {}; + SDummyTexture(const core::string& name) : ITexture(name), size(0,0) {}; virtual void* lock(bool readOnly = false) { return 0; }; virtual void unlock(){} diff --git a/source/Irrlicht/COBJMeshFileLoader.cpp b/source/Irrlicht/COBJMeshFileLoader.cpp index 75fb9a2c..b1c7eb71 100644 --- a/source/Irrlicht/COBJMeshFileLoader.cpp +++ b/source/Irrlicht/COBJMeshFileLoader.cpp @@ -47,9 +47,9 @@ COBJMeshFileLoader::~COBJMeshFileLoader() //! returns true if the file maybe is able to be loaded by this class //! based on the file extension (e.g. ".bsp") -bool COBJMeshFileLoader::isALoadableFileExtension(const c8* filename) const +bool COBJMeshFileLoader::isALoadableFileExtension(const core::string& filename) const { - return strstr(filename, ".obj")!=0; + return core::hasFileExtension ( filename, "obj" ); } @@ -73,8 +73,8 @@ IAnimatedMesh* COBJMeshFileLoader::createMesh(io::IReadFile* file) Materials.push_back(currMtl); u32 smoothingGroup=0; - const core::stringc fullName = file->getFileName(); - const core::stringc relPath = FileSystem->getFileDir(fullName)+"/"; + const core::string fullName = file->getFileName(); + const core::string relPath = FileSystem->getFileDir(fullName)+"/"; c8* buf = new c8[filesize]; memset(buf, 0, filesize); @@ -311,7 +311,7 @@ IAnimatedMesh* COBJMeshFileLoader::createMesh(io::IReadFile* file) } -const c8* COBJMeshFileLoader::readTextures(const c8* bufPtr, const c8* const bufEnd, SObjMtl* currMaterial, const core::stringc& relPath) +const c8* COBJMeshFileLoader::readTextures(const c8* bufPtr, const c8* const bufEnd, SObjMtl* currMaterial, const core::string& relPath) { u8 type=0; // map_Kd - diffuse color texture map // map_Ks - specular color texture map @@ -410,15 +410,15 @@ const c8* COBJMeshFileLoader::readTextures(const c8* bufPtr, const c8* const buf if (clamp) currMaterial->Meshbuffer->Material.setFlag(video::EMF_TEXTURE_WRAP, video::ETC_CLAMP); - core::stringc texname(textureNameBuf); + core::string texname(textureNameBuf); texname.replace('\\', '/'); video::ITexture * texture = 0; - if (FileSystem->existFile(texname.c_str())) - texture = SceneManager->getVideoDriver()->getTexture(texname.c_str()); + if (FileSystem->existFile(texname)) + texture = SceneManager->getVideoDriver()->getTexture(texname); else // try to read in the relative path, the .obj is loaded from - texture = SceneManager->getVideoDriver()->getTexture( (relPath + texname).c_str() ); + texture = SceneManager->getVideoDriver()->getTexture( relPath + texname ); if ( texture ) { if (type==0) @@ -450,14 +450,20 @@ const c8* COBJMeshFileLoader::readTextures(const c8* bufPtr, const c8* const buf } -void COBJMeshFileLoader::readMTL(const c8* fileName, const core::stringc& relPath) +void COBJMeshFileLoader::readMTL(const c8* fileName, const core::string& relPath) { io::IReadFile * mtlReader; - if (FileSystem->existFile(fileName)) - mtlReader = FileSystem->createAndOpenFile(fileName); + + core::string realFile ( fileName ); + + if (FileSystem->existFile(realFile)) + mtlReader = FileSystem->createAndOpenFile(realFile.c_str() ); else + { // try to read in the relative path, the .obj is loaded from - mtlReader = FileSystem->createAndOpenFile((relPath + fileName).c_str()); + core::string r2 = relPath + realFile; + mtlReader = FileSystem->createAndOpenFile(r2.c_str()); + } if (!mtlReader) // fail to open and read file return; diff --git a/source/Irrlicht/COBJMeshFileLoader.h b/source/Irrlicht/COBJMeshFileLoader.h index 2e10594b..6d428611 100644 --- a/source/Irrlicht/COBJMeshFileLoader.h +++ b/source/Irrlicht/COBJMeshFileLoader.h @@ -30,7 +30,7 @@ public: //! returns true if the file maybe is able to be loaded by this class //! based on the file extension (e.g. ".obj") - virtual bool isALoadableFileExtension(const c8* fileName) const; + virtual bool isALoadableFileExtension(const core::string& filename) const; //! creates/loads an animated mesh from the file. //! \return Pointer to the created mesh. Returns 0 if loading failed. @@ -71,7 +71,7 @@ private: }; // helper method for material reading - const c8* readTextures(const c8* bufPtr, const c8* const bufEnd, SObjMtl* currMaterial, const core::stringc& relPath); + const c8* readTextures(const c8* bufPtr, const c8* const bufEnd, SObjMtl* currMaterial, const core::string& relPath); // returns a pointer to the first printable character available in the buffer const c8* goFirstWord(const c8* buf, const c8* const bufEnd, bool acrossNewlines=true); @@ -87,7 +87,7 @@ private: const c8* goAndCopyNextWord(c8* outBuf, const c8* inBuf, u32 outBufLength, const c8* const pBufEnd); //! Read the material from the given file - void readMTL(const c8* fileName, const core::stringc& relPath); + void readMTL(const c8* fileName, const core::string& relPath); //! Find and return the material with the given name SObjMtl* findMtl(const core::stringc& mtlName, const core::stringc& grpName); diff --git a/source/Irrlicht/COBJMeshWriter.cpp b/source/Irrlicht/COBJMeshWriter.cpp index a1ed075f..91adb00e 100644 --- a/source/Irrlicht/COBJMeshWriter.cpp +++ b/source/Irrlicht/COBJMeshWriter.cpp @@ -164,7 +164,7 @@ bool COBJMeshWriter::writeMesh(io::IWriteFile* file, scene::IMesh* mesh, s32 fla if (mat.size() == 0) return true; - file = FileSystem->createAndWriteFile((name).c_str()); + file = FileSystem->createAndWriteFile( name ); if (file) { os::Printer::log("Writing material", file->getFileName()); diff --git a/source/Irrlicht/COCTLoader.cpp b/source/Irrlicht/COCTLoader.cpp index 1cb3ddbd..23cdfb14 100644 --- a/source/Irrlicht/COCTLoader.cpp +++ b/source/Irrlicht/COCTLoader.cpp @@ -209,7 +209,7 @@ IAnimatedMesh* COCTLoader::createMesh(io::IReadFile* file) tex.push_back(SceneManager->getVideoDriver()->getTexture(path)); else // try to read in the relative path of the OCT file - tex.push_back(SceneManager->getVideoDriver()->getTexture( (relpath + path).c_str() )); + tex.push_back(SceneManager->getVideoDriver()->getTexture( (relpath + path) )); } // prepare lightmaps @@ -323,9 +323,9 @@ IAnimatedMesh* COCTLoader::createMesh(io::IReadFile* file) //! returns true if the file maybe is able to be loaded by this class //! based on the file extension (e.g. ".bsp") -bool COCTLoader::isALoadableFileExtension(const c8* filename) const +bool COCTLoader::isALoadableFileExtension(const core::string& filename) const { - return strstr(filename, ".oct")!=0; + return core::hasFileExtension ( filename, "oct" ); } diff --git a/source/Irrlicht/COCTLoader.h b/source/Irrlicht/COCTLoader.h index 6e08c78c..2f364946 100644 --- a/source/Irrlicht/COCTLoader.h +++ b/source/Irrlicht/COCTLoader.h @@ -70,7 +70,7 @@ namespace scene //! returns true if the file maybe is able to be loaded by this class //! based on the file extension (e.g. ".cob") - virtual bool isALoadableFileExtension(const c8* fileName) const; + virtual bool isALoadableFileExtension(const core::string& filename) const; //! creates/loads an animated mesh from the file. //! \return Pointer to the created mesh. Returns 0 if loading failed. diff --git a/source/Irrlicht/COSOperator.cpp b/source/Irrlicht/COSOperator.cpp index 3e0a7f74..72f3f909 100644 --- a/source/Irrlicht/COSOperator.cpp +++ b/source/Irrlicht/COSOperator.cpp @@ -6,7 +6,10 @@ #include "IrrCompileConfig.h" #ifdef _IRR_WINDOWS_API_ +#ifdef _IRR_XBOX_PLATFORM_ +#else #include +#endif #else #include #include @@ -46,7 +49,8 @@ void COSOperator::copyToClipboard(const c8* text) const return; // Windows version -#if defined(_IRR_WINDOWS_API_) +#if defined(_IRR_XBOX_PLATFORM_) +#elif defined(_IRR_WINDOWS_API_) if (!OpenClipboard(NULL) || text == 0) return; @@ -79,7 +83,9 @@ void COSOperator::copyToClipboard(const c8* text) const //! \return Returns 0 if no string is in there. c8* COSOperator::getTextFromClipboard() const { -#if defined(_IRR_WINDOWS_API_) +#if defined(_IRR_XBOX_PLATFORM_) + return 0; +#elif defined(_IRR_WINDOWS_API_) if (!OpenClipboard(NULL)) return 0; @@ -104,7 +110,7 @@ c8* COSOperator::getTextFromClipboard() const bool COSOperator::getProcessorSpeedMHz(u32* MHz) const { -#if defined(_IRR_WINDOWS_API_) && !defined(_WIN32_WCE ) +#if defined(_IRR_WINDOWS_API_) && !defined(_WIN32_WCE ) && !defined (_IRR_XBOX_PLATFORM_) LONG Error; HKEY Key; @@ -146,7 +152,7 @@ bool COSOperator::getProcessorSpeedMHz(u32* MHz) const bool COSOperator::getSystemMemory(u32* Total, u32* Avail) const { -#if defined(_IRR_WINDOWS_API_) +#if defined(_IRR_WINDOWS_API_) && !defined (_IRR_XBOX_PLATFORM_) MEMORYSTATUS MemoryStatus; MemoryStatus.dwLength = sizeof(MEMORYSTATUS); diff --git a/source/Irrlicht/COctTreeSceneNode.cpp b/source/Irrlicht/COctTreeSceneNode.cpp index 2e9ffacd..e45c5a54 100644 --- a/source/Irrlicht/COctTreeSceneNode.cpp +++ b/source/Irrlicht/COctTreeSceneNode.cpp @@ -104,10 +104,11 @@ void COctTreeSceneNode::render() SViewFrustum frust = *camera->getViewFrustum(); //transform the frustum to the current absolute transformation - core::matrix4 invTrans(AbsoluteTransformation); - invTrans.makeInverse(); - - frust.transform(invTrans); + if ( !AbsoluteTransformation.isIdentity() ) + { + core::matrix4 invTrans(AbsoluteTransformation, core::matrix4::EM4CONST_INVERSE); + frust.transform(invTrans); + } /* //const core::aabbox3d &box = frust.getBoundingBox(); */ @@ -180,9 +181,14 @@ void COctTreeSceneNode::render() if (transparent == isTransparentPass) { driver->setMaterial(Materials[i]); +#if defined (OCTTREE_USE_HARDWARE) + driver->drawMeshBuffer ( &LightMapMeshes[i] ); + +#else driver->drawIndexedTriangleList( &LightMapMeshes[i].Vertices[0], LightMapMeshes[i].Vertices.size(), d[i].Indices, d[i].CurrentSize / 3); +#endif } } @@ -277,6 +283,7 @@ bool COctTreeSceneNode::createTree(IMesh* mesh) u32 nodeCount = 0; u32 polyCount = 0; + u32 i; Box = mesh->getBoundingBox(); @@ -288,9 +295,10 @@ bool COctTreeSceneNode::createTree(IMesh* mesh) { case video::EVT_STANDARD: { - for (u32 i=0; igetMeshBufferCount(); ++i) + for (i=0; igetMeshBufferCount(); ++i) { IMeshBuffer* b = mesh->getMeshBuffer(i); + if (b->getVertexCount() && b->getIndexCount()) { Materials.push_back(b->getMaterial()); @@ -318,9 +326,22 @@ bool COctTreeSceneNode::createTree(IMesh* mesh) break; case video::EVT_2TCOORDS: { - for (u32 i=0; igetMeshBufferCount(); ++i) + IMeshBuffer* b; + u32 meshReserve = 0; + for ( i=0; i < mesh->getMeshBufferCount(); ++i) { - IMeshBuffer* b = mesh->getMeshBuffer(i); + b = mesh->getMeshBuffer(i); + if (b->getVertexCount() && b->getIndexCount()) + { + meshReserve += 1; + } + + } + LightMapMeshes.reallocate ( LightMapMeshes.size() + meshReserve ); + + for ( i=0; i < mesh->getMeshBufferCount(); ++i) + { + b = mesh->getMeshBuffer(i); if (b->getVertexCount() && b->getIndexCount()) { @@ -329,6 +350,10 @@ bool COctTreeSceneNode::createTree(IMesh* mesh) OctTree::SMeshChunk& nchunk = LightMapMeshes.getLast(); nchunk.MaterialId = Materials.size() - 1; +#if defined (OCTTREE_USE_HARDWARE) + nchunk.setHardwareMappingHint ( b->getHardwareMappingHint_Vertex() ); +#endif + u32 v; nchunk.Vertices.reallocate(b->getVertexCount()); for (v=0; vgetVertexCount(); ++v) @@ -424,7 +449,7 @@ void COctTreeSceneNode::deserializeAttributes(io::IAttributes* in, io::SAttribut const s32 oldMinimal = MinimalPolysPerNode; MinimalPolysPerNode = in->getAttributeAsInt("MinimalPolysPerNode"); - core::stringc newMeshStr = in->getAttributeAsString("Mesh"); + core::string newMeshStr = in->getAttributeAsString("Mesh"); IMesh* newMesh = 0; diff --git a/source/Irrlicht/COctTreeTriangleSelector.cpp b/source/Irrlicht/COctTreeTriangleSelector.cpp index 316ef7f3..8df329c5 100644 --- a/source/Irrlicht/COctTreeTriangleSelector.cpp +++ b/source/Irrlicht/COctTreeTriangleSelector.cpp @@ -114,20 +114,24 @@ void COctTreeTriangleSelector::getTriangles(core::triangle3df* triangles, const core::aabbox3d& box, const core::matrix4* transform) const { - core::matrix4 mat; + core::matrix4 mat ( core::matrix4::EM4CONST_NOTHING ); core::aabbox3d invbox = box; if (SceneNode) { - mat = SceneNode->getAbsoluteTransformation(); - mat.makeInverse(); + SceneNode->getAbsoluteTransformation().getInverse ( mat ); mat.transformBoxEx(invbox); } - mat.makeIdentity(); - if (transform) + { mat = *transform; + } + else + { + mat.makeIdentity(); + } + if (SceneNode) mat *= SceneNode->getAbsoluteTransformation(); @@ -158,10 +162,9 @@ void COctTreeTriangleSelector::getTrianglesFromOctTree( for (i=0; iTriangles[i]; - mat->transformVect(triangles[trianglesWritten].pointA); - mat->transformVect(triangles[trianglesWritten].pointB); - mat->transformVect(triangles[trianglesWritten].pointC); + mat->transformVect(triangles[trianglesWritten].pointA, node->Triangles[i].pointA ); + mat->transformVect(triangles[trianglesWritten].pointB, node->Triangles[i].pointB ); + mat->transformVect(triangles[trianglesWritten].pointC, node->Triangles[i].pointC ); ++trianglesWritten; } @@ -173,16 +176,87 @@ void COctTreeTriangleSelector::getTrianglesFromOctTree( //! Gets all triangles which have or may have contact with a 3d line. +// new version: from user Piraaate void COctTreeTriangleSelector::getTriangles(core::triangle3df* triangles, s32 arraySize, s32& outTriangleCount, const core::line3d& line, const core::matrix4* transform) const { +#if 0 core::aabbox3d box(line.start); box.addInternalPoint(line.end); // TODO: Could be optimized for line a little bit more. COctTreeTriangleSelector::getTriangles(triangles, arraySize, outTriangleCount, box, transform); +#else + + core::matrix4 mat ( core::matrix4::EM4CONST_NOTHING ); + + core::vector3df vectStartInv ( line.start ), vectEndInv ( line.end ); + if (SceneNode) + { + mat = SceneNode->getAbsoluteTransformation(); + mat.makeInverse(); + mat.transformVect(vectStartInv, line.start); + mat.transformVect(vectEndInv, line.end); + } + core::line3d invline(vectStartInv, vectEndInv); + + mat.makeIdentity(); + + if (transform) + mat = (*transform); + + if (SceneNode) + mat *= SceneNode->getAbsoluteTransformation(); + + s32 trianglesWritten = 0; + + if (Root) + getTrianglesFromOctTree(Root, trianglesWritten, arraySize, invline, &mat, triangles); + + outTriangleCount = trianglesWritten; +#endif +} + +void COctTreeTriangleSelector::getTrianglesFromOctTree(SOctTreeNode* node, s32& trianglesWritten, s32 maximumSize, + const core::line3d& line, const core::matrix4* transform, + core::triangle3df* triangles)const +{ + if (!node->Box.intersectsWithLine(line)) + return; + + s32 cnt = node->Triangles.size(); + if (cnt + trianglesWritten > maximumSize) + cnt -= cnt + trianglesWritten - maximumSize; + + s32 i; + + if ( transform->isIdentity() ) + { + for (i=0; iTriangles[i]; + ++trianglesWritten; + } + } + else + { + for (i=0; iTriangles[i]; + transform->transformVect(triangles[trianglesWritten].pointA); + transform->transformVect(triangles[trianglesWritten].pointB); + transform->transformVect(triangles[trianglesWritten].pointC); + ++trianglesWritten; + } + } + + for (i=0; i<8; ++i) + if (node->Child[i]) + getTrianglesFromOctTree(node->Child[i], trianglesWritten, + maximumSize, line, transform, triangles); + } diff --git a/source/Irrlicht/COctTreeTriangleSelector.h b/source/Irrlicht/COctTreeTriangleSelector.h index 1e11efb8..dea7b7e4 100644 --- a/source/Irrlicht/COctTreeTriangleSelector.h +++ b/source/Irrlicht/COctTreeTriangleSelector.h @@ -62,6 +62,11 @@ private: const core::matrix4* transform, core::triangle3df* triangles) const; + void getTrianglesFromOctTree(SOctTreeNode* node, s32& trianglesWritten, + s32 maximumSize, const core::line3d& line, + const core::matrix4* transform, + core::triangle3df* triangles) const; + SOctTreeNode* Root; s32 NodeCount; s32 MinimalPolysPerNode; diff --git a/source/Irrlicht/COgreMeshFileLoader.cpp b/source/Irrlicht/COgreMeshFileLoader.cpp index b4009ca8..84cd2e13 100644 --- a/source/Irrlicht/COgreMeshFileLoader.cpp +++ b/source/Irrlicht/COgreMeshFileLoader.cpp @@ -84,9 +84,9 @@ COgreMeshFileLoader::~COgreMeshFileLoader() //! returns true if the file maybe is able to be loaded by this class //! based on the file extension (e.g. ".bsp") -bool COgreMeshFileLoader::isALoadableFileExtension(const c8* filename) const +bool COgreMeshFileLoader::isALoadableFileExtension(const core::string& filename) const { - return strstr(filename, ".mesh")!=0; + return core::hasFileExtension ( filename, "mesh" ); } @@ -394,7 +394,7 @@ void COgreMeshFileLoader::composeMeshBufferMaterial(scene::IMeshBuffer* mb, cons material=Materials[k].Techniques[0].Passes[0].Material; if (Materials[k].Techniques[0].Passes[0].Texture.Filename.size()) { - material.setTexture(0, Driver->getTexture(Materials[k].Techniques[0].Passes[0].Texture.Filename.c_str())); + material.setTexture(0, Driver->getTexture(Materials[k].Techniques[0].Passes[0].Texture.Filename)); if (!material.getTexture(0)) { // retry with relative path @@ -405,7 +405,7 @@ void COgreMeshFileLoader::composeMeshBufferMaterial(scene::IMeshBuffer* mb, cons idx = relative.findLast('/'); if (idx != -1) relative = relative.subString(idx+1, relative.size()-idx-1); - material.setTexture(0, Driver->getTexture((CurrentlyLoadingFromPath+"/"+relative).c_str())); + material.setTexture(0, Driver->getTexture((CurrentlyLoadingFromPath+"/"+relative))); } } break; @@ -936,13 +936,13 @@ void COgreMeshFileLoader::loadMaterials(io::IReadFile* meshFile) #ifdef IRR_OGRE_LOADER_DEBUG os::Printer::log("Load Materials"); #endif - core::stringc token,filename=meshFile->getFileName(); - core::stringc material = filename.subString(0, filename.size()-4) + "material"; - io::IReadFile* file = FileSystem->createAndOpenFile(material.c_str()); + core::stringc token =meshFile->getFileName(); + core::string filename = token.subString(0, token.size()-4) + L"material"; + io::IReadFile* file = FileSystem->createAndOpenFile(filename.c_str()); if (!file) { - os::Printer::log("Could not load OGRE material", material.c_str()); + os::Printer::log("Could not load OGRE material", filename.c_str()); return; } diff --git a/source/Irrlicht/COgreMeshFileLoader.h b/source/Irrlicht/COgreMeshFileLoader.h index 29adf0fb..e5a8eca6 100644 --- a/source/Irrlicht/COgreMeshFileLoader.h +++ b/source/Irrlicht/COgreMeshFileLoader.h @@ -34,7 +34,7 @@ public: //! returns true if the file maybe is able to be loaded by this class //! based on the file extension (e.g. ".cob") - virtual bool isALoadableFileExtension(const c8* fileName) const; + virtual bool isALoadableFileExtension(const core::string& filename) const; //! creates/loads an animated mesh from the file. //! \return Pointer to the created mesh. Returns 0 if loading failed. diff --git a/source/Irrlicht/COpenGLDriver.cpp b/source/Irrlicht/COpenGLDriver.cpp index 8f92df10..2fbcc21f 100644 --- a/source/Irrlicht/COpenGLDriver.cpp +++ b/source/Irrlicht/COpenGLDriver.cpp @@ -721,7 +721,7 @@ void COpenGLDriver::setTransform(E_TRANSFORMATION_STATE state, const core::matri extGlActiveTexture(GL_TEXTURE0_ARB + i); glMatrixMode(GL_TEXTURE); - if (mat.isIdentity() && !isRTT) + if (!isRTT && mat.isIdentity() ) glLoadIdentity(); else { @@ -1762,7 +1762,7 @@ inline void COpenGLDriver::createGLTextureMatrix(GLfloat *o, const core::matrix4 //! returns a device dependent texture from a software surface (IImage) -video::ITexture* COpenGLDriver::createDeviceDependentTexture(IImage* surface, const char* name) +video::ITexture* COpenGLDriver::createDeviceDependentTexture(IImage* surface, const core::string& name) { return new COpenGLTexture(surface, name, this); } @@ -2887,15 +2887,13 @@ IGPUProgrammingServices* COpenGLDriver::getGPUProgrammingServices() } -ITexture* COpenGLDriver::addRenderTargetTexture(const core::dimension2d& size, const c8* name) +ITexture* COpenGLDriver::addRenderTargetTexture(const core::dimension2d& size, const core::string& name) { //disable mip-mapping bool generateMipLevels = getTextureCreationFlag(ETCF_CREATE_MIP_MAPS); setTextureCreationFlag(ETCF_CREATE_MIP_MAPS, false); video::ITexture* rtt = 0; - if (name==0) - name="rt"; #if defined(GL_EXT_framebuffer_object) // if driver supports FrameBufferObjects, use them if (queryFeature(EVDF_FRAMEBUFFER_OBJECT)) @@ -3211,7 +3209,7 @@ namespace video // WINDOWS VERSION // ----------------------------------- #ifdef _IRR_USE_WINDOWS_DEVICE_ -IVideoDriver* createOpenGLDriver(const irr::SIrrlichtCreationParameters& params, +IVideoDriver* createOpenGLDriver(const SIrrlichtCreationParameters& params, io::IFileSystem* io) { #ifdef _IRR_COMPILE_WITH_OPENGL_ diff --git a/source/Irrlicht/COpenGLDriver.h b/source/Irrlicht/COpenGLDriver.h index 8358a644..5432febf 100644 --- a/source/Irrlicht/COpenGLDriver.h +++ b/source/Irrlicht/COpenGLDriver.h @@ -7,6 +7,10 @@ #include "IrrCompileConfig.h" +#include "SIrrCreationParameters.h" + +#ifdef _IRR_COMPILE_WITH_OPENGL_ + #if defined(_IRR_WINDOWS_API_) // include windows headers for HWND #define WIN32_LEAN_AND_MEAN @@ -15,9 +19,6 @@ #include "CIrrDeviceMacOSX.h" #endif -#include "SIrrCreationParameters.h" - -#ifdef _IRR_COMPILE_WITH_OPENGL_ #include "CNullDriver.h" #include "IMaterialRendererServices.h" @@ -310,7 +311,7 @@ namespace video virtual u32 getMaximalPrimitiveCount() const; virtual ITexture* addRenderTargetTexture(const core::dimension2d& size, - const c8* name); + const core::string& name); //! set or reset render target virtual bool setRenderTarget(video::E_RENDER_TARGET target, bool clearTarget, @@ -362,7 +363,7 @@ namespace video //! inits the parts of the open gl driver used on all platforms bool genericDriverInit(const core::dimension2d& screenSize, bool stencilBuffer); //! returns a device dependent texture from a software surface (IImage) - virtual video::ITexture* createDeviceDependentTexture(IImage* surface, const char* name); + virtual video::ITexture* createDeviceDependentTexture(IImage* surface, const core::string& name); //! creates a transposed matrix in supplied GLfloat array to pass to OpenGL inline void createGLMatrix(GLfloat gl_matrix[16], const core::matrix4& m); diff --git a/source/Irrlicht/COpenGLParallaxMapRenderer.h b/source/Irrlicht/COpenGLParallaxMapRenderer.h index a97c3ab8..3424c3fe 100644 --- a/source/Irrlicht/COpenGLParallaxMapRenderer.h +++ b/source/Irrlicht/COpenGLParallaxMapRenderer.h @@ -35,6 +35,7 @@ public: //! Returns the render capability of the material. virtual s32 getRenderCapability() const; + virtual void OnSetMaterial(const SMaterial& material) { } virtual void OnSetMaterial(const video::SMaterial& material, const video::SMaterial& lastMaterial, bool resetAllRenderstates, video::IMaterialRendererServices* services); diff --git a/source/Irrlicht/COpenGLTexture.cpp b/source/Irrlicht/COpenGLTexture.cpp index 01bc1860..0ba3b488 100644 --- a/source/Irrlicht/COpenGLTexture.cpp +++ b/source/Irrlicht/COpenGLTexture.cpp @@ -21,7 +21,7 @@ namespace video { //! constructor for usual textures -COpenGLTexture::COpenGLTexture(IImage* origImage, const char* name, COpenGLDriver* driver) +COpenGLTexture::COpenGLTexture(IImage* origImage, const core::string& name, COpenGLDriver* driver) : ITexture(name), ColorFormat(ECF_A8R8G8B8), Driver(driver), Image(0), TextureName(0), InternalFormat(GL_RGBA), PixelFormat(GL_BGRA_EXT), PixelType(GL_UNSIGNED_BYTE), @@ -54,7 +54,7 @@ COpenGLTexture::COpenGLTexture(IImage* origImage, const char* name, COpenGLDrive } //! constructor for basic setup (only for derived classes) -COpenGLTexture::COpenGLTexture(const char* name, COpenGLDriver* driver) +COpenGLTexture::COpenGLTexture(const core::string& name, COpenGLDriver* driver) : ITexture(name), ColorFormat(ECF_A8R8G8B8), Driver(driver), Image(0), TextureName(0), InternalFormat(GL_RGBA), PixelFormat(GL_BGRA_EXT), PixelType(GL_UNSIGNED_BYTE), @@ -449,7 +449,7 @@ static bool checkFBOStatus(COpenGLDriver* Driver); //! RTT ColorFrameBuffer constructor COpenGLFBOTexture::COpenGLFBOTexture(const core::dimension2d& size, - const char* name, + const core::string& name, COpenGLDriver* driver) : COpenGLTexture(name, driver), DepthTexture(0), ColorFrameBuffer(0) { @@ -532,7 +532,7 @@ void COpenGLFBOTexture::unbindRTT() //! RTT DepthBuffer constructor COpenGLFBODepthTexture::COpenGLFBODepthTexture( const core::dimension2d& size, - const char* name, + const core::string& name, COpenGLDriver* driver, bool useStencil) : COpenGLFBOTexture(size, name, driver), DepthRenderBuffer(0), diff --git a/source/Irrlicht/COpenGLTexture.h b/source/Irrlicht/COpenGLTexture.h index 73dc0bee..adc0e1c8 100644 --- a/source/Irrlicht/COpenGLTexture.h +++ b/source/Irrlicht/COpenGLTexture.h @@ -48,7 +48,7 @@ class COpenGLTexture : public ITexture public: //! constructor - COpenGLTexture(IImage* surface, const char* name, COpenGLDriver* driver=0); + COpenGLTexture(IImage* surface, const core::string& name, COpenGLDriver* driver=0); //! destructor virtual ~COpenGLTexture(); @@ -102,7 +102,7 @@ public: protected: //! protected constructor with basic setup, no GL texture name created, for derived classes - COpenGLTexture(const char* name, COpenGLDriver* driver); + COpenGLTexture(const core::string& name, COpenGLDriver* driver); //! get the desired color format based on texture creation flags and the input format. ECOLOR_FORMAT getBestColorFormat(ECOLOR_FORMAT format); @@ -139,7 +139,7 @@ class COpenGLFBOTexture : public COpenGLTexture public: //! FrameBufferObject constructor - COpenGLFBOTexture(const core::dimension2d& size, const char* name, COpenGLDriver* driver=0); + COpenGLFBOTexture(const core::dimension2d& size, const core::string& name, COpenGLDriver* driver=0); //! destructor virtual ~COpenGLFBOTexture(); @@ -164,7 +164,7 @@ class COpenGLFBODepthTexture : public COpenGLFBOTexture { public: //! FrameBufferObject depth constructor - COpenGLFBODepthTexture(const core::dimension2d& size, const char* name, COpenGLDriver* driver=0, bool useStencil=false); + COpenGLFBODepthTexture(const core::dimension2d& size, const core::string& name, COpenGLDriver* driver=0, bool useStencil=false); //! destructor virtual ~COpenGLFBODepthTexture(); diff --git a/source/Irrlicht/CPakReader.cpp b/source/Irrlicht/CPakReader.cpp index 9daca52c..3b4189ce 100644 --- a/source/Irrlicht/CPakReader.cpp +++ b/source/Irrlicht/CPakReader.cpp @@ -3,19 +3,84 @@ // For conditions of distribution and use, see copyright notice in irrlicht.h // Code contributed by skreamz +#include "IrrCompileConfig.h" #include "CPakReader.h" #include "os.h" - -#include "IrrCompileConfig.h" +#include "coreutil.h" namespace irr { namespace io { +//! Constructor +CArchiveLoaderPAK::CArchiveLoaderPAK( io::IFileSystem* fs) +: FileSystem(fs) +{ + #ifdef _DEBUG + setDebugName("CArchiveLoaderPAK"); + #endif +} + +//! destructor +CArchiveLoaderPAK::~CArchiveLoaderPAK() +{ +} + + +//! returns true if the file maybe is able to be loaded by this class +bool CArchiveLoaderPAK::isALoadableFileFormat(const core::string& filename) const +{ + return core::hasFileExtension ( filename, "zip", "pk3" ); +} + + +//! Creates an archive from the filename +/** \param file File handle to check. +\return Pointer to newly created archive, or 0 upon error. */ +IFileArchive* CArchiveLoaderPAK::createArchive(const core::string& filename, bool ignoreCase, bool ignorePaths) const +{ + IFileArchive *archive = 0; + io::IReadFile* file = FileSystem->createAndOpenFile(filename); + + if (file) + { + archive = createArchive ( file, ignoreCase, ignorePaths ); + file->drop (); + } + + return archive; +} + +//! creates/loads an archive from the file. +//! \return Pointer to the created archive. Returns 0 if loading failed. +IFileArchive* CArchiveLoaderPAK::createArchive(io::IReadFile* file, bool ignoreCase, bool ignorePaths) const +{ + IFileArchive *archive = 0; + if ( file ) + { + file->seek ( 0 ); + archive = new CPakReader(file, ignoreCase, ignorePaths); + } + return archive; +} + +//! Check if the file might be loaded by this class +/** Check might look into the file. +\param file File handle to check. +\return True if file seems to be loadable. */ +bool CArchiveLoaderPAK::isALoadableFileFormat(io::IReadFile* file) const +{ + return false; +} + + +/*! + PAK Reader +*/ CPakReader::CPakReader(IReadFile* file, bool ignoreCase, bool ignorePaths) -: File(file), IgnoreCase(ignoreCase), IgnorePaths(ignorePaths) +: File(file), IgnoreCase(ignoreCase), IgnorePaths(ignorePaths), Type ( "pak" ) { #ifdef _DEBUG setDebugName("CPakReader"); @@ -52,7 +117,7 @@ void CPakReader::extractFilename(SPakFileEntry* entry) if (IgnoreCase) entry->pakFileName.make_lower(); - const c8* p = entry->pakFileName.c_str() + lorfn; + const c16* p = entry->pakFileName.c_str() + lorfn; // suche ein slash oder den anfang. @@ -131,7 +196,7 @@ bool CPakReader::scanLocalHeader() //! opens a file by file name -IReadFile* CPakReader::openFile(const c8* filename) +IReadFile* CPakReader::openFile(const core::string& filename) { s32 index = findFile(filename); @@ -146,14 +211,13 @@ IReadFile* CPakReader::openFile(const c8* filename) //! opens a file by index IReadFile* CPakReader::openFile(s32 index) { - File->seek(FileList[index].pos); - return createLimitReadFile(FileList[index].simpleFileName.c_str(), File, FileList[index].length); + return createLimitReadFile(FileList[index].simpleFileName, File, FileList[index].pos, FileList[index].length); } //! returns count of files in archive -s32 CPakReader::getFileCount() +u32 CPakReader::getFileCount() { return FileList.size(); } @@ -161,44 +225,24 @@ s32 CPakReader::getFileCount() //! returns data of file -const SPakFileEntry* CPakReader::getFileInfo(s32 index) const +const IFileArchiveEntry* CPakReader::getFileInfo(u32 index) { return &FileList[index]; } -//! deletes the path from a filename -void CPakReader::deletePathFromFilename(core::stringc& filename) -{ - // delete path from filename - const c8* p = filename.c_str() + filename.size(); - - // search for path separator or beginning - - while (*p!='/' && *p!='\\' && p!=filename.c_str()) - --p; - - if (p != filename.c_str()) - { - ++p; - filename = p; - } -} - - - //! returns fileindex -s32 CPakReader::findFile(const c8* simpleFilename) +s32 CPakReader::findFile(const core::string& filename) { SPakFileEntry entry; - entry.simpleFileName = simpleFilename; + entry.simpleFileName = filename; if (IgnoreCase) entry.simpleFileName.make_lower(); if (IgnorePaths) - deletePathFromFilename(entry.simpleFileName); + core::deletePathFromFilename(entry.simpleFileName); s32 res = FileList.binary_search(entry); diff --git a/source/Irrlicht/CPakReader.h b/source/Irrlicht/CPakReader.h index 82d75e0d..61f1f94a 100644 --- a/source/Irrlicht/CPakReader.h +++ b/source/Irrlicht/CPakReader.h @@ -9,6 +9,7 @@ #include "IReadFile.h" #include "irrArray.h" #include "irrString.h" +#include "IFileSystem.h" namespace irr { @@ -22,28 +23,50 @@ namespace io }; - struct SPakFileEntry + struct SPakFileEntry: public IFileArchiveEntry { - core::stringc pakFileName; - core::stringc simpleFileName; - core::stringc path; + core::string pakFileName; u32 pos; u32 length; + }; - bool operator < (const SPakFileEntry& other) const - { - return simpleFileName < other.simpleFileName; - } + //! Archiveloader capable of loading ZIP Archives + class CArchiveLoaderPAK : public IArchiveLoader + { + public: + //! Constructor + CArchiveLoaderPAK(io::IFileSystem* fs); - bool operator == (const SPakFileEntry& other) const - { - return simpleFileName == other.simpleFileName; - } + //! destructor + virtual ~CArchiveLoaderPAK(); + + //! returns true if the file maybe is able to be loaded by this class + //! based on the file extension (e.g. ".zip") + virtual bool isALoadableFileFormat(const core::string& filename) const; + + //! Creates an archive from the filename + /** \param file File handle to check. + \return Pointer to newly created archive, or 0 upon error. */ + virtual IFileArchive* createArchive(const core::string& filename, bool ignoreCase, bool ignorePaths) const; + + //! Check if the file might be loaded by this class + /** Check might look into the file. + \param file File handle to check. + \return True if file seems to be loadable. */ + virtual bool isALoadableFileFormat(io::IReadFile* file) const; + + //! creates/loads an archive from the file. + //! \return Pointer to the created archive. Returns 0 if loading failed. + virtual io::IFileArchive* createArchive(io::IReadFile* file, bool ignoreCase, bool ignorePaths) const; + + private: + io::IFileSystem* FileSystem; }; - class CPakReader : public IReferenceCounted + //! reads from pak + class CPakReader : public IFileArchive { public: @@ -51,30 +74,40 @@ namespace io virtual ~CPakReader(); //! opens a file by file name - virtual IReadFile* openFile(const c8* filename); + virtual IReadFile* openFile(const core::string& filename); //! opens a file by index IReadFile* openFile(s32 index); //! returns count of files in archive - s32 getFileCount(); + virtual u32 getFileCount(); //! returns data of file - const SPakFileEntry* getFileInfo(s32 index) const; + virtual const IFileArchiveEntry* getFileInfo(u32 index); //! returns fileindex - s32 findFile(const c8* filename); + virtual s32 findFile(const core::string& filename); + + //! get the class Type + virtual const core::string& getArchiveType() { return Type; } + + //! return the id of the file Archive + virtual const core::string& getArchiveName () + { + return File->getFileName(); + } + private: + core::string Type; + //! scans for a local header, returns false if there is no more local file header. bool scanLocalHeader(); //! splits filename from zip file into useful filenames and paths void extractFilename(SPakFileEntry* entry); - //! deletes the path from a filename - void deletePathFromFilename(core::stringc& filename); IReadFile* File; diff --git a/source/Irrlicht/CParticleBoxEmitter.cpp b/source/Irrlicht/CParticleBoxEmitter.cpp index 86b8f17f..138e0515 100644 --- a/source/Irrlicht/CParticleBoxEmitter.cpp +++ b/source/Irrlicht/CParticleBoxEmitter.cpp @@ -120,7 +120,7 @@ void CParticleBoxEmitter::serializeAttributes(io::IAttributes* out, io::SAttribu //! Reads attributes of the object. -s32 CParticleBoxEmitter::deserializeAttributes(s32 startIndex, io::IAttributes* in, io::SAttributeReadWriteOptions* options) +void CParticleBoxEmitter::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options) { // read data and correct input values here @@ -162,7 +162,6 @@ s32 CParticleBoxEmitter::deserializeAttributes(s32 startIndex, io::IAttributes* MaxLifeTime = core::max_(MaxLifeTime, MinLifeTime); MinLifeTime = core::min_(MinLifeTime, MaxLifeTime); - return in->findAttribute("MaxAngleDegrees"); } diff --git a/source/Irrlicht/CParticleBoxEmitter.h b/source/Irrlicht/CParticleBoxEmitter.h index 052ee49c..f59e7719 100644 --- a/source/Irrlicht/CParticleBoxEmitter.h +++ b/source/Irrlicht/CParticleBoxEmitter.h @@ -90,7 +90,7 @@ public: virtual void serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options) const; //! Reads attributes of the object. - virtual s32 deserializeAttributes(s32 startIndex, io::IAttributes* in, io::SAttributeReadWriteOptions* options); + virtual void deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options); private: diff --git a/source/Irrlicht/CParticleFadeOutAffector.cpp b/source/Irrlicht/CParticleFadeOutAffector.cpp index 87c3897e..5559c424 100644 --- a/source/Irrlicht/CParticleFadeOutAffector.cpp +++ b/source/Irrlicht/CParticleFadeOutAffector.cpp @@ -58,24 +58,10 @@ void CParticleFadeOutAffector::serializeAttributes(io::IAttributes* out, io::SAt //! scripting languages, editors, debuggers or xml deserialization purposes. //! \param startIndex: start index where to start reading attributes. //! \return: returns last index of an attribute read by this affector -s32 CParticleFadeOutAffector::deserializeAttributes(s32 startIndex, io::IAttributes* in, io::SAttributeReadWriteOptions* options) +void CParticleFadeOutAffector::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options) { - const char* name = in->getAttributeName(startIndex); - - if (!name || strcmp(name, "TargetColor")) - return startIndex; // attribute not valid - - TargetColor = in->getAttributeAsColor(startIndex); - ++startIndex; - - name = in->getAttributeName(startIndex); - if (!name || strcmp(name, "FadeOutTime")) - return startIndex; // attribute not valid - - FadeOutTime = in->getAttributeAsFloat(startIndex); - - ++startIndex; - return startIndex; + TargetColor = in->getAttributeAsColor("TargetColor"); + FadeOutTime = in->getAttributeAsFloat("FadeOutTime"); } diff --git a/source/Irrlicht/CParticleFadeOutAffector.h b/source/Irrlicht/CParticleFadeOutAffector.h index 9db8af46..7ad97fa0 100644 --- a/source/Irrlicht/CParticleFadeOutAffector.h +++ b/source/Irrlicht/CParticleFadeOutAffector.h @@ -47,7 +47,7 @@ public: //! scripting languages, editors, debuggers or xml deserialization purposes. //! \param startIndex: start index where to start reading attributes. //! \return: returns last index of an attribute read by this affector - virtual s32 deserializeAttributes(s32 startIndex, io::IAttributes* in, io::SAttributeReadWriteOptions* options); + virtual void deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options); private: diff --git a/source/Irrlicht/CParticleGravityAffector.cpp b/source/Irrlicht/CParticleGravityAffector.cpp index 295677c8..c57ca34e 100644 --- a/source/Irrlicht/CParticleGravityAffector.cpp +++ b/source/Irrlicht/CParticleGravityAffector.cpp @@ -51,24 +51,10 @@ void CParticleGravityAffector::serializeAttributes(io::IAttributes* out, io::SAt //! Reads attributes of the object. -s32 CParticleGravityAffector::deserializeAttributes(s32 startIndex, io::IAttributes* in, io::SAttributeReadWriteOptions* options) +void CParticleGravityAffector::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options) { - const char* name = in->getAttributeName(startIndex); - - if (!name || strcmp(name, "Gravity")) - return startIndex; // attribute not valid - - Gravity = in->getAttributeAsVector3d(startIndex); - ++startIndex; - - name = in->getAttributeName(startIndex); - if (!name || strcmp(name, "TimeForceLost")) - return startIndex; // attribute not valid - - TimeForceLost = in->getAttributeAsFloat(startIndex); - - ++startIndex; - return startIndex; + Gravity = in->getAttributeAsVector3d("Gravity"); + TimeForceLost = in->getAttributeAsFloat("TimeForceLost"); } diff --git a/source/Irrlicht/CParticleGravityAffector.h b/source/Irrlicht/CParticleGravityAffector.h index 1ab67a00..d517c25f 100644 --- a/source/Irrlicht/CParticleGravityAffector.h +++ b/source/Irrlicht/CParticleGravityAffector.h @@ -49,10 +49,9 @@ public: //! scripting languages, editors, debuggers or xml deserialization purposes. //! \param startIndex: start index where to start reading attributes. //! \return: returns last index of an attribute read by this affector - virtual s32 deserializeAttributes(s32 startIndex, io::IAttributes* in, io::SAttributeReadWriteOptions* options); + virtual void deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options); private: - f32 TimeForceLost; core::vector3df Gravity; }; diff --git a/source/Irrlicht/CParticlePointEmitter.cpp b/source/Irrlicht/CParticlePointEmitter.cpp index 889076b7..7a94f6d0 100644 --- a/source/Irrlicht/CParticlePointEmitter.cpp +++ b/source/Irrlicht/CParticlePointEmitter.cpp @@ -99,7 +99,7 @@ void CParticlePointEmitter::serializeAttributes(io::IAttributes* out, io::SAttri //! Reads attributes of the object. -s32 CParticlePointEmitter::deserializeAttributes(s32 startIndex, io::IAttributes* in, io::SAttributeReadWriteOptions* options) +void CParticlePointEmitter::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options) { Direction = in->getAttributeAsVector3d("Direction"); if (Direction.getLength() == 0) @@ -122,8 +122,6 @@ s32 CParticlePointEmitter::deserializeAttributes(s32 startIndex, io::IAttributes MinLifeTime = core::max_(0u, MinLifeTime); MaxLifeTime = core::max_(MaxLifeTime, MinLifeTime); MinLifeTime = core::min_(MinLifeTime, MaxLifeTime); - - return in->findAttribute("MaxAngleDegrees"); } diff --git a/source/Irrlicht/CParticlePointEmitter.h b/source/Irrlicht/CParticlePointEmitter.h index ae436ae2..4ae94045 100644 --- a/source/Irrlicht/CParticlePointEmitter.h +++ b/source/Irrlicht/CParticlePointEmitter.h @@ -81,7 +81,7 @@ public: virtual void serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options) const; //! Reads attributes of the object. - virtual s32 deserializeAttributes(s32 startIndex, io::IAttributes* in, io::SAttributeReadWriteOptions* options); + virtual void deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options); private: diff --git a/source/Irrlicht/CParticleScaleAffector.cpp b/source/Irrlicht/CParticleScaleAffector.cpp index 6bf002c6..6b051e44 100644 --- a/source/Irrlicht/CParticleScaleAffector.cpp +++ b/source/Irrlicht/CParticleScaleAffector.cpp @@ -23,18 +23,17 @@ namespace irr } - void CParticleScaleAffector::serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options) + void CParticleScaleAffector::serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options) const { out->addFloat("ScaleToWidth", ScaleTo.Width); out->addFloat("ScaleToHeight", ScaleTo.Height); } - s32 CParticleScaleAffector::deserializeAttributes(s32 startIndex, io::IAttributes* in, io::SAttributeReadWriteOptions* options) + void CParticleScaleAffector::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options) { ScaleTo.Width = in->getAttributeAsFloat("ScaleToWidth"); ScaleTo.Height = in->getAttributeAsFloat("ScaleToHeight"); - return 0; } diff --git a/source/Irrlicht/CParticleScaleAffector.h b/source/Irrlicht/CParticleScaleAffector.h index 6079ab76..99f7b0bf 100644 --- a/source/Irrlicht/CParticleScaleAffector.h +++ b/source/Irrlicht/CParticleScaleAffector.h @@ -17,14 +17,14 @@ namespace irr //! Writes attributes of the object. //! Implement this to expose the attributes of your scene node animator for //! scripting languages, editors, debuggers or xml serialization purposes. - virtual void serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options); + virtual void serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options) const; //! Reads attributes of the object. //! Implement this to set the attributes of your scene node animator for //! scripting languages, editors, debuggers or xml deserialization purposes. //! \param startIndex: start index where to start reading attributes. //! \return: returns last index of an attribute read by this affector - virtual s32 deserializeAttributes(s32 startIndex, io::IAttributes* in, io::SAttributeReadWriteOptions* options); + virtual void deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options); //! Get emitter type virtual E_PARTICLE_AFFECTOR_TYPE getType() const; diff --git a/source/Irrlicht/CParticleSystemSceneNode.cpp b/source/Irrlicht/CParticleSystemSceneNode.cpp index 984c8a3c..552d744d 100644 --- a/source/Irrlicht/CParticleSystemSceneNode.cpp +++ b/source/Irrlicht/CParticleSystemSceneNode.cpp @@ -613,10 +613,15 @@ void CParticleSystemSceneNode::deserializeAttributes(io::IAttributes* in, io::SA u32 idx = 0; +#if 0 if (Emitter) idx = Emitter->deserializeAttributes(idx, in); ++idx; +#else + if (Emitter) + Emitter->deserializeAttributes(in); +#endif // read affectors @@ -655,8 +660,13 @@ void CParticleSystemSceneNode::deserializeAttributes(io::IAttributes* in, io::SA if (aff) { +#if 0 idx = aff->deserializeAttributes(idx, in, options); ++idx; +#else + aff->deserializeAttributes(in, options); +#endif + addAffector(aff); aff->drop(); } diff --git a/source/Irrlicht/CQ3LevelMesh.cpp b/source/Irrlicht/CQ3LevelMesh.cpp index 85ce38f1..7fc1e97a 100644 --- a/source/Irrlicht/CQ3LevelMesh.cpp +++ b/source/Irrlicht/CQ3LevelMesh.cpp @@ -12,32 +12,36 @@ #include "irrString.h" #include "ILightSceneNode.h" #include "IQ3Shader.h" +#include "IFileList.h" + +//#define TJUNCTION_SOLVER_ROUND +//#define TJUNCTION_SOLVER_0125 namespace irr { namespace scene { + using namespace quake3; //! constructor -CQ3LevelMesh::CQ3LevelMesh(io::IFileSystem* fs, scene::ISceneManager* smgr) +CQ3LevelMesh::CQ3LevelMesh( io::IFileSystem* fs, + scene::ISceneManager* smgr, + const Q3LevelLoadParameter &loadParam) : Textures(0), LightMaps(0), Vertices(0), Faces(0), Planes(0), Nodes(0), Leafs(0), LeafFaces(0), - MeshVerts(0), Brushes(0), FileSystem(fs), SceneManager(smgr) + MeshVerts(0), Brushes(0), FileSystem(fs), SceneManager(smgr),LoadParam (loadParam) { #ifdef _DEBUG IReferenceCounted::setDebugName("CQ3LevelMesh"); #endif - for ( s32 i = 0; i!= quake3::E_Q3_MESH_SIZE; ++i ) + for ( s32 i = 0; i!= E_Q3_MESH_SIZE; ++i ) { Mesh[i] = 0; } - if (smgr) - Driver = smgr->getVideoDriver(); - else - Driver = 0; + Driver = smgr ? smgr->getVideoDriver() : 0; if (Driver) Driver->grab(); @@ -52,16 +56,7 @@ CQ3LevelMesh::CQ3LevelMesh(io::IFileSystem* fs, scene::ISceneManager* smgr) //! destructor CQ3LevelMesh::~CQ3LevelMesh() { - delete [] Textures; - delete [] LightMaps; - delete [] Vertices; - delete [] Faces; - delete [] Planes; - delete [] Nodes; - delete [] Leafs; - delete [] LeafFaces; - delete [] MeshVerts; - delete [] Brushes; + cleanLoader (); if (Driver) Driver->drop(); @@ -69,10 +64,13 @@ CQ3LevelMesh::~CQ3LevelMesh() if (FileSystem) FileSystem->drop(); - for ( s32 i = 0; i!= quake3::E_Q3_MESH_SIZE; ++i ) + for ( s32 i = 0; i!= E_Q3_MESH_SIZE; ++i ) { - if (Mesh[i]) + if ( Mesh[i] ) + { Mesh[i]->drop(); + Mesh[i] = 0; + } } ReleaseShader(); @@ -88,7 +86,6 @@ bool CQ3LevelMesh::loadFile(io::IReadFile* file) LevelName = file->getFileName(); - tBSPHeader header; file->read(&header, sizeof(tBSPHeader)); #ifdef __BIG_ENDIAN__ @@ -96,33 +93,50 @@ bool CQ3LevelMesh::loadFile(io::IReadFile* file) header.version = os::Byteswap::byteswap(header.version); #endif - if (header.strID != 0x50534249 || header.version != 0x2e) + if ( (header.strID != 0x50534249 || // IBSP + ( header.version != 0x2e // quake3 + && header.version != 0x2f // rtcw + ) + ) + && + ( header.strID != 0x50534252 || header.version != 1 ) // RBSP, starwars jedi, sof + ) { os::Printer::log("Could not load .bsp file, unknown header.", file->getFileName(), ELL_ERROR); return false; } - // now read lumps +#if 0 + if ( header.strID == 0x50534252 ) // RBSP Raven + { + LoadParam.swapHeader = 1; + } +#endif + // now read lumps file->read(&Lumps[0], sizeof(tBSPLump)*kMaxLumps); - #ifdef __BIG_ENDIAN__ - for (int i=0;idrop(); - Mesh[index] = 0; - } -} - - //! returns the animated mesh based on a detail level. 0 is the lowest, 255 the highest detail. Note, that some Meshes will ignore the detail level. IMesh* CQ3LevelMesh::getMesh(s32 frameInMs, s32 detailLevel, s32 startFrameLoop, s32 endFrameLoop) { @@ -187,13 +205,14 @@ void CQ3LevelMesh::loadTextures(tBSPLump* l, io::IReadFile* file) file->seek(l->offset); file->read(Textures, l->length); - for (s32 i=0;iread(LightMaps, l->length); } - +/*! +*/ void CQ3LevelMesh::loadVerts(tBSPLump* l, io::IReadFile* file) { NumVertices = l->length / sizeof(tBSPVertex); @@ -216,7 +236,7 @@ void CQ3LevelMesh::loadVerts(tBSPLump* l, io::IReadFile* file) file->seek(l->offset); file->read(Vertices, l->length); - #ifdef __BIG_ENDIAN__ + if ( LoadParam.swapHeader ) for (s32 i=0;ilength / sizeof(tBSPFace); @@ -242,70 +263,83 @@ void CQ3LevelMesh::loadFaces(tBSPLump* l, io::IReadFile* file) file->seek(l->offset); file->read(Faces, l->length); - #ifdef __BIG_ENDIAN__ - for ( s32 i=0;i entity; @@ -319,28 +353,48 @@ void CQ3LevelMesh::loadEntities(tBSPLump* l, io::IReadFile* file) } -// load shaders named in bsp -void CQ3LevelMesh::loadShaders(tBSPLump* l, io::IReadFile* file) +/*! + load fog brushes +*/ +void CQ3LevelMesh::loadFogs(tBSPLump* l, io::IReadFile* file) { - u32 files = l->length / sizeof(tBSPShader); + u32 files = l->length / sizeof(tBSPFog); file->seek( l->offset ); - - tBSPShader def; + tBSPFog fog; + const IShader *shader; + STexShader t; for ( u32 i = 0; i!= files; ++i ) { - file->read( &def, sizeof( def ) ); - getShader(def.strName); + file->read( &fog, sizeof( fog ) ); + + shader = getShader( fog.shader ); + t.Texture = 0; + t.ShaderID = shader ? shader->id : -1; + + FogMap.push_back ( t ); } } +/*! + load models named in bsp +*/ void CQ3LevelMesh::loadModels(tBSPLump* l, io::IReadFile* file) { - // ignore + u32 files = l->length / sizeof(tBSPModel); + file->seek( l->offset ); + + tBSPModel def; + for ( u32 i = 0; i!= files; ++i ) + { + file->read( &def, sizeof( def ) ); + } + } - +/*! +*/ void CQ3LevelMesh::loadMeshVerts(tBSPLump* l, io::IReadFile* file) { NumMeshVerts = l->length / sizeof(s32); @@ -349,37 +403,43 @@ void CQ3LevelMesh::loadMeshVerts(tBSPLump* l, io::IReadFile* file) file->seek(l->offset); file->read(MeshVerts, l->length); - #ifdef __BIG_ENDIAN__ - for (int i=0;iVariableGroup.push_back( quake3::SVarGroup() ); + groupList->VariableGroup.push_back( SVarGroup() ); active = last = 0; do @@ -535,7 +595,7 @@ void CQ3LevelMesh::parser_parse( const void * data, const u32 size, CQ3LevelMesh { //stack = core::min_( stack + 1, 7 ); - groupList->VariableGroup.push_back( quake3::SVarGroup() ); + groupList->VariableGroup.push_back( SVarGroup() ); last = active; active = groupList->VariableGroup.size() - 1; entity.clear(); @@ -584,8 +644,8 @@ void CQ3LevelMesh::parser_parse( const void * data, const u32 size, CQ3LevelMesh // new group groupList->drop(); - groupList = new quake3::SVarGroupList(); - groupList->VariableGroup.push_back( quake3::SVarGroup() ); + groupList = new SVarGroupList(); + groupList->VariableGroup.push_back( SVarGroup() ); last = 0; } @@ -602,6 +662,34 @@ void CQ3LevelMesh::parser_parse( const void * data, const u32 size, CQ3LevelMesh } +/* + this loader applies only textures for stage 1 & 2 +*/ +s32 CQ3LevelMesh::setShaderFogMaterial( video::SMaterial &material, const tBSPFace * face ) const +{ + material.MaterialType = video::EMT_SOLID; + material.Wireframe = false; + material.Lighting = false; + material.BackfaceCulling = false; + material.setTexture(0, 0); + material.setTexture(1, 0); + material.setTexture(2, 0); + material.setTexture(3, 0); + material.ZBuffer = video::EMDF_DEPTH_LESS_EQUAL; + material.ZWriteEnable = false; + material.MaterialTypeParam = 0.f; + + s32 shaderState = -1; + + if ( (u32) face->fogNum < FogMap.size() ) + { + material.setTexture(0, FogMap [ face->fogNum ].Texture); + shaderState = FogMap [ face->fogNum ].ShaderID; + } + + return shaderState; + +} /* this loader applies only textures for stage 1 & 2 */ @@ -630,25 +718,27 @@ s32 CQ3LevelMesh::setShaderMaterial( video::SMaterial &material, const tBSPFace if ( face->lightmapID >= 0 ) { material.setTexture(1, Lightmap [ face->lightmapID ]); - material.MaterialType = quake3::defaultMaterialType; + material.MaterialType = LoadParam.defaultLightMapMaterial; } // store shader ID material.MaterialTypeParam2 = (f32) shaderState; - const quake3::SShader *shader = getShader(shaderState); + const IShader *shader = getShader(shaderState); if ( 0 == shader ) return shaderState; - const quake3::SVarGroup *group; + return shaderState; + +#if 0 + const SVarGroup *group; - s32 index; // generic group = shader->getGroup( 1 ); if ( group ) { - material.BackfaceCulling = quake3::isDisabled( group->get( "cull" ) ); + material.BackfaceCulling = getCullingFunction( group->get( "cull" ) ); if ( group->isDefined( "surfaceparm", "nolightmap" ) ) { @@ -670,18 +760,27 @@ s32 CQ3LevelMesh::setShaderMaterial( video::SMaterial &material, const tBSPFace startPos = 0; - index = group->getIndex( "depthwrite" ); - if ( index >= 0 ) + if ( group->isDefined( "depthwrite" ) ) { material.ZWriteEnable = true; } - quake3::SBlendFunc blendfunc; - quake3::getBlendFunc( group->get( "blendfunc" ), blendfunc ); - quake3::getBlendFunc( group->get( "alphafunc" ), blendfunc ); + SBlendFunc blendfunc ( LoadParam.defaultModulate ); + getBlendFunc( group->get( "blendfunc" ), blendfunc ); + getBlendFunc( group->get( "alphafunc" ), blendfunc ); + + if ( 0 == LoadParam.alpharef && + ( blendfunc.type == video::EMT_TRANSPARENT_ALPHA_CHANNEL || + blendfunc.type == video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF + ) + ) + { + blendfunc.type = video::EMT_TRANSPARENT_ALPHA_CHANNEL; + blendfunc.param0 = 0.f; + } material.MaterialType = blendfunc.type; - material.MaterialTypeParam = blendfunc.param; + material.MaterialTypeParam = blendfunc.param0; // try if we can match better shaderState |= (material.MaterialType == video::EMT_SOLID ) ? 0x00020000 : 0; @@ -696,42 +795,67 @@ s32 CQ3LevelMesh::setShaderMaterial( video::SMaterial &material, const tBSPFace material.MaterialTypeParam2 = (f32) shaderState; return shaderState; +#endif } -//! constructs a mesh from the quake 3 level file. -void CQ3LevelMesh::constructMesh2() + +/*! +*/ +void CQ3LevelMesh::solveTJunction() { - s32 i, j, k; +} + +/*! + constructs a mesh from the quake 3 level file. +*/ +void CQ3LevelMesh::constructMesh() +{ + if ( LoadParam.verbose > 0 ) + { + LoadParam.startTime = os::Timer::getRealTime(); + + if ( LoadParam.verbose > 1 ) + { + snprintf( buf, sizeof ( buf ), + "quake3::constructMesh start to create %d faces, %d vertices,%d mesh vertices", + NumFaces, + NumVertices, + NumMeshVerts + ); + os::Printer::log(buf, ELL_INFORMATION); + } + + } + + s32 i, j, k,s; s32 *index; video::S3DVertex2TCoords temp[3]; - video::SMaterial material; + video::SMaterial material2; + + SToBuffer item [ E_Q3_MESH_SIZE ]; + u32 itemSize; - SToBuffer item; - - core::array < SToBuffer > toBuffer; - - const s32 mesh0size = (NumTextures+1) * (NumLightMaps+1); - for ( i=0; i < mesh0size; ++i) + for ( i=0; i < NumFaces; ++i) { - scene::SMeshBufferLightMap* buffer = new scene::SMeshBufferLightMap(); - - Mesh[quake3::E_Q3_MESH_GEOMETRY]->addMeshBuffer(buffer); - buffer->drop(); - } - - for ( i=0; ifogNum >= 0 ) + { + setShaderFogMaterial ( material2, face ); + item[itemSize].index = E_Q3_MESH_FOG; + item[itemSize].takeVertexColor = 1; + itemSize += 1; + } + + switch( face->type ) { case 1: // normal polygons case 2: // patches @@ -739,117 +863,81 @@ void CQ3LevelMesh::constructMesh2() { if ( 0 == shader ) { - item.takeVertexColor = material.getTexture(0) == 0 || material.getTexture(1) == 0; - item.index = quake3::E_Q3_MESH_GEOMETRY; - toBuffer.push_back( item ); + if ( LoadParam.cleanUnResolvedMeshes || material.getTexture(0) ) + { + item[itemSize].takeVertexColor = 1; + item[itemSize].index = E_Q3_MESH_GEOMETRY; + itemSize += 1; + } + else + { + item[itemSize].takeVertexColor = 1; + item[itemSize].index = E_Q3_MESH_UNRESOLVED; + itemSize += 1; + } } else { - item.takeVertexColor = 1; - item.index = quake3::E_Q3_MESH_ITEMS; - toBuffer.push_back( item ); + item[itemSize].takeVertexColor = 1; + item[itemSize].index = E_Q3_MESH_ITEMS; + itemSize += 1; } } break; -/* - case 1: // normal polygons - case 2: // patches - if ( material.Textures[0] && 0 == shader ) - { - item.takeVertexColor = material.Textures[1] == 0; - item.index = quake3::E_Q3_MESH_GEOMETRY; - toBuffer.push_back( item ); - } - else - if ( material.Textures[0] ) - { - item.takeVertexColor = material.Textures[1] == 0; - item.index = quake3::E_Q3_MESH_GEOMETRY; - toBuffer.push_back( item ); - if ( 0 == (shaderState & 0xFFFF0000 ) ) - { - item.takeVertexColor = 1; - item.index = quake3::E_Q3_MESH_ITEMS; - toBuffer.push_back( item ); - } - } - else - { - item.takeVertexColor = 1; - item.index = quake3::E_Q3_MESH_ITEMS; - toBuffer.push_back( item ); - } + case 4: // billboards + //item[itemSize].takeVertexColor = 1; + //item[itemSize].index = E_Q3_MESH_ITEMS; + //itemSize += 1; break; - case 3: // mesh vertices - if ( material.Textures[0] && ( shaderState & 0xFFFF0000 ) == 0x00030000 ) - { - item.takeVertexColor = material.Textures[1] == 0; - item.index = quake3::E_Q3_MESH_GEOMETRY; - toBuffer.push_back( item ); - } - else - { - item.takeVertexColor = 1; - item.index = quake3::E_Q3_MESH_ITEMS; - toBuffer.push_back( item ); - } - break; -*/ - case 4: // billboards - item.takeVertexColor = 1; - item.index = quake3::E_Q3_MESH_ITEMS; - toBuffer.push_back( item ); - break; } - for ( u32 g = 0; g!= toBuffer.size(); ++g ) + for ( u32 g = 0; g != itemSize; ++g ) { - scene::SMeshBufferLightMap* buffer; + scene::SMeshBufferLightMap* buffer = 0; - if ( toBuffer[g].index == quake3::E_Q3_MESH_GEOMETRY ) + if ( item[g].index == E_Q3_MESH_GEOMETRY ) { - if ( 0 == toBuffer[g].takeVertexColor ) + if ( 0 == item[g].takeVertexColor ) { - toBuffer[g].takeVertexColor = material.getTexture(0) == 0 || material.getTexture(1) == 0; + item[g].takeVertexColor = material.getTexture(0) == 0 || material.getTexture(1) == 0; } + if (Faces[i].lightmapID < -1 || Faces[i].lightmapID > NumLightMaps-1) { Faces[i].lightmapID = -1; } +#if 0 // there are lightmapsids and textureid with -1 const s32 tmp_index = ((Faces[i].lightmapID+1) * (NumTextures+1)) + (Faces[i].textureID+1); - buffer = (SMeshBufferLightMap*) Mesh[quake3::E_Q3_MESH_GEOMETRY]->getMeshBuffer(tmp_index); + buffer = (SMeshBufferLightMap*) Mesh[E_Q3_MESH_GEOMETRY]->getMeshBuffer(tmp_index); + buffer->setHardwareMappingHint ( EHM_STATIC ); buffer->getMaterial() = material; - } - else - { - // Construct a unique mesh for each shader or combine meshbuffers for same shader -#if 0 - buffer = 0; - if ( shader ) - { - const quake3::SVarGroup *group = shader->getGroup( 1 ); - if ( group ) - { - if ( group->getIndex( "deformvertexes" ) >= 0 ) - { - buffer = (SMeshBufferLightMap*) Mesh[ toBuffer[g].index ]->getMeshBuffer( material ); - } - } - - } -#else - buffer = (SMeshBufferLightMap*) Mesh[ toBuffer[g].index ]->getMeshBuffer( material ); #endif + } + + // Construct a unique mesh for each shader or combine meshbuffers for same shader + if ( 0 == buffer ) + { + + if ( LoadParam.mergeShaderBuffer == 1 ) + { + // combine + buffer = (SMeshBufferLightMap*) Mesh[ item[g].index ]->getMeshBuffer( + item[g].index != E_Q3_MESH_FOG ? material : material2 ); + } + + // create a seperate mesh buffer if ( 0 == buffer ) { buffer = new scene::SMeshBufferLightMap(); - Mesh[ toBuffer[g].index ]->addMeshBuffer( buffer ); + Mesh[ item[g].index ]->addMeshBuffer( buffer ); buffer->drop(); - buffer->getMaterial() = material; + buffer->getMaterial() = item[g].index != E_Q3_MESH_FOG ? material : material2; + if ( item[g].index == E_Q3_MESH_GEOMETRY ) + buffer->setHardwareMappingHint ( EHM_STATIC ); } } @@ -859,25 +947,49 @@ void CQ3LevelMesh::constructMesh2() case 4: // billboards break; case 2: // patches - createCurvedSurface2(buffer, i, PatchTesselation,toBuffer[g].takeVertexColor); + createCurvedSurface_bezier( buffer, i, + LoadParam.patchTesselation, + item[g].takeVertexColor + ); break; case 1: // normal polygons case 3: // mesh vertices - index = MeshVerts + face->meshVertIndex; k = buffer->getVertexCount(); - buffer->Indices.reallocate(buffer->getIndexCount()+face->numMeshVerts); + // reallocate better if many small meshes are used + s = buffer->getIndexCount()+face->numMeshVerts; + if ( buffer->Indices.allocated_size () < (u32) s ) + { + if ( buffer->Indices.allocated_size () > 0 && + face->numMeshVerts < 20 && NumFaces > 1000 + ) + { + s = buffer->getIndexCount() + (NumFaces >> 3 * face->numMeshVerts ); + } + buffer->Indices.reallocate( s); + } + for ( j = 0; j < face->numMeshVerts; ++j ) { buffer->Indices.push_back( k + index [j] ); } - buffer->Vertices.reallocate(k+face->numOfVerts); + s = k+face->numOfVerts; + if ( buffer->Vertices.allocated_size () < (u32) s ) + { + if ( buffer->Indices.allocated_size () > 0 && + face->numOfVerts < 20 && NumFaces > 1000 + ) + { + s = buffer->getIndexCount() + (NumFaces >> 3 * face->numOfVerts ); + } + buffer->Vertices.reallocate( s); + } for ( j = 0; j != face->numOfVerts; ++j ) { - copy( &temp[0], &Vertices[ j + face->vertexIndex ], toBuffer[g].takeVertexColor ); + copy( &temp[0], &Vertices[ j + face->vertexIndex ], item[g].takeVertexColor ); buffer->Vertices.push_back( temp[0] ); } break; @@ -885,118 +997,42 @@ void CQ3LevelMesh::constructMesh2() } // end switch } } + + if ( LoadParam.verbose > 0 ) + { + LoadParam.endTime = os::Timer::getRealTime(); + + snprintf( buf, sizeof ( buf ), + "quake3::constructMesh needed %04d ms to create %d faces, %d vertices,%d mesh vertices", + LoadParam.endTime - LoadParam.startTime, + NumFaces, + NumVertices, + NumMeshVerts + ); + os::Printer::log(buf, ELL_INFORMATION); + } + } -//! constructs a mesh from the quake 3 level file. -void CQ3LevelMesh::constructMesh() -{ - // reserve buffer. - s32 i; // new ISO for scoping problem with some compilers - - for (i=0; i<(NumTextures+1) * (NumLightMaps+1); ++i) - { - scene::SMeshBufferLightMap* buffer = new scene::SMeshBufferLightMap(); - - buffer->Material.MaterialType = video::EMT_LIGHTMAP_M4; - buffer->Material.Wireframe = false; - buffer->Material.Lighting = false; - - Mesh[0]->addMeshBuffer(buffer); - - buffer->drop(); - } - - // go through all faces and add them to the buffer. - - video::S3DVertex2TCoords temp[3]; - - for (i=0; i NumLightMaps-1) - Faces[i].lightmapID = -1; - - // there are lightmapsids and textureid with -1 - s32 meshBufferIndex = ((Faces[i].lightmapID+1) * (NumTextures+1)) + (Faces[i].textureID+1); - SMeshBufferLightMap* meshBuffer = ((SMeshBufferLightMap*)Mesh[0]->getMeshBuffer(meshBufferIndex)); - - switch(Faces[i].type) - { - //case 3: // mesh vertices - case 1: // normal polygons - { - meshBuffer->Vertices.reallocate(meshBuffer->getVertexCount()+3*Faces[i].numMeshVerts); - meshBuffer->Indices.reallocate(meshBuffer->getIndexCount()+3*Faces[i].numMeshVerts); - for (s32 tf=0; tfgetVertexCount(); - s32 vidxes[3]; - - vidxes[0] = MeshVerts[Faces[i].meshVertIndex + tf +0] - + Faces[i].vertexIndex; - vidxes[1] = MeshVerts[Faces[i].meshVertIndex + tf +1] - + Faces[i].vertexIndex; - vidxes[2] = MeshVerts[Faces[i].meshVertIndex + tf +2] - + Faces[i].vertexIndex; - - // add all three vertices - copy( &temp[0], &Vertices[ vidxes[0] ], 0 ); - copy( &temp[1], &Vertices[ vidxes[1] ], 0 ); - copy( &temp[2], &Vertices[ vidxes[2] ], 0 ); - - meshBuffer->Vertices.push_back( temp[0] ); - meshBuffer->Vertices.push_back( temp[1] ); - meshBuffer->Vertices.push_back( temp[2] ); - - // add indexes - - meshBuffer->Indices.push_back(idx); - meshBuffer->Indices.push_back(idx+1); - meshBuffer->Indices.push_back(idx+2); - } - } - break; - case 2: // curved surfaces - createCurvedSurface(meshBuffer, i); - break; - - case 4: // billboards - break; - } // end switch - } -} - - -// helper method for creating curved surfaces, sent in by Dean P. Macri. -inline f32 CQ3LevelMesh::Blend( const f64 s[3], const f64 t[3], const tBSPVertex *v[9], int offset) -{ - f64 res = 0.0; - f32 *ptr; - - for( int i=0; i<3; ++i ) - { - for( int j=0; j<3; ++j ) - { - ptr = (f32 *)( (char*)v[i*3+j] + offset ); - res += s[i] * t[j] * (*ptr); - } - } - - return (f32) res; -} - - -void CQ3LevelMesh::S3DVertex2TCoords_64::copyto( video::S3DVertex2TCoords &dest ) const + + + +void CQ3LevelMesh::S3DVertex2TCoords_64::copy( video::S3DVertex2TCoords &dest ) const { +#if defined (TJUNCTION_SOLVER_ROUND) dest.Pos.X = core::round_( (f32) Pos.X ); dest.Pos.Y = core::round_( (f32) Pos.Y ); dest.Pos.Z = core::round_( (f32) Pos.Z ); - //dest.Pos.X = (f32) Pos.X; - //dest.Pos.Y = (f32) Pos.Y; - //dest.Pos.Z = (f32) Pos.Z; +#elif defined (TJUNCTION_SOLVER_0125) + dest.Pos.X = (f32) ( floor ( Pos.X * 8.f + 0.5 ) * 0.125 ); + dest.Pos.Y = (f32) ( floor ( Pos.Y * 8.f + 0.5 ) * 0.125 ); + dest.Pos.Z = (f32) ( floor ( Pos.Z * 8.f + 0.5 ) * 0.125 ); +#else + dest.Pos.X = (f32) Pos.X; + dest.Pos.Y = (f32) Pos.Y; + dest.Pos.Z = (f32) Pos.Z; +#endif dest.Normal.X = (f32) Normal.X; dest.Normal.Y = (f32) Normal.Y; @@ -1015,12 +1051,19 @@ void CQ3LevelMesh::S3DVertex2TCoords_64::copyto( video::S3DVertex2TCoords &dest void CQ3LevelMesh::copy( S3DVertex2TCoords_64 * dest, const tBSPVertex * source, s32 vertexcolor ) const { - //dest->Pos.X = core::round( source->vPosition[0] ); - //dest->Pos.Y = core::round( source->vPosition[2] ); - //dest->Pos.Z = core::round( source->vPosition[1] ); +#if defined (TJUNCTION_SOLVER_ROUND) + dest->Pos.X = core::round_( source->vPosition[0] ); + dest->Pos.Y = core::round_( source->vPosition[2] ); + dest->Pos.Z = core::round_( source->vPosition[1] ); +#elif defined (TJUNCTION_SOLVER_0125) + dest->Pos.X = (f32) ( floor ( source->vPosition[0] * 8.f + 0.5 ) * 0.125 ); + dest->Pos.Y = (f32) ( floor ( source->vPosition[2] * 8.f + 0.5 ) * 0.125 ); + dest->Pos.Z = (f32) ( floor ( source->vPosition[1] * 8.f + 0.5 ) * 0.125 ); +#else dest->Pos.X = source->vPosition[0]; dest->Pos.Y = source->vPosition[2]; dest->Pos.Z = source->vPosition[1]; +#endif dest->Normal.X = source->vNormal[0]; dest->Normal.Y = source->vNormal[2]; @@ -1034,10 +1077,11 @@ void CQ3LevelMesh::copy( S3DVertex2TCoords_64 * dest, const tBSPVertex * source, if ( vertexcolor ) { - u32 a = core::s32_min( source->color[3] * quake3::defaultModulate, 255 ); - u32 r = core::s32_min( source->color[0] * quake3::defaultModulate, 255 ); - u32 g = core::s32_min( source->color[1] * quake3::defaultModulate, 255 ); - u32 b = core::s32_min( source->color[2] * quake3::defaultModulate, 255 ); + //u32 a = core::s32_min( source->color[3] * LoadParam.defaultModulate, 255 ); + u32 a = source->color[3]; + u32 r = core::s32_min( source->color[0] * LoadParam.defaultModulate, 255 ); + u32 g = core::s32_min( source->color[1] * LoadParam.defaultModulate, 255 ); + u32 b = core::s32_min( source->color[2] * LoadParam.defaultModulate, 255 ); dest->Color.set(a * 1.f/255.f, r * 1.f/255.f, g * 1.f/255.f, b * 1.f/255.f); @@ -1051,13 +1095,19 @@ void CQ3LevelMesh::copy( S3DVertex2TCoords_64 * dest, const tBSPVertex * source, inline void CQ3LevelMesh::copy( video::S3DVertex2TCoords * dest, const tBSPVertex * source, s32 vertexcolor ) const { +#if defined (TJUNCTION_SOLVER_ROUND) dest->Pos.X = core::round_( source->vPosition[0] ); dest->Pos.Y = core::round_( source->vPosition[2] ); dest->Pos.Z = core::round_( source->vPosition[1] ); - - //dest->Pos.X = source->vPosition[0]; - //dest->Pos.Y = source->vPosition[2]; - //dest->Pos.Z = source->vPosition[1]; +#elif defined (TJUNCTION_SOLVER_0125) + dest->Pos.X = (f32) ( floor ( source->vPosition[0] * 8.f + 0.5 ) * 0.125 ); + dest->Pos.Y = (f32) ( floor ( source->vPosition[2] * 8.f + 0.5 ) * 0.125 ); + dest->Pos.Z = (f32) ( floor ( source->vPosition[1] * 8.f + 0.5 ) * 0.125 ); +#else + dest->Pos.X = source->vPosition[0]; + dest->Pos.Y = source->vPosition[2]; + dest->Pos.Z = source->vPosition[1]; +#endif dest->Normal.X = source->vNormal[0]; dest->Normal.Y = source->vNormal[2]; @@ -1071,10 +1121,11 @@ inline void CQ3LevelMesh::copy( video::S3DVertex2TCoords * dest, const tBSPVerte if ( vertexcolor ) { - u32 a = core::s32_min( source->color[3] * quake3::defaultModulate, 255 ); - u32 r = core::s32_min( source->color[0] * quake3::defaultModulate, 255 ); - u32 g = core::s32_min( source->color[1] * quake3::defaultModulate, 255 ); - u32 b = core::s32_min( source->color[2] * quake3::defaultModulate, 255 ); + //u32 a = core::s32_min( source->color[3] * LoadParam.defaultModulate, 255 ); + u32 a = source->color[3]; + u32 r = core::s32_min( source->color[0] * LoadParam.defaultModulate, 255 ); + u32 g = core::s32_min( source->color[1] * LoadParam.defaultModulate, 255 ); + u32 b = core::s32_min( source->color[2] * LoadParam.defaultModulate, 255 ); dest->Color.color = a << 24 | r << 16 | g << 8 | b; } @@ -1094,7 +1145,7 @@ void CQ3LevelMesh::SBezier::tesselate( s32 level ) column[1].set_used( level + 1 ); column[2].set_used( level + 1 ); - const f64 w = 0.0 + core::reciprocal( (f32) level ); + const f64 w = 0.0 + (1.0 / (f64) level ); //Tesselate along the columns for( j = 0; j <= level; ++j) @@ -1116,7 +1167,7 @@ void CQ3LevelMesh::SBezier::tesselate( s32 level ) for( k = 0; k <= level; ++k) { f = column[0][j].getInterpolated_quadratic(column[1][j], column[2][j], w * (f64) k); - f.copyto( v ); + f.copy( v ); Patch->Vertices.push_back( v ); } } @@ -1136,6 +1187,7 @@ void CQ3LevelMesh::SBezier::tesselate( s32 level ) Patch->Indices.push_back( inx + 0 ); Patch->Indices.push_back( inx + (level + 1 ) + 1 ); Patch->Indices.push_back( inx + 1 ); + } } } @@ -1144,7 +1196,7 @@ void CQ3LevelMesh::SBezier::tesselate( s32 level ) /*! no subdivision */ -void CQ3LevelMesh::createCurvedSurface3(SMeshBufferLightMap* meshBuffer, +void CQ3LevelMesh::createCurvedSurface_nosubdivision(SMeshBufferLightMap* meshBuffer, s32 faceIndex, s32 patchTesselation, s32 storevertexcolor) @@ -1155,6 +1207,8 @@ void CQ3LevelMesh::createCurvedSurface3(SMeshBufferLightMap* meshBuffer, // number of control points across & up const u32 controlWidth = face->size[0]; const u32 controlHeight = face->size[1]; + if ( 0 == controlWidth || 0 == controlHeight ) + return; video::S3DVertex2TCoords v; @@ -1186,11 +1240,12 @@ void CQ3LevelMesh::createCurvedSurface3(SMeshBufferLightMap* meshBuffer, /*! */ -void CQ3LevelMesh::createCurvedSurface2(SMeshBufferLightMap* meshBuffer, +void CQ3LevelMesh::createCurvedSurface_bezier(SMeshBufferLightMap* meshBuffer, s32 faceIndex, s32 patchTesselation, s32 storevertexcolor) { + tBSPFace * face = &Faces[faceIndex]; u32 j,k; @@ -1198,10 +1253,18 @@ void CQ3LevelMesh::createCurvedSurface2(SMeshBufferLightMap* meshBuffer, const u32 controlWidth = face->size[0]; const u32 controlHeight = face->size[1]; + if ( 0 == controlWidth || 0 == controlHeight ) + return; + // number of biquadratic patches const u32 biquadWidth = (controlWidth - 1)/2; const u32 biquadHeight = (controlHeight -1)/2; + if ( LoadParam.verbose > 1 ) + { + LoadParam.startTime = os::Timer::getRealTime(); + } + // Create space for a temporary array of the patch's control points core::array controlPoint; controlPoint.set_used( controlWidth * controlHeight ); @@ -1274,159 +1337,41 @@ void CQ3LevelMesh::createCurvedSurface2(SMeshBufferLightMap* meshBuffer, } delete Bezier.Patch; -} - -void CQ3LevelMesh::createCurvedSurface(SMeshBufferLightMap* meshBuffer, s32 i) -{ - // this implementation for loading curved surfaces was - // sent in by Dean P. Macri. It was a little bit modified - // by me afterwards. - s32 idx; - s32 cpidx[9]; - - const tBSPVertex *v[9]; - video::S3DVertex2TCoords currentVertex[4]; - - for( s32 row=0; row 1 ) { - for( s32 col=0; colgetVertexCount(); - ct[0] = (1.0-t)*(1.0-t); - ct[1] = 2.0 * (1.0 - t) * t; - ct[2] = t * t; - nxt[0] = (1.0-t-tstep)*(1.0-t-tstep); - nxt[1] = 2.0 * (1.0 - t - tstep) * (t+tstep); - nxt[2] = (t+tstep) * (t+tstep); - - // Vert 1 - currentVertex[0].Color.set(255,255,255,255); - currentVertex[0].Pos.X = floorf( Blend( cs, ct, v, (char*)&v[0]->vPosition[0] - (char*)v[0])+ 0.5f); - currentVertex[0].Pos.Y = floorf( Blend( cs, ct, v, (char*)&v[0]->vPosition[2] - (char*)v[0])+ 0.5f); - currentVertex[0].Pos.Z = floorf( Blend( cs, ct, v, (char*)&v[0]->vPosition[1] - (char*)v[0])+ 0.5f); - currentVertex[0].Normal.X = Blend( cs, ct, v, (char*)&v[0]->vNormal[0] - (char*)v[0]); - currentVertex[0].Normal.Y = Blend( cs, ct, v, (char*)&v[0]->vNormal[2] - (char*)v[0]); - currentVertex[0].Normal.Z = Blend( cs, ct, v, (char*)&v[0]->vNormal[1] - (char*)v[0]); - currentVertex[0].TCoords.X = Blend( cs, ct, v, (char*)&v[0]->vTextureCoord[0] - (char*)v[0]); - currentVertex[0].TCoords.Y = Blend( cs, ct, v, (char*)&v[0]->vTextureCoord[1] - (char*)v[0]); - currentVertex[0].TCoords2.X = Blend( cs, ct, v, (char*)&v[0]->vLightmapCoord[0] - (char*)v[0]); - currentVertex[0].TCoords2.Y = Blend( cs, ct, v, (char*)&v[0]->vLightmapCoord[1] - (char*)v[0]); - // Vert 2 - currentVertex[1].Color.set(255,255,255,255); - currentVertex[1].Pos.X = floorf( Blend( cs, nxt, v, (char*)&v[0]->vPosition[0] - (char*)v[0])+ 0.5f); - currentVertex[1].Pos.Y = floorf( Blend( cs, nxt, v, (char*)&v[0]->vPosition[2] - (char*)v[0])+ 0.5f); - currentVertex[1].Pos.Z = floorf( Blend( cs, nxt, v, (char*)&v[0]->vPosition[1] - (char*)v[0])+ 0.5f); - currentVertex[1].Normal.X = Blend( cs, nxt, v, (char*)&v[0]->vNormal[0] - (char*)v[0]); - currentVertex[1].Normal.Y = Blend( cs, nxt, v, (char*)&v[0]->vNormal[2] - (char*)v[0]); - currentVertex[1].Normal.Z = Blend( cs, nxt, v, (char*)&v[0]->vNormal[1] - (char*)v[0]); - currentVertex[1].TCoords.X = Blend( cs, nxt, v, (char*)&v[0]->vTextureCoord[0] - (char*)v[0]); - currentVertex[1].TCoords.Y = Blend( cs, nxt, v, (char*)&v[0]->vTextureCoord[1] - (char*)v[0]); - currentVertex[1].TCoords2.X = Blend( cs, nxt, v, (char*)&v[0]->vLightmapCoord[0] - (char*)v[0]); - currentVertex[1].TCoords2.Y = Blend( cs, nxt, v, (char*)&v[0]->vLightmapCoord[1] - (char*)v[0]); - // Vert 3 - currentVertex[2].Color.set(255,255,255,255); - currentVertex[2].Pos.X = floorf( Blend( nxs, ct, v, (char*)&v[0]->vPosition[0] - (char*)v[0])+ 0.5f); - currentVertex[2].Pos.Y = floorf( Blend( nxs, ct, v, (char*)&v[0]->vPosition[2] - (char*)v[0])+ 0.5f); - currentVertex[2].Pos.Z = floorf( Blend( nxs, ct, v, (char*)&v[0]->vPosition[1] - (char*)v[0])+ 0.5f); - currentVertex[2].Normal.X = Blend( nxs, ct, v, (char*)&v[0]->vNormal[0] - (char*)v[0]); - currentVertex[2].Normal.Y = Blend( nxs, ct, v, (char*)&v[0]->vNormal[2] - (char*)v[0]); - currentVertex[2].Normal.Z = Blend( nxs, ct, v, (char*)&v[0]->vNormal[1] - (char*)v[0]); - currentVertex[2].TCoords.X = Blend( nxs, ct, v, (char*)&v[0]->vTextureCoord[0] - (char*)v[0]); - currentVertex[2].TCoords.Y = Blend( nxs, ct, v, (char*)&v[0]->vTextureCoord[1] - (char*)v[0]); - currentVertex[2].TCoords2.X = Blend( nxs, ct, v, (char*)&v[0]->vLightmapCoord[0] - (char*)v[0]); - currentVertex[2].TCoords2.Y = Blend( nxs, ct, v, (char*)&v[0]->vLightmapCoord[1] - (char*)v[0]); - // Vert 4 - currentVertex[3].Color.set(255,255,255,255); - currentVertex[3].Pos.X = floorf(Blend( nxs, nxt, v, (char*)&v[0]->vPosition[0] - (char*)v[0])+ 0.5f); - currentVertex[3].Pos.Y = floorf(Blend( nxs, nxt, v, (char*)&v[0]->vPosition[2] - (char*)v[0])+ 0.5f); - currentVertex[3].Pos.Z = floorf(Blend( nxs, nxt, v, (char*)&v[0]->vPosition[1] - (char*)v[0])+ 0.5f); - currentVertex[3].Normal.X = Blend( nxs, nxt, v, (char*)&v[0]->vNormal[0] - (char*)v[0]); - currentVertex[3].Normal.Y = Blend( nxs, nxt, v, (char*)&v[0]->vNormal[2] - (char*)v[0]); - currentVertex[3].Normal.Z = Blend( nxs, nxt, v, (char*)&v[0]->vNormal[1] - (char*)v[0]); - currentVertex[3].TCoords.X = Blend( nxs, nxt, v, (char*)&v[0]->vTextureCoord[0] - (char*)v[0]); - currentVertex[3].TCoords.Y = Blend( nxs, nxt, v, (char*)&v[0]->vTextureCoord[1] - (char*)v[0]); - currentVertex[3].TCoords2.X = Blend( nxs, nxt, v, (char*)&v[0]->vLightmapCoord[0] - (char*)v[0]); - currentVertex[3].TCoords2.Y = Blend( nxs, nxt, v, (char*)&v[0]->vLightmapCoord[1] - (char*)v[0]); - // Put the vertices in the mesh buffer - meshBuffer->Vertices.push_back(currentVertex[0]); - meshBuffer->Vertices.push_back(currentVertex[2]); - meshBuffer->Vertices.push_back(currentVertex[1]); - - meshBuffer->Vertices.push_back(currentVertex[3]); - - // add indexes - meshBuffer->Indices.push_back(idx); - meshBuffer->Indices.push_back(idx+1); - meshBuffer->Indices.push_back(idx+2); - // add indexes - meshBuffer->Indices.push_back(idx+2); - meshBuffer->Indices.push_back(idx+1); - meshBuffer->Indices.push_back(idx+3); - } - } - } + snprintf( buf, sizeof ( buf ), + "quake3::createCurvedSurface_bezier needed %04d ms to create bezier patch.(%dx%d)", + LoadParam.endTime - LoadParam.startTime, + biquadWidth, + biquadHeight + ); + os::Printer::log(buf, ELL_INFORMATION); } + } + + //! get's an interface to the entities -const quake3::tQ3EntityList & CQ3LevelMesh::getEntityList() +tQ3EntityList & CQ3LevelMesh::getEntityList( const c8 * fileName ) { + if ( fileName ) + { + } + Entity.sort(); + return Entity; } /*! */ -const quake3::SShader * CQ3LevelMesh::getShader(u32 index) const +const IShader * CQ3LevelMesh::getShader(u32 index) const { index &= 0xFFFF; @@ -1439,23 +1384,36 @@ const quake3::SShader * CQ3LevelMesh::getShader(u32 index) const } -//! loads the shader definition -const quake3::SShader * CQ3LevelMesh::getShader( const c8 * filename, bool fileNameIsValid ) +/*! + loads the shader definition +*/ +const IShader* CQ3LevelMesh::getShader( const c8 * filename, bool fileNameIsValid ) { - quake3::SShader search; - search.name = filename; - search.name.replace( '\\', '/' ); + core::stringc searchName ( filename ); + IShader search; + search.name = searchName; + search.name.replace( '\\', '/' ); + search.name.make_lower(); + + + core::stringc message; s32 index; //! is Shader already in cache? index = Shader.linear_search( search ); if ( index >= 0 ) { + if ( LoadParam.verbose > 1 ) + { + message = searchName + " found " + Shader[index].name; + os::Printer::log("quake3:getShader", message.c_str(), ELL_INFORMATION); + } + return &Shader[index]; } - core::stringc loadFile; + core::string loadFile; if ( !fileNameIsValid ) { @@ -1466,7 +1424,7 @@ const quake3::SShader * CQ3LevelMesh::getShader( const c8 * filename, bool fileN s32 end = cut.findLast( '/' ); s32 start = cut.findLast( '/', end - 1 ); - loadFile = "scripts"; + loadFile = LoadParam.scriptDir; loadFile.append( cut.subString( start, end - start ) ); loadFile.append( ".shader" ); } @@ -1484,34 +1442,52 @@ const quake3::SShader * CQ3LevelMesh::getShader( const c8 * filename, bool fileN ShaderFile.push_back( loadFile ); if ( !FileSystem->existFile( loadFile.c_str() ) ) + { + if ( LoadParam.verbose > 1 ) + { + message = loadFile + " for " + searchName + " failed "; + os::Printer::log("quake3:getShader", message.c_str(), ELL_INFORMATION); + } return 0; + } io::IReadFile *file = FileSystem->createAndOpenFile( loadFile.c_str() ); if ( 0 == file ) return 0; - core::stringc message; - message = loadFile + " for " + core::stringc( filename ); - os::Printer::log("Loaded shader", message.c_str(), ELL_INFORMATION); + if ( LoadParam.verbose ) + { + message = loadFile + " for " + searchName; + os::Printer::log("quake3:getShader Load shader", message.c_str(), ELL_INFORMATION); + } // load script core::array script; const long len = file->getSize(); script.set_used( len + 2 ); - script[ len + 1 ] = 0; file->seek( 0 ); file->read( script.pointer(), len ); file->drop(); + script[ len + 1 ] = 0; + // start a parser instance parser_parse( script.pointer(), len, &CQ3LevelMesh::scriptcallback_shader ); // search again index = Shader.linear_search( search ); if ( index >= 0 ) + { + if ( LoadParam.verbose > 1 ) + { + message = searchName + " found " + Shader[index].name; + os::Printer::log("quake3:getShader", message.c_str(), ELL_INFORMATION); + } + return &Shader[index]; + } return 0; } @@ -1522,21 +1498,52 @@ void CQ3LevelMesh::InitShader() { ReleaseShader(); - quake3::SShader element; + IShader element; - quake3::SVarGroup group; - quake3::SVariable variable; + SVarGroup group; + SVariable variable ( "noshader" ); - variable.name = "noshader"; group.Variable.push_back( variable ); - element.VarGroup = new quake3::SVarGroupList(); + element.VarGroup = new SVarGroupList(); element.VarGroup->VariableGroup.push_back( group ); - element.name = element.VarGroup->VariableGroup[0].Variable[0].name.c_str(); + element.VarGroup->VariableGroup.push_back( SVarGroup() ); + element.name = element.VarGroup->VariableGroup[0].Variable[0].name; + element.id = Shader.size(); Shader.push_back( element ); - // load common named shader - getShader("scripts/common.shader"); + if ( LoadParam.loadAllShaders ) + { + io::eFileSystemType current = FileSystem->setFileListSystem ( io::FILESYSTEM_VIRTUAL ); + core::string save = FileSystem->getWorkingDirectory(); + + core::string newDir; + newDir = "/"; + newDir += LoadParam.scriptDir; + newDir += "/"; + FileSystem->changeWorkingDirectoryTo ( newDir.c_str() ); + + core::stringc s; + io::IFileList *fileList = FileSystem->createFileList (); + for (u32 i=0; i< fileList->getFileCount(); ++i) + { + s = fileList->getFullFileName(i); + if ( s.find ( ".shader" ) >= 0 ) + { + if ( 0 == LoadParam.loadSkyShader && s.find ( "sky.shader" ) >= 0 ) + { + } + else + { + getShader ( s.c_str () ); + } + } + } + fileList->drop (); + + FileSystem->changeWorkingDirectoryTo ( save ); + FileSystem->setFileListSystem ( current ); + } } @@ -1553,6 +1560,8 @@ void CQ3LevelMesh::ReleaseShader() } +/*! +*/ void CQ3LevelMesh::ReleaseEntity() { for ( u32 i = 0; i!= Entity.size(); ++i ) @@ -1564,165 +1573,165 @@ void CQ3LevelMesh::ReleaseEntity() // entity only has only one valid level.. and no assoziative name.. -void CQ3LevelMesh::scriptcallback_entity( quake3::SVarGroupList *& grouplist ) +void CQ3LevelMesh::scriptcallback_entity( SVarGroupList *& grouplist ) { - quake3::SEntity element; - if ( grouplist->VariableGroup.size() != 2 ) return; + grouplist->grab(); + + SEntity element; + element.VarGroup = grouplist; + element.id = Entity.size(); element.name = grouplist->VariableGroup[1].get( "classname" ); - grouplist->grab(); - element.VarGroup = grouplist; - element.id = Shader.size(); Entity.push_back( element ); } //!. script callback for shaders -void CQ3LevelMesh::scriptcallback_shader( quake3::SVarGroupList *& grouplist ) +void CQ3LevelMesh::scriptcallback_shader( SVarGroupList *& grouplist ) { - quake3::SShader element; - // TODO: There might be something wrong with this fix, but it avoids a core dump... if (grouplist->VariableGroup[0].Variable.size()==0) return; // end fix - grouplist->grab(); + IShader element; + grouplist->grab(); element.VarGroup = grouplist; - element.name = element.VarGroup->VariableGroup[0].Variable[0].name.c_str(); + element.name = element.VarGroup->VariableGroup[0].Variable[0].name; element.id = Shader.size(); Shader.push_back( element ); } -//! loads the textures -void CQ3LevelMesh::loadTextures() -{ - if (!Driver) - return; - - core::stringc s; - core::stringc extensions[2]; - extensions[0] = ".jpg"; - extensions[1] = ".tga"; - - // load textures - - core::array tex; - tex.set_used(NumTextures+1); - - tex[0] = 0; - - s32 t;// new ISO for scoping problem with some compilers - - for (t=1; t<(NumTextures+1); ++t) - { - tex[t] = 0; - - if ( !tex[t] ) - { - for (s32 e=0; e<2; ++e) - { - s = Textures[t-1].strName; - s.append(extensions[e]); - if (FileSystem->existFile(s.c_str())) - { - tex[t] = Driver->getTexture(s.c_str()); - break; - } - } - } - if (!tex[t]) - { - os::Printer::log("Q3: no texmap for texturename ", Textures[t-1].strName, ELL_WARNING); - } - } - - // load lightmaps. - core::array lig; - lig.set_used(NumLightMaps+1); - - lig[0] = 0; - c8 lightmapname[255]; - core::dimension2d lmapsize(128,128); - - //bool oldMipMapState = Driver->getTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS); - //Driver->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, false); - - video::IImage* lmapImg; - for (t=1; t<(NumLightMaps+1); ++t) - { - sprintf(lightmapname, "%s.lightmap.%d", LevelName.c_str(), t); - - // lightmap is a CTexture::R8G8B8 format - lmapImg = Driver->createImageFromData( - video::ECF_R8G8B8, - lmapsize, - LightMaps[t-1].imageBits, true, false ); - - lig[t] = Driver->addTexture( lightmapname, lmapImg ); - lmapImg->drop(); - - } - //Driver->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, oldMipMapState); - - - // attach textures to materials. - for (s32 l=0; lgetMeshBuffer(l*(NumTextures+1) + t); - b->Material.setTexture(1, lig[l]); - b->Material.setTexture(0, tex[t]); - - if (!b->Material.getTexture(1)) - b->Material.MaterialType = video::EMT_SOLID; - - if (!b->Material.getTexture(0)) - b->Material.MaterialType = video::EMT_SOLID; - } - } -} - - -// delete all buffers without geometry in it. +/*! + delete all buffers without geometry in it. +*/ void CQ3LevelMesh::cleanMeshes() { + if ( 0 == LoadParam.cleanUnResolvedMeshes ) + return; + // delete all buffers without geometry in it. - for ( u32 g = 0; g < quake3::E_Q3_MESH_SIZE; ++g ) + u32 run = 0; + u32 remove = 0; + + irr::scene::SMesh *m; + IMeshBuffer *b; + for ( u32 g = 0; g < E_Q3_MESH_SIZE; ++g ) { - u32 i = 0; bool texture0important = ( g == 0 ); - while(i < Mesh[g]->MeshBuffers.size()) + + run = 0; + remove = 0; + m = Mesh[g]; + if ( LoadParam.verbose > 0 ) { - if (Mesh[g]->MeshBuffers[i]->getVertexCount() == 0 || - Mesh[g]->MeshBuffers[i]->getIndexCount() == 0 || - ( texture0important && Mesh[g]->MeshBuffers[i]->getMaterial().getTexture(0) == 0 ) + LoadParam.startTime = os::Timer::getRealTime(); + if ( LoadParam.verbose > 1 ) + { + snprintf( buf, sizeof ( buf ), + "quake3::cleanMeshes%d start for %d meshes", + g, + m->MeshBuffers.size() + ); + os::Printer::log(buf, ELL_INFORMATION); + } + } + + u32 i = 0; + s32 blockstart = -1; + s32 blockcount; + + while( i < m->MeshBuffers.size()) + { + run += 1; + + b = m->MeshBuffers[i]; + + if ( b->getVertexCount() == 0 || b->getIndexCount() == 0 || + ( texture0important && b->getMaterial().getTexture(0) == 0 ) ) { + if ( blockstart < 0 ) + { + blockstart = i; + blockcount = 0; + } + blockcount += 1; + i += 1; + // delete Meshbuffer - Mesh[g]->MeshBuffers[i]->drop(); - Mesh[g]->MeshBuffers.erase(i); + i -= 1; + remove += 1; + b->drop(); + m->MeshBuffers.erase(i); } else - ++i; + { + // clean blockwise + if ( blockstart >= 0 ) + { + if ( LoadParam.verbose > 1 ) + { + snprintf( buf, sizeof ( buf ), + "quake3::cleanMeshes%d cleaning mesh %d %d size", + g, + blockstart, + blockcount + ); + os::Printer::log(buf, ELL_INFORMATION); + } + blockstart = -1; + } + i += 1; + } } + + if ( LoadParam.verbose > 0 ) + { + LoadParam.endTime = os::Timer::getRealTime(); + snprintf( buf, sizeof ( buf ), + "quake3::cleanMeshes%d needed %04d ms to clean %d of %d meshes", + g, + LoadParam.endTime - LoadParam.startTime, + remove, + run + ); + os::Printer::log(buf, ELL_INFORMATION); + } + } + } // recalculate bounding boxes void CQ3LevelMesh::calcBoundingBoxes() { + if ( LoadParam.verbose > 0 ) + { + LoadParam.startTime = os::Timer::getRealTime(); + + if ( LoadParam.verbose > 1 ) + { + snprintf( buf, sizeof ( buf ), + "quake3::calcBoundingBoxes start create %d textures and %d lightmaps", + NumTextures, + NumLightMaps + ); + os::Printer::log(buf, ELL_INFORMATION); + } + + } + // create bounding box - for ( u32 g = 0; g != quake3::E_Q3_MESH_SIZE; ++g ) + for ( u32 g = 0; g != E_Q3_MESH_SIZE; ++g ) { for ( u32 j=0; j < Mesh[g]->MeshBuffers.size(); ++j) { @@ -1732,49 +1741,54 @@ void CQ3LevelMesh::calcBoundingBoxes() Mesh[g]->recalculateBoundingBox(); } -} - -/* -//! loads a texture -video::ITexture* CQ3LevelMesh::loadTexture( const tStringList &stringList ) -{ - static const char * extension[2] = + if ( LoadParam.verbose > 0 ) { - ".jpg", - ".tga" - }; + LoadParam.endTime = os::Timer::getRealTime(); - core::stringc loadFile; - for ( u32 i = 0; i!= stringList.size(); ++i ) - { - for ( u32 g = 0; g != 2 ; ++g ) - { - cutFilenameExtension( loadFile, stringList[i] ).append( extension[g] ); - - if ( FileSystem->existFile( loadFile.c_str() ) ) - { - video::ITexture* t = Driver->getTexture( loadFile.c_str() ); - if ( t ) - return t; - } - } + snprintf( buf, sizeof ( buf ), + "quake3::calcBoundingBoxes needed %04d ms to create %d textures and %d lightmaps", + LoadParam.endTime - LoadParam.startTime, + NumTextures, + NumLightMaps + ); + os::Printer::log( buf, ELL_INFORMATION); } - return 0; + } -*/ + //! loads the textures -void CQ3LevelMesh::loadTextures2() +void CQ3LevelMesh::loadTextures() { if (!Driver) return; + if ( LoadParam.verbose > 0 ) + { + LoadParam.startTime = os::Timer::getRealTime(); + + if ( LoadParam.verbose > 1 ) + { + snprintf( buf, sizeof ( buf ), + "quake3::loadTextures start create %d textures and %d lightmaps", + NumTextures, + NumLightMaps + ); + os::Printer::log( buf, ELL_INFORMATION); + } + + } + + c8 lightmapname[255]; s32 t; // load lightmaps. Lightmap.set_used(NumLightMaps+1); - c8 lightmapname[255]; +/* + bool oldMipMapState = Driver->getTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS); + Driver->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, false); +*/ core::dimension2d lmapsize(128,128); video::IImage* lmapImg; @@ -1786,21 +1800,23 @@ void CQ3LevelMesh::loadTextures2() lmapImg = Driver->createImageFromData( video::ECF_R8G8B8, lmapsize, - LightMaps[t].imageBits, true, false ); + LightMaps[t].imageBits, false, true ); Lightmap[t] = Driver->addTexture( lightmapname, lmapImg ); lmapImg->drop(); } +// Driver->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, oldMipMapState); + // load textures Tex.set_used( NumTextures+1 ); - const quake3::SShader * shader; + const IShader * shader; core::stringc list; core::stringc check; - quake3::tTexArray textureArray; + tTexArray textureArray; // pre-load shaders for ( t=0; t< NumTextures; ++t) @@ -1822,7 +1838,7 @@ void CQ3LevelMesh::loadTextures2() Tex[t].ShaderID = shader->id; // if texture name == stage1 Texture map - const quake3::SVarGroup * group; + const SVarGroup * group; group = shader->getGroup( 2 ); if ( group ) @@ -1848,10 +1864,24 @@ void CQ3LevelMesh::loadTextures2() } u32 pos = 0; - quake3::getTextures( textureArray, list, pos, FileSystem, Driver ); + getTextures( textureArray, list, pos, FileSystem, Driver ); Tex[t].Texture = textureArray[0]; } + + if ( LoadParam.verbose > 0 ) + { + LoadParam.endTime = os::Timer::getRealTime(); + + snprintf( buf, sizeof ( buf ), + "quake3::loadTextures needed %04d ms to create %d textures and %d lightmaps", + LoadParam.endTime - LoadParam.startTime, + NumTextures, + NumLightMaps + ); + os::Printer::log( buf, ELL_INFORMATION); + } + } diff --git a/source/Irrlicht/CQ3LevelMesh.h b/source/Irrlicht/CQ3LevelMesh.h index ca08ba37..42bef61d 100644 --- a/source/Irrlicht/CQ3LevelMesh.h +++ b/source/Irrlicht/CQ3LevelMesh.h @@ -24,7 +24,10 @@ namespace scene public: //! constructor - CQ3LevelMesh(io::IFileSystem* fs, scene::ISceneManager* smgr); + CQ3LevelMesh( io::IFileSystem* fs, + scene::ISceneManager* smgr, + const quake3::Q3LevelLoadParameter &loadParam + ); //! destructor virtual ~CQ3LevelMesh(); @@ -43,8 +46,6 @@ namespace scene virtual IMesh* getMesh(s32 frameInMs, s32 detailLevel=255, s32 startFrameLoop=-1, s32 endFrameLoop=-1); - virtual void releaseMesh( s32 index ); - //! Returns an axis aligned bounding box of the mesh. //! \return A bounding box of this mesh is returned. virtual const core::aabbox3d& getBoundingBox() const; @@ -56,15 +57,14 @@ namespace scene virtual E_ANIMATED_MESH_TYPE getMeshType() const; //! loads the shader definition - virtual const quake3::SShader * getShader( const c8 * filename, bool fileNameIsValid=true ); + virtual const quake3::IShader * getShader( const c8 * filename, bool fileNameIsValid=true ); //! returns a already loaded Shader - virtual const quake3::SShader * getShader( u32 index ) const; + virtual const quake3::IShader * getShader( u32 index ) const; //! get's an interface to the entities - virtual const quake3::tQ3EntityList & getEntityList(); - + virtual quake3::tQ3EntityList & getEntityList( const c8 * fileName ); //Link to held meshes? ... @@ -109,16 +109,11 @@ namespace scene private: - //! constructs a mesh from the quake 3 level file. + void constructMesh(); - - //! loads the textures + void solveTJunction(); void loadTextures(); - void constructMesh2(); - - void loadTextures2(); - struct STexShader { video::ITexture* Texture; @@ -130,30 +125,36 @@ namespace scene enum eLumps { - kEntities = 0, // Stores player/object positions, etc... - kTextures, // Stores texture information - kPlanes, // Stores the splitting planes - kNodes, // Stores the BSP nodes - kLeafs, // Stores the leafs of the nodes - kLeafFaces, // Stores the leaf's indices into the faces - kLeafBrushes, // Stores the leaf's indices into the brushes - kModels, // Stores the info of world models - kBrushes, // Stores the brushes info (for collision) - kBrushSides, // Stores the brush surfaces info - kVertices, // Stores the level vertices - kMeshVerts, // Stores the model vertices offsets - kShaders, // Stores the shader files (blending, anims..) - kFaces, // Stores the faces for the level - kLightmaps, // Stores the lightmaps for the level - kLightVolumes, // Stores extra world lighting information - kVisData, // Stores PVS and cluster info (visibility) - kMaxLumps // A constant to store the number of lumps + kEntities = 0, // Stores player/object positions, etc... + kShaders = 1, // Stores texture information + kPlanes = 2, // Stores the splitting planes + kNodes = 3, // Stores the BSP nodes + kLeafs = 4, // Stores the leafs of the nodes + kLeafFaces = 5, // Stores the leaf's indices into the faces + kLeafBrushes = 6, // Stores the leaf's indices into the brushes + kModels = 7, // Stores the info of world models + kBrushes = 8, // Stores the brushes info (for collision) + kBrushSides = 9, // Stores the brush surfaces info + kVertices = 10, // Stores the level vertices + kMeshVerts = 11, // Stores the model vertices offsets + kFogs = 12, // Stores the shader files (blending, anims..) + kFaces = 13, // Stores the faces for the level + kLightmaps = 14, // Stores the lightmaps for the level + kLightGrid = 15, // Stores extra world lighting information + kVisData = 16, // Stores PVS and cluster info (visibility) + kLightArray = 17, // RBSP + kMaxLumps // A constant to store the number of lumps }; - struct tBSPLump + enum eBspSurfaceType { - s32 offset; - s32 length; + BSP_MST_BAD, + BSP_MST_PLANAR, + BSP_MST_PATCH, + BSP_MST_TRIANGLE_SOUP, + BSP_MST_FLARE, + BSP_MST_FOLIAGE + }; struct tBSPHeader @@ -161,6 +162,14 @@ namespace scene s32 strID; // This should always be 'IBSP' s32 version; // This should be 0x2e for Quake 3 files }; + tBSPHeader header; + + struct tBSPLump + { + s32 offset; + s32 length; + }; + struct tBSPVertex { @@ -174,7 +183,7 @@ namespace scene struct tBSPFace { s32 textureID; // The index into the texture array - s32 effect; // The index for the effects (or -1 = n/a) + s32 fogNum; // The index for the effects (or -1 = n/a) s32 type; // 1=polygon, 2=patch, 3=mesh, 4=billboard s32 vertexIndex; // The index into this face's first vertex s32 numOfVerts; // The number of vertices for this face @@ -258,12 +267,13 @@ namespace scene s32 numOfBrushes; // The number brushes for the model }; - struct tBSPShader + struct tBSPFog { - c8 strName[64]; // The name of the shader file - s32 brushIndex; // The brush index for this shader - s32 unknown; // This is 99% of the time 5 + c8 shader[64]; // The name of the shader file + s32 brushIndex; // The brush index for this shader + s32 visibleSide; // the brush side that ray tests need to clip against (-1 == none }; + core::array < STexShader > FogMap; struct tBSPLights { @@ -287,20 +297,15 @@ namespace scene void loadBrushes (tBSPLump* l, io::IReadFile* file); // load the brushes of the BSP void loadBrushSides (tBSPLump* l, io::IReadFile* file); // load the brushsides of the BSP void loadLeafBrushes(tBSPLump* l, io::IReadFile* file); // load the brushes of the leaf - void loadShaders (tBSPLump* l, io::IReadFile* file); // load the shaders - - // second parameter i is the zero based index of the current face. - void createCurvedSurface(SMeshBufferLightMap* meshBuffer, s32 i); + void loadFogs (tBSPLump* l, io::IReadFile* file); // load the shaders //bi-quadratic bezier patches - void createCurvedSurface2(SMeshBufferLightMap* meshBuffer, + void createCurvedSurface_bezier(SMeshBufferLightMap* meshBuffer, s32 faceIndex, s32 patchTesselation, s32 storevertexcolor); - void createCurvedSurface3(SMeshBufferLightMap* meshBuffer, + void createCurvedSurface_nosubdivision(SMeshBufferLightMap* meshBuffer, s32 faceIndex, s32 patchTesselation, s32 storevertexcolor); - f32 Blend( const f64 s[3], const f64 t[3], const tBSPVertex *v[9], int offset); - struct S3DVertex2TCoords_64 { core::vector3d Pos; @@ -309,7 +314,7 @@ namespace scene core::vector2d TCoords; core::vector2d TCoords2; - void copyto( video::S3DVertex2TCoords &dest ) const; + void copy( video::S3DVertex2TCoords &dest ) const; S3DVertex2TCoords_64() {} S3DVertex2TCoords_64(const core::vector3d& pos, const core::vector3d& normal, const video::SColorf& color, @@ -348,7 +353,7 @@ namespace scene }; SBezier Bezier; - s32 PatchTesselation; + quake3::Q3LevelLoadParameter LoadParam; tBSPLump Lumps[kMaxLumps]; @@ -421,10 +426,10 @@ namespace scene void dumpVarGroup( const quake3::SVarGroup * group, s32 stack ) const; void scriptcallback_entity( quake3::SVarGroupList *& grouplist ); - quake3::tQ3EntityList Entity; + core::array < quake3::IShader > Entity; //quake3::tQ3EntityList Entity; void scriptcallback_shader( quake3::SVarGroupList *& grouplist ); - core::array < quake3::SShader > Shader; + core::array < quake3::IShader > Shader; quake3::tStringList ShaderFile; void InitShader(); void ReleaseShader(); @@ -432,6 +437,7 @@ namespace scene s32 setShaderMaterial( video::SMaterial & material, const tBSPFace * face ) const; + s32 setShaderFogMaterial( video::SMaterial &material, const tBSPFace * face ) const; struct SToBuffer { @@ -440,8 +446,9 @@ namespace scene }; void cleanMeshes(); + void cleanLoader (); void calcBoundingBoxes(); - + c8 buf[128]; }; } // end namespace scene diff --git a/source/Irrlicht/CQuake3ShaderSceneNode.cpp b/source/Irrlicht/CQuake3ShaderSceneNode.cpp index 9f8e3538..abbb2af5 100644 --- a/source/Irrlicht/CQuake3ShaderSceneNode.cpp +++ b/source/Irrlicht/CQuake3ShaderSceneNode.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2009 Nikolaus Gebhardt / Thomas Alten +// Copyright (C) 2002-2009 Thomas Alten / Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h @@ -20,13 +20,19 @@ namespace irr namespace scene { +// who, if not you.. +using namespace quake3; CQuake3ShaderSceneNode::CQuake3ShaderSceneNode( scene::ISceneNode* parent, scene::ISceneManager* mgr,s32 id, - io::IFileSystem *fileSystem, scene::IMeshBuffer *buffer, - const quake3::SShader * shader) - : scene::ISceneNode(parent, mgr, id), MeshBuffer(0), Original(0), - Shader(shader), TimeAbs(0.f) + io::IFileSystem *fileSystem, scene::IMeshBuffer *original, + const IShader * shader) +: scene::IMeshSceneNode(parent, mgr, id, + core::vector3df ( 0.f, 0.f, 0.f ), + core::vector3df ( 0.f, 0.f, 0.f ), + core::vector3df ( 1.f, 1.f, 1.f )), +Mesh ( 0 ), MeshBuffer(0), Original(0), +Shader(shader), TimeAbs(0.f) { #ifdef _DEBUG core::stringc dName = "CQuake3ShaderSceneNode "; @@ -35,31 +41,86 @@ CQuake3ShaderSceneNode::CQuake3ShaderSceneNode( setDebugName( dName.c_str() ); #endif - MeshBuffer = new SMeshBuffer(); - Original = new SMeshBufferLightMap(); - // name the Scene Node this->Name = Shader->name; + // take lightmap vertex type + MeshBuffer = new SMeshBuffer(); + + Mesh = new SMesh (); + Mesh->addMeshBuffer ( MeshBuffer ); + MeshBuffer->drop (); + + //Original = new SMeshBufferLightMap(); + Original = (scene::SMeshBufferLightMap*) original; + Original->grab(); + // clone meshbuffer to modifiable buffer - cloneBuffer( static_cast< scene::SMeshBufferLightMap *>( buffer ) ); + cloneBuffer( (scene::SMeshBufferLightMap*) original ); + // load all Textures in all stages loadTextures( fileSystem ); - setAutomaticCulling( scene::EAC_BOX ); + setAutomaticCulling( scene::EAC_OFF ); + } CQuake3ShaderSceneNode::~CQuake3ShaderSceneNode() { - if (MeshBuffer) - MeshBuffer->drop(); + if (Mesh) + Mesh->drop(); + if (Original) Original->drop(); } + +/* + create single copies +*/ +void CQuake3ShaderSceneNode::cloneBuffer( scene::SMeshBufferLightMap * buffer ) +{ + MeshBuffer->Material = buffer->Material; + MeshBuffer->Indices = buffer->Indices; + + video::S3DVertex dst; + core::aabbox3df bbox; + + const u32 vsize = buffer->Vertices.size(); + + MeshBuffer->Vertices.reallocate( vsize ); + for ( u32 i = 0; i!= vsize; ++i ) + { + const video::S3DVertex2TCoords& src = buffer->Vertices[i]; + + dst.Pos = src.Pos; + dst.Normal = src.Normal; + dst.Color = 0xFFFFFFFF; + dst.TCoords = src.TCoords; + MeshBuffer->Vertices.push_back( dst ); + + if ( i == 0 ) + bbox.reset ( src.Pos ); + else + bbox.addInternalPoint ( src.Pos ); + } + + // move the (temp) Mesh to a ScenePosititon + // set Scene Node Position + setPosition( bbox.getCenter() ); + + core::matrix4 m; + m.setTranslation( -bbox.getCenter() ); + SceneManager->getMeshManipulator()->transform( MeshBuffer, m ); + + // No Texture!. Use Shader-Pointer for sorting + MeshBuffer->Material.setTexture(0, (video::ITexture*) Shader); +} + +#if 0 /* create single copies */ @@ -71,6 +132,9 @@ void CQuake3ShaderSceneNode::cloneBuffer( scene::SMeshBufferLightMap * buffer ) Original->Indices = buffer->Indices; MeshBuffer->Indices = buffer->Indices; + video::S3DVertex dst; + core::aabbox3df bbox; + const u32 vsize = buffer->Vertices.size(); Original->Vertices.reallocate( vsize ); @@ -83,43 +147,68 @@ void CQuake3ShaderSceneNode::cloneBuffer( scene::SMeshBufferLightMap * buffer ) Original->Vertices.push_back(src); // we have a different vertex format +#if 0 + // automatic downcast to S3DVertex MeshBuffer->Vertices.push_back(src); MeshBuffer->Vertices.getLast().Color=0xFFFFFFFF; +#else + dst.Pos = src.Pos; + dst.Normal = src.Normal; + dst.Color = 0xFFFFFFFF; + dst.TCoords = src.TCoords; + MeshBuffer->Vertices.push_back( dst ); +#endif + + if ( i == 0 ) + bbox.reset ( src.Pos ); + else + bbox.addInternalPoint ( src.Pos ); } - MeshBuffer->recalculateBoundingBox(); + //MeshBuffer->recalculateBoundingBox(); -#if 1 - // move the (temp) Mesh + // move the (temp) Mesh to a ScenePosititon + // this is necessary for sorting transparent nodes + // this is necessary if you plane to attach child nodes { // original bounding box - const core::aabbox3df& b = MeshBuffer->getBoundingBox(); + //const core::aabbox3df& bbox = MeshBuffer->getBoundingBox(); // set Scene Node Position - setPosition( b.getCenter() ); + setPosition( bbox.getCenter() ); core::matrix4 m; - m.setTranslation( -b.getCenter() ); + m.setTranslation( -bbox.getCenter() ); SceneManager->getMeshManipulator()->transform( Original, m ); SceneManager->getMeshManipulator()->transform( MeshBuffer, m ); - - MeshBuffer->recalculateBoundingBox(); } -#endif - // used for sorting + + // No Texture!. Use Shader-Pointer for sorting MeshBuffer->Material.setTexture(0, (video::ITexture*) Shader); } - +#endif /* load the textures for all stages */ void CQuake3ShaderSceneNode::loadTextures( io::IFileSystem * fileSystem ) { - const quake3::SVarGroup *group; + const SVarGroup *group; u32 i; + video::IVideoDriver *driver = SceneManager->getVideoDriver(); + + // generic stage + u32 mipmap = 0; + group = Shader->getGroup( 1 ); + if ( group->isDefined ( "nomipmaps" ) ) + { + mipmap = 2 | (driver->getTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS)? 1: 0 ); + driver->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, false); + } + // clear all stages and prefill empty + Q3Texture.setAllocStrategy ( core::ALLOC_STRATEGY_SAFE ); Q3Texture.clear(); for ( i = 0; i != Shader->VarGroup->VariableGroup.size(); ++i ) { @@ -145,7 +234,7 @@ void CQuake3ShaderSceneNode::loadTextures( io::IFileSystem * fileSystem ) else { pos = 0; - quake3::getTextures( Q3Texture [i].Texture, mapname, pos, fileSystem, SceneManager->getVideoDriver() ); + getTextures( Q3Texture [i].Texture, mapname, pos, fileSystem, driver ); } } @@ -163,9 +252,9 @@ void CQuake3ShaderSceneNode::loadTextures( io::IFileSystem * fileSystem ) // first parameter is frequency pos = 0; - Q3Texture [i].TextureFrequency = core::max_( 0.0001f, quake3::getAsFloat( animmap, pos ) ); + Q3Texture [i].TextureFrequency = core::max_( 0.0001f, getAsFloat( animmap, pos ) ); - quake3::getTextures( Q3Texture [i].Texture, animmap, pos,fileSystem, SceneManager->getVideoDriver() ); + getTextures( Q3Texture [i].Texture, animmap, pos,fileSystem, driver ); } // get clamp map @@ -180,10 +269,13 @@ void CQuake3ShaderSceneNode::loadTextures( io::IFileSystem * fileSystem ) if ( 0 == clampmap.size() ) continue; - Q3Texture [i].TextureAddressMode = video::ETC_CLAMP; + Q3Texture [i].TextureAddressMode = video::ETC_CLAMP_TO_EDGE; pos = 0; - quake3::getTextures( Q3Texture [i].Texture, clampmap, pos,fileSystem, SceneManager->getVideoDriver() ); + getTextures( Q3Texture [i].Texture, clampmap, pos,fileSystem, driver ); } + + if ( mipmap & 2 ) + driver->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, mipmap & 1); } /* @@ -193,7 +285,7 @@ void CQuake3ShaderSceneNode::OnRegisterSceneNode() { if ( isVisible() ) { - SceneManager->registerNodeForRendering(this, isTransparent() ? ESNRP_TRANSPARENT: ESNRP_SOLID ); + SceneManager->registerNodeForRendering(this, getRenderStage() ); } ISceneNode::OnRegisterSceneNode(); } @@ -201,37 +293,51 @@ void CQuake3ShaderSceneNode::OnRegisterSceneNode() /* is this a transparent node ? */ -bool CQuake3ShaderSceneNode::isTransparent() const +E_SCENE_NODE_RENDER_PASS CQuake3ShaderSceneNode::getRenderStage() const { - bool ret = false; + E_SCENE_NODE_RENDER_PASS ret = ESNRP_SOLID; // generic stage - const quake3::SVarGroup *group; - + const SVarGroup *group; + group = Shader->getGroup( 1 ); /* - if ( group->isDefined( "surfaceparm", "nonsolid" ) ) + else + if ( group->getIndex( "portal" ) >= 0 ) { - ret = true; + ret = ESNRP_TRANSPARENT_EFFECT; } -*/ - if ( group->isDefined( "surfaceparm", "trans" ) ) + else +*/ + if ( strstr ( Shader->name.c_str(), "flame" ) + ) { - ret = true; + ret = ESNRP_TRANSPARENT_EFFECT; + } + else + if ( group->isDefined( "surfaceparm", "water" ) ) + { + ret = ESNRP_TRANSPARENT_EFFECT; } else { - for ( u32 stage = 0; stage < Shader->VarGroup->VariableGroup.size(); ++stage ) + // Look if first drawing stage needs graphical underlay + for ( u32 stage = 2; stage < Shader->VarGroup->VariableGroup.size(); ++stage ) { - if ( 0 == Q3Texture [ stage].Texture.size() ) + if ( 0 == Q3Texture [ stage ].Texture.size() ) continue; group = Shader->getGroup( stage ); - quake3::SBlendFunc blendfunc; - quake3::getBlendFunc( group->get( "blendfunc" ), blendfunc ); - quake3::getBlendFunc( group->get( "alphafunc" ), blendfunc ); - ret = blendfunc.isTransparent; + SBlendFunc blendfunc ( video::EMFN_MODULATE_1X ); + getBlendFunc( group->get( "blendfunc" ), blendfunc ); + getBlendFunc( group->get( "alphafunc" ), blendfunc ); + + //ret = blendfunc.isTransparent ? ESNRP_TRANSPARENT : ESNRP_SOLID; + if ( blendfunc.isTransparent ) + { + ret = ESNRP_TRANSPARENT; + } break; } } @@ -246,68 +352,191 @@ bool CQuake3ShaderSceneNode::isTransparent() const void CQuake3ShaderSceneNode::render() { video::IVideoDriver* driver = SceneManager->getVideoDriver(); - - bool isTransparentPass = - SceneManager->getSceneNodeRenderPass() == scene::ESNRP_TRANSPARENT; + E_SCENE_NODE_RENDER_PASS pass = SceneManager->getSceneNodeRenderPass(); video::SMaterial material; - const quake3::SVarGroup *group; + const SVarGroup *group; material.Lighting = false; material.setTexture(1, 0); material.NormalizeNormals = false; +/* + if ( 0 == strstr ( Shader->name.c_str(), "chapthroatooz" ) ) + return; +*/ // generic stage group = Shader->getGroup( 1 ); - material.BackfaceCulling = quake3::isDisabled( group->get( "cull" ) ); + material.BackfaceCulling = getCullingFunction( group->get( "cull" ) ); -// u32 zEnable = group->getIndex( "polygonoffset" ) >= 0; + u32 pushProjection = 0; + core::matrix4 projection ( core::matrix4::EM4CONST_NOTHING ); + +/* + if ( !group->isDefined ( "deformvertexes", "autosprite2" ) ) + return; +*/ + // decal ( solve z-fighting ) + if ( group->isDefined( "polygonoffset" ) ) + { + projection = driver->getTransform( video::ETS_PROJECTION ); + + core::matrix4 decalProjection ( projection ); + +/* + f32 n = SceneManager->getActiveCamera()->getNearValue(); + f32 f = SceneManager->getActiveCamera()->getFarValue (); + + f32 delta = 0.01f; + f32 pz = 0.2f; + f32 epsilon = -2.f * f * n * delta / ( ( f + n ) * pz * ( pz + delta ) ); + decalProjection[10] *= 1.f + epsilon; +*/ + // TODO: involve camera + decalProjection[10] -= 0.0002f; + driver->setTransform( video::ETS_PROJECTION, decalProjection ); + pushProjection |= 1; + } driver->setTransform(video::ETS_WORLD, AbsoluteTransformation ); - u32 drawCount = 0; - for ( u32 stage = 0; stage < Shader->VarGroup->VariableGroup.size(); ++stage ) - //for ( u32 stage = 2; stage < 3; ++stage ) + //! render all stages + //u32 drawCount = group->isDefined( "surfaceparm", "trans" ); + u32 drawCount = (pass == ESNRP_TRANSPARENT_EFFECT) ? 1 : 0; + core::matrix4 textureMatrix ( core::matrix4::EM4CONST_NOTHING ); + for ( u32 stage = 1; stage < Shader->VarGroup->VariableGroup.size(); ++stage ) { SQ3Texture &q = Q3Texture[stage]; // advance current stage - core::matrix4 texture; - animate( stage, texture ); + textureMatrix.makeIdentity(); + animate( stage, textureMatrix ); - // stage 1 finished, no drawing stage ( vertex transform only ) - if ( 0 == q.Texture.size() ) + // stage finished, no drawing stage ( vertex transform only ) + video::ITexture * tex = q.Texture.size() ? q.Texture [ q.TextureIndex ] : 0; + if ( 0 == tex ) continue; // current stage group = Shader->getGroup( stage ); - material.setTexture(0, q.Texture[ q.TextureIndex ]); - material.ZBuffer = quake3::getDepthFunction( group->get( "depthfunc" ) ); + material.setTexture(0, tex ); + material.ZBuffer = getDepthFunction( group->get( "depthfunc" ) ); - if ( group->getIndex( "depthwrite" ) >= 0 ) + if ( group->isDefined( "depthwrite" ) ) { material.ZWriteEnable = true; } else { - material.ZWriteEnable = drawCount ? false: !isTransparentPass; + material.ZWriteEnable = drawCount == 0; } //resolve quake3 blendfunction to irrlicht Material Type - quake3::SBlendFunc blendfunc; - quake3::getBlendFunc( group->get( "blendfunc" ), blendfunc ); - quake3::getBlendFunc( group->get( "alphafunc" ), blendfunc ); + SBlendFunc blendfunc ( video::EMFN_MODULATE_1X ); + getBlendFunc( group->get( "blendfunc" ), blendfunc ); + getBlendFunc( group->get( "alphafunc" ), blendfunc ); material.MaterialType = blendfunc.type; - material.MaterialTypeParam = blendfunc.param; + material.MaterialTypeParam = blendfunc.param0; material.TextureLayer[0].TextureWrap = q.TextureAddressMode; - material.setTextureMatrix( 0, texture ); + material.setTextureMatrix( 0, textureMatrix ); driver->setMaterial( material ); driver->drawMeshBuffer( MeshBuffer ); drawCount += 1; + + } + + if ( DebugDataVisible & scene::EDS_MESH_WIRE_OVERLAY ) + { + video::SMaterial deb_m; + deb_m.Wireframe = true; + deb_m.Lighting = false; + deb_m.BackfaceCulling = material.BackfaceCulling; + driver->setMaterial( deb_m ); + + driver->drawMeshBuffer( MeshBuffer ); + } + + // show normals + if ( DebugDataVisible & scene::EDS_NORMALS ) + { + video::SMaterial deb_m; + + IAnimatedMesh * arrow = SceneManager->addArrowMesh ( + "__debugnormalq3", + 0xFFECEC00,0xFF999900, + 4, 8, + 8.f, 6.f, + 0.5f,1.f + ); + if ( 0 == arrow ) + { + arrow = SceneManager->getMesh ( "__debugnormalq3" ); + } + const IMesh *mesh = arrow->getMesh ( 0 ); + + // find a good scaling factor + + core::matrix4 m2; + + // draw normals + const scene::IMeshBuffer* mb = MeshBuffer; + const u32 vSize = video::getVertexPitchFromType(mb->getVertexType()); + const video::S3DVertex* v = ( const video::S3DVertex*)mb->getVertices(); + + //f32 colCycle = 270.f / (f32) core::s32_max ( mb->getVertexCount() - 1, 1 ); + + for ( u32 i=0; i != mb->getVertexCount(); ++i ) + { + // Align to v->normal + m2.buildRotateFromTo ( core::vector3df ( 0.f, 1.f, 0 ), v->Normal ); + m2.setTranslation ( v->Pos + AbsoluteTransformation.getTranslation () ); +/* + core::quaternion quatRot( v->Normal.Z, 0.f, -v->Normal.X, 1 + v->Normal.Y ); + quatRot.normalize(); + quatRot.getMatrix ( m2, v->Pos ); + + m2 [ 12 ] += AbsoluteTransformation [ 12 ]; + m2 [ 13 ] += AbsoluteTransformation [ 13 ]; + m2 [ 14 ] += AbsoluteTransformation [ 14 ]; +*/ + driver->setTransform(video::ETS_WORLD, m2 ); + + deb_m.Lighting = true; +/* + irr::video::SColorHSL color; + irr::video::SColor rgb(0); + color.Hue = i * colCycle * core::DEGTORAD; + color.Saturation = 1.f; + color.Luminance = 0.5f; + color.toRGB( deb_m.EmissiveColor ); +*/ + switch ( i ) + { + case 0: deb_m.EmissiveColor = 0xFFFFFFFF; break; + case 1: deb_m.EmissiveColor = 0xFFFF0000; break; + case 2: deb_m.EmissiveColor = 0xFF00FF00; break; + case 3: deb_m.EmissiveColor = 0xFF0000FF; break; + default: + deb_m.EmissiveColor = v->Color; break; + } + driver->setMaterial( deb_m ); + + for ( u32 a = 0; a != mesh->getMeshBufferCount(); ++a ) + driver->drawMeshBuffer ( mesh->getMeshBuffer ( a ) ); + + v = (const video::S3DVertex*) ( (u8*) v + vSize ); + } + driver->setTransform(video::ETS_WORLD, AbsoluteTransformation); + } + + + if ( pushProjection & 1 ) + { + driver->setTransform( video::ETS_PROJECTION, projection ); } if ( DebugDataVisible & scene::EDS_BBOX ) @@ -315,14 +544,22 @@ void CQuake3ShaderSceneNode::render() video::SMaterial deb_m; deb_m.Lighting = false; driver->setMaterial(deb_m); - driver->draw3DBox( getBoundingBox(), video::SColor(0,255,255,255)); + driver->setTransform(video::ETS_WORLD, AbsoluteTransformation); + driver->draw3DBox( getBoundingBox(), video::SColor(255,255,0,0)); } + } /*! +3.3.1 deformVertexes wave
+ Designed for water surfaces, modifying the values differently at each point. + It accepts the standard wave functions of the type sin, triangle, square, sawtooth + or inversesawtooth. The "div" parameter is used to control the wave "spread" + - a value equal to the tessSize of the surface is a good default value + (tessSize is subdivision size, in game units, used for the shader when seen in the game world) . */ -void CQuake3ShaderSceneNode::vertextransform_wave( f32 dt, quake3::SModifierFunction &function ) +void CQuake3ShaderSceneNode::deformvertexes_wave( f32 dt, SModifierFunction &function ) { function.wave = core::reciprocal( function.wave ); @@ -334,22 +571,164 @@ void CQuake3ShaderSceneNode::vertextransform_wave( f32 dt, quake3::SModifierFunc const video::S3DVertex2TCoords &src = Original->Vertices[i]; video::S3DVertex &dst = MeshBuffer->Vertices[i]; - const f32 wavephase = (src.Pos.X + src.Pos.Y + src.Pos.Z) * function.wave; + if ( 0 == function.count ) + { + dst.Pos = src.Pos - getPosition (); + } + + const f32 wavephase = (dst.Pos.X + dst.Pos.Y + dst.Pos.Z) * function.wave; function.phase = phase + wavephase; const f32 f = function.evaluate( dt ); - dst.Pos.X = src.Pos.X + f * src.Normal.X; - dst.Pos.Y = src.Pos.Y + f * src.Normal.Y; - dst.Pos.Z = src.Pos.Z + f * src.Normal.Z; + dst.Pos.X += f * src.Normal.X; + dst.Pos.Y += f * src.Normal.Y; + dst.Pos.Z += f * src.Normal.Z; + + if ( i == 0 ) + MeshBuffer->BoundingBox.reset ( dst.Pos ); + else + MeshBuffer->BoundingBox.addInternalPoint ( dst.Pos ); } + function.count = 1; } /*! + deformVertexes move x y z func base amplitude phase freq + The move parameter is used to make a brush, curve patch or model + appear to move together as a unit. The x y z values are the distance + and direction in game units the object appears to move relative to + it's point of origin in the map. The func base amplitude phase freq values are + the same as found in other waveform manipulations. + + The product of the function modifies the values x, y, and z. + Therefore, if you have an amplitude of 5 and an x value of 2, + the object will travel 10 units from its point of origin along the x axis. + This results in a total of 20 units of motion along the x axis, since the + amplitude is the variation both above and below the base. + + It must be noted that an object made with this shader does not actually + change position, it only appears to. + + Design Notes: + If an object is made up of surfaces with different shaders, all must have + matching deformVertexes move values or the object will appear to tear itself apart. */ -void CQuake3ShaderSceneNode::vertextransform_bulge( f32 dt, quake3::SModifierFunction &function ) + +void CQuake3ShaderSceneNode::deformvertexes_move( f32 dt, SModifierFunction &function ) { - function.func = 0; + function.wave = core::reciprocal( function.wave ); + const f32 f = function.evaluate( dt ); + + const u32 vsize = MeshBuffer->Vertices.size(); + for ( u32 i = 0; i != vsize; ++i ) + { + const video::S3DVertex2TCoords &src = Original->Vertices[i]; + video::S3DVertex &dst = MeshBuffer->Vertices[i]; + + if ( 0 == function.count ) + { + dst.Pos = src.Pos - getPosition (); + } + + dst.Pos.X += f * function.x; + dst.Pos.Y += f * function.y; + dst.Pos.Z += f * function.z; + + if ( i == 0 ) + MeshBuffer->BoundingBox.reset ( dst.Pos ); + else + MeshBuffer->BoundingBox.addInternalPoint ( dst.Pos ); + } + function.count = 1; + +} + +/*! + 3.3.2 deformVertexes normal
+ This deformation affects the normals of a vertex without actually moving it, + which will effect later shader options like lighting and especially environment mapping. + If the shader stages don't use normals in any of their calculations, there will + be no visible effect. + + Design Notes: Putting values of 0.1 t o 0.5 in Amplitude and 1.0 to 4.0 in the + Frequency can produce some satisfying results. Some things that have been + done with it: A small fluttering bat, falling leaves, rain, flags. +*/ +void CQuake3ShaderSceneNode::deformvertexes_normal( f32 dt, SModifierFunction &function ) +{ + function.func = SINUS; + const u32 vsize = MeshBuffer->Vertices.size(); + for ( u32 i = 0; i != vsize; ++i ) + { + const video::S3DVertex2TCoords &src = Original->Vertices[i]; + video::S3DVertex &dst = MeshBuffer->Vertices[i]; + + function.base = atan2f ( src.Pos.X, src.Pos.Y ); + function.phase = src.Pos.X + src.Pos.Z; + + const f32 lat = function.evaluate( dt ); + + function.base = src.Normal.Y; + function.phase = src.Normal.Z + src.Normal.X; + + const f32 lng = function.evaluate( dt ); + + dst.Normal.X = cosf ( lat ) * sinf ( lng ); + dst.Normal.Y = sinf ( lat ) * sinf ( lng ); + dst.Normal.Z = cosf ( lng ); + + } +} + + +/*! + 3.3.3 deformVertexes bulge + This forces a bulge to move along the given s and t directions. Designed for use + on curved pipes. + + Specific parameter definitions for deform keywords: +
This is roughly defined as the size of the waves that occur. + It is measured in game units. Smaller values create a greater + density of smaller wave forms occurring in a given area. + Larger values create a lesser density of waves, or otherwise put, + the appearance of larger waves. To look correct this value should + closely correspond to the value (in pixels) set for tessSize (tessellation size) + of the texture. A value of 100.0 is a good default value + (which means your tessSize should be close to that for things to look "wavelike"). + + This is the type of wave form being created. Sin stands for sine wave, + a regular smoothly flowing wave. Triangle is a wave with a sharp ascent + and a sharp decay. It will make a choppy looking wave forms. + A square wave is simply on or off for the period of the + frequency with no in between. The sawtooth wave has the ascent of a + triangle wave, but has the decay cut off sharply like a square wave. + An inversesawtooth wave reverses this. + + This is the distance, in game units that the apparent surface of the + texture is displaced from the actual surface of the brush as placed + in the editor. A positive value appears above the brush surface. + A negative value appears below the brush surface. + An example of this is the Quad effect, which essentially is a + shell with a positive base value to stand it away from the model + surface and a 0 (zero) value for amplitude. + + The distance that the deformation moves away from the base value. + See Wave Forms in the introduction for a description of amplitude. + + See Wave Forms in the introduction for a description of phase) + + See Wave Forms in the introduction for a description of frequency) + + Design Note: The div and amplitude parameters, when used in conjunction with + liquid volumes like water should take into consideration how much the water + will be moving. A large ocean area would have have massive swells (big div values) + that rose and fell dramatically (big amplitude values). While a small, quiet pool + may move very little. +*/ +void CQuake3ShaderSceneNode::deformvertexes_bulge( f32 dt, SModifierFunction &function ) +{ + function.func = SINUS; function.wave = core::reciprocal( function.bulgewidth ); dt *= function.bulgespeed * 0.1f; @@ -366,82 +745,231 @@ void CQuake3ShaderSceneNode::vertextransform_bulge( f32 dt, quake3::SModifierFun const f32 f = function.evaluate( dt ); - dst.Pos.X = src.Pos.X + f * src.Normal.X; - dst.Pos.Y = src.Pos.Y + f * src.Normal.Y; - dst.Pos.Z = src.Pos.Z + f * src.Normal.Z; - } -} - -/*! -*/ -void CQuake3ShaderSceneNode::vertextransform_autosprite( f32 dt, quake3::SModifierFunction &function ) -{ - const core::matrix4 &m = SceneManager->getActiveCamera()->getViewFrustum()->Matrices [ video::ETS_VIEW ]; - const core::vector3df view( -m[2], -m[6] , -m[10] ); - - const u32 vsize = MeshBuffer->Vertices.size(); - - core::aabbox3df box; - u32 g; - - for ( u32 i = 0; i < vsize; i += 4 ) - { - // in pairs of 4 - box.reset( Original->Vertices[i].Pos ); - for ( g = 1; g != 4; ++g ) + if ( 0 == function.count ) { - box.addInternalPoint( Original->Vertices[i + g].Pos ); + dst.Pos = src.Pos - getPosition (); } - core::vector3df c = box.getCenter(); - f32 sh = 0.5f * ( box.MaxEdge.Z - box.MinEdge.Z ); - f32 sv = 0.5f * ( box.MaxEdge.Y - box.MinEdge.Y ); + dst.Pos.X += f * src.Normal.X; + dst.Pos.Y += f * src.Normal.Y; + dst.Pos.Z += f * src.Normal.Z; - const core::vector3df h( m[0] * sh, m[4] * sh, m[8] * sh ); - const core::vector3df v( m[1] * sv, m[5] * sv, m[9] * sv ); - - MeshBuffer->Vertices[ i + 0 ].Pos = c + h + v; - MeshBuffer->Vertices[ i + 1 ].Pos = c - h - v; - MeshBuffer->Vertices[ i + 2 ].Pos = c + h - v; - MeshBuffer->Vertices[ i + 3 ].Pos = c - h + v; - - MeshBuffer->Vertices[ i + 0 ].Normal = view; - MeshBuffer->Vertices[ i + 1 ].Normal = view; - MeshBuffer->Vertices[ i + 2 ].Normal = view; - MeshBuffer->Vertices[ i + 3 ].Normal = view; + if ( i == 0 ) + MeshBuffer->BoundingBox.reset ( dst.Pos ); + else + MeshBuffer->BoundingBox.addInternalPoint ( dst.Pos ); } + + function.count = 1; +} + + +/*! + deformVertexes autosprite + + This function can be used to make any given triangle quad + (pair of triangles that form a square rectangle) automatically behave + like a sprite without having to make it a separate entity. This means + that the "sprite" on which the texture is placed will rotate to always + appear at right angles to the player's view as a sprite would. Any four-sided + brush side, flat patch, or pair of triangles in a model can have the autosprite + effect on it. The brush face containing a texture with this shader keyword must + be square. +*/ +void CQuake3ShaderSceneNode::deformvertexes_autosprite( f32 dt, SModifierFunction &function ) +{ + u32 vsize = MeshBuffer->Vertices.size(); + u32 g; + u32 i; + + const core::vector3df& camPos = SceneManager->getActiveCamera()->getPosition(); + + video::S3DVertex * dv = MeshBuffer->Vertices.pointer(); + const video::S3DVertex2TCoords * vin = Original->Vertices.pointer(); + + core::matrix4 lookat ( core::matrix4::EM4CONST_NOTHING ); + core::quaternion q; + for ( i = 0; i < vsize; i += 4 ) + { + // quad-plane + core::vector3df center = 0.25f * ( vin[i+0].Pos + vin[i+1].Pos + vin[i+2].Pos + vin[i+3].Pos ); + core::vector3df forward = camPos - center; + + q.rotationFromTo ( vin[i].Normal, forward ); + q.getMatrixCenter ( lookat, center, getPosition () ); + + for ( g = 0; g < 4; ++g ) + { + lookat.transformVect ( dv[i+g].Pos, vin[i+g].Pos ); + lookat.rotateVect ( dv[i+g].Normal, vin[i+g].Normal ); + } + + } + function.count = 1; +} + + +/*! + deformVertexes autosprite2 + Is a slightly modified "sprite" that only rotates around the middle of its longest axis. + This allows you to make a pillar of fire that you can walk around, or an energy beam + stretched across the room. +*/ + +struct sortaxis +{ + core::vector3df v; + bool operator < ( const sortaxis &other ) const + { + return v.getLengthSQ () < other.v.getLengthSQ (); + } +}; + +void CQuake3ShaderSceneNode::deformvertexes_autosprite2( f32 dt, SModifierFunction &function ) +{ + u32 vsize = MeshBuffer->Vertices.size(); + u32 g; + u32 i; + + const core::vector3df camPos = SceneManager->getActiveCamera()->getAbsolutePosition(); + + video::S3DVertex * dv = MeshBuffer->Vertices.pointer(); + const video::S3DVertex2TCoords * vin = Original->Vertices.pointer(); + + core::matrix4 lookat ( core::matrix4::EM4CONST_NOTHING ); + + core::array < sortaxis > axis; + axis.set_used ( 3 ); + + for ( i = 0; i < vsize; i += 4 ) + { + // quad-plane + core::vector3df center = 0.25f * ( vin[i+0].Pos + vin[i+1].Pos + vin[i+2].Pos + vin[i+3].Pos ); + + // longes axe + axis[0].v = vin[i+1].Pos - vin[i+0].Pos; + axis[1].v = vin[i+2].Pos - vin[i+0].Pos; + axis[2].v = vin[i+3].Pos - vin[i+0].Pos; + axis.set_sorted ( false ); + axis.sort (); + + lookat.buildAxisAlignedBillboard ( camPos, center, getPosition (), axis[1].v, vin[i+0].Normal ); + + for ( g = 0; g < 4; ++g ) + { + lookat.transformVect ( dv[i+g].Pos, vin[i+g].Pos ); + lookat.rotateVect ( dv[i+g].Normal, vin[i+g].Normal ); + } + } + function.count = 1; } /* Generate Vertex Color */ -void CQuake3ShaderSceneNode::vertextransform_rgbgen( f32 dt, quake3::SModifierFunction &function ) +void CQuake3ShaderSceneNode::vertextransform_rgbgen( f32 dt, SModifierFunction &function ) { u32 i; const u32 vsize = MeshBuffer->Vertices.size(); - switch ( function.masterfunc1 ) + switch ( function.rgbgen ) { - case 6: - //identity + case IDENTITY: + //rgbgen identity for ( i = 0; i != vsize; ++i ) - MeshBuffer->Vertices[i].Color = 0xFFFFFFFF; + MeshBuffer->Vertices[i].Color.color = 0xFFFFFFFF; break; - case 7: - // vertex + + case IDENTITYLIGHTING: + // rgbgen identitylighting TODO: overbright for ( i = 0; i != vsize; ++i ) - MeshBuffer->Vertices[i].Color = Original->Vertices[i].Color; + MeshBuffer->Vertices[i].Color.color = 0xFF7F7F7F; break; - case 5: + + case EXACTVERTEX: + // alphagen exactvertex TODO lighting + case VERTEX: + // rgbgen vertex + for ( i = 0; i != vsize; ++i ) + MeshBuffer->Vertices[i].Color.color = Original->Vertices[i].Color.color; + break; + case WAVE: { - // wave + // rgbGen wave f32 f = function.evaluate( dt ) * 255.f; s32 value = core::clamp( core::floor32(f), 0, 255 ); - value |= value << 8; - value |= value << 16; + value = 0xFF000000 | value << 16 | value << 8 | value; for ( i = 0; i != vsize; ++i ) - MeshBuffer->Vertices[i].Color = value; + MeshBuffer->Vertices[i].Color.color = value; + } break; + case CONSTANT: + //rgbgen const ( x y z ) + video::SColorf cf( function.x, function.y, function.z ); + u32 col = cf.toSColor ().color; + for ( i = 0; i != vsize; ++i ) + MeshBuffer->Vertices[i].Color.color = col; + break; + + } +} + +/* + Generate Vertex Color, Alpha +*/ +void CQuake3ShaderSceneNode::vertextransform_alphagen( f32 dt, SModifierFunction &function ) +{ + u32 i; + const u32 vsize = MeshBuffer->Vertices.size(); + + switch ( function.alphagen ) + { + case IDENTITY: + //alphagen identity + for ( i = 0; i != vsize; ++i ) + MeshBuffer->Vertices[i].Color.setAlpha ( 0xFF ); + break; + + case EXACTVERTEX: + // alphagen exactvertex TODO lighting + case VERTEX: + // alphagen vertex + for ( i = 0; i != vsize; ++i ) + MeshBuffer->Vertices[i].Color.setAlpha ( Original->Vertices[i].Color.getAlpha() ); + break; + case CONSTANT: + { + // alphagen const + u32 a = (u32) ( function.x * 255.f ); + for ( i = 0; i != vsize; ++i ) + MeshBuffer->Vertices[i].Color.setAlpha ( a ); + } break; + + case LIGHTINGSPECULAR: + { + // alphagen lightingspecular TODO!!! + const SViewFrustum *frustum = SceneManager->getActiveCamera()->getViewFrustum(); + const core::matrix4 &view = frustum->Matrices [ video::ETS_VIEW ]; + + const f32 *m = view.pointer(); + + for ( i = 0; i != vsize; ++i ) + { + const core::vector3df &n = Original->Vertices[i].Normal; + MeshBuffer->Vertices[i].Color.setAlpha ((u32)( 128.f *(1.f+(n.X*m[0]+n.Y*m[1]+n.Z*m[2])))); + } + + } break; + + + case WAVE: + { + // alphagen wave + f32 f = function.evaluate( dt ) * 255.f; + s32 value = core::clamp( core::floor32(f), 0, 255 ); + + for ( i = 0; i != vsize; ++i ) + MeshBuffer->Vertices[i].Color.setAlpha ( value ); } break; } } @@ -451,17 +979,17 @@ void CQuake3ShaderSceneNode::vertextransform_rgbgen( f32 dt, quake3::SModifierFu /* Generate Texture Coordinates */ -void CQuake3ShaderSceneNode::vertextransform_tcgen( f32 dt, quake3::SModifierFunction &function ) +void CQuake3ShaderSceneNode::vertextransform_tcgen( f32 dt, SModifierFunction &function ) { u32 i; const u32 vsize = MeshBuffer->Vertices.size(); switch ( function.tcgen ) { - case 12: + case TURBULENCE: //tcgen turb { - function.wave = core::reciprocal( function.wave ); + function.wave = core::reciprocal( function.phase ); const f32 phase = function.phase; @@ -481,31 +1009,52 @@ void CQuake3ShaderSceneNode::vertextransform_tcgen( f32 dt, quake3::SModifierFun } break; - case 8: + case TEXTURE: // tcgen texture for ( i = 0; i != vsize; ++i ) MeshBuffer->Vertices[i].TCoords = Original->Vertices[i].TCoords; break; - case 9: + case LIGHTMAP: // tcgen lightmap for ( i = 0; i != vsize; ++i ) MeshBuffer->Vertices[i].TCoords = Original->Vertices[i].TCoords2; break; - case 10: + case ENVIRONMENT: { - // tcgen environment ( D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR ) + // tcgen environment + const SViewFrustum *frustum = SceneManager->getActiveCamera()->getViewFrustum(); + const core::matrix4 &view = frustum->Matrices [ video::ETS_VIEW ]; + const f32 *m = view.pointer(); + + core::vector3df n; + for ( i = 0; i != vsize; ++i ) + { + //const core::vector3df &n = Original->Vertices[i].Normal; + + n = frustum->cameraPosition - Original->Vertices[i].Pos; + n.normalize(); + n += Original->Vertices[i].Normal; + n.normalize(); + + MeshBuffer->Vertices[i].TCoords.X = 0.5f*(1.f+(n.X*m[0]+n.Y*m[1]+n.Z*m[2])); + MeshBuffer->Vertices[i].TCoords.Y = 0.5f*(1.f+(n.X*m[4]+n.Y*m[5]+n.Z*m[6])); + } + +#if 0 + // tcgen environment // using eye linear, sphere map may be cooler;-) // modelmatrix is identity - const core::matrix4 &view = SceneManager->getActiveCamera()->getViewFrustum()->Matrices [ video::ETS_VIEW ]; - const core::matrix4 &viewinverse = SceneManager->getActiveCamera()->getViewFrustum()->Matrices [ SViewFrustum::ETS_VIEW_MODEL_INVERSE_3 ]; + const SViewFrustum *frustum = SceneManager->getActiveCamera()->getViewFrustum(); + const core::matrix4 &view = frustum->Matrices [ video::ETS_VIEW ]; + const core::matrix4 &viewinverse = frustum->Matrices [ SViewFrustum::ETS_VIEW_MODEL_INVERSE_3 ]; // eyePlane core::vector3df eyePlaneS; core::vector3df eyePlaneT; - viewinverse.transformVect( eyePlaneS, core::vector3df(1.f, 0.f, 0.f) ); - viewinverse.transformVect( eyePlaneT, core::vector3df(0.f, 1.f, 0.f) ); + viewinverse.rotateVect( eyePlaneS, core::vector3df(1.f, 0.f, 0.f) ); + viewinverse.rotateVect( eyePlaneT, core::vector3df(0.f, 1.f, 0.f) ); eyePlaneS.normalize(); eyePlaneT.normalize(); @@ -514,20 +1063,20 @@ void CQuake3ShaderSceneNode::vertextransform_tcgen( f32 dt, quake3::SModifierFun for ( i = 0; i != vsize; ++i ) { // vertex in eye space - view.transformVect( v, Original->Vertices[i].Pos ); + view.rotateVect( v, Original->Vertices[i].Pos ); v.normalize(); - MeshBuffer->Vertices[i].TCoords.X = (1.f + eyePlaneS.dotProduct(v) ) * 0.5f; - MeshBuffer->Vertices[i].TCoords.Y = 1.f - ( (1.f + eyePlaneT.dotProduct(v) ) * 0.5f ); + MeshBuffer->Vertices[i].TCoords.X = ( (1.f + eyePlaneS.dotProduct(v) ) * 0.5f ); + MeshBuffer->Vertices[i].TCoords.Y = ( (1.f - eyePlaneT.dotProduct(v) ) * 0.5f ); } - +#endif } break; } } - +#if 0 /* Transform Texture Coordinates */ @@ -571,7 +1120,7 @@ void CQuake3ShaderSceneNode::transformtex( const core::matrix4 &m, const u32 add } } - +#endif /* @@ -583,42 +1132,42 @@ void CQuake3ShaderSceneNode::transformtex( const core::matrix4 &m, const u32 add */ void CQuake3ShaderSceneNode::animate( u32 stage,core::matrix4 &texture ) { - const quake3::SVarGroup *group = Shader->getGroup( stage ); + const SVarGroup *group = Shader->getGroup( stage ); // select current texture - if ( Q3Texture [ stage ].TextureFrequency != 0.f ) + SQ3Texture &q3Tex = Q3Texture [ stage ]; + if ( q3Tex.TextureFrequency != 0.f ) { - s32 v = core::floor32( TimeAbs * Q3Texture[stage].TextureFrequency ); - Q3Texture [ stage ].TextureIndex = v % Q3Texture[stage].Texture.size(); + s32 v = core::floor32( TimeAbs * q3Tex.TextureFrequency ); + q3Tex.TextureIndex = v % q3Tex.Texture.size(); } core::matrix4 m2; - quake3::SModifierFunction function; + SModifierFunction function; - f32 f0; - f32 f1; + f32 f[16]; // walk group for all modifiers for ( u32 g = 0; g != group->Variable.size(); ++g ) { - const quake3::SVariable &v = group->Variable[g]; + const SVariable &v = group->Variable[g]; // get the modifier static const c8 * modifierList[] = { - "tcmod","deformvertexes","rgbgen","tcgen","map" + "tcmod","deformvertexes","rgbgen","tcgen","map","alphagen" }; u32 pos = 0; - function.masterfunc0 = quake3::isEqual( v.name, pos, modifierList, 5 ); + function.masterfunc0 = (eQ3ModifierFunction) isEqual( v.name, pos, modifierList, 6 ); - if ( -2 == function.masterfunc0 ) + if ( UNKNOWN == function.masterfunc0 ) continue; switch ( function.masterfunc0 ) { //tcmod - case 0: + case TCMOD: m2.makeIdentity(); break; } @@ -629,135 +1178,204 @@ void CQuake3ShaderSceneNode::animate( u32 stage,core::matrix4 &texture ) "scroll","scale","rotate","stretch","turb", "wave","identity","vertex", "texture","lightmap","environment","$lightmap", - "bulge","autosprite","autosprite2" + "bulge","autosprite","autosprite2","transform", + "exactvertex","const","lightingspecular","move","normal", + "identitylighting" }; + static const c8 * groupToken[] = { "(", ")" }; pos = 0; - function.masterfunc1 = quake3::isEqual( v.content, pos, funclist, 14 ); + function.masterfunc1 = (eQ3ModifierFunction) isEqual( v.content, pos, funclist, 22 ); + if ( function.masterfunc1 != UNKNOWN ) + function.masterfunc1 = (eQ3ModifierFunction) ((u32) function.masterfunc1 + FUNCTION2 + 1); switch ( function.masterfunc1 ) { - case 0: - // scroll - f0 = quake3::getAsFloat( v.content, pos ) * TimeAbs; - f1 = quake3::getAsFloat( v.content, pos ) * TimeAbs; - m2.setTextureTranslate( f0, f1 ); + case SCROLL: + // tcMod scroll + f[0] = getAsFloat( v.content, pos ) * TimeAbs; + f[1] = getAsFloat( v.content, pos ) * TimeAbs; + m2.setTextureTranslate( f[0], f[1] ); break; - case 1: - // scale - f0 = quake3::getAsFloat( v.content, pos ); - f1 = quake3::getAsFloat( v.content, pos ); - m2.setTextureScale( f0, f1 ); + case SCALE: + // tcmod scale + f[0] = getAsFloat( v.content, pos ); + f[1] = getAsFloat( v.content, pos ); + m2.setTextureScale( f[0], f[1] ); break; - case 2: - //rotate - m2.setTextureRotationCenter( quake3::getAsFloat( v.content, pos ) * core::DEGTORAD * TimeAbs ); + case ROTATE: + // tcmod rotate + m2.setTextureRotationCenter( getAsFloat( v.content, pos ) * + core::DEGTORAD * + TimeAbs + ); break; - case 3: - case 4: - case 5: - case 6: - case 7: + case TRANSFORM: + // tcMod + memset(f, 0, sizeof ( f )); + f[10] = f[15] = 1.f; + + f[0] = getAsFloat( v.content, pos ); + f[1] = getAsFloat( v.content, pos ); + f[4] = getAsFloat( v.content, pos ); + f[5] = getAsFloat( v.content, pos ); + f[8] = getAsFloat( v.content, pos ); + f[9] = getAsFloat( v.content, pos ); + m2.setM ( f ); + break; + + case STRETCH: // stretch + case TURBULENCE: // turb + case WAVE: // wave + case IDENTITY: // identity + case IDENTITYLIGHTING: + case VERTEX: // vertex + case MOVE: + case CONSTANT: { // turb == sin, default == sin - function.func = 0; + function.func = SINUS; - if (function.masterfunc1 == 5 && function.masterfunc0 == 1) + if ( function.masterfunc0 == DEFORMVERTEXES ) { - // deformvertexes, wave - function.wave = quake3::getAsFloat( v.content, pos ); - } - - if (function.masterfunc1 == 3 || - function.masterfunc1 == 4 || - function.masterfunc1 == 5) - { - // stretch, wave, tub - quake3::getModifierFunc( function, v.content, pos ); + switch ( function.masterfunc1 ) + { + case WAVE: + // deformvertexes wave + function.wave = getAsFloat( v.content, pos ); + break; + case MOVE: + //deformvertexes move + function.x = getAsFloat( v.content, pos ); + function.z = getAsFloat( v.content, pos ); + function.y = getAsFloat( v.content, pos ); + break; + } } switch ( function.masterfunc1 ) { - case 3: - // stretch - f0 = core::reciprocal( function.evaluate(TimeAbs) ); - m2.setTextureScaleCenter( f0, f0 ); + case STRETCH: + case TURBULENCE: + case WAVE: + case MOVE: + getModifierFunc( function, v.content, pos ); break; - case 4: - { - // turb -/* - quake3::SModifierFunction ampFunction; - ampFunction.func = 0; - ampFunction.freq = function.freq; - ampFunction.base = 1.f; - ampFunction.amp = 0.2f; - f2 = ampFunction.evaluate( TimeAbs ); + } - f0 = function.evaluate( TimeAbs ); - function.func = 1; - f1 = function.evaluate( TimeAbs ); - - m2.setTextureTranslate( f0, f1 ); - m2.setTextureScaleCenter( f2, f2 ); - //m2.setTextureScale( f2, f2 ); -*/ - }break; - case 5: - if ( function.masterfunc0 == 1 ) - { - vertextransform_wave( TimeAbs, function ); - } - else - { - vertextransform_rgbgen( TimeAbs, function ); - } + switch ( function.masterfunc1 ) + { + case STRETCH: + //tcMod stretch + f[0] = core::reciprocal( function.evaluate(TimeAbs) ); + m2.setTextureScaleCenter( f[0], f[0] ); break; - case 6: - case 7: - vertextransform_rgbgen( TimeAbs, function ); + case TURBULENCE: + //tcMod turb + //function.tcgen = TURBULENCE; + m2.setTextureRotationCenter( function.frequency * + core::DEGTORAD * + TimeAbs + ); + break; + case WAVE: + case IDENTITY: + case IDENTITYLIGHTING: + case VERTEX: + case EXACTVERTEX: + case CONSTANT: + case LIGHTINGSPECULAR: + case MOVE: + switch ( function.masterfunc0 ) + { + case DEFORMVERTEXES: + switch ( function.masterfunc1 ) + { + case WAVE: + deformvertexes_wave( TimeAbs, function ); + break; + case MOVE: + deformvertexes_move( TimeAbs, function ); + break; + } + break; + case RGBGEN: + function.rgbgen = function.masterfunc1; + if ( function.rgbgen == CONSTANT ) + { + isEqual ( v.content, pos, groupToken, 2 ); + function.x = getAsFloat( v.content, pos ); + function.y = getAsFloat( v.content, pos ); + function.z = getAsFloat( v.content, pos ); + } + //vertextransform_rgbgen( TimeAbs, function ); + break; + case ALPHAGEN: + function.alphagen = function.masterfunc1; + if ( function.alphagen == CONSTANT ) + { + function.x = getAsFloat( v.content, pos ); + } + + //vertextransform_alphagen( TimeAbs, function ); + break; + } break; } } break; - case 8: - case 9: - case 10: + case TEXTURE: + case LIGHTMAP: + case ENVIRONMENT: // "texture","lightmap","environment" function.tcgen = function.masterfunc1; break; - case 11: + case $LIGHTMAP: // map == lightmap, tcgen == lightmap - function.tcgen = 9; + function.tcgen = LIGHTMAP; break; - case 12: + case BULGE: // deformvertexes bulge - function.bulgewidth = quake3::getAsFloat( v.content, pos ); - function.bulgeheight = quake3::getAsFloat( v.content, pos ); - function.bulgespeed = quake3::getAsFloat( v.content, pos ); + function.bulgewidth = getAsFloat( v.content, pos ); + function.bulgeheight = getAsFloat( v.content, pos ); + function.bulgespeed = getAsFloat( v.content, pos ); - vertextransform_bulge(TimeAbs, function); + deformvertexes_bulge(TimeAbs, function); break; - case 13: - case 14: + case NORMAL: + // deformvertexes normal + function.amp = getAsFloat( v.content, pos ); + function.frequency = getAsFloat( v.content, pos ); + + deformvertexes_normal(TimeAbs, function); + break; + + case AUTOSPRITE: // deformvertexes autosprite - vertextransform_autosprite(TimeAbs, function); + deformvertexes_autosprite(TimeAbs, function); break; + case AUTOSPRITE2: + // deformvertexes autosprite2 + deformvertexes_autosprite2(TimeAbs, function); + break; + + } // func switch ( function.masterfunc0 ) { - case 0: + case TCMOD: texture *= m2; break; } } // group - // texture coordinate modifier - vertextransform_tcgen(TimeAbs, function); + vertextransform_rgbgen( TimeAbs, function ); + vertextransform_alphagen( TimeAbs, function ); + vertextransform_tcgen( TimeAbs, function ); } @@ -780,7 +1398,7 @@ u32 CQuake3ShaderSceneNode::getMaterialCount() const video::SMaterial& CQuake3ShaderSceneNode::getMaterial(u32 i) { - video::SMaterial& m = MeshBuffer->getMaterial(); + video::SMaterial& m = MeshBuffer->Material; m.setTexture(0, 0); if ( Q3Texture [ i ].TextureIndex ) m.setTexture(0, Q3Texture [ i ].Texture [ Q3Texture [ i ].TextureIndex ]); diff --git a/source/Irrlicht/CQuake3ShaderSceneNode.h b/source/Irrlicht/CQuake3ShaderSceneNode.h index 7ffc7b6d..06f527ef 100644 --- a/source/Irrlicht/CQuake3ShaderSceneNode.h +++ b/source/Irrlicht/CQuake3ShaderSceneNode.h @@ -5,11 +5,13 @@ #ifndef __C_QUAKE3_SCENE_NODE_H_INCLUDED__ #define __C_QUAKE3_SCENE_NODE_H_INCLUDED__ -#include "ISceneNode.h" +#include "IMeshSceneNode.h" #include "IQ3Shader.h" #include "IFileSystem.h" #include "SMeshBuffer.h" #include "SMeshBufferLightMap.h" +#include "SMesh.h" +#include "ISceneManager.h" namespace irr { @@ -17,13 +19,15 @@ namespace scene { //! Scene node which is a quake3 shader. -class CQuake3ShaderSceneNode : public scene::ISceneNode +class CQuake3ShaderSceneNode : public scene::IMeshSceneNode { public: - CQuake3ShaderSceneNode( ISceneNode* parent, ISceneManager* mgr,s32 id, - io::IFileSystem *fileSystem,IMeshBuffer *buffer, - const quake3::SShader * shader); + CQuake3ShaderSceneNode( ISceneNode* parent, ISceneManager* mgr, s32 id, + io::IFileSystem *fileSystem, + IMeshBuffer *original, + const quake3::IShader * shader + ); virtual ~CQuake3ShaderSceneNode(); @@ -35,17 +39,29 @@ public: virtual u32 getMaterialCount() const; virtual video::SMaterial& getMaterial(u32 i); + //! Returns type of the scene node + virtual ESCENE_NODE_TYPE getType() const { return ESNT_Q3SHADER_SCENE_NODE; } + + virtual void setMesh(IMesh* mesh){} + virtual IMesh* getMesh() { return Mesh; } + virtual void setReadOnlyMaterials(bool readonly) {} + virtual bool isReadOnlyMaterials() const { return true; } + private: - SMeshBuffer* MeshBuffer; + const quake3::IShader* Shader; + SMesh *Mesh; SMeshBufferLightMap* Original; - const quake3::SShader* Shader; + SMeshBuffer* MeshBuffer; struct SQ3Texture { SQ3Texture () : TextureIndex ( 0 ), TextureFrequency(0.f), - TextureAddressMode( video::ETC_REPEAT ) {} + TextureAddressMode( video::ETC_REPEAT ) + { + Texture.setAllocStrategy ( core::ALLOC_STRATEGY_SAFE ); + } quake3::tTexArray Texture; @@ -57,20 +73,27 @@ private: core::array< SQ3Texture > Q3Texture; void loadTextures ( io::IFileSystem * fileSystem ); + void addBuffer ( scene::SMeshBufferLightMap * buffer ); void cloneBuffer ( scene::SMeshBufferLightMap * buffer ); - void vertextransform_wave ( f32 dt, quake3::SModifierFunction &function ); - void vertextransform_bulge( f32 dt, quake3::SModifierFunction &function ); - void vertextransform_autosprite( f32 dt, quake3::SModifierFunction &function ); + void deformvertexes_wave ( f32 dt, quake3::SModifierFunction &function ); + void deformvertexes_move ( f32 dt, quake3::SModifierFunction &function ); + void deformvertexes_bulge( f32 dt, quake3::SModifierFunction &function ); + void deformvertexes_autosprite( f32 dt, quake3::SModifierFunction &function ); + void deformvertexes_autosprite2( f32 dt, quake3::SModifierFunction &function ); + void deformvertexes_normal ( f32 dt, quake3::SModifierFunction &function ); + void vertextransform_tcgen ( f32 dt, quake3::SModifierFunction &function ); void vertextransform_rgbgen ( f32 dt, quake3::SModifierFunction &function ); + void vertextransform_alphagen ( f32 dt, quake3::SModifierFunction &function ); void transformtex ( const core::matrix4 &m, const u32 clamp ); f32 TimeAbs; + void animate( u32 stage, core::matrix4 &texture ); - bool isTransparent() const; + E_SCENE_NODE_RENDER_PASS getRenderStage() const; }; diff --git a/source/Irrlicht/CReadFile.cpp b/source/Irrlicht/CReadFile.cpp index a8550f3e..5c431204 100644 --- a/source/Irrlicht/CReadFile.cpp +++ b/source/Irrlicht/CReadFile.cpp @@ -10,7 +10,7 @@ namespace io { -CReadFile::CReadFile(const c8* fileName) +CReadFile::CReadFile(const core::string& fileName) : File(0), FileSize(0), Filename(fileName) { #ifdef _DEBUG @@ -73,7 +73,11 @@ void CReadFile::openFile() return; } +#if defined ( _IRR_WCHAR_FILESYSTEM ) + File = _wfopen(Filename.c_str(), L"rb"); +#else File = fopen(Filename.c_str(), "rb"); +#endif if (File) { @@ -87,14 +91,14 @@ void CReadFile::openFile() //! returns name of file -const c8* CReadFile::getFileName() const +const core::string& CReadFile::getFileName() const { - return Filename.c_str(); + return Filename; } -IReadFile* createReadFile(const c8* fileName) +IReadFile* createReadFile(const core::string& fileName) { CReadFile* file = new CReadFile(fileName); if (file->isOpen()) diff --git a/source/Irrlicht/CReadFile.h b/source/Irrlicht/CReadFile.h index 497c58c1..a768a3ee 100644 --- a/source/Irrlicht/CReadFile.h +++ b/source/Irrlicht/CReadFile.h @@ -22,8 +22,7 @@ namespace io { public: - CReadFile(const wchar_t* fileName); - CReadFile(const c8* fileName); + CReadFile(const core::string& fileName); virtual ~CReadFile(); @@ -46,7 +45,7 @@ namespace io virtual long getPos() const; //! returns name of file - virtual const c8* getFileName() const; + virtual const core::string& getFileName() const; private: @@ -55,7 +54,7 @@ namespace io FILE* File; long FileSize; - core::stringc Filename; + core::string Filename; }; } // end namespace io diff --git a/source/Irrlicht/CSTLMeshFileLoader.cpp b/source/Irrlicht/CSTLMeshFileLoader.cpp index 8779dbb5..b60353bd 100644 --- a/source/Irrlicht/CSTLMeshFileLoader.cpp +++ b/source/Irrlicht/CSTLMeshFileLoader.cpp @@ -23,9 +23,9 @@ namespace scene //! returns true if the file maybe is able to be loaded by this class //! based on the file extension (e.g. ".bsp") -bool CSTLMeshFileLoader::isALoadableFileExtension(const c8* filename) const +bool CSTLMeshFileLoader::isALoadableFileExtension(const core::string& filename) const { - return strstr(filename, ".stl")!=0; + return core::hasFileExtension ( filename, "stl" ); } diff --git a/source/Irrlicht/CSTLMeshFileLoader.h b/source/Irrlicht/CSTLMeshFileLoader.h index 3210f294..318efaf8 100644 --- a/source/Irrlicht/CSTLMeshFileLoader.h +++ b/source/Irrlicht/CSTLMeshFileLoader.h @@ -22,7 +22,7 @@ public: //! returns true if the file maybe is able to be loaded by this class //! based on the file extension (i.e. ".stl") - virtual bool isALoadableFileExtension(const c8* fileName) const; + virtual bool isALoadableFileExtension(const core::string& filename) const; //! creates/loads an animated mesh from the file. //! \return Pointer to the created mesh. Returns 0 if loading failed. diff --git a/source/Irrlicht/CSceneCollisionManager.cpp b/source/Irrlicht/CSceneCollisionManager.cpp index 063c2d2d..3b6d90bc 100644 --- a/source/Irrlicht/CSceneCollisionManager.cpp +++ b/source/Irrlicht/CSceneCollisionManager.cpp @@ -317,9 +317,6 @@ core::vector3df CSceneCollisionManager::getCollisionResultPosition( f32 slidingSpeed, const core::vector3df& gravity) { - if (!selector || radius.X == 0.0f || radius.Y == 0.0f || radius.Z == 0.0f) - return position; - return collideEllipsoidWithWorld(selector, position, radius, direction, slidingSpeed, gravity, triout, hitPosition, outFalling, outNode); } @@ -397,7 +394,7 @@ bool CSceneCollisionManager::testTriangleIntersection(SCollisionData* colData, (colData->basePoint - trianglePlane.Normal) + (colData->velocity * t0); - if (triangle.isPointInsideFast(planeIntersectionPoint)) + if (triangle.isPointInside(planeIntersectionPoint)) { foundCollision = true; t = t0; diff --git a/source/Irrlicht/CSceneManager.cpp b/source/Irrlicht/CSceneManager.cpp index 50483e75..987fd992 100644 --- a/source/Irrlicht/CSceneManager.cpp +++ b/source/Irrlicht/CSceneManager.cpp @@ -14,7 +14,6 @@ #include "IGUIEnvironment.h" #include "IMaterialRenderer.h" #include "IReadFile.h" -#include "ILightManager.h" #include "os.h" @@ -260,6 +259,7 @@ CSceneManager::CSceneManager(video::IVideoDriver* driver, io::IFileSystem* fs, ISceneNodeAnimatorFactory* animatorFactory = new CDefaultSceneNodeAnimatorFactory(this, CursorControl); registerSceneNodeAnimatorFactory(animatorFactory); animatorFactory->drop(); + } @@ -299,11 +299,18 @@ CSceneManager::~CSceneManager() for (i=0; idrop(); + //! force to remove hardwareTextures from the driver + //! because Scenes may hold internally data bounded to sceneNodes + //! which may be destroyed twice + if (Driver) + Driver->removeAllHardwareBuffers (); + if(LightManager) LightManager->drop(); // remove all nodes and animators before dropping the driver // as render targets may be destroyed twice + removeAll(); removeAnimators(); @@ -313,7 +320,7 @@ CSceneManager::~CSceneManager() //! gets an animateable mesh. loads it if needed. returned pointer must not be dropped. -IAnimatedMesh* CSceneManager::getMesh(const c8* filename) +IAnimatedMesh* CSceneManager::getMesh(const core::string& filename) { IAnimatedMesh* msh = MeshCache->getMeshByFilename(filename); if (msh) @@ -322,16 +329,14 @@ IAnimatedMesh* CSceneManager::getMesh(const c8* filename) io::IReadFile* file = FileSystem->createAndOpenFile(filename); if (!file) { - os::Printer::log("Could not load mesh, because file could not be opened.", filename, ELL_ERROR); + os::Printer::log("Could not load mesh, because file could not be opened: ", filename, ELL_ERROR); return 0; } - core::stringc name = filename; - name.make_lower(); s32 count = MeshLoaderList.size(); for (s32 i=count-1; i>=0; --i) { - if (MeshLoaderList[i]->isALoadableFileExtension(name.c_str())) + if (MeshLoaderList[i]->isALoadableFileExtension(filename)) { // reset file to avoid side effects of previous calls to createMesh file->seek(0); @@ -362,7 +367,7 @@ IAnimatedMesh* CSceneManager::getMesh(io::IReadFile* file) if (!file) return 0; - core::stringc name = file->getFileName(); + core::string name = file->getFileName(); IAnimatedMesh* msh = MeshCache->getMeshByFilename(file->getFileName()); if (msh) return msh; @@ -371,7 +376,7 @@ IAnimatedMesh* CSceneManager::getMesh(io::IReadFile* file) s32 count = MeshLoaderList.size(); for (s32 i=count-1; i>=0; --i) { - if (MeshLoaderList[i]->isALoadableFileExtension(name.c_str())) + if (MeshLoaderList[i]->isALoadableFileExtension(name)) { // reset file to avoid side effects of previous calls to createMesh file->seek(0); @@ -454,9 +459,9 @@ IBillboardTextSceneNode* CSceneManager::addBillboardTextSceneNode(gui::IGUIFont* //! Adds a scene node, which can render a quake3 shader -ISceneNode* CSceneManager::addQuake3SceneNode(IMeshBuffer* meshBuffer, - const quake3::SShader * shader, - ISceneNode* parent, s32 id) +IMeshSceneNode* CSceneManager::addQuake3SceneNode(IMeshBuffer* meshBuffer, + const quake3::IShader * shader, + ISceneNode* parent, s32 id ) { #ifdef _IRR_COMPILE_WITH_BSP_LOADER_ if ( 0 == shader ) @@ -465,7 +470,9 @@ ISceneNode* CSceneManager::addQuake3SceneNode(IMeshBuffer* meshBuffer, if (!parent) parent = this; - CQuake3ShaderSceneNode* node = new CQuake3ShaderSceneNode( parent, this, id, FileSystem, meshBuffer, shader ); + CQuake3ShaderSceneNode* node = new CQuake3ShaderSceneNode( parent, + this, id, FileSystem, + meshBuffer, shader ); node->drop(); return node; @@ -723,7 +730,6 @@ IBillboardSceneNode* CSceneManager::addBillboardSceneNode(ISceneNode* parent, } - //! Adds a skybox scene node. A skybox is a big cube with 6 textures on it and //! is drawn around the camera position. ISceneNode* CSceneManager::addSkyBoxSceneNode(video::ITexture* top, video::ITexture* bottom, @@ -744,14 +750,14 @@ ISceneNode* CSceneManager::addSkyBoxSceneNode(video::ITexture* top, video::IText //! Adds a skydome scene node. A skydome is a large (half-) sphere with a //! panoramic texture on it and is drawn around the camera position. ISceneNode* CSceneManager::addSkyDomeSceneNode(video::ITexture* texture, - u32 horiRes, u32 vertRes, f64 texturePercentage, - f64 spherePercentage, ISceneNode* parent, s32 id) + u32 horiRes, u32 vertRes, f32 texturePercentage,f32 spherePercentage, f32 radius, + ISceneNode* parent, s32 id) { if (!parent) parent = this; ISceneNode* node = new CSkyDomeSceneNode(texture, horiRes, vertRes, - texturePercentage, spherePercentage, parent, this, id); + texturePercentage, spherePercentage, radius, parent, this, id); node->drop(); return node; @@ -777,7 +783,7 @@ IParticleSystemSceneNode* CSceneManager::addParticleSystemSceneNode( //! Adds a terrain scene node to the scene graph. ITerrainSceneNode* CSceneManager::addTerrainSceneNode( - const char* heightMapFileName, + const core::string& heightMapFileName, ISceneNode* parent, s32 id, const core::vector3df& position, const core::vector3df& rotation, @@ -877,16 +883,13 @@ IDummyTransformationSceneNode* CSceneManager::addDummyTransformationSceneNode( //! specify a name for the mesh, because the mesh is added to the mesh pool, //! and can be retrieved again using ISceneManager::getMesh with the name as //! parameter. -IAnimatedMesh* CSceneManager::addHillPlaneMesh(const c8* name, +IAnimatedMesh* CSceneManager::addHillPlaneMesh(const core::string& name, const core::dimension2d& tileSize, const core::dimension2d& tileCount, video::SMaterial* material, f32 hillHeight, const core::dimension2d& countHills, const core::dimension2d& textureRepeatCount) { - if (!name) - return 0; - if (MeshCache->isMeshLoaded(name)) return MeshCache->getMeshByFilename(name); @@ -915,15 +918,12 @@ IAnimatedMesh* CSceneManager::addHillPlaneMesh(const c8* name, //! Adds a terrain mesh to the mesh pool. -IAnimatedMesh* CSceneManager::addTerrainMesh(const c8* name, +IAnimatedMesh* CSceneManager::addTerrainMesh(const core::string& name, video::IImage* texture, video::IImage* heightmap, const core::dimension2d& stretchSize, f32 maxHeight, const core::dimension2d& defaultVertexBlockSize) { - if (!name) - return 0; - if (MeshCache->isMeshLoaded(name)) return MeshCache->getMeshByFilename(name); @@ -951,14 +951,11 @@ IAnimatedMesh* CSceneManager::addTerrainMesh(const c8* name, } //! Adds an arrow mesh to the mesh pool. -IAnimatedMesh* CSceneManager::addArrowMesh(const c8* name, +IAnimatedMesh* CSceneManager::addArrowMesh(const core::string& name, video::SColor vtxColor0, video::SColor vtxColor1, u32 tesselationCylinder, u32 tesselationCone, f32 height, f32 cylinderHeight, f32 width0,f32 width1) { - if (!name) - return 0; - if (MeshCache->isMeshLoaded(name)) return MeshCache->getMeshByFilename(name); @@ -988,7 +985,7 @@ IAnimatedMesh* CSceneManager::addArrowMesh(const c8* name, //! Adds a static sphere mesh to the mesh pool. -IAnimatedMesh* CSceneManager::addSphereMesh(const c8* name, +IAnimatedMesh* CSceneManager::addSphereMesh(const c16* name, f32 radius, u32 polyCountX, u32 polyCountY) { if (!name) @@ -1190,6 +1187,13 @@ u32 CSceneManager::registerNodeForRendering(ISceneNode* node, E_SCENE_NODE_RENDE taken = 1; } break; + case ESNRP_TRANSPARENT_EFFECT: + if (!isCulled(node)) + { + TransparentEffectNodeList.push_back(TransparentNodeEntry(node, camWorldPos)); + taken = 1; + } + break; case ESNRP_AUTOMATIC: if (!isCulled(node)) { @@ -1254,7 +1258,9 @@ void CSceneManager::drawAll() // reset attributes Parameters.setAttribute ( "culled", 0 ); Parameters.setAttribute ( "calls", 0 ); - Parameters.setAttribute ( "drawn", 0 ); + Parameters.setAttribute ( "drawn_solid", 0 ); + Parameters.setAttribute ( "drawn_transparent", 0 ); + Parameters.setAttribute ( "drawn_transparent_effect", 0 ); // reset all transforms video::IVideoDriver* driver = getVideoDriver(); @@ -1403,8 +1409,7 @@ void CSceneManager::drawAll() SolidNodeList[i].Node->render(); } - Parameters.setAttribute ( "drawn", (s32) SolidNodeList.size() ); - + Parameters.setAttribute ( "drawn_solid", (s32) SolidNodeList.size() ); SolidNodeList.set_used(0); if(LightManager) @@ -1445,8 +1450,8 @@ void CSceneManager::drawAll() // render transparent objects. { CurrentRendertime = ESNRP_TRANSPARENT; - TransparentNodeList.sort(); // sort by distance from camera + TransparentNodeList.sort(); // sort by distance from camera if(LightManager) { LightManager->OnRenderPassPreRender(CurrentRendertime); @@ -1465,12 +1470,41 @@ void CSceneManager::drawAll() TransparentNodeList[i].Node->render(); } + Parameters.setAttribute ( "drawn_transparent", (s32) TransparentNodeList.size() ); TransparentNodeList.set_used(0); if(LightManager) LightManager->OnRenderPassPostRender(CurrentRendertime); } + // render transparent effect objects. + { + CurrentRendertime = ESNRP_TRANSPARENT_EFFECT; + + TransparentEffectNodeList.sort(); // sort by distance from camera + + if(LightManager) + { + LightManager->OnRenderPassPreRender(CurrentRendertime); + + for (i=0; iOnNodePreRender(node); + node->render(); + LightManager->OnNodePostRender(node); + } + } + else + { + for (i=0; irender(); + } + + Parameters.setAttribute ( "drawn_transparent_effect", (s32) TransparentEffectNodeList.size() ); + TransparentEffectNodeList.set_used(0); + } + if(LightManager) LightManager->OnPostRender(); @@ -1624,7 +1658,7 @@ IMeshManipulator* CSceneManager::getMeshManipulator() //! Creates a simple ITriangleSelector, based on a mesh. ITriangleSelector* CSceneManager::createTriangleSelector(IMesh* mesh, ISceneNode* node) { - if (!mesh || !node) + if (!mesh) return 0; return new CTriangleSelector(mesh, node); @@ -1646,7 +1680,7 @@ ITriangleSelector* CSceneManager::createOctTreeTriangleSelector(IMesh* mesh, ISceneNode* node, s32 minimalPolysPerNode) { - if (!mesh || !node) + if (!mesh) return 0; return new COctTreeTriangleSelector(mesh, node, minimalPolysPerNode); @@ -1922,7 +1956,7 @@ ISceneNodeAnimatorFactory* CSceneManager::getSceneNodeAnimatorFactory(u32 index) //! Saves the current scene into a file. //! \param filename: Name of the file . -bool CSceneManager::saveScene(const c8* filename, ISceneUserDataSerializer* userDataSerializer) +bool CSceneManager::saveScene(const core::string& filename, ISceneUserDataSerializer* userDataSerializer) { bool ret = false; io::IWriteFile* file = FileSystem->createAndWriteFile(filename); @@ -1962,7 +1996,7 @@ bool CSceneManager::saveScene(io::IWriteFile* file, ISceneUserDataSerializer* us //! Loads a scene. Note that the current scene is not cleared before. //! \param filename: Name of the file . -bool CSceneManager::loadScene(const c8* filename, ISceneUserDataSerializer* userDataSerializer) +bool CSceneManager::loadScene(const core::string& filename, ISceneUserDataSerializer* userDataSerializer) { bool ret = false; io::IReadFile* read = FileSystem->createAndOpenFile(filename); diff --git a/source/Irrlicht/CSceneManager.h b/source/Irrlicht/CSceneManager.h index 04256e54..b9e09986 100644 --- a/source/Irrlicht/CSceneManager.h +++ b/source/Irrlicht/CSceneManager.h @@ -12,6 +12,7 @@ #include "irrArray.h" #include "IMeshLoader.h" #include "CAttributes.h" +#include "ILightManager.h" namespace irr { @@ -40,7 +41,7 @@ namespace scene virtual ~CSceneManager(); //! gets an animateable mesh. loads it if needed. returned pointer must not be dropped. - virtual IAnimatedMesh* getMesh(const c8* filename); + virtual IAnimatedMesh* getMesh(const core::string& filename); //! gets an animateable mesh. loads it if needed. returned pointer must not be dropped. virtual IAnimatedMesh* getMesh(io::IReadFile* file); @@ -168,7 +169,7 @@ namespace scene //! panoramic texture on it and is drawn around the camera position. virtual ISceneNode* addSkyDomeSceneNode(video::ITexture* texture, u32 horiRes=16, u32 vertRes=8, - f64 texturePercentage=0.9, f64 spherePercentage=2.0, + f32 texturePercentage=0.9, f32 spherePercentage=2.0,f32 radius = 1000.f, ISceneNode* parent=0, s32 id=-1); //! Adds a text scene node, which is able to display @@ -186,7 +187,7 @@ namespace scene video::SColor colorTop = 0xFFFFFFFF, video::SColor colorBottom = 0xFFFFFFFF); //! Adds a scene node, which can render a quake3 shader - virtual ISceneNode* addQuake3SceneNode(IMeshBuffer* meshBuffer, const quake3::SShader * shader, + virtual IMeshSceneNode* addQuake3SceneNode(IMeshBuffer* meshBuffer, const quake3::IShader * shader, ISceneNode* parent=0, s32 id=-1 ); @@ -198,26 +199,26 @@ namespace scene //! for the mesh because the mesh is added to the mesh pool and //! can be retrieved back using ISceneManager::getMesh with the //! name as parameter. - virtual IAnimatedMesh* addHillPlaneMesh(const c8* name, + virtual IAnimatedMesh* addHillPlaneMesh(const core::string& name, const core::dimension2d& tileSize, const core::dimension2d& tileCount, video::SMaterial* material = 0, f32 hillHeight = 0.0f, const core::dimension2d& countHills = core::dimension2d(1.0f, 1.0f), const core::dimension2d& textureRepeatCount = core::dimension2d(1.0f, 1.0f)); //! Adds a terrain mesh to the mesh pool. - virtual IAnimatedMesh* addTerrainMesh(const c8* meshname, video::IImage* texture, video::IImage* heightmap, + virtual IAnimatedMesh* addTerrainMesh(const core::string& meshname, video::IImage* texture, video::IImage* heightmap, const core::dimension2d& stretchSize, f32 maxHeight, const core::dimension2d& defaultVertexBlockSize); //! Add a arrow mesh to the mesh pool - virtual IAnimatedMesh* addArrowMesh(const c8* name, + virtual IAnimatedMesh* addArrowMesh(const core::string& name, video::SColor vtxColor0, video::SColor vtxColor1, u32 tesselationCylinder, u32 tesselationCone, f32 height, f32 cylinderHeight, f32 width0, f32 width1); //! Adds a static sphere mesh to the mesh pool. - IAnimatedMesh* addSphereMesh(const c8* name, + IAnimatedMesh* addSphereMesh(const c16* name, f32 radius, u32 polyCountX, u32 polyCountY); //! Adds a particle system scene node. @@ -229,7 +230,7 @@ namespace scene //! Adds a terrain scene node to the scene graph. virtual ITerrainSceneNode* addTerrainSceneNode( - const c8* heightMapFileName, + const core::string& heightMapFileName, ISceneNode* parent=0, s32 id=-1, const core::vector3df& position = core::vector3df(0.0f,0.0f,0.0f), const core::vector3df& rotation = core::vector3df(0.0f,0.0f,0.0f), @@ -429,14 +430,14 @@ namespace scene //! Saves the current scene into a file. //! \param filename: Name of the file . - virtual bool saveScene(const c8* filename, ISceneUserDataSerializer* userDataSerializer=0); + virtual bool saveScene(const core::string& filename, ISceneUserDataSerializer* userDataSerializer=0); //! Saves the current scene into a file. virtual bool saveScene(io::IWriteFile* file, ISceneUserDataSerializer* userDataSerializer=0); //! Loads a scene. Note that the current scene is not cleared before. //! \param filename: Name of the file . - virtual bool loadScene(const c8* filename, ISceneUserDataSerializer* userDataSerializer=0); + virtual bool loadScene(const core::string& filename, ISceneUserDataSerializer* userDataSerializer=0); //! Loads a scene. Note that the current scene is not cleared before. virtual bool loadScene(io::IReadFile* file, ISceneUserDataSerializer* userDataSerializer=0); @@ -504,29 +505,29 @@ namespace scene void* TextureValue; }; - + //! sort on distance (center) to camera struct TransparentNodeEntry { TransparentNodeEntry(ISceneNode* n, const core::vector3df& camera) : Node(n) { - Distance = (f32)(Node->getAbsoluteTransformation().getTranslation().getDistanceFromSQ(camera)); + Distance = Node->getAbsoluteTransformation().getTranslation().getDistanceFromSQ(camera); } bool operator < (const TransparentNodeEntry& other) const { - return (Distance > other.Distance); + return Distance > other.Distance; } ISceneNode* Node; private: - f32 Distance; + f64 Distance; }; //! sort on distance (sphere) to camera struct DistanceNodeEntry { - DistanceNodeEntry(ISceneNode* n, f64 d) + DistanceNodeEntry(ISceneNode* n, f32 d) : Node(n), Distance(d) {} DistanceNodeEntry(ISceneNode* n, const core::vector3df& cameraPos) @@ -574,6 +575,7 @@ namespace scene core::array SkyBoxList; core::array SolidNodeList; core::array TransparentNodeList; + core::array TransparentEffectNodeList; core::array MeshLoaderList; core::array DeletionList; diff --git a/source/Irrlicht/CSceneNodeAnimatorCollisionResponse.cpp b/source/Irrlicht/CSceneNodeAnimatorCollisionResponse.cpp index b1fab102..3397daf4 100644 --- a/source/Irrlicht/CSceneNodeAnimatorCollisionResponse.cpp +++ b/source/Irrlicht/CSceneNodeAnimatorCollisionResponse.cpp @@ -25,7 +25,8 @@ CSceneNodeAnimatorCollisionResponse::CSceneNodeAnimatorCollisionResponse( World(world), Object(object), SceneManager(scenemanager), LastTime(0), SlidingSpeed(slidingSpeed), Falling(false), IsCamera(false), AnimateCameraTarget(true), CollisionOccurred(false), - CollisionCallback(0) + CollisionCallback(0), + FirstUpdate ( true ) { #ifdef _DEBUG setDebugName("CSceneNodeAnimatorCollisionResponse"); @@ -65,6 +66,7 @@ void CSceneNodeAnimatorCollisionResponse::setEllipsoidRadius( const core::vector3df& radius) { Radius = radius; + FirstUpdate = true; } @@ -80,6 +82,7 @@ core::vector3df CSceneNodeAnimatorCollisionResponse::getEllipsoidRadius() const void CSceneNodeAnimatorCollisionResponse::setGravity(const core::vector3df& gravity) { Gravity = gravity; + FirstUpdate = true; } @@ -116,10 +119,6 @@ core::vector3df CSceneNodeAnimatorCollisionResponse::getEllipsoidTranslation() c //! the scene node may collide. void CSceneNodeAnimatorCollisionResponse::setWorld(ITriangleSelector* newWorld) { - Falling = false; - - LastTime = os::Timer::getTime(); - if (World) World->drop(); @@ -127,6 +126,8 @@ void CSceneNodeAnimatorCollisionResponse::setWorld(ITriangleSelector* newWorld) if (World) World->grab(); + FirstUpdate = true; + } @@ -148,6 +149,23 @@ void CSceneNodeAnimatorCollisionResponse::animateNode(ISceneNode* node, u32 time if(!Object || !World) return; + // trigger reset + if ( timeMs == 0 ) + { + FirstUpdate = true; + timeMs = LastTime; + } + + if ( FirstUpdate ) + { + LastPosition = Object->getPosition(); + Falling = false; + LastTime = timeMs; + FallingVelocity.set ( 0, 0, 0 ); + + FirstUpdate = false; + } + u32 diff = timeMs - LastTime; LastTime = timeMs; @@ -163,9 +181,7 @@ void CSceneNodeAnimatorCollisionResponse::animateNode(ISceneNode* node, u32 time core::vector3df force = vel + FallingVelocity; - const core::vector3df nullVector ( 0.f, 0.f, 0.f ); - - if ( force != nullVector ) + if ( AnimateCameraTarget ) { // TODO: divide SlidingSpeed by frame time @@ -267,6 +283,19 @@ void CSceneNodeAnimatorCollisionResponse::setCollisionCallback(ICollisionCallbac CollisionCallback->grab(); } +//! Should the Target react on collision ( default = true ) +void CSceneNodeAnimatorCollisionResponse::setAnimateTarget ( bool enable ) +{ + AnimateCameraTarget = enable; + FirstUpdate = true; +} + +//! Should the Target react on collision ( default = true ) +bool CSceneNodeAnimatorCollisionResponse::getAnimateTarget () const +{ + return AnimateCameraTarget; +} + } // end namespace scene } // end namespace irr diff --git a/source/Irrlicht/CSceneNodeAnimatorCollisionResponse.h b/source/Irrlicht/CSceneNodeAnimatorCollisionResponse.h index d425d226..df951c94 100644 --- a/source/Irrlicht/CSceneNodeAnimatorCollisionResponse.h +++ b/source/Irrlicht/CSceneNodeAnimatorCollisionResponse.h @@ -54,6 +54,10 @@ namespace scene //! 'Jump' the animator, by adding a jump speed opposite to its gravity virtual void jump(f32 jumpSpeed); + //! Should the Target react on collision ( default = true ) + virtual void setAnimateTarget ( bool enable ); + virtual bool getAnimateTarget () const; + //! Returns current vector of gravity. virtual core::vector3df getGravity() const; @@ -135,6 +139,7 @@ namespace scene bool Falling; bool IsCamera; bool AnimateCameraTarget; + bool FirstUpdate; bool CollisionOccurred; core::vector3df CollisionPoint; diff --git a/source/Irrlicht/CSkyDomeSceneNode.cpp b/source/Irrlicht/CSkyDomeSceneNode.cpp index 570169cf..2393b7de 100644 --- a/source/Irrlicht/CSkyDomeSceneNode.cpp +++ b/source/Irrlicht/CSkyDomeSceneNode.cpp @@ -7,6 +7,7 @@ #include "IVideoDriver.h" #include "ISceneManager.h" #include "ICameraSceneNode.h" +#include "IAnimatedMesh.h" #include "os.h" namespace irr @@ -30,21 +31,21 @@ namespace scene parameters stretches the image to fit the chosen "sphere-size". */ CSkyDomeSceneNode::CSkyDomeSceneNode(video::ITexture* sky, u32 horiRes, u32 vertRes, - f64 texturePercentage, f64 spherePercentage, ISceneNode* parent, ISceneManager* mgr, s32 id) + f32 texturePercentage, f32 spherePercentage, f32 radius, + ISceneNode* parent, ISceneManager* mgr, s32 id) : ISceneNode(parent, mgr, id), Buffer(0) { #ifdef _DEBUG setDebugName("CSkyDomeSceneNode"); #endif - f64 radius = 1000.0; /* Adjust this to get more or less perspective distorsion. */ - f64 azimuth, azimuth_step; - f64 elevation, elevation_step; + f32 azimuth, azimuth_step; + f32 elevation, elevation_step; u32 k; video::S3DVertex vtx; - AutomaticCullingState = scene::EAC_OFF; + setAutomaticCulling ( scene::EAC_OFF ); Buffer = new SMeshBuffer(); Buffer->Material.Lighting = false; @@ -54,34 +55,34 @@ CSkyDomeSceneNode::CSkyDomeSceneNode(video::ITexture* sky, u32 horiRes, u32 vert Buffer->BoundingBox.MaxEdge.set(0,0,0); Buffer->BoundingBox.MinEdge.set(0,0,0); - azimuth_step = 2.*core::PI64/(f64)horiRes; + azimuth_step = (core::PI * 2.f ) /horiRes; if (spherePercentage<0.) spherePercentage=-spherePercentage; if (spherePercentage>2.) spherePercentage=2.; - elevation_step = spherePercentage*core::PI64/2./(f64)vertRes; + elevation_step = spherePercentage*core::HALF_PI/ (f32) vertRes; Buffer->Vertices.reallocate((horiRes+1)*(vertRes+1)); Buffer->Indices.reallocate(3*(2*vertRes-1)*horiRes); vtx.Color.set(255,255,255,255); - vtx.Normal.set(0.0f,0.0f,0.0f); + vtx.Normal.set(0.0f,-1.f,0.0f); - const f32 tcV = (f32)texturePercentage/(f32)vertRes; + const f32 tcV = texturePercentage / vertRes; for (k = 0, azimuth = 0; k <= horiRes; ++k) { - elevation = core::PI64/2.; - const f32 tcU = (f32)k/(f32)horiRes; - const f64 sinA = sin(azimuth); - const f64 cosA = cos(azimuth); + elevation = core::HALF_PI; + const f32 tcU = (f32) k / (f32) horiRes; + const f32 sinA = sinf(azimuth); + const f32 cosA = cosf(azimuth); for (u32 j = 0; j <= vertRes; ++j) { - const f64 cosEr = radius*cos(elevation); - vtx.Pos.set((f32) (cosEr*sinA), - (f32) (radius*sin(elevation)+50.0f), - (f32) (cosEr*cosA)); + const f32 cosEr = radius*cosf(elevation); + vtx.Pos.set( cosEr*sinA,radius*sinf(elevation)+0.0f,cosEr*cosA); + vtx.TCoords.set(tcU, j*tcV); - vtx.TCoords.set(tcU, (f32)j*tcV); + vtx.Normal = -vtx.Pos; + vtx.Normal.normalize(); Buffer->Vertices.push_back(vtx); elevation -= elevation_step; @@ -135,6 +136,60 @@ void CSkyDomeSceneNode::render() driver->setMaterial(Buffer->Material); driver->drawMeshBuffer(Buffer); } + + // for debug purposes only: + if ( DebugDataVisible ) + { + video::SMaterial m; + m.Lighting = false; + driver->setMaterial(m); + + if ( DebugDataVisible & scene::EDS_NORMALS ) + { + IAnimatedMesh * arrow = SceneManager->addArrowMesh ( + "__debugnormal2", 0xFFECEC00, + 0xFF999900, 4, 8, 1.f * 40.f, 0.6f * 40.f, 0.05f * 40.f, 0.3f * 40.f); + if ( 0 == arrow ) + { + arrow = SceneManager->getMesh ( "__debugnormal2" ); + } + IMesh *mesh = arrow->getMesh(0); + + // find a good scaling factor + core::matrix4 m2; + + // draw normals + const scene::IMeshBuffer* mb = Buffer; + const u32 vSize = video::getVertexPitchFromType(mb->getVertexType()); + const video::S3DVertex* v = ( const video::S3DVertex*)mb->getVertices(); + for ( u32 i=0; i != mb->getVertexCount(); ++i ) + { + // align to v->Normal + core::quaternion quatRot(v->Normal.X, 0.f, -v->Normal.X, 1+v->Normal.Y); + quatRot.normalize(); + quatRot.getMatrix(m2, v->Pos); + + m2 = AbsoluteTransformation * m2; + + driver->setTransform(video::ETS_WORLD, m2); + for (u32 a = 0; a != mesh->getMeshBufferCount(); ++a) + driver->drawMeshBuffer(mesh->getMeshBuffer(a)); + + v = (const video::S3DVertex*) ( (u8*) v + vSize ); + } + driver->setTransform(video::ETS_WORLD, AbsoluteTransformation); + } + + // show mesh + if ( DebugDataVisible & scene::EDS_MESH_WIRE_OVERLAY ) + { + m.Wireframe = true; + driver->setMaterial(m); + + driver->drawMeshBuffer( Buffer ); + } + } + } @@ -148,7 +203,9 @@ const core::aabbox3d& CSkyDomeSceneNode::getBoundingBox() const void CSkyDomeSceneNode::OnRegisterSceneNode() { if (IsVisible) - SceneManager->registerNodeForRendering(this, ESNRP_SKY_BOX); + { + SceneManager->registerNodeForRendering(this, ESNRP_SKY_BOX ); + } ISceneNode::OnRegisterSceneNode(); } diff --git a/source/Irrlicht/CSkyDomeSceneNode.h b/source/Irrlicht/CSkyDomeSceneNode.h index 77dc0ac7..abbe6835 100644 --- a/source/Irrlicht/CSkyDomeSceneNode.h +++ b/source/Irrlicht/CSkyDomeSceneNode.h @@ -18,7 +18,7 @@ class CSkyDomeSceneNode : public ISceneNode { public: CSkyDomeSceneNode(video::ITexture* texture, u32 horiRes, u32 vertRes, - f64 texturePercentage, f64 spherePercentage, + f32 texturePercentage, f32 spherePercentage, f32 radius, ISceneNode* root, ISceneManager* smgr, s32 id); virtual ~CSkyDomeSceneNode(); virtual void OnRegisterSceneNode(); diff --git a/source/Irrlicht/CSoftwareDriver.cpp b/source/Irrlicht/CSoftwareDriver.cpp index d6b986b9..9a63f3b9 100644 --- a/source/Irrlicht/CSoftwareDriver.cpp +++ b/source/Irrlicht/CSoftwareDriver.cpp @@ -890,11 +890,9 @@ const core::matrix4& CSoftwareDriver::getTransform(E_TRANSFORMATION_STATE state) //! Creates a render target texture. -ITexture* CSoftwareDriver::addRenderTargetTexture(const core::dimension2d& size, const c8* name) +ITexture* CSoftwareDriver::addRenderTargetTexture(const core::dimension2d& size, const core::string& name) { CImage* img = new CImage(video::ECF_A1R5G5B5, size); - if (!name) - name="rt"; ITexture* tex = new CSoftwareTexture(img, name, true); img->drop(); addTexture(tex); diff --git a/source/Irrlicht/CSoftwareDriver.h b/source/Irrlicht/CSoftwareDriver.h index c9e4c562..e306d793 100644 --- a/source/Irrlicht/CSoftwareDriver.h +++ b/source/Irrlicht/CSoftwareDriver.h @@ -101,7 +101,7 @@ namespace video //! Creates a render target texture. virtual ITexture* addRenderTargetTexture(const core::dimension2d& size, - const c8* name); + const core::string& name); //! Clears the ZBuffer. virtual void clearZBuffer(); diff --git a/source/Irrlicht/CSoftwareDriver2.cpp b/source/Irrlicht/CSoftwareDriver2.cpp index e336a910..fc91f780 100644 --- a/source/Irrlicht/CSoftwareDriver2.cpp +++ b/source/Irrlicht/CSoftwareDriver2.cpp @@ -1,13 +1,12 @@ -// Copyright (C) 2002-2009 Nikolaus Gebhardt / Thomas Alten +// Copyright (C) 2002-2008 Nikolaus Gebhardt / Thomas Alten // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h -#include "CSoftwareDriver2.h" - #include "IrrCompileConfig.h" #ifdef _IRR_COMPILE_WITH_BURNINGSVIDEO_ +#include "CSoftwareDriver2.h" #include "SoftwareDriver2_helper.h" #include "CSoftwareTexture2.h" #include "CSoftware2MaterialRenderer.h" @@ -57,7 +56,7 @@ CBurningVideoDriver::CBurningVideoDriver(const core::dimension2d& windowSiz //BurningShader[ETR_TEXTURE_FLAT] = createTriangleRendererTextureFlat2(DepthBuffer); //BurningShader[ETR_TEXTURE_FLAT_WIRE] = createTriangleRendererTextureFlatWire2(DepthBuffer); BurningShader[ETR_TEXTURE_GOURAUD] = createTriangleRendererTextureGouraud2(DepthBuffer); - BurningShader[ETR_TEXTURE_GOURAUD_LIGHTMAP] = createTriangleRendererTextureLightMap2_M1(DepthBuffer); + BurningShader[ETR_TEXTURE_GOURAUD_LIGHTMAP_M1] = createTriangleRendererTextureLightMap2_M1(DepthBuffer); BurningShader[ETR_TEXTURE_GOURAUD_LIGHTMAP_M2] = createTriangleRendererTextureLightMap2_M2(DepthBuffer); BurningShader[ETR_TEXTURE_GOURAUD_LIGHTMAP_M4] = createTriangleRendererGTextureLightMap2_M4(DepthBuffer); BurningShader[ETR_TEXTURE_LIGHTMAP_M4] = createTriangleRendererTextureLightMap2_M4(DepthBuffer); @@ -195,7 +194,7 @@ void CBurningVideoDriver::setCurrentShader() case EMT_LIGHTMAP: case EMT_LIGHTMAP_LIGHTING: - shader = ETR_TEXTURE_GOURAUD_LIGHTMAP; + shader = ETR_TEXTURE_GOURAUD_LIGHTMAP_M1; break; case EMT_LIGHTMAP_M2: @@ -221,6 +220,10 @@ void CBurningVideoDriver::setCurrentShader() shader = ETR_TEXTURE_GOURAUD_DETAIL_MAP; break; + case EMT_REFLECTION_2_LAYER: + shader = ETR_INVALID; + break; + default: break; @@ -248,28 +251,26 @@ void CBurningVideoDriver::setCurrentShader() if ( CurrentShader ) { CurrentShader->setZCompareFunc ( Material.org.ZBuffer ); + CurrentShader->setRenderTarget(RenderTargetSurface, ViewPort); + CurrentShader->setMaterial ( Material ); + switch ( shader ) { case ETR_TEXTURE_GOURAUD_ALPHA: case ETR_TEXTURE_GOURAUD_ALPHA_NOZ: + case ETR_TEXTURE_BLEND: CurrentShader->setParam ( 0, Material.org.MaterialTypeParam ); break; - - case EMT_ONETEXTURE_BLEND: - { - E_BLEND_FACTOR srcFact,dstFact; - E_MODULATE_FUNC modulate; - unpack_texureBlendFunc ( srcFact, dstFact, modulate, Material.org.MaterialTypeParam ); - CurrentShader->setParam ( 0, Material.org.MaterialTypeParam ); - } - break; default: break; } - - CurrentShader->setRenderTarget(RenderTargetSurface, ViewPort); - CurrentShader->setMaterial ( Material ); } + + if ( shader != ETR_TEXTURE_BLEND ) + { + //CurrentShader = 0; + } + } @@ -306,50 +307,49 @@ bool CBurningVideoDriver::queryFeature(E_VIDEO_DRIVER_FEATURE feature) const //! sets transformation void CBurningVideoDriver::setTransform(E_TRANSFORMATION_STATE state, const core::matrix4& mat) { - Transformation[state].m = mat; - Transformation[state].isIdentity = mat.isIdentity(); + Transformation[state] = mat; + TransformationFlag[state] = mat.isIdentity(); switch ( state ) { case ETS_VIEW: - Transformation[ETS_VIEW_PROJECTION].m.setbyproduct_nocheck ( - Transformation[ETS_PROJECTION].m, - Transformation[ETS_VIEW].m + Transformation[ETS_VIEW_PROJECTION].setbyproduct_nocheck ( + Transformation[ETS_PROJECTION], + Transformation[ETS_VIEW] ); break; case ETS_WORLD: - if ( Transformation[state].isIdentity ) + if ( TransformationFlag[state] ) { Transformation[ETS_CURRENT] = Transformation[ETS_VIEW_PROJECTION]; } else { - Transformation[ETS_CURRENT].m.setbyproduct_nocheck ( - Transformation[ETS_VIEW_PROJECTION].m, - Transformation[ETS_WORLD].m + Transformation[ETS_CURRENT].setbyproduct_nocheck ( + Transformation[ETS_VIEW_PROJECTION], + Transformation[ETS_WORLD] ); } - Transformation[ETS_CURRENT].isIdentity = 0; + TransformationFlag[ETS_CURRENT] = 0; #ifdef SOFTWARE_DRIVER_2_LIGHTING if ( Material.org.Lighting ) { - if ( Transformation[state].isIdentity ) + if ( TransformationFlag[state] ) { Transformation[ETS_WORLD_VIEW] = Transformation[ETS_VIEW]; } else { - Transformation[ETS_WORLD_VIEW].m.setbyproduct_nocheck ( - Transformation[ETS_VIEW].m, - Transformation[ETS_WORLD].m + Transformation[ETS_WORLD_VIEW].setbyproduct_nocheck ( + Transformation[ETS_VIEW], + Transformation[ETS_WORLD] ); } - - core::matrix4 m2 ( Transformation[ETS_WORLD_VIEW].m ); + core::matrix4 m2 ( Transformation[ETS_WORLD_VIEW] ); m2.makeInverse (); - m2.getTransposed ( Transformation[ETS_WORLD_VIEW_INVERSE_TRANSPOSED].m ); + m2.getTransposed ( Transformation[ETS_WORLD_VIEW_INVERSE_TRANSPOSED] ); } #endif break; @@ -480,7 +480,7 @@ void CBurningVideoDriver::setViewPort(const core::rect& area) core::rect rendert(0,0,RenderTargetSize.Width,RenderTargetSize.Height); ViewPort.clipAgainst(rendert); - Transformation [ ETS_CLIPSCALE ].m.buildNDCToDCMatrix ( ViewPort, 1 ); + Transformation [ ETS_CLIPSCALE ].buildNDCToDCMatrix ( ViewPort, 1 ); if (CurrentShader) @@ -569,10 +569,22 @@ REALINLINE u32 CBurningVideoDriver::clipToFrustumTest ( const s4DVertex * v ) c REALINLINE u32 CBurningVideoDriver::clipToFrustumTest ( const s4DVertex * v ) const { u32 flag = 0; + + if ( v->Pos.z <= v->Pos.w ) flag |= 1; + if (-v->Pos.z <= v->Pos.w ) flag |= 2; + + if ( v->Pos.x <= v->Pos.w ) flag |= 4; + if (-v->Pos.x <= v->Pos.w ) flag |= 8; + + if ( v->Pos.y <= v->Pos.w ) flag |= 16; + if (-v->Pos.y <= v->Pos.w ) flag |= 32; + +/* for ( u32 i = 0; i!= 6; ++i ) { core::setbit_cond( flag, v->Pos.dotProduct ( NDCPlane[i] ) <= 0.f, 1 << i ); } +*/ return flag; } @@ -684,8 +696,8 @@ inline void CBurningVideoDriver::ndc_2_dc_and_project ( s4DVertex *dest,s4DVerte const f32 iw = core::reciprocal ( w ); // to device coordinates - dest[g].Pos.x = iw * ( source[g].Pos.x * Transformation [ ETS_CLIPSCALE ].m[ 0] + w * Transformation [ ETS_CLIPSCALE ].m[12] ); - dest[g].Pos.y = iw * ( source[g].Pos.y * Transformation [ ETS_CLIPSCALE ].m[ 5] + w * Transformation [ ETS_CLIPSCALE ].m[13] ); + dest[g].Pos.x = iw * ( source[g].Pos.x * Transformation [ ETS_CLIPSCALE ][ 0] + w * Transformation [ ETS_CLIPSCALE ][12] ); + dest[g].Pos.y = iw * ( source[g].Pos.y * Transformation [ ETS_CLIPSCALE ][ 5] + w * Transformation [ ETS_CLIPSCALE ][13] ); #ifndef SOFTWARE_DRIVER_2_USE_WBUFFER dest[g].Pos.z = iw * source[g].Pos.z; @@ -723,8 +735,9 @@ inline void CBurningVideoDriver::ndc_2_dc_and_project2 ( const s4DVertex **v, co const f32 iw = core::reciprocal ( w ); // to device coordinates - a[1].Pos.x = iw * ( a->Pos.x * Transformation [ ETS_CLIPSCALE ].m[ 0] + w * Transformation [ ETS_CLIPSCALE ].m[12] ); - a[1].Pos.y = iw * ( a->Pos.y * Transformation [ ETS_CLIPSCALE ].m[ 5] + w * Transformation [ ETS_CLIPSCALE ].m[13] ); + const f32 * p = Transformation [ ETS_CLIPSCALE ].pointer(); + a[1].Pos.x = iw * ( a->Pos.x * p[ 0] + w * p[12] ); + a[1].Pos.y = iw * ( a->Pos.y * p[ 5] + w * p[13] ); #ifndef SOFTWARE_DRIVER_2_USE_WBUFFER a[1].Pos.z = a->Pos.z * iw; @@ -874,7 +887,7 @@ void CBurningVideoDriver::VertexCache_fill(const u32 sourceIndex, dest = (s4DVertex *) ( (u8*) VertexCache.mem.data + ( destIndex << ( SIZEOF_SVERTEX_LOG2 + 1 ) ) ); // transform Model * World * Camera * Projection * NDCSpace matrix - Transformation [ ETS_CURRENT].m.transformVect ( &dest->Pos.x, ((S3DVertex*) source )->Pos ); + Transformation [ ETS_CURRENT].transformVect ( &dest->Pos.x, ((S3DVertex*) source )->Pos ); #ifdef SOFTWARE_DRIVER_2_USE_VERTEX_COLOR @@ -887,11 +900,11 @@ void CBurningVideoDriver::VertexCache_fill(const u32 sourceIndex, #endif // transfer texture coordinates - if ( Transformation [ ETS_TEXTURE_0 ].isIdentity ) + const core::vector2d *srcT = &((S3DVertex*) source )->TCoords; + + if ( TransformationFlag [ ETS_TEXTURE_0 ] && TransformationFlag [ ETS_TEXTURE_1 ] ) { - // only look on first transform - irr::memcpy32_small ( &dest->Tex[0], - &((S3DVertex*) source )->TCoords, + irr::memcpy32_small ( &dest->Tex[0],srcT, vSize[VertexCache.vType].TexSize * ( sizeof ( f32 ) * 2 ) ); } @@ -908,29 +921,30 @@ void CBurningVideoDriver::VertexCache_fill(const u32 sourceIndex, Uw Vw 0 0 */ - const core::vector2d *src = &((S3DVertex*) source )->TCoords; u32 t; + f32 tx1, ty1; for ( t = 0; t != vSize[VertexCache.vType].TexSize; ++t ) { - const core::matrix4& M = Transformation [ ETS_TEXTURE_0 + t ].m; - if ( Material.org.TextureLayer[t].TextureWrap==ETC_REPEAT ) + const core::matrix4& M = Transformation [ ETS_TEXTURE_0 + t ]; + + switch ( Material.org.TextureLayer[t].TextureWrap ) { - dest->Tex[t].x = M[0] * src[t].X + M[4] * src[t].Y + M[8]; - dest->Tex[t].y = M[1] * src[t].X + M[5] * src[t].Y + M[9]; - } - else - { - f32 tx1, ty1; + case ETC_REPEAT: + default: + dest->Tex[t].x = M[0] * srcT[t].X + M[4] * srcT[t].Y + M[8]; + dest->Tex[t].y = M[1] * srcT[t].X + M[5] * srcT[t].Y + M[9]; + break; + case ETC_CLAMP: + case ETC_CLAMP_TO_EDGE: + tx1 = M[0] * srcT[t].X + M[4] * srcT[t].Y + M[8]; + ty1 = M[1] * srcT[t].X + M[5] * srcT[t].Y + M[9]; - tx1 = M[0] * src[t].X + M[4] * src[t].Y + M[8]; - ty1 = M[1] * src[t].X + M[5] * src[t].Y + M[9]; - - dest->Tex[t].x = tx1 <= 0.f ? 0.f : tx1 >= 1.f ? 1.f : tx1; - dest->Tex[t].y = ty1 <= 0.f ? 0.f : ty1 >= 1.f ? 1.f : ty1; - - //dest->Tex[t].x = core::clamp ( M[0] * src[t].X + M[4] * src[t].Y + M[8], 0.f, 1.f ); - //dest->Tex[t].y = core::clamp ( M[1] * src[t].X + M[5] * src[t].Y + M[9], 0.f, 1.f ); + dest->Tex[t].x = tx1 <= 0.f ? 0.f : tx1 >= 1.f ? 1.f : tx1; + dest->Tex[t].y = ty1 <= 0.f ? 0.f : ty1 >= 1.f ? 1.f : ty1; + //dest->Tex[t].x = core::clamp ( M[0] * src[t].X + M[4] * src[t].Y + M[8], 0.f, 1.f ); + //dest->Tex[t].y = core::clamp ( M[1] * src[t].X + M[5] * src[t].Y + M[9], 0.f, 1.f ); + break; } } @@ -988,12 +1002,18 @@ REALINLINE void CBurningVideoDriver::VertexCache_get ( s4DVertex ** face ) u32 fillIndex = 0; u32 dIndex; u32 i; + u32 sourceIndex; while ( VertexCache.indicesIndex < VertexCache.indexCount && fillIndex < VERTEXCACHE_ELEMENT ) { - u32 sourceIndex = VertexCache.indices [ VertexCache.indicesIndex++ ]; + sourceIndex = VertexCache.iType == 1 ? + ((u16*)VertexCache.indices) [ VertexCache.indicesIndex ] : + ((u32*)VertexCache.indices) [ VertexCache.indicesIndex ]; + + + VertexCache.indicesIndex += 1; // if not exist, push back s32 exist = 0; @@ -1053,20 +1073,44 @@ REALINLINE void CBurningVideoDriver::VertexCache_get ( s4DVertex ** face ) const u32 i0 = core::if_c_a_else_0 ( VertexCache.pType != scene::EPT_TRIANGLE_FAN, VertexCache.indicesRun ); - face[0] = VertexCache_getVertex ( VertexCache.indices[ i0 ] ); - face[1] = VertexCache_getVertex ( VertexCache.indices[ VertexCache.indicesRun + 1] ); - face[2] = VertexCache_getVertex ( VertexCache.indices[ VertexCache.indicesRun + 2] ); + if ( VertexCache.iType == 1 ) + { + const u16 *p = (const u16 *) VertexCache.indices; + face[0] = VertexCache_getVertex ( p[ i0 ] ); + face[1] = VertexCache_getVertex ( p[ VertexCache.indicesRun + 1] ); + face[2] = VertexCache_getVertex ( p[ VertexCache.indicesRun + 2] ); + } + else + { + const u32 *p = (const u32 *) VertexCache.indices; + face[0] = VertexCache_getVertex ( p[ i0 ] ); + face[1] = VertexCache_getVertex ( p[ VertexCache.indicesRun + 1] ); + face[2] = VertexCache_getVertex ( p[ VertexCache.indicesRun + 2] ); + } VertexCache.indicesRun += VertexCache.primitivePitch; } +/*! +*/ REALINLINE void CBurningVideoDriver::VertexCache_get2 ( s4DVertex ** face ) { const u32 i0 = core::if_c_a_else_0 ( VertexCache.pType != scene::EPT_TRIANGLE_FAN, VertexCache.indicesRun ); - VertexCache_fill ( VertexCache.indices[ i0 ], 0 ); - VertexCache_fill ( VertexCache.indices[ VertexCache.indicesRun + 1], 1 ); - VertexCache_fill ( VertexCache.indices[ VertexCache.indicesRun + 2], 2 ); + if ( VertexCache.iType == 1 ) + { + const u16 *p = (const u16 *) VertexCache.indices; + VertexCache_fill ( p[ i0 ], 0 ); + VertexCache_fill ( p[ VertexCache.indicesRun + 1], 1 ); + VertexCache_fill ( p[ VertexCache.indicesRun + 2], 2 ); + } + else + { + const u32 *p = (const u32 *) VertexCache.indices; + VertexCache_fill ( p[ i0 ], 0 ); + VertexCache_fill ( p[ VertexCache.indicesRun + 1], 1 ); + VertexCache_fill ( p[ VertexCache.indicesRun + 2], 2 ); + } VertexCache.indicesRun += VertexCache.primitivePitch; @@ -1076,9 +1120,12 @@ REALINLINE void CBurningVideoDriver::VertexCache_get2 ( s4DVertex ** face ) } +/*! +*/ void CBurningVideoDriver::VertexCache_reset ( const void* vertices, u32 vertexCount, - const u16* indices, u32 primitiveCount, - E_VERTEX_TYPE vType,scene::E_PRIMITIVE_TYPE pType ) + const void* indices, u32 primitiveCount, + E_VERTEX_TYPE vType,scene::E_PRIMITIVE_TYPE pType, + E_INDEX_TYPE iType) { VertexCache.vertices = vertices; VertexCache.vertexCount = vertexCount; @@ -1089,6 +1136,7 @@ void CBurningVideoDriver::VertexCache_reset ( const void* vertices, u32 vertexCo VertexCache.vType = vType; VertexCache.pType = pType; + VertexCache.iType = iType == EIT_16BIT ? 1 : 2; switch ( VertexCache.pType ) { @@ -1111,39 +1159,16 @@ void CBurningVideoDriver::drawVertexPrimitiveList(const void* vertices, u32 vert const void* indexList, u32 primitiveCount, E_VERTEX_TYPE vType, scene::E_PRIMITIVE_TYPE pType, E_INDEX_TYPE iType) -{ - switch (iType) - { - case (EIT_16BIT): - { - drawVertexPrimitiveList16(vertices, vertexCount, (const u16*) indexList, primitiveCount, vType, pType); - break; - } - case (EIT_32BIT): - { - os::Printer::log("Software driver can not render 32bit buffers", ELL_ERROR); - break; - } - } - - -} - - - -//! draws a vertex primitive list -void CBurningVideoDriver::drawVertexPrimitiveList16(const void* vertices, u32 vertexCount, const u16* indexList, u32 primitiveCount, E_VERTEX_TYPE vType, scene::E_PRIMITIVE_TYPE pType) { if (!checkPrimitiveCount(primitiveCount)) return; - CNullDriver::drawVertexPrimitiveList(vertices, vertexCount, indexList, primitiveCount, vType, pType, EIT_16BIT); + CNullDriver::drawVertexPrimitiveList(vertices, vertexCount, indexList, primitiveCount, vType, pType, iType); if ( 0 == CurrentShader ) return; - - VertexCache_reset ( vertices, vertexCount, indexList, primitiveCount, vType, pType ); + VertexCache_reset ( vertices, vertexCount, indexList, primitiveCount, vType, pType, iType ); const s4DVertex * face[3]; @@ -1262,7 +1287,7 @@ void CBurningVideoDriver::drawVertexPrimitiveList16(const void* vertices, u32 ve /* // TODO: don't stick on 32 Bit Pointer - #define PointerAsValue(x) ( (u32) (u32*) (x) ) + #define PointerAsValue(x) ( (u32) (u32*) (x) ) // if not complete inside clipping necessary if ( ( test & VERTEX4D_INSIDE ) != VERTEX4D_INSIDE ) @@ -1328,8 +1353,10 @@ void CBurningVideoDriver::drawVertexPrimitiveList16(const void* vertices, u32 ve ); os::Printer::print ( buf ); */ + } + //! Sets the dynamic ambient light color. The default color is //! (0,0,0,0) which means it is dark. //! \param color: New color of the ambient light. @@ -1347,7 +1374,7 @@ s32 CBurningVideoDriver::addDynamicLight(const SLight& dl) l.LightIsOn = true; // light in eye space - Transformation[ETS_VIEW].m.transformVect ( &l.posEyeSpace.x, l.org.Position ); + Transformation[ETS_VIEW].transformVect ( &l.posEyeSpace.x, l.org.Position ); l.constantAttenuation = l.org.Attenuation.X; l.linearAttenuation = l.org.Attenuation.Y; @@ -1363,14 +1390,10 @@ s32 CBurningVideoDriver::addDynamicLight(const SLight& dl) { l.posEyeSpace.normalize_xyz (); } break; - - default: - break; } LightSpace.Light.push_back ( l ); - (void)CNullDriver::addDynamicLight( l.org ); - + (void) CNullDriver::addDynamicLight( l.org ); return LightSpace.Light.size() - 1; } @@ -1381,8 +1404,6 @@ void CBurningVideoDriver::turnLightOn(s32 lightIndex, bool turnOn) LightSpace.Light[lightIndex].LightIsOn = turnOn; } - - //! deletes all dynamic lights there are void CBurningVideoDriver::deleteAllDynamicLights() { @@ -1413,6 +1434,18 @@ void CBurningVideoDriver::lightVertex ( s4DVertex *dest, const S3DVertex *source return; } + sVec4 dColor; + + if ( Lights.size () == 0 ) + { + dColor = LightSpace.Global_AmbientLight; + dColor += Material.EmissiveColor; + dColor.saturate(); + + dest->Color[0] = dColor; + return; + } + // eyespace /* core::matrix4 modelview = Transformation[ETS_WORLD].m * Transformation[ETS_VIEW].m; @@ -1427,7 +1460,7 @@ void CBurningVideoDriver::lightVertex ( s4DVertex *dest, const S3DVertex *source sVec4 vertexEyeSpaceUnit; // vertex in eye space - Transformation[ETS_WORLD_VIEW].m.transformVect ( &vertexEyeSpace.x, source->Pos ); + Transformation[ETS_WORLD_VIEW].transformVect ( &vertexEyeSpace.x, source->Pos ); vertexEyeSpace.project_xyz (); vertexEyeSpaceUnit = vertexEyeSpace; @@ -1435,7 +1468,7 @@ void CBurningVideoDriver::lightVertex ( s4DVertex *dest, const S3DVertex *source // vertex normal in eye-space //modelviewinversetransposed.transformVect ( &normalEyeSpace.x, source->Normal ); - Transformation[ETS_WORLD_VIEW_INVERSE_TRANSPOSED].m.rotateVect ( &normalEyeSpace.x, source->Normal ); + Transformation[ETS_WORLD_VIEW_INVERSE_TRANSPOSED].rotateVect ( &normalEyeSpace.x, source->Normal ); if ( Material.org.NormalizeNormals ) { normalEyeSpace.normalize_xyz(); @@ -1459,9 +1492,6 @@ void CBurningVideoDriver::lightVertex ( s4DVertex *dest, const S3DVertex *source { const SBurningShaderLight &light = LightSpace.Light[i]; - if(!light.LightIsOn) - continue; - sVec4 vp; // unit vector vertex to light sVec4 lightHalf; // blinn-phong reflection @@ -1513,9 +1543,6 @@ void CBurningVideoDriver::lightVertex ( s4DVertex *dest, const S3DVertex *source lightHalf.z = vp.z - 1.f; lightHalf.normalize_xyz(); } break; - - default: - break; } // build diffuse reflection @@ -1541,8 +1568,6 @@ void CBurningVideoDriver::lightVertex ( s4DVertex *dest, const S3DVertex *source } - sVec4 dColor; - dColor = LightSpace.Global_AmbientLight; dColor += Material.EmissiveColor; dColor += ambient * Material.AmbientColor; @@ -1593,7 +1618,7 @@ void CBurningVideoDriver::draw2DLine(const core::position2d& start, void CBurningVideoDriver::drawPixel(u32 x, u32 y, const SColor & color) { ((CImage*)BackBuffer)->setPixel(x, y, color); -} +} //! draw an 2d rectangle void CBurningVideoDriver::draw2DRectangle(SColor color, const core::rect& pos, @@ -1635,11 +1660,13 @@ void CBurningVideoDriver::OnResize(const core::dimension2d& size) if (ScreenSize != realSize) { - if (ViewPort.getWidth() == (s32)ScreenSize.Width && - ViewPort.getHeight() == (s32)ScreenSize.Height) + if (ViewPort.getWidth() == ScreenSize.Width && + ViewPort.getHeight() == ScreenSize.Height) { - ViewPort = core::rect(core::position2d(0,0), - core::dimension2di(realSize)); + ViewPort.UpperLeftCorner.X = 0; + ViewPort.UpperLeftCorner.Y = 0; + ViewPort.LowerRightCorner.X = realSize.Width; + ViewPort.LowerRightCorner.X = realSize.Height; } ScreenSize = realSize; @@ -1678,9 +1705,9 @@ void CBurningVideoDriver::draw2DRectangle(const core::rect& position, if (!pos.isValid()) return; - const core::dimension2d renderTargetSize ( ViewPort.getSize() ); + const core::dimension2d renderTargetSize ( ViewPort.getSize() ); - const s32 xPlus = -(s32)(renderTargetSize.Width>>1); + const s32 xPlus = -(renderTargetSize.Width>>1); const f32 xFact = 1.0f / (renderTargetSize.Width>>1); const s32 yPlus = renderTargetSize.Height-(renderTargetSize.Height>>1); @@ -1780,8 +1807,8 @@ void CBurningVideoDriver::draw2DRectangle(const core::rect& position, void CBurningVideoDriver::draw3DLine(const core::vector3df& start, const core::vector3df& end, SColor color) { - Transformation [ ETS_CURRENT].m.transformVect ( &CurrentOut.data[0].Pos.x, start ); - Transformation [ ETS_CURRENT].m.transformVect ( &CurrentOut.data[2].Pos.x, end ); + Transformation [ ETS_CURRENT].transformVect ( &CurrentOut.data[0].Pos.x, start ); + Transformation [ ETS_CURRENT].transformVect ( &CurrentOut.data[2].Pos.x, end ); u32 g; u32 vOut; @@ -1829,13 +1856,13 @@ void CBurningVideoDriver::draw3DLine(const core::vector3df& start, const wchar_t* CBurningVideoDriver::getName() const { #ifdef BURNINGVIDEO_RENDERER_BEAUTIFUL - return L"burnings video 0.39b"; + return L"burnings video 0.40b"; #elif defined ( BURNINGVIDEO_RENDERER_ULTRA_FAST ) - return L"burnings video 0.39uf"; + return L"burnings video 0.40uf"; #elif defined ( BURNINGVIDEO_RENDERER_FAST ) - return L"burnings video 0.39f"; + return L"burnings video 0.40f"; #else - return L"burnings video 0.39"; + return L"burnings video 0.40"; #endif } @@ -1857,18 +1884,16 @@ ECOLOR_FORMAT CBurningVideoDriver::getColorFormat() const //! Returns the transformation set by setTransform const core::matrix4& CBurningVideoDriver::getTransform(E_TRANSFORMATION_STATE state) const { - return Transformation[state].m; + return Transformation[state]; } //! Creates a render target texture. ITexture* CBurningVideoDriver::addRenderTargetTexture(const core::dimension2d& size, - const c8* name) + const core::string& name) { CImage* img = new CImage(BURNINGSHADER_COLOR_FORMAT, size); - if (!name) - name="rt"; - ITexture* tex = new CSoftwareTexture2(img, name, false, true); + ITexture* tex = new CSoftwareTexture2(img, name, CSoftwareTexture2::IS_RENDERTARGET ); img->drop(); addTexture(tex); tex->drop(); @@ -1891,14 +1916,19 @@ IImage* CBurningVideoDriver::createScreenShot() return new CImage(BackBuffer->getColorFormat(), BackBuffer); else return 0; + } //! returns a device dependent texture from a software surface (IImage) //! THIS METHOD HAS TO BE OVERRIDDEN BY DERIVED DRIVERS WITH OWN TEXTURES -ITexture* CBurningVideoDriver::createDeviceDependentTexture(IImage* surface, const char* name) +ITexture* CBurningVideoDriver::createDeviceDependentTexture(IImage* surface, const core::string& name) { - return new CSoftwareTexture2(surface, name, getTextureCreationFlag(ETCF_CREATE_MIP_MAPS)); + return new CSoftwareTexture2( + surface, name, + (getTextureCreationFlag(ETCF_CREATE_MIP_MAPS) ? CSoftwareTexture2::GEN_MIPMAP : 0 ) | + (getTextureCreationFlag(ETCF_ALLOW_NON_POWER_2) ? 0 : CSoftwareTexture2::NP2_SIZE ) + ); } @@ -1908,7 +1938,13 @@ ITexture* CBurningVideoDriver::createDeviceDependentTexture(IImage* surface, con //! call. u32 CBurningVideoDriver::getMaximalPrimitiveCount() const { - return 0x00800000; + return 0xFFFFFFFF; +} + +//! Returns the graphics card vendor name. +core::stringc CBurningVideoDriver::getVendorInfo() +{ + return "Burningsvideo: Ing. Thomas Alten (c) 2006-2008"; } diff --git a/source/Irrlicht/CSoftwareDriver2.h b/source/Irrlicht/CSoftwareDriver2.h index fd0d1b12..bf781b74 100644 --- a/source/Irrlicht/CSoftwareDriver2.h +++ b/source/Irrlicht/CSoftwareDriver2.h @@ -123,7 +123,7 @@ namespace video virtual const core::matrix4& getTransform(E_TRANSFORMATION_STATE state) const; //! Creates a render target texture. - virtual ITexture* addRenderTargetTexture(const core::dimension2d& size, const c8* name); + virtual ITexture* addRenderTargetTexture(const core::dimension2d& size, const core::string& name); //! Clears the DepthBuffer. virtual void clearZBuffer(); @@ -150,14 +150,12 @@ namespace video video::SColor leftDownEdge = video::SColor(0,0,0,0), video::SColor rightDownEdge = video::SColor(0,0,0,0)); + //! Returns the graphics card vendor name. + virtual core::stringc getVendorInfo(); + protected: - void drawVertexPrimitiveList16(const void* vertices, u32 vertexCount, - const u16* indexList, u32 primitiveCount, - E_VERTEX_TYPE vType, scene::E_PRIMITIVE_TYPE pType); - - //! sets a render target void setRenderTarget(video::CImage* image); @@ -166,7 +164,7 @@ namespace video //! returns a device dependent texture from a software surface (IImage) //! THIS METHOD HAS TO BE OVERRIDDEN BY DERIVED DRIVERS WITH OWN TEXTURES - virtual video::ITexture* createDeviceDependentTexture(IImage* surface, const char* name); + virtual video::ITexture* createDeviceDependentTexture(IImage* surface, const core::string& name); video::CImage* BackBuffer; video::IImagePresenter* Presenter; @@ -204,13 +202,8 @@ namespace video ETS2_COUNT }; - struct SMatrixStack - { - s32 isIdentity; - core::matrix4 m; - }; - - SMatrixStack Transformation[ETS2_COUNT]; + u32 TransformationFlag[ETS2_COUNT]; + core::matrix4 Transformation[ETS2_COUNT]; // Vertex Cache static const SVSize vSize[]; @@ -218,8 +211,9 @@ namespace video SVertexCache VertexCache; void VertexCache_reset (const void* vertices, u32 vertexCount, - const u16* indices, u32 indexCount, - E_VERTEX_TYPE vType,scene::E_PRIMITIVE_TYPE pType); + const void* indices, u32 indexCount, + E_VERTEX_TYPE vType,scene::E_PRIMITIVE_TYPE pType, + E_INDEX_TYPE iType); void VertexCache_get ( s4DVertex ** face ); void VertexCache_get2 ( s4DVertex ** face ); diff --git a/source/Irrlicht/CSoftwareTexture.cpp b/source/Irrlicht/CSoftwareTexture.cpp index 23ecfec7..024c3888 100644 --- a/source/Irrlicht/CSoftwareTexture.cpp +++ b/source/Irrlicht/CSoftwareTexture.cpp @@ -14,7 +14,7 @@ namespace video { //! constructor -CSoftwareTexture::CSoftwareTexture(IImage* image, const char* name, bool renderTarget) +CSoftwareTexture::CSoftwareTexture(IImage* image, const core::string& name, bool renderTarget) : ITexture(name), Texture(0), IsRenderTarget(renderTarget) { #ifdef _DEBUG diff --git a/source/Irrlicht/CSoftwareTexture.h b/source/Irrlicht/CSoftwareTexture.h index c8854ddd..62f9c9b8 100644 --- a/source/Irrlicht/CSoftwareTexture.h +++ b/source/Irrlicht/CSoftwareTexture.h @@ -21,7 +21,7 @@ class CSoftwareTexture : public ITexture public: //! constructor - CSoftwareTexture(IImage* surface, const char* name, bool renderTarget=false); + CSoftwareTexture(IImage* surface, const core::string& name, bool renderTarget=false); //! destructor virtual ~CSoftwareTexture(); diff --git a/source/Irrlicht/CSoftwareTexture2.cpp b/source/Irrlicht/CSoftwareTexture2.cpp index 93fbbe15..451962fd 100644 --- a/source/Irrlicht/CSoftwareTexture2.cpp +++ b/source/Irrlicht/CSoftwareTexture2.cpp @@ -16,15 +16,15 @@ namespace video { //! constructor -CSoftwareTexture2::CSoftwareTexture2(IImage* image, const char* name, bool generateMipLevels, bool isRenderTarget) -: ITexture(name), MipMapLOD(0), HasMipMaps(generateMipLevels), IsRenderTarget(isRenderTarget) +CSoftwareTexture2::CSoftwareTexture2(IImage* image, const core::string& name, u32 flags ) +: ITexture(name), MipMapLOD(0), Flags ( flags ) { #ifdef _DEBUG setDebugName("CSoftwareTexture2"); #endif #ifndef SOFTWARE_DRIVER_2_MIPMAPPING - HasMipMaps = false; + Flags &= ~GEN_MIPMAP; #endif memset32 ( MipMap, 0, sizeof ( MipMap ) ); @@ -34,7 +34,10 @@ CSoftwareTexture2::CSoftwareTexture2(IImage* image, const char* name, bool gener OrigSize = image->getDimension(); core::dimension2d optSize( - OrigSize.getOptimalSize(true, false, false)); + OrigSize.getOptimalSize( 0 != ( Flags & NP2_SIZE ), + false, false, + ( Flags & NP2_SIZE ) ? SOFTWARE_DRIVER_2_TEXTURE_MAXSIZE : 0) + ); if ( OrigSize == optSize ) { @@ -42,7 +45,16 @@ CSoftwareTexture2::CSoftwareTexture2(IImage* image, const char* name, bool gener } else { - //os::Printer::log ( "Burningvideo: Warning Texture reformat", ELL_WARNING ); + char buf[128]; + core::stringw showName ( name ); + snprintf ( buf, 128, "Burningvideo: Warning Texture %ls reformat %dx%d -> %dx%d,%d", + showName.c_str(), + OrigSize.Width, OrigSize.Height, optSize.Width, optSize.Height, + BURNINGSHADER_COLOR_FORMAT + ); + + OrigSize = optSize; + os::Printer::log ( buf, ELL_WARNING ); MipMap[0] = new CImage(BURNINGSHADER_COLOR_FORMAT, optSize); // temporary CImage needed @@ -73,7 +85,7 @@ CSoftwareTexture2::~CSoftwareTexture2() //! modifying the texture void CSoftwareTexture2::regenerateMipMapLevels() { - if ( !HasMipMaps ) + if ( !hasMipMaps () ) return; s32 i; diff --git a/source/Irrlicht/CSoftwareTexture2.h b/source/Irrlicht/CSoftwareTexture2.h index 679e71ac..75d51dd1 100644 --- a/source/Irrlicht/CSoftwareTexture2.h +++ b/source/Irrlicht/CSoftwareTexture2.h @@ -23,7 +23,13 @@ class CSoftwareTexture2 : public ITexture public: //! constructor - CSoftwareTexture2(IImage* surface, const char* name, bool generateMipLevels, bool isRenderTarget=false); + enum eTex2Flags + { + GEN_MIPMAP = 1, + IS_RENDERTARGET = 2, + NP2_SIZE = 4 + }; + CSoftwareTexture2( IImage* surface, const core::string& name, u32 flags ); //! destructor virtual ~CSoftwareTexture2(); @@ -97,20 +103,20 @@ public: //! Select a Mipmap Level virtual void setCurrentMipMapLOD ( s32 lod ) { - if ( HasMipMaps ) + if ( Flags & GEN_MIPMAP ) MipMapLOD = lod; } //! support mipmaps virtual bool hasMipMaps() const { - return HasMipMaps; + return Flags & GEN_MIPMAP; } //! is a render target virtual bool isRenderTarget() const { - return IsRenderTarget; + return (Flags & IS_RENDERTARGET) != 0; } private: @@ -119,7 +125,7 @@ private: CImage * MipMap[SOFTWARE_DRIVER_2_MIPMAPPING_MAX]; s32 MipMapLOD; - bool HasMipMaps, IsRenderTarget; + u32 Flags; }; diff --git a/source/Irrlicht/CTRGouraud2.cpp b/source/Irrlicht/CTRGouraud2.cpp index ecd086ef..d0f7af71 100644 --- a/source/Irrlicht/CTRGouraud2.cpp +++ b/source/Irrlicht/CTRGouraud2.cpp @@ -185,10 +185,10 @@ void CTRGouraud2::scanline_bilinear () #endif #endif - dst = lockedSurface + ( line.y * RenderTarget->getDimension().Width ) + xStart; + dst = (tVideoSample*)RenderTarget->lock() + ( line.y * RenderTarget->getDimension().Width ) + xStart; #ifdef USE_ZBUFFER - z = lockedDepthBuffer + ( line.y * RenderTarget->getDimension().Width ) + xStart; + z = (fp24*) DepthBuffer->lock() + ( line.y * RenderTarget->getDimension().Width ) + xStart; #endif @@ -318,11 +318,6 @@ void CTRGouraud2::drawTriangle ( const s4DVertex *a,const s4DVertex *b,const s4D f32 subPixel; #endif - lockedSurface = (tVideoSample*)RenderTarget->lock(); - -#ifdef USE_ZBUFFER - lockedDepthBuffer = (fp24*) DepthBuffer->lock(); -#endif #ifdef IPOL_T0 IT[0].data = (tVideoSample*)IT[0].Texture->lock(); diff --git a/source/Irrlicht/CTRGouraudAlpha2.cpp b/source/Irrlicht/CTRGouraudAlpha2.cpp index 465f77f9..1e551102 100644 --- a/source/Irrlicht/CTRGouraudAlpha2.cpp +++ b/source/Irrlicht/CTRGouraudAlpha2.cpp @@ -188,10 +188,10 @@ void CTRGouraudAlpha2::scanline_bilinear () #endif #endif - dst = lockedSurface + ( line.y * RenderTarget->getDimension().Width ) + xStart; + dst = (tVideoSample*)RenderTarget->lock() + ( line.y * RenderTarget->getDimension().Width ) + xStart; #ifdef USE_ZBUFFER - z = lockedDepthBuffer + ( line.y * RenderTarget->getDimension().Width ) + xStart; + z = (fp24*) DepthBuffer->lock() + ( line.y * RenderTarget->getDimension().Width ) + xStart; #endif @@ -269,8 +269,8 @@ void CTRGouraudAlpha2::drawTriangle ( const s4DVertex *a,const s4DVertex *b,cons { // sort on height, y if ( F32_A_GREATER_B ( a->Pos.y , b->Pos.y ) ) swapVertexPointer(&a, &b); - if ( F32_A_GREATER_B ( a->Pos.y , c->Pos.y ) ) swapVertexPointer(&a, &c); if ( F32_A_GREATER_B ( b->Pos.y , c->Pos.y ) ) swapVertexPointer(&b, &c); + if ( F32_A_GREATER_B ( a->Pos.y , b->Pos.y ) ) swapVertexPointer(&a, &b); // calculate delta y of the edges @@ -330,12 +330,6 @@ void CTRGouraudAlpha2::drawTriangle ( const s4DVertex *a,const s4DVertex *b,cons f32 subPixel; #endif - lockedSurface = (tVideoSample*)RenderTarget->lock(); - -#ifdef USE_ZBUFFER - lockedDepthBuffer = (fp24*) DepthBuffer->lock(); -#endif - #ifdef IPOL_T0 IT[0].data = (tVideoSample*)IT[0].Texture->lock(); #endif diff --git a/source/Irrlicht/CTRGouraudAlphaNoZ2.cpp b/source/Irrlicht/CTRGouraudAlphaNoZ2.cpp index cfa31a32..38c3a1c1 100644 --- a/source/Irrlicht/CTRGouraudAlphaNoZ2.cpp +++ b/source/Irrlicht/CTRGouraudAlphaNoZ2.cpp @@ -187,10 +187,10 @@ void CTRGouraudAlphaNoZ2::scanline_bilinear () #endif #endif - dst = lockedSurface + ( line.y * RenderTarget->getDimension().Width ) + xStart; + dst = (tVideoSample*)RenderTarget->lock() + ( line.y * RenderTarget->getDimension().Width ) + xStart; #ifdef USE_ZBUFFER - z = lockedDepthBuffer + ( line.y * RenderTarget->getDimension().Width ) + xStart; + z = (fp24*) DepthBuffer->lock() + ( line.y * RenderTarget->getDimension().Width ) + xStart; #endif @@ -271,8 +271,8 @@ void CTRGouraudAlphaNoZ2::drawTriangle ( const s4DVertex *a,const s4DVertex *b,c { // sort on height, y if ( F32_A_GREATER_B ( a->Pos.y , b->Pos.y ) ) swapVertexPointer(&a, &b); - if ( F32_A_GREATER_B ( a->Pos.y , c->Pos.y ) ) swapVertexPointer(&a, &c); if ( F32_A_GREATER_B ( b->Pos.y , c->Pos.y ) ) swapVertexPointer(&b, &c); + if ( F32_A_GREATER_B ( a->Pos.y , b->Pos.y ) ) swapVertexPointer(&a, &b); // calculate delta y of the edges @@ -332,12 +332,6 @@ void CTRGouraudAlphaNoZ2::drawTriangle ( const s4DVertex *a,const s4DVertex *b,c f32 subPixel; #endif - lockedSurface = (tVideoSample*)RenderTarget->lock(); - -#ifdef USE_ZBUFFER - lockedDepthBuffer = DepthBuffer->lock(); -#endif - #ifdef IPOL_T0 IT[0].data = (tVideoSample*)IT[0].Texture->lock(); #endif diff --git a/source/Irrlicht/CTRTextureBlend.cpp b/source/Irrlicht/CTRTextureBlend.cpp index a09a671f..4857a9ed 100644 --- a/source/Irrlicht/CTRTextureBlend.cpp +++ b/source/Irrlicht/CTRTextureBlend.cpp @@ -33,7 +33,7 @@ #define CMP_W #define WRITE_W -//#define IPOL_C0 +#define IPOL_C0 #define IPOL_T0 //#define IPOL_T1 @@ -87,15 +87,27 @@ public: virtual void drawTriangle ( const s4DVertex *a,const s4DVertex *b,const s4DVertex *c ); virtual void setZCompareFunc ( u32 func); + virtual void setParam ( u32 index, f32 value); + private: - void scanline_bilinear (); + // fragment shader + typedef void (CTRTextureBlend::*tFragmentShader) (); + void fragment_dst_color_zero (); + void fragment_dst_color_one (); + void fragment_dst_color_src_alpha (); + void fragment_dst_color_one_minus_dst_alpha (); + void fragment_zero_one_minus_scr_color (); + void fragment_src_color_src_alpha (); + void fragment_one_one_minus_src_alpha (); + void fragment_one_minus_dst_alpha_one(); + void fragment_src_alpha_one(); + tFragmentShader fragmentShader; sScanConvertData scan; sScanLineData line; u32 ZCompare; - }; //! constructor @@ -109,7 +121,8 @@ CTRTextureBlend::CTRTextureBlend(IDepthBuffer* zbuffer) ZCompare = 1; } - +/*! +*/ void CTRTextureBlend::setZCompareFunc ( u32 func) { ZCompare = func; @@ -117,7 +130,95 @@ void CTRTextureBlend::setZCompareFunc ( u32 func) /*! */ -void CTRTextureBlend::scanline_bilinear () +void CTRTextureBlend::setParam ( u32 index, f32 value) +{ + u8 showname = 0; + + E_BLEND_FACTOR srcFact,dstFact; + E_MODULATE_FUNC modulate; + unpack_texureBlendFunc ( srcFact, dstFact, modulate, value ); + + fragmentShader = 0; + + if ( srcFact == EBF_DST_COLOR && dstFact == EBF_ZERO ) + { + fragmentShader = &CTRTextureBlend::fragment_dst_color_zero; + } + else + if ( srcFact == EBF_DST_COLOR && dstFact == EBF_ONE ) + { + fragmentShader = &CTRTextureBlend::fragment_dst_color_one; + } + else + if ( srcFact == EBF_DST_COLOR && dstFact == EBF_SRC_ALPHA) + { + fragmentShader = &CTRTextureBlend::fragment_dst_color_src_alpha; + } + else + if ( srcFact == EBF_DST_COLOR && dstFact == EBF_ONE_MINUS_DST_ALPHA) + { + fragmentShader = &CTRTextureBlend::fragment_dst_color_one_minus_dst_alpha; + } + else + if ( srcFact == EBF_ZERO && dstFact == EBF_ONE_MINUS_SRC_COLOR ) + { + fragmentShader = &CTRTextureBlend::fragment_zero_one_minus_scr_color; + } + else + if ( srcFact == EBF_ONE && dstFact == EBF_ONE_MINUS_SRC_ALPHA) + { + fragmentShader = &CTRTextureBlend::fragment_one_one_minus_src_alpha; + } + else + if ( srcFact == EBF_ONE_MINUS_DST_ALPHA && dstFact == EBF_ONE ) + { + fragmentShader = &CTRTextureBlend::fragment_one_minus_dst_alpha_one; + } + else + if ( srcFact == EBF_SRC_ALPHA && dstFact == EBF_ONE ) + { + fragmentShader = &CTRTextureBlend::fragment_src_alpha_one; + } + else + { + showname = 1; + fragmentShader = &CTRTextureBlend::fragment_dst_color_zero; + } + + static const c8 *n[] = + { + "gl_zero", + "gl_one", + "gl_dst_color", + "gl_one_minus_dst_color", + "gl_src_color", + "gl_one_minus_src_color", + "gl_src_alpha", + "gl_one_minus_src_alpha", + "gl_dst_alpha", + "gl_one_minus_dst_alpha", + "gl_src_alpha_saturate" + }; + + static E_BLEND_FACTOR lsrcFact = EBF_ZERO; + static E_BLEND_FACTOR ldstFact = EBF_ZERO; + + if ( showname && ( lsrcFact != srcFact || ldstFact != dstFact ) ) + { + char buf[128]; + snprintf ( buf, 128, "missing shader: %s %s",n[srcFact], n[dstFact] ); + os::Printer::log( buf, ELL_INFORMATION ); + + lsrcFact = srcFact; + ldstFact = dstFact; + } + +} + + +/*! +*/ +void CTRTextureBlend::fragment_dst_color_src_alpha () { tVideoSample *dst; @@ -141,7 +242,7 @@ void CTRTextureBlend::scanline_bilinear () fp24 slopeW; #endif #ifdef IPOL_C0 - sVec4 slopeC; + sVec4 slopeC[MATERIAL_MAX_COLORS]; #endif #ifdef IPOL_T0 sVec2 slopeT[BURNING_MATERIAL_MAX_TEXTURES]; @@ -166,7 +267,7 @@ void CTRTextureBlend::scanline_bilinear () slopeW = (line.w[1] - line.w[0]) * invDeltaX; #endif #ifdef IPOL_C0 - slopeC = (line.c[1] - line.c[0]) * invDeltaX; + slopeC[0] = (line.c[0][1] - line.c[0][0]) * invDeltaX; #endif #ifdef IPOL_T0 slopeT[0] = (line.t[0][1] - line.t[0][0]) * invDeltaX; @@ -184,7 +285,7 @@ void CTRTextureBlend::scanline_bilinear () line.w[0] += slopeW * subPixel; #endif #ifdef IPOL_C0 - line.c[0] += slopeC * subPixel; + line.c[0][0] += slopeC[0] * subPixel; #endif #ifdef IPOL_T0 line.t[0][0] += slopeT[0] * subPixel; @@ -194,17 +295,17 @@ void CTRTextureBlend::scanline_bilinear () #endif #endif - dst = lockedSurface + ( line.y * RenderTarget->getDimension().Width ) + xStart; + dst = (tVideoSample*)RenderTarget->lock() + ( line.y * RenderTarget->getDimension().Width ) + xStart; #ifdef USE_ZBUFFER - z = lockedDepthBuffer + ( line.y * RenderTarget->getDimension().Width ) + xStart; + z = (fp24*) DepthBuffer->lock() + ( line.y * RenderTarget->getDimension().Width ) + xStart; #endif - f32 inversew = FIX_POINT_F32_MUL; + f32 iw = FIX_POINT_F32_MUL; - tFixPoint r0, g0, b0; - tFixPoint r1, g1, b1; + tFixPoint a0, r0, g0, b0; + tFixPoint r1, g1, b1; s32 i; @@ -223,21 +324,21 @@ void CTRTextureBlend::scanline_bilinear () z[i] = line.w[0]; #endif -#ifdef INVERSEW - inversew = fix_inverse32 ( line.w[0] ); +#ifdef INVERSE_W + iw = fix_inverse32 ( line.w[0] ); #endif - getSample_texture ( r0, g0, b0, + getSample_texture ( (tFixPointu&) a0, (tFixPointu&)r0, (tFixPointu&)g0, (tFixPointu&)b0, &IT[0], - f32_to_fixPoint ( line.t[0][0].x,inversew), - f32_to_fixPoint ( line.t[0][0].y,inversew) + tofix ( line.t[0][0].x,iw), + tofix ( line.t[0][0].y,iw) ); - + color_to_fix ( r1, g1, b1, dst[i] ); - dst[i] = fix_to_color ( clampfix_maxcolor ( imulFix_tex4 ( r0, r1 ) ), - clampfix_maxcolor ( imulFix_tex4 ( g0, g1 ) ), - clampfix_maxcolor ( imulFix_tex4 ( b0, b1 ) ) + dst[i] = fix_to_color ( clampfix_maxcolor ( imulFix_tex2 ( r0, r1 ) ), + clampfix_maxcolor ( imulFix_tex2 ( g0, g1 ) ), + clampfix_maxcolor ( imulFix_tex2 ( b0, b1 ) ) ); } @@ -246,6 +347,9 @@ void CTRTextureBlend::scanline_bilinear () #endif #ifdef IPOL_T0 line.t[0][0] += slopeT[0]; +#endif +#ifdef IPOL_C0 + line.c[0][0] += slopeC[0]; #endif } break; @@ -263,20 +367,162 @@ void CTRTextureBlend::scanline_bilinear () z[i] = line.w[0]; #endif -#ifdef INVERSEW - inversew = fix_inverse32 ( line.w[0] ); +#ifdef INVERSE_W + iw = fix_inverse32 ( line.w[0] ); #endif - getSample_texture ( r0, g0, b0, - &IT[0], - f32_to_fixPoint ( line.t[0][0].x,inversew), - f32_to_fixPoint ( line.t[0][0].y,inversew) - ); + getSample_texture ( (tFixPointu&) a0, (tFixPointu&)r0, (tFixPointu&)g0, (tFixPointu&)b0, + &IT[0], + tofix ( line.t[0][0].x,iw), + tofix ( line.t[0][0].y,iw) + ); + color_to_fix ( r1, g1, b1, dst[i] ); - dst[i] = fix_to_color ( clampfix_maxcolor ( imulFix_tex4 ( r0, r1 ) ), - clampfix_maxcolor ( imulFix_tex4 ( g0, g1 ) ), - clampfix_maxcolor ( imulFix_tex4 ( b0, b1 ) ) + dst[i] = fix_to_color ( clampfix_maxcolor ( imulFix_tex2 ( r0, r1 ) ), + clampfix_maxcolor ( imulFix_tex2 ( g0, g1 ) ), + clampfix_maxcolor ( imulFix_tex2 ( b0, b1 ) ) + ); + + } + +#ifdef IPOL_W + line.w[0] += slopeW; +#endif +#ifdef IPOL_T0 + line.t[0][0] += slopeT[0]; +#endif +#ifdef IPOL_C0 + line.c[0][0] += slopeC[0]; +#endif + }break; + } // zcompare + +} + +/*! +*/ +void CTRTextureBlend::fragment_src_color_src_alpha () +{ + tVideoSample *dst; + +#ifdef USE_ZBUFFER + fp24 *z; +#endif + + s32 xStart; + s32 xEnd; + s32 dx; + + +#ifdef SUBTEXEL + f32 subPixel; +#endif + +#ifdef IPOL_Z + f32 slopeZ; +#endif +#ifdef IPOL_W + fp24 slopeW; +#endif +#ifdef IPOL_C0 + sVec4 slopeC[MATERIAL_MAX_COLORS]; +#endif +#ifdef IPOL_T0 + sVec2 slopeT[BURNING_MATERIAL_MAX_TEXTURES]; +#endif + + // apply top-left fill-convention, left + xStart = core::ceil32( line.x[0] ); + xEnd = core::ceil32( line.x[1] ) - 1; + + dx = xEnd - xStart; + + if ( dx < 0 ) + return; + + // slopes + const f32 invDeltaX = core::reciprocal_approxim ( line.x[1] - line.x[0] ); + +#ifdef IPOL_Z + slopeZ = (line.z[1] - line.z[0]) * invDeltaX; +#endif +#ifdef IPOL_W + slopeW = (line.w[1] - line.w[0]) * invDeltaX; +#endif +#ifdef IPOL_C0 + slopeC[0] = (line.c[0][1] - line.c[0][0]) * invDeltaX; +#endif +#ifdef IPOL_T0 + slopeT[0] = (line.t[0][1] - line.t[0][0]) * invDeltaX; +#endif +#ifdef IPOL_T1 + slopeT[1] = (line.t[1][1] - line.t[1][0]) * invDeltaX; +#endif + +#ifdef SUBTEXEL + subPixel = ( (f32) xStart ) - line.x[0]; +#ifdef IPOL_Z + line.z[0] += slopeZ * subPixel; +#endif +#ifdef IPOL_W + line.w[0] += slopeW * subPixel; +#endif +#ifdef IPOL_C0 + line.c[0][0] += slopeC[0] * subPixel; +#endif +#ifdef IPOL_T0 + line.t[0][0] += slopeT[0] * subPixel; +#endif +#ifdef IPOL_T1 + line.t[1][0] += slopeT[1] * subPixel; +#endif +#endif + + dst = (tVideoSample*)RenderTarget->lock() + ( line.y * RenderTarget->getDimension().Width ) + xStart; + +#ifdef USE_ZBUFFER + z = (fp24*) DepthBuffer->lock() + ( line.y * RenderTarget->getDimension().Width ) + xStart; +#endif + + + f32 iw = FIX_POINT_F32_MUL; + + tFixPoint a0, r0, g0, b0; + tFixPoint r1, g1, b1; + + s32 i; + + switch ( ZCompare ) + { + case 1: + for ( i = 0; i <= dx; ++i ) + { +#ifdef CMP_W + if ( line.w[0] >= z[i] ) +#endif + + { + +#ifdef WRITE_W + z[i] = line.w[0]; +#endif + +#ifdef INVERSE_W + iw = fix_inverse32 ( line.w[0] ); +#endif + + getSample_texture ( (tFixPointu&) a0, (tFixPointu&)r0, (tFixPointu&)g0, (tFixPointu&)b0, + &IT[0], + tofix ( line.t[0][0].x,iw), + tofix ( line.t[0][0].y,iw) + ); + + color_to_fix ( r1, g1, b1, dst[i] ); + + dst[i] = fix_to_color ( clampfix_maxcolor ( imulFix_tex2 ( r0, r1 ) ), + clampfix_maxcolor ( imulFix_tex2 ( g0, g1 ) ), + clampfix_maxcolor ( imulFix_tex2 ( b0, b1 ) ) ); } @@ -285,18 +531,1472 @@ void CTRTextureBlend::scanline_bilinear () #endif #ifdef IPOL_T0 line.t[0][0] += slopeT[0]; +#endif +#ifdef IPOL_C0 + line.c[0][0] += slopeC[0]; +#endif + } + break; + + case 2: + for ( i = 0; i <= dx; ++i ) + { +#ifdef CMP_W + if ( line.w[0] == z[i] ) +#endif + + { + +#ifdef WRITE_W + z[i] = line.w[0]; +#endif + +#ifdef INVERSE_W + iw = fix_inverse32 ( line.w[0] ); +#endif + + getSample_texture ( (tFixPointu&) a0, (tFixPointu&)r0, (tFixPointu&)g0, (tFixPointu&)b0, + &IT[0], + tofix ( line.t[0][0].x,iw), + tofix ( line.t[0][0].y,iw) + ); + + color_to_fix ( r1, g1, b1, dst[i] ); + + dst[i] = fix_to_color ( clampfix_maxcolor ( imulFix_tex2 ( r0, r1 ) ), + clampfix_maxcolor ( imulFix_tex2 ( g0, g1 ) ), + clampfix_maxcolor ( imulFix_tex2 ( b0, b1 ) ) + ); + + } + +#ifdef IPOL_W + line.w[0] += slopeW; +#endif +#ifdef IPOL_T0 + line.t[0][0] += slopeT[0]; +#endif +#ifdef IPOL_C0 + line.c[0][0] += slopeC[0]; #endif }break; } // zcompare } +/*! +*/ +void CTRTextureBlend::fragment_one_one_minus_src_alpha() +{ + tVideoSample *dst; + +#ifdef USE_ZBUFFER + fp24 *z; +#endif + + s32 xStart; + s32 xEnd; + s32 dx; + + +#ifdef SUBTEXEL + f32 subPixel; +#endif + +#ifdef IPOL_Z + f32 slopeZ; +#endif +#ifdef IPOL_W + fp24 slopeW; +#endif +#ifdef IPOL_C0 + sVec4 slopeC[MATERIAL_MAX_COLORS]; +#endif +#ifdef IPOL_T0 + sVec2 slopeT[BURNING_MATERIAL_MAX_TEXTURES]; +#endif + + // apply top-left fill-convention, left + xStart = core::ceil32( line.x[0] ); + xEnd = core::ceil32( line.x[1] ) - 1; + + dx = xEnd - xStart; + + if ( dx < 0 ) + return; + + // slopes + const f32 invDeltaX = core::reciprocal_approxim ( line.x[1] - line.x[0] ); + +#ifdef IPOL_Z + slopeZ = (line.z[1] - line.z[0]) * invDeltaX; +#endif +#ifdef IPOL_W + slopeW = (line.w[1] - line.w[0]) * invDeltaX; +#endif +#ifdef IPOL_C0 + slopeC[0] = (line.c[0][1] - line.c[0][0]) * invDeltaX; +#endif +#ifdef IPOL_T0 + slopeT[0] = (line.t[0][1] - line.t[0][0]) * invDeltaX; +#endif +#ifdef IPOL_T1 + slopeT[1] = (line.t[1][1] - line.t[1][0]) * invDeltaX; +#endif + +#ifdef SUBTEXEL + subPixel = ( (f32) xStart ) - line.x[0]; +#ifdef IPOL_Z + line.z[0] += slopeZ * subPixel; +#endif +#ifdef IPOL_W + line.w[0] += slopeW * subPixel; +#endif +#ifdef IPOL_C0 + line.c[0][0] += slopeC[0] * subPixel; +#endif +#ifdef IPOL_T0 + line.t[0][0] += slopeT[0] * subPixel; +#endif +#ifdef IPOL_T1 + line.t[1][0] += slopeT[1] * subPixel; +#endif +#endif + + dst = (tVideoSample*)RenderTarget->lock() + ( line.y * RenderTarget->getDimension().Width ) + xStart; + +#ifdef USE_ZBUFFER + z = (fp24*) DepthBuffer->lock() + ( line.y * RenderTarget->getDimension().Width ) + xStart; +#endif + + + f32 iw = FIX_POINT_F32_MUL; + + tFixPointu a0,r0, g0, b0; + tFixPoint r1, g1, b1; + tFixPoint r2, g2, b2; + + s32 i; + + switch ( ZCompare ) + { + case 1: + for ( i = 0; i <= dx; ++i ) + { +#ifdef CMP_W + if ( line.w[0] >= z[i] ) +#endif + + { + +#ifdef WRITE_W + z[i] = line.w[0]; +#endif + +#ifdef INVERSE_W + iw = fix_inverse32 ( line.w[0] ); +#endif + + getSample_texture ( a0, r0, g0, b0, IT + 0, tofix ( line.t[0][0].x,iw),tofix ( line.t[0][0].y,iw) ); + a0 = FIX_POINT_ONE - a0; + + color_to_fix1 ( r1, g1, b1, dst[i] ); +#ifdef IPOL_C0 + getSample_color ( r2, g2, b2, line.c[0][0],iw ); + + dst[i] = fix_to_color ( imulFix ( r0 + imulFix ( r1, a0 ), r2 ), + imulFix ( g0 + imulFix ( g1, a0 ), g2 ), + imulFix ( b0 + imulFix ( b1, a0 ), b2 ) + ); +#else + dst[i] = fix_to_color ( r0 + imulFix ( r1, a0 ), + g0 + imulFix ( g1, a0 ), + b0 + imulFix ( b1, a0 ) + ); + +#endif + + } + +#ifdef IPOL_W + line.w[0] += slopeW; +#endif +#ifdef IPOL_T0 + line.t[0][0] += slopeT[0]; +#endif +#ifdef IPOL_C0 + line.c[0][0] += slopeC[0]; +#endif + } + break; + + case 2: + for ( i = 0; i <= dx; ++i ) + { +#ifdef CMP_W + if ( line.w[0] == z[i] ) +#endif + + { + +#ifdef WRITE_W + z[i] = line.w[0]; +#endif + +#ifdef INVERSE_W + iw = fix_inverse32 ( line.w[0] ); +#endif + getSample_texture ( a0, r0, g0, b0, IT + 0, tofix ( line.t[0][0].x,iw),tofix ( line.t[0][0].y,iw) ); + a0 = FIX_POINT_ONE - a0; + + color_to_fix1 ( r1, g1, b1, dst[i] ); +#ifdef IPOL_C0 + getSample_color ( r2, g2, b2, line.c[0][0],iw ); + + dst[i] = fix_to_color ( imulFix ( r0 + imulFix ( r1, a0 ), r2 ), + imulFix ( g0 + imulFix ( g1, a0 ), g2 ), + imulFix ( b0 + imulFix ( b1, a0 ), b2 ) + ); +#else + dst[i] = fix_to_color ( r0 + imulFix ( r1, a0 ), + g0 + imulFix ( g1, a0 ), + b0 + imulFix ( b1, a0 ) + ); + +#endif + + } + +#ifdef IPOL_W + line.w[0] += slopeW; +#endif +#ifdef IPOL_T0 + line.t[0][0] += slopeT[0]; +#endif +#ifdef IPOL_C0 + line.c[0][0] += slopeC[0]; +#endif + }break; + } // zcompare + +} + +/*! +*/ +void CTRTextureBlend::fragment_one_minus_dst_alpha_one () +{ + tVideoSample *dst; + +#ifdef USE_ZBUFFER + fp24 *z; +#endif + + s32 xStart; + s32 xEnd; + s32 dx; + + +#ifdef SUBTEXEL + f32 subPixel; +#endif + +#ifdef IPOL_Z + f32 slopeZ; +#endif +#ifdef IPOL_W + fp24 slopeW; +#endif +#ifdef IPOL_C0 + sVec4 slopeC[MATERIAL_MAX_COLORS]; +#endif +#ifdef IPOL_T0 + sVec2 slopeT[BURNING_MATERIAL_MAX_TEXTURES]; +#endif + + // apply top-left fill-convention, left + xStart = core::ceil32( line.x[0] ); + xEnd = core::ceil32( line.x[1] ) - 1; + + dx = xEnd - xStart; + + if ( dx < 0 ) + return; + + // slopes + const f32 invDeltaX = core::reciprocal_approxim ( line.x[1] - line.x[0] ); + +#ifdef IPOL_Z + slopeZ = (line.z[1] - line.z[0]) * invDeltaX; +#endif +#ifdef IPOL_W + slopeW = (line.w[1] - line.w[0]) * invDeltaX; +#endif +#ifdef IPOL_C0 + slopeC[0] = (line.c[0][1] - line.c[0][0]) * invDeltaX; +#endif +#ifdef IPOL_T0 + slopeT[0] = (line.t[0][1] - line.t[0][0]) * invDeltaX; +#endif +#ifdef IPOL_T1 + slopeT[1] = (line.t[1][1] - line.t[1][0]) * invDeltaX; +#endif + +#ifdef SUBTEXEL + subPixel = ( (f32) xStart ) - line.x[0]; +#ifdef IPOL_Z + line.z[0] += slopeZ * subPixel; +#endif +#ifdef IPOL_W + line.w[0] += slopeW * subPixel; +#endif +#ifdef IPOL_C0 + line.c[0][0] += slopeC[0] * subPixel; +#endif +#ifdef IPOL_T0 + line.t[0][0] += slopeT[0] * subPixel; +#endif +#ifdef IPOL_T1 + line.t[1][0] += slopeT[1] * subPixel; +#endif +#endif + + dst = (tVideoSample*)RenderTarget->lock() + ( line.y * RenderTarget->getDimension().Width ) + xStart; + +#ifdef USE_ZBUFFER + z = (fp24*) DepthBuffer->lock() + ( line.y * RenderTarget->getDimension().Width ) + xStart; +#endif + + + f32 iw = FIX_POINT_F32_MUL; + + tFixPoint r0, g0, b0; + tFixPoint a1, r1, g1, b1; + tFixPoint r2, g2, b2; + + s32 i; + + switch ( ZCompare ) + { + case 1: + for ( i = 0; i <= dx; ++i ) + { +#ifdef CMP_W + if ( line.w[0] >= z[i] ) +#endif + + { + +#ifdef WRITE_W + z[i] = line.w[0]; +#endif + +#ifdef INVERSE_W + iw = fix_inverse32 ( line.w[0] ); +#endif + + getSample_texture ( r0, g0, b0, IT + 0, tofix ( line.t[0][0].x,iw),tofix ( line.t[0][0].y,iw) ); + color_to_fix1 ( a1, r1, g1, b1, dst[i] ); +#ifdef IPOL_C0 + getSample_color ( r2, g2, b2, line.c[0][0],iw ); + + a1 = FIX_POINT_ONE - a1; + dst[i] = fix_to_color ( imulFix ( imulFix ( r0, a1 ) + r1, r2 ), + imulFix ( imulFix ( g0, a1 ) + g1, g2 ), + imulFix ( imulFix ( b0, a1 ) + b1, b2 ) + ); +#else + dst[i] = fix_to_color ( imulFix ( r0, a1) + r0, + imulFix ( g0, a1) + g0, + imulFix ( b0, a1) + b0 + ); + +#endif + + } + +#ifdef IPOL_W + line.w[0] += slopeW; +#endif +#ifdef IPOL_T0 + line.t[0][0] += slopeT[0]; +#endif +#ifdef IPOL_C0 + line.c[0][0] += slopeC[0]; +#endif + } + break; + + case 2: + for ( i = 0; i <= dx; ++i ) + { +#ifdef CMP_W + if ( line.w[0] == z[i] ) +#endif + + { + +#ifdef WRITE_W + z[i] = line.w[0]; +#endif + +#ifdef INVERSE_W + iw = fix_inverse32 ( line.w[0] ); +#endif + getSample_texture ( r0, g0, b0, IT + 0, tofix ( line.t[0][0].x,iw),tofix ( line.t[0][0].y,iw) ); + color_to_fix1 ( a1, r1, g1, b1, dst[i] ); + +#ifdef IPOL_C0 + getSample_color ( r2, g2, b2, line.c[0][0],iw ); + + a1 = FIX_POINT_ONE - a1; + dst[i] = fix_to_color ( imulFix ( imulFix ( r0, a1 ) + r1, r2 ), + imulFix ( imulFix ( g0, a1 ) + g1, g2 ), + imulFix ( imulFix ( b0, a1 ) + b1, b2 ) + ); +#else + dst[i] = fix_to_color ( imulFix ( r0, a1) + r0, + imulFix ( g0, a1) + g0, + imulFix ( b0, a1) + b0 + ); + +#endif + + } + +#ifdef IPOL_W + line.w[0] += slopeW; +#endif +#ifdef IPOL_T0 + line.t[0][0] += slopeT[0]; +#endif +#ifdef IPOL_C0 + line.c[0][0] += slopeC[0]; +#endif + }break; + } // zcompare + +} + +/*! +*/ +void CTRTextureBlend::fragment_src_alpha_one () +{ + tVideoSample *dst; + +#ifdef USE_ZBUFFER + fp24 *z; +#endif + + s32 xStart; + s32 xEnd; + s32 dx; + + +#ifdef SUBTEXEL + f32 subPixel; +#endif + +#ifdef IPOL_Z + f32 slopeZ; +#endif +#ifdef IPOL_W + fp24 slopeW; +#endif +#ifdef IPOL_C0 + sVec4 slopeC[MATERIAL_MAX_COLORS]; +#endif +#ifdef IPOL_T0 + sVec2 slopeT[BURNING_MATERIAL_MAX_TEXTURES]; +#endif + + // apply top-left fill-convention, left + xStart = core::ceil32( line.x[0] ); + xEnd = core::ceil32( line.x[1] ) - 1; + + dx = xEnd - xStart; + + if ( dx < 0 ) + return; + + // slopes + const f32 invDeltaX = core::reciprocal_approxim ( line.x[1] - line.x[0] ); + +#ifdef IPOL_Z + slopeZ = (line.z[1] - line.z[0]) * invDeltaX; +#endif +#ifdef IPOL_W + slopeW = (line.w[1] - line.w[0]) * invDeltaX; +#endif +#ifdef IPOL_C0 + slopeC[0] = (line.c[0][1] - line.c[0][0]) * invDeltaX; +#endif +#ifdef IPOL_T0 + slopeT[0] = (line.t[0][1] - line.t[0][0]) * invDeltaX; +#endif +#ifdef IPOL_T1 + slopeT[1] = (line.t[1][1] - line.t[1][0]) * invDeltaX; +#endif + +#ifdef SUBTEXEL + subPixel = ( (f32) xStart ) - line.x[0]; +#ifdef IPOL_Z + line.z[0] += slopeZ * subPixel; +#endif +#ifdef IPOL_W + line.w[0] += slopeW * subPixel; +#endif +#ifdef IPOL_C0 + line.c[0][0] += slopeC[0] * subPixel; +#endif +#ifdef IPOL_T0 + line.t[0][0] += slopeT[0] * subPixel; +#endif +#ifdef IPOL_T1 + line.t[1][0] += slopeT[1] * subPixel; +#endif +#endif + + dst = (tVideoSample*)RenderTarget->lock() + ( line.y * RenderTarget->getDimension().Width ) + xStart; + +#ifdef USE_ZBUFFER + z = (fp24*) DepthBuffer->lock() + ( line.y * RenderTarget->getDimension().Width ) + xStart; +#endif + + + f32 iw = FIX_POINT_F32_MUL; + + tFixPointu a0, r0, g0, b0; + tFixPoint r1, g1, b1; + tFixPoint r2, g2, b2; + + s32 i; + + switch ( ZCompare ) + { + case 1: + for ( i = 0; i <= dx; ++i ) + { +#ifdef CMP_W + if ( line.w[0] >= z[i] ) +#endif + + { + + +#ifdef INVERSE_W + iw = fix_inverse32 ( line.w[0] ); +#endif + + getSample_texture ( a0, r0, g0, b0, IT + 0, tofix ( line.t[0][0].x,iw),tofix ( line.t[0][0].y,iw) ); + if ( a0 > 0 ) + { + a0 >>= 8; + + color_to_fix ( r1, g1, b1, dst[i] ); + +#ifdef IPOL_C0 + getSample_color ( r2, g2, b2, line.c[0][0],iw ); + + dst[i] = fix4_to_color ( a0, + clampfix_maxcolor ( imulFix (r0,a0 ) + r1), + clampfix_maxcolor ( imulFix (g0,a0 ) + g1), + clampfix_maxcolor ( imulFix (b0,a0 ) + b1) + ); + +/* + a0 >>= 8; + dst[i] = fix4_to_color ( a0, + imulFix ( imulFix ( r0, a0 ) + r1, r2 ), + imulFix ( imulFix ( g0, a0 ) + g1, g2 ), + imulFix ( imulFix ( b0, a0 ) + b1, b2 ) + ); +*/ +#else + dst[i] = fix4_to_color ( a0, + clampfix_maxcolor ( imulFix (r0,a0 ) + r1 ), + clampfix_maxcolor ( imulFix (g0,a0 ) + g1 ), + clampfix_maxcolor ( imulFix (b0,a0 ) + b1 ) + ); + +#endif + +#ifdef WRITE_W + //z[i] = line.w[0]; +#endif + } + + } + +#ifdef IPOL_W + line.w[0] += slopeW; +#endif +#ifdef IPOL_T0 + line.t[0][0] += slopeT[0]; +#endif +#ifdef IPOL_C0 + line.c[0][0] += slopeC[0]; +#endif + } + break; + + case 2: + for ( i = 0; i <= dx; ++i ) + { +#ifdef CMP_W + if ( line.w[0] == z[i] ) +#endif + { + +#ifdef INVERSE_W + iw = fix_inverse32 ( line.w[0] ); +#endif + + getSample_texture ( a0, r0, g0, b0, IT + 0, tofix ( line.t[0][0].x,iw),tofix ( line.t[0][0].y,iw) ); + if ( a0 > 0 ) + { + a0 >>= 8; + + color_to_fix ( r1, g1, b1, dst[i] ); + +#ifdef IPOL_C0 + getSample_color ( r2, g2, b2, line.c[0][0],iw ); + + dst[i] = fix4_to_color ( a0, + clampfix_maxcolor ( imulFix ( imulFix (r0,a0 ) + r1, r2 ) ), + clampfix_maxcolor ( imulFix ( imulFix (g0,a0 ) + g1, g2 ) ), + clampfix_maxcolor ( imulFix ( imulFix (b0,a0 ) + b1, b2 ) ) + ); + +/* + a0 >>= 8; + dst[i] = fix4_to_color ( a0, + imulFix ( imulFix ( r0, a0 ) + r1, r2 ), + imulFix ( imulFix ( g0, a0 ) + g1, g2 ), + imulFix ( imulFix ( b0, a0 ) + b1, b2 ) + ); +*/ +#else + dst[i] = fix4_to_color ( a0, + clampfix_maxcolor ( imulFix (r0,a0 ) + r1 ), + clampfix_maxcolor ( imulFix (g0,a0 ) + g1 ), + clampfix_maxcolor ( imulFix (b0,a0 ) + b1 ) + ); + +#endif + +#ifdef WRITE_W + z[i] = line.w[0]; +#endif + } + } +#ifdef IPOL_W + line.w[0] += slopeW; +#endif +#ifdef IPOL_T0 + line.t[0][0] += slopeT[0]; +#endif +#ifdef IPOL_C0 + line.c[0][0] += slopeC[0]; +#endif + }break; + } // zcompare + +} + + +/*! +*/ +void CTRTextureBlend::fragment_dst_color_one_minus_dst_alpha () +{ + tVideoSample *dst; + +#ifdef USE_ZBUFFER + fp24 *z; +#endif + + s32 xStart; + s32 xEnd; + s32 dx; + + +#ifdef SUBTEXEL + f32 subPixel; +#endif + +#ifdef IPOL_Z + f32 slopeZ; +#endif +#ifdef IPOL_W + fp24 slopeW; +#endif +#ifdef IPOL_C0 + sVec4 slopeC[MATERIAL_MAX_COLORS]; +#endif +#ifdef IPOL_T0 + sVec2 slopeT[BURNING_MATERIAL_MAX_TEXTURES]; +#endif + + // apply top-left fill-convention, left + xStart = core::ceil32( line.x[0] ); + xEnd = core::ceil32( line.x[1] ) - 1; + + dx = xEnd - xStart; + + if ( dx < 0 ) + return; + + // slopes + const f32 invDeltaX = core::reciprocal_approxim ( line.x[1] - line.x[0] ); + +#ifdef IPOL_Z + slopeZ = (line.z[1] - line.z[0]) * invDeltaX; +#endif +#ifdef IPOL_W + slopeW = (line.w[1] - line.w[0]) * invDeltaX; +#endif +#ifdef IPOL_C0 + slopeC[0] = (line.c[0][1] - line.c[0][0]) * invDeltaX; +#endif +#ifdef IPOL_T0 + slopeT[0] = (line.t[0][1] - line.t[0][0]) * invDeltaX; +#endif +#ifdef IPOL_T1 + slopeT[1] = (line.t[1][1] - line.t[1][0]) * invDeltaX; +#endif + +#ifdef SUBTEXEL + subPixel = ( (f32) xStart ) - line.x[0]; +#ifdef IPOL_Z + line.z[0] += slopeZ * subPixel; +#endif +#ifdef IPOL_W + line.w[0] += slopeW * subPixel; +#endif +#ifdef IPOL_C0 + line.c[0][0] += slopeC[0] * subPixel; +#endif +#ifdef IPOL_T0 + line.t[0][0] += slopeT[0] * subPixel; +#endif +#ifdef IPOL_T1 + line.t[1][0] += slopeT[1] * subPixel; +#endif +#endif + + dst = (tVideoSample*)RenderTarget->lock() + ( line.y * RenderTarget->getDimension().Width ) + xStart; + +#ifdef USE_ZBUFFER + z = (fp24*) DepthBuffer->lock() + ( line.y * RenderTarget->getDimension().Width ) + xStart; +#endif + + + f32 iw = FIX_POINT_F32_MUL; + + tFixPoint r0, g0, b0; + tFixPoint a1, r1, g1, b1; + tFixPoint r2, g2, b2; + + s32 i; + + switch ( ZCompare ) + { + case 1: + for ( i = 0; i <= dx; ++i ) + { +#ifdef CMP_W + if ( line.w[0] >= z[i] ) +#endif + + { + +#ifdef WRITE_W + z[i] = line.w[0]; +#endif + +#ifdef INVERSE_W + iw = fix_inverse32 ( line.w[0] ); +#endif + + getSample_texture ( r0, g0, b0, IT + 0, tofix ( line.t[0][0].x,iw),tofix ( line.t[0][0].y,iw) ); + color_to_fix1 ( a1, r1, g1, b1, dst[i] ); +#ifdef IPOL_C0 + getSample_color ( r2, g2, b2, line.c[0][0],iw ); + + a1 = FIX_POINT_ONE - a1; + dst[i] = fix_to_color ( imulFix ( imulFix ( r1, r0 + a1 ), r2 ), + imulFix ( imulFix ( g1, g0 + a1 ), g2 ), + imulFix ( imulFix ( b1, b0 + a1 ), b2 ) + ); +#else + dst[i] = fix_to_color ( imulFix ( r1, r0 + a1 ), + imulFix ( g1, g0 + a1 ), + imulFix ( b1, b0 + a1 ) + ); + +#endif + + } + +#ifdef IPOL_W + line.w[0] += slopeW; +#endif +#ifdef IPOL_T0 + line.t[0][0] += slopeT[0]; +#endif +#ifdef IPOL_C0 + line.c[0][0] += slopeC[0]; +#endif + } + break; + + case 2: + for ( i = 0; i <= dx; ++i ) + { +#ifdef CMP_W + if ( line.w[0] == z[i] ) +#endif + + { + +#ifdef WRITE_W + z[i] = line.w[0]; +#endif + +#ifdef INVERSE_W + iw = fix_inverse32 ( line.w[0] ); +#endif + getSample_texture ( r0, g0, b0, IT + 0, tofix ( line.t[0][0].x,iw),tofix ( line.t[0][0].y,iw) ); + color_to_fix1 ( a1, r1, g1, b1, dst[i] ); + +#ifdef IPOL_C0 + getSample_color ( r2, g2, b2, line.c[0][0],iw ); + + a1 = FIX_POINT_ONE - a1; + dst[i] = fix_to_color ( imulFix ( imulFix ( r1, r0 + a1 ), r2 ), + imulFix ( imulFix ( g1, g0 + a1 ), g2 ), + imulFix ( imulFix ( b1, b0 + a1 ), b2 ) + ); +#else + dst[i] = fix_to_color ( imulFix ( r1, r0 + a1 ), + imulFix ( g1, g0 + a1 ), + imulFix ( b1, b0 + a1 ) + ); + +#endif + + } + +#ifdef IPOL_W + line.w[0] += slopeW; +#endif +#ifdef IPOL_T0 + line.t[0][0] += slopeT[0]; +#endif +#ifdef IPOL_C0 + line.c[0][0] += slopeC[0]; +#endif + }break; + } // zcompare + +} + +/*! +*/ +void CTRTextureBlend::fragment_dst_color_zero () +{ + tVideoSample *dst; + +#ifdef USE_ZBUFFER + fp24 *z; +#endif + + s32 xStart; + s32 xEnd; + s32 dx; + + +#ifdef SUBTEXEL + f32 subPixel; +#endif + +#ifdef IPOL_Z + f32 slopeZ; +#endif +#ifdef IPOL_W + fp24 slopeW; +#endif +#ifdef IPOL_C0 + sVec4 slopeC[MATERIAL_MAX_COLORS]; +#endif +#ifdef IPOL_T0 + sVec2 slopeT[BURNING_MATERIAL_MAX_TEXTURES]; +#endif + + // apply top-left fill-convention, left + xStart = core::ceil32( line.x[0] ); + xEnd = core::ceil32( line.x[1] ) - 1; + + dx = xEnd - xStart; + + if ( dx < 0 ) + return; + + // slopes + const f32 invDeltaX = core::reciprocal_approxim ( line.x[1] - line.x[0] ); + +#ifdef IPOL_Z + slopeZ = (line.z[1] - line.z[0]) * invDeltaX; +#endif +#ifdef IPOL_W + slopeW = (line.w[1] - line.w[0]) * invDeltaX; +#endif +#ifdef IPOL_C0 + slopeC[0] = (line.c[0][1] - line.c[0][0]) * invDeltaX; +#endif +#ifdef IPOL_T0 + slopeT[0] = (line.t[0][1] - line.t[0][0]) * invDeltaX; +#endif +#ifdef IPOL_T1 + slopeT[1] = (line.t[1][1] - line.t[1][0]) * invDeltaX; +#endif + +#ifdef SUBTEXEL + subPixel = ( (f32) xStart ) - line.x[0]; +#ifdef IPOL_Z + line.z[0] += slopeZ * subPixel; +#endif +#ifdef IPOL_W + line.w[0] += slopeW * subPixel; +#endif +#ifdef IPOL_C0 + line.c[0][0] += slopeC[0] * subPixel; +#endif +#ifdef IPOL_T0 + line.t[0][0] += slopeT[0] * subPixel; +#endif +#ifdef IPOL_T1 + line.t[1][0] += slopeT[1] * subPixel; +#endif +#endif + + dst = (tVideoSample*)RenderTarget->lock() + ( line.y * RenderTarget->getDimension().Width ) + xStart; + +#ifdef USE_ZBUFFER + z = (fp24*) DepthBuffer->lock() + ( line.y * RenderTarget->getDimension().Width ) + xStart; +#endif + + + f32 iw = FIX_POINT_F32_MUL; + + tFixPoint r0, g0, b0; + tFixPoint r1, g1, b1; + tFixPoint r2, g2, b2; + + s32 i; + + switch ( ZCompare ) + { + case 1: + for ( i = 0; i <= dx; ++i ) + { +#ifdef CMP_W + if ( line.w[0] >= z[i] ) +#endif + + { + +#ifdef WRITE_W + z[i] = line.w[0]; +#endif + +#ifdef INVERSE_W + iw = fix_inverse32 ( line.w[0] ); +#endif + + getSample_texture ( r0, g0, b0, IT + 0, tofix ( line.t[0][0].x,iw),tofix ( line.t[0][0].y,iw) ); + color_to_fix1 ( r1, g1, b1, dst[i] ); + +#ifdef IPOL_C0 + getSample_color ( r2, g2, b2, line.c[0][0],iw ); + + dst[i] = fix_to_color ( imulFix ( imulFix ( r0, r1 ), r2 ), + imulFix ( imulFix ( g0, g1 ), g2 ), + imulFix ( imulFix ( b0, b1 ), b2 ) ); +#else + dst[i] = fix_to_color ( imulFix ( r0, r1 ), + imulFix ( g0, g1 ), + imulFix ( b0, b1 ) + ); + +#endif + + } + +#ifdef IPOL_W + line.w[0] += slopeW; +#endif +#ifdef IPOL_T0 + line.t[0][0] += slopeT[0]; +#endif +#ifdef IPOL_C0 + line.c[0][0] += slopeC[0]; +#endif + } + break; + + case 2: + for ( i = 0; i <= dx; ++i ) + { +#ifdef CMP_W + if ( line.w[0] == z[i] ) +#endif + + { + +#ifdef WRITE_W + z[i] = line.w[0]; +#endif + +#ifdef INVERSE_W + iw = fix_inverse32 ( line.w[0] ); +#endif + getSample_texture ( r0, g0, b0, IT + 0, tofix ( line.t[0][0].x,iw),tofix ( line.t[0][0].y,iw) ); + color_to_fix1 ( r1, g1, b1, dst[i] ); + +#ifdef IPOL_C0 + getSample_color ( r2, g2, b2, line.c[0][0],iw ); + + dst[i] = fix_to_color ( imulFix ( imulFix ( r0, r1 ), r2 ), + imulFix ( imulFix ( g0, g1 ), g2 ), + imulFix ( imulFix ( b0, b1 ), b2 ) + ); +#else + dst[i] = fix_to_color ( imulFix ( r0, r1 ), + imulFix ( g0, g1 ), + imulFix ( b0, b1 ) + ); + +#endif + + } + +#ifdef IPOL_W + line.w[0] += slopeW; +#endif +#ifdef IPOL_T0 + line.t[0][0] += slopeT[0]; +#endif +#ifdef IPOL_C0 + line.c[0][0] += slopeC[0]; +#endif + }break; + } // zcompare + +} + +/*! +*/ +void CTRTextureBlend::fragment_dst_color_one () +{ + tVideoSample *dst; + +#ifdef USE_ZBUFFER + fp24 *z; +#endif + + s32 xStart; + s32 xEnd; + s32 dx; + + +#ifdef SUBTEXEL + f32 subPixel; +#endif + +#ifdef IPOL_Z + f32 slopeZ; +#endif +#ifdef IPOL_W + fp24 slopeW; +#endif +#ifdef IPOL_C0 + sVec4 slopeC[MATERIAL_MAX_COLORS]; +#endif +#ifdef IPOL_T0 + sVec2 slopeT[BURNING_MATERIAL_MAX_TEXTURES]; +#endif + + // apply top-left fill-convention, left + xStart = core::ceil32( line.x[0] ); + xEnd = core::ceil32( line.x[1] ) - 1; + + dx = xEnd - xStart; + + if ( dx < 0 ) + return; + + // slopes + const f32 invDeltaX = core::reciprocal_approxim ( line.x[1] - line.x[0] ); + +#ifdef IPOL_Z + slopeZ = (line.z[1] - line.z[0]) * invDeltaX; +#endif +#ifdef IPOL_W + slopeW = (line.w[1] - line.w[0]) * invDeltaX; +#endif +#ifdef IPOL_C0 + slopeC[0] = (line.c[0][1] - line.c[0][0]) * invDeltaX; +#endif +#ifdef IPOL_T0 + slopeT[0] = (line.t[0][1] - line.t[0][0]) * invDeltaX; +#endif +#ifdef IPOL_T1 + slopeT[1] = (line.t[1][1] - line.t[1][0]) * invDeltaX; +#endif + +#ifdef SUBTEXEL + subPixel = ( (f32) xStart ) - line.x[0]; +#ifdef IPOL_Z + line.z[0] += slopeZ * subPixel; +#endif +#ifdef IPOL_W + line.w[0] += slopeW * subPixel; +#endif +#ifdef IPOL_C0 + line.c[0][0] += slopeC[0] * subPixel; +#endif +#ifdef IPOL_T0 + line.t[0][0] += slopeT[0] * subPixel; +#endif +#ifdef IPOL_T1 + line.t[1][0] += slopeT[1] * subPixel; +#endif +#endif + + dst = (tVideoSample*)RenderTarget->lock() + ( line.y * RenderTarget->getDimension().Width ) + xStart; + +#ifdef USE_ZBUFFER + z = (fp24*) DepthBuffer->lock() + ( line.y * RenderTarget->getDimension().Width ) + xStart; +#endif + + + f32 iw = FIX_POINT_F32_MUL; + + tFixPoint r0, g0, b0; + tFixPoint r1, g1, b1; + tFixPoint r2, g2, b2; + + s32 i; + + switch ( ZCompare ) + { + case 1: + for ( i = 0; i <= dx; ++i ) + { +#ifdef CMP_W + if ( line.w[0] >= z[i] ) +#endif + + { + +#ifdef WRITE_W + z[i] = line.w[0]; +#endif + +#ifdef INVERSE_W + iw = fix_inverse32 ( line.w[0] ); +#endif + + getSample_texture ( r0, g0, b0, IT + 0, tofix ( line.t[0][0].x,iw),tofix ( line.t[0][0].y,iw) ); + color_to_fix ( r1, g1, b1, dst[i] ); +#ifdef IPOL_C0 + getSample_color ( r2, g2, b2, line.c[0][0],iw ); + + dst[i] = fix_to_color ( clampfix_maxcolor ( imulFix_tex1 ( r0, r1 ) + r1 ), + clampfix_maxcolor ( imulFix_tex1 ( g0, g1 ) + g1 ), + clampfix_maxcolor ( imulFix_tex1 ( b0, b1 ) + b1 ) + ); + +#else + dst[i] = fix_to_color ( clampfix_maxcolor ( imulFix_tex1 ( r0, r1 ) + r1 ), + clampfix_maxcolor ( imulFix_tex1 ( g0, g1 ) + g1 ), + clampfix_maxcolor ( imulFix_tex1 ( b0, b1 ) + b1 ) + ); + +#endif + + } + +#ifdef IPOL_W + line.w[0] += slopeW; +#endif +#ifdef IPOL_T0 + line.t[0][0] += slopeT[0]; +#endif +#ifdef IPOL_C0 + line.c[0][0] += slopeC[0]; +#endif + } + break; + + case 2: + for ( i = 0; i <= dx; ++i ) + { +#ifdef CMP_W + if ( line.w[0] == z[i] ) +#endif + + { + +#ifdef WRITE_W + z[i] = line.w[0]; +#endif + +#ifdef INVERSE_W + iw = fix_inverse32 ( line.w[0] ); +#endif + getSample_texture ( r0, g0, b0, IT + 0, tofix ( line.t[0][0].x,iw),tofix ( line.t[0][0].y,iw) ); + color_to_fix ( r1, g1, b1, dst[i] ); + +#ifdef IPOL_C0 + getSample_color ( r2, g2, b2, line.c[0][0],iw ); + + dst[i] = fix_to_color ( clampfix_maxcolor ( imulFix_tex1 ( r0, r1 ) + r1 ), + clampfix_maxcolor ( imulFix_tex1 ( g0, g1 ) + g1 ), + clampfix_maxcolor ( imulFix_tex1 ( b0, b1 ) + b1 ) + ); + +#else + dst[i] = fix_to_color ( clampfix_maxcolor ( imulFix_tex1 ( r0, r1 ) + r1 ), + clampfix_maxcolor ( imulFix_tex1 ( g0, g1 ) + g1 ), + clampfix_maxcolor ( imulFix_tex1 ( b0, b1 ) + b1 ) + ); + +#endif + + + } + +#ifdef IPOL_W + line.w[0] += slopeW; +#endif +#ifdef IPOL_T0 + line.t[0][0] += slopeT[0]; +#endif +#ifdef IPOL_C0 + line.c[0][0] += slopeC[0]; +#endif + }break; + } // zcompare + +} + +/*! +*/ +void CTRTextureBlend::fragment_zero_one_minus_scr_color () +{ + tVideoSample *dst; + +#ifdef USE_ZBUFFER + fp24 *z; +#endif + + s32 xStart; + s32 xEnd; + s32 dx; + + +#ifdef SUBTEXEL + f32 subPixel; +#endif + +#ifdef IPOL_Z + f32 slopeZ; +#endif +#ifdef IPOL_W + fp24 slopeW; +#endif +#ifdef IPOL_C0 + sVec4 slopeC[MATERIAL_MAX_COLORS]; +#endif +#ifdef IPOL_T0 + sVec2 slopeT[BURNING_MATERIAL_MAX_TEXTURES]; +#endif + + // apply top-left fill-convention, left + xStart = core::ceil32( line.x[0] ); + xEnd = core::ceil32( line.x[1] ) - 1; + + dx = xEnd - xStart; + + if ( dx < 0 ) + return; + + // slopes + const f32 invDeltaX = core::reciprocal_approxim ( line.x[1] - line.x[0] ); + +#ifdef IPOL_Z + slopeZ = (line.z[1] - line.z[0]) * invDeltaX; +#endif +#ifdef IPOL_W + slopeW = (line.w[1] - line.w[0]) * invDeltaX; +#endif +#ifdef IPOL_C0 + slopeC[0] = (line.c[0][1] - line.c[0][0]) * invDeltaX; +#endif +#ifdef IPOL_T0 + slopeT[0] = (line.t[0][1] - line.t[0][0]) * invDeltaX; +#endif +#ifdef IPOL_T1 + slopeT[1] = (line.t[1][1] - line.t[1][0]) * invDeltaX; +#endif + +#ifdef SUBTEXEL + subPixel = ( (f32) xStart ) - line.x[0]; +#ifdef IPOL_Z + line.z[0] += slopeZ * subPixel; +#endif +#ifdef IPOL_W + line.w[0] += slopeW * subPixel; +#endif +#ifdef IPOL_C0 + line.c[0][0] += slopeC[0] * subPixel; +#endif +#ifdef IPOL_T0 + line.t[0][0] += slopeT[0] * subPixel; +#endif +#ifdef IPOL_T1 + line.t[1][0] += slopeT[1] * subPixel; +#endif +#endif + + dst = (tVideoSample*)RenderTarget->lock() + ( line.y * RenderTarget->getDimension().Width ) + xStart; + +#ifdef USE_ZBUFFER + z = (fp24*) DepthBuffer->lock() + ( line.y * RenderTarget->getDimension().Width ) + xStart; +#endif + + + f32 iw = FIX_POINT_F32_MUL; + + tFixPoint r0, g0, b0; + tFixPoint r1, g1, b1; + tFixPoint r2, g2, b2; + + s32 i; + + switch ( ZCompare ) + { + case 1: + for ( i = 0; i <= dx; ++i ) + { +#ifdef CMP_W + if ( line.w[0] >= z[i] ) +#endif + + { + +#ifdef WRITE_W + z[i] = line.w[0]; +#endif + +#ifdef INVERSE_W + iw = fix_inverse32 ( line.w[0] ); +#endif + + getSample_texture ( r0, g0, b0, IT + 0, tofix ( line.t[0][0].x,iw),tofix ( line.t[0][0].y,iw) ); + color_to_fix1 ( r1, g1, b1, dst[i] ); +#ifdef IPOL_C0 + getSample_color ( r2, g2, b2, line.c[0][0],iw ); + + dst[i] = fix_to_color ( imulFix ( FIX_POINT_ONE - r0, r1 ), + imulFix ( FIX_POINT_ONE - g0, g1 ), + imulFix ( FIX_POINT_ONE - b0, b1 ) + ); + +#else + dst[i] = fix_to_color ( imulFix ( FIX_POINT_ONE - r0, r1 ), + imulFix ( FIX_POINT_ONE - g0, g1 ), + imulFix ( FIX_POINT_ONE - b0, b1 ) + ); + +#endif + + } + +#ifdef IPOL_W + line.w[0] += slopeW; +#endif +#ifdef IPOL_T0 + line.t[0][0] += slopeT[0]; +#endif +#ifdef IPOL_C0 + line.c[0][0] += slopeC[0]; +#endif + } + break; + + case 2: + for ( i = 0; i <= dx; ++i ) + { +#ifdef CMP_W + if ( line.w[0] == z[i] ) +#endif + + { + +#ifdef WRITE_W + z[i] = line.w[0]; +#endif + +#ifdef INVERSE_W + iw = fix_inverse32 ( line.w[0] ); +#endif + getSample_texture ( r0, g0, b0, IT + 0, tofix ( line.t[0][0].x,iw),tofix ( line.t[0][0].y,iw) ); + color_to_fix1 ( r1, g1, b1, dst[i] ); +#ifdef IPOL_C0 + getSample_color ( r2, g2, b2, line.c[0][0],iw ); + + dst[i] = fix_to_color ( imulFix ( FIX_POINT_ONE - r0, r1 ), + imulFix ( FIX_POINT_ONE - g0, g1 ), + imulFix ( FIX_POINT_ONE - b0, b1 ) + ); + +#else + dst[i] = fix_to_color ( imulFix ( FIX_POINT_ONE - r0, r1 ), + imulFix ( FIX_POINT_ONE - g0, g1 ), + imulFix ( FIX_POINT_ONE - b0, b1 ) + ); + +#endif + + } + +#ifdef IPOL_W + line.w[0] += slopeW; +#endif +#ifdef IPOL_T0 + line.t[0][0] += slopeT[0]; +#endif +#ifdef IPOL_C0 + line.c[0][0] += slopeC[0]; +#endif + }break; + } // zcompare + +} + + + void CTRTextureBlend::drawTriangle ( const s4DVertex *a,const s4DVertex *b,const s4DVertex *c ) { + if ( 0 == fragmentShader ) + return; + // sort on height, y if ( F32_A_GREATER_B ( a->Pos.y , b->Pos.y ) ) swapVertexPointer(&a, &b); - if ( F32_A_GREATER_B ( a->Pos.y , c->Pos.y ) ) swapVertexPointer(&a, &c); if ( F32_A_GREATER_B ( b->Pos.y , c->Pos.y ) ) swapVertexPointer(&b, &c); + if ( F32_A_GREATER_B ( a->Pos.y , b->Pos.y ) ) swapVertexPointer(&a, &b); // calculate delta y of the edges @@ -334,8 +2034,8 @@ void CTRTextureBlend::drawTriangle ( const s4DVertex *a,const s4DVertex *b,const #endif #ifdef IPOL_C0 - scan.slopeC[0] = (c->Color[0] - a->Color[0]) * scan.invDeltaY[0]; - scan.c[0] = a->Color[0]; + scan.slopeC[0][0] = (c->Color[0] - a->Color[0]) * scan.invDeltaY[0]; + scan.c[0][0] = a->Color[0]; #endif #ifdef IPOL_T0 @@ -356,12 +2056,6 @@ void CTRTextureBlend::drawTriangle ( const s4DVertex *a,const s4DVertex *b,const f32 subPixel; #endif - lockedSurface = (tVideoSample*)RenderTarget->lock(); - -#ifdef USE_ZBUFFER - lockedDepthBuffer = (fp24*) DepthBuffer->lock(); -#endif - #ifdef IPOL_T0 IT[0].data = (tVideoSample*)IT[0].Texture->lock(); #endif @@ -388,8 +2082,8 @@ void CTRTextureBlend::drawTriangle ( const s4DVertex *a,const s4DVertex *b,const #endif #ifdef IPOL_C0 - scan.slopeC[1] = (b->Color[0] - a->Color[0]) * scan.invDeltaY[1]; - scan.c[1] = a->Color[0]; + scan.slopeC[0][1] = (b->Color[0] - a->Color[0]) * scan.invDeltaY[1]; + scan.c[0][1] = a->Color[0]; #endif #ifdef IPOL_T0 @@ -424,8 +2118,8 @@ void CTRTextureBlend::drawTriangle ( const s4DVertex *a,const s4DVertex *b,const #endif #ifdef IPOL_C0 - scan.c[0] += scan.slopeC[0] * subPixel; - scan.c[1] += scan.slopeC[1] * subPixel; + scan.c[0][0] += scan.slopeC[0][0] * subPixel; + scan.c[0][1] += scan.slopeC[0][1] * subPixel; #endif #ifdef IPOL_T0 @@ -457,8 +2151,8 @@ void CTRTextureBlend::drawTriangle ( const s4DVertex *a,const s4DVertex *b,const #endif #ifdef IPOL_C0 - line.c[scan.left] = scan.c[0]; - line.c[scan.right] = scan.c[1]; + line.c[0][scan.left] = scan.c[0][0]; + line.c[0][scan.right] = scan.c[0][1]; #endif #ifdef IPOL_T0 @@ -472,7 +2166,7 @@ void CTRTextureBlend::drawTriangle ( const s4DVertex *a,const s4DVertex *b,const #endif // render a scanline - scanline_bilinear ( ); + (this->*fragmentShader) (); scan.x[0] += scan.slopeX[0]; scan.x[1] += scan.slopeX[1]; @@ -488,8 +2182,8 @@ void CTRTextureBlend::drawTriangle ( const s4DVertex *a,const s4DVertex *b,const #endif #ifdef IPOL_C0 - scan.c[0] += scan.slopeC[0]; - scan.c[1] += scan.slopeC[1]; + scan.c[0][0] += scan.slopeC[0][0]; + scan.c[0][1] += scan.slopeC[0][1]; #endif #ifdef IPOL_T0 @@ -521,7 +2215,7 @@ void CTRTextureBlend::drawTriangle ( const s4DVertex *a,const s4DVertex *b,const scan.w[0] = a->Pos.w + scan.slopeW[0] * temp[0]; #endif #ifdef IPOL_C0 - scan.c[0] = a->Color[0] + scan.slopeC[0] * temp[0]; + scan.c[0][0] = a->Color[0] + scan.slopeC[0][0] * temp[0]; #endif #ifdef IPOL_T0 scan.t[0][0] = a->Tex[0] + scan.slopeT[0][0] * temp[0]; @@ -547,8 +2241,8 @@ void CTRTextureBlend::drawTriangle ( const s4DVertex *a,const s4DVertex *b,const #endif #ifdef IPOL_C0 - scan.slopeC[1] = (c->Color[0] - b->Color[0]) * scan.invDeltaY[2]; - scan.c[1] = b->Color[0]; + scan.slopeC[0][1] = (c->Color[0] - b->Color[0]) * scan.invDeltaY[2]; + scan.c[0][1] = b->Color[0]; #endif #ifdef IPOL_T0 @@ -584,8 +2278,8 @@ void CTRTextureBlend::drawTriangle ( const s4DVertex *a,const s4DVertex *b,const #endif #ifdef IPOL_C0 - scan.c[0] += scan.slopeC[0] * subPixel; - scan.c[1] += scan.slopeC[1] * subPixel; + scan.c[0][0] += scan.slopeC[0][0] * subPixel; + scan.c[0][1] += scan.slopeC[0][1] * subPixel; #endif #ifdef IPOL_T0 @@ -617,8 +2311,8 @@ void CTRTextureBlend::drawTriangle ( const s4DVertex *a,const s4DVertex *b,const #endif #ifdef IPOL_C0 - line.c[scan.left] = scan.c[0]; - line.c[scan.right] = scan.c[1]; + line.c[0][scan.left] = scan.c[0][0]; + line.c[0][scan.right] = scan.c[0][1]; #endif #ifdef IPOL_T0 @@ -632,7 +2326,7 @@ void CTRTextureBlend::drawTriangle ( const s4DVertex *a,const s4DVertex *b,const #endif // render a scanline - scanline_bilinear ( ); + (this->*fragmentShader) (); scan.x[0] += scan.slopeX[0]; scan.x[1] += scan.slopeX[1]; @@ -648,8 +2342,8 @@ void CTRTextureBlend::drawTriangle ( const s4DVertex *a,const s4DVertex *b,const #endif #ifdef IPOL_C0 - scan.c[0] += scan.slopeC[0]; - scan.c[1] += scan.slopeC[1]; + scan.c[0][0] += scan.slopeC[0][0]; + scan.c[0][1] += scan.slopeC[0][1]; #endif #ifdef IPOL_T0 @@ -682,6 +2376,7 @@ void CTRTextureBlend::drawTriangle ( const s4DVertex *a,const s4DVertex *b,const } + } // end namespace video } // end namespace irr diff --git a/source/Irrlicht/CTRTextureDetailMap2.cpp b/source/Irrlicht/CTRTextureDetailMap2.cpp index 122a139a..1ae47ff4 100644 --- a/source/Irrlicht/CTRTextureDetailMap2.cpp +++ b/source/Irrlicht/CTRTextureDetailMap2.cpp @@ -184,10 +184,10 @@ void CTRTextureDetailMap2::scanline_bilinear () #endif #endif - dst = lockedSurface + ( line.y * RenderTarget->getDimension().Width ) + xStart; + dst = (tVideoSample*)RenderTarget->lock() + ( line.y * RenderTarget->getDimension().Width ) + xStart; #ifdef USE_ZBUFFER - z = lockedDepthBuffer + ( line.y * RenderTarget->getDimension().Width ) + xStart; + z = (fp24*) DepthBuffer->lock() + ( line.y * RenderTarget->getDimension().Width ) + xStart; #endif @@ -216,16 +216,16 @@ void CTRTextureDetailMap2::scanline_bilinear () #ifdef INVERSE_W inversew = fix_inverse32 ( line.w[0] ); - tx0 = f32_to_fixPoint ( line.t[0][0].x,inversew); - ty0 = f32_to_fixPoint ( line.t[0][0].y,inversew); - tx1 = f32_to_fixPoint ( line.t[1][0].x,inversew); - ty1 = f32_to_fixPoint ( line.t[1][0].y,inversew); + tx0 = tofix ( line.t[0][0].x,inversew); + ty0 = tofix ( line.t[0][0].y,inversew); + tx1 = tofix ( line.t[1][0].x,inversew); + ty1 = tofix ( line.t[1][0].y,inversew); #else - tx0 = f32_to_fixPoint ( line.t[0][0].x ); - ty0 = f32_to_fixPoint ( line.t[0][0].y ); - tx1 = f32_to_fixPoint ( line.t[1][0].x ); - ty1 = f32_to_fixPoint ( line.t[1][0].y ); + tx0 = tofix ( line.t[0][0].x ); + ty0 = tofix ( line.t[0][0].y ); + tx1 = tofix ( line.t[1][0].x ); + ty1 = tofix ( line.t[1][0].y ); #endif getSample_texture ( r0, g0, b0, &IT[0], tx0,ty0 ); getSample_texture ( r1, g1, b1, &IT[1], tx1,ty1 ); @@ -275,8 +275,8 @@ void CTRTextureDetailMap2::drawTriangle ( const s4DVertex *a,const s4DVertex *b, { // sort on height, y if ( F32_A_GREATER_B ( a->Pos.y , b->Pos.y ) ) swapVertexPointer(&a, &b); - if ( F32_A_GREATER_B ( a->Pos.y , c->Pos.y ) ) swapVertexPointer(&a, &c); if ( F32_A_GREATER_B ( b->Pos.y , c->Pos.y ) ) swapVertexPointer(&b, &c); + if ( F32_A_GREATER_B ( a->Pos.y , b->Pos.y ) ) swapVertexPointer(&a, &b); // calculate delta y of the edges @@ -335,12 +335,6 @@ void CTRTextureDetailMap2::drawTriangle ( const s4DVertex *a,const s4DVertex *b, f32 subPixel; #endif - lockedSurface = (tVideoSample*)RenderTarget->lock(); - -#ifdef USE_ZBUFFER - lockedDepthBuffer = (fp24*) DepthBuffer->lock(); -#endif - #ifdef IPOL_T0 IT[0].data = (tVideoSample*)IT[0].Texture->lock(); #endif diff --git a/source/Irrlicht/CTRTextureGouraud2.cpp b/source/Irrlicht/CTRTextureGouraud2.cpp index f4288673..41ab3133 100644 --- a/source/Irrlicht/CTRTextureGouraud2.cpp +++ b/source/Irrlicht/CTRTextureGouraud2.cpp @@ -183,10 +183,10 @@ void CTRTextureGouraud2::scanline_bilinear () #endif #endif - dst = lockedSurface + ( line.y * RenderTarget->getDimension().Width ) + xStart; + dst = (tVideoSample*)RenderTarget->lock() + ( line.y * RenderTarget->getDimension().Width ) + xStart; #ifdef USE_ZBUFFER - z = lockedDepthBuffer + ( line.y * RenderTarget->getDimension().Width ) + xStart; + z = (fp24*) DepthBuffer->lock() + ( line.y * RenderTarget->getDimension().Width ) + xStart; #endif @@ -226,18 +226,18 @@ void CTRTextureGouraud2::scanline_bilinear () #ifdef INVERSE_W inversew = fix_inverse32 ( line.w[0] ); - tx0 = f32_to_fixPoint ( line.t[0][0].x, inversew); - ty0 = f32_to_fixPoint ( line.t[0][0].y, inversew); + tx0 = tofix ( line.t[0][0].x, inversew); + ty0 = tofix ( line.t[0][0].y, inversew); #ifdef IPOL_C0 - r1 = f32_to_fixPoint ( line.c[0][0].y ,inversew ); - g1 = f32_to_fixPoint ( line.c[0][0].z ,inversew ); - b1 = f32_to_fixPoint ( line.c[0][0].w ,inversew ); + r1 = tofix ( line.c[0][0].y ,inversew ); + g1 = tofix ( line.c[0][0].z ,inversew ); + b1 = tofix ( line.c[0][0].w ,inversew ); #endif #else - tx0 = f32_to_fixPoint ( line.t[0][0].x ); - ty0 = f32_to_fixPoint ( line.t[0][0].y ); + tx0 = tofix ( line.t[0][0].x ); + ty0 = tofix ( line.t[0][0].y ); #ifdef IPOL_C0 getTexel_plain2 ( r1, g1, b1, line.c[0][0] ); #endif @@ -287,8 +287,8 @@ void CTRTextureGouraud2::drawTriangle ( const s4DVertex *a,const s4DVertex *b,co { // sort on height, y if ( F32_A_GREATER_B ( a->Pos.y , b->Pos.y ) ) swapVertexPointer(&a, &b); - if ( F32_A_GREATER_B ( a->Pos.y , c->Pos.y ) ) swapVertexPointer(&a, &c); if ( F32_A_GREATER_B ( b->Pos.y , c->Pos.y ) ) swapVertexPointer(&b, &c); + if ( F32_A_GREATER_B ( a->Pos.y , b->Pos.y ) ) swapVertexPointer(&a, &b); // calculate delta y of the edges @@ -348,12 +348,6 @@ void CTRTextureGouraud2::drawTriangle ( const s4DVertex *a,const s4DVertex *b,co f32 subPixel; #endif - lockedSurface = (tVideoSample*)RenderTarget->lock(); - -#ifdef USE_ZBUFFER - lockedDepthBuffer = (fp24*) DepthBuffer->lock(); -#endif - #ifdef IPOL_T0 IT[0].data = (tVideoSample*)IT[0].Texture->lock(); #endif diff --git a/source/Irrlicht/CTRTextureGouraudAdd2.cpp b/source/Irrlicht/CTRTextureGouraudAdd2.cpp index 46363de5..cfa421aa 100644 --- a/source/Irrlicht/CTRTextureGouraudAdd2.cpp +++ b/source/Irrlicht/CTRTextureGouraudAdd2.cpp @@ -183,10 +183,10 @@ void CTRTextureGouraudAdd2::scanline_bilinear () #endif #endif - dst = lockedSurface + ( line.y * RenderTarget->getDimension().Width ) + xStart; + dst = (tVideoSample*)RenderTarget->lock() + ( line.y * RenderTarget->getDimension().Width ) + xStart; #ifdef USE_ZBUFFER - z = lockedDepthBuffer + ( line.y * RenderTarget->getDimension().Width ) + xStart; + z = (fp24*) DepthBuffer->lock() + ( line.y * RenderTarget->getDimension().Width ) + xStart; #endif @@ -204,7 +204,6 @@ void CTRTextureGouraudAdd2::scanline_bilinear () tFixPoint r0, g0, b0; tFixPoint r1, g1, b1; - tFixPoint r2, g2, b2; #endif @@ -219,13 +218,6 @@ void CTRTextureGouraudAdd2::scanline_bilinear () { -#ifdef WRITE_Z - z[i] = line.z[0]; -#endif -#ifdef WRITE_W - z[i] = line.w[0]; -#endif - #ifdef BURNINGVIDEO_RENDERER_FAST @@ -237,14 +229,14 @@ void CTRTextureGouraudAdd2::scanline_bilinear () dst[i] = PixelAdd32 ( dst[i], - getTexel_plain ( &IT[0], d + f32_to_fixPoint ( line.t[0][0].x,inversew), - d + f32_to_fixPoint ( line.t[0][0].y,inversew) ) + getTexel_plain ( &IT[0], d + tofix ( line.t[0][0].x,inversew), + d + tofix ( line.t[0][0].y,inversew) ) ); #else dst[i] = PixelAdd32 ( dst[i], - getTexel_plain ( &IT[0], d + f32_to_fixPoint ( line.t[0][0].x), - d + f32_to_fixPoint ( line.t[0][0].y) ) + getTexel_plain ( &IT[0], d + tofix ( line.t[0][0].x), + d + tofix ( line.t[0][0].y) ) ); #endif @@ -253,21 +245,27 @@ void CTRTextureGouraudAdd2::scanline_bilinear () #ifdef INVERSE_W inversew = fix_inverse32 ( line.w[0] ); - tx0 = f32_to_fixPoint ( line.t[0][0].x,inversew); - ty0 = f32_to_fixPoint ( line.t[0][0].y,inversew); + tx0 = tofix ( line.t[0][0].x,inversew); + ty0 = tofix ( line.t[0][0].y,inversew); #else - tx0 = f32_to_fixPoint ( line.t[0][0].x ); - ty0 = f32_to_fixPoint ( line.t[0][0].y ); + tx0 = tofix ( line.t[0][0].x ); + ty0 = tofix ( line.t[0][0].y ); #endif getSample_texture ( r0, g0, b0, &IT[0], tx0,ty0 ); color_to_fix ( r1, g1, b1, dst[i] ); - r2 = clampfix_maxcolor ( r1 + r0 ); - g2 = clampfix_maxcolor ( g1 + g0 ); - b2 = clampfix_maxcolor ( b1 + b0 ); + dst[i] = fix_to_color ( clampfix_maxcolor ( r1 + r0 ), + clampfix_maxcolor ( g1 + g0 ), + clampfix_maxcolor ( b1 + b0 ) + ); +#endif - dst[i] = fix_to_color ( r2, g2, b2 ); +#ifdef WRITE_Z + z[i] = line.z[0]; +#endif +#ifdef WRITE_W + z[i] = line.w[0]; #endif } @@ -297,8 +295,8 @@ void CTRTextureGouraudAdd2::drawTriangle ( const s4DVertex *a,const s4DVertex *b // sort on height, y if ( F32_A_GREATER_B ( a->Pos.y , b->Pos.y ) ) swapVertexPointer(&a, &b); - if ( F32_A_GREATER_B ( a->Pos.y , c->Pos.y ) ) swapVertexPointer(&a, &c); if ( F32_A_GREATER_B ( b->Pos.y , c->Pos.y ) ) swapVertexPointer(&b, &c); + if ( F32_A_GREATER_B ( a->Pos.y , b->Pos.y ) ) swapVertexPointer(&a, &b); // calculate delta y of the edges scan.invDeltaY[0] = core::reciprocal ( c->Pos.y - a->Pos.y ); @@ -354,12 +352,6 @@ void CTRTextureGouraudAdd2::drawTriangle ( const s4DVertex *a,const s4DVertex *b f32 subPixel; #endif - lockedSurface = (tVideoSample*)RenderTarget->lock(); - -#ifdef USE_ZBUFFER - lockedDepthBuffer = (fp24*) DepthBuffer->lock(); -#endif - #ifdef IPOL_T0 IT[0].data = (tVideoSample*)IT[0].Texture->lock(); #endif diff --git a/source/Irrlicht/CTRTextureGouraudAddNoZ2.cpp b/source/Irrlicht/CTRTextureGouraudAddNoZ2.cpp index 0798f440..2225a86f 100644 --- a/source/Irrlicht/CTRTextureGouraudAddNoZ2.cpp +++ b/source/Irrlicht/CTRTextureGouraudAddNoZ2.cpp @@ -28,9 +28,9 @@ #define SUBTEXEL #define INVERSE_W -//#define USE_ZBUFFER +#define USE_ZBUFFER #define IPOL_W -//#define CMP_W +#define CMP_W //#define WRITE_W //#define IPOL_C0 @@ -110,7 +110,7 @@ void CTRTextureGouraudAddNoZ2::scanline_bilinear () { tVideoSample *dst; -#ifdef IPOL_Z +#ifdef USE_ZBUFFER fp24 *z; #endif @@ -183,10 +183,10 @@ void CTRTextureGouraudAddNoZ2::scanline_bilinear () #endif #endif - dst = lockedSurface + ( line.y * RenderTarget->getDimension().Width ) + xStart; + dst = (tVideoSample*)RenderTarget->lock() + ( line.y * RenderTarget->getDimension().Width ) + xStart; -#ifdef IPOL_Z - z = lockedDepthBuffer + ( line.y * RenderTarget->getDimension().Width ) + xStart; +#ifdef USE_ZBUFFER + z = (fp24*) DepthBuffer->lock() + ( line.y * RenderTarget->getDimension().Width ) + xStart; #endif @@ -206,16 +206,19 @@ void CTRTextureGouraudAddNoZ2::scanline_bilinear () { #ifdef CMP_Z if ( line.z[0] < z[i] ) +#endif +#ifdef CMP_W + if ( line.w[0] >= z[i] ) #endif { #ifdef IPOL_W inversew = fix_inverse32 ( line.w[0] ); - tx0 = f32_to_fixPoint ( line.t[0][0].x,inversew); - ty0 = f32_to_fixPoint ( line.t[0][0].y,inversew); + tx0 = tofix ( line.t[0][0].x,inversew); + ty0 = tofix ( line.t[0][0].y,inversew); #else - tx0 = f32_to_fixPoint ( line.t[0][0].x ); - ty0 = f32_to_fixPoint ( line.t[0][0].y ); + tx0 = tofix ( line.t[0][0].x ); + ty0 = tofix ( line.t[0][0].y ); #endif getSample_texture ( r0, g0, b0, &IT[0], tx0,ty0 ); @@ -231,6 +234,9 @@ void CTRTextureGouraudAddNoZ2::scanline_bilinear () #ifdef WRITE_Z z[i] = line.z[0]; +#endif +#ifdef WRITE_W + z[i] = line.w[0]; #endif } @@ -257,8 +263,8 @@ void CTRTextureGouraudAddNoZ2::drawTriangle ( const s4DVertex *a,const s4DVertex { // sort on height, y if ( F32_A_GREATER_B ( a->Pos.y , b->Pos.y ) ) swapVertexPointer(&a, &b); - if ( F32_A_GREATER_B ( a->Pos.y , c->Pos.y ) ) swapVertexPointer(&a, &c); if ( F32_A_GREATER_B ( b->Pos.y , c->Pos.y ) ) swapVertexPointer(&b, &c); + if ( F32_A_GREATER_B ( a->Pos.y , b->Pos.y ) ) swapVertexPointer(&a, &b); // calculate delta y of the edges @@ -317,12 +323,6 @@ void CTRTextureGouraudAddNoZ2::drawTriangle ( const s4DVertex *a,const s4DVertex f32 subPixel; #endif - lockedSurface = (tVideoSample*)RenderTarget->lock(); - -#ifdef IPOL_Z - lockedDepthBuffer = DepthBuffer->lock(); -#endif - #ifdef IPOL_T0 IT[0].data = (tVideoSample*)IT[0].Texture->lock(); #endif @@ -628,7 +628,7 @@ void CTRTextureGouraudAddNoZ2::drawTriangle ( const s4DVertex *a,const s4DVertex RenderTarget->unlock(); -#ifdef IPOL_Z +#ifdef USE_ZBUFFER DepthBuffer->unlock(); #endif diff --git a/source/Irrlicht/CTRTextureGouraudAlpha.cpp b/source/Irrlicht/CTRTextureGouraudAlpha.cpp index 617f4d68..b7465d8f 100644 --- a/source/Irrlicht/CTRTextureGouraudAlpha.cpp +++ b/source/Irrlicht/CTRTextureGouraudAlpha.cpp @@ -33,7 +33,7 @@ #define CMP_W #define WRITE_W -//#define IPOL_C0 +#define IPOL_C0 #define IPOL_T0 //#define IPOL_T1 @@ -147,7 +147,7 @@ void CTRTextureGouraudAlpha2::scanline_bilinear () fp24 slopeW; #endif #ifdef IPOL_C0 - sVec4 slopeC; + sVec4 slopeC[MATERIAL_MAX_COLORS]; #endif #ifdef IPOL_T0 sVec2 slopeT[BURNING_MATERIAL_MAX_TEXTURES]; @@ -172,7 +172,7 @@ void CTRTextureGouraudAlpha2::scanline_bilinear () slopeW = (line.w[1] - line.w[0]) * invDeltaX; #endif #ifdef IPOL_C0 - slopeC = (line.c[1] - line.c[0]) * invDeltaX; + slopeC[0] = (line.c[0][1] - line.c[0][0]) * invDeltaX; #endif #ifdef IPOL_T0 slopeT[0] = (line.t[0][1] - line.t[0][0]) * invDeltaX; @@ -190,7 +190,7 @@ void CTRTextureGouraudAlpha2::scanline_bilinear () line.w[0] += slopeW * subPixel; #endif #ifdef IPOL_C0 - line.c[0] += slopeC * subPixel; + line.c[0][0] += slopeC[0] * subPixel; #endif #ifdef IPOL_T0 line.t[0][0] += slopeT[0] * subPixel; @@ -200,10 +200,10 @@ void CTRTextureGouraudAlpha2::scanline_bilinear () #endif #endif - dst = lockedSurface + ( line.y * RenderTarget->getDimension().Width ) + xStart; + dst = (tVideoSample*)RenderTarget->lock() + ( line.y * RenderTarget->getDimension().Width ) + xStart; #ifdef USE_ZBUFFER - z = lockedDepthBuffer + ( line.y * RenderTarget->getDimension().Width ) + xStart; + z = (fp24*) DepthBuffer->lock() + ( line.y * RenderTarget->getDimension().Width ) + xStart; #endif @@ -215,10 +215,14 @@ void CTRTextureGouraudAlpha2::scanline_bilinear () u32 dIndex = ( line.y & 3 ) << 2; #else - tFixPointu a0; - tFixPointu r0, g0, b0; + tFixPoint a0; + tFixPoint r0, g0, b0; #endif +#ifdef IPOL_C0 + tFixPoint r1, g1, b1; + tFixPoint r2, g2, b2; +#endif for ( s32 i = 0; i <= dx; ++i ) { @@ -239,20 +243,20 @@ void CTRTextureGouraudAlpha2::scanline_bilinear () inversew = fix_inverse32 ( line.w[0] ); - u32 argb = getTexel_plain ( &IT[0], d + f32_to_fixPoint ( line.t[0][0].x,inversew), - d + f32_to_fixPoint ( line.t[0][0].y,inversew) + u32 argb = getTexel_plain ( &IT[0], d + tofix ( line.t[0][0].x,inversew), + d + tofix ( line.t[0][0].y,inversew) ); #else - u32 argb = getTexel_plain ( &IT[0], d + f32_to_fixPoint ( line.t[0][0].x), - d + f32_to_fixPoint ( line.t[0][0].y) + u32 argb = getTexel_plain ( &IT[0], d + tofix ( line.t[0][0].x), + d + tofix ( line.t[0][0].y) ); #endif const u32 alpha = ( argb >> 24 ); - if ( alpha >= AlphaRef ) + if ( alpha > AlphaRef ) { #ifdef WRITE_Z z[i] = line.z[0]; @@ -267,15 +271,21 @@ void CTRTextureGouraudAlpha2::scanline_bilinear () #else +#ifdef INVERSE_W inversew = fix_inverse32 ( line.w[0] ); - - getSample_texture ( a0, r0, g0, b0, + getSample_texture ( (tFixPointu&) a0, (tFixPointu&) r0, (tFixPointu&)g0, (tFixPointu&)b0, &IT[0], - f32_to_fixPoint ( line.t[0][0].x,inversew), - f32_to_fixPoint ( line.t[0][0].y,inversew) + tofix ( line.t[0][0].x,inversew), + tofix ( line.t[0][0].y,inversew) ); - - if ( a0 >= AlphaRef ) +#else + getSample_texture ( (tFixPointu&) a0, (tFixPointu&) r0, (tFixPointu&)g0, (tFixPointu&)b0, + &IT[0], + tofix ( line.t[0][0].x), + tofix ( line.t[0][0].y) + ); +#endif + if ( (tFixPointu) a0 > AlphaRef ) { #ifdef WRITE_Z z[i] = line.z[0]; @@ -284,10 +294,40 @@ void CTRTextureGouraudAlpha2::scanline_bilinear () z[i] = line.w[0]; #endif +#ifdef INVERSE_W + getSample_color ( r2, g2, b2, line.c[0][0], inversew ); +#else + getSample_color ( r2, g2, b2, line.c[0][0] ); +#endif + r0 = imulFix ( r0, r2 ); + g0 = imulFix ( g0, g2 ); + b0 = imulFix ( b0, b2 ); + + color_to_fix ( r1, g1, b1, dst[i] ); + + a0 >>= 8; + + r2 = r1 + imulFix ( a0, r0 - r1 ); + g2 = g1 + imulFix ( a0, g0 - g1 ); + b2 = b1 + imulFix ( a0, b0 - b1 ); + dst[i] = fix4_to_color ( a0, r2, g2, b2 ); + +/* dst[i] = PixelBlend32 ( dst[i], fix_to_color ( r0,g0, b0 ), fixPointu_to_u32 ( a0 ) ); +*/ +/* + getSample_color ( r2, g2, b2, line.c[0][0], inversew * COLOR_MAX ); + color_to_fix ( r1, g1, b1, dst[i] ); + + r2 = r0 + imulFix ( a0, r1 - r0 ); + g2 = g0 + imulFix ( a0, g1 - g0 ); + b2 = b0 + imulFix ( a0, b1 - b0 ); + dst[i] = fix_to_color ( r2, g2, b2 ); +*/ + } #endif @@ -300,7 +340,7 @@ void CTRTextureGouraudAlpha2::scanline_bilinear () line.w[0] += slopeW; #endif #ifdef IPOL_C0 - line.c[0] += slopeC; + line.c[0][0] += slopeC[0]; #endif #ifdef IPOL_T0 line.t[0][0] += slopeT[0]; @@ -316,8 +356,8 @@ void CTRTextureGouraudAlpha2::drawTriangle ( const s4DVertex *a,const s4DVertex { // sort on height, y if ( F32_A_GREATER_B ( a->Pos.y , b->Pos.y ) ) swapVertexPointer(&a, &b); - if ( F32_A_GREATER_B ( a->Pos.y , c->Pos.y ) ) swapVertexPointer(&a, &c); if ( F32_A_GREATER_B ( b->Pos.y , c->Pos.y ) ) swapVertexPointer(&b, &c); + if ( F32_A_GREATER_B ( a->Pos.y , b->Pos.y ) ) swapVertexPointer(&a, &b); // calculate delta y of the edges @@ -355,8 +395,8 @@ void CTRTextureGouraudAlpha2::drawTriangle ( const s4DVertex *a,const s4DVertex #endif #ifdef IPOL_C0 - scan.slopeC[0] = (c->Color[0] - a->Color[0]) * scan.invDeltaY[0]; - scan.c[0] = a->Color[0]; + scan.slopeC[0][0] = (c->Color[0] - a->Color[0]) * scan.invDeltaY[0]; + scan.c[0][0] = a->Color[0]; #endif #ifdef IPOL_T0 @@ -377,12 +417,6 @@ void CTRTextureGouraudAlpha2::drawTriangle ( const s4DVertex *a,const s4DVertex f32 subPixel; #endif - lockedSurface = (tVideoSample*)RenderTarget->lock(); - -#ifdef USE_ZBUFFER - lockedDepthBuffer = (fp24*) DepthBuffer->lock(); -#endif - #ifdef IPOL_T0 IT[0].data = (tVideoSample*)IT[0].Texture->lock(); #endif @@ -409,8 +443,8 @@ void CTRTextureGouraudAlpha2::drawTriangle ( const s4DVertex *a,const s4DVertex #endif #ifdef IPOL_C0 - scan.slopeC[1] = (b->Color[0] - a->Color[0]) * scan.invDeltaY[1]; - scan.c[1] = a->Color[0]; + scan.slopeC[0][1] = (b->Color[0] - a->Color[0]) * scan.invDeltaY[1]; + scan.c[0][1] = a->Color[0]; #endif #ifdef IPOL_T0 @@ -445,8 +479,8 @@ void CTRTextureGouraudAlpha2::drawTriangle ( const s4DVertex *a,const s4DVertex #endif #ifdef IPOL_C0 - scan.c[0] += scan.slopeC[0] * subPixel; - scan.c[1] += scan.slopeC[1] * subPixel; + scan.c[0][0] += scan.slopeC[0][0] * subPixel; + scan.c[0][1] += scan.slopeC[0][1] * subPixel; #endif #ifdef IPOL_T0 @@ -478,8 +512,8 @@ void CTRTextureGouraudAlpha2::drawTriangle ( const s4DVertex *a,const s4DVertex #endif #ifdef IPOL_C0 - line.c[scan.left] = scan.c[0]; - line.c[scan.right] = scan.c[1]; + line.c[0][scan.left] = scan.c[0][0]; + line.c[0][scan.right] = scan.c[0][1]; #endif #ifdef IPOL_T0 @@ -509,8 +543,8 @@ void CTRTextureGouraudAlpha2::drawTriangle ( const s4DVertex *a,const s4DVertex #endif #ifdef IPOL_C0 - scan.c[0] += scan.slopeC[0]; - scan.c[1] += scan.slopeC[1]; + scan.c[0][0] += scan.slopeC[0][0]; + scan.c[0][1] += scan.slopeC[0][1]; #endif #ifdef IPOL_T0 @@ -542,7 +576,7 @@ void CTRTextureGouraudAlpha2::drawTriangle ( const s4DVertex *a,const s4DVertex scan.w[0] = a->Pos.w + scan.slopeW[0] * temp[0]; #endif #ifdef IPOL_C0 - scan.c[0] = a->Color[0] + scan.slopeC[0] * temp[0]; + scan.c[0][0] = a->Color[0] + scan.slopeC[0][0] * temp[0]; #endif #ifdef IPOL_T0 scan.t[0][0] = a->Tex[0] + scan.slopeT[0][0] * temp[0]; @@ -568,8 +602,8 @@ void CTRTextureGouraudAlpha2::drawTriangle ( const s4DVertex *a,const s4DVertex #endif #ifdef IPOL_C0 - scan.slopeC[1] = (c->Color[0] - b->Color[0]) * scan.invDeltaY[2]; - scan.c[1] = b->Color[0]; + scan.slopeC[0][1] = (c->Color[0] - b->Color[0]) * scan.invDeltaY[2]; + scan.c[0][1] = b->Color[0]; #endif #ifdef IPOL_T0 @@ -605,8 +639,8 @@ void CTRTextureGouraudAlpha2::drawTriangle ( const s4DVertex *a,const s4DVertex #endif #ifdef IPOL_C0 - scan.c[0] += scan.slopeC[0] * subPixel; - scan.c[1] += scan.slopeC[1] * subPixel; + scan.c[0][0] += scan.slopeC[0][0] * subPixel; + scan.c[0][1] += scan.slopeC[0][1] * subPixel; #endif #ifdef IPOL_T0 @@ -638,8 +672,8 @@ void CTRTextureGouraudAlpha2::drawTriangle ( const s4DVertex *a,const s4DVertex #endif #ifdef IPOL_C0 - line.c[scan.left] = scan.c[0]; - line.c[scan.right] = scan.c[1]; + line.c[0][scan.left] = scan.c[0][0]; + line.c[0][scan.right] = scan.c[0][1]; #endif #ifdef IPOL_T0 @@ -669,8 +703,8 @@ void CTRTextureGouraudAlpha2::drawTriangle ( const s4DVertex *a,const s4DVertex #endif #ifdef IPOL_C0 - scan.c[0] += scan.slopeC[0]; - scan.c[1] += scan.slopeC[1]; + scan.c[0][0] += scan.slopeC[0][0]; + scan.c[0][1] += scan.slopeC[0][1]; #endif #ifdef IPOL_T0 diff --git a/source/Irrlicht/CTRTextureGouraudAlphaNoZ.cpp b/source/Irrlicht/CTRTextureGouraudAlphaNoZ.cpp index 590aeb70..cca68ee1 100644 --- a/source/Irrlicht/CTRTextureGouraudAlphaNoZ.cpp +++ b/source/Irrlicht/CTRTextureGouraudAlphaNoZ.cpp @@ -200,10 +200,10 @@ void CTRTextureGouraudAlphaNoZ::scanline_bilinear () #endif #endif - dst = lockedSurface + ( line.y * RenderTarget->getDimension().Width ) + xStart; + dst = (tVideoSample*)RenderTarget->lock() + ( line.y * RenderTarget->getDimension().Width ) + xStart; #ifdef USE_ZBUFFER - z = lockedDepthBuffer + ( line.y * RenderTarget->getDimension().Width ) + xStart; + z = (fp24*) DepthBuffer->lock() + ( line.y * RenderTarget->getDimension().Width ) + xStart; #endif @@ -239,20 +239,20 @@ void CTRTextureGouraudAlphaNoZ::scanline_bilinear () inversew = fix_inverse32 ( line.w[0] ); - u32 argb = getTexel_plain ( &IT[0], d + f32_to_fixPoint ( line.t[0][0].x,inversew), - d + f32_to_fixPoint ( line.t[0][0].y,inversew) + u32 argb = getTexel_plain ( &IT[0], d + tofix ( line.t[0][0].x,inversew), + d + tofix ( line.t[0][0].y,inversew) ); #else - u32 argb = getTexel_plain ( &IT[0], d + f32_to_fixPoint ( line.t[0][0].x), - d + f32_to_fixPoint ( line.t[0][0].y) + u32 argb = getTexel_plain ( &IT[0], d + tofix ( line.t[0][0].x), + d + tofix ( line.t[0][0].y) ); #endif const u32 alpha = ( argb >> 24 ); - if ( alpha >= AlphaRef ) + if ( alpha > AlphaRef ) { #ifdef WRITE_Z z[i] = line.z[0]; @@ -267,15 +267,23 @@ void CTRTextureGouraudAlphaNoZ::scanline_bilinear () #else +#ifdef INVERSE_W + inversew = fix_inverse32 ( line.w[0] ); getSample_texture ( a0, r0, g0, b0, &IT[0], - f32_to_fixPoint ( line.t[0][0].x,inversew), - f32_to_fixPoint ( line.t[0][0].y,inversew) + tofix ( line.t[0][0].x,inversew), + tofix ( line.t[0][0].y,inversew) ); - - if ( a0 >= AlphaRef ) +#else + getSample_texture ( a0, r0, g0, b0, + &IT[0], + tofix ( line.t[0][0].x), + tofix ( line.t[0][0].y) + ); +#endif + if ( a0 > AlphaRef ) { #ifdef WRITE_Z z[i] = line.z[0]; @@ -316,8 +324,8 @@ void CTRTextureGouraudAlphaNoZ::drawTriangle ( const s4DVertex *a,const s4DVerte { // sort on height, y if ( F32_A_GREATER_B ( a->Pos.y , b->Pos.y ) ) swapVertexPointer(&a, &b); - if ( F32_A_GREATER_B ( a->Pos.y , c->Pos.y ) ) swapVertexPointer(&a, &c); if ( F32_A_GREATER_B ( b->Pos.y , c->Pos.y ) ) swapVertexPointer(&b, &c); + if ( F32_A_GREATER_B ( a->Pos.y , b->Pos.y ) ) swapVertexPointer(&a, &b); // calculate delta y of the edges @@ -377,11 +385,6 @@ void CTRTextureGouraudAlphaNoZ::drawTriangle ( const s4DVertex *a,const s4DVerte f32 subPixel; #endif - lockedSurface = (tVideoSample*)RenderTarget->lock(); - -#ifdef USE_ZBUFFER - lockedDepthBuffer = (fp24*) DepthBuffer->lock(); -#endif #ifdef IPOL_T0 IT[0].data = (tVideoSample*)IT[0].Texture->lock(); diff --git a/source/Irrlicht/CTRTextureGouraudNoZ2.cpp b/source/Irrlicht/CTRTextureGouraudNoZ2.cpp index 18a7db06..ff2cd313 100644 --- a/source/Irrlicht/CTRTextureGouraudNoZ2.cpp +++ b/source/Irrlicht/CTRTextureGouraudNoZ2.cpp @@ -188,10 +188,10 @@ void CTRTextureGouraudNoZ2::scanline_bilinear ( ) #endif #endif - dst = lockedSurface + ( line.y * RenderTarget->getDimension().Width ) + xStart; + dst = (tVideoSample*)RenderTarget->lock() + ( line.y * RenderTarget->getDimension().Width ) + xStart; #ifdef USE_ZBUFFER - z = lockedDepthBuffer + ( line.y * RenderTarget->getDimension().Width ) + xStart; + z = (fp24*) DepthBuffer->lock() + ( line.y * RenderTarget->getDimension().Width ) + xStart; #endif @@ -216,11 +216,11 @@ void CTRTextureGouraudNoZ2::scanline_bilinear ( ) #ifdef INVERSE_W inversew = fix_inverse32 ( line.w[0] ); - tx0 = f32_to_fixPoint ( line.t[0][0].x,inversew); - ty0 = f32_to_fixPoint ( line.t[0][0].y,inversew); + tx0 = tofix ( line.t[0][0].x,inversew); + ty0 = tofix ( line.t[0][0].y,inversew); #else - tx0 = f32_to_fixPoint ( line.t[0][0].x ); - ty0 = f32_to_fixPoint ( line.t[0][0].y ); + tx0 = tofix ( line.t[0][0].x ); + ty0 = tofix ( line.t[0][0].y ); #endif dst[i] = getTexel_plain ( &IT[0], tx0, ty0 ); @@ -259,8 +259,8 @@ void CTRTextureGouraudNoZ2::drawTriangle ( const s4DVertex *a,const s4DVertex *b { // sort on height, y if ( F32_A_GREATER_B ( a->Pos.y , b->Pos.y ) ) swapVertexPointer(&a, &b); - if ( F32_A_GREATER_B ( a->Pos.y , c->Pos.y ) ) swapVertexPointer(&a, &c); if ( F32_A_GREATER_B ( b->Pos.y , c->Pos.y ) ) swapVertexPointer(&b, &c); + if ( F32_A_GREATER_B ( a->Pos.y , b->Pos.y ) ) swapVertexPointer(&a, &b); // calculate delta y of the edges @@ -320,12 +320,6 @@ void CTRTextureGouraudNoZ2::drawTriangle ( const s4DVertex *a,const s4DVertex *b f32 subPixel; #endif - lockedSurface = (tVideoSample*)RenderTarget->lock(); - -#ifdef USE_ZBUFFER - lockedDepthBuffer = DepthBuffer->lock(); -#endif - #ifdef IPOL_T0 IT[0].data = (tVideoSample*)IT[0].Texture->lock(); #endif diff --git a/source/Irrlicht/CTRTextureGouraudVertexAlpha2.cpp b/source/Irrlicht/CTRTextureGouraudVertexAlpha2.cpp index e03c4e05..183164ef 100644 --- a/source/Irrlicht/CTRTextureGouraudVertexAlpha2.cpp +++ b/source/Irrlicht/CTRTextureGouraudVertexAlpha2.cpp @@ -182,10 +182,10 @@ void CTRTextureVertexAlpha2::scanline_bilinear ( ) #endif #endif - dst = lockedSurface + ( line.y * RenderTarget->getDimension().Width ) + xStart; + dst = (tVideoSample*)RenderTarget->lock() + ( line.y * RenderTarget->getDimension().Width ) + xStart; #ifdef USE_ZBUFFER - z = lockedDepthBuffer + ( line.y * RenderTarget->getDimension().Width ) + xStart; + z = (fp24*) DepthBuffer->lock() + ( line.y * RenderTarget->getDimension().Width ) + xStart; #endif @@ -228,8 +228,8 @@ void CTRTextureVertexAlpha2::scanline_bilinear ( ) dst[i] = PixelAdd32 ( dst[i], - getTexel_plain ( &IT[0], f32_to_fixPoint ( line.t[0][0].x,inversew), - f32_to_fixPoint ( line.t[0][0].y,inversew) ) + getTexel_plain ( &IT[0], tofix ( line.t[0][0].x,inversew), + tofix ( line.t[0][0].y,inversew) ) ); #else @@ -237,19 +237,19 @@ void CTRTextureVertexAlpha2::scanline_bilinear ( ) #ifdef INVERSE_W inversew = fix_inverse32 ( line.w[0] ); - tx0 = f32_to_fixPoint ( line.t[0][0].x,inversew); - ty0 = f32_to_fixPoint ( line.t[0][0].y,inversew); + tx0 = tofix ( line.t[0][0].x,inversew); + ty0 = tofix ( line.t[0][0].y,inversew); #ifdef IPOL_C0 - a3 = f32_to_fixPoint ( line.c[0][0].y,inversew ); + a3 = tofix ( line.c[0][0].y,inversew ); #endif #else - tx0 = f32_to_fixPoint ( line.t[0][0].x ); - ty0 = f32_to_fixPoint ( line.t[0][0].y ); + tx0 = tofix ( line.t[0][0].x ); + ty0 = tofix ( line.t[0][0].y ); #ifdef IPOL_C0 - a3 = f32_to_fixPoint ( line.c[0][0].y ); + a3 = tofix ( line.c[0][0].y ); #endif @@ -302,8 +302,8 @@ void CTRTextureVertexAlpha2::drawTriangle ( const s4DVertex *a,const s4DVertex * { // sort on height, y if ( F32_A_GREATER_B ( a->Pos.y , b->Pos.y ) ) swapVertexPointer(&a, &b); - if ( F32_A_GREATER_B ( a->Pos.y , c->Pos.y ) ) swapVertexPointer(&a, &c); if ( F32_A_GREATER_B ( b->Pos.y , c->Pos.y ) ) swapVertexPointer(&b, &c); + if ( F32_A_GREATER_B ( a->Pos.y , b->Pos.y ) ) swapVertexPointer(&a, &b); // calculate delta y of the edges @@ -363,12 +363,6 @@ void CTRTextureVertexAlpha2::drawTriangle ( const s4DVertex *a,const s4DVertex * f32 subPixel; #endif - lockedSurface = (tVideoSample*)RenderTarget->lock(); - -#ifdef USE_ZBUFFER - lockedDepthBuffer = (fp24*) DepthBuffer->lock(); -#endif - #ifdef IPOL_T0 IT[0].data = (tVideoSample*)IT[0].Texture->lock(); #endif diff --git a/source/Irrlicht/CTRTextureLightMap2_Add.cpp b/source/Irrlicht/CTRTextureLightMap2_Add.cpp index 9441092c..8f493084 100644 --- a/source/Irrlicht/CTRTextureLightMap2_Add.cpp +++ b/source/Irrlicht/CTRTextureLightMap2_Add.cpp @@ -183,10 +183,10 @@ REALINLINE void CTRTextureLightMap2_Add::scanline_bilinear () #endif #endif - dst = lockedSurface + ( line.y * RenderTarget->getDimension().Width ) + xStart; + dst = (tVideoSample*)RenderTarget->lock() + ( line.y * RenderTarget->getDimension().Width ) + xStart; #ifdef USE_ZBUFFER - z = lockedDepthBuffer + ( line.y * RenderTarget->getDimension().Width ) + xStart; + z = (fp24*) DepthBuffer->lock() + ( line.y * RenderTarget->getDimension().Width ) + xStart; #endif @@ -229,19 +229,19 @@ REALINLINE void CTRTextureLightMap2_Add::scanline_bilinear () const tFixPointu d = dithermask [ dIndex | ( i ) & 3 ]; dst[i] = PixelAdd32 ( - getTexel_plain ( &IT[0], d + f32_to_fixPoint ( line.t[0][0].x,inversew), - d + f32_to_fixPoint ( line.t[0][0].y,inversew) ), - getTexel_plain ( &IT[1], d + f32_to_fixPoint ( line.t[1][0].x,inversew), - d + f32_to_fixPoint ( line.t[1][0].y,inversew) ) + getTexel_plain ( &IT[0], d + tofix ( line.t[0][0].x,inversew), + d + tofix ( line.t[0][0].y,inversew) ), + getTexel_plain ( &IT[1], d + tofix ( line.t[1][0].x,inversew), + d + tofix ( line.t[1][0].y,inversew) ) ); #else const tFixPointu d = dithermask [ dIndex | ( i ) & 3 ]; dst[i] = PixelAdd32 ( - getTexel_plain ( &IT[0], d + f32_to_fixPoint ( line.t[0][0].x), - d + f32_to_fixPoint ( line.t[0][0].y) ), - getTexel_plain ( &IT[1], d + f32_to_fixPoint ( line.t[1][0].x), - d + f32_to_fixPoint ( line.t[1][0].y) ) + getTexel_plain ( &IT[0], d + tofix ( line.t[0][0].x), + d + tofix ( line.t[0][0].y) ), + getTexel_plain ( &IT[1], d + tofix ( line.t[1][0].x), + d + tofix ( line.t[1][0].y) ) ); #endif @@ -249,8 +249,8 @@ REALINLINE void CTRTextureLightMap2_Add::scanline_bilinear () #else const f32 inversew = fix_inverse32 ( line.w[0] ); - getSample_texture ( r0, g0, b0, &IT[0], f32_to_fixPoint ( line.t[0][0].x,inversew), f32_to_fixPoint ( line.t[0][0].y,inversew) ); - getSample_texture ( r1, g1, b1, &IT[1], f32_to_fixPoint ( line.t[0][1].x,inversew), f32_to_fixPoint ( line.t[0][1].y,inversew) ); + getSample_texture ( r0, g0, b0, &IT[0], tofix ( line.t[0][0].x,inversew), tofix ( line.t[0][0].y,inversew) ); + getSample_texture ( r1, g1, b1, &IT[1], tofix ( line.t[0][1].x,inversew), tofix ( line.t[0][1].y,inversew) ); dst[i] = fix_to_color ( clampfix_maxcolor ( r0 + r1 ), clampfix_maxcolor ( g0 + g1 ), @@ -283,8 +283,8 @@ void CTRTextureLightMap2_Add::drawTriangle ( const s4DVertex *a,const s4DVertex { // sort on height, y if ( F32_A_GREATER_B ( a->Pos.y , b->Pos.y ) ) swapVertexPointer(&a, &b); - if ( F32_A_GREATER_B ( a->Pos.y , c->Pos.y ) ) swapVertexPointer(&a, &c); if ( F32_A_GREATER_B ( b->Pos.y , c->Pos.y ) ) swapVertexPointer(&b, &c); + if ( F32_A_GREATER_B ( a->Pos.y , b->Pos.y ) ) swapVertexPointer(&a, &b); // calculate delta y of the edges @@ -346,12 +346,6 @@ void CTRTextureLightMap2_Add::drawTriangle ( const s4DVertex *a,const s4DVertex // query access to TexMaps - lockedSurface = (tVideoSample*)RenderTarget->lock(); - -#ifdef USE_ZBUFFER - lockedDepthBuffer = (fp24*) DepthBuffer->lock(); -#endif - #ifdef IPOL_T0 IT[0].data = (tVideoSample*)IT[0].Texture->lock(); #endif diff --git a/source/Irrlicht/CTRTextureLightMap2_M1.cpp b/source/Irrlicht/CTRTextureLightMap2_M1.cpp index dd197ca0..7ae9051f 100644 --- a/source/Irrlicht/CTRTextureLightMap2_M1.cpp +++ b/source/Irrlicht/CTRTextureLightMap2_M1.cpp @@ -126,7 +126,7 @@ REALINLINE void CTRTextureLightMap2_M1::scanline_bilinear2 () const f32 invDeltaX = core::reciprocal_approxim ( line.x[1] - line.x[0] ); // search z-buffer for first not occulled pixel - z = lockedDepthBuffer + ( line.y * RenderTarget->getDimension().Width ) + xStart; + z = (fp24*) DepthBuffer->lock() + ( line.y * RenderTarget->getDimension().Width ) + xStart; // subTexel const f32 subPixel = ( (f32) xStart ) - line.x[0]; @@ -172,7 +172,7 @@ REALINLINE void CTRTextureLightMap2_M1::scanline_bilinear2 () line.z[0] = a; line.z[1] = b; #endif - dst = lockedSurface + ( line.y * RenderTarget->getDimension().Width ) + xStart; + dst = (tVideoSample*)RenderTarget->lock() + ( line.y * RenderTarget->getDimension().Width ) + xStart; a = (f32) i + subPixel; @@ -186,6 +186,9 @@ REALINLINE void CTRTextureLightMap2_M1::scanline_bilinear2 () #ifdef BURNINGVIDEO_RENDERER_FAST u32 dIndex = ( line.y & 3 ) << 2; + tFixPoint r0, g0, b0; + tFixPoint r1, g1, b1; + #else // tFixPoint r0, g0, b0; @@ -217,26 +220,18 @@ REALINLINE void CTRTextureLightMap2_M1::scanline_bilinear2 () const tFixPointu d = dithermask [ dIndex | ( i ) & 3 ]; - dst[i] = PixelMul32 ( - getTexel_plain ( &IT[0], d + f32_to_fixPoint ( line.t[0][0].x,inversew), - d + f32_to_fixPoint ( line.t[0][0].y,inversew) ), - getTexel_plain ( &IT[1], d + f32_to_fixPoint ( line.t[1][0].x,inversew), - d + f32_to_fixPoint ( line.t[1][0].y,inversew) ) - ); - - + getSample_texture ( r0, g0, b0, &IT[0], d + tofix ( line.t[0][0].x,inversew), d + tofix ( line.t[0][0].y,inversew) ); + getSample_texture ( r1, g1, b1, &IT[1], d + tofix ( line.t[1][0].x,inversew), d + tofix ( line.t[1][0].y,inversew) ); #else + getSample_texture ( r0, g0, b0, &IT[0], tofix ( line.t[0][0].x,inversew), tofix ( line.t[0][0].y,inversew) ); + getSample_texture ( r1, g1, b1, &IT[1], tofix ( line.t[1][0].x,inversew), tofix ( line.t[1][0].y,inversew) ); - - getSample_texture ( r0, g0, b0, &IT[0], f32_to_fixPoint ( line.t[0][0].x,inversew), f32_to_fixPoint ( line.t[0][0].y,inversew) ); - getSample_texture ( r1, g1, b1, &IT[1], f32_to_fixPoint ( line.t[1][0].x,inversew), f32_to_fixPoint ( line.t[1][0].y,inversew) ); - - dst[i] = fix_to_color ( clampfix_maxcolor ( imulFix_tex1 ( r0, r1 ) ), - clampfix_maxcolor ( imulFix_tex1 ( g0, g1 ) ), - clampfix_maxcolor ( imulFix_tex1 ( b0, b1 ) ) - ); #endif + dst[i] = fix_to_color ( imulFix_tex1 ( r0, r1 ), + imulFix_tex1 ( g0, g1 ), + imulFix_tex1 ( b0, b1 ) + ); } #ifdef IPOL_W @@ -252,16 +247,14 @@ REALINLINE void CTRTextureLightMap2_M1::scanline_bilinear2 () - - void CTRTextureLightMap2_M1::drawTriangle ( const s4DVertex *a,const s4DVertex *b,const s4DVertex *c ) { sScanConvertData scan; // sort on height, y if ( F32_A_GREATER_B ( a->Pos.y , b->Pos.y ) ) swapVertexPointer(&a, &b); - if ( F32_A_GREATER_B ( a->Pos.y , c->Pos.y ) ) swapVertexPointer(&a, &c); if ( F32_A_GREATER_B ( b->Pos.y , c->Pos.y ) ) swapVertexPointer(&b, &c); + if ( F32_A_GREATER_B ( a->Pos.y , b->Pos.y ) ) swapVertexPointer(&a, &b); // calculate delta y of the edges @@ -323,12 +316,6 @@ void CTRTextureLightMap2_M1::drawTriangle ( const s4DVertex *a,const s4DVertex * // query access to TexMaps - lockedSurface = (tVideoSample*)RenderTarget->lock(); - -#ifdef USE_ZBUFFER - lockedDepthBuffer = (fp24*) DepthBuffer->lock(); -#endif - #ifdef IPOL_T0 IT[0].data = (tVideoSample*)IT[0].Texture->lock(); #endif @@ -661,6 +648,8 @@ namespace irr namespace video { + + //! creates a flat triangle renderer IBurningShader* createTriangleRendererTextureLightMap2_M1(IDepthBuffer* zbuffer) { @@ -676,3 +665,4 @@ IBurningShader* createTriangleRendererTextureLightMap2_M1(IDepthBuffer* zbuffer) } // end namespace irr + diff --git a/source/Irrlicht/CTRTextureLightMap2_M2.cpp b/source/Irrlicht/CTRTextureLightMap2_M2.cpp index 644565e2..fe9f0803 100644 --- a/source/Irrlicht/CTRTextureLightMap2_M2.cpp +++ b/source/Irrlicht/CTRTextureLightMap2_M2.cpp @@ -126,7 +126,7 @@ REALINLINE void CTRTextureLightMap2_M2::scanline_bilinear2 () const f32 invDeltaX = core::reciprocal_approxim ( line.x[1] - line.x[0] ); // search z-buffer for first not occulled pixel - z = lockedDepthBuffer + ( line.y * RenderTarget->getDimension().Width ) + xStart; + z = (fp24*) DepthBuffer->lock() + ( line.y * RenderTarget->getDimension().Width ) + xStart; // subTexel const f32 subPixel = ( (f32) xStart ) - line.x[0]; @@ -172,7 +172,7 @@ REALINLINE void CTRTextureLightMap2_M2::scanline_bilinear2 () line.z[0] = a; line.z[1] = b; #endif - dst = lockedSurface + ( line.y * RenderTarget->getDimension().Width ) + xStart; + dst = (tVideoSample*)RenderTarget->lock() + ( line.y * RenderTarget->getDimension().Width ) + xStart; a = (f32) i + subPixel; @@ -220,11 +220,11 @@ REALINLINE void CTRTextureLightMap2_M2::scanline_bilinear2 () const tFixPointu d = dithermask [ dIndex | ( i ) & 3 ]; - getSample_texture ( r0, g0, b0, &IT[0], d + f32_to_fixPoint ( line.t[0][0].x,inversew), d + f32_to_fixPoint ( line.t[0][0].y,inversew) ); - getSample_texture ( r1, g1, b1, &IT[1], d + f32_to_fixPoint ( line.t[1][0].x,inversew), d + f32_to_fixPoint ( line.t[1][0].y,inversew) ); + getSample_texture ( r0, g0, b0, &IT[0], d + tofix ( line.t[0][0].x,inversew), d + tofix ( line.t[0][0].y,inversew) ); + getSample_texture ( r1, g1, b1, &IT[1], d + tofix ( line.t[1][0].x,inversew), d + tofix ( line.t[1][0].y,inversew) ); #else - getSample_texture ( r0, g0, b0, &IT[0], f32_to_fixPoint ( line.t[0][0].x,inversew), f32_to_fixPoint ( line.t[0][0].y,inversew) ); - getSample_texture ( r1, g1, b1, &IT[1], f32_to_fixPoint ( line.t[1][0].x,inversew), f32_to_fixPoint ( line.t[1][0].y,inversew) ); + getSample_texture ( r0, g0, b0, &IT[0], tofix ( line.t[0][0].x,inversew), tofix ( line.t[0][0].y,inversew) ); + getSample_texture ( r1, g1, b1, &IT[1], tofix ( line.t[1][0].x,inversew), tofix ( line.t[1][0].y,inversew) ); #endif @@ -253,8 +253,8 @@ void CTRTextureLightMap2_M2::drawTriangle ( const s4DVertex *a,const s4DVertex * // sort on height, y if ( F32_A_GREATER_B ( a->Pos.y , b->Pos.y ) ) swapVertexPointer(&a, &b); - if ( F32_A_GREATER_B ( a->Pos.y , c->Pos.y ) ) swapVertexPointer(&a, &c); if ( F32_A_GREATER_B ( b->Pos.y , c->Pos.y ) ) swapVertexPointer(&b, &c); + if ( F32_A_GREATER_B ( a->Pos.y , b->Pos.y ) ) swapVertexPointer(&a, &b); // calculate delta y of the edges @@ -316,12 +316,6 @@ void CTRTextureLightMap2_M2::drawTriangle ( const s4DVertex *a,const s4DVertex * // query access to TexMaps - lockedSurface = (tVideoSample*)RenderTarget->lock(); - -#ifdef USE_ZBUFFER - lockedDepthBuffer = (fp24*) DepthBuffer->lock(); -#endif - #ifdef IPOL_T0 IT[0].data = (tVideoSample*)IT[0].Texture->lock(); #endif diff --git a/source/Irrlicht/CTRTextureLightMap2_M4.cpp b/source/Irrlicht/CTRTextureLightMap2_M4.cpp index ebc864d5..7e362b79 100644 --- a/source/Irrlicht/CTRTextureLightMap2_M4.cpp +++ b/source/Irrlicht/CTRTextureLightMap2_M4.cpp @@ -130,8 +130,8 @@ REALINLINE void CTRTextureLightMap2_M4::scanline_bilinear2_mag () // search z-buffer for first not occulled pixel i = ( line.y * RenderTarget->getDimension().Width ) + xStart; - z = lockedDepthBuffer + i; - dst = lockedSurface + i; + z = (fp24*) DepthBuffer->lock() + i; + dst = (tVideoSample*)RenderTarget->lock() + i; // subTexel const f32 subPixel = ( (f32) xStart ) - line.x[0]; @@ -224,11 +224,11 @@ REALINLINE void CTRTextureLightMap2_M4::scanline_bilinear2_mag () const tFixPointu d = dithermask [ dIndex | ( i ) & 3 ]; - getSample_texture ( r0, g0, b0, &IT[0], d + f32_to_fixPoint ( line.t[0][0].x,inversew), d + f32_to_fixPoint ( line.t[0][0].y,inversew) ); - getSample_texture ( r1, g1, b1, &IT[1], d + f32_to_fixPoint ( line.t[1][0].x,inversew), d + f32_to_fixPoint ( line.t[1][0].y,inversew) ); + getSample_texture ( r0, g0, b0, &IT[0], d + tofix ( line.t[0][0].x,inversew), d + tofix ( line.t[0][0].y,inversew) ); + getSample_texture ( r1, g1, b1, &IT[1], d + tofix ( line.t[1][0].x,inversew), d + tofix ( line.t[1][0].y,inversew) ); #else - getSample_texture ( r0, g0, b0, &IT[0], f32_to_fixPoint ( line.t[0][0].x,inversew), f32_to_fixPoint ( line.t[0][0].y,inversew) ); - getSample_texture ( r1, g1, b1, &IT[1], f32_to_fixPoint ( line.t[1][0].x,inversew), f32_to_fixPoint ( line.t[1][0].y,inversew) ); + getSample_texture ( r0, g0, b0, &IT[0], tofix ( line.t[0][0].x,inversew), tofix ( line.t[0][0].y,inversew) ); + getSample_texture ( r1, g1, b1, &IT[1], tofix ( line.t[1][0].x,inversew), tofix ( line.t[1][0].y,inversew) ); #endif @@ -274,7 +274,7 @@ REALINLINE void CTRTextureLightMap2_M4::scanline_bilinear2_min () const f32 invDeltaX = core::reciprocal_approxim ( line.x[1] - line.x[0] ); // search z-buffer for first not occulled pixel - z = lockedDepthBuffer + ( line.y * RenderTarget->getDimension().Width ) + xStart; + z = (fp24*) DepthBuffer->lock() + ( line.y * RenderTarget->getDimension().Width ) + xStart; // subTexel const f32 subPixel = ( (f32) xStart ) - line.x[0]; @@ -320,7 +320,7 @@ REALINLINE void CTRTextureLightMap2_M4::scanline_bilinear2_min () line.z[0] = a; line.z[1] = b; #endif - dst = lockedSurface + ( line.y * RenderTarget->getDimension().Width ) + xStart; + dst = (tVideoSample*)RenderTarget->lock() + ( line.y * RenderTarget->getDimension().Width ) + xStart; a = (f32) i + subPixel; @@ -354,8 +354,8 @@ REALINLINE void CTRTextureLightMap2_M4::scanline_bilinear2_min () #endif - getTexel_fix ( r0, g0, b0, &IT[0], f32_to_fixPoint ( line.t[0][0].x,inversew), f32_to_fixPoint ( line.t[0][0].y,inversew) ); - getTexel_fix ( r1, g1, b1, &IT[1], f32_to_fixPoint ( line.t[1][0].x,inversew), f32_to_fixPoint ( line.t[1][0].y,inversew) ); + getTexel_fix ( r0, g0, b0, &IT[0], tofix ( line.t[0][0].x,inversew), tofix ( line.t[0][0].y,inversew) ); + getTexel_fix ( r1, g1, b1, &IT[1], tofix ( line.t[1][0].x,inversew), tofix ( line.t[1][0].y,inversew) ); dst[i] = fix_to_color ( clampfix_maxcolor ( imulFix_tex4 ( r0, r1 ) ), clampfix_maxcolor ( imulFix_tex4 ( g0, g1 ) ), @@ -458,10 +458,10 @@ REALINLINE void CTRTextureLightMap2_M4::scanline_bilinear () #endif #endif - dst = lockedSurface + ( line.y * RenderTarget->getDimension().Width ) + xStart; + dst = (tVideoSample*)RenderTarget->lock() + ( line.y * RenderTarget->getDimension().Width ) + xStart; #ifdef USE_ZBUFFER - z = lockedDepthBuffer + ( line.y * RenderTarget->getDimension().Width ) + xStart; + z = (fp24*) DepthBuffer->lock() + ( line.y * RenderTarget->getDimension().Width ) + xStart; #endif @@ -492,22 +492,22 @@ REALINLINE void CTRTextureLightMap2_M4::scanline_bilinear () #ifdef INVERSE_W inversew = fix_inverse32 ( line.w[0] ); - tx0 = f32_to_fixPoint ( line.t[0][0].x,inversew); - ty0 = f32_to_fixPoint ( line.t[0][0].y,inversew); - tx1 = f32_to_fixPoint ( line.t[1][0].x,inversew); - ty1 = f32_to_fixPoint ( line.t[1][0].y,inversew); + tx0 = tofix ( line.t[0][0].x,inversew); + ty0 = tofix ( line.t[0][0].y,inversew); + tx1 = tofix ( line.t[1][0].x,inversew); + ty1 = tofix ( line.t[1][0].y,inversew); #ifdef IPOL_C0 - r3 = f32_to_fixPoint ( line.c[0].y ,inversew ); - g3 = f32_to_fixPoint ( line.c[0].z ,inversew ); - b3 = f32_to_fixPoint ( line.c[0].w ,inversew ); + r3 = tofix ( line.c[0].y ,inversew ); + g3 = tofix ( line.c[0].z ,inversew ); + b3 = tofix ( line.c[0].w ,inversew ); #endif #else - tx0 = f32_to_fixPoint ( line.t[0][0].x ); - ty0 = f32_to_fixPoint ( line.t[0][0].y ); - tx1 = f32_to_fixPoint ( line.t[1][0].x ); - ty1 = f32_to_fixPoint ( line.t[1][0].y ); + tx0 = tofix ( line.t[0][0].x ); + ty0 = tofix ( line.t[0][0].y ); + tx1 = tofix ( line.t[1][0].x ); + ty1 = tofix ( line.t[1][0].y ); #endif getSample_texture ( r0, g0, b0, &IT[0], tx0, ty0 ); @@ -581,8 +581,8 @@ void CTRTextureLightMap2_M4::drawTriangle_Min ( const s4DVertex *a,const s4DVert // sort on height, y if ( F32_A_GREATER_B ( a->Pos.y , b->Pos.y ) ) swapVertexPointer(&a, &b); - if ( F32_A_GREATER_B ( a->Pos.y , c->Pos.y ) ) swapVertexPointer(&a, &c); if ( F32_A_GREATER_B ( b->Pos.y , c->Pos.y ) ) swapVertexPointer(&b, &c); + if ( F32_A_GREATER_B ( a->Pos.y , b->Pos.y ) ) swapVertexPointer(&a, &b); // calculate delta y of the edges @@ -644,12 +644,6 @@ void CTRTextureLightMap2_M4::drawTriangle_Min ( const s4DVertex *a,const s4DVert // query access to TexMaps - lockedSurface = (tVideoSample*)RenderTarget->lock(); - -#ifdef USE_ZBUFFER - lockedDepthBuffer = (fp24*) DepthBuffer->lock(); -#endif - #ifdef IPOL_T0 IT[0].data = (tVideoSample*)IT[0].Texture->lock(); #endif @@ -984,8 +978,8 @@ void CTRTextureLightMap2_M4::drawTriangle ( const s4DVertex *a,const s4DVertex * // sort on height, y if ( F32_A_GREATER_B ( a->Pos.y , b->Pos.y ) ) swapVertexPointer(&a, &b); - if ( F32_A_GREATER_B ( a->Pos.y , c->Pos.y ) ) swapVertexPointer(&a, &c); if ( F32_A_GREATER_B ( b->Pos.y , c->Pos.y ) ) swapVertexPointer(&b, &c); + if ( F32_A_GREATER_B ( a->Pos.y , b->Pos.y ) ) swapVertexPointer(&a, &b); // calculate delta y of the edges @@ -1047,12 +1041,6 @@ void CTRTextureLightMap2_M4::drawTriangle ( const s4DVertex *a,const s4DVertex * // query access to TexMaps - lockedSurface = (tVideoSample*)RenderTarget->lock(); - -#ifdef USE_ZBUFFER - lockedDepthBuffer = (fp24*) DepthBuffer->lock(); -#endif - #ifdef IPOL_T0 IT[0].data = (tVideoSample*)IT[0].Texture->lock(); #endif diff --git a/source/Irrlicht/CTRTextureLightMapGouraud2_M4.cpp b/source/Irrlicht/CTRTextureLightMapGouraud2_M4.cpp index 6d818920..031adcf2 100644 --- a/source/Irrlicht/CTRTextureLightMapGouraud2_M4.cpp +++ b/source/Irrlicht/CTRTextureLightMapGouraud2_M4.cpp @@ -183,10 +183,10 @@ void CTRGTextureLightMap2_M4::scanline_bilinear () #endif #endif - dst = lockedSurface + ( line.y * RenderTarget->getDimension().Width ) + xStart; + dst = (tVideoSample*)RenderTarget->lock() + ( line.y * RenderTarget->getDimension().Width ) + xStart; #ifdef USE_ZBUFFER - z = lockedDepthBuffer + ( line.y * RenderTarget->getDimension().Width ) + xStart; + z = (fp24*) DepthBuffer->lock() + ( line.y * RenderTarget->getDimension().Width ) + xStart; #endif @@ -217,22 +217,28 @@ void CTRGTextureLightMap2_M4::scanline_bilinear () #ifdef INVERSE_W inversew = fix_inverse32 ( line.w[0] ); - tx0 = f32_to_fixPoint ( line.t[0][0].x,inversew); - ty0 = f32_to_fixPoint ( line.t[0][0].y,inversew); - tx1 = f32_to_fixPoint ( line.t[1][0].x,inversew); - ty1 = f32_to_fixPoint ( line.t[1][0].y,inversew); + tx0 = tofix ( line.t[0][0].x,inversew); + ty0 = tofix ( line.t[0][0].y,inversew); + tx1 = tofix ( line.t[1][0].x,inversew); + ty1 = tofix ( line.t[1][0].y,inversew); #ifdef IPOL_C0 - r3 = f32_to_fixPoint ( line.c[0][0].y ,inversew ); - g3 = f32_to_fixPoint ( line.c[0][0].z ,inversew ); - b3 = f32_to_fixPoint ( line.c[0][0].w ,inversew ); + r3 = tofix ( line.c[0][0].y ,inversew ); + g3 = tofix ( line.c[0][0].z ,inversew ); + b3 = tofix ( line.c[0][0].w ,inversew ); #endif #else - tx0 = f32_to_fixPoint ( line.t[0][0].x ); - ty0 = f32_to_fixPoint ( line.t[0][0].y ); - tx1 = f32_to_fixPoint ( line.t[1][0].x ); - ty1 = f32_to_fixPoint ( line.t[1][0].y ); + tx0 = tofix ( line.t[0][0].x ); + ty0 = tofix ( line.t[0][0].y ); + tx1 = tofix ( line.t[1][0].x ); + ty1 = tofix ( line.t[1][0].y ); + +#ifdef IPOL_C0 + r3 = tofix ( line.c[0][0].y ); + g3 = tofix ( line.c[0][0].z ); + b3 = tofix ( line.c[0][0].w ); +#endif #endif getSample_texture ( r0, g0, b0, &IT[0], tx0, ty0 ); @@ -291,8 +297,8 @@ void CTRGTextureLightMap2_M4::drawTriangle ( const s4DVertex *a,const s4DVertex { // sort on height, y if ( F32_A_GREATER_B ( a->Pos.y , b->Pos.y ) ) swapVertexPointer(&a, &b); - if ( F32_A_GREATER_B ( a->Pos.y , c->Pos.y ) ) swapVertexPointer(&a, &c); if ( F32_A_GREATER_B ( b->Pos.y , c->Pos.y ) ) swapVertexPointer(&b, &c); + if ( F32_A_GREATER_B ( a->Pos.y , b->Pos.y ) ) swapVertexPointer(&a, &b); // calculate delta y of the edges @@ -355,12 +361,6 @@ void CTRGTextureLightMap2_M4::drawTriangle ( const s4DVertex *a,const s4DVertex // query access to TexMaps - lockedSurface = (tVideoSample*)RenderTarget->lock(); - -#ifdef USE_ZBUFFER - lockedDepthBuffer = (fp24*) DepthBuffer->lock(); -#endif - #ifdef IPOL_T0 IT[0].data = (tVideoSample*)IT[0].Texture->lock(); #endif diff --git a/source/Irrlicht/CTRTextureWire2.cpp b/source/Irrlicht/CTRTextureWire2.cpp index 843c94b9..96789b17 100644 --- a/source/Irrlicht/CTRTextureWire2.cpp +++ b/source/Irrlicht/CTRTextureWire2.cpp @@ -169,9 +169,9 @@ void CTRTextureWire2::renderLine ( const s4DVertex *a,const s4DVertex *b ) const if ( 0 == dx ) return; - dst = (tVideoSample*) ( (u8*) lockedSurface + ( aposy * pitch0 ) + (aposx << VIDEO_SAMPLE_GRANULARITY ) ); + dst = (tVideoSample*) ( (u8*) (tVideoSample*)RenderTarget->lock() + ( aposy * pitch0 ) + (aposx << VIDEO_SAMPLE_GRANULARITY ) ); #ifdef USE_ZBUFFER - z = (fp24*) ( (u8*) lockedDepthBuffer + ( aposy * pitch1 ) + (aposx << 2 ) ); + z = (fp24*) ( (u8*) (fp24*) DepthBuffer->lock() + ( aposy * pitch1 ) + (aposx << 2 ) ); #endif c = dx << 1; @@ -247,15 +247,8 @@ void CTRTextureWire2::drawTriangle ( const s4DVertex *a,const s4DVertex *b,const // sort on height, y if ( F32_A_GREATER_B ( a->Pos.y , b->Pos.y ) ) swapVertexPointer(&a, &b); - if ( F32_A_GREATER_B ( a->Pos.y , c->Pos.y ) ) swapVertexPointer(&a, &c); if ( F32_A_GREATER_B ( b->Pos.y , c->Pos.y ) ) swapVertexPointer(&b, &c); - - - lockedSurface = (tVideoSample*)RenderTarget->lock(); - -#ifdef USE_ZBUFFER - lockedDepthBuffer = (fp24*) DepthBuffer->lock(); -#endif + if ( F32_A_GREATER_B ( a->Pos.y , b->Pos.y ) ) swapVertexPointer(&a, &b); renderLine ( a, b ); renderLine ( b, c ); @@ -278,12 +271,6 @@ void CTRTextureWire2::drawLine ( const s4DVertex *a,const s4DVertex *b) // sort on height, y if ( a->Pos.y > b->Pos.y ) swapVertexPointer(&a, &b); - lockedSurface = (tVideoSample*)RenderTarget->lock(); - -#ifdef USE_ZBUFFER - lockedDepthBuffer = (fp24*) DepthBuffer->lock(); -#endif - renderLine ( a, b ); RenderTarget->unlock(); diff --git a/source/Irrlicht/CTerrainSceneNode.cpp b/source/Irrlicht/CTerrainSceneNode.cpp index cb8997bf..e4ea8497 100644 --- a/source/Irrlicht/CTerrainSceneNode.cpp +++ b/source/Irrlicht/CTerrainSceneNode.cpp @@ -741,7 +741,7 @@ namespace scene 0.3f); if (0 == arrow) { - arrow = SceneManager->getMesh("__debugnormal"); + arrow = SceneManager->getMesh( "__debugnormal"); } IMesh *mesh = arrow->getMesh(0); @@ -1410,7 +1410,7 @@ namespace scene void CTerrainSceneNode::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options) { - core::stringc newHeightmap = in->getAttributeAsString("Heightmap"); + core::string newHeightmap = in->getAttributeAsString("Heightmap"); f32 tcoordScale1 = in->getAttributeAsFloat("TextureScale1"); f32 tcoordScale2 = in->getAttributeAsFloat("TextureScale2"); diff --git a/source/Irrlicht/CTerrainSceneNode.h b/source/Irrlicht/CTerrainSceneNode.h index 6d7ce011..49f9a09f 100644 --- a/source/Irrlicht/CTerrainSceneNode.h +++ b/source/Irrlicht/CTerrainSceneNode.h @@ -329,7 +329,7 @@ namespace scene // needed for (de)serialization f32 TCoordScale1; f32 TCoordScale2; - core::stringc HeightmapFile; + core::string HeightmapFile; io::IFileSystem* FileSystem; }; diff --git a/source/Irrlicht/CTriangleSelector.cpp b/source/Irrlicht/CTriangleSelector.cpp index 9a4d8083..b3664e3f 100644 --- a/source/Irrlicht/CTriangleSelector.cpp +++ b/source/Irrlicht/CTriangleSelector.cpp @@ -85,10 +85,15 @@ void CTriangleSelector::getTriangles(core::triangle3df* triangles, for (s32 i=0; i& fileName, bool append) : FileSize(0) { #ifdef _DEBUG @@ -81,7 +81,11 @@ void CWriteFile::openFile(bool append) return; } +#if defined(_IRR_WCHAR_FILESYSTEM) + File = _wfopen(Filename.c_str(), append ? L"ab" : L"wb"); +#else File = fopen(Filename.c_str(), append ? "ab" : "wb"); +#endif if (File) { @@ -96,14 +100,14 @@ void CWriteFile::openFile(bool append) //! returns name of file -const c8* CWriteFile::getFileName() const +const core::string& CWriteFile::getFileName() const { - return Filename.c_str(); + return Filename; } -IWriteFile* createWriteFile(const c8* fileName, bool append) +IWriteFile* createWriteFile(const core::string& fileName, bool append) { CWriteFile* file = new CWriteFile(fileName, append); if (file->isOpen()) diff --git a/source/Irrlicht/CWriteFile.h b/source/Irrlicht/CWriteFile.h index f1add8ed..e403e4e6 100644 --- a/source/Irrlicht/CWriteFile.h +++ b/source/Irrlicht/CWriteFile.h @@ -22,8 +22,7 @@ namespace io { public: - CWriteFile(const wchar_t* fileName, bool append); - CWriteFile(const c8* fileName, bool append); + CWriteFile(const core::string& fileName, bool append); virtual ~CWriteFile(); @@ -37,7 +36,7 @@ namespace io virtual long getPos() const; //! Returns name of file. - virtual const c8* getFileName() const; + virtual const core::string& getFileName() const; //! returns if file is open bool isOpen() const; @@ -47,7 +46,7 @@ namespace io //! opens the file void openFile(bool append); - core::stringc Filename; + core::string Filename; FILE* File; long FileSize; }; diff --git a/source/Irrlicht/CXMeshFileLoader.cpp b/source/Irrlicht/CXMeshFileLoader.cpp index dff65509..dd55c67a 100644 --- a/source/Irrlicht/CXMeshFileLoader.cpp +++ b/source/Irrlicht/CXMeshFileLoader.cpp @@ -40,9 +40,9 @@ CXMeshFileLoader::CXMeshFileLoader(scene::ISceneManager* smgr, io::IFileSystem* //! returns true if the file maybe is able to be loaded by this class //! based on the file extension (e.g. ".bsp") -bool CXMeshFileLoader::isALoadableFileExtension(const c8* filename) const +bool CXMeshFileLoader::isALoadableFileExtension(const core::string& filename) const { - return strncmp(&filename[strlen(filename)-2], ".x", 2) == 0; + return core::hasFileExtension ( filename, "x" ); } @@ -448,7 +448,7 @@ bool CXMeshFileLoader::readFileIntoMemory(io::IReadFile* file) P = &Buffer[16]; readUntilEndOfLine(); - FilePath = FileSystem->getFileDir(file->getFileName()); + FilePath = FileSystem->getFileDir(file->getFileName()) + "/"; FilePath += '/'; return true; diff --git a/source/Irrlicht/CXMeshFileLoader.h b/source/Irrlicht/CXMeshFileLoader.h index b0c2d608..a90e1433 100644 --- a/source/Irrlicht/CXMeshFileLoader.h +++ b/source/Irrlicht/CXMeshFileLoader.h @@ -31,7 +31,7 @@ public: //! returns true if the file maybe is able to be loaded by this class //! based on the file extension (e.g. ".cob") - virtual bool isALoadableFileExtension(const c8* fileName) const; + virtual bool isALoadableFileExtension(const core::string& filename) const; //! creates/loads an animated mesh from the file. //! \return Pointer to the created mesh. Returns 0 if loading failed. @@ -178,7 +178,7 @@ private: // counter for number arrays in binary format u32 BinaryNumCount; u32 Line; - core::stringc FilePath; + core::string FilePath; CSkinnedMesh::SJoint *CurFrame; diff --git a/source/Irrlicht/CZipReader.cpp b/source/Irrlicht/CZipReader.cpp index 2bb8f1f9..8c2bc096 100644 --- a/source/Irrlicht/CZipReader.cpp +++ b/source/Irrlicht/CZipReader.cpp @@ -6,6 +6,7 @@ #include "CFileList.h" #include "CReadFile.h" #include "os.h" +#include "coreutil.h" #include "IrrCompileConfig.h" #ifdef _IRR_COMPILE_WITH_ZLIB_ @@ -21,9 +22,73 @@ namespace irr namespace io { +//! Constructor +CArchiveLoaderZIP::CArchiveLoaderZIP( io::IFileSystem* fs) +: FileSystem(fs) +{ + #ifdef _DEBUG + setDebugName("CArchiveLoaderZIP"); + #endif +} + +//! destructor +CArchiveLoaderZIP::~CArchiveLoaderZIP() +{ +} + + +//! returns true if the file maybe is able to be loaded by this class +bool CArchiveLoaderZIP::isALoadableFileFormat(const core::string& filename) const +{ + return core::hasFileExtension ( filename, "zip", "pk3" ); +} + + +//! Creates an archive from the filename +/** \param file File handle to check. +\return Pointer to newly created archive, or 0 upon error. */ +IFileArchive* CArchiveLoaderZIP::createArchive(const core::string& filename, bool ignoreCase, bool ignorePaths) const +{ + IFileArchive *archive = 0; + io::IReadFile* file = FileSystem->createAndOpenFile(filename); + + if (file) + { + archive = createArchive ( file, ignoreCase, ignorePaths ); + file->drop (); + } + + return archive; +} + +//! creates/loads an archive from the file. +//! \return Pointer to the created archive. Returns 0 if loading failed. +IFileArchive* CArchiveLoaderZIP::createArchive(io::IReadFile* file, bool ignoreCase, bool ignorePaths) const +{ + IFileArchive *archive = 0; + if ( file ) + { + file->seek ( 0 ); + archive = new CZipReader(file, ignoreCase, ignorePaths); + } + return archive; +} + +//! Check if the file might be loaded by this class +/** Check might look into the file. +\param file File handle to check. +\return True if file seems to be loadable. */ +bool CArchiveLoaderZIP::isALoadableFileFormat(io::IReadFile* file) const +{ + return false; +} + +/* + ZIP Archive +*/ CZipReader::CZipReader(IReadFile* file, bool ignoreCase, bool ignorePaths) -: File(file), IgnoreCase(ignoreCase), IgnorePaths(ignorePaths) +: File(file), IgnoreCase(ignoreCase), IgnorePaths(ignorePaths), Type ( "zip" ) { #ifdef _DEBUG setDebugName("CZipReader"); @@ -33,8 +98,11 @@ CZipReader::CZipReader(IReadFile* file, bool ignoreCase, bool ignorePaths) { File->grab(); + Base = File->getFileName(); + // scan local headers while (scanLocalHeader()); + //while (scanLocalHeader2()); // prepare file index for binary search FileList.sort(); @@ -60,7 +128,7 @@ void CZipReader::extractFilename(SZipFileEntry* entry) if (IgnoreCase) entry->zipFileName.make_lower(); - const c8* p = entry->zipFileName.c_str() + lorfn; + const c16* p = entry->zipFileName.c_str() + lorfn; // suche ein slash oder den anfang. @@ -97,12 +165,90 @@ void CZipReader::extractFilename(SZipFileEntry* entry) entry->simpleFileName = entry->zipFileName; // thanks to Pr3t3nd3r for this fix } +#if 0 +#include +const c8 *sigName( u32 sig ) +{ + switch ( sig ) + { + case 0x04034b50: return "PK0304"; + case 0x02014b50: return "PK0102"; + case 0x06054b50: return "PK0506"; + } + return "unknown"; +} + +bool CZipReader::scanLocalHeader2() +{ + c8 buf [ 128 ]; + c8 *c; + + File->read( &temp.header.Sig, 4 ); + sprintf ( buf, "sig: %08x,%s,", temp.header.Sig, sigName ( temp.header.Sig ) ); + OutputDebugStringA ( buf ); + + // Local File Header + if ( temp.header.Sig == 0x04034b50 ) + { + File->read( &temp.header.VersionToExtract, sizeof( temp.header ) - 4 ); + + temp.zipFileName.reserve( temp.header.FilenameLength+2); + c = (c8*) temp.zipFileName.c_str(); + File->read( c, temp.header.FilenameLength); + c [ temp.header.FilenameLength ] = 0; + temp.zipFileName.verify(); + + sprintf ( buf, "%d,'%s'\n", temp.header.CompressionMethod, c ); + OutputDebugStringA ( buf ); + + if (temp.header.ExtraFieldLength) + { + File->seek( temp.header.ExtraFieldLength, true); + } + + if (temp.header.GeneralBitFlag & ZIP_INFO_IN_DATA_DESCRITOR) + { + // read data descriptor + File->seek(sizeof(SZIPFileDataDescriptor), true ); + } + + // compressed data + temp.fileDataPosition = File->getPos(); + File->seek( temp.header.DataDescriptor.CompressedSize, true); + FileList.push_back( temp ); + return true; + } + + // Central directory structure + if ( temp.header.Sig == 0x04034b50 ) + { + //SZIPFileCentralDirFileHeader h; + //File->read( &h, sizeof( h ) - 4 ); + return true; + } + + // End of central dir + if ( temp.header.Sig == 0x06054b50 ) + { + return true; + } + + // eof + if ( temp.header.Sig == 0x02014b50 ) + { + return false; + } + + return false; +} + +#endif //! scans for a local header, returns false if there is no more local file header. bool CZipReader::scanLocalHeader() { - c8 tmp[1024]; + //c8 tmp[1024]; SZipFileEntry entry; entry.fileDataPosition = 0; @@ -128,10 +274,13 @@ bool CZipReader::scanLocalHeader() return false; // local file headers end here. // read filename - entry.zipFileName.reserve(entry.header.FilenameLength+2); - File->read(tmp, entry.header.FilenameLength); - tmp[entry.header.FilenameLength] = 0x0; - entry.zipFileName = tmp; + { + c8 *tmp = new c8 [ entry.header.FilenameLength + 2 ]; + File->read(tmp, entry.header.FilenameLength); + tmp[entry.header.FilenameLength] = 0x0; + entry.zipFileName = tmp; + delete [] tmp; + } extractFilename(&entry); @@ -154,7 +303,6 @@ bool CZipReader::scanLocalHeader() // store position in file entry.fileDataPosition = File->getPos(); - // move forward length of data File->seek(entry.header.DataDescriptor.CompressedSize, true); @@ -170,7 +318,7 @@ bool CZipReader::scanLocalHeader() //! opens a file by file name -IReadFile* CZipReader::openFile(const c8* filename) +IReadFile* CZipReader::openFile(const core::string& filename) { s32 index = findFile(filename); @@ -197,36 +345,39 @@ IReadFile* CZipReader::openFile(s32 index) //9 - Reserved for enhanced Deflating //10 - PKWARE Date Compression Library Imploding - switch(FileList[index].header.CompressionMethod) + const SZipFileEntry &e = FileList[index]; + wchar_t buf[64]; + switch(e.header.CompressionMethod) { case 0: // no compression { - File->seek(FileList[index].fileDataPosition); - return createLimitReadFile(FileList[index].simpleFileName.c_str(), File, FileList[index].header.DataDescriptor.UncompressedSize); + return createLimitReadFile( e.simpleFileName, File, e.fileDataPosition, e.header.DataDescriptor.CompressedSize); } case 8: { #ifdef _IRR_COMPILE_WITH_ZLIB_ - const u32 uncompressedSize = FileList[index].header.DataDescriptor.UncompressedSize; - const u32 compressedSize = FileList[index].header.DataDescriptor.CompressedSize; + const u32 uncompressedSize = e.header.DataDescriptor.UncompressedSize; + const u32 compressedSize = e.header.DataDescriptor.CompressedSize; void* pBuf = new c8[ uncompressedSize ]; if (!pBuf) { - os::Printer::log("Not enough memory for decompressing", FileList[index].simpleFileName.c_str(), ELL_ERROR); + swprintf ( buf, 64, L"Not enough memory for decompressing %s", e.simpleFileName.c_str() ); + os::Printer::log( buf, ELL_ERROR); return 0; } c8 *pcData = new c8[ compressedSize ]; if (!pcData) { - os::Printer::log("Not enough memory for decompressing", FileList[index].simpleFileName.c_str(), ELL_ERROR); + swprintf ( buf, 64, L"Not enough memory for decompressing %s", e.simpleFileName.c_str() ); + os::Printer::log( buf, ELL_ERROR); return 0; } //memset(pcData, 0, compressedSize ); - File->seek(FileList[index].fileDataPosition); + File->seek( e.fileDataPosition ); File->read(pcData, compressedSize ); // Setup the inflate stream. @@ -257,19 +408,21 @@ IReadFile* CZipReader::openFile(s32 index) if (err != Z_OK) { - os::Printer::log("Error decompressing", FileList[index].simpleFileName.c_str(), ELL_ERROR); + swprintf ( buf, 64, L"Error decompressing %s", e.simpleFileName.c_str() ); + os::Printer::log( buf, ELL_ERROR); delete [] (c8*)pBuf; return 0; } else - return io::createMemoryReadFile(pBuf, uncompressedSize, FileList[index].zipFileName.c_str(), true); + return io::createMemoryReadFile(pBuf, uncompressedSize, e.zipFileName, true); #else return 0; // zlib not compiled, we cannot decompress the data. #endif } default: - os::Printer::log("file has unsupported compression method.", FileList[index].simpleFileName.c_str(), ELL_ERROR); + swprintf ( buf, 64, L"file has unsupported compression method. %s", e.simpleFileName.c_str() ); + os::Printer::log( buf, ELL_ERROR); return 0; }; } @@ -277,7 +430,7 @@ IReadFile* CZipReader::openFile(s32 index) //! returns count of files in archive -s32 CZipReader::getFileCount() +u32 CZipReader::getFileCount() { return FileList.size(); } @@ -285,35 +438,21 @@ s32 CZipReader::getFileCount() //! returns data of file -const SZipFileEntry* CZipReader::getFileInfo(s32 index) const +const IFileArchiveEntry* CZipReader::getFileInfo(u32 index) { return &FileList[index]; } - -//! deletes the path from a filename -void CZipReader::deletePathFromFilename(core::stringc& filename) -{ - // delete path from filename - const c8* p = filename.c_str() + filename.size(); - - // search for path separator or beginning - - while (*p!='/' && *p!='\\' && p!=filename.c_str()) - --p; - - if (p != filename.c_str()) - { - ++p; - filename = p; - } +//! return the id of the file Archive +const core::string& CZipReader::getArchiveName () +{ + return Base; } - //! returns fileindex -s32 CZipReader::findFile(const c8* simpleFilename) +s32 CZipReader::findFile( const core::string& simpleFilename) { SZipFileEntry entry; entry.simpleFileName = simpleFilename; @@ -322,7 +461,7 @@ s32 CZipReader::findFile(const c8* simpleFilename) entry.simpleFileName.make_lower(); if (IgnorePaths) - deletePathFromFilename(entry.simpleFileName); + core::deletePathFromFilename(entry.simpleFileName); s32 res = FileList.binary_search(entry); @@ -343,52 +482,127 @@ s32 CZipReader::findFile(const c8* simpleFilename) // ----------------------------------------------------------------------------- + +//! Constructor +CArchiveLoaderMount::CArchiveLoaderMount( io::IFileSystem* fs) +: FileSystem(fs) +{ + #ifdef _DEBUG + setDebugName("CArchiveLoaderMount"); + #endif +} + + +//! destructor +CArchiveLoaderMount::~CArchiveLoaderMount() +{ +} + + +//! returns true if the file maybe is able to be loaded by this class +bool CArchiveLoaderMount::isALoadableFileFormat(const core::string& filename) const +{ + bool ret = false; + core::string fname ( filename ); + deletePathFromFilename ( fname ); + + if ( 0 == fname.size() ) + { + ret = true; + } + + return ret; +} + + +//! Creates an archive from the filename +IFileArchive* CArchiveLoaderMount::createArchive(const core::string& filename, bool ignoreCase, bool ignorePaths) const +{ + IFileArchive *archive = 0; + + eFileSystemType current = FileSystem->setFileListSystem ( FILESYSTEM_NATIVE ); + + core::string save = FileSystem->getWorkingDirectory (); + core::string fullPath = FileSystem->getAbsolutePath ( filename ); + FileSystem->flatenFilename ( fullPath ); + + if ( FileSystem->changeWorkingDirectoryTo ( fullPath ) ) + { + archive = new CMountPointReader(FileSystem, fullPath, ignoreCase, ignorePaths); + } + + FileSystem->changeWorkingDirectoryTo ( save ); + FileSystem->setFileListSystem ( current ); + + return archive; +} + +//! Check if the file might be loaded by this class +/** Check might look into the file. +\param file File handle to check. +\return True if file seems to be loadable. */ +bool CArchiveLoaderMount::isALoadableFileFormat(io::IReadFile* file) const +{ + return false; +} + +//! creates/loads an archive from the file. +//! \return Pointer to the created archive. Returns 0 if loading failed. +IFileArchive* CArchiveLoaderMount::createArchive(io::IReadFile* file, bool ignoreCase, bool ignorePaths) const +{ + return 0; +} + #if 1 -class CUnzipReadFile : public CReadFile +//! simple Reader ( does not handle ignorecase and ignorePath ) +// its more a simple wrapper for handling relative directories +// advantage: speed +class CMountPointReadFile : public CReadFile { public: - CUnzipReadFile ( const core::stringc &realName, const c8 * hashName ) - : CReadFile( realName.c_str ()) + CMountPointReadFile ( const core::string& realName, + const core::string& hashName ) + : CReadFile( realName ), CallFileName ( hashName ) { - CallFileName = hashName; } - virtual ~CUnzipReadFile () {} + virtual ~CMountPointReadFile () {} - virtual const c8* getFileName() const + virtual const core::string& getFileName() const { - return CallFileName.c_str (); + return CallFileName; } - core::stringc CallFileName; + core::string CallFileName; }; -CUnZipReader::CUnZipReader( IFileSystem * parent, const c8* basename, bool ignoreCase, bool ignorePaths) +/*! +*/ +CMountPointReader::CMountPointReader( IFileSystem * parent, const core::string& basename, bool ignoreCase, bool ignorePaths) :CZipReader ( 0, ignoreCase, ignorePaths ), Parent ( parent ) { Base = basename; - if ( Base [ Base.size() - 1 ] != '\\' || - Base [ Base.size() - 1 ] != '/' - ) - { - Base += "/"; - } + u16 last = Base.size() ? Base [ Base.size() - 1 ] : 0; + if ( last != '\\' && last != '/' ) + { + Base += '/'; + } + Type = "mount"; } -void CUnZipReader::buildDirectory ( ) +void CMountPointReader::buildDirectory ( ) { } //! opens a file by file name -IReadFile* CUnZipReader::openFile(const c8* filename) +IReadFile* CMountPointReader::openFile(const core::string& filename) { - core::stringc fname; - fname = Base; + core::string fname ( Base ); fname += filename; - CUnzipReadFile* file = new CUnzipReadFile( fname, filename); + CMountPointReadFile* file = new CMountPointReadFile( fname, filename); if (file->isOpen()) return file; @@ -398,7 +612,7 @@ IReadFile* CUnZipReader::openFile(const c8* filename) } //! returns fileindex -s32 CUnZipReader::findFile(const c8* filename) +s32 CMountPointReader::findFile(const core::string& filename) { IReadFile *file = openFile ( filename ); if ( 0 == file ) @@ -409,19 +623,23 @@ s32 CUnZipReader::findFile(const c8* filename) #else -CUnZipReader::CUnZipReader( IFileSystem * parent, const c8* basename, bool ignoreCase, bool ignorePaths) +//! compatible Folder Archticture +// +CMountPointReader::CMountPointReader( IFileSystem * parent, const core::string& basename, bool ignoreCase, bool ignorePaths) : CZipReader( 0, ignoreCase, ignorePaths ), Parent ( parent ) { - strcpy ( Buf, Parent->getWorkingDirectory () ); + Type = "mount"; + core::string work = Parent->getWorkingDirectory (); Parent->changeWorkingDirectoryTo ( basename ); + FileList.clear(); buildDirectory ( ); - Parent->changeWorkingDirectoryTo ( Buf ); + Parent->changeWorkingDirectoryTo ( work ); FileList.sort(); } -void CUnZipReader::buildDirectory ( ) +void CMountPointReader::buildDirectory ( ) { IFileList * list = new CFileList(); @@ -439,9 +657,9 @@ void CUnZipReader::buildDirectory ( ) } else { - const c8 * rel = list->getFileName ( i ); + const core::string& rel = list->getFileName ( i ); - if (strcmp( rel, "." ) && strcmp( rel, ".." )) + if ( rel != "." && rel != ".." ) { Parent->changeWorkingDirectoryTo ( rel ); buildDirectory (); @@ -453,8 +671,13 @@ void CUnZipReader::buildDirectory ( ) list->drop (); } +s32 CMountPointReader::findFile(const core::string& simpleFilename) +{ + return CZipReader::findFile( simpleFilename); +} + //! opens a file by file name -IReadFile* CUnZipReader::openFile(const c8* filename) +IReadFile* CMountPointReader::openFile(const core::string& filename) { s32 index = -1; @@ -465,8 +688,8 @@ IReadFile* CUnZipReader::openFile(const c8* filename) else if ( FileList.size () ) { - const core::stringc search = FileList[0].path + filename; - index = findFile( search.c_str() ); + core::string search = FileList[0].path + filename; + index = findFile( search ); } if (index == -1) diff --git a/source/Irrlicht/CZipReader.h b/source/Irrlicht/CZipReader.h index a6317b42..077873e2 100644 --- a/source/Irrlicht/CZipReader.h +++ b/source/Irrlicht/CZipReader.h @@ -10,6 +10,7 @@ #include "irrArray.h" #include "irrString.h" #include "IFileSystem.h" +#include "IFileList.h" namespace irr { @@ -34,14 +35,14 @@ namespace io struct SZIPFileDataDescriptor { - s32 CRC32; - s32 CompressedSize; - s32 UncompressedSize; + u32 CRC32; + u32 CompressedSize; + u32 UncompressedSize; } PACK_STRUCT; struct SZIPFileHeader { - s32 Sig; + u32 Sig; // 'PK0304' little endian (0x04034b50) s16 VersionToExtract; s16 GeneralBitFlag; s16 CompressionMethod; @@ -50,6 +51,47 @@ namespace io SZIPFileDataDescriptor DataDescriptor; s16 FilenameLength; s16 ExtraFieldLength; + // filename (variable size) + // extra field (variable size ) + } PACK_STRUCT; + + struct SZIPFileCentralDirFileHeader + { + u32 central_file_header_signature; // 'PK0102' (0x02014b50) + u16 version_made_by; + u16 version_needed_to_extract; + u16 general_purpose_bit_flag; + u16 compression_method; + u16 last_mod_file_time; + u16 last_mod_file_date; + u32 crc_32; + u32 compressed_size; + u32 uncompressed_size; + u16 filename_length; + u16 extra_field_length; + u16 file_comment_length; + u16 disk_number_start; + u16 internal_file_attributes; + u32 external_file_attributes; + u32 relative_offset_of_local_header; + + // filename (variable size) + // extra field (variable size) + // file comment (variable size) + + } PACK_STRUCT; + + struct SZIPFileCentralDirEnd + { + u32 sig; // 'PK0506' end_of central dir signature // (0x06054b50) + u16 numberDisk; // number of this disk + u16 numberStart; // number of the disk with the start of the central directory + u16 totalDisk; // total number of entries in the central dir on this disk + u16 totalEntries; // total number of entries in the central dir + u32 size; // size of the central directory + u32 offset; // offset of start of centraldirectory with respect to the starting disk number + u16 comment_length; // zipfile comment length + // zipfile comment (variable size) } PACK_STRUCT; // Default alignment @@ -60,34 +102,56 @@ namespace io #undef PACK_STRUCT - struct SZipFileEntry + struct SZipFileEntry : public IFileArchiveEntry { - core::stringc zipFileName; - core::stringc simpleFileName; - core::stringc path; + SZipFileEntry () {} + + core::string zipFileName; s32 fileDataPosition; // position of compressed data in file SZIPFileHeader header; - - bool operator < (const SZipFileEntry& other) const - { - return simpleFileName < other.simpleFileName; - } - - - bool operator == (const SZipFileEntry& other) const - { - return simpleFileName == other.simpleFileName; - } }; + //! Archiveloader capable of loading ZIP Archives + class CArchiveLoaderZIP : public IArchiveLoader + { + public: + + //! Constructor + CArchiveLoaderZIP(io::IFileSystem* fs); + + //! destructor + virtual ~CArchiveLoaderZIP(); + + //! returns true if the file maybe is able to be loaded by this class + //! based on the file extension (e.g. ".zip") + virtual bool isALoadableFileFormat(const core::string& filename) const; + + //! Creates an archive from the filename + /** \param file File handle to check. + \return Pointer to newly created archive, or 0 upon error. */ + virtual IFileArchive* createArchive(const core::string& filename, bool ignoreCase, bool ignorePaths) const; + + //! Check if the file might be loaded by this class + /** Check might look into the file. + \param file File handle to check. + \return True if file seems to be loadable. */ + virtual bool isALoadableFileFormat(io::IReadFile* file) const; + + //! creates/loads an archive from the file. + //! \return Pointer to the created archive. Returns 0 if loading failed. + virtual io::IFileArchive* createArchive(io::IReadFile* file, bool ignoreCase, bool ignorePaths) const; + + private: + io::IFileSystem* FileSystem; + }; /*! Zip file Reader written April 2002 by N.Gebhardt. Doesn't decompress data, only reads the file and is able to open uncompressed entries. */ - class CZipReader : public virtual IReferenceCounted + class CZipReader : public IFileArchive { public: @@ -95,61 +159,102 @@ namespace io virtual ~CZipReader(); //! opens a file by file name - virtual IReadFile* openFile(const c8* filename); + virtual IReadFile* openFile(const core::string& filename); //! opens a file by index - IReadFile* openFile(s32 index); + virtual IReadFile* openFile(s32 index); //! returns count of files in archive - s32 getFileCount(); + virtual u32 getFileCount(); //! returns data of file - const SZipFileEntry* getFileInfo(s32 index) const; + virtual const IFileArchiveEntry* getFileInfo(u32 index); //! returns fileindex - s32 findFile(const c8* filename); + virtual s32 findFile(const core::string& filename); + + //! return the id of the file Archive + virtual const core::string& getArchiveName (); + + //! get the class Type + virtual const core::string& getArchiveType() { return Type; } private: //! scans for a local header, returns false if there is no more //! local file header. bool scanLocalHeader(); + bool scanLocalHeader2(); IReadFile* File; - + SZipFileEntry temp; protected: //! splits filename from zip file into useful filenames and paths void extractFilename(SZipFileEntry* entry); - //! deletes the path from a filename - void deletePathFromFilename(core::stringc& filename); - bool IgnoreCase; bool IgnorePaths; core::array FileList; + + core::string Type; + core::string Base; }; - class CUnZipReader : public CZipReader + //! Archiveloader capable of loading MountPoint Archives + class CArchiveLoaderMount : public IArchiveLoader { public: - CUnZipReader(IFileSystem *parent, const c8* basename, + //! Constructor + CArchiveLoaderMount(io::IFileSystem* fs); + + //! destructor + virtual ~CArchiveLoaderMount(); + + //! returns true if the file maybe is able to be loaded by this class + //! based on the file extension (e.g. ".zip") + virtual bool isALoadableFileFormat(const core::string& filename) const; + + //! Creates an archive from the filename + /** \param file File handle to check. + \return Pointer to newly created archive, or 0 upon error. */ + virtual IFileArchive* createArchive(const core::string& filename, bool ignoreCase, bool ignorePaths) const; + + //! Check if the file might be loaded by this class + /** Check might look into the file. + \param file File handle to check. + \return True if file seems to be loadable. */ + virtual bool isALoadableFileFormat(io::IReadFile* file) const; + + //! creates/loads an archive from the file. + //! \return Pointer to the created archive. Returns 0 if loading failed. + virtual IFileArchive* createArchive(io::IReadFile* file, bool ignoreCase, bool ignorePaths) const; + + private: + io::IFileSystem* FileSystem; + }; + + //! A File Archive whichs uses a a mountpoint + class CMountPointReader : public CZipReader + { + public: + + CMountPointReader(IFileSystem *parent, const core::string& basename, bool ignoreCase, bool ignorePaths); //! opens a file by file name - virtual IReadFile* openFile(const c8* filename); + virtual IReadFile* openFile(const core::string& filename); //! returns fileindex - s32 findFile(const c8* filename); + virtual s32 findFile(const core::string& filename); private: IFileSystem *Parent; void buildDirectory (); - core::stringc Base; }; } // end namespace io diff --git a/source/Irrlicht/IBurningShader.cpp b/source/Irrlicht/IBurningShader.cpp index d4f00dc8..bb2e99c6 100644 --- a/source/Irrlicht/IBurningShader.cpp +++ b/source/Irrlicht/IBurningShader.cpp @@ -61,14 +61,14 @@ namespace video if (RenderTarget) RenderTarget->drop(); - RenderTarget = surface; + RenderTarget = (video::CImage* ) surface; if (RenderTarget) { RenderTarget->grab(); - //lockedSurface = (tVideoSample*)RenderTarget->lock(); - //lockedDepthBuffer = DepthBuffer->lock(); + //(tVideoSample*)RenderTarget->lock() = (tVideoSample*)RenderTarget->lock(); + //(fp24*) DepthBuffer->lock() = DepthBuffer->lock(); } } diff --git a/source/Irrlicht/IBurningShader.h b/source/Irrlicht/IBurningShader.h index bc824561..82e37d72 100644 --- a/source/Irrlicht/IBurningShader.h +++ b/source/Irrlicht/IBurningShader.h @@ -16,6 +16,7 @@ #include "irrArray.h" #include "SLight.h" #include "SMaterial.h" +#include "os.h" namespace irr @@ -74,15 +75,14 @@ namespace video ETR_TEXTURE_GOURAUD_VERTEX_ALPHA, - ETR_TEXTURE_GOURAUD_LIGHTMAP, + ETR_TEXTURE_GOURAUD_LIGHTMAP_M1, ETR_TEXTURE_GOURAUD_LIGHTMAP_M2, - ETR_TEXTURE_LIGHTMAP_M4, ETR_TEXTURE_GOURAUD_LIGHTMAP_M4, - - ETR_TEXTURE_GOURAUD_LIGHTMAP_ADD, + ETR_TEXTURE_LIGHTMAP_M4, ETR_TEXTURE_GOURAUD_DETAIL_MAP, - + ETR_TEXTURE_GOURAUD_LIGHTMAP_ADD, + ETR_GOURAUD_ALPHA, ETR_GOURAUD_ALPHA_NOZ, @@ -120,12 +120,9 @@ namespace video protected: - video::IImage* RenderTarget; + video::CImage* RenderTarget; IDepthBuffer* DepthBuffer; - fp24* lockedDepthBuffer; - tVideoSample* lockedSurface; - sInternalTexture IT[ BURNING_MATERIAL_MAX_TEXTURES ]; static const tFixPointu dithermask[ 4 * 4]; diff --git a/source/Irrlicht/Irrlicht.cpp b/source/Irrlicht/Irrlicht.cpp index c798ec5f..36b78a30 100644 --- a/source/Irrlicht/Irrlicht.cpp +++ b/source/Irrlicht/Irrlicht.cpp @@ -43,6 +43,12 @@ namespace core { const matrix4 IdentityMatrix(matrix4::EM4CONST_IDENTITY); } + +namespace video +{ + SMaterial IdentityMaterial; +} + } // end namespace irr @@ -57,7 +63,7 @@ BOOL APIENTRY DllMain( HANDLE hModule, switch (ul_reason_for_call) { case DLL_PROCESS_ATTACH: - #if defined(_DEBUG) && !defined(__GNUWIN32__) && !defined(__BORLANDC__) && !defined (_WIN32_WCE) + #if defined(_DEBUG) && !defined(__GNUWIN32__) && !defined(__BORLANDC__) && !defined (_WIN32_WCE) && !defined (_IRR_XBOX_PLATFORM_) _CrtSetDbgFlag(_CRTDBG_LEAK_CHECK_DF | _CRTDBG_ALLOC_MEM_DF); #endif break; diff --git a/source/Irrlicht/Irrlicht7.1.vcproj b/source/Irrlicht/Irrlicht7.1.vcproj index 9cf048da..66aa9008 100644 --- a/source/Irrlicht/Irrlicht7.1.vcproj +++ b/source/Irrlicht/Irrlicht7.1.vcproj @@ -226,254 +226,184 @@ OutputDirectory="$(ConfigurationName)" IntermediateDirectory="$(ConfigurationName)" ConfigurationType="4" - InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops" UseOfMFC="0" - ATLMinimizesCRunTimeLibraryUsage="false" - CharacterSet="0" - > - - - - - + ATLMinimizesCRunTimeLibraryUsage="FALSE" + CharacterSet="0"> + CompileAs="0"/> - - + Name="VCCustomBuildTool"/> + OutputFile="..\..\lib\Win32-visualstudio\Irrlicht.lib"/> + Name="VCMIDLTool" + PreprocessorDefinitions="_DEBUG" + MkTypLibCompatible="TRUE" + SuppressStartupBanner="TRUE" + TargetEnvironment="1" + TypeLibraryName=".\..\Debug/Irrlicht.tlb"/> + Name="VCPostBuildEventTool"/> + Name="VCPreBuildEventTool"/> + Name="VCPreLinkEventTool"/> + Name="VCResourceCompilerTool" + PreprocessorDefinitions="_DEBUG" + Culture="3079"/> + + + + - - - - - + WholeProgramOptimization="TRUE"> + CompileAs="0"/> - - + Name="VCCustomBuildTool"/> + OutputFile="..\..\lib\Win32-visualstudio\Irrlicht.lib"/> + Name="VCMIDLTool" + PreprocessorDefinitions="NDEBUG" + MkTypLibCompatible="TRUE" + SuppressStartupBanner="TRUE" + TargetEnvironment="1" + TypeLibraryName=".\..\Release/Irrlicht.tlb"/> + Name="VCPostBuildEventTool"/> + Name="VCPreBuildEventTool"/> + Name="VCPreLinkEventTool"/> + Name="VCResourceCompilerTool" + PreprocessorDefinitions="NDEBUG" + Culture="3079"/> + + + + - - - - - + WholeProgramOptimization="TRUE"> + CompileAs="0"/> - - + Name="VCCustomBuildTool"/> + OutputFile="..\..\lib\Win32-visualstudio\Irrlicht.lib"/> + Name="VCMIDLTool" + PreprocessorDefinitions="NDEBUG" + MkTypLibCompatible="TRUE" + SuppressStartupBanner="TRUE" + TargetEnvironment="1" + TypeLibraryName=".\..\Release/Irrlicht.tlb"/> + Name="VCPostBuildEventTool"/> + Name="VCPreBuildEventTool"/> + Name="VCPreLinkEventTool"/> + Name="VCResourceCompilerTool" + PreprocessorDefinitions="NDEBUG" + Culture="3079"/> + + + + @@ -781,10 +711,10 @@ RelativePath=".\..\..\include\ITextSceneNode.h"> + RelativePath=".\..\..\include\ITriangleSelector.h"> + RelativePath=".\..\..\include\IVolumeLightSceneNode.h"> @@ -805,10 +735,10 @@ RelativePath=".\..\..\include\SMeshBufferTangents.h"> + RelativePath=".\..\..\include\SParticle.h"> + RelativePath=".\..\..\include\SSkinMeshBuffer.h"> @@ -858,6 +788,9 @@ + + @@ -891,6 +824,9 @@ + + @@ -967,6 +903,12 @@ + + + + @@ -1051,6 +993,12 @@ + + + + @@ -1707,6 +1655,12 @@ + + + + @@ -1809,12 +1763,6 @@ - - - - @@ -1830,6 +1778,12 @@ + + + + @@ -1951,18 +1905,18 @@ - - - - + + + + - - @@ -698,6 +697,10 @@ RelativePath=".\..\..\include\aabbox3d.h" > + + @@ -730,6 +733,10 @@ RelativePath=".\..\..\include\irrString.h" > + + @@ -782,6 +789,10 @@ RelativePath=".\..\..\include\IAttributes.h" > + + @@ -842,6 +853,10 @@ RelativePath=".\..\..\include\IAnimatedMeshMD2.h" > + + @@ -902,22 +917,14 @@ RelativePath=".\..\..\include\IMetaTriangleSelector.h" > - - - - - - + + @@ -1003,7 +1010,7 @@ > + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -1118,6 +1189,10 @@ RelativePath=".\..\..\include\IGUIToolbar.h" > + + @@ -1219,6 +1294,14 @@ RelativePath=".\CGUIImage.h" > + + + + @@ -1331,6 +1414,14 @@ RelativePath="CGUIToolBar.h" > + + + + @@ -1955,10 +2046,6 @@ RelativePath=".\CSceneManager.h" > - - @@ -2442,6 +2529,10 @@ RelativePath="CTriangleSelector.h" > + + @@ -121,7 +120,7 @@ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops" UseOfMFC="0" ATLMinimizesCRunTimeLibraryUsage="false" - CharacterSet="2" + CharacterSet="1" WholeProgramOptimization="1" > + + @@ -357,10 +361,6 @@ RelativePath=".\..\..\include\ITimer.h" > - - @@ -717,11 +717,11 @@ > + + + + @@ -1073,6 +1081,14 @@ RelativePath="CGUIToolBar.h" > + + + + @@ -2084,14 +2100,6 @@ RelativePath="CParticleGravityAffector.h" > - - - - @@ -2112,6 +2120,14 @@ RelativePath=".\CParticleRotationAffector.cpp" > + + + + @@ -2272,14 +2288,6 @@ RelativePath=".\CIrrMeshWriter.h" > - - - - @@ -2288,6 +2296,14 @@ RelativePath=".\COBJMeshWriter.h" > + + + + + { + SMeshChunk () + :scene::CMeshBuffer() + { + grab (); + } + + virtual ~SMeshChunk () + { + //removeAllHardwareBuffers + MaterialId = 0; + } + + s32 MaterialId; + }; +#else struct SMeshChunk { core::array Vertices; core::array Indices; s32 MaterialId; }; +#endif struct SIndexChunk { @@ -290,27 +316,36 @@ private: { u32 i; // new ISO for scoping problem in some compilers - // not fully inside - //if ( parentTest != 2 ) + // if parent is fully inside, no further check for the children is needed +#if defined (OCTTREE_PARENTTEST ) + if ( parentTest != 2 ) +#endif { core::vector3df edges[8]; Box.getEdges(edges); for (i=0; i!=scene::SViewFrustum::VF_PLANE_COUNT; ++i) { - bool boxInFrustum=false; + u32 boxInFrustum=0; for (u32 j=0; j!=8; ++j) { if (frustum.planes[i].classifyPointRelation(edges[j]) != core::ISREL3D_FRONT) { - boxInFrustum=true; + boxInFrustum += 1; +#if !defined (OCTTREE_PARENTTEST ) break; +#endif } } - if (!boxInFrustum) // all edges outside + if ( 0 == boxInFrustum) // all edges outside return; + +#if defined (OCTTREE_PARENTTEST ) + if ( 8 == boxInFrustum) // all edges in, all children in + parentTest = 2; +#endif } } diff --git a/source/Irrlicht/S4DVertex.h b/source/Irrlicht/S4DVertex.h index 0b5482a2..6c34d769 100644 --- a/source/Irrlicht/S4DVertex.h +++ b/source/Irrlicht/S4DVertex.h @@ -281,7 +281,7 @@ const u32 MATERIAL_MAX_COLORS = 1; const u32 BURNING_MATERIAL_MAX_TEXTURES = 2; // dummy Vertex. used for calculation vertex memory size -struct __s4DVertex +struct s4DVertex_proxy { sVec4 Pos; @@ -296,6 +296,9 @@ struct __s4DVertex #define SIZEOF_SVERTEX 64 #define SIZEOF_SVERTEX_LOG2 6 +/*! + Internal BurningVideo Vertex +*/ struct s4DVertex { sVec4 Pos; @@ -308,7 +311,7 @@ struct s4DVertex u32 flag; - u8 fill [ SIZEOF_SVERTEX - sizeof (__s4DVertex) ]; + u8 fill [ SIZEOF_SVERTEX - sizeof (s4DVertex_proxy) ]; // f = a * t + b * ( 1 - t ) void interpolate(const s4DVertex& b, const s4DVertex& a, const f32 t) @@ -391,7 +394,7 @@ struct SVertexCache const void* vertices; u32 vertexCount; - const u16* indices; + const void* indices; u32 indexCount; u32 indicesIndex; @@ -402,12 +405,13 @@ struct SVertexCache u32 vType; //E_VERTEX_TYPE u32 pType; //scene::E_PRIMITIVE_TYPE + u32 iType; //E_INDEX_TYPE iType }; // swap 2 pointer -inline void swapVertexPointer(const s4DVertex** v1, const s4DVertex** v2) +REALINLINE void swapVertexPointer(const s4DVertex** v1, const s4DVertex** v2) { const s4DVertex* b = *v1; *v1 = *v2; @@ -484,9 +488,9 @@ inline void getTexel_plain2 ( tFixPoint &r, tFixPoint &g, tFixPoint &b, const sVec4 &v ) { - r = f32_to_fixPoint ( v.y ); - g = f32_to_fixPoint ( v.z ); - b = f32_to_fixPoint ( v.w ); + r = tofix ( v.y ); + g = tofix ( v.z ); + b = tofix ( v.w ); } /* @@ -496,22 +500,31 @@ inline void getSample_color ( tFixPoint &a, tFixPoint &r, tFixPoint &g, tFixPoin const sVec4 &v ) { - a = f32_to_fixPoint ( v.x ); - r = f32_to_fixPoint ( v.y, COLOR_MAX * FIX_POINT_F32_MUL); - g = f32_to_fixPoint ( v.z, COLOR_MAX * FIX_POINT_F32_MUL); - b = f32_to_fixPoint ( v.w, COLOR_MAX * FIX_POINT_F32_MUL); + a = tofix ( v.x ); + r = tofix ( v.y, COLOR_MAX * FIX_POINT_F32_MUL); + g = tofix ( v.z, COLOR_MAX * FIX_POINT_F32_MUL); + b = tofix ( v.w, COLOR_MAX * FIX_POINT_F32_MUL); } /* load a color value */ -inline void getSample_color ( tFixPoint &r, tFixPoint &g, tFixPoint &b, - const sVec4 &v - ) +inline void getSample_color ( tFixPoint &r, tFixPoint &g, tFixPoint &b,const sVec4 &v ) { - r = f32_to_fixPoint ( v.y, COLOR_MAX * FIX_POINT_F32_MUL); - g = f32_to_fixPoint ( v.z, COLOR_MAX * FIX_POINT_F32_MUL); - b = f32_to_fixPoint ( v.w, COLOR_MAX * FIX_POINT_F32_MUL); + r = tofix ( v.y, COLOR_MAX * FIX_POINT_F32_MUL); + g = tofix ( v.z, COLOR_MAX * FIX_POINT_F32_MUL); + b = tofix ( v.w, COLOR_MAX * FIX_POINT_F32_MUL); +} + +/* + load a color value +*/ +inline void getSample_color ( tFixPoint &r, tFixPoint &g, tFixPoint &b, + const sVec4 &v, const f32 mulby ) +{ + r = tofix ( v.y, mulby); + g = tofix ( v.z, mulby); + b = tofix ( v.w, mulby); } diff --git a/source/Irrlicht/SoftwareDriver2_compile_config.h b/source/Irrlicht/SoftwareDriver2_compile_config.h index f15eed5a..30c66328 100644 --- a/source/Irrlicht/SoftwareDriver2_compile_config.h +++ b/source/Irrlicht/SoftwareDriver2_compile_config.h @@ -22,18 +22,21 @@ #define SOFTWARE_DRIVER_2_MIPMAPPING #define SOFTWARE_DRIVER_2_USE_WBUFFER #define SOFTWARE_DRIVER_2_TEXTURE_TRANSFORM + #define SOFTWARE_DRIVER_2_TEXTURE_MAXSIZE 0 #endif +//! Set Flags for Windows Mobile #ifdef BURNINGVIDEO_RENDERER_CE #define SOFTWARE_DRIVER_2_PERSPECTIVE_CORRECT #define SOFTWARE_DRIVER_2_SUBTEXEL - #define SOFTWARE_DRIVER_2_BILINEAR - #define SOFTWARE_DRIVER_2_LIGHTING + //#define SOFTWARE_DRIVER_2_BILINEAR + //#define SOFTWARE_DRIVER_2_LIGHTING #define SOFTWARE_DRIVER_2_USE_VERTEX_COLOR #define SOFTWARE_DRIVER_2_16BIT #define SOFTWARE_DRIVER_2_MIPMAPPING #define SOFTWARE_DRIVER_2_USE_WBUFFER - #define SOFTWARE_DRIVER_2_TEXTURE_TRANSFORM + //#define SOFTWARE_DRIVER_2_TEXTURE_TRANSFORM + #define SOFTWARE_DRIVER_2_TEXTURE_MAXSIZE 128 #endif #ifdef BURNINGVIDEO_RENDERER_FAST @@ -45,6 +48,7 @@ #define SOFTWARE_DRIVER_2_32BIT #define SOFTWARE_DRIVER_2_MIPMAPPING #define SOFTWARE_DRIVER_2_USE_WBUFFER + #define SOFTWARE_DRIVER_2_TEXTURE_MAXSIZE 0 #endif #ifdef BURNINGVIDEO_RENDERER_ULTRA_FAST @@ -58,6 +62,7 @@ //#define SOFTWARE_DRIVER_2_32BIT #define SOFTWARE_DRIVER_2_MIPMAPPING #define SOFTWARE_DRIVER_2_USE_WBUFFER + #define SOFTWARE_DRIVER_2_TEXTURE_MAXSIZE 0 #endif // Derivate flags @@ -70,12 +75,12 @@ #endif // mip mapping -#ifdef SOFTWARE_DRIVER_2_MIPMAPPING - #ifdef BURNINGVIDEO_RENDERER_BEAUTIFUL +#if defined ( SOFTWARE_DRIVER_2_MIPMAPPING ) + #if defined( BURNINGVIDEO_RENDERER_BEAUTIFUL ) #define SOFTWARE_DRIVER_2_MIPMAPPING_MAX 8 #define SOFTWARE_DRIVER_2_MIPMAPPING_LOD_BIAS -1 - #else - #define SOFTWARE_DRIVER_2_MIPMAPPING_MAX 8 + #elif defined ( BURNINGVIDEO_RENDERER_CE ) + #define SOFTWARE_DRIVER_2_MIPMAPPING_MAX 4 #define SOFTWARE_DRIVER_2_MIPMAPPING_LOD_BIAS 0 #endif #else diff --git a/source/Irrlicht/SoftwareDriver2_helper.h b/source/Irrlicht/SoftwareDriver2_helper.h index 1a13c60e..9db36a18 100644 --- a/source/Irrlicht/SoftwareDriver2_helper.h +++ b/source/Irrlicht/SoftwareDriver2_helper.h @@ -36,6 +36,7 @@ namespace irr #define SHIFT_B 0 #define COLOR_MAX 0xFF + #define COLOR_MAX_LOG2 8 #define COLOR_BRIGHT_WHITE 0xFFFFFFFF #define VIDEO_SAMPLE_GRANULARITY 2 @@ -54,6 +55,7 @@ namespace irr #define SHIFT_B 0 #define COLOR_MAX 0x1F + #define COLOR_MAX_LOG2 5 #define COLOR_BRIGHT_WHITE 0xFFFF #define VIDEO_SAMPLE_GRANULARITY 1 @@ -118,7 +120,11 @@ REALINLINE void memcpy32_small ( void * dest, const void *source, u32 bytesize ) // integer log2 of a float ieee 754. TODO: non ieee floating point static inline s32 s32_log2_f32( f32 f) { +#ifdef IRRLICHT_FAST_MATH + u32 x = IR ( f ); +#else u32 x = core::IR ( f ); +#endif return ((x & 0x7F800000) >> 23) - 127; } @@ -289,7 +295,7 @@ REALINLINE u32 PixelAdd32 ( const u32 c2, const u32 c1) return modulo | clamp; } - +#if 1 // 1 - Bit Alpha Blending inline u16 PixelBlend16 ( const u16 destination, const u16 source ) @@ -318,7 +324,38 @@ inline u32 PixelBlend16_simd ( const u32 destination, const u32 source ) return destination; } } +#else +// 1 - Bit Alpha Blending +inline u16 PixelBlend16 ( const u16 c2, const u16 c1 ) +{ + return core::if_c_a_else_b ( c1 & 0x8000, c1, c2 ); +/* + u16 c = c1 & 0x8000; + + c >>= 15; + c += 0x7fff; + + return (c & c2 ) | c1; +*/ +} + +// 1 - Bit Alpha Blending 16Bit SIMD +inline u32 PixelBlend16_simd ( const u32 c2, const u32 c1 ) +{ + return core::if_c_a_else_b ( c1 & 0x80008000, c1, c2 ); + +/* + u32 c = c1 & 0x80008000; + + c >>= 15; + c += 0x7fff7fff; + + return (c & c2 ) | c1; +*/ +} + +#endif /*! Pixel = dest * ( 1 - SourceAlpha ) + source * SourceAlpha @@ -439,7 +476,7 @@ static inline int f_round2(f32 f) convert f32 to Fix Point. multiply is needed anyway, so scale mulby */ -REALINLINE tFixPoint f32_to_fixPoint (const f32 x, const f32 mulby = FIX_POINT_F32_MUL ) +REALINLINE tFixPoint tofix (const f32 x, const f32 mulby = FIX_POINT_F32_MUL ) { return (tFixPoint) (x * mulby); } @@ -461,12 +498,21 @@ REALINLINE tFixPoint imulFix(const tFixPoint x, const tFixPoint y) return ( x * y) >> ( FIX_POINT_PRE ); } +/* + Fix Point , Fix Point Multiply x * y * 2 +*/ +REALINLINE tFixPoint imulFix2(const tFixPoint x, const tFixPoint y) +{ + return ( x * y) >> ( FIX_POINT_PRE -1 ); +} + + /* Multiply x * y * 1 */ REALINLINE tFixPoint imulFix_tex1(const tFixPoint x, const tFixPoint y) { - return ( ( (tFixPointu) x >> 2 ) * ( (tFixPointu) y >> 2 ) ) >> (tFixPointu) ( FIX_POINT_PRE + 1 ); + return ( ( (tFixPointu) x >> 2 ) * ( (tFixPointu) y >> 2 ) ) >> (tFixPointu) ( FIX_POINT_PRE + 4 ); } /* @@ -528,30 +574,81 @@ inline s32 f32_to_23Bits(const f32 x) REALINLINE tVideoSample fix_to_color ( const tFixPoint r, const tFixPoint g, const tFixPoint b ) { #ifdef __BIG_ENDIAN__ - return ( r & FIXPOINT_COLOR_MAX) >> ( FIX_POINT_PRE - 8) | + return FIXPOINT_COLOR_MAX | + ( r & FIXPOINT_COLOR_MAX) >> ( FIX_POINT_PRE - 8) | ( g & FIXPOINT_COLOR_MAX) << ( 16 - FIX_POINT_PRE ) | - //( g & FIXPOINT_COLOR_MAX) << ( SHIFT_G - FIX_POINT_PRE ) | ( b & FIXPOINT_COLOR_MAX) << ( 24 - FIX_POINT_PRE ); #else - return ( r & FIXPOINT_COLOR_MAX) << ( SHIFT_R - FIX_POINT_PRE ) | + return ( FIXPOINT_COLOR_MAX & FIXPOINT_COLOR_MAX) << ( SHIFT_A - FIX_POINT_PRE ) | + ( r & FIXPOINT_COLOR_MAX) << ( SHIFT_R - FIX_POINT_PRE ) | ( g & FIXPOINT_COLOR_MAX) >> ( FIX_POINT_PRE - SHIFT_G ) | - //( g & FIXPOINT_COLOR_MAX) << ( SHIFT_G - FIX_POINT_PRE ) | ( b & FIXPOINT_COLOR_MAX) >> ( FIX_POINT_PRE - SHIFT_B ); #endif } /*! - return fixpoint from VideoSample + return VideoSample from fixpoint +*/ +REALINLINE tVideoSample fix4_to_color ( const tFixPoint a, const tFixPoint r, const tFixPoint g, const tFixPoint b ) +{ +#ifdef __BIG_ENDIAN__ + return ( a & (FIX_POINT_FRACT_MASK - 1 )) >> ( FIX_POINT_PRE ) | + ( r & FIXPOINT_COLOR_MAX) >> ( FIX_POINT_PRE - 8) | + ( g & FIXPOINT_COLOR_MAX) << ( 16 - FIX_POINT_PRE ) | + ( b & FIXPOINT_COLOR_MAX) << ( 24 - FIX_POINT_PRE ); +#else + return ( a & (FIX_POINT_FRACT_MASK - 1 )) << ( SHIFT_A - 1 ) | + ( r & FIXPOINT_COLOR_MAX) << ( SHIFT_R - FIX_POINT_PRE ) | + ( g & FIXPOINT_COLOR_MAX) >> ( FIX_POINT_PRE - SHIFT_G ) | + ( b & FIXPOINT_COLOR_MAX) >> ( FIX_POINT_PRE - SHIFT_B ); +#endif + +} + +/*! + return fixpoint from VideoSample granularity COLOR_MAX */ inline void color_to_fix ( tFixPoint &r, tFixPoint &g, tFixPoint &b, const tVideoSample t00 ) { - r = (t00 & MASK_R) >> ( SHIFT_R - FIX_POINT_PRE ); - //g = (t00 & MASK_G) >> ( SHIFT_G - FIX_POINT_PRE ); - g = (t00 & MASK_G) << ( FIX_POINT_PRE - SHIFT_G ); - b = (t00 & MASK_B) << ( FIX_POINT_PRE - SHIFT_B ); + (tFixPointu&) r = (t00 & MASK_R) >> ( SHIFT_R - FIX_POINT_PRE ); + (tFixPointu&) g = (t00 & MASK_G) << ( FIX_POINT_PRE - SHIFT_G ); + (tFixPointu&) b = (t00 & MASK_B) << ( FIX_POINT_PRE - SHIFT_B ); } +/*! + return fixpoint from VideoSample granularity COLOR_MAX +*/ +inline void color_to_fix ( tFixPoint &a, tFixPoint &r, tFixPoint &g, tFixPoint &b, const tVideoSample t00 ) +{ + (tFixPointu&) a = (t00 & MASK_A) >> ( SHIFT_A - FIX_POINT_PRE ); + (tFixPointu&) r = (t00 & MASK_R) >> ( SHIFT_R - FIX_POINT_PRE ); + (tFixPointu&) g = (t00 & MASK_G) << ( FIX_POINT_PRE - SHIFT_G ); + (tFixPointu&) b = (t00 & MASK_B) << ( FIX_POINT_PRE - SHIFT_B ); +} + +/*! + return fixpoint from VideoSample granularity 0..FIX_POINT_ONE +*/ +inline void color_to_fix1 ( tFixPoint &r, tFixPoint &g, tFixPoint &b, const tVideoSample t00 ) +{ + (tFixPointu&) r = (t00 & MASK_R) >> ( SHIFT_R + COLOR_MAX_LOG2 - FIX_POINT_PRE ); + (tFixPointu&) g = (t00 & MASK_G) >> ( SHIFT_G + COLOR_MAX_LOG2 - FIX_POINT_PRE ); + (tFixPointu&) b = (t00 & MASK_B) << ( FIX_POINT_PRE - COLOR_MAX_LOG2 ); +} + +/*! + return fixpoint from VideoSample granularity 0..FIX_POINT_ONE +*/ +inline void color_to_fix1 ( tFixPoint &a, tFixPoint &r, tFixPoint &g, tFixPoint &b, const tVideoSample t00 ) +{ + (tFixPointu&) a = (t00 & MASK_A) >> ( SHIFT_A + COLOR_MAX_LOG2 - FIX_POINT_PRE ); + (tFixPointu&) r = (t00 & MASK_R) >> ( SHIFT_R + COLOR_MAX_LOG2 - FIX_POINT_PRE ); + (tFixPointu&) g = (t00 & MASK_G) >> ( SHIFT_G + COLOR_MAX_LOG2 - FIX_POINT_PRE ); + (tFixPointu&) b = (t00 & MASK_B) << ( FIX_POINT_PRE - COLOR_MAX_LOG2 ); +} + + // ----- FP24 ---- floating point z-buffer @@ -861,17 +958,14 @@ struct AbsRectangle s32 y1; }; -inline void intersect ( AbsRectangle &dest, const AbsRectangle& a, const AbsRectangle& b) +//! 2D Intersection test +inline bool intersect ( AbsRectangle &dest, const AbsRectangle& a, const AbsRectangle& b) { dest.x0 = core::s32_max( a.x0, b.x0 ); dest.y0 = core::s32_max( a.y0, b.y0 ); dest.x1 = core::s32_min( a.x1, b.x1 ); dest.y1 = core::s32_min( a.y1, b.y1 ); -} - -inline bool isValid (const AbsRectangle& a) -{ - return a.x0 < a.x1 && a.y0 < a.y1; + return dest.x0 < dest.x1 && dest.y0 < dest.y1; } // some 1D defines diff --git a/source/Irrlicht/os.cpp b/source/Irrlicht/os.cpp index ba647737..3d8d4585 100644 --- a/source/Irrlicht/os.cpp +++ b/source/Irrlicht/os.cpp @@ -68,7 +68,11 @@ namespace os //! prints a debuginfo string void Printer::print(const c8* message) { -#if !defined (_WIN32_WCE ) +#if defined (_WIN32_WCE ) + core::stringw tmp ( message ); + tmp += L"\n"; + OutputDebugStringW( tmp.c_str() ); +#else c8* tmp = new c8[strlen(message) + 2]; sprintf(tmp, "%s\n", message); OutputDebugString(tmp); @@ -83,7 +87,7 @@ namespace os void Timer::initTimer() { -#if !defined(_WIN32_WCE) +#if !defined(_WIN32_WCE) && !defined (_IRR_XBOX_PLATFORM_) // disable hires timer on multiple core systems, bios bugs result in bad hires timers. SYSTEM_INFO sysinfo; GetSystemInfo(&sysinfo); @@ -97,7 +101,7 @@ namespace os { if (HighPerformanceTimerSupport) { -#if !defined(_WIN32_WCE) +#if !defined(_WIN32_WCE) && !defined (_IRR_XBOX_PLATFORM_) // Avoid potential timing inaccuracies across multiple cores by // temporarily setting the affinity of this process to one core. DWORD_PTR affinityMask; @@ -107,7 +111,7 @@ namespace os LARGE_INTEGER nTime; BOOL queriedOK = QueryPerformanceCounter(&nTime); -#if !defined(_WIN32_WCE) +#if !defined(_WIN32_WCE) && !defined (_IRR_XBOX_PLATFORM_) // Restore the true affinity. if(MultiCore) (void)SetThreadAffinityMask(GetCurrentThread(), affinityMask); @@ -173,10 +177,14 @@ namespace os void Printer::log(const c8* message, const c8* hint, ELOG_LEVEL ll) { - if (!Logger) - return; + if (Logger) + Logger->log(message, hint, ll); + } - Logger->log(message, hint, ll); + void Printer::log(const c8* message, const core::string& hint, ELOG_LEVEL ll) + { + if (Logger) + Logger->log(message, hint.c_str(), ll); } void Printer::log(const wchar_t* message, ELOG_LEVEL ll) diff --git a/source/Irrlicht/os.h b/source/Irrlicht/os.h index 0aa9cfa3..b5cb38a3 100644 --- a/source/Irrlicht/os.h +++ b/source/Irrlicht/os.h @@ -7,6 +7,7 @@ #include "IrrCompileConfig.h" // for endian check #include "irrTypes.h" +#include "irrString.h" #include "ILogger.h" namespace irr @@ -31,6 +32,7 @@ namespace os static void print(const c8* message); static void log(const c8* message, ELOG_LEVEL ll = ELL_INFORMATION); static void log(const c8* message, const c8* hint, ELOG_LEVEL ll = ELL_INFORMATION); + static void log(const c8* message, const core::string& hint, ELOG_LEVEL ll = ELL_INFORMATION); static void log(const wchar_t* message, ELOG_LEVEL ll = ELL_INFORMATION); static ILogger* Logger; };