so how do I delete it afterwards?
3D Circle Drawer
well, because it is a scene node you do it this way:I also updated the post with the code and added an example for setting the color, too... 
Code: Select all
// creation
circleclass* circleNode = new circleclass(core::vector3df(50, 0, 100), 20, 40, core::vector3df(0,1,0), smgr->getRootSceneNode(), smgr);
circleNode->drop();
// deletion
circleNode->remove();while(!asleep) sheep++;
IrrExtensions:
http://abusoft.g0dsoft.com
try Stendhal a MORPG written in Java
IrrExtensions:

http://abusoft.g0dsoft.com
try Stendhal a MORPG written in Java
First of all:
Thank You Acki
Secondly, thanks
I appreciate the fact that you don't treat me as an inferior programmer, even though I posted in the project announcement I've only been using c++ for a month.... (was doing VB before).
I'm definitely going to learn as much as possible from this code.
But to be honest, the purpose of my code was to show how to generate an N-sided polygon using linear algebra. It wasnt to show off or anything, which I think a few people assumed.
I spent some time looking at different ways to do it (deconstructing the plane vectors for example) but the quickest, and also simplest way to do it was to use the original implicit definition of the plane and unit circle to find the vertices.
Acki, would you mind answering two questions?
How come your doing this? doesnt this mean you have 2 copies of every vertex besides the first and the last+1?
And I don't know much about dynamic creation, but when you make the pointer, why do you need the new operator? does that prevent a stack overflow?
Along with that question, if I drop() the node, does it still exist somewhere else in memory? would that be in the heap?
Also, using brace namespace method, is that just old C style or is there an after-compilation difference?
Thank You Acki
Secondly, thanks
I'm definitely going to learn as much as possible from this code.
But to be honest, the purpose of my code was to show how to generate an N-sided polygon using linear algebra. It wasnt to show off or anything, which I think a few people assumed.
I spent some time looking at different ways to do it (deconstructing the plane vectors for example) but the quickest, and also simplest way to do it was to use the original implicit definition of the plane and unit circle to find the vertices.
Acki, would you mind answering two questions?
Code: Select all
vert.Pos = center + radius * cos(2 * core::PI / vertexcount * x) * v1 + radius * sin(2 * core::PI / vertexcount * x) * v2;
vert.Color = video::SColor(255, 255,0,0);
lstIndices.push_back(lstVertices.size());
lstVertices.push_back(vert);
Box.addInternalPoint(vert.Pos);
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,0,0);
lstIndices.push_back(lstVertices.size());
lstVertices.push_back(vert);
Box.addInternalPoint(vert.Pos);
And I don't know much about dynamic creation, but when you make the pointer, why do you need the new operator? does that prevent a stack overflow?
Along with that question, if I drop() the node, does it still exist somewhere else in memory? would that be in the heap?
Also, using brace namespace method, is that just old C style or is there an after-compilation difference?
Actually, this is one case where the 'irrlicht rules' are wrong. The memory is allocated with new, but the scene node is inserted into the scene graph. Once the node is in the scene graph and the reference count is stabilized (the call to drop right after the node is associated with the scene), the node should be removed with a call to node->remove(), which will properly delete the node.randomMesh wrote:If you create object on the heap, you should delete it after use, or memory leaks will occur.Code: Select all
circleclass* c = new circleclass(core::vector3df(-50 + (2 * t), 0, 100), 20, 40, core::vector3df(0,1,0), smgr->getRootSceneNode(), smgr);
To avoid confusion, I typically do something like this.
Code: Select all
class MySceneNode : public ISceneNode
{
public:
static MySceneNode* addMySceneNode(ISceneNode* parent, ISceneManager* mgr, s32 id = -1);
private:
MySceneNode(ISceneNode* parent, ISceneManager* mgr, s32 id);
};
/* static */ MySceneNode*
MySceneNode::addMySceneNode(ISceneNode* parent, ISceneManager* mgr, s32 id)
{
if (!parent)
parent = smgr->getRootSceneNode();
MySceneNode* node = new MySceneNode(parent, smgr, id);
node->drop();
return node;
}
MySceneNode::MySceneNode(ISceneNode* parent, ISceneManager* mgr, s32 id)
: ISceneNode(parent, smgr, id)
{
}
Yes. The code could be simplified to store each vertex only once. This would require that you use the EPT_LINES primitive type and refer to each vertex twice using the index buffer. A better solution would be to use EPT_LINE_STRIP, which would cut the size of the index buffer in half.Abraxas) wrote:How come your doing this? doesnt this mean you have 2 copies of every vertex besides the first and the last+1?
The new operator is used to dynamically allocate an object. On many systems, the amount of memory that is available for the stack is restricted to some small size. Allocating large objects on the stack can cause the program to use up all of this available space, and the result is usually memory corruption due to stack overflow.Abraxas) wrote:I don't know much about dynamic creation, but when you make the pointer, why do you need the new operator? does that prevent a stack overflow
It depends. You should really read about the IReferenceCounted class in the documentation. The gist of it is, every object derived from that class has a reference count. When an object is created, it gets an initial reference count of zero. When something calls grab() on the object, the reference count is incremented, and when something calls drop(), the reference count is decremented. When the reference count goes to zero, the object deletes itself.Abraxas) wrote:if I drop() the node, does it still exist somewhere else in memory? would that be in the heap?
Namespaces put classes and functions into seperate groups to avoid problems when classes or functions with the same names need to be used. This construct does not exist in the C language, and the namespace of functions and methods are actually encoded into their names so that they can be found at link time.Abraxas) wrote:using brace namespace method, is that just old C style or is there an after-compilation difference
Travis
even vitek explained this already I will post my explanations too, they are mainly the same (what a wonder) but in other words... 

