lighting the sun giving absurd results - opengl

I am trying to develop space simulator. I am trying to use sun as the light source. My problem is that the lighting dosent work as expected. Maybe i am using the wrong calculation for the normals. I am using a single "createsphere" function to create a sphere, and then use different coordinates and sizes to display them. The problem is that all the spheres on the screen show almost the same effect(i.e i've applied only one light source but it seems to have been implemented to all the spheres) .and also the light rotates along with them. I am not sure where the problem is ...i am posting my code ...
the code for sphere display
void DisplaySphere_sun (double R, GLuint texture)
{
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
int b,m = 0;
glScalef (0.0125 * R, 0.0125 * R, 0.0125 * R);
glBindTexture (GL_TEXTURE_2D, texture);
glBegin (GL_TRIANGLE_STRIP);
for ( b = 0; b <VertexCount; b++)
{
/*if((b%3)==0)
{
glNormal3f(normal[m].x,normal[m].y,normal[m].z);
m++;
}*/
glTexCoord2f (VERTEX[b].U, VERTEX[b].V);
/*glNormal3f(-VERTEX[b].X, -VERTEX[b].Y, -VERTEX[b].Z);*/
glVertex3f (VERTEX[b].Y, VERTEX[b].X, -VERTEX[b].Z);
}
m = 0;
for ( b = 0; b <VertexCount; b++)
{
/*if((b%3)==0)
{
glNormal3f(normal[m].x,normal[m].y,normal[m].z);
m++;
}*/
glTexCoord2f (VERTEX[b].U, -VERTEX[b].V);
/* glNormal3f(-VERTEX[b].X, -VERTEX[b].Y, -VERTEX[b].Z);*/
glVertex3f (VERTEX[b].Y, VERTEX[b].X, VERTEX[b].Z);
}
glEnd();
//glRotatef(120,0,0,0);
}
the code for creating a sphere
void CreateSphere (double R, double X, double Y, double Z) {
int n,m;
double a;
double b;
n = 0;
m = 0;
for( b = 0; b <= 90 - space; b+=space){
for( a = 0; a <= 360 - space; a+=space)
{
VERTEX[n].X = R * sin((a) / 180 * PI) * sin((b) / 180 * PI) - X;
VERTEX[n].Y = R * cos((a) / 180 * PI) * sin((b) / 180 * PI) + Y;
VERTEX[n].Z = R * cos((b) / 180 * PI) - Z;
VERTEX[n].V = (2 * b) / 360;
VERTEX[n].U = (a) / 360;
n++;
VERTEX[n].X = R * sin((a) / 180 * PI) * sin((b + space) / 180 * PI) - X;
VERTEX[n].Y = R * cos((a) / 180 * PI) * sin((b + space) / 180 * PI) + Y;
VERTEX[n].Z = R * cos((b + space) / 180 * PI) - Z;
VERTEX[n].V = (2 * (b + space)) / 360;
VERTEX[n].U = (a) / 360;
n++;
VERTEX[n].X = R * sin((a + space) / 180 * PI) * sin((b) / 180 * PI) - X;
VERTEX[n].Y = R * cos((a + space) / 180 * PI) * sin((b) / 180 * PI) + Y;
VERTEX[n].Z = R * cos((b) / 180 * PI) - Z;
VERTEX[n].V = (2 * b) / 360;
VERTEX[n].U = (a + space) / 360;
n++;
VERTEX[n].X = R * sin((a + space) / 180 * PI) * sin((b + space) /180 * PI) - X;
VERTEX[n].Y = R * cos((a + space) / 180 * PI) * sin((b + space) /180 * PI) + Y;
VERTEX[n].Z = R * cos((b + space) / 180 * PI) - Z;
VERTEX[n].V = (2 * (b + space)) / 360;
VERTEX[n].U = (a + space) / 360;
n++;
}
}
}
and code for lighting the sun
glPushMatrix();
gluLookAt (0.0, 10.0, 2.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0); //defines a viewing transformation.
// Now translate to the sun
glTranslatef(0.0, -7.0, 3.0);
/* For LIGHT0 */
GLfloat lightZeroPosition[] = {0.0f, 0.0f, 0.0f, 1.0f};
/*GLfloat lightvec[] = {0.5f, 0.2f, 0.0f, 1.0f};*/
GLfloat lightZeroColor[] = {0.5f, 0.5f, 0.5f, 1.0f};
GLfloat amb[] = {1, 1, 1, 1};
GLfloat spec[] = {0.3, 0.3, 0.3, 1};
glLightfv(GL_LIGHT0, GL_POSITION, lightZeroPosition);
glLightfv(GL_LIGHT0, GL_DIFFUSE, lightZeroColor);
glLightfv(GL_LIGHT0, GL_SPECULAR, spec);
glEnable(GL_LIGHT0);
glRotatef(angle,0,0,1);
DisplaySphere(5,textures);
// function to display the sun
glPopMatrix();

I'm a bit puzzled, why you don't draw the sun at the orign of the solar system? The sun is a star, and stars carry over 95% of their stellar systems mass, so the center of gravity of the whole thing is within the sun for most planets (only Jupiter has so much mass, that it shifts the center of gravity slightly outside the sun's photosphere radius).
As for your lighting problem, one normally doesn't illuminate light sources. Just switch off lighting when drawing the sun. Then when drawing the planets place the light source within the sun. OpenGL is not a global renderer, i.e. after you've drawn something, it completely forgets about it, i.e. you won't get any lighting interactions between the things you draw (means also, no shadows for free).
This is how I'd draw a solar system (pseudocode):
draw_solar_system():
glPushMatrix()
glDisable(GL_LIGHTING)
draw_origin_sphere(sun_radius)
glEnable(GL_LIGHTING)
glLightfv(GL_LIGHT0, GL_POSITION, (0., 0., 0., 1.))
glLightfv(GL_LIGHT0, GL_DIFFUSE, (1., 1., 1., 1.))
glLightfv(GL_LIGHT0, GL_AMBIENT, (0., 0., 0., 1.))
for p in planets:
glPushMatrix()
glRotatef(p.orbital_inclination, p.axis_of_orbital_inclination)
glRotatef(p.orbital_angle, 0., 1., 0.)
glTranslatef(p.orbit_radius, 1., 0. 0.)
glRotate(p.axial_of_inclination, p.axis_of_axis_inclination)
glRotate(p.time_of_day, 0., 1., 0.)
draw_origin_sphere(p.radius)
glPopMatrix()
glPopMatrix()

Related

Creating multiple Bezier curves using GL_MAP1_VERTEX_3 function in OpenGL

So I am trying to create an arbitrary curved shape using OpenGL and currently my code is only able to produce one curve between the specified control points, below is my OpenGL code:
#include <GL/glut.h>
#include <stdlib.h>
GLfloat controlPoints[18][3] =
{
{0.0, 8.0, 0.0},
{ -1.5, 3.0, 0.0}, //2
{-5.5, 4.0, 0.0},
{-5.5, 4.0, 0.0},
{-2.5, 0.0, 0.0}, //4
{-6.0, -4.0, 0.0},
{-6.0, -4.0, 0.0},
{-1.5, -3.0, 0.0}, //6
{0.0, -8.0, 0.0},
{0.0, -8.0, 0.0},
{1.0, -3.0, 0.0}, //8
{6.0, -5.0, 0.0},
{6.0, -5.0, 0.0},
{3.0, 0.0, 0.0}, //10
{6.5, 4.5, 0.0},
{6.5, 4.5, 0.0},
{1.5, 3.0, 0.0}, //12
{0.0, 8.0, 0.0}
};
void init(void)
{
glClearColor(0.0, 0.0, 0.0, 0.0);
glShadeModel(GL_FLAT);
for (int i = 0; (i + 3) < 3; i += 3)
{
glMap1f(GL_MAP1_VERTEX_3, 0.0, 1.0, 3, 4, &controlPoints[i][0]);
}
//glMap1f(GL_MAP1_VERTEX_3, 0.0, 1.0, 3, 4, &controlPoints2[0][0]);
glEnable(GL_MAP1_VERTEX_3);
// The evaluator with a stride of 3 and an order of 4
}
void display(void)
{
int i;
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glColor3f(1.0, 1.0, 1.0);
//draw(controlPoints);
//draw(controlPoints2);
glBegin(GL_LINE_STRIP);
{
for (int i = 0; i <= 18; i++)
{
glEvalCoord1f((GLfloat)i / 18.0);
}
}
glEnd();
glBegin(GL_LINE_STRIP);
{
for (i = 0; i < 18; i++)
{
glVertex3fv(&controlPoints[i][0]);
}
}
glEnd();
glPointSize(6.0);
glColor3f(0.0, 0.0, 1.0);
glBegin(GL_POINTS);
{
for (i = 0; i < 18; i++)
{
glVertex3fv(&controlPoints[i][0]);
}
}
glEnd();
void reshape(int w, int h)
{
glViewport(0, 0, (GLsizei)w, (GLsizei)h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
if (w <= h)
{
glOrtho(-10.0, 10.0, -10.0 * (GLfloat)h / (GLfloat)w, 10.0 * (GLfloat)h / (GLfloat)w, -10.0, 10.0);
}
else
{
glOrtho(-10.0 * (GLfloat)h / (GLfloat)w, 10.0 * (GLfloat)h / (GLfloat)w, -10.0, 10.0, -10.0, 10.0);
}
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
void keyboard(unsigned char key, int x, int y)
{
switch (key)
{
case 27:
exit(0);
break;
}
}
int main(int argc, char** argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
glutInitWindowSize(500, 500);
glutInitWindowPosition(100, 100);
glutCreateWindow(argv[0]);
init();
glutDisplayFunc(display);
glutReshapeFunc(reshape);
glutKeyboardFunc(keyboard);
glutMainLoop();
return 0;
}
How do I modify my init portion of the code such that able to produce 6 curves between the three control points totaling up to 18? and if not possible is there a way I can do it using GL_LINE_STRIP?
Below is what my current output looks like:
My advice - avoid openGL evaluators completely!
Aside from some SGI machines back in the 90's, no GPU vendor has ever added hardware support for them, so it falls back to a fairly inefficient software implementation.
Anyhow, there are a few problems in your code...
glMap1f(GL_MAP1_VERTEX_3, 0.0, 1.0, 3,
4, ///< this says you want 4 control points per curve
&controlPoints[i][0]);
However, there is something wrong here in the control points:
GLfloat controlPoints[18][3] =
{
{0.0, 8.0, 0.0},
{ -1.5, 3.0, 0.0}, //2
{-5.5, 4.0, 0.0}, ///< I'm assuming this is the last control point you want?
{-5.5, 4.0, 0.0}, ///< however this is duplicated here?
It looks as though you want a quadratic curve? (i.e. 3 control points per curve?)
// enable evaluators
glEnable(GL_MAP1_VERTEX_3);
// step through each triplet of CV's
for(int cv = 0; cv < 18; cv += 3) {
// specify the control point array
glMap1f(GL_MAP1_VERTEX_3, 0.0, 1.0,
3, ///< each vertex has 3 floats.
3, ///< I assume you want 3? (as in 3x CV per curve)
&controlPoints[cv][0]);
// render this curve segment
glBegin(GL_LINE_STRIP);
{
// choose how many divisions you want
int NUM_DIVISIONS = 32;
for (int i = 0; i <= NUM_DIVISIONS; i++)
{
glEvalCoord1f((GLfloat)i / (GLfloat) NUM_DIVISIONS);
}
}
glEnd();
}
glDisable(GL_MAP1_VERTEX_3);
However, as I said above, GL evaluators are terrible.
It's actually just a lot easier to simply write the code yourself.
One option would be to simply tessellate each curve, and then render (This would work with your current control point layout)
void render_quadratic_curves(
GLfloat controlPoints[][3],
int num_curves,
int num_divisions) {
int out_size_of_each_curve = (num_divisions + 1) * 3;
// allocate enough memory to store a curves
GLfloat* temp = new GLfloat[out_size_of_each_curve];
// re-render from the same vertex array.
glVertexPointer(3, GL_FLOAT, sizeof(float) * 3, temp);
glEnableClientState(GL_VERTEX_ARRAY);
for(int curve = 0; curve < num_curves; ++curve) {
// pointers to the control points for this curve
const GLfloat* P0 = controlPoints[3 * curve + 0];
const GLfloat* P1 = controlPoints[3 * curve + 1];
const GLfloat* P2 = controlPoints[3 * curve + 2];
for(int division = 0; division <= num_divisions; ++division) {
GLfloat t = (GLfloat) division / (GLfloat) NUM_DIVISIONS;
GLfloat inv_t = (1.0f - t);
// compute bezier coefficients for quadratic curve
GLfloat B0 = inv_t * inv_t;
GLfloat B1 = 2.0f * inv_t * t;
GLfloat B2 = t * t;
// compute XYZ coordinates
GLfloat x = P0[0] * B0 +
P1[0] * B1 +
P2[0] * B2;
GLfloat y = P0[1] * B0 +
P1[1] * B1 +
P2[1] * B2;
GLfloat z = P0[2] * B0 +
P1[2] * B1 +
P2[2] * B2;
// insert into the buffer for rendering
temp[3 * division + 0] = x;
temp[3 * division + 1] = y;
temp[3 * division + 2] = z;
}
// render this curve in one go as a strip
glDrawArrays(GL_LINE_STRIP, 0, num_divisions + 1);
}
// cleanup
glDisableClientState(GL_VERTEX_ARRAY);
delete [] temp;
}
However, in your case above you effectively have a loop, so this can be done in one go instead with GL_LINE_LOOP instead (This approach would nicely fit into a VBO)
void render_quadratic_curves_as_loop(
GLfloat controlPoints[][3],
int num_curves,
int num_divisions) {
// curves are 1 vertex smaller in size than previously,
// since the start vertex of one curve, is shared with the
// last vertex of the previous curve
int out_size_of_each_curve = num_divisions * 3;
// allocate enough memory to store all of the curves
GLfloat* temp = new GLfloat[out_size_of_each_curve * num_curves];
for(int curve = 0; curve < num_curves; ++curve) {
GLfloat* this_curve = temp + curve * out_size_of_each_curve;
// pointers to the control points for this curve
const GLfloat* P0 = controlPoints[3 * curve + 0];
const GLfloat* P1 = controlPoints[3 * curve + 1];
const GLfloat* P2 = controlPoints[3 * curve + 2];
// note! I am using less than here!
// the last vertex of each curve is simply the first
// vertex of the next one...
for(int division = 0; division < num_divisions; ++division) {
GLfloat t = (GLfloat) division / (GLfloat) NUM_DIVISIONS;
GLfloat inv_t = (1.0f - t);
// compute bezier coefficients for quadratic curve
GLfloat B0 = inv_t * inv_t;
GLfloat B1 = 2.0f * inv_t * t;
GLfloat B2 = t * t;
// compute XYZ coordinates
GLfloat x = P0[0] * B0 +
P1[0] * B1 +
P2[0] * B2;
GLfloat y = P0[1] * B0 +
P1[1] * B1 +
P2[1] * B2;
GLfloat z = P0[2] * B0 +
P1[2] * B1 +
P2[2] * B2;
// insert into the buffer for rendering
this_curve[3 * division + 0] = x;
this_curve[3 * division + 1] = y;
this_curve[3 * division + 2] = z;
}
}
// re-render from the same vertex array.
// This *could* be replaced with a VBO.
glVertexPointer(3, GL_FLOAT, sizeof(float) * 3, temp);
glEnableClientState(GL_VERTEX_ARRAY);
// render all of the curves in one go.
glDrawArrays(GL_LINE_LOOP, 0, out_size_of_each_curve * num_curves);
// cleanup
glDisableClientState(GL_VERTEX_ARRAY);
delete [] temp;
}
// You'll now need to remove the duplicate CV's from your array
GLfloat controlPoints[12][3] =
{
{0.0, 8.0, 0.0},
{ -1.5, 3.0, 0.0}, //2
{-5.5, 4.0, 0.0},
{-2.5, 0.0, 0.0}, //4
{-6.0, -4.0, 0.0},
{-1.5, -3.0, 0.0}, //6
{0.0, -8.0, 0.0},
{1.0, -3.0, 0.0}, //8
{6.0, -5.0, 0.0},
{3.0, 0.0, 0.0}, //10
{6.5, 4.5, 0.0},
{1.5, 3.0, 0.0}, //12
};
render_quadratic_curves_as_loop(controlPoints, 6, 32);
If you actually want 4 CV's per curve, then you can easily extend this into a cubic bezier.
// obviously each curve will now need an additional CV
void render_cubic_curves_as_loop(
GLfloat controlPoints[][3],
int num_curves,
int num_divisions) {
// curves are 1 vertex smaller in size than previously,
// since the start vertex of one curve, is shared with the
// last vertex of the previous curve
int out_size_of_each_curve = num_divisions * 3;
// allocate enough memory to store all of the curves
GLfloat* temp = new GLfloat[out_size_of_each_curve * num_curves];
for(int curve = 0; curve < num_curves; ++curve) {
GLfloat* this_curve = temp + curve * out_size_of_each_curve;
// pointers to the control points for this curve
const GLfloat* P0 = controlPoints[4 * curve + 0];
const GLfloat* P1 = controlPoints[4 * curve + 1];
const GLfloat* P2 = controlPoints[4 * curve + 2];
const GLfloat* P3 = controlPoints[4 * curve + 2];
// note! I am using less than here!
// the last vertex of each curve is simply the first
// vertex of the next one...
for(int division = 0; division < num_divisions; ++division) {
GLfloat t = (GLfloat) division / (GLfloat) NUM_DIVISIONS;
GLfloat inv_t = (1.0f - t);
// compute bezier coefficients for cubic curve
GLfloat B0 = inv_t * inv_t * inv_t;
GLfloat B1 = 3.0f * inv_t * inv_t * t;
GLfloat B2 = 3.0f * inv_t * t * t;
GLfloat B2 = t * t;
// compute XYZ coordinates
GLfloat x = P0[0] * B0 +
P1[0] * B1 +
P2[0] * B2 +
P3[0] * B3;
GLfloat y = P0[1] * B0 +
P1[1] * B1 +
P2[1] * B2 +
P3[1] * B3;
GLfloat z = P0[2] * B0 +
P1[2] * B1 +
P2[2] * B2 +
P3[2] * B3;
// insert into the buffer for rendering
this_curve[3 * division + 0] = x;
this_curve[3 * division + 1] = y;
this_curve[3 * division + 2] = z;
}
}
// re-render from the same vertex array.
// This *could* be replaced with a VBO.
glVertexPointer(3, GL_FLOAT, sizeof(float) * 3, temp);
glEnableClientState(GL_VERTEX_ARRAY);
// render all of the curves in one go.
glDrawArrays(GL_LINE_LOOP, 0, out_size_of_each_curve * num_curves);
// cleanup
glDisableClientState(GL_VERTEX_ARRAY);
delete [] temp;
}
NOTE: on modern hardware, if you have tessellation shaders available, that's usually the best option. Failing that, if you have hardware instancing, you can specify the basis coefficients as a shared vertex buffer, and the control points can be specified per instance.
generate a VBO to store the blending coefficients, and set the VBO to have a vertex divisor of 0.
void populate_shared_vertex_data_for_VBO(float* out, int NUM_DIVISIONS) {
for(int i = 0; i <= NUM_DIVISIONS; ++i) {
GLfloat t = (GLfloat) division / (GLfloat) (NUM_DIVISIONS + 1);
GLfloat inv_t = (1.0f - t);
// compute bezier coefficients for cubic curve
GLfloat B0 = inv_t * inv_t * inv_t;
GLfloat B1 = 3.0f * inv_t * inv_t * t;
GLfloat B2 = 3.0f * inv_t * t * t;
GLfloat B2 = t * t;
out[0] = B0;
out[1] = B1;
out[2] = B2;
out[3] = B3;
out += 4;
}
}
Load the control points for all curves into a single BIG VBO, set up the 4 per-instance attributes (i.e. specify 4 varying shader inputs, one for each CV, set each stride to sizeof(Cubic_Curve_CVS), and set the divisor to 1).
struct Cubic_Curve_CVS {
float P0[3];
float P1[3];
float P2[3];
float P3[3];
};
Cubic_Curve_CVS VBO_DATA[NUM_CURVES]; ///< load this
The vertex shader ends up being pretty simple to implement:
#version 450
uniform mat4 vs_mvp;
// share this buffer between all indices,
// i.e. glVertexAttribDivisor(0, 0);
layout(location = 0) in vec4 vs_coeffs;
// make these per-instance attributes
// i.e. :
// glVertexAttribDivisor(1, 1);
// glVertexAttribDivisor(2, 1);
// glVertexAttribDivisor(3, 1);
// glVertexAttribDivisor(4, 1);
layout(location = 1) in vec4 vs_CV0;
layout(location = 2) in vec4 vs_CV1;
layout(location = 3) in vec4 vs_CV2;
layout(location = 4) in vec4 vs_CV3;
void main()
{
float B0 = vs_coeffs.x;
float B1 = vs_coeffs.y;
float B2 = vs_coeffs.z;
float B3 = vs_coeffs.w;
vec4 V = vs_CV0 * B0 +
vs_CV1 * B1 +
vs_CV2 * B2 +
vs_CV3 * B3;
gl_Position = vs_mvp * V;
}
and then just render the whole lot in one go with glDrawArraysInstanced.

OpenGL independent rotation

I'm trying to draw these shaped bellow this this:
What I want
Tried this code:
glLoadIdentity();
glColor3f(0.98f, 0.83f, 0.73f);
glBegin(GL_POLYGON);
for (float i = 0; i <= (2 * p); i += 0.001) {
x = 100 * cos(i)-10;
y = 115 * sin(i)+270;
glVertex2f(x, y);
}
glEnd();
glRotatef(-135.0f, 0.0f, 0.0f, 1.0f);
glColor3f(1.0f, 0.83f, 0.0f);
glBegin(GL_POLYGON);
for (float i = p; i <= (2 * p); i += 0.001) {
x = 100 * cos(i) - 10;
y = 115 * sin(i) + 270;
glVertex2f(x, y);
}
But this is what I get:
What I get
If I want to only use the glLoadIdentity and glRotatef for rotation, do you have any idea about how to fix it?
Note:
I don't want to use push/pop or translation
You have to rotate the object around its center and move the rotated object to its position in the world. glRotatef rotates the vertices around (0, 0). Draw the object around (0, 0) and glTranslate to move the object to its position in the world:
glTranslate(-10.0f, 270.0f, 0.0f);
glRotatef(-135.0f, 0.0f, 0.0f, 1.0f);
glColor3f(1.0f, 0.83f, 0.0f);
glBegin(GL_POLYGON);
for (float i = p; i <= (2 * p); i += 0.001) {
x = 100 * cos(i);
y = 115 * sin(i);
glVertex2f(x, y);
}
Note, the matrix operations like glRotate and glTranslate specify a new matrix and multiply the current matrix by the new matrix.
If you are not allowed to use glTranslate, you have to rotate the translation vector (-10, 270) in the opposite direction. Use the trigonometric functions sin an cos to rotate the vector (see Rotation matrix). You need to invert the angle and convert it to Radians since the unit of sin and cos is Radian.
float tx = -10.0f;
float ty = 270.0f;
float angle = -135.0f;
float inv_angle_rad = -angle * M_PI / 180.0f;
float tx_rot = tx * cos(inv_angle_rad) - ty * sin(inv_angle_rad);
float ty_rot = tx * sin(inv_angle_rad) + ty * cos(inv_angle_rad);
glRotatef(angle, 0.0f, 0.0f, 1.0f);
glColor3f(1.0f, 0.83f, 0.0f);
glBegin(GL_POLYGON);
for (float i = p; i <= (2 * p); i += 0.001) {
x = 100 * cos(i) + tx_rot;
y = 115 * sin(i) + ty_rot;
glVertex2f(x, y);
}

Draw and Rotate an Arrow

I am trying to draw an arrow using the style below but this arrow should be also rotated according to a condition (need to pass the degree for each condition). I can draw the rectangle and a triangle but I cannot draw the triangle as an arrowhead. Also, how can I include the rotation degree into the code? Is there any easier way to draw an arrow and rotate it?
int triangleRect=4, triangleTri=3, lineWidth=3;
double twicePi = 2.0f * M_PI, angle_offsetR =1.5* M_PI/2, radius = 0.05,
xR=m_start.x(), y=m_start.y(), xT=m_start.x()+ m_rect_width;
glColor3f(0,1,0);
glLineWidth(lineWidth);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_MULTISAMPLE);
glEnable(GL_POINT_SMOOTH);
glEnable(GL_LINE_SMOOTH);
glBegin(GL_TRIANGLE_FAN);
//RECTANGLE
for(int i = 0; i <= triangleRect; i++) {
glVertex2f((xR + (radius * cos(i * twicePi / triangleRect + angle_offsetR)))* m_parent_width_function(),
(y + (radius * sin(i * twicePi / triangleRect + angle_offsetR)))* m_parent_height_function());
}
// TRIANGLE
for(int i = 0; i <= triangleTri; i++) {
glVertex2f((xT + (radius * cos(i * twicePi / triangleTri + angle_offsetR)))* m_parent_width_function(),
(y + (radius * sin(i * twicePi / triangleTri + angle_offsetR)))* m_parent_height_function());
}
glEnd();
You accidentally add angle_offsetR to the angle for the triangle vectors. Furthermore you've to restart a GL_TRIANGLE_FAN primitiv when you draw an new shape (see Triangle primitives).
If you want to rotate the model, then set the add a rotation around the z axis to the model view matrix by glRotatef.
Do not translate and scale the vertex coordinates. Use glScale and glTranslate. The matrix transformations are not commutative, the order matters:
float angle_of_roation = 30.0; // 30°
glPushMatrix();
// scale
glScalef( m_parent_width_function(), m_parent_height_function(), 1.0f);
// move triangle and rectangle to the position in the world
glTranslatef(xR, y, 0.0f);
// roatate triangle and rectangle
glRotatef(angle_of_roation, 0, 0, 1);
//RECTANGLE
glBegin(GL_TRIANGLE_FAN);
for(int i = 0; i <= triangleRect; i++) {
float angle = i * twicePi / triangleRect + angle_offsetR;
glVertex2f(radius * cos(angle), radius * sin(angle));
}
glEnd();
glPushMatrix();
// translate triangle relative to rectangle
glTranslatef(xT-xR, 0.0f, 0.0f);
// TRIANGLE
glBegin(GL_TRIANGLE_FAN);
for(int i = 0; i <= triangleTri; i++) {
float angle = i * twicePi / triangleTri;
glVertex2f(radius * cos(angle), radius * sin(angle));
}
glEnd();
glPopMatrix();
glPopMatrix();

How to do texture mapping for cylinder created by GL_TRIANGLE_STRIP in OpenGL and how to taper a cylinder

I am currently trying to create a model of squidward from spongebob squarepant's house.
I have created a cyllinder out of GL_TRIANGLE_STRIPs as I am not allowed to use any predefined OpenGL models to create the shapes.
I am trying to do texture mapping for each triangle on the cylinder but the texture comes out stretched and not as it is supposed to be.
Here is my code for the cylinder
glPushMatrix();
glTranslated(xPos, yPos, TABLETOP_Z - cubeLen);
glScaled(cubeLen / 2, cubeLen / 2, 1.0);
glBegin(GL_TRIANGLE_STRIP);
glTexCoord3f(xPos, yPos, TABLETOP_Z);
glTexCoord3f(xPos, yPos, TABLETOP_Z);
for (int i = 0; i <= 32; i++) {
double x_next = 1.0 * cos((i + 1) * 2.0 * PI/ (32 - 2.0));
double y_next = 1.0 * sin((i + 1) * 2.0 * PI / (32 - 2.0));
if (i % 2 == 0) {
glTexCoord3f(x_next, y_next, TABLETOP_Z + cubeLen);
glVertex3f(x_next, y_next, TABLETOP_Z + cubeLen);
} else {
glTexCoord3f(x_next, y_next, TABLETOP_Z);
glVertex3f(x_next, y_next, TABLETOP_Z);
}
}
glEnd();
glPopMatrix();
And here is what the texture is supposed to look like:
And here is what it looks like on the cylinder
The texture coordinates are 2-dimenional and have to be in range [0.0, 1.0]:
glBegin(GL_TRIANGLE_STRIP);
for (int i = 0; i <= 32; i++) {
double x_next = 1.0 * cos((i + 1) * 2.0 * PI/ (32 - 2.0));
double y_next = 1.0 * sin((i + 1) * 2.0 * PI / (32 - 2.0));
if (i % 2 == 0) {
glTexCoord3f((float)i / 32.0f, 1.0f);
glVertex3f(x_next, y_next, TABLETOP_Z + cubeLen);
} else {
glTexCoord3f((float)i / 32.0f, 0.0f);
glVertex3f(x_next, y_next, TABLETOP_Z);
}
}
glEnd();
See How do opengl texture coordinates work?

Separating Triangle Strips in Circular Annulus

Given the problem description:
More specifically, the problem involves specifically the decorated annulus. The problem I am having is to separate the lightly shaded triangle from the dark shaded triangles.
I have produced code (based on a previous example) that produces a circular annulus. However, the triangles are together rather than separate, and produce the same color.
Here is the code that I have produced so far:
///////////////////////////////////////////////////////////////////////////////////////////
// circularAnnuluses.cpp
//
// This program draws three identical-looking circular annuluses in three different ways -
// see comments below.
//
// Interaction:
// Press the space bar to toggle between wirefrime and filled for the lower annulus.
//
// Sumanta Guha.
///////////////////////////////////////////////////////////////////////////////////////////
#include <cstdlib>
#include <cmath>
#include <iostream>
#ifdef __APPLE__
# include <GL/glew.h>
# include <GL/freeglut.h>
# include <OpenGL/glext.h>
#else
# include <GL/glew.h>
# include <GL/freeglut.h>
//# include <GL/glext.h>
#pragma comment(lib, "glew32.lib")
#endif
#define PI 3.14159265
#define N 6.0 // Number of vertices on the boundary of the disc.
using namespace std;
// Globals.
static int isWire = 0; // Is wireframe?
// Drawing routine.
void drawScene(void)
{
float angle;
int i;
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Clear the buffers including
// the depth buffer.
glPolygonMode(GL_FRONT, GL_FILL);
// Lower circular annulus: with a true hole.
if (isWire) glPolygonMode(GL_FRONT, GL_LINE); else glPolygonMode(GL_FRONT, GL_FILL);
glBegin(GL_TRIANGLE_STRIP);
for (i = 0; i <= N; ++i)
{
angle = 2 * PI * i / N;
glColor3f(1.0, 0.0, 0.0);
glVertex3f(50 + cos(angle) * 10.0, 50 + sin(angle) * 10.0, 0.0);
glColor3f(0, 1, 0);
glVertex3f(50 + cos(angle) * 20.0, 50 + sin(angle) * 20.0, 0.0);
}
glEnd();
// Write labels.
glColor3f(0.0, 0.0, 0.0);
glFlush();
}
// Initialization routine.
void setup(void)
{
glClearColor(1.0, 1.0, 1.0, 0.0);
}
// OpenGL window reshape routine.
void resize(int w, int h)
{
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0.0, 100.0, 0.0, 100.0, -1.0, 1.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
// Keyboard input processing routine.
void keyInput(unsigned char key, int x, int y)
{
switch (key)
{
case ' ':
if (isWire == 0) isWire = 1;
else isWire = 0;
glutPostRedisplay();
break;
case 27:
exit(0);
break;
default:
break;
}
}
// Routine to output interaction instructions to the C++ window.
void printInteraction(void)
{
cout << "Interaction:" << endl;
cout << "Press the space bar to toggle between wirefrime and filled for the lower annulus." << endl;
}
// Main routine.
int main(int argc, char** argv)
{
printInteraction();
glutInit(&argc, argv);
glutInitContextVersion(4, 3);
glutInitContextProfile(GLUT_COMPATIBILITY_PROFILE);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGBA | GLUT_DEPTH);
glutInitWindowSize(500, 500);
glutInitWindowPosition(100, 100);
glutCreateWindow("DecoratedAnnulus.cpp");
glutDisplayFunc(drawScene);
glutReshapeFunc(resize);
glutKeyboardFunc(keyInput);
glewExperimental = GL_TRUE;
glewInit();
setup();
glutMainLoop();
}
The section of code where the problem lies is in the 'drawscene' function. I believe there should be two different for loops to separate the triangles from one another, but whenever I try to split the for loop it produces a monster of a shape.
I'm not exactly sure where to begin to complete this last problem.
As mentioned in the other answer, a possibility is to switch to flat shading mode by glShadeModel.
But note, you've also to offset the vertex coordinates of the outer circle:
glShadeModel( GL_FLAT );
glBegin(GL_TRIANGLE_STRIP);
for (i = 0; i <= N; ++i)
{
angle1 = 2 * PI * i / N;
angle2 = 2 * PI * (i+0.5) / N;
glColor3f(1.0, 0.0, 0.0);
glVertex3f(50 + cos(angle1) * 10.0, 50 + sin(angle1) * 10.0, 0.0);
glColor3f(0, 1, 0);
glVertex3f(50 + cos(angle2) * 20.0, 50 + sin(angle2) * 20.0, 0.0);
}
glEnd();
The other possibility is to draw the inner and outer triangles with the primitive type GL_TRIANGLES in 2 separate loops:
glShadeModel( GL_SMOOTH );
glBegin(GL_TRIANGLES);
glColor3f(1.0, 0.0, 0.0);
for (i = 0; i <= N; ++i)
{
angle1 = 2 * PI * i / N;
angle2 = 2 * PI * (i+0.5) / N;
angle3 = 2 * PI * (i+1) / N;
glVertex3f(50 + cos(angle1) * 10.0, 50 + sin(angle1) * 10.0, 0.0);
glVertex3f(50 + cos(angle2) * 20.0, 50 + sin(angle2) * 20.0, 0.0);
glVertex3f(50 + cos(angle3) * 10.0, 50 + sin(angle3) * 10.0, 0.0);
}
glEnd();
glBegin(GL_TRIANGLES);
glColor3f(0, 1, 0);
for (i = 0; i <= N; ++i)
{
angle1 = 2 * PI * (i-0.5) / N;
angle2 = 2 * PI * i / N;
angle3 = 2 * PI * (i+0.5) / N;
glVertex3f(50 + cos(angle1) * 20.0, 50 + sin(angle1) * 20.0, 0.0);
glVertex3f(50 + cos(angle2) * 10.0, 50 + sin(angle2) * 10.0, 0.0);
glVertex3f(50 + cos(angle3) * 20.0, 50 + sin(angle3) * 20.0, 0.0);
}
glEnd();
Both methods generate the following image:
If you want a more "circular" look, then you've to tessellate the segments along the inner or outer circle. Use the primitive type GL_TRIANGLE_FAN (see Triangle primitives) to draw a single segment:
int N2 = 10;
glShadeModel( GL_SMOOTH );
# draw the red segments
glColor3f(1.0, 0.0, 0.0);
for (int i = 0; i <= N; ++i)
{
float angle1 = 2 * PI * i / N;
float angle2 = 2 * PI * (i+0.5) / N;
float angle3 = 2 * PI * (i+1) / N;
# draw a single red segment
glBegin(GL_TRIANGLE_FAN);
glVertex3f(50 + cos(angle2) * 20.0, 50 + sin(angle2) * 20.0, 0.0);
for (int j = 0; j <= N2; ++j)
{
float a = angle1 + (angle3 - angle1) * (float)j / (float)N2;
glVertex3f(50 + cos(a) * 10.0, 50 + sin(a) * 10.0, 0.0);
}
glEnd();
}
# draw the green sgements
glColor3f(0, 1, 0);
for (int i = 0; i <= N; ++i)
{
float angle1 = 2 * PI * (i-0.5) / N;
float angle2 = 2 * PI * i / N;
float angle3 = 2 * PI * (i+0.5) / N;
# draw a single green segment
glBegin(GL_TRIANGLE_FAN);
glVertex3f(50 + cos(angle2) * 10.0, 50 + sin(angle2) * 10.0, 0.0);
for (int j = 0; j <= N2; ++j)
{
float a = angle1 + (angle3 - angle1) * (float)j / (float)N2;
glVertex3f(50 + cos(a) * 20.0, 50 + sin(a) * 20.0, 0.0);
}
glEnd();
}