Beispiel #1
0
        /// <summary>
        /// Clasifica un punto respecto de un Cuerpo Convexo de N caras.
        /// Puede devolver OUTSIDE o INSIDE (si es coincidente se considera como INSIDE).
        /// Los planos del Cuerpo Convexo deben apuntar hacia adentro.
        /// </summary>
        /// <param name="q">Punto a clasificar</param>
        /// <param name="polyhedron">Cuerpo Convexo</param>
        /// <returns>Resultado de la clasificación</returns>
        public static ConvexPolyhedronResult classifyPointConvexPolyhedron(Vector3 q, TgcConvexPolyhedron polyhedron)
        {
            bool             fistTime = true;
            PointPlaneResult lastC    = PointPlaneResult.BEHIND;
            PointPlaneResult c;

            for (int i = 0; i < polyhedron.Planes.Length; i++)
            {
                c = TgcCollisionUtils.classifyPointPlane(q, polyhedron.Planes[i]);

                if (c == PointPlaneResult.COINCIDENT)
                {
                    continue;
                }

                //guardar clasif para primera vez
                if (fistTime)
                {
                    fistTime = false;
                    lastC    = c;
                }


                //comparar con ultima clasif
                if (c != lastC)
                {
                    //basta con que haya una distinta para que este Afuera
                    return(ConvexPolyhedronResult.OUTSIDE);
                }
            }

            //Si todos dieron el mismo resultado, entonces esta adentro
            return(ConvexPolyhedronResult.INSIDE);
        }
        /// <summary>
        /// Picking sobre un triangulo
        /// </summary>
        public bool pickTriangle(out TgcTriangle triangle, out int triangleIndex)
        {
            pickingRay.updateRay();
            Vector3 segmentA = pickingRay.Ray.Origin;
            Vector3 segmentB = segmentA + Vector3.Scale(pickingRay.Ray.Direction, 10000f);
            float   minDist  = float.MaxValue;

            triangle      = null;
            triangleIndex = -1;

            //Buscar la menor colision rayo-triangulo
            for (int i = 0; i < triangles.Count; i++)
            {
                TgcTriangle tri = triangles[i];

                float   t;
                Vector3 uvw;
                Vector3 col;
                if (TgcCollisionUtils.intersectLineTriangle(segmentA, segmentB, tri.A, tri.B, tri.C, out uvw, out t, out col))
                {
                    float dist = Vector3.Length(col - segmentA);
                    if (dist < minDist)
                    {
                        minDist       = dist;
                        triangle      = tri;
                        triangleIndex = i;
                    }
                }
            }

            return(triangle != null);
        }
Beispiel #3
0
        /// <summary>
        /// Indica si un BoundingSphere colisiona con un BoundingBox.
        /// </summary>
        /// <param name="sphere">BoundingSphere</param>
        /// <param name="aabb">BoundingBox</param>
        /// <returns>True si hay colisión</returns>
        public static bool testSphereAABB(TgcBoundingSphere sphere, TgcBoundingBox aabb)
        {
            //Compute squared distance between sphere center and AABB
            float sqDist = TgcCollisionUtils.sqDistPointAABB(sphere.Center, aabb);

            //Sphere and AABB intersect if the (squared) distance
            //between them is less than the (squared) sphere radius
            return(sqDist <= sphere.Radius * sphere.Radius);
        }
Beispiel #4
0
 /// <summary>
 /// Indica si un punto se encuentra dentro de un Cuerpo Convexo.
 /// Los planos del Cuerpo Convexo deben apuntar hacia adentro.
 /// Es más ágil que llamar a classifyPointConvexPolyhedron()
 /// </summary>
 /// <param name="q">Punto a clasificar</param>
 /// <param name="polyhedron">Cuerpo Convexo</param>
 /// <returns>True si se encuentra adentro.</returns>
 public static bool testPointConvexPolyhedron(Vector3 q, TgcConvexPolyhedron polyhedron)
 {
     for (int i = 0; i < polyhedron.Planes.Length; i++)
     {
         //Si el punto está detrás de algún plano, entonces está afuera
         if (TgcCollisionUtils.classifyPointPlane(q, polyhedron.Planes[i]) == PointPlaneResult.BEHIND)
         {
             return(false);
         }
     }
     //Si está delante de todos los planos, entonces está adentro.
     return(true);
 }
