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 :
Quizás no sea un problema de frustum, quizás sea un problema de clipping. Prueba a reducir el plano Near.
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.
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.
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
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
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.
Gracias :b
Un saludo!