well, why should I offend you for this ???
you made a code and it worked, although your coding style is not the best...
the reason why I posted was that you first claimed the code to be efficient (IIRC) and I wanted to show you that it isn't...

and you see each number is 2 times there (also start and end)...
this was the easiest way to do this at that moment...
this has nothing to do with stack overflows and such, it's simply the way how it works...
you could get a stack overflow if you create it on the stack though...
when you create an object this way (new operator) Irrlicht increases the reference counter so you need to drop it again...
and no, it's not old C style, but an advanced C++ concept !!!
maybe this page can help you understand C++ better: http://www.cplusplus.com/doc/tutorial/
you're welcome !!!Abraxas) wrote:First of all:
Thank You Acki
Secondly, thanksI appreciate the fact that you don't treat me as an inferior programmer, even though I posted in the project announcement I've only been using c++ for a month.... (was doing VB before).
well, why should I offend you for this ???
you made a code and it worked, although your coding style is not the best...
the reason why I posted was that you first claimed the code to be efficient (IIRC) and I wanted to show you that it isn't...
that's the way it should be !!!Abraxas) wrote:I'm definitely going to learn as much as possible from this code.
well, it's simply because each line segment needs 2 points (start and end) from 0-1, 1-2, 2-3 and so on...Abraxas) wrote:How come your doing this? doesnt this mean you have 2 copies of every vertex besides the first and the last+1?
and you see each number is 2 times there (also start and end)...
this was the easiest way to do this at that moment...
because the new operator creates the object on the heap and returns a pointer...Abraxas) wrote:And I don't know much about dynamic creation, but when you make the pointer, why do you need the new operator? does that prevent a stack overflow?
this has nothing to do with stack overflows and such, it's simply the way how it works...
you could get a stack overflow if you create it on the stack though...
yes, the drop is how Irrlicht handles objects to prevent them from deleting when still in use (called ReferenceCount)...Abraxas) wrote:Along with that question, if I drop() the node, does it still exist somewhere else in memory? would that be in the heap?
when you create an object this way (new operator) Irrlicht increases the reference counter so you need to drop it again...
I did this because in Irrlicht the scene nodes are in this namespace(s)...Abraxas) wrote:Also, using brace namespace method, is that just old C style or is there an after-compilation difference?
and no, it's not old C style, but an advanced C++ concept !!!
maybe this page can help you understand C++ better: http://www.cplusplus.com/doc/tutorial/
while(!asleep) sheep++;
IrrExtensions:
http://abusoft.g0dsoft.com
try Stendhal a MORPG written in Java
IrrExtensions:

