I hope you can help me with a little problem...
I know how to draw a circle, that's not a problem - here is the code in c#
void DrawEllipse()
{
GL.Color3(0.5, 0.6, 0.2);
float x, y, z;
double t;
GL.Begin(BeginMode.Points);
for (t = 0; t <= 360; t += 0.25)
{
x = (float)(3*Math.Sin(t));
y = (float)(3*Math.Cos(t));
z = (float)0;
GL.Vertex3(x, y, z);
}
GL.End();
}
But there is a problem - when I Rotate 'Gl.Rotate(angle, axis)' and then redraw a circle - yeah, it's still circle in the 3D, but I want a circle in the screen - I mean static circle which is not rotating with 3D object in it... Is that possible? How to repair the code?
Are you trying to draw a 2D circle on top of a 3D scene to create a HUD or similar? If you are then you should research 2D OpenGL, glOrtho and using multiple viewports in a scene. There is a discussion around this here:
http://www.gamedev.net/topic/388298-opengl-hud/
Just draw it at a position before the camera!
Use pushMatrix() and popMatrix().
Or you can draw the other things between pushMatrix() and popMatrix(). Then draw the circle.
HUD (heads-up display): http://en.wikipedia.org/wiki/HUD_(video_gaming)
void setupScene ()
{
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
// set the perspective
glFrustum(...) // or glu's perspective
}
void loop ()
{
// main scene
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glViewport (...)
// push the camera position into GL_MODELVIEW
// (i.e. the inverse matrix of its object position)
// draw your normal 3D objects
// switch to 2D projection (for the HUD)
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
glOrtho(....)
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
// draw the objects onto the HUD
// switch back to 3d projection (i.e. restore GL_PROJECTION)
// glEnable (GL_DEPTH_TEST);
glMatrixMode(GL_PROJECTION);
glPopMatrix();
// glMatrixMode(GL_MODELVIEW);
// swap buffers
}
The commented code is optional, depending on what you're gonna do in the end. Take it as hints.
Related
I need to draw a triangle in 2d at the center of the screen and rotate it at the center only using a passive mouse actions any reference code?
void myDisplay(void)
{
glClear(GL_COLOR_BUFFER_BIT); // clear the screen
glBegin(GL_TRIANGLES);
glVertex2i(100, 50); // draw three points
glVertex2i(100, 130);
glVertex2i(150, 130);
glEnd();
glFlush();
This is the image and the triangle:
Assume we have a triangle with one vertex lying in the center of the screen (NDC=[0,0]), that is symmetric along the x-axis. The problem of letting the triangle point to the mouse is than the problem of finding the angle between the vector going from the center of the screen to the mouseposition and the x-axis ([1,0]). A solution for doing this can look like the following:
Vec2 mousePosition = queryMousePositionAsDoneInYourAPI();
float angle = acos(dot(normalize(mousePosition - [width/2, height/2]), [1,0]));
glLoadIdentity();
glRotatef(angle, 0,0,1);
glBegin();
drawTriangle
glEnd();
I need to draw a cube and project it with the default projection matrix. Also, I want to draw a hud controlling the orientation of the sphere. The hud is projected with another projection matrix.
render()
{
DrawGUI(); // project GUI with another projection matrix
glPushMatrix();
glutSolidCube(); // project the cube with the default projection matrix
glPopMatrix();
glutSwapBuffers();
}
reshape()
{
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(...);
...
}
DrawGUI()
{
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
gluOrtho2D(...); // project the GUI with this matrix
glMatrixMode(GL_MODELVEIW);
glPushMatrix();
glLoadIdentity();
glBegin();
//... drawing GUI
glEnd();
glPopMatrix();
glMatrixMode(GL_PROJECTION);
glPopMatrix();
glMatrixMode(GL_MODELVIEW);
}
#define BUFFER_LENGTH 64
void processSelection(int xPos, int yPos)
{
static GLuint selectBuff[BUFFER_LENGTH];
GLint hits, viewport[4];
glSelectBuffer(BUFFER_LENGTH, selectBuff);
glGetIntegerv(GL_VIEWPORT, viewport);
// Switch to projection and save the matrix
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glRenderMode(GL_SELECT);
glLoadIdentity();
gluPickMatrix(xPos, viewport[3] - yPos, 2,2, viewport);
glOrtho (-100, 100, -100, 100, -100, 100); // this line of code is the most
glMatrixMode(GL_MODELVIEW);
render();
hits = glRenderMode(GL_RENDER);
//...process hits
// Restore the projection matrix
glMatrixMode(GL_PROJECTION);
glPopMatrix();
glMatrixMode(GL_MODELVIEW);
}
The render part works well. Both the GUI and the cube are drawn without problem. However, the selection does not work as intended.
My question is: Since I project 3D models with different projection matrix, how should I deal with selection? I try to implement the typical selection buffer approach, but every time I click in the window, the selection buffer always contains the GUI even if I do not click on the GUI. Also, if I click on the cube, the selection buffer ends up with both the cube and the GUI.
If you use the selection buffer approach, you render with mixed projections as you do when doing the usual render. The only difference, is, that you apply that pick matrix as well. Also don't try to be too clever with the matrix pushing / poping. It rarely makes sense to use that in the projection matrix stack (hence it requires to have only 2 push levels, instead of the 32 for the modelview). Also don't use the reshape function to define the projection matrix.
DrawCube()
{
glMatrixMode(GL_MODELVEIW);
glLoadIdentity();
glutSolidCube();
}
DrawGUI()
{
glMatrixMode(GL_MODELVEIW);
glLoadIdentity();
glBegin();
//... drawing GUI
glEnd();
}
void render()
{
// base the projection on whats already in the projection
// matrix stack. For normal render this is identity, for
// selection it is a pick matrix.
glMatrixMode(GL_PROJECTION);
glPushMatrix();
gluOrtho2D(...); // project the GUI with this matrix
DrawGUI();
glMatrixMode(GL_PROJECTION);
glPopMatrix();
glMatrixMode(GL_PROJECTION);
glPushMatrix();
gluPerspective(...);
glMatrixMode(GL_PROJECTION);
glPopMatrix();
}
void display()
{
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
render();
glutSwapBuffers();
}
#define BUFFER_LENGTH 64
void select(int xPos, int yPos)
{
static GLuint selectBuff[BUFFER_LENGTH];
GLint hits, viewport[4];
glSelectBuffer(BUFFER_LENGTH, selectBuff);
glGetIntegerv(GL_VIEWPORT, viewport);
// Switch to projection and augment it with a picking matrix
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPickMatrix(xPos, viewport[3] - yPos, 2,2, viewport);
glRenderMode(GL_SELECT);
render();
hits = glRenderMode(GL_RENDER);
//...process hits
}
Note that OpenGL selection mode is usually not GPU accelerated and hence very slow. Also it's been deprecated and removed from modern OpenGL versions. It's highly recommended to use either index buffer selection (i.e. render each object with a dedicated index "color") or perform manual ray-intersection picking into the scene data.
I'm trying to draw a square on the screen but it clearly draws a rectangle.
This is my render code:
glClear(GL_COLOR_BUFFER_BIT);
glTranslatef(0,0,-0.1);
glBegin(GL_QUADS);
glVertex3f(0,0,0);
glVertex3f(1,0,0);
glVertex3f(1,1,0);
glVertex3f(0,1,0);
glEnd();
SDL_GL_SwapBuffers();
And OpenGL Init code:
glClearColor(0,0,0,0.6f);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(30,640.0/480.0,.3f,200.0);
glMatrixMode(GL_MODELVIEW);
Why is this happening?
I don't see anywhere in your code where you have set-up the glViewport. I will rather write something like this in your init method:
glViewport(0,0,640,480); // Reset The Current Viewport
glMatrixMode(GL_PROJECTION); // Select The Projection Matrix
glLoadIdentity(); // Reset The Projection Matrix
// Calculate The Aspect Ratio Of The Window
gluPerspective(30.0f,(GLfloat)640/(GLfloat)480,0.3f,200.0f);
glMatrixMode(GL_MODELVIEW); // Select The Modelview Matrix
glLoadIdentity();
also check the second Nehe tutorial it will help you to start with OpenGL for very basic stuff like drawing primitives such as triangle, square etc...
Try using gluOrtho2D to generate a correct orthogonal projection matrix, in your case gluOrtho2D(0,640,0,480), this is assuming you want a square in 2D and not 3D.
This will of course change your coordinate system from (0,1),(0,1) to (0,640),(0,480).
I have written a simple openGL program in C++. This program draws a sphere in 3D perspective projection and tries to draw a line joining the center of the sphere to the current cursor position in 2D orthographic projection. Now for drawing the line I can't figure out the coordinate of center of the sphere.
This is my code :
#ifdef __APPLE__
#include <GLUT/glut.h>
#else
#include <GL/glut.h>
#endif
void passive(int,int);
void reshape(int,int);
void init(void);
void display(void);
void camera(void);
int cursorX,cursorY,width,height;
int main (int argc,char **argv) {
glutInit (&argc,argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_DEPTH | GLUT_RGBA);
glutInitWindowSize(1364,689);
glutInitWindowPosition(0,0);
glutCreateWindow("Sample");
init();
glutDisplayFunc(display);
glutIdleFunc(display);
glutPassiveMotionFunc(passive);
glutReshapeFunc(reshape);
glutMainLoop();
return 0;
}
void display() {
glClearColor (0.0,0.0,0.0,1.0);
glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// Render 3D content
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(60,(GLfloat)width/(GLfloat)height,1.0,100.0); // create 3D perspective projection matrix
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
camera();
glTranslatef(-6,-2,0);
glColor3f(1,0,0);
glutSolidSphere(5,50,50);
glPopMatrix();
// Render 2D content
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(0, width,height, 0); // create 2D orthographic projection matrix
glMatrixMode(GL_MODELVIEW);
glColor3f(1,1,1);
glBegin(GL_LINES);
glVertex2f( centreX,centreY ); // coordinate of center of the sphere in orthographic projection
glVertex2f( cursorX,cursorY );
glEnd();
glutSwapBuffers();
}
void camera(void) {
glRotatef(0.0,1.0,0.0,0.0);
glRotatef(0.0,0.0,1.0,0.0);
glTranslated(0,0,-20);
}
void init(void) {
glEnable (GL_DEPTH_TEST);
glEnable (GL_BLEND);
glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_COLOR_MATERIAL);
}
void reshape(int w, int h) {
width=w; height=h;
}
void passive(int x1,int y1) {
cursorX=x1; cursorY=y1;
}
I can,t figure out the values for centreX and centreY. Anyway I can get the correct values to draw the line?
You may be interested in using something like gluProject to go from your object coordinates to the actual (projected) position on screen. Once you have the screen coordinates of the object, it's easy to draw a line from one point to another.
In this case, you'll want to project the centre point of the sphere. For more complex objects I've found that it makes sense to project all of the corners of the object's bounding box and then take the extents of the screenspace position of those corners.
You should get the modelview, viewport and projection matrices before you switch to your orthographic projection (2D mode).
Obviously, in order to go from a screen position (say, where you clicked in the window) to a world position, you'll want to use its companion function, gluUnProject.
Note that the coordinates that come out of gluProject do not necessarily correspond directly to the window position; you might have to flip the "Y" coordinate.
Take a look at this GDSE discussion for some other ideas about how to solve the problem.
Been integrating this camera tutorial http://www.swiftless.com/tutorials/opengl/camera2.html and having a bit of trouble centering the camera in the skybox.
Using this code below makes my camera inside the box:
void reshape(int w, int h)
{
glViewport(0, 0, (GLsizei) w, (GLsizei) h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
if (w <= h)
glOrtho(-1.0, 1.0, -1.0*(GLfloat)h/(GLfloat)w,
1.0*(GLfloat)h/(GLfloat)w, -10.0, 10.0);
else
glOrtho(-1.0*(GLfloat)w/(GLfloat)h,
1.0*(GLfloat)w/(GLfloat)h, -1.0, 1.0, -10.0, 10.0);
glMatrixMode(GL_MODELVIEW);
}
To draw the skybox, I followed this tutorial: http://sidvind.com/wiki/Skybox_tutorial
I've been trying to translate objects closer to the camera, but didn't work as I expected. Now I'm not sure what I need to do.
Appreciate any help.
First: Don'y apply the projection in the reshape handler. Otherwise simple things appear impossible (like doing a skybox). Second: For a skybox to work you must use the very same projection like for the rendering of the rest of the scene. What you should change is the translation of the modelview to 0, yet keeping the camera orientation.
You can do this by setting the last column of the modelview matrix to (0,0,0,1).
So this makes your rendering code like this:
void render_skybox()
{
push_modelview();
set_modelview_column(3, 0, 0, 1);
draw_skybox();
pop_modelview();
}
void render()
{
set_viewport();
set_projection();
apply_camera_transform();
render_skybox();
render_scene();
}