Browse Source

added cylinder shape support

muiroc 7 years ago
parent
commit
0a36e974da

+ 25 - 0
doc/classes/CylinderShape.xml

@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<class name="CylinderShape" inherits="Shape" category="Core" version="3.1">
+	<brief_description>
+		Cylinder shape for collisions.
+	</brief_description>
+	<description>
+		Cylinder shape for collisions.
+	</description>
+	<tutorials>
+	</tutorials>
+	<demos>
+	</demos>
+	<methods>
+	</methods>
+	<members>
+		<member name="height" type="float" setter="set_height" getter="get_height">
+			The cylinder's height.
+		</member>
+		<member name="radius" type="float" setter="set_radius" getter="get_radius">
+			The cylinder's radius.
+		</member>
+	</members>
+	<constants>
+	</constants>
+</class>

+ 7 - 4
doc/classes/PhysicsServer.xml

@@ -1413,16 +1413,19 @@
 		<constant name="SHAPE_CAPSULE" value="4" enum="ShapeType">
 		<constant name="SHAPE_CAPSULE" value="4" enum="ShapeType">
 			The [Shape] is a [CapsuleShape].
 			The [Shape] is a [CapsuleShape].
 		</constant>
 		</constant>
-		<constant name="SHAPE_CONVEX_POLYGON" value="5" enum="ShapeType">
+		<constant name="SHAPE_CYLINDER" value="5" enum="ShapeType">
+			The [Shape] is a [CylinderShape].
+		</constant>
+		<constant name="SHAPE_CONVEX_POLYGON" value="6" enum="ShapeType">
 			The [Shape] is a [ConvexPolygonShape].
 			The [Shape] is a [ConvexPolygonShape].
 		</constant>
 		</constant>
-		<constant name="SHAPE_CONCAVE_POLYGON" value="6" enum="ShapeType">
+		<constant name="SHAPE_CONCAVE_POLYGON" value="7" enum="ShapeType">
 			The [Shape] is a [ConcavePolygonShape].
 			The [Shape] is a [ConcavePolygonShape].
 		</constant>
 		</constant>
-		<constant name="SHAPE_HEIGHTMAP" value="7" enum="ShapeType">
+		<constant name="SHAPE_HEIGHTMAP" value="8" enum="ShapeType">
 			The [Shape] is a [HeightMapShape].
 			The [Shape] is a [HeightMapShape].
 		</constant>
 		</constant>
-		<constant name="SHAPE_CUSTOM" value="8" enum="ShapeType">
+		<constant name="SHAPE_CUSTOM" value="9" enum="ShapeType">
 			This constant is used internally by the engine. Any attempt to create this kind of shape results in an error.
 			This constant is used internally by the engine. Any attempt to create this kind of shape results in an error.
 		</constant>
 		</constant>
 		<constant name="AREA_PARAM_GRAVITY" value="0" enum="AreaParameter">
 		<constant name="AREA_PARAM_GRAVITY" value="0" enum="AreaParameter">

+ 6 - 0
editor/icons/icon_cylinder_shape.svg

@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg width="16" height="16" version="1.1" viewBox="0 0 14.999999 14.999999" xmlns="http://www.w3.org/2000/svg">
+<rect fill="#68b6ff" width="13.171325" height="7.6993308" x="0.89037383" y="3.6879442"/>
+<ellipse fill="#a2d2ff" cx="7.4772978" cy="3.7229116" rx="6.5864792" ry="2.820821"/>
+<ellipse fill="#68b6ff" cx="7.4746876" cy="11.34481" rx="6.5864792" ry="2.8208208"/>
+</svg>

+ 116 - 0
editor/spatial_editor_gizmos.cpp

@@ -36,6 +36,7 @@
 #include "scene/resources/box_shape.h"
 #include "scene/resources/box_shape.h"
 #include "scene/resources/capsule_shape.h"
 #include "scene/resources/capsule_shape.h"
 #include "scene/resources/convex_polygon_shape.h"
 #include "scene/resources/convex_polygon_shape.h"
+#include "scene/resources/cylinder_shape.h"
 #include "scene/resources/plane_shape.h"
 #include "scene/resources/plane_shape.h"
 #include "scene/resources/primitive_meshes.h"
 #include "scene/resources/primitive_meshes.h"
 #include "scene/resources/ray_shape.h"
 #include "scene/resources/ray_shape.h"