http://abusoft.g0dsoft.com
try Stendhal a MORPG written in Java
This is going back a bit in this thread but I just want to make a point about vertexPrimitiveList.
It uses drawline anyway. How else?
It's not any more efficient than calling drawLine. Why would it be?Acki wrote:I think it would be much more efficient to use a VertexPrimitiveList...
It does the same number of calls to draw either way!vitek wrote:Unless you are going to use primitive lists, the very efficient comment in the title should be removed entirely. A single draw...() call is much more efficient than 10000 of them.
It uses drawline anyway. How else?
Code: Select all
for (u32 i=0; i < primitiveCount-1; ++i)
draw3DLine(((S3DVertex*)vertices)[indexList[i]].Pos,
((S3DVertex*)vertices)[indexList[i+1]].Pos,
((S3DVertex*)vertices)[indexList[i]].Color);I can hear birds chirping

I live in the Eye of Insanity.
I live in the Eye of Insanity.
It is. A call to draw3DLine() does essentially the same thing as a single call to drawVertexPrimitiveList() with a single line primitive. To draw a line with 10000 segments, you have to make 10000 function calls, each of which call through to the driver, which is very expensive. A single call to drawVertexPrimitiveList() can be used to draw 10000 line segments and avoid all of this overhead.Ulf wrote:This is going back a bit in this thread but I just want to make a point about vertexPrimitiveList.
It's not any more efficient than calling drawLine. Why would it be?Acki wrote:I think it would be much more efficient to use a VertexPrimitiveList...
No, it doesn't.Ulf wrote:It does the same number of calls to draw either way!vitek wrote:Unless you are going to use primitive lists, the very efficient comment in the title should be removed entirely. A single draw...() call is much more efficient than 10000 of them.
As mentioned above, draw3DLine() draws just one line primitive per function call. The drawVertexPrimitiveList() can draw many thousands of primitives in a single call. This could be done even more efficiently by using hardware buffers, but Irrlicht only supports drawing triangles using them.Ulf wrote:It uses drawline anyway. How else?
Travis
@vitek
Ok. Using openGL as an example, are you saying that draw3DLine must call glBegin and glEnd every time, but drawVertexPrimitiveList does not? Does drawVertexPrimitiveList only call them once and draw all lines in a loop? I noticed that after looking at it carefully.
**EDIT**
But with all the extra work drawVertexPrimitiveList does, is it necessarily faster? Do the begin and end take up so much time?
**EDIT**
Also, each video driver does it differently.
The NULL driver does nothing.
The software driver does it as follows (as shown before)
So in the software drivers case, it's exactly the same. It draws 3D lines over and over in a loop. That is the same as if you do that yourself.
Software Driver2 after setting up hundreds of parameters, ends up calling the following:
Is drawTriangle faster than calling drawLine 3 times? Doubt it. Must be virtually the same.
The openGL and directX drivers do it bit differently. They have many more parameters and I don't understand it fully yet.
But don't they basically do the same thing? They set up an array, then they loop through it calling drawline between every 2 vertices.
I don't mean they call the Irrlicht drawline, they call their own drawline function.
Where are the benefits in speed obtained?
Ok. Using openGL as an example, are you saying that draw3DLine must call glBegin and glEnd every time, but drawVertexPrimitiveList does not? Does drawVertexPrimitiveList only call them once and draw all lines in a loop? I noticed that after looking at it carefully.
**EDIT**
But with all the extra work drawVertexPrimitiveList does, is it necessarily faster? Do the begin and end take up so much time?
**EDIT**
Also, each video driver does it differently.
The NULL driver does nothing.
The software driver does it as follows (as shown before)
Code: Select all
for (u32 i=0; i < primitiveCount-1; ++i)
draw3DLine(((S3DVertex*)vertices)[indexList[i]].Pos,
((S3DVertex*)vertices)[indexList[i+1]].Pos,
((S3DVertex*)vertices)[indexList[i]].Color);Software Driver2 after setting up hundreds of parameters, ends up calling the following:
Code: Select all
// re-tesselate ( triangle-fan, 0-1-2,0-2-3.. )
for ( g = 0; g <= vOut - 6; g += 2 )
{
// rasterize
CurrentShader->drawTriangle ( CurrentOut.data + 0 + 1,
CurrentOut.data + g + 3,
CurrentOut.data + g + 5);
}The openGL and directX drivers do it bit differently. They have many more parameters and I don't understand it fully yet.
But don't they basically do the same thing? They set up an array, then they loop through it calling drawline between every 2 vertices.
I don't mean they call the Irrlicht drawline, they call their own drawline function.
Where are the benefits in speed obtained?
Last edited by Ulf on Wed Nov 25, 2009 8:26 am, edited 1 time in total.
I can hear birds chirping

