📄 ivp_physic_private.cxx
字号:
// Copyright (C) Ipion Software GmbH 1999-2000. All rights reserved.
#include <ivp_physics.hxx>
#ifndef WIN32
# pragma implementation "ivp_physic_private.hxx"
# pragma implementation "ivp_listener_object.hxx"
# pragma implementation "ivp_listener_collision.hxx"
# pragma implementation "ivp_controller.hxx"
#endif
#include <ivp_listener_object.hxx>
#include <ivp_listener_collision.hxx>
#include <ivp_physic_private.hxx>
#include <ivp_i_object_vhash.hxx>
#include <ivp_i_collision_vhash.hxx>
#include <ivp_mindist_intern.hxx> //because of Mindist
#include <ivp_friction.hxx>
#include <ivu_active_value.hxx>
#include <ivp_actuator.hxx>
#include <ivp_debug_manager.hxx> //because of debug psi_synchrone
#include <ivp_merge_core.hxx>
#include <ivp_debug.hxx>
#include <ivp_universe_manager.hxx>
#include <ivp_authenticity.hxx>
void IVP_Listener_Collision::event_pre_collision( IVP_Event_Collision *){;}; // the user app sould override this
void IVP_Listener_Collision::event_post_collision( IVP_Event_Collision *){;}; // the user app sould override this
void IVP_Listener_Collision::event_collision_object_deleted( IVP_Real_Object *){;}; // only object private callbacks are called
// friction
// set the IVP_LISTENER_COLLISION_CALLBACK_FRICTION bit in the constructor if you want to use this
void IVP_Listener_Collision::event_friction_created(IVP_Event_Friction *){;}; // the user app sould override this
void IVP_Listener_Collision::event_friction_deleted(IVP_Event_Friction *){;}; // the user app sould override this
IVP_Cluster *IVP_Cluster_Manager::get_root_cluster()
{
return root_cluster;
}
IVP_Cluster_Manager::IVP_Cluster_Manager(IVP_Environment *env)
{
P_MEM_CLEAR(this);
environment = env;
root_cluster = new IVP_Cluster(env);
this->obj_callback_hash = new IVP_Object_Callback_Table_Hash(16);
this->collision_callback_hash = new IVP_Collision_Callback_Table_Hash(16);
}
void IVP_Cluster_Manager::fire_event_object_deleted(IVP_Event_Object *event_obj)
{
IVP_Object_Callback_Table *obj_table;
IVP_Real_Object *ro = event_obj->real_object;
obj_table = this->obj_callback_hash->find_table(ro);
if ( obj_table != NULL ) {
int i;
for (i=obj_table->listeners.len()-1; i>=0; i--) {
IVP_Listener_Object *lis = obj_table->listeners.element_at(i);
lis->event_object_deleted(event_obj);
if (i>0 && !obj_callback_hash->find_table(ro)) break; // object deleted
}
}
}
void IVP_Cluster_Manager::fire_event_object_frozen(IVP_Event_Object *event_obj)
{
IVP_Object_Callback_Table *obj_table;
IVP_Real_Object *ro = event_obj->real_object;
obj_table = this->obj_callback_hash->find_table(ro);
if ( obj_table != NULL ) {
int i;
for (i=obj_table->listeners.len()-1; i>=0; i--) {
IVP_Listener_Object *lis = obj_table->listeners.element_at(i);
lis->event_object_frozen(event_obj);
if (i>0 && !obj_callback_hash->find_table(ro)) break; // object deleted
}
}
}
void IVP_Cluster_Manager::fire_event_object_created(IVP_Event_Object *event_obj)
{
IVP_Object_Callback_Table *obj_table;
IVP_Real_Object *ro = event_obj->real_object;
obj_table = this->obj_callback_hash->find_table(ro);
if ( obj_table != NULL ) {
int i;
for (i=obj_table->listeners.len()-1; i>=0; i--) {
IVP_Listener_Object *lis = obj_table->listeners.element_at(i);
lis->event_object_created(event_obj);
if (i>0 && !obj_callback_hash->find_table(ro)) break; // object deleted
}
}
}
void IVP_Cluster_Manager::fire_event_object_revived(IVP_Event_Object *event_obj)
{
IVP_Object_Callback_Table *obj_table;
IVP_Real_Object *ro = event_obj->real_object;
obj_table = this->obj_callback_hash->find_table(ro);
if ( obj_table != NULL ) {
int i;
for (i=obj_table->listeners.len()-1; i>=0; i--) {
IVP_Listener_Object *lis = obj_table->listeners.element_at(i);
lis->event_object_revived(event_obj);
if (i>0 && !obj_callback_hash->find_table(ro)) break; // object deleted
}
}
}
void IVP_Cluster_Manager::fire_event_pre_collision(IVP_Real_Object *real_object, IVP_Event_Collision *event_obj)
{
IVP_Collision_Callback_Table *obj_table;
obj_table = this->collision_callback_hash->find_table(real_object);
if ( obj_table != NULL ) {
int i;
for (i=obj_table->listeners.len()-1; i>=0; i--) {
IVP_Listener_Collision *lis = obj_table->listeners.element_at(i);
if (!(lis->get_enabled_callbacks() & IVP_LISTENER_COLLISION_CALLBACK_PRE_COLLISION)) continue;
lis->event_pre_collision(event_obj);
if (i>0 && !collision_callback_hash->find_table(real_object)) break; // object deleted
}
}
}
void IVP_Cluster_Manager::fire_event_post_collision(IVP_Real_Object *real_object, IVP_Event_Collision *event_obj)
{
IVP_Collision_Callback_Table *obj_table;
obj_table = this->collision_callback_hash->find_table(real_object);
if ( obj_table != NULL ) {
int i;
for (i=obj_table->listeners.len()-1; i>=0; i--) {
IVP_Listener_Collision *lis = obj_table->listeners.element_at(i);
if (!(lis->get_enabled_callbacks() & IVP_LISTENER_COLLISION_CALLBACK_POST_COLLISION)) continue;
lis->event_post_collision(event_obj);
if (i>0 && !collision_callback_hash->find_table(real_object)) break; // object deleted
}
}
}
void IVP_Cluster_Manager::fire_event_collision_object_deleted(IVP_Real_Object *real_object)
{
IVP_Collision_Callback_Table *obj_table;
obj_table = this->collision_callback_hash->find_table(real_object);
if ( obj_table != NULL ) {
int i;
for (i=obj_table->listeners.len()-1; i>=0; i--) {
IVP_Listener_Collision *lis = obj_table->listeners.element_at(i);
if (!(lis->get_enabled_callbacks() & IVP_LISTENER_COLLISION_CALLBACK_OBJECT_DELETED)) continue;
lis->event_collision_object_deleted(real_object);
if (i>0 && !collision_callback_hash->find_table(real_object)) break; // object deleted
}
}
}
void IVP_Cluster_Manager::fire_event_friction_created(IVP_Real_Object *real_object, IVP_Event_Friction *event_friction)
{
IVP_Collision_Callback_Table *obj_table;
obj_table = this->collision_callback_hash->find_table(real_object);
if ( obj_table != NULL ) {
int i;
for (i=obj_table->listeners.len()-1; i>=0; i--) {
IVP_Listener_Collision *lis = obj_table->listeners.element_at(i);
if (!(lis->get_enabled_callbacks() & IVP_LISTENER_COLLISION_CALLBACK_FRICTION)) continue;
lis->event_friction_created(event_friction);
if (i>0 && !collision_callback_hash->find_table(real_object)) break; // object deleted
}
}
}
void IVP_Cluster_Manager::fire_event_friction_deleted(IVP_Real_Object *real_object, IVP_Event_Friction *event_friction)
{
IVP_Collision_Callback_Table *obj_table;
obj_table = this->collision_callback_hash->find_table(real_object);
if ( obj_table != NULL ) {
int i;
for (i=obj_table->listeners.len()-1; i>=0; i--) {
IVP_Listener_Collision *lis = obj_table->listeners.element_at(i);
if (!(lis->get_enabled_callbacks() & IVP_LISTENER_COLLISION_CALLBACK_FRICTION)) continue;
lis->event_friction_deleted(event_friction);
if (i>0 && !collision_callback_hash->find_table(real_object)) break; // object deleted
}
}
}
IVP_Real_Object *IVP_Cluster_Manager::get_next_real_object_in_cluster_tree(IVP_Object *object){
IVP_Object *next_object;
if (number_of_real_objects == 0) return NULL;
if (object == NULL){
IVP_Cluster *root = get_root_cluster();
object = root->get_first_object_of_cluster();
next_object = object; // no object supplied: we get the root cluster and we want the first object in root cluster!
if (!object) return NULL;
}
else {
next_object = object->next_in_cluster; // object supplied: just get the next object in cluster
}
IVP_OBJECT_TYPE type = object->get_type();
// try to go down as deep as possible
if(type == IVP_CLUSTER){
IVP_Cluster *cluster = object->to_cluster();
while(1){
object = cluster->get_first_object_of_cluster();
if (object){
type = object->get_type();
if (type != IVP_CLUSTER) return object->to_real();
cluster = object->to_cluster();
continue;
}else{
break; // just get next_in_cluster
}
}
}
IVP_Object *next;
// go up until a next pointer is found
for (next=next_object; !next; next=object->next_in_cluster) {
IVP_Object *old_father = object;
object = object->father_cluster;
if (!object){
IVP_Cluster *root = get_root_cluster();
if ( root == old_father ) return(NULL); /* necessary to avoid endless loop caused by the last object
* (ball's father is cluster; cluster has no father,
* therefore we would "get_root_cluster()" which is the same as
* the old cluster and whose first object is the "static ball"
* --> perfect endless loop :-) [SF, 25 nov 1999]
*/
object = root->get_first_object_of_cluster();
if (!object) return NULL;
}
}
// now a next is found
object = next;
type = object->get_type();
if (type == IVP_CLUSTER){
return get_next_real_object_in_cluster_tree(object);
}
return object->to_real();
}
void IVP_Cluster_Manager::check_for_unused_objects(IVP_Universe_Manager *um){
const IVP_Universe_Manager_Settings *ums = um->provide_universe_settings();
if (number_of_real_objects < ums->num_objects_in_environment_threshold_0) return;
{
int i = int( ums->check_objects_per_second_threshold_0 * environment->get_delta_PSI_time());
for ( ; i>=0; i-- ){
IVP_Real_Object *an_object = this->an_object_to_be_checked;
this->an_object_to_be_checked = get_next_real_object_in_cluster_tree(this->an_object_to_be_checked);
if (!an_object) return; // no objects available
if (an_object->get_collision_check_reference_count() != 0) continue;
um->object_no_longer_needed(an_object);
if (number_of_real_objects < ums->num_objects_in_environment_threshold_0) return;
}
}
if (number_of_real_objects < ums->num_objects_in_environment_threshold_1) return;
{
int i = int( ums->check_objects_per_second_threshold_1 * environment->get_delta_PSI_time());
for ( ; i>=0; i-- ){
IVP_Real_Object *an_object = this->an_object_to_be_checked;
if (!an_object) return; // no objects available
this->an_object_to_be_checked = get_next_real_object_in_cluster_tree(this->an_object_to_be_checked);
if (an_object->get_collision_check_reference_count() != 1) continue;
um->object_no_longer_needed(an_object);
if (number_of_real_objects < ums->num_objects_in_environment_threshold_1) return;
}
}
return;
}
IVP_Universe_Manager_Settings::IVP_Universe_Manager_Settings(){
num_objects_in_environment_threshold_0 = 1;
check_objects_per_second_threshold_0 = 1;
num_objects_in_environment_threshold_1 = 1000000;
check_objects_per_second_threshold_1 = 10;
};
IVP_Object_Callback_Table::~IVP_Object_Callback_Table()
{
return;
}
IVP_Collision_Callback_Table::~IVP_Collision_Callback_Table()
{
return;
}
IVP_Cluster_Manager::~IVP_Cluster_Manager()
{
P_DELETE( root_cluster );
P_DELETE(this->obj_callback_hash);
P_DELETE(this->collision_callback_hash);
}
void IVP_Cluster_Manager::add_listener_object(IVP_Real_Object *real_object, IVP_Listener_Object *listener)
{
IVP_Object_Callback_Table *obj_table;
obj_table = this->obj_callback_hash->find_table(real_object);
if ( obj_table != NULL ) {
obj_table->listeners.add(listener);
}
else {
obj_table = new IVP_Object_Callback_Table();
obj_table->real_object = real_object;
obj_table->listeners.add(listener);
this->obj_callback_hash->add_table(obj_table);
real_object->flags.object_listener_exists = 1;
}
return;
}
void IVP_Cluster_Manager::add_listener_collision(IVP_Real_Object *real_object, IVP_Listener_Collision *listener)
{
IVP_Collision_Callback_Table *obj_table;
obj_table = this->collision_callback_hash->find_table(real_object);
if ( obj_table != NULL ) {
obj_table->listeners.add(listener);
}
else {
obj_table = new IVP_Collision_Callback_Table();
obj_table->real_object = real_object;
obj_table->listeners.add(listener);
this->collision_callback_hash->add_table(obj_table);
real_object->flags.collision_listener_exists = 1;
}
return;
}
void IVP_Cluster_Manager::remove_listener_object(IVP_Real_Object *real_object, IVP_Listener_Object *listener)
{
IVP_Object_Callback_Table *obj_table;
obj_table = this->obj_callback_hash->find_table(real_object);
if ( obj_table != NULL ) {
obj_table->listeners.remove(listener);
if ( obj_table->listeners.len() == 0 ) {
this->obj_callback_hash->remove_table(real_object);
delete obj_table;
real_object->flags.object_listener_exists = 0;
}
}
return;
}
void IVP_Cluster_Manager::remove_listener_collision(IVP_Real_Object *real_object, IVP_Listener_Collision *listener)
{
IVP_Collision_Callback_Table *obj_table;
obj_table = this->collision_callback_hash->find_table(real_object);
if ( obj_table != NULL ) {
obj_table->listeners.remove(listener);
if ( obj_table->listeners.len() == 0 ) {
this->collision_callback_hash->remove_table(real_object);
delete obj_table;
real_object->flags.collision_listener_exists = 0;
}
}
return;
}
void IVP_Cluster_Manager::add_object(IVP_Real_Object * /*real_object*/ ){
this->number_of_real_objects++;
}
void IVP_Cluster_Manager::remove_object(IVP_Real_Object *real_object)
{
this->number_of_real_objects--;
IVP_Object_Callback_Table *obj_table;
obj_table = this->obj_callback_hash->find_table(real_object);
if ( obj_table != NULL ) {
this->obj_callback_hash->remove_table(real_object);
delete obj_table;
}
IVP_Collision_Callback_Table *coll_table;
coll_table = this->collision_callback_hash->find_table(real_object);
if ( coll_table != NULL ) {
this->collision_callback_hash->remove_table(real_object);
delete coll_table;
}
if (real_object == an_object_to_be_checked){
an_object_to_be_checked = get_next_real_object_in_cluster_tree(an_object_to_be_checked);
if (real_object == an_object_to_be_checked){
an_object_to_be_checked = NULL;
}
}
IVP_Universe_Manager *um = environment->get_universe_manager();
if (um){
um->event_object_deleted(real_object);
}
return;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -