123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922 |
- /*************************************************************************/
- /* body_shape.cpp */
- /*************************************************************************/
- /* This file is part of: */
- /* GODOT ENGINE */
- /* http://www.godotengine.org */
- /*************************************************************************/
- /* Copyright (c) 2007-2016 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 (!is_inside_tree() || !can_update_body)
- return;
- if (!get_tree()->is_editor_hint())
- return;
- 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) {
- if (unparenting)
- return;
- CollisionObject *co=p_cshape->cast_to<CollisionObject>();
- ERR_FAIL_COND(!co);
- if (shape.is_valid()) {
- update_shape_index=co->get_shape_count();
- co->add_shape(shape,get_transform());
- if (trigger)
- co->set_shape_as_trigger( co->get_shape_count() -1, true );
- } else {
- update_shape_index=-1;
- }
- }
- void CollisionShape::_notification(int p_what) {
- switch(p_what) {
- case NOTIFICATION_ENTER_TREE: {
- unparenting=false;
- can_update_body=get_tree()->is_editor_hint();
- set_notify_local_transform(!can_update_body);
- if (get_tree()->is_debugging_collisions_hint()) {
- _create_debug_shape();
- }
- //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 (can_update_body && updating_body) {
- _update_body();
- }
- } break;
- case NOTIFICATION_EXIT_TREE: {
- /* if (indicator_instance.is_valid()) {
- VisualServer::get_singleton()->free(indicator_instance);
- indicator_instance=RID();
- }*/
- can_update_body=false;
- set_notify_local_transform(false);
- if (debug_shape) {
- debug_shape->queue_delete();
- debug_shape=NULL;
- }
- } break;
- case NOTIFICATION_UNPARENTED: {
- unparenting=true;
- if (can_update_body && updating_body)
- _update_body();
- } break;
- case NOTIFICATION_PARENTED: {
- if (can_update_body && updating_body)
- _update_body();
- } break;
- case NOTIFICATION_LOCAL_TRANSFORM_CHANGED: {
- if (!can_update_body && update_shape_index>=0) {
- CollisionObject *co = get_parent()->cast_to<CollisionObject>();
- if (co) {
- co->set_shape_transform(update_shape_index,get_transform());
- }
- }
- } break;
- }
- }
- void CollisionShape::resource_changed(RES res) {
- update_gizmo();
- }
- void CollisionShape::_set_update_shape_index(int p_index) {
- update_shape_index=p_index;
- }
- int CollisionShape::_get_update_shape_index() const{
- return update_shape_index;
- }
- void CollisionShape::_bind_methods() {
- //not sure if this should do anything
- ObjectTypeDB::bind_method(_MD("resource_changed","resource"),&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);
- ObjectTypeDB::bind_method(_MD("_set_update_shape_index","index"),&CollisionShape::_set_update_shape_index);
- ObjectTypeDB::bind_method(_MD("_get_update_shape_index"),&CollisionShape::_get_update_shape_index);
- ObjectTypeDB::bind_method(_MD("get_collision_object_shape_index"),&CollisionShape::get_collision_object_shape_index);
- 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"));
- ADD_PROPERTY( PropertyInfo( Variant::INT, "_update_shape_index", PROPERTY_HINT_NONE, "",PROPERTY_USAGE_NOEDITOR), _SCS("_set_update_shape_index"), _SCS("_get_update_shape_index"));
- }
- 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();
- } else if (can_update_body && update_shape_index>=0 && is_inside_tree()){
- CollisionObject *co = get_parent()->cast_to<CollisionObject>();
- if (co) {
- co->set_shape(update_shape_index,p_shape);
- }
- }
- }
- 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();
- } else if (can_update_body && update_shape_index>=0 && is_inside_tree()){
- CollisionObject *co = get_parent()->cast_to<CollisionObject>();
- if (co) {
- co->set_shape_as_trigger(update_shape_index,p_trigger);
- }
- }
- }
- bool CollisionShape::is_trigger() const{
- return trigger;
- }
- CollisionShape::CollisionShape() {
- //indicator = VisualServer::get_singleton()->mesh_create();
- updating_body=true;
- unparenting=false;
- update_shape_index=-1;
- trigger=false;
- can_update_body=false;
- debug_shape=NULL;
- }
- CollisionShape::~CollisionShape() {
- if (!shape.is_null())
- shape->unregister_owner(this);
- //VisualServer::get_singleton()->free(indicator);
- }
- void CollisionShape::_create_debug_shape() {
- if (debug_shape) {
- debug_shape->queue_delete();;
- debug_shape=NULL;
- }
- Ref<Shape> s = get_shape();
- if (s.is_null())
- return;
- Ref<Mesh> mesh = s->get_debug_mesh();
- MeshInstance *mi = memnew( MeshInstance );
- mi->set_mesh(mesh);
- add_child(mi);
- debug_shape=mi;
- }
- #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
|