createTorusMesh can now create a partial torus

Capping the torus also supported.
Bit arguably if caps belong in this function, but default for caps is off and they can be useful.
(one could also code partial minor circles ... but I'm stopping there)


git-svn-id: svn://svn.code.sf.net/p/irrlicht/code/trunk@6225 dfc29bdd-3216-0410-991c-e03cc46cb475
This commit is contained in:
cutealien 2021-06-28 14:33:08 +00:00
parent 28fd5f8a4f
commit 38e2aa1338
3 changed files with 68 additions and 16 deletions

View File

@ -186,12 +186,22 @@ public:
//! Create a torus mesh
/** Note: Segments might get reduced to ensure it fits into 16-bit meshbuffer.
With 255 segments for minor and major circle you'll hit the maximum.
When using caps 2 more vertices are added.
Note: UV's for caps are probably not useful
\param majorRadius Starting from mesh center
\param minorRadius Starting from a circle at majorRadius distance around center
\param majorSegments Segments for major circle. Will use at least 3 segments.
\param minorSegments Segments for minor circle. Will use at least 3 segments.
\param angleStart Start major circle between 0 and 360° and < angleEnd
\param angleEnd End major circle between 0 and 360° and > angleStart
\param capEnds When you don't create a full major circle you might want caps
0 = no caps (default)
Bit 1: add cap at angleStart
Bit 2: add cap at angleEnd
*/
virtual IMesh* createTorusMesh(f32 majorRadius, f32 minorRadius, u32 majorSegments = 32, u32 minorSegments = 16) const = 0;
virtual IMesh* createTorusMesh(f32 majorRadius, f32 minorRadius,
u32 majorSegments = 32, u32 minorSegments = 16,
f32 angleStart=0.f, f32 angleEnd=360.f, int capEnds=0) const = 0;
//! Create a volume light mesh.
/**

View File

@ -925,7 +925,7 @@ IMesh* CGeometryCreator::createConeMesh(f32 radius, f32 length, u32 tesselation,
return mesh;
}
irr::scene::IMesh* CGeometryCreator::createTorusMesh(irr::f32 majorRadius, irr::f32 minorRadius, irr::u32 majorSegments, irr::u32 minorSegments) const
irr::scene::IMesh* CGeometryCreator::createTorusMesh(irr::f32 majorRadius, irr::f32 minorRadius, irr::u32 majorSegments, irr::u32 minorSegments, f32 angleStart, f32 angleEnd, int capEnds) const
{
if ( majorRadius == 0.f || minorRadius == 0.f )
return 0;
@ -938,7 +938,8 @@ irr::scene::IMesh* CGeometryCreator::createTorusMesh(irr::f32 majorRadius, irr::
// Note: first/last vertices of major and minor lines are on same position, but not shared to allow for independent uv's.
// prevent 16-bit vertex buffer overflow
u32 numVertices = (majorSegments+1)*(minorSegments+1);
const u32 numCapVertices = (capEnds & 1 ? 1 : 0) + (capEnds & 2 ? 1 : 0);
u32 numVertices = (majorSegments+1)*(minorSegments+1)+numCapVertices;
while (numVertices > 65536)
{
if ( majorSegments > 2*minorSegments )
@ -950,7 +951,7 @@ irr::scene::IMesh* CGeometryCreator::createTorusMesh(irr::f32 majorRadius, irr::
majorSegments /= 2;
minorSegments /= 2;
}
numVertices = (majorSegments+1)*(minorSegments+1);
numVertices = (majorSegments+1)*(minorSegments+1)+numCapVertices;
}
const u32 majorLines = majorSegments+1;
@ -961,27 +962,32 @@ irr::scene::IMesh* CGeometryCreator::createTorusMesh(irr::f32 majorRadius, irr::
buffer->Indices.reallocate(majorSegments*minorSegments*6);
buffer->Vertices.reallocate(numVertices);
if ( angleStart > angleEnd )
core::swap(angleStart, angleEnd);
const f32 radStart = angleStart * core::DEGTORAD;
const f32 radEnd = angleEnd * core::DEGTORAD;
const f32 radMajor = radEnd-radStart;
const f32 radStepMajor = radMajor / majorSegments;
const f32 TWO_PI = 2.f*core::PI;
const f32 angleStepMajor = TWO_PI / majorSegments;
const f32 angleStepMinor = TWO_PI / minorSegments;
const f32 radStepMinor = TWO_PI / minorSegments;
// vertices
for ( irr::u32 major = 0; major < majorLines; ++major)
{
const f32 angleMajor = major*angleStepMajor;
const f32 cosMajor = cosf(angleMajor);
const f32 sinMajor = sinf(angleMajor);
const f32 radMajor = radStart + major*radStepMajor;
const f32 cosMajor = cosf(radMajor);
const f32 sinMajor = sinf(radMajor);
// points of major circle
const core::vector3df pm(majorRadius*cosMajor, 0.f, majorRadius * sinMajor);
const core::vector3df pm(majorRadius*cosMajor, 0.f, majorRadius * sinMajor);
for ( irr::u32 minor = 0; minor < minorLines; ++minor)
{
const f32 angleMinor = minor*angleStepMinor;
const f32 cosMinor = cosf(angleMinor);
const f32 radMinor = minor*radStepMinor;
const f32 cosMinor = cosf(radMinor);
const core::vector3df n(cosMinor * cosMajor, sinf(angleMinor), cosMinor * sinMajor);
const core::vector2df uv(angleMajor/TWO_PI, angleMinor/TWO_PI);
const core::vector3df n(cosMinor * cosMajor, sinf(radMinor), cosMinor * sinMajor);
const core::vector2df uv(radMajor/TWO_PI, radMinor/TWO_PI);
buffer->Vertices.push_back( video::S3DVertex(pm+n*minorRadius, n, color, uv) );
}
}
@ -991,7 +997,7 @@ irr::scene::IMesh* CGeometryCreator::createTorusMesh(irr::f32 majorRadius, irr::
{
for ( irr::u32 minor = 0; minor < minorSegments; ++minor)
{
irr::u16 i = major*minorLines+minor;
const irr::u16 i = major*minorLines+minor;
buffer->Indices.push_back(i+1);
buffer->Indices.push_back(i+minorLines);
buffer->Indices.push_back(i);
@ -1002,6 +1008,41 @@ irr::scene::IMesh* CGeometryCreator::createTorusMesh(irr::f32 majorRadius, irr::
}
}
// add start caps
if ( capEnds & 1 )
{
const core::vector3df p(cosf(radStart), 0.f, sinf(radStart));
const core::vector3df n( p.crossProduct(core::vector3df(0,-1,0)) );
const core::vector2df uv(radStart/TWO_PI, 0.5f);
buffer->Vertices.push_back( video::S3DVertex(p*majorRadius, n, color, uv) );
const irr::u16 i=buffer->Vertices.size()-1;
for ( irr::u32 minor = 0; minor < minorSegments; ++minor)
{
buffer->Indices.push_back(minor+1);
buffer->Indices.push_back(minor);
buffer->Indices.push_back(i);
}
}
// add end caps
if ( capEnds & 2 )
{
const core::vector3df p(cosf(radEnd), 0.f, sinf(radEnd));
const core::vector3df n( p.crossProduct(core::vector3df(0,1,0)) );
const core::vector2df uv(radEnd/TWO_PI, 0.5f);
buffer->Vertices.push_back( video::S3DVertex(p*majorRadius, n, color, uv) );
const irr::u16 i=buffer->Vertices.size()-1;
const irr::u16 k=i-numCapVertices;
for ( irr::u32 minor = 0; minor < minorSegments; ++minor)
{
buffer->Indices.push_back(k-minor-1);
buffer->Indices.push_back(k-minor);
buffer->Indices.push_back(i);
}
}
// recalculate bounding box
buffer->BoundingBox.MaxEdge.X = core::abs_(majorRadius)+core::abs_(minorRadius);
buffer->BoundingBox.MaxEdge.Z = buffer->BoundingBox.MaxEdge.X;

View File

@ -52,7 +52,8 @@ public:
f32 oblique=0.f) const _IRR_OVERRIDE_;
virtual IMesh* createTorusMesh(f32 majorRadius, f32 minorRadius,
u32 majorSegments, u32 minorSegments) const _IRR_OVERRIDE_;
u32 majorSegments, u32 minorSegments,
f32 angleStart, f32 angleEnd, int capEnds) const _IRR_OVERRIDE_;
virtual IMesh* createVolumeLightMesh(
const u32 subdivideU=32, const u32 subdivideV=32,