draw3DCircle

Post those lines of code you feel like sharing or find what you require for your project here; or simply use them as tutorials.
Post Reply
wing64
Competition winner
Posts: 242
Joined: Wed Jul 23, 2008 2:35 am
Location: Thailand
Contact:

draw3DCircle

Post by wing64 »

Code: Select all

void draw3DCircle( video::IVideoDriver* driver, core::vector3df center, f32 radius, u32 vertexcount, core::vector3df normal, video::SColor color )
{
        core::array<video::S3DVertex> lstVertices;
        core::array<u16> lstIndices;
 
        // We want the vertex count to reflect a polygon
        if (vertexcount < 3) vertexcount = 3;
        if (vertexcount > 10000) vertexcount = 10000;
 
        normal.normalize();
 
        //Here we find the intersection of a plane whos normal is our normal vector,
        //with a sphere with radius 'radius'.
 
        //The equation of this circle is P + sV1 + tV2
        //where v1 id (0, c, -b) and v2 is (c, 0, -a), we need at least one nonzero one.
        core::vector3df v1 = core::vector3df(0, normal.Z, -normal.Y);
        core::vector3df v2 = core::vector3df(normal.Z, 0, -normal.X);
 
        if(v1 != core::vector3df(0,0,0))
        {
                v1 = v1 / sqrt(1 - (normal.X * normal.X));
                v2 = v1.crossProduct(normal);
        }
        else
        {
                v2 = v2 / sqrt(1 - (normal.Y * normal.Y));
                v1 = v2.crossProduct(normal);
        }
 
        lstIndices.clear();
        lstVertices.clear();
 
        video::S3DVertex vert;
        for(u32 x = 0; x < vertexcount; ++x)
        {
                vert.Pos = center + radius * cos(2 * core::PI / vertexcount * x) * v1 + radius * sin(2 * core::PI / vertexcount * x) * v2;
                vert.Color = color;
                lstIndices.push_back(lstVertices.size());
                lstVertices.push_back(vert);
                vert.Pos = center + radius * cos(2 * core::PI / vertexcount * (x + 1)) * v1 + radius * sin(2 * core::PI / vertexcount * (x + 1)) * v2;
                vert.Color = video::SColor(255, 255,255,255);
                lstIndices.push_back(lstVertices.size());
                lstVertices.push_back(vert);
        }
 
        // render
        driver->drawVertexPrimitiveList(&lstVertices[0], lstVertices.size(), &lstIndices[0], lstIndices.size() / 2, video::EVT_STANDARD, scene::EPT_LINES, video::EIT_16BIT);
}
 
*I copy and cut from somewhere in this forum (very sorry i forgot it)
Mel
Competition winner
Posts: 2292
Joined: Wed May 07, 2008 11:40 am
Location: Granada, Spain

Re: draw3DCircle

Post by Mel »

Nice, very nice! :)
"There is nothing truly useless, it always serves as a bad example". Arthur A. Schmitt
Abraxas)
Posts: 227
Joined: Sun Oct 18, 2009 7:24 am

Re: draw3DCircle

Post by Abraxas) »

Why do I feel like this is a copy of my 3d circle thread we worked on a couple years ago
Abraxas)
Posts: 227
Joined: Sun Oct 18, 2009 7:24 am

Re: draw3DCircle

Post by Abraxas) »

chronologicaldot
Competition winner
Posts: 685
Joined: Mon Sep 10, 2012 8:51 am

Re: draw3DCircle

Post by chronologicaldot »

You're right about that. There's alot of code from Acki's circleclass.cpp. But this guy's code reduces it to a single function, which I imagine would be faster for the job.
TheMrCerebro
Competition winner
Posts: 80
Joined: Tue Jun 29, 2010 10:06 pm
Location: Valencia, Spain

Re: draw3DCircle

Post by TheMrCerebro »

Nice job! :wink:
Follow me on twitter: @themrcerebro
Nadro
Posts: 1648
Joined: Sun Feb 19, 2006 9:08 am
Location: Warsaw, Poland

Re: draw3DCircle

Post by Nadro »

You should use "reallocate" (or construct an array with predefined size based on vertexcount size) for lstVertices and lstIndices for get better performance (or just use operator new for these variables instead of array).
Library helping with network requests, tasks management, logger etc in desktop and mobile apps: https://github.com/GrupaPracuj/hermes
Marthog
Posts: 31
Joined: Sun Oct 03, 2010 8:33 pm
Contact:

Re: draw3DCircle

Post by Marthog »

I optimimized the function a bit. It is now 1.3 (3 vertices) to 4 (10000 vertices) times faster. But for a more faster solution you have to create the arrays once and draw them each frame again.

Code: Select all

