Avoid warning and make local variable lower-case.
git-svn-id: svn://svn.code.sf.net/p/irrlicht/code/trunk@6000 dfc29bdd-3216-0410-991c-e03cc46cb475
This commit is contained in:
327
source/Irrlicht/COctreeTriangleSelector.cpp
Normal file
327
source/Irrlicht/COctreeTriangleSelector.cpp
Normal file
@@ -0,0 +1,327 @@
|
||||
// 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 "COctreeTriangleSelector.h"
|
||||
#include "ISceneNode.h"
|
||||
|
||||
#include "os.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace scene
|
||||
{
|
||||
|
||||
//! constructor
|
||||
COctreeTriangleSelector::COctreeTriangleSelector(const IMesh* mesh,
|
||||
ISceneNode* node, s32 minimalPolysPerNode)
|
||||
: CTriangleSelector(mesh, node, false)
|
||||
, 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);
|
||||
}
|
||||
}
|
||||
|
||||
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()
|
||||
{
|
||||
delete Root;
|
||||
}
|
||||
|
||||
|
||||
void COctreeTriangleSelector::constructOctree(SOctreeNode* node)
|
||||
{
|
||||
++NodeCount;
|
||||
|
||||
node->Box.reset(node->Triangles[0].pointA);
|
||||
|
||||
// get bounding box
|
||||
const u32 cnt = node->Triangles.size();
|
||||
for (u32 i=0; i<cnt; ++i)
|
||||
{
|
||||
node->Box.addInternalPoint(node->Triangles[i].pointA);
|
||||
node->Box.addInternalPoint(node->Triangles[i].pointB);
|
||||
node->Box.addInternalPoint(node->Triangles[i].pointC);
|
||||
}
|
||||
|
||||
// calculate children
|
||||
|
||||
if (!node->Box.isEmpty() && (s32)node->Triangles.size() > MinimalPolysPerNode)
|
||||
{
|
||||
const core::vector3df& middle = node->Box.getCenter();
|
||||
core::vector3df edges[8];
|
||||
node->Box.getEdges(edges);
|
||||
|
||||
core::aabbox3d<f32> box;
|
||||
core::array<core::triangle3df> keepTriangles(node->Triangles.size()); // reserving enough memory, so we don't get re-allocations per child
|
||||
|
||||
for (s32 ch=0; ch<8; ++ch)
|
||||
{
|
||||
box.reset(middle);
|
||||
box.addInternalPoint(edges[ch]);
|
||||
node->Child[ch] = new SOctreeNode();
|
||||
|
||||
for (s32 i=0; i<(s32)node->Triangles.size(); ++i)
|
||||
{
|
||||
if (node->Triangles[i].isTotalInsideBox(box))
|
||||
{
|
||||
node->Child[ch]->Triangles.push_back(node->Triangles[i]);
|
||||
//node->Triangles.erase(i);
|
||||
//--i;
|
||||
}
|
||||
else
|
||||
{
|
||||
keepTriangles.push_back(node->Triangles[i]);
|
||||
}
|
||||
}
|
||||
memcpy(node->Triangles.pointer(), keepTriangles.pointer(),
|
||||
sizeof(core::triangle3df)*keepTriangles.size());
|
||||
|
||||
node->Triangles.set_used(keepTriangles.size());
|
||||
keepTriangles.set_used(0);
|
||||
}
|
||||
keepTriangles.clear(); // release memory early, for large meshes it can matter.
|
||||
node->Triangles.reallocate(node->Triangles.size(), true); // shrink memory to minimum necessary
|
||||
|
||||
// Note: We use an extra loop to construct child-nodes instead of doing
|
||||
// that in above loop to avoid memory fragmentation which happens if
|
||||
// the code has to switch between allocating memory for this node and
|
||||
// the child nodes (thanks @Squarefox for noting this).
|
||||
for (s32 ch=0; ch<8; ++ch)
|
||||
{
|
||||
if (node->Child[ch]->Triangles.empty())
|
||||
{
|
||||
delete node->Child[ch];
|
||||
node->Child[ch] = 0;
|
||||
}
|
||||
else
|
||||
constructOctree(node->Child[ch]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//! Gets all triangles which lie within a specific bounding box.
|
||||
void COctreeTriangleSelector::getTriangles(core::triangle3df* triangles,
|
||||
s32 arraySize, s32& outTriangleCount,
|
||||
const core::aabbox3d<f32>& box,
|
||||
const core::matrix4* transform, bool useNodeTransform,
|
||||
irr::core::array<SCollisionTriangleRange>* outTriangleInfo) const
|
||||
{
|
||||
core::matrix4 mat(core::matrix4::EM4CONST_NOTHING);
|
||||
core::aabbox3d<f32> invbox = box;
|
||||
|
||||
if (SceneNode && useNodeTransform)
|
||||
{
|
||||
if ( SceneNode->getAbsoluteTransformation().getInverse(mat) )
|
||||
mat.transformBoxEx(invbox);
|
||||
else
|
||||
// TODO: case not handled well, we can only return all triangles
|
||||
return CTriangleSelector::getTriangles(triangles, arraySize, outTriangleCount, transform, useNodeTransform, outTriangleInfo);
|
||||
}
|
||||
|
||||
if (transform)
|
||||
mat = *transform;
|
||||
else
|
||||
mat.makeIdentity();
|
||||
|
||||
if (SceneNode && useNodeTransform)
|
||||
mat *= SceneNode->getAbsoluteTransformation();
|
||||
|
||||
s32 trianglesWritten = 0;
|
||||
|
||||
if (Root)
|
||||
getTrianglesFromOctree(Root, trianglesWritten,
|
||||
arraySize, invbox, &mat, triangles);
|
||||
|
||||
if ( outTriangleInfo )
|
||||
{
|
||||
SCollisionTriangleRange triRange;
|
||||
triRange.RangeSize = trianglesWritten;
|
||||
triRange.Selector = const_cast<COctreeTriangleSelector*>(this);
|
||||
triRange.SceneNode = SceneNode;
|
||||
triRange.MeshBuffer = MeshBuffer;
|
||||
triRange.MaterialIndex = MaterialIndex;
|
||||
outTriangleInfo->push_back(triRange);
|
||||
}
|
||||
|
||||
outTriangleCount = trianglesWritten;
|
||||
}
|
||||
|
||||
|
||||
void COctreeTriangleSelector::getTrianglesFromOctree(
|
||||
SOctreeNode* node, s32& trianglesWritten,
|
||||
s32 maximumSize, const core::aabbox3d<f32>& box,
|
||||
const core::matrix4* mat, core::triangle3df* triangles) const
|
||||
{
|
||||
if (!box.intersectsWithBox(node->Box))
|
||||
return;
|
||||
|
||||
const u32 cnt = node->Triangles.size();
|
||||
|
||||
for (u32 i=0; i<cnt; ++i)
|
||||
{
|
||||
const core::triangle3df& srcTri = node->Triangles[i];
|
||||
// This isn't an accurate test, but it's fast, and the
|
||||
// API contract doesn't guarantee complete accuracy.
|
||||
if (srcTri.isTotalOutsideBox(box))
|
||||
continue;
|
||||
|
||||
core::triangle3df& dstTri = triangles[trianglesWritten];
|
||||
mat->transformVect(dstTri.pointA, srcTri.pointA );
|
||||
mat->transformVect(dstTri.pointB, srcTri.pointB );
|
||||
mat->transformVect(dstTri.pointC, srcTri.pointC );
|
||||
++trianglesWritten;
|
||||
|
||||
// Halt when the out array is full.
|
||||
if (trianglesWritten == maximumSize)
|
||||
return;
|
||||
}
|
||||
|
||||
for (u32 i=0; i<8; ++i)
|
||||
if (node->Child[i])
|
||||
getTrianglesFromOctree(node->Child[i], trianglesWritten,
|
||||
maximumSize, box, mat, triangles);
|
||||
}
|
||||
|
||||
|
||||
//! Gets all triangles which have or may have contact with a 3d line.
|
||||
// new version: from user Piraaate
|
||||
void COctreeTriangleSelector::getTriangles(core::triangle3df* triangles, s32 arraySize,
|
||||
s32& outTriangleCount, const core::line3d<f32>& line,
|
||||
const core::matrix4* transform, bool useNodeTransform,
|
||||
irr::core::array<SCollisionTriangleRange>* outTriangleInfo) const
|
||||
{
|
||||
#if 0
|
||||
core::aabbox3d<f32> box(line.start);
|
||||
box.addInternalPoint(line.end);
|
||||
|
||||
// TODO: Could be optimized for line a little bit more.
|
||||
COctreeTriangleSelector::getTriangles(triangles, arraySize, outTriangleCount,
|
||||
box, transform);
|
||||
#else
|
||||
|
||||
core::matrix4 mat ( core::matrix4::EM4CONST_NOTHING );
|
||||
|
||||
core::vector3df vectStartInv ( line.start ), vectEndInv ( line.end );
|
||||
if (SceneNode && useNodeTransform)
|
||||
{
|
||||
mat = SceneNode->getAbsoluteTransformation();
|
||||
mat.makeInverse();
|
||||
mat.transformVect(vectStartInv, line.start);
|
||||
mat.transformVect(vectEndInv, line.end);
|
||||
}
|
||||
core::line3d<f32> invline(vectStartInv, vectEndInv);
|
||||
|
||||
mat.makeIdentity();
|
||||
|
||||
if (transform)
|
||||
mat = (*transform);
|
||||
|
||||
if (SceneNode && useNodeTransform)
|
||||
mat *= SceneNode->getAbsoluteTransformation();
|
||||
|
||||
s32 trianglesWritten = 0;
|
||||
|
||||
if (Root)
|
||||
getTrianglesFromOctree(Root, trianglesWritten, arraySize, invline, &mat, triangles);
|
||||
|
||||
if ( outTriangleInfo )
|
||||
{
|
||||
SCollisionTriangleRange triRange;
|
||||
triRange.RangeSize = trianglesWritten;
|
||||
triRange.Selector = const_cast<COctreeTriangleSelector*>(this);
|
||||
triRange.SceneNode = SceneNode;
|
||||
triRange.MeshBuffer = MeshBuffer;
|
||||
triRange.MaterialIndex = MaterialIndex;
|
||||
outTriangleInfo->push_back(triRange);
|
||||
}
|
||||
|
||||
outTriangleCount = trianglesWritten;
|
||||
#endif
|
||||
}
|
||||
|
||||
void COctreeTriangleSelector::getTrianglesFromOctree(SOctreeNode* node,
|
||||
s32& trianglesWritten, s32 maximumSize, const core::line3d<f32>& line,
|
||||
const core::matrix4* transform, core::triangle3df* triangles) const
|
||||
{
|
||||
if (!node->Box.intersectsWithLine(line))
|
||||
return;
|
||||
|
||||
s32 cnt = node->Triangles.size();
|
||||
if (cnt + trianglesWritten > maximumSize)
|
||||
cnt -= cnt + trianglesWritten - maximumSize;
|
||||
|
||||
s32 i;
|
||||
|
||||
if ( transform->isIdentity() )
|
||||
{
|
||||
for (i=0; i<cnt; ++i)
|
||||
{
|
||||
triangles[trianglesWritten] = node->Triangles[i];
|
||||
++trianglesWritten;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (i=0; i<cnt; ++i)
|
||||
{
|
||||
triangles[trianglesWritten] = node->Triangles[i];
|
||||
transform->transformVect(triangles[trianglesWritten].pointA);
|
||||
transform->transformVect(triangles[trianglesWritten].pointB);
|
||||
transform->transformVect(triangles[trianglesWritten].pointC);
|
||||
++trianglesWritten;
|
||||
}
|
||||
}
|
||||
|
||||
for (i=0; i<8; ++i)
|
||||
if (node->Child[i])
|
||||
getTrianglesFromOctree(node->Child[i], trianglesWritten,
|
||||
maximumSize, line, transform, triangles);
|
||||
}
|
||||
|
||||
|
||||
} // end namespace scene
|
||||
} // end namespace irr
|
Reference in New Issue
Block a user