Foros - Stratos

Programadores => Programación gráfica => Mensaje iniciado por: CoLSoN2 en 18 de Noviembre de 2002, 10:55:58 PM

Título: Checkear Cubos con Frustum
Publicado por: CoLSoN2 en 18 de Noviembre de 2002, 10:55:58 PM
                                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:

(http://www.warcraft3es.com/sad.GIF)

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

(http://www.warcraft3es.com/sad2.GIF)

(esto es solo en algunas posiciones de la camara). Aver si podriais saber xq :                                
Título: Checkear Cubos con Frustum
Publicado por: Haddd en 19 de Noviembre de 2002, 12:08:24 AM
                                Quizás no sea un problema de frustum, quizás sea un problema de clipping. Prueba a reducir el plano Near.                                
Título: Checkear Cubos con Frustum
Publicado por: Repoker en 19 de Noviembre de 2002, 05:19:45 PM
                                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.                                
Título: Checkear Cubos con Frustum
Publicado por: Sante05 en 19 de Noviembre de 2002, 06:42:43 PM
                                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.                                
Título: hmm
Publicado por: CoLSoN2 en 19 de Noviembre de 2002, 08:47:44 PM
                                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                                
Título: Checkear Cubos con Frustum
Publicado por: MChiz en 19 de Noviembre de 2002, 11:05:18 PM
                                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                                
Título: hm
Publicado por: CoLSoN2 en 19 de Noviembre de 2002, 11:59:00 PM
                                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.                                
Título: Checkear Cubos con Frustum
Publicado por: MChiz en 20 de Noviembre de 2002, 11:06:42 AM
                                Gracias :b
Un saludo!