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();
}
Related
I tried to scroll text horizontally in a OpenGL app. The text comes perfect and smooth part by part at the screen when starting from the right side. When the first letter then touches the side of the window at the left side, the whole text disappears. I want that the text goes over the border, so that it vanished smoothly and start again from the right side. It's a sort of banner i try to make. Someone who knows how to solve this problem?
#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;
float xsize = 800;
float ysize = 300;
void print_bitmap_string(/*void* font,*/ const char* s)
{
while (*s) {
glutBitmapCharacter(GLUT_BITMAP_TIMES_ROMAN_24, *s);
s++;
}
}
void 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 = xsize/2;
float y_pos = 70;
void draw()
{
const char* bitmap_font_names[7] = { "Testing train application for windows!!##" };
glPushMatrix();
/* Draw the strings, according to the current mode and font. */
glTranslatef(0.5, -100, 0);
//set the text color
glColor4f(0.0f, 173.0f, 115.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();
}
void display(void)
{
//change background color
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glClear(GL_COLOR_BUFFER_BIT);
draw();
glColor3f(0.0, 255.0, 0.0);
/*glBegin(GL_TRIANGLES);
glVertex2f(20 + x_pos, 0 + y_pos);
glVertex2f(50 + x_pos, 10 + y_pos);
glVertex2f(20 + x_pos, 20 + y_pos);
glEnd();*/
glutSwapBuffers();
}
void timer(int) {
glutPostRedisplay();
glutTimerFunc(1000 / 90, timer, 0);
switch (state) {
case 1:
if (x_pos > (-xsize / 2) - 200) {
x_pos -= 1;
}
else {
state = -1;
}
break;
case -1:
x_pos = (xsize / 2);
state = 1;
break;
}
cout << x_pos << endl;
}
int main(int argc, char** argv)
{
glutInitWindowSize(xsize, ysize);
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE);
glutCreateWindow("Train Display");
glutDisplayFunc(display);
glutReshapeFunc(reshape);
glutTimerFunc(1000, timer, 0);
glutMainLoop();
return 0;
}
It looks like OpenGL may not allow you to explicitly draw bitmaps outside of the viewport.
From the documentation on glRasterPos,
To set a valid raster position outside the viewport, first set a valid raster position, then call glBitmap with NULL as the bitmap parameter.
The documentation on glBitmap elaborates on this aspect:
To set a valid raster position outside the viewport, first set a valid raster position inside the viewport, then call glBitmap with NULL as the bitmap parameter and with xmove and ymove set to the offsets of the new raster position. This technique is useful when panning an image around the viewport.
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();
}
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'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();
I have been trying to draw multiple balls for a game I am making, I have tried to get this working but there are problems in my init class and display method class, I have commented it where the errors are.
Ball.h:
#pragma once
#include "Vector2f.h"
#include "Vector3f.h"
class Ball
{
private:
Vector3f position;
Vector3f velocity;
public:
Ball(void);
~Ball(void);
void Draw();
void SetPos(Vector3f New_position);
void SetVel(Vector3f New_velocity);
Vector3f GetPos();
};
Ball.cpp
#include "Ball.h"
#include "Vector2f.h"
#include "Vector3f.h"
#include "Glut/glut.h"
#include "GL/gl.h"
#include "GL/glu.h"
Ball::Ball(void)
{
Vector3f Temp_position;
position = Temp_position;
Vector3f Temp_velocity;
velocity = Temp_velocity;
}
Ball::~Ball(void)
{
}
void Ball::SetPos(Vector3f New_position)
{
position = New_position;
}
void Ball::Draw()
{
glPushMatrix();
glTranslatef(position.X(), position.Y(), position.Z());
glColor3d(1, 0, 0);
glutSolidSphere(0.3, 50, 50);
glPopMatrix();
}
void Ball::SetVel(Vector3f New_velocity)
{
velocity = New_velocity;
}
Vector3f Ball::GetPos()
{
Vector3f temp;
temp = position;
return temp;
}
I want the be able to draw an array of the balls in Main.cpp
Main.cpp
#include "Display.h"
#include "Vector3f.h"
#include "Ball.h"
#include "Glut/glut.h"
#include "GL/gl.h"
#include "GL/glu.h"
#include <math.h>
static float TableWidth = 4; // Z axis normal = 4
float Display::eyeX = -7.5; //-7.5
float Display::eyeY = 3; //3
float Display::eyeZ = 5; //5
float Display::Position[4] = { 1.0f, 0.0f, -3.5, 1.0f };
float Display::translateZ = -3.5;
float Display::translateX = 0.0;
//Timer Display::m_Timer = Timer();
float Display::lightX = 5.0; //5 2.5
float Display::lightY = 5.0;
float Display::lightZ = 2.5;
float m_TableX = -5.0f;
float m_TableZ = -2.5f;
float m_TableWidth = 2.5f;
float m_TableLength = 5.0f;
float ballx = 0.7;
float bally = 0.1;
float ballz = -0.7;
Ball Redball;
float BALL_RED_START = 0;
float RADIUS_OF_BALL = 0.3;
float BALL_RED_END = 8;
float m_ball;
void Display::Init(int argc, char ** argv)
{
glutInit(&argc, argv); // initializes glut
// sets display mode. These parameter set RGB colour model
// and double buffering.
glutInitWindowSize(500,500);
glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE);
glutCreateWindow("Pool Version 1.0");
// Set glut callback functions
glutDisplayFunc(Display::DisplayScene);
glutIdleFunc(Display::Idle);
glutReshapeFunc(Display::Resize);
glutKeyboardFunc(Display::KeyboardInput);
//m_Timer.getSeconds();
glEnable(GL_DEPTH_TEST);
glPointSize(5);
glEnable(GL_NORMALIZE);
glEnable(GL_LIGHTING);
glClearColor(0,0,0,1);
glEnable(GL_COLOR_MATERIAL);
float white[] = { 1.0f, 1.0f, 1.0f, 1.0f };
glLightfv(GL_LIGHT0, GL_DIFFUSE, white);
glEnable(GL_LIGHT0);
Redball.SetPos(Vector3f(0.0,0.3,0.0));
for(int i = BALL_RED_START; i < BALL_RED_START; i++)
{
glColor3f(1,0,0);
Redball[i]->SetPos(Vector3f (i+128,RADIUS_OF_BALL,45)); //I tried this but it doesn't work Error C2227
}
// Begin glut main loop
glutMainLoop();
}
void BallMovement()
{
//Vector3f position(0.0,0.3,0.0);
/*Redball.SetPos(Vector3f(0.0,0.3,0.0));*/
Vector3f New_velocity(0.01,0,0);
Redball.SetVel(New_velocity);
Vector3f New_position;
Vector3f Old_position;
Old_position = Redball.GetPos();
//New_position = Old_position + New_velocity;
New_position.SetX(Old_position.X() + New_velocity.X());
New_position.SetY(Old_position.Y() + New_velocity.Y());
New_position.SetZ(Old_position.Z() + New_velocity.Z());
Redball.SetPos(New_position);
}
void Display::DisplayScene()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Clear the back buffer
glPushMatrix();
glLoadIdentity();
glNormal3f(0,1,0);
Vector3f didums = Redball.GetPos();
gluLookAt(eyeX, eyeY, eyeZ, // eye position
0, 0, 0, // what I'm looking at
0.0, 1.0, 0); // Up direction
float Position[] = {lightX, lightY, lightZ, 1.0f};
glLightfv(GL_LIGHT0, GL_POSITION, Position);
DrawLight(0, Position);
/* Rendering code goes here */
for (int i = BALL_RED_START; i<BALL_RED_END;i++)
{
glColor3f(1,0,0);
Redball[i]->Draw(); //I tried this but it doesn't work Error C2227
}
drawTable();
drawTableLegFrontLeft();
drawTableLegFrontRight();
drawTableLegBackLeft();
drawTableLegBackRight();
drawCushions();
//drawCircle();
//drawHCircle();
Table(-2,-4.5,2,4.5); // Draws the table top in trianglestrip -4.5, 0.5, -0.5, 9.5
glPopMatrix();
glutSwapBuffers(); // Swap the front and back buffers
}
void Display::Resize(int w, int h)
{
/* Resize is called when window is resized */
glMatrixMode(GL_PROJECTION); // set matrix mode to profection
// this dictates how the 3d scene is "squashed" onto the 2d screen
glLoadIdentity();
glViewport(0, 0, w, h); // Set the part of the window to use.
gluPerspective(45, // field of view
(float)w/(float)h, // ration of window
1, // front clipping plane
1000 // back clipping plane
); // set the area in the 3d scene to draw
glMatrixMode(GL_MODELVIEW); // Setthe matrix mode to model view
// the matrix specifies how the 3d scene is viewed
/*glLoadIdentity();
gluLookAt(-3.5, 2, eyeZ, // eye position
1, 1, 0, // what I'm looking at
0.0, 1.0, 0); // Up direction*/
}
void Display::Idle()
{
/* When nothing else is happening, idle is called.
* Simulation should be done here and then
* the display method should be called
*/
BallMovement();
glutPostRedisplay();
}
I see you have declared Ball as Ball Redball; which will create a single Ball on the stack.
Then you attempt to treat it as a collection of Balls with Redball[i]->SetPos(...) and Redball[i]->Draw(). It appears you are attempting to work with 8 of them.
What you want to do is create an array of Balls, with a max size of 8 (according to BALL_RED_END). For simplicity, you could do
Ball RedBall[8];
for( //some conditions here )
{
RedBall[i].Draw();
}
as your declaration and usage.
Remember that anytime you use Redball.SetPos(...) will no longer be valid.