Add createTorusMesh function to IGeometryCreator

Mmmm .... Donuts!


git-svn-id: svn://svn.code.sf.net/p/irrlicht/code/trunk@6222 dfc29bdd-3216-0410-991c-e03cc46cb475
This commit is contained in:
cutealien 2021-06-25 16:19:11 +00:00
parent 479358755b
commit 9ba392e902
4 changed files with 111 additions and 2 deletions

@ -1,5 +1,6 @@
--------------------------
Changes in 1.9 (not yet released)
- Add IGeometryCreator::createTorusMesh to create donuts.
- Don't try loading broken image files twice with same loader anymore.
- Make CImageLoaderJPG thread safe. Thanks @ Edoardo Lolletti for report and patch (patch #324)
- Add ETCF_SUPPORT_VERTEXT_TEXTURE flag which can be used to enable vertex texture sampling support in Direct3D 9.

@ -183,6 +183,16 @@ public:
const video::SColor& colorBottom=video::SColor(0xffffffff),
f32 oblique=0.f) const =0;
//! Create a torus mesh
/** Note: Segments might get reduced to ensure it fits into 16-bit meshbuffer.
With 256 segments for minor and major circle you'll hit the maximum.
\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.
\param minorSegments Segments for minor circle. Will use at least 3
*/
virtual IMesh* createTorusMesh(f32 majorRadius, f32 minorRadius, u32 majorSegments = 32, u32 minorSegments = 16) const = 0;
//! Create a volume light mesh.
/**
\param subdivideU Horizontal patch count.

@ -378,7 +378,7 @@ IMesh* CGeometryCreator::createTerrainMesh(video::IImage* texture,
blockSize.Height = hMapSize.Height - processed.Y;
SMeshBuffer* buffer = new SMeshBuffer();
buffer->setHardwareMappingHint(scene::EHM_STATIC);
buffer->setHardwareMappingHint(EHM_STATIC);
buffer->Vertices.reallocate(blockSize.getArea());
// add vertices of vertex block
u32 y;
@ -500,7 +500,7 @@ IMesh* CGeometryCreator::createArrowMesh(const u32 tesselationCylinder,
IMesh* mesh2 = createConeMesh(width1, height-cylinderHeight, tesselationCone, vtxColor1, vtxColor0);
for (u32 i=0; i<mesh2->getMeshBufferCount(); ++i)
{
scene::IMeshBuffer* buffer = mesh2->getMeshBuffer(i);
IMeshBuffer* buffer = mesh2->getMeshBuffer(i);
for (u32 j=0; j<buffer->getVertexCount(); ++j)
buffer->getPosition(j).Y += cylinderHeight;
buffer->setDirty(EBT_VERTEX);
@ -925,6 +925,101 @@ 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
{
if ( majorRadius == 0.f || minorRadius == 0.f )
return 0;
if ( majorSegments < 3 )
majorSegments = 3;
if ( minorSegments < 3 )
minorSegments = 3;
// 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);
while (numVertices > 65536)
{
if ( majorSegments > 2*minorSegments )
majorSegments /= 2;
else if ( minorSegments > 2*majorSegments )
minorSegments /= 2;
else
{
majorSegments /= 2;
minorSegments /= 2;
}
numVertices = (majorSegments+1)*(minorSegments+1);
}
const u32 majorLines = majorSegments+1;
const u32 minorLines = minorSegments+1;
const video::SColor color(255,255,255,255);
SMeshBuffer* buffer = new SMeshBuffer();
buffer->Indices.reallocate(majorSegments*minorSegments*6);
buffer->Vertices.reallocate(numVertices);
const f32 TWO_PI = 2.f*core::PI;
const f32 angleStepMajor = TWO_PI / majorSegments;
const f32 angleStepMinor = TWO_PI / minorSegments;
// vertices
for ( irr::u32 major = 0; major < majorLines; ++major)
{
const f32 angleMajor = major*angleStepMajor;
const f32 cosMajor = cos(angleMajor);
const f32 sinMajor = sin(angleMajor);
// points of major circle
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 = cos(angleMinor);
core::vector3df p;
p.X = pm.X + minorRadius * cosMinor * cosMajor;
p.Z = pm.Z + minorRadius * cosMinor * sinMajor;
p.Y = minorRadius * sin(angleMinor);
const core::vector3df n((p-pm)/minorRadius);
const core::vector2df uv(angleMajor/TWO_PI, angleMinor/TWO_PI);
buffer->Vertices.push_back( video::S3DVertex(p, n, color, uv) );
}
}
// indices
for ( irr::u32 major = 0; major < majorSegments; ++major)
{
for ( irr::u32 minor = 0; minor < minorSegments; ++minor)
{
irr::u16 i = major*minorLines+minor;
buffer->Indices.push_back(i+1);
buffer->Indices.push_back(i+minorLines);
buffer->Indices.push_back(i);
buffer->Indices.push_back(i+1);
buffer->Indices.push_back(i+minorLines+1);
buffer->Indices.push_back(i+minorLines);
}
}
// recalculate bounding box
buffer->BoundingBox.MaxEdge.X = core::abs_(majorRadius)+core::abs_(minorRadius);
buffer->BoundingBox.MaxEdge.Z = buffer->BoundingBox.MaxEdge.X;
buffer->BoundingBox.MaxEdge.Y = core::abs_(minorRadius);
buffer->BoundingBox.MinEdge = buffer->BoundingBox.MaxEdge*-1.f;
SMesh* mesh = new SMesh();
mesh->addMeshBuffer(buffer);
buffer->drop();
mesh->setHardwareMappingHint(EHM_STATIC);
mesh->recalculateBoundingBox();
return mesh;
}
void CGeometryCreator::addToBuffer(const video::S3DVertex& v, SMeshBuffer* Buffer) const
{

@ -51,6 +51,9 @@ public:
const video::SColor& colorBottom=0xffffffff,
f32 oblique=0.f) const _IRR_OVERRIDE_;
virtual IMesh* createTorusMesh(f32 majorRadius, f32 minorRadius,
u32 majorSegments, u32 minorSegments) const _IRR_OVERRIDE_;
virtual IMesh* createVolumeLightMesh(
const u32 subdivideU=32, const u32 subdivideV=32,
const video::SColor footColor=0xffffffff,