I'm very new to OpenGL. I have a simple program that allows me to have once bouncing ball. Do you know how I can tweek the code to have two or more balls bounce (using multithreads)? I'm also supposed to have the balls bounce off each other should a collision occur. Here is the code I have for one bouncing ball.
/*
* GL07BouncingBall.cpp: A ball bouncing inside the window
*/
#include <string>
#include <iostream>
#include <thread>
using namespace std;
#include <windows.h> // for MS Windows
#include <GL/glut.h> // GLUT, includes glu.h and gl.h
#include <Math.h> // Needed for sin, cos
#define PI 3.14159265f
// Global variables
char title[] = "Bouncing Ball (2D)"; // Windowed mode's title
int windowWidth = 640; // Windowed mode's width
int windowHeight = 480; // Windowed mode's height
int windowPosX = 50; // Windowed mode's top-left corner x
int windowPosY = 50; // Windowed mode's top-left corner y
GLfloat ballRadius = 0.2f; // Radius of the bouncing ball
GLfloat ballX = 0.0f; // Ball's center (x, y) position
GLfloat ballY = 0.0f;
GLfloat ballXMax, ballXMin, ballYMax, ballYMin; // Ball's center (x, y) bounds
GLfloat xSpeed = 0.02f; // Ball's speed in x and y directions
GLfloat ySpeed = 0.007f;
int refreshMillis = 30; // Refresh period in milliseconds
// Projection clipping area
GLdouble clipAreaXLeft, clipAreaXRight, clipAreaYBottom, clipAreaYTop;
/* Initialize OpenGL Graphics */
void initGL() {
glClearColor(0.0, 0.0, 0.0, 1.0); // Set background (clear) color to black
}
/* Callback handler for window re-paint event */
void display() {
glClear(GL_COLOR_BUFFER_BIT); // Clear the color buffer
glMatrixMode(GL_MODELVIEW); // To operate on the model-view matrix
glLoadIdentity(); // Reset model-view matrix
glTranslatef(ballX, ballY, 0.0f); // Translate to (xPos, yPos)
// Use triangular segments to form a circle
glBegin(GL_TRIANGLE_FAN);
glColor3f(0.0f, 0.0f, 1.0f); // Blue
glVertex2f(0.0f, 0.0f); // Center of circle
int numSegments = 100;
GLfloat angle;
for (int i = 0; i <= numSegments; i++) { // Last vertex same as first vertex
angle = i * 2.0f * PI / numSegments; // 360 deg for all segments
glVertex2f(cos(angle) * ballRadius, sin(angle) * ballRadius);
}
glEnd();
glutSwapBuffers(); // Swap front and back buffers (of double buffered mode)
// Animation Control - compute the location for the next refresh
ballX += xSpeed;
ballY += ySpeed;
// Check if the ball exceeds the edges
if (ballX > ballXMax) {
ballX = ballXMax;
xSpeed = -xSpeed;
} else if (ballX < ballXMin) {
ballX = ballXMin;
xSpeed = -xSpeed;
}
if (ballY > ballYMax) {
ballY = ballYMax;
ySpeed = -ySpeed;
} else if (ballY < ballYMin) {
ballY = ballYMin;
ySpeed = -ySpeed;
}
}
/* Call back when the windows is re-sized */
void reshape(GLsizei width, GLsizei height) {
// Compute aspect ratio of the new window
if (height == 0) height = 1; // To prevent divide by 0
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 area to match the viewport
glMatrixMode(GL_PROJECTION); // To operate on the Projection matrix
glLoadIdentity(); // Reset the projection matrix
if (width >= height) {
clipAreaXLeft = -1.0 * aspect;
clipAreaXRight = 1.0 * aspect;
clipAreaYBottom = -1.0;
clipAreaYTop = 1.0;
} else {
clipAreaXLeft = -1.0;
clipAreaXRight = 1.0;
clipAreaYBottom = -1.0 / aspect;
clipAreaYTop = 1.0 / aspect;
}
gluOrtho2D(clipAreaXLeft, clipAreaXRight, clipAreaYBottom, clipAreaYTop);
ballXMin = clipAreaXLeft + ballRadius;
ballXMax = clipAreaXRight - ballRadius;
ballYMin = clipAreaYBottom + ballRadius;
ballYMax = clipAreaYTop - ballRadius;
}
/* Called back when the timer expired */
void Timer(int value) {
glutPostRedisplay(); // Post a paint request to activate display()
glutTimerFunc(refreshMillis, Timer, 0); // subsequent timer call at milliseconds
}
/* Main function: GLUT runs as a console application starting at main() */
int main(int argc, char** argv) {
glutInit(&argc, argv); // Initialize GLUT
glutInitDisplayMode(GLUT_DOUBLE); // Enable double buffered mode
glutInitWindowSize(windowWidth, windowHeight); // Initial window width and height
glutInitWindowPosition(windowPosX, windowPosY); // Initial window top-left corner (x, y)
glutCreateWindow(title); // Create window with given title
glutDisplayFunc(display); // Register callback handler for window re-paint
glutReshapeFunc(reshape); // Register callback handler for window re-shape
glutTimerFunc(0, Timer, 0); // First timer call immediately
initGL(); // Our own OpenGL initialization
glutMainLoop(); // Enter event-processing loop
return 0;
}
**Edit:
I've added improvements to my code. I've now created two balls, each with its own speed, color, and center. Although, the two balls remain static. The function in which I create the balls is defined by:
void create(double s, GLfloat ballRadius, GLfloat ballX, GLfloat ballY, GLfloat xSpeed, GLfloat ySpeed)//, double r, double t)
{
//ballRadius = f;
//xSpeed = r;
//ySpeed = t;
glTranslatef(ballX, ballY, 0.0f); // Translate to (xPos, yPos)
glBegin(GL_TRIANGLE_FAN);
glColor3f(s, 0.0f, 1.0f); // Blue
glVertex2f(0.0, 0.0f); // Center of circle
int numSegments = 100;
GLfloat angle;
for (int i = 0; i <= numSegments; i++) { // Last vertex same as first vertex
angle = i * 2.0f * PI / numSegments; // 360 deg for all segments
glVertex2f(cos(angle) * ballRadius, sin(angle) * ballRadius);
}
glEnd();
// Animation Control - compute the location for the next refresh
ballX += xSpeed;
ballY += ySpeed;
// Check if the ball exceeds the edges
if (ballX > ballXMax) {
ballX = ballXMax;
xSpeed = -xSpeed;
} else if (ballX < ballXMin) {
ballX = ballXMin;
xSpeed = -xSpeed;
}
if (ballY > ballYMax) {
ballY = ballYMax;
ySpeed = -ySpeed;
} else if (ballY < ballYMin) {
ballY = ballYMin;
ySpeed = -ySpeed;
}
}
And I call this function by:
create(1.0, 0.2f, 0.0f, 0.0f, 0.02f, 0.007f);
create(0.0, 0.1f, 0.0f, 0.0f, 0.04f, 0.014f);
for two separate balls
This code "creates" a circle
// Use triangular segments to form a circle
glBegin(GL_TRIANGLE_FAN);
glColor3f(0.0f, 0.0f, 1.0f); // Blue
glVertex2f(0.0f, 0.0f); // Center of circle
int numSegments = 100;
GLfloat angle;
for (int i = 0; i <= numSegments; i++) { // Last vertex same as first vertex
angle = i * 2.0f * PI / numSegments; // 360 deg for all segments
glVertex2f(cos(angle) * ballRadius, sin(angle) * ballRadius);
}
glEnd();
Related
I am trying to scroll a text as a banner. I used openGL with glut to make this work. The whole code works if I use a figure like a square. The square scrolls over the screen.
Now I want to do this with text. Every time this program started. The text came at its starting position, but when the timer starts, it vanished. This is probably because the screen was cleared every clocktick, but the screen doesn't build up again.
Someone who can help me with this translation animation and text?
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <iostream>
#ifdef WIN32
#include <windows.h>
#endif
#include <GL/gl.h>
#include <GL/glut.h>
using namespace std;
static int font_index = 0;
int state = 1;
void print_bitmap_string(/*void* font,*/ const char* s)
{
while (*s) {
glutBitmapCharacter(GLUT_BITMAP_TIMES_ROMAN_24, *s);
s++;
}
}
void my_reshape(int w, int h)
{
GLdouble size;
GLdouble aspect;
/* Use the whole window. */
glViewport(0, 0, w, h);
/* We are going to do some 2-D orthographic drawing. */
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
size = (GLdouble)((w >= h) ? w : h) / 2.0;
if (w <= h) {
aspect = (GLdouble)h / (GLdouble)w;
glOrtho(-size, size, -size * aspect, size * aspect, -100000.0, 100000.0);
}
else {
aspect = (GLdouble)w / (GLdouble)h;
glOrtho(-size * aspect, size * aspect, -size, size, -100000.0, 100000.0);
}
/* Make the world and window coordinates coincide so that 1.0 in */
/* model space equals one pixel in window space. */
glScaled(aspect, aspect, 1.0);
/* Now determine where to draw things. */
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
float yild;
float ystep;
float x_pos = -200;
float y_pos = 70;
void draw()
{
const char* bitmap_font_names[7] = { "Hello train" };
/* Draw the strings, according to the current mode and font. */
glTranslatef(0.5, -100, 0);
//set the text color
glColor4f(0.0f, 255.0f, 140.0f, 1.0f);
ystep = 100.0;
yild = 20.0;
glRasterPos2f(x_pos, y_pos + 1.25 * yild);
print_bitmap_string(bitmap_font_names[0]);
}
void display(void)
{
//change background color
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glClear(GL_COLOR_BUFFER_BIT);
draw();
glColor3f(0.0, 1.0, 0.0);
glBegin(GL_POLYGON);
glVertex2f(x_pos + 0.5f, 0.0f);
glVertex2f(x_pos+1.0f, 0.5f);
glVertex2f(x_pos+0.5f, 0.5f);
glEnd();
glutSwapBuffers();
}
void timer(int) {
glutPostRedisplay();
glutTimerFunc(1000 , timer, 0);
switch (state) {
case 1:
if (x_pos > -295) {
x_pos -= 1;
}
else {
state = -1;
}
break;
case -1:
x_pos = 180;
state = 1;
break;
}
cout << x_pos << endl;
}
int main(int argc, char** argv)
{
glutInitWindowSize(500, 150);
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE);
glutCreateWindow("Train Display");
glutDisplayFunc(display);
glutReshapeFunc(my_reshape);
glutTimerFunc(1000, timer, 0);
glutMainLoop();
return 0;
}
glTranslate does not just set a translation matrix, but multiply the current matrix by a translation matrix. You need to load the identity matrix with glLoadIdentity before glTranslatef or save and restore the current matrix with glPushMatrix/glPopMatrix:
void draw()
{
const char* bitmap_font_names[7] = { "Hello train" };
glPushMatrix();
/* Draw the strings, according to the current mode and font. */
glTranslatef(0.5, -100, 0);
//set the text color
glColor4f(0.0f, 255.0f, 140.0f, 1.0f);
ystep = 100.0;
yild = 20.0;
glRasterPos2f(x_pos, y_pos + 1.25 * yild);
print_bitmap_string(bitmap_font_names[0]);
glPopMatrix();
}
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'm trying to make a program where I'm able to zoom in & out on the figures I've drawn, but is not doing it; it's switching the orientation of the figures and if I keep scrolling, it just disappears. The function that are suppose to be executed for this to work are the MouseFunc() along with the renderScene(). Any explanation for the problem or help is welcomed.
#include"glut.h"
#include<cmath>
#include<iostream>
using namespace std;
float xr = 0, yr = 0; //to control the object's movement from left to right
// XZ position of the camera
float x = 0.0f, z = 5.0f; //Module 4
float angleX = 0.0f; //Module 4
//Shift + ArrowKey rotation
float transX = 0.0f;
float transY = 0.0f;
float rotY = 0.0f;
//end
//Mouse Commands
//float ZoomFactor = 0.5;
GLfloat theta3 = 0;
GLfloat phi = 0;
GLfloat rho = 5;
GLfloat camX = 0;
GLfloat camY = 0;
GLfloat camZ = 0;
GLfloat upX = 0;
GLfloat upY = 0;
GLfloat upZ = 0;
//end
GLfloat angle = 0.0f;
int refreshmill = 1;
void timer(int value) { //to control the rotation of the object
glutTimerFunc(refreshmill, timer, 0);
}
void myDisplay(void) {
//Circle One
float theta;
glClear(GL_COLOR_BUFFER_BIT);
glColor3f(1, 0, 0);
glPushMatrix();
glBegin(GL_POLYGON);
for (int x = 0; x < 360; x++) {
theta = x * 3.142 / 180;
glVertex2f(150 * cos(theta) + xr, 150 * sin(theta) + yr);
}
glEnd();
glPopMatrix();
//Circle Two
float theta2;
glPushMatrix();
glTranslatef(0.5f, 0.0f, 0.0f); // rotation
glRotatef(angle, 0.0f, 0.0f, -0.5f); // rotation
glBegin(GL_POLYGON);
glColor3f(0, 0, 1);
for (int x = 0; x < 360; x++) {
theta2 = x * 3.142 / 180;
glVertex2f(150 + 15 * cos(theta2) + xr, 15 * sin(theta2) + yr);
}
angle += 0.2; // rotation
glEnd();
glPopMatrix();
//Draw Star
glColor3ub(119, 193, 15);
glPushMatrix();
glBegin(GL_POLYGON);
glVertex2d(15 + xr, 60 + yr);
glVertex2d(75 + xr, 75 + yr); //right peak
glVertex2d(15 + xr, 90 + yr);
glVertex2d(0 + xr, 150 + yr); //Up-peak Changed
glVertex2d(-15 + xr, 90 + yr);
glVertex2d(-75 + xr, 75 + yr);
glVertex2d(-15 + xr, 60 + yr);
glVertex2d(0 + xr, 0 + yr);
glEnd();
glPopMatrix();
}
//Close code
void handleKeypress(unsigned char key, int x, int y){
switch (key){
case 27: //when the escape key is pressed the program will exit.
exit(0);
}
}
//Movement of drawing
void keyboard(int key, int x, int y) {
float fraction = 0.1f;
bool shift = false;
int mod = glutGetModifiers();
if (mod == GLUT_ACTIVE_SHIFT) {
shift = true;
}
if (!shift) {
switch (key) {
case GLUT_KEY_RIGHT: xr++; break;
case GLUT_KEY_LEFT: xr--; break;
case GLUT_KEY_UP: angleX -= 1.0f; break; //Module 4
case GLUT_KEY_DOWN: angleX += 1.0f; break; //Module 4
}
}
else {
switch (key) {
case GLUT_KEY_LEFT:// Rotación del dibujo hacia la izquierda en el eje de Y
rotY -= 1.0f;
break;
case GLUT_KEY_RIGHT:// Rotación del dibujo hacia la derecha en el eje de Y
rotY += 1.0f;
break;
}
}
}
//Mouse Function
void MouseFunc(int button, int state, int x, int y){
if (button > 4){
rho = rho + 3.0;
}
else (button < 3);{
rho = rho - 3.0;
}
}
void renderScene(void) {
glClear(GL_COLOR_BUFFER_BIT);
glColor3f(0.0, 1.0, 0.0);
glRotatef(rotY, 0.0, 1.0, 0.0); //Rotation with Shift + ArrowKey
GLfloat camX = rho * cos(theta3*3.1415926f / 180)*sin(phi*3.1415926f / 180);
GLfloat camY = rho * sin(theta3*3.1415926f / 180);
GLfloat camZ = rho * cos(theta3*3.1415926f / 180)*cos(phi*3.1415926f / 180);
// Reduce theta slightly to obtain another point on the same longitude line on the sphere.
GLfloat dt = 1;
GLfloat eyeXtemp = -rho * cos((theta3 - dt)*3.1415926f / 180)*sin(phi*3.1415926f / 180);
GLfloat eyeYtemp = -rho * sin((theta3 - dt)*3.1415926f / 180);
GLfloat eyeZtemp = -rho * cos((theta3 - dt)*3.1415926f / 180)*cos(phi*3.1415926f / 180);
// Connect these two points to obtain the camera's up vector.
GLfloat upX = eyeXtemp - camX;
GLfloat upY = eyeYtemp - camY;
GLfloat upZ = eyeZtemp - camZ;
// Clear Color and Depth Buffers
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// Reset transformations
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
// Set the camera
gluLookAt(camX, camY, camZ, 0, 0, 0, upX, upY, upZ);
gluLookAt(x, 0.0f, z, x, 0.0f, z - 1.0f, 0.0f, 1.0f, 0.0f); //Module 4
glRotatef(angleX, 1, 0, 0); //Module 4
myDisplay();
glFlush();
glutPostRedisplay();
glutSwapBuffers();
}
void init() {
glClearColor(0, 0, 0, 1);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(0.0f, 0.1f, 0.1f, 0.0f);
glOrtho(-250, 250, -250, 250, -250, 250); //IMPORTANT- Define from negative to positive
glMatrixMode(GL_MODELVIEW);
}
int main(int argc, char** argv) {
// init GLUT and create window
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
glutInitWindowSize(500, 500);
glutInitWindowPosition(0, 0);
glutCreateWindow("Homework: Circle");
// register callbacks
glutDisplayFunc(renderScene);
glutTimerFunc(0,timer,0);
glutKeyboardFunc(handleKeypress);
glutSpecialFunc(keyboard);
glutMouseFunc(MouseFunc);
// OpenGL init
init();
// enter GLUT event processing cycle
glutMainLoop();
}
Is wired to set a perspective and an orthographic projection. Delete the perspective projection gluPerspective:
void init() {
glClearColor(0, 0, 0, 1);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
//gluPerspective(0.0f, 0.1f, 0.1f, 0.0f); <---- delete
glOrtho(-250, 250, -250, 250, -250, 250);
glMatrixMode(GL_MODELVIEW);
}
If you want to zoom, the the orthographic projection has to be changed (glOrtho). The projection matrix describes the mapping from 3D points of a scene, to 2D points of the viewport.
Implement a mouse wheel event, which changes the zoom, in a restricted range:
e.g.
GLdouble zoom = 0.0f;
void MouseFunc(int button, int state, int x, int y){
GLdouble min_z = -100.0;
GLdouble max_z = 100.0;
if (button == 4 && zoom < max_z) {
zoom += 3.0;
}
else if (button == 3 && zoom > min_z) {
zoom -= 3.0;
}
}
Modify the orthographic projection, dependent on the zoom in the display loop renderScene:
void renderScene(void) {
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
GLdouble ortho = 250 + zoom;
glOrtho(-ortho, ortho, -ortho, ortho, -250, 250);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
// [...]
}
I have a problem with this :
"expected primary-expression before ‘/’ token"
Help me please
Thanks
the error shows on : angle = i * 2.0f * PI / numSegments;
Here is my code:
void display() {
glClear(GL_COLOR_BUFFER_BIT); // Clear colour buffer
glMatrixMode(GL_MODELVIEW); // To operateon the model-view matrix
glLoadIdentity(); // Reset model-view matrix
glTranslatef(ballX, ballY, 0.0f); //translate to (xPos, yPos)
// use triangular segments to form a circle
glBegin(GL_TRIANGLE_FAN);
glColor3f(0.0f, 0.0f, 1.0f); // Biru
glVertex2f(0.0f, 0.0f); // center of circle
int numSegments = 100;
GLfloat angle;
for (int i = 0; i <= numSegments; i++) { // last vertex same as first vertex
angle = i * 2.0f * PI / numSegments;
glVertex2f(cos(angle) * ballRadius, sin(angle) * ballRadius);
}
glEnd();
glutSwapBuffers(); // Swap front and back buffers (of double buffered mode)
// animation control - compute the location for the next refresh
ballX += xSpeed;
ballY += ySpeed;
//Check if the ball exceeds the edges
if (ballX > ballXMax) {
ballX = ballXMax;
xSpeed = -xSpeed;
}
else if(ballX < ballXMin) {
ballX = ballXMin;
xSpeed = -xSpeed;
}
if (ballY > ballYMax) {
ballY = ballYMax;
ySpeed = -ySpeed;
}
else if (ballY < ballYMin) {
ballY = ballYMin;
ySpeed = -ySpeed;
}
}
Maddeningly, neither the C nor the C++ Standards define a value for pi, and the compiler error you're getting is entirely consistent with PI not being defined.
If you're not using Boost with C++, the easiest thing to do is to define PI yourself, to a very large number of decimal places in order to guard yourself against future precision changes in your types. In POSIX you could use M_PI, but then your code is not strictly portable.
I am building a virtual oscilloscope with OpenGL. I am able to plot the x and y axis and also create a grid. But I cannot get the grid lines to stipple using the code below... Any suggestions ?? glLineStipple is called in the DrawMainWindow function that is passed to glutDisplayFunction....
#include <GL/gl.h>
#include <GL/glu.h>
#include <GL/glut.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
//procedures for shared memory access
#include <sys/shm.h>
#include <sys/stat.h>
#include "binary_sems.h"
///////////////////////////////////////
//debug - FIXME - Add Controls !!!
///////////////////////////////////////
////////////////////////////////////////
// So in debug turn this off to run
// the oscilloscope standalone
////////////////////////////////////////
//#define USE_COMMS
////////////////////////////////////////
// Define a constant for the value of PI
////////////////////////////////////////
#define GL_PI 3.1415f
// Rotation amounts
static GLfloat xRot = 0.0f;
static GLfloat yRot = 0.0f;
//range
GLfloat nRange = 1000.0f;
//gain control
float gain = 1.00;
//enable / disable grid
int grid_enable = 1;
//debug
int frame_id=0;
//////////////////////////////////////////
//Shared Memory Variables
//////////////////////////////////////////
/*variable for shared memory*/
int segment_id;
char *shared_memory;
/*variables for semaphore*/
int semid;
//variables
float BorderClr[3] = {1, 1, 1}; //Default colour for borders
float Ch1TrClr[3] = {1, 1, 0}; //Default colour for channel 1 traces
float GridClr[3] = {1, 1, 1}; //Default colour for grid
float TextClr[3] = {1, 0, 0}; //Default colour for text
float PauseClr[3] = {1, 0, 0}; //Colour for "Paused" text
//defines
#define DISP_BUFFER_LENGTH 1000
//structure defining data points
typedef struct voltage_samples{
float volts; //this is the raw voltage data
float volts_scaled; //this is the scaled voltage data for display (x)
float time_stamp; //this is the time stamp (y )
} DISPLAY_SAMPLES;
//declare a buffer of display samples
DISPLAY_SAMPLES sample_buffer[DISP_BUFFER_LENGTH];
int display_update = 0;
//Function Prototypes
void DrawMainWindow(void);
void IdleProcessing(void);
void SetupRC(void);
void ChangeSize(int w, int h);
void SpecialKeys(int key, int x, int y);
void WriteText(char *text, float height, float x, float y, float z);
////////////////////////////////////////////////////////
//Procedure Entry Point
////////////////////////////////////////////////////////
int main(int argc, char **argv)
{
#ifdef USE_COMMS
//Verify that the shared memory data buffer
//has been specified
if(argc != 3){
printf("ERROR:Usage::APPLICATION <Shared Memory Segment ID> <Semaphore ID for this shared memory segment>\n");
return(-1);
}
//Initialize shared memory parameters
/*get the segment ID from the command line */
segment_id = strtol(argv[1],NULL,0);
/*get the semaphore ID from the comand line*/
semid = strtol(argv[2],NULL,0);
/*attach to the shared memory segment*/
shared_memory = (char *)shmat(segment_id, 0, 0);
#endif
//Initialization parameters for glut
glutInit(&argc, argv);
//Suggest to O/S where the window should
//be initialized at.
//glutInitWindowPosition(0,0);
//Initialize the window size
glutInitWindowSize(640,480);
//Argument for next opened window
glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA);
//Create the window
glutCreateWindow("CUDA Oscilloscope");
//Register Special Keys and Change Size Functions
glutReshapeFunc(ChangeSize);
glutSpecialFunc(SpecialKeys);
//Register callback function for redrawing window
glutDisplayFunc(DrawMainWindow);
//Register callback function for idle processing
glutIdleFunc(IdleProcessing);
//Enable depth testing ???
glEnable(GL_DEPTH_TEST);
//Set up drawing environment
//SetupRC();
//Start the infinite loop - function will never return
//till controlled ^c
glutMainLoop();
return 0;
}
/////////////////////////////////////////////////////////
//Functions
/////////////////////////////////////////////////////////
void DrawMainWindow(void)
{
//GLfloat x, y, z;
float x,y,z;
//Clear buffer
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
//Save previous settings
glPushMatrix();
//Draw all samples
glColor3fv(Ch1TrClr);
//Get scaled / processed data from buffer;
//this was the data that was created during
//idle state
glBegin(GL_POINTS);
z = 0.00;
for(int ii=0; ii < DISP_BUFFER_LENGTH; ii++){
//plot point on the coordinate
x = -nRange + ii*2.00;
y = sample_buffer[ii].volts_scaled;
//plot the coordinate
glVertex3f(x,y,z);
}
glEnd();
if(grid_enable == 1){
//Grid Color and Line Widths
glColor3fv(GridClr);
//Draw X and Y axis
GLint factor = 10;
GLushort pattern = 0x5555;
glLineWidth(2);
//Draw X-Axis
glBegin(GL_LINES);
glLineStipple(factor, pattern);
glVertex3f(-nRange, 0.00, 0.00);
glVertex3f( nRange, 0.00, 0.00);
glEnd();
//Draw Y-Axis
glBegin(GL_LINES);
glLineStipple(factor, pattern);
glVertex3f(0.00, -nRange, 0.00);
glVertex3f(0.00, nRange, 0.00);
glEnd();
//Draw a 10x10 grid ( stipple lines )
factor = 10;
pattern = 0x5050;
glLineWidth(1);
// //Bottom to top - horizintal lines
for(float ii=-nRange; ii < nRange; ii += 100)
{
glLineStipple(factor, pattern);
glBegin(GL_LINES);
glVertex3f(-nRange, ii, 0.00);
glVertex3f( nRange, ii, 0.00);
glEnd();
}
// //Left to right - vertical lines
for(float ii=-nRange; ii < nRange+100; ii += 100)
{
glLineStipple(factor, pattern);
glBegin(GL_LINES);
glVertex3f(ii, -nRange, 0.00);
glVertex3f(ii, nRange, 0.00);
glEnd();
}
}
//Write Measurement parameters to the screen
glColor3fv(TextClr);
WriteText("(Y)::Vertical Scale=", 50.00, 300.00, 800.00, 0.00);
WriteText("(X)::Horizontal Scale=", 50.00, 300.00, 700.00, 0.00);
//FIXME - Display Time Settings
//FIXME - Display "Paused" if capture is paused
//FIXME - Display trigger settings
//FIXME - Display Ch1 Settings
//Restore previous settings
glPopMatrix();
//Puts rendered scene on front buffer
//glFlush is called by glutSwapBuffers implicitely
glutSwapBuffers();
}
//FIXME - Several functions are required for GUI
void IdleProcessing(void)
{
/*clear read buffer so new write data can be added*/
initSemAvailable(semid, 1);
/*try bump down semaphore to indicate completion of memory read*/
reserveSem(semid,0);
//Here we acquire and process the content of the
//data buffer
double *p = (double *)shared_memory;
for(int ii=0; ii < DISP_BUFFER_LENGTH; ii++){
#ifdef USE_COMMS
sample_buffer[ii].volts_scaled = gain*p[ii];
#else
sample_buffer[ii].volts_scaled = gain*cos((2.0f*GL_PI)*ii*4/DISP_BUFFER_LENGTH + rand()%2) + rand()%10;
#endif
}
#ifdef DEBUG
for(int ii=0; ii < DISP_BUFFER_LENGTH; ii++){
if(ii%10==0){
printf("\n");
}
printf("%f ",sample_buffer[ii].volts_scaled);
}
printf("\n");
#endif
printf("Frame Cntr = %d\r",frame_id);
frame_id++;
//FIXME - data processing during idle time
DrawMainWindow();
}
// This function does any needed initialization on the rendering
// context.
void SetupRC()
{
// Black background
glClearColor(0.0f, 0.0f, 0.0f, 1.0f );
// Set drawing color to green
glColor3f(1.0f, 1.0f, 1.0f);
//enable line stippling
glEnable(GL_LINE_STIPPLE);
}
void SpecialKeys(int key, int x, int y)
{
if(key == GLUT_KEY_UP){
//xRot-= 5.0f;
if(gain < 10000.00)
gain = gain + 100.0;
}
if(key == GLUT_KEY_DOWN){
//xRot += 5.0f;
if(gain > 0.00)
gain = gain - 100.0;
}
if(key == GLUT_KEY_LEFT)
//yRot -= 5.0f;
grid_enable = 1;
if(key == GLUT_KEY_RIGHT)
//yRot += 5.0f;
grid_enable = 0;
if(key > 356.0f)
xRot = 0.0f;
if(key < -1.0f)
xRot = 355.0f;
if(key > 356.0f)
yRot = 0.0f;
if(key < -1.0f)
yRot = 355.0f;
// Refresh the Window
glutPostRedisplay();
}
void ChangeSize(int w, int h)
{
// Prevent a divide by zero
if(h == 0)
h = 1;
// Set Viewport to window dimensions
glViewport(0, 0, w, h);
// Reset projection matrix stack
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
// Establish clipping volume (left, right, bottom, top, near, far)
if (w <= h)
glOrtho (-nRange, nRange, -nRange*h/w, nRange*h/w, -nRange, nRange);
else
glOrtho (-nRange*w/h, nRange*w/h, -nRange, nRange, -nRange, nRange);
// Reset Model view matrix stack
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
void WriteText(char *text, float height, float x, float y, float z)
{
const float charHeight = 119.05;
glPushMatrix();
glTranslatef(x,y,z);
glScalef(height/charHeight/1.5, height/charHeight, height/charHeight);
while(*text){
glutStrokeCharacter(GLUT_STROKE_MONO_ROMAN, (int)*text);
*text++;
}
glPopMatrix();
}