I live in the Eye of Insanity.
I live in the Eye of Insanity.
Ok I understand.hybrid wrote:Yes, glBegin, glEnd, and almost all other gl* methods are quite costly. As vitek said, these are driver calls, which often also includes major state changes in the OpenGL state machine. So unless you only draw one or two lines each frame, a vertex primitive list will be significantly faster.
But, as I showed in my edits to my post, am I correct in saying that some implementations of drawVertexPrimitiveList do nothing more than call drawLine in a loop anyway?
So really only the directX and openGL versions are faster?
Or is the software driver 2 faster as well? It just seems to draw triangles instead of lines.. couldn't be much different.
What do you say hybrid?
I think I asked this before... but what is the SDL version?
Is that for Windows to connect with SDL library?
And where is the Mac version? Is that in a separate distribution?
I can hear birds chirping

I live in the Eye of Insanity.
I live in the Eye of Insanity.
In the worst case, the drawVertexPrimitiveList() calls draw3DLine(), making it just as slow, possibly slightly slower due to function call overhead. In the best case, thousands of primitives can be rendered with a single call. In my testing with the OpenGL driver, I get 1000fps using drawVertexPrimitiveList() and 125 with draw3DLine() when rendering 10000 lines.Ulf wrote:But, as I showed in my edits to my post, am I correct in saying that some implementations of drawVertexPrimitiveList do nothing more than call drawLine in a loop anyway?
Unfortunately You can't do an apples-to-apples comparison of rendering lines with the burning renderer because it crashes when trying to render lines. It is known to only support rendering triangles. I did a quick test rendering 10000 triangles [drawVertexPrimitiveList(..., EPT_TRIANGLES) vs drawTriangle()] and the results are as follows.
Code: Select all
drawVertexPrimitiveList() draw3DTriangle()
opengl 837 fps 116 fps
burning 142 fps 75 fps
software 213 fps 13 fps
Yes, the accelerated drivers (the ones that are complete and are used most frequently) have the most to gain from using drawVertexPrimitiveList(). As mentioned, the burning driver doesn't work with non-triangle primitive types, and I consider that to be a bug. I also noticed problems when rendering triangles with the software driver and draw3DTriangle().Ulf wrote:So really only the directX and openGL versions are faster? Or is the software driver 2 faster as well? It just seems to draw triangles instead of lines.. couldn't be much different.
Travis
@vitek @hybrid
Thanks for the insight. I do look into the Irrlicht code to work it out but it's nice to get pointers as it is very time consuming to trace everything.
I'll take that on board. I know I'm already doing the wrong thing by using the 2D drawing, as everyone suggested to use hardware acceleration and use orthogonal projection.
But I'll learn won't I?
Anyway, I learned that, in my 2D game engine I should separate the draw functionality from the objects if I want to be able to render many objects at once.
The only problem with that is, each object may be from a different source texture. So I won't really be able to draw a batch of images with draw2DImageBatch because it only takes a single texture, but many frames.
So if the objects are from the same texture it can be done, but not otherwise.
My objects that don't have textures, instead having color and being filled can be drawn in a batch using drawVertexPrimitiveList.
Eventually I will probably change it to orthogonal 3D, but I'd like to experiment with 2D first.
Thanks for the insight. I do look into the Irrlicht code to work it out but it's nice to get pointers as it is very time consuming to trace everything.
I'll take that on board. I know I'm already doing the wrong thing by using the 2D drawing, as everyone suggested to use hardware acceleration and use orthogonal projection.
But I'll learn won't I?
Anyway, I learned that, in my 2D game engine I should separate the draw functionality from the objects if I want to be able to render many objects at once.
The only problem with that is, each object may be from a different source texture. So I won't really be able to draw a batch of images with draw2DImageBatch because it only takes a single texture, but many frames.
So if the objects are from the same texture it can be done, but not otherwise.
My objects that don't have textures, instead having color and being filled can be drawn in a batch using drawVertexPrimitiveList.
Eventually I will probably change it to orthogonal 3D, but I'd like to experiment with 2D first.
I can hear birds chirping

