Changeset View
Changeset View
Standalone View
Standalone View
source/blender/blenkernel/intern/rigidbody.c
| Show First 20 Lines • Show All 1,562 Lines • ▼ Show 20 Lines | static void rigidbody_update_sim_world(Scene *scene, RigidBodyWorld *rbw) | ||||
| /* update gravity, since this RNA setting is not part of RigidBody settings */ | /* update gravity, since this RNA setting is not part of RigidBody settings */ | ||||
| RB_dworld_set_gravity(rbw->shared->physics_world, adj_gravity); | RB_dworld_set_gravity(rbw->shared->physics_world, adj_gravity); | ||||
| /* update object array in case there are changes */ | /* update object array in case there are changes */ | ||||
| rigidbody_update_ob_array(rbw); | rigidbody_update_ob_array(rbw); | ||||
| } | } | ||||
| static void rigidbody_update_sim_ob( | static void rigidbody_update_sim_ob( | ||||
| Depsgraph *depsgraph, Scene *scene, RigidBodyWorld *rbw, Object *ob, RigidBodyOb *rbo) | Depsgraph *depsgraph, Object *ob, RigidBodyOb *rbo) | ||||
| { | { | ||||
| float loc[3]; | float loc[3]; | ||||
| float rot[4]; | float rot[4]; | ||||
| float scale[3]; | float scale[3]; | ||||
| /* only update if rigid body exists */ | /* only update if rigid body exists */ | ||||
| if (rbo->shared->physics_object == NULL) { | if (rbo->shared->physics_object == NULL) { | ||||
| return; | return; | ||||
| Show All 36 Lines | if (is_selected && (G.moving & G_TRANSFORM_OBJ)) { | ||||
| RB_body_set_mass(rbo->shared->physics_object, 0.0f); | RB_body_set_mass(rbo->shared->physics_object, 0.0f); | ||||
| } | } | ||||
| /* update rigid body location and rotation for kinematic bodies */ | /* update rigid body location and rotation for kinematic bodies */ | ||||
| if (rbo->flag & RBO_FLAG_KINEMATIC || (is_selected && (G.moving & G_TRANSFORM_OBJ))) { | if (rbo->flag & RBO_FLAG_KINEMATIC || (is_selected && (G.moving & G_TRANSFORM_OBJ))) { | ||||
| RB_body_activate(rbo->shared->physics_object); | RB_body_activate(rbo->shared->physics_object); | ||||
| RB_body_set_loc_rot(rbo->shared->physics_object, loc, rot); | RB_body_set_loc_rot(rbo->shared->physics_object, loc, rot); | ||||
| } | } | ||||
| /* update influence of effectors - but don't do it on an effector */ | /* NOTE: passive objects don't need to be updated since they don't move */ | ||||
| /* only dynamic bodies need effector update */ | |||||
| else if (rbo->type == RBO_TYPE_ACTIVE && | /* NOTE: no other settings need to be explicitly updated here, | ||||
| ((ob->pd == NULL) || (ob->pd->forcefield == PFIELD_NULL))) { | * since RNA setters take care of the rest :) | ||||
| */ | |||||
| } | |||||
| static void rigidbody_update_sim_ob_effectors( | |||||
| Depsgraph *depsgraph, Scene *scene, RigidBodyWorld *rbw, Object *ob, RigidBodyOb *rbo) | |||||
| { | |||||
| if (rbo->type == RBO_TYPE_ACTIVE) { | |||||
| EffectorWeights *effector_weights = rbw->effector_weights; | EffectorWeights *effector_weights = rbw->effector_weights; | ||||
| EffectedPoint epoint; | EffectedPoint epoint; | ||||
| ListBase *effectors; | ListBase *effectors; | ||||
| /* get effectors present in the group specified by effector_weights */ | /* get effectors present in the group specified by effector_weights */ | ||||
| effectors = BKE_effectors_create(depsgraph, ob, NULL, effector_weights); | effectors = BKE_effectors_create(depsgraph, ob, NULL, effector_weights); | ||||
| if (effectors) { | if (effectors) { | ||||
| float eff_force[3] = {0.0f, 0.0f, 0.0f}; | float eff_force[3] = {0.0f, 0.0f, 0.0f}; | ||||
| float eff_loc[3], eff_vel[3]; | float eff_loc[3], eff_vel[3]; | ||||
| /* create dummy 'point' which represents last known position of object as result of sim */ | /* create dummy 'point' which represents last known position of object as result of sim */ | ||||
| /* XXX: this can create some inaccuracies with sim position, | /* XXX: this can create some inaccuracies with sim position, | ||||
| * but is probably better than using un-simulated values? */ | * but is probably better than using un-simulated values? */ | ||||
| RB_body_get_position(rbo->shared->physics_object, eff_loc); | RB_body_get_position(rbo->shared->physics_object, eff_loc); | ||||
| RB_body_get_linear_velocity(rbo->shared->physics_object, eff_vel); | RB_body_get_linear_velocity(rbo->shared->physics_object, eff_vel); | ||||
| pd_point_from_loc(scene, eff_loc, eff_vel, 0, &epoint); | pd_point_from_loc(scene, eff_loc, eff_vel, 0, &epoint); | ||||
| /* ensure charge isn't undefined on rigidbodies, use the strength to determine the charge */ | |||||
| epoint.charge = ob->pd && ob->pd->f_strength < 0.0 ? -1.0 : 1.0; | |||||
weasel: `epoint.charge = ob->pd ? ob->pd->f_strength : 0;` works perfectly | |||||
| /* Calculate net force of effectors, and apply to sim object: | /* Calculate net force of effectors, and apply to sim object: | ||||
| * - we use 'central force' since apply force requires a "relative position" | * - we use 'central force' since apply force requires a "relative position" | ||||
| * which we don't have... */ | * which we don't have... */ | ||||
| BKE_effectors_apply(effectors, NULL, effector_weights, &epoint, eff_force, NULL); | BKE_effectors_apply(effectors, NULL, effector_weights, &epoint, eff_force, NULL); | ||||
| if (G.f & G_DEBUG) { | if (G.f & G_DEBUG) { | ||||
| printf("\tapplying force (%f,%f,%f) to '%s'\n", | printf("\tapplying force (%f,%f,%f) to '%s'\n", | ||||
| eff_force[0], | eff_force[0], | ||||
| eff_force[1], | eff_force[1], | ||||
| eff_force[2], | eff_force[2], | ||||
| ob->id.name + 2); | ob->id.name + 2); | ||||
| } | } | ||||
| /* activate object in case it is deactivated */ | /* activate object in case it is deactivated */ | ||||
| if (!is_zero_v3(eff_force)) { | if (!is_zero_v3(eff_force)) { | ||||
| RB_body_activate(rbo->shared->physics_object); | RB_body_activate(rbo->shared->physics_object); | ||||
| } | } | ||||
| RB_body_apply_central_force(rbo->shared->physics_object, eff_force); | RB_body_apply_central_force(rbo->shared->physics_object, eff_force); | ||||
| } | } | ||||
| else if (G.f & G_DEBUG) { | else if (G.f & G_DEBUG) { | ||||
| printf("\tno forces to apply to '%s'\n", ob->id.name + 2); | printf("\tno forces to apply to '%s'\n", ob->id.name + 2); | ||||
| } | } | ||||
| /* cleanup */ | /* cleanup */ | ||||
| BKE_effectors_free(effectors); | BKE_effectors_free(effectors); | ||||
| } | } | ||||
| /* NOTE: passive objects don't need to be updated since they don't move */ | |||||
| /* NOTE: no other settings need to be explicitly updated here, | |||||
| * since RNA setters take care of the rest :) | |||||
| */ | |||||
| } | } | ||||
| /** | /** | ||||
| * Updates and validates world, bodies and shapes. | * Updates and validates world, bodies and shapes. | ||||
| * | * | ||||
| * \param rebuild: Rebuild entire simulation | * \param rebuild: Rebuild entire simulation | ||||
| */ | */ | ||||
| static void rigidbody_update_simulation(Depsgraph *depsgraph, | static void rigidbody_update_simulation(Depsgraph *depsgraph, | ||||
| ▲ Show 20 Lines • Show All 75 Lines • ▼ Show 20 Lines | if (ob->type == OB_MESH) { | ||||
| /* XXX: we assume that this can only get applied for active/passive shapes | /* XXX: we assume that this can only get applied for active/passive shapes | ||||
| * that will be included as rigidbodies. */ | * that will be included as rigidbodies. */ | ||||
| RB_body_set_collision_shape(rbo->shared->physics_object, rbo->shared->physics_shape); | RB_body_set_collision_shape(rbo->shared->physics_object, rbo->shared->physics_shape); | ||||
| } | } | ||||
| } | } | ||||
| rbo->flag &= ~(RBO_FLAG_NEEDS_VALIDATE | RBO_FLAG_NEEDS_RESHAPE); | rbo->flag &= ~(RBO_FLAG_NEEDS_VALIDATE | RBO_FLAG_NEEDS_RESHAPE); | ||||
| /* update simulation object... */ | /* update simulation object... */ | ||||
| rigidbody_update_sim_ob(depsgraph, scene, rbw, ob, rbo); | rigidbody_update_sim_ob(depsgraph, ob, rbo); | ||||
| } | |||||
| } | |||||
| FOREACH_COLLECTION_OBJECT_RECURSIVE_END; | |||||
| /* update forces */ | |||||
| FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN (rbw->group, ob) { | |||||
| if (ob->type == OB_MESH) { | |||||
| /* validate that we've got valid object set up here... */ | |||||
| RigidBodyOb *rbo = ob->rigidbody_object; | |||||
| /* TODO remove this whole block once we are sure we never get NULL rbo here anymore. */ | |||||
| /* This cannot be done in CoW evaluation context anymore... */ | |||||
| if (rbo == NULL) { | |||||
| BLI_assert(!"CoW object part of RBW object collection without RB object data, " | |||||
| "should not happen.\n"); | |||||
| } | |||||
| /* update effectors influence */ | |||||
| rigidbody_update_sim_ob_effectors(depsgraph, scene, rbw, ob, rbo); | |||||
| } | } | ||||
| } | } | ||||
| FOREACH_COLLECTION_OBJECT_RECURSIVE_END; | FOREACH_COLLECTION_OBJECT_RECURSIVE_END; | ||||
| /* update constraints */ | /* update constraints */ | ||||
| if (rbw->constraints == NULL) { /* no constraints, move on */ | if (rbw->constraints == NULL) { /* no constraints, move on */ | ||||
| return; | return; | ||||
| } | } | ||||
| ▲ Show 20 Lines • Show All 423 Lines • Show Last 20 Lines | |||||
epoint.charge = ob->pd ? ob->pd->f_strength : 0; works perfectly