@@ -1861,6 +1862,11 @@ String CollisionShapeSpatialGizmo::get_handle_name(int p_idx) const {
 		return p_idx == 0 ? "Radius" : "Height";
 		return p_idx == 0 ? "Radius" : "Height";
 	}
 	}
 
 
+	if (Object::cast_to<CylinderShape>(*s)) {
+
+		return p_idx == 0 ? "Radius" : "Height";
+	}
+
 	if (Object::cast_to<RayShape>(*s)) {
 	if (Object::cast_to<RayShape>(*s)) {
 
 
 		return "Length";
 		return "Length";
@@ -1892,6 +1898,12 @@ Variant CollisionShapeSpatialGizmo::get_handle_value(int p_idx) const {
 		return p_idx == 0 ? cs->get_radius() : cs->get_height();
 		return p_idx == 0 ? cs->get_radius() : cs->get_height();
 	}
 	}
 
 
+	if (Object::cast_to<CylinderShape>(*s)) {
+
+		Ref<CylinderShape> cs = s;
+		return p_idx == 0 ? cs->get_radius() : cs->get_height();
+	}
+
 	if (Object::cast_to<RayShape>(*s)) {
 	if (Object::cast_to<RayShape>(*s)) {
 
 
 		Ref<RayShape> cs = s;
 		Ref<RayShape> cs = s;
@@ -1972,6 +1984,24 @@ void CollisionShapeSpatialGizmo::set_handle(int p_idx, Camera *p_camera, const P
 		else if (p_idx == 1)
 		else if (p_idx == 1)
 			cs->set_height(d * 2.0);
 			cs->set_height(d * 2.0);
 	}
 	}
+
+	if (Object::cast_to<CylinderShape>(*s)) {
+
+		Vector3 axis;
+		axis[p_idx == 0 ? 0 : 1] = 1.0;
+		Ref<CylinderShape> cs = s;
+		Vector3 ra, rb;
+		Geometry::get_closest_points_between_segments(Vector3(), axis * 4096, sg[0], sg[1], ra, rb);
+		float d = axis.dot(ra);
+
+		if (d < 0.001)
+			d = 0.001;
+
+		if (p_idx == 0)
+			cs->set_radius(d);
+		else if (p_idx == 1)
+			cs->set_height(d * 2.0);
+	}
 }
 }
 void CollisionShapeSpatialGizmo::commit_handle(int p_idx, const Variant &p_restore, bool p_cancel) {
 void CollisionShapeSpatialGizmo::commit_handle(int p_idx, const Variant &p_restore, bool p_cancel) {
 	Ref<Shape> s = cs->get_shape();
 	Ref<Shape> s = cs->get_shape();
@@ -2033,6 +2063,31 @@ void CollisionShapeSpatialGizmo::commit_handle(int p_idx, const Variant &p_resto
 		ur->commit_action();
 		ur->commit_action();
 	}
 	}
 
 
+	if (Object::cast_to<CylinderShape>(*s)) {
+
+		Ref<CylinderShape> ss = s;
+		if (p_cancel) {
+			if (p_idx == 0)
+				ss->set_radius(p_restore);
+			else
+				ss->set_height(p_restore);
+			return;
+		}
+
+		UndoRedo *ur = SpatialEditor::get_singleton()->get_undo_redo();
+		if (p_idx == 0) {
+			ur->create_action(TTR("Change Cylinder Shape Radius"));
+			ur->add_do_method(ss.ptr(), "set_radius", ss->get_radius());
+			ur->add_undo_method(ss.ptr(), "set_radius", p_restore);
+		} else {
+			ur->create_action(TTR("Change Cylinder Shape Height"));
+			ur->add_do_method(ss.ptr(), "set_height", ss->get_height());
+			ur->add_undo_method(ss.ptr(), "set_height", p_restore);
+		}
+
+		ur->commit_action();
+	}
+
 	if (Object::cast_to<RayShape>(*s)) {
 	if (Object::cast_to<RayShape>(*s)) {
 
 
 		Ref<RayShape> ss = s;
 		Ref<RayShape> ss = s;
@@ -2209,6 +2264,67 @@ void CollisionShapeSpatialGizmo::redraw() {
 		add_handles(handles);
 		add_handles(handles);
 	}
 	}
 
 
+	if (Object::cast_to<CylinderShape>(*s)) {
+
+		Ref<CylinderShape> cs = s;
+		float radius = cs->get_radius();
+		float height = cs->get_height();
+
+		Vector<Vector3> points;
+
+		Vector3 d(0, height * 0.5, 0);
+		for (int i = 0; i < 360; i++) {
+
+			float ra = Math::deg2rad((float)i);
+			float rb = Math::deg2rad((float)i + 1);
+			Point2 a = Vector2(Math::sin(ra), Math::cos(ra)) * radius;
+			Point2 b = Vector2(Math::sin(rb), Math::cos(rb)) * radius;
+
+			points.push_back(Vector3(a.x, 0, a.y) + d);
+			points.push_back(Vector3(b.x, 0, b.y) + d);
+
+			points.push_back(Vector3(a.x, 0, a.y) - d);
+			points.push_back(Vector3(b.x, 0, b.y) - d);
+
+			if (i % 90 == 0) {
+
+				points.push_back(Vector3(a.x, 0, a.y) + d);
+				points.push_back(Vector3(a.x, 0, a.y) - d);
+			}
+		}
+
+		add_lines(points, material);
+
+		Vector<Vector3> collision_segments;
+
+		for (int i = 0; i < 64; i++) {
+
+			float ra = i * Math_PI * 2.0 / 64.0;
+			float rb = (i + 1) * Math_PI * 2.0 / 64.0;
+			Point2 a = Vector2(Math::sin(ra), Math::cos(ra)) * radius;
+			Point2 b = Vector2(Math::sin(rb), Math::cos(rb)) * radius;
+
+			collision_segments.push_back(Vector3(a.x, 0, a.y) + d);
+			collision_segments.push_back(Vector3(b.x, 0, b.y) + d);
+
+			collision_segments.push_back(Vector3(a.x, 0, a.y) - d);
+			collision_segments.push_back(Vector3(b.x, 0, b.y) - d);
+
+			if (i % 16 == 0) {
+
+				collision_segments.push_back(Vector3(a.x, 0, a.y) + d);
+				collision_segments.push_back(Vector3(a.x, 0, a.y) - d);
+			}
+		}
+
+		add_collision_segments(collision_segments);
+
+		Vector<Vector3> handles;
+		handles.push_back(Vector3(cs->get_radius(), 0, 0));
+		handles.push_back(Vector3(0, cs->get_height() * 0.5, 0));
+		add_handles(handles);
+	}
+
 	if (Object::cast_to<PlaneShape>(*s)) {
 	if (Object::cast_to<PlaneShape>(*s)) {
 
 
 		Ref<PlaneShape> ps = s;
 		Ref<PlaneShape> ps = s;

+ 4 - 0
modules/bullet/bullet_physics_server.cpp

@@ -113,6 +113,10 @@ RID BulletPhysicsServer::shape_create(ShapeType p_shape) {
 
 
 			shape = bulletnew(CapsuleShapeBullet);
 			shape = bulletnew(CapsuleShapeBullet);
 		} break;
 		} break;
+		case SHAPE_CYLINDER: {
+
+			shape = bulletnew(CylinderShapeBullet);
+		} break;
 		case SHAPE_CONVEX_POLYGON: {
 		case SHAPE_CONVEX_POLYGON: {
 
 
 			shape = bulletnew(ConvexPolygonShapeBullet);
 			shape = bulletnew(ConvexPolygonShapeBullet);

+ 1 - 0
modules/bullet/rigid_body_bullet.cpp

@@ -226,6 +226,7 @@ void RigidBodyBullet::KinematicUtilities::copyAllOwnerShapes() {
 			case PhysicsServer::SHAPE_SPHERE:
 			case PhysicsServer::SHAPE_SPHERE:
 			case PhysicsServer::SHAPE_BOX:
 			case PhysicsServer::SHAPE_BOX:
 			case PhysicsServer::SHAPE_CAPSULE:
 			case PhysicsServer::SHAPE_CAPSULE:
+			case PhysicsServer::SHAPE_CYLINDER:
 			case PhysicsServer::SHAPE_CONVEX_POLYGON:
 			case PhysicsServer::SHAPE_CONVEX_POLYGON:
 			case PhysicsServer::SHAPE_RAY: {
 			case PhysicsServer::SHAPE_RAY: {
 				shapes[i].shape = static_cast<btConvexShape *>(shape_wrapper->shape->create_bt_shape(owner_scale * shape_wrapper->scale, safe_margin));
 				shapes[i].shape = static_cast<btConvexShape *>(shape_wrapper->shape->create_bt_shape(owner_scale * shape_wrapper->scale, safe_margin));

+ 37 - 0
modules/bullet/shape_bullet.cpp

@@ -113,6 +113,10 @@ btCapsuleShapeZ *ShapeBullet::create_shape_capsule(btScalar radius, btScalar hei
 	return bulletnew(btCapsuleShapeZ(radius, height));
 	return bulletnew(btCapsuleShapeZ(radius, height));
 }
 }
 
 
+btCylinderShape *ShapeBullet::create_shape_cylinder(btScalar radius, btScalar height) {
+	return bulletnew(btCylinderShape(btVector3(radius, height / 2.0, radius)));
+}
+
 btConvexPointCloudShape *ShapeBullet::create_shape_convex(btAlignedObjectArray<btVector3> &p_vertices, const btVector3 &p_local_scaling) {
 btConvexPointCloudShape *ShapeBullet::create_shape_convex(btAlignedObjectArray<btVector3> &p_vertices, const btVector3 &p_local_scaling) {
 	return bulletnew(btConvexPointCloudShape(&p_vertices[0], p_vertices.size(), p_local_scaling));
 	return bulletnew(btConvexPointCloudShape(&p_vertices[0], p_vertices.size(), p_local_scaling));
 }
 }
@@ -254,6 +258,39 @@ btCollisionShape *CapsuleShapeBullet::create_bt_shape(const btVector3 &p_implici
 	return prepare(ShapeBullet::create_shape_capsule(radius * p_implicit_scale[0] + p_margin, height * p_implicit_scale[1] + p_margin));
 	return prepare(ShapeBullet::create_shape_capsule(radius * p_implicit_scale[0] + p_margin, height * p_implicit_scale[1] + p_margin));
 }
 }
 
 
+/* Cylinder */
+
+CylinderShapeBullet::CylinderShapeBullet() :
+		ShapeBullet() {}
+
+void CylinderShapeBullet::set_data(const Variant &p_data) {
+	Dictionary d = p_data;
+	ERR_FAIL_COND(!d.has("radius"));
+	ERR_FAIL_COND(!d.has("height"));
+	setup(d["height"], d["radius"]);
+}
+
+Variant CylinderShapeBullet::get_data() const {
+	Dictionary d;
+	d["radius"] = radius;
+	d["height"] = height;
+	return d;
+}
+
+PhysicsServer::ShapeType CylinderShapeBullet::get_type() const {
+	return PhysicsServer::SHAPE_CYLINDER;
+}
+
+void CylinderShapeBullet::setup(real_t p_height, real_t p_radius) {
+	radius = p_radius;
+	height = p_height;
+	notifyShapeChanged();
+}
+
+btCollisionShape *CylinderShapeBullet::create_bt_shape(const btVector3 &p_implicit_scale, real_t p_margin) {
+	return prepare(ShapeBullet::create_shape_cylinder(radius * p_implicit_scale[0] + p_margin, height * p_implicit_scale[1] + p_margin));
+}
+
 /* Convex polygon */
 /* Convex polygon */
 
 
 ConvexPolygonShapeBullet::ConvexPolygonShapeBullet() :
 ConvexPolygonShapeBullet::ConvexPolygonShapeBullet() :

+ 20 - 0
modules/bullet/shape_bullet.h

@@ -82,6 +82,7 @@ public:
 	static class btSphereShape *create_shape_sphere(btScalar radius);
 	static class btSphereShape *create_shape_sphere(btScalar radius);
 	static class btBoxShape *create_shape_box(const btVector3 &boxHalfExtents);
 	static class btBoxShape *create_shape_box(const btVector3 &boxHalfExtents);
 	static class btCapsuleShapeZ *create_shape_capsule(btScalar radius, btScalar height);
 	static class btCapsuleShapeZ *create_shape_capsule(btScalar radius, btScalar height);
+	static class btCylinderShape *create_shape_cylinder(btScalar radius, btScalar height);
 	/// IMPORTANT: Remember to delete the shape interface by calling: delete my_shape->getMeshInterface();
 	/// IMPORTANT: Remember to delete the shape interface by calling: delete my_shape->getMeshInterface();
 	static class btConvexPointCloudShape *create_shape_convex(btAlignedObjectArray<btVector3> &p_vertices, const btVector3 &p_local_scaling = btVector3(1, 1, 1));
 	static class btConvexPointCloudShape *create_shape_convex(btAlignedObjectArray<btVector3> &p_vertices, const btVector3 &p_local_scaling = btVector3(1, 1, 1));
 	static class btScaledBvhTriangleMeshShape *create_shape_concave(btBvhTriangleMeshShape *p_mesh_shape, const btVector3 &p_local_scaling = btVector3(1, 1, 1));
 	static class btScaledBvhTriangleMeshShape *create_shape_concave(btBvhTriangleMeshShape *p_mesh_shape, const btVector3 &p_local_scaling = btVector3(1, 1, 1));
@@ -158,6 +159,25 @@ private:
 	void setup(real_t p_height, real_t p_radius);
 	void setup(real_t p_height, real_t p_radius);
 };
 };
 
 
+class CylinderShapeBullet : public ShapeBullet {
+
+	real_t height;
+	real_t radius;
+
+public:
+	CylinderShapeBullet();
+
+	_FORCE_INLINE_ real_t get_height() { return height; }
+	_FORCE_INLINE_ real_t get_radius() { return radius; }
+	virtual void set_data(const Variant &p_data);
+	virtual Variant get_data() const;
+	virtual PhysicsServer::ShapeType get_type() const;
+	virtual btCollisionShape *create_bt_shape(const btVector3 &p_implicit_scale, real_t p_margin = 0);
+
+private:
+	void setup(real_t p_height, real_t p_radius);
+};
+
 class ConvexPolygonShapeBullet : public ShapeBullet {
 class ConvexPolygonShapeBullet : public ShapeBullet {
 
 
 public:
 public:

+ 2 - 0
scene/register_scene_types.cpp

@@ -128,6 +128,7 @@
 #include "scene/resources/concave_polygon_shape_2d.h"
 #include "scene/resources/concave_polygon_shape_2d.h"
 #include "scene/resources/convex_polygon_shape.h"
 #include "scene/resources/convex_polygon_shape.h"
 #include "scene/resources/convex_polygon_shape_2d.h"
 #include "scene/resources/convex_polygon_shape_2d.h"
+#include "scene/resources/cylinder_shape.h"
 #include "scene/resources/default_theme/default_theme.h"
 #include "scene/resources/default_theme/default_theme.h"
 #include "scene/resources/dynamic_font.h"
 #include "scene/resources/dynamic_font.h"
 #include "scene/resources/dynamic_font_stb.h"
 #include "scene/resources/dynamic_font_stb.h"
@@ -510,6 +511,7 @@ void register_scene_types() {
 	ClassDB::register_class<SphereShape>();
 	ClassDB::register_class<SphereShape>();
 	ClassDB::register_class<BoxShape>();
 	ClassDB::register_class<BoxShape>();
 	ClassDB::register_class<CapsuleShape>();
 	ClassDB::register_class<CapsuleShape>();
+	ClassDB::register_class<CylinderShape>();
 	ClassDB::register_class<PlaneShape>();
 	ClassDB::register_class<PlaneShape>();
 	ClassDB::register_class<ConvexPolygonShape>();
 	ClassDB::register_class<ConvexPolygonShape>();
 	ClassDB::register_class<ConcavePolygonShape>();
 	ClassDB::register_class<ConcavePolygonShape>();

+ 116 - 0
scene/resources/cylinder_shape.cpp

@@ -0,0 +1,116 @@
+/*************************************************************************/
+/*  cylinder_shape.cpp                                                   */
+/*************************************************************************/
+/*                       This file is part of:                           */
+/*                           GODOT ENGINE                                */
+/*                      https://godotengine.org                          */
+/*************************************************************************/
+/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur.                 */
+/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md)    */
+/*                                                                       */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the       */
+/* "Software"), to deal in the Software without restriction, including   */
+/* without limitation the rights to use, copy, modify, merge, publish,   */
+/* distribute, sublicense, and/or sell copies of the Software, and to    */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions:                                             */
+/*                                                                       */
+/* The above copyright notice and this permission notice shall be        */
+/* included in all copies or substantial portions of the Software.       */
+/*                                                                       */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,       */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF    */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY  */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,  */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
+/*************************************************************************/
+
+#include "cylinder_shape.h"
+#include "servers/physics_server.h"
+
+Vector<Vector3> CylinderShape::_gen_debug_mesh_lines() {
+
+	float radius = get_radius();
+	float height = get_height();
+
+	Vector<Vector3> points;
+
+	Vector3 d(0, height * 0.5, 0);
+	for (int i = 0; i < 360; i++) {
+
+		float ra = Math::deg2rad((float)i);
+		float rb = Math::deg2rad((float)i + 1);
+		Point2 a = Vector2(Math::sin(ra), Math::cos(ra)) * radius;
+		Point2 b = Vector2(Math::sin(rb), Math::cos(rb)) * radius;
+
+		points.push_back(Vector3(a.x, 0, a.y) + d);
+		points.push_back(Vector3(b.x, 0, b.y) + d);
+
+		points.push_back(Vector3(a.x, 0, a.y) - d);
+		points.push_back(Vector3(b.x, 0, b.y) - d);
+
+		if (i % 90 == 0) {
+
+			points.push_back(Vector3(a.x, 0, a.y) + d);
+			points.push_back(Vector3(a.x, 0, a.y) - d);
+		}
+	}
+
+	return points;
+}
+
+void CylinderShape::_update_shape() {
+
+	Dictionary d;
+	d["radius"] = radius;
+	d["height"] = height;
+	PhysicsServer::get_singleton()->shape_set_data(get_shape(), d);
+}
+
+void CylinderShape::set_radius(float p_radius) {
+
+	radius = p_radius;
+	_update_shape();
+	notify_change_to_owners();
+	_change_notify("radius");
+}
+
+float CylinderShape::get_radius() const {
+
+	return radius;
+}
+
+void CylinderShape::set_height(float p_height) {
+
+	height = p_height;
+	_update_shape();
+	notify_change_to_owners();
+	_change_notify("height");
+}
+
+float CylinderShape::get_height() const {
+
+	return height;
+}
+
+void CylinderShape::_bind_methods() {
+
+	ClassDB::bind_method(D_METHOD("set_radius", "radius"), &CylinderShape::set_radius);
+	ClassDB::bind_method(D_METHOD("get_radius"), &CylinderShape::get_radius);
+	ClassDB::bind_method(D_METHOD("set_height", "height"), &CylinderShape::set_height);
+	ClassDB::bind_method(D_METHOD("get_height"), &CylinderShape::get_height);
+
+	ADD_PROPERTY(PropertyInfo(Variant::REAL, "radius", PROPERTY_HINT_RANGE, "0.01,4096,0.01"), "set_radius", "get_radius");
+	ADD_PROPERTY(PropertyInfo(Variant::REAL, "height", PROPERTY_HINT_RANGE, "0.01,4096,0.01"), "set_height", "get_height");
+}
+
+CylinderShape::CylinderShape() :
+		Shape(PhysicsServer::get_singleton()->shape_create(PhysicsServer::SHAPE_CYLINDER)) {
+
+	radius = 1.0;
+	height = 2.0;
+	_update_shape();
+}

+ 57 - 0
scene/resources/cylinder_shape.h

@@ -0,0 +1,57 @@
+/*************************************************************************/
+/*  cylinder_shape.h                                                     */
+/*************************************************************************/
+/*                       This file is part of:                           */
+/*                           GODOT ENGINE                                */
+/*                      https://godotengine.org                          */
+/*************************************************************************/
+/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur.                 */
+/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md)    */
+/*                                                                       */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the       */
+/* "Software"), to deal in the Software without restriction, including   */
+/* without limitation the rights to use, copy, modify, merge, publish,   */
+/* distribute, sublicense, and/or sell copies of the Software, and to    */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions:                                             */
+/*                                                                       */
+/* The above copyright notice and this permission notice shall be        */
+/* included in all copies or substantial portions of the Software.       */
+/*                                                                       */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,       */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF    */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY  */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,  */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
+/*************************************************************************/
+
+#ifndef CYLINDER_SHAPE_H
+#define CYLINDER_SHAPE_H
+
+#include "scene/resources/shape.h"
+
+class CylinderShape : public Shape {
+
+	GDCLASS(CylinderShape, Shape);
+	float radius;
+	float height;
+
+protected:
+	static void _bind_methods();
+	virtual void _update_shape();
+
+	virtual Vector<Vector3> _gen_debug_mesh_lines();
+
+public:
+	void set_radius(float p_radius);
+	float get_radius() const;
+	void set_height(float p_height);
+	float get_height() const;
+
+	CylinderShape();
+};
+
+#endif // CYLINDER_SHAPE_H

+ 5 - 0
servers/physics/physics_server_sw.cpp

@@ -65,6 +65,11 @@ RID PhysicsServerSW::shape_create(ShapeType p_shape) {
 
 
 			shape = memnew(CapsuleShapeSW);
 			shape = memnew(CapsuleShapeSW);
 		} break;
 		} break;
+		case SHAPE_CYLINDER: {
+
+			ERR_EXPLAIN("CylinderShape is not supported in GodotPhysics. Please switch to Bullet in the Project Settings.");
+			ERR_FAIL_V(RID());
+		} break;
 		case SHAPE_CONVEX_POLYGON: {
 		case SHAPE_CONVEX_POLYGON: {
 
 
 			shape = memnew(ConvexPolygonShapeSW);
 			shape = memnew(ConvexPolygonShapeSW);

+ 1 - 0
servers/physics_server.cpp

@@ -664,6 +664,7 @@ void PhysicsServer::_bind_methods() {
 	BIND_ENUM_CONSTANT(SHAPE_SPHERE);
 	BIND_ENUM_CONSTANT(SHAPE_SPHERE);
 	BIND_ENUM_CONSTANT(SHAPE_BOX);
 	BIND_ENUM_CONSTANT(SHAPE_BOX);
 	BIND_ENUM_CONSTANT(SHAPE_CAPSULE);
 	BIND_ENUM_CONSTANT(SHAPE_CAPSULE);
+	BIND_ENUM_CONSTANT(SHAPE_CYLINDER);
 	BIND_ENUM_CONSTANT(SHAPE_CONVEX_POLYGON);
 	BIND_ENUM_CONSTANT(SHAPE_CONVEX_POLYGON);
 	BIND_ENUM_CONSTANT(SHAPE_CONCAVE_POLYGON);
 	BIND_ENUM_CONSTANT(SHAPE_CONCAVE_POLYGON);
 	BIND_ENUM_CONSTANT(SHAPE_HEIGHTMAP);
 	BIND_ENUM_CONSTANT(SHAPE_HEIGHTMAP);

+ 1 - 0
servers/physics_server.h

@@ -228,6 +228,7 @@ public:
 		SHAPE_SPHERE, ///< float:"radius"
 		SHAPE_SPHERE, ///< float:"radius"
 		SHAPE_BOX, ///< vec3:"extents"
 		SHAPE_BOX, ///< vec3:"extents"
 		SHAPE_CAPSULE, ///< dict( float:"radius", float:"height"):capsule
 		SHAPE_CAPSULE, ///< dict( float:"radius", float:"height"):capsule
+		SHAPE_CYLINDER, ///< dict( float:"radius", float:"height"):cylinder
 		SHAPE_CONVEX_POLYGON, ///< array of planes:"planes"
 		SHAPE_CONVEX_POLYGON, ///< array of planes:"planes"
 		SHAPE_CONCAVE_POLYGON, ///< vector3 array:"triangles" , or Dictionary with "indices" (int array) and "triangles" (Vector3 array)
 		SHAPE_CONCAVE_POLYGON, ///< vector3 array:"triangles" , or Dictionary with "indices" (int array) and "triangles" (Vector3 array)
 		SHAPE_HEIGHTMAP, ///< dict( int:"width", int:"depth",float:"cell_size", float_array:"heights"
 		SHAPE_HEIGHTMAP, ///< dict( int:"width", int:"depth",float:"cell_size", float_array:"heights"