I am reading a book of opengl and there is a function to draw a circle but I don't know how to put this function in my code and run it and also I don't know what parameter I put in this.
I am new to opengl and I am trying to figure it out.
Code
#include <stdlib.h>
#include <GL/glut.h>
#include <cmath>
void keyboard(unsigned char key, int x, int y);
void display(void);
void drawCircle(float cx, float cy, float r, int num_segments);
int main(int argc, char** argv)
{
glutInit(&argc, argv);
glutKeyboardFunc(&keyboard);
glutDisplayFunc(&display);
glutMainLoop();
return EXIT_SUCCESS;
}
void keyboard(unsigned char key, int x, int y)
{
switch (key)
{
case '\x1B':
exit(EXIT_SUCCESS);
break;
}
}
void display()
{
glClear(GL_COLOR_BUFFER_BIT);
//drawCircle(, , , );
glFlush();
}
void drawCircle(float cx, float cy, float r, int num_segments)
{
glBegin(GL_LINE_LOOP);
for (int i = 0; i < num_segments; i++)
{
float theta = i * (2.0f * PI / num_segments); // get the current angle
float x = r * cos(theta); // calculate the x component
float y = r * sin(theta); // calculate the y component
glVertex2f(x + cx, y + cy); // output vertex
}
glEnd();
}
You're missing window creation and a setting the color of the circle you are
drawing:
#include <stdlib.h>
#include <gl/glut.h>
#include <math.h>
#define M_PI 3.14159265359
void keyboard(unsigned char key, int x, int y);
void display(void);
void drawCircle(float cx, float cy, float r, int num_segments);
int main(int argc, char** argv)
{
int width = 1280;
int height = 720;
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGB | GLUT_SINGLE);
glutInitWindowSize(width, height);
glutCreateWindow("circle");
glutKeyboardFunc(&keyboard);
glutDisplayFunc(&display);
glutMainLoop();
return EXIT_SUCCESS;
}
void keyboard(unsigned char key, int x, int y)
{
switch (key)
{
case '\x1B':
exit(EXIT_SUCCESS);
break;
}
}
void display()
{
glColor3f(1.0, 0, 0);
glClear(GL_COLOR_BUFFER_BIT);
gluOrtho2D(0.0, 1280, 0.0, 720);
glColor3f(1.0, 1.0, 1.0);
drawCircle(640, 360, 100, 200);
glFlush();
}
void drawCircle(float cx, float cy, float r, int num_segments)
{
glBegin(GL_LINE_LOOP);
for (int i = 0; i < num_segments; i++)
{
float theta = i * (2.0f * M_PI / num_segments); // get the current angle
float x = r * cos(theta); // calculate the x component
float y = r * sin(theta); // calculate the y component
glVertex2f(x + cx, y + cy); // output vertex
}
glEnd();
}
Related
Take inputs from keyboard such as "+" or "-" and increase/decrease sides accordingly. For example if a triangle is currently displayed and if i press "+", it should transform into a rectangle etc. How can I achieve that?
static void DisplayShape(void)
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glColor3d(1,0.1,0.6);
glBegin(GL_POINTS);
for(int i=0;i<n;++i) // n - sides count
{
glVertex2f(); // the n-sided shape is to be drawn here
}
glEnd();
glutSwapBuffers();
}
static void key(unsigned char key, int x, int y)
{
switch (key)
{
case 27 :
case 'q': // quit
exit(0);
break;
case '+': // increase sides count
n++;
break;
case '-': // decrease sides count
if (n > 3) // cannot be less than 3
{
n--;
}
break;
}
glutPostRedisplay();
}
static void idle(void)
{
glutPostRedisplay();
}
int main(int argc, char *argv[])
{
glutInit(&argc, argv);
glutInitWindowSize(640,480);
glutInitWindowPosition(10,10);
glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);
glutCreateWindow("GLUT Shapes");
glutDisplayFunc(DisplayShape);
glutKeyboardFunc(key);
glutIdleFunc(idle);
glutMainLoop();
return EXIT_SUCCESS;
}
Distribute the N-points around a circle. Compute the angle between the vectors from the center of the circle to the points (360°/N). Calculate the points using their Polar Coordinates:
const float x0 = 0.0f;
const float y0 = 0.0f;
const float sideLen = 0.5;
float dist = sideLen / 2.0f / sin(M_PI * 2.0f / n / 2.0f);
float startAngle = -M_PI * (n - 2) / 2 / n;
glBegin(GL_LINE_LOOP);
for (int i = 0; i < n; ++i) // n - sides count
{
float sideAngle = M_PI * 2.0 * i / n + startAngle;
float x = x0 + dist * cos(sideAngle);
float y = y0 + dist * sin(sideAngle);
glVertex2f(x, y);
}
glEnd();
Complete example:
#include <GL/gl.h>
#include <GL/glu.h>
#include <GL/freeglut.h>
#define _USE_MATH_DEFINES
#include <math.h>
int n = 3;
static void DisplayShape(void)
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glColor3d(1, 0.1, 0.6);
const float x0 = 0.0f;
const float y0 = 0.0f;
const float sideLen = 0.5;
float dist = sideLen / 2.0f / sin(M_PI * 2.0f / n / 2.0f);
float startAngle = -M_PI * (n - 2) / 2 / n;
glBegin(GL_LINE_LOOP);
for (int i = 0; i < n; ++i) // n - sides count
{
float sideAngle = M_PI * 2.0 * i / n + startAngle;
float x = x0 + dist * cos(sideAngle);
float y = y0 + dist * sin(sideAngle);
glVertex2f(x, y);
}
glEnd();
glutSwapBuffers();
glutPostRedisplay();
}
static void key(unsigned char key, int x, int y)
{
switch (key)
{
case 27:
case 'q': // quit
exit(0);
break;
case '+': // increase sides count
n++;
break;
case '-': // decrease sides count
if (n > 3) // cannot be less than 3
n--;
break;
}
glutPostRedisplay();
}
static void reshape(int width, int height)
{
glViewport(0, 0, width, height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
double aspect = (double)width / height;
glOrtho(-aspect, aspect, -1.0, 1.0, -1.0, 1.0);
glMatrixMode(GL_MODELVIEW);
}
int main(int argc, char* argv[])
{
glutInit(&argc, argv);
glutInitWindowSize(640, 480);
glutInitWindowPosition(10, 10);
glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);
glutCreateWindow("GLUT Shapes");
glutReshapeFunc(reshape);
glutDisplayFunc(DisplayShape);
glutKeyboardFunc(key);
glutMainLoop();
return EXIT_SUCCESS;
}
I'm trying to create a 2D hollow grid on top of a purple background; however, what's being displayed whenever I create the grid is a white window.
I created the 2D grid using GL_Lines, as I only wanted the borders to be colored white and not the inside of the grid, which is not what happens.
#include <stdio.h>
#include <stdlib.h>
#include <ctime>
#include <cmath>
#include <string.h>
#include<GL/glut.h>
int gridX = 1000;
int gridY = 600;
void drawGrid();
void drawUnit(int, int);
void drawGrid() {
for (int x = 0; x < gridX; x++) {
for (int y = 0; y < gridY; y++) {
drawUnit(x, y);
}
}
}
void drawUnit(int x, int y) {
glLineWidth(1.0);
glColor3f(1.0,1.0,1.0);
glBegin(GL_LINE);//(x,y)(x+1,y)(x+1,y+1)(x,y+1)
glVertex2f(x,y);
glVertex2f(x+1, y);
glVertex2f(x + 1, y);
glVertex2f(x+1, y+1);
glVertex2f(x + 1, y + 1);
glVertex2f(x, y+1);
glVertex2f(x, y + 1);
glVertex2f(x, y);
glEnd();
}
void Display() {
glClear(GL_COLOR_BUFFER_BIT);
drawGrid();
glFlush();
}
void main(int argc, char** argr) {
glutInit(&argc, argr);
glutInitWindowSize(gridX, gridY);
drawGrid();
glutCreateWindow("OpenGL - 2D Template");
glutDisplayFunc(Display);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
glClearColor(120.0f / 255.0f, 92.0f / 255.0f, 166.0f / 255.0f, 0.0f);
gluOrtho2D(0.0, gridX, 0.0, gridY);
glutMainLoop();
}
GL_LINE is not an OpenGL primitive type. But GL_LINES is a line primitive type (see Line primitives):
glBegin(GL_LINE);
glBegin(GL_LINES);
GL_LINE is a polygon rasterization mode (see glPolygonMode).
One cell in your grid is only 1 pixel in size. This results in the entire screen being filled in white. Use a different size for the cells. For instance:
void drawGrid()
{
int size = 10;
for (int x = 0; x < gridX; x += 10)
{
for (int y = 0; y < gridY; y += 10)
{
drawUnit(x, y, size);
}
}
}
void drawUnit(int x, int y, int size)
{
glLineWidth(1.0);
glColor3f(1.0,1.0,1.0);
glBegin(GL_LINES);
glVertex2f(x,y);
glVertex2f(x+size, y);
glVertex2f(x + size, y);
glVertex2f(x+size, y+size);
glVertex2f(x + size, y + size);
glVertex2f(x, y+size);
glVertex2f(x, y + size);
glVertex2f(x, y);
glEnd();
}
I have just tried to run the Bresenham function which draws a line from 2 vertexes, but only the white screen of GLUT appear, there is no line at all. Here is my source code, can anybody help me?
#include <math.h>
#include <windows.h>
#include <GL/glut.h>
#include <GL/gl.h>
void init(void)
{
glClearColor(1.0, 1.0, 1.0, 0.0);
glMatrixMode(GL_PROJECTION);
gluOrtho2D(0.0, 500.0, 0.0, 500.0);
}
void Bresenham(int x1, int y1, int x2, int y2) {
int Dx = abs(x2 - x1);
int Dy = abs(y2 - y1);
int p = 2 * Dy - Dx;
int c1 = 2 * Dy;
int c2 = 2 * (Dy - Dx);
int x = x1;
int y = y1;
int x_unit = 1, y_unit = 1;
glVertex2d(x, y);
while (x != x2) {
if (p<0) p += c1;
else {
p += c2;
y += y_unit;
}
x += x_unit;
glVertex2d(x, y);
}
}
void display(void)
{
glClear(GL_COLOR_BUFFER_BIT);
glBegin(GL_POLYGON);
Bresenham(50, 150, 300, 200);
glEnd();
glFlush();
}
int main(int iArgc, char** cppArgv) {
glutInit(&iArgc, cppArgv);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
glutInitWindowSize(600, 600);
glutInitWindowPosition(50, 50);
glutCreateWindow("Line");
init();
int x1=50, y1=150, x2=300, y2=200;
glutDisplayFunc(display);
glutMainLoop();
return EXIT_SUCCESS;
}
Make sure your background color doesn't match your drawing color. Kinda hard to see white-on-white :)
Drawing the line in red works on my machine:
#include <GL/glut.h>
void Bresenham(int x1, int y1, int x2, int y2)
{
int Dx = abs(x2 - x1);
int Dy = abs(y2 - y1);
int p = 2 * Dy - Dx;
int c1 = 2 * Dy;
int c2 = 2 * (Dy - Dx);
int x = x1;
int y = y1;
int x_unit = 1, y_unit = 1;
glVertex2d(x, y);
while (x != x2)
{
if (p<0)
p += c1;
else
{
p += c2;
y += y_unit;
}
x += x_unit;
glVertex2d(x, y);
}
}
void display(void)
{
glClearColor(1.0, 1.0, 1.0, 0.0);
glClear(GL_COLOR_BUFFER_BIT);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0.0, 500.0, 0.0, 500.0, -1, 1);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glBegin(GL_POLYGON);
glColor3ub( 255, 0, 0 );
Bresenham(50, 150, 300, 200);
glEnd();
glutSwapBuffers();
}
int main(int argc, char** argv )
{
glutInit( &argc, argv );
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);
glutInitWindowSize(600, 600);
glutCreateWindow("Line");
glutDisplayFunc(display);
glutMainLoop();
return 0;
}
I want to draw a 2D line with parameters defined by user. But the range of x and y axis is [-1,1].
How can I draw the line that can be completely displayed in the window? I used gluOrtho2D(-10.0, 10.0, -10.0, 10.0) but it doesn't seem a good choice because the range is dynamic according to the parameters.
For example, the line is y=ax^3+bx^2+cx+d. the range of x is [1, 100].
My code is:
#include "pch.h"
#include<windows.h>
#include <gl/glut.h>
#include <iostream>
using namespace std;
double a, b, c, d;
void init(void)
{
glClear(GL_COLOR_BUFFER_BIT);
glMatrixMode(GL_PROJECTION);
gluOrtho2D(-10.0, 10.0, -10.0, 10.0);
}
double power(double x, int p) {
double y = 1.0;
for (int i = 0; i < p; ++i) {
y *= x;
}
return y;
}
void linesegment(void)
{
glClear(GL_COLOR_BUFFER_BIT);
glColor3f(1, 0, 0);
glPointSize(1);
glBegin(GL_POINTS);
for (int i = 1; i <= 10; ++i) {
double y = a * power(i, 3) + b * power(i, 2) + c * i + d;
glVertex2f(i, y);
}
glEnd();
glFlush();
}
int main(int argc, char**argv)
{
if (argc < 4) {
cout << "should input 4 numbers" << endl;
return 0;
}
a = atof(argv[1]);
b = atof(argv[2]);
c = atof(argv[3]);
d = atof(argv[4]);
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
glutInitWindowPosition(50, 100);
glutInitWindowSize(400, 300);
glutCreateWindow("AnExample");
init();
glutDisplayFunc(linesegment);
glutMainLoop();
return 0;
}
Setting projection matrix is not a one-time-only operation. You can change it anytime you like. As a matter of fact, the way you do init is strongly discouraged. Just set the projection parameters in your drawing function. Also use standard library functions and don't roll your own. No need to implement power yourself. Just use the pow standard library function. Last but not least, use double buffering; for it gives better performance, and has better compatibility.
#include "pch.h"
#include <windows.h>
#include <gl/glut.h>
#include <iostream>
#include <cmath>
using namespace std;
double a, b, c, d;
double x_min, x_max, y_min, y_max; // <<<<---- fill these per your needs
void linesegment(void)
{
glClear(GL_COLOR_BUFFER_BIT);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(x_min, x_max, y_min, y_max, -1, 1);
glColor3f(1, 0, 0);
glPointSize(1);
glBegin(GL_POINTS);
for (int i = 1; i <= 10; ++i) {
double y = a * pow(i, 3) + b * pow(i, 2) + c * i + d;
glVertex2f(i, y);
}
glEnd();
glFlush();
}
I've written a code that inputs n and draws N-pointed star,
just like this one:
when n=5 and filed
the problem that is whenever n=7 or 8 or 16 or 25...
I get a problem in the star drawing it becomes like this :
when n=7 and filled
Here's my code:
#include <iostream>
#include <ctime>
#include <vector>
#include <glut.h>
using namespace std;
float starCenterX, starCenterY, starRadius;
int numPoints;
bool bDrawFill = false;
void DrawStar (float cx, float cy, float radius, int numPoints);
void DrawStarFilled (float cx, float cy, float radius, int numPoints);
float width, height; // global variables to store window width and height
// render text
void renderBitmapString (float x, float y, float z, void* font, const char* string)
{
const char *c;
glRasterPos3f (x, y,z);
for (c = string; *c != '\0'; c++)
glutBitmapCharacter (font, *c);
}
void init ()
{
glClearColor (1.0, 1.0, 1.0, 0.0); // set display-window color to white
}
void reshape (int width, int height)
{
::width = width;
::height = height;
glViewport (0, 0, width, height);
glMatrixMode (GL_PROJECTION); // set projection parameters
glLoadIdentity ();
gluOrtho2D (0.0, width, 0.0, height);
glMatrixMode (GL_MODELVIEW); // set projection parameters
glLoadIdentity ();
}
void display ()
{
glClear (GL_COLOR_BUFFER_BIT); // clear display window
glColor3f (0, 0, 1);
renderBitmapString (10, height - 20, 0, GLUT_BITMAP_TIMES_ROMAN_24, "Name : Saif Badran");
renderBitmapString (10, height - 50, 0, GLUT_BITMAP_TIMES_ROMAN_24, "ID : 0142852");
renderBitmapString (10, height - 80, 0, GLUT_BITMAP_TIMES_ROMAN_24, "Section : 2");
DrawStar(starCenterX,starCenterY,starRadius,numPoints);
if(bDrawFill)
DrawStarFilled(starCenterX,starCenterY,starRadius,numPoints);
glFlush (); // process all openGl routines as quickly as possible
}
void processNormalKeys (unsigned char key, int x, int y)
{
if(key=='w' || key=='W')
starCenterY+=4;
else if(key=='z' || key=='Z')
starCenterY-=4;
else if(key=='a' || key=='A')
starCenterX-=4;
else if(key=='d' || key=='D')
starCenterX+=4;
else if(key=='f' || key=='F')
bDrawFill = (bDrawFill==1?0:1);
}
void mouseClick (int button, int state, int x, int y)
{
if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN)
{
starCenterX = x;
starCenterY = height - y;
}
}
void activeMouseMotion (int x, int y)
{
starRadius = abs(starCenterX-x);
}
void main (int argc, char** argv)
{
cout<<"Enter number of points : ";
cin>>numPoints;
numPoints = (numPoints < 2) ? 2 : numPoints;
glutInit (&argc, argv); // initialize GLUT
glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB); // set display mode
glutInitWindowPosition (20, 20); // set top left display window position
glutInitWindowSize (600, 600); // set display window width and height
glutCreateWindow ("Homework#2 : Star Drawing"); // create display window
init (); // execute initialization function
glutKeyboardFunc (processNormalKeys);
glutMouseFunc (mouseClick);
glutMotionFunc (activeMouseMotion);
glutReshapeFunc (reshape);
glutDisplayFunc (display); // send graphics to display window
glutIdleFunc (display);
glutMainLoop (); // dispaly everthing and wait
}
void DrawStar (float cx, float cy, float radius, int numPoints)
{
const float DegToRad = 3.14159 / 180;
glColor3f(1.0,0.0,0.0);
glBegin (GL_POINTS);
int count = 1;
for (int i = 0; i <= 360; i+=360/(numPoints*2)) {
float DegInRad = i * DegToRad;
if(count%2!=0)
glVertex2d (cx + cos (DegInRad) * radius, cy + sin (DegInRad) * radius);
else
glVertex2d ((cx + cos (DegInRad) * radius/2), (cy + sin (DegInRad) * radius/2));
count++;
}
glEnd();
glBegin (GL_LINE_LOOP);
count = 1;
for (int i = 0; i <= 360; i+=360/(numPoints*2)) {
float DegInRad = i * DegToRad;
if(count%2!=0)
glVertex2d (cx + cos (DegInRad) * radius, cy + sin (DegInRad) * radius);
else
glVertex2d ((cx + cos (DegInRad) * radius/2), (cy + sin (DegInRad) * radius/2));
count++;
}
glEnd();
}
void DrawStarFilled (float cx, float cy, float radius, int numPoints)
{
const float DegToRad = 3.14159 / 180;
glBegin (GL_TRIANGLE_FAN);
int count = 1;
glVertex2f(starCenterX, starCenterY);
for (int i = 0; i <= 360; i+=360/(numPoints*2)) {
float DegInRad = i * DegToRad;
if(count%2!=0)
glVertex2d (cx + cos (DegInRad) * radius, cy + sin (DegInRad) * radius);
else
glVertex2d ((cx + cos (DegInRad) * radius/2), (cy + sin (DegInRad) * radius/2));
count++;
}
glEnd();
}
The issue is in this line:
for (int i = 0; i <= 360; i+=360/(numPoints*2)) {
For numPoints = 5, for each step i will be incremented with 360/(2*5) = 36.
For numPoints = 7, for each step i will be incremented with 360/(2*7) = 25 (integer division, truncating 25.714... to 25). So, at each step there is a 0.714.. degrees loss. Cummulated, this is: 360 - 14 * 25 = 10 degrees. This can be seen on the output picture.
To solve this we can use a floating point variable for the step counter, and to increment it with a floating point value obtained from a floating point division, using for example 360.0 as the numerator. (Actually 360.0 is stored as a double, to store it as a single precision float it should be 360.0f).
for (float i = 0; i <= 360; i+=360.0/(numPoints*2)) {
But doing so, we may have trouble at the i <= 360 comparison, there are quantization errors resulting from floating point operations (i could be slightly smaller or bigger than the "mathematical" value). So it would be better to keep the integer counter for the loop, and do the floating point operations afterwards. This code part:
for (int i = 0; i <= 360; i+=360/(numPoints*2)) {
float DegInRad = i * DegToRad;
would then be changed to:
for (int i = 0; i <= numPoints*2; i++) {
float DegInRad = i * 360.0/(numPoints*2) * DegToRad;