Stratos: Punto de Encuentro de Desarrolladores

¡Bienvenido a Stratos!

Acceder

Foros





ayuda a hacer un render optimo a una esfera...

Iniciado por xeex, 06 de Agosto de 2008, 10:06:48 PM

« anterior - próximo »

xeex

Hola...
No se que estare haciendo mal pero hago una esfera de digamos 32 meridianos y 32 paralelos, pero me resulta muy muy lenta al momento de mostrarla...
¿como esta implementada la glutSolidSphere?
no me hace falta el codigo que genera los vertices sino el como fue hecha... con triangle_strip? o es acaso quad_strip?
se usan vertex array?

a la glutSolidSphere por mas meridianos y paralelos que le pongo se sigue viendo rapidisimo, en cambio mi esfera no.

por favor ayuda...

Pogacha

Podes hacer 3 cosas optimizar:
Una lista de comandos.
Un vertex buffer donde los vertes.
Y un triangle strip para los triangulos

Saludos

xeex

gracias
...una lista de comandos?
...no te entendi.

Pogacha


Prompt

Lo normal es usar VBO, Vertex Buffer Object.

Busca directamente como hacer un vertex y un index buffer.

Saludos

Pogacha

CitarVBO

Esta y el triangle strip será lo que mas velocidad le den a la esfera

Prompt

Cita de: "Pogacha"
CitarVBO

Esta y el triangle strip será lo que mas velocidad le den a la esfera

posi! :)

Prompt

Y no hacer glTranslate y glRotate por fixed pipelines xD

Evitar usar el fixed pipeline a toda costa, para una tetera no vas a saturar el BUS de datos por frame pero bueno :P

tamat

todos los consejos anteriores son buenos, aun así no me cuadra que una simple esfera te vaya tan lento. Puedes poner el codigo aquí?
Por un stratos menos tenso

Prompt

Puede estar saturando el BUS de la tarjeta con algun bucle bestia que cambia datos.

Bottle Neck en CPU o GPU...

Usar gDebugger / VTune o hazte un profiler sencillo que mida tiempos :)

xeex

gracias a todos...ahora pongo el codigo para que me corrijan

Cuando hago la esfera lo hago de la sigiente forma:
- Cargo la textura para la esfera con cargarTGA().
- Genero la esfera, sus vertices, 4 por cada lado, y la normal asociada a cada lado. Todo lo anterior coordenadas de vertices y normales, lo guardo en un vector.
- LLamo a la funcion genera_lista que lo que hace es sacar del vector los vertices y normales, dibujar los lados y meterlos a un displaylist
- Luego mostrar la lista con la funcion dibuja.

-el numero de paralelos en la esfera es de 256
-el numero demeridianos en la esfera es de 256
-por lo tanto el numero de lados de la esfera es 65536
-La funcion cargaTGA es oviable...solo la puse.