void draw3DCircle( video::IVideoDriver* driver, core::vector3df center, f32 radius, u32 vertexcount, core::vector3df normal, video::SColor color )
{
        // We want the vertex count to reflect a polygon
        if (vertexcount < 3) vertexcount = 3;
        if (vertexcount > 10000) vertexcount = 10000;
 
 
        core::array<video::S3DVertex> lstVertices(vertexcount+1);
        lstVertices.set_used(vertexcount+1);
        core::array<u16> lstIndices(vertexcount*2);
        lstIndices.set_used(vertexcount*2);
 
        normal.normalize();
 
        //Here we find the intersection of a plane whos normal is our normal vector,
        //with a sphere with radius 'radius'.
 
        //The equation of this circle is P + sV1 + tV2
        //where v1 id (0, c, -b) and v2 is (c, 0, -a), we need at least one nonzero one.
        core::vector3df v1 = core::vector3df(0, normal.Z, -normal.Y);
        core::vector3df v2 = core::vector3df(normal.Z, 0, -normal.X);
 
        if(v1 != core::vector3df(0,0,0))
        {
                v1 = v1 / sqrt(1 - (normal.X * normal.X));
                v2 = v1.crossProduct(normal);
        }
        else
        {
                v2 = v2 / sqrt(1 - (normal.Y * normal.Y));
                v1 = v2.crossProduct(normal);
        }
 
        const f32 angle = 2*core::PI/vertexcount;
    
        video::S3DVertex vert;
        vert.Color = color;         // Always the same color: don't set it every time new
 
        vert.Pos = center + radius * v1;        // Set position for first vertex
 
        lstVertices[0] = vert;      // Set first vertex
 
        for(u32 x = 0; x < vertexcount; ++x)
        {
            // Position of start vertex = position of end vertex
            lstIndices[2*x] = x;
 
            const f32 angle_mul_xp1 = angle * (x + 1);
            vert.Pos = center + radius * ( cos(angle_mul_xp1) * v1 + sin(angle_mul_xp1) * v2 );
            lstIndices[2*x+1] = x+1;
            lstVertices[x+1] = vert;
        }
 
        // render
        driver->drawVertexPrimitiveList(&lstVertices[0], vertexcount+1, &lstIndices[0], vertexcount, video::EVT_STANDARD, scene::EPT_LINES, video::EIT_16BIT);
}
By the way: drawVertexPrimitiveList crashes on Burningsvideo and the color is ignored except on software renderer.
Rust fanboy
Abraxas)
Posts: 227
Joined: Sun Oct 18, 2009 7:24 am

Re: draw3DCircle

Post by Abraxas) »

chronologicaldot wrote:You're right about that. There's alot of code from Acki's circleclass.cpp. But this guy's code reduces it to a single function, which I imagine would be faster for the job.
The comments in the code... are from my original code. We worked it to reduce overhead as much as possible, but the actual idea behind the calculations was from the thread, and code, I started.

Not that I mind anyone using the code, seeing as I posted it on an online forum, It's still nice to give credit to the original thread and the people who discussed it.

Originally the code I made was used just to make a static circle, which could be probably better represented by a finite plane with a circular texture and transparencies and using the mech combiner.
rubenwardy
Posts: 91
Joined: Mon Mar 05, 2012 4:51 pm
Location: Bristol, UK
Contact:

Re: draw3DCircle

Post by rubenwardy »

What is a 3d circle? Is it not a sphere.
hendu
Posts: 2600
Joined: Sat Dec 18, 2010 12:53 pm

Re: draw3DCircle

Post by hendu »

Think "portal" or "hula hoop". It's a circle, but it may look like an ellipse or even a line depending on where you look at it from.
Abraxas)
Posts: 227
Joined: Sun Oct 18, 2009 7:24 am

Re: draw3DCircle

Post by Abraxas) »

2D circle in 3D space, drawing it can be tricky because you want a certain orientation, radius, and vertex count to make it actually look like a circle.
Neirdan
Posts: 39
Joined: Tue Aug 14, 2012 10:29 pm

Re: draw3DCircle

Post by Neirdan »

A simplier 2D version of it.
Why are you using EPT_LINES instead of EPT_LINE_LOOP?

Code: Select all

 
void draw3DCircle(irr::video::IVideoDriver* driver, irr::core::vector3df center, irr::f32 radius, irr::u32 nbpts, irr::video::SColor clr) {
    core::array<video::S3DVertex> Vertices;
    core::array<u16> Indices;
    video::S3DVertex tempVertex;
    irr::f32 angle=360/nbpts;
 
    Indices.clear();
    Vertices.clear();
 
    for(irr::u32 i=0; i<nbpts; ++i) {
        tempVertex.Pos.X=center.X+radius*cos(angle*0.0174527*i);
        tempVertex.Pos.Y=0;
        tempVertex.Pos.Z=center.Z+radius*sin(angle*0.0174527*i);
        tempVertex.Color = clr;
        Indices.push_back(Vertices.size());
        Vertices.push_back(tempVertex);
    }
 
    //Render
    driver->drawVertexPrimitiveList(&Vertices[0],Vertices.size(),&Indices[0],Indices.size(),video::EVT_STANDARD,scene::EPT_LINE_LOOP,video::EIT_16BIT);
}
 
Abraxas)
Posts: 227
Joined: Sun Oct 18, 2009 7:24 am

Re: draw3DCircle

Post by Abraxas) »

So why is your function called draw3DCircle? The whole point of the circle in 3D is to be the basis of all kinds of graphics effects, doing it in 2D is a waste of time IMO, might as well just use a billboard.
Neirdan
Posts: 39
Joined: Tue Aug 14, 2012 10:29 pm

Re: draw3DCircle

Post by Neirdan »

The circle actually is in 3d. I just don't use the Y axis.
Post Reply