public bool colisionConPisoDesnivelado(TgcMesh pisoDesnivelado)
        {
            TgcBoundingSphere esferaAuxiliar = new TgcBoundingSphere(esferaPersonaje.Center, esferaPersonaje.Radius);

            esferaAuxiliar.moveCenter(new TGCVector3(0f, -RADIO_ESFERA, 0f));
            return(TgcCollisionUtils.testSphereAABB(esferaAuxiliar, pisoDesnivelado.BoundingBox));
        }
        public bool colisionaPorArribaDe(TgcMesh mesh)
        {
            TgcBoundingSphere esferaAuxiliar = new TgcBoundingSphere(esferaPersonaje.Center, esferaPersonaje.Radius);

            esferaAuxiliar.moveCenter(new TGCVector3(0f, -RADIO_ESFERA, 0f));
            return(TgcCollisionUtils.testSphereAABB(esferaAuxiliar, mesh.BoundingBox));
        }
 public TGCVector3 manageColisionEsferaOBB(TgcBoundingSphere esfera, TGCVector3 movementVector, TgcBoundingOrientedBox OBB)
 {
     //Si esta parador Arriba de la caja
     if (colisionaEsferaOBB(esfera, OBB) && esfera.Center.Y > OBB.Center.Y + OBB.Extents.Y)
     {
         esfera.moveCenter(movementVector);
         return(movementVector);
     }//Si choca por debajo a la plataforma
     else if (colisionaEsferaOBB(esfera, OBB) && esfera.Center.Y < OBB.Center.Y - OBB.Extents.Y)
     {
         movementVector.Y = -EPSILON;
         esfera.moveCenter(movementVector);
         return(movementVector);
     }
     else //Si la choca por los costados
     {
         movementVector.Y = 25 * EPSILON;
         esfera.moveCenter(-movementVector);
         return(-movementVector);
     }
 }
Beispiel #4
0
        public void seguirASlider(Vector3 posJugador, float elapsedTime, float velocidad)
        {
            Vector3 direccion = posJugador - mesh.Position;

            direccion.Normalize();
            direccion.Y = 0;
            mesh.rotateY(((float)Math.Atan2(direccion.X, direccion.Z) - mesh.Rotation.Y - Geometry.DegreeToRadian(180f)));
            bounding.rotateY((float)Math.Atan2(direccion.X, direccion.Z) - mesh.Rotation.Y - Geometry.DegreeToRadian(180f));
            direccion *= velocidad;
            TgcBoundingSphere     characterSphere = new TgcBoundingSphere(mesh.BoundingBox.calculateBoxCenter(), 10f);
            List <TgcBoundingBox> lista           = new List <TgcBoundingBox>();

            foreach (TgcMesh meshito in escena.Meshes)
            {
                lista.Add(meshito.BoundingBox);
            }
            Vector3 realMovement = slidin.moveCharacter(characterSphere, direccion, lista);

            characterSphere.moveCenter(realMovement * elapsedTime);
            mesh.move(realMovement * elapsedTime);
            mesh.Position = new Vector3(mesh.Position.X, 5.02f, mesh.Position.Z);

            bounding.move(realMovement);
        }
 //mueve al mesh y a su bounding box
 new public void move(Vector3 movimiento)
 {
     base.move(movimiento);
     boundingSphere.moveCenter(movimiento);
 }
Beispiel #6
0
        public void Update(float elapsedTime)
        {
            int     velocidadEnemigo = randomEnemigo.Next(10, 15);
            float   angulo;
            Enemigo otroEnemigo;

            Vector3 posicionPlayer = GuiController.Instance.CurrentCamera.getPosition();

            // vector con direccion al jugador
            Vector3 direccionPlayer = posicionPlayer - enemigo.Position;

            direccionPlayer.Y = 0;

            Vector3 direccionMovimiento = direccionPlayer;

            if (ColisionesAdmin.Instance.ColisionEnemigoConObjetos(this))
            {
                if (direccionColisionObjeto == vectorNulo)
                {
                    angulo  = (180 * (float)Math.Atan2(direccionMovimiento.Z, direccionMovimiento.X)) / (float)Math.PI;// +45;
                    angulo += 90;
                    direccionColisionObjeto = Rotar(angulo);
                }
            }
            else
            {
                direccionColisionObjeto = vectorNulo;

                if (this.colisionado == true)
                {
                    if (!ColisionesAdmin.Instance.ColisionEnemigoConEnemigos(this, out otroEnemigo))
                    {
                        this.colisionado         = false;
                        direccionColisionEnemigo = vectorNulo;
                    }
                    else if (direccionColisionEnemigo == vectorNulo)
                    {
                        angulo = (180 * (float)Math.Atan2(direccionMovimiento.Z, direccionMovimiento.X)) / (float)Math.PI;// +45;
                        int anguloGiro = randomEnemigo.Next(45, 90);
                        if (randomEnemigo.Next(0, 2) == 1)
                        {
                            anguloGiro *= -1;
                        }
                        angulo += anguloGiro;
                        direccionColisionEnemigo = Rotar(angulo);
                    }
                }
                else
                {
                    if (ColisionesAdmin.Instance.ColisionEnemigoConEnemigos(this, out otroEnemigo))
                    {
                        otroEnemigo.colisionado = true;
                    }

                    if (direccionRandom == vectorNulo && randomEnemigo.Next(0, 500) == 1)
                    {
                        angulo = (180 * (float)FastMath.Atan2(direccionMovimiento.Z, direccionMovimiento.X)) / (float)Math.PI;// +45;
                        int anguloGiro = 30;
                        if (randomEnemigo.Next(0, 2) == 1)
                        {
                            anguloGiro = 90;
                        }
                        angulo         += anguloGiro;
                        direccionRandom = Rotar(angulo);
                    }
                    else if (direccionRandom != vectorNulo && randomEnemigo.Next(0, 50) == 1)
                    {
                        direccionRandom = vectorNulo;
                    }
                }
            }

            if (direccionRandom != vectorNulo)
            {
                direccionMovimiento = direccionRandom;
            }
            if (direccionColisionEnemigo != vectorNulo)
            {
                direccionMovimiento = direccionColisionEnemigo;
            }
            if (direccionColisionObjeto != vectorNulo)
            {
                direccionMovimiento = direccionColisionObjeto;
            }

            direccionMovimiento.Normalize();

            // rotar al enemigo para que mire al jugador
            enemigo.rotateY((float)Math.Atan2(direccionMovimiento.X, direccionMovimiento.Z) - enemigo.Rotation.Y + FastMath.PI);

            enemigo.updateAnimation();

            enemigo.move(direccionMovimiento * velocidadEnemigo * elapsedTime);
            cabeza.moveCenter(direccionMovimiento * velocidadEnemigo * elapsedTime);
            enemigo.BoundingBox.move(direccionMovimiento * velocidadEnemigo * elapsedTime);

            emisorDeParticulas.Position = new Vector3(enemigo.Position.X, emisorDeParticulas.Position.Y, enemigo.Position.Z);
        }
        /// <summary>
        ///     Detección de colisiones recursiva
        /// </summary>
        public void doCollideWithWorld(TgcBoundingSphere characterSphere, Vector3 movementVector,
                                       List <Collider> colliders, int recursionDepth, TgcBoundingSphere movementSphere, bool sliding,
                                       float slidingMinY)
        {
            //Limitar recursividad
            if (recursionDepth > 5)
            {
                return;
            }

            //Posicion deseada
            var originalSphereCenter = characterSphere.Center;
            var nextSphereCenter     = originalSphereCenter + movementVector;

            //Buscar el punto de colision mas cercano de todos los objetos candidatos
            Collision = false;
            Vector3 q;
            float   t;
            Vector3 n;
            var     minT = float.MaxValue;

            foreach (var collider in colliders)
            {
                //Colisionar Sphere en movimiento contra Collider (cada Collider resuelve la colision)
                if (collider.intersectMovingSphere(characterSphere, movementVector, movementSphere, out t, out q, out n))
                {
                    //Quedarse con el menor instante de colision
                    if (t < minT)
                    {
                        minT                = t;
                        Collision           = true;
                        LastCollisionPoint  = q;
                        LastCollisionNormal = n;
                        lastCollider        = collider;
                    }
                }
            }

            //Si nunca hubo colisión, avanzar todo lo requerido
            if (!Collision)
            {
                //Avanzar todo lo pedido
                //lastCollisionDistance = movementVector.Length();
                characterSphere.moveCenter(movementVector);
                return;
            }

            //Solo movernos si ya no estamos muy cerca
            if (minT >= EPSILON)
            {
                //Restar un poco al instante de colision, para movernos hasta casi esa distancia
                minT -= EPSILON;
                var realMovementVector = movementVector * minT;

                //Mover el BoundingSphere
                characterSphere.moveCenter(realMovementVector);

                //Quitarle al punto de colision el EPSILON restado al movimiento, para no afectar al plano de sliding
                var v = Vector3.Normalize(realMovementVector);
                LastCollisionPoint -= v * EPSILON;
            }

            if (sliding)
            {
                //Calcular plano de Sliding, como un plano tangete al punto de colision con la esfera, apuntando hacia el centro de la esfera
                var slidePlaneOrigin = LastCollisionPoint;
                var slidePlaneNormal = characterSphere.Center - LastCollisionPoint;
                slidePlaneNormal.Normalize();
                var slidePlane = Plane.FromPointNormal(slidePlaneOrigin, slidePlaneNormal);

                //Calcular vector de movimiento para sliding, proyectando el punto de destino original sobre el plano de sliding
                var distance            = TgcCollisionUtils.distPointPlane(nextSphereCenter, slidePlane);
                var newDestinationPoint = nextSphereCenter - distance * slidePlaneNormal;
                var slideMovementVector = newDestinationPoint - LastCollisionPoint;

                //No hacer recursividad si es muy pequeño
                slideMovementVector.Scale(SlideFactor);
                if (slideMovementVector.Length() < EPSILON)
                {
                    return;
                }

                if (LastCollisionNormal.Y <= slidingMinY)
                {
                    //Recursividad para aplicar sliding
                    doCollideWithWorld(characterSphere, slideMovementVector, colliders, recursionDepth + 1,
                                       movementSphere, sliding, slidingMinY);
                }
            }
        }
        /// <summary>
        /// Detección de colisiones recursiva
        /// </summary>
        public void doCollideWithWorld(TgcBoundingSphere characterSphere, Vector3 movementVector, List <TgcBoundingBox> obstaculos, int recursionDepth)
        {
            //Limitar recursividad
            if (recursionDepth > 5)
            {
                return;
            }

            //Ver si la distancia a recorrer es para tener en cuenta
            float distanceToTravelSq = movementVector.LengthSq();

            if (distanceToTravelSq < EPSILON)
            {
                return;
            }

            //Posicion deseada
            Vector3 originalSphereCenter = characterSphere.Center;
            Vector3 nextSphereCenter     = originalSphereCenter + movementVector;

            //Buscar el punto de colision mas cercano de todos los objetos candidatos
            float   minCollisionDistSq = float.MaxValue;
            Vector3 realMovementVector = movementVector;

            TgcBoundingBox.Face collisionFace     = null;
            TgcBoundingBox      collisionObstacle = null;
            Vector3             nearestPolygonIntersectionPoint = Vector3.Empty;

            foreach (TgcBoundingBox obstaculoBB in obstaculos)
            {
                //Obtener los polígonos que conforman las 6 caras del BoundingBox
                TgcBoundingBox.Face[] bbFaces = obstaculoBB.computeFaces();

                foreach (TgcBoundingBox.Face bbFace in bbFaces)
                {
                    Vector3 pNormal = TgcCollisionUtils.getPlaneNormal(bbFace.Plane);

                    TgcRay  movementRay = new TgcRay(originalSphereCenter, movementVector);
                    float   brutePlaneDist;
                    Vector3 brutePlaneIntersectionPoint;
                    if (!TgcCollisionUtils.intersectRayPlane(movementRay, bbFace.Plane, out brutePlaneDist, out brutePlaneIntersectionPoint))
                    {
                        continue;
                    }

                    float movementRadiusLengthSq = Vector3.Multiply(movementVector, characterSphere.Radius).LengthSq();
                    if (brutePlaneDist * brutePlaneDist > movementRadiusLengthSq)
                    {
                        continue;
                    }


                    //Obtener punto de colisión en el plano, según la normal del plano
                    float   pDist;
                    Vector3 planeIntersectionPoint;
                    Vector3 sphereIntersectionPoint;
                    TgcRay  planeNormalRay = new TgcRay(originalSphereCenter, -pNormal);
                    bool    embebbed       = false;
                    bool    collisionFound = false;
                    if (TgcCollisionUtils.intersectRayPlane(planeNormalRay, bbFace.Plane, out pDist, out planeIntersectionPoint))
                    {
                        //Ver si el plano está embebido en la esfera
                        if (pDist <= characterSphere.Radius)
                        {
                            embebbed = true;

                            //TODO: REVISAR ESTO, caso embebido a analizar con más detalle
                            sphereIntersectionPoint = originalSphereCenter - pNormal * characterSphere.Radius;
                        }
                        //Esta fuera de la esfera
                        else
                        {
                            //Obtener punto de colisión del contorno de la esfera según la normal del plano
                            sphereIntersectionPoint = originalSphereCenter - Vector3.Multiply(pNormal, characterSphere.Radius);

                            //Disparar un rayo desde el contorno de la esfera hacia el plano, con el vector de movimiento
                            TgcRay sphereMovementRay = new TgcRay(sphereIntersectionPoint, movementVector);
                            if (!TgcCollisionUtils.intersectRayPlane(sphereMovementRay, bbFace.Plane, out pDist, out planeIntersectionPoint))
                            {
                                //no hay colisión
                                continue;
                            }
                        }

                        //Ver si planeIntersectionPoint pertenece al polígono
                        Vector3 newMovementVector;
                        float   newMoveDistSq;
                        Vector3 polygonIntersectionPoint;
                        if (pointInBounbingBoxFace(planeIntersectionPoint, bbFace))
                        {
                            if (embebbed)
                            {
                                //TODO: REVISAR ESTO, nunca debería pasar
                                //throw new Exception("El polígono está dentro de la esfera");
                            }

                            polygonIntersectionPoint = planeIntersectionPoint;
                            collisionFound           = true;
                        }
                        else
                        {
                            //Buscar el punto mas cercano planeIntersectionPoint que tiene el polígono real de esta cara
                            polygonIntersectionPoint = TgcCollisionUtils.closestPointRectangle3d(planeIntersectionPoint,
                                                                                                 bbFace.Extremes[0], bbFace.Extremes[1], bbFace.Extremes[2]);

                            //Revertir el vector de velocidad desde el nuevo polygonIntersectionPoint para ver donde colisiona la esfera, si es que llega
                            Vector3 reversePointSeg = polygonIntersectionPoint - movementVector;
                            if (TgcCollisionUtils.intersectSegmentSphere(polygonIntersectionPoint, reversePointSeg, characterSphere, out pDist, out sphereIntersectionPoint))
                            {
                                collisionFound = true;
                            }
                        }

                        if (collisionFound)
                        {
                            //Nuevo vector de movimiento acotado
                            newMovementVector = polygonIntersectionPoint - sphereIntersectionPoint;
                            newMoveDistSq     = newMovementVector.LengthSq();

                            if (newMoveDistSq <= distanceToTravelSq && newMoveDistSq < minCollisionDistSq)
                            {
                                minCollisionDistSq = newMoveDistSq;
                                realMovementVector = newMovementVector;
                                nearestPolygonIntersectionPoint = polygonIntersectionPoint;
                                collisionFace     = bbFace;
                                collisionObstacle = obstaculoBB;
                            }
                        }
                    }
                }
            }

            //Si nunca hubo colisión, avanzar todo lo requerido
            if (collisionFace == null)
            {
                //Avanzar hasta muy cerca
                float movementLength = movementVector.Length();
                movementVector.Multiply((movementLength - EPSILON) / movementLength);
                characterSphere.moveCenter(movementVector);
                return;
            }

            //Solo movernos si ya no estamos muy cerca
            if (minCollisionDistSq >= EPSILON)
            {
                //Mover el BoundingSphere hasta casi la nueva posición real
                float movementLength = realMovementVector.Length();
                realMovementVector.Multiply((movementLength - EPSILON) / movementLength);
                characterSphere.moveCenter(realMovementVector);
            }



            //Calcular plano de Sliding
            Vector3 slidePlaneOrigin = nearestPolygonIntersectionPoint;
            Vector3 slidePlaneNormal = characterSphere.Center - nearestPolygonIntersectionPoint;

            slidePlaneNormal.Normalize();

            Plane slidePlane = Plane.FromPointNormal(slidePlaneOrigin, slidePlaneNormal);

            //Proyectamos el punto original de destino en el plano de sliding
            TgcRay  slideRay = new TgcRay(nearestPolygonIntersectionPoint + Vector3.Multiply(movementVector, slideFactor), slidePlaneNormal);
            float   slideT;
            Vector3 slideDestinationPoint;

            if (TgcCollisionUtils.intersectRayPlane(slideRay, slidePlane, out slideT, out slideDestinationPoint))
            {
                //Nuevo vector de movimiento
                Vector3 slideMovementVector = slideDestinationPoint - nearestPolygonIntersectionPoint;

                if (slideMovementVector.LengthSq() < EPSILON)
                {
                    return;
                }

                //Recursividad para aplicar sliding
                doCollideWithWorld(characterSphere, slideMovementVector, obstaculos, recursionDepth + 1);
            }
        }
        /// <summary>
        /// Detección de colisiones recursiva
        /// </summary>
        public void doCollideWithWorld(TgcBoundingSphere characterSphere, Vector3 movementVector, List<IColisionable> obstaculos, int recursionDepth, ColisionInfo colisionInfo)
        {
            //Limitar recursividad
            if (recursionDepth > 5)
            {
                return;
            }

            //Ver si la distancia a recorrer es para tener en cuenta
            float distanceToTravelSq = movementVector.LengthSq();

            if (distanceToTravelSq < EPSILON)
            {
                return;
            }

            //Posicion deseada
            Vector3 originalSphereCenter = characterSphere.Center;
            Vector3 nextSphereCenter = originalSphereCenter + movementVector;

            //Buscar el punto de colision mas cercano de todos los objetos candidatos
            float minCollisionDistSq = float.MaxValue;
            Vector3 realMovementVector = movementVector;
            TgcBoundingAxisAlignBox.Face collisionFace = null;
            IColisionable collisionObstacle = null;
            Vector3 nearestPolygonIntersectionPoint = Vector3.Empty;
            foreach (IColisionable obstaculoBB in obstaculos)
            {
                //Obtener los polígonos que conforman las 6 caras del BoundingBox
                TgcBoundingAxisAlignBox.Face[] bbFaces = obstaculoBB.GetTgcBoundingBox().computeFaces();

                foreach (TgcBoundingAxisAlignBox.Face bbFace in bbFaces)
                {
                    Vector3 pNormal = TgcCollisionUtils.getPlaneNormal(bbFace.Plane);

                    TgcRay movementRay = new TgcRay(originalSphereCenter, movementVector);
                    float brutePlaneDist;
                    Vector3 brutePlaneIntersectionPoint;
                    if (!TgcCollisionUtils.intersectRayPlane(movementRay, bbFace.Plane, out brutePlaneDist, out brutePlaneIntersectionPoint))
                    {
                        continue;
                    }

                    float movementRadiusLengthSq = Vector3.Multiply(movementVector, characterSphere.Radius).LengthSq();
                    if (brutePlaneDist * brutePlaneDist > movementRadiusLengthSq)
                    {
                        continue;
                    }

                    //Obtener punto de colisión en el plano, según la normal del plano
                    float pDist;
                    Vector3 planeIntersectionPoint;
                    Vector3 sphereIntersectionPoint;
                    TgcRay planeNormalRay = new TgcRay(originalSphereCenter, -pNormal);
                    bool embebbed = false;
                    bool collisionFound = false;
                    if (TgcCollisionUtils.intersectRayPlane(planeNormalRay, bbFace.Plane, out pDist, out planeIntersectionPoint))
                    {
                        //Ver si el plano está embebido en la esfera
                        if (pDist <= characterSphere.Radius)
                        {
                            embebbed = true;

                            //TODO: REVISAR ESTO, caso embebido a analizar con más detalle
                            sphereIntersectionPoint = originalSphereCenter - pNormal * characterSphere.Radius;
                        }
                        //Esta fuera de la esfera
                        else
                        {
                            //Obtener punto de colisión del contorno de la esfera según la normal del plano
                            sphereIntersectionPoint = originalSphereCenter - Vector3.Multiply(pNormal, characterSphere.Radius);

                            //Disparar un rayo desde el contorno de la esfera hacia el plano, con el vector de movimiento
                            TgcRay sphereMovementRay = new TgcRay(sphereIntersectionPoint, movementVector);
                            if (!TgcCollisionUtils.intersectRayPlane(sphereMovementRay, bbFace.Plane, out pDist, out planeIntersectionPoint))
                            {
                                //no hay colisión
                                continue;
                            }
                        }

                        //Ver si planeIntersectionPoint pertenece al polígono
                        Vector3 newMovementVector;
                        float newMoveDistSq;
                        Vector3 polygonIntersectionPoint;
                        if (pointInBounbingBoxFace(planeIntersectionPoint, bbFace))
                        {
                            if (embebbed)
                            {
                                //TODO: REVISAR ESTO, nunca debería pasar
                                //throw new Exception("El polígono está dentro de la esfera");
                            }

                            polygonIntersectionPoint = planeIntersectionPoint;
                            collisionFound = true;
                        }
                        else
                        {
                            //Buscar el punto mas cercano planeIntersectionPoint que tiene el polígono real de esta cara
                            polygonIntersectionPoint = TgcCollisionUtils.closestPointRectangle3d(planeIntersectionPoint,
                                bbFace.Extremes[0], bbFace.Extremes[1], bbFace.Extremes[2]);

                            //Revertir el vector de velocidad desde el nuevo polygonIntersectionPoint para ver donde colisiona la esfera, si es que llega
                            Vector3 reversePointSeg = polygonIntersectionPoint - movementVector;
                            if (TgcCollisionUtils.intersectSegmentSphere(polygonIntersectionPoint, reversePointSeg, characterSphere, out pDist, out sphereIntersectionPoint))
                            {
                                collisionFound = true;
                            }
                        }

                        if (collisionFound)
                        {
                            //Nuevo vector de movimiento acotado
                            newMovementVector = polygonIntersectionPoint - sphereIntersectionPoint;
                            newMoveDistSq = newMovementVector.LengthSq();

                            //se colisiono con algo, lo agrego a la lista
                            colisionInfo.Add(obstaculoBB);

                            if (newMoveDistSq <= distanceToTravelSq && newMoveDistSq < minCollisionDistSq)
                            {
                                minCollisionDistSq = newMoveDistSq;
                                realMovementVector = newMovementVector;
                                nearestPolygonIntersectionPoint = polygonIntersectionPoint;
                                collisionFace = bbFace;
                                collisionObstacle = obstaculoBB;

                            }
                        }
                    }
                }
            }

            //Si nunca hubo colisión, avanzar todo lo requerido
            if (collisionFace == null)
            {
                //Avanzar hasta muy cerca
                float movementLength = movementVector.Length();
                movementVector.Multiply((movementLength - EPSILON) / movementLength);
                characterSphere.moveCenter(movementVector);
                return;
            }

            //Solo movernos si ya no estamos muy cerca
            if (minCollisionDistSq >= EPSILON)
            {
                //Mover el BoundingSphere hasta casi la nueva posición real
                float movementLength = realMovementVector.Length();
                realMovementVector.Multiply((movementLength - EPSILON) / movementLength);
                characterSphere.moveCenter(realMovementVector);
            }

            //Calcular plano de Sliding
            Vector3 slidePlaneOrigin = nearestPolygonIntersectionPoint;
            Vector3 slidePlaneNormal = characterSphere.Center - nearestPolygonIntersectionPoint;
            slidePlaneNormal.Normalize();

            Plane slidePlane = Plane.FromPointNormal(slidePlaneOrigin, slidePlaneNormal);

            //Proyectamos el punto original de destino en el plano de sliding
            TgcRay slideRay = new TgcRay(nearestPolygonIntersectionPoint + Vector3.Multiply(movementVector, slideFactor), slidePlaneNormal);
            float slideT;
            Vector3 slideDestinationPoint;

            if (TgcCollisionUtils.intersectRayPlane(slideRay, slidePlane, out slideT, out slideDestinationPoint))
            {
                //Nuevo vector de movimiento
                Vector3 slideMovementVector = slideDestinationPoint - nearestPolygonIntersectionPoint;

                if (slideMovementVector.LengthSq() < EPSILON)
                {
                    return;
                }

                //Recursividad para aplicar sliding
                doCollideWithWorld(characterSphere, slideMovementVector, obstaculos, recursionDepth + 1, colisionInfo);
            }

            return;
        }
