Beginner question: managing multiple objects


#1

Hello,

I want to draw several circles “along a circle”
(like the example https://www.libcinder.org/docs/guides/opengl/part1.html (chapter Transformations)) and several lines between them. It is supposed to be a very simple graph layout algorithm.

in the example they generate a fixed amount of circles and Batch->draw() them.
I can not really do that since circles will be added, removed and so on.
This is what i tried to do (I guess i am used to general c++ logic):

  • Ideally i would want a vector of my nodes.
  • generate a vector of circle objects (+ properties) and store those in a vector.
  • generate a vectorgl::BatchRef Batch of references to the circle objects in the vector.
  • just call draw(),update() whatever and iteratively call Batch[i]->draw() over the vector.

what works is directly storing refs to circles in a vector.
vectorgl::BatchRef Batch;
Batch.push_back(gl::Batch::create( circle, shader ));

what i can not get to work is referencing the circles in the circle-vector (last line):
vectorgeom::Circle() Nodes;
vectorgl::BatchRef Batch;
Nodes.push_back(circle);
Batch.push_back(gl::Batch::create( Nodes[i], shader ));

The approach is flawed but how do i do this elegantly?
I guess there is a propper way to solve such a situation.

Any help appreciated.

Thanks


#2

Hi,

you could use instanced rendering, which is a relatively advanced topic. You can find a similar sample here. It works like this:

  • Create a Batch from a geom::Circle. Define the circle with a position of (0,0) and a radius of 1.
  • Create a std::vector<ci::vec4>. The vec4 describes the origin (xyz) and radius (w) for each of the circles in your scene. Your std::vector should be large enough to hold the data for the maximum number of circles. We will call this the “instanced data”.
  • Add a Vbo to your VboMesh to hold the instanced data. Assign it to the geom::CUSTOM_0 attribute.
  • On update(), call mapReplace on the instanced data buffer and write the position and radius of each active circle to it. Skip circles that are off-screen or otherwise invisible. Also count the number of active circles. Don’t forget to unmap the buffer when you’re done.
  • On draw(), render all circles using a single draw call:
    mBatch->drawInstanced( numCircles ).
  • In your vertex shader, use the position to offset the vertices of the geom::Circle and use the radius to scale them.

-Paul

P.S.: I’m happy to create a sample application if you need more info.


#3

Hello.

Thanks for your answer.
That points me into the right direction.
Since i have to pause development until next weekend,
a sample app would be really nice.

thanks alot


#4

Ok, here you go :slight_smile:


#5

splendid. Thanks a ton.


#6

Wow, this really helps me get going. No way i would have gotten there alone.

Thanks again


#7

Hi everyone,

I have a quick question around this topic. I’ve been playing around with drawInstanced and a simple question appeared. Can I get pixel values after rendering it with shader?

Here is n example: Using round circles (bashes), the image is then drawn on these bashes using drawInstanced. Is there a clean and quick way I can get to these pixel rgbs?

Example here:

Thanks!