For reference I'm using this guide.
I've gone over several guides including one that almost had the answer I was looking for.
I'm trying to draw an Icosahedron (an approximation on a sphere), as soon as I figure out why I'm not drawing I'll subdivide it so that I can progress from drawing with 20 triangles to 80 and then to 320 but currently I'm just trying to draw one with 20 sides.
I've gone through debugging and really can't see what's wrong with the program, all variables have the right values when they encounter a function.
Here's my program:
#define _USE_MATH_DEFINES
#define X .525731112119133606f
#define Z .850650808352039932f
#define N 0.0f
#include <glut.h>
#include <math.h>
#include <iostream>
using namespace std;
GLsizei winWidth = 1000, winHeight = 1000;
static GLfloat vdata[12][3] = {
{ -X,N,Z },{ X,N,Z },{ -X,N,-Z },{ X,N,-Z },
{ N,Z,X },{ N,Z,-X },{ N,-Z,X },{ N,-Z,-X },
{ Z,X,N },{ -Z,X, N },{ Z,-X,N },{ -Z,-X, N }
};
static GLuint tindices[20][3] = {
{ 0,4,1 },{ 0,9,4 },{ 9,5,4 },{ 4,5,8 },{ 4,8,1 },
{ 8,10,1 },{ 8,3,10 },{ 5,3,8 },{ 5,2,3 },{ 2,7,3 },
{ 7,10,3 },{ 7,6,10 },{ 7,11,6 },{ 11,0,6 },{ 0,1,6 },
{ 6,1,10 },{ 9,0,11 },{ 9,11,2 },{ 9,2,5 },{ 7,2,11 }
};
double randFrac() {
return (double)rand() / RAND_MAX;
}
void init(void){
glClearColor(1.0, 1.0, 1.0, 0.0); // White display window.
}
void drawTriangle(float* v1, float* v2, float* v3) {
glBegin(GL_TRIANGLES);
glNormal3fv(v1);
glVertex3fv(v1);
glNormal3fv(v2);
glVertex3fv(v2);
glNormal3fv(v3);
glVertex3fv(v3);
glEnd();
}
void normalize(float v[3]) {
GLfloat d = sqrt(v[0] * v[0] + v[1] * v[1] + v[1] * v[2]);
if (!d) {
cerr << "VECTOR HAS LENGTH OF ZERO";
return;
}
v[0] /= d;
v[1] /= d;
v[2] /= d;
}
void subdivide(float* v1, float* v2, float* v3, long depth) {
GLfloat v12[3],v23[3], v31[3];
if (!depth) {
drawTriangle(v1, v2, v3);
return;
}
for (GLint i = 0; i < 3; i++) {
v12[i] = (v1[i] + v2[i]) / 2.0;
v23[i] = (v2[i] + v3[i]) / 2.0;
v31[i] = (v1[i] + v3[i]) / 2.0;;
}
normalize(v12);
normalize(v23);
normalize(v31);
subdivide(v1, v12, v31, depth - 1);
subdivide(v2, v23, v12, depth - 1);
subdivide(v3, v31, v23, depth - 1);
subdivide(v12, v23, v31, depth - 1);
}
void drawIcosahedrons() {
glClear(GL_COLOR_BUFFER_BIT); // Clear display window.
glColor3f(0.0, 0.0, 1.0); // Set line color to blue.
/* Set viewing transformation. */
gluLookAt(5.0, 5.0, 5.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
for (int i = 0; i < 20; i++) {
glColor3f(randFrac(), randFrac(), randFrac()); // set sides to random color
drawTriangle(&vdata[tindices[i][0]][0], &vdata[tindices[i][1]][0], &vdata[tindices[i][2]][0]);
}
}
void winReshapeFcn(GLint newWidth, GLint newHeight) {
glViewport(0, 0, newWidth, newHeight);
glMatrixMode(GL_PROJECTION);
glFrustum(-1.0, 1.0, -1.0, 1.0, 2.0, 20.0);
glMatrixMode(GL_MODELVIEW);
glClear(GL_COLOR_BUFFER_BIT);
}
void main (int argc, char** argv){
glutInit(&argc, argv);
glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB);
glutInitWindowPosition (100, 100);
glutInitWindowSize (winWidth, winHeight);
glutCreateWindow ("title");
init();
glutDisplayFunc (drawIcosahedrons);
glutReshapeFunc (winReshapeFcn);
glutMainLoop();
}
My apologies everyone, I forgot to glFlush(); after I finished drawing.
Related
I am trying to draw some 3d ( a sun) and 2d (ground, cloud, ...) shapes in the same window, it actually worked! But the problem is when I when I run the program, it does not show smooth screen, it shows one shape then the other (while the first disappears), then the next shape and so on...
here is the code, than you.
#include<windows.h>
#include<stdio.h>
#include<GL/glut.h>
#include<stdlib.h>
#include<math.h>
#include<string.h>
#define CIRCLE_RADIUS 0.15f
# define PI 3.14159265358979323846
int eggs_caught = 0, missed_eggs = 0, level_count = 1, points = 0;
int egg_xc, egg_yc;
// for coordinates of egg
int basket_x, basket_y;
// for coordinates of basket
int a = 600, b = 650; // for default size of the screen
int s = 0;
// for menu option
int dropped_eggs = 0;
int speed_1 = 1, speed_2 = 1.5, speed_3 = 2, speed_4 = 2.5;
int w = 48, h = 48, t = 10, e = 9, g = 12;
void myinit();
void start_screen(int, int);
void cloud1();
void egg();
void basket(int, int);
void duck(int, int);
void print_score();
void egg_start();
void color();
void score();
void display(void);
void basket_set(int, int);
void myReshape(int, int);
void keys(unsigned char, int, int);
void menu(int);
void myinit()
{
}
void sun()
{
GLfloat black[] = { 0.0, 0.0, 0.0, 1.0 };
GLfloat yellow[] = { 1.0, 1.0, 0.0, 1.0 };
GLfloat direction[] = { 1.0, 1.0, 1.0, 0.0 };
glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, yellow);
glMaterialfv(GL_FRONT, GL_SPECULAR, yellow);
glMaterialf(GL_FRONT, GL_SHININESS, 30);
glLightfv(GL_LIGHT0, GL_AMBIENT, black);
glLightfv(GL_LIGHT0, GL_DIFFUSE, yellow);
glLightfv(GL_LIGHT0, GL_SPECULAR, yellow);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glEnable(GL_DEPTH_TEST);
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glPushMatrix();
glTranslatef(0, 0.0, 0);
glutSolidSphere(0.5, 30, 30);
glPopMatrix();
glPopMatrix();
glFlush();
glDisable(GL_LIGHTING);
glDisable(GL_LIGHT0);
glDisable(GL_DEPTH_TEST);
}
void cloud1()
{
float theta;
GLfloat angle;
glLineWidth(1.5);
glColor3f(1, 1, 1);
glBegin(GL_POLYGON);
for (int i = 0; i < 360; i++)
{
theta = i * PI * i / 180;
glVertex2f(100 + 50 * cos(theta) / 2, 590 + 50 * sin(theta) / 2);
}
glEnd();
glLineWidth(1.5);
glColor3f(1, 1, 1);
glBegin(GL_POLYGON);
for (int i = 0; i < 360; i++)
{
theta = i * PI * i / 180;
glVertex2f(130 + 50 * cos(theta) / 2, 580 + 50 * sin(theta) / 2);
}
glEnd();
glLineWidth(1.5);
glColor3f(1, 1, 1);
glBegin(GL_POLYGON);
for (int i = 0; i < 360; i++)
{
theta = i * PI * i / 180;
glVertex2f(140 + 50 * cos(theta) / 2, 600 + 50 * sin(theta) / 2);
}
glEnd();
glLineWidth(1.5);
glColor3f(1, 1, 1);
glBegin(GL_POLYGON);
for (int i = 0; i < 360; i++)
{
theta = i * PI * i / 180;
glVertex2f(170 + 50 * cos(theta) / 2, 590 + 50 * sin(theta) / 2);
}
glEnd();
glFlush();
}
void backk(int i, int j)
{
glColor3f(0, .5, 1);
glBegin(GL_QUADS);
glVertex2f(0.0 + i, 0.0 + j);
glVertex2f(600.0 + i, 0.0 + j);
glVertex2f(600.0 + i, -500 + j);
glVertex2f(0.0 + i, -500 + j);
glEnd();
glFlush();
}
void ground(int i, int j)
{
glBegin(GL_QUADS);
glColor3f(0, 1.0, 0);
glVertex2f(0.0 + i, 0.0 + j);
glVertex2f(600.0 + i, 0.0 + j);
glVertex2f(600.0 + i, -j);
glVertex2f(0.0 + i, -j);
glEnd();
}
void duck(int i, int j)
{
int h;
glColor3f(1.0, 1.0, 0.0);
glBegin(GL_POLYGON);
glVertex2f(45 + i, 45 + j);
glVertex2f(70 + i, 20 + j);
glVertex2f(95 + i, 20 + j);
glVertex2f(120 + i, 45 + j);
glVertex2f(95 + i, 70 + j);
glVertex2f(70 + i, 70 + j);
glVertex2f(95 + i, 95 + j);
glVertex2f(82.5 + i, 107.5 + j);
glVertex2f(32.5 + i, 57.5 + j);
glEnd();
glFlush();
for (h = 0; h < 13; h += 4)
{
glBegin(GL_LINES);
glColor3f(0.7, 0.4, 0);
glVertex2f(57.5 + h + i, 52.5 + h + j);
glVertex2f(100 + h + i, 30 + h + j);
glEnd();
glFlush();
}
glColor3f(0.0, 1.0, 0.0);
glBegin(GL_POLYGON);
glVertex2f(82.5 + i, 107.5 + j);
glVertex2f(65 + i, 107.5 + j);
glVertex2f(50 + i, 95 + j);
glVertex2f(70 + i, 95 + j);
glEnd();
glFlush();
glColor3f(0.0, 0.0, 0.0);
glPointSize(5);
glBegin(GL_POINTS);
glVertex2f(76 + i, 101 + j);
glEnd();
glColor3f(0.0, 1.0, 0.0);
glBegin(GL_LINE_LOOP);
glVertex2f(72.5 + i, 107.5 + j);
glVertex2f(67.5 + i, 112.5 + j);
glVertex2f(72.5 + i, 110 + j);
glVertex2f(77.5 + i, 112.5 + j);
glEnd();
glFlush();
}
void display(void)
{
GLfloat aspect = GLfloat(a) / GLfloat(b);
glOrtho(-2.5 * aspect, 2.5 * aspect, -2.5, 2.5, -10.0, 10.0);
glClear(GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(-2.5 * aspect, 2.5 * aspect, -2.5, 2.5, -10.0, 10.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
sun();
glClear(GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0, (GLdouble)a, 0.0, (GLdouble)b, 0, 1);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
cloud1();
ground(0, 650);
backk(0, 650);
duck(40, 375);
duck(180, 375);
duck(320, 375);
}
void myReshape(int w, int h)
{
}
void keys(unsigned char key, int x, int y)
{
}
int main(int argc, char** argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB | GLUT_DEPTH);
glutInitWindowSize(a, b);
glutCreateWindow("EGG GAME");
myinit();
glutInitWindowPosition(100, 100);
glutAttachMenu(GLUT_RIGHT_BUTTON);
glutDisplayFunc(display);
glutKeyboardFunc(keys);
glutIdleFunc(display);
glutReshapeFunc(myReshape);
glutMainLoop();
}
not using GLUT but this is What I see at first look.
glClear(GL_DEPTH_BUFFER_BIT);
why not clear also color? try glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
no glutSwapBuffers();
without this call at the end of display function your render is not updated when it needs to.
no glFlush/glFinish before swapping buffers
its safe to have them at the end. I see you got them in some of the rendering calls not all though.
using int operands for glVertex2f
Why not use glVertex2i instead when all of your coordinates are integers anyway. The int to float conversions slowing things down ...
Take a look at some simple GLUT example I just found:
cube.c
In there the Display look like this:
void display(void)
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
drawBox(); // here yoru rendering stuff instead
glFlush(); // I usually add this before swapping buffers
glutSwapBuffers();
}
so change your code accordingly...
On top of all this I would maybe try to use Blending for the clouds ...
My assignment is to perform transformations (reflections) on a 2D object.
Lets say my original object is a circle:
o
I want to reflect it across a line y = 5 for example.
o | o
Then I want to reflect the two objects across a line x = 5 for example.
o o
__
o o
Then finally I want to reflect the four objects across a line y = 10 for example.
o o | o o
o o | o o
So ultimately I want the end result to include 8 circles.
My question is, how would I go about implementing that into my code?
This is the code for my project:
#include <glut.h>
GLfloat square[4][3] = {{5, 0,0}, {5,20,0},{-5,20,0}, {-5,0,0}};
GLfloat square2[4][3] = { { 10, -5,0 },{ 10,25,0 },{ 0,25,0 },{ 0,-5,0 } };
GLfloat square3[4][3] = { { 0, -5,0 },{ 0,25,0 },{ -10,25,0 },{ -10,-5,0 } };
GLfloat colors[3][3] = {{0,0,1},{1,1,1},{0,0,0}};
void draw_square(void){
glBegin(GL_POLYGON);
for(int i = 0; i < 4; i++){
glVertex3fv(square[i]);
}
glEnd();
}
void draw_square2(void) {
glBegin(GL_POLYGON);
for (int i = 0; i < 4; i++) {
glVertex3fv(square2[i]);
}
glEnd();
}
void draw_square3(void) {
glBegin(GL_POLYGON);
for (int i = 0; i < 4; i++) {
glVertex3fv(square3[i]);
}
glEnd();
}
void draw_ring(void){
for(int r =0; r < 360;r+=45){
glPushMatrix();
glRotated(r, 0,0,1);
glTranslated(0,50,0);
draw_square();
glPopMatrix();
}
}
void draw_ring2(void) {
for (int r = 0; r < 360; r += 45) {
glPushMatrix();
glRotated(r, 0, 0, 1);
glTranslated(0, 50, 0);
draw_square2();
glPopMatrix();
}
}
void draw_ring3(void) {
for (int r = 0; r < 360; r += 45) {
glPushMatrix();
glRotated(r, 0, 0, 1);
glTranslated(0, 50, 0);
draw_square3();
glPopMatrix();
}
}
The display function below creates the set of overlapping rings that I want to reflect. The way it is now, I only get one set of overlapping rings at the bottom left corner. I want the output to be 8 sets of overlapping rings. Ive been trying to find a way to create the reflections I need, but i cant seem to figure it out.
void display(void){
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
glPushMatrix();
glColor3fv(colors[0]);
draw_ring();
glColor3fv(colors[1]);
draw_ring2();
glColor3fv(colors[2]);
draw_ring3();
glPopMatrix();
glFlush();
}
void main(int argc, char** argv){
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_SINGLE|GLUT_RGB|GLUT_DEPTH);
glutInitWindowSize(1000,600);
glutInitWindowPosition(200,100);
glutCreateWindow("Project 2");
glClearColor(1.0,1.0,0.0,1.0);
glEnable(GL_DEPTH_TEST);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(-100.0, 1000.0, -100.0,600.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glutDisplayFunc(display);
glutMainLoop();
}
Any help would be greatly appreciated.
Note, that drawing by glBegin/glEnd sequences and the fixed function pipeline matrix stack is deprecated since decades.
Read about Fixed Function Pipeline and see Vertex Specification and Shader for a state of the art way of rendering.
Anyway, if you want to tile the objects, then you can do this by nested loops:
void draw_object( void )
{
glPushMatrix();
glColor3fv(colors[0]);
draw_ring();
glColor3fv(colors[1]);
draw_ring2();
glColor3fv(colors[2]);
draw_ring3();
glPopMatrix();
}
void display(void)
{
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
int tile_x = 4;
int tile_y = 2;
float tile_dist = 200.0f;
for ( int x = 0; x < tile_x; ++ x )
{
for (int y = 0; y < tile_y; ++ y )
{
glPushMatrix();
glTranslatef( (float)x * tile_dist, (float)y * tile_dist, 0.0f );
draw_object();
glPopMatrix();
}
}
glFlush();
}
The same tile effect can be achieved by a recursive function:
void display_tiles_recursive( int level, float dist )
{
if ( level == 0 )
{
draw_object();
return;
}
int tile = level / 2;
bool tile_x = level % 2 != 0;
float offset_x = tile_x ? pow(2.0f, (float)tile) * dist : 0.0f;
float offset_y = tile_x ? 0.0f : pow(2.0f, (float)(tile-1)) * dist;
glPushMatrix();
display_tiles_recursive( level - 1, dist );
glTranslatef( offset_x, offset_y, 0.0f );
display_tiles_recursive( level - 1, dist );
glPopMatrix();
}
void display_mirror(void)
{
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
display_tiles_recursive( 3, 200.0f );
glFlush();
}
If you want to achieve a repeated mirror effect, then have to mirror the even tiles along the x and y axis. The mirroring can be achieved by glScale. glScalef( -1.0f, 1.0f, 1.0f ); to mirror along the x-axis and glScalef( 1.0f, -1.0f, 1.0f ); to mirror along the y axis. You can extend the recursive tiling function to get this effect:
void display_mirror_recursive( int level, float dist, bool even_x, bool even_y )
{
if ( level == 0 )
{
glPushMatrix();
if ( even_x )
glScalef( -1.0f, 1.0f, 1.0f );
if ( even_y )
glScalef( 1.0f, -1.0f, 1.0f );
draw_object();
glPopMatrix();
return;
}
int tile = level / 2;
bool tile_x = level % 2 != 0;
float offset_x = tile_x ? pow(2.0f, (float)tile) * dist : 0.0f;
float offset_y = tile_x ? 0.0f : pow(2.0f, (float)(tile-1)) * dist;
glPushMatrix();
display_mirror_recursive( level - 1, dist, even_x, even_y );
glTranslatef( offset_x, offset_y, 0.0f );
if ( level == 1 )
even_y = !even_y;
if ( level == 2)
even_x = !even_x;
display_mirror_recursive( level - 1, dist, even_x, even_y );
glPopMatrix();
}
void display(void)
{
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
display_mirror_recursive( 3, 200.0f, false, false );
glFlush();
}
I am trying to generate the Sierpinski Gasket using a function that draws dot patterns and will generate the gasket.
But when I compile and run the program it displays nothing but black screen. What's causing the problem?
Here is my code:
#include <Windows.h>
#include <gl/GL.h>
#include <glut.h>
void myInit(void) {
glClearColor(1.0, 1.0, 1.0, 0.0);
glColor3f(0.0f, 0.0f, 0.0f);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(0.0, 640.0, 0.0, 480.0);
}
class GLintPoint {
public:
GLint x, y;
};
int random(int m) {
return rand() % m;
}
void drawDot(GLint x, GLint y)
{
glBegin(GL_POINTS);
glVertex2i(x, y);
glEnd();
}
void Sierpinski(void) {
GLintPoint T[3] = {{ 10, 10 }, {300, 30}, {200, 300}};
int index = random(3);
GLintPoint point = T[index];
for (int i = 0; i < 1000; i++)
{
index = random(3);
point.x = (point.x + T[index].x) / 2;
point.y = (point.y + T[index].y) / 2;
drawDot(point.x, point.y);
}
glFlush();
}
void main(int argc, char** argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
glutInitWindowSize(640, 480);
glutInitWindowPosition(100, 150);
glutCreateWindow("Sierpinski Gasket");
glutDisplayFunc(drawDot);
myInit();
glutMainLoop();
}
If you want to draw black dots on a white background, then you have to clear glClear the background:
glClear( GL_COLOR_BUFFER_BIT );
Note, glClearColor sets the color which is used to clear the view port, but doesn't clear anything itself.
Your code should look somehow like this:
void drawDot(GLint x, GLint y)
{
glVertex2i(x, y);
}
void Sierpinski(void) {
GLintPoint T[3] = {{ 10, 10 }, {300, 30}, {200, 300}};
int index = random(3);
GLintPoint point = T[index];
glClearColor(1.0, 1.0, 1.0, 1.0); // set up white clear color
glClear( GL_COLOR_BUFFER_BIT ); // clear the back ground (white)
glMatrixMode( GL_MODELVIEW );
glPushMatrix(); // setup model matrix
glScalef( 1.5f, 1.5f, 1.0f ); // scale the point distribution
glColor3f( 0.0f, 0.0f, 0.0f ); // set black draw color
glPointSize( 5.0f ); // set the size of the points
glBegin(GL_POINTS);
for (int i = 0; i < 1000; i++)
{
index = random(3);
point.x = (point.x + T[index].x) / 2;
point.y = (point.y + T[index].y) / 2;
drawDot(point.x, point.y);
}
glEnd();
glPopMatrix(); // reset model matrix
glFlush();
}
I am taking a computer graphics class that teaches us how to use OpenGL with the glut libraries. I have an idea for a final project that involves lighting and textures being put on a dinosaur model that I found online. My first step is to simplify the existing online code so I can begin working on my project.
Unfortunately, the online code for this model is broken, and I cannot seem to figure it out. I am not sure what gluTessCallback does, but my program is very upset with two lines of this code that is making it impossible to run this program on Visual Studio 2012.
Below is the code, and I have indicated which two lines are giving me the trouble.
typedef enum {
RESERVED, BODY_SIDE, BODY_EDGE, BODY_WHOLE, ARM_SIDE, ARM_EDGE, ARM_WHOLE,
LEG_SIDE, LEG_EDGE, LEG_WHOLE, EYE_SIDE, EYE_EDGE, EYE_WHOLE, DINOSAUR
} displayLists;
GLfloat angle = -150; /* in degrees */
GLboolean doubleBuffer = GL_TRUE, iconic = GL_FALSE, keepAspect = GL_FALSE;
int moving, begin;
int W = 300, H = 300;
GLdouble bodyWidth = 2.0;
int newModel = 1;
GLfloat body[][2] = { { 0, 3 },{ 1, 1 },{ 5, 1 },{ 8, 4 },{ 10, 4 },{ 11, 5 },
{ 11, 11.5 },{ 13, 12 },{ 13, 13 },{ 10, 13.5 },{ 13, 14 },{ 13, 15 },{ 11, 16 },
{ 8, 16 },{ 7, 15 },{ 7, 13 },{ 8, 12 },{ 7, 11 },{ 6, 6 },{ 4, 3 },{ 3, 2 },
{ 1, 2 } };
GLfloat arm[][2] = { { 8, 10 },{ 9, 9 },{ 10, 9 },{ 13, 8 },{ 14, 9 },{ 16, 9 },
{ 15, 9.5 },{ 16, 10 },{ 15, 10 },{ 15.5, 11 },{ 14.5, 10 },{ 14, 11 },{ 14, 10 },
{ 13, 9 },{ 11, 11 },{ 9, 11 } };
GLfloat leg[][2] = { { 8, 6 },{ 8, 4 },{ 9, 3 },{ 9, 2 },{ 8, 1 },{ 8, 0.5 },{ 9, 0 },
{ 12, 0 },{ 10, 1 },{ 10, 2 },{ 12, 4 },{ 11, 6 },{ 10, 7 },{ 9, 7 } };
GLfloat eye[][2] = { { 8.75, 15 },{ 9, 14.7 },{ 9.6, 14.7 },{ 10.1, 15 },
{ 9.6, 15.25 },{ 9, 15.25 } };
GLfloat lightZeroPosition[] = { 10.0, 4.0, 10.0, 1.0 };
GLfloat lightZeroColor[] = { 0.8, 1.0, 0.8, 1.0 }; /* green-tinted */
GLfloat lightOnePosition[] = { -1.0, -2.0, 1.0, 0.0 };
GLfloat lightOneColor[] = { 0.6, 0.3, 0.2, 1.0 }; /* red-tinted */
GLfloat skinColor[] = { 0.1, 1.0, 0.1, 1.0 }, eyeColor[] = { 1.0, 0.2, 0.2, 1.0 };
void
extrudeSolidFromPolygon(GLfloat data[][2], unsigned int dataSize,
GLdouble thickness, GLuint side, GLuint edge, GLuint whole)
{
static GLUtriangulatorObj *tobj = NULL;
GLdouble vertex[3], dx, dy, len;
int i;
int count = dataSize / (int)(2 * sizeof(GLfloat));
if (tobj == NULL) {
tobj = gluNewTess(); /* create and initialize a GLU
polygon tesselation object */
/////////////////////////////////////////////////////////////////////////////////////////
// THESE LINES WILL NOT COMPILE. Says that the glBegin and glVertex2fv are incompatable.
gluTessCallback(tobj, GLU_BEGIN, glBegin);
gluTessCallback(tobj, GLU_VERTEX, glVertex2fv); /* semi-tricky */
/////////////////////////////////////////////////////////////////////////////////////////
gluTessCallback(tobj, GLU_END, glEnd);
}
glNewList(side, GL_COMPILE);
glShadeModel(GL_SMOOTH); /* smooth minimizes seeing
tessellation */
gluBeginPolygon(tobj);
/////////////////////////////////////////////////////////////////////////////////////////
// ALSO A PROBLEM WITH THIS SECTION OF CODE?
for (i = 0; i < count; i++) {
vertex[0] = data[i][0];
vertex[1] = data[i][1];
vertex[2] = 0;
gluTessVertex(tobj, vertex, data[i]);
}
gluEndPolygon(tobj);
glEndList();
/////////////////////////////////////////////////////////////////////////////////////////
glNewList(edge, GL_COMPILE);
glShadeModel(GL_FLAT); /* flat shade keeps angular hands
from being "smoothed" */
glBegin(GL_QUAD_STRIP);
for (i = 0; i <= count; i++) {
/* mod function handles closing the edge */
glVertex3f(data[i % count][0], data[i % count][1], 0.0);
glVertex3f(data[i % count][0], data[i % count][1], thickness);
/* Calculate a unit normal by dividing by Euclidean
distance. We * could be lazy and use
glEnable(GL_NORMALIZE) so we could pass in * arbitrary
normals for a very slight performance hit. */
dx = data[(i + 1) % count][1] - data[i % count][1];
dy = data[i % count][0] - data[(i + 1) % count][0];
len = sqrt(dx * dx + dy * dy);
glNormal3f(dx / len, dy / len, 0.0);
}
glEnd();
glEndList();
glNewList(whole, GL_COMPILE);
glFrontFace(GL_CW);
glCallList(edge);
glNormal3f(0.0, 0.0, -1.0); /* constant normal for side */
glCallList(side);
glPushMatrix();
glTranslatef(0.0, 0.0, thickness);
glFrontFace(GL_CCW);
glNormal3f(0.0, 0.0, 1.0); /* opposite normal for other side */
glCallList(side);
glPopMatrix();
glEndList();
}
void
makeDinosaur(void)
{
GLfloat bodyWidth = 3.0;
extrudeSolidFromPolygon(body, sizeof(body), bodyWidth,
BODY_SIDE, BODY_EDGE, BODY_WHOLE);
extrudeSolidFromPolygon(arm, sizeof(arm), bodyWidth / 4,
ARM_SIDE, ARM_EDGE, ARM_WHOLE);
extrudeSolidFromPolygon(leg, sizeof(leg), bodyWidth / 2,
LEG_SIDE, LEG_EDGE, LEG_WHOLE);
extrudeSolidFromPolygon(eye, sizeof(eye), bodyWidth + 0.2,
EYE_SIDE, EYE_EDGE, EYE_WHOLE);
glNewList(DINOSAUR, GL_COMPILE);
glMaterialfv(GL_FRONT, GL_DIFFUSE, skinColor);
glCallList(BODY_WHOLE);
glPushMatrix();
glTranslatef(0.0, 0.0, bodyWidth);
glCallList(ARM_WHOLE);
glCallList(LEG_WHOLE);
glTranslatef(0.0, 0.0, -bodyWidth - bodyWidth / 4);
glCallList(ARM_WHOLE);
glTranslatef(0.0, 0.0, -bodyWidth / 4);
glCallList(LEG_WHOLE);
glTranslatef(0.0, 0.0, bodyWidth / 2 - 0.1);
glMaterialfv(GL_FRONT, GL_DIFFUSE, eyeColor);
glCallList(EYE_WHOLE);
glPopMatrix();
glEndList();
}
void
recalcModelView(void)
{
glPopMatrix();
glPushMatrix();
glRotatef(angle, 0.0, 1.0, 0.0);
glTranslatef(-8, -8, -bodyWidth / 2);
newModel = 0;
}
void
redraw(void)
{
if (newModel)
recalcModelView();
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glCallList(DINOSAUR);
glutSwapBuffers();
}
/* ARGSUSED2 */
void
mouse(int button, int state, int x, int y)
{
if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN) {
moving = 1;
begin = x;
}
if (button == GLUT_LEFT_BUTTON && state == GLUT_UP) {
moving = 0;
}
}
/* ARGSUSED1 */
void
motion(int x, int y)
{
if (moving) {
angle = angle + (x - begin);
begin = x;
newModel = 1;
glutPostRedisplay();
}
}
GLboolean lightZeroSwitch = GL_TRUE, lightOneSwitch = GL_TRUE;
void
controlLights(int value)
{
switch (value) {
case 1:
lightZeroSwitch = !lightZeroSwitch;
if (lightZeroSwitch) {
glEnable(GL_LIGHT0);
}
else {
glDisable(GL_LIGHT0);
}
break;
case 2:
lightOneSwitch = !lightOneSwitch;
if (lightOneSwitch) {
glEnable(GL_LIGHT1);
}
else {
glDisable(GL_LIGHT1);
}
break;
}
glutPostRedisplay();
}
int
main(int argc, char **argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);
glutCreateWindow("glutdino");
glutDisplayFunc(redraw);
glutMouseFunc(mouse);
glutMotionFunc(motion);
glutCreateMenu(controlLights);
glutAddMenuEntry("Toggle right light", 1);
glutAddMenuEntry("Toggle left light", 2);
glutAttachMenu(GLUT_RIGHT_BUTTON);
makeDinosaur();
glEnable(GL_CULL_FACE);
glEnable(GL_DEPTH_TEST);
glEnable(GL_LIGHTING);
glMatrixMode(GL_PROJECTION);
gluPerspective( /* field of view in degree */ 40.0,
/* aspect ratio */ 1.0,
/* Z near */ 1.0, /* Z far */ 40.0);
glMatrixMode(GL_MODELVIEW);
gluLookAt(0.0, 0.0, 30.0, /* eye is at (0,0,30) */
0.0, 0.0, 0.0, /* center is at (0,0,0) */
0.0, 1.0, 0.); /* up is in postivie Y direction */
glPushMatrix(); /* dummy push so we can pop on model
recalc */
glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, 1);
glLightfv(GL_LIGHT0, GL_POSITION, lightZeroPosition);
glLightfv(GL_LIGHT0, GL_DIFFUSE, lightZeroColor);
glLightf(GL_LIGHT0, GL_CONSTANT_ATTENUATION, 0.1);
glLightf(GL_LIGHT0, GL_LINEAR_ATTENUATION, 0.05);
glLightfv(GL_LIGHT1, GL_POSITION, lightOnePosition);
glLightfv(GL_LIGHT1, GL_DIFFUSE, lightOneColor);
glEnable(GL_LIGHT0);
glEnable(GL_LIGHT1);
glutMainLoop();
return 0; /* ANSI C requires main to return int. */
}
I tried to make it clear where the problem is. OpenGl is bringing me to my wit's end. Is there nowhere I can get a simple 3D dinosaur model to play with on the internet?
I hope you can provide me some insight on this gluTessCallback issue so I can get this working. All I want is a solid dinosaur model.
Looking at the man page, the signature of the callback passed to gluTessCallback() depends on the enum value passed as the second argument. This means that if you're using C++, or a version of C that uses function prototypes, you will need a typecast to cast your function to the type expected by gluTessCallback().
According to the man page, the argument type is defined as _GLUfuncptr. However, that type is not defined in the glu.h header I found. The type according to the spec and header is a function with no arguments and a return type of GLvoid. You can define your own function type for this, and then cast to it:
typedef GLvoid (*TessFuncPtr)();
gluTessCallback(tobj, GLU_BEGIN, (TessFuncPtr)glBegin);
gluTessCallback(tobj, GLU_VERTEX, (TessFuncPtr)glVertex2fv);
If you're just learning OpenGL, you should be aware that almost all of the calls in this code are deprecated and obsolete. This includes:
Immediate mode rendering (glBegin, glEnd, etc).
Display lists.
Matrix stack.
Fixed function lighting and material definitions.
I think you would be much better off learning a current version of OpenGL. For example the tessellation functionality you are trying to use was defined close to 25 years ago. Aside from being deprecated, I don't think it was ever widely used in the first place.
I am trying to read the value from glEvalCoord, but not getting the exact values which I should get. My code is
GLfloat ctrlpoints[4][3] = {
{ -4.0, -4.0, 0.0}, { -2.0, 4.0, 0.0},
{ 2.0, -4.0, 0.0}, { 4.0, 4.0, 0.0}};
void display()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
glEnable(GL_LIGHTING);
glMap1f(GL_MAP1_VERTEX_3, 0.0, 1.0, 3, 4, &ctrlpoints[0][0]);
glEnable(GL_MAP1_VERTEX_3);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
GLint size;
GLfloat feedBuffer[1024];
glFeedbackBuffer (1024, GL_3D, feedBuffer);
glRenderMode (GL_FEEDBACK);
glBegin (GL_POINTS);
for (int i=0; i<=30; ++i)
{
GLfloat t = GLfloat(i)/30;
glEvalCoord1f(t);
}
glEnd();
size = glRenderMode (GL_RENDER);
cerr<<size<<endl;
}
Now, I am not sure but shouldn't it give me 30*3 values for each of the x, y and z coordinates of the curve?? But I am getting only 7*3 values. And the output of size is 28.
I think your size is 28 because your projection/modelview pair is clipping out some points.
"In feedback mode, each primitive that would be rasterized ... generates a block of values that's copied into the feedback array."
Try this:
#include <GL/glut.h>
#include <iostream>
using namespace std;
void display()
{
glClear( GL_COLOR_BUFFER_BIT );
glMatrixMode( GL_PROJECTION );
glLoadIdentity();
double w = glutGet( GLUT_WINDOW_WIDTH );
double h = glutGet( GLUT_WINDOW_HEIGHT );
double ar = w / h;
glOrtho( -5 * ar, 5 * ar, -5, 5, -1, 1 );
glMatrixMode( GL_MODELVIEW );
glLoadIdentity();
GLfloat ctrlpoints[4][3] =
{
{ -4.0, -4.0, 0.0 }, { -2.0, 4.0, 0.0 },
{ 2.0, -4.0, 0.0 }, { 4.0, 4.0, 0.0 }
};
glMap1f(GL_MAP1_VERTEX_3, 0.0, 1.0, 3, 4, &ctrlpoints[0][0]);
glEnable(GL_MAP1_VERTEX_3);
GLfloat feedBuffer[1024];
glFeedbackBuffer (1024, GL_3D, feedBuffer);
glRenderMode (GL_FEEDBACK);
glPointSize( 5 );
glColor3ub( 255, 255, 255 );
glBegin (GL_POINTS);
for (int i=0; i<=30; ++i)
{
GLfloat t = GLfloat(i)/30;
glEvalCoord1f(t);
}
glEnd();
GLint size = glRenderMode (GL_RENDER);
cerr << size << endl;
glutSwapBuffers();
}
int main( int argc, char **argv )
{
glutInit( &argc, argv );
glutInitDisplayMode( GLUT_RGBA | GLUT_DOUBLE );
glutInitWindowSize( 640, 480 );
glutCreateWindow( "GLUT" );
glutDisplayFunc( display );
glutMainLoop();
return 0;
}
I added a slightly larger projection matrix.
With that I get a size of 124:
31 points * 3 floats per point = 93
31 points * 1 GL_POINT_TOKEN per point = 31
31 + 91 = 124