Detección de Colisiones de Objetos 3D en WPF

Window Presentation Foundation proporciona la posibilidad de trabajar con objetos 3D dentro de una aplicación. Ello hace que se puedan desarrollar aplicaciones muy ricas utilizando modelos en 3D.

Si la aplicación trabaja con objetos 3D que dan la posibilidad de desplazarse a lo largo de la pantalla puede ser interesante detectar colisiones entre ellos. A la hora de detectar colisiones entre objetos en una aplicación podemos optar por varias estrategias. Por ejemplo, dentro de XNA podemos encontrar: bounding box, bounding sphere y bounding frustrum. El Framework de XNA ya proporciona métodos para facilitar las colisiones entre los objetos.

  • Bounding box: Esta técnica se utiliza cuando el objeto se adapta a una forma rectangular. Lo que hace es envolver el modelo en una caja. Si el modelo no es totalmente rectangular puede que se den falsas colisiones.
  • bounding sphere: Es técnica envuelve el objeto con una esfera. Se utiliza cuando el modelo se adapta mejor a la forma de una esfera.
  • bounding frustrum: Esta técnica no es usada realmente para controlar las colisiones. Ya que controla el espació visto por la cámara. Así puede determinar si lo que se está viendo es un objeto o no y por consiguiente decidir si dibujarlo o no.

La técnica más sencilla de desarrollar con WPF es la de bounding box. El Framework proporciona los métodos necesarios para ello.

Dentro de un GeometryModel3D podemos encontrar la propiedad Bound. Esta propiedad devuelve un objeto del tipo Rect3D. Este objeto representa el rectángulo que envuelve al modelo. Además la propia clase Rect3D cuenta con un método, IntersectsWith. Este método recibe como parámetros otro objeto Rect3D y verifica si entre ambos rectángulos hay una intersección. Si hay una intersección, devuelve True. Eso quiere decir que los objetos están colisionando.

Rect3D rectModel1 = ((GeometryModel3D)mv3D.Content).Bounds;
Rect3D rectModel2 = ((GeometryModel3D)mv3D.Content).Bounds;

if (rectModel1.IntersectsWith(rectModel2))
{
    //Se ha producido una colisión.
}
else
{
    //No hay colision entre ambos modelos.
}

Si sobre el modelo se ha hecho alguna transformación, habrá que tenerlo en cuenta a la hora de obtener el rectángulo que envuelve al modelo. De tal manera, que también esa transformación deberá ser aplicada al Rect3D resultante. Para ello existe el método TransformBounds que aplica las transformaciones a un Rect3D.

 

ModelVisual3D mv3D = new ModelVisual3D();
ModelVisual3D mv3D2 = new ModelVisual3D();

mv3D.Content.Transform = new ScaleTransform3D(0.2, 0.2, 0.2);
mv3D2.Content.Transform = new ScaleTransform3D(0.2, 0.2, 0.2);

Rect3D rectModel1 = mv3D.Transform.TransformBounds(mv3D.Content.Bounds);
Rect3D rectModel2 = mv3D2.Transform.TransformBounds(mv3D2.Content.Bounds);

if (rectModel1.IntersectsWith(rectModel2))
{
    //Se ha producido una colisión.
}
else
{
    //No hay colision entre ambos modelos.
}

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *