pone lento error cinema opengl graphics geometry rendering 4d

lento - ¿Cómo debo manejar los objetos morphing en OpenGL?



cinema 4d se pone lento (1)

Quiero intentar escribir un patio de juegos similar a este 4D juguetes , así que comencé a aprender OpenGL.
desde mi comprensión actual, las personas usan VBO y matriz de transformación uniforme para objetos mayormente estáticos
(como cubos, animaciones esqueléticas, etc., que generalmente solo implica transformaciones)

También escuché que la transformación entre modelos también usa VBO para almacenar en caché ambos modelos, ya que ambos estarán bien definidos y no tanto como intermedios.

pero en los juguetes 4D mencionados anteriormente, los objetos se deforman y se recortan mucho.
y es probable que no haya modelos definidos y muchas transiciones en el medio.
(podría ser un cuadrado simple ahora, y una bola puntiaguda cortada por la mitad más tarde).
en este caso, ¿actualizar-vertex-VBO-per-frame o Vertex Arrays (que vi en otra pregunta) es una solución adecuada?


Para empezar, usaría 4D -> 3D proyección 4D -> 3D lugar de cortarla con hyperplane. El resultado no es el mismo, pero te acercará más a tu objetivo (por lo que puedes actualizarlo para cortarlo). De manera similar, al igual que en 3D -> 2D conversiones 3D -> 2D utilizadas en los gráficos, tienes 2 opciones, una está utilizando la proyección en perspectiva y la segunda es simplemente ignorar las coordenadas de la 4ª dimensión durante el renderizado. Usaré este último ya que es más simple.

  1. estructuras

    Para hacer esto tan simple como pueda, usaré wire-frame en lugar de BR rendering. Por lo tanto, necesita manejar una malla 4D (estructura de alambre). Yo usaría 2 tablas:

    double pnt[]; // 4D point list (x,y,z,u) int lin[]; // lines point indexes (i0,i1)

    el primero almacena todos los vértices de su malla y el segundo mantiene pares de puntos de índice conectados por líneas en representación de marco de alambre.

  2. transforma

    Si solo ignorase la cuarta coordenada, no obtendríamos la funcionalidad deseada. Entonces, para hacer que funcione la 4ta dimensión, necesitamos agregar la transformada 4D para orientar nuestra malla en 4D antes de renderizar. Por lo tanto, utilice la matriz de transformación homogénea y le permite llamar a la rep . En 4D debería ser una matriz ortonormal de 5x5 con una rotación de parte de rotación de 4x4 .

    Para hacerlo aún más fácil, evite las rotaciones suaves por el momento (como en 4D, que no es tan fácil) y en su lugar, calcule la matriz aleatoria de rotación 4x4 . Así que simplemente configure todas las celdas al azar <-1,+1> . Maneja cada fila como vector de base. Para hacerlos ortonormales simplemente hazlos unitarios y explota el producto cruzado. Para obtener más información, consulte:

    • ¿Cómo generar un círculo de alta dimensión orientado al azar en python?
  3. hacer

    simplemente convierte la tabla de puntos por tu matriz de transformación

    (x'',y'',z'',u'',W) = rep * (x,y,z,u,1)

    luego toma el (x ,y , z`) y render ...

Aquí ejemplo simple de OpenGL / C ++ de 4D hyper cube:

//--------------------------------------------------------------------------- //--- Mesh 4D: ver 0.000 ---------------------------------------------------- //--------------------------------------------------------------------------- #ifndef _mesh4D_h #define _mesh4D_h //--------------------------------------------------------------------------- #include <math.h> #include "nd_math.h" #include "list.h" //--------------------------------------------------------------------------- const double pi = M_PI; const double pi2 =2.0*M_PI; const double pipol=0.5*M_PI; const double deg=M_PI/180.0; const double rad=180.0/M_PI; //--------------------------------------------------------------------------- class mesh4D { public: matrix<5> rep; // 4D uniform 5x5 transform matrix List<double> pnt; // 4D point list (x,y,z,u) List<int> lin; // lines point indexes (i0,i1) mesh4D() {} mesh4D(mesh4D& a) { *this=a; } ~mesh4D() {} mesh4D* operator = (const mesh4D *a) { *this=*a; return this; } //mesh4D* operator = (const mesh4D &a) { ...copy... return this; } void set_randomrep(); // random oriented uniform 4D transform matrix with origin (0,0,0,0) void set_hypercube(double a); void draw(); }; //--------------------------------------------------------------------------- void mesh4D::set_randomrep() { int i,j; matrix<4> rot; rep.unit(); rot.rnd(); rot.orthonormal(); for (i=0;i<4;i++) for (j=0;j<4;j++) rep[i][j]=rot[i][j]; } void mesh4D::set_hypercube(double a) { rep.unit(); // reset orientation pnt.num=0; // clear point list lin.num=0; // clear line list pnt.add(-a); pnt.add(-a); pnt.add(-a); pnt.add(-a); pnt.add(+a); pnt.add(-a); pnt.add(-a); pnt.add(-a); pnt.add(-a); pnt.add(+a); pnt.add(-a); pnt.add(-a); pnt.add(+a); pnt.add(+a); pnt.add(-a); pnt.add(-a); pnt.add(-a); pnt.add(-a); pnt.add(+a); pnt.add(-a); pnt.add(+a); pnt.add(-a); pnt.add(+a); pnt.add(-a); pnt.add(-a); pnt.add(+a); pnt.add(+a); pnt.add(-a); pnt.add(+a); pnt.add(+a); pnt.add(+a); pnt.add(-a); pnt.add(-a); pnt.add(-a); pnt.add(-a); pnt.add(+a); pnt.add(+a); pnt.add(-a); pnt.add(-a); pnt.add(+a); pnt.add(-a); pnt.add(+a); pnt.add(-a); pnt.add(+a); pnt.add(+a); pnt.add(+a); pnt.add(-a); pnt.add(+a); pnt.add(-a); pnt.add(-a); pnt.add(+a); pnt.add(+a); pnt.add(+a); pnt.add(-a); pnt.add(+a); pnt.add(+a); pnt.add(-a); pnt.add(+a); pnt.add(+a); pnt.add(+a); pnt.add(+a); pnt.add(+a); pnt.add(+a); pnt.add(+a); // A0 lin.add( 0+0); lin.add( 0+1); lin.add( 0+1); lin.add( 0+3); lin.add( 0+3); lin.add( 0+2); lin.add( 0+2); lin.add( 0+0); // A1 lin.add( 4+0); lin.add( 4+1); lin.add( 4+1); lin.add( 4+3); lin.add( 4+3); lin.add( 4+2); lin.add( 4+2); lin.add( 4+0); // A=A0+A1 lin.add( 0+0); lin.add( 4+0); lin.add( 0+1); lin.add( 4+1); lin.add( 0+2); lin.add( 4+2); lin.add( 0+3); lin.add( 4+3); // B0 lin.add( 8+0); lin.add( 8+1); lin.add( 8+1); lin.add( 8+3); lin.add( 8+3); lin.add( 8+2); lin.add( 8+2); lin.add( 8+0); // B1 lin.add(12+0); lin.add(12+1); lin.add(12+1); lin.add(12+3); lin.add(12+3); lin.add(12+2); lin.add(12+2); lin.add(12+0); // B=B0+B1 lin.add( 8+0); lin.add(12+0); lin.add( 8+1); lin.add(12+1); lin.add( 8+2); lin.add(12+2); lin.add( 8+3); lin.add(12+3); // hyper cube = A+B lin.add( 0+0); lin.add( 8+0); lin.add( 0+1); lin.add( 8+1); lin.add( 0+2); lin.add( 8+2); lin.add( 0+3); lin.add( 8+3); lin.add( 0+4); lin.add( 8+4); lin.add( 0+5); lin.add( 8+5); lin.add( 0+6); lin.add( 8+6); lin.add( 0+7); lin.add( 8+7); } //--------------------------------------------------------------------------- void mesh4D::draw() { int i,j; double _zero=1e-3; vector<5> a,b; glBegin(GL_LINES); for (i=0;i<lin.num;) { // extrac first point j=lin[i]*4; i++; a.a[0]=pnt[j]; j++; a.a[1]=pnt[j]; j++; a.a[2]=pnt[j]; j++; a.a[3]=pnt[j]; j++; a.a[4]=1.0; // W=1 // extrac second point j=lin[i]*4; i++; b.a[0]=pnt[j]; j++; b.a[1]=pnt[j]; j++; b.a[2]=pnt[j]; j++; b.a[3]=pnt[j]; j++; b.a[4]=1.0; // W=1 // transform a=rep*a; b=rep*b; // render glVertex3dv(a.a); // use just x,y,z glVertex3dv(b.a); // use just x,y,z } glEnd(); } //--------------------------------------------------------------------------- #endif //---------------------------------------------------------------------------

Utilicé mi plantilla dynamic list.h así:


List<double> xxx; es lo mismo que double xxx[];
xxx.add(5); agrega 5 al final de la lista
xxx[7] elemento de matriz de acceso (seguro)
xxx.dat[7] access array element (inseguro pero acceso directo rápido)
xxx.num es el tamaño real utilizado de la matriz
xxx.reset() borra la matriz y establece xxx.num=0
xxx.allocate(100) preasignar espacio para 100 elementos

el nd_math.h es mío lib para computaciones N-Dimensionales. Lo que necesita es solo 4D, 5D vector y 4x4 , 5x5 matriz matemática de álgebra lineal.

Ambas bibliotecas son un poco grandes y también problemas legales me impiden compartir su código aquí.

El uso es simple:

// globals and init mesh4D mesh double animx=-50.0,danimx=0.0; double animy= 0.0,danimy=2.0; mesh.set_hypercube(0.5); // render glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluOrtho2D( -2.0, 2.0, -2.0, 2.0 ); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glRotated(animx,1.0,0.0,0.0); glRotated(animy,0.0,1.0,0.0); mesh.draw(); glFlush(); SwapBuffers(hdc); // some timer animx+=danimx; if (animx>=360.0) animx-=360.0; animy+=danimy; if (animy>=360.0) animy-=360.0; call_render_here(); // on key press or mouse wheel or what ever mesh.set_randomrep();

Y aquí una vista previa para algunas rotaciones de rep ...

para que de esta manera puedas representar cualquier malla de estructura de alambre (incluso la representación BR debería funcionar de esta manera).

Si desea actualizar al corte , debe tomar cada línea de marco de alambre y calcular su intersección con el hiperplano de corte. Si elegimos hyperplane que pasa por el punto

O(0,0,0,u_cut)

y tiene normal

N(0,0,0,1)

Entonces la tarea se simplificará mucho. hay 3 opciones Consideremos la línea de borde con los puntos finales A,B :

  1. sin intersección

    ((A.u > u_cut)&&(B.u > u_cut)) || ((A.u < u_cut)&&(B.u < u_cut))

    simplemente ignora ese borde

  2. 1 intersección

    ((A.u >= u_cut)&&(B.u <= u_cut)) || ((A.u <= u_cut)&&(B.u >= u_cut))

    así que calcule la intersección a través de la interpolación lineal

    x = A.x + (B.x-A.x)*(u_cut-A.u)/(B.u-A.u) y = A.y + (B.y-A.y)*(u_cut-A.u)/(B.u-A.u) z = A.z + (B.z-A.z)*(u_cut-A.u)/(B.u-A.u)

    y recuerda ese punto y también el borde al que pertenece.

  3. completamente adentro

    (A.u == u_cut)&&(B.u == u_cut)

    solo recuerda ambos puntos finales y también renderiza este borde.

Después de que todos los bordes se procesen de esta manera, deberá analizar los puntos de intersección recordados y crear nuevos bordes a partir de ellos en función de la información de conectividad entre los bordes. No hice esto todavía así que no puedo ayudar con esto. Intentaría conectar puntos recordados compartiendo el mismo vecino pero no estoy seguro si eso es suficiente en 4D .

Para obtener más información, eche un vistazo a los QA relacionados que acabo de encontrar:

  • Visualizar objetos 4D en OpenGL
  • Proyección en perspectiva 4D a 3D
  • Rotaciones 4D

Código [Edit1] con perspectiva

//--------------------------------------------------------------------------- //--- Mesh 4D: ver 0.001 ---------------------------------------------------- //--------------------------------------------------------------------------- #ifndef _mesh4D_h #define _mesh4D_h //--------------------------------------------------------------------------- #include <math.h> #include "nd_math.h" #include "list.h" //--------------------------------------------------------------------------- const double pi = M_PI; const double pi2 =2.0*M_PI; const double pipol=0.5*M_PI; const double deg=M_PI/180.0; const double rad=180.0/M_PI; //--------------------------------------------------------------------------- class mesh4D { public: matrix<5> rep; // 4D uniform 5x5 transform matrix List<double> pnt; // 4D point list (x,y,z,u) List<int> lin; // lines point indexes (i0,i1) mesh4D() {} mesh4D(mesh4D& a) { *this=a; } ~mesh4D() {} mesh4D* operator = (const mesh4D *a) { *this=*a; return this; } //mesh4D* operator = (const mesh4D &a) { ...copy... return this; } void set_randomrep(); // random oriented uniform 4D transform matrix with origin (0,0,0,0) void set_hypercube(double a); void draw(); }; //--------------------------------------------------------------------------- void mesh4D::set_randomrep() { int i,j; matrix<4> rot; rot.rnd(); rot.orthonormal(); for (i=0;i<4;i++) for (j=0;j<4;j++) rep[i][j]=rot[i][j]; } //--------------------------------------------------------------------------- void mesh4D::set_hypercube(double a) { rep.unit(); // reset orientation rep[0][4]=0.0; // set position rep[1][4]=0.0; rep[2][4]=0.0; rep[3][4]=3.0*a; pnt.num=0; // clear point list lin.num=0; // clear line list pnt.add(-a); pnt.add(-a); pnt.add(-a); pnt.add(-a); pnt.add(+a); pnt.add(-a); pnt.add(-a); pnt.add(-a); pnt.add(-a); pnt.add(+a); pnt.add(-a); pnt.add(-a); pnt.add(+a); pnt.add(+a); pnt.add(-a); pnt.add(-a); pnt.add(-a); pnt.add(-a); pnt.add(+a); pnt.add(-a); pnt.add(+a); pnt.add(-a); pnt.add(+a); pnt.add(-a); pnt.add(-a); pnt.add(+a); pnt.add(+a); pnt.add(-a); pnt.add(+a); pnt.add(+a); pnt.add(+a); pnt.add(-a); pnt.add(-a); pnt.add(-a); pnt.add(-a); pnt.add(+a); pnt.add(+a); pnt.add(-a); pnt.add(-a); pnt.add(+a); pnt.add(-a); pnt.add(+a); pnt.add(-a); pnt.add(+a); pnt.add(+a); pnt.add(+a); pnt.add(-a); pnt.add(+a); pnt.add(-a); pnt.add(-a); pnt.add(+a); pnt.add(+a); pnt.add(+a); pnt.add(-a); pnt.add(+a); pnt.add(+a); pnt.add(-a); pnt.add(+a); pnt.add(+a); pnt.add(+a); pnt.add(+a); pnt.add(+a); pnt.add(+a); pnt.add(+a); // A0 lin.add( 0+0); lin.add( 0+1); lin.add( 0+1); lin.add( 0+3); lin.add( 0+3); lin.add( 0+2); lin.add( 0+2); lin.add( 0+0); // A1 lin.add( 4+0); lin.add( 4+1); lin.add( 4+1); lin.add( 4+3); lin.add( 4+3); lin.add( 4+2); lin.add( 4+2); lin.add( 4+0); // A=A0+A1 lin.add( 0+0); lin.add( 4+0); lin.add( 0+1); lin.add( 4+1); lin.add( 0+2); lin.add( 4+2); lin.add( 0+3); lin.add( 4+3); // B0 lin.add( 8+0); lin.add( 8+1); lin.add( 8+1); lin.add( 8+3); lin.add( 8+3); lin.add( 8+2); lin.add( 8+2); lin.add( 8+0); // B1 lin.add(12+0); lin.add(12+1); lin.add(12+1); lin.add(12+3); lin.add(12+3); lin.add(12+2); lin.add(12+2); lin.add(12+0); // B=B0+B1 lin.add( 8+0); lin.add(12+0); lin.add( 8+1); lin.add(12+1); lin.add( 8+2); lin.add(12+2); lin.add( 8+3); lin.add(12+3); // hyper cube = A+B lin.add( 0+0); lin.add( 8+0); lin.add( 0+1); lin.add( 8+1); lin.add( 0+2); lin.add( 8+2); lin.add( 0+3); lin.add( 8+3); lin.add( 0+4); lin.add( 8+4); lin.add( 0+5); lin.add( 8+5); lin.add( 0+6); lin.add( 8+6); lin.add( 0+7); lin.add( 8+7); } //--------------------------------------------------------------------------- void mesh4D::draw() { int i,j; const double _zero=1e-3; double focal_length=1.0; vector<5> a,b; glBegin(GL_LINES); for (i=0;i<lin.num;) { // extrac first point j=lin[i]*4; i++; a.a[0]=pnt[j]; j++; a.a[1]=pnt[j]; j++; a.a[2]=pnt[j]; j++; a.a[3]=pnt[j]; j++; a.a[4]=1.0; // W=1 // extrac second point j=lin[i]*4; i++; b.a[0]=pnt[j]; j++; b.a[1]=pnt[j]; j++; b.a[2]=pnt[j]; j++; b.a[3]=pnt[j]; j++; b.a[4]=1.0; // W=1 // transform a=rep*a; b=rep*b; // perspective: camera projection plane u=0, focus at (0,0,0,-focal_length) if (a[3]>=0.0) a*=divide(focal_length,a[3]+focal_length); else a.zero(); if (b[3]>=0.0) b*=divide(focal_length,b[3]+focal_length); else b.zero(); // render glVertex3dv(a.a); // use just x,y,z glVertex3dv(b.a); // use just x,y,z } glEnd(); } //--------------------------------------------------------------------------- #endif //---------------------------------------------------------------------------

Y vista previa:

[Editar2] malla sólida y sección transversal

así que cambié la arquitectura bastante. reper4D matriz de transformada reper4D 4D 5x5 ( reper4D ) a un archivo separado y agregué colores y definición de malla mediante 4x símplex (4 puntos tetraedros laterales). El corte es simplemente calcular la intersección (como se describe arriba) de hiperplano simplex y de corte que resulta en 3 puntos (triángulo), 4 puntos (tetraedro) o 0 puntos. Que se puede renderizar fácilmente (no es necesario analizar las conexiones entre los bordes). Por cierto. Creo que así es como funciona Miegakure . Aquí el código actualizado:

//--------------------------------------------------------------------------- //--- Mesh 4D: ver 1.000 ---------------------------------------------------- //--------------------------------------------------------------------------- #ifndef _mesh4D_h #define _mesh4D_h //--------------------------------------------------------------------------- #include "list.h" #include "reper4D.h" //--------------------------------------------------------------------------- class mesh4D { public: reper4D rep; // 4D uniform 5x5 transform matrix List<double> pnt; // 4D point list (x,y,z,w) List<int> lin; // 4D wireframe (i0,i1) List<int> fac; // 4D simplexes (i0,i1,i2,i3) List<DWORD> col; // simplex colors (RGB) mesh4D() {} mesh4D(mesh4D& a) { *this=a; } ~mesh4D() {} mesh4D* operator = (const mesh4D *a) { *this=*a; return this; } //mesh4D* operator = (const mesh4D &a) { ...copy... return this; } void set_hypercube(double a); void draw_cut(double w_cut); // render cross section by w=w_cut hyperplane void draw (double focal_length=-1.0,double w_near=-1.0); // render mesh (focal_length<0) -> no perspective, else perspective view in W+ direction void draw_wireframe(double focal_length=-1.0,double w_near=-1.0); // render wireframe (focal_length<0) -> no perspective, else perspective view in W+ direction }; //--------------------------------------------------------------------------- void mesh4D::set_hypercube(double a) { const double tab_pnt[]= { -a, -a, -a, -a, +a, -a, -a, -a, -a, +a, -a, -a, +a, +a, -a, -a, -a, -a, +a, -a, +a, -a, +a, -a, -a, +a, +a, -a, +a, +a, +a, -a, -a, -a, -a, +a, +a, -a, -a, +a, -a, +a, -a, +a, +a, +a, -a, +a, -a, -a, +a, +a, +a, -a, +a, +a, -a, +a, +a, +a, +a, +a, +a, +a, }; const int tab_lin[]= { // A0 0+0, 0+1, 0+1, 0+3, 0+3, 0+2, 0+2, 0+0, // A1 4+0, 4+1, 4+1, 4+3, 4+3, 4+2, 4+2, 4+0, // A=A0+A1 0+0, 4+0, 0+1, 4+1, 0+2, 4+2, 0+3, 4+3, // B0 8+0, 8+1, 8+1, 8+3, 8+3, 8+2, 8+2, 8+0, // B1 12+0, 12+1, 12+1, 12+3, 12+3, 12+2, 12+2, 12+0, // B=B0+B1 8+0, 12+0, 8+1, 12+1, 8+2, 12+2, 8+3, 12+3, // hyper cube = A+B 0+0, 8+0, 0+1, 8+1, 0+2, 8+2, 0+3, 8+3, 0+4, 8+4, 0+5, 8+5, 0+6, 8+6, 0+7, 8+7, }; // 5x simplex per cube #define _cube(a0,a1,a2,a3,a4,a5,a6,a7) a1,a2,a4,a7, a0,a1,a2,a4, a2,a4,a6,a7, a1,a2,a3,a7, a1,a4,a5,a7 // 4D hypercube = 8 cubes const int tab_fac[]= { _cube( 0, 1, 2, 3, 4, 5, 6, 7), _cube( 0, 1, 2, 3, 8, 9,10,11), _cube( 4, 5, 6, 7,12,13,14,15), _cube( 8, 9,10,11,12,13,14,15), _cube( 0, 1, 4, 5, 8, 9,12,13), _cube( 0, 2, 4, 6, 8,10,12,14), _cube( 1, 3, 5, 7, 9,11,13,15), _cube( 2, 3, 6, 7,10,11,14,15), }; #undef _cube const DWORD tab_col[]= { // BBGGRR, BBGGRR, BBGGRR, BBGGRR, BBGGRR, 0x00FF0000,0x00FF0000,0x00FF0000,0x00FF0000,0x00FF0000, 0x0000FF00,0x0000FF00,0x0000FF00,0x0000FF00,0x0000FF00, 0x000000FF,0x000000FF,0x000000FF,0x000000FF,0x000000FF, 0x0000FFFF,0x0000FFFF,0x0000FFFF,0x0000FFFF,0x0000FFFF, 0x00FF00FF,0x00FF00FF,0x00FF00FF,0x00FF00FF,0x00FF00FF, 0x00FFFF00,0x00FFFF00,0x00FFFF00,0x00FFFF00,0x00FFFF00, 0x00FFFFFF,0x00FFFFFF,0x00FFFFFF,0x00FFFFFF,0x00FFFFFF, 0x004080FF,0x004080FF,0x004080FF,0x004080FF,0x004080FF, }; int i,n; vector<4> p; rep.reset(); pnt.num=0; for (i=0,n=sizeof(tab_pnt)/sizeof(tab_pnt[0]);i<n;i++) pnt.add(tab_pnt[i]); lin.num=0; for (i=0,n=sizeof(tab_lin)/sizeof(tab_lin[0]);i<n;i++) lin.add(tab_lin[i]); fac.num=0; for (i=0,n=sizeof(tab_fac)/sizeof(tab_fac[0]);i<n;i++) fac.add(tab_fac[i]); col.num=0; for (i=0,n=sizeof(tab_col)/sizeof(tab_col[0]);i<n;i++) col.add(tab_col[i]); } //--------------------------------------------------------------------------- void mesh4D::draw_cut(double w_cut) { const double _zero=1e-6; const int edge2[]={0,1,0,2,0,3,1,2,2,3,3,1,-1}; // simplex wireframe i0,i1 const int edge3[]={0,1,2,3,0,1,3,1,2,3,2,0,-1}; // simplex triangles i0,i1,i2 int e,i,j,k,k0,k1,k2,inside[4]; DWORD rgb; vector<4> p[4],q[4]; vector<3> xyz[4],nor,a,b; for (i=0;i<fac.num;) { rgb=col[i>>2]; // extrac points (x,y,z,w) for (k=0;k<4;k++) { j=fac[i]*4; i++; p[k].a[0]=pnt[j]; j++; p[k].a[1]=pnt[j]; j++; p[k].a[2]=pnt[j]; j++; p[k].a[3]=pnt[j]; j++; // transform rep.l2g(p[k],p[k]); inside[k]=1; } // process edge2 and compute cross section cut intersection points for (e=0,k=0;edge2[e]>=0;) { k0=edge2[e]; e++; k1=edge2[e]; e++; // fully inside if (fabs(p[k0][3]-w_cut)+fabs(p[k1][3]-w_cut)<=_zero) { if ((k<4)&&(inside[k0])){ q[k]=p[k0]; k++; inside[k0]=0; } if ((k<4)&&(inside[k1])){ q[k]=p[k1]; k++; inside[k1]=0; } continue; } // no intersection if (((p[k0][3]> w_cut)&&(p[k1][3]> w_cut))||((p[k0][3]< w_cut)&&(p[k1][3]< w_cut))) continue; // 1 intersection if (k<4) { q[k]=p[k1]-p[k0]; q[k]*=divide(w_cut-p[k0][3],p[k1][3]-p[k0][3]); q[k]+=p[k0]; q[k][3]=w_cut; k++; continue; } } // 4D -> 3D vector for (k0=0;k0<k;k0++) for (k1=0;k1<3;k1++) xyz[k0][k1]=q[k0][k1]; // render triangle if (k==3) { // normal a=xyz[1]-xyz[0]; b=xyz[2]-xyz[1]; nor.cross(a,b); nor.unit(); // render glBegin(GL_TRIANGLES); glNormal3dv(nor.a); glColor4ubv((BYTE*)(&rgb)); glVertex3dv(xyz[0].a); glVertex3dv(xyz[1].a); glVertex3dv(xyz[2].a); glEnd(); } // render simplex if (k==4) for (e=0;edge3[e]>=0;) { k0=edge3[e]; e++; k1=edge3[e]; e++; k2=edge3[e]; e++; // normal a=xyz[k1]-xyz[k0]; b=xyz[k2]-xyz[k1]; nor.cross(a,b); nor.unit(); // render glBegin(GL_TRIANGLES); glNormal3dv(nor.a); glColor4ubv((BYTE*)(&rgb)); glVertex3dv(xyz[k0].a); glVertex3dv(xyz[k1].a); glVertex3dv(xyz[k2].a); glEnd(); } } } //--------------------------------------------------------------------------- void mesh4D::draw(double focal_length,double w_near) { const int edge3[]={0,1,2,3,0,1,3,1,2,3,2,0,-1}; // simplex triangles i0,i1,i2 int i,j,k,k0,k1,k2; DWORD rgb; vector<4> p; vector<3> xyz[4],nor,a,b; // 4D simplexes glColor3f(0.3,0.3,0.3); for (i=0;i<fac.num;) { rgb=col[i>>2]; // extrac points (x,y,z,w) for (k=0;k<4;k++) { j=fac[i]*4; i++; p[0]=pnt[j]; j++; p[1]=pnt[j]; j++; p[2]=pnt[j]; j++; p[3]=pnt[j]; j++; // transform rep.l2g(p,p); // perspective projection if (focal_length>0.0) { p[3]-=w_near; if (p[3]>=0.0) p*=divide(focal_length,p[3]+focal_length); else p.zero(); } // 4D -> 3D vector xyz[k].ld(p[0],p[1],p[2]); } // render simplex for (k=0;edge3[k]>=0;) { k0=edge3[k]; k++; k1=edge3[k]; k++; k2=edge3[k]; k++; // normal a=xyz[k1]-xyz[k0]; b=xyz[k2]-xyz[k1]; nor.cross(a,b); nor.unit(); // render // glBegin(GL_LINE_LOOP); glBegin(GL_TRIANGLES); glNormal3dv(nor.a); glColor4ubv((BYTE*)(&rgb)); glVertex3dv(xyz[k0].a); glVertex3dv(xyz[k1].a); glVertex3dv(xyz[k2].a); glEnd(); } } } //--------------------------------------------------------------------------- void mesh4D::draw_wireframe(double focal_length,double w_near) { int i,j,k; vector<4> p[4]; // 4D wireframe glColor3f(1.0,1.0,1.0); glBegin(GL_LINES); for (i=0;i<lin.num;) { // extrac points (x,y,z,w) for (k=0;k<2;k++) { j=lin[i]*4; i++; p[k].a[0]=pnt[j]; j++; p[k].a[1]=pnt[j]; j++; p[k].a[2]=pnt[j]; j++; p[k].a[3]=pnt[j]; j++; // transform rep.l2g(p[k],p[k]); // perspective projection if (focal_length>0.0) { p[k][3]-=w_near; if (p[k][3]>=0.0) p[k]*=divide(focal_length,p[k][3]+focal_length); else p[k].zero(); } // render glVertex3dv(p[k].a); // use just x,y,z } } glEnd(); } //--------------------------------------------------------------------------- #endif //---------------------------------------------------------------------------

Y la vista previa para el procesamiento de la sección transversal:

La peor parte fue definir el hipercubo como un conjunto de símiles ...