I have some code which draws a line along the x, y and z axes. My problem is that these lines are being clipped so that they are invisible near the origin:
This sounds like a far clipping plane issue, but I gave zFar=50 to gluPerspective, which should be plenty. Making it even larger doesn't seem to help. What else could be causing the clipping?
Here is my code:
import static org.lwjgl.opengl.GL11.*;
import org.lwjgl.opengl.*;
import org.lwjgl.util.glu.GLU;
public class Test {
static int width = 300, height = 200;
public static void main(String[] _) throws Exception {
Display.setDisplayMode(new DisplayMode(width, height));
Display.create();
glClear(GL_COLOR_BUFFER_BIT);
// projection matrix
glMatrixMode(GL_PROJECTION_MATRIX);
glLoadIdentity();
GLU.gluPerspective(50, width / (float) height, .1f, 50);
// modelview matrix
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
GLU.gluLookAt(
.8f, .8f, .8f,
0, 0, 0,
0, 1, 0);
// draw a line for each axis
glBegin(GL_LINES);
// x axis in red
glColor3f(1, 0, 0);
glVertex3i(0, 0, 0);
glVertex3i(10, 0, 0);
// y axis in green
glColor3f(0, 1, 0);
glVertex3i(0, 0, 0);
glVertex3i(0, 10, 0);
// z axis in blue
glColor3f(0, 0, 1);
glVertex3i(0, 0, 0);
glVertex3i(0, 0, 10);
glEnd();
Display.update();
// wait for a close event
while (!Display.isCloseRequested()) {
Thread.sleep(20);
Display.processMessages();
}
Display.destroy();
}
}
Update - Removing glLoadIdentity(); after glMatrixMode(GL_MODELVIEW); gives the desired result, but I don't understand why. Isn't the default modelview matrix the identity matrix?
Update - I wrote a C version of the same code and it works as desired. Why the difference?
Indeed, after testing it, it turns out that glMatrixMode(GL_PROJECTION_MATRIX); should be glMatrixMode(GL_PROJECTION); instead.
So it seems that the modelview was active by default and glLoadIdentity() cleared the results of GLU.gluPerspective(50, width / (float) height, .1f, 50);
edit: Btw. in case you wonder what GL_PROJECTION_MATRIX is for, it's to retrieve the current matrix from the top of the matrix stack with glGetFloatv(GL_PROJECTION_MATRIX,output); or glGetDoublev(GL_PROJECTION_MATRIX,output);
Related
I tried to draw a teapot and view it in 3D but when I ran the program, nothing showed up. There is nothing in the window. I know it has something to do with my gluLookAt() function but I am not sure how to fix it.
// helloteapot.cc
//#include <GLUT/gl.h>
#include <GLUT/glut.h>
#include "GL/glui.h"
void display () {
/* clear window */
glClear(GL_COLOR_BUFFER_BIT);
/* draw scene */
glColor3f(1.0, 0.0, 0.0);
glTranslatef(0.0, 0.5, 0.0);
glutSolidTeapot(0.15);
/* flush drawing routines to the window */
glFlush();
}
int main ( int argc, char * argv[] ) {
glutInit(&argc,argv);
/* setup the size, position, and display mode for new windows */
glutInitWindowSize(800,600);
glutInitWindowPosition(0,0);
glutInitDisplayMode(GLUT_RGB);
/* create and set up a window */
glutCreateWindow("hello, teapot!");
glutDisplayFunc(display);
/*GLfloat width = 800;
GLfloat height = 600;
GLfloat aspect = (GLfloat)width / (GLfloat)height;
// Set the viewport to cover the new window
glViewport(0, 0, width, height);*/
// Set the aspect ratio of the clipping volume to match the
viewport
glMatrixMode(GL_PROJECTION); // To operate on the Projection
matrix
glLoadIdentity(); // Reset
// Enable perspective projection with fovy, aspect, zNear and zFar
//luPerspective(45.0f, aspect, -100.0f, 100.0f);
gluLookAt(0, 0, 0, 0, 0.5, 0, 0, -1, 0);
/* tell GLUT to wait for events */
glutMainLoop();
}
You have asked GL to position the camera at the origin, aim the camera upwards towards the point (0, 0.5, 0), and have also specified (incorrectly) the up vector to be 0, -1, 0. The problem is that the camera's forward direction is (0, 1, 0) [as specified by your eye and aim positions], and this direction conflicts with the up vector or (0, -1, 0). Try using a vector at right angles to the forward direction instead! (e.g. [1, 0, 0], [0, 0, 1])
gluLookAt(
0, 0, 0, //< camera location
0, 0.5, 0, //< looking towards point
1, 0, 0); //< which direction is up?
I'm trying to look at the square from the other side using the gluLookAt() function.
After using the function, nothing changes, although I expected that the corners of the square will change.
I set the camera point to the rightmost part of the world and look at its center, where the square is located.
He had to stretch out to the sides. Why hasn't anything changed?
Code:
#include "includes.h"
using namespace std;
constexpr auto FPS_RATE = 60;
int windowHeight = 600, windowWidth = 600, windowDepth = 600;
void init();
void idleFunction();
void displayFunction();
double getTime();
double getTime()
{
using Duration = std::chrono::duration<double>;
return std::chrono::duration_cast<Duration>(
std::chrono::high_resolution_clock::now().time_since_epoch()
).count();
}
const double frame_delay = 1.0 / FPS_RATE;
double last_render = 0;
void init()
{
glutDisplayFunc(displayFunction);
glutIdleFunc(idleFunction);
glViewport(0, 0, windowWidth, windowHeight);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(-windowWidth / 2, windowWidth / 2, -windowHeight / 2, windowHeight / 2, -windowDepth / 2, windowDepth / 2);
glClearColor(0.0, 0.0, 0.0, 0.0);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL);
}
void idleFunction()
{
const double current_time = getTime();
if ((current_time - last_render) > frame_delay)
{
last_render = current_time;
glutPostRedisplay();
}
}
void displayFunction()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glBegin(GL_POLYGON);
gluLookAt(-300, 0, 0,
0, 0, 0,
0, 1, 0);
glColor3f(1, 1, 1);
glVertex3i(-150, 150, 0);
glVertex3i(150, 150, 0);
glVertex3i(150, -150, 0);
glVertex3i(-150, -150, 0);
glEnd();
glutSwapBuffers();
}
int main(int argc, char* argv[])
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);
glutInitWindowSize(windowWidth, windowHeight);
glutInitWindowPosition((GetSystemMetrics(SM_CXSCREEN) - windowWidth) / 2, (GetSystemMetrics(SM_CYSCREEN) - windowHeight) / 2);
glutCreateWindow("Window");
init();
glutMainLoop();
return 0;
}
The issue is caused because gluLookAt() is call with in a glBegin/glEnd sequence. This is not allowed. You've to call gluLookAt before glBegin.
Once drawing of primitives was started by glBegin it is only allowed to specify vertex coordinates (glVertex) and change attributes (e.g. glColor, glTexCoord ...), till the drawn is ended (glEnd).
All other instruction will be ignored and cause a GL_INVALID_OPERATION error (error code 1282).
Further note, that glLookAt doesn't set a the current matrix. It defines a matrix and multiplies the current matrix by the new matrix. Set the matrix mode (glMatrixMode) and set Identity matrix by glLoadIdentity before gluLookAt.
With the view matrix
gluLookAt(-300, 0, 0, 0, 0, 0, 0, 1, 0);
you want "see" anything, because with that matrix the line of sight is set along the x-axis and you look at the 2 dimensional polygon from the side.
Note, the polygon is a 2D object. The size of the object appears different if you look at it from the front, from the side (then it is a line and not visible) or from an direction in between. The first 3 parameters of gluLookAt define the point of view the next 3 parameters define the point you look at. The vector from the point of view to the point you look at is the line of sight.
Probably yo want look along the z-axis:
void displayFunction()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(0, 0, -300, 0, 0, 0, 0, 1, 0);
glBegin(GL_POLYGON);
glColor3f(1, 1, 1);
glVertex3i(-150, 150, 0);
glVertex3i(150, 150, 0);
glVertex3i(150, -150, 0);
glVertex3i(-150, -150, 0);
glEnd();
glutSwapBuffers();
}
You use Orthographic (parallel) projection. If you would use Perspective projection, then the projected size of the object would decrease, when the distance to the point of view increases. Perspective projection can be set by gluPerspective. e.g.:
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(90.0, (double)windowWidth / windowHeight, 0.1, 600.0);
#include<stdio.h>
#include<stdlib.h>
#include<math.h>
#include<GL/glut.h>
double cameraAngle;
void grid_and_axes() {
// draw the three major AXES
glBegin(GL_LINES);
//X axis
glColor3f(0, 1, 0); //100% Green
glVertex3f(-150, 0, 0);
glVertex3f(150, 0, 0);
//Y axis
glColor3f(0, 0, 1); //100% Blue
glVertex3f(0, -150, 0); // intentionally extended to -150 to 150, no big deal
glVertex3f(0, 150, 0);
//Z axis
glColor3f(1, 1, 1); //100% White
glVertex3f(0, 0, -150);
glVertex3f(0, 0, 150);
glEnd();
//some gridlines along the field
int i;
glColor3f(0.5, 0.5, 0.5); //grey
glBegin(GL_LINES);
for (i = -10; i <= 10; i++) {
if (i == 0)
continue; //SKIP the MAIN axes
//lines parallel to Y-axis
glVertex3f(i * 10, -100, 0);
glVertex3f(i * 10, 100, 0);
//lines parallel to X-axis
glVertex3f(-100, i * 10, 0);
glVertex3f(100, i * 10, 0);
}
glEnd();
}
void display() {
//codes for Models, Camera
//clear the display
//glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glClearColor(0, 0, 0, 0); //color black
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); //clear buffers to preset values
/***************************
/ set-up camera (view) here
****************************/
//load the correct matrix -- MODEL-VIEW matrix
glMatrixMode(GL_MODELVIEW); //specify which matrix is the current matrix
//initialize the matrix
glLoadIdentity(); //replace the current matrix with the identity matrix [Diagonals have 1, others have 0]
//now give three info
//1. where is the camera (viewer)?
//2. where is the camera looking?
//3. Which direction is the camera's UP direction?
//gluLookAt(0,-150,20, 0,0,0, 0,0,1);
gluLookAt(150 * sin(cameraAngle), -150 * cos(cameraAngle), 50, 0, 0, 0, 0, 0, 1);
/*************************
/ Grid and axes Lines
**************************/
grid_and_axes();
/****************************
/ Add your objects from here
****************************/
/*glColor3f(1, 0, 0);
glutSolidCone(20, 20, 20, 20);
glColor3f(0, 0, 1);
GLUquadricObj *cyl = gluNewQuadric();
gluCylinder(cyl, 10, 10, 50, 20, 20);
glTranslatef(0, 0, 50);
glColor3f(1, 0, 0);
glutSolidCone(10, 20, 20, 20);
*/
glColor3f(1, 0, 0);
glutSolidCube(1);
I am not getting any cube here.
However if I use any transformation property like scaling or rotate then I get the desired cube like
glColor3f(1, 0, 0);
glScalef(50,5,60);
glutSolidCube(1);
what is the problem?
Another problem I am facing that color doesn't work if i don't use transformation property like above mentioned. If I write:
glColor3f(1, 0, 0);
glutSolidCone(20, 20, 20, 20);
For above codes color doesn't work; i get the default colored cone
However if I change this two lines to these 3 lines then color works perfectly:
glColor3f(1,0,0);
glTranslatef(0, 0, 50);
glutSolidCone(10,20,20,20);
then color works; what is the problem? Please help
//ADD this line in the end --- if you use double buffer (i.e. GL_DOUBLE)
glutSwapBuffers();
}
void animate() {
//codes for any changes in Models, Camera
cameraAngle += 0.001; // camera will rotate at 0.002 radians per frame.
//codes for any changes in Models
//MISSING SOMETHING? -- YES: add the following
glutPostRedisplay(); //this will call the display AGAIN
}
void init() {
//codes for initialization
cameraAngle = 0; //angle in radian
//clear the screen
glClearColor(0, 0, 0, 0);
/************************
/ set-up projection here
************************/
//load the PROJECTION matrix
glMatrixMode(GL_PROJECTION);
//initialize the matrix
glLoadIdentity();
/*
gluPerspective() — set up a perspective projection matrix
fovy - Specifies the field of view angle, in degrees, in the y direction.
aspect ratio - Specifies the aspect ratio that determines the field of view in the x direction. The aspect ratio is the ratio of x (width) to y (height).
zNear - Specifies the distance from the viewer to the near clipping plane (always positive).
zFar - Specifies the distance from the viewer to the far clipping plane (always positive).
*/
gluPerspective(70, 1, 0.1, 10000.0);
}
int main(int argc, char **argv) {
glutInit(&argc, argv); //initialize the GLUT library
glutInitWindowSize(500, 500);
glutInitWindowPosition(100, 100);
/*
glutInitDisplayMode - inits display mode
GLUT_DOUBLE - allows for display on the double buffer window
GLUT_RGBA - shows color (Red, green, blue) and an alpha
GLUT_DEPTH - allows for depth buffer
*/
glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGB);
glutCreateWindow("Some Title");
init(); //codes for initialization
glEnable(GL_DEPTH_TEST); //enable Depth Testing
glutDisplayFunc(display); //display callback function
glutIdleFunc(animate); //what you want to do in the idle time (when no drawing is occuring)
glutMainLoop(); //The main loop of OpenGL
return 0;
}
I am not getting any cube here.
You do get a cube. It is just that tiny speck where the axis intersect. What else would you expect to see when you draw something 2 units big, ~160 units away, with a 70 degree field of view?
Another problem I am facing that color doesn't work if i don't use transformation property like above mentioned.
[...] I get the default colored cone.
I've no idea what you even mean by that. The "default color" would be the initial value of GL's builtin color attribute - which is (1, 1, 1, 1) - white. With the code you have set up, you will get the color which you set before. So the only guess I can make here is that you confused yourself by not properly taking GL's state machine into account.
But besides all that, you should not use that code at all - this is using the fixed function pipeline and immediate mode drawing - features which are deprecated since a decade now, and not supported at all by modern core profiles of OpenGL. Trying to learn that stuff in 2017 is a waste of time. And btw:
glutMainLoop(); //The main loop of OpenGL
Nope. Just NO!!!. OpenGL does not have a "main loop". GLUT is not OpenGL. Honestly, this is all just horrible.
How to move a 2D object in the direction of a point (not a GL_POINTS, but coordinates) using OpenGL?
For a better understanding of my code:
I've splited most of my code into different source codes, but this is the one that is actually creating the shapes and setting the scene:
void setupScene(int clearColor[]) {
glClearColor(clearColor[0], clearColor[1], clearColor[2], clearColor[3]);
//glClearColor(250, 250, 250, 1.0); // Set the cleared screen colour to black.
glViewport(0, 0, WINDOW_WIDTH, WINDOW_HEIGHT); // This sets up the viewport so that the coordinates (0, 0) are at the top left of the window.
// Set up the orthographic projection so that coordinates (0, 0) are in the top left.
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0, WINDOW_WIDTH, WINDOW_HEIGHT, 0, -10, 10);
// Back to the modelview so we can draw stuff.
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Clear the screen and depth buffer.
}
void drawScene() {
setupScene((int[]){250, 250, 250, 1});
triangle(210, WINDOW_WIDTH, WINDOW_HEIGHT);
glBegin(GL_QUADS);
glColor3f(RGB(80), RGB(80), RGB(80));
glPushMatrix();
glTranslatef(400, 400, 0);
glVertex2d(200, 100);
glVertex2d(100, 100);
glVertex2d(100, 200);
glVertex2d(200, 200);
glPopMatrix();
glEnd();
glutSwapBuffers(); // Send the scene to the screen.
}
void update(int value) {
glutPostRedisplay(); // Tell GLUT that the display has changed.
glutTimerFunc(25, update, 0); // Tell GLUT to call update again in 25 milliseconds.
}
You need to translate the modelview matrix. Assuming you're in modelview mode already:
glPushMatrix();
glTranslatef(x, y, z);
// Draw your shape
glPopMatrix();
[Edit]
#paddy: Something like this? I tried this but the square isn't moving.
pastebin.com/2PCsy5kC
Try explicitly selecting the modelview matrix. Your example does not tell us which mode it's currently in:
glSetMatrixMode(GL_MODELVIEW);
glPushMatrix();
glTranslatef(x, y, z);
// Draw your shape
glPopMatrix();
Normally at the beginning of your render you reset everything... So you enter the GL_PROJECTION mode, call glLoadIdentity() to reset it and set up your camera, then do this for the GL_MODELVIEW matrix as well.
Answer on the behalf of the OP:
Thanks #paddy, I was trying to understand the use of glTranslatef and came with the solution. Here is the working code, it will create a square at 100x100 and will move it until 400x200:
void setupScene(int clearColor[]) {
glClearColor(clearColor[0], clearColor[1], clearColor[2], clearColor[3]);
//glClearColor(250, 250, 250, 1.0); // Set the cleared screen colour to black.
glViewport(0, 0, WINDOW_WIDTH, WINDOW_HEIGHT); // This sets up the viewport so that the coordinates (0, 0) are at the top left of the window.
// Set up the orthographic projection so that coordinates (0, 0) are in the top left.
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0, WINDOW_WIDTH, WINDOW_HEIGHT, 0, -10, 10);
// Back to the modelview so we can draw stuff.
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Clear the screen and depth buffer.
}
int a = 100;
int b = 200;
int x = 100;
int y = 100;
void drawScene() {
setupScene((int[]){250, 250, 250, 1});
triangle(210, WINDOW_WIDTH, WINDOW_HEIGHT);
glPushMatrix();
glTranslatef(x, y, 0);
glBegin(GL_QUADS);
glColor3f(RGB(80), RGB(80), RGB(80));
glVertex2d(b, a);
glVertex2d(a, a);
glVertex2d(a, b);
glVertex2d(b, b);
glEnd();
glPopMatrix();
glutSwapBuffers(); // Send the scene to the screen.
}
void update(int value) {
if (x != 400 && y != 200) {
x += 4;
y += 2;
}
glutPostRedisplay(); // Tell GLUT that the display has changed.
glutTimerFunc(25, update, 0); // Tell GLUT to call update again in 25 milliseconds.
}
I am trying to set up a Picture in picture style "map" display for a graphics program that displays a car. (Just shows the view from top again in a smaller view port.) However, the second viewport seems to flicker. I thought I was doing this correctly, but I may be not conceptualizing this correctly.
void display(void) {
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);
// Set Perspective
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(fov, aspect, near, far);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glViewport(0, 0, 500, 500);
// Lighting follows Camera if inserted here.
//Set Camera
calculateCamera();
gluLookAt(eyeX + carPosX, eyeY + carPosY, eyeZ + carPosZ, cX + carPosX,
cY + carPosY, cZ + carPosZ, 0, 1, 0);
displayEnvironment();
glClear(GL_DEPTH_BUFFER_BIT);
// Set Perspective
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(fov, aspect, near, far);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glViewport(0,0,150,150);
gluLookAt(0, 140, 0,0, 0, 0, 1, 0, 0);
displayEnvironment();
}
Where/when are you swapping buffers? Maybe you're not waiting for the render to finish?