Beispiel #10
0
        /// <summary>
        ///     Detección de colisiones recursiva
        /// </summary>
        /// <param name="eSphere">Sphere de radio 1 pasada a Elipsoid space</param>
        /// <param name="eMovementVector">Movimiento pasado a Elipsoid space</param>
        /// <param name="eRadius">Radio de la elipsoide</param>
        /// <param name="colliders">Objetos contra los cuales colisionar</param>
        /// <param name="recursionDepth">Nivel de recursividad</param>
        /// <param name="movementSphere">Esfera real que representa el movimiento abarcado</param>
        /// <param name="slidingMinY">Minimo valor de normal Y de colision para hacer sliding</param>
        /// <returns>Resultado de colision</returns>
        public CollisionResult doCollideWithWorld(TgcBoundingSphere eSphere, TGCVector3 eMovementVector, TGCVector3 eRadius,
                                                  List <Collider> colliders, int recursionDepth, TgcBoundingSphere movementSphere, float slidingMinY)
        {
            var result = new CollisionResult();

            result.collisionFound = false;

            //Limitar recursividad
            if (recursionDepth > 5)
            {
                return(result);
            }

            //Posicion deseada
            var nextSphereCenter = eSphere.Center + eMovementVector;

            //Buscar el punto de colision mas cercano de todos los objetos candidatos
            TGCVector3 q;
            float      t;
            TGCVector3 n;
            var        minT = float.MaxValue;

            foreach (var collider in colliders)
            {
                //Colisionar Sphere en movimiento contra Collider (cada Collider resuelve la colision)
                if (collider.intersectMovingElipsoid(eSphere, eMovementVector, eRadius, movementSphere, out t, out q,
                                                     out n))
                {
                    //Quedarse con el menor instante de colision
                    if (t < minT)
                    {
                        minT = t;
                        result.collisionFound  = true;
                        result.collisionPoint  = q;
                        result.collisionNormal = n;
                        result.collider        = collider;
                    }
                }
            }

            //Si nunca hubo colisión, avanzar todo lo requerido
            if (!result.collisionFound)
            {
                //Avanzar todo lo pedido
                eSphere.moveCenter(eMovementVector);
                result.realMovmentVector = eMovementVector;
                result.collisionNormal   = TGCVector3.Empty;
                result.collisionPoint    = TGCVector3.Empty;
                result.collider          = null;
                return(result);
            }

            //Solo movernos si ya no estamos muy cerca
            if (minT >= EPSILON)
            {
                //Restar un poco al instante de colision, para movernos hasta casi esa distancia
                minT -= EPSILON;
                result.realMovmentVector = eMovementVector * minT;
                eSphere.moveCenter(result.realMovmentVector);

                //Quitarle al punto de colision el EPSILON restado al movimiento, para no afectar al plano de sliding
                var v = TGCVector3.Normalize(result.realMovmentVector);
                result.collisionPoint -= v * EPSILON;
            }

            //Calcular plano de Sliding, como un plano tangete al punto de colision con la esfera, apuntando hacia el centro de la esfera
            var slidePlaneOrigin = result.collisionPoint;
            var slidePlaneNormal = eSphere.Center - result.collisionPoint;

            slidePlaneNormal.Normalize();
            var slidePlane = TGCPlane.FromPointNormal(slidePlaneOrigin, slidePlaneNormal);

            //Calcular vector de movimiento para sliding, proyectando el punto de destino original sobre el plano de sliding
            var distance            = TgcCollisionUtils.distPointPlane(nextSphereCenter, slidePlane);
            var newDestinationPoint = nextSphereCenter - distance * slidePlaneNormal;
            var slideMovementVector = newDestinationPoint - result.collisionPoint;

            //No hacer recursividad si es muy pequeño
            slideMovementVector.Scale(SlideFactor);
            if (slideMovementVector.Length() < EPSILON)
            {
                return(result);
            }

            //Ver si posee la suficiente pendiente en Y para hacer sliding
            if (result.collisionNormal.Y <= slidingMinY)
            {
                //Recursividad para aplicar sliding
                doCollideWithWorld(eSphere, slideMovementVector, eRadius, colliders, recursionDepth + 1, movementSphere,
                                   slidingMinY);
            }

            return(result);
        }
