I am trying to implement a Sierpinsky pyramid, that is like a Sierpinsky triangle but in 3D.
I have this structure to contain all the data about a pyramid:
typedef struct
{
GLfloat xUp;
GLfloat yUp;
GLfloat zUp;
GLfloat base;
GLfloat height;
}pyramid;
Then I've written a function that calculates three sub-pyramids:
void findSubPyramids( pyramid pyr, pyramid subs[3])
{
for(int i=0; i<3; i++)
{
subs[i].height=pyr.height/2.0;
subs[i].base=pyr.base/2.0;
}
memcpy(subs,&pyr,3*sizeof(GLfloat));
subs[1].yUp= pyr.yUp-pyr.height/2.0;
subs[1].xUp= pyr.xUp+pyr.base/4.0;
subs[1].zUp= pyr.zUp-pyr.base/4.0;
subs[2].yUp= subs[1].yUp;
subs[2].xUp= pyr.xUp-pyr.base/4.0;
subs[2].zUp= subs[1].zUp;
}
But this algorithm implementation is wrong: something is wrong with the zUp coordinate of the two sub-pyramids at bottom: indeed the pyramid is not drawn as I want:
But if I use glOrtho instead of gluPerspective the pyramid is drawn ok.I know that the gluPerspective and the functions I use are right, but is the algorithm to be wrong.
This is where I implement the algorithm that calculated all the sub-pyramids:
void drawSierpinskyPyramid (pyramid pyr)
{
assert(EQUAL(pyr.height, pyr.base));
if(pyr.base > 4.0)
{
setRandomColor();
pyramid subs[3];
drawPyramid(pyr);
findSubPyramids(pyr, subs);
for(int i=0; i<3; i++)
{
drawSierpinskyPyramid(subs[i]);
}
}
}
I don't get what's wrong.
Give this a shot:
// gcc -std=c99 main.c -lglut -lGL -lGLU
#include <GL/glut.h>
#include <math.h>
#include <stdlib.h>
typedef struct
{
float x, y, z;
} Vec3f;
void glTriangle( Vec3f* v0, Vec3f* v1, Vec3f* v2 )
{
glColor3ub( rand() % 255, rand() % 255, rand() % 255 );
glVertex3fv( (GLfloat*)v0 );
glVertex3fv( (GLfloat*)v1 );
glVertex3fv( (GLfloat*)v2 );
}
// v0, v1, v2 = base, v3 = top
void glTetrahedron( Vec3f* v0, Vec3f* v1, Vec3f* v2, Vec3f* v3 )
{
glTriangle( v0, v2, v1 );
glTriangle( v0, v1, v3 );
glTriangle( v1, v2, v3 );
glTriangle( v2, v0, v3 );
}
Vec3f Lerp( Vec3f* v0, Vec3f* v1, float u )
{
Vec3f ret = {
v0->x + ( v1->x - v0->x ) * u,
v0->y + ( v1->y - v0->y ) * u,
v0->z + ( v1->z - v0->z ) * u,
};
return ret;
}
void glSierpinskiPyramid( Vec3f* v0, Vec3f* v1, Vec3f* v2, Vec3f* v3, unsigned int level )
{
if( level == 0 )
{
glTetrahedron( v0, v1, v2, v3 );
return;
}
// midpoints
Vec3f m01 = Lerp( v0, v1, 0.5 );
Vec3f m12 = Lerp( v1, v2, 0.5 );
Vec3f m02 = Lerp( v0, v2, 0.5 );
Vec3f m03 = Lerp( v0, v3, 0.5 );
Vec3f m13 = Lerp( v1, v3, 0.5 );
Vec3f m23 = Lerp( v2, v3, 0.5 );
glSierpinskiPyramid( v0, &m01, &m02, &m03, level-1 );
glSierpinskiPyramid( &m01, v1, &m12, &m13, level-1 );
glSierpinskiPyramid( &m02, &m12, v2, &m23, level-1 );
glSierpinskiPyramid( &m03, &m13, &m23, v3, level-1 );
}
void display()
{
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
glMatrixMode( GL_PROJECTION );
glLoadIdentity();
double w = glutGet( GLUT_WINDOW_WIDTH );
double h = glutGet( GLUT_WINDOW_HEIGHT );
gluPerspective( 60, w / h, 0.1, 100 );
glMatrixMode( GL_MODELVIEW );
glLoadIdentity();
glTranslatef( 0, 0, -9 );
srand(0);
glPushMatrix();
glScalef( 3, 3, 3 );
static float angle = 0;
angle += 1;
glRotatef( angle/3, 0.2, 1, 0 );
Vec3f v0 = { -1, -1 / sqrtf(3), -1 / sqrtf(6) };
Vec3f v1 = { 1, -1 / sqrtf(3), -1 / sqrtf(6) };
Vec3f v2 = { 0, 2 / sqrtf(3), -1 / sqrtf(6) };
Vec3f v3 = { 0, 0, 3 / sqrtf(6) };
glBegin( GL_TRIANGLES );
glSierpinskiPyramid( &v0, &v1, &v2, &v3, 3 );
glEnd();
glPopMatrix();
glutSwapBuffers();
}
void timer(int extra)
{
glutPostRedisplay();
glutTimerFunc(16, timer, 0);
}
int main( int argc, char **argv )
{
glutInit( &argc, argv );
glutInitDisplayMode( GLUT_RGBA | GLUT_DEPTH | GLUT_DOUBLE );
glutInitWindowSize( 640, 480 );
glutCreateWindow( "Sierpinski Pyramid" );
glutDisplayFunc( display );
glutTimerFunc(0, timer, 0);
glEnable( GL_DEPTH_TEST );
glEnable( GL_CULL_FACE );
glutMainLoop();
return 0;
}
Related
I created this code to draw an object and move it in the direction of x,y or z according to keyboard buttons.
It works perfect and doesn't output any error but the object just appears without moving.
Here is the code:
#include <GL/glut.h>
static GLint rotate = 0;
static GLint axis = 0;
static int xDegrees = 0;
static int yDegrees = 0;
static int zDegrees = 0;
static int direction = 0;
static int stop = 0;
void specialKeyboard( int axis, int x, int y )
{
switch( axis )
{
case GLUT_KEY_RIGHT:
direction = 1;
break;
case GLUT_KEY_LEFT:
direction = -1;
break;
}
}
void change( int* degrees )
{
*degrees = ( ( *degrees ) + direction ) % 360;
}
void rotate1()
{
switch( axis )
{
case '0':
change( &xDegrees );
break;
case '1':
change( &yDegrees );
break;
case '2':
change( &zDegrees );
break;
}
glutPostRedisplay();
}
void keyboard( unsigned char key, int x, int y )
{
switch( key )
{
case 'x':
axis = 0;
glutIdleFunc( rotate1 );
stop = 0;
break;
case 'y':
axis = 1;
glutIdleFunc( rotate1 );
stop = 0;
break;
case 'z':
axis = 2;
glutIdleFunc( rotate1 );
stop = 0;
break;
case 's':
stop = !stop;
if( stop )
glutIdleFunc( NULL );
else
glutIdleFunc( rotate1 );
break;
}
}
void resize( int w, int h )
{
glViewport( 0, 0, w, h );
glMatrixMode( GL_PROJECTION );
glLoadIdentity();
gluPerspective( 50., w / (double)h, 1., 10. );
glMatrixMode( GL_MODELVIEW );
}
void render()
{
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
glLoadIdentity();
gluLookAt( 0.0, 0.0, 5.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0 );
// Rotate the teapot
glRotatef( xDegrees, 1, 0, 0 );
glRotatef( yDegrees, 0, 1, 0 );
glRotatef( zDegrees, 0, 0, 1 );
glColor3f( 1.0, 1.0, 1.0 );
glutWireTeapot( 1.5 );
glutSwapBuffers();
}
int main( int argc, char* argv[] )
{
glutInit( &argc, argv );
glutInitDisplayMode( GLUT_RGB | GLUT_DOUBLE );
glutInitWindowSize( 640, 480 );
glutCreateWindow( "IVI - Sesion 2" );
glEnable( GL_DEPTH_TEST );
glutDisplayFunc( render );
glutReshapeFunc( resize );
glutKeyboardFunc( keyboard );
glutSpecialFunc( specialKeyboard );
glutMainLoop();
return 0;
}
The problem is because of those
case '0':
...
case '1':
...
axis 0 and axis '0' (ASCII 48) are not the same, switch to
case 0:
...
case 1:
...
and it will work pressing x, y, z ...
I want to rotate a simple cube in OpenGL using GLUT in C. The rotation will occur when I press a key.
If I use glRotatef(angle, 0.0f, 1.0f, 0.0f) the cube will rotate instantly without an animation. I would like to rotate it slowly so it takes about 2 seconds to complete the rotation.
Create a keyboard callback that toggles a bool and a timer callback that updates an angle:
#include <GL/glut.h>
char spin = 0;
void keyboard( unsigned char key, int x, int y )
{
if( key == ' ' )
{
spin = !spin;
}
}
float angle = 0;
void timer( int value )
{
if( spin )
{
angle += 3;
}
glutTimerFunc( 16, timer, 0 );
glutPostRedisplay();
}
void display()
{
double w = glutGet( GLUT_WINDOW_WIDTH );
double h = glutGet( GLUT_WINDOW_HEIGHT );
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
glMatrixMode( GL_PROJECTION );
glLoadIdentity();
gluPerspective( 45, w / h, 0.1, 10 );
glMatrixMode( GL_MODELVIEW );
glLoadIdentity();
gluLookAt( 2, 2, 2, 0, 0, 0, 0, 0, 1 );
glColor3ub( 255, 0, 0 );
glRotatef( angle, 0, 0, 1 );
glutWireCube( 1 );
glutSwapBuffers();
}
int main( int argc, char **argv )
{
glutInit( &argc, argv );
glutInitDisplayMode( GLUT_RGBA | GLUT_DEPTH | GLUT_DOUBLE );
glutInitWindowSize( 640, 480 );
glutCreateWindow( "GLUT" );
glutDisplayFunc( display );
glutKeyboardFunc( keyboard );
glutTimerFunc( 0, timer, 0 );
glutMainLoop();
return 0;
}
The following code doesn't show the circle on the screen, why doesn't work?
I can't see any error.
void display(void){
glClear(GL_COLOR_BUFFER_BIT);
int circle_points=100;
int i;
double theta,cx=200, cy=300,r=100;
int MyCircle(){
glBegin(GL_LINE_LOOP);
glColor3f(1.0,1.0,1.0); //preto
for(i=0;i<circle_points;i++){
theta=(2*pi*i)/circle_points;
glVertex2f(cx+r*cos(theta),cy+r*sin(theta));
}
glEnd();
}
glFlush();
}
No idea why you are trying to declare a function inside a function. I'm not quite sure how that compiled, much less ran.
The logic is sound though:
#include <GL/glut.h>
#include <math.h>
void MyCircle( void )
{
const int circle_points=100;
const float cx=0, cy=0, r=100;
const float pi = 3.14159f;
int i = 0;
glBegin(GL_LINE_LOOP);
glColor3f(1.0,1.0,1.0); //preto
for(i=0;i<circle_points;i++)
{
const float theta=(2*pi*i)/circle_points;
glVertex2f(cx+r*cos(theta),cy+r*sin(theta));
}
glEnd();
}
void display( void )
{
const double w = glutGet( GLUT_WINDOW_WIDTH );
const double h = glutGet( GLUT_WINDOW_HEIGHT );
const double ar = w / h;
glClear( GL_COLOR_BUFFER_BIT );
glMatrixMode( GL_PROJECTION );
glLoadIdentity();
glOrtho( -150 * ar, 150 * ar, -150, 150, -1, 1 );
glMatrixMode( GL_MODELVIEW );
glLoadIdentity();
MyCircle();
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;
}
this is my draw() function written in C, using vertex arrays:
void draw(float x1, float x2, float y1, float y2)
{
glPushMatrix();
glScalef(1.0 / (x2 - x1), 1.0 / (y2 - y1), 1.0);
glTranslatef(-x1, -y1, 0.0);
glColor3f(1.0, 1.0, 1.0);
if( pts.size > 0 )
{
glEnableClientState( GL_VERTEX_ARRAY );
glVertexPointer( 2, GL_FLOAT, 0, (float*)pts.data );
glDrawArrays( GL_LINE_STRIP, 0, pts.size / 2 );
glDisableClientState( GL_VERTEX_ARRAY );
}
glPopMatrix();
};
before calling draw(), pts get's updated inside the update() function:
void update(double (* func)(double x), float x1, float x2, int N)
{
double x, dx = (double)1.0/(double)N;
vector_cleanup( &pts );
m = 0;
for(x = x1; x < x2; x += dx)
{
vector_resize( &pts, pts.size + 2 );
*(float*)vector_get( &pts, pts.size-2 ) = (float)x;
*(float*)vector_get( &pts, pts.size-1 ) = (float)func3(x);
m++;
}
}
I hope that by converting this code to use VBO, my graphics performance will increase.
EDIT: func3() can be anything, e.g. sin(x) or just some linear mapping. All I'm currently trying to do is, to find out how quickly I can plot a bunch of points.
Using GLEW for extension wrangling:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <GL/glew.h>
#include <GL/glut.h>
typedef struct vector /*dynamic vector of void* pointers. This one is used only by the deflate compressor*/
{
void* data;
size_t size; /*in groups of bytes depending on type*/
size_t allocsize; /*in bytes*/
unsigned typesize; /*sizeof the type you store in data*/
} vector;
static unsigned vector_resize(vector* p, size_t size) /*returns 1 if success, 0 if failure ==> nothing done*/
{
if(size * p->typesize > p->allocsize)
{
size_t newsize = size * p->typesize * 2;
void* data = realloc(p->data, newsize);
if(data)
{
p->allocsize = newsize;
p->data = data;
p->size = size;
}
else return 0;
}
else p->size = size;
return 1;
}
static void vector_cleanup(void* p)
{
((vector*)p)->size = ((vector*)p)->allocsize = 0;
free(((vector*)p)->data);
((vector*)p)->data = NULL;
}
static void vector_init(vector* p, unsigned typesize)
{
p->data = NULL;
p->size = p->allocsize = 0;
p->typesize = typesize;
}
static void* vector_get(vector* p, size_t index)
{
return &((char*)p->data)[index * p->typesize];
}
/* function to calculate each data point */
float func(float x)
{
return (float)sin(x);
}
GLuint vbo = 0;
GLsizei vertcount = 0;
void update(float (* func)(float x), float x1, float x2, int N)
{
float x, dx = 1.0f/N;
vector pts;
vector_init( &pts, sizeof( float ) );
for(x = x1; x < x2; x += dx)
{
vector_resize( &pts, pts.size + 2 );
*(float*)vector_get( &pts, pts.size-2 ) = x;
*(float*)vector_get( &pts, pts.size-1 ) = func(x);
}
vertcount = (GLsizei)( pts.size / 2 );
glBindBuffer( GL_ARRAY_BUFFER, vbo );
glBufferData( GL_ARRAY_BUFFER, pts.size * pts.typesize, pts.data, GL_DYNAMIC_DRAW );
glBindBuffer( GL_ARRAY_BUFFER, 0 );
vector_cleanup( &pts );
}
/* plotting function - very slow */
void draw(float x1, float x2, float y1, float y2)
{
glPushMatrix();
glScalef( 1.0f / (x2 - x1), 1.0f / (y2 - y1), 1.0f );
glTranslatef( -x1, -y1, 0.0f );
glColor3f( 1.0f, 1.0f, 1.0f );
glBindBuffer( GL_ARRAY_BUFFER, vbo );
glEnableClientState( GL_VERTEX_ARRAY );
glVertexPointer( 2, GL_FLOAT, 0, 0 );
glDrawArrays( GL_LINE_STRIP, 0, vertcount );
glDisableClientState( GL_VERTEX_ARRAY );
glBindBuffer( GL_ARRAY_BUFFER, 0 );
glPopMatrix();
};
/* Redrawing func */
float xmin = -10, xmax = 10, ymin = -5, ymax = 5;
void redraw(void)
{
glClearColor(0, 0, 0, 0);
glClear(GL_COLOR_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
// -x, +x, -y, +y, number points
draw(xmin, xmax, ymin, ymax);
glutSwapBuffers();
};
/* Idle proc. Redisplays, if called. */
int nPoints = 3000;
void idle(void)
{
// shift 'xmin' & 'xmax' by one.
xmin++;
xmax++;
update(func, xmin, xmax, nPoints);
glutPostRedisplay();
};
/* Key press processing */
void key(unsigned char c, int x, int y)
{
if(c == 27) exit(0);
};
/* Window reashape */
void reshape(int w, int h)
{
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0, 1, 0, 1, -1, 1);
glMatrixMode(GL_MODELVIEW);
};
/* Main function */
int main(int argc, char **argv)
{
GLenum err;
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE);
glutCreateWindow("Graph plotter");
glutReshapeWindow(1024, 800);
// init GLEW and output some GL info
err = glewInit();
printf("GL_VERSION : %s\n", glGetString(GL_VERSION) );
printf("GL_VENDOR : %s\n", glGetString(GL_VENDOR) );
printf("GL_RENDERER : %s\n", glGetString(GL_RENDERER) );
if( GLEW_OK != err )
{
printf("glewInit failed: %s", glewGetErrorString(err));
return EXIT_FAILURE;
}
if( !glewIsSupported("GL_VERSION_1_5") )
{
printf("OpenGL version 1.5 or greater required.\n");
return EXIT_FAILURE;
}
glGenBuffers( 1, &vbo );
/* Register GLUT callbacks. */
glutDisplayFunc(redraw);
glutKeyboardFunc(key);
glutReshapeFunc(reshape);
glutIdleFunc(idle);
/* Init the GL state */
glLineWidth(2.0);
/* Main loop */
glutMainLoop();
return 0;
}
I am trying to animate random point that i have created so they move across the screen and re-appear this is what i have done so far but does not work.the code is not the completed version of what i have i have only posted what i thought would be enough for this question could anyone help me animated the points
void TimerFunc(int value)
{
xpos[0]=xpos[0]+0.25;
glutPostRedisplay();
glutTimerFunc(25, TimerFunc, 1);
}
struct Point
{
float rship;
};
std::vector< Point > points;
void display(void)
{
glClear (GL_COLOR_BUFFER_BIT); /* clear window */
glColor3f(1.0, 1.0, 1.0); /* white drawing objects */
/* define object to be drawn as a square polygon */
//Draw points
glEnableClientState( GL_VERTEX_ARRAY );
glVertexPointer( 2, GL_FLOAT, sizeof(Point), &points[0].x );
glPointSize( 1 ); //1 pixel dot
glDrawArrays( GL_POINTS, 0, points.size() );
glDisableClientState( GL_VERTEX_ARRAY );
//glEnable( GL_POINT_SMOOTH );/*round smooth points*/
glFlush(); /* execute drawing commands in buffer */
}
int main(int argc, char** argv)
for( int i = 0; i <250; ++i )
{
Point pt;
pt.x = -100 + (rand() % 200);
pt.y = -100 + (rand() % 200);
points.push_back(pt);
xpos[i] = pt.x;
ypos[i] = pt.y;
}
Quick 'n dirty:
#include <GL/glut.h>
#include <vector>
#include <cstdlib>
struct Point
{
float x, y;
unsigned char r, g, b, a;
};
std::vector< Point > points;
void timer( int value )
{
// move all points left each frame
for( size_t i = 0; i < points.size(); ++i )
{
points[i].x -= 1;
// wrap point around if it's moved off
// the edge of our 100x100 area
if( points[i].x < -50 )
{
points[i].x = 100 + points[i].x;
}
}
glutPostRedisplay();
glutTimerFunc(30, timer, 1);
}
void display(void)
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(-50, 50, -50, 50, -1, 1);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
// draw
glColor3ub( 255, 255, 255 );
glEnableClientState( GL_VERTEX_ARRAY );
glEnableClientState( GL_COLOR_ARRAY );
glVertexPointer( 2, GL_FLOAT, sizeof(Point), &points[0].x );
glColorPointer( 4, GL_UNSIGNED_BYTE, sizeof(Point), &points[0].r );
glPointSize( 3.0 );
glDrawArrays( GL_POINTS, 0, points.size() );
glDisableClientState( GL_VERTEX_ARRAY );
glDisableClientState( GL_COLOR_ARRAY );
glFlush();
glutSwapBuffers();
}
void reshape(int w, int h)
{
glViewport(0, 0, w, h);
}
int main(int argc, char **argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGBA | GLUT_DEPTH | GLUT_DOUBLE);
glutInitWindowSize(640,480);
glutCreateWindow("Scrolling Points");
glutDisplayFunc(display);
glutReshapeFunc(reshape);
glutTimerFunc(30, timer, 1);
// populate points
for( size_t i = 0; i < 1000; ++i )
{
Point pt;
pt.x = -50 + (rand() % 100);
pt.y = -50 + (rand() % 100);
pt.r = rand() % 255;
pt.g = rand() % 255;
pt.b = rand() % 255;
pt.a = 255;
points.push_back(pt);
}
glutMainLoop();
return 0;
}