void PhysicsServerSW::shape_set_custom_solver_bias(RID p_shape, real_t p_bias) { ShapeSW *shape = shape_owner.get(p_shape); ERR_FAIL_COND(!shape); shape->set_custom_bias(p_bias); }
bool PhysicsDirectSpaceStateSW::rest_info(RID p_shape, const Transform& p_shape_xform,float p_margin,ShapeRestInfo *r_info, const Set<RID>& p_exclude,uint32_t p_layer_mask,uint32_t p_object_type_mask) { ShapeSW *shape = static_cast<PhysicsServerSW*>(PhysicsServer::get_singleton())->shape_owner.get(p_shape); ERR_FAIL_COND_V(!shape,0); AABB aabb = p_shape_xform.xform(shape->get_aabb()); aabb=aabb.grow(p_margin); int amount = space->broadphase->cull_aabb(aabb,space->intersection_query_results,SpaceSW::INTERSECTION_QUERY_MAX,space->intersection_query_subindex_results); _RestCallbackData rcd; rcd.best_len=0; rcd.best_object=NULL; rcd.best_shape=0; for(int i=0;i<amount;i++) { if (!_match_object_type_query(space->intersection_query_results[i],p_layer_mask,p_object_type_mask)) continue; const CollisionObjectSW *col_obj=space->intersection_query_results[i]; int shape_idx=space->intersection_query_subindex_results[i]; if (p_exclude.has( col_obj->get_self() )) continue; rcd.object=col_obj; rcd.shape=shape_idx; bool sc = CollisionSolverSW::solve_static(shape,p_shape_xform,col_obj->get_shape(shape_idx),col_obj->get_transform() * col_obj->get_shape_transform(shape_idx),_rest_cbk_result,&rcd,NULL,p_margin); if (!sc) continue; } if (rcd.best_len==0) return false; r_info->collider_id=rcd.best_object->get_instance_id(); r_info->shape=rcd.best_shape; r_info->normal=rcd.best_normal; r_info->point=rcd.best_contact; r_info->rid=rcd.best_object->get_self(); if (rcd.best_object->get_type()==CollisionObjectSW::TYPE_BODY) { const BodySW *body = static_cast<const BodySW*>(rcd.best_object); Vector3 rel_vec = r_info->point-body->get_transform().get_origin(); r_info->linear_velocity = body->get_linear_velocity() + (body->get_angular_velocity()).cross(body->get_transform().origin-rcd.best_contact);// * mPos); } else { r_info->linear_velocity=Vector3(); } return true; }
void PhysicsServerSW::shape_set_data(RID p_shape, const Variant& p_data) { ShapeSW *shape = shape_owner.get(p_shape); ERR_FAIL_COND(!shape); shape->set_data(p_data); };
bool PhysicsDirectSpaceStateSW::collide_shape(RID p_shape, const Transform& p_shape_xform,float p_margin,Vector3 *r_results,int p_result_max,int &r_result_count, const Set<RID>& p_exclude,uint32_t p_layer_mask,uint32_t p_object_type_mask){ if (p_result_max<=0) return 0; ShapeSW *shape = static_cast<PhysicsServerSW*>(PhysicsServer::get_singleton())->shape_owner.get(p_shape); ERR_FAIL_COND_V(!shape,0); AABB aabb = p_shape_xform.xform(shape->get_aabb()); aabb=aabb.grow(p_margin); int amount = space->broadphase->cull_aabb(aabb,space->intersection_query_results,SpaceSW::INTERSECTION_QUERY_MAX,space->intersection_query_subindex_results); bool collided=false; int cc=0; r_result_count=0; PhysicsServerSW::CollCbkData cbk; cbk.max=p_result_max; cbk.amount=0; cbk.ptr=r_results; CollisionSolverSW::CallbackResult cbkres=NULL; PhysicsServerSW::CollCbkData *cbkptr=NULL; if (p_result_max>0) { cbkptr=&cbk; cbkres=PhysicsServerSW::_shape_col_cbk; } for(int i=0;i<amount;i++) { if (!_match_object_type_query(space->intersection_query_results[i],p_layer_mask,p_object_type_mask)) continue; const CollisionObjectSW *col_obj=space->intersection_query_results[i]; int shape_idx=space->intersection_query_subindex_results[i]; if (p_exclude.has( col_obj->get_self() )) { continue; } //print_line("AGAINST: "+itos(col_obj->get_self().get_id())+":"+itos(shape_idx)); //print_line("THE ABBB: "+(col_obj->get_transform() * col_obj->get_shape_transform(shape_idx)).xform(col_obj->get_shape(shape_idx)->get_aabb())); if (CollisionSolverSW::solve_static(shape,p_shape_xform,col_obj->get_shape(shape_idx),col_obj->get_transform() * col_obj->get_shape_transform(shape_idx),cbkres,cbkptr,NULL,p_margin)) { collided=true; } } r_result_count=cbk.amount; return collided; }
RID PhysicsServerSW::body_get_shape(RID p_body, int p_shape_idx) const { BodySW *body = body_owner.get(p_body); ERR_FAIL_COND_V(!body,RID()); ShapeSW *shape = body->get_shape(p_shape_idx); ERR_FAIL_COND_V(!shape,RID()); return shape->get_self(); }
RID PhysicsServerSW::area_get_shape(RID p_area, int p_shape_idx) const { AreaSW *area = area_owner.get(p_area); ERR_FAIL_COND_V(!area,RID()); ShapeSW *shape = area->get_shape(p_shape_idx); ERR_FAIL_COND_V(!shape,RID()); return shape->get_self(); }
void PhysicsServerSW::body_set_shape(RID p_body, int p_shape_idx, RID p_shape) { BodySW *body = body_owner.get(p_body); ERR_FAIL_COND(!body); ShapeSW *shape = shape_owner.get(p_shape); ERR_FAIL_COND(!shape); ERR_FAIL_COND(!shape->is_configured()); body->set_shape(p_shape_idx, shape); }
void PhysicsServerSW::area_set_shape(RID p_area, int p_shape_idx, RID p_shape) { AreaSW *area = area_owner.get(p_area); ERR_FAIL_COND(!area); ShapeSW *shape = shape_owner.get(p_shape); ERR_FAIL_COND(!shape); ERR_FAIL_COND(!shape->is_configured()); area->set_shape(p_shape_idx, shape); }
RID PhysicsServerSW::shape_create(ShapeType p_shape) { ShapeSW *shape = NULL; switch (p_shape) { case SHAPE_PLANE: { shape = memnew(PlaneShapeSW); } break; case SHAPE_RAY: { shape = memnew(RayShapeSW); } break; case SHAPE_SPHERE: { shape = memnew(SphereShapeSW); } break; case SHAPE_BOX: { shape = memnew(BoxShapeSW); } break; case SHAPE_CAPSULE: { shape = memnew(CapsuleShapeSW); } 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: { shape = memnew(ConvexPolygonShapeSW); } break; case SHAPE_CONCAVE_POLYGON: { shape = memnew(ConcavePolygonShapeSW); } break; case SHAPE_HEIGHTMAP: { shape = memnew(HeightMapShapeSW); } break; case SHAPE_CUSTOM: { ERR_FAIL_V(RID()); } break; } RID id = shape_owner.make_rid(shape); shape->set_self(id); return id; };
int PhysicsDirectSpaceStateSW::intersect_shape(const RID& p_shape, const Transform& p_xform,float p_margin,ShapeResult *r_results,int p_result_max,const Set<RID>& p_exclude,uint32_t p_layer_mask,uint32_t p_object_type_mask) { if (p_result_max<=0) return 0; ShapeSW *shape = static_cast<PhysicsServerSW*>(PhysicsServer::get_singleton())->shape_owner.get(p_shape); ERR_FAIL_COND_V(!shape,0); Rect3 aabb = p_xform.xform(shape->get_aabb()); int amount = space->broadphase->cull_aabb(aabb,space->intersection_query_results,SpaceSW::INTERSECTION_QUERY_MAX,space->intersection_query_subindex_results); int cc=0; //Transform ai = p_xform.affine_inverse(); for(int i=0;i<amount;i++) { if (cc>=p_result_max) break; if (!_match_object_type_query(space->intersection_query_results[i],p_layer_mask,p_object_type_mask)) continue; //area cant be picked by ray (default) if (p_exclude.has( space->intersection_query_results[i]->get_self())) continue; const CollisionObjectSW *col_obj=space->intersection_query_results[i]; int shape_idx=space->intersection_query_subindex_results[i]; if (!CollisionSolverSW::solve_static(shape,p_xform,col_obj->get_shape(shape_idx),col_obj->get_transform() * col_obj->get_shape_transform(shape_idx), NULL,NULL,NULL,p_margin,0)) continue; if (r_results) { r_results[cc].collider_id=col_obj->get_instance_id(); if (r_results[cc].collider_id!=0) r_results[cc].collider=ObjectDB::get_instance(r_results[cc].collider_id); else r_results[cc].collider=NULL; r_results[cc].rid=col_obj->get_self(); r_results[cc].shape=shape_idx; } cc++; } return cc; }
RID PhysicsServerSW::shape_create(ShapeType p_shape) { ShapeSW *shape = NULL; switch (p_shape) { case SHAPE_PLANE: { shape = memnew(PlaneShapeSW); } break; case SHAPE_RAY: { shape = memnew(RayShapeSW); } break; case SHAPE_SPHERE: { shape = memnew(SphereShapeSW); } break; case SHAPE_BOX: { shape = memnew(BoxShapeSW); } break; case SHAPE_CAPSULE: { shape = memnew(CapsuleShapeSW); } break; case SHAPE_CONVEX_POLYGON: { shape = memnew(ConvexPolygonShapeSW); } break; case SHAPE_CONCAVE_POLYGON: { shape = memnew(ConcavePolygonShapeSW); } break; case SHAPE_HEIGHTMAP: { shape = memnew(HeightMapShapeSW); } break; case SHAPE_CUSTOM: { ERR_FAIL_V(RID()); } break; } RID id = shape_owner.make_rid(shape); shape->set_self(id); return id; };
Vector3 PhysicsDirectSpaceStateSW::get_closest_point_to_object_volume(RID p_object, const Vector3 p_point) const { CollisionObjectSW *obj = PhysicsServerSW::singleton->area_owner.getornull(p_object); if (!obj) { obj = PhysicsServerSW::singleton->body_owner.getornull(p_object); } ERR_FAIL_COND_V(!obj, Vector3()); ERR_FAIL_COND_V(obj->get_space() != space, Vector3()); float min_distance = 1e20; Vector3 min_point; bool shapes_found = false; for (int i = 0; i < obj->get_shape_count(); i++) { if (obj->is_shape_set_as_disabled(i)) continue; Transform shape_xform = obj->get_transform() * obj->get_shape_transform(i); ShapeSW *shape = obj->get_shape(i); Vector3 point = shape->get_closest_point_to(shape_xform.affine_inverse().xform(p_point)); point = shape_xform.xform(point); float dist = point.distance_to(p_point); if (dist < min_distance) { min_distance = dist; min_point = point; } shapes_found = true; } if (!shapes_found) { return obj->get_transform().origin; //no shapes found, use distance to origin. } else { return min_point; } }
void PhysicsServerSW::free(RID p_rid) { if (shape_owner.owns(p_rid)) { ShapeSW *shape = shape_owner.get(p_rid); while(shape->get_owners().size()) { ShapeOwnerSW *so=shape->get_owners().front()->key(); so->remove_shape(shape); } shape_owner.free(p_rid); memdelete(shape); } else if (body_owner.owns(p_rid)) { BodySW *body = body_owner.get(p_rid); // if (body->get_state_query()) // _clear_query(body->get_state_query()); // if (body->get_direct_state_query()) // _clear_query(body->get_direct_state_query()); body->set_space(NULL); while( body->get_shape_count() ) { body->remove_shape(0); } while (body->get_constraint_map().size()) { RID self = body->get_constraint_map().front()->key()->get_self(); ERR_FAIL_COND(!self.is_valid()); free(self); } body_owner.free(p_rid); memdelete(body); } else if (area_owner.owns(p_rid)) { AreaSW *area = area_owner.get(p_rid); // if (area->get_monitor_query()) // _clear_query(area->get_monitor_query()); area->set_space(NULL); while( area->get_shape_count() ) { area->remove_shape(0); } area_owner.free(p_rid); memdelete(area); } else if (space_owner.owns(p_rid)) { SpaceSW *space = space_owner.get(p_rid); while(space->get_objects().size()) { CollisionObjectSW *co = (CollisionObjectSW *)space->get_objects().front()->get(); co->set_space(NULL); } active_spaces.erase(space); free(space->get_default_area()->get_self()); free(space->get_static_global_body()); space_owner.free(p_rid); memdelete(space); } else if (joint_owner.owns(p_rid)) { JointSW *joint = joint_owner.get(p_rid); for(int i=0;i<joint->get_body_count();i++) { joint->get_body_ptr()[i]->remove_constraint(joint); } joint_owner.free(p_rid); memdelete(joint); } else { ERR_EXPLAIN("Invalid ID"); ERR_FAIL(); } };
bool PhysicsDirectSpaceStateSW::cast_motion(const RID& p_shape, const Transform& p_xform,const Vector3& p_motion,float p_margin,float &p_closest_safe,float &p_closest_unsafe, const Set<RID>& p_exclude,uint32_t p_layer_mask,uint32_t p_object_type_mask,ShapeRestInfo *r_info) { ShapeSW *shape = static_cast<PhysicsServerSW*>(PhysicsServer::get_singleton())->shape_owner.get(p_shape); ERR_FAIL_COND_V(!shape,false); AABB aabb = p_xform.xform(shape->get_aabb()); aabb=aabb.merge(AABB(aabb.pos+p_motion,aabb.size)); //motion aabb=aabb.grow(p_margin); //if (p_motion!=Vector3()) // print_line(p_motion); int amount = space->broadphase->cull_aabb(aabb,space->intersection_query_results,SpaceSW::INTERSECTION_QUERY_MAX,space->intersection_query_subindex_results); float best_safe=1; float best_unsafe=1; Transform xform_inv = p_xform.affine_inverse(); MotionShapeSW mshape; mshape.shape=shape; mshape.motion=xform_inv.basis.xform(p_motion); bool best_first=true; Vector3 closest_A,closest_B; for(int i=0;i<amount;i++) { if (!_match_object_type_query(space->intersection_query_results[i],p_layer_mask,p_object_type_mask)) continue; if (p_exclude.has( space->intersection_query_results[i]->get_self())) continue; //ignore excluded const CollisionObjectSW *col_obj=space->intersection_query_results[i]; int shape_idx=space->intersection_query_subindex_results[i]; Vector3 point_A,point_B; Vector3 sep_axis=p_motion.normalized(); Transform col_obj_xform = col_obj->get_transform() * col_obj->get_shape_transform(shape_idx); //test initial overlap, does it collide if going all the way? if (CollisionSolverSW::solve_distance(&mshape,p_xform,col_obj->get_shape(shape_idx),col_obj_xform,point_A,point_B,aabb,&sep_axis)) { //print_line("failed motion cast (no collision)"); continue; } //test initial overlap #if 0 if (CollisionSolverSW::solve_static(shape,p_xform,col_obj->get_shape(shape_idx),col_obj_xform,NULL,NULL,&sep_axis)) { print_line("failed initial cast (collision at begining)"); return false; } #else sep_axis=p_motion.normalized(); if (!CollisionSolverSW::solve_distance(shape,p_xform,col_obj->get_shape(shape_idx),col_obj_xform,point_A,point_B,aabb,&sep_axis)) { //print_line("failed motion cast (no collision)"); return false; } #endif //just do kinematic solving float low=0; float hi=1; Vector3 mnormal=p_motion.normalized(); for(int i=0;i<8;i++) { //steps should be customizable.. Transform xfa = p_xform; float ofs = (low+hi)*0.5; Vector3 sep=mnormal; //important optimization for this to work fast enough mshape.motion=xform_inv.basis.xform(p_motion*ofs); Vector3 lA,lB; bool collided = !CollisionSolverSW::solve_distance(&mshape,p_xform,col_obj->get_shape(shape_idx),col_obj_xform,lA,lB,aabb,&sep); if (collided) { //print_line(itos(i)+": "+rtos(ofs)); hi=ofs; } else { point_A=lA; point_B=lB; low=ofs; } } if (low<best_safe) { best_first=true; //force reset best_safe=low; best_unsafe=hi; } if (r_info && (best_first || (point_A.distance_squared_to(point_B) < closest_A.distance_squared_to(closest_B) && low<=best_safe))) { closest_A=point_A; closest_B=point_B; r_info->collider_id=col_obj->get_instance_id(); r_info->rid=col_obj->get_self(); r_info->shape=shape_idx; r_info->point=closest_B; r_info->normal=(closest_A-closest_B).normalized(); best_first=false; if (col_obj->get_type()==CollisionObjectSW::TYPE_BODY) { const BodySW *body=static_cast<const BodySW*>(col_obj); r_info->linear_velocity= body->get_linear_velocity() + (body->get_angular_velocity()).cross(body->get_transform().origin - closest_B); } } } p_closest_safe=best_safe; p_closest_unsafe=best_unsafe; return true; }