è una figata.
ho scaricato un source "cube.c" che disegnava un cubo.
l'ho un pò modificato.
questo codice è un macello, però fa certe cose:
con le frecce di direzione muove i solidi.
con w a s d muove la luce.
con r e g cambia il colore della luce (verde e rossa)
con esc esce.
con il mouse (tenendo premuto e muovendo) si possono muovere i solidi.
così com'è si può compilare con il compilatore C microsoft di visual studio 2008.
bisogna solo aggiungere le librerie GLUT seguendo le istruzioni sull'apposito sito.
funziona anche su mac os 10.5.5 con gli ultimi developer tools.
il framework GLUT è già incluso.
bisogna dire al gcc di usare -framework GLUT e -framework GL se non ricordo male. il comando preciso l'ho sul macbook.
per compilarlo su mac os bisogna cambiare la GL in
#include <GL/glut.h>
#include <GL/gl.h>
#include <GL/glu.h>
con GLUT.
ah, exit(0) non piace al gcc... non ho provato a vedere cosa vuole, ho commentato la riga, era tardi ieri sera.
comunque funziona il programma.
mi pare migliore su mac os, su windos fa cose strane, ogni tanto scatta e mi ripresenta il frame vecchio o un frame vecchio a caso.
forse è colpa dei driver video, boh.
uso opengl come double buffer, un frame in memoria e uno a video che vengono switchati in continuazione per visualizzare l'animazione.
se volete contribuire fate pure!
c'è dentro anche la routine che muove con un timer i solidi, adesso è disattivata
//glutTimerFunc(0, timer, 0);
basta scommentarla
la inizializzo con 0 millisecondi, poi dopo la prima chiamata metto 500 se non ricordo male.
insomma, è proprio fico l'OpenGL.
qualcuno sa come si usa #ifdef, per rendere il source compilabile senza modifiche su windos, mac, linux e perché no anche stupix?
tipo #ifdef windows... #ifdef mac....
per via dei diversi percorsi per le librerie e quel probabile problema con exit.
Codice: Seleziona tutto
/* Copyright (c) Mark J. Kilgard, 1997. */
/* This program is freely distributable without licensing fees
and is provided without guarantee or warrantee expressed or
implied. This program is -not- in the public domain. */
/* This program was requested by Patrick Earl; hopefully someone else
will write the equivalent Direct3D immediate mode program. */
#include <stdio.h>
#include <math.h>
#include <GL/glut.h>
#include <GL/gl.h>
#include <GL/glu.h>
//float color[] = {r,g,b,a};
GLfloat light_diffuse[] = {1.0, 0.0, 0.0, 1.0}; /* Red diffuse light. */
//GLfloat light_position[] = {1.0, 1.0, 1.0, 0.0}; /* Infinite light location. */
GLfloat light_position[4] = {0,0,4,0};
GLfloat n[6][3] = { /* Normals for the 6 faces of a cube. */
{-1.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {1.0, 0.0, 0.0},
{0.0, -1.0, 0.0}, {0.0, 0.0, 1.0}, {0.0, 0.0, -1.0} };
GLint faces[6][4] = { /* Vertex indices for the 6 faces of a cube. */
{0, 1, 2, 3}, {3, 2, 6, 7}, {7, 6, 5, 4},
{4, 5, 1, 0}, {5, 6, 2, 1}, {7, 4, 0, 3} };
GLfloat v[8][3]; /* Will be filled in with X,Y,Z vertexes. */
GLfloat angle1 = 20; /* in degrees */
GLfloat angle2 = 30; /* in degrees */
int moving, startx, starty;
static float angle=0.0,ratio;
static float lx=0.0f,ly=0.0f,lz=-1.0f;
static float x=0.0f,y=0.0f,z=5.0f;
void timer(int param)
{
const angoloV = 0.5;
const angoloH = 1;
glRotatef(angoloV,0,1,0);
glRotatef(angoloH,1,0,0);
glutSwapBuffers();
glutPostRedisplay();
glutTimerFunc(50, timer, 0);
}
void
drawBox(void)
{
int i;
for (i = 0; i < 6; i++) {
glBegin(GL_QUADS);
glNormal3fv(&n[i][0]);
glVertex3fv(&v[faces[i][0]][0]);
glVertex3fv(&v[faces[i][1]][0]);
glVertex3fv(&v[faces[i][2]][0]);
glVertex3fv(&v[faces[i][3]][0]);
glEnd();
}
}
void
display(void)
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glTranslatef(1, 0.0, 0.0);
glutSolidSphere(0.5,100,100);
glTranslatef(-1, 0.0, 0.0);
glutSolidCube(1);
glMaterialf(GL_FRONT, GL_SHININESS, 100.0);
//drawBox();
glutSwapBuffers();
}
void
init(void)
{
/* Setup cube vertex data. */
//v[0][0] = v[1][0] = v[2][0] = v[3][0] = -1;
//v[4][0] = v[5][0] = v[6][0] = v[7][0] = 1;
//v[0][1] = v[1][1] = v[4][1] = v[5][1] = -1;
//v[2][1] = v[3][1] = v[6][1] = v[7][1] = 1;
//v[0][2] = v[3][2] = v[4][2] = v[7][2] = 1;
//v[1][2] = v[2][2] = v[5][2] = v[6][2] = -1;
/* Enable a single OpenGL light. */
glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse);
glLightfv(GL_LIGHT0, GL_POSITION, light_position);
glEnable(GL_LIGHT0);
glEnable(GL_LIGHTING);
/* Use depth buffering for hidden surface elimination. */
glEnable(GL_DEPTH_TEST);
/* Setup the view of the cube. */
glMatrixMode(GL_PROJECTION);
gluPerspective( /* field of view in degree */ 40.0,
/* aspect ratio */ 1.0,
/* Z near */ 1.0, /* Z far */ 10.0);
glMatrixMode(GL_MODELVIEW);
gluLookAt(0.0, 0.0, 5.0, /* eye is at (0,0,5) */
0.0, 0.0, 0.0, /* center is at (0,0,0) */
0.0, 1.0, 0.); /* up is in positive Y direction */
/* Adjust cube position to be asthetic angle. */
glTranslatef(0.0, 0.0, -1.0);
glRotatef(60, 1.0, 0.0, 0.0);
glRotatef(-20, 0.0, 0.0, 1.0);
}
void inputKey(int key, int x, int y) {
//angle = 0.5;
//glRotatef(angle,0,1,0);
//glRotatef(angle,1,0,0);
float angoloV = 0.0;
float angoloH = 0.0;
switch (key) {
case GLUT_KEY_LEFT :
//printf("%d\n", key);
//angle -= 0.01f;
//orientMe(angle);break;
angoloH -= 0.5;
glRotatef(angoloH,0,1,0);
break;
case GLUT_KEY_RIGHT :
//angle +=0.01f;
//orientMe(angle);break;
angoloH += 0.5;
glRotatef(angoloH,0,1,0);
break;
case GLUT_KEY_UP :
angoloV -= 0.5;
glRotatef(angoloV,1,0,0);
//moveMeFlat(1);break;
break;
case GLUT_KEY_DOWN :
//moveMeFlat(-1);break;
angoloV += 0.5;
glRotatef(angoloV,1,0,0);
break;
}
glutSwapBuffers();
glutPostRedisplay();
printf("angolo h:%f - angolo v:%f\n", angoloH, angoloV);
}
void orientMe(float ang) {
lx = sin(ang);
lz = -cos(ang);
glLoadIdentity();
gluLookAt(x, y, z,
x + lx,y + ly,z + lz,
0.0f,1.0f,0.0f);
}
void moveMeFlat(int direction) {
x = x + direction*(lx)*0.1;
z = z + direction*(lz)*0.1;
glLoadIdentity();
gluLookAt(x, y, z,
x + lx,y + ly,z + lz,
0.0f,1.0f,0.0f);
}
void changeSize(int w, int h)
{
// Prevent a divide by zero, when window is too short
// (you cant make a window of zero width).
if(h == 0)
h = 1;
ratio = 1.0f * w / h;
// Reset the coordinate system before modifying
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
// Set the viewport to be the entire window
glViewport(0, 0, w, h);
// Set the clipping volume
gluPerspective(40,ratio,1,10);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(x, y, z,
x + lx,y + ly,z + lz,
0.0f,1.0f,0.0f);
}
void processNormalKeys(unsigned char key, int x, int y) {
//printf("%c\n", key);
fflush:
switch (key) {
case 27:
exit(0);
printf("exit\n");
break;
case 'r':
light_diffuse[0] = 1;
light_diffuse[1] = 0;
light_diffuse[2] = 0;
light_diffuse[3] = 0;
printf("luce diffusa rossa\n");
break;
case 'g':
light_diffuse[0] = 0;
light_diffuse[1] = 1;
light_diffuse[2] = 0;
light_diffuse[3] = 0;
printf("luce diffusa verde\n");
break;
case '<':
glEnable(GL_LIGHT1);
printf("ambient light accesa\n");
break;
case '>':
glDisable(GL_LIGHT1);
printf("ambient light spenta\n");
break;
case 'w':
light_position[1] += 1.0;
printf("luce: x%f - y%f\n", light_diffuse[0], light_diffuse[1]);
break;
case 's':
light_position[1] -= 1.0;
printf("luce: x%f - y%f\n", light_diffuse[0], light_diffuse[1]);
break;
case 'a':
light_position[0] -= 1.0;
printf("luce: x%f - y%f\n", light_diffuse[0], light_diffuse[1]);
break;
case 'd':
light_position[0] += 1.0;
printf("luce: x%f - y%f\n", light_diffuse[0], light_diffuse[1]);
break;
default:
printf("not implemented!\n");
break;
}
glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse);
glLightfv(GL_LIGHT0, GL_POSITION, light_position);
glLightfv(GL_LIGHT1, GL_AMBIENT, light_diffuse);
glutSwapBuffers();
glutPostRedisplay();
}
void
mouse(int button, int state, int x, int y)
{
if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN) {
moving = 1;
startx = x;
starty = y;
}
if (button == GLUT_LEFT_BUTTON && state == GLUT_UP) {
moving = 0;
}
}
/* ARGSUSED1 */
void
motion(int x, int y)
{
if (moving) {
angle1 = angle1 + (x - startx);
angle2 = angle2 + (y - starty);
startx = x;
starty = y;
glRotatef(angle2, 1.0, 0.0, 0.0);
glRotatef(angle1, 0.0, 1.0, 0.0);
glutPostRedisplay();
}
}
int
main(int argc, char **argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
glutInitWindowSize(800, 800);
glutCreateWindow("red 3D lighted cube");
init();
glutMouseFunc(mouse);
glutMotionFunc(motion);
glutKeyboardFunc(processNormalKeys);
glutSpecialFunc(inputKey);
glutDisplayFunc(display);
glutReshapeFunc(changeSize);
//glutTimerFunc(0, timer, 0);
glutMainLoop();
return 0; /* ANSI C requires main to return int. */
}