diff options
Diffstat (limited to 'scene/3d')
-rw-r--r-- | scene/3d/navigation.cpp | 497 | ||||
-rw-r--r-- | scene/3d/navigation.h | 132 | ||||
-rw-r--r-- | scene/3d/navigation_agent.cpp | 5 | ||||
-rw-r--r-- | scene/3d/navigation_agent.h | 10 | ||||
-rw-r--r-- | scene/3d/navigation_mesh.cpp | 237 | ||||
-rw-r--r-- | scene/3d/navigation_mesh.h | 68 | ||||
-rw-r--r-- | scene/3d/visual_instance.cpp | 17 | ||||
-rw-r--r-- | scene/3d/visual_instance.h | 4 |
8 files changed, 970 insertions, 0 deletions
diff --git a/scene/3d/navigation.cpp b/scene/3d/navigation.cpp new file mode 100644 index 0000000000..4b0d233fbe --- /dev/null +++ b/scene/3d/navigation.cpp @@ -0,0 +1,497 @@ +#include "navigation.h" + +void Navigation::_navmesh_link(int p_id) { + + ERR_FAIL_COND(!navmesh_map.has(p_id)); + NavMesh &nm=navmesh_map[p_id]; + ERR_FAIL_COND(nm.linked); + + print_line("LINK"); + + DVector<Vector3> vertices=nm.navmesh->get_vertices(); + int len = vertices.size(); + if (len==0) + return; + + DVector<Vector3>::Read r=vertices.read(); + + for(int i=0;i<nm.navmesh->get_polygon_count();i++) { + + //build + + List<Polygon>::Element *P=nm.polygons.push_back(Polygon()); + Polygon &p=P->get(); + + Vector<int> poly = nm.navmesh->get_polygon(i); + int plen=poly.size(); + const int *indices=poly.ptr(); + bool valid=true; + p.edges.resize(plen); + + Vector3 center; + + for(int j=0;j<plen;j++) { + + int idx = indices[j]; + if (idx<0 || idx>=len) { + valid=false; + break; + } + + Polygon::Edge e; + Vector3 ep=nm.xform.xform(r[idx]); + center+=ep; + e.point=_get_point(ep); + p.edges[j]=e; + } + + if (!valid) { + nm.polygons.pop_back(); + ERR_CONTINUE(!valid); + continue; + } + + p.center=center/plen; + + //connect + + for(int j=0;j<plen;j++) { + + int next = (j+1)%plen; + EdgeKey ek(p.edges[j].point,p.edges[next].point); + + Map<EdgeKey,Connection>::Element *C=connections.find(ek); + if (!C) { + + Connection c; + c.A=&p; + c.A_edge=j; + c.B=NULL; + c.B_edge=-1; + connections[ek]=c; + } else { + + if (C->get().B!=NULL) { + print_line(String()+_get_vertex(ek.a)+" -> "+_get_vertex(ek.b)); + } + ERR_CONTINUE(C->get().B!=NULL); //wut + + C->get().B=&p; + C->get().B_edge=j; + C->get().A->edges[C->get().A_edge].C=&p; + C->get().A->edges[C->get().A_edge].C_edge=j;; + p.edges[j].C=C->get().A; + p.edges[j].C_edge=C->get().A_edge; + //connection successful. + } + } + } + + nm.linked=true; + +} + + +void Navigation::_navmesh_unlink(int p_id) { + + ERR_FAIL_COND(!navmesh_map.has(p_id)); + NavMesh &nm=navmesh_map[p_id]; + ERR_FAIL_COND(!nm.linked); + + print_line("UNLINK"); + + for (List<Polygon>::Element *E=nm.polygons.front();E;E=E->next()) { + + + Polygon &p=E->get(); + + int ec = p.edges.size(); + Polygon::Edge *edges=p.edges.ptr(); + + for(int i=0;i<ec;i++) { + int next = (i+1)%ec; + + EdgeKey ek(edges[i].point,edges[next].point); + Map<EdgeKey,Connection>::Element *C=connections.find(ek); + ERR_CONTINUE(!C); + if (C->get().B) { + //disconnect + + C->get().B->edges[C->get().B_edge].C=NULL; + C->get().B->edges[C->get().B_edge].C_edge=-1; + C->get().A->edges[C->get().A_edge].C=NULL; + C->get().A->edges[C->get().A_edge].C_edge=-1; + + if (C->get().A==&E->get()) { + + C->get().A=C->get().B; + C->get().A_edge=C->get().B_edge; + } + C->get().B=NULL; + C->get().B_edge=-1; + + } else { + connections.erase(C); + //erase + } + } + } + + nm.polygons.clear(); + + nm.linked=false; + + +} + + +int Navigation::navmesh_create(const Ref<NavigationMesh>& p_mesh,const Transform& p_xform) { + + int id = last_id++; + NavMesh nm; + nm.linked=false; + nm.navmesh=p_mesh; + nm.xform=p_xform; + navmesh_map[id]=nm; + + _navmesh_link(id); + + return id; +} + +void Navigation::navmesh_set_transform(int p_id, const Transform& p_xform){ + + ERR_FAIL_COND(!navmesh_map.has(p_id)); + NavMesh &nm=navmesh_map[p_id]; + if (nm.xform==p_xform) + return; //bleh + _navmesh_unlink(p_id); + nm.xform=p_xform; + _navmesh_link(p_id); + + + +} +void Navigation::navmesh_remove(int p_id){ + + ERR_FAIL_COND(!navmesh_map.has(p_id)); + _navmesh_unlink(p_id); + navmesh_map.erase(p_id); + +} + +Vector<Vector3> Navigation::get_simple_path(const Vector3& p_start, const Vector3& p_end) { + + + Polygon *begin_poly=NULL; + Polygon *end_poly=NULL; + Vector3 begin_point; + Vector3 end_point; + float begin_d=1e20; + float end_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 spoint = f.get_closest_point_to(p_start); + float dpoint = spoint.distance_to(p_start); + if (dpoint<begin_d) { + begin_d=dpoint; + begin_poly=&p; + begin_point=spoint; + } + + spoint = f.get_closest_point_to(p_end); + dpoint = spoint.distance_to(p_end); + if (dpoint<end_d) { + end_d=dpoint; + end_poly=&p; + end_point=spoint; + } + } + + p.prev_edge=-1; + } + } + + if (!begin_poly || !end_poly) { + + //print_line("No Path Path"); + return Vector<Vector3>(); //no path + } + + if (begin_poly==end_poly) { + + Vector<Vector3> path; + path.resize(2); + path[0]=begin_point; + path[1]=end_point; + //print_line("Direct Path"); + return path; + } + + + bool found_route=false; + + List<Polygon*> open_list; + + for(int i=0;i<begin_poly->edges.size();i++) { + + if (begin_poly->edges[i].C) { + + begin_poly->edges[i].C->prev_edge=begin_poly->edges[i].C_edge; + begin_poly->edges[i].C->distance=begin_poly->center.distance_to(begin_poly->edges[i].C->center); + open_list.push_back(begin_poly->edges[i].C); + + if (begin_poly->edges[i].C==end_poly) { + found_route=true; + } + } + } + + + while(!found_route) { + + if (open_list.size()==0) { + // print_line("NOU OPEN LIST"); + break; + } + //check open list + + List<Polygon*>::Element *least_cost_poly=NULL; + float least_cost=1e30; + + //this could be faster (cache previous results) + for (List<Polygon*>::Element *E=open_list.front();E;E=E->next()) { + + Polygon *p=E->get(); + + + float cost=p->distance; + cost+=p->center.distance_to(end_point); + + if (cost<least_cost) { + + least_cost_poly=E; + least_cost=cost; + } + } + + + Polygon *p=least_cost_poly->get(); + //open the neighbours for search + + for(int i=0;i<p->edges.size();i++) { + + + Polygon::Edge &e=p->edges[i]; + + if (!e.C) + continue; + + float distance = p->center.distance_to(e.C->center) + p->distance; + + if (e.C->prev_edge!=-1) { + //oh this was visited already, can we win the cost? + + if (e.C->distance>distance) { + + e.C->prev_edge=e.C_edge; + e.C->distance=distance; + } + } else { + //add to open neighbours + + e.C->prev_edge=e.C_edge; + e.C->distance=distance; + open_list.push_back(e.C); + + if (e.C==end_poly) { + //oh my reached end! stop algorithm + found_route=true; + break; + + } + + } + } + + if (found_route) + break; + + open_list.erase(least_cost_poly); + } + + if (found_route) { + + //use midpoints for now + Polygon *p=end_poly; + Vector<Vector3> path; + path.push_back(end_point); + while(true) { + int prev = p->prev_edge; + int prev_n = (p->prev_edge+1)%p->edges.size(); + Vector3 point = (_get_vertex(p->edges[prev].point) + _get_vertex(p->edges[prev_n].point))*0.5; + path.push_back(point); + p = p->edges[prev].C; + if (p==begin_poly) + break; + } + + path.push_back(begin_point); + + + path.invert();; + + return path; + } + + + return Vector<Vector3>(); + +} + +Vector3 Navigation::get_closest_point_to_segment(const Vector3& p_from,const Vector3& p_to) { + + + bool use_collision=false; + Vector3 closest_point; + 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; + if (f.intersects_segment(p_from,p_to,&inters)) { + + if (!use_collision) { + closest_point=inters; + use_collision=true; + closest_point_d=p_from.distance_to(inters); + } else if (closest_point_d > inters.distance_to(p_from)){ + + closest_point=inters; + closest_point_d=p_from.distance_to(inters); + } + } + } + + if (!use_collision) { + + for(int i=0;i<p.edges.size();i++) { + + Vector3 a,b; + + Geometry::get_closest_points_between_segments(p_from,p_to,_get_vertex(p.edges[i].point),_get_vertex(p.edges[(i+1)%p.edges.size()].point),a,b); + + float d = a.distance_to(b); + if (d<closest_point_d) { + + closest_point_d=d; + closest_point=b; + } + + } + } + } + } + + return closest_point; +} + +Vector3 Navigation::get_closest_point(const Vector3& p_point) { + + Vector3 closest_point; + 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; + } + } + } + } + + return closest_point; + +} + +Vector3 Navigation::get_closest_point_normal(const Vector3& p_point){ + + Vector3 closest_point; + Vector3 closest_normal; + 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; + closest_normal=f.get_plane().normal; + } + } + } + } + + return closest_normal; + +} + + +void Navigation::_bind_methods() { + + ObjectTypeDB::bind_method(_MD("navmesh_create","mesh:NavigationMesh","xform"),&Navigation::navmesh_create); + ObjectTypeDB::bind_method(_MD("navmesh_set_transform","id","xform"),&Navigation::navmesh_set_transform); + ObjectTypeDB::bind_method(_MD("navmesh_remove","id"),&Navigation::navmesh_remove); + + ObjectTypeDB::bind_method(_MD("get_simple_path","start","end"),&Navigation::get_simple_path); + 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_point"),&Navigation::get_closest_point); + ObjectTypeDB::bind_method(_MD("get_closest_point_normal","to_point"),&Navigation::get_closest_point_normal); + +} + +Navigation::Navigation() { + + ERR_FAIL_COND( sizeof(Point)!=8 ); + cell_size=0.01; //one centimeter + last_id=1; +} + diff --git a/scene/3d/navigation.h b/scene/3d/navigation.h new file mode 100644 index 0000000000..40f474858c --- /dev/null +++ b/scene/3d/navigation.h @@ -0,0 +1,132 @@ +#ifndef NAVIGATION_H +#define NAVIGATION_H + +#include "scene/3d/spatial.h" +#include "scene/3d/navigation_mesh.h" + +class Navigation : public Spatial { + + OBJ_TYPE( Navigation, Spatial); + + + union Point { + + struct { + int64_t x:21; + int64_t y:22; + int64_t z:21; + }; + + uint64_t key; + bool operator<(const Point& p_key) const { return key < p_key.key; } + }; + + + struct EdgeKey { + + Point a; + Point b; + + bool operator<(const EdgeKey& p_key) const { + return (a.key==p_key.a.key)?(b.key<p_key.b.key):(a.key<p_key.a.key); + }; + + EdgeKey(const Point& p_a=Point(),const Point& p_b=Point()) { + a=p_a; + b=p_b; + if (a.key > b.key) { + SWAP(a,b); + } + } + }; + + + + struct Polygon { + + struct Edge { + Point point; + Polygon *C; //connection + int C_edge; + Edge() { C=NULL; C_edge=-1; } + }; + + Vector<Edge> edges; + + Vector3 center; + + float distance; + int prev_edge; + }; + + + struct Connection { + + Polygon *A; + int A_edge; + Polygon *B; + int B_edge; + Connection() { A=NULL; B=NULL; A_edge=-1; B_edge=-1;} + }; + + Map<EdgeKey,Connection> connections; + + + struct NavMesh { + + Transform xform; + bool linked; + Ref<NavigationMesh> navmesh; + List<Polygon> polygons; + + }; + + + + _FORCE_INLINE_ Point _get_point(const Vector3& p_pos) const { + + int x = int(Math::floor(p_pos.x/cell_size)); + int y = int(Math::floor(p_pos.y/cell_size)); + int z = int(Math::floor(p_pos.z/cell_size)); + + Point p; + p.key=0; + p.x=x; + p.y=y; + p.z=z; + return p; + + } + + _FORCE_INLINE_ Vector3 _get_vertex(const Point& p_point) const { + + return Vector3(p_point.x,p_point.y,p_point.z)*cell_size; + } + + void _navmesh_link(int p_id); + void _navmesh_unlink(int p_id); + + float cell_size; + Map<int,NavMesh> navmesh_map; + int last_id; + +protected: + + static void _bind_methods(); + +public: + + //API should be as dynamic as possible + int navmesh_create(const Ref<NavigationMesh>& p_mesh,const Transform& p_xform); + void navmesh_set_transform(int p_id, const Transform& p_xform); + void navmesh_remove(int p_id); + + Vector<Vector3> get_simple_path(const Vector3& p_start, const Vector3& p_end); + Vector3 get_closest_point_to_segment(const Vector3& p_from,const Vector3& p_to); + Vector3 get_closest_point(const Vector3& p_point); + Vector3 get_closest_point_normal(const Vector3& p_point); + + Navigation(); +}; + +#endif // NAVIGATION_H diff --git a/scene/3d/navigation_agent.cpp b/scene/3d/navigation_agent.cpp new file mode 100644 index 0000000000..9b304e45ec --- /dev/null +++ b/scene/3d/navigation_agent.cpp @@ -0,0 +1,5 @@ +#include "navigation_agent.h" + +NavigationAgent::NavigationAgent() +{ +} diff --git a/scene/3d/navigation_agent.h b/scene/3d/navigation_agent.h new file mode 100644 index 0000000000..baceb693a5 --- /dev/null +++ b/scene/3d/navigation_agent.h @@ -0,0 +1,10 @@ +#ifndef NAVIGATION_AGENT_H +#define NAVIGATION_AGENT_H + +class NavigationAgent +{ +public: + NavigationAgent(); +}; + +#endif // NAVIGATION_AGENT_H diff --git a/scene/3d/navigation_mesh.cpp b/scene/3d/navigation_mesh.cpp new file mode 100644 index 0000000000..cf2e22a573 --- /dev/null +++ b/scene/3d/navigation_mesh.cpp @@ -0,0 +1,237 @@ +#include "navigation_mesh.h" +#include "navigation.h" + + +void NavigationMesh::create_from_mesh(const Ref<Mesh>& p_mesh) { + + + vertices=DVector<Vector3>(); + clear_polygons(); + + for(int i=0;i<p_mesh->get_surface_count();i++) { + + if (p_mesh->surface_get_primitive_type(i)!=Mesh::PRIMITIVE_TRIANGLES) + continue; + Array arr = p_mesh->surface_get_arrays(i); + DVector<Vector3> varr = arr[Mesh::ARRAY_VERTEX]; + DVector<int> iarr = arr[Mesh::ARRAY_INDEX]; + if (varr.size()==0 || iarr.size()==0) + continue; + + int from = vertices.size(); + vertices.append_array(varr); + int rlen = iarr.size(); + DVector<int>::Read r = iarr.read(); + + for(int j=0;j<rlen;j+=3) { + Vector<int> vi; + vi.resize(3); + vi[0]=r[j+0]+from; + vi[1]=r[j+1]+from; + vi[2]=r[j+2]+from; + + add_polygon(vi); + } + } +} + +void NavigationMesh::set_vertices(const DVector<Vector3>& p_vertices) { + + vertices=p_vertices; +} + +DVector<Vector3> NavigationMesh::get_vertices() const{ + + return vertices; +} + + +void NavigationMesh::_set_polygons(const Array& p_array) { + + polygons.resize(p_array.size()); + for(int i=0;i<p_array.size();i++) { + polygons[i].indices=p_array[i]; + } +} + +Array NavigationMesh::_get_polygons() const { + + Array ret; + ret.resize(polygons.size()); + for(int i=0;i<ret.size();i++) { + ret[i]=polygons[i].indices; + } + + return ret; +} + + +void NavigationMesh::add_polygon(const Vector<int>& p_polygon){ + + Polygon polygon; + polygon.indices=p_polygon; + polygons.push_back(polygon); + +} +int NavigationMesh::get_polygon_count() const{ + + return polygons.size(); +} +Vector<int> NavigationMesh::get_polygon(int p_idx){ + + ERR_FAIL_INDEX_V(p_idx,polygons.size(),Vector<int>()); + return polygons[p_idx].indices; +} +void NavigationMesh::clear_polygons(){ + + polygons.clear(); +} + +void NavigationMesh::_bind_methods() { + + ObjectTypeDB::bind_method(_MD("set_vertices","vertices"),&NavigationMesh::set_vertices); + ObjectTypeDB::bind_method(_MD("get_vertices"),&NavigationMesh::get_vertices); + + ObjectTypeDB::bind_method(_MD("add_polygon","polygon"),&NavigationMesh::add_polygon); + ObjectTypeDB::bind_method(_MD("get_polygon_count"),&NavigationMesh::get_polygon_count); + ObjectTypeDB::bind_method(_MD("get_polygon","idx"),&NavigationMesh::get_polygon); + ObjectTypeDB::bind_method(_MD("clear_polygons"),&NavigationMesh::clear_polygons); + + ObjectTypeDB::bind_method(_MD("_set_polygons","polygons"),&NavigationMesh::_set_polygons); + ObjectTypeDB::bind_method(_MD("_get_polygons"),&NavigationMesh::_get_polygons); + + ADD_PROPERTY(PropertyInfo(Variant::VECTOR3_ARRAY,"vertices",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR),_SCS("set_vertices"),_SCS("get_vertices")); + ADD_PROPERTY(PropertyInfo(Variant::ARRAY,"polygons",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR),_SCS("_set_polygons"),_SCS("_get_polygons")); +} + +NavigationMesh::NavigationMesh() { + +} + +void NavigationMeshInstance::set_enabled(bool p_enabled) { + + if (enabled==p_enabled) + return; + enabled=p_enabled; + + if (!is_inside_scene()) + return; + + if (!enabled) { + + if (nav_id!=-1) { + navigation->navmesh_remove(nav_id); + nav_id=-1; + } + } else { + + if (navigation) { + + if (navmesh.is_valid()) { + + nav_id = navigation->navmesh_create(navmesh,get_relative_transform(navigation)); + } + } + + } + + update_gizmo(); +} + +bool NavigationMeshInstance::is_enabled() const { + + + return enabled; +} + + +///////////////////////////// + + +void NavigationMeshInstance::_notification(int p_what) { + + + switch(p_what) { + case NOTIFICATION_ENTER_SCENE: { + + Spatial *c=this; + while(c) { + + navigation=c->cast_to<Navigation>(); + if (navigation) { + + if (enabled && navmesh.is_valid()) { + + nav_id = navigation->navmesh_create(navmesh,get_relative_transform(navigation)); + } + break; + } + + c=c->get_parent_spatial(); + } + + } break; + case NOTIFICATION_TRANSFORM_CHANGED: { + + if (navigation && nav_id!=-1) { + navigation->navmesh_set_transform(nav_id,get_relative_transform(navigation)); + } + + } break; + case NOTIFICATION_EXIT_SCENE: { + + if (navigation) { + + if (nav_id!=-1) { + navigation->navmesh_remove(nav_id); + nav_id=-1; + } + } + navigation=NULL; + } break; + } +} + + +void NavigationMeshInstance::set_navigation_mesh(const Ref<NavigationMesh>& p_navmesh) { + + if (p_navmesh==navmesh) + return; + + if (navigation && nav_id!=-1) { + navigation->navmesh_remove(nav_id); + nav_id=-1; + } + navmesh=p_navmesh; + + if (navigation && navmesh.is_valid() && enabled) { + nav_id = navigation->navmesh_create(navmesh,get_relative_transform(navigation)); + } + update_gizmo(); + +} + +Ref<NavigationMesh> NavigationMeshInstance::get_navigation_mesh() const{ + + return navmesh; +} + +void NavigationMeshInstance::_bind_methods() { + + ObjectTypeDB::bind_method(_MD("set_navigation_mesh","navmesh"),&NavigationMeshInstance::set_navigation_mesh); + ObjectTypeDB::bind_method(_MD("get_navigation_mesh"),&NavigationMeshInstance::get_navigation_mesh); + + ObjectTypeDB::bind_method(_MD("set_enabled","enabled"),&NavigationMeshInstance::set_enabled); + ObjectTypeDB::bind_method(_MD("is_enabled"),&NavigationMeshInstance::is_enabled); + + ADD_PROPERTY( PropertyInfo(Variant::OBJECT,"navmesh",PROPERTY_HINT_RESOURCE_TYPE,"NavigationMesh"),_SCS("set_navigation_mesh"),_SCS("get_navigation_mesh")); + ADD_PROPERTY( PropertyInfo(Variant::BOOL,"enabled"),_SCS("set_enabled"),_SCS("is_enabled")); +} + +NavigationMeshInstance::NavigationMeshInstance() { + + navigation=NULL; + nav_id=-1; + enabled=true; + +} diff --git a/scene/3d/navigation_mesh.h b/scene/3d/navigation_mesh.h new file mode 100644 index 0000000000..fccf405f9d --- /dev/null +++ b/scene/3d/navigation_mesh.h @@ -0,0 +1,68 @@ +#ifndef NAVIGATION_MESH_H +#define NAVIGATION_MESH_H + +#include "scene/3d/spatial.h" +#include "scene/resources/mesh.h" + + +class NavigationMesh : public Resource { + + OBJ_TYPE( NavigationMesh, Resource ); + + DVector<Vector3> vertices; + struct Polygon { + Vector<int> indices; + }; + Vector<Polygon> polygons; + +protected: + + static void _bind_methods(); + + void _set_polygons(const Array& p_array); + Array _get_polygons() const; +public: + + void create_from_mesh(const Ref<Mesh>& p_mesh); + + void set_vertices(const DVector<Vector3>& p_vertices); + DVector<Vector3> get_vertices() const; + + void add_polygon(const Vector<int>& p_polygon); + int get_polygon_count() const; + Vector<int> get_polygon(int p_idx); + void clear_polygons(); + + NavigationMesh(); +}; + + +class Navigation; + +class NavigationMeshInstance : public Spatial { + + OBJ_TYPE(NavigationMeshInstance,Spatial); + + bool enabled; + int nav_id; + Navigation *navigation; + Ref<NavigationMesh> navmesh; +protected: + + void _notification(int p_what); + static void _bind_methods(); +public: + + + + void set_enabled(bool p_enabled); + bool is_enabled() const; + + void set_navigation_mesh(const Ref<NavigationMesh>& p_navmesh); + Ref<NavigationMesh> get_navigation_mesh() const; + + NavigationMeshInstance(); +}; + + +#endif // NAVIGATION_MESH_H diff --git a/scene/3d/visual_instance.cpp b/scene/3d/visual_instance.cpp index 625da9b093..d6c46f9bf6 100644 --- a/scene/3d/visual_instance.cpp +++ b/scene/3d/visual_instance.cpp @@ -276,6 +276,18 @@ bool GeometryInstance::get_flag(Flags p_flag) const{ } +void GeometryInstance::set_baked_light_texture_id(int p_id) { + + baked_light_texture_id=p_id; + VS::get_singleton()->instance_geometry_set_baked_light_texture_index(get_instance(),baked_light_texture_id); + +} + +int GeometryInstance::get_baked_light_texture_id() const{ + + return baked_light_texture_id; +} + void GeometryInstance::_bind_methods() { @@ -291,6 +303,9 @@ void GeometryInstance::_bind_methods() { ObjectTypeDB::bind_method(_MD("set_draw_range_end","mode"), &GeometryInstance::set_draw_range_end); ObjectTypeDB::bind_method(_MD("get_draw_range_end"), &GeometryInstance::get_draw_range_end); + ObjectTypeDB::bind_method(_MD("set_baked_light_texture_id","id"), &GeometryInstance::set_baked_light_texture_id); + ObjectTypeDB::bind_method(_MD("get_baked_light_texture_id"), &GeometryInstance::get_baked_light_texture_id); + ObjectTypeDB::bind_method(_MD("_baked_light_changed"), &GeometryInstance::_baked_light_changed); ADD_PROPERTYI( PropertyInfo( Variant::BOOL, "geometry/visible"), _SCS("set_flag"), _SCS("get_flag"),FLAG_VISIBLE); @@ -304,6 +319,7 @@ void GeometryInstance::_bind_methods() { ADD_PROPERTYI( PropertyInfo( Variant::BOOL, "geometry/depth_scale"), _SCS("set_flag"), _SCS("get_flag"),FLAG_DEPH_SCALE); ADD_PROPERTYI( PropertyInfo( Variant::BOOL, "geometry/visible_in_all_rooms"), _SCS("set_flag"), _SCS("get_flag"),FLAG_VISIBLE_IN_ALL_ROOMS); ADD_PROPERTYI( PropertyInfo( Variant::BOOL, "geometry/use_baked_light"), _SCS("set_flag"), _SCS("get_flag"),FLAG_USE_BAKED_LIGHT); + ADD_PROPERTY( PropertyInfo( Variant::INT, "geometry/baked_light_tex_id"), _SCS("set_baked_light_texture_id"), _SCS("get_baked_light_texture_id")); ADD_SIGNAL( MethodInfo("visibility_changed")); @@ -329,6 +345,7 @@ GeometryInstance::GeometryInstance() { flags[FLAG_DEPH_SCALE]=false; flags[FLAG_VISIBLE_IN_ALL_ROOMS]=false; baked_light_instance=NULL; + baked_light_texture_id=0; } diff --git a/scene/3d/visual_instance.h b/scene/3d/visual_instance.h index 1cf96d5d9e..4b4e1e391b 100644 --- a/scene/3d/visual_instance.h +++ b/scene/3d/visual_instance.h @@ -106,6 +106,7 @@ private: float draw_end; void _find_baked_light(); BakedLightInstance *baked_light_instance; + int baked_light_texture_id; void _baked_light_changed(); protected: @@ -126,6 +127,9 @@ public: void set_material_override(const Ref<Material>& p_material); Ref<Material> get_material_override() const; + void set_baked_light_texture_id(int p_id); + int get_baked_light_texture_id() const; + GeometryInstance(); }; |