PDA

View Full Version : simple OpenGL code, but won't draw anything.



rstout
10-06-2015, 09:03 PM
Trying to create this seemingly simply program and make it draw.
It is a pseudocode example from the text book.
It compiles and runs without errors, but all I get is a blank white screen.
It should be drawing GL_LINE_STRIPs.

Suggestions??
Thanks.



// Experiment 2
// Experimentation with scaling and translation
// 6 Oct 2015

#include <windows.h>
#include "stdafx.h"
#include <iostream>
#include <math.h>
#include <time.h>
#include <gl/Gl.h>
#include <gl/Glu.h>
#include <gl/Glut.h>
using namespace std;

#define PI 3.14159265

// ************************************************** ****************
// Global Variables

const float screenWidth = 800.0; // max screen width in pixels
const float screenHeight = 600.0; // max screen height in pixels
float color[] = { 0.0, 0.0, 0.0 }; // color
GLdouble A = screenWidth / 4.0; // scaling and translation variables
GLdouble B = 0.0;
GLdouble C = screenHeight / 2.0;
GLdouble D = C;

// ************************************************** ****************
// Function Declarations

void myInit(void); // my initialization routine
void myDisplay(void); // the redraw function
void Random_Color(); // generate a random color
float f(float x); // any f(x) I want
void Print_Msg(int, char*); // Print messages to screen

// ************************************************** ****************

int main(int argc, char* argv[])
{
srand(time(NULL)); // seed RNG
Random_Color(); // gen a random color for drawing

glutInit(&argc, argv); // initialize the toolkit
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB); // set the display mode
glutInitWindowSize(screenWidth, screenHeight); // set the window size

glutInitWindowPosition(0, 0); // set window starting position

glutCreateWindow("Experiment 2"); // open the screen window
glutDisplayFunc(myDisplay); // register the redraw function
myInit(); // call my initialization routine
glFlush();
glutMainLoop(); // go into a perpetual loop

}

// ************************************************** ****************
// START FUNCTION DEFINITIONS
// ************************************************** ****************

// ************************************************** ****************
// myInit()

void myInit(void) {

glClearColor(1.0, 1.0, 1.0, 0.0); // the background color is white
// glColor3f(0.0f, 0.0f, 0.0f); // the drawing color is black
glPointSize(2.0); // a 'dot' is 2 by 2 pixels
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(0.0, screenWidth, 0.0, screenHeight);
}

// ************************************************** ****************
// myDisplay()

void myDisplay(void) {

glClear(GL_COLOR_BUFFER_BIT); // clear the screen
glColor3f(color[0], color[1], color[2]); // set drawing color

glBegin(GL_LINE_STRIP); // Draw line strips
for (int x = 0; x <= 300; x += 3) { // scaled and
glVertex2d(A * x + B, C * f(x) + D); // translated
}
glEnd();
glFlush(); // send all output to display

}

// ************************************************** ****************
// Random_Color()

void Random_Color(void) {
// This routine will generate a random color and store it in color[0-2].
// color[] is a global array of floats.

for (int c = 0; c < 3; c++) { color[c] = ((float)(rand() % 100) / 100); }
}


// ************************************************** ****************
// f()

float f(float x) {
// any f(x) I want

return cos(2 * PI * x);
}


// ************************************************** ****************
// Add next function here


// ************************************************** ****************
// Print_Msg()

void Print_Msg(int Msg, char* Message) {
// Receives an Int value and a char string
// If the INT is zero, simply print the string argument.
// If the INT is non-zero, print the corresponding message from the
// list below, ignoring the string, if any, supplied as the 2nd arg.

switch (Msg) {
case 0: cout << endl << Message; // print msg as given
break;
case 1: cout << endl << "Error 1" << endl; // Placeholder
break;
case 2: cout << endl << "Error 2" << endl; // Placeholder
break;
default: break;
} // end SWITCH
cout << endl; // pad a line before returning
} // end function. Returns nothing.

GClements
10-07-2015, 12:41 AM
It compiles and runs without errors, but all I get is a blank white screen.


x is always an integer, so cos(2 * PI * x) is always 1. Thus C * f(x) + D is always 600, i.e. you're drawing a horizontal line exactly along the edge of the window. Depending upon floating-point rounding error, the line may or may not be drawn; even if it is drawn, it won't be particularly visible.

Also, successive X coordinates are 0, 600, 1200, ..., so most of them are far to the right of the viewport.

rstout
10-09-2015, 04:11 PM
x is always an integer, so cos(2 * PI * x) is always 1. Thus C * f(x) + D is always 600, i.e. you're drawing a horizontal line exactly along the edge of the window. Depending upon floating-point rounding error, the line may or may not be drawn; even if it is drawn, it won't be particularly visible.

Thanks, that was helpful. But still confusing...

I modified the call to f(x) to cast x to float:
f((float)x)

But, in the call to cosine: cos(2.0 * PI * x), the output is still = 1.

However, casting the whole expression to int: cos((int)2.0 * PI * x)) , seems to work.

So it is odd that casting the cosine argument to an int works since cosine expects a double.

Well, I think I can close this inquiry as complete since we figured out that the code was in fact drawing, just not somewhere where I could see it.
I just need to confirm that the functions and methods are getting the type of variables they are expecting.
Thanks for all the help.

The attached output shows the values:
printf("%f, %f, %f \n", 2.0 * PI * x, cos(2.0 * PI * x), cos((int)(2.0 * PI * x)));

0.000000, 1.000000, 1.000000
18.849556, 1.000000, 0.660317
37.699112, 1.000000, 0.765414
56.548668, 1.000000, 0.853220
75.398224, 1.000000, 0.921751
94.247780, 1.000000, 0.969459
113.097335, 1.000000, 0.995267
131.946891, 1.000000, 0.584209
150.796447, 1.000000, 0.699251
169.646003, 1.000000, 0.798496
188.495559, 1.000000, 0.879703
207.345115, 1.000000, 0.941037
226.194671, 1.000000, 0.981111
245.044227, 1.000000, 0.999022
263.893783, 1.000000, 0.626468
282.743338, 1.000000, 0.736213

GClements
10-09-2015, 05:39 PM
Thanks, that was helpful. But still confusing...

I modified the call to f(x) to cast x to float:
f((float)x)

But, in the call to cosine: cos(2.0 * PI * x), the output is still = 1.

That won't help in the slightest. If you want to draw a sine wave, you have to change the step to something much less than one, so that you're getting multiple samples per cycle.



However, casting the whole expression to int: cos((int)2.0 * PI * x)) , seems to work.

You missed an opening parenthesis somewhere.



So it is odd that casting the cosine argument to an int works since cosine expects a double.


Not really. The compiler knows that cos() expects a double and will convert it.



The attached output shows the values:
printf("%f, %f, %f \n", 2.0 * PI * x, cos(2.0 * PI * x), cos((int)(2.0 * PI * x)));

The reason that this works is that casting the argument to an int means that it's no longer a multiple of 2*PI. Pi is irrational, so a non-zero integer will never be a multiple of pi. Beyond that, the value modulo 2*pi will be different for each call, meaning that the cosine will also be different.