📄 ivp_clustering_visualizer.cxx
字号:
// Copyright (C) Ipion Software GmbH 2000. All rights reserved.
// IVP_EXPORT_PRIVATE
/*******************************************************************************
* INCLUDES
******************************************************************************/
// IVP includes
#include <ivp_physics.hxx>
#include <ivu_vhash.hxx>
#include <ivp_surman_polygon.hxx>
#include <ivp_compact_ledge.hxx>
#include <ivp_compact_surface.hxx>
#include <ivp_clustering_visual_hash.hxx>
#include <ivp_cache_object.hxx>
#include <ivp_clustering_visualizer.hxx>
/*******************************************************************************
* INTERNAL CLASSES & STRUCTS
******************************************************************************/
class IVP_Clustering_Visualizer_Shortrange_Nodedata {
public:
IVP_Compact_Ledgetree_Node * node;
int n_touches;
IVP_BOOL reported_ledge;
IVP_Clustering_Visualizer_Shortrange_Nodedata() {
this->node = NULL;
this->n_touches = 0;
this->reported_ledge = IVP_FALSE;
};
};
class IVP_Clustering_Visualizer_Shortrange_Objectdata {
public:
IVP_Real_Object * real_object;
IVP_U_Vector<IVP_Clustering_Visualizer_Shortrange_Nodedata> ledgetree_nodes;
IVP_U_Point center;
IVP_DOUBLE radius;
IVP_Clustering_Visualizer_Shortrange_Objectdata() {
this->real_object = NULL;
};
};
/*******************************************************************************
* GLOBAL VARIABLES
******************************************************************************/
#ifdef IVP_HOME_BUILD
IVP_Clustering_Visualizer ivp_global_clustering_visualizer;
#endif
/*******************************************************************************
* PRIVATE METHODS
******************************************************************************/
IVP_Clustering_Visualizer_Shortrange_Callback::~IVP_Clustering_Visualizer_Shortrange_Callback() {
return;
}
void IVP_Clustering_Visualizer_Shortrange::add_node_to_pipeline(const IVP_Compact_Ledgetree_Node *node, IVP_BOOL reported_ledge) {
int x;
for (x=0; x<this->pipelined_private_property_data->ledgetree_nodes.len(); x++) {
IVP_Clustering_Visualizer_Shortrange_Nodedata *nodedata = this->pipelined_private_property_data->ledgetree_nodes.element_at(x);
if ( nodedata->node == node ) {
nodedata->reported_ledge = (IVP_BOOL)((int)nodedata->reported_ledge || (int)reported_ledge);
if ( node->is_terminal() ) {
nodedata->n_touches++; // no reference counting for non-terminal nodes!
}
return;
}
}
IVP_Clustering_Visualizer_Shortrange_Nodedata *new_nodedata = new IVP_Clustering_Visualizer_Shortrange_Nodedata();
new_nodedata->node = (IVP_Compact_Ledgetree_Node *)node;
if ( node->is_terminal() ) new_nodedata->n_touches = 1;
else new_nodedata->n_touches = 0; // no reference counting for non-terminal nodes!
new_nodedata->reported_ledge = reported_ledge;
this->pipelined_private_property_data->ledgetree_nodes.add(new_nodedata);
//if ( this->remove_longrange_visualization ) {
// ivp_global_clustering_visualizer.longrange.devisualize(this->private_property);
//}
return;
}
IVP_BOOL IVP_Clustering_Visualizer_Shortrange::recursively_traverse_cluster(const IVP_Compact_Ledgetree_Node *node) {
// returns: IVP_TRUE, whenever node has been aborted (this includes terminal nodes!)
// IVP_FALSE, whenever node is inner node of traversal tree
// calculate some global values
IVP_U_Point distance_between_centers;
IVP_U_Point center; center.set(node->center.k);
distance_between_centers.subtract(¢er, &this->intruder_position_in_private_property_cs);
{
// first check sphere against sphere.
this->stats_n_sphere_collisiontests++;
IVP_DOUBLE sum_of_radii = this->intruder_radius + node->radius;
if ( distance_between_centers.quad_length() >= sum_of_radii * sum_of_radii ) goto abort;
}
// --> sphere collision detected!
{
// now check bounding box against bounding box.
this->stats_n_box_collisiontests++;
register IVP_FLOAT work = IVP_COMPACT_BOUNDINGBOX_STEP_SIZE * node->radius;
if ( IVP_Inline_Math::fabsd(distance_between_centers.k[0]) >= (node->box_sizes[0] * work + this->intruder_radius) ) goto abort;
if ( IVP_Inline_Math::fabsd(distance_between_centers.k[1]) >= (node->box_sizes[1] * work + this->intruder_radius) ) goto abort;
if ( IVP_Inline_Math::fabsd(distance_between_centers.k[2]) >= (node->box_sizes[2] * work + this->intruder_radius) ) goto abort;
}
// --> bounding box collision detected!
if ( node->is_terminal() ) {
this->add_node_to_pipeline(node, IVP_TRUE);
return(IVP_TRUE);
}
else if ( this->boxmode == TRAVERSED_BOXES ) {
this->add_node_to_pipeline(node, IVP_FALSE);
}
{
this->recursively_traverse_cluster(node->left_son());
this->recursively_traverse_cluster(node->right_son());
}
return(IVP_FALSE);
abort:
if ( this->boxmode != TERMINALS_ONLY ) { // display for ABORTED_BOXES and TRAVERSED_BOXES
this->add_node_to_pipeline(node, IVP_FALSE);
}
return(IVP_TRUE);
}
/*******************************************************************************
* PUBLIC METHODS
******************************************************************************/
void IVP_Clustering_Visualizer_Shortrange::visualize_collisions() {
if ( !this->enabled ) return;
this->stats_n_reported_ledges = 0;
int i;
for (i=0; i<this->output_callbacks.len(); i++) {
IVP_Clustering_Visualizer_Shortrange_Callback *callback = this->output_callbacks.element_at(i);
int x;
for (x=this->pipelined_objects.len()-1; x>=0; x--) {
IVP_Clustering_Visualizer_Shortrange_Objectdata *objectdata = this->pipelined_objects.element_at(x);
int y;
for (y=objectdata->ledgetree_nodes.len()-1; y>=0; y--) {
IVP_Clustering_Visualizer_Shortrange_Nodedata *nodedata = objectdata->ledgetree_nodes.element_at(y);
IVP_Compact_Ledgetree_Node *node = nodedata->node;
callback->private_property = objectdata->real_object; //this->private_property;
callback->node = node;
callback->n_touches = nodedata->n_touches;
callback->position.set(node->center.k);
callback->sphere_radius = node->radius;
callback->reported_ledge = nodedata->reported_ledge;
if ( callback->reported_ledge ) this->stats_n_reported_ledges++;
IVP_DOUBLE work = IVP_COMPACT_BOUNDINGBOX_STEP_SIZE * node->radius;
callback->box_extents.k[0] = node->box_sizes[0] * work;
callback->box_extents.k[1] = node->box_sizes[1] * work;
callback->box_extents.k[2] = node->box_sizes[2] * work;
callback->visualize_request_for_node();
objectdata->ledgetree_nodes.remove(nodedata);
P_DELETE(nodedata);
}
// ***
if ( objectdata->radius > 0.0 ) {
callback->position.set(&objectdata->center);
callback->box_extents.k[0] = objectdata->radius;
callback->visualize_request_for_intruder_radius();
}
// ***
this->pipelined_objects.remove(objectdata);
P_DELETE(objectdata);
}
}
// reset values for next frame
this->stats_n_sphere_collisiontests = 0;
this->stats_n_box_collisiontests = 0;
return;
}
void IVP_Clustering_Visualizer_Shortrange::analyze_collision(IVP_Real_Object *object0, IVP_DOUBLE radius0, IVP_Real_Object *object1, IVP_DOUBLE radius1) {
if ( !this->enabled ) return;
int x;
for (x=0; x<2; x++) {
if ( x == 0 ) {
this->private_property = object1;
this->intruder = object0;
this->intruder_radius = radius0;
} else {
this->private_property = object0;
this->intruder = object1;
this->intruder_radius = radius1;
}
// filter out any unwanted objects
if ( this->use_intruder_accept_filter && !this->accept_filter_intruder->find(this->intruder) ) continue; // only process intruder objects that are mentioned in the filter!
if ( this->use_intruder_reject_filter && this->reject_filter_intruder->find(this->intruder) ) continue; // only process intruder objects that are mentioned in the filter!
if ( this->use_private_property_accept_filter && !this->accept_filter_private_property->find(this->private_property) ) continue; // only process private_property objects that are mentioned in the filter!
if ( this->use_private_property_reject_filter && this->reject_filter_private_property->find(this->private_property) ) continue; // only process private_property objects that are mentioned in the filter!
IVP_SurfaceManager_Polygon *surface_manager = (IVP_SurfaceManager_Polygon *)private_property->get_surface_manager(); // because of above verification we KNOW that object is of type 'polygon'
const IVP_Compact_Surface *compact_surface = surface_manager->get_compact_surface();
const IVP_Compact_Ledgetree_Node *private_property_ledgetree_rootnode = compact_surface->get_compact_ledge_tree_root();
this->intruder->get_m_world_f_object_AT(&intruder_matrix);
IVP_Cache_Object *object_cache = this->private_property->get_cache_object();
object_cache->transform_position_to_object_coords(&intruder_matrix.vv, &this->intruder_position_in_private_property_cs);
object_cache->remove_reference();
this->pipelined_private_property_data = NULL;
int x;
for (x=0; x<this->pipelined_objects.len(); x++) {
IVP_Clustering_Visualizer_Shortrange_Objectdata *objectdata = this->pipelined_objects.element_at(x);
if ( objectdata->real_object == this->private_property ) {
this->pipelined_private_property_data = objectdata;
break;
}
}
if ( !this->pipelined_private_property_data ) {
this->pipelined_private_property_data = new IVP_Clustering_Visualizer_Shortrange_Objectdata();
this->pipelined_private_property_data->real_object = this->private_property;
this->pipelined_private_property_data->center.set(&intruder_matrix.vv);
this->pipelined_private_property_data->radius = this->intruder_radius;
this->pipelined_objects.add(this->pipelined_private_property_data);
}
this->recursively_traverse_cluster(private_property_ledgetree_rootnode);
// *** temporary hack !!!
//IVP_U_Float_Point center(&intruder_matrix.vv);
//ivp_global_clustering_visualizer.longrange.add_object(this->intruder, ¢er, this->intruder_radius);
// *** temporary hack !!!
}
return;
}
void IVP_Clustering_Visualizer_Shortrange::add_object_to_intruder_filter(IVP_Real_Object *obj, IVP_CLUSTERING_VISUALIZER_FILTER filter) {
switch ( filter ) {
case ACCEPT:
{
if ( !this->accept_filter_intruder->find(obj) ) { // pair already stored?
this->accept_filter_intruder->add(obj); // no, then store now...
}
}
break;
case REJECT:
{
if ( !this->reject_filter_intruder->find(obj) ) { // pair already stored?
this->reject_filter_intruder->add(obj); // no, then store now...
}
}
break;
}
return;
}
void IVP_Clustering_Visualizer_Shortrange::remove_object_from_intruder_filter(IVP_Real_Object *obj, IVP_CLUSTERING_VISUALIZER_FILTER filter) {
switch ( filter ) {
case ACCEPT:
{
if ( this->accept_filter_intruder->find(obj) ) { // pair stored in hash?
this->accept_filter_intruder->remove(obj); // yes, remove...
}
}
break;
case REJECT:
{
if ( this->reject_filter_intruder->find(obj) ) { // pair stored in hash?
this->reject_filter_intruder->remove(obj); // yes, remove...
}
}
break;
}
return;
}
void IVP_Clustering_Visualizer_Shortrange::add_object_to_private_property_filter(IVP_Real_Object *obj, IVP_CLUSTERING_VISUALIZER_FILTER filter) {
switch ( filter ) {
case ACCEPT:
{
if ( !this->accept_filter_private_property->find(obj) ) { // pair already stored?
this->accept_filter_private_property->add(obj); // no, then store now...
}
}
break;
case REJECT:
{
if ( !this->reject_filter_private_property->find(obj) ) { // pair already stored?
this->reject_filter_private_property->add(obj); // no, then store now...
}
}
break;
}
return;
}
void IVP_Clustering_Visualizer_Shortrange::remove_object_from_private_property_filter(IVP_Real_Object *obj, IVP_CLUSTERING_VISUALIZER_FILTER filter) {
switch ( filter ) {
case ACCEPT:
{
if ( this->accept_filter_private_property->find(obj) ) { // pair stored in hash?
this->accept_filter_private_property->remove(obj); // yes, remove...
}
}
break;
case REJECT:
{
if ( this->reject_filter_private_property->find(obj) ) { // pair stored in hash?
this->reject_filter_private_property->remove(obj); // yes, remove...
}
}
break;
}
return;
}
void IVP_Clustering_Visualizer_Shortrange::install_visualize_callback(IVP_Clustering_Visualizer_Shortrange_Callback *callback) {
this->output_callbacks.add(callback);
return;
}
void IVP_Clustering_Visualizer_Shortrange::remove_visualize_callback(IVP_Clustering_Visualizer_Shortrange_Callback *callback) {
if ( this->output_callbacks.index_of(callback) == -1 ) return;
this->output_callbacks.remove(callback);
return;
}
void IVP_Clustering_Visualizer_Shortrange::enable() {
this->enabled = IVP_TRUE;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -