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();
}
Related
So, I have a matrix of pairs of x and y coordinates, each line in the matrix represents a route, which I would like to represent as a GL_LINE_STRIP in OpenGL. The thing is I would like to draw the lines with different colors each time. I thought my code would work, but somehow OpenGL keeps drawing the line_strips with the same color.
I thought this would do the work, xy is the matrix of pairs of coordinates:
static void Redraw(void)
{
...
glClear(GL_COLOR_BUFFER_BIT);
//drawing routes
srand(time(NULL));
for(int i = 0; i < xy.size(); i++)
{
vector<pair<int, int>> route = xy[i];
double r = ((double) rand() / (RAND_MAX));
double g = ((double) rand() / (RAND_MAX));
double b = ((double) rand() / (RAND_MAX));
glColor3f(r,g,b);
glLineWidth(2);
glBegin(GL_LINE_STRIP);
for(int j = 0; j < route.size();j++)
glVertex2d(route[j].first, route[j].second);
glEnd();
}
glFlush();
}
and my main:
int main(int argc,char *argv[])
{
glutInit(&argc,argv);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
glutInitWindowSize(1080,720);
glutInitWindowPosition(0,0);
glutCreateWindow("h_constante");
gluOrtho2D(0,1000,0,1000);
glutDisplayFunc(Redraw);
glutMainLoop();
return 0;
}
I was pushing all my nodes inside the first line in the matrix so I was actually drawing one big GL_LINE_STRIP. Thanks a lot for all the help!
// #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 working on an nbody simulator and I want to display it with OpenGL. I want to always be looking at the centre of mass reference frame. I have the following code. I calculate the COM and I set the center coordinate in the gluLookAt function to be the center of mass. I then subtract the "zoom" from the z coordinate to get the eye position. By logic this should ensure that I am always looking at whatever value the center of mass is. The only issue is that I marked where the center of mass should be on the screen with a red dot and it is moving. Shouldn't it never move if I am always looking at it from the same relative position? Here is my code. Focus on the display function since I assume that is where the error will be. I had similar code working in another project and I can't really find any differences.
#include "Universe.cuh"
#include <iostream>
#include <cstdlib>
#include <ctime>
#include "timer.hpp"
#include <GL/glut.h>
Universe u;
float* vbuf;
double angle = 0.0, zoom = 1000;
void display()
{
glClearColor(0, 0, 0, 0);
glClear(GL_COLOR_BUFFER_BIT);
glLoadIdentity();
float3 c = u.getCenterOfMass();
gluLookAt(c.x, c.y, c.z - zoom, c.x, c.y, c.z, 0, 1, 0);
glScalef(0.1, 0.1, 0.1);
glRotated(angle, 1, 0, 0);
glColor4f(1, 1, 1, 0.25);
glBegin(GL_POINTS);
{
glColor3f(1.0, 0.0, 0.0);
glVertex3d(c.x, c.y, c.z);
}
glEnd();
glutSwapBuffers();
}
void reshape(int w, int h)
{
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(60, (double)w / (double)h, 1.0, zoom * 1e9);
glMatrixMode(GL_MODELVIEW);
}
void copy_to_vbuf()
{
for(int i = 0; i < u.size(); i++)
{
vbuf[3 * i + 0] = u.getObjects()[i].p.x;
vbuf[3 * i + 1] = u.getObjects()[i].p.y;
vbuf[3 * i + 2] = u.getObjects()[i].p.z;
}
}
void keyboard(unsigned char c, int x, int y)
{
if(c == 'w')
angle += 1;
else if(c == 's')
angle -= 1;
else if(c == '=')
zoom /= 1.2;
else if(c == '-')
zoom *= 1.2;
glutPostRedisplay();
}
void idle()
{
u.timeStep();
copy_to_vbuf();
glutPostRedisplay();
}
int main(int argc, char** argv)
{
cudaSetDevice(0);
srand(time(0));
u.getConfiguration().max_velocity = 10;
u.getConfiguration().softening_factor = 0.01;
u.getConfiguration().threshold_angle = 35;
u.getConfiguration().time_step = 0.1;
const int N = 5;
vbuf = new float[3 * N];
for(int i = 0; i < N; i++)
{
Object o;
o.m = rand() % 100 + 1;
o.p.x = 500.0 * rand() / RAND_MAX - 250.0;
o.p.y = 500.0 * rand() / RAND_MAX - 250.0;
o.p.z = 500.0 * rand() / RAND_MAX - 250.0;
u.addObject(o);
}
copy_to_vbuf();
glutInit(&argc, argv);
glutInitDisplayMode(GL_DOUBLE);
glutInitWindowSize(1000, 1000);
glutCreateWindow("N-Body");
glutReshapeFunc(reshape);
glutDisplayFunc(display);
glutIdleFunc(idle);
glutKeyboardFunc(keyboard);
glEnable(GL_POINT_SMOOTH);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glPointSize(1.0);
glutMainLoop();
return 0;
}
Two points regarding:
glScalef(0.1, 0.1, 0.1);
glRotated(angle, 1, 0, 0);
Since your axis is not centered on the 'COM', when you apply rotation the COM point will not stay in place and logically would move around the screen.
AFIK the normal order is scale,rotate,translate for transformations. This will apply the rotation and then scale.
EDIT:
To expand on that: Currently you take an arbitrary point rotate it, scale it and then focus on the point where it used to be. If you want to rotate your model (e.g. point marking the 'COM') around itself, it needs to be centered at (0,0,0).
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.
i have the following code which draws nothing.
If i use glBegin(GL_POINTS) it draws a circle but with polygon mode it doesn't.
int WXSIZE=500,WYSIZE=500;
//Coordinate system
float Xmin=-8, Xmax=8, Ymin=-8, Ymax=8;
void setupmywindow()
{
glClearColor(0,0,0,0);
gluOrtho2D(Xmin, Xmax, Ymin, Ymax);
}
void mypolygon(float radius) //test object
{
glColor3f(1,0,0);
int numPoints=20;
float x,y;
float centerx,centery=0;
for (int i = 0; i < numPoints; i++)
{
x = centerx + radius * sin(2.0*PI*i/numPoints);
y = centery + radius * cos(2.0*PI*i/numPoints);
glPolygonMode(GL_FRONT_AND_BACK,GL_LINE);
glBegin(GL_POLYGON);
glVertex2f(x, y);
glEnd();
}
}
void myDisplay()
//single object
{
glClear(GL_COLOR_BUFFER_BIT);
mypolygon(2.0);
glutSwapBuffers();
}
int main(int argc, char **argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE|GLUT_RGB);
glutInitWindowSize(WXSIZE,WYSIZE);
glutCreateWindow("My graphic window");
setupmywindow();
glutDisplayFunc(myDisplay);
glutMainLoop();
}
Any suggestions?
EDIT----------------------
glBegin(GL_POLYGON);
for (int i = 0; i < numPoints; i++)
{
x = centerx + radius * sin(2.0*PI*i/numPoints);
y = centery + radius * cos(2.0*PI*i/numPoints);
glVertex2f(x, y);
}
glEnd();
I messed it with the loop.
In every loop you are drawing a polygon, that consists of a single vertex, so nothing. Just put the glBegin/glEnd (and the glPolygonMode) outside of the for loop and only draw glVertex in the loop. Of course it works with points, as a n times a single point is the same as n points. But n polygon consisting of one point each is not the same as one polygon consisting of n points.
Your polygon seems to be on the wrong side. By default, OpenGL only shows front faces, which need to be specified counterclockwise. You can:
Invert the order of your primitives (for (int i = numPoints-1; i >= 0 ; i--))
Invert the front face (glFrontFace(GL_CW))
Disable back face culling (glDisable(GL_CULL_FACE)).
When you call glBegin with GL_POLYGON, it is expecting I believe a minimum of three vertices. Standard drawing protocol is to draw using triangles, witch vertices in sets of three, since you need three vertices for each triangle face. You are only feeding it a single vertex, so you're not going to see anything. Try changing it to this:
glBegin(GL_TRIANGLES);
glVertex2f(x1, y1);
glVertex2f(x2, y2);
glVertex2f(x3, y3);
glEnd();