Beispiel #5
0
        /// <summary>
        /// Indica si un Ray colisiona con un Plano.
        /// Tanto la normal del plano como la dirección del Ray se asumen normalizados.
        /// </summary>
        /// <param name="ray">Ray a testear</param>
        /// <param name="plane">Plano a testear</param>
        /// <param name="t">Instante de colisión</param>
        /// <param name="q">Punto de colisión con el plano</param>
        /// <returns>True si hubo colisión</returns>
        public static bool intersectRayPlane(TgcRay ray, Plane plane, out float t, out Vector3 q)
        {
            Vector3 planeNormal = TgcCollisionUtils.getPlaneNormal(plane);
            float   numer       = plane.Dot(ray.Origin);
            float   denom       = Vector3.Dot(planeNormal, ray.Direction);

            t = -numer / denom;

            if (t > 0.0f)
            {
                q = ray.Origin + ray.Direction * t;
                return(true);
            }

            q = Vector3.Empty;
            return(false);
        }
Beispiel #6
0
        /// <summary>
        /// Indica si un segmento de recta colisiona con un BoundingSphere.
        /// Si el resultado es True se carga el punto de colision (q) y la distancia de colision en el t.
        /// La dirección del Ray debe estar normalizada.
        /// </summary>
        /// <param name="p0">Punto inicial del segmento</param>
        /// <param name="p1">Punto final del segmento</param>
        /// <param name="s">BoundingSphere</param>
        /// <param name="t">Distancia de colision del segmento</param>
        /// <param name="q">Punto de colision</param>
        /// <returns>True si hay colision</returns>
        public static bool intersectSegmentSphere(Vector3 p0, Vector3 p1, TgcBoundingSphere sphere, out float t, out Vector3 q)
        {
            Vector3 segmentDir = p1 - p0;
            TgcRay  ray        = new TgcRay(p0, segmentDir);

            if (TgcCollisionUtils.intersectRaySphere(ray, sphere, out t, out q))
            {
                float   segmentLengthSq   = segmentDir.LengthSq();
                Vector3 collisionDiff     = q - p0;
                float   collisionLengthSq = collisionDiff.LengthSq();
                if (collisionLengthSq <= segmentLengthSq)
                {
                    return(true);
                }
            }

            return(false);
        }
Beispiel #7
0
        /// <summary>
        /// Dado el punto p, devuelve el punto del contorno del BoundingBox mas próximo a p.
        /// </summary>
        /// <param name="p">Punto a testear</param>
        /// <param name="aabb">BoundingBox a testear</param>
        /// <returns>Punto mas cercano a p del BoundingBox</returns>
        public static Vector3 closestPointAABB(Vector3 p, TgcBoundingBox aabb)
        {
            float[] aabbMin = toArray(aabb.PMin);
            float[] aabbMax = toArray(aabb.PMax);
            float[] pArray  = toArray(p);
            float[] q       = new float[3];

            // For each coordinate axis, if the point coordinate value is
            // outside box, clamp it to the box, else keep it as is
            for (int i = 0; i < 3; i++)
            {
                float v = pArray[i];
                if (v < aabbMin[i])
                {
                    v = aabbMin[i];                 // v = max(v, b.min[i])
                }
                if (v > aabbMax[i])
                {
                    v = aabbMax[i];                 // v = min(v, b.max[i])
                }
                q[i] = v;
            }
            return(TgcCollisionUtils.toVector3(q));
        }