📄 ivp_object.cxx
字号:
// Copyright (C) Ipion Software GmbH 1999-2000. All rights reserved.
#ifndef WIN32
# pragma implementation "ivp_object.hxx"
# pragma implementation "ivp_real_object.hxx"
#endif
#include <ivp_physics.hxx>
#include <string.h>
#include <ivu_matrix_macros.hxx>
#include <ivu_float.hxx>
#include <ivp_core_macros.hxx>
#include <ivp_sim_unit.hxx>
#include <ivp_physic_private.hxx>
#include <ivp_listener_object.hxx>
#include <ivp_templates.hxx>
#include <ivp_hull_manager.hxx>
#include <ivp_mindist_intern.hxx>
#include <ivp_friction.hxx>
#include <ivp_actuator.hxx>
#include <ivp_cache_object.hxx>
#include <ivp_debug_manager.hxx>
#include <ivp_i_friction_hash.hxx>
#include <ivp_i_controller_vhash.hxx>
#include <ivp_clustering_longrange.hxx>
#include <ivu_min_hash.hxx>
#include <ivp_radar.hxx>
#include <ivp_phantom.hxx>
#include <ivp_calc_next_psi_solver.hxx>
void IVP_Real_Object::change_nocoll_group_ident(const char *new_string ) {
if (!new_string){
nocoll_group_ident[0] = 0;
return;
}
if (strlen(new_string) > IVP_NO_COLL_GROUP_STRING_LEN){
CORE;
}
strncpy( nocoll_group_ident, new_string, IVP_NO_COLL_GROUP_STRING_LEN);
}
void IVP_Real_Object::set_pinned(IVP_BOOL is_pinned)
{
IVP_Core* core = this->get_core();
/**
* Set the core pinned flag and zero the velocities
*/
core->pinned = is_pinned;
core->speed.set_to_zero();
core->rot_speed.set_to_zero();
if(is_pinned == IVP_TRUE)
{
/**
* Disable collision detection
*/
IVP_BOOL c_enabled = is_collision_detection_enabled();
this->enable_collision_detection(IVP_FALSE);
/**
* Pinning: Set the inertia tensor inverse and mass inverse to 0; this
* will make the object virtually of infinite mass (i.e. 1/mass ~= 0)
*/
core->inv_rot_inertia.set(0.0f, 0.0f, 0.0f);
core->inv_rot_inertia.hesse_val = 0.0f;
/**
* Reset collision detection
*/
this->enable_collision_detection(c_enabled);
}
else
{
/**
* Unpinning: Set the inertia tensor inverse to be the inverse of the
* inertia tensor, and the mass inverse to be the inverse of the mass.
* (i.e., restore the object mass values)
*/
const IVP_U_Float_Point* i = core->get_rot_inertia();
core->inv_rot_inertia.set(1.0f / i->k[0], 1.0f / i->k[1], 1.0f / i->k[2]);
core->inv_rot_inertia.hesse_val = 1.0f / core->get_mass();
/**
* Rebuild mindists for this object
*/
this->get_environment()->get_mindist_manager()->recheck_ov_element(this);
}
}
void IVP_Real_Object::change_fast_piling_allowed(IVP_BOOL bool_flag) {
this->friction_core->set_fast_piling_allowed(bool_flag);
}
void IVP_Real_Object::change_mass( IVP_FLOAT new_mass ) {
this->get_core()->set_mass(new_mass);
}
void IVP_Real_Object::change_unmovable_flag( IVP_BOOL flag ) {
//printf("changing_unmov_flag to %d at time %f csimfl %d osimfl %d\n",flag,get_core()->environment->get_current_time(),this->get_core()->movement_state,this->object_movement_state);
//friction info is stored differently in movables and unmovables, so destroy first
IVP_Core *my_core=this->get_core();
if( my_core->physical_unmoveable == flag ) {
return;
}
int d;
for(d = my_core->objects.len()-1;d>=0;d--) {
IVP_Real_Object *r_obj=my_core->objects.element_at(d);
r_obj->unlink_contact_points(IVP_FALSE);
}
//printf("for_umove_info %lx\n",(long)my_core->core_friction_info.for_unmoveables.l_friction_info_hash);
if(my_core->physical_unmoveable) {
P_DELETE(my_core->core_friction_info.for_unmoveables.l_friction_info_hash);
} else {
my_core->core_friction_info.for_moveables.moveable_core_friction_info=NULL;
}
if(my_core->movement_state < IVP_MT_NOT_SIM) {
my_core->freeze_simulation_core();
}
my_core->physical_unmoveable = flag;
if(flag==IVP_TRUE) {
//switched from movable to unmovable
//printf("switch_to_unmovable: controllers: %d\n",my_core->controllers_of_core.len());
if(my_core->sim_unit_of_core) {
my_core->sim_unit_of_core->sim_unit_remove_core(my_core);
my_core->sim_unit_of_core=new IVP_Simulation_Unit();
my_core->sim_unit_of_core->add_sim_unit_core(my_core);
my_core->sim_unit_of_core->set_unit_movement_type(IVP_MT_NOT_SIM);
//clear all controllers. CORRECT would be: give all controllers signal that core switched to unmovable
int ic;
for(ic=my_core->controllers_of_core.len()-1;ic>=0;ic--) {
my_core->controllers_of_core.remove_at(ic);
}
my_core->environment->get_sim_units_manager()->add_sim_unit_to_manager(my_core->sim_unit_of_core);
my_core->add_core_controller(my_core->environment->standard_gravity_controller);
}
} else {
//printf("switch_to_movable\n");
}
}
void IVP_Real_Object::recompile_values_changed() {
this->get_core()->values_changed_recalc_redundants();
}
void IVP_Real_Object::recompile_material_changed() {
this->get_core()->values_changed_recalc_redundants();
}
void IVP_Real_Object::enable_collision_detection(IVP_BOOL enable){
if (enable){
if (!this->flags.collision_detection_enabled ){
get_environment()->get_mindist_manager()->enable_collision_detection_for_object(this);
this->flags.collision_detection_enabled = IVP_TRUE;
}
}else{
if (this->flags.collision_detection_enabled ){
P_DELETE(this->ov_element);
this->flags.collision_detection_enabled = IVP_FALSE;
unlink_contact_points(IVP_TRUE); //do it silently (do not wake up objects)
}
}
}
void IVP_Real_Object::ensure_in_simulation_now(){
// Note IVP_MT_STATIC != IVP_MT_NOT_SIM
IVP_ASSERT( !this->get_core()->physical_unmoveable );
if (this->physical_core->movement_state==IVP_MT_NOT_SIM){
this->revive_object_for_simulation();
}
};
void IVP_Real_Object::set_new_m_object_f_core( const IVP_U_Matrix *new_m_object_f_core){
IVP_U_Matrix new_m_core_f_object; new_m_core_f_object.set_transpose(new_m_object_f_core);
IVP_Anchor *a;
for (a = anchors; a ; a= a->anchor_next_in_object){
new_m_core_f_object.vmult4( &a->object_pos, &a->core_pos );
}
if ( new_m_core_f_object.vv.quad_length() < P_RES_EPS * P_RES_EPS){
flags.shift_core_f_object_is_zero = IVP_TRUE;
shift_core_f_object.set_to_zero();
}else{
shift_core_f_object.set( &new_m_core_f_object.vv );
flags.shift_core_f_object_is_zero = IVP_FALSE;
}
const IVP_U_Matrix *m = new_m_object_f_core;
if ( m->get_elem(0,0) == 1.0f && m->get_elem(1,1) == 1.0f && m->get_elem(2,2) == 1.0f ){
P_DELETE( q_core_f_object );
}else{
if (!q_core_f_object) q_core_f_object = new IVP_U_Quat();
q_core_f_object->set_quaternion(&new_m_core_f_object);
q_core_f_object->normize_quat();
}
// invalid caches !!
if (cache_object){
get_environment()->get_cache_object_manager()->invalid_cache_object(this); // removes cache_ledge_point too
}
}
void IVP_Real_Object::set_new_quat_object_f_core( const IVP_U_Quat *new_quat_object_f_core, const IVP_U_Point *trans_object_f_core){
IVP_U_Matrix m;
new_quat_object_f_core->set_matrix(&m);
m.vv.set(trans_object_f_core);
set_new_m_object_f_core(&m);
}
void IVP_Real_Object::add_listener_collision(IVP_Listener_Collision *listener){
environment->get_cluster_manager()->add_listener_collision(this,listener);
}
void IVP_Real_Object::remove_listener_collision(IVP_Listener_Collision *listener){
environment->get_cluster_manager()->remove_listener_collision(this,listener);
}
void IVP_Real_Object::add_listener_object(IVP_Listener_Object *listener){
environment->get_cluster_manager()->add_listener_object(this,listener);
}
void IVP_Real_Object::remove_listener_object(IVP_Listener_Object *listener){
environment->get_cluster_manager()->remove_listener_object(this,listener);
}
void IVP_Real_Object::insert_anchor(IVP_Anchor *new_anchor)
{
new_anchor->anchor_prev_in_object=NULL;
new_anchor->anchor_next_in_object=this->anchors;
if (this->anchors){
this->anchors->anchor_prev_in_object=new_anchor;
}
this->anchors=new_anchor;
}
void IVP_Real_Object::remove_anchor(IVP_Anchor *destroy_anch)
{
IVP_Anchor *previous=destroy_anch->anchor_prev_in_object;
IVP_Anchor *following=destroy_anch->anchor_next_in_object;
if(previous!=NULL)
{
previous->anchor_next_in_object=following;
} else {
this->anchors=following;
}
if(following!=NULL)
{
following->anchor_prev_in_object=previous;
}
}
// update all mindists between this objects and other objects whose core has invalid 'mindist_event_already_done'
void IVP_Real_Object::update_exact_mindist_events_of_object() {
IVP_Synapse_Real *syn, *syn_next; // minimal dist may remove itself from list
for (syn = this->get_first_exact_synapse(); syn; syn = syn_next){
syn_next= syn->get_next();
IVP_Mindist *mindist = syn->get_mindist();
IVP_Core *core0 = mindist->get_synapse(0)->get_object()->physical_core;
IVP_Core *core1 = mindist->get_synapse(1)->get_object()->physical_core;
//at least one core has already right time code
if(core0->mindist_event_already_done != core1->mindist_event_already_done) { /// #+# OS: vector for recalc mindists
mindist->recalc_mindist(); // should not be needed as the current position has not changed
if (mindist->recalc_result == IVP_MDRR_OK){
mindist->update_exact_mindist_events(IVP_FALSE, IVP_EH_BIG_DELAY); // check length, do not check for hull, update time manager ...
}
}
}
}
IVP_BOOL IVP_Real_Object::disable_simulation() {
IVP_Core *core=get_core();
if(core->physical_unmoveable) {
return IVP_TRUE;
}
if(core->is_in_wakeup_vec) {
core->environment->remove_revive_core(core);
}
if(core->movement_state < IVP_MT_NOT_SIM) {
for(int c = core->objects.len()-1;c>=0;c--) {
IVP_Real_Object *r_obj=core->objects.element_at(c);
r_obj->unlink_contact_points(IVP_TRUE); //trick to prevent any friction systems to wake up my object again
}
core->q_world_f_core_calm_reference[0].set(&core->q_world_f_core_next_psi);
core->position_world_f_core_calm_reference[0].set( &core->pos_world_f_core_last_psi );
IVP_Time now_time=core->environment->get_current_time();
IVP_Time ref_time=now_time-20; //bad hack: this ensures that 'sim_unit_calc_movement_state' switches off simulation
core->time_of_calm_reference[0] = ref_time;
core->sim_unit_of_core->do_sim_unit_union_find();
return core->sim_unit_of_core->sim_unit_calc_movement_state(core->environment);
}
return IVP_TRUE;
}
// called at AT-Time
// normally wake up at PSI-time not allowed (not allowed in simulate_sim_units loop)
void IVP_Real_Object::revive_object_for_simulation()
{
if(this->get_movement_state() == IVP_MT_NOT_SIM){ // STATICS won't be revived too
//IVP_Environment *env=this->get_environment();
//IVP_ASSERT( env->state == IVP_ES_AT ); //TL: without this assert no controll
// this->friction_core->init_core_for_simulation();
this->friction_core->sim_unit_of_core->sim_unit_revive_for_simulation(this->friction_core->environment);
}
}
IVP_Real_Object::IVP_Real_Object(IVP_Cluster *cluster,IVP_SurfaceManager *surface_manager_,
const IVP_Template_Real_Object *templ_obj, const IVP_U_Quat *q_world_f_object, const IVP_U_Point *position)
: IVP_Real_Object_Fast(cluster, templ_obj)
{
IVP_U_Quat q_world_f_object_static;
if (!q_world_f_object){
q_world_f_object = &q_world_f_object_static;
q_world_f_object_static.init();
}
// ivp_message("IVP_Real_Object::IVP_Real_Object 0x%x - %s\n", this, templ_obj->get_name());
exact_synapses = NULL;
invalid_synapses = NULL;
friction_synapses = NULL;
surface_manager = surface_manager_;
anchors = NULL;
ov_element = NULL; // will be set by IVP_Mindist_Manager::enable_collision_detection
((int *) &flags)[0] = 0;
q_core_f_object = NULL;
shift_core_f_object.set_to_zero();
cache_object = NULL;
controller_phantom = NULL;
strncpy(nocoll_group_ident, templ_obj->get_nocoll_group_ident(),IVP_NO_COLL_GROUP_STRING_LEN);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -