diff --git a/changes.txt b/changes.txt index ce3fe6d..17b2687 100644 --- a/changes.txt +++ b/changes.txt @@ -11,6 +11,8 @@ Changes in ogl-es (not yet released - will be merged with trunk at some point) -------------------------- Changes in 1.9 (not yet released) +- Add IMeshSceneNode::setNodeRegistration to allow registering MeshSceneNodes to the SceneManager per buffer instead of per node +- Add SMaterialLayer::hasSetTextureMatrix and SMaterialLayer::resetTextureMatrix - Add IShaderConstantSetCallBack::OnCreate to allow earlier access to IMaterialRendererServices - CIrrDeviceWin32::yield() now uses Sleep(0) instead of Sleep(1). We had Sleep(1) to allow yielding to all processes back in Windows XP time. diff --git a/examples/09.Meshviewer/main.cpp b/examples/09.Meshviewer/main.cpp index 1a5f51a..5a8f215 100644 --- a/examples/09.Meshviewer/main.cpp +++ b/examples/09.Meshviewer/main.cpp @@ -255,7 +255,7 @@ void loadModel(const io::path& filename) // that's not so simple. so we do it brute force gui::IGUIContextMenu* menu = (gui::IGUIContextMenu*)Device->getGUIEnvironment()->getRootGUIElement()->getElementFromId(GUI_ID_TOGGLE_DEBUG_INFO, true); if (menu) - for(int item = 1; item < 6; ++item) + for(int item = 1; item < 7; ++item) menu->setItemChecked(item, false); updateScaleInfo(Model); } diff --git a/include/ESceneNodeUpdateAbs.h b/include/ESceneNodeUpdateAbs.h index 6b4a115..4a75163 100644 --- a/include/ESceneNodeUpdateAbs.h +++ b/include/ESceneNodeUpdateAbs.h @@ -17,7 +17,11 @@ namespace scene //! Only transform the position of the node transformation matrix //! by the parent transformation matrix. //! Parent will not affect the rotation/scale of the node transformation. - ESNUA_TRANSFORM_POSITION + ESNUA_TRANSFORM_POSITION, + + //! Use the relative matrix as absolute transformation matrix + //! Parent node transformation is ignored just like when the parent is set to 0 + ESNUA_RELATIVE }; //! Names for culling type @@ -25,6 +29,7 @@ namespace scene { "matrix", "pos", + "relative", 0 }; diff --git a/include/IMaterialRendererServices.h b/include/IMaterialRendererServices.h index c4ef674..321afd1 100644 --- a/include/IMaterialRendererServices.h +++ b/include/IMaterialRendererServices.h @@ -24,20 +24,6 @@ public: //! Destructor virtual ~IMaterialRendererServices() {} - //! Can be called by an IMaterialRenderer to make its work easier. - /** Sets all basic renderstates if needed. - Basic render states are diffuse, ambient, specular, and emissive color, - specular power, bilinear and trilinear filtering, wireframe mode, - gouraudshading, lighting, zbuffer, zwriteenable, backfaceculling and - fog enabling. - \param material The new material to be used. - \param lastMaterial The material used until now. - \param resetAllRenderstates Set to true if all renderstates should be - set, regardless of their current state. */ - virtual void setBasicRenderStates(const SMaterial& material, - const SMaterial& lastMaterial, - bool resetAllRenderstates) = 0; - //! Return an index constant for the vertex shader based on a name. virtual s32 getVertexShaderConstantID(const c8* name) = 0; diff --git a/include/IMeshSceneNode.h b/include/IMeshSceneNode.h index 309f46d..25600e7 100644 --- a/include/IMeshSceneNode.h +++ b/include/IMeshSceneNode.h @@ -15,6 +15,20 @@ namespace scene class IShadowVolumeSceneNode; class IMesh; +//! Option for nodes how to register themeselves at the SceneManager +enum ENodeRegistration +{ + //! Each node registers once and renders all it's mesh-buffers + ENR_DEFAULT, + + //! Register a new node per mesh-buffer at the SceneManager + //! It allows the SceneManager to sort in each render stage per buffer instead of per node. + //! This can be useful when having several transparent buffers in a mesh. + //! Depending on the scene (and hardware) this can have a positive or negative effect on performance. + //! It can avoid texture-switches, but adds nodes to sort and more matrix transformations are set. + ENR_PER_MESH_BUFFER +}; + //! A scene node displaying a static mesh class IMeshSceneNode : public ISceneNode @@ -28,9 +42,11 @@ public: const core::vector3df& position = core::vector3df(0,0,0), const core::vector3df& rotation = core::vector3df(0,0,0), const core::vector3df& scale = core::vector3df(1,1,1)) - : ISceneNode(parent, mgr, id, position, rotation, scale) {} + : ISceneNode(parent, mgr, id, position, rotation, scale) + , NodeRegistration(ENR_DEFAULT) + {} - //! Sets a new mesh to display + //! Sets a new mesh to display or update mesh when it changed /** \param mesh Mesh to display. */ virtual void setMesh(IMesh* mesh) = 0; @@ -73,6 +89,23 @@ public: /** This flag can be set by setReadOnlyMaterials(). \return Whether the materials are read-only. */ virtual bool isReadOnlyMaterials() const = 0; + + //! Set how the node registers itself to the SceneManager + /** Note: Derived classes can ignore this flag, so think of it as a hint. */ + virtual void setNodeRegistration(ENodeRegistration nodeRegistration) + { + NodeRegistration = nodeRegistration; + } + + //! How does a node register itself to the SceneManager + /** Note: Derived classes may ignore this flag */ + virtual ENodeRegistration getNodeRegistration() const + { + return NodeRegistration; + } + +protected: + ENodeRegistration NodeRegistration; }; } // end namespace scene diff --git a/include/ISceneManager.h b/include/ISceneManager.h index eae5d49..64ab0e8 100644 --- a/include/ISceneManager.h +++ b/include/ISceneManager.h @@ -66,7 +66,7 @@ namespace scene //! In this pass, lights are transformed into camera space and added to the driver ESNRP_LIGHT =2, - //! This is used for sky boxes. + //! This is mostly used for sky boxes. Stage between light and solid. ESNRP_SKY_BOX =4, //! All normal objects can use this for registering themselves. diff --git a/include/ISceneNode.h b/include/ISceneNode.h index a20daab..18c5bff 100644 --- a/include/ISceneNode.h +++ b/include/ISceneNode.h @@ -79,7 +79,7 @@ namespace scene //! This method is called just before the rendering process of the whole scene. /** Nodes may register themselves in the render pipeline during this call, - precalculate the geometry which should be rendered, and prevent their + pre-calculate the geometry which should be rendered, and prevent their children from being able to register themselves if they are clipped by simply not calling their OnRegisterSceneNode method. If you are implementing your own scene node, you should overwrite this method @@ -95,7 +95,7 @@ namespace scene { if (IsVisible) { - ISceneNodeList::Iterator it = Children.begin(); + ISceneNodeList::ConstIterator it = Children.begin(); for (; it != Children.end(); ++it) (*it)->OnRegisterSceneNode(); } @@ -114,7 +114,7 @@ namespace scene { // animate this node with all animators - ISceneNodeAnimatorList::Iterator ait = Animators.begin(); + ISceneNodeAnimatorList::ConstIterator ait = Animators.begin(); while (ait != Animators.end()) { // continue to the next node before calling animateNode() @@ -133,7 +133,7 @@ namespace scene // perform the post render process on all children - ISceneNodeList::Iterator it = Children.begin(); + ISceneNodeList::ConstIterator it = Children.begin(); for (; it != Children.end(); ++it) (*it)->OnAnimate(timeMs); } @@ -543,7 +543,7 @@ namespace scene //! Set a culling style or disable culling completely. - /** Box cullling (EAC_BOX) is set by default. Note that not + /** Box culling (EAC_BOX) is set by default. Note that not all SceneNodes support culling and that some nodes always cull their geometry because it is their only reason for existence, for example the OctreeSceneNode. @@ -682,16 +682,24 @@ namespace scene { if (Parent) { - if ( AbsPosUpdateBehavior == ESNUA_TRANSFORM_MATRIX ) + switch ( AbsPosUpdateBehavior ) + { + case ESNUA_TRANSFORM_MATRIX: { AbsoluteTransformation = Parent->getAbsoluteTransformation() * getRelativeTransformation(); } - else if ( AbsPosUpdateBehavior == ESNUA_TRANSFORM_POSITION ) + break; + case ESNUA_TRANSFORM_POSITION: { AbsoluteTransformation = getRelativeTransformation(); Parent->getAbsoluteTransformation().transformVect(reinterpret_cast(AbsoluteTransformation[12])); } + break; + case ESNUA_RELATIVE: + AbsoluteTransformation = getRelativeTransformation(); + break; + } } else AbsoluteTransformation = getRelativeTransformation(); @@ -821,7 +829,7 @@ namespace scene // clone children - ISceneNodeList::Iterator it = toCopyFrom->Children.begin(); + ISceneNodeList::ConstIterator it = toCopyFrom->Children.begin(); for (; it != toCopyFrom->Children.end(); ++it) (*it)->clone(this, newManager); diff --git a/include/SMaterialLayer.h b/include/SMaterialLayer.h index 51ddf66..48698cd 100644 --- a/include/SMaterialLayer.h +++ b/include/SMaterialLayer.h @@ -45,7 +45,7 @@ namespace video "texture_clamp_mirror_clamp_to_border", 0}; //! Struct for holding material parameters which exist per texture layer - // Note for implementors: Serialization is in CNullDriver + // Note for implementers: Serialization is in CNullDriver class SMaterialLayer { public: @@ -153,6 +153,25 @@ namespace video *TextureMatrix = mat; } + //! Check if we have set a custom texture matrix + //! Note that otherwise we get an IdentityMatrix as default + inline bool hasSetTextureMatrix() const + { + return TextureMatrix != 0; + } + + //! Reset texture matrix to identity matrix + //! Releases memory, which is expensive, but ver rarely useful for optimizations + void resetTextureMatrix() + { + if ( TextureMatrix ) + { + MatrixAllocator.destruct(TextureMatrix); + MatrixAllocator.deallocate(TextureMatrix); + TextureMatrix = 0; + } + } + //! Inequality operator /** \param b Layer to compare to. \return True if layers are different, else false. */ diff --git a/source/Irrlicht/CBufferRenderNode.h b/source/Irrlicht/CBufferRenderNode.h new file mode 100644 index 0000000..923434f --- /dev/null +++ b/source/Irrlicht/CBufferRenderNode.h @@ -0,0 +1,185 @@ +// Copyright (C) 2002-2012 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#include "IMeshSceneNode.h" +#include "IVideoDriver.h" +#include "ISceneManager.h" +#include "ISceneNode.h" + +namespace irr +{ +namespace scene +{ + +// A node which helps rendering a single buffer of an IMeshSceneNode +// It solves several problems: +// - Allowing the scene manager to sort meshbuffers. Currently it only sorts nodes, so we have to put each meshbuffer in an extra node to allow that +// The reason we want that is +// a) Better sorting when a node has several transparent buffers (without it they will be just drawn in original order) +// b) It can allow to avoid texture changes in the render-pipeline which can make quite a bit of a performance difference +// - It buffers the RenderPass. Bit of an abuse of this interface maybe? +// Strangely the check for finding out the correct render pass constantly shows up in profilers. +// Not exactly sure why as the check looks pretty cheap. My best guess is that there are some cache misses going on due to several virtual +// function pointers being involved in the transparency check. +// +// For now (added pre Irrlicht 1.9) this interface is still a bit experimental. Maybe could go into public headers later, not sure yet. +// Or maybe the SceneManager shouldn't work with nodes at all but a simplified interface to render buffers from which Nodes can derive? +// CBufferRenderNode isn't really a node - it has to work around nearly all the ISceneNode functions, it only has to be one because +// the SceneManager can't sort anything else but nodes. +class CBufferRenderNode : public ISceneNode +{ +public: + CBufferRenderNode(irr::scene::IMeshSceneNode& parent, irr::scene::ISceneManager* mgr, irr::u32 bufferIdx) + : ISceneNode(0, mgr) // we don't want it in the scenegraph + , MeshNodeParent(parent) + , BufferIdx(bufferIdx) + , RenderPass(ESNRP_NONE) + , ParentDoesRender(true) + { + // While it's not the parent in the SceneGraph, we still want to allow accessing it + // That can be useful p.E. in a light manager + // Arguably if it's a good idea as it's a bit going against the ISceneNode interface - having a parent which doesn't have this node as child. + // But the alternative is adding another member to the ISceneNode or having SceneManager not use the ISceneNode for rendering + // So for now it should be fine, but if that interface ever get's public... we might have to reconsider + Parent = &MeshNodeParent; + } + + u32 prepareRendering(E_SCENE_NODE_RENDER_PASS pass, bool parentDoesRender) + { + RenderPass = pass; + ParentDoesRender = parentDoesRender; + if ( !ParentDoesRender ) + return SceneManager->registerNodeForRendering(this, pass); + return 0; + } + + E_SCENE_NODE_RENDER_PASS getRenderPass() const + { + return RenderPass; + } + + // When true render() this node hasn't registered itself for rendering, but expects it's owner to do the rendering + bool getDoesParentRender() const + { + return ParentDoesRender; + } + + // Render meshbuffer, but don't set transformation + // It's assumed that this function is only called from within the correct render stage + void renderBuffer(video::IVideoDriver* driver) + { + const IMeshBuffer* mb = MeshNodeParent.getMesh()->getMeshBuffer(BufferIdx); + if (mb) + { + const video::SMaterial& material = MeshNodeParent.getMaterial(BufferIdx); + driver->setMaterial(material); + driver->drawMeshBuffer(mb); + } + } + + //! Renders the node. + virtual void render() IRR_OVERRIDE + { + video::IVideoDriver* driver = SceneManager->getVideoDriver(); + driver->setTransform(video::ETS_WORLD, MeshNodeParent.getAbsoluteTransformation()); + renderBuffer(driver); + + // resetting each time so direct calls to render() for parent node continue to work + RenderPass = ESNRP_NONE; + ParentDoesRender = true; + } + + virtual const core::aabbox3d& getBoundingBox() const IRR_OVERRIDE + { + return MeshNodeParent.getMesh()->getMeshBuffer(BufferIdx)->getBoundingBox(); + } + + virtual video::SMaterial& getMaterial(u32 num) IRR_OVERRIDE + { + return MeshNodeParent.getMaterial(BufferIdx); + } + + virtual u32 getMaterialCount() const IRR_OVERRIDE + { + return 1; + } + + virtual const core::matrix4& getAbsoluteTransformation() const IRR_OVERRIDE + { + return MeshNodeParent.getAbsoluteTransformation(); + } + + virtual const core::aabbox3d getTransformedBoundingBox() const IRR_OVERRIDE + { + core::aabbox3d box = getBoundingBox(); + getAbsoluteTransformation().transformBoxEx(box); + return box; + } + + virtual void getTransformedBoundingBoxEdges(core::array< core::vector3d >& edges) const IRR_OVERRIDE + { + edges.set_used(8); + getBoundingBox().getEdges( edges.pointer() ); + for ( u32 i=0; i<8; ++i ) + getAbsoluteTransformation().transformVect( edges[i] ); + } + + virtual core::matrix4 getRelativeTransformation() const IRR_OVERRIDE + { + return MeshNodeParent.getRelativeTransformation(); + } + + virtual s32 getID() const IRR_OVERRIDE + { + return MeshNodeParent.getID(); + } + + virtual const core::vector3df& getScale() const IRR_OVERRIDE + { + return MeshNodeParent.getScale(); + } + + virtual const core::vector3df& getRotation() const IRR_OVERRIDE + { + return MeshNodeParent.getRotation(); + } + + virtual const core::vector3df& getPosition() const IRR_OVERRIDE + { + return MeshNodeParent.getPosition(); + } + + virtual core::vector3df getAbsolutePosition() const IRR_OVERRIDE + { + return MeshNodeParent.getAbsolutePosition(); + } + + virtual ITriangleSelector* getTriangleSelector() const IRR_OVERRIDE + { + return MeshNodeParent.getTriangleSelector(); + } + + // Not allowing any of that stuff + virtual void OnRegisterSceneNode()IRR_OVERRIDE {} + virtual void OnAnimate(u32 timeMs) IRR_OVERRIDE {} + virtual void addChild(ISceneNode* child) IRR_OVERRIDE {} + virtual void addAnimator(ISceneNodeAnimator* animator) IRR_OVERRIDE {} + virtual void setScale(const core::vector3df& scale) IRR_OVERRIDE {} + virtual void setRotation(const core::vector3df& rotation) IRR_OVERRIDE {} + virtual void setPosition(const core::vector3df& newpos) IRR_OVERRIDE {} + virtual void setParent(ISceneNode* newParent) IRR_OVERRIDE {} + virtual void setTriangleSelector(ITriangleSelector* selector) IRR_OVERRIDE {} + virtual void updateAbsolutePosition() IRR_OVERRIDE {} + virtual void serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options=0) const IRR_OVERRIDE {} + virtual void deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options=0) IRR_OVERRIDE {} + +private: + irr::scene::IMeshSceneNode& MeshNodeParent; + irr::u32 BufferIdx; // Note: Not saving the meshbuffer pointer as meshes can add/remove buffers and we don't want to keep track of that + E_SCENE_NODE_RENDER_PASS RenderPass; + bool ParentDoesRender; +}; + +} // end namespace scene +} // end namespace irr diff --git a/source/Irrlicht/CColladaFileLoader.cpp b/source/Irrlicht/CColladaFileLoader.cpp index 4d74f48..cec931f 100644 --- a/source/Irrlicht/CColladaFileLoader.cpp +++ b/source/Irrlicht/CColladaFileLoader.cpp @@ -20,11 +20,12 @@ #include "IAttributes.h" #include "IMeshCache.h" #include "IMeshSceneNode.h" -#include "SMeshBufferLightMap.h" +#include "CDynamicMeshBuffer.h" #include "irrMap.h" #ifdef _DEBUG -#define COLLADA_READER_DEBUG +// Lots of messages, with how slow some consoles are loading can then take minutes +// #define COLLADA_READER_DEBUG #endif namespace irr { @@ -2123,16 +2124,16 @@ void CColladaFileLoader::readPolygonSection(io::IXMLReaderUTF8* reader, { // standard mesh buffer - scene::SMeshBuffer* mbuffer = new SMeshBuffer(); + scene::CDynamicMeshBuffer* mbuffer = new CDynamicMeshBuffer(video::EVT_STANDARD, IndexTypeHint == EITH_16BIT ? video::EIT_16BIT : video::EIT_32BIT); buffer = mbuffer; core::map vertMap; for (u32 i=0; i indices; + core::array indices; const u32 vertexCount = polygons[i].Indices.size() / maxOffset; - mbuffer->Vertices.reallocate(mbuffer->Vertices.size()+vertexCount); + mbuffer->getVertexBuffer().reallocate(mbuffer->getVertexBuffer().size()+vertexCount); // for all index/semantic groups for (u32 v=0; vgetVertexCount()); - mbuffer->Vertices.push_back(vtx); + mbuffer->getVertexBuffer().push_back(vtx); vertMap.insert(vtx, mbuffer->getVertexCount()-1); } } // end for all vertices @@ -2221,9 +2222,9 @@ void CColladaFileLoader::readPolygonSection(io::IXMLReaderUTF8* reader, // as full tessellation is problematic for (u32 ind = 0; ind+2 < indices.size(); ++ind) { - mbuffer->Indices.push_back(indices[0]); - mbuffer->Indices.push_back(indices[ind+2]); - mbuffer->Indices.push_back(indices[ind+1]); + mbuffer->getIndexBuffer().push_back(indices[0]); + mbuffer->getIndexBuffer().push_back(indices[ind+2]); + mbuffer->getIndexBuffer().push_back(indices[ind+1]); } } else @@ -2231,25 +2232,30 @@ void CColladaFileLoader::readPolygonSection(io::IXMLReaderUTF8* reader, // it's just triangles for (u32 ind = 0; ind < indices.size(); ind+=3) { - mbuffer->Indices.push_back(indices[ind+2]); - mbuffer->Indices.push_back(indices[ind+1]); - mbuffer->Indices.push_back(indices[ind+0]); + mbuffer->getIndexBuffer().push_back(indices[ind+2]); + mbuffer->getIndexBuffer().push_back(indices[ind+1]); + mbuffer->getIndexBuffer().push_back(indices[ind+0]); } } } // end for all polygons + + if ( getIndexTypeHint() == EITH_OPTIMAL && mbuffer->getVertexCount() <= 65536 ) + { + mbuffer->getIndexBuffer().setType(video::EIT_16BIT); // from 32 to 16 bit + } } else { // lightmap mesh buffer - scene::SMeshBufferLightMap* mbuffer = new SMeshBufferLightMap(); + scene::CDynamicMeshBuffer* mbuffer = new CDynamicMeshBuffer(video::EVT_2TCOORDS, IndexTypeHint == EITH_16BIT ? video::EIT_16BIT : video::EIT_32BIT); buffer = mbuffer; for (u32 i=0; iVertices.reallocate(mbuffer->Vertices.size()+vertexCount); + mbuffer->getVertexBuffer().reallocate(mbuffer->getVertexBuffer().size()+vertexCount); // for all vertices in array for (u32 v=0; vVertices.push_back(vtx); + mbuffer->getVertexBuffer().push_back(vtx); } // end for all vertices // add vertex indices - const u32 oldVertexCount = mbuffer->Vertices.size() - vertexCount; + const u32 oldVertexCount = mbuffer->getVertexBuffer().size() - vertexCount; for (u32 face=0; faceIndices.push_back(oldVertexCount + 0); - mbuffer->Indices.push_back(oldVertexCount + 1 + face); - mbuffer->Indices.push_back(oldVertexCount + 2 + face); + mbuffer->getIndexBuffer().push_back(oldVertexCount + 0); + mbuffer->getIndexBuffer().push_back(oldVertexCount + 1 + face); + mbuffer->getIndexBuffer().push_back(oldVertexCount + 2 + face); } } // end for all polygons + + if ( getIndexTypeHint() == EITH_OPTIMAL && mbuffer->getVertexCount() <= 65536 ) + { + mbuffer->getIndexBuffer().setType(video::EIT_16BIT); // from 32 to 16 bit + } } const SColladaMaterial* m = findMaterial(materialName); if (m) { buffer->getMaterial() = m->Mat; - SMesh tmpmesh; - tmpmesh.addMeshBuffer(buffer); - SceneManager->getMeshManipulator()->setVertexColors(&tmpmesh,m->Mat.DiffuseColor); + SceneManager->getMeshManipulator()->setVertexColors(buffer,m->Mat.DiffuseColor); if (m->Transparency != 1.0f) - SceneManager->getMeshManipulator()->setVertexColorAlpha(&tmpmesh,core::floor32(m->Transparency*255.0f)); + SceneManager->getMeshManipulator()->setVertexColorAlpha(buffer,core::floor32(m->Transparency*255.0f)); } // add future bind reference for the material core::stringc meshbufferReference = geometryId+"/"+materialName; diff --git a/source/Irrlicht/CColladaFileLoader.h b/source/Irrlicht/CColladaFileLoader.h index b8b661c..e3cd69e 100644 --- a/source/Irrlicht/CColladaFileLoader.h +++ b/source/Irrlicht/CColladaFileLoader.h @@ -10,7 +10,6 @@ #include "IVideoDriver.h" #include "irrString.h" #include "SMesh.h" -#include "SMeshBuffer.h" #include "ISceneManager.h" #include "irrMap.h" #include "CAttributes.h" diff --git a/source/Irrlicht/CD3D9Driver.h b/source/Irrlicht/CD3D9Driver.h index c25ca01..0d8c343 100644 --- a/source/Irrlicht/CD3D9Driver.h +++ b/source/Irrlicht/CD3D9Driver.h @@ -222,8 +222,8 @@ namespace video virtual void OnResize(const core::dimension2d& size) IRR_OVERRIDE; //! Can be called by an IMaterialRenderer to make its work easier. - virtual void setBasicRenderStates(const SMaterial& material, const SMaterial& lastMaterial, - bool resetAllRenderstates) IRR_OVERRIDE; + void setBasicRenderStates(const SMaterial& material, const SMaterial& lastMaterial, + bool resetAllRenderstates); //! Returns type of video driver virtual E_DRIVER_TYPE getDriverType() const IRR_OVERRIDE; diff --git a/source/Irrlicht/CD3D9HLSLMaterialRenderer.cpp b/source/Irrlicht/CD3D9HLSLMaterialRenderer.cpp index 7da1112..639caac 100644 --- a/source/Irrlicht/CD3D9HLSLMaterialRenderer.cpp +++ b/source/Irrlicht/CD3D9HLSLMaterialRenderer.cpp @@ -275,11 +275,6 @@ bool CD3D9HLSLMaterialRenderer::createHLSLPixelShader(const char* pixelShaderPro return false; } -void CD3D9HLSLMaterialRenderer::setBasicRenderStates(const SMaterial& material, const SMaterial& lastMaterial, bool resetAllRenderstates) -{ - Driver->setBasicRenderStates(material, lastMaterial, resetAllRenderstates); -} - s32 CD3D9HLSLMaterialRenderer::getVertexShaderConstantID(const c8* name) { return getVariableID(true, name); diff --git a/source/Irrlicht/CD3D9HLSLMaterialRenderer.h b/source/Irrlicht/CD3D9HLSLMaterialRenderer.h index 3b61483..df3d2a2 100644 --- a/source/Irrlicht/CD3D9HLSLMaterialRenderer.h +++ b/source/Irrlicht/CD3D9HLSLMaterialRenderer.h @@ -47,7 +47,6 @@ public: bool OnRender(IMaterialRendererServices* service, E_VERTEX_TYPE vtxtype) IRR_OVERRIDE; // implementations for IMaterialRendererServices - virtual void setBasicRenderStates(const SMaterial& material, const SMaterial& lastMaterial, bool resetAllRenderstates) IRR_OVERRIDE; virtual s32 getVertexShaderConstantID(const c8* name) IRR_OVERRIDE; virtual s32 getPixelShaderConstantID(const c8* name) IRR_OVERRIDE; virtual void setVertexShaderConstant(const f32* data, s32 startRegister, s32 constantAmount=1) IRR_OVERRIDE; diff --git a/source/Irrlicht/CD3D9MaterialRenderer.h b/source/Irrlicht/CD3D9MaterialRenderer.h index 08f36bf..76aa04d 100644 --- a/source/Irrlicht/CD3D9MaterialRenderer.h +++ b/source/Irrlicht/CD3D9MaterialRenderer.h @@ -82,7 +82,7 @@ public: virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial, bool resetAllRenderstates, IMaterialRendererServices* services) IRR_OVERRIDE { - services->setBasicRenderStates(material, lastMaterial, resetAllRenderstates); + Driver->setBasicRenderStates(material, lastMaterial, resetAllRenderstates); if (material.MaterialType != lastMaterial.MaterialType || resetAllRenderstates) { @@ -105,7 +105,7 @@ public: virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial, bool resetAllRenderstates, IMaterialRendererServices* services) IRR_OVERRIDE { - services->setBasicRenderStates(material, lastMaterial, resetAllRenderstates); + Driver->setBasicRenderStates(material, lastMaterial, resetAllRenderstates); // if (material.MaterialType != lastMaterial.MaterialType || // material.MaterialTypeParam != lastMaterial.MaterialTypeParam || @@ -175,7 +175,7 @@ public: virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial, bool resetAllRenderstates, IMaterialRendererServices* services) IRR_OVERRIDE { - services->setBasicRenderStates(material, lastMaterial, resetAllRenderstates); + Driver->setBasicRenderStates(material, lastMaterial, resetAllRenderstates); if (material.MaterialType != lastMaterial.MaterialType || resetAllRenderstates) { @@ -199,7 +199,7 @@ public: virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial, bool resetAllRenderstates, IMaterialRendererServices* services) IRR_OVERRIDE { - services->setBasicRenderStates(material, lastMaterial, resetAllRenderstates); + Driver->setBasicRenderStates(material, lastMaterial, resetAllRenderstates); Driver->getBridgeCalls()->setBlend(true); Driver->getBridgeCalls()->setBlendFunc(D3DBLEND_ONE, D3DBLEND_INVSRCCOLOR); @@ -238,7 +238,7 @@ public: virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial, bool resetAllRenderstates, IMaterialRendererServices* services) IRR_OVERRIDE { - services->setBasicRenderStates(material, lastMaterial, resetAllRenderstates); + Driver->setBasicRenderStates(material, lastMaterial, resetAllRenderstates); Driver->getBridgeCalls()->setBlend(true); Driver->getBridgeCalls()->setBlendFunc(D3DBLEND_SRCALPHA, D3DBLEND_INVSRCALPHA); @@ -278,7 +278,7 @@ public: virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial, bool resetAllRenderstates, IMaterialRendererServices* services) IRR_OVERRIDE { - services->setBasicRenderStates(material, lastMaterial, resetAllRenderstates); + Driver->setBasicRenderStates(material, lastMaterial, resetAllRenderstates); Driver->getBridgeCalls()->setBlend(true); Driver->getBridgeCalls()->setBlendFunc(D3DBLEND_SRCALPHA, D3DBLEND_INVSRCALPHA); @@ -325,7 +325,7 @@ public: virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial, bool resetAllRenderstates, IMaterialRendererServices* services) IRR_OVERRIDE { - services->setBasicRenderStates(material, lastMaterial, resetAllRenderstates); + Driver->setBasicRenderStates(material, lastMaterial, resetAllRenderstates); if (material.MaterialType != lastMaterial.MaterialType || resetAllRenderstates) { @@ -367,7 +367,7 @@ public: virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial, bool resetAllRenderstates, IMaterialRendererServices* services) IRR_OVERRIDE { - services->setBasicRenderStates(material, lastMaterial, resetAllRenderstates); + Driver->setBasicRenderStates(material, lastMaterial, resetAllRenderstates); if (material.MaterialType != lastMaterial.MaterialType || resetAllRenderstates) { @@ -411,7 +411,7 @@ public: virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial, bool resetAllRenderstates, IMaterialRendererServices* services) IRR_OVERRIDE { - services->setBasicRenderStates(material, lastMaterial, resetAllRenderstates); + Driver->setBasicRenderStates(material, lastMaterial, resetAllRenderstates); if (material.MaterialType != lastMaterial.MaterialType || resetAllRenderstates) { @@ -436,7 +436,7 @@ public: virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial, bool resetAllRenderstates, IMaterialRendererServices* services) IRR_OVERRIDE { - services->setBasicRenderStates(material, lastMaterial, resetAllRenderstates); + Driver->setBasicRenderStates(material, lastMaterial, resetAllRenderstates); if (material.MaterialType != lastMaterial.MaterialType || resetAllRenderstates) { @@ -471,7 +471,7 @@ public: virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial, bool resetAllRenderstates, IMaterialRendererServices* services) IRR_OVERRIDE { - services->setBasicRenderStates(material, lastMaterial, resetAllRenderstates); + Driver->setBasicRenderStates(material, lastMaterial, resetAllRenderstates); if (material.MaterialType != lastMaterial.MaterialType || resetAllRenderstates) { @@ -507,7 +507,7 @@ public: virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial, bool resetAllRenderstates, IMaterialRendererServices* services) IRR_OVERRIDE { - services->setBasicRenderStates(material, lastMaterial, resetAllRenderstates); + Driver->setBasicRenderStates(material, lastMaterial, resetAllRenderstates); Driver->getBridgeCalls()->setBlend(true); Driver->getBridgeCalls()->setBlendFunc(D3DBLEND_SRCALPHA, D3DBLEND_INVSRCALPHA); diff --git a/source/Irrlicht/CD3D9ShaderMaterialRenderer.cpp b/source/Irrlicht/CD3D9ShaderMaterialRenderer.cpp index a53acc6..0f943be 100644 --- a/source/Irrlicht/CD3D9ShaderMaterialRenderer.cpp +++ b/source/Irrlicht/CD3D9ShaderMaterialRenderer.cpp @@ -132,7 +132,7 @@ void CD3D9ShaderMaterialRenderer::OnSetMaterial(const video::SMaterial& material } } - services->setBasicRenderStates(material, lastMaterial, resetAllRenderstates); + Driver->setBasicRenderStates(material, lastMaterial, resetAllRenderstates); if (BaseMaterial) BaseMaterial->OnSetMaterial(material, lastMaterial, resetAllRenderstates, services); diff --git a/source/Irrlicht/CIrrDeviceFB.h b/source/Irrlicht/CIrrDeviceFB.h index e0562f2..c8d6812 100644 --- a/source/Irrlicht/CIrrDeviceFB.h +++ b/source/Irrlicht/CIrrDeviceFB.h @@ -1,222 +1,222 @@ -// Copyright (C) 2002-2007 Nikolaus Gebhardt -// Copyright (C) 2007-2012 Christian Stehno -// This file is part of the "Irrlicht Engine". -// For conditions of distribution and use, see copyright notice in irrlicht.h - -#ifndef IRR_C_IRR_DEVICE_FB_H_INCLUDED -#define IRR_C_IRR_DEVICE_FB_H_INCLUDED - -#include "IrrCompileConfig.h" - -#ifdef _IRR_COMPILE_WITH_FB_DEVICE_ - -#include "CIrrDeviceStub.h" -#include "SIrrCreationParameters.h" -#include "IrrlichtDevice.h" -#include "IImagePresenter.h" -#include "ICursorControl.h" - -#define KeySym s32 -#include -#include - -namespace irr -{ - class CIrrDeviceFB : public CIrrDeviceStub, public video::IImagePresenter - { - public: - - //! constructor - CIrrDeviceFB(const SIrrlichtCreationParameters& params); - - //! destructor - virtual ~CIrrDeviceFB(); - - //! runs the device. Returns false if device wants to be deleted - virtual bool run() IRR_OVERRIDE; - - //! Cause the device to temporarily pause execution and let other processes to run - // This should bring down processor usage without major performance loss for Irrlicht - virtual void yield() IRR_OVERRIDE; - - //! Pause execution and let other processes to run for a specified amount of time. - virtual void sleep(u32 timeMs, bool pauseTimer) IRR_OVERRIDE; - - //! sets the caption of the window - virtual void setWindowCaption(const wchar_t* text) IRR_OVERRIDE; - - //! returns if window is active. if not, nothing need to be drawn - virtual bool isWindowActive() const IRR_OVERRIDE; - - //! returns if window has focus - virtual bool isWindowFocused() const IRR_OVERRIDE; - - //! returns if window is minimized - virtual bool isWindowMinimized() const IRR_OVERRIDE; - - //! Minimizes window - virtual void minimizeWindow() IRR_OVERRIDE; - - //! Maximizes window - virtual void maximizeWindow() IRR_OVERRIDE; - - //! Restores original window size - virtual void restoreWindow() IRR_OVERRIDE; - - //! returns current window position (not supported for this device) - virtual core::position2di getWindowPosition() IRR_OVERRIDE - { - return core::position2di(-1, -1); - } - - //! presents a surface in the client area - virtual bool present(video::IImage* surface, void* windowId = 0, core::rect* src=0 ) IRR_OVERRIDE; - - //! notifies the device that it should close itself - virtual void closeDevice() IRR_OVERRIDE; - - //! Sets if the window should be resizeable in windowed mode. - virtual void setResizable(bool resize=false) IRR_OVERRIDE; - - //! Returns the type of this device - virtual E_DEVICE_TYPE getType() const IRR_OVERRIDE; - - private: - - //! create the driver - void createDriver(); - - bool createWindow(const core::dimension2d& windowSize, u32 bits); - - //! Implementation of the cursor control - class CCursorControl : public gui::ICursorControl - { - public: - - CCursorControl(CIrrDeviceFB* dev, bool null) - : Device(dev), IsVisible(true), Null(null) - { - Device->grab(); - } - - ~CCursorControl() - { - Device->drop(); - } - - //! Changes the visible state of the mouse cursor. - virtual void setVisible(bool visible) IRR_OVERRIDE - { - IsVisible = visible; - } - - //! Returns if the cursor is currently visible. - virtual bool isVisible() const IRR_OVERRIDE - { - return IsVisible; - } - - //! Sets the new position of the cursor. - virtual void setPosition(const core::position2d &pos) IRR_OVERRIDE - { - setPosition(pos.X, pos.Y); - } - - //! Sets the new position of the cursor. - virtual void setPosition(f32 x, f32 y) IRR_OVERRIDE - { - setPosition((s32)(x*Device->CreationParams.WindowSize.Width), (s32)(y*Device->CreationParams.WindowSize.Height)); - } - - //! Sets the new position of the cursor. - virtual void setPosition(const core::position2d &pos) IRR_OVERRIDE - { - setPosition(pos.X, pos.Y); - } - - //! Sets the new position of the cursor. - virtual void setPosition(s32 x, s32 y) IRR_OVERRIDE - { - } - - //! Returns the current position of the mouse cursor. - virtual const core::position2d& getPosition(bool updateCursor) IRR_OVERRIDE - { - if ( updateCursor ) - updateCursorPos(); - return CursorPos; - } - - //! Returns the current position of the mouse cursor. - virtual core::position2d getRelativePosition(bool updateCursor) IRR_OVERRIDE - { - if ( updateCursor) - updateCursorPos(); - return core::position2d(CursorPos.X / (f32)Device->CreationParams.WindowSize.Width, - CursorPos.Y / (f32)Device->CreationParams.WindowSize.Height); - } - - virtual void setReferenceRect(core::rect* rect=0) IRR_OVERRIDE - { - } - +// Copyright (C) 2002-2007 Nikolaus Gebhardt +// Copyright (C) 2007-2012 Christian Stehno +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#ifndef IRR_C_IRR_DEVICE_FB_H_INCLUDED +#define IRR_C_IRR_DEVICE_FB_H_INCLUDED + +#include "IrrCompileConfig.h" + +#ifdef _IRR_COMPILE_WITH_FB_DEVICE_ + +#include "CIrrDeviceStub.h" +#include "SIrrCreationParameters.h" +#include "IrrlichtDevice.h" +#include "IImagePresenter.h" +#include "ICursorControl.h" + +#define KeySym s32 +#include +#include + +namespace irr +{ + class CIrrDeviceFB : public CIrrDeviceStub, public video::IImagePresenter + { + public: + + //! constructor + CIrrDeviceFB(const SIrrlichtCreationParameters& params); + + //! destructor + virtual ~CIrrDeviceFB(); + + //! runs the device. Returns false if device wants to be deleted + virtual bool run() IRR_OVERRIDE; + + //! Cause the device to temporarily pause execution and let other processes to run + // This should bring down processor usage without major performance loss for Irrlicht + virtual void yield() IRR_OVERRIDE; + + //! Pause execution and let other processes to run for a specified amount of time. + virtual void sleep(u32 timeMs, bool pauseTimer) IRR_OVERRIDE; + + //! sets the caption of the window + virtual void setWindowCaption(const wchar_t* text) IRR_OVERRIDE; + + //! returns if window is active. if not, nothing need to be drawn + virtual bool isWindowActive() const IRR_OVERRIDE; + + //! returns if window has focus + virtual bool isWindowFocused() const IRR_OVERRIDE; + + //! returns if window is minimized + virtual bool isWindowMinimized() const IRR_OVERRIDE; + + //! Minimizes window + virtual void minimizeWindow() IRR_OVERRIDE; + + //! Maximizes window + virtual void maximizeWindow() IRR_OVERRIDE; + + //! Restores original window size + virtual void restoreWindow() IRR_OVERRIDE; + + //! returns current window position (not supported for this device) + virtual core::position2di getWindowPosition() IRR_OVERRIDE + { + return core::position2di(-1, -1); + } + + //! presents a surface in the client area + virtual bool present(video::IImage* surface, void* windowId = 0, core::rect* src=0 ) IRR_OVERRIDE; + + //! notifies the device that it should close itself + virtual void closeDevice() IRR_OVERRIDE; + + //! Sets if the window should be resizeable in windowed mode. + virtual void setResizable(bool resize=false) IRR_OVERRIDE; + + //! Returns the type of this device + virtual E_DEVICE_TYPE getType() const IRR_OVERRIDE; + + private: + + //! create the driver + void createDriver(); + + bool createWindow(const core::dimension2d& windowSize, u32 bits); + + //! Implementation of the cursor control + class CCursorControl : public gui::ICursorControl + { + public: + + CCursorControl(CIrrDeviceFB* dev, bool null) + : Device(dev), IsVisible(true), Null(null) + { + Device->grab(); + } + + ~CCursorControl() + { + Device->drop(); + } + + //! Changes the visible state of the mouse cursor. + virtual void setVisible(bool visible) IRR_OVERRIDE + { + IsVisible = visible; + } + + //! Returns if the cursor is currently visible. + virtual bool isVisible() const IRR_OVERRIDE + { + return IsVisible; + } + + //! Sets the new position of the cursor. + virtual void setPosition(const core::position2d &pos) IRR_OVERRIDE + { + setPosition(pos.X, pos.Y); + } + + //! Sets the new position of the cursor. + virtual void setPosition(f32 x, f32 y) IRR_OVERRIDE + { + setPosition((s32)(x*Device->CreationParams.WindowSize.Width), (s32)(y*Device->CreationParams.WindowSize.Height)); + } + + //! Sets the new position of the cursor. + virtual void setPosition(const core::position2d &pos) IRR_OVERRIDE + { + setPosition(pos.X, pos.Y); + } + + //! Sets the new position of the cursor. + virtual void setPosition(s32 x, s32 y) IRR_OVERRIDE + { + } + + //! Returns the current position of the mouse cursor. + virtual const core::position2d& getPosition(bool updateCursor) IRR_OVERRIDE + { + if ( updateCursor ) + updateCursorPos(); + return CursorPos; + } + + //! Returns the current position of the mouse cursor. + virtual core::position2d getRelativePosition(bool updateCursor) IRR_OVERRIDE + { + if ( updateCursor) + updateCursorPos(); + return core::position2d(CursorPos.X / (f32)Device->CreationParams.WindowSize.Width, + CursorPos.Y / (f32)Device->CreationParams.WindowSize.Height); + } + + virtual void setReferenceRect(core::rect* rect=0) IRR_OVERRIDE + { + } + virtual bool getReferenceRect(core::rect& rect) IRR_OVERRIDE { rect.UpperLeftCorner = core::vector2di(0,0); rect.LowerRightCorner.X = (irr::s32)Device->CreationParams.WindowSize.Width; rect.LowerRightCorner.Y = (irr::s32)Device->CreationParams.WindowSize.Height; return false; - } - - private: - - void updateCursorPos() - { - } - - core::position2d CursorPos; - CIrrDeviceFB* Device; - bool IsVisible; - bool Null; - }; - - friend class CCursorControl; - - int Framebuffer; - int EventDevice; - int KeyboardDevice; - struct fb_fix_screeninfo fbfixscreeninfo; - struct fb_var_screeninfo fbscreeninfo; - struct fb_var_screeninfo oldscreeninfo; - long KeyboardMode; - u8* SoftwareImage; - - u32 Pitch; - video::ECOLOR_FORMAT FBColorFormat; - bool Close; - - struct SKeyMap - { - SKeyMap() {} - SKeyMap(s32 x11, s32 win32) - : X11Key(x11), Win32Key(win32) - { - } - - KeySym X11Key; - s32 Win32Key; - - bool operator<(const SKeyMap& o) const - { - return X11Key KeyMap; - }; - - -} // end namespace irr - -#endif // _IRR_USE_FB_DEVICE_ -#endif // IRR_C_IRR_DEVICE_FB_H_INCLUDED + } + + private: + + void updateCursorPos() + { + } + + core::position2d CursorPos; + CIrrDeviceFB* Device; + bool IsVisible; + bool Null; + }; + + friend class CCursorControl; + + int Framebuffer; + int EventDevice; + int KeyboardDevice; + struct fb_fix_screeninfo fbfixscreeninfo; + struct fb_var_screeninfo fbscreeninfo; + struct fb_var_screeninfo oldscreeninfo; + long KeyboardMode; + u8* SoftwareImage; + + u32 Pitch; + video::ECOLOR_FORMAT FBColorFormat; + bool Close; + + struct SKeyMap + { + SKeyMap() {} + SKeyMap(s32 x11, s32 win32) + : X11Key(x11), Win32Key(win32) + { + } + + KeySym X11Key; + s32 Win32Key; + + bool operator<(const SKeyMap& o) const + { + return X11Key KeyMap; + }; + + +} // end namespace irr + +#endif // _IRR_USE_FB_DEVICE_ +#endif // IRR_C_IRR_DEVICE_FB_H_INCLUDED diff --git a/source/Irrlicht/CMeshSceneNode.cpp b/source/Irrlicht/CMeshSceneNode.cpp index 59d1c1c..7e3a6b9 100644 --- a/source/Irrlicht/CMeshSceneNode.cpp +++ b/source/Irrlicht/CMeshSceneNode.cpp @@ -3,6 +3,7 @@ // For conditions of distribution and use, see copyright notice in irrlicht.h #include "CMeshSceneNode.h" +#include "CBufferRenderNode.h" #include "IVideoDriver.h" #include "ISceneManager.h" #include "S3DVertex.h" @@ -22,14 +23,12 @@ namespace irr namespace scene { - - //! constructor CMeshSceneNode::CMeshSceneNode(IMesh* mesh, ISceneNode* parent, ISceneManager* mgr, s32 id, const core::vector3df& position, const core::vector3df& rotation, const core::vector3df& scale) -: IMeshSceneNode(parent, mgr, id, position, rotation, scale), Mesh(0), Shadow(0), - PassCount(0), ReadOnlyMaterials(false) + : IMeshSceneNode(parent, mgr, id, position, rotation, scale) + , Mesh(0), Shadow(0), ReadOnlyMaterials(false) { #ifdef _DEBUG setDebugName("CMeshSceneNode"); @@ -42,6 +41,7 @@ CMeshSceneNode::CMeshSceneNode(IMesh* mesh, ISceneNode* parent, ISceneManager* m //! destructor CMeshSceneNode::~CMeshSceneNode() { + setUsedBufferRenderNodes(0); if (Shadow) Shadow->drop(); if (Mesh) @@ -54,39 +54,60 @@ void CMeshSceneNode::OnRegisterSceneNode() { if (IsVisible && Mesh) { - // because this node supports rendering of mixed mode meshes consisting of + Box = Mesh->getBoundingBox(); // in case mesh was modified, as clipping happens when registering nodes for rendering + + // Because this node supports rendering of mixed mode meshes consisting of // transparent and solid material at the same time, we need to go through all // materials, check of what type they are and register this node for the right // render pass according to that. + // Also some buffers might register into their own render node video::IVideoDriver* driver = SceneManager->getVideoDriver(); - PassCount = 0; int transparentCount = 0; int solidCount = 0; - // count transparent and solid materials in this scene node - const u32 numMaterials = ReadOnlyMaterials ? Mesh->getMeshBufferCount() : Materials.size(); - for (u32 i=0; igetMeshBuffer(i)->getMaterial() : Materials[i]; + // count transparent and solid materials in this scene node + const u32 numMaterials = ReadOnlyMaterials ? Mesh->getMeshBufferCount() : Materials.size(); + const bool parentRenders = NodeRegistration == ENR_DEFAULT || numMaterials < 2; + for (u32 i=0; igetMeshBuffer(i)->getMaterial() : Materials[i]; - if ( driver->needsTransparentRenderPass(material) ) - ++transparentCount; - else - ++solidCount; - - if (solidCount && transparentCount) - break; + if ( driver->needsTransparentRenderPass(material) ) + { + BufferRenderNodes[i]->prepareRendering(ESNRP_TRANSPARENT, parentRenders); + if ( parentRenders ) + { + ++transparentCount; + } + } + else + { + BufferRenderNodes[i]->prepareRendering(ESNRP_SOLID, parentRenders); + if ( parentRenders ) + { + ++solidCount; + } + } + } } // register according to material types counted if (solidCount) - SceneManager->registerNodeForRendering(this, scene::ESNRP_SOLID); + SceneManager->registerNodeForRendering(this, ESNRP_SOLID); if (transparentCount) - SceneManager->registerNodeForRendering(this, scene::ESNRP_TRANSPARENT); + SceneManager->registerNodeForRendering(this, ESNRP_TRANSPARENT); + + if (Shadow) // update (not render) shadow node after lights have been set up + SceneManager->registerNodeForRendering(this, ESNRP_SKY_BOX); + + if (DebugDataVisible) // debug data has it's own render-stage between solid and transparence + SceneManager->registerNodeForRendering(this, ESNRP_SHADOW); ISceneNode::OnRegisterSceneNode(); } @@ -96,109 +117,110 @@ void CMeshSceneNode::OnRegisterSceneNode() //! renders the node. void CMeshSceneNode::render() { - video::IVideoDriver* driver = SceneManager->getVideoDriver(); - - if (!Mesh || !driver) + if (!Mesh ) return; - const bool isTransparentPass = - SceneManager->getSceneNodeRenderPass() == scene::ESNRP_TRANSPARENT; + const E_SCENE_NODE_RENDER_PASS renderPass = SceneManager->getSceneNodeRenderPass(); - ++PassCount; - - driver->setTransform(video::ETS_WORLD, AbsoluteTransformation); - Box = Mesh->getBoundingBox(); - - if (Shadow && PassCount==1) - Shadow->updateShadowVolumes(); - - // for debug purposes only: - - bool renderMeshes = true; - video::SMaterial mat; - if (DebugDataVisible && PassCount==1) + if ( renderPass == ESNRP_SKY_BOX ) { - // overwrite half transparency - if (DebugDataVisible & scene::EDS_HALF_TRANSPARENCY) - { - for (u32 g=0; ggetMeshBufferCount(); ++g) - { - mat = Materials[g]; - mat.MaterialType = video::EMT_TRANSPARENT_ADD_COLOR; - driver->setMaterial(mat); - driver->drawMeshBuffer(Mesh->getMeshBuffer(g)); - } - renderMeshes = false; - } + if (Shadow ) + Shadow->updateShadowVolumes(); } - - // render original meshes - if (renderMeshes) + else if ( renderPass == ESNRP_SHADOW ) { - for (u32 i=0; igetMeshBufferCount(); ++i) + // for debug purposes only + if ( DebugDataVisible ) { - scene::IMeshBuffer* mb = Mesh->getMeshBuffer(i); - if (mb) + video::IVideoDriver* driver = SceneManager->getVideoDriver(); + driver->setTransform(video::ETS_WORLD, AbsoluteTransformation); + + // render with half transparency + if (DebugDataVisible & scene::EDS_HALF_TRANSPARENCY) { - const video::SMaterial& material = ReadOnlyMaterials ? mb->getMaterial() : Materials[i]; - - const bool transparent = driver->needsTransparentRenderPass(material); - - // only render transparent buffer if this is the transparent render pass - // and solid only in solid pass - if (transparent == isTransparentPass) + for (u32 g=0; ggetMeshBufferCount(); ++g) { - driver->setMaterial(material); - driver->drawMeshBuffer(mb); + irr::video::SMaterial mat = Materials[g]; + mat.MaterialType = video::EMT_TRANSPARENT_ADD_COLOR; + driver->setMaterial(mat); + driver->drawMeshBuffer(Mesh->getMeshBuffer(g)); + } + } + + video::SMaterial m; + m.Lighting = false; + m.AntiAliasing=0; + driver->setMaterial(m); + + if (DebugDataVisible & scene::EDS_BBOX) + { + driver->draw3DBox(Box, video::SColor(255,255,255,255)); + } + if (DebugDataVisible & scene::EDS_BBOX_BUFFERS) + { + for (u32 g=0; ggetMeshBufferCount(); ++g) + { + driver->draw3DBox( + Mesh->getMeshBuffer(g)->getBoundingBox(), + video::SColor(255,190,128,128)); + } + } + + if (DebugDataVisible & scene::EDS_NORMALS) + { + // draw normals + const f32 debugNormalLength = SceneManager->getParameters()->getAttributeAsFloat(DEBUG_NORMAL_LENGTH); + const video::SColor debugNormalColor = SceneManager->getParameters()->getAttributeAsColor(DEBUG_NORMAL_COLOR); + const u32 count = Mesh->getMeshBufferCount(); + + for (u32 i=0; i != count; ++i) + { + driver->drawMeshBufferNormals(Mesh->getMeshBuffer(i), debugNormalLength, debugNormalColor); + } + } + + // show mesh + if (DebugDataVisible & scene::EDS_MESH_WIRE_OVERLAY) + { + m.Wireframe = true; + driver->setMaterial(m); + + for (u32 g=0; ggetMeshBufferCount(); ++g) + { + driver->drawMeshBuffer(Mesh->getMeshBuffer(g)); } } } } - - // for debug purposes only: - if (DebugDataVisible && PassCount==1) + else // solid, transparent or unknown (none when render is called without SceneManager) render stages { - video::SMaterial m; - m.Lighting = false; - m.AntiAliasing=0; - driver->setMaterial(m); + video::IVideoDriver* driver = SceneManager->getVideoDriver(); + driver->setTransform(video::ETS_WORLD, AbsoluteTransformation); - if (DebugDataVisible & scene::EDS_BBOX) + // render buffers, or at least those which don't render in their own node + for (u32 i=0; idraw3DBox(Box, video::SColor(255,255,255,255)); - } - if (DebugDataVisible & scene::EDS_BBOX_BUFFERS) - { - for (u32 g=0; ggetMeshBufferCount(); ++g) + CBufferRenderNode* bufRenderNode = BufferRenderNodes[i]; + if ( bufRenderNode->getDoesParentRender()) { - driver->draw3DBox( - Mesh->getMeshBuffer(g)->getBoundingBox(), - video::SColor(255,190,128,128)); - } - } + E_SCENE_NODE_RENDER_PASS bufferRenderPass = bufRenderNode->getRenderPass(); - if (DebugDataVisible & scene::EDS_NORMALS) - { - // draw normals - const f32 debugNormalLength = SceneManager->getParameters()->getAttributeAsFloat(DEBUG_NORMAL_LENGTH); - const video::SColor debugNormalColor = SceneManager->getParameters()->getAttributeAsColor(DEBUG_NORMAL_COLOR); - const u32 count = Mesh->getMeshBufferCount(); + // render() called without OnRegisterSceneNode, but still wants to render in a specific render stage + // Note: Not checking transparency every time, as check got slightly expensive (I think it's prone to cache-misses) + if ( bufferRenderPass == ESNRP_NONE && renderPass > ESNRP_NONE ) + { + if ( driver->needsTransparentRenderPass(getMaterial(i)) ) + { + bufferRenderPass = ESNRP_TRANSPARENT; + } + else + { + bufferRenderPass = ESNRP_SOLID; + } + } - for (u32 i=0; i != count; ++i) - { - driver->drawMeshBufferNormals(Mesh->getMeshBuffer(i), debugNormalLength, debugNormalColor); - } - } - - // show mesh - if (DebugDataVisible & scene::EDS_MESH_WIRE_OVERLAY) - { - m.Wireframe = true; - driver->setMaterial(m); - - for (u32 g=0; ggetMeshBufferCount(); ++g) - { - driver->drawMeshBuffer(Mesh->getMeshBuffer(g)); + if ( bufRenderNode->getRenderPass() == renderPass ) + bufRenderNode->renderBuffer(driver); } } } @@ -207,7 +229,7 @@ void CMeshSceneNode::render() //! Removes a child from this scene node. //! Implemented here, to be able to remove the shadow properly, if there is one, -//! or to remove attached childs. +//! or to remove attached children. bool CMeshSceneNode::removeChild(ISceneNode* child) { if (child && Shadow == child) @@ -256,6 +278,22 @@ u32 CMeshSceneNode::getMaterialCount() const return Materials.size(); } +void CMeshSceneNode::setUsedBufferRenderNodes(irr::u32 num) +{ + if ( BufferRenderNodes.size() > num ) + { + for ( irr::u32 i=num; idrop(); + BufferRenderNodes.erase(num, BufferRenderNodes.size()-num); + } + else if ( BufferRenderNodes.size() < num ) + { + for ( irr::u32 i=BufferRenderNodes.size(); i < num; ++i ) + { + BufferRenderNodes.push_back( new CBufferRenderNode(*this, SceneManager, i) ); + } + } +} //! Sets a new mesh void CMeshSceneNode::setMesh(IMesh* mesh) @@ -264,10 +302,16 @@ void CMeshSceneNode::setMesh(IMesh* mesh) { mesh->grab(); if (Mesh) + { Mesh->drop(); + } Mesh = mesh; + + // Note: Mesh can change amount of meshbuffers later and we don't handle that so far so that would cause trouble + // For now assuming users call setMesh again in that case copyMaterials(); + setUsedBufferRenderNodes(Mesh ? Mesh->getMeshBufferCount() : 0); } } diff --git a/source/Irrlicht/CMeshSceneNode.h b/source/Irrlicht/CMeshSceneNode.h index 3b1c1b1..0453703 100644 --- a/source/Irrlicht/CMeshSceneNode.h +++ b/source/Irrlicht/CMeshSceneNode.h @@ -12,6 +12,7 @@ namespace irr { namespace scene { + class CBufferRenderNode; class CMeshSceneNode : public IMeshSceneNode { @@ -83,6 +84,7 @@ namespace scene protected: + void setUsedBufferRenderNodes(irr::u32 num); void copyMaterials(); core::array Materials; @@ -92,8 +94,9 @@ namespace scene IMesh* Mesh; IShadowVolumeSceneNode* Shadow; - s32 PassCount; bool ReadOnlyMaterials; + + core::array BufferRenderNodes; }; } // end namespace scene diff --git a/source/Irrlicht/COGLES2Driver.h b/source/Irrlicht/COGLES2Driver.h index bc63431..acf3b23 100644 --- a/source/Irrlicht/COGLES2Driver.h +++ b/source/Irrlicht/COGLES2Driver.h @@ -207,7 +207,7 @@ namespace video virtual const core::matrix4& getTransform(E_TRANSFORMATION_STATE state) const IRR_OVERRIDE; //! Can be called by an IMaterialRenderer to make its work easier. - virtual void setBasicRenderStates(const SMaterial& material, const SMaterial& lastmaterial, bool resetAllRenderstates) IRR_OVERRIDE; + void setBasicRenderStates(const SMaterial& material, const SMaterial& lastmaterial, bool resetAllRenderstates); //! Compare in SMaterial doesn't check texture parameters, so we should call this on each OnRender call. void setTextureRenderStates(const SMaterial& material, bool resetAllRenderstates); diff --git a/source/Irrlicht/COGLES2MaterialRenderer.cpp b/source/Irrlicht/COGLES2MaterialRenderer.cpp index cfa1032..6be01a5 100644 --- a/source/Irrlicht/COGLES2MaterialRenderer.cpp +++ b/source/Irrlicht/COGLES2MaterialRenderer.cpp @@ -340,14 +340,6 @@ bool COGLES2MaterialRenderer::linkProgram() return true; } - -void COGLES2MaterialRenderer::setBasicRenderStates(const SMaterial& material, - const SMaterial& lastMaterial, - bool resetAllRenderstates) -{ - Driver->setBasicRenderStates(material, lastMaterial, resetAllRenderstates); -} - void COGLES2MaterialRenderer::startUseProgram() { Driver->getCacheHandler()->setProgram(Program); diff --git a/source/Irrlicht/COGLES2MaterialRenderer.h b/source/Irrlicht/COGLES2MaterialRenderer.h index b85ad4b..4a933c9 100644 --- a/source/Irrlicht/COGLES2MaterialRenderer.h +++ b/source/Irrlicht/COGLES2MaterialRenderer.h @@ -53,8 +53,6 @@ public: virtual s32 getRenderCapability() const IRR_OVERRIDE; - virtual void setBasicRenderStates(const SMaterial& material, const SMaterial& lastMaterial, bool resetAllRenderstates) IRR_OVERRIDE; - virtual void startUseProgram() IRR_OVERRIDE; virtual s32 getVertexShaderConstantID(const c8* name) IRR_OVERRIDE; diff --git a/source/Irrlicht/COGLESDriver.h b/source/Irrlicht/COGLESDriver.h index b9d1817..c67ee87 100644 --- a/source/Irrlicht/COGLESDriver.h +++ b/source/Irrlicht/COGLESDriver.h @@ -201,8 +201,8 @@ namespace video virtual const core::matrix4& getTransform(E_TRANSFORMATION_STATE state) const IRR_OVERRIDE; //! Can be called by an IMaterialRenderer to make its work easier. - virtual void setBasicRenderStates(const SMaterial& material, const SMaterial& lastmaterial, - bool resetAllRenderstates) IRR_OVERRIDE; + void setBasicRenderStates(const SMaterial& material, const SMaterial& lastmaterial, + bool resetAllRenderstates); //! Compare in SMaterial doesn't check texture parameters, so we should call this on each OnRender call. virtual void setTextureRenderStates(const SMaterial& material, bool resetAllRenderstates); diff --git a/source/Irrlicht/COpenGLDriver.h b/source/Irrlicht/COpenGLDriver.h index 1bbc938..b0485c0 100644 --- a/source/Irrlicht/COpenGLDriver.h +++ b/source/Irrlicht/COpenGLDriver.h @@ -272,8 +272,8 @@ namespace video virtual const core::matrix4& getTransform(E_TRANSFORMATION_STATE state) const IRR_OVERRIDE; //! Can be called by an IMaterialRenderer to make its work easier. - virtual void setBasicRenderStates(const SMaterial& material, const SMaterial& lastmaterial, - bool resetAllRenderstates) IRR_OVERRIDE; + void setBasicRenderStates(const SMaterial& material, const SMaterial& lastmaterial, + bool resetAllRenderstates); //! Compare in SMaterial doesn't check texture parameters, so we should call this on each OnRender call. virtual void setTextureRenderStates(const SMaterial& material, bool resetAllRenderstates); diff --git a/source/Irrlicht/COpenGLSLMaterialRenderer.cpp b/source/Irrlicht/COpenGLSLMaterialRenderer.cpp index df2cb06..9c4104e 100644 --- a/source/Irrlicht/COpenGLSLMaterialRenderer.cpp +++ b/source/Irrlicht/COpenGLSLMaterialRenderer.cpp @@ -563,15 +563,6 @@ bool COpenGLSLMaterialRenderer::linkProgram() return true; } - -void COpenGLSLMaterialRenderer::setBasicRenderStates(const SMaterial& material, - const SMaterial& lastMaterial, - bool resetAllRenderstates) -{ - // forward - Driver->setBasicRenderStates(material, lastMaterial, resetAllRenderstates); -} - void COpenGLSLMaterialRenderer::startUseProgram() { if (Program2) @@ -584,7 +575,7 @@ void COpenGLSLMaterialRenderer::stopUseProgram() { // Not going to reset irrGlUseProgram/extGlUseProgramObject as it shouldn't really matter - // Force reset of material to ensure OnSetMaterial will be called or we can miss + // Force reset of material to ensure OnSetMaterial will be called or we can miss // the next UseProgram call Driver->DoResetRenderStates(); } diff --git a/source/Irrlicht/COpenGLSLMaterialRenderer.h b/source/Irrlicht/COpenGLSLMaterialRenderer.h index 92605a7..0e53ca2 100644 --- a/source/Irrlicht/COpenGLSLMaterialRenderer.h +++ b/source/Irrlicht/COpenGLSLMaterialRenderer.h @@ -67,12 +67,11 @@ public: //! Access the callback provided by the users when creating shader materials virtual IShaderConstantSetCallBack* getShaderConstantSetCallBack() const IRR_OVERRIDE - { + { return CallBack; } // implementations for IMaterialRendererServices - virtual void setBasicRenderStates(const SMaterial& material, const SMaterial& lastMaterial, bool resetAllRenderstates) IRR_OVERRIDE; virtual void startUseProgram() IRR_OVERRIDE; virtual void stopUseProgram() IRR_OVERRIDE; virtual s32 getVertexShaderConstantID(const c8* name) IRR_OVERRIDE; diff --git a/source/Irrlicht/CSoftwareDriver2.h b/source/Irrlicht/CSoftwareDriver2.h index 18ed97e..01ae812 100644 --- a/source/Irrlicht/CSoftwareDriver2.h +++ b/source/Irrlicht/CSoftwareDriver2.h @@ -264,9 +264,9 @@ namespace video //IMaterialRendererService - virtual void setBasicRenderStates(const SMaterial& material, + void setBasicRenderStates(const SMaterial& material, const SMaterial& lastMaterial, - bool resetAllRenderstates) IRR_OVERRIDE; + bool resetAllRenderstates); //pass BaseMaterialID void setFallback_Material(E_MATERIAL_TYPE fallback_MaterialType diff --git a/source/Irrlicht/IBurningShader.cpp b/source/Irrlicht/IBurningShader.cpp index 56d3359..43417ca 100644 --- a/source/Irrlicht/IBurningShader.cpp +++ b/source/Irrlicht/IBurningShader.cpp @@ -299,7 +299,7 @@ void IBurningShader::OnSetMaterial(const SMaterial& material, const SMaterial& l { if (Driver) Driver->setFallback_Material(BaseMaterial, VertexShaderProgram_buildin); - services->setBasicRenderStates(material, lastMaterial, resetAllRenderstates); + Driver->setBasicRenderStates(material, lastMaterial, resetAllRenderstates); if (CallBack) CallBack->OnSetMaterial(material); @@ -331,13 +331,6 @@ IShaderConstantSetCallBack* IBurningShader::getShaderConstantSetCallBack() const return CallBack; } -// implementations for the render services -void IBurningShader::setBasicRenderStates(const SMaterial& material, const SMaterial& lastMaterial, bool resetAllRenderstates) -{ - // forward - Driver->setBasicRenderStates(material, lastMaterial, resetAllRenderstates); -} - static BurningUniform _empty = { "null",BL_VERTEX_FLOAT,{0.f,0.f,0.f,0.f} }; const f32* IBurningShader::getUniform(const c8* name, EBurningUniformFlags flags) const { diff --git a/source/Irrlicht/IBurningShader.h b/source/Irrlicht/IBurningShader.h index c19fdc7..71ffd69 100644 --- a/source/Irrlicht/IBurningShader.h +++ b/source/Irrlicht/IBurningShader.h @@ -334,7 +334,6 @@ public: virtual IShaderConstantSetCallBack* getShaderConstantSetCallBack() const IRR_OVERRIDE; // implementations for the render services - virtual void setBasicRenderStates(const SMaterial& material, const SMaterial& lastMaterial, bool resetAllRenderstates) IRR_OVERRIDE; virtual s32 getVertexShaderConstantID(const c8* name) IRR_OVERRIDE; virtual s32 getPixelShaderConstantID(const c8* name) IRR_OVERRIDE; virtual void setVertexShaderConstant(const f32* data, s32 startRegister, s32 constantAmount = 1) IRR_OVERRIDE; diff --git a/source/Irrlicht/Irrlicht10.0.vcxproj b/source/Irrlicht/Irrlicht10.0.vcxproj index 861b582..a1b3419 100644 --- a/source/Irrlicht/Irrlicht10.0.vcxproj +++ b/source/Irrlicht/Irrlicht10.0.vcxproj @@ -1038,6 +1038,7 @@ + diff --git a/source/Irrlicht/Irrlicht10.0.vcxproj.filters b/source/Irrlicht/Irrlicht10.0.vcxproj.filters index bf38c40..0c54eb7 100644 --- a/source/Irrlicht/Irrlicht10.0.vcxproj.filters +++ b/source/Irrlicht/Irrlicht10.0.vcxproj.filters @@ -1489,6 +1489,9 @@ include\scene + + Irrlicht\scene\sceneNodes + diff --git a/source/Irrlicht/Irrlicht17.0.vcxproj b/source/Irrlicht/Irrlicht17.0.vcxproj index 88c4ab7..465cdd3 100644 --- a/source/Irrlicht/Irrlicht17.0.vcxproj +++ b/source/Irrlicht/Irrlicht17.0.vcxproj @@ -776,6 +776,7 @@ + diff --git a/source/Irrlicht/Irrlicht17.0.vcxproj.filters b/source/Irrlicht/Irrlicht17.0.vcxproj.filters index 330b026..7cb136e 100644 --- a/source/Irrlicht/Irrlicht17.0.vcxproj.filters +++ b/source/Irrlicht/Irrlicht17.0.vcxproj.filters @@ -1438,6 +1438,9 @@ include + + Irrlicht\scene\sceneNodes + diff --git a/tests/tests-last-passed-at.txt b/tests/tests-last-passed-at.txt index 7164271..f7f59af 100644 --- a/tests/tests-last-passed-at.txt +++ b/tests/tests-last-passed-at.txt @@ -1,4 +1,4 @@ Tests finished. 72 tests of 72 passed. Compiled as DEBUG -Test suite pass at GMT Fri Apr 21 14:37:22 2023 +Test suite pass at GMT Fri May 05 18:39:44 2023