Drawing pixels from buffer and position (glDrawPixels) - c

Basically I am doing some tests to simulate various window inside a scene. Everything works fine until I try to position better the window that I am drawing inside the scene.
The important code is here:
// camFront = glReadPixels ...
glMatrixMode( GL_MODELVIEW );
glLoadIdentity();
//glRasterPos3f(1.0, 0.5, 0.0); // <-- commented out
// Zooming window
glPixelZoom(0.5, 0.5);
glDrawPixels(500, 250, GL_RGB, GL_UNSIGNED_BYTE, camFront); //> camFront is the buffer of the window
glutSwapBuffers();
Basically when glRasterPos3f is commented out I got my nice window drawn inside my scene:
Now If i try to position that window with glRasterPos3f, the window disappears completly from the scene... Any clues?

One possible The cause of this problem is an invalid rasterpos. The raster pos is set after transforming x,y and z just like any other pixel. This includes the clipping stage.
The easy test is to see if when a bright point (or something more visible) is drawn at your x,y and z it appears on the screen.
Where is (1.0, 0.5, 0.0) in your screen? Is it visible?
The coordinate has to be a visible point that is projected onto screen, becoming a 2d coordinate. Try putting the code before the modelview part, maybe then the coordinate will be where you expected.
Because you reset the matrix with glLoadIdentity, the point (1.0, 0.5, 0.0) will be at the right edge of screen - possibly clipped as too far right or too close to camera.
GLboolean valid;
glGetBooleanv(GL_CURRENT_RASTER_POSITION_VALID, &valid);
if(valid == GL_FALSE)
printf("Error");
(The second test is better than drawing something, but won't help tell you where it is being drawn if it is not invalid)

Related

Make objects move in Cairo

I need to use Cairo to make geometric formulas move through the screen.
How does one "move" objects (like circles) in Cairo? I did try cairo_translate(cr, x, y) function but it seems to change the referential for all the objects and I don't know how to produce de "movement". In other frameworks I would increment the x value and change the speed with an appropriate clock() function to control FPS's, then I would paint the drawing area background and draw the object with new coordinates.
But I don't know how to produce this with Cairo and all documentation I can find does not mention how this is done.
This is the code I have:
genRandVector(numOfBalls);
/* creates big ball */
cairo_set_line_width(cr, 5);
cairo_set_source_rgb(cr, 0, 0, 0);
cairo_arc(cr, balls_MAP[0].x, balls_MAP[0].y, CONF.big_rad, 0, 2 * M_PI);
cairo_stroke_preserve(cr);
cairo_set_source_rgb(cr, 0.9, 0.9, 0.9);
cairo_fill(cr);
/* creates other balls */
int i;
cairo_close_path(cr);
cairo_set_source_rgb(cr, 0, 0, 0);
for(i = 1; i < numOfBalls; i++) {
cairo_arc(cr, balls_MAP[i].x, balls_MAP[i].y, CONF.small_rad, 0, 2 * M_PI);
cairo_stroke_preserve(cr);
cairo_fill(cr);
cairo_close_path(cr);
}
And my circles are still. I would like to make all of them move randomly. I just don't know how to make them "move".
cairo doesn't animate things, and it doesn't have the concept of objects. Using cairo is more like using a paintbrush on a canvas: once you draw something onto the canvas, it's stuck there and you can't refer to it to change its properties at all, let alone move it around.
Therefore, to animate things drawn with cairo, you have to wipe the part of the canvas that's being animated and draw it again. How to do that depends on what toolkit you are using to display your graphics.
From the tags, I assume you are using GTK+. There are several methods of GtkWidget, such as gtk_widget_queue_draw() and gtk_widget_queue_draw_area(), that will schedule a redraw of your widget. Call this in a g_timeout_add() handler to schedule your animation. You'll get a drawing signal (the same one you're using already) for the portion of the GtkWidget that you chose to redraw (which you can get from within the draw handler with cairo_clip_extents()). Since the relevant portion of the canvas will be blanked already when you enter the draw handler, you can just start drawing your next frame.
You may wish to consider using a dedicated animation framework instead if your needs are sufficiently complicated. Clutter is one specifically designed to be used with GTK+, but there are also others.

Cairo multiple shapes in drawing area

