I drew a rectangle in the X-Z play of a 3D, XYZ, plane using the code below.
#include <GL/glut.h>
void drawPlane() {
GLfloat A[3] = { 0, 0, 0};
GLfloat B[3] = { 1, 0, 0};
GLfloat C[3] = { 1, 0, 1};
GLfloat D[3] = { 0, 0, 1};
glBegin(GL_POLYGON);
glVertex3fv(A);
glVertex3fv(B);
glVertex3fv(C);
glVertex3fv(D);
glEnd();
}
// Display Call Back
void draw(){
glLoadIdentity();
glTranslatef(0.0, 0.5, 1); //i thought this would do the camera thing
drawPlane();
glutSwapBuffers();// Render Now
return;
}
// Initialization
void initialize()
{
glClearColor(0.1f, 0.1f, 0.1f, 0.1f); // Set Background Color
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Clear all drawings in buffer
}
// Main
int main(int argc, char* argv[])
{
glutInit(&argc, argv); // Initialize GLUT
int x = 512, y = 512; // x and y value
glutInitWindowPosition(
(int)(glutGet(GLUT_SCREEN_WIDTH) - x) / 2,
(int)(glutGet(GLUT_SCREEN_HEIGHT) - y) / 2); // Position the window's center
glutInitWindowSize(x, y); // Set the window's initial width & height
glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH); // ESSENTIAL BUT HAVE NO IDEA WHAT THIS DOES
glutCreateWindow("3d Bowling Game"); // Create a window with the given title
glutDisplayFunc(draw); // Register display callback handler for window re-paint
glutMainLoop(); // Enter the event-processing loop
initialize();
return 0;
}
How do I change the camera angle in order to view all of the coordinates like below.
Related
I am trying to achieve a perspective view for a rectangular plane in the X-Z axis like below.
The code below almost achieves that.
What am i doing wrong? I find the documentation to be lacking/confusing.
#include <GL/glut.h>
const int RED_COLOR[3] = {255, 0, 0};
// color to draw in
void setDrawColor(const int decimalCodeRGB[3]) {
float denominator = 255.0;
//convert to float
float r = decimalCodeRGB[0] / denominator;
float g = decimalCodeRGB[1] / denominator;
float b = decimalCodeRGB[2] / denominator;
glColor3f(r, g, b); // set draw color
}
void drawPlane() {
GLfloat A[3] = { -1, 0, 1 };
GLfloat B[3] = { 1, 0, 1 };
GLfloat C[3] = { 1, 0, -1 };
GLfloat D[3] = { -1, 0, -1 };
glBegin(GL_POLYGON);
glVertex3fv(A);
glVertex3fv(B);
glVertex3fv(C);
glVertex3fv(D);
glEnd();
}
GLfloat CamX = 0, CamY = 2, CamZ = 1;
// Display Call Back
void draw() {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Clear all drawings in buffer
glLoadIdentity();
gluLookAt(CamX, CamY, CamZ, 0, 0, 0, 0, 1, 0);
drawPlane();
glutSwapBuffers();// Render Now i.e convert Buffer to Picture
return;
}
// Initialization
void initialize()
{
glClearColor(0.1f, 0.1f, 0.1f, 0.1f); // Set Background Color
setDrawColor(RED_COLOR); // sets the drawing color to red
glEnable(GL_DEPTH_TEST); // enable viewing the 3d
glMatrixMode(GL_PROJECTION); // change to perspective projection
glLoadIdentity(); // what does this do?
glFrustum(-1, 1, -1, 1, 2, 10); // what does this do?
glMatrixMode(GL_MODELVIEW); // what does this do?
}
// Main
int main(int argc, char* argv[])
{
glutInit(&argc, argv); // Initialize GLUT
int x = 512, y = 512; // x and y value
glutInitWindowPosition(
(int)(glutGet(GLUT_SCREEN_WIDTH) - x) / 2,
(int)(glutGet(GLUT_SCREEN_HEIGHT) - y) / 2); // Position the window's center
glutInitWindowSize(x, y); // Set the window's initial width & height
glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH); // initialise the buffers needed. double buff, one for RGB color the other for x,y, z
glutCreateWindow("3D Bowling Game"); // Create a window with the given title
initialize(); // Custom initialisation
glutDisplayFunc(draw); // Register display callback handler for window re-paint
glutMainLoop(); // Enter the event-processing loop
return 0;
}
// End
How do I change the camera to 45 degrees to Z axis?
Am i calling the functions in the right Order?
The screenshot below shows the desired result.
below is the actual result
I used the glutWireSphere API for drawing my sphere, however, it is not showing.
#include <GL/glut.h>
const int RED_COLOR[3] = {255, 0, 0};
const int GREEN_COLOR[3] = { 0, 0, 255};
// color to draw in
void setDrawColor(const int rgb[3]) {
float d = 255.0; // d = max value in an rgb color spectrum
glColor3f(rgb[0]/d, rgb[1]/d, rgb[2]/d); // set draw color R=x/255 G=y/255 B=z/255 where x,y,z are values in rgb channel respectively
}
void drawPlane() {
GLfloat A[3] = { -1, 0, 1 };
GLfloat B[3] = { 1, 0, 1 };
GLfloat C[3] = { 1, 0, -1 };
GLfloat D[3] = { -1, 0, -1 };
glBegin(GL_POLYGON);
glVertex3fv(A);
glVertex3fv(B);
glVertex3fv(C);
glVertex3fv(D);
glEnd();
}
GLfloat CamX = 0, CamY = 2, CamZ = 2;
// Display Call Back
void draw() {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Clear all drawings in buffer
glLoadIdentity();
gluLookAt(CamX, CamY, CamZ, 0, 0, 0, 0, 1, 0);
drawPlane();
setDrawColor(GREEN_COLOR); // sets the drawing color to GREEN
glutWireSphere(0.2, 20, 20);
glutSwapBuffers();// Render Now i.e convert Buffer to Picture
return;
}
// Initialization
void initialize()
{
glClearColor(0.1f, 0.1f, 0.1f, 0.1f); // Set Background Color
setDrawColor(RED_COLOR); // sets the drawing color to red
glEnable(GL_DEPTH_TEST); // enable viewing the 3d
glMatrixMode(GL_PROJECTION); // change to perspective projection
glLoadIdentity(); // what does this do?
glFrustum(-1, 1, -1, 1, 2, 10); // what does this do?
glMatrixMode(GL_MODELVIEW); // what does this do?
}
// Main
int main(int argc, char* argv[])
{
glutInit(&argc, argv); // Initialize GLUT
int x = 512, y = 512; // x and y value
glutInitWindowPosition(
(int)(glutGet(GLUT_SCREEN_WIDTH) - x) / 2,
(int)(glutGet(GLUT_SCREEN_HEIGHT) - y) / 2); // Position the window's center
glutInitWindowSize(x, y); // Set the window's initial width & height
glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH); // initialise the buffers needed. double buff, one for RGB color the other for x,y, z
glutCreateWindow("3D Bowling Game"); // Create a window with the given title
initialize(); // Custom initialisation
glutDisplayFunc(draw); // Register display callback handler for window re-paint
glutMainLoop(); // Enter the event-processing loop
return 0;
}
what am i doing wrong?
I need to make a game for a project on college. Everything works fine, the only problem is translating mouse coords (0,0 in top left corner) to openGL coords (0,0 in center of the screen).
In class we got the formula for doing this:
double openglX = ((double)x - [half horizontal res]) / [horizontal res] * [horizontal opengl range];
double openglY = -((double)y - [half vertical res]) / [vertical res] * [vertical opengl range];
#include <iostream>
#include <list>
#include <vector>
#include <cstdlib>
#include <ctime>
#define NDEBUG
#include <GL/freeglut.h>
const int GAME_LOGIC_REFRESH_TIME = 10;
/* GLUT callback Handlers */
void resize(int width, int height)
{
const float ar = (float)width / (float)height;
glViewport(0, 0, width, height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glFrustum(-ar, ar, -1.0, 1.0, 2.0, 100.0);
gluLookAt(0, 0, 45, 0, 0, 0, 0, 1, 0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
void gameLogic(int value)
{
if (value == 0)
{
}
else if(value==1)
{
}
}
void move_ship(int x, int y)
{
double openglX = ((double)x - 600) / 1200 * 46;
double openglY = -((double)y - 500) / 1000 * 38;
player.SetPosition(openglX);
}
/* helper functions for settings options and parameters */
void InitGLUTScene(const char* window_name)
{
glutInitWindowSize(1200, 1000);
glutInitWindowPosition(40, 40);
glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH | GLUT_MULTISAMPLE);
glutCreateWindow(window_name);
glClearColor(0, 0, 0, 0);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LESS);
glEnable(GL_LIGHT0);
glEnable(GL_NORMALIZE);
glEnable(GL_COLOR_MATERIAL);
}
void SetCallbackFunctions()
{
glutReshapeFunc(resize);
glutDisplayFunc(display);
glutIdleFunc(idle);
glutTimerFunc(GAME_LOGIC_REFRESH_TIME, gameLogic, 0);
glutMouseFunc(mouse);
glutPassiveMotionFunc(move_ship);
}
void SetObjectsPositions()
{
}
int main(int argc, char *argv[])
{
srand(time(NULL));
glutInit(&argc, argv);
InitGLUTScene("Space Invaders");
SetCallbackFunctions();
SetObjectsPositions();
glutMainLoop();
return 0;
}
Calculations in move_ship are quite good close to center of the screen, but at the edges they are off enough, that it's a big problem and the player can't reach the edge of the screen.
The first thing I notice is you have some magical numbers in your method move_ship() . Your callback resize() is able to change the width and height, so using constants in move_ship() seems like a bug to me.
The formula should be
void mouseToGl(
double& x, double& y, // output GL coords
double mx, double my, // mouse coords in pixels (0,0 is top left)
double W, double H) // screen dimension width, height
{
x = 2.0 * (mx / W) - 1.0;
y = 2.0 * ((my - W + 1) / W) - 1.0;
}
I've checked every other related question on this site but none of the solutions have worked for me. I'm simply trying to follow my rectangle, which moves left and right with key presses in OpenGL. Here's my very simple program:
/*Begin useful backend functions/vars*/
/*************************************/
//Window size and refresh rate (60 fps)
int width = 500;
int height = 500;
int interval = 1000 / 60;
//Used to draw rectangles
void drawRect(float x, float y, float width, float height) {
glBegin(GL_QUADS);
glVertex2f(x, y);
glVertex2f(x + width, y);
glVertex2f(x + width, y + height);
glVertex2f(x, y + height);
glEnd();
}
/***********************************/
/*End useful backend functions/vars*/
/*Game vars*/
/***********/
//keycodes
#define keyA 0x41
#define keyD 0x44
//player
int playerWidth = 30;
int playerHeight = 50;
int playerSpeed = 3;
//player starting position
float playerX = width / 2;
float playerY = 25.0f;
/***************/
/*End game vars*/
/*Game specific functions*/
/*************************/
void keyboard() {
//Move player (and camera) on key presses
if (GetAsyncKeyState(keyA)) {
playerX -= playerSpeed;
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(-playerSpeed,0,0);
}
if (GetAsyncKeyState(keyD)) {
playerX += playerSpeed;
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(playerSpeed, 0, 0);
}
}
/********************/
/*End game functions*/
/*Draw and update for window*/
/****************************/
void draw() {
//Initialliy clear
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
//Draw player
drawRect(playerX, playerY, playerWidth, playerHeight);
//Swap buffers to end
glutSwapBuffers();
}
void update(int value) {
// input handling
keyboard();
// Call update() again in 'interval' milliseconds
glutTimerFunc(interval, update, 0);
// Redisplay frame
glutPostRedisplay();
}
/*****************/
/*End draw/update*/
/*Main function*/
/***************/
int main(int argc, char** argv) {
// initialize opengl (via glut)
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
glutInitWindowSize(width, height);
glutCreateWindow("My Game");
// Register callback functions
glutDisplayFunc(draw);
glutTimerFunc(interval, update, 0);
// setup scene to be 2d
glViewport(0, 0, width, height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(0, width, 0, height);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
//set draw color to white
glColor3f(1.0f, 1.0f, 1.0f);
//start the whole thing
glutMainLoop();
return 0;
}
/*************/
/*End of main*/
The keyboard movement works perfectly, however:
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(-playerSpeed,0,0);
inside my keyboard() function, does nothing. And if I try it with GL_PROJECTION, it turns my screen black.
First of all note, that drawing by glBegin/glEnd sequences and the fixed function matrix stack is deprecated since decades. See Fixed Function Pipeline and Legacy OpenGL.
Simplify things.
Add a the keyboard events for key up and down (glutKeyboardFunc / glutKeyboardUpFunc). This functions only modifies the speed of the player. The speed is set when a button is pressed and is set 0, when a button is release:
int playerSpeed = 0;
void keyboardDown(unsigned char key, int x, int y)
{
if (key == 'a')
playerSpeed -= 3;
else if (key == 'd')
playerSpeed = 3;
}
void keyboardUp( unsigned char key, int x, int y )
{
playerSpeed = 0;
}
The timer event just modifies the position of the player:
void update(int value)
{
playerX += playerSpeed;
glutTimerFunc(interval, update, 0);
glutPostRedisplay();
}
In draw the model matrix is set and the rectangle is drawn:
void draw()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(playerX, playerY, 0);
//Draw player
drawRect(0, 0, playerWidth, playerHeight);
//Swap buffers to end
glutSwapBuffers();
}
Set the callback functions in main:
int main(int argc, char** argv)
{
// ...
glutDisplayFunc(draw);
glutTimerFunc(interval, update, 0);
glutKeyboardFunc( keyboardDown );
glutKeyboardUpFunc( keyboardUp );
// ...
}
The program should simulate a planet rotating around another planet.
I use gltranslatef to let the planet move around the bigger planet, but the problem is that the planet should hide when is over the bigger planet, because dz is -0.5.
But if I test the program I always see the red planet over the blue one.
Another problem I have: the planet rotates too fast, how do I slow it?
#include <OpenGL/OpenGL.h>
#include <GLUT/GLUT.h>
#include "utility.h"
GLfloat dx=0.0;
GLfloat dz=-0.5;
bool plus=true;
void init()
{
glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);
glLoadIdentity();
glOrtho(-1, 1, -1, 1, -1, 1);
glEnable(GLUT_DEPTH);
}
void render()
{
glClearColor(BLACK);
glClear(GL_COLOR_BUFFER_BIT);
glColor4f(BLUE);
glutWireSphere(0.25, 100, 100);
glPushMatrix();
glLoadIdentity();
glTranslatef(-0.5+dx, 0.0, -dz);
glColor4f(RED);
glutWireSphere(0.05, 100, 100);
glPopMatrix();
glFlush();
}
void idle()
{
if(plus)
{
dx+=0.05;
}
else
{
dx-=0.05;
}
if(dx>=1.0)
{
dx=0.5;
plus=false;
}
else if(dx<=-0.0)
{
dx=0.0;
plus=true;
}
glutPostRedisplay();
}
int main(int argc, const char * argv[])
{
glutInit(&argc, (char**)argv);
glutInitWindowSize(500, 500);
glutInitWindowPosition(150, 150);
glutInitWindowPosition(0, 0);
glutCreateWindow("Simple");
glutIdleFunc(idle);
init();
glutDisplayFunc(render);
glutMainLoop();
return 0;
}
I haven't understood well how does the idle function work, why it gets called so many times? Can't I choose a time interval with which the idle function gets called?
More info: RED and BLUE are RGB floats, defined in the utility.h header file.
plus is a bool that is used to know if I have to decrease or increase dx.
Give this a shot:
#include <GL/glut.h>
double GetSeconds()
{
return glutGet(GLUT_ELAPSED_TIME) / 1000.0f;
}
void render()
{
glClearColor(0,0,0,0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode( GL_MODELVIEW );
glLoadIdentity();
glColor3ub(0,0,255);
glutWireSphere(0.25, 100, 100);
glPushMatrix();
glLoadIdentity();
static double prv = GetSeconds();
double cur = GetSeconds();
double delta = cur - prv;
prv = cur;
const float DEG_PER_SEC = 60.0f;
static float angle = 0.0f;
angle += DEG_PER_SEC * delta;
while( angle > 360 ) angle -= 360;
glPushMatrix();
glRotatef( angle, 0, 1, 0 );
glTranslatef( 0.5, 0, 0);
glColor3ub(255,0,0);
glutWireSphere(0.05, 100, 100);
glPopMatrix();
glutSwapBuffers();
}
void reshape(int w, int h)
{
glViewport(0,0,w,h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(-1, 1, -1, 1, -1, 1);
}
void timer(int extra)
{
glutPostRedisplay();
glutTimerFunc(16, timer, 0);
}
int main(int argc, const char * argv[])
{
glutInit(&argc, (char**)argv);
glutInitWindowSize(500, 500);
glutInitWindowPosition(150, 150);
glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);
glutCreateWindow("Simple");
glutReshapeFunc(reshape);
glutTimerFunc(0, timer, 0);
glutDisplayFunc(render);
glEnable( GL_DEPTH_TEST );
glutMainLoop();
return 0;
}
Important parts:
Explicit glMatrixMode() calls
Calling glutInitDisplayMode() before glutCreateWindow()
Double-buffering requires glutSwapBuffers()
Clearing the depth buffer via GL_DEPTH_BUFFER_BIT
glEnable( GL_DEPTH_TEST )
glRotatef() for planet rotation
Timer-based animation