diff --git a/changes.txt b/changes.txt index a58844d4..1ad8a06c 100644 --- a/changes.txt +++ b/changes.txt @@ -10,6 +10,8 @@ Changes in ogl-es (not yet released - will be merged with trunk at some point) -------------------------- Changes in 1.9 (not yet released) +- Lets the BSP loader find textures inserted with relative paths. Thx@ curaga for patch +- Slightly simplified ALLOC_STRATEGY_DOUBLE in arrays - Add alternavive BoundingBox calculation for BillboardSceneNode which can take in a camera node. Thx @Seven and @JacKDuRdEn for bugreports. - FPS camera now supports keyboard rotation. - Base FPS-camera movement on last position of mouse instead of always center (works better on platforms where cursor-placement is not allowed) diff --git a/examples/09.Meshviewer/main.cpp b/examples/09.Meshviewer/main.cpp index 559646e7..b06e0577 100644 --- a/examples/09.Meshviewer/main.cpp +++ b/examples/09.Meshviewer/main.cpp @@ -220,7 +220,9 @@ void loadModel(const c8* fn) return; } + u32 then = Device->getTimer()->getRealTime(); scene::IAnimatedMesh* m = Device->getSceneManager()->getMesh( filename.c_str() ); + Device->getLogger()->log("Loading time (ms): ", core::stringc(Device->getTimer()->getRealTime() - then).c_str()); if (!m) { @@ -323,7 +325,7 @@ void createToolBox() } /* -Function updateToolBox() is called each frame to update dynamic information in +Function updateToolBox() is called each frame to update dynamic information in the toolbox. */ void updateToolBox() @@ -354,8 +356,8 @@ void updateToolBox() void onKillFocus() { - // Avoid that the FPS-camera continues moving when the user presses alt-tab while - // moving the camera. + // Avoid that the FPS-camera continues moving when the user presses alt-tab while + // moving the camera. const core::list& animators = Camera[1]->getAnimators(); core::list::ConstIterator iter = animators.begin(); while ( iter != animators.end() ) @@ -524,11 +526,11 @@ public: */ bool OnKeyUp(irr::EKEY_CODE keyCode) { - // Don't handle keys if we have a modal dialog open as it would lead + // Don't handle keys if we have a modal dialog open as it would lead // to unexpected application behaviour for the user. if ( hasModalDialog() ) return false; - + if (keyCode == irr::KEY_ESCAPE) { if (Device) diff --git a/include/IQ3Shader.h b/include/IQ3Shader.h index f8a8a07d..14c2a004 100644 --- a/include/IQ3Shader.h +++ b/include/IQ3Shader.h @@ -856,6 +856,10 @@ namespace quake3 loadFile.append ( extension[g] ); } + texture = driver->findTexture( loadFile ); + if ( texture ) + break; + if ( fileSystem->existFile ( loadFile ) ) { texture = driver->getTexture( loadFile ); diff --git a/include/ISceneManager.h b/include/ISceneManager.h index 2c244296..732ba2ee 100644 --- a/include/ISceneManager.h +++ b/include/ISceneManager.h @@ -1081,10 +1081,10 @@ namespace scene //! Get scene nodes by type. /** \param type: Type of scene node to find (ESNT_ANY will return all child nodes). - \param outNodes: array to be filled with results. - \param start: Scene node to start from. All children of this scene - node are searched. If null is specified, the root scene node is - taken. */ + \param outNodes: results will be added to this array (outNodes is not cleared). + \param start: Scene node to start from. This node and all children of this scene + node are checked (recursively, so also children of children, etc). If null is specified, + the root scene node is taken as start-node. */ virtual void getSceneNodesFromType(ESCENE_NODE_TYPE type, core::array& outNodes, ISceneNode* start=0) = 0; diff --git a/include/ITriangleSelector.h b/include/ITriangleSelector.h index 1d5985c7..04aa0467 100644 --- a/include/ITriangleSelector.h +++ b/include/ITriangleSelector.h @@ -22,12 +22,12 @@ class ITriangleSelector; class IMeshBuffer; //! Additional information about the triangle arrays returned by ITriangleSelector::getTriangles -/** ITriangleSelector are free to fill out this information fully, partly or ignore it. +/** ITriangleSelector are free to fill out this information fully, partly or ignore it. Usually they will try to fill it when they can and set values to 0 otherwise. */ struct SCollisionTriangleRange { - SCollisionTriangleRange() + SCollisionTriangleRange() : RangeStart(0), RangeSize(0) , Selector(0), SceneNode(0) , MeshBuffer(0), MaterialIndex(0) @@ -42,10 +42,10 @@ struct SCollisionTriangleRange return triangleIndex >= RangeStart && triangleIndex < RangeStart+RangeSize; } - //! First index in the array for which this struct is valid + //! First index in the returned triangle array for which this struct is valid irr::u32 RangeStart; - //! Number of elements in the array for which this struct is valid (starting with RangeStart) + //! Number of elements in the returned triangle array for which this struct is valid (starting with RangeStart) irr::u32 RangeSize; //! Real selector which contained those triangles (useful when working with MetaTriangleSelector) @@ -89,17 +89,17 @@ public: into the array. \param transform Pointer to matrix for transforming the triangles before they are returned. Useful for example to scale all triangles - down into an ellipsoid space. - \param useNodeTransform When the selector has a node then transform the - triangles by that node's transformation matrix. - \param outTriangleInfo When a pointer to an array is passed then that + down into an ellipsoid space. + \param useNodeTransform When the selector has a node then transform the + triangles by that node's transformation matrix. + \param outTriangleInfo When a pointer to an array is passed then that array is filled with additional information about the returned triangles. - One element of SCollisionTriangleRange added for each range of triangles which - has distinguishable information. For example one range per meshbuffer. + One element of SCollisionTriangleRange added for each range of triangles which + has distinguishable information. For example one range per meshbuffer. */ virtual void getTriangles(core::triangle3df* triangles, s32 arraySize, - s32& outTriangleCount, const core::matrix4* transform=0, - bool useNodeTransform=true, + s32& outTriangleCount, const core::matrix4* transform=0, + bool useNodeTransform=true, irr::core::array* outTriangleInfo=0) const = 0; //! Gets the triangles for one associated node which may lie within a specific bounding box. @@ -120,12 +120,12 @@ public: will be written into the array. \param transform Pointer to matrix for transforming the triangles before they are returned. Useful for example to scale all triangles - down into an ellipsoid space. - \param useNodeTransform When the selector has a node then transform the - triangles by that node's transformation matrix. - \param outTriangleInfo When a pointer to an array is passed then that + down into an ellipsoid space. + \param useNodeTransform When the selector has a node then transform the + triangles by that node's transformation matrix. + \param outTriangleInfo When a pointer to an array is passed then that array is filled with additional information about the returned triangles. - One element of SCollisionTriangleRange added for each range of triangles which + One element of SCollisionTriangleRange added for each range of triangles which has distinguishable information. For example one range per meshbuffer. */ virtual void getTriangles(core::triangle3df* triangles, s32 arraySize, s32& outTriangleCount, const core::aabbox3d& box, @@ -150,12 +150,12 @@ public: will be written into the array. \param transform Pointer to matrix for transforming the triangles before they are returned. Useful for example to scale all triangles - down into an ellipsoid space. - \param useNodeTransform When the selector has a node then transform the + down into an ellipsoid space. + \param useNodeTransform When the selector has a node then transform the triangles by that node's transformation matrix. - \param outTriangleInfo When a pointer to an array is passed then that + \param outTriangleInfo When a pointer to an array is passed then that array is filled with additional information about the returned triangles. - One element of SCollisionTriangleRange added for each range of triangles which + One element of SCollisionTriangleRange added for each range of triangles which has distinguishable information. For example one range per meshbuffer. */ virtual void getTriangles(core::triangle3df* triangles, s32 arraySize, s32& outTriangleCount, const core::line3d& line, @@ -179,7 +179,7 @@ public: //! Get scene node associated with a given triangle. /** With CMetaTriangleSelector-selectors it's possible to find out a node - belonging to a certain triangle index. + belonging to a certain triangle index. NOTE: triangleIndex has nothing to do with the order of triangles returned by getTriangles functions! So you can _not_ use this function to find out anything about to which node returned triangles belong. Use STriangleCollisionInfo struct for that. diff --git a/include/irrAllocator.h b/include/irrAllocator.h index 648c410c..c7450ed7 100644 --- a/include/irrAllocator.h +++ b/include/irrAllocator.h @@ -108,12 +108,12 @@ public: #define DEBUG_CLIENTBLOCK new( _CLIENT_BLOCK, __FILE__, __LINE__) #endif -//! defines an allocation strategy +//! defines an allocation strategy (used only by irr::array so far) enum eAllocStrategy { - ALLOC_STRATEGY_SAFE = 0, - ALLOC_STRATEGY_DOUBLE = 1, - ALLOC_STRATEGY_SQRT = 2 + ALLOC_STRATEGY_SAFE = 0, // increase size by 1 + ALLOC_STRATEGY_DOUBLE = 1, // double size when under 500 elements, beyond that increase by 1/4th size. Plus a small constant. + ALLOC_STRATEGY_SQRT = 2 // not implemented }; diff --git a/include/irrArray.h b/include/irrArray.h index a46c6f8c..05528035 100644 --- a/include/irrArray.h +++ b/include/irrArray.h @@ -126,9 +126,7 @@ public: //! Insert item into array at specified position. - /** Please use this only if you know what you are doing (possible - performance loss). The preferred method of adding elements should be - push_back(). + /** \param element: Element to be inserted \param index: Where position to insert the new element. */ void insert(const T& element, u32 index=0) @@ -147,8 +145,7 @@ public: switch ( strategy ) { case ALLOC_STRATEGY_DOUBLE: - newAlloc = used + 1 + (allocated < 500 ? - (allocated < 5 ? 5 : used) : used >> 2); + newAlloc = used + 5 + (allocated < 500 ? used : used >> 2); break; default: case ALLOC_STRATEGY_SAFE: diff --git a/include/irrMath.h b/include/irrMath.h index 99341721..013d2c78 100644 --- a/include/irrMath.h +++ b/include/irrMath.h @@ -243,7 +243,7 @@ namespace core //! returns if a equals b, taking possible rounding errors into account template - inline T equals(const T a, const T b, const T tolerance = roundingError()) + inline bool equals(const T a, const T b, const T tolerance = roundingError()) { return (a + tolerance >= b) && (a - tolerance <= b); } diff --git a/source/Irrlicht/CGUITabControl.cpp b/source/Irrlicht/CGUITabControl.cpp index 6bfc531b..a6009b1d 100644 --- a/source/Irrlicht/CGUITabControl.cpp +++ b/source/Irrlicht/CGUITabControl.cpp @@ -580,12 +580,14 @@ void CGUITabControl::draw() core::rect frameRect(AbsoluteRect); + // some empty background as placeholder when there are no tabs if (Tabs.empty()) driver->draw2DRectangle(skin->getColor(EGDC_3D_HIGH_LIGHT), frameRect, &AbsoluteClippingRect); if (!font) return; + // tab button bar can be above or below the tabs if ( VerticalAlignment == EGUIA_UPPERLEFT ) { frameRect.UpperLeftCorner.Y += 2; @@ -610,6 +612,7 @@ void CGUITabControl::draw() //const wchar_t* activetext = 0; CGUITab *activeTab = 0; + // Draw all tab-buttons except the active one for (u32 i=CurrentScrollTabIndex; idraw2DRectangle(skin->getColor(EGDC_3D_HIGH_LIGHT), tr, &AbsoluteClippingRect); } else { - tr.UpperLeftCorner.X = AbsoluteRect.UpperLeftCorner.X; - tr.LowerRightCorner.X = 1000; tr.UpperLeftCorner.Y = frameRect.UpperLeftCorner.Y - 1; tr.LowerRightCorner.Y = frameRect.UpperLeftCorner.Y; driver->draw2DRectangle(skin->getColor(EGDC_3D_DARK_SHADOW), tr, &AbsoluteClippingRect); } } + // drawing some border and background for the tab-area. skin->draw3DTabBody(this, Border, FillBackground, AbsoluteRect, &AbsoluteClippingRect, TabHeight, VerticalAlignment); // enable scrollcontrols on need diff --git a/source/Irrlicht/COBJMeshFileLoader.cpp b/source/Irrlicht/COBJMeshFileLoader.cpp index fe89af96..9b1eba5d 100644 --- a/source/Irrlicht/COBJMeshFileLoader.cpp +++ b/source/Irrlicht/COBJMeshFileLoader.cpp @@ -78,9 +78,9 @@ IAnimatedMesh* COBJMeshFileLoader::createMesh(io::IReadFile* file) const u32 WORD_BUFFER_LENGTH = 512; - core::array vertexBuffer; - core::array normalsBuffer; - core::array textureCoordBuffer; + core::array > vertexBuffer(1000); + core::array > normalsBuffer(1000); + core::array > textureCoordBuffer(1000); SObjMtl * currMtl = new SObjMtl(); Materials.push_back(currMtl); @@ -101,6 +101,10 @@ IAnimatedMesh* COBJMeshFileLoader::createMesh(io::IReadFile* file) bool useGroups = !SceneManager->getParameters()->getAttributeAsBool(OBJ_LOADER_IGNORE_GROUPS); bool useMaterials = !SceneManager->getParameters()->getAttributeAsBool(OBJ_LOADER_IGNORE_MATERIAL_FILES); irr::u32 lineNr = 1; // only counts non-empty lines, still useful in debugging to locate errors + core::array faceCorners; + faceCorners.reallocate(32); // should be large enough + const core::stringc TAG_OFF = "off"; + while(bufPtr != bufEnd) { switch(bufPtr[0]) @@ -173,7 +177,7 @@ IAnimatedMesh* COBJMeshFileLoader::createMesh(io::IReadFile* file) #ifdef _IRR_DEBUG_OBJ_LOADER_ os::Printer::log("Loaded smoothing group start",smooth, ELL_DEBUG); #endif - if (core::stringc("off")==smooth) + if (TAG_OFF==smooth) smoothingGroup=0; else smoothingGroup=core::strtoul10(smooth); @@ -215,8 +219,7 @@ IAnimatedMesh* COBJMeshFileLoader::createMesh(io::IReadFile* file) const c8* linePtr = wordBuffer.c_str(); const c8* const endPtr = linePtr+wordBuffer.size(); - core::array faceCorners; - faceCorners.reallocate(32); // should be large enough + faceCorners.set_used(0); // fast clear // read in all vertices linePtr = goNextWord(linePtr, endPtr); @@ -279,8 +282,6 @@ IAnimatedMesh* COBJMeshFileLoader::createMesh(io::IReadFile* file) currMtl->Meshbuffer->Indices.push_back( faceCorners[i] ); currMtl->Meshbuffer->Indices.push_back( faceCorners[0] ); } - faceCorners.set_used(0); // fast clear - faceCorners.reallocate(32); } break; diff --git a/source/Irrlicht/COGLES2Driver.cpp b/source/Irrlicht/COGLES2Driver.cpp index c4cde00c..ba435a10 100644 --- a/source/Irrlicht/COGLES2Driver.cpp +++ b/source/Irrlicht/COGLES2Driver.cpp @@ -1798,11 +1798,7 @@ COGLES2Driver::~COGLES2Driver() } // Color Mask - CacheHandler->setColorMask( - (material.ColorMask & ECP_RED)?GL_TRUE:GL_FALSE, - (material.ColorMask & ECP_GREEN)?GL_TRUE:GL_FALSE, - (material.ColorMask & ECP_BLUE)?GL_TRUE:GL_FALSE, - (material.ColorMask & ECP_ALPHA)?GL_TRUE:GL_FALSE); + CacheHandler->setColorMask(material.ColorMask); // Blend Equation if (material.BlendOperation == EBO_NONE) @@ -2122,7 +2118,7 @@ COGLES2Driver::~COGLES2Driver() if (!(debugDataVisible & (scene::EDS_SKELETON|scene::EDS_MESH_WIRE_OVERLAY))) { - CacheHandler->setColorMask(false, false, false, false); + CacheHandler->setColorMask(ECP_NONE); glEnable(GL_STENCIL_TEST); } @@ -2191,7 +2187,7 @@ COGLES2Driver::~COGLES2Driver() setRenderStates2DMode(true, false, false); CacheHandler->setDepthMask(false); - CacheHandler->setColorMask(true, true, true, true); + CacheHandler->setColorMask(ECP_ALL); CacheHandler->setBlend(true); CacheHandler->setBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); @@ -2447,10 +2443,15 @@ COGLES2Driver::~COGLES2Driver() void COGLES2Driver::clearBuffers(u16 flag, SColor color, f32 depth, u8 stencil) { GLbitfield mask = 0; + u8 colorMask = 0; + bool depthMask = false; + + CacheHandler->getColorMask(colorMask); + CacheHandler->getDepthMask(depthMask); if (flag & ECBF_COLOR) { - CacheHandler->setColorMask(true, true, true, true); + CacheHandler->setColorMask(ECP_ALL); const f32 inv = 1.0f / 255.0f; glClearColor(color.getRed() * inv, color.getGreen() * inv, @@ -2474,6 +2475,9 @@ COGLES2Driver::~COGLES2Driver() if (mask) glClear(mask); + + CacheHandler->setColorMask(colorMask); + CacheHandler->setDepthMask(depthMask); } diff --git a/source/Irrlicht/COpenGLCoreCacheHandler.h b/source/Irrlicht/COpenGLCoreCacheHandler.h index 828be0c0..85cd9f2f 100644 --- a/source/Irrlicht/COpenGLCoreCacheHandler.h +++ b/source/Irrlicht/COpenGLCoreCacheHandler.h @@ -170,10 +170,10 @@ class COpenGLCoreCacheHandler public: COpenGLCoreCacheHandler(TOpenGLDriver* driver) : - Driver(driver), TextureCache(STextureCache(this, Driver->getFeature().TextureUnit)), FrameBufferCount(0), - BlendEquation(0), BlendSourceRGB(0), BlendDestinationRGB(0), BlendSourceAlpha(0), BlendDestinationAlpha(0), - Blend(0), ColorMask(0), CullFaceMode(GL_BACK), CullFace(false), DepthFunc(GL_LESS), DepthMask(true), - DepthTest(false), FrameBufferID(0), ProgramID(0), ActiveTexture(GL_TEXTURE0), ViewportX(0), ViewportY(0) + Driver(driver), TextureCache(STextureCache(this, Driver->getFeature().TextureUnit)), FrameBufferCount(0), BlendEquation(0), BlendSourceRGB(0), + BlendDestinationRGB(0), BlendSourceAlpha(0), BlendDestinationAlpha(0), Blend(0), BlendEquationInvalid(false), BlendFuncInvalid(false), BlendInvalid(false), + ColorMask(0), ColorMaskInvalid(false), CullFaceMode(GL_BACK), CullFace(false), DepthFunc(GL_LESS), DepthMask(true), DepthTest(false), FrameBufferID(0), + ProgramID(0), ActiveTexture(GL_TEXTURE0), ViewportX(0), ViewportY(0) { const COpenGLCoreFeature& feature = Driver->getFeature(); @@ -185,8 +185,7 @@ public: BlendSourceAlpha = new GLenum[FrameBufferCount]; BlendDestinationAlpha = new GLenum[FrameBufferCount]; Blend = new bool[FrameBufferCount]; - - ColorMask = new bool[FrameBufferCount][4]; + ColorMask = new u8[FrameBufferCount]; // Initial OpenGL values from specification. @@ -205,9 +204,7 @@ public: BlendDestinationAlpha[i] = GL_ZERO; Blend[i] = false; - - for (u32 j = 0; j < 4; ++j) - ColorMask[i][j] = true; + ColorMask[i] = ECP_ALL; } glBlendFunc(GL_ONE, GL_ZERO); @@ -260,12 +257,14 @@ public: void setBlendEquation(GLenum mode) { - if (BlendEquation[0] != mode) + if (BlendEquation[0] != mode || BlendEquationInvalid) { Driver->irrGlBlendEquation(mode); for (GLuint i = 0; i < FrameBufferCount; ++i) BlendEquation[i] = mode; + + BlendEquationInvalid = false; } } @@ -276,13 +275,15 @@ public: Driver->irrGlBlendEquationIndexed(index, mode); BlendEquation[index] = mode; + BlendEquationInvalid = true; } } void setBlendFunc(GLenum source, GLenum destination) { if (BlendSourceRGB[0] != source || BlendDestinationRGB[0] != destination || - BlendSourceAlpha[0] != source || BlendDestinationAlpha[0] != destination) + BlendSourceAlpha[0] != source || BlendDestinationAlpha[0] != destination || + BlendFuncInvalid) { glBlendFunc(source, destination); @@ -293,6 +294,8 @@ public: BlendSourceAlpha[i] = source; BlendDestinationAlpha[i] = destination; } + + BlendFuncInvalid = false; } } @@ -301,7 +304,8 @@ public: if (sourceRGB != sourceAlpha || destinationRGB != destinationAlpha) { if (BlendSourceRGB[0] != sourceRGB || BlendDestinationRGB[0] != destinationRGB || - BlendSourceAlpha[0] != sourceAlpha || BlendDestinationAlpha[0] != destinationAlpha) + BlendSourceAlpha[0] != sourceAlpha || BlendDestinationAlpha[0] != destinationAlpha || + BlendFuncInvalid) { Driver->irrGlBlendFuncSeparate(sourceRGB, destinationRGB, sourceAlpha, destinationAlpha); @@ -312,6 +316,8 @@ public: BlendSourceAlpha[i] = sourceAlpha; BlendDestinationAlpha[i] = destinationAlpha; } + + BlendFuncInvalid = false; } } else @@ -331,6 +337,7 @@ public: BlendDestinationRGB[index] = destination; BlendSourceAlpha[index] = source; BlendDestinationAlpha[index] = destination; + BlendFuncInvalid = true; } } @@ -347,6 +354,7 @@ public: BlendDestinationRGB[index] = destinationRGB; BlendSourceAlpha[index] = sourceAlpha; BlendDestinationAlpha[index] = destinationAlpha; + BlendFuncInvalid = true; } } else @@ -357,7 +365,7 @@ public: void setBlend(bool enable) { - if (Blend[0] != enable) + if (Blend[0] != enable || BlendInvalid) { if (enable) glEnable(GL_BLEND); @@ -366,6 +374,8 @@ public: for (GLuint i = 0; i < FrameBufferCount; ++i) Blend[i] = enable; + + BlendInvalid = false; } } @@ -379,37 +389,38 @@ public: Driver->irrGlDisableIndexed(GL_BLEND, index); Blend[index] = enable; + BlendInvalid = true; } } // Color Mask. - void setColorMask(bool red, bool green, bool blue, bool alpha) + void getColorMask(u8& mask) { - if (ColorMask[0][0] != red || ColorMask[0][1] != green || ColorMask[0][2] != blue || ColorMask[0][3] != alpha) + mask = ColorMask[0]; + } + + void setColorMask(u8 mask) + { + if (ColorMask[0] != mask || ColorMaskInvalid) { - glColorMask(red, green, blue, alpha); + glColorMask((mask & ECP_RED) ? GL_TRUE : GL_FALSE, (mask & ECP_GREEN) ? GL_TRUE : GL_FALSE, (mask & ECP_BLUE) ? GL_TRUE : GL_FALSE, (mask & ECP_ALPHA) ? GL_TRUE : GL_FALSE); for (GLuint i = 0; i < FrameBufferCount; ++i) - { - ColorMask[i][0] = red; - ColorMask[i][1] = green; - ColorMask[i][2] = blue; - ColorMask[i][3] = alpha; - } + ColorMask[i] = mask; + + ColorMaskInvalid = false; } } - void setColorMaskIndexed(GLuint index, bool red, bool green, bool blue, bool alpha) + void setColorMaskIndexed(GLuint index, u8 mask) { - if (index < FrameBufferCount && (ColorMask[index][0] != red || ColorMask[index][1] != green || ColorMask[index][2] != blue || ColorMask[index][3] != alpha)) + if (index < FrameBufferCount && ColorMask[index] != mask) { - Driver->irrGlColorMaskIndexed(index, red, green, blue, alpha); + Driver->irrGlColorMaskIndexed(index, (mask & ECP_RED) ? GL_TRUE : GL_FALSE, (mask & ECP_GREEN) ? GL_TRUE : GL_FALSE, (mask & ECP_BLUE) ? GL_TRUE : GL_FALSE, (mask & ECP_ALPHA) ? GL_TRUE : GL_FALSE); - ColorMask[index][0] = red; - ColorMask[index][1] = green; - ColorMask[index][2] = blue; - ColorMask[index][3] = alpha; + ColorMask[index] = mask; + ColorMaskInvalid = true; } } @@ -432,6 +443,7 @@ public: glEnable(GL_CULL_FACE); else glDisable(GL_CULL_FACE); + CullFace = enable; } } @@ -447,6 +459,11 @@ public: } } + void getDepthMask(bool& depth) + { + depth = DepthMask; + } + void setDepthMask(bool enable) { if (DepthMask != enable) @@ -455,6 +472,7 @@ public: glDepthMask(GL_TRUE); else glDepthMask(GL_FALSE); + DepthMask = enable; } } @@ -467,6 +485,7 @@ public: glEnable(GL_DEPTH_TEST); else glDisable(GL_DEPTH_TEST); + DepthTest = enable; } } @@ -554,8 +573,13 @@ protected: GLenum* BlendSourceAlpha; GLenum* BlendDestinationAlpha; bool* Blend; + bool BlendEquationInvalid; + bool BlendFuncInvalid; + bool BlendInvalid; + - bool(*ColorMask)[4]; + u8* ColorMask; + bool ColorMaskInvalid; GLenum CullFaceMode; bool CullFace; diff --git a/source/Irrlicht/COpenGLDriver.cpp b/source/Irrlicht/COpenGLDriver.cpp index 36a286a3..373dc0c2 100644 --- a/source/Irrlicht/COpenGLDriver.cpp +++ b/source/Irrlicht/COpenGLDriver.cpp @@ -467,7 +467,7 @@ bool COpenGLDriver::updateVertexHardwareBuffer(SHWBufferLink_opengl *HWBuffer) extGlBindBuffer(GL_ARRAY_BUFFER, 0); - return (!testGLError()); + return (!testGLError(__LINE__)); #else return false; #endif @@ -541,7 +541,7 @@ bool COpenGLDriver::updateIndexHardwareBuffer(SHWBufferLink_opengl *HWBuffer) extGlBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); - return (!testGLError()); + return (!testGLError(__LINE__)); #else return false; #endif @@ -735,10 +735,7 @@ void COpenGLDriver::runOcclusionQuery(scene::ISceneNode* node, bool visible) #else 0); #endif - if ( testGLError() ) - { - os::Printer::log("Occlusion Query failed", ELL_ERROR); - } + testGLError(__LINE__); } } @@ -766,10 +763,7 @@ void COpenGLDriver::updateOcclusionQuery(scene::ISceneNode* node, bool block) 0, #endif &available); - if ( testGLError() ) - { - os::Printer::log("extGlGetQueryObjectiv failed", ELL_ERROR); - } + testGLError(__LINE__); } if (available==GL_TRUE) { @@ -785,10 +779,7 @@ void COpenGLDriver::updateOcclusionQuery(scene::ISceneNode* node, bool block) if (queryFeature(EVDF_OCCLUSION_QUERY)) OcclusionQueries[index].Result = available; } - if ( testGLError() ) - { - os::Printer::log("extGlGetQueryObjectiv failed", ELL_ERROR); - } + testGLError(__LINE__); } } @@ -1295,87 +1286,24 @@ void COpenGLDriver::draw2DImage(const video::ITexture* texture, const core::posi if (!sourceRect.isValid()) return; - core::position2d targetPos(destPos); - core::position2d sourcePos(sourceRect.UpperLeftCorner); - // This needs to be signed as it may go negative. - core::dimension2d sourceSize(sourceRect.getSize()); + // clip these coordinates + core::rect targetRect(destPos, sourceRect.getSize()); if (clipRect) { - if (targetPos.X < clipRect->UpperLeftCorner.X) - { - sourceSize.Width += targetPos.X - clipRect->UpperLeftCorner.X; - if (sourceSize.Width <= 0) - return; - - sourcePos.X -= targetPos.X - clipRect->UpperLeftCorner.X; - targetPos.X = clipRect->UpperLeftCorner.X; - } - - if (targetPos.X + sourceSize.Width > clipRect->LowerRightCorner.X) - { - sourceSize.Width -= (targetPos.X + sourceSize.Width) - clipRect->LowerRightCorner.X; - if (sourceSize.Width <= 0) - return; - } - - if (targetPos.Y < clipRect->UpperLeftCorner.Y) - { - sourceSize.Height += targetPos.Y - clipRect->UpperLeftCorner.Y; - if (sourceSize.Height <= 0) - return; - - sourcePos.Y -= targetPos.Y - clipRect->UpperLeftCorner.Y; - targetPos.Y = clipRect->UpperLeftCorner.Y; - } - - if (targetPos.Y + sourceSize.Height > clipRect->LowerRightCorner.Y) - { - sourceSize.Height -= (targetPos.Y + sourceSize.Height) - clipRect->LowerRightCorner.Y; - if (sourceSize.Height <= 0) - return; - } - } - - // clip these coordinates - - if (targetPos.X<0) - { - sourceSize.Width += targetPos.X; - if (sourceSize.Width <= 0) + targetRect.clipAgainst(*clipRect); + if ( targetRect.getWidth() < 0 || targetRect.getHeight() < 0 ) return; - - sourcePos.X -= targetPos.X; - targetPos.X = 0; } const core::dimension2d& renderTargetSize = getCurrentRenderTargetSize(); - - if (targetPos.X + sourceSize.Width > (s32)renderTargetSize.Width) - { - sourceSize.Width -= (targetPos.X + sourceSize.Width) - renderTargetSize.Width; - if (sourceSize.Width <= 0) + targetRect.clipAgainst( core::rect(0,0, (s32)renderTargetSize.Width, (s32)renderTargetSize.Height) ); + if ( targetRect.getWidth() < 0 || targetRect.getHeight() < 0 ) return; - } - - if (targetPos.Y<0) - { - sourceSize.Height += targetPos.Y; - if (sourceSize.Height <= 0) - return; - - sourcePos.Y -= targetPos.Y; - targetPos.Y = 0; - } - - if (targetPos.Y + sourceSize.Height >(s32)renderTargetSize.Height) - { - sourceSize.Height -= (targetPos.Y + sourceSize.Height) - renderTargetSize.Height; - if (sourceSize.Height <= 0) - return; - } // ok, we've clipped everything. // now draw it. + const core::dimension2d sourceSize(targetRect.getSize()); + const core::position2d sourcePos(sourceRect.UpperLeftCorner + (targetRect.UpperLeftCorner-destPos)); const core::dimension2d& ss = texture->getOriginalSize(); const f32 invW = 1.f / static_cast(ss.Width); @@ -1386,8 +1314,6 @@ void COpenGLDriver::draw2DImage(const video::ITexture* texture, const core::posi (sourcePos.X + sourceSize.Width) * invW, (sourcePos.Y + sourceSize.Height) * invH); - const core::rect poss(targetPos, sourceSize); - disableTextures(1); if (!CacheHandler->getTextureCache().set(0, texture)) return; @@ -1398,10 +1324,10 @@ void COpenGLDriver::draw2DImage(const video::ITexture* texture, const core::posi Quad2DVertices[2].Color = color; Quad2DVertices[3].Color = color; - Quad2DVertices[0].Pos = core::vector3df((f32)poss.UpperLeftCorner.X, (f32)poss.UpperLeftCorner.Y, 0.0f); - Quad2DVertices[1].Pos = core::vector3df((f32)poss.LowerRightCorner.X, (f32)poss.UpperLeftCorner.Y, 0.0f); - Quad2DVertices[2].Pos = core::vector3df((f32)poss.LowerRightCorner.X, (f32)poss.LowerRightCorner.Y, 0.0f); - Quad2DVertices[3].Pos = core::vector3df((f32)poss.UpperLeftCorner.X, (f32)poss.LowerRightCorner.Y, 0.0f); + Quad2DVertices[0].Pos = core::vector3df((f32)targetRect.UpperLeftCorner.X, (f32)targetRect.UpperLeftCorner.Y, 0.0f); + Quad2DVertices[1].Pos = core::vector3df((f32)targetRect.LowerRightCorner.X, (f32)targetRect.UpperLeftCorner.Y, 0.0f); + Quad2DVertices[2].Pos = core::vector3df((f32)targetRect.LowerRightCorner.X, (f32)targetRect.LowerRightCorner.Y, 0.0f); + Quad2DVertices[3].Pos = core::vector3df((f32)targetRect.UpperLeftCorner.X, (f32)targetRect.LowerRightCorner.Y, 0.0f); Quad2DVertices[0].TCoords = core::vector2df(tcoords.UpperLeftCorner.X, tcoords.UpperLeftCorner.Y); Quad2DVertices[1].TCoords = core::vector2df(tcoords.LowerRightCorner.X, tcoords.UpperLeftCorner.Y); @@ -2111,7 +2037,7 @@ void COpenGLDriver::setMaterial(const SMaterial& material) //! prints error if an error happened. -bool COpenGLDriver::testGLError() +bool COpenGLDriver::testGLError(int code) { #ifdef _DEBUG GLenum g = glGetError(); @@ -2120,22 +2046,22 @@ bool COpenGLDriver::testGLError() case GL_NO_ERROR: return false; case GL_INVALID_ENUM: - os::Printer::log("GL_INVALID_ENUM", ELL_ERROR); break; + os::Printer::log("GL_INVALID_ENUM", core::stringc(code).c_str(), ELL_ERROR); break; case GL_INVALID_VALUE: - os::Printer::log("GL_INVALID_VALUE", ELL_ERROR); break; + os::Printer::log("GL_INVALID_VALUE", core::stringc(code).c_str(), ELL_ERROR); break; case GL_INVALID_OPERATION: - os::Printer::log("GL_INVALID_OPERATION", ELL_ERROR); break; + os::Printer::log("GL_INVALID_OPERATION", core::stringc(code).c_str(), ELL_ERROR); break; case GL_STACK_OVERFLOW: - os::Printer::log("GL_STACK_OVERFLOW", ELL_ERROR); break; + os::Printer::log("GL_STACK_OVERFLOW", core::stringc(code).c_str(), ELL_ERROR); break; case GL_STACK_UNDERFLOW: - os::Printer::log("GL_STACK_UNDERFLOW", ELL_ERROR); break; + os::Printer::log("GL_STACK_UNDERFLOW", core::stringc(code).c_str(), ELL_ERROR); break; case GL_OUT_OF_MEMORY: - os::Printer::log("GL_OUT_OF_MEMORY", ELL_ERROR); break; + os::Printer::log("GL_OUT_OF_MEMORY", core::stringc(code).c_str(), ELL_ERROR); break; case GL_TABLE_TOO_LARGE: - os::Printer::log("GL_TABLE_TOO_LARGE", ELL_ERROR); break; + os::Printer::log("GL_TABLE_TOO_LARGE", core::stringc(code).c_str(), ELL_ERROR); break; #if defined(GL_EXT_framebuffer_object) case GL_INVALID_FRAMEBUFFER_OPERATION_EXT: - os::Printer::log("GL_INVALID_FRAMEBUFFER_OPERATION", ELL_ERROR); break; + os::Printer::log("GL_INVALID_FRAMEBUFFER_OPERATION", core::stringc(code).c_str(), ELL_ERROR); break; #endif }; // _IRR_DEBUG_BREAK_IF(true); @@ -2540,11 +2466,7 @@ void COpenGLDriver::setBasicRenderStates(const SMaterial& material, const SMater } // Color Mask - CacheHandler->setColorMask( - (material.ColorMask & ECP_RED)?GL_TRUE:GL_FALSE, - (material.ColorMask & ECP_GREEN)?GL_TRUE:GL_FALSE, - (material.ColorMask & ECP_BLUE)?GL_TRUE:GL_FALSE, - (material.ColorMask & ECP_ALPHA)?GL_TRUE:GL_FALSE); + CacheHandler->setColorMask(material.ColorMask); // Blend Equation if (material.BlendOperation == EBO_NONE) @@ -3903,10 +3825,15 @@ bool COpenGLDriver::setRenderTargetEx(IRenderTarget* target, u16 clearFlag, SCol void COpenGLDriver::clearBuffers(u16 flag, SColor color, f32 depth, u8 stencil) { GLbitfield mask = 0; + u8 colorMask = 0; + bool depthMask = false; + + CacheHandler->getColorMask(colorMask); + CacheHandler->getDepthMask(depthMask); if (flag & ECBF_COLOR) { - CacheHandler->setColorMask(true, true, true, true); + CacheHandler->setColorMask(ECP_ALL); const f32 inv = 1.0f / 255.0f; glClearColor(color.getRed() * inv, color.getGreen() * inv, @@ -3930,6 +3857,9 @@ void COpenGLDriver::clearBuffers(u16 flag, SColor color, f32 depth, u8 stencil) if (mask) glClear(mask); + + CacheHandler->setColorMask(colorMask); + CacheHandler->setDepthMask(depthMask); } @@ -4004,10 +3934,7 @@ IImage* COpenGLDriver::createScreenShot(video::ECOLOR_FORMAT format, video::E_RE } glReadBuffer(tgt); glReadPixels(0, 0, ScreenSize.Width, ScreenSize.Height, fmt, type, pixels); - if ( testGLError() ) - { - os::Printer::log("glReadPixels failed", ELL_ERROR); - } + testGLError(__LINE__); glReadBuffer(GL_BACK); } @@ -4043,7 +3970,7 @@ IImage* COpenGLDriver::createScreenShot(video::ECOLOR_FORMAT format, video::E_RE if (newImage) { - if (testGLError() || !pixels) + if (testGLError(__LINE__) || !pixels) { os::Printer::log("createScreenShot failed", ELL_ERROR); newImage->drop(); diff --git a/source/Irrlicht/COpenGLDriver.h b/source/Irrlicht/COpenGLDriver.h index 192bd12a..e9d79d17 100644 --- a/source/Irrlicht/COpenGLDriver.h +++ b/source/Irrlicht/COpenGLDriver.h @@ -345,9 +345,9 @@ namespace video //! Returns an image created from the last rendered frame. virtual IImage* createScreenShot(video::ECOLOR_FORMAT format=video::ECF_UNKNOWN, video::E_RENDER_TARGET target=video::ERT_FRAME_BUFFER) _IRR_OVERRIDE_; - //! checks if an OpenGL error has happend and prints it + //! checks if an OpenGL error has happened and prints it (+ some internal code which is usually the line number) //! for performance reasons only available in debug mode - bool testGLError(); + bool testGLError(int code=0); //! Set/unset a clipping plane. //! There are at least 6 clipping planes available for the user to set at will. diff --git a/source/Irrlicht/CWebGL1Driver.cpp b/source/Irrlicht/CWebGL1Driver.cpp index 9e194d20..6dfb8b21 100644 --- a/source/Irrlicht/CWebGL1Driver.cpp +++ b/source/Irrlicht/CWebGL1Driver.cpp @@ -696,7 +696,7 @@ void CWebGL1Driver::drawStencilShadow(bool clearStencilBuffer, lockRenderStateMode(); CacheHandler->setDepthMask(false); - CacheHandler->setColorMask(true, true, true, true); + CacheHandler->setColorMask(ECP_ALL); CacheHandler->setBlend(true); CacheHandler->setBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);