/// <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); }
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); }