Fix CMetaTriangleSelector and allow creating octrees for single meshbuffers.

CMetaTriangleSelector had been (even more) broken after last check-in,sorry. Now fixed again.
Making octrees triangle selector return meshbuffer information would be possible, but not without some cost or larger rewrite. So instead I've added another workaround - it's now possible to create octress for single meshbuffers. If that makes sense for speed is something users have to check per scene (slower than using a single octree obviously), but at least it's now possible in case someone needs it.

git-svn-id: svn://svn.code.sf.net/p/irrlicht/code/trunk@5352 dfc29bdd-3216-0410-991c-e03cc46cb475
master
cutealien 2016-12-07 13:30:02 +00:00
parent 543e70dc34
commit 1073bff853
8 changed files with 137 additions and 4 deletions

View File

@ -1,6 +1,7 @@
--------------------------
Changes in 1.9 (not yet released)
- ITriangleSelector now can also return meshbuffer collision information.
- core::string::split now adds delimiter to token before delimiter when keepSeparators is true. That way we never end up with 2 tokens for an original string with a single character.
- Bugfix: SMesh::recalculateBoundingBox() does now ignore empty boundingboxes of meshbuffers instead of adding them.
- IIrrXMLReader::getAttributeValueAsInt and IIrrXMLReader::getAttributeValueAsFloat can now return a custom default-value when the attribute is not found.

View File

@ -93,8 +93,33 @@ int main()
{
q3node->setPosition(core::vector3df(-1350,-130,-1400));
selector = smgr->createOctreeTriangleSelector(
q3node->getMesh(), q3node, 128);
/*
There is currently no way to split an octree by material.
So if we need that we have to create an octrees per meshbuffer
and put them together in a MetaTriangleSelector.
*/
if ( separateMeshBuffers && q3node->getMesh()->getMeshBufferCount() > 1)
{
scene::IMetaTriangleSelector * metaSelector = smgr->createMetaTriangleSelector();
for ( irr::u32 m=0; m < q3node->getMesh()->getMeshBufferCount(); ++m )
{
scene::ITriangleSelector*
bufferSelector = smgr->createOctreeTriangleSelector(
q3node->getMesh()->getMeshBuffer(m), m, q3node);
if ( bufferSelector )
{
metaSelector->addTriangleSelector( bufferSelector );
bufferSelector->drop();
}
}
selector = metaSelector;
}
else
{
selector = smgr->createOctreeTriangleSelector(
q3node->getMesh(), q3node, 128);
}
q3node->setTriangleSelector(selector);
// We're not done with this selector yet, so don't drop it.
}

View File