//aqui cargo la texura de tipo tga
int cargarTGA( char *nombre, textura *imagen)
{
GLubyte cabezeraTGA[12]={0,0,2,0,0,0,0,0,0,0,0,0}; // Cabecera de un tga sin compresión
GLubyte compararTGA[12]; // Acá vamos a comprar la cabecera
GLubyte cabezera[6]; // Los 6 bytes importantes
GLuint bytesporpunto; // Cuantos bytes hay por punto
GLuint tamanoimagen; // Acá guardaremos el tamaño de la imagen
GLuint temp,i;    // Variable temporal, y una para usar con el for
GLuint tipo=GL_RGBA; // Nuestro tipo por defecto, lo veremos mas abajo

FILE *archivo=fopen(nombre, "rb"); // Cargamos nuestro archivo en memoria
if( archivo == NULL ||// Existe nuestro archivo??
   fread(compararTGA,1,sizeof(compararTGA),archivo)!=sizeof(compararTGA) || // Hay 12 bytes para leer??
   memcmp(cabezeraTGA,compararTGA,sizeof(compararTGA))!=0 || // Son iguales??
   fread(cabezera,1,sizeof(cabezera),archivo)!=sizeof(cabezera))
    {
if(archivo==NULL)
return 0; // No se abrió el archivo
else
        {
fclose(archivo);
return 0;
}
}
   imagen->largo=256*cabezera[1]+ cabezera[0];
imagen->ancho=256*cabezera[3]+ cabezera[2];

/* Ahora vemos si hay datos no válidos, como largo o ancho iguales menores a 0 o iguales a 0 */
if( imagen->largo <= 0 || // Largo mayor que 0??
   imagen->ancho <= 0 || // Ancho mayor que 0??
   (cabezera[4]!=24 && cabezera[4]!=32)) { // bpp es 24 o 32?? (solo se cargan 24 y 32 bpp)
fclose(archivo);
return 0;
}
imagen->bpp=cabezera[4];    // Acá se guardan los bits por punto
bytesporpunto=cabezera[4]/8; // Acá los bytes por punto (1 byte = 8 bits)
tamanoimagen=imagen->largo * imagen->ancho * bytesporpunto;
   // Esta es la memoria que necesitaremos para guardar los datos de la textura
/* Ahora reservamos espacio en memoria para nuestra textura, luego leemos la
      textura del archivo */
imagen->dibujo = (GLubyte *)malloc(tamanoimagen); // Reservamos la memoria necesaria para nuestra textura
if(imagen->dibujo== NULL || // Se logró reservar la memoria???
  fread(imagen->dibujo, 1, tamanoimagen, archivo) != tamanoimagen ) {
       // Se lee, y se comprueba que lo leído es de la misma longitud que la asignada a a dibujo.
if(imagen->dibujo != NULL)
free(imagen->dibujo);
fclose(archivo);
return 0;
}
/* El formato tga guarda las imágenes en BGR, y opengl usa RGB,por lo cambiamos de lugares */
for(i=0; i < int(tamanoimagen); i+=bytesporpunto)
{
temp=imagen->dibujo[i];           // Guardamos el primer valor
imagen->dibujo[i] = imagen->dibujo[i + 2]; // Asignamos el nuevo primer valor
imagen->dibujo[i + 2] = temp;   // Asignamos el ultimo valor
}

fclose (archivo); // Cerramos el archivo

/* Listo, terminamos con el código de carga, volvemos a opengl, ahora hay
      que asignarle a la textura un ID, luego decirle a opengl cuales son el largo,
      el ancho y los bpp */
   
glGenTextures(1,&imagen->ID); // Crea un ID para la textura, buscando un id que este vacío
glBindTexture(GL_TEXTURE_2D, imagen->ID); // Seleccionamos nuestra textura
if(imagen->bpp ==24) tipo= GL_RGB; // Si nuestra textura es de 24 bits, entonces
                                       // se crea una textura rgb, sino una rgba
/* Ahora creamos nuestra textura, entrando el largo, ancho y tipo */
glTexImage2D(GL_TEXTURE_2D, 0, tipo, imagen->ancho, imagen->largo, 0, tipo, GL_UNSIGNED_BYTE, imagen->dibujo);
/* Ahora le decimos a opengl como queremos que se vea nuestra textura, MAG_FILTER
      es cuando la textura es mas grande que el lugar donde la asignamos, y MIG_FILTER,
      es cuando la textura es mas pequeña que el lugar donde la asignamos, GL_LINEAR es
      para que se vea bien tanto cerca como lejos, pero ocupa bastante procesador.
      Otra opción el GL_NEARES, que ocupa menos procesador */
   //glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT);
   //glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT);
   //glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP_TO_EDGE);
//glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP_TO_EDGE);  
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); // La m
   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
return 1; // Todo salió bien
}




//estructura en donde alojo la textura previamente cargada con cargarTGA()
typedef struct {
GLubyte *dibujo; // Un puntero  los datos de la imagen
GLuint bpp; // bpp significa bits per pixel (bits por punto)
// es la calidad en palabras sencillas
GLuint largo; // Largo de la textura
GLuint ancho; // Ancho de la textura
GLuint ID;    // ID de la textura, es como su nombre para opengl
} textura;





GLuint lista_esfera;//la lista para la esfera
int numero_de_lados_esfera=65536;
textura textura_esfera;
float *vector;//aki dejare la normal y 4 vertices por lado para la esfera







