diff --git a/changes.txt b/changes.txt index ce3fe6d3..17b26871 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 1a5f51a9..5a8f2153 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 6b4a1154..4a751637 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 c4ef6749..321afd1a 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 309f46db..25600e76 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 eae5d49b..64ab0e8c 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 a20daab0..18c5bff8 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 51ddf668..48698cd5 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 00000000..923434fa --- /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 4d74f48d..cec931f8 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 b8b661ce..e3cd69e4 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 c25ca017..0d8c343c 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 7da11125..639caac1 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 3b61483e..df3d2a28 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 08f36bf4..76aa04d4 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 a53acc67..0f943be7 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 e0562f2a..c8d68123 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 59d1c1cd..7e3a6b9f 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 3b1c1b1c..04537035 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 bc634310..acf3b23b 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 cfa10321..6be01a57 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 b85ad4b2..4a933c91 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 b9d18171..c67ee871 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 1bbc9387..b0485c03 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 df2cb060..9c4104e9 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 92605a73..0e53ca2f 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 18ed97e8..01ae8127 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 56d3359e..43417ca3 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 c19fdc7e..71ffd698 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 861b5825..a1b34199 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 bf38c40b..0c54eb7c 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 88c4ab76..465cdd31 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 330b0260..7cb136ed 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 71642710..f7f59afa 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