diff options
Diffstat (limited to '')
| -rw-r--r-- | scene/3d/body_shape.cpp | 829 |
1 files changed, 829 insertions, 0 deletions
diff --git a/scene/3d/body_shape.cpp b/scene/3d/body_shape.cpp new file mode 100644 index 000000000..b291ce7c7 --- /dev/null +++ b/scene/3d/body_shape.cpp @@ -0,0 +1,829 @@ +/*************************************************************************/ +/* body_shape.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* http://www.godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* 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 "body_shape.h" +#include "servers/visual_server.h" +#include "scene/resources/sphere_shape.h" +#include "scene/resources/ray_shape.h" +#include "scene/resources/box_shape.h" +#include "scene/resources/capsule_shape.h" +//#include "scene/resources/cylinder_shape.h" +#include "scene/resources/convex_polygon_shape.h" +#include "scene/resources/concave_polygon_shape.h" +#include "scene/resources/height_map_shape.h" +#include "scene/resources/plane_shape.h" +#include "mesh_instance.h" +#include "physics_body.h" +#include "quick_hull.h" + +void CollisionShape::_update_body() { + + + + if (get_parent() && get_parent()->cast_to<CollisionObject>()) + get_parent()->cast_to<CollisionObject>()->_update_shapes_from_children(); + +} + +void CollisionShape::make_convex_from_brothers() { + + Node *p = get_parent(); + if (!p) + return; + + for(int i=0;i<p->get_child_count();i++) { + + Node *n = p->get_child(i); + if (n->cast_to<MeshInstance>()) { + + MeshInstance *mi=n->cast_to<MeshInstance>(); + Ref<Mesh> m = mi->get_mesh(); + if (m.is_valid()) { + + Ref<Shape> s = m->create_convex_shape(); + set_shape(s); + } + } + } + +} + + +void CollisionShape::_update_indicator() { + + while (VisualServer::get_singleton()->mesh_get_surface_count(indicator)) + VisualServer::get_singleton()->mesh_remove_surface(indicator,0); + + if (shape.is_null()) + return; + + DVector<Vector3> points; + DVector<Vector3> normals; + + VS::PrimitiveType pt = VS::PRIMITIVE_TRIANGLES; + + if (shape->cast_to<RayShape>()) { + + RayShape *rs = shape->cast_to<RayShape>(); + points.push_back(Vector3()); + points.push_back(Vector3(0,0,rs->get_length())); + pt = VS::PRIMITIVE_LINES; + } else if (shape->cast_to<SphereShape>()) { + +// VisualServer *vs=VisualServer::get_singleton(); + SphereShape *shapeptr=shape->cast_to<SphereShape>(); + + + Color col(0.4,1.0,1.0,0.5); + + int lats=6; + int lons=12; + float size=shapeptr->get_radius(); + + + for(int i = 1; i <= lats; i++) { + double lat0 = Math_PI * (-0.5 + (double) (i - 1) / lats); + double z0 = Math::sin(lat0); + double zr0 = Math::cos(lat0); + + double lat1 = Math_PI * (-0.5 + (double) i / lats); + double z1 = Math::sin(lat1); + double zr1 = Math::cos(lat1); + + for(int j = lons; j >= 1; j--) { + + double lng0 = 2 * Math_PI * (double) (j - 1) / lons; + double x0 = Math::cos(lng0); + double y0 = Math::sin(lng0); + + double lng1 = 2 * Math_PI * (double) (j) / lons; + double x1 = Math::cos(lng1); + double y1 = Math::sin(lng1); + + Vector3 v4=Vector3(x0 * zr0, z0, y0 *zr0)*size; + Vector3 v3=Vector3(x0 * zr1, z1, y0 *zr1)*size; + Vector3 v2=Vector3(x1 * zr1, z1, y1 *zr1)*size; + Vector3 v1=Vector3(x1 * zr0, z0, y1 *zr0)*size; + + Vector<Vector3> line; + line.push_back(v1); + line.push_back(v2); + line.push_back(v3); + line.push_back(v4); + + + points.push_back(v1); + points.push_back(v2); + points.push_back(v3); + + points.push_back(v1); + points.push_back(v3); + points.push_back(v4); + + normals.push_back(v1.normalized()); + normals.push_back(v2.normalized()); + normals.push_back(v3.normalized()); + + normals.push_back(v1.normalized()); + normals.push_back(v3.normalized()); + normals.push_back(v4.normalized()); + + } + } + } else if (shape->cast_to<BoxShape>()) { + + BoxShape *shapeptr=shape->cast_to<BoxShape>(); + + for (int i=0;i<6;i++) { + + + Vector3 face_points[4]; + + + for (int j=0;j<4;j++) { + + float v[3]; + v[0]=1.0; + v[1]=1-2*((j>>1)&1); + v[2]=v[1]*(1-2*(j&1)); + + for (int k=0;k<3;k++) { + + if (i<3) + face_points[j][(i+k)%3]=v[k]*(i>=3?-1:1); + else + face_points[3-j][(i+k)%3]=v[k]*(i>=3?-1:1); + } + } + Vector3 normal; + normal[i%3]=(i>=3?-1:1); + + for(int j=0;j<4;j++) + face_points[j]*=shapeptr->get_extents(); + + points.push_back(face_points[0]); + points.push_back(face_points[1]); + points.push_back(face_points[2]); + + points.push_back(face_points[0]); + points.push_back(face_points[2]); + points.push_back(face_points[3]); + + for(int n=0;n<6;n++) + normals.push_back(normal); + + } + + } else if (shape->cast_to<ConvexPolygonShape>()) { + + ConvexPolygonShape *shapeptr=shape->cast_to<ConvexPolygonShape>(); + + Geometry::MeshData md; + QuickHull::build(Variant(shapeptr->get_points()),md); + + for(int i=0;i<md.faces.size();i++) { + + for(int j=2;j<md.faces[i].indices.size();j++) { + points.push_back(md.vertices[md.faces[i].indices[0]]); + points.push_back(md.vertices[md.faces[i].indices[j-1]]); + points.push_back(md.vertices[md.faces[i].indices[j]]); + normals.push_back(md.faces[i].plane.normal); + normals.push_back(md.faces[i].plane.normal); + normals.push_back(md.faces[i].plane.normal); + } + } + } else if (shape->cast_to<ConcavePolygonShape>()) { + + ConcavePolygonShape *shapeptr=shape->cast_to<ConcavePolygonShape>(); + + points = shapeptr->get_faces(); + for(int i=0;i<points.size()/3;i++) { + + Vector3 n = Plane( points[i*3+0],points[i*3+1],points[i*3+2] ).normal; + normals.push_back(n); + normals.push_back(n); + normals.push_back(n); + } + + } else if (shape->cast_to<CapsuleShape>()) { + + CapsuleShape *shapeptr=shape->cast_to<CapsuleShape>(); + + DVector<Plane> planes = Geometry::build_capsule_planes(shapeptr->get_radius(), shapeptr->get_height()/2.0, 12, Vector3::AXIS_Z); + Geometry::MeshData md = Geometry::build_convex_mesh(planes); + + for(int i=0;i<md.faces.size();i++) { + + for(int j=2;j<md.faces[i].indices.size();j++) { + points.push_back(md.vertices[md.faces[i].indices[0]]); + points.push_back(md.vertices[md.faces[i].indices[j-1]]); + points.push_back(md.vertices[md.faces[i].indices[j]]); + normals.push_back(md.faces[i].plane.normal); + normals.push_back(md.faces[i].plane.normal); + normals.push_back(md.faces[i].plane.normal); + + } + } + + } else if (shape->cast_to<PlaneShape>()) { + + PlaneShape *shapeptr=shape->cast_to<PlaneShape>(); + + Plane p = shapeptr->get_plane(); + Vector3 n1 = p.get_any_perpendicular_normal(); + Vector3 n2 = p.normal.cross(n1).normalized(); + + Vector3 pface[4]={ + p.normal*p.d+n1*100.0+n2*100.0, + p.normal*p.d+n1*100.0+n2*-100.0, + p.normal*p.d+n1*-100.0+n2*-100.0, + p.normal*p.d+n1*-100.0+n2*100.0, + }; + + points.push_back(pface[0]); + points.push_back(pface[1]); + points.push_back(pface[2]); + + points.push_back(pface[0]); + points.push_back(pface[2]); + points.push_back(pface[3]); + + normals.push_back(p.normal); + normals.push_back(p.normal); + normals.push_back(p.normal); + normals.push_back(p.normal); + normals.push_back(p.normal); + normals.push_back(p.normal); + + } + + if (!points.size()) + return; + RID material = VisualServer::get_singleton()->fixed_material_create(); + VisualServer::get_singleton()->fixed_material_set_param(material,VS::FIXED_MATERIAL_PARAM_DIFFUSE,Color(0,0.6,0.7,0.3)); + VisualServer::get_singleton()->fixed_material_set_param(material,VS::FIXED_MATERIAL_PARAM_EMISSION,0.7); + if (normals.size()==0) + VisualServer::get_singleton()->material_set_flag(material,VS::MATERIAL_FLAG_UNSHADED,true); + VisualServer::get_singleton()->material_set_flag(material,VS::MATERIAL_FLAG_DOUBLE_SIDED,true); + Array d; + d.resize(VS::ARRAY_MAX); + d[VS::ARRAY_VERTEX]=points; + if (normals.size()) + d[VS::ARRAY_NORMAL]=normals; + VisualServer::get_singleton()->mesh_add_surface(indicator,pt,d); + VisualServer::get_singleton()->mesh_surface_set_material(indicator,0,material,true); + +} + + +void CollisionShape::_add_to_collision_object(Object* p_cshape) { + + CollisionObject *co=p_cshape->cast_to<CollisionObject>(); + ERR_FAIL_COND(!co); + + if (shape.is_valid()) { + + co->add_shape(shape,get_transform()); + if (trigger) + co->set_shape_as_trigger( co->get_shape_count() -1, true ); + } +} + +void CollisionShape::_notification(int p_what) { + + switch(p_what) { + + case NOTIFICATION_ENTER_WORLD: { + indicator_instance = VisualServer::get_singleton()->instance_create2(indicator,get_world()->get_scenario()); + } break; + case NOTIFICATION_TRANSFORM_CHANGED: { + VisualServer::get_singleton()->instance_set_transform(indicator_instance,get_global_transform()); + if (updating_body) { + _update_body(); + } + } break; + case NOTIFICATION_EXIT_WORLD: { + if (indicator_instance.is_valid()) { + VisualServer::get_singleton()->free(indicator_instance); + indicator_instance=RID(); + } + } break; + case NOTIFICATION_UNPARENTED: { + if (updating_body) + _update_body(); + } break; + case NOTIFICATION_PARENTED: { + if (updating_body) + _update_body(); + } break; + } +} + + +void CollisionShape::resource_changed(RES res) { + + update_gizmo(); + + +} + +void CollisionShape::_bind_methods() { + + //not sure if this should do anything + ObjectTypeDB::bind_method(_MD("resource_changed"),&CollisionShape::resource_changed); + ObjectTypeDB::bind_method(_MD("set_shape","shape"),&CollisionShape::set_shape); + ObjectTypeDB::bind_method(_MD("get_shape"),&CollisionShape::get_shape); + ObjectTypeDB::bind_method(_MD("_add_to_collision_object"),&CollisionShape::_add_to_collision_object); + ObjectTypeDB::bind_method(_MD("set_trigger","enable"),&CollisionShape::set_trigger); + ObjectTypeDB::bind_method(_MD("is_trigger"),&CollisionShape::is_trigger); + ObjectTypeDB::bind_method(_MD("make_convex_from_brothers"),&CollisionShape::make_convex_from_brothers); + ObjectTypeDB::set_method_flags("CollisionShape","make_convex_from_brothers",METHOD_FLAGS_DEFAULT|METHOD_FLAG_EDITOR); + + + ADD_PROPERTY( PropertyInfo( Variant::OBJECT, "shape", PROPERTY_HINT_RESOURCE_TYPE, "Shape"), _SCS("set_shape"), _SCS("get_shape")); + ADD_PROPERTY(PropertyInfo(Variant::BOOL,"trigger"),_SCS("set_trigger"),_SCS("is_trigger")); +} + + +void CollisionShape::set_shape(const Ref<Shape> &p_shape) { + + if (!shape.is_null()) + shape->unregister_owner(this); + shape=p_shape; + if (!shape.is_null()) + shape->register_owner(this); + update_gizmo(); + if (updating_body) + _update_body(); +} + +Ref<Shape> CollisionShape::get_shape() const { + + return shape; +} + + +void CollisionShape::set_updating_body(bool p_update) { + updating_body=p_update; +} + +bool CollisionShape::is_updating_body() const { + + return updating_body; +} + +void CollisionShape::set_trigger(bool p_trigger) { + + trigger=p_trigger; + if (updating_body) + _update_body(); +} + +bool CollisionShape::is_trigger() const{ + + return trigger; +} + +CollisionShape::CollisionShape() { + + indicator = VisualServer::get_singleton()->mesh_create(); + updating_body=true; + trigger=false; +} + +CollisionShape::~CollisionShape() { + if (!shape.is_null()) + shape->unregister_owner(this); + VisualServer::get_singleton()->free(indicator); +} + +#if 0 +#include "body_volume.h" + +#include "scene/3d/physics_body.h" +#include "geometry.h" + +#define ADD_TRIANGLE( m_a, m_b, m_c, m_color)\ +{\ + Vector<Vector3> points;\ + points.resize(3);\ + points[0]=m_a;\ + points[1]=m_b;\ + points[2]=m_c;\ + Vector<Color> colors;\ + colors.resize(3);\ + colors[0]=m_color;\ + colors[1]=m_color;\ + colors[2]=m_color;\ + vs->poly_add_primitive(p_indicator,points,Vector<Vector3>(),colors,Vector<Vector3>());\ +} + + +void CollisionShape::_notification(int p_what) { + + switch (p_what) { + case NOTIFICATION_ENTER_SCENE: { + + + if (get_root_node()->get_editor() && !indicator.is_valid()) { + + indicator=VisualServer::get_singleton()->poly_create(); + RID mat=VisualServer::get_singleton()->fixed_material_create(); + VisualServer::get_singleton()->material_set_flag( mat, VisualServer::MATERIAL_FLAG_UNSHADED, true ); + VisualServer::get_singleton()->material_set_flag( mat, VisualServer::MATERIAL_FLAG_WIREFRAME, true ); + VisualServer::get_singleton()->material_set_flag( mat, VisualServer::MATERIAL_FLAG_DOUBLE_SIDED, true ); + VisualServer::get_singleton()->material_set_line_width( mat, 3 ); + + VisualServer::get_singleton()->poly_set_material(indicator,mat,true); + + update_indicator(indicator); + } + + if (indicator.is_valid()) { + + indicator_instance=VisualServer::get_singleton()->instance_create2(indicator,get_world()->get_scenario()); + VisualServer::get_singleton()->instance_attach_object_instance_ID(indicator_instance,get_instance_ID()); + } + volume_changed(); + } break; + case NOTIFICATION_EXIT_SCENE: { + + if (indicator_instance.is_valid()) { + + VisualServer::get_singleton()->free(indicator_instance); + } + volume_changed(); + } break; + case NOTIFICATION_TRANSFORM_CHANGED: { + + if (indicator_instance.is_valid()) { + + VisualServer::get_singleton()->instance_set_transform(indicator_instance,get_global_transform()); + } + volume_changed(); + } break; + default: {} + } +} + +void CollisionShape::volume_changed() { + + if (indicator.is_valid()) + update_indicator(indicator); + + Object *parent=get_parent(); + if (!parent) + return; + PhysicsBody *physics_body=parent->cast_to<PhysicsBody>(); + + ERR_EXPLAIN("CollisionShape parent is not of type PhysicsBody"); + ERR_FAIL_COND(!physics_body); + + physics_body->recompute_child_volumes(); + +} + +RID CollisionShape::_get_visual_instance_rid() const { + + return indicator_instance; + +} + +void CollisionShape::_bind_methods() { + + ObjectTypeDB::bind_method("_get_visual_instance_rid",&CollisionShape::_get_visual_instance_rid); +} + +CollisionShape::CollisionShape() { + +} + +CollisionShape::~CollisionShape() { + + if (indicator.is_valid()) { + + VisualServer::get_singleton()->free(indicator); + } + +} + +void CollisionShapeSphere::_set(const String& p_name, const Variant& p_value) { + + if (p_name=="radius") { + radius=p_value; + volume_changed(); + } + +} + +Variant CollisionShapeSphere::_get(const String& p_name) const { + + if (p_name=="radius") { + return radius; + } + + return Variant(); +} + +void CollisionShapeSphere::_get_property_list( List<PropertyInfo> *p_list) const { + + p_list->push_back( PropertyInfo(Variant::REAL,"radius",PROPERTY_HINT_RANGE,"0.01,16384,0.01") ); +} + +void CollisionShapeSphere::update_indicator(RID p_indicator) { + + VisualServer *vs=VisualServer::get_singleton(); + + vs->poly_clear(p_indicator); + Color col(0.4,1.0,1.0,0.5); + + int lats=6; + int lons=12; + float size=radius; + + for(int i = 1; i <= lats; i++) { + double lat0 = Math_PI * (-0.5 + (double) (i - 1) / lats); + double z0 = Math::sin(lat0); + double zr0 = Math::cos(lat0); + + double lat1 = Math_PI * (-0.5 + (double) i / lats); + double z1 = Math::sin(lat1); + double zr1 = Math::cos(lat1); + + for(int j = lons; j >= 1; j--) { + + double lng0 = 2 * Math_PI * (double) (j - 1) / lons; + double x0 = Math::cos(lng0); + double y0 = Math::sin(lng0); + + double lng1 = 2 * Math_PI * (double) (j) / lons; + double x1 = Math::cos(lng1); + double y1 = Math::sin(lng1); + + Vector3 v4=Vector3(x0 * zr0, z0, y0 *zr0)*size; + Vector3 v3=Vector3(x0 * zr1, z1, y0 *zr1)*size; + Vector3 v2=Vector3(x1 * zr1, z1, y1 *zr1)*size; + Vector3 v1=Vector3(x1 * zr0, z0, y1 *zr0)*size; + + Vector<Vector3> line; + line.push_back(v1); + line.push_back(v2); + line.push_back(v3); + line.push_back(v4); + + Vector<Color> cols; + cols.push_back(col); + cols.push_back(col); + cols.push_back(col); + cols.push_back(col); + + + VisualServer::get_singleton()->poly_add_primitive(p_indicator,line,Vector<Vector3>(),cols,Vector<Vector3>()); + } + } +} + +void CollisionShapeSphere::append_to_volume(Ref<Shape> p_volume) { + + p_volume->add_sphere_shape(radius,get_transform()); +} + + +CollisionShapeSphere::CollisionShapeSphere() { + + radius=1.0; +} + +/* BOX */ + + +void CollisionShapeBox::_set(const String& p_name, const Variant& p_value) { + + if (p_name=="half_extents") { + half_extents=p_value; + volume_changed(); + } + +} + +Variant CollisionShapeBox::_get(const String& p_name) const { + + if (p_name=="half_extents") { + return half_extents; + } + + return Variant(); +} + +void CollisionShapeBox::_get_property_list( List<PropertyInfo> *p_list) const { + + p_list->push_back( PropertyInfo(Variant::VECTOR3,"half_extents" ) ); +} + + +void CollisionShapeBox::update_indicator(RID p_indicator) { + + VisualServer *vs=VisualServer::get_singleton(); + + vs->poly_clear(p_indicator); + Color col(0.4,1.0,1.0,0.5); + + + for (int i=0;i<6;i++) { + + + Vector3 face_points[4]; + + for (int j=0;j<4;j++) { + + float v[3]; + v[0]=1.0; + v[1]=1-2*((j>>1)&1); + v[2]=v[1]*(1-2*(j&1)); + + for (int k=0;k<3;k++) { + + if (i<3) + face_points[j][(i+k)%3]=v[k]*(i>=3?-1:1); + else + face_points[3-j][(i+k)%3]=v[k]*(i>=3?-1:1); + } + } + + for(int j=0;j<4;j++) + face_points[i]*=half_extents; + + ADD_TRIANGLE(face_points[0],face_points[1],face_points[2],col); + ADD_TRIANGLE(face_points[2],face_points[3],face_points[0],col); + + } +} + +void CollisionShapeBox::append_to_volume(Ref<Shape> p_volume) { + + p_volume->add_box_shape(half_extents,get_transform()); +} + + +CollisionShapeBox::CollisionShapeBox() { + + half_extents=Vector3(1,1,1); +} + +/* CYLINDER */ + + +void CollisionShapeCylinder::_set(const String& p_name, const Variant& p_value) { + + if (p_name=="radius") { + radius=p_value; + volume_changed(); + } + if (p_name=="height") { + height=p_value; + volume_changed(); + } + +} + +Variant CollisionShapeCylinder::_get(const String& p_name) const { + + if (p_name=="radius") { + return radius; + } + if (p_name=="height") { + return height; + } + return Variant(); +} + +void CollisionShapeCylinder::_get_property_list( List<PropertyInfo> *p_list) const { + + p_list->push_back( PropertyInfo(Variant::REAL,"radius",PROPERTY_HINT_RANGE,"0.01,16384,0.01") ); + p_list->push_back( PropertyInfo(Variant::REAL,"height",PROPERTY_HINT_RANGE,"0.01,16384,0.01") ); +} + + +void CollisionShapeCylinder::update_indicator(RID p_indicator) { + + VisualServer *vs=VisualServer::get_singleton(); + + vs->poly_clear(p_indicator); + Color col(0.4,1.0,1.0,0.5); + + DVector<Plane> planes = Geometry::build_cylinder_planes(radius, height, 12, Vector3::AXIS_Z); + Geometry::MeshData md = Geometry::build_convex_mesh(planes); + + for(int i=0;i<md.faces.size();i++) { + + for(int j=2;j<md.faces[i].indices.size();j++) { + ADD_TRIANGLE(md.vertices[md.faces[i].indices[0]],md.vertices[md.faces[i].indices[j-1]],md.vertices[md.faces[i].indices[j]],col); + } + } + +} + +void CollisionShapeCylinder::append_to_volume(Ref<Shape> p_volume) { + + p_volume->add_cylinder_shape(radius,height*2.0,get_transform()); +} + + +CollisionShapeCylinder::CollisionShapeCylinder() { + + height=1; + radius=1; +} + +/* CAPSULE */ + + +void CollisionShapeCapsule::_set(const String& p_name, const Variant& p_value) { + + if (p_name=="radius") { + radius=p_value; + volume_changed(); + } + + if (p_name=="height") { + height=p_value; + volume_changed(); + } + +} + +Variant CollisionShapeCapsule::_get(const String& p_name) const { + + if (p_name=="radius") { + return radius; + } + if (p_name=="height") { + return height; + } + return Variant(); +} + +void CollisionShapeCapsule::_get_property_list( List<PropertyInfo> *p_list) const { + + p_list->push_back( PropertyInfo(Variant::REAL,"radius",PROPERTY_HINT_RANGE,"0.01,16384,0.01") ); + p_list->push_back( PropertyInfo(Variant::REAL,"height",PROPERTY_HINT_RANGE,"0.01,16384,0.01") ); +} + + +void CollisionShapeCapsule::update_indicator(RID p_indicator) { + + VisualServer *vs=VisualServer::get_singleton(); + + vs->poly_clear(p_indicator); + Color col(0.4,1.0,1.0,0.5); + + DVector<Plane> planes = Geometry::build_capsule_planes(radius, height, 12, 3, Vector3::AXIS_Z); + Geometry::MeshData md = Geometry::build_convex_mesh(planes); + + for(int i=0;i<md.faces.size();i++) { + + for(int j=2;j<md.faces[i].indices.size();j++) { + ADD_TRIANGLE(md.vertices[md.faces[i].indices[0]],md.vertices[md.faces[i].indices[j-1]],md.vertices[md.faces[i].indices[j]],col); + } + } + +} + +void CollisionShapeCapsule::append_to_volume(Ref<Shape> p_volume) { + + + p_volume->add_capsule_shape(radius,height,get_transform()); +} + + +CollisionShapeCapsule::CollisionShapeCapsule() { + + height=1; + radius=1; +} +#endif |
