I already know none of you is going to be able to replicate this bug but I don't even know what to try anymore. This is the code:
void Arrow2D(double x, double y, double x2, double y2, double width) {
double deltaX = x2 - x;
double deltaY = y2 - y;
double angle = atan2(deltaY, deltaX) * 180 / 3.14;
double heightArrow = sqrt(deltaX*deltaX + deltaY*deltaY);
printf("height = sqrt(%f) = %f\n", deltaX*deltaX + deltaY*deltaY, heightArrow);
/*glPushMatrix(GL_MODELVIEW);
glRotatef(angle, 0.0, 0.0, 1.0);
glColor3f(1.0, 1.0, 1.0);
//glTranslatef(200, 200, 0);
glBegin(GL_QUADS);
glVertex2f(-width/2, 20);
glVertex2f(-width/2, 0);
glVertex2f(width/2, 0);
glVertex2f(width/2, 20);
glEnd();
glBegin(GL_TRIANGLES);
glVertex2f(-width/1.2, 20);
glVertex2f(+width/1.2, 20);
glVertex2f(0, 30);
glEnd();
glPopMatrix(GL_MODELVIEW);*/
}
Now, if the second part is commented the value of the variable heightArrow gets printed correctly. If I uncomment the commented code I just get the following print:
height = sqrt(5000.000000) = 0.000000
Basically I always get 0 as output (this is the same behavior for the atan2 function that I'm using to calculate the angle). The Arrow2D method is called in one of my visualization functions called in the GLUT display method.
Related
The following code shows a straight cylinder/pipe in OpenGL C language.
#include <stdio.h>
#include <stdlib.h>
#include <GL/glut.h>
#include <math.h>
#define PI 3.1415927
void draw_cylinder(GLfloat radius, GLfloat height, GLubyte R, GLubyte G, GLubyte B)
{
GLfloat x = 0.0;
GLfloat y = 0.0;
GLfloat angle = 0.0;
GLfloat angle_stepsize = 0.1;
// Draw the tube
glColor3ub(R-40,G-40,B-40);
glBegin(GL_QUAD_STRIP);
angle = 0.0;
while( angle < 2*PI ) {
x = radius * cos(angle);
y = radius * sin(angle);
glVertex3f(x, y , height);
glVertex3f(x, y , 0.0);
angle = angle + angle_stepsize;
}
glVertex3f(radius, 0.0, height);
glVertex3f(radius, 0.0, 0.0);
glEnd();
// Draw the circle on top of cylinder
glColor3ub(R,G,B);
glBegin(GL_POLYGON);
angle = 0.0;
while( angle < 2*PI ) {
x = radius * cos(angle);
y = radius * sin(angle);
glVertex3f(x, y , height);
angle = angle + angle_stepsize;
}
glVertex3f(radius, 0.0, height);
glEnd();
}
void display(void)
{
glClear(GL_COLOR_BUFFER_BIT);
glLoadIdentity();
glTranslatef(-0.5,0.0,-2.5);
glRotatef(100.0, 0.725, 1.0, 1.0);
draw_cylinder(0.15, 1.0, 255, 160, 100);
glFlush();
}
void reshape(int width, int height)
{
if (width == 0 || height == 0) return;
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(35.0, (GLdouble)width/(GLdouble)height,0.5, 20.0);
glMatrixMode(GL_MODELVIEW);
glViewport(0, 0, width, height);
}
int main(int argc, char **argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
glutInitWindowSize(640,580);
glutCreateWindow("Create Cylinder");
glClearColor(0.0,0.0,0.0,0.0);
glutDisplayFunc(display);
glutReshapeFunc(reshape);
glutMainLoop();
return 0;
}
At the moment it draws a straight cylinder/pipe. And I wanted to curve it to look like this.
First I recommend to split the cylinder into slices. The following cone will draw exactly the same cylinder, but it splits the cylinder int slices. The slices have different colors to visualize the effect.
GLfloat h0, h1, angle, x, y;
int i, j;
int slices = 8;
for ( i = 0; i < slices; i++ )
{
h0 = (float)i / (float)slices;
h1 = (float)(i+1) / (float)slices;
glColor3f( 1.0f-h0, 0.0, h1 );
glBegin(GL_QUAD_STRIP);
for ( j = 0; j <= 360; ++ j )
{
angle = PI * (float)j * PI / 180.0f;
x = radius * cos(angle);
y = radius * sin(angle);
glVertex3f( x, y, h0 );
glVertex3f( x, y, h1 );
}
glEnd();
}
Then you have to define a bend radius and a bend start and end angle. The following code draw a bended pipe form bend_ang0 to bend_ang1, with a radius bend_radius. The bend angles can be calculated in relation to the bend radius and the length of the pipe:
GLfloat w0, w1, ang0, ang1, angle, x, y, xb, yb, zb;
int i, j;
int slices = 8;
GLfloat bend_radius = 1.0f;
GLfloat bend_angle, bend_ang0, bend_ang1;
bend_angle = bend_radius * height;
bend_ang0 = -bend_angle/2.0f;
bend_ang1 = bend_angle/2.0f;
for ( i = 0; i < slices; i++ )
{
w0 = (float)i / (float)slices;
w1 = (float)(i+1) / (float)slices;
ang0 = bend_ang0 + (bend_ang1-bend_ang0) * w0;
ang1 = bend_ang0 + (bend_ang1-bend_ang0) * w1;
glColor3f( 1.0f-w0, 0.0, w1 );
glBegin(GL_QUAD_STRIP);
for ( j = 0; j <= 360; ++ j )
{
angle = PI * (float)j * PI / 180.0f;
x = radius * cos(angle) + bend_radius;
y = radius * sin(angle);
xb = sin( ang0 ) * x;
yb = y;
zb = cos( ang0 ) * x;
glVertex3f( xb, yb, zb );
xb = sin( ang1 ) * x;
yb = y;
zb = cos( ang1 ) * x;
glVertex3f( xb, yb, zb );
}
glEnd();
}
For the following image I activated the depth test and changed the model view matrix:
void display(void)
{
glEnable( GL_DEPTH_TEST );
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
glTranslatef(0.0f, -0.5f, -4.0f);
glRotatef(-90.0f, 1.0f, 0.0, 0.0f);
draw_cylinder(0.15, 2.0, 255, 160, 100);
glFlush();
}
Currently you are drawing the entire height of the cylinder in one go ... to create a curved surface you must instead take your existing code and have it create a succession of tiny cylinders each with a tiny height then stack them up to consume the original height.
One approach would be to introduce a new function which becomes the parent of your
void draw_cylinder(GLfloat radius, GLfloat height, GLubyte R, GLubyte G, GLubyte B)
perhaps call it
draw_curved_cylinder
inside this new function you have a loop where you make calls to draw_cylinder giving it the parameters of each of these tiny cylinders ... currently your draw function blindly stretches the height from 0 to your given height ... replace that with settings for the given tiny cylinder ... also to make the final cylinder curved each tiny cylinder must have its X and Y coordinates follow the curved trajectory so in that new function draw_curved_cylinder increment those so they vary as your synthesize each new tiny cylinder
PS - be aware that you are not using modern OpenGL - glBegin is obsolete and should be avoided
I am trying to rotate the viewer about the y-axis. I have a function called tranform_eye() which will calculate the next position of eyex, eyey and eyez after each update.
Can anyone help me figure out how to calculate the values for eyex, eyey and eyez?
My Code:
float eyex = 5;
float eyey = 5;
float eyez = 5;
void display() {
transform_eye();
glMatrixMode(GL_PROJECTION); // To operate on model-view matrix
glLoadIdentity();
gluPerspective(40.0, 1.0, 1.0, 10000.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(eyex, eyey, eyez,
0.0, 0.0, 0.0,
0.0, 1.0, 0.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Clear color and depth buffers
drawTriangles();
glutSwapBuffers(); // Swap the front and back frame buffers (double buffering)
}
void transform(){
/// calculate new eyex, y z.
}
Applying the math from e.g. this answer gives us:
void transform()
{
float theta = 0.01; //angle in radians to rotate every frame
float cosTheta = cos(theta);
float sinTheta = sin(theta);
float newX = cosTheta * eyeX + sinTheta * eyeZ;
eyeZ = -sinTheta * eyeX + cosTheta * eyeZ;
eyeX = newX;
}
The following code shows a straight cylinder/pipe in OpenGL C language.
#include <stdio.h>
#include <stdlib.h>
#include <GL/glut.h>
#include <math.h>
#define PI 3.1415927
void draw_cylinder(GLfloat radius, GLfloat height, GLubyte R, GLubyte G, GLubyte B)
{
GLfloat x = 0.0;
GLfloat y = 0.0;
GLfloat angle = 0.0;
GLfloat angle_stepsize = 0.1;
// Draw the tube
glColor3ub(R-40,G-40,B-40);
glBegin(GL_QUAD_STRIP);
angle = 0.0;
while( angle < 2*PI ) {
x = radius * cos(angle);
y = radius * sin(angle);
glVertex3f(x, y , height);
glVertex3f(x, y , 0.0);
angle = angle + angle_stepsize;
}
glVertex3f(radius, 0.0, height);
glVertex3f(radius, 0.0, 0.0);
glEnd();
// Draw the circle on top of cylinder
glColor3ub(R,G,B);
glBegin(GL_POLYGON);
angle = 0.0;
while( angle < 2*PI ) {
x = radius * cos(angle);
y = radius * sin(angle);
glVertex3f(x, y , height);
angle = angle + angle_stepsize;
}
glVertex3f(radius, 0.0, height);
glEnd();
}
void display(void)
{
glClear(GL_COLOR_BUFFER_BIT);
glLoadIdentity();
glTranslatef(-0.5,0.0,-2.5);
glRotatef(100.0, 0.725, 1.0, 1.0);
draw_cylinder(0.15, 1.0, 255, 160, 100);
glFlush();
}
void reshape(int width, int height)
{
if (width == 0 || height == 0) return;
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(35.0, (GLdouble)width/(GLdouble)height,0.5, 20.0);
glMatrixMode(GL_MODELVIEW);
glViewport(0, 0, width, height);
}
int main(int argc, char **argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
glutInitWindowSize(640,580);
glutCreateWindow("Create Cylinder");
glClearColor(0.0,0.0,0.0,0.0);
glutDisplayFunc(display);
glutReshapeFunc(reshape);
glutMainLoop();
return 0;
}
At the moment it draws a straight cylinder/pipe. And I wanted to curve it to look like this.
First I recommend to split the cylinder into slices. The following cone will draw exactly the same cylinder, but it splits the cylinder int slices. The slices have different colors to visualize the effect.
GLfloat h0, h1, angle, x, y;
int i, j;
int slices = 8;
for ( i = 0; i < slices; i++ )
{
h0 = (float)i / (float)slices;
h1 = (float)(i+1) / (float)slices;
glColor3f( 1.0f-h0, 0.0, h1 );
glBegin(GL_QUAD_STRIP);
for ( j = 0; j <= 360; ++ j )
{
angle = PI * (float)j * PI / 180.0f;
x = radius * cos(angle);
y = radius * sin(angle);
glVertex3f( x, y, h0 );
glVertex3f( x, y, h1 );
}
glEnd();
}
Then you have to define a bend radius and a bend start and end angle. The following code draw a bended pipe form bend_ang0 to bend_ang1, with a radius bend_radius. The bend angles can be calculated in relation to the bend radius and the length of the pipe:
GLfloat w0, w1, ang0, ang1, angle, x, y, xb, yb, zb;
int i, j;
int slices = 8;
GLfloat bend_radius = 1.0f;
GLfloat bend_angle, bend_ang0, bend_ang1;
bend_angle = bend_radius * height;
bend_ang0 = -bend_angle/2.0f;
bend_ang1 = bend_angle/2.0f;
for ( i = 0; i < slices; i++ )
{
w0 = (float)i / (float)slices;
w1 = (float)(i+1) / (float)slices;
ang0 = bend_ang0 + (bend_ang1-bend_ang0) * w0;
ang1 = bend_ang0 + (bend_ang1-bend_ang0) * w1;
glColor3f( 1.0f-w0, 0.0, w1 );
glBegin(GL_QUAD_STRIP);
for ( j = 0; j <= 360; ++ j )
{
angle = PI * (float)j * PI / 180.0f;
x = radius * cos(angle) + bend_radius;
y = radius * sin(angle);
xb = sin( ang0 ) * x;
yb = y;
zb = cos( ang0 ) * x;
glVertex3f( xb, yb, zb );
xb = sin( ang1 ) * x;
yb = y;
zb = cos( ang1 ) * x;
glVertex3f( xb, yb, zb );
}
glEnd();
}
For the following image I activated the depth test and changed the model view matrix:
void display(void)
{
glEnable( GL_DEPTH_TEST );
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
glTranslatef(0.0f, -0.5f, -4.0f);
glRotatef(-90.0f, 1.0f, 0.0, 0.0f);
draw_cylinder(0.15, 2.0, 255, 160, 100);
glFlush();
}
Currently you are drawing the entire height of the cylinder in one go ... to create a curved surface you must instead take your existing code and have it create a succession of tiny cylinders each with a tiny height then stack them up to consume the original height.
One approach would be to introduce a new function which becomes the parent of your
void draw_cylinder(GLfloat radius, GLfloat height, GLubyte R, GLubyte G, GLubyte B)
perhaps call it
draw_curved_cylinder
inside this new function you have a loop where you make calls to draw_cylinder giving it the parameters of each of these tiny cylinders ... currently your draw function blindly stretches the height from 0 to your given height ... replace that with settings for the given tiny cylinder ... also to make the final cylinder curved each tiny cylinder must have its X and Y coordinates follow the curved trajectory so in that new function draw_curved_cylinder increment those so they vary as your synthesize each new tiny cylinder
PS - be aware that you are not using modern OpenGL - glBegin is obsolete and should be avoided
I have been asked to design and animate a solar system in openGL. I am doing so in C. I am a bit confused as to exactly how I should go about animating the orbits. How should I be incrementing the rotation angle for each planet to control the speed of it's orbit around the sun?
Here is all of the code I have written so far, just trying to take it step by step:
#include <GL/glut.h>
#include <GL/glu.h>
#define FACTOR 30.0
#define SLICES 25
#define STACKS 25
//Viewing angle variables
int eye_x = 2.0;
int eye_y = 3.0;
int eye_z = 10.0;
int up_x = 0.0;
int up_y = 1.0;
int up_z = 0.0;
//Planet diameters in relation to earth
double sun_radius = 100.0;
double earth_radius = 1.0;
double moon_radius = 0.2724;
double mercury_radius = 0.383;
double venus_radius = 0.949;
double mars_radius = 0.532;
double jupiter_radius = 11.21;
double saturn_radius = 9.45;
double uranus_radius = 4.01;
double neptune_radius = 3.88;
double pluto_radius = 0.187;
//Planet distances from sun in relation to earth's distance
double mercury_distance = (sun_radius / FACTOR) + 0.387;
double venus_distance = mercury_distance + 0.723;
double earth_distance = venus_distance + 1.0;
double mars_distance = earth_distance + 1.52;
double jupiter_distance = mars_distance + 5.20;
double saturn_distance = jupiter_distance + 9.58;
double uranus_distance = saturn_distance + 19.20;
double neptune_distance = uranus_distance + 30.05;
double pluto_distance = neptune_distance + 39.24;
/**
* Init function initializing the background to black.
*/
void init()
{
glClearColor(0.0, 0.0, 0.0, 0.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
glOrtho(-100.0, 100.0, -100.0, 100.0, -100.0, 100.0);
glMatrixMode(GL_MODELVIEW | GL_PROJECTION);
glEnable(GL_DEPTH_TEST);
gluLookAt(eye_x, eye_y, eye_z, 0.0, 0.0, 0.0, up_x, up_y, up_z);
}
/*
void stars()
{
int noOfStars = rand() % 10;
int i = 0;
while(i < noOfStars)
{
glColor3f(1.0, 1.0, 1.0);
glPointSize(20.0f);
int x = rand() % 10;
int y = rand() % 10;
int z = -8.0;
glBegin(GL_POINTS);
glVertex3f(x, y, z);
glEnd();
i++;
}
glFlush();
glutSwapBuffers();
}
*/
void display()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
//stars();
//"Zoom out"
glTranslatef(0.0, 0.0, -20.0);
//Draw sun
glColor4f(1.0, 0.5, 0.0, 0.3);
glutWireSphere(sun_radius / FACTOR, SLICES, STACKS);
//Draw mercury
//Rotate around sun
//glRotatef(, 0.0, 1.0, 0.0);
//Distance from sun to mercury
glTranslatef(mercury_distance, 0.0, 0.0);
glPushMatrix();
//glRotatef( , 0.0, 1.0, 0.0);
glColor4f(1.0, 0.75, 0.75, 0.3);
glutWireSphere(mercury_radius, SLICES, STACKS);
glPopMatrix();
/*
//Draw venus
//Distance from sun to venus
glTranslatef(venus_distance, 0.0, 0.0);
glPushMatrix();
glColor4f(1.0, 0.75, 0.75, 0.3);
glutWireSphere(venus_radius, SLICES, STACKS);
glPopMatrix();
//Draw earth
//Distance from sun to earth
glTranslatef(earth_distance, 0.0, 0.0);
glPushMatrix();
glColor4f(1.0, 0.75, 0.75, 0.3);
glutWireSphere(earth_radius, SLICES, STACKS);
glPopMatrix();
*/
glFlush();
glutSwapBuffers();
}
void reshape(int w, int h)
{
glViewport(0, 0, (GLsizei) w, (GLsizei) h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glFrustum(-1.0, 1.0, -1.0, 1.0, 1.5, 20.0);
glMatrixMode(GL_MODELVIEW);
}
int main(int argc, char* argv[])
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH);
glutInitWindowPosition(0,0);
glutInitWindowSize(1000, 1000);
glutCreateWindow("solar system");
init();
glutDisplayFunc(display);
glutReshapeFunc(reshape);
glutMainLoop();
return 0;
}
First, there is not a single distance from the sun for any of the planets - they move in a Kepler ellipse. (Earth was closest to the sun two weeks ago at the beginning of January and will be farthest away in summer.)
Accordingly, the position angle of a planet will not change at a constant rate, if you want to do this accurately. You can of course simplify and say that planetary orbits are close enough to circles for this not to matter (and say that Pluto is not a planet any more, so it even doesn't matter there).
But let's go for an exact solution: This is governed by Newton's law:
F = g * M_1 * M_2 / r^2 // How do you put equations here?
and energy conservation, trading kinetic energy E = M v^2 / 2 for potential energy E = - g * M_1 * M_2 / r
So, to simulate the motion of a planet around the sun, get its position, its velocity and the gravitational force acting upon it, calculate where you end up one time step later, calculate the new velocity and force acting on it, and repeat. (Do the same for all planets and ignore gravitational interactions between them for the moment.)
That would be an actual simulation of the solar system. If you only want to simulate the positions at any given time, look up Keplers laws - essentially a consequence of applying Newtons law.
I just saw that the article above even has a section on "Position as a function of time" - so that should help you with the algorithm.
I have got the following code to draw a filled circle in opengl. The problem is that it draws at the center of the screen. How do I make it draw in another position of it?
Here is the code:
#define CIRCLE_RADIUS = 0.15f
int circle_points = 100;
void draw()
{
glClear(GL_COLOR_BUFFER_BIT);
double angle = 2* PI/circle_points ;
glPolygonMode( GL_FRONT, GL_FILL );
glColor3f(0.2, 0.5, 0.5 );
glBegin(GL_POLYGON);
double angle1 = 0.0;
glVertex2d( CIRCLE_RADIUS * cos(0.0) , CIRCLE_RADIUS * sin(0.0));
int i;
for (i = 0; i < circle_points; i++)
{
glVertex2d(CIRCLE_RADIUS * cos(angle1), CIRCLE_RADIUS *sin(angle1));
angle1 += angle ;
}
glEnd();
glFlush();
}
The obvious way would be to call glTranslate first. Note, however, that you can already accomplish the same a bit more easily with a combination of glPointSize and glPoint:
glPointSize(CIRCLE_RADIUS/2.0f);
glPoint(center_x, center_y, center_z);
Before you start drawing the circles, you'll want something like:
glEnable(GL_POINT_SMOOTH);
glHint(GL_POINT_SMOOTH_HINT, GL_NICEST);
Otherwise, your "circles" could end up as squares.
Edit: Without knowing how you've set up your coordinates, it's impossible to know what the "top-left" position is, but you could do something like this:
void draw_circle(float x, float y, float radius) {
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glLoadIdentity();
glTranslatef(x, y, 0.0f);
static const int circle_points = 100;
static const float angle = 2.0f * 3.1416f / circle_points;
// this code (mostly) copied from question:
glBegin(GL_POLYGON);
double angle1=0.0;
glVertex2d(radius * cos(0.0) , radius * sin(0.0));
int i;
for (i=0; i<circle_points; i++)
{
glVertex2d(radius * cos(angle1), radius *sin(angle1));
angle1 += angle;
}
glEnd();
glPopMatrix();
}
You could then call (for example):
draw_circle(0.0f, 0.0f, 0.2f); // centered
draw_circle(1.0f, 0.0f, 0.2f); // right of center
draw_circle(1.0f, 1.0f, 0.2f); // right and up from center
Of course, the directions I've given assume haven't (for example) rotated your view, so x increases to the right and y increases upward.