/// <summary>
        ///     Detección de colisiones, filtrando los obstaculos que se encuentran dentro del radio de movimiento
        /// </summary>
        private void collideWithWorld(TgcBoundingSphere characterSphere, Vector3 movementVector,
                                      List <Collider> colliders, bool sliding, float slidingMinY)
        {
            //Ver si la distancia a recorrer es para tener en cuenta
            var distanceToTravelSq = movementVector.LengthSq();

            if (distanceToTravelSq < EPSILON)
            {
                return;
            }

            //Dejar solo los obstáculos que están dentro del radio de movimiento de la esfera
            var halfMovementVec = Vector3.Multiply(movementVector, 0.5f);

            movementSphere.setValues(
                characterSphere.Center + halfMovementVec,
                halfMovementVec.Length() + characterSphere.Radius
                );
            objetosCandidatos.Clear();
            foreach (var collider in colliders)
            {
                if (collider.Enable && TgcCollisionUtils.testSphereSphere(movementSphere, collider.BoundingSphere))
                {
                    objetosCandidatos.Add(collider);
                }
            }

            //Detectar colisiones y deplazar con sliding
            doCollideWithWorld(characterSphere, movementVector, objetosCandidatos, 0, movementSphere, sliding,
                               slidingMinY);
        }
Пример #2
0
        public ArtificialIntelligence(TGCVector3 posicionInicial, SoundsManager soundsManager) : base(posicionInicial, soundsManager)
        {
            this.CreateMesh(GlobalConcepts.GetInstance().GetMediaDir() + "meshCreator\\meshes\\Vehiculos\\Camioneta\\Camioneta-TgcScene.xml", posicionInicial);
            string reverseLightsPath, frontLightsPath, breakLightsPath;

            reverseLightsPath = GlobalConcepts.GetInstance().GetMediaDir() + "meshCreator\\meshes\\Vehiculos\\Camioneta\\LucesMarchaAtras\\Luces-TgcScene.xml";
            frontLightsPath   = GlobalConcepts.GetInstance().GetMediaDir() + "meshCreator\\meshes\\Vehiculos\\Camioneta\\LucesDelanteras\\Luces-TgcScene.xml";
            breakLightsPath   = GlobalConcepts.GetInstance().GetMediaDir() + "meshCreator\\meshes\\Vehiculos\\Camioneta\\LucesFrenado\\Luces-TgcScene.xml";
            this.CreateLights(reverseLightsPath, breakLightsPath, frontLightsPath);
            this.CreateWheels();
            radarSphere.setValues(this.GetPosition(), 75f);
            radarSphere.setRenderColor(Color.DarkViolet);
            this.aiState = new SearchWeapons(this);
            this.CreateSounds(soundsManager);
            this.velocidadMaximaDeAvance = 40f;
            velocidadRotacion            = 2f;
        }
        /// <summary>
        /// Mover Elipsoide con detección de colisiones, sliding y gravedad.
        /// Se actualiza la posición del centro del Elipsoide
        /// </summary>
        /// <param name="characterElipsoid">Elipsoide del cuerpo a mover</param>
        /// <param name="movementVector">Movimiento a realizar</param>
        /// <param name="colliders">Obstáculos contra los cuales se puede colisionar</param>
        /// <returns>Desplazamiento relativo final efecutado al Elipsoide</returns>
        public Vector3 moveCharacter(TgcElipsoid characterElipsoid, Vector3 movementVector, List <Collider> colliders)
        {
            //Guardar posicion original del Elipsoide
            Vector3 originalElipsoidCenter = characterElipsoid.Center;

            //Pasar elipsoid space
            Vector3 eCenter         = TgcVectorUtils.div(characterElipsoid.Center, characterElipsoid.Radius);
            Vector3 eMovementVector = TgcVectorUtils.div(movementVector, characterElipsoid.Radius);

            eSphere.setValues(eCenter, 1);
            Vector3 eOrigCenter = eSphere.Center;


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

            if (distanceToTravelSq >= EPSILON)
            {
                //Mover la distancia pedida
                selectPotentialColliders(characterElipsoid, movementVector, colliders);
                this.result = doCollideWithWorld(eSphere, eMovementVector, characterElipsoid.Radius, objetosCandidatos, 0, movementSphere, 1);
            }

            //Aplicar gravedad
            if (gravityEnabled)
            {
                //Mover con gravedad
                Vector3 eGravity = TgcVectorUtils.div(gravityForce, characterElipsoid.Radius);
                selectPotentialColliders(characterElipsoid, eGravity, colliders);
                this.result = doCollideWithWorld(eSphere, eGravity, characterElipsoid.Radius, objetosCandidatos, 0, movementSphere, onGroundMinDotValue);
            }

            //Mover Elipsoid pasando valores de colision a R3
            Vector3 movement = TgcVectorUtils.mul(eSphere.Center - eOrigCenter, characterElipsoid.Radius);

            characterElipsoid.moveCenter(movement);

            //Ajustar resultados
            result.realMovmentVector = TgcVectorUtils.mul(result.realMovmentVector, characterElipsoid.Radius);
            result.collisionPoint    = TgcVectorUtils.mul(result.collisionPoint, characterElipsoid.Radius);


            return(movement);
        }
        /// <summary>
        /// Selecciona todos los colliders que estan dentro de la esfera que representa el movimiento.
        /// Carga la lista objetosCandidatos
        /// </summary>
        private void selectPotentialColliders(TgcElipsoid characterElipsoid, Vector3 movementVector, List <Collider> colliders)
        {
            //Dejar solo los obstáculos que están dentro del radio de movimiento del elipsoide (lo consideramos una esfera, con su mayor radio)
            Vector3 halfMovementVec = Vector3.Multiply(movementVector, 0.5f);

            movementSphere.setValues(
                characterElipsoid.Center + halfMovementVec,
                halfMovementVec.Length() + characterElipsoid.getMaxRadius()
                );


            //Elegir todos los colliders que pasan un test Sphere-Sphere
            objetosCandidatos.Clear();
            foreach (Collider collider in colliders)
            {
                if (collider.Enable && TgcCollisionUtils.testSphereSphere(movementSphere, collider.BoundingSphere))
                {
                    objetosCandidatos.Add(collider);
                }
            }
        }
        /// <summary>
        ///     Detectar colision entre una esfera que se mueve y un triangulo
        /// </summary>
        /// <param name="sphere">BoundingSphere</param>
        /// <param name="movementVector">Vector de movimiento de la esferfa</param>
        /// <param name="triangle">Triangulo</param>
        /// <param name="collisionPoint">Menor punto de colision encontrado</param>
        /// <returns>True si hay colision</returns>
        private bool intersectMovingSphereTriangle(TgcBoundingSphere sphere, Vector3 movementVector, Triangle triangle,
                                                   out float minT, out Vector3 collisionPoint)
        {
            float   t;
            Vector3 q;

            collisionPoint = Vector3.Empty;
            minT           = float.MaxValue;

            //Ver si la esfera en movimiento colisiona con el plano del triangulo
            if (!TgcCollisionUtils.intersectMovingSpherePlane(sphere, movementVector, triangle.Plane, out t, out q))
            {
                return(false);
            }

            //Ver si la esfera ya esta dentro del Plano, hacer un chequeo Sphere-Triangle
            if (t == 0.0f)
            {
                if (TgcCollisionUtils.testSphereTriangle(sphere, triangle.A, triangle.B, triangle.C, out q))
                {
                    minT           = 0.0f;
                    collisionPoint = q;
                    return(true);
                }
            }
            else
            {
                //Si el punto de colision contra el plano pertenece al triangulo, entonces ya encontramos el punto de colision
                if (TgcCollisionUtils.testPointInTriangle(q, triangle.A, triangle.B, triangle.C))
                {
                    minT           = t;
                    collisionPoint = q;
                    return(true);
                }
            }

            //Ver de que lado del plano del triangulo esta la esfera
            var distPlane   = triangle.Plane.Dot(sphere.Center);
            var sphereRad   = distPlane >= 0.0f ? sphere.Radius : -sphere.Radius;
            var planeNormal = TgcCollisionUtils.getPlaneNormal(triangle.Plane);

            //Chequear colision entre la esfera en movimiento y los tres Edge y obtener el menor punto de colision
            //Es como un Ray del centro de la esfera contra un edge que se convierte en cilindro sin endcap
            var segmentEnd = sphere.Center + movementVector;

            if (intersectSegmentCylinderNoEndcap(sphere.Center, segmentEnd, triangle.A, triangle.B, sphere.Radius, out t))
            {
                minT = TgcCollisionUtils.min(t, minT);
            }
            if (intersectSegmentCylinderNoEndcap(sphere.Center, segmentEnd, triangle.B, triangle.C, sphere.Radius, out t))
            {
                minT = TgcCollisionUtils.min(t, minT);
            }
            if (intersectSegmentCylinderNoEndcap(sphere.Center, segmentEnd, triangle.C, triangle.A, sphere.Radius, out t))
            {
                minT = TgcCollisionUtils.min(t, minT);
            }
            //Si hubo colision, retornar la menor encontrada
            if (minT != float.MaxValue)
            {
                collisionPoint = sphere.Center + minT * movementVector - sphereRad * planeNormal;
                return(true);
            }

            //Sino, chequear colision entra la esfera y los tres vertices del triangulo y obtener la menor
            //Es como un Ray del centro de la esfera contra un vertice que se convierte en esfera
            var vertSphere = new TgcBoundingSphere();

            minT = float.MaxValue;
            vertSphere.setValues(triangle.A, sphere.Radius);
            if (TgcCollisionUtils.intersectSegmentSphere(sphere.Center, segmentEnd, vertSphere, out t, out q))
            {
                minT = TgcCollisionUtils.min(t, minT);
            }
            vertSphere.setValues(triangle.B, sphere.Radius);
            if (TgcCollisionUtils.intersectSegmentSphere(sphere.Center, segmentEnd, vertSphere, out t, out q))
            {
                minT = TgcCollisionUtils.min(t, minT);
            }
            vertSphere.setValues(triangle.C, sphere.Radius);
            if (TgcCollisionUtils.intersectSegmentSphere(sphere.Center, segmentEnd, vertSphere, out t, out q))
            {
                minT = TgcCollisionUtils.min(t, minT);
            }
            //Si hubo colision, retornar la menor encontrada
            if (minT != float.MaxValue)
            {
                collisionPoint = sphere.Center + minT * movementVector - sphereRad * planeNormal;
                return(true);
            }

            //No hay colision
            return(false);
        }
 protected virtual void Item_ScaleChanged(Item item)
 {
     Scale = Vector3Extension.One * item.Scale.MaxCoordinate();
     Sphere.setValues(Sphere.Center, _Radius * Scale.X);
 }