diff options
author | Juan Linietsky <reduzio@gmail.com> | 2014-09-16 21:19:54 -0300 |
---|---|---|
committer | Juan Linietsky <reduzio@gmail.com> | 2014-09-16 21:19:54 -0300 |
commit | f00f4b9296a827ac1014cc2cc84b0dfbb4cac497 (patch) | |
tree | 57da76829a89ceb42d258865a3a4afb3cf51d5d4 /scene | |
parent | 642c63319eb7471c9accc0c50dfffef5d72c0078 (diff) |
CollisionPolygon (3D)
Workaround for round() on PC.
Diffstat (limited to 'scene')
-rw-r--r-- | scene/2d/collision_polygon_2d.cpp | 3 | ||||
-rw-r--r-- | scene/3d/collision_polygon.cpp | 206 | ||||
-rw-r--r-- | scene/3d/collision_polygon.h | 50 | ||||
-rw-r--r-- | scene/main/viewport.cpp | 1 | ||||
-rw-r--r-- | scene/register_scene_types.cpp | 3 |
5 files changed, 261 insertions, 2 deletions
diff --git a/scene/2d/collision_polygon_2d.cpp b/scene/2d/collision_polygon_2d.cpp index 5ab223a1b8..ef63286697 100644 --- a/scene/2d/collision_polygon_2d.cpp +++ b/scene/2d/collision_polygon_2d.cpp @@ -153,6 +153,7 @@ void CollisionPolygon2D::set_build_mode(BuildMode p_mode) { ERR_FAIL_INDEX(p_mode,2); build_mode=p_mode; + _update_parent(); } CollisionPolygon2D::BuildMode CollisionPolygon2D::get_build_mode() const{ @@ -174,7 +175,7 @@ void CollisionPolygon2D::_bind_methods() { ObjectTypeDB::bind_method(_MD("set_build_mode"),&CollisionPolygon2D::set_build_mode); ObjectTypeDB::bind_method(_MD("get_build_mode"),&CollisionPolygon2D::get_build_mode); - ADD_PROPERTY( PropertyInfo(Variant::INT,"build_mode",PROPERTY_HINT_ENUM,"Automatic,Segments,Solids"),_SCS("set_build_mode"),_SCS("get_build_mode")); + ADD_PROPERTY( PropertyInfo(Variant::INT,"build_mode",PROPERTY_HINT_ENUM,"Solids,Segments"),_SCS("set_build_mode"),_SCS("get_build_mode")); ADD_PROPERTY( PropertyInfo(Variant::VECTOR2_ARRAY,"polygon"),_SCS("set_polygon"),_SCS("get_polygon")); } diff --git a/scene/3d/collision_polygon.cpp b/scene/3d/collision_polygon.cpp new file mode 100644 index 0000000000..5a613f360a --- /dev/null +++ b/scene/3d/collision_polygon.cpp @@ -0,0 +1,206 @@ +#include "collision_polygon.h" + +#include "collision_object.h" +#include "scene/resources/concave_polygon_shape.h" +#include "scene/resources/convex_polygon_shape.h" + +void CollisionPolygon::_add_to_collision_object(Object *p_obj) { + + + CollisionObject *co = p_obj->cast_to<CollisionObject>(); + ERR_FAIL_COND(!co); + + if (polygon.size()==0) + return; + + bool solids=build_mode==BUILD_SOLIDS; + + Vector< Vector<Vector2> > decomp = Geometry::decompose_polygon(polygon); + if (decomp.size()==0) + return; + + if (true || solids) { + + //here comes the sun, lalalala + //decompose concave into multiple convex polygons and add them + for(int i=0;i<decomp.size();i++) { + Ref<ConvexPolygonShape> convex = memnew( ConvexPolygonShape ); + DVector<Vector3> cp; + int cs = decomp[i].size(); + cp.resize(cs*2); + { + DVector<Vector3>::Write w = cp.write(); + int idx=0; + for(int j=0;j<cs;j++) { + + Vector2 d = decomp[i][j]; + w[idx++]=Vector3(d.x,d.y,depth*0.5); + w[idx++]=Vector3(d.x,d.y,-depth*0.5); + } + } + + convex->set_points(cp); + co->add_shape(convex,get_transform()); + + } + + } else { +#if 0 + Ref<ConcavePolygonShape> concave = memnew( ConcavePolygonShape ); + + DVector<Vector2> segments; + segments.resize(polygon.size()*2); + DVector<Vector2>::Write w=segments.write(); + + for(int i=0;i<polygon.size();i++) { + w[(i<<1)+0]=polygon[i]; + w[(i<<1)+1]=polygon[(i+1)%polygon.size()]; + } + + w=DVector<Vector2>::Write(); + concave->set_segments(segments); + + co->add_shape(concave,get_transform()); +#endif + } + + + //co->add_shape(shape,get_transform()); + +} + +void CollisionPolygon::_update_parent() { + + Node *parent = get_parent(); + if (!parent) + return; + CollisionObject *co = parent->cast_to<CollisionObject>(); + if (!co) + return; + co->_update_shapes_from_children(); +} + +void CollisionPolygon::_notification(int p_what) { + + + switch(p_what) { + case NOTIFICATION_TRANSFORM_CHANGED: { + + if (!is_inside_scene()) + break; + _update_parent(); + + } break; +#if 0 + case NOTIFICATION_DRAW: { + for(int i=0;i<polygon.size();i++) { + + Vector2 p = polygon[i]; + Vector2 n = polygon[(i+1)%polygon.size()]; + draw_line(p,n,Color(0,0.6,0.7,0.5),3); + } + + Vector< Vector<Vector2> > decomp = Geometry::decompose_polygon(polygon); +#define DEBUG_DECOMPOSE +#ifdef DEBUG_DECOMPOSE + Color c(0.4,0.9,0.1); + for(int i=0;i<decomp.size();i++) { + + c.set_hsv( Math::fmod(c.get_h() + 0.738,1),c.get_s(),c.get_v(),0.5); + draw_colored_polygon(decomp[i],c); + } +#endif + + } break; +#endif + } +} + +void CollisionPolygon::set_polygon(const Vector<Point2>& p_polygon) { + + polygon=p_polygon; + + for(int i=0;i<polygon.size();i++) { + + Vector3 p1(polygon[i].x,polygon[i].y,depth*0.5); + + if (i==0) + aabb=AABB(p1,Vector3()); + else + aabb.expand_to(p1); + + Vector3 p2(polygon[i].x,polygon[i].y,-depth*0.5); + aabb.expand_to(p2); + + + } + if (aabb==AABB()) { + + aabb=AABB(Vector3(-1,-1,-1),Vector3(2,2,2)); + } else { + aabb.pos-=aabb.size*0.3; + aabb.size+=aabb.size*0.6; + } + _update_parent(); + update_gizmo(); +} + +Vector<Point2> CollisionPolygon::get_polygon() const { + + return polygon; +} + +void CollisionPolygon::set_build_mode(BuildMode p_mode) { + + ERR_FAIL_INDEX(p_mode,2); + build_mode=p_mode; + _update_parent(); +} + +CollisionPolygon::BuildMode CollisionPolygon::get_build_mode() const{ + + return build_mode; +} + +AABB CollisionPolygon::get_item_rect() const { + + return aabb; +} + +void CollisionPolygon::set_depth(float p_depth) { + + depth=p_depth; + _update_parent(); + update_gizmo(); +} + +float CollisionPolygon::get_depth() const { + + return depth; +} + + +void CollisionPolygon::_bind_methods() { + + ObjectTypeDB::bind_method(_MD("_add_to_collision_object"),&CollisionPolygon::_add_to_collision_object); + ObjectTypeDB::bind_method(_MD("set_polygon","polygon"),&CollisionPolygon::set_polygon); + ObjectTypeDB::bind_method(_MD("get_polygon"),&CollisionPolygon::get_polygon); + + ObjectTypeDB::bind_method(_MD("set_depth","depth"),&CollisionPolygon::set_depth); + ObjectTypeDB::bind_method(_MD("get_depth"),&CollisionPolygon::get_depth); + + ObjectTypeDB::bind_method(_MD("set_build_mode"),&CollisionPolygon::set_build_mode); + ObjectTypeDB::bind_method(_MD("get_build_mode"),&CollisionPolygon::get_build_mode); + + ADD_PROPERTY( PropertyInfo(Variant::INT,"build_mode",PROPERTY_HINT_ENUM,"Solids,Triangles"),_SCS("set_build_mode"),_SCS("get_build_mode")); + ADD_PROPERTY( PropertyInfo(Variant::VECTOR2_ARRAY,"polygon"),_SCS("set_polygon"),_SCS("get_polygon")); + ADD_PROPERTY( PropertyInfo(Variant::REAL,"depth"),_SCS("set_depth"),_SCS("get_depth")); +} + +CollisionPolygon::CollisionPolygon() { + + aabb=AABB(Vector3(-1,-1,-1),Vector3(2,2,2)); + build_mode=BUILD_SOLIDS; + depth=1.0; + +} diff --git a/scene/3d/collision_polygon.h b/scene/3d/collision_polygon.h new file mode 100644 index 0000000000..efb3666778 --- /dev/null +++ b/scene/3d/collision_polygon.h @@ -0,0 +1,50 @@ +#ifndef COLLISION_POLYGON_H +#define COLLISION_POLYGON_H + +#include "scene/3d/spatial.h" +#include "scene/resources/shape.h" + + + +class CollisionPolygon : public Spatial { + + OBJ_TYPE(CollisionPolygon,Spatial); +public: + + enum BuildMode { + BUILD_SOLIDS, + BUILD_TRIANGLES, + }; + +protected: + + + float depth; + AABB aabb; + BuildMode build_mode; + Vector<Point2> polygon; + + void _add_to_collision_object(Object *p_obj); + void _update_parent(); + +protected: + + void _notification(int p_what); + static void _bind_methods(); +public: + + void set_build_mode(BuildMode p_mode); + BuildMode get_build_mode() const; + + void set_depth(float p_depth); + float get_depth() const; + + void set_polygon(const Vector<Point2>& p_polygon); + Vector<Point2> get_polygon() const; + + virtual AABB get_item_rect() const; + CollisionPolygon(); +}; + +VARIANT_ENUM_CAST( CollisionPolygon::BuildMode ); +#endif // COLLISION_POLYGON_H diff --git a/scene/main/viewport.cpp b/scene/main/viewport.cpp index 83dd64c31d..92dcef803c 100644 --- a/scene/main/viewport.cpp +++ b/scene/main/viewport.cpp @@ -1252,6 +1252,7 @@ void Viewport::_bind_methods() { ObjectTypeDB::bind_method(_MD("set_use_own_world","enable"), &Viewport::set_use_own_world); ObjectTypeDB::bind_method(_MD("is_using_own_world"), &Viewport::is_using_own_world); + ObjectTypeDB::bind_method(_MD("get_camera:Camera"), &Viewport::get_camera); ObjectTypeDB::bind_method(_MD("set_as_audio_listener","enable"), &Viewport::set_as_audio_listener); ObjectTypeDB::bind_method(_MD("is_audio_listener","enable"), &Viewport::is_audio_listener); diff --git a/scene/register_scene_types.cpp b/scene/register_scene_types.cpp index 804c6c6f34..08e6ff2e54 100644 --- a/scene/register_scene_types.cpp +++ b/scene/register_scene_types.cpp @@ -199,7 +199,7 @@ #include "scene/3d/proximity_group.h" #include "scene/3d/navigation_mesh.h" #include "scene/3d/navigation.h" - +#include "scene/3d/collision_polygon.h" #endif #include "scene/scene_binds.h" @@ -409,6 +409,7 @@ void register_scene_types() { ObjectTypeDB::register_type<Area>(); ObjectTypeDB::register_type<ProximityGroup>(); ObjectTypeDB::register_type<CollisionShape>(); + ObjectTypeDB::register_type<CollisionPolygon>(); ObjectTypeDB::register_type<RayCast>(); ObjectTypeDB::register_virtual_type<EditableShape>(); ObjectTypeDB::register_type<EditableSphere>(); |