summaryrefslogtreecommitdiff
path: root/scene/3d/navigation.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'scene/3d/navigation.cpp')
-rw-r--r--scene/3d/navigation.cpp85
1 files changed, 78 insertions, 7 deletions
diff --git a/scene/3d/navigation.cpp b/scene/3d/navigation.cpp
index ce002fb44b..ce28350be0 100644
--- a/scene/3d/navigation.cpp
+++ b/scene/3d/navigation.cpp
@@ -30,6 +30,7 @@ void Navigation::_navmesh_link(int p_id) {
p.edges.resize(plen);
Vector3 center;
+ float sum=0;
for(int j=0;j<plen;j++) {
@@ -44,8 +45,19 @@ void Navigation::_navmesh_link(int p_id) {
center+=ep;
e.point=_get_point(ep);
p.edges[j]=e;
+
+ if (j>=2) {
+ Vector3 epa = nm.xform.xform(r[indices[j-2]]);
+ Vector3 epb = nm.xform.xform(r[indices[j-1]]);
+
+ sum+=up.dot((epb-epa).cross(ep-epa));
+
+ }
+
}
+ p.clockwise=sum>0;
+
if (!valid) {
nm.polygons.pop_back();
ERR_CONTINUE(!valid);
@@ -73,9 +85,14 @@ void Navigation::_navmesh_link(int p_id) {
} else {
if (C->get().B!=NULL) {
- print_line(String()+_get_vertex(ek.a)+" -> "+_get_vertex(ek.b));
+ ConnectionPending pending;
+ pending.polygon=&p;
+ pending.edge=j;
+ p.edges[j].P=C->get().pending.push_back(pending);
+ continue;
+ //print_line(String()+_get_vertex(ek.a)+" -> "+_get_vertex(ek.b));
}
- ERR_CONTINUE(C->get().B!=NULL); //wut
+ //ERR_CONTINUE(C->get().B!=NULL); //wut
C->get().B=&p;
C->get().B_edge=j;
@@ -114,8 +131,13 @@ void Navigation::_navmesh_unlink(int p_id) {
EdgeKey ek(edges[i].point,edges[next].point);
Map<EdgeKey,Connection>::Element *C=connections.find(ek);
+
ERR_CONTINUE(!C);
- if (C->get().B) {
+
+ if (edges[i].P) {
+ C->get().pending.erase(edges[i].P);
+ edges[i].P=NULL;
+ } else if (C->get().B) {
//disconnect
C->get().B->edges[C->get().B_edge].C=NULL;
@@ -131,6 +153,20 @@ void Navigation::_navmesh_unlink(int p_id) {
C->get().B=NULL;
C->get().B_edge=-1;
+ if (C->get().pending.size()) {
+ //reconnect if something is pending
+ ConnectionPending cp = C->get().pending.front()->get();
+ C->get().pending.pop_front();
+
+ C->get().B=cp.polygon;
+ C->get().B_edge=cp.edge;
+ C->get().A->edges[C->get().A_edge].C=cp.polygon;
+ C->get().A->edges[C->get().A_edge].C_edge=cp.edge;
+ cp.polygon->edges[cp.edge].C=C->get().A;
+ cp.polygon->edges[cp.edge].C_edge=C->get().A_edge;
+ cp.polygon->edges[cp.edge].P=NULL;
+ }
+
} else {
connections.erase(C);
//erase
@@ -259,12 +295,14 @@ Vector<Vector3> Navigation::get_simple_path(const Vector3& p_start, const Vector
}
}
+
if (!begin_poly || !end_poly) {
//print_line("No Path Path");
return Vector<Vector3>(); //no path
}
+
if (begin_poly==end_poly) {
Vector<Vector3> path;
@@ -399,7 +437,8 @@ Vector<Vector3> Navigation::get_simple_path(const Vector3& p_start, const Vector
left = _get_vertex(p->edges[prev].point);
right = _get_vertex(p->edges[prev_n].point);
- if (CLOCK_TANGENT(apex_point,left,(left+right)*0.5).dot(up) < 0){
+ //if (CLOCK_TANGENT(apex_point,left,(left+right)*0.5).dot(up) < 0){
+ if (p->clockwise) {
SWAP(left,right);
}
}
@@ -490,10 +529,10 @@ Vector<Vector3> Navigation::get_simple_path(const Vector3& p_start, const Vector
}
-Vector3 Navigation::get_closest_point_to_segment(const Vector3& p_from,const Vector3& p_to) {
+Vector3 Navigation::get_closest_point_to_segment(const Vector3& p_from,const Vector3& p_to,const bool& p_use_collision) {
- bool use_collision=false;
+ bool use_collision=p_use_collision;
Vector3 closest_point;
float closest_point_d=1e20;
NavMesh *closest_navmesh=NULL;
@@ -614,6 +653,37 @@ Vector3 Navigation::get_closest_point_normal(const Vector3& p_point){
}
+Object* Navigation::get_closest_point_owner(const Vector3& p_point){
+
+ Vector3 closest_point;
+ Object *owner=NULL;
+ float closest_point_d=1e20;
+
+ for (Map<int,NavMesh>::Element*E=navmesh_map.front();E;E=E->next()) {
+
+ if (!E->get().linked)
+ continue;
+ for(List<Polygon>::Element *F=E->get().polygons.front();F;F=F->next()) {
+
+ Polygon &p=F->get();
+ for(int i=2;i<p.edges.size();i++) {
+
+ Face3 f(_get_vertex(p.edges[0].point),_get_vertex(p.edges[i-1].point),_get_vertex(p.edges[i].point));
+ Vector3 inters = f.get_closest_point_to(p_point);
+ float d = inters.distance_to(p_point);
+ if (d<closest_point_d) {
+ closest_point=inters;
+ closest_point_d=d;
+ owner=E->get().owner;
+ }
+ }
+ }
+ }
+
+ return owner;
+
+}
+
void Navigation::set_up_vector(const Vector3& p_up) {
@@ -633,9 +703,10 @@ void Navigation::_bind_methods() {
ObjectTypeDB::bind_method(_MD("navmesh_remove","id"),&Navigation::navmesh_remove);
ObjectTypeDB::bind_method(_MD("get_simple_path","start","end","optimize"),&Navigation::get_simple_path,DEFVAL(true));
- ObjectTypeDB::bind_method(_MD("get_closest_point_to_segment","start","end"),&Navigation::get_closest_point_to_segment);
+ ObjectTypeDB::bind_method(_MD("get_closest_point_to_segment","start","end","use_collision"),&Navigation::get_closest_point_to_segment,DEFVAL(false));
ObjectTypeDB::bind_method(_MD("get_closest_point","to_point"),&Navigation::get_closest_point);
ObjectTypeDB::bind_method(_MD("get_closest_point_normal","to_point"),&Navigation::get_closest_point_normal);
+ ObjectTypeDB::bind_method(_MD("get_closest_point_owner","to_point"),&Navigation::get_closest_point_owner);
ObjectTypeDB::bind_method(_MD("set_up_vector","up"),&Navigation::set_up_vector);
ObjectTypeDB::bind_method(_MD("get_up_vector"),&Navigation::get_up_vector);