Related
I'm using my Macbook with Xcode and OpenGL (coding using C++) to learn how to add cameras to a graphic. Here I want to add a camera behind an object as a third-person view camera, and then use the 'WASD' buttons to move the object and use the mouse cursor to change the object's direction while the camera remains behind the object. But nothing is being drawn in the window, and I get no errors from Xcode. I have no idea where I'm going wrong.
My code is:
#include <iostream>
#include <string>
#define GLEW_STATIC
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <glm/glm.hpp>
#include <glm/ext.hpp>
#include <glm/gtx/string_cast.hpp>
GLFWwindow* window = NULL;
const char* WINDOW_TITLE = "GRA_Tutorial";
const GLint WINDOW_WIDTH = 800;
const GLint WINDOW_HEIGHT = 600;
bool initOpenGL();
void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods);
void drawSolidCube(float r);
//cube key control boolean
bool wKey, sKey, aKey, dKey;
static void error_callback(int error, const char* description)
{
fprintf(stderr, "Error: %s\n", description);
}
int main()
{
std::cout << "GRA_Tutorial!" << std::endl;
if (!initOpenGL())
{
std::cerr << "GLFW initialisation failed." << std::endl;
return -1;
}
/* Enable depth testing */
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LESS);
/* Enable back-face culling */
glEnable(GL_CULL_FACE);
glCullFace(GL_BACK);
/* Enable transparency blending */
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
/* Choose a colour to clear the screen (RGBA range [0, 1]) */
glClearColor(0.4f, 0.5f, 0.6f, 1.0f);
/* Cube */
float cubeSize = 0.5f;
glm::vec3 cube_pos = glm::vec3(0.f, 0.f, -2.f); // Position in World Space
glm::vec3 cube_head = glm::vec3(0.f, 0.f, 1.f);
glm::vec3 cube_fixup = glm::vec3(0.f, 1.f, 0.f);
glm::vec3 cube_up = cube_fixup;
glm::vec3 cube_direction;
glm::vec3 cube_right;
glm::mat4 cube_rotation;
/* Set mouse start position at centre of window */
glfwSetCursorPos(window, WINDOW_WIDTH / 2, WINDOW_HEIGHT / 2);
double mouseX, mouseY;
glfwGetCursorPos(window, &mouseX, &mouseY);
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_HIDDEN);
float sensitivity = 0.01f;
float cubeSpeed = 0.001f;
//camera
/* Vectors containing eye coordinates */
glm::vec3 pos;
/* Loop until the user closes the window */
while (!glfwWindowShouldClose(window))
{
/* Render here */
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
/* Projection */
glViewport(0, 0, WINDOW_WIDTH, WINDOW_HEIGHT);
glMatrixMode(GL_PROJECTION); // switch from model/view to projection mode
glLoadIdentity(); // reset matrix
/* Perspective projection */
float aspectRatio = static_cast<GLdouble>(WINDOW_WIDTH) / static_cast<GLdouble>(WINDOW_HEIGHT);
//gluPerspective(60.0, aspect, 1.0, 1000.0);
float znear = 0.1f;
float zfar = 1000.f;
float fovyInDegrees = 60.f;
glm::mat4 proj = glm::perspective(glm::radians(fovyInDegrees), aspectRatio, znear, zfar);
float* matProjectionArray = glm::value_ptr(proj);
glLoadMatrixf(matProjectionArray);
/* Set modelview matrix as the current matrix */
glMatrixMode(GL_MODELVIEW);
/* Reset the current matrix */
glLoadIdentity();
/* Camera */
pos = cube_pos + (cube_up* 1.f) + (cube_direction * -2.f);
glm::vec3 cameraDirection = glm::normalize(cube_direction);
glm::vec3 up = glm::vec3(0.0f, 1.0f, 0.0f);
glm::vec3 cameraRight = glm::normalize(glm::cross(up, cameraDirection));
glm::vec3 cameraUp = glm::cross(cameraDirection, cameraRight);
glm::mat4 view = glm::mat4(
cameraRight[0], cameraUp[0], -cameraDirection[0], 0.0f,
cameraRight[1], cameraUp[1], -cameraDirection[1], 0.0f,
cameraRight[2], cameraUp[2], -cameraDirection[2], 0.0f,
0.0f, 0.0f, 0.0f, 1.0f
);
view = glm::translate(view, -pos);
float* viewArray = glm::value_ptr(view);
glLoadMatrixf(viewArray);
/* Cube */
cube_direction = glm::normalize(cube_head);
cube_right = glm::normalize(glm::cross(cube_fixup, cube_direction));
cube_up = glm::cross(cube_direction, cube_right);
cube_rotation = glm::mat4(
-cube_right[0], -cube_right[1], -cube_right[2], 0.0f,
cube_up[0], cube_up[1], cube_up[2], 0.0f,
-cube_direction[0], -cube_direction[1], -cube_direction[2], 0.0f,
0.0f, 0.0f, 0.0f, 1.0f
);
// Mouse input
double xpos, ypos;
glfwGetCursorPos(window, &xpos, &ypos);
cube_head = cube_head + cube_right * (float)((xpos - mouseX) * sensitivity);
cube_head = cube_head + cube_up * (float)(-(ypos - mouseY) * sensitivity);
mouseX = xpos;
mouseY = ypos;
// Key input
if (wKey)
{
cube_pos = cube_pos + cube_direction * cubeSpeed;
}
if (sKey)
{
cube_pos = cube_pos + cube_direction * -cubeSpeed;
}
if (aKey)
{
cube_pos = cube_pos + cube_right * -cubeSpeed;
}
if (dKey)
{
cube_pos = cube_pos + cube_right * cubeSpeed;
}
glPushMatrix(); // save transformation state
//Do not add translate into rotation matrix as this will translate object origin coordinate
//cube_rotation = glm::translate(p1_rotation, p1_pos);
glTranslatef(cube_pos[0], cube_pos[1], cube_pos[2]); // Apply translation
glMultMatrixf(glm::value_ptr(cube_rotation)); // Apply rotation
drawSolidCube(cubeSize); // draw a cube
glPopMatrix(); // restore transformation state
glPushMatrix();
drawSolidCube(cubeSize); // draw a stationary cube for comparison
glPopMatrix();
/* Swap front and back buffers */
glfwSwapBuffers(window);
/* Poll for and process events */
glfwPollEvents();
}
glfwTerminate();
return 0;
}
bool initOpenGL()
{
/* Initialize the GLFW library */
if (!glfwInit()) {
std::cout << "GLFW initialisation failed." << std::endl;
return false;
}
glfwSetErrorCallback(error_callback);
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_COMPAT_PROFILE);
/* For macOS uncomment the following line */
//glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
/* Create a windowed mode window and its OpenGL context */
window = glfwCreateWindow(WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_TITLE, NULL, NULL);
if (!window)
{
std::cout << "GLFW failed to create window." << std::endl;
glfwTerminate();
return false;
}
/* Make the window's context current */
glfwMakeContextCurrent(window);
glfwSetKeyCallback(window, key_callback);
/* Initialize the GLEW library */
glewExperimental = GL_TRUE;
GLenum err = glewInit();
if (err != GLEW_OK)
{
/* Problem: glewInit failed, something is seriously wrong */
std::cout << "GLEW initialisation failed: " << glewGetErrorString(err) << std::endl;
return false;
}
std::cout << "Status: Using GLEW " << glewGetString(GLEW_VERSION) << std::endl;
return true;
}
void drawSolidCube(float r)
{
glBegin(GL_QUADS);
// Back face (z = r)
glColor4f(1.0f, 0.0f, 0.0f, 0.5f); // Red
glVertex3f(r, r, r);
glVertex3f(r, -r, r);
glVertex3f(-r, -r, r);
glVertex3f(-r, r, r);
// Near face (z = -r)
glColor4f(0.0f, 1.0f, 0.0f, 0.5f); // Green
glVertex3f(r, r, -r);
glVertex3f(-r, r, -r);
glVertex3f(-r, -r, -r);
glVertex3f(r, -r, -r);
// Right face (x = r)
glColor4f(0.0f, 0.0f, 1.0f, 0.5f); // Blue
glVertex3f(r, r, r);
glVertex3f(r, r, -r);
glVertex3f(r, -r, -r);
glVertex3f(r, -r, r);
// Left face (x = -r)
glColor4f(1.0f, 1.0f, 0.0f, 0.5f); // Yellow
glVertex3f(-r, r, r);
glVertex3f(-r, -r, r);
glVertex3f(-r, -r, -r);
glVertex3f(-r, r, -r);
// Top face (y = r)
glColor4f(1.0f, 0.0f, 1.0f, 0.5f); // Magenta
glVertex3f(r, r, r);
glVertex3f(-r, r, r);
glVertex3f(-r, r, -r);
glVertex3f(r, r, -r);
// Bottom face (y = -r)
glColor4f(0.0f, 1.0f, 1.0f, 0.5f); // Cyan
glVertex3f(r, -r, r);
glVertex3f(r, -r, -r);
glVertex3f(-r, -r, -r);
glVertex3f(-r, -r, r);
glEnd();
}
void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods)
{
if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS)
{
std::cout << "Esc key is pressed." << std::endl;
glfwSetWindowShouldClose(window, GL_TRUE);
}
if (key == GLFW_KEY_W && action == GLFW_PRESS)
{
wKey = true;
}
if (key == GLFW_KEY_W && action == GLFW_RELEASE)
{
wKey = false;
}
if (key == GLFW_KEY_S && action == GLFW_PRESS)
{
sKey = true;
}
if (key == GLFW_KEY_S && action == GLFW_RELEASE)
{
sKey = false;
}
if (key == GLFW_KEY_A && action == GLFW_PRESS)
{
aKey = true;
}
if (key == GLFW_KEY_A && action == GLFW_RELEASE)
{
aKey = false;
}
if (key == GLFW_KEY_D && action == GLFW_PRESS)
{
dKey = true;
}
if (key == GLFW_KEY_D && action == GLFW_RELEASE)
{
dKey = false;
}
if (key == GLFW_KEY_SPACE && action == GLFW_PRESS)
{
glLoadIdentity();
}
}
NOTE I know that my plane and the cylinder are badly built but their purpose is just to have something to see on the screen. Considering (px,py,pz), the camera position, and (dx, dy, dz), the view direction.
Important: My camera should follow a structure similar to the one I implemented here, so I can't use glRotate, glTranslate everything has to be done manually, the imposition of my teacher sadly, And also I am using Visual Studio.
FIX: My translations are all ok now I fixed a thing in the case GLUT_KEY_LEFT and GLUT_KEY_RIGTH.
Problem: Now the remaning problem is in the mouse_motion, when I click with left mouse button and drag the mouse around the screen my camera changes it direction really fast and sometimes when I go up it faces down its strange and hard to describe XD.
Warning: Warning C26451 Arithmetic overflow: Using operator '+' on a 4 byte value and then casting the result to a 8 byte value. Cast the value to the wider type before calling operator '+' to avoid overflow (io.2). class2 main.cpp 199 .
This is my the line that says gluLookAt(px, py, pz, px+dx, py+dy, pz+dz, 0.0f, 1.0f, 0.0f); How can I fix it?
Camera: I just want the motion of the mouse to allow me to define the direction I want to go and use the up, down, left, right keys to move.
#include <math.h>
#include <ctime>
#include <iostream>
#ifdef __APPLE__
#include <GLUT/glut.h>
#else
#include <GL/glut.h>
#endif
#define PI 3.1415926535897932384626433832795
//For Camera
#define GlUT_KEY_UP 72
#define KEY_DOWN 80
#define KEY_LEFT 75
#define KEY_RIGHT 77
// angle of rotation for the camera direction
float angle = 0.0f; //alpha
float angle1 = 0.0f; //beta
// actual vector representing the camera's direction
float dx = 0.0f;
float dy = 0.0f;
float dz = 1.0f;
// XZ position of the camera
float px = 0.0f;
float py = 0.0f;
float pz = 10.0f;
float speed = 1.0f;
float rotateSpeed = 0.0008f;
//For FPS
int timebase;
float frame;
void changeSize(int w, int h) {
// Prevent a divide by zero, when window is too short
// (you cant make a window with zero width).
if(h == 0)
h = 1;
// compute window's aspect ratio
float ratio = w * 1.0 / h;
// Set the projection matrix as current
glMatrixMode(GL_PROJECTION);
// Load Identity Matrix
glLoadIdentity();
// Set the viewport to be the entire window
glViewport(0, 0, w, h);
// Set perspective
gluPerspective(45.0f ,ratio, 1.0f ,1000.0f);
// return to the model view matrix mode
glMatrixMode(GL_MODELVIEW);
}
// Draw Figures
void drawAxis() {
glBegin(GL_LINES);
// X axis in Red
glColor3f(1.0f, 0.0f, 0.0f);
glVertex3f(100.0f, 0.0f, 0.0f);
glVertex3f(-100.0f, 0.0f, 0.0f);
// Y Axis in Green
glColor3f(0.0f, 1.0f, 0.0f);
glVertex3f(0.0f, 100.0f, 0.0f);
glVertex3f(0.0f, -100.0f, 0.0f);
// Z Axis in Blue
glColor3f(0.0f, 0.0f, 1.0f);
glVertex3f(0.0f, 0.0f, 100.0f);
glVertex3f(0.0f, 0.0f, -100.0f);
glEnd();
}
void drawPlane(float width) {
width/=2;
glBegin(GL_TRIANGLE_FAN);
glColor3f(4.0f, 1.0f, 1.0f);
glVertex3d(width, 0,width);
glVertex3d(width, 0, -width);
glVertex3d(-width, 0,-width);
glColor3f(3.0f, 1.0f, 0.0f);
glVertex3d(width, 0, width);
glVertex3d(-width, 0, -width);
glVertex3d(-width, 0, width);
glColor3f(0.0f, 0.0f, 1.0f);
glVertex3d(width, 0, -width);
glVertex3d(width, 0, width);
glVertex3d(-width, 0, -width);
glColor3f(1.0f, 1.0f, 1.0f);
glVertex3d(-width, 0, -width);
glVertex3d(width, 0, width);
glVertex3d(-width, 0, width);
glEnd();
}
void drawCylinder(float radius, float height, int slices) {
float interval = 2 * PI / slices;
float next_a, next_h;
for (float a = 0; a < 2 * PI; a += interval) {
next_a = a + interval;
if (next_a > 2 * PI) {
next_a = 2 * PI;
}
glBegin(GL_TRIANGLES);
//Top
glColor3f(0.698f, 0.133f, 0.133f);
glVertex3f(0.0f, height / 2, 0.0f);
glVertex3f(radius * sin(a), height / 2, radius * cos(a));
glVertex3f(radius * sin(next_a), height / 2, radius * cos(next_a));
//Bottom
glColor3f(0.698f, 0.133f, 0.133f);
glVertex3f(0.0f, -height / 2, 0.0f);
glVertex3f(radius * sin(next_a), -height / 2, radius * cos(next_a));
glVertex3f(radius * sin(a), -height / 2, radius * cos(a));
for (float h = -height / 2; h < height / 2; h += height) {
next_h = h + height;
if (next_h > height / 2) {
next_h = height / 2;
}
//Walls
glColor3f(1.0f, 0.271f, 0.0f);
glVertex3f(radius * sin(next_a), next_h, radius * cos(next_a));
glVertex3f(radius * sin(a), next_h, radius * cos(a));
glVertex3f(radius * sin(next_a), h, radius * cos(next_a));
glColor3f((a + 0.05) / (2 * PI), (a + 0.3) / (2 * PI), (h + height / 2) / height);
glVertex3f(radius * sin(a), next_h, radius * cos(a));
glVertex3f(radius * sin(a), h, radius * cos(a));
glVertex3f(radius * sin(next_a), h, radius * cos(next_a));
}
glEnd();
}
}
void renderScene(void) {
// clear buffers
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// set the camera
glLoadIdentity();
//FPS Camera
gluLookAt(px, py, pz, px+dx, py+dy, pz+dz, 0.0f, 1.0f, 0.0f);
// put the geometric transformations here
// put drawing instructions here
drawAxis();
drawPlane(4);
drawCylinder(1,3,30);
//FPS counter
frame++;
int final_time = glutGet(GLUT_ELAPSED_TIME);
if (final_time - timebase > 1000) {
int fps = frame * 1000.0f / (final_time - timebase);
char title[(((sizeof fps) * CHAR_BIT) + 2) / 3 + 2];
sprintf(title,"FPS: %d", fps);
glutSetWindowTitle(title);
timebase = final_time;
frame = 0;
}
// End of frame
glutSwapBuffers();
}
//FPS Camera
void move(int key, int x, int y) {
switch (key) {
case GLUT_KEY_RIGHT: {
px -= (dz * speed);
pz += (dx * speed);
break;
}
case GLUT_KEY_LEFT: {
px += (dz * speed);
pz -= (dx * speed);
break;
}
case GLUT_KEY_UP: {
px += (dx * speed);
pz += (dz * speed);
break;
}
case GLUT_KEY_DOWN: {
px -= (dx * speed);
pz -= (dz * speed);
break;
}
default: {
break;
}
}
glutPostRedisplay();
}
void mouse_motion(int x, int y) {
float lx = x - 800;
float ly = y - 800;
angle = angle + lx * rotateSpeed;
angle1 = angle1 + ly * rotateSpeed;
dx = cos(angle1) * sin(angle);
dy = sin(angle1);
dz = cos(angle1) * cos(angle);
}
int main(int argc, char **argv) {
// init GLUT and the window
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DEPTH|GLUT_DOUBLE|GLUT_RGBA);
glutInitWindowPosition(100,100);
glutInitWindowSize(800,800);
glutCreateWindow("CG");
// Required callback registry
glutIdleFunc(renderScene);
glutDisplayFunc(renderScene);
glutReshapeFunc(changeSize);
//FPS
timebase = glutGet(GLUT_ELAPSED_TIME);
// put here the registration of the keyboard callbacks
glutSpecialFunc(move);
glutMotionFunc(mouse_motion);
//glutPassiveMotionFunc(mouse_motion);
// OpenGL settings
glEnable(GL_DEPTH_TEST);
glEnable(GL_CULL_FACE);
// enter GLUT's main cycle
glutMainLoop();
return 1;
}
I want to make the codes that draw trajectory as the object's moving when I clicked any position on the screen.
I set the initial center point as a starting point. And I want to set the other point with mouse button clicked (destination point) as variables but I can't figure out how to do this.
float v1[3] = { -35.0f, 22.5f, 0.0f };
float v2[3] = { -35.0f, -22.5f, 0.0f };
float v3[3] = { 0.0f, 42.5f, 0.0f };
float v4[3] = { 0.0f, -42.5f, 0.0f };
float v5[3] = { 35.0f, 22.5f, 0.0f };
float v6[3] = { 35.0f, -22.5f, 0.0f };
This is the initial position of the object. (6-point star with 2 triangles)
float px, py;
float center_s[3] = { 0.0f, 0.0f, 0.0f };
float center_d[3] = { px, py, 0.0f };
center_s is the starting point and center_d is the destination point with variable px, py.
void lines(void) {
glColor3f(1.0, 0.0, 0.0);
glPointSize(5);
glBegin(GL_POINTS);
glVertex3fv(center_s);
glLineWidth(1);
glBegin(GL_LINES);
glVertex3fv(center_s);
glVertex3fv(center_d);
}
This function draws trajectory with red lines from center_s to center_d. Also it draws a center point.
case GLUT_LEFT_BUTTON:
if (state == GLUT_DOWN) {
x = mx;
y = glutGet(GLUT_WINDOW_HEIGHT) - my;
px = x + 35.0;
py = y + 42.5;
glutIdleFunc(lines);
}
glutPostRedisplay();
break;
Here is the problem. When the left mouse button is pressed, the star has to move to the clicked position and calculates the center point of the position and draw the line. But if I run these codes, the movement trajectory is not drawn.
Please let me know what the problem is. Plus, the star must move at a constant speed to the clicked location. (Not teleportation)
Following is the full codes:
#include <stdlib.h>
#include <GL/glut.h>
float v1[3] = { -35.0f, 22.5f, 0.0f };
float v2[3] = { -35.0f, -22.5f, 0.0f };
float v3[3] = { 0.0f, 42.5f, 0.0f };
float v4[3] = { 0.0f, -42.5f, 0.0f };
float v5[3] = { 35.0f, 22.5f, 0.0f };
float v6[3] = { 35.0f, -22.5f, 0.0f };
float px, py;
float center_s[3] = { 0.0f, 0.0f, 0.0f };
float center_d[3] = { px, py, 0.0f };
static GLfloat spin = 0.0;
float x = 400.0f, y = 442.5f;
float color1[3] = { 1.0f, 1.0f, 1.0f };
float color2[3] = { 1.0f, 1.0f, 1.0f };
int mode = 1;
int rotate = 1;
void init(void);
void triangle_1(void);
void triangle_2(void);
void lines(void);
void display(void);
void spinDisplay_1(void);
void spinDisplay_2(void);
void reshape(int, int);
void changeColor(int);
void mouse(int, int, int, int);
////////////////////////////////////////////////////////////////////
int main(int argc, char **argv) {
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);
glutInitWindowSize(500, 500);
glutInitWindowPosition(300, 300);
glutCreateWindow("6-Point Star");
init();
glutDisplayFunc(display);
glutReshapeFunc(reshape);
glutMouseFunc(mouse);
glutMainLoop();
return 0;
}
////////////////////////////////////////////////////////////////////
void init(void) {
glClearColor(0.0, 0.0, 0.0, 0.0);
glShadeModel(GL_FLAT);
}
void triangle_1(void) {
glColor3fv(color1);
glBegin(GL_TRIANGLE_FAN);
glVertex3fv(v1);
glVertex3fv(v4);
glVertex3fv(v5);
glEnd();
}
void triangle_2(void) {
glColor3fv(color2);
glBegin(GL_TRIANGLE_FAN);
glVertex3fv(v2);
glVertex3fv(v3);
glVertex3fv(v6);
glEnd();
}
void lines(void) {
glColor3f(1.0, 0.0, 0.0);
glPointSize(5);
glBegin(GL_POINTS);
glVertex3fv(center_s);
glLineWidth(1);
glBegin(GL_LINES);
glVertex3fv(center_s);
glVertex3fv(center_d);
}
void display(void) {
glClear(GL_COLOR_BUFFER_BIT);
glPushMatrix();
glTranslatef(x, y, 0.0f);
glRotatef(spin, 0.0, 0.0, 1.0);
triangle_1();
triangle_2();
glPopMatrix();
glutSwapBuffers();
}
void spinDisplay_1(void) {
spin = spin + 2.0;
if (spin > 360.0) {
spin = spin - 360.0;
}
glutPostRedisplay();
}
void spinDisplay_2(void) {
spin = spin - 2.0;
if (spin < 360.0) {
spin = spin + 360.0;
}
glutPostRedisplay();
}
void reshape(int w, int h) {
glViewport(0, 0, (GLsizei)w, (GLsizei)h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(0.0, 500.0, 0.0, 500.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
void changeColor(int n) {
if (n == 1) {
color1[0] = 0.0f, color1[1] = 0.0f, color1[2] = 1.0f;
color2[0] = 0.0f, color2[1] = 1.0f, color2[2] = 0.0f;
}
else if (n == 2) {
color1[0] = 1.0f, color1[1] = 1.0f, color1[2] = 1.0f;
color2[0] = 1.0f, color2[1] = 1.0f, color2[2] = 1.0f;
}
}
void mouse(int button, int state, int mx, int my) {
switch (button) {
case GLUT_LEFT_BUTTON:
if (state == GLUT_DOWN) {
x = mx;
y = glutGet(GLUT_WINDOW_HEIGHT) - my;
px = x + 35.0;
py = y + 42.5;
glutIdleFunc(lines);
}
glutPostRedisplay();
break;
case GLUT_MIDDLE_BUTTON:
if (state == GLUT_DOWN) {
if (mode == 1) {
changeColor(mode);
mode = 2;
}
else if (mode == 2) {
changeColor(mode);
mode = 1;
}
}
glutPostRedisplay();
break;
case GLUT_RIGHT_BUTTON:
if (state == GLUT_DOWN)
if (rotate == 1) {
glutIdleFunc(spinDisplay_1);
rotate = 2;
}
else if (rotate == 2) {
glutIdleFunc(spinDisplay_2);
rotate = 1;
}
break;
default:
break;
}
}
You're missing a few glEnd() and unless you have other plans for center_s and center_d then you don't need them. As x and y is center_s, while px and py is center_d.
So first of all in mouse() just assign the mouse position to px and py instead of x and y.
case GLUT_LEFT_BUTTON:
if (state == GLUT_DOWN) {
px = mx;
py = glutGet(GLUT_WINDOW_HEIGHT) - my;
}
Now next you need a way to obtain the delta time. Delta time is the time passed since the last frame. For ease I added the following code to the top of display().
int timeNow = glutGet(GLUT_ELAPSED_TIME);
float delta = (float)(timeNow - timeLastFrame) / 1000.0f;
timeLastFrame = timeNow;
Remember to declare int timeLastFrame = 0; among your global variables.
Now (still in display()) we can calculate the direction of the travel path. We do this by calculating the difference between the two points. Then calculate the length and normalize the difference.
float dx = px - x;
float dy = py - y;
float length = sqrt(dx * dx + dy * dy);
dx /= length;
dy /= length;
Now you just put it all together.
if (length > 1.0f) {
x += dx * speed * delta;
y += dy * speed * delta;
}
So while length > 1.0 then we move towards px and py at the speed of float speed = 100.0f; (declare this among your global variables as well).
Just to reemphasize. Yes, do delete glutIdleFunc(lines) from mouse(). Then we add it in display() instead. The full extend of display() should look like this now:
void display(void) {
int timeNow = glutGet(GLUT_ELAPSED_TIME);
float delta = (float)(timeNow - timeLastFrame) / 1000.0f;
timeLastFrame = timeNow;
float dx = px - x;
float dy = py - y;
float length = sqrt(dx * dx + dy * dy);
dx /= length;
dy /= length;
if (length > 1.0f) {
x += dx * speed * delta;
y += dy * speed * delta;
}
glClear(GL_COLOR_BUFFER_BIT);
glPushMatrix();
glTranslatef(x, y, 0.0f);
glRotatef(spin, 0.0, 0.0, 1.0);
triangle_1();
triangle_2();
glPopMatrix();
lines();
glutSwapBuffers();
glutPostRedisplay();
}
Remember glutPostRedisplay(). If not then it won't redraw and thus not animate. Also remember to #include <math.h> for sqrt().
Everything before glClear() could be moved to your glutIdleFunc() callback.
Since there was no need for center_s and center_d then lines() can be boiled down to:
void lines(void) {
glColor3f(1.0, 0.0, 0.0);
glPointSize(5);
glBegin(GL_POINTS);
glVertex2f(px, py);
glEnd();
glLineWidth(1);
glBegin(GL_LINES);
glVertex2f(x, y);
glVertex2f(px, py);
glEnd();
}
The result should look something like this:
For future reference. If you don't want to do the linear algebra by hand. Then you can use something like GLM.
I'm trying to play around with OpenGL and this is my very first code. How can I change to different view to 2 object drawn on the screen?
Is there anyway to do this manually, in stead of using function gluPerspective()?
I tried glRotatef(60, 0.0, 0.0, 5.0) but there is nothing happen. Cos I want to see other faces of the Pyramid and also different view of the rotating sphere.
Also I want to set different colours to different objects that I draw on the screen, how can I do that?
The code to set colour for each object, which is glColor3f, I put it in between glPushMatrix() and glPopMatrix(), also I always include the line glLoadIdentity() before starting draw objects on screen. As far as I know, this line will reset the settings of the previous objects and allows me to set new properties for new object.
Then why when I press button D, the sphere is blue when it supposes to be in white?
Here is my full code:
#include <windows.h>
#include <GL/glew.h>
#include <GL/gl.h>
#include <math.h>
#include <GLFW/glfw3.h>
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#define X .525731112119133606
#define Z .850650808352039932
#define Y 0.0
#define PI 3.1415926535898
#define CIRCLE_STEP 5000
using namespace std;
// Open an OpenGL window
GLFWwindow* window;
int keyboard = 0, itr;
bool big_Sphere = true, sphereWithNormalV = false, animation = false;
GLdouble angle = 0;
/****Step 1: define vertices in (x, y, z) form****/
// Coordinates to draw a Icosahedron
GLfloat icoVertices[12][3] = {
{-X, Y, Z}, {X, Y, Z}, {-X, Y, -Z}, {X, Y, -Z},
{Y, Z, X}, {Y, Z, -X}, {Y, -Z, X}, {Y, -Z, -X},
{Z, X, Y}, {-Z, X, Y}, {Z, -X, Y}, {-Z, -X, Y}
};
// Coordinates to draw a Pyramid
GLfloat pyVertices[4][3] = {
{0.0f, 1.0f, 0.0f},
{1.0f, 0.0f, 0.0f},
{-1.0f, 0.0f, 0.0f},
{0.0f, 0.0f, -1.0f}
};
static GLuint icoIndices[20][3] = {
{0,4,1}, {0,9,4}, {9,5,4}, {4,5,8}, {4,8,1},
{8,10,1}, {8,3,10}, {5,3,8}, {5,2,3}, {2,7,3},
{7,10,3}, {7,6,10}, {7,11,6}, {11,0,6}, {0,1,6},
{6,1,10}, {9,0,11}, {9,11,2}, {9,2,5}, {7,2,11} };
static GLuint pyIndices[4][3] = {
{0,1,2}, {0,1,3}, {0,2,3}, {1,2,3}
};
/************************/
void normalize3f(float v[3]) {
GLfloat d = sqrt(v[0]*v[0]+v[1]*v[1]+v[2]*v[2]);
if (d == 0.0) {
fprintf(stderr, "zero length vector");
return;
}
v[0] /= d; v[1] /= d; v[2] /= d;
}
void sphereNormalV(GLfloat p1[3], GLfloat p2[3], GLfloat p3[3])
{
glBegin(GL_LINES);
glVertex3f(p1[0] *1.5,p1[1] *1.5, p1[2] *1.5);
glVertex3fv(p1);
glEnd();
glBegin(GL_LINES);
glVertex3f(p2[0] *1.1,p2[1] *1.1, p2[2] *1.1);
glVertex3fv(p2);
glEnd();
glBegin(GL_LINES);
glVertex3f(p3[0] *1.1,p3[1] *1.1, p3[2] *1.1);
glVertex3fv(p3);
glEnd();
}
void drawtriangle(float *v1, float *v2, float *v3)
{
glBegin(GL_LINE_LOOP);
//glNormal3fv(v1);
glVertex3fv(v1);
//glNormal3fv(v2);
glVertex3fv(v2);
//glNormal3fv(v3);
glVertex3fv(v3);
glEnd();
}
void subdivide(GLfloat *v1, GLfloat *v2, GLfloat *v3, long depth)
{
GLfloat v12[3], v23[3], v31[3];
GLint i;
if (depth == 0){
drawtriangle(v1, v2, v3);
if (sphereWithNormalV == true){
sphereNormalV(v1, v2, v3);
}
return;
}
for (i = 0; i < 3; i++) {
v12[i] = v1[i]+v2[i];
v23[i] = v2[i]+v3[i];
v31[i] = v3[i]+v1[i];
}
normalize3f(v12);
normalize3f(v23);
normalize3f(v31);
subdivide(v1, v12, v31, depth-1);
subdivide(v2, v23, v12, depth-1);
subdivide(v3, v31, v23, depth-1);
subdivide(v12, v23, v31, depth-1);
}
void drawSphere(GLfloat x, GLfloat y, GLfloat z){
glLoadIdentity();
glPushMatrix();
if (big_Sphere == true){
glScaled(0.4, 0.55, 0.4);
}else{
glScaled(0.13, 0.18, 0.13);
}
if (animation){
glTranslatef(x, y, z);
}
glBegin(GL_LINE_LOOP);
for (int i = 0; i < 20; i++) {
subdivide(&icoVertices[icoIndices[i][0]][0], &icoVertices[icoIndices[i][1]][0], &icoVertices[icoIndices[i][2]][0], 3);
}
glEnd();
glPopMatrix();
}
void drawPyramid(){//(GLfloat x, GLfloat y, GLfloat z){
glLoadIdentity();
glPushMatrix();
glScaled(0.13, 0.18, 0.13);
glBegin(GL_LINE_LOOP);
for (int i = 0; i < 4; i++){
glColor3f(1.0f, 0.0f, 0.0f);
glVertex3fv(pyVertices[pyIndices[i][0]]);
glColor3f(0.0f, 1.0f, 0.0f);
glVertex3fv(pyVertices[pyIndices[i][1]]);
glColor3f(0.0f, 0.0f, 1.0f);
glVertex3fv(pyVertices[pyIndices[i][2]]);
}
glEnd();
glPopMatrix();
}
int getKeyPressed(){
if (glfwGetKey(window, GLFW_KEY_A)){
keyboard = GLFW_KEY_A;
}
if (glfwGetKey(window, GLFW_KEY_B)){
keyboard = GLFW_KEY_B;
}
if (glfwGetKey(window, GLFW_KEY_C)){
keyboard = GLFW_KEY_A;
}
if (glfwGetKey(window, GLFW_KEY_D)){
keyboard = GLFW_KEY_D;
}
if (glfwGetKey(window, GLFW_KEY_E)){
keyboard = GLFW_KEY_E;
}
return keyboard;
}
void controlSphere(bool _big_Sphere, bool _sphereNormalV, bool _animation){
big_Sphere = _big_Sphere;
sphereWithNormalV = _sphereNormalV;
animation = _animation;
}
void gluPerspective(double fovy,double aspect, double zNear, double zFar)
{
// Start in projection mode.
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
double xmin, xmax, ymin, ymax;
ymax = zNear * tan(fovy * PI / 360.0);
ymin = -ymax;
xmin = ymin * aspect;
xmax = ymax * aspect;
glFrustum(xmin, xmax, ymin, ymax, zNear, zFar);
}
int main( void ) {
if (!glfwInit()){
fprintf(stderr, "Failed to initialize GLFW.\n");
return -1;
}
// Create a windowed mode window and its OpenGL context
window = glfwCreateWindow(1100, 800, "Hello World", NULL, NULL);
if (window == NULL) {
fprintf(stderr, "glfw failed to create window.\n");
//glfwTerminate();
return -1;
}
// Make the window's context current
glfwMakeContextCurrent(window);
glewInit();
if (glewInit() != GLEW_OK){
fprintf(stderr, "Failed to initialize GLEW: %s.\n", glewGetErrorString(glewInit()));
return -1;
}
// 4x anti aliasing
glfwWindowHint(GLFW_SAMPLES, 4);
/**Step 3: Main loop for OpenGL draw the shape**
/* Main loop */
int i = 0;
GLfloat pos_X, pos_Y;
glRotatef(60, 0.0f, 0.3f, 0.4f);
do{
//glMatrixMode(GL_MODELVIEW);
glClear(GL_COLOR_BUFFER_BIT);
switch(getKeyPressed()){
case 65:
controlSphere(true, false, false);
drawSphere(0, 0, 0);
break;
case 66:
controlSphere(true, true, false);
drawSphere(0, 0, 0);
break;
case 67:
// drawPyramid();
break;
case 68:
// drawing a Sphere moving in a circular path
controlSphere(false, false, true);
angle = 2*PI*i/CIRCLE_STEP;
pos_X = cos(angle) * 4.5;
pos_Y = sin(angle) * 4.5;
drawSphere(pos_X, pos_Y, 0);
i += 1;
angle += 1;
if (angle >= 360){
angle = 0;
}
// drawing a Pyramid rotate around its y axis
drawPyramid();
break;
default:
controlSphere(true, false, false);
drawSphere(0, 0, 0);
break;
}
Sleep(1);
// Swap front and back rendering buffers
glfwSwapBuffers(window);
//Poll for and process events
glfwPollEvents();
} // check if the ESC key was pressed or the window was closed
while(glfwGetKey(window, GLFW_KEY_ESCAPE) != GLFW_PRESS && glfwWindowShouldClose(window) == 0);
/***********************************************/
// Close window and terminate GLFW
glfwDestroyWindow(window);
glfwTerminate();
// Exit program
exit( EXIT_SUCCESS );
}
Is there anyway to do this manually, in stead of using function gluPerspective()?
I don't really understand this question. But if you want to set multiples objects (that have the same parameters) with different transformations, scale, rotation and/or translation, you need to push this to the stack and then draw the desired object. A good starting point can be found here: http://www.songho.ca/opengl/gl_transform.html
Also I want to set different colours to different objects that I draw on the screen, how can I do that?
Your sphere is blue because the last call for glColor3f() was in drawPyramid().
You can change the color of your ball by just calling glColor3f (1.0f, 1.0f, 1.0f); in the beginning of its draw function:
void drawSphere (GLfloat x, GLfloat y, GLfloat z)
{
glColor3f (1.0f, 1.0f, 1.0f);
...
}
A really great site to learn OpenGL from the old pipeline (what you just implemented) to the new (GLSL) is http://www.lighthouse3d.com/tutorials/.
You are looking for Multiple viewports which allows the to split the screen. In your case two different viewports two different cameras(one for each) will be enough.
Check this post.
I am new on OpenGl and what I want to achieve is to give a texture the alpha from 1.0 to 0.0
I has been searching and only found "how to load alpha in images" but I cant find how to apply alpha to an object
I has been tried with:
gl.glEnable(GL10.GL_ALPHA_TEST);
alpha += 0.002f;
if(alpha > 1) alpha = 1f;
gl.glAlphaFunc(GL10.GL_EQUAL, alpha);
But it doesnt work, How I can give alpha value(To make the effect of fade) to an object/texture?
This is my class
public class Palabra {
public float posX = 0f;
public float posY = 0f;
public float scaleX = 2f;
public float scaleY = 2f;
public float alpha= 0.5f;
public State estado;
private FloatBuffer vertexBuffer, texBuffer; // Buffer for vertex-array
private float[] vertices = { // Vertices for a face
0.0f, 0.0f, 0.2f, // 0. left-bottom-front
2.1f, 0.0f, 0.2f, // 1. right-bottom-front
0.0f, 0.35f, 0.2f, // 2. left-top-front
2.1f, 0.35f, 0.2f // 3. right-top-front
};
float[] texCoords = { // Texture coords for the above face
0.00f, 0.0f, 1.0f, // A. left-bottom
1.00f, 0.0f, 1.0f, // B. right-bottom
0.00f, 0.2f, 1.0f, // C. left-top
1.00f, 0.2f, 1.0f // D. right-top
};
public enum State {
MISS, NORMAL,GREAT,AWESOME,PERFECT;
}
public Palabra(int a) {
// Setup vertex-array buffer. Vertices in float. An float has 4 bytes
ByteBuffer vbb = ByteBuffer.allocateDirect(vertices.length * 4);
vbb.order(ByteOrder.nativeOrder()); // Use native byte order
vertexBuffer = vbb.asFloatBuffer(); // Convert from byte to float
vertexBuffer.put(vertices); // Copy data into buffer
vertexBuffer.position(0); // Rewind
// Setup texture-coords-array buffer, in float. An float has 4 bytes
// (NEW)
ByteBuffer tbb = ByteBuffer.allocateDirect(texCoords.length * 4);
tbb.order(ByteOrder.nativeOrder());
texBuffer = tbb.asFloatBuffer();
texBuffer.put(texCoords);
texBuffer.position(0);
posX = (float) 0.00f;
switch(a)
{
case 0:
posY = (float) 1f;
break;
case 1:
posY = (float) 1.5f;
break;
case 2:
posY = (float) 2f;
break;
case 3:
posY = (float) 2.5f;
break;
case 4:
posY = (float) 3f;
break;
}
}
public void draw(GL10 gl)
{
gl.glMatrixMode(GL10.GL_MODELVIEW);
gl.glLoadIdentity();
gl.glPushMatrix();
gl.glTranslatef(posX, posY, 0f);
gl.glScalef(scaleX, scaleY, 0f);
scaleX -= 0.02f;
scaleY -= 0.02f;
posX += 0.02f;
if(scaleX < 1)
{
scaleX = 1f;
posX -= 0.02f;
}
if(scaleY < 1) scaleY = 1f;
gl.glMatrixMode(GL10.GL_TEXTURE);
gl.glLoadIdentity();
switch(this.estado)
{
case AWESOME:
gl.glTranslatef(0.0f, 0.2f, 0f);
break;
case GREAT:
gl.glTranslatef(0.0f, 0.4f, 0f);
break;
case NORMAL:
gl.glTranslatef(0.0f, 0.6f, 0f);
break;
case MISS:
gl.glTranslatef(0.0f, 0.8f, 0f);
break;
case PERFECT:
break;
}
gl.glFrontFace(GL10.GL_CCW); // Front face in counter-clockwise
// orientation
gl.glEnable(GL10.GL_CULL_FACE); // Enable cull face
gl.glCullFace(GL10.GL_BACK); // Cull the back face (don't display)
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertexBuffer);
gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY); // Enable
// texture-coords-array
// (NEW)
gl.glTexCoordPointer(3, GL10.GL_FLOAT, 0, texBuffer); // Define
// texture-coords
// buffer (NEW)
gl.glEnable(GL10.GL_BLEND);
gl.glBlendFunc(GL10.GL_SRC_ALPHA, GL10.GL_ONE_MINUS_SRC_ALPHA);
// front
gl.glBindTexture(GL10.GL_TEXTURE_2D, TextureLoader.palabrasIDs[0]);
gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, 4);
gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARRAY); // Disable
// texture-coords-array
// (NEW)
gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
gl.glDisable(GL10.GL_CULL_FACE);
gl.glDisable(GL10.GL_BLEND);
gl.glPopMatrix();
}
}
I made it!
That is the code
gl.glEnable(GL10.GL_BLEND);
gl.glBlendFunc(GL10.GL_SRC_ALPHA, GL10.GL_ONE_MINUS_SRC_ALPHA);
gl.glColor4f(1f, 1f, 1f,alpha);
alpha -= 0.002f;
if(alpha < 0) alpha = 0f;