Stratos: Punto de Encuentro de Desarrolladores

¡Bienvenido a Stratos!

Acceder

Foros





Checkear Cubos con Frustum

Iniciado por CoLSoN2, 18 de Noviembre de 2002, 10:55:58 PM

« anterior - próximo »

CoLSoN2

                                tengo esta función que checkea si algún vertice del box está en el frustum:


bool W3C_GFX_Frustum::CheckCube(float XCenter, float YCenter,

       float ZCenter, float Size)

{

// nos aseguramos que al menos 1 punto esté en el frustum

for (short i=0;i<6;i++)

{



 if(D3DXPlaneDotCoord(&m_Planes[i], &D3DXVECTOR3(XCenter, YCenter, ZCenter)) >= 0.0f)

  continue;

 if(D3DXPlaneDotCoord(&m_Planes[i], &D3DXVECTOR3(XCenter+Size, YCenter, ZCenter)) >= 0.0f)

  continue;

 if(D3DXPlaneDotCoord(&m_Planes[i], &D3DXVECTOR3(XCenter, YCenter+Size, ZCenter)) >= 0.0f)

  continue;

 if(D3DXPlaneDotCoord(&m_Planes[i], &D3DXVECTOR3(XCenter+Size, YCenter+Size, ZCenter)) >= 0.0f)

  continue;

 if(D3DXPlaneDotCoord(&m_Planes[i], &D3DXVECTOR3(XCenter, YCenter, ZCenter+Size)) >= 0.0f)

  continue;

 if(D3DXPlaneDotCoord(&m_Planes[i], &D3DXVECTOR3(XCenter+Size, YCenter, ZCenter+Size)) >= 0.0f)

  continue;

 if(D3DXPlaneDotCoord(&m_Planes[i], &D3DXVECTOR3(XCenter, YCenter+Size, ZCenter+Size)) >= 0.0f)

  continue;

 if(D3DXPlaneDotCoord(&m_Planes[i], &D3DXVECTOR3(XCenter+Size, YCenter+Size, ZCenter+Size)) >= 0.0f)

  continue;

 if(D3DXPlaneDotCoord(&m_Planes[i], &D3DXVECTOR3(XCenter+Size/2, YCenter+Size/2, ZCenter+Size/2)) >= 0.0f)

  continue;  

 return false;

}

return true;

}



para aclararos un poco, XCenter,YCenter y ZCenter es igual a XPos, YPos, ZPos en el dibujo, y width = Size:



y con esto, al acercarme mucho al terreno , algunos nodos no se renderizan:



(esto es solo en algunas posiciones de la camara). Aver si podriais saber xq :                                
Manuel F. Lara
Descargar juegos indie  - blog sobre juegos indie y casual
El Desarrollo Personal.com  - blog sobre productividad, motivación y espíritu emprendedor

Haddd

                                Quizás no sea un problema de frustum, quizás sea un problema de clipping. Prueba a reducir el plano Near.                                

Repoker

                                Eso mismo le aconsejé yo.. en mi opinion el plano NEAR está demasiado alejado de la camara, y por eso los poligonos esos de delante quedan omitidos al renderizar contra el frustrum :P

Si no es eso.. pues no se, la verdad.                                

Sante05

                                Por la imagen, yo diria que Hadd y Repoker tienen razón, y se trata realmente de un problema de clipping. Sin embargo, y espero que algún "experto" responda a esto, ¿es ese sistema se chequeo correcto?
Me refiero a que pueden darse casos en los que el frustum intersecta con el cubo sin que ninguno de los puntos del cubo esté dentro del frustum. En ese caso ese algoritmo fallaría, cuando realmente si se está produciendo una intersección.

Otro sistema para reducir ese fallo que conozco es el siguiente:
Si no hay ningún vértice del cubo en el interior del frustum, aun asi puede haber interseccion, asi que comprobamos si TODOS los vértices del cubo están detrás de alguno de los planos que forman el frustum. Si es así, ya estamos seguros de que el cubo nunca intersecta con el frustum.

Esto no lo he probado en la práctica, así que no sé si es demasiado lento (supongo que sí, que los expertos opinen), pero aquí lo tienes por si te ayuda:



