/// <summary> /// Picking con los planos XZ e YZ ubicados en el centro del objeto /// </summary> public TGCVector3 getPickingZ(TgcRay ray, TGCVector3 objCenter) { //Mover ambos planos hacia el centro del objeto pickingXZAabb.setExtremes( new TGCVector3(pickingXZAabb.PMin.X, objCenter.Y - SMALL_VAL, pickingXZAabb.PMin.Z), new TGCVector3(pickingXZAabb.PMax.X, objCenter.Y, pickingXZAabb.PMax.Z)); pickingYZAabb.setExtremes( new TGCVector3(objCenter.X - SMALL_VAL, pickingYZAabb.PMin.Y, pickingYZAabb.PMin.Z), new TGCVector3(objCenter.X, pickingYZAabb.PMax.Y, pickingYZAabb.PMax.Z)); TGCVector3 q1, q2; bool r1, r2; r1 = TgcCollisionUtils.intersectRayAABB(ray, pickingXZAabb, out q1); r2 = TgcCollisionUtils.intersectRayAABB(ray, pickingYZAabb, out q2); if (r1 && r2) { var objPos = new TGCVector2(objCenter.X, objCenter.Y); var diff1 = TGCVector2.Length(new TGCVector2(q1.X, q1.Y) - objPos); var diff2 = TGCVector2.Length(new TGCVector2(q2.X, q2.Y) - objPos); return(diff1 < diff2 ? q1 : q2); } if (r1) { return(clampPickingResult(q1)); } if (r2) { return(clampPickingResult(q2)); } return(objCenter); }
/// <summary> /// Hacer picking contra todos los ejes y devolver el eje seleccionado (si hay colision). /// Tambien se evaluan los ejes compuestos (XY, XZ, YZ) /// </summary> public Axis doPickAxis(TgcRay ray) { TGCVector3 collP; if (TgcCollisionUtils.intersectRayAABB(ray, boxX.BoundingBox, out collP)) { return(Axis.X); } if (TgcCollisionUtils.intersectRayAABB(ray, boxY.BoundingBox, out collP)) { return(Axis.Y); } if (TgcCollisionUtils.intersectRayAABB(ray, boxZ.BoundingBox, out collP)) { return(Axis.Z); } if (TgcCollisionUtils.intersectRayAABB(ray, boxXZ.BoundingBox, out collP)) { return(Axis.XZ); } if (TgcCollisionUtils.intersectRayAABB(ray, boxXY.BoundingBox, out collP)) { return(Axis.XY); } if (TgcCollisionUtils.intersectRayAABB(ray, boxYZ.BoundingBox, out collP)) { return(Axis.YZ); } return(Axis.None); }
public override bool intersectRay(TgcRay ray, Matrix transform, out Vector3 q) { COLLISION_SPHERE.setCenter(Vector3.TransformCoordinate(position, transform)); float t; return(TgcCollisionUtils.intersectRaySphere(ray, COLLISION_SPHERE, out t, out q)); }
public static Vector3 getClosesPointBetween(TgcRay rayCast, BoundingBoxCollider boundingBox) { Vector3 vector = new Vector3(); TgcCollisionUtils.intersectRayAABB(rayCast, boundingBox.Aabb, out vector); return(vector); }
public Rayo(TGCVector3 origen, TGCVector3 direccion) { this.origen = origen; this.direccion = direccion; this.ray = new TgcRay(origen, direccion); this.puntoInterseccion = TGCVector3.Empty; }
/// <summary> /// Picking con los planos XY e YZ ubicados en el centro del objeto /// </summary> public Vector3 getPickingY(TgcRay ray, Vector3 objCenter) { //Mover ambos planos hacia el centro del objeto pickingXYAabb.setExtremes( new Vector3(pickingXYAabb.PMin.X, pickingXYAabb.PMin.Y, objCenter.Z - SMALL_VAL), new Vector3(pickingXYAabb.PMax.X, pickingXYAabb.PMax.Y, objCenter.Z)); pickingYZAabb.setExtremes( new Vector3(objCenter.X - SMALL_VAL, pickingYZAabb.PMin.Y, pickingYZAabb.PMin.Z), new Vector3(objCenter.X, pickingYZAabb.PMax.Y, pickingYZAabb.PMax.Z)); Vector3 q1, q2; bool r1, r2; r1 = TgcCollisionUtils.intersectRayAABB(ray, pickingXYAabb, out q1); r2 = TgcCollisionUtils.intersectRayAABB(ray, pickingYZAabb, out q2); if (r1 && r2) { Vector2 objPos = new Vector2(objCenter.X, objCenter.Z); float diff1 = Vector2.Length(new Vector2(q1.X, q1.Z) - objPos); float diff2 = Vector2.Length(new Vector2(q2.X, q2.Z) - objPos); return(diff1 < diff2 ? q1 : q2); } else if (r1) { return(clampPickingResult(q1)); } else if (r2) { return(clampPickingResult(q2)); } return(objCenter); }
public Item Pick(TgcRay ray) { var item = _Items.FirstOrDefault(i => i.Intercepts(ray)); if (item != null) { Remove(item); } return(item); }
public override bool intersectRay(TgcRay ray, Matrix transform, out Vector3 q) { Vector3[] v = new Vector3[vertices.Count]; for (int i = 0; i < v.Length; i++) { v[i] = Vector3.TransformCoordinate(vertices[i].position, transform); } float t; return(TgcCollisionUtils.intersectRayConvexPolygon(ray, v, out t, out q)); }
public override bool intersectRay(TgcRay ray, Matrix transform, out Vector3 q) { //Actualizar OBB con posiciones de la arista para utilizar en colision EditablePolyUtils.updateObbFromSegment(COLLISION_OBB, Vector3.TransformCoordinate(a.position, transform), Vector3.TransformCoordinate(b.position, transform), 0.4f); //ray-obb return(TgcCollisionUtils.intersectRayObb(ray, COLLISION_OBB, out q)); }
public bool isIntersectedBy(TgcRay r) { var tMin = (this.PMin.X - r.Origin.X) / r.Direction.X; var tMax = (this.PMax.X - r.Origin.X) / r.Direction.X; float aux; if (tMin > tMax) { aux = tMin; tMin = tMax; tMax = aux; } ; var tyMin = (this.PMin.Y - r.Origin.Y) / r.Direction.Y; var tyMax = (this.PMax.Y - r.Origin.Y) / r.Direction.Y; if (tyMin > tyMax) { aux = tyMin; tyMin = tyMax; tyMax = aux; } ; if ((tMin > tyMax) || (tyMin > tMax)) { return(false); } if (tyMin > tMin) { tMin = tyMin; } if (tyMax < tMax) { tMax = tyMax; } var tzMin = (this.PMin.Z - r.Origin.Z) / r.Direction.Z; var tzMax = (this.PMax.Z - r.Origin.Z) / r.Direction.Z; if (tzMin > tzMax) { aux = tzMin; tzMin = tzMax; tzMax = aux; } ; return(!(tMin > tzMax) && !(tzMin > tMax)); }
public bool hasDirectSightWith(Checkpoint aCheckPoint) { TgcRay rayCast = new TgcRay(); rayCast.Origin = this.Position; rayCast.Direction = aCheckPoint.Position - this.Position; float distance = Vector3.Length(aCheckPoint.Position - this.Position); BoundingBoxCollider boundingBox = new BoundingBoxCollider(); CollisionManager.getClosestBoundingBox(rayCast, out boundingBox, null); return(boundingBox == null || (Vector3.Length(CollisionManager.getClosesPointBetween(rayCast, boundingBox) - rayCast.Origin) > distance)); }
private bool IntersectRayAABB(TgcRay ray, TgcBoundingAxisAlignBox aabb) { TgcBoundingAxisAlignBox.Face[] faces = aabb.computeFaces(); foreach (TgcBoundingAxisAlignBox.Face face in faces) { if (TgcCollisionUtils.intersectRayPlane(ray, face.Plane, out float t, out TGCVector3 intersection)) { return(true); } } return(false); }
/// <summary> /// Picking con plano XY ubicado en el centro del objeto /// </summary> public Vector3 getPickingXY(TgcRay ray, Vector3 objCenter) { //Mover aabb en Y al centro del mesh pickingXYAabb.setExtremes( new Vector3(pickingXYAabb.PMin.X, pickingXYAabb.PMin.Y, objCenter.Z - SMALL_VAL), new Vector3(pickingXYAabb.PMax.X, pickingXYAabb.PMax.Y, objCenter.Z)); Vector3 q; bool r = TgcCollisionUtils.intersectRayAABB(ray, pickingXYAabb, out q); if (r) { return(clampPickingResult(q)); } return(objCenter); }
/// <summary> /// Constructor de la camara a partir de un TgcD3dInput el cual ya tiene por default el eyePosition (0,0,0), el mouseCenter a partir del centro del a pantalla, RotationSpeed 1.0f, /// MovementSpeed y JumpSpeed 500f, el directionView (0,0,-1) /// </summary> public Camera() { cameraRotation = TGCMatrix.RotationX(updownRot) * TGCMatrix.RotationY(leftrightRot); down = new TgcRay(); horx = new TgcRay(); horz = new TgcRay(); down.Direction = new TGCVector3(0, -1, 0); horx.Direction = new TGCVector3(1, 0, 0); horz.Direction = new TGCVector3(0, 0, 1); g.camera = this; g.hands = new Hands(); }
/// <summary> /// Picking con plano YZ ubicado en el centro del objeto /// </summary> public TGCVector3 getPickingYZ(TgcRay ray, TGCVector3 objCenter) { //Mover aabb en Y al centro del mesh pickingYZAabb.setExtremes( new TGCVector3(objCenter.X - SMALL_VAL, pickingYZAabb.PMin.Y, pickingYZAabb.PMin.Z), new TGCVector3(objCenter.X, pickingYZAabb.PMax.Y, pickingYZAabb.PMax.Z)); TGCVector3 q; var r = TgcCollisionUtils.intersectRayAABB(ray, pickingYZAabb, out q); if (r) { return(clampPickingResult(q)); } return(objCenter); }
protected bool IsReallyTheFloor(Collidable element) { TGCVector3 directionOfCollision = new TGCVector3(0, -1f, 0); TgcRay ray = new TgcRay(); ray.Origin = this.auto.GetLastPosition(); ray.Direction = directionOfCollision; TGCPlane plane = element.GetPlaneOfCollision(ray, this.auto); TGCVector3 normal = new TGCVector3(0, 1, 0); if (normal != new TGCVector3(0, 1, 0)) { return(false); } return(true); }
private TGCPlane CreatePlane(TgcRay ray, TgcBoundingAxisAlignBox.Face[] faces, TGCVector3 testPoint) { float instante; TGCVector3 intersection; List <TGCPlane> candidatesPlanes = new List <TGCPlane>(); foreach (TgcBoundingAxisAlignBox.Face face in faces) { if (TgcCollisionUtils.intersectRayPlane(ray, face.Plane, out instante, out intersection)) { candidatesPlanes.Add(face.Plane); } } return(this.SelectPlane(candidatesPlanes, testPoint)); }
private void Collide(Vehicle car) { TgcRay ray = new TgcRay(); ray.Origin = this.GetLastPosition(); ray.Direction = this.GetDirectionOfCollision(); if (this.IntersectRayAABB(ray, car.mesh.BoundingBox)) { float distanceAI = car.GetDistanceOfCollision(this.vectorAdelante, this.velocidadActual); float distance = this.GetDistanceOfCollision(car.GetVectorAdelante(), car.GetVelocidadActual()); car.SetEstado(new Crashing(car, distanceAI, this.GetVectorAdelante())); this.SetEstado(new Crashing(this, distance, car.GetVectorAdelante())); car.TakeDamage(5f); TakeDamage(5f); } }
/// <summary> /// Retorna true si hubo interseccion con el plano del terreno y setea el collisionPoint con la altura en ese punto. /// </summary> /// <param name="ray"></param> /// <param name="collisionPoint"></param> /// <returns></returns> public bool intersectRayPlane(TgcRay ray, out Vector3 collisionPoint) { collisionPoint = Vector3.Empty; float minHeight = (minIntensity + traslation.Y) * ScaleY; float t; //Me fijo si intersecta con el BB del terreno. if (!TgcCollisionUtils.intersectRayPlane(ray, new Plane(0, 1, 0, -minHeight), out t, out collisionPoint)) { return(false); } return(interpoledHeight(collisionPoint.X, collisionPoint.Z, out collisionPoint.Y)); }
public static Boolean getClosestBoundingBox(TgcRay rayCast, out BoundingBoxCollider boundingBoxResult, BoundingBoxCollider boundingBox) { List <BoundingBoxCollider> boundingBoxes = getColisions(rayCast); boundingBoxes.Remove(boundingBox); if (boundingBoxes.Count == 0) { boundingBoxResult = null; return(false); } else { List <Vector3> vectors = boundingBoxes.ConvertAll(b => { Vector3 vector = new Vector3(); TgcCollisionUtils.intersectRayAABB(rayCast, b.Aabb, out vector); return(vector); }); boundingBoxResult = boundingBoxes.Find(b => { Vector3 vector = new Vector3(); TgcCollisionUtils.intersectRayAABB(rayCast, b.Aabb, out vector); return(vectors.TrueForAll(v => Vector3.Length(vector - rayCast.Origin) <= Vector3.Length(v - rayCast.Origin))); }); return(true); } }
public TGCPlane GetPlaneOfCollision(TgcRay ray, Vehicle car) { TgcMesh collide = null; foreach (TgcMesh element in this.elements) { if (IsColliding(element, car)) { collide = element; } } if (collide == null) { throw new Exception("Hubo un error no esperado"); } TgcBoundingAxisAlignBox.Face[] faces = collide.BoundingBox.computeFaces(); return(this.CreatePlane(ray, faces, car.GetLastPosition())); }
/// <summary> /// Retorna true si hubo interseccion con el plano del terreno y setea el collisionPoint con la altura en ese punto. /// </summary> /// <param name="ray"></param> /// <param name="collisionPoint"></param> /// <returns></returns> public bool intersectRayTGCPlane(TgcRay ray, out TGCVector3 collisionPoint) { collisionPoint = TGCVector3.Empty; var minHeight = (minIntensity + traslation.Y) * ScaleY; float t; //Me fijo si intersecta con el BB del terreno. if (!TgcCollisionUtils.intersectRayPlane(ray, new TGCPlane(0, 1, 0, -minHeight), out t, out collisionPoint)) { return(false); } var collisionPointY = collisionPoint.Y; var interseccion = interpoledHeight(collisionPoint.X, collisionPoint.Z, out collisionPointY); collisionPoint.Y = collisionPointY; return(interseccion); }
public Vector3 fireLauncher() { //Disparamos el arma, nos fijamos si colisiona con un enemigo, y si hay obstaculos en el medio TgcRay ray = new TgcRay(CustomFpsCamera.Instance.Position, CustomFpsCamera.Instance.LookAt - CustomFpsCamera.Instance.Position); Vector3 newPosition = new Vector3(0, 0, 0); List <Vector3> posicionObstaculos = new List <Vector3>(); foreach (TgcMesh obstaculo in vegetation) { if (TgcCollisionUtils.intersectRayAABB(ray, obstaculo.BoundingBox, out newPosition)) { posicionObstaculos.Add(newPosition); } } for (int i = enemies.Count - 1; i >= 0; i--) { if (TgcCollisionUtils.intersectRayAABB(ray, enemies[i].mesh.BoundingBox, out newPosition)) { posicionObstaculos.Add(newPosition); } } //////////////////////////disparo a barriles//////////////////////////////////////// for (int i = barriles.Count - 1; i >= 0; i--) { if (TgcCollisionUtils.intersectRayAABB(ray, barriles[i].mesh.BoundingBox, out newPosition)) { posicionObstaculos.Add(newPosition); } } posicionObstaculos.Add(intersectRayTerrain(ray)); posicionObstaculos.Sort(delegate(Vector3 x, Vector3 y) { return(distanciaACamara(x).CompareTo(distanciaACamara(y))); }); Vector3 min = posicionObstaculos[0]; return(min); }
public bool pointParallelipedXZColission(Parallelepiped par, TGCVector3 pos, float colissionLen) { var ray = new TgcRay(); ray.Direction = new TGCVector3(1, 0, 0); ray.Origin = pos + new TGCVector3(-colissionLen, 0, 0); if (par.intersectRay(ray, out float t, out TGCVector3 q) && t < 2f * colissionLen) { return(true); } ray.Direction = new TGCVector3(0, 0, 1); ray.Origin = pos + new TGCVector3(0, 0, -colissionLen); if (par.intersectRay(ray, out t, out q) && t < 2f * colissionLen) { return(true); } return(false); }
public Vector3 intersectRayTerrain(TgcRay ray) { int iteraciones = heightmapResolution / cantidadFilasColumnas * (int)currentScaleXZ; Vector3 dir = ray.Direction; dir.Normalize(); Vector3 origin = ray.Origin; Vector3 pos = origin; float y = 0; for (int i = 0; i < iteraciones; i++) { interpoledHeight(pos.X, pos.Z, out y); if (FastMath.Abs(pos.Y - y) < 1f) { return(pos); } pos += dir; } return(pos); }
private void Collide(TgcMesh elemento, Vehicle car) { //direccion a la que estoy yendo antes de chocar TGCVector3 directionOfCollision = car.GetDirectionOfCollision(); TgcRay ray = new TgcRay(); ray.Origin = car.GetLastPosition(); ray.Direction = directionOfCollision; //interseco el rayo con el aabb, para conocer un punto del plano con el que colisione TgcBoundingAxisAlignBox.Face[] faces; faces = elemento.BoundingBox.computeFaces(); TGCPlane plane = this.CreatePlane(ray, faces, car.GetLastPosition()); TGCVector3 normal = GlobalConcepts.GetInstance().GetNormalPlane(plane); TGCVector3 output = normal + directionOfCollision * 2; float angle = car.SetDirection(output, normal); car.Crash(angle); while (TgcCollisionUtils.testObbAABB(car.GetTGCBoundingOrientedBox(), elemento.BoundingBox)) { car.Translate(TGCMatrix.Translation(normal)); car.Transform(); } }
/// <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); } }
public void update() { dir = TGCVector3.Empty; if (mode == -1)//cambiar por un switch { if (g.map.candlesPlaced > 0) { mode = 3; } return; } else if (mode == 0) { //va hacia el jugador, la aceleracion salta entre + y - cada tanto speedToPlayer(); } else if (mode == 1) { //mientras se lo este mirando no ataca al jugador, se queda cerca //@todo chequeo especial, antes se usaba los triangulos de la camara if (true) { if (setObj) { setObj = false; if (speed > 3500f) { speed -= g.game.ElapsedTime * acceleration; } //aca estoy consiguiendo un valor en un radio del jugador, mas o menos en la direccion que mira //seguro que hay una forma mejor de calcular esto obj = g.camera.cameraRotatedTarget * 100f + TGCVector3.Cross(g.camera.cameraRotatedTarget * 100f, TGCVector3.Up) * g.map.Random.Next(-10000, 10000); obj.Normalize(); obj *= 2000f + 1000 * g.hands.state; obj += g.camera.eyePosition; } dir = obj - pos; if (dir.Length() < 500f) { setObj = true; } } else { setObj = true; speedToPlayer(); } } else if (mode == 3) { //@todo se puede optimizar guardando la direccion de movimiento y una cantidad de pasos en vez //de tener objobj y calcular cada frame var lightMove = lightObjObj - lightObj; if (lightMove.Length() < 1000f) { lightObjObj = new TGCVector2(); var rnd = g.map.Random; lightObjObj.X = (float)rnd.NextDouble(); lightObjObj.Y = (float)rnd.NextDouble(); lightObjObj.Normalize(); lightObjObj *= (float)rnd.NextDouble() * 150000f; lightObjObj += new TGCVector2(g.camera.eyePosition.X, g.camera.eyePosition.Z); lightMove = lightObjObj - lightObj; } lightMove.Normalize(); lightMove *= 5000f; lightObj += lightMove * g.game.ElapsedTime; flyHeight = g.camera.terrainHeight(pos) + 2500f; dir.X = lightObj.X - pos.X; dir.Y = flyHeight - pos.Y; dir.Z = lightObj.Y - pos.Z; var sightLine = new TGCVector2(dir.X, dir.Z); var playerLine = new TGCVector2(g.camera.eyePosition.X - pos.X, g.camera.eyePosition.Z - pos.Z); sightLine.Normalize(); playerLine.Normalize(); if (TGCVector2.Dot(sightLine, playerLine) >= .96) { var sight = g.camera.Position - pos; //detectar colisiones timeInView += g.game.ElapsedTime; if (timeInView > 1) { mode = 0; } } else { timeInView = 0; } } Console.WriteLine(mode); dir.Normalize(); dir.Multiply(speed * (g.cameraSprites.squeletonHalfSpeed ? .0f : 1f) * (g.map.candlesPlaced == g.cameraSprites.candlesRequired ? .2f : 1f) * g.game.ElapsedTime); //11000f colDir = new TGCVector3(dir.X, 0, dir.Z); colDir.Normalize(); colDir *= 1000; //colDir.X = Math.Max(colDir.X, dir.X); //colDir.Z = Math.Max(colDir.Z, dir.Z);//puede que sea demasiado precavido esto cPos = pos + TGCVector3.Up * height; var chunk = g.chunks.fromCoordinates(pos); float len = colDir.Length(); float t; TGCVector3 q;//esta porque c# me obliga var ray = new TgcRay(); ray.Direction = colDir; ray.Origin = cPos; var intersecRay = new Func <bool>(() => { foreach (var mesh in chunk.meshes) { if (mesh.paralleliped.intersectRay(ray, out t, out q) && t < len) { return(true); } } foreach (var multimesh in chunk.multimeshes) { foreach (var par in multimesh.parallelipeds) { if (par.intersectRay(ray, out t, out q) && t < len) { return(true); } } } return(false); }); if (intersecRay()) { swithSideTimer = 0f; setObj = true; ray.Direction = TGCVector3.Cross(colDir, TGCVector3.Up) * sidePref; if (intersecRay()) { ray.Direction = -ray.Direction; if (intersecRay()) { dir = -dir; } else { dir = -TGCVector3.Cross(dir, TGCVector3.Up) * sidePref; } sidePref = -sidePref; } else { dir = TGCVector3.Cross(dir, TGCVector3.Up) * sidePref; } } else { //si no hay nada enfrente mirar al jugador swithSideTimer += g.game.ElapsedTime; if (swithSideTimer > 3f) { swithSideTimer = 0; sidePref = -sidePref; } lookAt = new TGCVector3(dir.X, 0, dir.Z); lookAt.Normalize(); lookin = new TGCVector3(0, 0, -1); } pos += dir; //Logger.Log(rot); musica.Position = pos; g.game.DirectSound.Listener3d.Position = g.camera.eyePosition; }
/// <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; }
public bool ColisionDisparo(TgcRay disparo) { Vector3 interseccion; float distancia; foreach (Enemigo enemigo in enemigos.ListaDeEnemigosOrdenadaPorDistancia()) { if (TgcCollisionUtils.intersectRayAABB(disparo, enemigo.BoundingBoxEnemigo(), out interseccion)) { enemigo.Herir(damage_Body, interseccion); if (enemigo.Murio()) { enemigo.Muriendo = true; this.jugador.puntos += 10; } this.jugador.puntos += 1; return(true); } if (TgcCollisionUtils.intersectRaySphere(disparo, enemigo.BoundingBoxCabeza(), out distancia, out interseccion)) { enemigo.Herir(damage_Head, interseccion); if (enemigo.Murio()) { enemigo.Muriendo = true; this.jugador.puntos += 10; } this.jugador.puntos += 2; return(true); } } foreach (TgcMesh barril in escenario.BarrilesExplosivos()) { if (TgcCollisionUtils.intersectRayAABB(disparo, barril.BoundingBox, out interseccion)) { //Se podria hacer un objeto barril, por ahora meto el código acá. -Alex //Hasta aca ya sabemos que el disparo le dio al barril. float d, xc, zc; xc = barril.Position.X; zc = barril.Position.Z; var listaDeEnemigos = enemigos.ListaDeEnemigos(); foreach (var enemigo in listaDeEnemigos) { //Calculo la distancia hasta el barril d = FastMath.Sqrt(FastMath.Pow2(enemigo.Position().X - xc) + FastMath.Pow2(enemigo.Position().Z - zc)); //Me fijo si cumple con el radio (si tenemos el objeto barril, cada barril puede tener su radio) if (d <= 300) //Radio hardcodeado { enemigo.Herir(300 / (0.05F * d), interseccion); if (enemigo.Murio()) { enemigo.Muriendo = true; this.jugador.puntos += 10; } } } //Aparte, el barril exploto... sound_Explosion.play(); escenario.BorrarObjeto(barril.Name); return(true); } } return(false); }
public void Update(float elapsedTime) { // correr if (GuiController.Instance.D3dInput.keyPressed(Microsoft.DirectX.DirectInput.Key.LeftShift)) { camera.MovementSpeed = RUNNING_SPEED; } else if (GuiController.Instance.D3dInput.keyUp(Microsoft.DirectX.DirectInput.Key.LeftShift)) { camera.MovementSpeed = WALKING_SPEED; } /*Si se movio, chequeo colisiones con objetos... Esto no funciona como debería, aparte no podemos atajar el movimiento antes de renderearlo y queda medio feo. * para solucionarlo tendríamos que hacer que la camara sigua al mesh (es decir, que el mesh sea el que se mueve con WASD) y ahí podemos atajar la colision antes * El otro problema es como se genera el bounding box del mesh, deje seteado para que se renderize el mesh del sniper así lo ven, solucionar esto CREO que es facil */ if (!posicionSegura.Equals(camera.getPosition())) { if (moviendo == false) { elapsedMOVE = 0.0f; moviendo = true; } else { elapsedMOVE += elapsedTime; } if (ColisionesAdmin.Instance.ColisionConObjetos()) { camera.move(posicionSegura - camera.getPosition()); } else { posicionSegura = camera.getPosition(); } } else { moviendo = false; } if (ColisionesAdmin.Instance.ColisionConEnemigos()) { this.vidas -= 1; sound_Die.play(); camera.move(posicionInicial - camera.getPosition()); } // Disparo if (!puedeDisparar) { elapsedROF += elapsedTime; } if (elapsedROF >= ROF) { puedeDisparar = true; } if (GuiController.Instance.D3dInput.buttonPressed(TgcViewer.Utils.Input.TgcD3dInput.MouseButtons.BUTTON_LEFT)) { if (ammo != 0) { if (puedeDisparar) { TgcRay disparo = new TgcRay(camera.getPosition(), Vector3.Subtract(camera.getLookAt(), camera.getPosition())); if (ColisionesAdmin.Instance.ColisionDisparo(disparo)) { sound_Hit.play(); } sound_Disparo.play(); puedeDisparar = false; elapsedROF = 0; ammo--; } } else { sound_DryFire.play(); } } // Activa el scope if (GuiController.Instance.D3dInput.buttonPressed(TgcViewer.Utils.Input.TgcD3dInput.MouseButtons.BUTTON_RIGHT)) { // Me fijo el estado del scope, cambio la matriz de proyeccion y la velocidad de rotación del mouse // (para disminuir la sens y que el mouse no vuele con el zoom) //Reproduzco el sonido del zoom sound_Zoom.play(); scope = !scope; if (scope) { zoom = zoomBase; camera.RotationSpeed = ROTATION_SPEED_SCOPE; } else { zoom = 1; camera.RotationSpeed = ROTATION_SPEED_NO_SCOPE; } } // Zoom con la rueda del mouse, SOLO si el scope esta activado if (scope) { if (GuiController.Instance.D3dInput.WheelPos > 0) { zoom += zoomWheel; } if (GuiController.Instance.D3dInput.WheelPos < 0) { zoom -= zoomWheel; } if (GuiController.Instance.D3dInput.WheelPos != 0 && zoom <= (zoomBase + zoomMaximo * zoomWheel) && zoom >= 1) { sound_Zoom.play(); } if (zoom > zoomBase + (zoomWheel * zoomMaximo)) { zoom = zoomBase + (zoomWheel * zoomMaximo); } if (zoom < zoomBase) { zoom = zoomBase; } } else { UpdateRifle(); } matrizConZoom.M11 = matrizSinZoom.M11 * zoom; matrizConZoom.M22 = matrizSinZoom.M22 * zoom; GuiController.Instance.D3dDevice.Transform.Projection = matrizConZoom; }