mirror of
https://github.com/minetest/irrlicht.git
synced 2024-11-16 15:30:25 +01:00
272 lines
7.3 KiB
C++
272 lines
7.3 KiB
C++
|
// 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 "IrrCompileConfig.h"
|
||
|
|
||
|
#ifdef _IRR_COMPILE_WITH_TERRAIN_SCENENODE_
|
||
|
|
||
|
#include "CTerrainTriangleSelector.h"
|
||
|
#include "CTerrainSceneNode.h"
|
||
|
#include "os.h"
|
||
|
|
||
|
namespace irr
|
||
|
{
|
||
|
namespace scene
|
||
|
{
|
||
|
|
||
|
|
||
|
//! constructor
|
||
|
CTerrainTriangleSelector::CTerrainTriangleSelector ( ITerrainSceneNode* node, s32 LOD )
|
||
|
: SceneNode(node)
|
||
|
{
|
||
|
#ifdef _DEBUG
|
||
|
setDebugName ("CTerrainTriangleSelector");
|
||
|
#endif
|
||
|
|
||
|
setTriangleData(node, LOD);
|
||
|
}
|
||
|
|
||
|
|
||
|
//! destructor
|
||
|
CTerrainTriangleSelector::~CTerrainTriangleSelector()
|
||
|
{
|
||
|
TrianglePatches.TrianglePatchArray.clear();
|
||
|
}
|
||
|
|
||
|
|
||
|
//! Clears and sets triangle data
|
||
|
void CTerrainTriangleSelector::setTriangleData(ITerrainSceneNode* node, s32 LOD)
|
||
|
{
|
||
|
// Get pointer to the GeoMipMaps vertices
|
||
|
const video::S3DVertex2TCoords* vertices = static_cast<const video::S3DVertex2TCoords*>(node->getRenderBuffer()->getVertices());
|
||
|
|
||
|
// Clear current data
|
||
|
const s32 count = (static_cast<CTerrainSceneNode*>(node))->TerrainData.PatchCount;
|
||
|
TrianglePatches.TotalTriangles = 0;
|
||
|
TrianglePatches.NumPatches = count*count;
|
||
|
|
||
|
TrianglePatches.TrianglePatchArray.reallocate(TrianglePatches.NumPatches);
|
||
|
for (s32 o=0; o<TrianglePatches.NumPatches; ++o)
|
||
|
TrianglePatches.TrianglePatchArray.push_back(SGeoMipMapTrianglePatch());
|
||
|
|
||
|
core::triangle3df tri;
|
||
|
core::array<u32> indices;
|
||
|
s32 tIndex = 0;
|
||
|
for(s32 x = 0; x < count; ++x )
|
||
|
{
|
||
|
for(s32 z = 0; z < count; ++z )
|
||
|
{
|
||
|
TrianglePatches.TrianglePatchArray[tIndex].NumTriangles = 0;
|
||
|
TrianglePatches.TrianglePatchArray[tIndex].Box = node->getBoundingBox( x, z );
|
||
|
u32 indexCount = node->getIndicesForPatch( indices, x, z, LOD );
|
||
|
|
||
|
TrianglePatches.TrianglePatchArray[tIndex].Triangles.reallocate(indexCount/3);
|
||
|
for(u32 i = 0; i < indexCount; i += 3 )
|
||
|
{
|
||
|
tri.pointA = vertices[indices[i+0]].Pos;
|
||
|
tri.pointB = vertices[indices[i+1]].Pos;
|
||
|
tri.pointC = vertices[indices[i+2]].Pos;
|
||
|
TrianglePatches.TrianglePatchArray[tIndex].Triangles.push_back(tri);
|
||
|
++TrianglePatches.TrianglePatchArray[tIndex].NumTriangles;
|
||
|
}
|
||
|
|
||
|
TrianglePatches.TotalTriangles += TrianglePatches.TrianglePatchArray[tIndex].NumTriangles;
|
||
|
++tIndex;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
//! Gets all triangles.
|
||
|
void CTerrainTriangleSelector::getTriangles(core::triangle3df* triangles,
|
||
|
s32 arraySize, s32& outTriangleCount,
|
||
|
const core::matrix4* transform, bool useNodeTransform,
|
||
|
irr::core::array<SCollisionTriangleRange>* outTriangleInfo) const
|
||
|
{
|
||
|
s32 count = TrianglePatches.TotalTriangles;
|
||
|
|
||
|
if (count > arraySize)
|
||
|
count = arraySize;
|
||
|
|
||
|
core::matrix4 mat;
|
||
|
|
||
|
if (transform)
|
||
|
mat = (*transform);
|
||
|
|
||
|
s32 tIndex = 0;
|
||
|
|
||
|
for (s32 i=0; i<TrianglePatches.NumPatches; ++i)
|
||
|
{
|
||
|
if (tIndex + TrianglePatches.TrianglePatchArray[i].NumTriangles <= count)
|
||
|
for (s32 j=0; j<TrianglePatches.TrianglePatchArray[i].NumTriangles; ++j)
|
||
|
{
|
||
|
triangles[tIndex] = TrianglePatches.TrianglePatchArray[i].Triangles[j];
|
||
|
|
||
|
mat.transformVect(triangles[tIndex].pointA);
|
||
|
mat.transformVect(triangles[tIndex].pointB);
|
||
|
mat.transformVect(triangles[tIndex].pointC);
|
||
|
|
||
|
++tIndex;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if ( outTriangleInfo )
|
||
|
{
|
||
|
SCollisionTriangleRange triRange;
|
||
|
triRange.RangeSize = tIndex;
|
||
|
triRange.Selector = const_cast<CTerrainTriangleSelector*>(this);
|
||
|
triRange.SceneNode = SceneNode;
|
||
|
outTriangleInfo->push_back(triRange);
|
||
|
}
|
||
|
|
||
|
outTriangleCount = tIndex;
|
||
|
}
|
||
|
|
||
|
|
||
|
//! Gets all triangles which lie within a specific bounding box.
|
||
|
void CTerrainTriangleSelector::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
|
||
|
{
|
||
|
s32 count = TrianglePatches.TotalTriangles;
|
||
|
|
||
|
if (count > arraySize)
|
||
|
count = arraySize;
|
||
|
|
||
|
core::matrix4 mat;
|
||
|
|
||
|
if (transform)
|
||
|
mat = (*transform);
|
||
|
|
||
|
s32 tIndex = 0;
|
||
|
|
||
|
for (s32 i=0; i<TrianglePatches.NumPatches; ++i)
|
||
|
{
|
||
|
if (tIndex + TrianglePatches.TrianglePatchArray[i].NumTriangles <= count &&
|
||
|
TrianglePatches.TrianglePatchArray[i].Box.intersectsWithBox(box))
|
||
|
for (s32 j=0; j<TrianglePatches.TrianglePatchArray[i].NumTriangles; ++j)
|
||
|
{
|
||
|
triangles[tIndex] = TrianglePatches.TrianglePatchArray[i].Triangles[j];
|
||
|
|
||
|
mat.transformVect(triangles[tIndex].pointA);
|
||
|
mat.transformVect(triangles[tIndex].pointB);
|
||
|
mat.transformVect(triangles[tIndex].pointC);
|
||
|
|
||
|
++tIndex;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if ( outTriangleInfo )
|
||
|
{
|
||
|
SCollisionTriangleRange triRange;
|
||
|
triRange.RangeSize = tIndex;
|
||
|
triRange.Selector = const_cast<CTerrainTriangleSelector*>(this);
|
||
|
triRange.SceneNode = SceneNode;
|
||
|
outTriangleInfo->push_back(triRange);
|
||
|
}
|
||
|
|
||
|
outTriangleCount = tIndex;
|
||
|
}
|
||
|
|
||
|
|
||
|
//! Gets all triangles which have or may have contact with a 3d line.
|
||
|
void CTerrainTriangleSelector::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
|
||
|
{
|
||
|
const s32 count = core::min_((s32)TrianglePatches.TotalTriangles, arraySize);
|
||
|
|
||
|
core::matrix4 mat;
|
||
|
|
||
|
if (transform)
|
||
|
mat = (*transform);
|
||
|
|
||
|
s32 tIndex = 0;
|
||
|
|
||
|
for (s32 i=0; i<TrianglePatches.NumPatches; ++i)
|
||
|
{
|
||
|
if (tIndex + TrianglePatches.TrianglePatchArray[i].NumTriangles <= count
|
||
|
&& TrianglePatches.TrianglePatchArray[i].Box.intersectsWithLine(line))
|
||
|
{
|
||
|
for (s32 j=0; j<TrianglePatches.TrianglePatchArray[i].NumTriangles; ++j)
|
||
|
{
|
||
|
triangles[tIndex] = TrianglePatches.TrianglePatchArray[i].Triangles[j];
|
||
|
|
||
|
mat.transformVect(triangles[tIndex].pointA);
|
||
|
mat.transformVect(triangles[tIndex].pointB);
|
||
|
mat.transformVect(triangles[tIndex].pointC);
|
||
|
|
||
|
++tIndex;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if ( outTriangleInfo )
|
||
|
{
|
||
|
SCollisionTriangleRange triRange;
|
||
|
triRange.RangeSize = tIndex;
|
||
|
triRange.Selector = const_cast<CTerrainTriangleSelector*>(this);
|
||
|
triRange.SceneNode = SceneNode;
|
||
|
outTriangleInfo->push_back(triRange);
|
||
|
}
|
||
|
|
||
|
outTriangleCount = tIndex;
|
||
|
}
|
||
|
|
||
|
|
||
|
//! Returns amount of all available triangles in this selector
|
||
|
s32 CTerrainTriangleSelector::getTriangleCount() const
|
||
|
{
|
||
|
return TrianglePatches.TotalTriangles;
|
||
|
}
|
||
|
|
||
|
|
||
|
ISceneNode* CTerrainTriangleSelector::getSceneNodeForTriangle(
|
||
|
u32 triangleIndex) const
|
||
|
{
|
||
|
return SceneNode;
|
||
|
}
|
||
|
|
||
|
|
||
|
/* Get the number of TriangleSelectors that are part of this one.
|
||
|
Only useful for MetaTriangleSelector others return 1
|
||
|
*/
|
||
|
u32 CTerrainTriangleSelector::getSelectorCount() const
|
||
|
{
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
|
||
|
/* Get the TriangleSelector based on index based on getSelectorCount.
|
||
|
Only useful for MetaTriangleSelector others return 'this' or 0
|
||
|
*/
|
||
|
ITriangleSelector* CTerrainTriangleSelector::getSelector(u32 index)
|
||
|
{
|
||
|
if (index)
|
||
|
return 0;
|
||
|
else
|
||
|
return this;
|
||
|
}
|
||
|
|
||
|
|
||
|
/* Get the TriangleSelector based on index based on getSelectorCount.
|
||
|
Only useful for MetaTriangleSelector others return 'this' or 0
|
||
|
*/
|
||
|
const ITriangleSelector* CTerrainTriangleSelector::getSelector(u32 index) const
|
||
|
{
|
||
|
if (index)
|
||
|
return 0;
|
||
|
else
|
||
|
return this;
|
||
|
}
|
||
|
|
||
|
|
||
|
} // end namespace scene
|
||
|
} // end namespace irr
|
||
|
|
||
|
#endif // _IRR_COMPILE_WITH_TERRAIN_SCENENODE_
|