BOOL cFrustum::CheckCube(float fCenterX, float fCenterY, float fCenterZ, float fSize){



char i=0;



//Tabla de resultados

BOOL bResults[6][8];



//Comprueba cada vertice con cada plano

for (i=0; i<6; i++){



 if(D3DXPlaneDotCoord(&d_Plane[i], &D3DXVECTOR3(fCenterX - fSize, fCenterY - fSize,

  fCenterZ - fSize)) < 0.0f){

  bResults[i][0] = FALSE;

 }else{

  bResults[i][0] = TRUE;

 }



 if(D3DXPlaneDotCoord(&d_Plane[i], &D3DXVECTOR3(fCenterX + fSize, fCenterY - fSize,

  fCenterZ - fSize)) < 0.0f){

  bResults[i][1] = FALSE;

 }else{

  bResults[i][1] = TRUE;

 }



 if(D3DXPlaneDotCoord(&d_Plane[i], &D3DXVECTOR3(fCenterX - fSize, fCenterY + fSize,

  fCenterZ - fSize)) < 0.0f){

  bResults[i][2] = FALSE;

 }else{

  bResults[i][2] = TRUE;

 }



 if(D3DXPlaneDotCoord(&d_Plane[i], &D3DXVECTOR3(fCenterX + fSize, fCenterY + fSize,

  fCenterZ - fSize)) < 0.0f){

  bResults[i][3] = FALSE;

 }else{

  bResults[i][3] = TRUE;

 }



 if(D3DXPlaneDotCoord(&d_Plane[i], &D3DXVECTOR3(fCenterX - fSize, fCenterY - fSize,

  fCenterZ + fSize)) < 0.0f){

  bResults[i][4] = FALSE;

 }else{

  bResults[i][4] = TRUE;

 }



 if(D3DXPlaneDotCoord(&d_Plane[i], &D3DXVECTOR3(fCenterX + fSize, fCenterY - fSize,

  fCenterZ + fSize)) < 0.0f){

  bResults[i][5] = FALSE;

 }else{

  bResults[i][5] = TRUE;

 }



 if(D3DXPlaneDotCoord(&d_Plane[i], &D3DXVECTOR3(fCenterX - fSize, fCenterY + fSize,

  fCenterZ + fSize)) < 0.0f){

  bResults[i][6] = FALSE;

 }else{

  bResults[i][6] = TRUE;

 }



 if(D3DXPlaneDotCoord(&d_Plane[i], &D3DXVECTOR3(fCenterX + fSize, fCenterY + fSize,

  fCenterZ + fSize)) < 0.0f){

  bResults[i][7] = FALSE;

 }else{

  bResults[i][7] = TRUE;

 }



}





//Si un vertice esta delante de todos los planos, el cubo intersecta con el frustum

for (i=0; i<8; i++){

 if ((bResults[0][i] == TRUE)&&(bResults[1][i] == TRUE)&&(bResults[2][i] == TRUE)&&

  (bResults[3][i] == TRUE)&&(bResults[4][i] == TRUE)&&(bResults[5][i] == TRUE))

  return TRUE;

}



//Si no hay ningun vertice dentro del frustum, aun asi el cubo puede intersectar. Para

//descartarlo, comprobamos si todos los vertices estan DETRAS de un plano. En caso

//afirmativo, el cubo no intersecta. Este metodo no es fiable al 100%, pero los resultados

//son validos en la mayoria de ocasiones

for(i=0; i<6; i++){

 if ((bResults[i][0] == FALSE) && (bResults[i][1] == FALSE) && (bResults[i][2] == FALSE) &&

  (bResults[i][3] == FALSE) && (bResults[i][4] == FALSE) && (bResults[i][5] == FALSE) &&

  (bResults[i][6] == FALSE) && (bResults[i][7] == FALSE))

  return FALSE;

}



return TRUE;

}



También estoy pensando si sería suficiente con hacer la última comprobación en la mayoría de los casos, aumentando así la velocidad y sin necesidad de esa tabla de resultados. Espero vuestras opiniones.                                

CoLSoN2

                                los planos los calculo asi:

