From ed191088913b6e36ad0749b7f487906ad7b80198 Mon Sep 17 00:00:00 2001 From: Sergej Reich Date: Sun, 21 Apr 2013 19:53:40 +0000 Subject: rigidbody: Add function to perform convex sweep test This is a experimental collision detection function, so the API might change in the future. Note: The simulation needs to be stepped before this function can be used, otherwise the rigid body world might not be valid. Patch [#34989] Bullet Convex sweep test API by Vilem Novak (pildanovak), thanks! --- intern/rigidbody/RBI_api.h | 6 +++ intern/rigidbody/rb_bullet_api.cpp | 50 ++++++++++++++++++++++++ source/blender/makesrna/intern/rna_rigidbody.c | 54 +++++++++++++++++++++++++- 3 files changed, 109 insertions(+), 1 deletion(-) diff --git a/intern/rigidbody/RBI_api.h b/intern/rigidbody/RBI_api.h index e7c88d96873..7a04961f99d 100644 --- a/intern/rigidbody/RBI_api.h +++ b/intern/rigidbody/RBI_api.h @@ -110,6 +110,12 @@ extern void RB_dworld_add_body(rbDynamicsWorld *world, rbRigidBody *body, int co /* Remove RigidBody from dynamics world */ extern void RB_dworld_remove_body(rbDynamicsWorld *world, rbRigidBody *body); +/* Collision detection */ + +void RB_world_convex_sweep_test(rbDynamicsWorld *world, rbRigidBody *object, + const float loc_start[3], const float loc_end[3], + float v_location[3], float v_hitpoint[3], float v_normal[3], int *r_hit); + /* ............ */ /* Create new RigidBody instance */ diff --git a/intern/rigidbody/rb_bullet_api.cpp b/intern/rigidbody/rb_bullet_api.cpp index e9e5e2a5e32..7bc480b1583 100644 --- a/intern/rigidbody/rb_bullet_api.cpp +++ b/intern/rigidbody/rb_bullet_api.cpp @@ -242,6 +242,56 @@ void RB_dworld_remove_body(rbDynamicsWorld *world, rbRigidBody *object) world->dynamicsWorld->removeRigidBody(body); } +/* Collision detection */ + +void RB_world_convex_sweep_test(rbDynamicsWorld *world, rbRigidBody *object, const float loc_start[3], const float loc_end[3], float v_location[3], float v_hitpoint[3], float v_normal[3], int *r_hit) +{ + btRigidBody *body = object->body; + btCollisionShape *collisionShape = body->getCollisionShape(); + /* only convex shapes are supported, but user can specify a non convex shape */ + if (collisionShape->isConvex()) { + btCollisionWorld::ClosestConvexResultCallback result(btVector3(loc_start[0], loc_start[1], loc_start[2]), btVector3(loc_end[0], loc_end[1], loc_end[2])); + + btQuaternion obRot = body->getWorldTransform().getRotation(); + + btTransform rayFromTrans; + rayFromTrans.setIdentity(); + rayFromTrans.setRotation(obRot); + rayFromTrans.setOrigin(btVector3(loc_start[0], loc_start[1], loc_start[2])); + + btTransform rayToTrans; + rayToTrans.setIdentity(); + rayToTrans.setRotation(obRot); + rayToTrans.setOrigin(btVector3(loc_end[0], loc_end[1], loc_end[2])); + + world->dynamicsWorld->convexSweepTest((btConvexShape*) collisionShape, rayFromTrans, rayToTrans, result, 0); + + if (result.hasHit()) { + *r_hit = 1; + + v_location[0] = result.m_convexFromWorld[0]+(result.m_convexToWorld[0]-result.m_convexFromWorld[0])*result.m_closestHitFraction; + v_location[1] = result.m_convexFromWorld[1]+(result.m_convexToWorld[1]-result.m_convexFromWorld[1])*result.m_closestHitFraction; + v_location[2] = result.m_convexFromWorld[2]+(result.m_convexToWorld[2]-result.m_convexFromWorld[2])*result.m_closestHitFraction; + + v_hitpoint[0] = result.m_hitPointWorld[0]; + v_hitpoint[1] = result.m_hitPointWorld[1]; + v_hitpoint[2] = result.m_hitPointWorld[2]; + + v_normal[0] = result.m_hitNormalWorld[0]; + v_normal[1] = result.m_hitNormalWorld[1]; + v_normal[2] = result.m_hitNormalWorld[2]; + + } + else { + *r_hit = 0; + } + } + else{ + /* we need to return a value if user passes non convex body, to report */ + *r_hit = -2; + } +} + /* ............ */ rbRigidBody *RB_body_new(rbCollisionShape *shape, const float loc[3], const float rot[4]) diff --git a/source/blender/makesrna/intern/rna_rigidbody.c b/source/blender/makesrna/intern/rna_rigidbody.c index daa1287c650..23c098d6aee 100644 --- a/source/blender/makesrna/intern/rna_rigidbody.c +++ b/source/blender/makesrna/intern/rna_rigidbody.c @@ -594,6 +594,24 @@ static void rna_RigidBodyCon_motor_ang_target_velocity_set(PointerRNA *ptr, floa #endif } +/* Sweep test */ +static void rna_RigidBodyWorld_convex_sweep_test(RigidBodyWorld *rbw, ReportList *reports, Object *object, float ray_start[3], float ray_end[3], float r_location[3], float r_hitpoint[3], float r_normal[3], int *r_hit) +{ +#ifdef WITH_BULLET + RigidBodyOb *rob = object->rigidbody_object; + + if (rbw->physics_world != NULL && rob->physics_object != NULL) { + RB_world_convex_sweep_test(rbw->physics_world, rob->physics_object, ray_start, ray_end, r_location, r_hitpoint, r_normal, r_hit); + if (*r_hit == -2) { + BKE_report(reports, RPT_ERROR, "A non convex collision shape was passed to the function. Use only convex collision shapes."); + } + } + else { + *r_hit=-1; + BKE_report(reports, RPT_ERROR, "Rigidbody world was not properly initialized, need to step the simulation first"); + } +#endif +} #else @@ -601,7 +619,8 @@ static void rna_def_rigidbody_world(BlenderRNA *brna) { StructRNA *srna; PropertyRNA *prop; - + FunctionRNA *func; + srna = RNA_def_struct(brna, "RigidBodyWorld", NULL); RNA_def_struct_sdna(srna, "RigidBodyWorld"); RNA_def_struct_ui_text(srna, "Rigid Body World", "Self-contained rigid body simulation environment and settings"); @@ -678,6 +697,39 @@ static void rna_def_rigidbody_world(BlenderRNA *brna) RNA_def_property_struct_type(prop, "EffectorWeights"); RNA_def_property_clear_flag(prop, PROP_EDITABLE); RNA_def_property_ui_text(prop, "Effector Weights", ""); + + /* Sweep test */ + func = RNA_def_function(srna, "convex_sweep_test", "rna_RigidBodyWorld_convex_sweep_test"); + RNA_def_function_ui_description(func, "Sweep test convex rigidbody against the current rigidbody world"); + RNA_def_function_flag(func, FUNC_USE_REPORTS); + + prop = RNA_def_pointer(func, "object", "Object", "", "Rigidbody object with a convex collision shape"); + RNA_def_property_flag(prop, PROP_REQUIRED | PROP_NEVER_NULL); + RNA_def_property_clear_flag(prop, PROP_THICK_WRAP); + + /* ray start and end */ + prop = RNA_def_float_vector(func, "start", 3, NULL, -FLT_MAX, FLT_MAX, "", "", -1e4, 1e4); + RNA_def_property_flag(prop, PROP_REQUIRED); + prop = RNA_def_float_vector(func, "end", 3, NULL, -FLT_MAX, FLT_MAX, "", "", -1e4, 1e4); + RNA_def_property_flag(prop, PROP_REQUIRED); + + prop = RNA_def_float_vector(func, "object_location", 3, NULL, -FLT_MAX, FLT_MAX, "Location", + "The hit location of this sweep test", -1e4, 1e4); + RNA_def_property_flag(prop, PROP_THICK_WRAP); + RNA_def_function_output(func, prop); + + prop = RNA_def_float_vector(func, "hitpoint", 3, NULL, -FLT_MAX, FLT_MAX, "Hitpoint", + "The hit location of this sweep test", -1e4, 1e4); + RNA_def_property_flag(prop, PROP_THICK_WRAP); + RNA_def_function_output(func, prop); + + prop = RNA_def_float_vector(func, "normal", 3, NULL, -FLT_MAX, FLT_MAX, "Normal", + "The face normal at the sweep test hit location", -1e4, 1e4); + RNA_def_property_flag(prop, PROP_THICK_WRAP); + RNA_def_function_output(func, prop); + + prop = RNA_def_int(func, "has_hit", 0, 0, 0, "", "If the function has found collision point, value is 1, otherwise 0", 0, 0); + RNA_def_function_output(func, prop); } static void rna_def_rigidbody_object(BlenderRNA *brna) -- cgit v1.2.3