//aqui genero los vertices y la normal de cada lado de la esfera
void generar_esfera()
  {  
     float radio=10;
     int pa=256;
     int me=256;      
     int nro_lados=pa*me;//65536 lados      
     vector = (float *) malloc (15*nro_lados*sizeof (float));// un vector en donde dejo los vertices y
                                                             //las normales de cada lado de la esfera
     //el porque de 15*numero de lados es por:
     //                                        N(nx,ny,nz)                N(nx,ny,nz)
     // 1 coordenada x    normal  lado 1       v2(x2,y2,z2) _____________ v3(x3,y3,z3)
     // 2 coordenada y    normal  lado 1                   |             |
     // 3 coordenada z    normal  lado 1                   |             |
     // 4 coordenada x vertice 1  lado 1                   | LADO        |
     // 5 coordenada y vertice 1  lado 1                   | ESFERA      |
     // 6 coordenada z vertice 1  lado 1       N(nx,ny,nz) |             |N(nx,ny,nz)
     // 7 coordenada x vertice 2  lado 1       v1(x1,y1,z1)|_____________|v4(x4,y4,z4)
     // 8 coordenada y vertice 2  lado 1
     // 9 coordenada z vertice 2  lado 1
     //10 coordenada x vertice 3  lado 1
     //11 coordenada y vertice 3  lado 1
     //12 coordenada z vertice 3  lado 1
     //13 coordenada x vertice 4  lado 1
     //14 coordenada y vertice 4  lado 1
     //15 coordenada z vertice 4  lado 1            
     
     float v1x,v1y,v1z,v2x,v2y,v2z,v3x,v3y,v3z,v4x,v4y,v4z,x1,x2,x3,x4,y1,y2,z1,z2,z3,z4;      
     for(int i=0;i<pa;++i)
        for(int j=0;j<me;++j)
           {              
              y1=2*radio/pa*i-radio;
              y2=2*radio/pa*(i+1)-radio;
              v1y=y1;  v2y=y2;  v3y=y2;  v4y=y1;              
                             
              x1=sin(360.0/me*j*3.14159265358979/180.0)*sqrt(radio*radio-y1*y1);
              x2=sin(360.0/me*j*3.14159265358979/180.0)*sqrt(radio*radio-y2*y2);
              x3=sin(360.0/me*(j+1)*3.14159265358979/180.0)*sqrt(radio*radio-y1*y1);
              x4=sin(360.0/me*(j+1)*3.14159265358979/180.0)*sqrt(radio*radio-y2*y2);
              v1x=x1;  v2x=x2;  v3x=x4;  v4x=x3;
             
              z1=cos(360.0/me*j*3.14159265358979/180.0)*sqrt(radio*radio-y1*y1);
              z2=cos(360.0/me*j*3.14159265358979/180.0)*sqrt(radio*radio-y2*y2);
              z3=cos(360.0/me*(j+1)*3.14159265358979/180.0)*sqrt(radio*radio-y1*y1);
              z4=cos(360.0/me*(j+1)*3.14159265358979/180.0)*sqrt(radio*radio-y2*y2);
              v1z=z1;  v2z=z2;  v3z=z4;  v4z=z3;          
             
              a=v1x-v2x; b=v1y-v2y; c=v1z-v2z;
              d=v3x-v2x; e=v3y-v2y; f=v3z-v2z;
              float   g=   b*f-e*c ;
              float   h= -(a*f-d*c);
              float  ii=   a*e-d*b ;
              float nor=   sqrt(g*g+h*h+ii*ii);
             
              //arriba estoy generando los vertices( v1x,v1y,v1z - v2x,v2y,v2z - v3x,v3y,v3z - v4x,v4y,v4z) para cada lado de la esfera              
              //junto con las coordenadas de la normal para ese lado (nx = g/nor, ny = h/nor, nz = ii/nor )                              
                             
              vector[0 +15*(i*me+j)] =g/nor; vector[ 1+15*(i*me+j)] =h/nor; vector[ 2+15*(i*me+j)] =ii/nor;
              vector[3 +15*(i*me+j)] =v1x;   vector[ 4+15*(i*me+j)] =v1y;   vector[ 5+15*(i*me+j)] =v1z;
              vector[6 +15*(i*me+j)] =v2x;   vector[ 7+15*(i*me+j)] =v2y;   vector[ 8+15*(i*me+j)] =v2z;
              vector[9 +15*(i*me+j)] =v3x;   vector[10+15*(i*me+j)] =v3y;   vector[11+15*(i*me+j)] =v3z;
              vector[12+15*(i*me+j)] =v4x;   vector[13+15*(i*me+j)] =v4y;   vector[14+15*(i*me+j)] =v4z;              
              //ahora tengo todas las coordenadas de la esfera en el vector
           }      
  }