dev->GetTransform(D3DTS_VIEW,&matview);

D3DXMatrixMultiply(&Matrix,&matview,&matproj);



 // calculamos los planos

m_Planes[0].a = Matrix._14 + Matrix._13; // plano cercano

m_Planes[0].b = Matrix._24 + Matrix._23;

m_Planes[0].c = Matrix._34 + Matrix._33;

m_Planes[0].d = Matrix._44 + Matrix._43;

D3DXPlaneNormalize(&m_Planes[0], &m_Planes[0]);



m_Planes[1].a = Matrix._14 - Matrix._13; // plano lejano

m_Planes[1].b = Matrix._24 - Matrix._23;

m_Planes[1].c = Matrix._34 - Matrix._33;

m_Planes[1].d = Matrix._44 - Matrix._43;

D3DXPlaneNormalize(&m_Planes[1], &m_Planes[1]);



m_Planes[2].a = Matrix._14 + Matrix._11; // plano izquierda

m_Planes[2].b = Matrix._24 + Matrix._21;

m_Planes[2].c = Matrix._34 + Matrix._31;

m_Planes[2].d = Matrix._44 + Matrix._41;

D3DXPlaneNormalize(&m_Planes[2], &m_Planes[2]);



m_Planes[3].a = Matrix._14 - Matrix._11; // plano derecha

m_Planes[3].b = Matrix._24 - Matrix._21;

m_Planes[3].c = Matrix._34 - Matrix._31;

m_Planes[3].d = Matrix._44 - Matrix._41;

D3DXPlaneNormalize(&m_Planes[3], &m_Planes[3]);



m_Planes[4].a = Matrix._14 - Matrix._12; // plano de arriba

m_Planes[4].b = Matrix._24 - Matrix._22;

m_Planes[4].c = Matrix._34 - Matrix._32;

m_Planes[4].d = Matrix._44 - Matrix._42;

D3DXPlaneNormalize(&m_Planes[4], &m_Planes[4]);



m_Planes[5].a = Matrix._14 + Matrix._12; // plano de abajo

m_Planes[5].b = Matrix._24 + Matrix._22;

m_Planes[5].c = Matrix._34 + Matrix._32;

m_Planes[5].d = Matrix._44 + Matrix._42;

D3DXPlaneNormalize(&m_Planes[5], &m_Planes[5]);


kreo k es el metodo estandar :
el parametro NEAR de la matriz de proyeccion, lo tengo en 1.0 , pero aunke lo ponga en 0.00001 sigue aciendo lo mismo                                
Manuel F. Lara
Descargar juegos indie  - blog sobre juegos indie y casual
El Desarrollo Personal.com  - blog sobre productividad, motivación y espíritu emprendedor

MChiz

                                Hola!
Esta es la funcion que yo utilizo. Tan solo mira el vertice que toca, con cada plano del frustum. Eso si, yo defino una AABB, y la formo con tan solo 2 vertices. Espero que sea de ayuda:

bool Frustum::isVisible( const AABBox &box ) const {
   const Vector3D &point0 = box.v[ 0 ],
               &point1 = box.v[ 1 ];

   for( int i = 0 ; i < 6 ; ++i ) {
      const Plane &plane = _plane[ i ];
      const Vector3D &normal = plane.normal;

      if( ( ( normal.x < 0.0f ) ? point0.x : point1.x ) * normal.x +
         ( ( normal.y < 0.0f ) ? point0.y : point1.y ) * normal.y +
         ( ( normal.z < 0.0f ) ? point0.z : point1.z ) * normal.z + plane.d  <= 0.0f )
         return false;
   }
   
   return true;
}

Un saludo!

PD: Como se mete codigo aqui? :b                                

CoLSoN2

                                nada nada, ya está , no era problema de eso parece..

lo de codigo , arriba mientras escribes el mensaje ai unos botones, uno pone CODE. Le das 1 vez, pasteas el codigo, y le das otra vez.                                
Manuel F. Lara
Descargar juegos indie  - blog sobre juegos indie y casual
El Desarrollo Personal.com  - blog sobre productividad, motivación y espíritu emprendedor

MChiz

                                Gracias :b
Un saludo!                                






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.