public static async Task <bool> MoveToPosWithNavMeshAsync(SharpDX.Vector3 vecDest, int NearDistance = 50) { if (Nav.D3.Navmesh.Current == null) { Nav.D3.Navmesh.Create(Enigma.D3.Engine.Current, new Nav.ExploreEngine.Nearest()); } var localAcd = ActorCommonDataHelper.GetLocalAcd(); var distance = vecDest.Distance(); // (Math.Pow(localAcd.x0D0_WorldPosX - vecDest.X, 2) + Math.Pow(localAcd.x0D4_WorldPosY - vecDest.Y, 2)); var minDistanceReached = distance; var dtDistanceReached = DateTime.Now; DateTime dtTimeout = DateTime.Now; while (distance > NearDistance) { if (DateTime.Now > dtTimeout.AddSeconds(30) || DateTime.Now > dtDistanceReached.AddSeconds(10)) { return(false); } SharpDX.Vector2 curVector = localAcd.ToSharpDXVector2(); // new SharpDX.Vector2(localAcd.x0D0_WorldPosX, localAcd.x0D4_WorldPosY); SharpDX.Vector2 destVector = new SharpDX.Vector2(vecDest.X, vecDest.Y); // Update current player position. Nav.D3.Navmesh.Current.Navigator.CurrentPos = localAcd.ToNavVec3(); // new Nav.Vec3(localAcd.x0D0_WorldPosX, localAcd.x0D4_WorldPosY, localAcd.x0D8_WorldPosZ); // Update destination. You can keep setting the same value there is internal check if destination has actually changed. // This destination overrides any internal destinations (including exploration). When You just want to explore You do // not need to set any destination. It will be set automatically. Nav.D3.Navmesh.Current.Navigator.Destination = new Nav.Vec3(vecDest.X, vecDest.Y, vecDest.Z); // Get current destination. Nav.Vec3 goToPosition = Nav.D3.Navmesh.Current.Navigator.GoToPosition; while (goToPosition.IsEmpty) { await Task.Delay(10); } SharpDX.Vector3 goToPositionVector = new SharpDX.Vector3(goToPosition.X, goToPosition.Y, goToPosition.Z); await MoveToPosAsync(goToPositionVector); } return(true); }
public void Deserialize(BinaryReader r) { min = new Vec3(r); max = new Vec3(r); is_empty = r.ReadBoolean(); }
public void Translate(Vec3 v) { min += v; max += v; }
public AABB(AABB aabb) { min = new Vec3(aabb.min); max = new Vec3(aabb.max); }
public Vec3 Align(Vec3 p) { return(Vec3.Min(Vec3.Max(Min, p), Max)); }
public void Translate(Vec3 v) { Min += v; Max += v; }
public GridCell(Vec3 min, Vec3 max, int id = -1, int area_id = -1) : base(min, max, MovementFlag.None, id) { InitGridCell(area_id); }
public path_pos(Vec3 p, Cell c) { pos = p; cell = c; }
public bool Contains2D(Vec3 p) { return(p.X >= min.X && p.X <= max.X && p.Y >= min.Y && p.Y <= max.Y); }
public bool Contains(Vec3 p, float z_tolerance = 0) { return(p.X >= min.X && p.X <= max.X && p.Y >= min.Y && p.Y <= max.Y && (p.Z + z_tolerance) >= min.Z && (p.Z - z_tolerance) <= max.Z); }
private bool InternalRayTest(Vec3 ray_origin, Vec3 ray_dir, ref Vec3 result, int num_dim) { // implementation based upon https://www.scratchapixel.com/lessons/3d-basic-rendering/minimal-ray-tracer-rendering-simple-shapes/ray-box-intersection // + added custom support for rays tangent to sides of AABB Vec3 ray_dir_inv = 1 / ray_dir; int[] sign = new int[] { ray_dir_inv.X < 0 ? 1 : 0, ray_dir_inv.Y < 0 ? 1 : 0, ray_dir_inv.Z < 0 ? 1 : 0 }; float tmin, tmax, tymin, tymax, tzmin, tzmax; tmin = (Bounds(sign[0]).X - ray_origin.X) * ray_dir_inv.X; tmax = (Bounds(1 - sign[0]).X - ray_origin.X) * ray_dir_inv.X; tymin = (Bounds(sign[1]).Y - ray_origin.Y) * ray_dir_inv.Y; tymax = (Bounds(1 - sign[1]).Y - ray_origin.Y) * ray_dir_inv.Y; if ((tmin > tymax) || (tymin > tmax)) { return(false); } bool tangent_x = float.IsNaN(tmin) || float.IsNaN(tmax); bool tangent_y = float.IsNaN(tymin) || float.IsNaN(tymax); if (tymin > tmin || tangent_x) { tmin = tymin; } if (tymax < tmax && !tangent_y) { tmax = tymax; } bool tangent_z = false; if (num_dim > 2) { tzmin = (Bounds(sign[2]).Z - ray_origin.Z) * ray_dir_inv.Z; tzmax = (Bounds(1 - sign[2]).Z - ray_origin.Z) * ray_dir_inv.Z; tangent_z = float.IsNaN(tzmin) || float.IsNaN(tzmax); if ((tmin > tzmax) || (tzmin > tmax)) { return(false); } if (tzmin > tmin || float.IsNaN(tmin)) { tmin = tzmin; } if (tzmax < tmax && !float.IsNaN(tmax)) { tmax = tzmax; } } if (tmax >= 0) { if (tmin < 0 && (tangent_x || tangent_y || tangent_z)) { result = ray_origin; } else { result = ray_origin + ray_dir * (tmin < 0 ? tmax : tmin); } return(true); } return(false); }
public bool RayTest(Vec3 ray_origin, Vec3 ray_dir, ref Vec3 result) { return(InternalRayTest(ray_origin, ray_dir, ref result, 3)); }
public void Deserialize(BinaryReader r) { Min = new Vec3(r); Max = new Vec3(r); }
public AABB(AABB aabb) { Min = new Vec3(aabb.Min); Max = new Vec3(aabb.Max); }
public bool RayTest2D(Vec3 ray_origin, Vec3 ray_dir, out Vec3 result) { return(InternalRayTest(ray_origin, ray_dir, out result, 2)); }
private bool InternalRayTest(Vec3 ray_origin, Vec3 ray_dir, out Vec3 result, int num_dim) { // implementation is brutal port from http://tog.acm.org/resources/GraphicsGems/gems/RayBox.c result = Vec3.Empty; const int RIGHT = 0; const int LEFT = 1; const int MIDDLE = 2; bool inside = true; float[] origin = new float[3] { ray_origin.X, ray_origin.Y, ray_origin.Z }; float[] minB = new float[3] { min.X, min.Y, min.Z }; float[] maxB = new float[3] { max.X, max.Y, max.Z }; float[] dir = new float[3] { ray_dir.X, ray_dir.Y, ray_dir.Z }; float[] coord = new float[3] { 0, 0, 0 }; int[] quadrant = new int[3] { 0, 0, 0 }; float[] candidatePlane = new float[3]; /* Find candidate planes; this loop can be avoided if * rays cast all from the eye(assume perpsective view) */ for (int i = 0; i < num_dim; ++i) { if (origin[i] < minB[i]) { quadrant[i] = LEFT; candidatePlane[i] = minB[i]; inside = false; } else if (origin[i] > maxB[i]) { quadrant[i] = RIGHT; candidatePlane[i] = maxB[i]; inside = false; } else { quadrant[i] = MIDDLE; } } /* Ray origin inside bounding box */ if (inside) { result = new Vec3(ray_origin); return(true); } float[] maxT = new float[3]; /* Calculate T distances to candidate planes */ for (int i = 0; i < num_dim; ++i) { if (quadrant[i] != MIDDLE && dir[i] != 0) { maxT[i] = (candidatePlane[i] - origin[i]) / dir[i]; } else { maxT[i] = -1; } } /* Get largest of the maxT's for final choice of intersection */ int whichPlane = 0; for (int i = 1; i < num_dim; ++i) { if (maxT[whichPlane] < maxT[i]) { whichPlane = i; } } /* Check final candidate actually inside box */ if (maxT[whichPlane] < 0) { return(false); } for (int i = 0; i < num_dim; ++i) { if (whichPlane != i) { coord[i] = origin[i] + maxT[whichPlane] * dir[i]; if (coord[i] < minB[i] || coord[i] > maxB[i]) { return(false); } } else { coord[i] = candidatePlane[i]; } } result = new Vec3(coord[0], coord[1], num_dim == 3 ? coord[2] : 0); return(true); /* ray hits box */ }
public AABB(float min_x, float min_y, float min_z, float max_x, float max_y, float max_z) { min = new Vec3(min_x, min_y, min_z); max = new Vec3(max_x, max_y, max_z); }
public static bool FindPath <T>(T start, ref T end, Vec3 from, Vec3 to, MovementFlag flags, ref List <path_pos> path, float random_coeff = 0, bool allow_disconnected = false) where T : Cell { if (path != null) { path.Clear(); } //based on http://en.wikipedia.org/wiki/A*_search_algorithm List <NodeInfo> open = new List <NodeInfo>(); List <NodeInfo> closed = new List <NodeInfo>(); Random rng = new Random(); if (start == null || end == null) { return(false); } NodeInfo s = new NodeInfo(start, from, null, 0, from.Distance(to)); open.Add(s); while (open.Count > 0) { //sort by cost float min_total_cost = open.Min(x => x.TotalCost); NodeInfo best = open.Find(x => x.TotalCost.Equals(min_total_cost)); open.Remove(best); //take node with lower cost from open list NodeInfo info = best; if (info.cell == end) { BuildPath(start, end, from, to, info, ref path); return(true); } closed.Insert(0, info); foreach (Cell.Neighbour neighbour in info.cell.Neighbours) { Cell cell_neighbour = neighbour.cell; if (cell_neighbour.Disabled || (neighbour.connection_flags & flags) != flags) { continue; } Vec3 leading_point = neighbour.border_point != null ? neighbour.border_point : cell_neighbour.Center; NodeInfo info_neighbour = GetNodeInfoFromList(cell_neighbour, leading_point, closed); // if already processed then skip this neighbour if (info_neighbour != null) { continue; } float random_dist_mod = -random_coeff + (2 * random_coeff) * (float)rng.NextDouble(); float new_g = info.g + (info.leading_point.IsEmpty ? info.cell.Distance(leading_point) : info.leading_point.Distance(leading_point)) * (1 + random_dist_mod) * info.cell.MovementCostMult; bool is_better = false; info_neighbour = GetNodeInfoFromList(cell_neighbour, leading_point, open); // if not in open list if (info_neighbour == null) { info_neighbour = new NodeInfo(cell_neighbour, leading_point, null, 0, leading_point.Distance(to) * (1 + random_dist_mod) * info.cell.MovementCostMult); is_better = true; open.Insert(0, info_neighbour); } else if (new_g < info_neighbour.g) { is_better = true; } if (is_better) { info_neighbour.parent = info; info_neighbour.g = new_g; } } } if (allow_disconnected && closed.Count > 0) { float min_total_cost = closed.Min(x => x.h); NodeInfo best = closed.Find(x => x.h.Equals(min_total_cost)); end = (T)best.cell; BuildPath(start, end, from, to, best, ref path); return(true); } return(false); }
public AABB(Vec3 min, Vec3 max) { this.min = new Vec3(min); this.max = new Vec3(max); }
public static AABB Mininum(AABB aabb1, AABB aabb2) { return(new AABB(Vec3.Max(aabb1.min, aabb2.min), Vec3.Min(aabb1.max, aabb2.max))); }
public AABB(Vec3 min, Vec3 max) { Min = new Vec3(min); Max = new Vec3(max); }