@ -1334,6 +1334,33 @@ namespace scene
virtual ITriangleSelector* createOctreeTriangleSelector(IMesh* mesh,
ISceneNode* node, s32 minimalPolysPerNode=32) = 0;
//! Creates a Triangle Selector for a single meshbuffer, optimized by an octree.
/** Triangle selectors
can be used for doing collision detection. This triangle selector is
optimized for huge amounts of triangle, it organizes them in an octree.
Please note that the created triangle selector is not automatically attached
to the scene node. You will have to call ISceneNode::setTriangleSelector()
for this. To create and attach a triangle selector is done like this:
\code
ITriangleSelector* s = sceneManager->createOctreeTriangleSelector(yourMesh,
yourSceneNode);
yourSceneNode->setTriangleSelector(s);
s->drop();
\endcode
For more information and examples on this, take a look at the collision
tutorial in the SDK.
\param meshBuffer: Meshbuffer of which the triangles are taken.
\param materialIndex: Setting this value allows the triangle selector to return the material index
\param node: Scene node of which visibility and transformation is used.
\param minimalPolysPerNode: Specifies the minimal polygons contained a octree node.
If a node gets less polys than this value, it will not be split into
smaller nodes.
\return The selector, or null if not successful.
If you no longer need the selector, you should call ITriangleSelector::drop().
See IReferenceCounted::drop() for more information. */
virtual ITriangleSelector* createOctreeTriangleSelector(IMeshBuffer* meshBuffer, irr::u32 materialIndex,
ISceneNode* node, s32 minimalPolysPerNode=32) = 0;
//! //! Creates a Triangle Selector, optimized by an octree.
/** \deprecated Use createOctreeTriangleSelector instead. This method may be removed by Irrlicht 1.9. */
_IRR_DEPRECATED_ ITriangleSelector* createOctTreeTriangleSelector(IMesh* mesh,

View File

@ -42,11 +42,23 @@ void CMetaTriangleSelector::getTriangles(core::triangle3df* triangles, s32 array
irr::core::array<SCollisionTriangleRange>* outTriangleInfo) const
{
s32 outWritten = 0;
irr::u32 outTriangleInfoSize = outTriangleInfo ? outTriangleInfo->size() : 0;
for (u32 i=0; i<TriangleSelectors.size(); ++i)
{
s32 t = 0;
TriangleSelectors[i]->getTriangles(triangles + outWritten,
arraySize - outWritten, t, transform, useNodeTransform, outTriangleInfo);
if ( outTriangleInfo )
{
irr::u32 newTriangleInfoSize = outTriangleInfo->size();
for ( u32 ti=outTriangleInfoSize; ti<newTriangleInfoSize; ++ti )
{
(*outTriangleInfo)[ti].RangeStart += outWritten;
}
outTriangleInfoSize = newTriangleInfoSize;
}
outWritten += t;
if (outWritten==arraySize)
break;
@ -63,11 +75,23 @@ void CMetaTriangleSelector::getTriangles(core::triangle3df* triangles, s32 array
irr::core::array<SCollisionTriangleRange>* outTriangleInfo) const
{
s32 outWritten = 0;
irr::u32 outTriangleInfoSize = outTriangleInfo ? outTriangleInfo->size() : 0;
for (u32 i=0; i<TriangleSelectors.size(); ++i)
{
s32 t = 0;
TriangleSelectors[i]->getTriangles(triangles + outWritten,
arraySize - outWritten, t, box, transform, useNodeTransform, outTriangleInfo);
if ( outTriangleInfo )
{
irr::u32 newTriangleInfoSize = outTriangleInfo->size();
for ( u32 ti=outTriangleInfoSize; ti<newTriangleInfoSize; ++ti )
{
(*outTriangleInfo)[ti].RangeStart += outWritten;
}
outTriangleInfoSize = newTriangleInfoSize;
}
outWritten += t;
if (outWritten==arraySize)
break;
@ -84,11 +108,23 @@ void CMetaTriangleSelector::getTriangles(core::triangle3df* triangles, s32 array
irr::core::array<SCollisionTriangleRange>* outTriangleInfo) const
{
s32 outWritten = 0;
irr::u32 outTriangleInfoSize = outTriangleInfo ? outTriangleInfo->size() : 0;
for (u32 i=0; i<TriangleSelectors.size(); ++i)
{
s32 t = 0;
TriangleSelectors[i]->getTriangles(triangles + outWritten,
arraySize - outWritten, t, line, transform, useNodeTransform, outTriangleInfo);
if ( outTriangleInfo )
{
irr::u32 newTriangleInfoSize = outTriangleInfo->size();
for ( u32 ti=outTriangleInfoSize; ti<newTriangleInfoSize; ++ti )
{
(*outTriangleInfo)[ti].RangeStart += outWritten;
}
outTriangleInfoSize = newTriangleInfoSize;
}
outWritten += t;
if (outWritten==arraySize)
break;

View File

@ -15,8 +15,9 @@ namespace scene
//! constructor
COctreeTriangleSelector::COctreeTriangleSelector(const IMesh* mesh,
ISceneNode* node, s32 minimalPolysPerNode)
: CTriangleSelector(mesh, node, false), Root(0), NodeCount(0),
MinimalPolysPerNode(minimalPolysPerNode)
: CTriangleSelector(mesh, node, false)
, Root(0), NodeCount(0)
, MinimalPolysPerNode(minimalPolysPerNode)
{
#ifdef _DEBUG
setDebugName("COctreeTriangleSelector");
@ -38,6 +39,30 @@ COctreeTriangleSelector::COctreeTriangleSelector(const IMesh* mesh,
}
}
COctreeTriangleSelector::COctreeTriangleSelector(const IMeshBuffer* meshBuffer, irr::u32 materialIndex, ISceneNode* node, s32 minimalPolysPerNode)
: CTriangleSelector(meshBuffer, materialIndex, node)
, Root(0), NodeCount(0)
, MinimalPolysPerNode(minimalPolysPerNode)
{
#ifdef _DEBUG
setDebugName("COctreeTriangleSelector");
#endif
if (!Triangles.empty())
{
const u32 start = os::Timer::getRealTime();
// create the triangle octree
Root = new SOctreeNode();
Root->Triangles = Triangles;
constructOctree(Root);
c8 tmp[256];
sprintf(tmp, "Needed %ums to create OctreeTriangleSelector.(%d nodes, %u polys)",
os::Timer::getRealTime() - start, NodeCount, Triangles.size());
os::Printer::log(tmp, ELL_INFORMATION);
}
}
//! destructor
COctreeTriangleSelector::~COctreeTriangleSelector()
@ -146,6 +171,8 @@ void COctreeTriangleSelector::getTriangles(core::triangle3df* triangles,
triRange.RangeSize = trianglesWritten;
triRange.Selector = const_cast<COctreeTriangleSelector*>(this);
triRange.SceneNode = SceneNode;
triRange.MeshBuffer = MeshBuffer;
triRange.MaterialIndex = MaterialIndex;
outTriangleInfo->push_back(triRange);
}
@ -236,6 +263,8 @@ void COctreeTriangleSelector::getTriangles(core::triangle3df* triangles, s32 arr
triRange.RangeSize = trianglesWritten;
triRange.Selector = const_cast<COctreeTriangleSelector*>(this);
triRange.SceneNode = SceneNode;
triRange.MeshBuffer = MeshBuffer;
triRange.MaterialIndex = MaterialIndex;
outTriangleInfo->push_back(triRange);
}

View File

@ -22,6 +22,9 @@ public:
//! Constructs a selector based on a mesh
COctreeTriangleSelector(const IMesh* mesh, ISceneNode* node, s32 minimalPolysPerNode);
//! Constructs a selector based on a meshbuffer
COctreeTriangleSelector(const IMeshBuffer* meshBuffer, irr::u32 materialIndex, ISceneNode* node, s32 minimalPolysPerNode);
virtual ~COctreeTriangleSelector();
//! Gets all triangles which lie within a specific bounding box.

View File

@ -1893,6 +1893,14 @@ ITriangleSelector* CSceneManager::createOctreeTriangleSelector(IMesh* mesh,
return new COctreeTriangleSelector(mesh, node, minimalPolysPerNode);
}
ITriangleSelector* CSceneManager::createOctreeTriangleSelector(IMeshBuffer* meshBuffer, irr::u32 materialIndex,
ISceneNode* node, s32 minimalPolysPerNode)
{
if ( !meshBuffer)
return 0;
return new COctreeTriangleSelector(meshBuffer, materialIndex, node, minimalPolysPerNode);
}
//! Creates a meta triangle selector.
IMetaTriangleSelector* CSceneManager::createMetaTriangleSelector()

View File

@ -359,6 +359,10 @@ namespace scene
virtual ITriangleSelector* createOctreeTriangleSelector(IMesh* mesh,
ISceneNode* node, s32 minimalPolysPerNode) _IRR_OVERRIDE_;
//! Creates a simple ITriangleSelector, based on a meshbuffer.
virtual ITriangleSelector* createOctreeTriangleSelector(IMeshBuffer* meshBuffer, irr::u32 materialIndex,
ISceneNode* node, s32 minimalPolysPerNode=32) _IRR_OVERRIDE_;
//! Creates a simple dynamic ITriangleSelector, based on a axis aligned bounding box.
virtual ITriangleSelector* createTriangleSelectorFromBoundingBox(
ISceneNode* node) _IRR_OVERRIDE_;