void drawTire(void)
{
GLint num_of_tri = 32;
GLfloat vertex[3];
const GLfloat delta_angle = 2.0*PI/float(num_of_tri);
//Draw Front tire
glBegin(GL_TRIANGLE_FAN);
glColor3f(0.5, 0.5, 0.5);
vertex[0] = vertex[1] = vertex[2] = 0.0;
glVertex3fv(vertex);
for(int i = 0; i < num_of_tri ; i++)
{
vertex[0] = cos(delta_angle*i) * wheelRadius; //wheel Radius is 1.0
vertex[1] = sin(delta_angle*i) * wheelRadius;
vertex[2] = 0.0;
glVertex3fv(vertex);
}
vertex[0] = 1.0 * wheelRadius;
vertex[1] = 0.0 * wheelRadius;
vertex[2] = 0.0;
glVertex3fv(vertex);
glEnd();
//Draw Back Tire
const GLfloat depth = -wheelRadius/1.5;
glBegin(GL_TRIANGLE_FAN);
glColor3f(1.0, 0.0, 0.0);
vertex[0] = vertex[1] = 0.0;
vertex[2] = depth;
glVertex3fv(vertex);
for(int i = 0; i < num_of_tri ; i++)
{
vertex[0] = cos(delta_angle*i) * wheelRadius;
vertex[1] = sin(delta_angle*i) * wheelRadius;
vertex[2] = depth;
glVertex3fv(vertex);
}
vertex[0] = 1.0 * wheelRadius;
vertex[1] = 0.0 * wheelRadius;
vertex[2] = depth;
glVertex3fv(vertex);
glEnd();
//Connect Front&Back
glBegin(GL_QUADS);
glColor3f(0.0, 0.0, 0.0);
for(int i = 0; i < num_of_tri; i++)
{
vertex[0] = cos(delta_angle*i) * wheelRadius;
vertex[1] = sin(delta_angle*i) * wheelRadius;
vertex[2] = 0;
glVertex3fv(vertex);
vertex[0] = cos(delta_angle*i) * wheelRadius;
vertex[1] = sin(delta_angle*i) * wheelRadius;
vertex[2] = depth;
glVertex3fv(vertex);
vertex[0] = cos(delta_angle*((i + 1)%num_of_tri)) * wheelRadius;
vertex[1] = sin(delta_angle*((i + 1)%num_of_tri)) * wheelRadius;
vertex[2] = depth;
glVertex3fv(vertex);
vertex[0] = cos(delta_angle*((i + 1)%num_of_tri)) * wheelRadius;
vertex[1] = sin(delta_angle*((i + 1)%num_of_tri)) * wheelRadius;
vertex[2] = 0;
glVertex3fv(vertex);
}
glEnd();
glFlush();
}
I'm using the above code to draw a (kind of) 3D car wheel. This code appears to work.
This is my init function:
void init(void)
{
glClearColor (1.0, 1.0, 1.0, 0.0);
glMatrixMode (GL_PROJECTION);
glLoadIdentity ();
gluPerspective(45.0f, (GLfloat)1366/(GLfloat)768, 0.1f, 100.0f);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(0.0, 0.0, 5.0, 0, 0, 0, 0, 1, 0);
}
This is my display function:
void display(void)
{
glClear(GL_COLOR_BUFFER_BIT);
drawTire();
glFlush();
}
The result is messed up car wheel as can be seen here: http://postimg.org/image/fuf9o75ub/
The front of the tire (the side that the camera should be looking at) is gray. The camera somehow looks at the back of the tire, which is red.
Also, the tire side (the one the that touches the ground. I have no idea how to name it) is also shown, which is weird (the black color).
Why does gluPerspective messes up 3D object, and how can one fix this? (I have tried changing the fov... result were almost the same)
Right now, you aren't using depth testing. This means that the last primitive rendered is the one "on top", since without depth testing, OpenGL has no way of knowing the 'depth' of a pixel after it has been rendered.
To solve this problem, OpenGL uses a depth buffer, which is a hidden screen-sized buffer that stores how far away each pixel is from the camera. With depth testing enabled, when OpenGL renders a fragment, it first checks the depth of the fragment and compares it to the value in the depth buffer. If the fragment's depth value is smaller than the stored value (note 1), then OpenGL concludes that the fragment is in front of an already rendered object and writes the fragment. Otherwise, its behind an object and ignores the fragment.
To use depth testing, you first need to make sure you've allocated a depth buffer when you created your context. This depends on what windowing library you are using, but usually they give you a depth buffer by default.
You then need call glEnable(GL_DEPTH_TEST) to begin using depth testing.
Additionally, you need to clear the depth values in the depth buffer when you re-render your scene. Change glClear(GL_COLOR_BUFFER_BIT) to glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT).
And that's all you need to use depth testing.
(note 1): More specfically, it uses whatever function was set glDepthFunc, though 99% of the time this is GL_LESS or GL_LEQUAL.
Related
I am trying to draw an arrow using the style below but this arrow should be also rotated according to a condition (need to pass the degree for each condition). I can draw the rectangle and a triangle but I cannot draw the triangle as an arrowhead. Also, how can I include the rotation degree into the code? Is there any easier way to draw an arrow and rotate it?
int triangleRect=4, triangleTri=3, lineWidth=3;
double twicePi = 2.0f * M_PI, angle_offsetR =1.5* M_PI/2, radius = 0.05,
xR=m_start.x(), y=m_start.y(), xT=m_start.x()+ m_rect_width;
glColor3f(0,1,0);
glLineWidth(lineWidth);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_MULTISAMPLE);
glEnable(GL_POINT_SMOOTH);
glEnable(GL_LINE_SMOOTH);
glBegin(GL_TRIANGLE_FAN);
//RECTANGLE
for(int i = 0; i <= triangleRect; i++) {
glVertex2f((xR + (radius * cos(i * twicePi / triangleRect + angle_offsetR)))* m_parent_width_function(),
(y + (radius * sin(i * twicePi / triangleRect + angle_offsetR)))* m_parent_height_function());
}
// TRIANGLE
for(int i = 0; i <= triangleTri; i++) {
glVertex2f((xT + (radius * cos(i * twicePi / triangleTri + angle_offsetR)))* m_parent_width_function(),
(y + (radius * sin(i * twicePi / triangleTri + angle_offsetR)))* m_parent_height_function());
}
glEnd();
You accidentally add angle_offsetR to the angle for the triangle vectors. Furthermore you've to restart a GL_TRIANGLE_FAN primitiv when you draw an new shape (see Triangle primitives).
If you want to rotate the model, then set the add a rotation around the z axis to the model view matrix by glRotatef.
Do not translate and scale the vertex coordinates. Use glScale and glTranslate. The matrix transformations are not commutative, the order matters:
float angle_of_roation = 30.0; // 30°
glPushMatrix();
// scale
glScalef( m_parent_width_function(), m_parent_height_function(), 1.0f);
// move triangle and rectangle to the position in the world
glTranslatef(xR, y, 0.0f);
// roatate triangle and rectangle
glRotatef(angle_of_roation, 0, 0, 1);
//RECTANGLE
glBegin(GL_TRIANGLE_FAN);
for(int i = 0; i <= triangleRect; i++) {
float angle = i * twicePi / triangleRect + angle_offsetR;
glVertex2f(radius * cos(angle), radius * sin(angle));
}
glEnd();
glPushMatrix();
// translate triangle relative to rectangle
glTranslatef(xT-xR, 0.0f, 0.0f);
// TRIANGLE
glBegin(GL_TRIANGLE_FAN);
for(int i = 0; i <= triangleTri; i++) {
float angle = i * twicePi / triangleTri;
glVertex2f(radius * cos(angle), radius * sin(angle));
}
glEnd();
glPopMatrix();
glPopMatrix();
I'm learning OpenGL ES to render for native android development. I'm able to get a triangle to draw. But I cannot get more than one triangle to draw. I just want to draw a rectangle, but if I tell the glVertexPointer function more than 3 vertices then it does not draw. I tried using GL_TRIANGLES and GL_TRIANGLE_STRIP.
What am I doing wrong?
struct Quad
{
GLfloat Vertices[18];
const GLbyte nNumVerts;
Quad(GLfloat i_fWidth, GLfloat i_fHeight) : nNumVerts(6)
{
GLfloat wide = i_fWidth / 2;
GLfloat high = i_fHeight / 2;
Vertices[0] = -wide; Vertices[1] = high; Vertices[2] = 0.0f;
Vertices[3] = -wide; Vertices[4] = -high; Vertices[5] = 0.0f;
Vertices[6] = wide; Vertices[7] = -high; Vertices[8] = 0.0f;
Vertices[9] = -wide; Vertices[10] = high; Vertices[11] = 0.0f;
Vertices[12] = wide; Vertices[13] = -high; Vertices[14] = 0.0f;
Vertices[15] = wide; Vertices[16] = high; Vertices[17] = 0.0f;
}
};
void Renderer::Render()
{
glClear(GL_COLOR_BUFFER_BIT);
glEnableClientState(GL_VERTEX_ARRAY);
// If I change "m_Quad.nNumVerts" to '3' instead of '6' it will draw a triangle
// Anything higher than '3' and it doesn't draw anything
glVertexPointer(m_Quad.nNumVerts, GL_FLOAT, 0, m_Quad.Vertices);
glDrawArrays(GL_TRIANGLES, 0, m_Quad.nNumVerts);
eglSwapBuffers(m_pEngine->pDisplay, m_pEngine->pSurface);
}
The first argument of glVertexPointer is the number of values per vertex, it should stays in 3 in this case.
glVertexPointer(3, GL_FLOAT, 0, m_Quad.Vertices);
I'm drawing a 10x10 grid of squares at a depth of 0 and trying to highlight the one the mouse is over. I've tried following the tutorial here: http://antongerdelan.net/opengl/raycasting.html
but I don't know if I did it right. I end up with a vector at the end, but I'm not sure what to do with it.
Here's a screenshot of the squares (not sure how it helps..)
http://postimg.org/image/dau330qwt/2
/* Enable attribute index 1 as being used */
glEnableVertexAttribArray(1);
float camera_z = 50;
float camera_x = 0;
float camera_y = 0;
GLuint MatrixID = glGetUniformLocation(program, "MVP");
GLuint ColorID = glGetUniformLocation(program, "input_color");
int mouse_x;
int mouse_y;
while (1) {
int window_width;
int window_height;
SDL_GetWindowSize(win, &window_width, &window_height);
glm::mat4 Projection = glm::perspective(45.0f, ((float)window_width) / window_height, 0.1f, 100.0f);
// printf("Camera at %f %f\n", camera_x, camera_y);
glm::mat4 View = glm::lookAt(glm::vec3(camera_x,camera_y,camera_z), // camera position
glm::vec3(camera_x,camera_y,0), // looking at
glm::vec3(0,1,0)); // up
int map_width = map.width();
int map_height = map.height();
/* Make our background black */
glClearColor(0.0, 0.0, 0.0, 1.0);
glClear(GL_COLOR_BUFFER_BIT);
// go through my 10x10 map and
for (int i = 0; i < map_width; i++) {
for ( int j = 0; j < map_height; j++) {
glm::mat4 Model = glm::translate(glm::mat4(1.0f), glm::vec3(i, j, 0.0f));
glm::mat4 MVP = Projection * View * Model;
glm::vec3 color = random_color();
glUniformMatrix4fv(MatrixID, 1, GL_FALSE, &MVP[0][0]);
glUniform3fv(ColorID, 1, &color[0]);
glDrawArrays(GL_LINE_LOOP, 0, 4);
}
}
/* Swap our buffers to make our changes visible */
SDL_GL_SwapWindow(win);
// printf("Window dimensions %d x %d\n", window_width, window_height);
float normalized_mouse_x = (2.0f * mouse_x) / window_width - 1.0f;
float normalized_mouse_y = 1.0f - (2.0f * mouse_y) / window_height;
printf("Normalized mouse position %f x %f\n", normalized_mouse_x, normalized_mouse_y);
glm::vec3 normalized_mouse_vector = glm::vec3(normalized_mouse_x, normalized_mouse_y, 1.0f);
glm::vec4 ray_clip = glm::vec4 (normalized_mouse_vector.x, normalized_mouse_vector.y, -1.0, 1.0);
glm::vec4 ray_eye = glm::inverse(Projection) * ray_clip;
ray_eye = glm::vec4(ray_eye.xy(), -1.0, 0.0);
glm::vec3 ray_world = (glm::inverse(View) * ray_eye).xyz();
ray_world = glm::normalize(ray_world);
// this prints out values like: World ray: 0.000266, 0.000382, 1.000000
printf("World ray: %f, %f, %f\n", ray_world.x, ray_world.y, ray_world.z);
// l = -(camera_z / ray_world.z)
float l = -(camera_z / ray_world.z);
float mouse_world_x = camera_x + l * ray_world.x;
float mouse_world_y = camera_y + l * ray_world.y;
printf("mouse world %f, %f\n", mouse_world_x, mouse_world_y);
}
Updated with code from BDL's comment. The output I get now is:
Normalized mouse position 0.087500 x 0.145833
World ray: 0.065083, 0.081353, 499.000000
World ray: 0.000130, 0.000163, 1.000000
mouse world -0.006521, -0.008152
I'm expecting the "mouse world" line to have numbers in the 1-10 range, not in the .00x range, though, based on the screenshot above showing a grid of squares with x and y ranging from 0-10.
Thanks for looking.
The intersection between a given ray r, starting at point C (in this case the camera position) with a x/y plane with z=0 can be calculated as follows:
C ... Camera position [cx,cy,cz]
r ... ray direction [rx,ry,rz]
We are searching for the point on the ray that has z=0
C + l*r = [x,y,0]
=>
cz + l*rz = 0
l * rz = -cz
l = -(cz / rz)
The xy-coordinates of the intersection are now:
x = cx + l * rx
y = cy + l * ry
What is left to do is to check in which rectangle this (x,y) coordinates are located.
I'm trying to run the "Cacti in the Desert" Billboard example from Chapter 15 of the OpenGL Game Programming book (Book source code available here). I'm having difficulty getting the desert terrain to be visible on my screen. I'm using GLFW for my window and the example code created it's own window, could this be the issue?
Or, could the issue be with the DisplayScene() function below. In this function, do I have to somehow set the following matrices from my camera class?
ViewMatrix = camera[currentCamera]->GetViewMatrix();
ProjectionMatrix = camera[currentCamera]->GetViewProjectionMatrix();
Here's the DisplayScene() function from the Cacti demo:
BOOL DisplayScene()
{
// used to track the orientation of the viewer
static GLfloat s_eye[] = { MAP_X * MAP_SCALE * 0.5, 8.0, -MAP_Z * MAP_SCALE * 0.5};
static GLfloat s_at[] = { 0.0, 0.0, 0.0 };
static GLfloat s_angle = -90.0;
float speed = 0.3f;
// check for rotation
if (g_keys[VK_LEFT])
{
s_angle -= 2.0;
}
if (g_keys[VK_RIGHT])
{
s_angle += 2.0;
}
// run if the shift key is pressed
if (KEY_DOWN(VK_SHIFT))
speed = speed * 2;
float rad = float(PI*s_angle/180.0f);
// check for forward and backward motion
if (g_keys[VK_UP])
{
s_eye[2] += (float)sin(rad) * speed;
s_eye[0] += (float)cos(rad) * speed;
}
if (g_keys[VK_DOWN])
{
s_eye[2] -= (float)sin(rad) * speed;
s_eye[0] -= (float)cos(rad) * speed;
}
// do bound's checking to make sure they don't leave the map
if (s_eye[0] < MAP_SCALE)
s_eye[0] = MAP_SCALE;
if (s_eye[0] > (MAP_X - 2) * MAP_SCALE)
s_eye[0] = (MAP_X - 2) * MAP_SCALE;
if (s_eye[2] < -(MAP_Z - 2) * MAP_SCALE)
s_eye[2] = -(MAP_Z - 2) * MAP_SCALE;
if (s_eye[2] > - MAP_SCALE)
s_eye[2] = -MAP_SCALE;
// set the eye position in relation to the ground
s_eye[1] = GetHeight(s_eye[0], s_eye[2]) + 2.0f;
//set the look at point to be at eye level in the direction the viewer is headed
s_at[0] = float(s_eye[0] + 100*cos(rad));
s_at[2] = float(s_eye[2] + 100*sin(rad));
s_at[1] = s_eye[1];
// set up the modelview matrix according to this viewer orientation
glLoadIdentity();
gluLookAt(s_eye[0], s_eye[1], s_eye[2],
s_at[0], s_at[1], s_at[2],
0.0, 1.0, 0.0
);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
DrawSand();
DrawCacti();
return TRUE;
} // end DisplayScene()
Here is the DrawSand() function to draw the terrain:
void DrawSand()
{
// select the sand texture
glBindTexture(GL_TEXTURE_2D, g_sand);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
// loop through all the triangle strips
for (int z = 0; z < MAP_Z-1; z++)
{
// draw the triangles in this strip
glDrawElements(GL_TRIANGLE_STRIP, MAP_X * 2, GL_UNSIGNED_INT, &g_indexArray[z * MAP_X * 2]);
}
} // end DrawSand()
I have this function of drawing a circle:
void draw_circle()
{
GLint num_of_tri = 32;
GLfloat vertex[3];
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
const GLfloat delta_angle = 2.0*PI/float(num_of_tri);
//Draw Front tire
glBegin(GL_TRIANGLE_FAN);
glColor3f(0.5, 0.5, 0.5);
vertex[0] = vertex[1] = vertex[2] = 0.0;
glVertex3fv(vertex);
for(int i = 0; i < num_of_tri ; i++)
{
vertex[0] = cos(delta_angle*i) * wheelRadius; //wheelRadius is 1.0
vertex[1] = sin(delta_angle*i) * wheelRadius;
vertex[2] = 0.0;
glVertex3fv(vertex);
}
vertex[0] = 1.0 * wheelRadius;
vertex[1] = 0.0 * wheelRadius;
vertex[2] = 0.0;
glVertex3fv(vertex);
glEnd();
}
This is my init function
void init(void)
{
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(0.0, 0.0, 1.5, 0, 0, 0, 0, 1, 0);
}
And this is my display function
void display(void)
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
draw_circle();
glFlush();
}
To my best understanding, the circle is drawn at the origin. So calling the gluLookAt function with eye values of (0,0,1.5) is not a problem right?
But whenever I'm calling gluLookAt with eye values of z, bigger than 1, the circle disappears. Why does this happen?
Any help would be appreciated.
You are missing a call to gluPerspective.
The default zNear and zFar values of (-1,1) exclude your circle when you move the eye point more than one unit away.
Edit your init function to include:
gluPerspective( 45.0f, ( GLfloat )screenWidth / ( GLfloat )screenHeight, 0.1f, 100.0f );
Or something similar.