void dibuja_lado_esfera(float nx,float ny,float nz,
                       float v1x,float v1y,float v1z,float v2x,float v2y,float v2z,
                       float v3x,float v3y,float v3z,float v4x,float v4y,float v4z)              
  {      
     glBegin(GL_QUADS);      
     glTexCoord2f(0.0,0.0);  glNormal3f(nx,ny,nz);  glVertex3f(v1x,v1y,v1z);
     glTexCoord2f(0.0,1.0);  glNormal3f(nx,ny,nz);  glVertex3f(v2x,v2y,v2z);
     glTexCoord2f(1.0,1.0);  glNormal3f(nx,ny,nz);  glVertex3f(v3x,v3y,v3z);
     glTexCoord2f(1.0,0.0);  glNormal3f(nx,ny,nz);  glVertex3f(v4x,v4y,v4z);
     glEnd();    
  }


void genera_lista()
  {        
     list_esfera=glGenLists(1);          
     glNewList(lista_esfera,GL_COMPILE);
     glBindTexture(GL_TEXTURE_2D,textura_esfera.ID);
     for(int i=0;i<numero_de_lados_esfera*15;++i)
        {
           dibuja_lado_esfera( vector[ 0+i] , vector[ 1+i] , vector[ 2+i] ,//envio la coordenada x,y,z de la normal para el lado n
                               vector[ 3+i] , vector[ 4+i] , vector[ 5+i] ,//envio la coordenada x,y,z del vertice1 para el lado n  
                               vector[ 6+i] , vector[ 7+i] , vector[ 8+i] ,//envio la coordenada x,y,z del vertice2 para el lado n
                               vector[ 9+i] , vector[10+i] , vector[11+i] ,//envio la coordenada x,y,z del vertice3 para el lado n
                               vector[12+i] , vector[13+i] , vector[14+i] );//envio la coordenada x,y,z del vertice4 para el lado n
           i=i+14;
        }                    
     glEndList();    
  }


void dibuja()  
  {
     glCallList(lista_esfera);
  }


void main()
  {
     cargarTGA("esfera.tga", &textura_esfera);
     generar_esfera();
     genera_lista();
     do
        {
           dibuja();
        }while(key[KEY_ESC]);      
  }




Ok, ahi esta, si me pueden corregir...partiendo por no usar QUADS sino QUAD_STRIP....

muchas gracias y saludos a todos.

Prompt

Jamás me acostumbrare a ver código en español y ver la palabra "arreglo"

Lo más wapo es ver:

vector ... =  ... // Arreglo de... xD

ya me explicarás cuando necesites usar la ñ que vas a hacer :P (que en un momento determinado se puede poner en unicode y blahblablah)

Voy a intentar descifrar el código... a ver

Prompt

Cita de: "xeex"
Ok, ahi esta, si me pueden corregir...partiendo por no usar QUADS sino QUAD_STRIP....

Tu problema aqui no son es QUAD_STRIP creeme. Que fps consigues? no se si lo dijiste

xeex

gracias por responder...trate de dejar el codigo lo mas simple...
mostrando la escena sin absolutamente nada en ella me da 120 FPS.
cuando muestro la esfera me da 20 FPS.

Prompt

Esto es código de glut, tu haces cuadrados simulando la esfera, si no veo mal, vas cuadradito por cuadradito.


static GLUquadricObj *quadObj;

