Can anyone explain what's going on or not going on so that I can correct it. Here's the code so far from a .cpp file. Running in Visual Studio Community 2015.
#include <windows.h>
#include <gl/GL.h>
#include <gl/glu.h>
#include <gl/glut.h>
#include <math.h>
#define M_PI 3.14159265358979323846
const int screenWidth = 640;
const int screenHeight = 480;
Here aa, bb, cc, & dd are used to map the world coordinates to screen coordinates. I printed them out to make sure it was working correctly and the coordinates are being calculated correctly. In this case 0 < radius <= 5.
void drawHex(GLdouble radius, GLdouble aa, GLdouble bb, GLdouble cc, GLdouble dd) {
glBegin(GL_POLYGON);
for (int i = 0; i < 6; i++) {
glVertex2d(((cos(i / 6.0 * 2 * M_PI) * radius) * aa) + cc,
((sin(i / 6.0 * 2 * M_PI) * radius) * bb) + dd);
}
glEnd();
glFlush();
}
Here I calculate A, B, C, and D to map the world to the view and pass them to the drawHex function.
void myDisplay(void) {
glClear(GL_COLOR_BUFFER_BIT);
GLdouble winWidth = glutGet(GLUT_WINDOW_WIDTH);
GLdouble winHeight = glutGet(GLUT_WINDOW_HEIGHT);
GLdouble A, B, C, D;
glViewport((GLint)0, (GLint)0, (GLint)winWidth, (GLint)winHeight);
A = winWidth / 10.0;
B = winHeight / 10.0;
C = 0 - (A * -5.0);
D = 0 - (B * -5.0);
drawHex(0.5, A, B, C, D);
}
Program inits and main loop.
void myInit() {
glClearColor(0.93, 0.93, 0.93, 0.0);
glColor3f(1.0, 0.0, 0.0);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(-5.0, 5.0, -5.0, 5.0);
glClear(GL_COLOR_BUFFER_BIT);
}
int main(int argc, char** argv) {
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
glutInitWindowSize(screenWidth, screenHeight);
glutInitWindowPosition(100, 150);
glutCreateWindow("Window");
myInit();
glutDisplayFunc(myDisplay);
glutMainLoop();
return 0;
}
All I get is a blank window with the background color. I'm expecting a hexagon in the middle of the view (not yet resized to maintain a proper aspect ratio).
In your call to gluOrtho2D you pass [-5, 5] as bounds on both dimensions. In your calculation, anything going beyond this would be clipped out and will not be visible. Lets see if this is the case.
The aa, bb, cc and dd you pass are constants; they always remain: 64, 48, 320 and 240. The value you'd get after correcting the above issue will always be within [-1, 1] since that's the codomain of cos and sin functions. This gets multiplied with radius * aa and added to cc. So worst case would be (1 * 0.5 * 64) + 320 = 352, which is clearly outside the -5 boundary you'd set via gluOrtho2D.
The same observations apply to y too. Do your math on paper first and then code this up. Make sure all the boundary conditions are within limits.
It's recommended that you pass GLUT_DOUBLE to avoid flickers and as the other answer mentions, you need swap buffers at the end of the display function for double buffering to work. Read the answer to Difference between single buffered(GLUT_SINGLE) and double buffered drawing(GLUT_DOUBLE) for details. Also, you don't need to call glViewport on every rendering call, instead put it in your init function.
I'm unfamiliar with glut but try adding glutSwapBuffers(); to the end of your drawing function. In OpenGL, there is always one frame being displayed to the user and one frame that is being rendered. Swapbuffers swaps these two frames: it sends the rendered frame to the user and pulls back the previous frame for further rendering.
Related
I have this code:
/*
* This is a simple program that computes FPS
* by means of a circular buffer
*/
#include <GL/glut.h>
//#include <numeric>
#include <unistd.h>
#include <time.h>
#include <stdio.h>
// Number of elements in the circular buffer
#define NELS 10
// Number of lines
#define NLINES 10000
// circular buffer used to compute frame rate
float circularBuffer[NELS];
int firstInd = 0, nEls = 0;
// function to get the number of elapsed ticks
uint32_t getTick()
{
struct timespec ts;
unsigned theTick = 0U;
clock_gettime( CLOCK_REALTIME, &ts );
theTick = ts.tv_nsec / 1000000;
theTick += ts.tv_sec * 1000;
return theTick;
}
// Function to compute real modulus and NOT remained as % does
inline int modulo(int a, int b) {
const int result = a % b;
return result >= 0 ? result : result + b;
}
// Compute sum of the elements in the circular buffer
float sumCircularBuffer()
{
int ind;
float sum = 0;
if (nEls > 0) {
for (ind=1; ind<=nEls; ind++) {
sum = sum + circularBuffer[modulo(firstInd-ind, NELS)];
}
}
return sum;
}
// accumulate buffer and update window title
void computeAndShowFrameRate(void)
{
static float lastTime = 0.0f;
static unsigned int frameCount = 0;
char windowTitle[100];
float sumFPS;
float currentTime = (float)getTick() * 0.001f;
// Initialize lastTime to the current time
if (lastTime == 0) {
lastTime = currentTime;
}
// increase frame count
frameCount++;
if (currentTime - lastTime > 1.0f) {
// insert the current fps in the circular buffer
circularBuffer[firstInd] = ((float)frameCount) / (currentTime - lastTime);
// update variable lastTime
lastTime = currentTime;
//circularBuffer[firstInd] = (float)frameCount;
firstInd = ((firstInd+1)%NELS);
if (nEls < NELS) {
nEls++;
}
frameCount = 0;
// sum elements in circular buffer
sumFPS = sumCircularBuffer();
snprintf(windowTitle, 100, "FPS = %6.2f", sumFPS/nEls);
// update window title
glutSetWindowTitle(windowTitle);
}
}
// display function
void display(void)
{
int currLineInd;
// get current frame rate
computeAndShowFrameRate();
// clear buffer
glClear (GL_COLOR_BUFFER_BIT);
for (currLineInd = 0; currLineInd<NLINES; currLineInd++) {
// draw line
glBegin(GL_LINES);
// random color
glColor3f((float)rand()/RAND_MAX, (float)rand()/RAND_MAX, (float)rand()/RAND_MAX);
// random first point
glVertex2f((float)rand()/RAND_MAX, (float)rand()/RAND_MAX);
// random color
glColor3f((float)rand()/RAND_MAX, (float)rand()/RAND_MAX, (float)rand()/RAND_MAX);
// random second point
glVertex2f((float)rand()/RAND_MAX, (float)rand()/RAND_MAX);
glEnd();
}
glFinish();
glutPostRedisplay();
}
// initialization function
void init (void)
{
// Use current time as seed for random generator
srand(time(0));
// select clearing color
glClearColor (0.0, 0.0, 0.0, 0.0);
// Orthographic projection
glOrtho(0.0, 1.0, 0.0, 1.0, -1.0, 1.0);
}
// Window size and mode
int main(int argc, char** argv)
{
// pass potential input arguments to glutInit
glutInit(&argc, argv);
// set display mode
// GLUT_SINGLE = single buffer window
glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB);
glutInitWindowSize (400, 400);
glutInitWindowPosition (100, 100);
glutCreateWindow ("OpenGL Window");
// Call initialization routinesx
init();
glutDisplayFunc(display);
glutMainLoop();
return 0;
}
I have to replace the glOrtho function with glFrustum and get the same result.
I read the opengl guide on khronos and understood the differences between glOrtho and glFrustum but i can't figure out how to calculate the parameters.
How do I calculate the parameters to pass to the glFrustum function?
glFrustum() require 6 parameters to specify 6 clipping planes: left, right, bottom, top, near and far planes. A visual representation would be like this:
The values that will come up with depend on your implementation and the scale of the models you are working with. As mentioned above, if the projected geometry is in front of the near plane or behind the far plane it will be clipped thus it won't be visible.
To solve this you either have to recompute the parameters for the glFrustum() function(bad idea) or move the camera/scene along the z-axis.
References:
http://www.songho.ca/opengl/gl_transform.html
https://learnopengl.com/Getting-started/Coordinate-Systems
With Perspective projection the distnace to the near and far plane have to be grater than 0,
0 < near < far
because you want to define a Viewing frustum:
If the distance to the near plane is less than 0, the result is undefined (Usually the instruction has no effect at all).
See glFrustum:
void glFrustum( GLdouble left,
GLdouble right,
GLdouble bottom,
GLdouble top,
GLdouble nearVal,
GLdouble farVal);
The distances left, right, bottom and top, are the distances from the center of the view to the side faces of the frustum, on the near plane. near and far specify the distances to the near and far plane of the frustum.
The geometry has to be between the near and the far plane, else it is clipped. Therefore, you have to move the shift along the z-axis in the negative direction (in negativ direction, because the view space z-axis points out of the view):
// initialization function
void init (void)
{
// [...]
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glFrustum(-0.1, 0.1, -0.1, 0.1, 0.1, 50.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(0.0f, 0.0f, -5.0f);
}
// #include loads up library files, the order can matter
// generally load glut.h last
#include <stdio.h> // this library is for standard input and output
#include "glut.h"// this library is for glut the OpenGL Utility Toolkit
#include <math.h>
// this is the initialisation function, called once only
void init() {
glClearColor(0.0, 0.0, 1.0, 0.0); // set what colour you want the background to be
glMatrixMode(GL_PROJECTION); // set the matrix mode, we will look at this later
// set the projection window size in x an y.
gluOrtho2D(0.0, 500, 0.0, 500.0);
}
// this is the display function it is called when ever you want to draw something
// all drawing should be called form here
void circle() {
// draw circle
float theta;
glClear(GL_COLOR_BUFFER_BIT); // clear the screen using the background colour
glBegin(GL_POLYGON);
glColor3f(1.0, 0.0, 0.0); // set colour to red
for (int i = 0; i < 320; i++) {
theta = i * 3.142 / 180;
glVertex2f(190 + 50 * cos(theta), 250 + 70 * sin(theta));
}
glEnd();
glFlush(); // force all drawing to finish
}
// this has the effect of repeatedly calling the display function
void display() {
circle();
}
// as with many programming languages the main() function is the entry point for execution of the program
int main(int argc, char** argv) {
glutInit(&argc, argv); //perform the GLUT initialization
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB); // more initialisation
glutInitWindowSize(800, 600); // set window position
glutInitWindowPosition(0, 0); // set window size
glutCreateWindow("Circle"); // create a display with a given caption for the title bar
init(); // call init function defined above
glutDisplayFunc(display); // define what function to call to draw
// the last function in the program puts the program into infinite loop
glutMainLoop();
// this line exits the program
return 0;
}
I've added comments so you can understand my code. The code creates a big red circle, and cuts the bottom right side of the circle, but I want to the cut only the bottom side. How can I achieve this? I would really appreciate the help.
Like this:
If you want to cut a circle by a Secant line, then you have to define an start angle and an end angle and to specify the vertex coordinates form the point on the circle with the start angle to the point with the end angle.
A Full angle has 360 degrees (2*PI radians). The bottom (south) has an angle of -90 degrees.
If you want to cut a part at the bottom of the circle, then the start and the end angle can be calculated like this:
int cutsegment = 45;
int start = -90 + cutsegment / 2;
int end = 270 - cutsegment / 2;
for (int i = start; i <= end; i++) {
theta = i * 3.142 / 180;
glVertex2f(190 + 50 * cos(theta), 250 + 70 * sin(theta));
}
I am making a 3d project in OpenGL which contain a ground (drawn as line loops). The issue I have is when the project starts only a single line is drawn as shown in the next image:
When I resize or maximize the window then the actual ground gets displayed like this:
Any idea how to resolve this issue? I'm a beginner in OpenGL programming.
Here is the code :
void drawHook(void);
void timer(int);
void drawFlorr();
float L = 100;
const int screenWidth = 1000; // width of screen window in pixels
const int screenHeight = 1000; // height of screen window in pixels
float ww = 800;
float wh = 800;
float f = 520, n = 10.0;
static GLdouble ort1[] = { -200, 200, -33, 140 };
static GLdouble viewer[] = { 525, 25, -180 };
static GLdouble objec[] = { 525.0, 25, -350 };
float x, y = 0.0, z, z1;
float xmax = screenWidth - 200.0;
float zmax = screenWidth - 200.0;
float xmin, zmin;
float step = 5.0;
float fov = 80;
void myInit(void)
{
glClearColor(0.0,0.0,0.0,0.0); // background color is white
glPointSize(2.0); // a 'dot' is 2 by 2 pixels
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(0.0, screenWidth, 0.0, screenHeight);//dino window
glViewport(0, 0, screenWidth, screenHeight);
}
void myDisplay(void)
{
glClear(GL_COLOR_BUFFER_BIT);
glLoadIdentity();
gluLookAt(viewer[0], viewer[1], viewer[2], objec[0], objec[1], objec[2], 0, 1, 0);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(fov, 1.333, n, f);
glPointSize(2.0);
glMatrixMode(GL_MODELVIEW);
drawFlorr();
glutSwapBuffers();
}
int main(int argc, char** argv)
{
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB); // set display mode
glutInitWindowSize(screenWidth, screenHeight); // set window size
glutInitWindowPosition(10, 10); // set window position on screen
glutCreateWindow("Dino Line Drawing"); // open the screen window
glutDisplayFunc(myDisplay); // register redraw function
myInit();
//glutTimerFunc(1,timer,1);
glutMainLoop(); // go into a perpetual loop
return 1;
}
void drawFlorr()
{
xmin = -100;
zmin = -100;
for (x = xmin; x < xmax; x += step)
{
for (z = zmin; z < zmax; z += step)
{
z1 = -z;
glBegin(GL_LINE_LOOP);
glVertex3f(x, y, z1);
glVertex3f(x, y, z1-step+1.0);
glVertex3f(x + step - 1.0, y, z1 - step + 1.0);
glVertex3f(x+step-1.0, y, z1);
glEnd();
}
}
}
Your code is broken in many ways:
Your myDisplay function uses whatever the current matrix mode is to set the view matrix on.
Initially, you leave the matrix mode as GL_PROJECTION in myInit()
These two together mean that for the first frame, you just use identity as MODELVIEW matrix, and just overwrite the projection matrix twice. After a resize, the frame ais drawn again, and your code does waht you probably intented to do.
However, there is more:
You do not have any resize handler, so your viewport will not change when you resize the window.
You are setting an ortho matrix initailly for the projection, although you are not planning to use it at all.
and, the most import point:
All of your code depends on deprecated functionality which is not even available in modern OpenGL at all. You should really not use this in 2016, but learn modern OpenGL instead (with "modern" meaning "only a decade old" here).
I'm trying to write code for a weaving pattern in OpenGL.
Weaving Pattern
Pic
Now, I am trying to write code for a similar pattern using a circle.
I draw a circle using points, each point is drawn using cos and sin functions.
I understand this is not as efiicient as SeigeLord's method as it makes higher use of resources.
I am able to get the circle, I want to get points on it's circumference.
My code :
#include<GL/glut.h>
#include<stdio.h>
#include<math.h>
int n, r;
void display()
{
int i, j;
glClearColor(0.0, 0.0, 0.0, 1.0);
glClear(GL_COLOR_BUFFER_BIT);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(-50, 50, -50, 50);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
for (i = 0;i <= 360;i += 1)
{
glBegin(GL_POINTS);
glVertex2f(r*cos(i), r*sin(i));
glEnd();
}
/*for (i = 0;i < 360;i += 10)
{
glBegin(GL_LINES);
glVertex2f(r*cos(i), r*sin(i));
glVertex2f(r*cos(i + 300), r*sin(i + 300));
glEnd();
}*/
glFlush();
}
int main(int argc, char **argv)
{
r = 30;
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGB | GLUT_SINGLE);
glutInitWindowPosition(300, 50);
glutInitWindowSize(800, 800);
glutCreateWindow("Cylinder");
glutDisplayFunc(display);
glutMainLoop();
}
I tried using the commented code for getting lines between points 300 degrees apart, do this every at point 10 degrees apart.(It looks good at 3 degrees apart).
Now, this obviously doesn't work as we use trigonometric functions, which won't space out the points equally.
I hope you understand my question, how can I get points on the circle equally apart?
One solution, I think might work is, while plotting the points itself, if I use an array to save every nth point, I may get equidistant points. Am I right? Is there any other way of getting the points?
Please do correct me if I am wrong anywhere above, I am just newbie here.
Note that sin and cos take their input in radians(i.e. 0 to 2* pi), not degrees(0 to 360). So your code should probably be
for (i = 0;i <= 360;i += 1)
{
glBegin(GL_POINTS);
glVertex2f(r*cos(i * (M_PI / 180.)), r*sin(i* (M_PI / 180.)));
glEnd();
}
edit:
To get N equidistant point we have to put them (1/N) part of the circle away from each other:
for (i = 0;i < N;i += 1)
{
double angle = i * (2.0 * M_PI / N);
glBegin(GL_POINTS);
glVertex2f(r*cos(angle), r*sin(angle));
glEnd();
}
I'm trying to create an effect of zooming on a rotating hexagon. I'm accomplishing this by changing the window. Once it "zooms in" it supposed to "zoom out", and then repeat continuously. I've managed to zoom in just fine, and by the looks of my code, it should zoom out as well, but once it zooms in, nothing else is drawn. I've debugged my code, and i can tell that the variables are indeed being incremented on this line:
gluOrtho2D(cx - w, cx + w, cy -h, cy +h);
But yet i still fail to see my hexagon "zoom out". Any help would be appreciated. I'm pretty sure its something simple i'm forgetting. But it keeps eluding me. My code follows:
#include <cstdlib>
#include <GL/glut.h>
#include <cmath>
#define PI 3.14159265
#define ZOOM_IN 1
#define ZOOM_OUT -1
using namespace std;
const int screenWidth = 500;
const int screenHeight = 500;
float cx = 0.0, cy = 0.0; //center of viewport (cx, cy)
float h=1.2, w = 1.2; //window size
int NumFrames = 10; //frames
int frame = 0;
int direction = ZOOM_IN;
//<<<<<<<<<<<<<<<<<<<<<<< myInit >>>>>>>>>>>>>>>>>>>>
void myinit() {
glClearColor (1.0, 1.0, 1.0, 1.0); //set the background color to white
glColor3f (0.0, 0.0, 0.0); //set the foreground color to black
glPointSize (3.0); //set the point size to 3 X 3 pixels
glViewport (0.0, 0.0, 500.0, 500.0); //set the viewport to be the entire window
//set up a world window to screen transformation
glMatrixMode (GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(-5.0, 5.0, -5.0, 5.0);
// glMatrixMode (GL_MODELVIEW);
}
//<<<<<<<<<<<<<<<<<<<<<<< hexswirl >>>>>>>>>>>>>>>>>>>>
void hexswirl() {
double angle; //the angle of rotation
double angleInc = 2*PI/6.0; //the angle increment
double inc = 5.0/50; //the radius increment
double radius = 5.0/50.0; //the radius to be used
//clear the background
glClear (GL_COLOR_BUFFER_BIT);
//draw the hexagon swirl
for (int j = 0; j <= 50; j++) {
//the angle of rotation depends on which hexagon is
//being drawn.
angle = j* (PI/180.0);
//draw one hexagon
glBegin (GL_LINE_STRIP);
for (int k=0; k <= 6; k++) {
angle += angleInc;
glVertex2d(radius * cos(angle), radius *sin(angle));
}
glEnd();
//determine the radius of the next hexagon
radius += inc;
}
//swap buffers for a smooth change from one
//frame to another
glutSwapBuffers();
glutPostRedisplay();
glFlush();
}
//<<<<<<<<<<<<<<<<<<<<<<< viewZoom >>>>>>>>>>>>>>>>>>>>
void viewZoom(int i) {
if(direction == ZOOM_IN) {
//change the width and height of the window each time
w *= 0.9;
h *= 0.9;
}
if(direction == ZOOM_OUT) {
w /= 0.9;
h /= 0.9;
}
if(i%10 == 0) {
direction = -direction;
}
//change the window and draw the hexagon swirl
gluOrtho2D (cx - w, cx + w, cy - h, cy + h);
hexswirl();
glutPostRedisplay();
glutTimerFunc(200, viewZoom,i+1);
}
//<<<<<<<<<<<<<<<<<<<<<<<< main >>>>>>>>>>>>>>>>>>>>>>
int main(int argc, char** argv) {
glutInit(&argc, argv);
glutInitDisplayMode( GLUT_DOUBLE | GLUT_RGB);
glutInitWindowSize(screenWidth, screenHeight);
glutInitWindowPosition(100,100);
glutCreateWindow("hexanim");
glutDisplayFunc(hexswirl);
viewZoom(1);
myinit();
glutMainLoop();
return 1;
}
I figured out a way around my problem. I still don't know why my window wasn't redrawing after "zooming in", but i decided to implement it through changing my viewport instead. I ended up switching out:
gluOrtho2D (cx - w, cx + w, cy - h, cy + h);
for
cx = screenWidth / w;
cy = screenHeight / h;
glViewport((screenWidth-cx)/2, (screenHeight-cy)/2, cx, cy);
(and made all the corresponding changes associated with it).