I live in the Eye of Insanity.
I live in the Eye of Insanity.
I finally had some time to code my drawGeodesicLine function. It draws the geodesic line (shortest path) between 2 points on a sphere (with given radius and origin (0,0,0)). The math is correct and everything works fine but I would like to put it in a SceneNode just like Acki did with the circleDrawer. Unfortunately, I didn't succeed in doing so; guess that's because I don't understand everything in his code 
So could maybe someone help me with this? (winking at Acki
)
Here's how it works so far...
Hint:
It does not work if p1 and p2 are pole and exact anti-pole, e.g. p1(50,0,0) p2(-50,0,0), since there is no distinct solution (each path has the same length). In that case you have to distort one point a little bit: p1(50, 0.1f, 0.1f). Also, the closer you get to the pole issue the more lines you need to draw (higher value for k) in order to get a perfect circlular path. That is because the algorithm uses a linear dispersion for the distances between the points and I wouldn't bother to make it a spherical dispersion like -e^-(x^2) in order to get equally partitioned segments on the sphere.
So could maybe someone help me with this? (winking at Acki
Here's how it works so far...
Hint:
It does not work if p1 and p2 are pole and exact anti-pole, e.g. p1(50,0,0) p2(-50,0,0), since there is no distinct solution (each path has the same length). In that case you have to distort one point a little bit: p1(50, 0.1f, 0.1f). Also, the closer you get to the pole issue the more lines you need to draw (higher value for k) in order to get a perfect circlular path. That is because the algorithm uses a linear dispersion for the distances between the points and I wouldn't bother to make it a spherical dispersion like -e^-(x^2) in order to get equally partitioned segments on the sphere.
Code: Select all
// FUNCTION
void geo(irr::core::array<S3DVertex> &arrayVertices,
irr::core::array<u16> &arrayIndices,
irr::core::vector3df p1, // starting point
irr::core::vector3df p2, // endpoint
irr::f32 r, // radius
irr::f32 k) // precision (how many lines)
{
// put p1 as first vertex
arrayIndices.push_back(arrayVertices.size());
arrayVertices.push_back( S3DVertex(p1, vector3df(0,0,0), SColor(255, 255,0,0), vector2df(0,0) ));
// calc vertices
for(f32 i = 1; i < k; i++)
{
f32 t;
// nevermind whats going on here :)
// but I can explain the maths if someone's interested
t = squareroot(
( pow(r,2) * pow(k,2) ) /
(
( pow((k-i),2) * pow(p1.X,2) + 2 * (k-i) * p1.X * i * p2.X + pow(i,2) * pow(p2.X,2) ) +
( pow((k-i),2) * pow(p1.Y,2) + 2 * (k-i) * p1.Y * i * p2.Y + pow(i,2) * pow(p2.Y,2) ) +
( pow((k-i),2) * pow(p1.Z,2) + 2 * (k-i) * p1.Z * i * p2.Z + pow(i,2) * pow(p2.Z,2) )
)
);
// the next vertex
S3DVertex newVertex;
// set postion of next vertex
newVertex.Pos = t * (
( ((k-i) / k) * p1 ) +
( (i/k) * p2 )
);
// set color
newVertex.Color = SColor(255, 255,0,0);
// put next vertex in array
arrayIndices.push_back(arrayVertices.size());
arrayVertices.push_back(newVertex);
}
// put p2 as last vertex
arrayIndices.push_back(arrayVertices.size());
arrayVertices.push_back( S3DVertex(p2, vector3df(0,0,0), SColor(255, 255,0,0), vector2df(0,0) ));
}Code: Select all
USAGE
// my arrays
irr::core::array<S3DVertex> arrayVertices;
irr::core::array<u16> arrayIndices;
// test points
vector3df p1 = vector3df(52,0,0);
vector3df p2 = vector3df(0,52,0);
// function call
// radius = 52
// precision = 25
geodesicLine(arrayVertices, arrayIndices, p1, p2, 52, 25);
Code: Select all
// RENDER LOOP
SMaterial mt;
mt.AntiAliasing = EAAM_QUALITY;
mt.AmbientColor = mt.DiffuseColor = mt.EmissiveColor = SColor(255, 255, 0, 0);
driver->setMaterial(mt);
driver->setTransform(video::ETS_WORLD, core::matrix4());
// primcount is "arrayIndices.size() - 1" since I'm using LINE_STRIP
driver->drawVertexPrimitiveList(&arrayVertices[0], arrayVertices.size(), &arrayIndices[0], (arrayIndices.size() - 1), EVT_STANDARD, EPT_LINE_STRIP, EIT_16BIT);