#define QUAD_OBJ_INIT() { if(!quadObj) initQuadObj(); }

static void
initQuadObj(void)
{
 quadObj = gluNewQuadric();
 if (!quadObj)
   __glutFatalError("out of memory.");
}

/* CENTRY */
void APIENTRY
glutWireSphere(GLdouble radius, GLint slices, GLint stacks)
{
 QUAD_OBJ_INIT();
 gluQuadricDrawStyle(quadObj, GLU_LINE);
 gluQuadricNormals(quadObj, GLU_SMOOTH);
 /* If we ever changed/used the texture or orientation state
    of quadObj, we'd need to change it to the defaults here
    with gluQuadricTexture and/or gluQuadricOrientation. */
 gluSphere(quadObj, radius, slices, stacks);
}

void APIENTRY
glutSolidSphere(GLdouble radius, GLint slices, GLint stacks)
{
 QUAD_OBJ_INIT();
 [b]gluQuadricDrawStyle[/b](quadObj, GLU_FILL);
 gluQuadricNormals(quadObj, GLU_SMOOTH);
 /* If we ever changed/used the texture or orientation state
    of quadObj, we'd need to change it to the defaults here
    with gluQuadricTexture and/or gluQuadricOrientation. */
 [b]gluSphere[/b](quadObj, radius, slices, stacks);
}


Esto va a ser una tochada...

Codigo de gluSphere