I'm trying to understand Cairo framework; but I don't know how to put more than one shape into the drawing area. All codes/tutorials I've seen are either too advanced or do not relate to this issue.
This is my code to draw a circle (I'm using C and gtk+3.0):
void draw(GtkWidget *this, cairo_t *cr, gpointer data) {
cairo_set_line_width(cr, 5);
cairo_set_source_rgb(cr, 0, 0, 0);
cairo_translate(cr, prog.width/2, prog.height/2);
cairo_arc(cr, 0, 0, 50, 0, 2 * M_PI);
cairo_stroke_preserve(cr);
cairo_set_source_rgb(cr, 0.9, 0.9, 0.9);
cairo_fill(cr);
}
I understand all but one thing: cairo_t *cr. From what I've been searching cr is a Context, but didn't quite grasped an intuitive idea of what it is about (maybe my question lies on this understanding?).
So, if I needed more circles near this one, how could I create them?
My try was using cairo_move_to(cr, x, y) and draw another shape but obviously it didn't work.
Thanks!
Yes, cairo_t is the type of a cairo context.
To draw on cairo, you set drawing parameters, a source which defines the color or image that gets drawn, and a path that specifies the shape that gets drawn, and then you call cairo_stroke() or cairo_fill() to do the actual drawing. After calling those, the path is reset (unless you use the _preserve versions of the functions), but everything else stays the same.
So to draw again, you just need to add more setup and drawing function calls after the first one.
cairo_move_to() does not actually move anything. What cairo_move_to() does is change the position of the "current point" of the path. Path components you add later, such as cairo_line_to(), will start at the current point and then set the current point to their end point.
In your case, you can draw multiple circles by adding a cairo_move_to() after the last line of your draw handler and then repeating the steps you used to draw the first circle.
cairo_arc() is different because you specify the center of the arc as the second and third arguments. To draw an arc somewhere else, you need to change those two arguments. (The current point does play a role in cairo_arc(); you'll need to see the documentation for information.)
The cairo documentation is the best place to start learning about cairo; it has lots of tutorials and samples.

showing verticies in openGL

I have a program that renders a 3D wire mesh model using this code fragment in a loop.
glBegin(GL_LINES);
glColor3f(.0f, 0.0f, 0.0f);
glVertex3d(xs,ys,zs);
glVertex3d(xe,ye,ze);
glEnd();
I need to add functionality so that the vertices where the line starts and ends can be rendered if the user desires, probably using a small shaded circle. The circle should be of a constant screen size, probably 4-6 pixels across and rendered at a size that is independent of where the camera is, or how close it is.
Can anyone suggest how to render such a vertex?
You can use GL_POINTS in your glBegin together with glPointSize function.

Using GLKBaseEffect is it possible to colorize a texture

I have a sheet of black shapes surrounded by transparency. I have successfully loaded this texture with GLKit and I can draw the shapes using GLKBaseEffect into rectangles. Is there a way to change the color of the black (ie non-transparent) pixels, so I can draw yellow shapes or blue shapes etc? Or do I need a custom shader to do this?
It seems like you'll need a custom shader (which I highly recommend working with) as you need to check individual texel color values, but here are some suggestions to try first:
You can pass color as per-vertex data in a vertex attribute array pointing to GLKVertexAttribColor. This will allow you to individually set the color of each vertex (and ultimately, faces) but it will be difficult to see where they line up against your texture.
You can try enabling the following property on your effect:
effect.colorMaterialEnabled = YES;
But, for both cases, if your texels are completely black then I don't think any changes in color will show.
I think a custom shader is definitely the way to go, as you'll need to do something like this:
highp vec4 finalColor;
highp vec4 textureColor = texture2D(uTexture, vTexel);
highp vec4 surfaceColor = uColor;
// If texel is non-transparent (check alpha channel)
if(textureColor.a > 0.001)
finalColor = surfaceColor;
else
finalColor = vec4(0.0, 0.0, 0.0, 0.0);
gl_FragColor = finalColor;
Where anything prefixed with u is a uniform variable passed into the shader.
To get fully colorized textures, use:
self.effect.texture2d0.envMode = GLKTextureEnvModeModulate;
Which tells OpenGL to take whatever color is in your texture and multiply it by whatever color the underlying geometry is. You can then use vertex coloring to get neat fades and whatnot.
NOTE: You'll want to change your texture from black to white (1, 1, 1, 1), so multiplication works correctly.
NOTE: Here are some other settings that you should already have in place:
self.effect.texture2d0.enabled = GL_TRUE;
self.effect.texture2d0.target = GLKTextureTarget2D;
self.effect.texture2d0.name = self.texture.name;
self.effect.colorMaterialEnabled = GL_TRUE;
NOTE: You can experiment with GLKTextureEnvModeDecal, too, which blends your texture on top of colored geometry (as when applying a decal), so the transparent parts of the texture show the geometry underneath.

Simplest way to set up a 3D OpenGL perspective projection

There have been many tutorials where each suggests using gluPerspective or glFrustum with a combination of other things, yet I've had difficulties setting up the right matrix. What code do I need to set up a 45˚ perspective view looking down the +z axis?
So far I have:
glShadeModel(GL_SMOOTH);
glClearColor(0,0,0,0);
glClearDepth(1);
glDepthFunc(GL_LEQUAL);
glViewport(0,0,width,height);
glEnable(GL_DEPTH_TEST);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45,1,0.1,100);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
But that doesn't seem to work. All I get is a black screen when I attempt to draw things.
EDIT: Here's the minimal drawing code:
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
glColor3ub(255,255,255);
glBegin(GL_TRIANGLE_STRIP);
glVertex3f(20,20,20);
glVertex3f(20,30,20);
glVertex3f(30,20,20);
glVertex3f(30,30,20);
glEnd();
Things such as points on (1,1,1) and (2,50,23). They do not appear.
Well there's your problem. The default OpenGL camera has the +Z axis pointing towards the camera. And since the camera is at Z=0, any position who's Z position is >0 is behind the camera.
Move your points in front of the camera. They need to at least have a -Z position.
EDIT: Here's the minimal drawing code:
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
glColor3ub(255,255,255);
glBegin(GL_TRIANGLE_STRIP);
glVertex3f(20,20,20);
glVertex3f(20,30,20);
glVertex3f(30,20,20);
glVertex3f(30,30,20);
glEnd();
Your vertex coordinates lie way outside the viewing volume. First, OpenGL by default "looks" down the negative Z axis, so your Z coordinates must be -100 < z < -0.1 for your choosen near and far clip plane.
But even if you flipped the sign on the Z coordinate, your vertices still would lie outside the 45° FOV. (20, 0, 20) is 45° from the viewing axis, and (30, 0, 20) even farther. Try centering your vertex coodinates around (0,0,-5) like (+/-1, +/-1, -5)

Resources