Beispiel #11
0
        /// <summary>
        /// Actualizar estado
        /// </summary>
        public void update()
        {
            float maxDist = 2 * handleSphere.Radius;
            float movement;
            float correction;

            switch (currentState)
            {
            //Hacer animacion de abrir cajon
            case LockerState.Opening:
                movement = movementSpeed * GuiController.Instance.ElapsedTime;

                //Mover
                mesh.move(0, 0, movement);
                handleSphere.moveCenter(new Vector3(0, 0, movement));

                //Ver si llegamos al limite
                if (handleSphere.Center.Z >= handleMaxZ)
                {
                    //Corregir lo que nos pasamos
                    correction = handleSphere.Center.Z - handleMaxZ;
                    mesh.move(0, 0, -correction);
                    handleSphere.moveCenter(new Vector3(0, 0, -correction));

                    //Pasar a estado abierto
                    currentState     = LockerState.Opened;
                    waintElapsedTime = 0;
                }

                break;

            //Abierto
            case LockerState.Opened:
                waintElapsedTime += GuiController.Instance.ElapsedTime;
                if (waintElapsedTime > WAIT_TIME)
                {
                    waintElapsedTime = WAIT_TIME;
                }
                break;

            //Cerrado
            case LockerState.Closed:
                waintElapsedTime += GuiController.Instance.ElapsedTime;
                if (waintElapsedTime > WAIT_TIME)
                {
                    waintElapsedTime = WAIT_TIME;
                }
                break;

            //Hacer animacion de cerrar cajon
            case LockerState.Closing:
                movement = -movementSpeed * GuiController.Instance.ElapsedTime;

                //Mover
                mesh.move(0, 0, movement);
                handleSphere.moveCenter(new Vector3(0, 0, movement));

                //Ver si llegamos al limite
                if (handleSphere.Center.Z <= handleMinZ)
                {
                    //Corregir lo que nos pasamos
                    correction = handleSphere.Center.Z - handleMinZ;
                    mesh.move(0, 0, -correction);
                    handleSphere.moveCenter(new Vector3(0, 0, -correction));

                    //Pasar a estado cerrado
                    currentState     = LockerState.Closed;
                    waintElapsedTime = 0;
                }
                break;
            }
        }