From 543e70dc34df2741fd9c84cfeda1b47ee58dedcf Mon Sep 17 00:00:00 2001 From: cutealien Date: Tue, 6 Dec 2016 17:10:57 +0000 Subject: [PATCH] CTriangleSelector can now be created for a single meshbuffer. It can still update with a node transformation, but it won't update when the mesh changes (so only useful for static meshes, not for animated ones). git-svn-id: svn://svn.code.sf.net/p/irrlicht/code/trunk@5351 dfc29bdd-3216-0410-991c-e03cc46cb475 --- include/ISceneCollisionManager.h | 2 +- include/ISceneManager.h | 11 ++++- include/ITriangleSelector.h | 2 +- source/Irrlicht/CSceneManager.cpp | 7 +++ source/Irrlicht/CSceneManager.h | 3 ++ source/Irrlicht/CTriangleSelector.cpp | 68 ++++++++++++++++++++++++--- source/Irrlicht/CTriangleSelector.h | 14 ++++++ 7 files changed, 98 insertions(+), 9 deletions(-) diff --git a/include/ISceneCollisionManager.h b/include/ISceneCollisionManager.h index bdf0a2d1..ccfe8639 100644 --- a/include/ISceneCollisionManager.h +++ b/include/ISceneCollisionManager.h @@ -36,7 +36,7 @@ namespace scene ISceneNode* Node; //! Meshbuffer which contained the triangle (is 0 when the selector doesn't have that information, only works when selectors are created per meshbuffer) - IMeshBuffer* MeshBuffer; + const IMeshBuffer* MeshBuffer; //! Index of selected material of the triangle in the SceneNode. Usually only valid when MeshBuffer is also set, otherwise always 0 irr::u32 MaterialIndex; diff --git a/include/ISceneManager.h b/include/ISceneManager.h index 4333eed3..4bd56a4a 100644 --- a/include/ISceneManager.h +++ b/include/ISceneManager.h @@ -1271,7 +1271,7 @@ namespace scene s->drop(); \endcode \param mesh: Mesh of which the triangles are taken. - \param node: Scene node of which visibility and transformation is used. + \param node: Scene node of which transformation is used. \param separateMeshbuffers: When true it's possible to get information which meshbuffer got hit in collision tests. But has a slight speed cost. \return The selector, or null if not successful. @@ -1279,6 +1279,15 @@ namespace scene See IReferenceCounted::drop() for more information. */ virtual ITriangleSelector* createTriangleSelector(IMesh* mesh, ISceneNode* node, bool separateMeshbuffers=false) = 0; + //! Creates a simple ITriangleSelector, based on a meshbuffer. + /** + This is a static selector which won't update when the mesh changes. + \param meshBuffer Triangles of that meshbuffer are used + \param materialIndex If you pass a material index that index can be returned by the triangle selector. + \para node: Scene node of which transformation is used. + */ + virtual ITriangleSelector* createTriangleSelector(const IMeshBuffer* meshBuffer, irr::u32 materialIndex, ISceneNode* node) = 0; + //! Creates a simple ITriangleSelector, based on an animated mesh scene node. /** Details of the mesh associated with the node will be extracted internally. \param node The animated mesh scene node from which to build the selector diff --git a/include/ITriangleSelector.h b/include/ITriangleSelector.h index 5aa5305d..1d5985c7 100644 --- a/include/ITriangleSelector.h +++ b/include/ITriangleSelector.h @@ -56,7 +56,7 @@ struct SCollisionTriangleRange //! Meshbuffer from which the triangles are from //! Is 0 when the ITriangleSelector doesn't support meshbuffer selection - IMeshBuffer* MeshBuffer; + const IMeshBuffer* MeshBuffer; //! Index of selected material in the SceneNode. Usually only valid when MeshBuffer is also set, otherwise always 0 irr::u32 MaterialIndex; diff --git a/source/Irrlicht/CSceneManager.cpp b/source/Irrlicht/CSceneManager.cpp index 91163077..15a4f6dd 100644 --- a/source/Irrlicht/CSceneManager.cpp +++ b/source/Irrlicht/CSceneManager.cpp @@ -1855,6 +1855,13 @@ ITriangleSelector* CSceneManager::createTriangleSelector(IMesh* mesh, ISceneNode return new CTriangleSelector(mesh, node, separateMeshbuffers); } +ITriangleSelector* CSceneManager::createTriangleSelector(const IMeshBuffer* meshBuffer, irr::u32 materialIndex, ISceneNode* node) +{ + if ( !meshBuffer) + return 0; + return new CTriangleSelector(meshBuffer, materialIndex, node); +} + //! Creates a ITriangleSelector, based on a the mesh owned by an animated scene node ITriangleSelector* CSceneManager::createTriangleSelector(IAnimatedMeshSceneNode* node, bool separateMeshbuffers) diff --git a/source/Irrlicht/CSceneManager.h b/source/Irrlicht/CSceneManager.h index f6bf4425..8a3cfd7a 100644 --- a/source/Irrlicht/CSceneManager.h +++ b/source/Irrlicht/CSceneManager.h @@ -345,6 +345,9 @@ namespace scene //! Creates a simple ITriangleSelector, based on a mesh. virtual ITriangleSelector* createTriangleSelector(IMesh* mesh, ISceneNode* node, bool separateMeshbuffers) _IRR_OVERRIDE_; + //! Creates a simple ITriangleSelector, based on a meshbuffer. + virtual ITriangleSelector* createTriangleSelector(const IMeshBuffer* meshBuffer, irr::u32 materialIndex, ISceneNode* node) _IRR_OVERRIDE_; + //! Creates a simple ITriangleSelector, based on an animated mesh scene node. //! Details of the mesh associated with the node will be extracted internally. //! Call ITriangleSelector::update() to have the triangle selector updated based diff --git a/source/Irrlicht/CTriangleSelector.cpp b/source/Irrlicht/CTriangleSelector.cpp index 127a9d16..0342b349 100644 --- a/source/Irrlicht/CTriangleSelector.cpp +++ b/source/Irrlicht/CTriangleSelector.cpp @@ -15,7 +15,7 @@ namespace scene //! constructor CTriangleSelector::CTriangleSelector(ISceneNode* node) -: SceneNode(node), AnimatedNode(0), LastMeshFrame(0) +: SceneNode(node), MeshBuffer(0), MaterialIndex(0), AnimatedNode(0), LastMeshFrame(0) { #ifdef _DEBUG setDebugName("CTriangleSelector"); @@ -27,7 +27,7 @@ CTriangleSelector::CTriangleSelector(ISceneNode* node) //! constructor CTriangleSelector::CTriangleSelector(const core::aabbox3d& box, ISceneNode* node) -: SceneNode(node), AnimatedNode(0), LastMeshFrame(0) +: SceneNode(node), MeshBuffer(0), MaterialIndex(0), AnimatedNode(0), LastMeshFrame(0) { #ifdef _DEBUG setDebugName("CTriangleSelector"); @@ -40,7 +40,7 @@ CTriangleSelector::CTriangleSelector(const core::aabbox3d& box, ISceneNode* //! constructor CTriangleSelector::CTriangleSelector(const IMesh* mesh, ISceneNode* node, bool separateMeshbuffers) -: SceneNode(node), AnimatedNode(0), LastMeshFrame(0) +: SceneNode(node), MeshBuffer(0), MaterialIndex(0), AnimatedNode(0), LastMeshFrame(0) { #ifdef _DEBUG setDebugName("CTriangleSelector"); @@ -49,6 +49,15 @@ CTriangleSelector::CTriangleSelector(const IMesh* mesh, ISceneNode* node, bool s createFromMesh(mesh, separateMeshbuffers); } +CTriangleSelector::CTriangleSelector(const IMeshBuffer* meshBuffer, irr::u32 materialIndex, ISceneNode* node) + : SceneNode(node), MeshBuffer(meshBuffer), MaterialIndex(materialIndex), AnimatedNode(0), LastMeshFrame(0) +{ + #ifdef _DEBUG + setDebugName("CTriangleSelector"); + #endif + + createFromMeshBuffer(meshBuffer); +} CTriangleSelector::CTriangleSelector(IAnimatedMeshSceneNode* node, bool separateMeshbuffers) : SceneNode(node), AnimatedNode(node), LastMeshFrame(0) @@ -100,6 +109,19 @@ void CTriangleSelector::createFromMesh(const IMesh* mesh, bool createBufferRange updateFromMesh(mesh); } +void CTriangleSelector::createFromMeshBuffer(const IMeshBuffer* meshBuffer) +{ + BufferRanges.clear(); + Triangles.clear(); + + if ( meshBuffer ) + { + Triangles.set_used(meshBuffer->getIndexCount() / 3); + } + + updateFromMeshBuffer(meshBuffer); +} + template static void updateTriangles(u32& triangleCount, core::array& triangles, u32 idxCnt, const TIndex* indices, const u8* vertices, u32 vertexPitch, const core::matrix4* bufferTransform) { @@ -167,10 +189,41 @@ void CTriangleSelector::updateFromMesh(const IMesh* mesh) const } // Update bounding box - if ( triangleCount ) + updateBoundingBox(); +} + +void CTriangleSelector::updateFromMeshBuffer(const IMeshBuffer* meshBuffer) const +{ + if ( !meshBuffer ) + return; + + u32 idxCnt = meshBuffer->getIndexCount(); + u32 vertexPitch = getVertexPitchFromType(meshBuffer->getVertexType()); + u8* vertices = (u8*)meshBuffer->getVertices(); + u32 triangleCount = 0; + switch ( meshBuffer->getIndexType() ) + { + case video::EIT_16BIT: + { + const u16* indices = meshBuffer->getIndices(); + updateTriangles(triangleCount, Triangles, idxCnt, indices, vertices, vertexPitch, 0); + } + break; + case video::EIT_32BIT: + { + const u32* indices = (u32*)meshBuffer->getIndices(); + updateTriangles(triangleCount, Triangles, idxCnt, indices, vertices, vertexPitch, 0); + } + break; + } +} + +void CTriangleSelector::updateBoundingBox() const +{ + if ( !Triangles.empty() ) { BoundingBox.reset( Triangles[0].pointA ); - for (u32 i=0; i < triangleCount; ++i) + for (u32 i=0; i < Triangles.size(); ++i) { const core::triangle3df& tri = Triangles[i]; BoundingBox.addInternalPoint(tri.pointA); @@ -184,7 +237,6 @@ void CTriangleSelector::updateFromMesh(const IMesh* mesh) const } } - void CTriangleSelector::update(void) const { if (!AnimatedNode) @@ -243,6 +295,8 @@ void CTriangleSelector::getTriangles(core::triangle3df* triangles, triRange.RangeSize = cnt; triRange.Selector = const_cast(this); triRange.SceneNode = SceneNode; + triRange.MeshBuffer = MeshBuffer; + triRange.MaterialIndex = MaterialIndex; outTriangleInfo->push_back(triRange); } else @@ -381,6 +435,8 @@ void CTriangleSelector::getTriangles(core::triangle3df* triangles, triRange.RangeSize = triangleCount; triRange.Selector = const_cast(this); triRange.SceneNode = SceneNode; + triRange.MeshBuffer = MeshBuffer; + triRange.MaterialIndex = MaterialIndex; outTriangleInfo->push_back(triRange); } } diff --git a/source/Irrlicht/CTriangleSelector.h b/source/Irrlicht/CTriangleSelector.h index eba5b90c..01acacff 100644 --- a/source/Irrlicht/CTriangleSelector.h +++ b/source/Irrlicht/CTriangleSelector.h @@ -29,6 +29,9 @@ public: //! Constructs a selector based on a mesh CTriangleSelector(const IMesh* mesh, ISceneNode* node, bool separateMeshbuffers); + //! Constructs a selector based on a meshbuffer + CTriangleSelector(const IMeshBuffer* meshBuffer, irr::u32 materialIndex, ISceneNode* node); + //! Constructs a selector based on an animated mesh scene node //!\param node An animated mesh scene node, which must have a valid mesh CTriangleSelector(IAnimatedMeshSceneNode* node, bool separateMeshbuffers); @@ -71,9 +74,18 @@ protected: //! Create from a mesh virtual void createFromMesh(const IMesh* mesh, bool createBufferRanges); + //! Create from a meshbuffer + virtual void createFromMeshBuffer(const IMeshBuffer* meshBuffer); + //! Update when the mesh has changed virtual void updateFromMesh(const IMesh* mesh) const; + //! Update when the meshbuffer has changed + virtual void updateFromMeshBuffer(const IMeshBuffer* meshBuffer) const; + + //! Update bounding box from triangles + void updateBoundingBox() const; + //! Update the triangle selector, which will only have an effect if it //! was built from an animated mesh and that mesh's frame has changed //! since the last time it was updated. @@ -85,6 +97,8 @@ protected: mutable core::array Triangles; // (mutable for CTriangleBBSelector) mutable core::aabbox3df BoundingBox; // Allows for trivial rejection + const IMeshBuffer* MeshBuffer; // non-zero when the selector is for a single meshbuffer + irr::u32 MaterialIndex; // Only set when MeshBuffer is non-zero IAnimatedMeshSceneNode* AnimatedNode; mutable u32 LastMeshFrame; };