void GLAPIENTRY
gluSphere(GLUquadric *qobj, GLdouble radius, GLint slices, GLint stacks)
{
   GLint i,j;
   GLfloat sinCache1a[CACHE_SIZE];
   GLfloat cosCache1a[CACHE_SIZE];
   GLfloat sinCache2a[CACHE_SIZE];
   GLfloat cosCache2a[CACHE_SIZE];
   GLfloat sinCache3a[CACHE_SIZE];
   GLfloat cosCache3a[CACHE_SIZE];
   GLfloat sinCache1b[CACHE_SIZE];
   GLfloat cosCache1b[CACHE_SIZE];
   GLfloat sinCache2b[CACHE_SIZE];
   GLfloat cosCache2b[CACHE_SIZE];
   GLfloat sinCache3b[CACHE_SIZE];
   GLfloat cosCache3b[CACHE_SIZE];
   GLfloat angle;
   GLfloat zLow, zHigh;
   GLfloat sintemp1, sintemp2, sintemp3 = 0.0, sintemp4 = 0.0;
   GLfloat costemp1, costemp2 = 0.0, costemp3 = 0.0, costemp4 = 0.0;
   GLboolean needCache2, needCache3;
   GLint start, finish;

   if (slices >= CACHE_SIZE) slices = CACHE_SIZE-1;
   if (stacks >= CACHE_SIZE) stacks = CACHE_SIZE-1;
   if (slices < 2 || stacks < 1 || radius < 0.0) {
gluQuadricError(qobj, GLU_INVALID_VALUE);
return;
   }

   /* Cache is the vertex locations cache */
   /* Cache2 is the various normals at the vertices themselves */
   /* Cache3 is the various normals for the faces */
   needCache2 = needCache3 = GL_FALSE;

   if (qobj->normals == GLU_SMOOTH) {
needCache2 = GL_TRUE;
   }

   if (qobj->normals == GLU_FLAT) {
if (qobj->drawStyle != GLU_POINT) {
   needCache3 = GL_TRUE;
}
if (qobj->drawStyle == GLU_LINE) {
   needCache2 = GL_TRUE;
}
   }

   for (i = 0; i < slices; i++) {
angle = 2 * PI * i / slices;
sinCache1a[i] = SIN(angle);
cosCache1a[i] = COS(angle);
if (needCache2) {
   sinCache2a[i] = sinCache1a[i];
   cosCache2a[i] = cosCache1a[i];
}
   }

   for (j = 0; j <= stacks; j++) {
angle = PI * j / stacks;
if (needCache2) {
   if (qobj->orientation == GLU_OUTSIDE) {
sinCache2b[j] = SIN(angle);
cosCache2b[j] = COS(angle);
   } else {
sinCache2b[j] = -SIN(angle);
cosCache2b[j] = -COS(angle);
   }
}
sinCache1b[j] = radius * SIN(angle);
cosCache1b[j] = radius * COS(angle);
   }
   /* Make sure it comes to a point */
   sinCache1b[0] = 0;
   sinCache1b[stacks] = 0;

   if (needCache3) {
for (i = 0; i < slices; i++) {
   angle = 2 * PI * (i-0.5) / slices;
   sinCache3a[i] = SIN(angle);
   cosCache3a[i] = COS(angle);
}
for (j = 0; j <= stacks; j++) {
   angle = PI * (j - 0.5) / stacks;
   if (qobj->orientation == GLU_OUTSIDE) {
sinCache3b[j] = SIN(angle);
cosCache3b[j] = COS(angle);
   } else {
sinCache3b[j] = -SIN(angle);
cosCache3b[j] = -COS(angle);
   }
}
   }

   sinCache1a[slices] = sinCache1a[0];
   cosCache1a[slices] = cosCache1a[0];
   if (needCache2) {
sinCache2a[slices] = sinCache2a[0];
cosCache2a[slices] = cosCache2a[0];
   }
   if (needCache3) {
sinCache3a[slices] = sinCache3a[0];
cosCache3a[slices] = cosCache3a[0];
   }

   switch (qobj->drawStyle) {
     case GLU_FILL:
/* Do ends of sphere as TRIANGLE_FAN's (if not texturing)
** We don't do it when texturing because we need to respecify the
** texture coordinates of the apex for every adjacent vertex (because
** it isn't a constant for that point)
*/
if (!(qobj->textureCoords)) {
   start = 1;
   finish = stacks - 1;

   /* Low end first (j == 0 iteration) */
   sintemp2 = sinCache1b[1];
   zHigh = cosCache1b[1];
   switch(qobj->normals) {
     case GLU_FLAT:
sintemp3 = sinCache3b[1];
costemp3 = cosCache3b[1];
break;
     case GLU_SMOOTH:
sintemp3 = sinCache2b[1];
costemp3 = cosCache2b[1];
glNormal3f(sinCache2a[0] * sinCache2b[0],
cosCache2a[0] * sinCache2b[0],
cosCache2b[0]);
break;
     default:
break;
   }
   glBegin(GL_TRIANGLE_FAN);
   glVertex3f(0.0, 0.0, radius);
   if (qobj->orientation == GLU_OUTSIDE) {
for (i = slices; i >= 0; i--) {
   switch(qobj->normals) {
     case GLU_SMOOTH:
glNormal3f(sinCache2a[i] * sintemp3,
cosCache2a[i] * sintemp3,
costemp3);
break;
     case GLU_FLAT:
if (i != slices) {
   glNormal3f(sinCache3a[i+1] * sintemp3,
   cosCache3a[i+1] * sintemp3,
   costemp3);
}
break;
     case GLU_NONE:
     default:
break;
   }
   glVertex3f(sintemp2 * sinCache1a[i],
   sintemp2 * cosCache1a[i], zHigh);
}
   } else {
for (i = 0; i <= slices; i++) {
   switch(qobj->normals) {
     case GLU_SMOOTH:
glNormal3f(sinCache2a[i] * sintemp3,
cosCache2a[i] * sintemp3,
costemp3);
break;
     case GLU_FLAT:
glNormal3f(sinCache3a[i] * sintemp3,
cosCache3a[i] * sintemp3,
costemp3);
break;
     case GLU_NONE:
     default:
break;
   }
   glVertex3f(sintemp2 * sinCache1a[i],
   sintemp2 * cosCache1a[i], zHigh);
}
   }
   glEnd();

   /* High end next (j == stacks-1 iteration) */
   sintemp2 = sinCache1b[stacks-1];
   zHigh = cosCache1b[stacks-1];
   switch(qobj->normals) {
     case GLU_FLAT:
sintemp3 = sinCache3b[stacks];
costemp3 = cosCache3b[stacks];
break;
     case GLU_SMOOTH:
sintemp3 = sinCache2b[stacks-1];
costemp3 = cosCache2b[stacks-1];
glNormal3f(sinCache2a[stacks] * sinCache2b[stacks],
cosCache2a[stacks] * sinCache2b[stacks],
cosCache2b[stacks]);
break;
     default:
break;
   }
   glBegin(GL_TRIANGLE_FAN);
   glVertex3f(0.0, 0.0, -radius);
   if (qobj->orientation == GLU_OUTSIDE) {
for (i = 0; i <= slices; i++) {
   switch(qobj->normals) {
     case GLU_SMOOTH:
glNormal3f(sinCache2a[i] * sintemp3,
cosCache2a[i] * sintemp3,
costemp3);
break;
     case GLU_FLAT:
glNormal3f(sinCache3a[i] * sintemp3,
cosCache3a[i] * sintemp3,
costemp3);
break;
     case GLU_NONE:
     default:
break;
   }
   glVertex3f(sintemp2 * sinCache1a[i],
   sintemp2 * cosCache1a[i], zHigh);
}
   } else {
for (i = slices; i >= 0; i--) {
   switch(qobj->normals) {
     case GLU_SMOOTH:
glNormal3f(sinCache2a[i] * sintemp3,
cosCache2a[i] * sintemp3,
costemp3);
break;
     case GLU_FLAT:
if (i != slices) {
   glNormal3f(sinCache3a[i+1] * sintemp3,
   cosCache3a[i+1] * sintemp3,
   costemp3);
}
break;
     case GLU_NONE:
     default:
break;
   }
   glVertex3f(sintemp2 * sinCache1a[i],
   sintemp2 * cosCache1a[i], zHigh);
}
   }
   glEnd();
} else {
   start = 0;
   finish = stacks;
}
for (j = start; j < finish; j++) {
   zLow = cosCache1b[j];
   zHigh = cosCache1b[j+1];
   sintemp1 = sinCache1b[j];
   sintemp2 = sinCache1b[j+1];
   switch(qobj->normals) {
     case GLU_FLAT:
sintemp4 = sinCache3b[j+1];
costemp4 = cosCache3b[j+1];
break;
     case GLU_SMOOTH:
if (qobj->orientation == GLU_OUTSIDE) {
   sintemp3 = sinCache2b[j+1];
   costemp3 = cosCache2b[j+1];
   sintemp4 = sinCache2b[j];
   costemp4 = cosCache2b[j];
} else {
   sintemp3 = sinCache2b[j];
   costemp3 = cosCache2b[j];
   sintemp4 = sinCache2b[j+1];
   costemp4 = cosCache2b[j+1];
}
break;
     default:
break;
   }

   glBegin(GL_QUAD_STRIP);
   for (i = 0; i <= slices; i++) {
switch(qobj->normals) {
 case GLU_SMOOTH:
   glNormal3f(sinCache2a[i] * sintemp3,
   cosCache2a[i] * sintemp3,
   costemp3);
   break;
 case GLU_FLAT:
 case GLU_NONE:
 default:
   break;
}
if (qobj->orientation == GLU_OUTSIDE) {
   if (qobj->textureCoords) {
glTexCoord2f(1 - (float) i / slices,
1 - (float) (j+1) / stacks);
   }
   glVertex3f(sintemp2 * sinCache1a[i],
   sintemp2 * cosCache1a[i], zHigh);
} else {
   if (qobj->textureCoords) {
glTexCoord2f(1 - (float) i / slices,
1 - (float) j / stacks);
   }
   glVertex3f(sintemp1 * sinCache1a[i],
   sintemp1 * cosCache1a[i], zLow);
}
switch(qobj->normals) {
 case GLU_SMOOTH:
   glNormal3f(sinCache2a[i] * sintemp4,
   cosCache2a[i] * sintemp4,
   costemp4);
   break;
 case GLU_FLAT:
   glNormal3f(sinCache3a[i] * sintemp4,
   cosCache3a[i] * sintemp4,
   costemp4);
   break;
 case GLU_NONE:
 default:
   break;
}
if (qobj->orientation == GLU_OUTSIDE) {
   if (qobj->textureCoords) {
glTexCoord2f(1 - (float) i / slices,
1 - (float) j / stacks);
   }
   glVertex3f(sintemp1 * sinCache1a[i],
   sintemp1 * cosCache1a[i], zLow);
} else {
   if (qobj->textureCoords) {
glTexCoord2f(1 - (float) i / slices,
1 - (float) (j+1) / stacks);
   }
   glVertex3f(sintemp2 * sinCache1a[i],
   sintemp2 * cosCache1a[i], zHigh);
}
   }
   glEnd();
}
break;
     case GLU_POINT:
glBegin(GL_POINTS);
for (j = 0; j <= stacks; j++) {
   sintemp1 = sinCache1b[j];
   costemp1 = cosCache1b[j];
   switch(qobj->normals) {
     case GLU_FLAT:
     case GLU_SMOOTH:
sintemp2 = sinCache2b[j];
costemp2 = cosCache2b[j];
break;
     default:
break;
   }
   for (i = 0; i < slices; i++) {
switch(qobj->normals) {
 case GLU_FLAT:
 case GLU_SMOOTH:
   glNormal3f(sinCache2a[i] * sintemp2,
   cosCache2a[i] * sintemp2,
   costemp2);
   break;
 case GLU_NONE:
 default:
   break;
}

zLow = j * radius / stacks;

if (qobj->textureCoords) {
   glTexCoord2f(1 - (float) i / slices,
   1 - (float) j / stacks);
}
glVertex3f(sintemp1 * sinCache1a[i],
sintemp1 * cosCache1a[i], costemp1);
   }
}
glEnd();
break;
     case GLU_LINE:
     case GLU_SILHOUETTE:
for (j = 1; j < stacks; j++) {
   sintemp1 = sinCache1b[j];
   costemp1 = cosCache1b[j];
   switch(qobj->normals) {
     case GLU_FLAT:
     case GLU_SMOOTH:
sintemp2 = sinCache2b[j];
costemp2 = cosCache2b[j];
break;
     default:
break;
   }

   glBegin(GL_LINE_STRIP);
   for (i = 0; i <= slices; i++) {
switch(qobj->normals) {
 case GLU_FLAT:
   glNormal3f(sinCache3a[i] * sintemp2,
   cosCache3a[i] * sintemp2,
   costemp2);
   break;
 case GLU_SMOOTH:
   glNormal3f(sinCache2a[i] * sintemp2,
   cosCache2a[i] * sintemp2,
   costemp2);
   break;
 case GLU_NONE:
 default:
   break;
}
if (qobj->textureCoords) {
   glTexCoord2f(1 - (float) i / slices,
   1 - (float) j / stacks);
}
glVertex3f(sintemp1 * sinCache1a[i],
sintemp1 * cosCache1a[i], costemp1);
   }
   glEnd();
}
for (i = 0; i < slices; i++) {
   sintemp1 = sinCache1a[i];
   costemp1 = cosCache1a[i];
   switch(qobj->normals) {
     case GLU_FLAT:
     case GLU_SMOOTH:
sintemp2 = sinCache2a[i];
costemp2 = cosCache2a[i];
break;
     default:
break;
   }

   glBegin(GL_LINE_STRIP);
   for (j = 0; j <= stacks; j++) {
switch(qobj->normals) {
 case GLU_FLAT:
   glNormal3f(sintemp2 * sinCache3b[j],
   costemp2 * sinCache3b[j],
   cosCache3b[j]);
   break;
 case GLU_SMOOTH:
   glNormal3f(sintemp2 * sinCache2b[j],
   costemp2 * sinCache2b[j],
   cosCache2b[j]);
   break;
 case GLU_NONE:
 default:
   break;
}

if (qobj->textureCoords) {
   glTexCoord2f(1 - (float) i / slices,
   1 - (float) j / stacks);
}
glVertex3f(sintemp1 * sinCache1b[j],
costemp1 * sinCache1b[j], cosCache1b[j]);
   }
   glEnd();
}
break;
     default:
break;
   }
}






Stratos es un servicio gratuito, cuyos costes se cubren en parte con la publicidad.
Por favor, desactiva el bloqueador de anuncios en esta web para ayudar a que siga adelante.
Muchísimas gracias.