⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ivp_object_polygon_tetra.cxx

📁 hl2 source code. Do not use it illegal.
💻 CXX
📖 第 1 页 / 共 5 页
字号:
// Copyright (C) Ipion Software GmbH 1999-2000. All rights reserved.


#include <ivp_physics.hxx>
#include <string.h>
#include <ivu_float.hxx>

#include <ivu_list.hxx>
#include <ivu_hash.hxx>
#include <ivu_geometry.hxx>

#ifndef WIN32
#	pragma implementation "ivp_object_polygon_tetra.hxx"
#endif

#include "ivp_triangle_gen.hxx"
#include <ivp_object_polygon_tetra.hxx>
#include <ivp_templates_intern.hxx>
#include <ivu_min_hash.hxx>
#include <ivp_tetra_intrude.hxx>

/* for debugging stop after some pops */
int	   n_physical_pops = -1;

/*** DEFINES ***/

//#define SUR_DEBUG
//#define CONVEX_DEBUG

#define P_POP_SURFACE_CONVEX_BLUR (0.1f * P_OBJECT_BLUR)		
#define P_POP_EPS_INIT 0.001f
#define P_POP_EPS_REDUCE_FACTOR 0.125f
#define P_POP_TOO_FLAT_EPS_FACTOR 2.1f // factor of P_Pop_Eps
#define P_POP_SCAL_EPS_INIT 0.01f
                        // [m] safety distance for collisions
#define P_CROSS_EPS 0.0001f
#define P_CROSS_EPS_QUAD (P_CROSS_EPS*P_CROSS_EPS)


/*** GLOBALS ***/
IVP_DOUBLE P_Pop_Eps;
IVP_DOUBLE P_Pop_Scal_Eps;
IVP_DOUBLE P_Pop_Too_Flat_Eps;

/*** METHODS AND SUBS ***/
int IVP_Poly_Point::point_num()
{
    if (!l_tetras) return -1;
    return this - this->l_tetras->points;
}

void IVP_Poly_Point::print(const char *text){
    printf("num %i: ",this->point_num());
    IVP_U_Point::print(text);
}

int IVP_Poly_Point::p(){
    this->print();
    return 0;
}

void p_del_double_triangles(IVP_Triangle **tri_a, IVP_Triangle **tri_b=NULL, IVP_Triangle **tri_c=NULL);
void p_del_double_triangles(IVP_Triangle **tri_a, IVP_Triangle **tri_b, IVP_Triangle **tri_c)
{
    if(tri_a) P_DELETE((*tri_a)->other_side);
    if(tri_b) P_DELETE((*tri_b)->other_side);
    if(tri_c) P_DELETE((*tri_c)->other_side);
    if(tri_a) P_DELETE((*tri_a));
    if(tri_b) P_DELETE((*tri_b));
    if(tri_c) P_DELETE((*tri_c));
}

int p_check_for_flat(IVP_Tri_Edge *a0, IVP_Tri_Edge *b0, IVP_DOUBLE eps)
{
	IVP_DOUBLE dist1 = -a0->triangle->tmp.gen.hesse.get_dist(b0->prev->start_point);
	IVP_DOUBLE dist2 = -b0->triangle->tmp.gen.hesse.get_dist(a0->prev->start_point);
	if( (dist1<eps) || (dist2<eps)){
	    //printf("%f %f\n",dist1,dist2);
	    return 1;
	}
	return 0;
}

void IVP_Triangle::calc_hesse()
{
    IVP_U_Point *p0, *p1, *p2;

    p0 = this->three_edges[0].start_point;
    p1 = this->three_edges[0].next->start_point;
    p2 = this->three_edges[0].prev->start_point;

    this->tmp.gen.hesse.calc_hesse(p0, p2, p1);
    this->tmp.gen.hesse.normize();
}

IVP_DOUBLE IVP_Triangle::calc_areasize()
{
    IVP_U_Hesse norm;
    IVP_U_Point *p0, *p1, *p2;

    p0 = this->three_edges[0].start_point;
    p1 = this->three_edges[0].next->start_point;
    p2 = this->three_edges[0].prev->start_point;

    norm.calc_hesse(p0, p2, p1);
    return norm.real_length() * 0.5f;
}

int IVP_Triangle::print(const char *comment)
{
    // OG problems with sun
    return 0;
    
    const char *obj_name = "unknown name";
    printf("%s '%s' T(%d %d %d) \n",
	   (comment)?comment:"",
	   (obj_name)?obj_name:"",
	   this->three_edges[0].start_point->point_num(), 
	   this->three_edges[0].next->start_point->point_num(),
	   this->three_edges[0].prev->start_point->point_num()
	);
    return 0;
}

IVP_Tri_Edge *IVP_Tri_Edge::other_side()
{
    int i;
    if(!this->triangle->other_side) return NULL;
    IVP_Tri_Edge *e = &this->triangle->other_side->three_edges[0];
    for(i=2; i>=0; i--){
	if(e->next->start_point == this->start_point) return e;
	e++;
    }
    return NULL;
}


void IVP_Tri_Edge::print(const char *text){
    if (!text) text = "";
    const char *name = start_point->get_real_object2()->get_name();
    if (!name) name = "noname";
    printf("%s '%s'	start_%lX: %i	",text,name, 0xff & ( ( (long)this->start_point->l_tetras  ) >>8), this->start_point->point_num());
    this->triangle->print("\n");
}

int IVP_Tri_Edge::p(){
    this->print();
    return 0;
}


int IVP_Object_Polygon_Tetra::check_concavity_and_manage(IVP_Tri_Edge *edge, P_CONVEXIFY_STATE )
{
    // prepo perfect links and perfect hidden flags
    // uses/sets opposite edge

    int flag = edge->check_concavity(edge->opposite);
    edge->opposite->concavity = edge->concavity;
    edge->tmp.gen.concav_flag = (char)flag;
    edge->opposite->tmp.gen.concav_flag = (char)flag;

    if((flag==-2)){
	move_edge_to_epsilon_hash(edge);
    }else{
	move_edge_to_normal_hash(edge);
    }
    return flag;
}

		       
int IVP_Tri_Edge::check_concavity(IVP_Tri_Edge *other_edge)
{
    // calcs concavity and test if edge could be popped
    // sets ggf. concavity and unsolvable of this
    // values for other_edge have to be copied manually afterwards

    // -2: partly overlapping
    // -1: identical
    // 0: convex
    // 1: concav
    
    if(!this){
	printf("NULL edge in check_concavity.\n");
    }

    
    // set concavity as measure for concavity volume (+ -> convex)
    IVP_DOUBLE concav = -this->triangle->tmp.gen.hesse.get_dist(other_edge->prev->start_point);
    {
	IVP_DOUBLE concav2 = -other_edge->triangle->tmp.gen.hesse.get_dist(this->prev->start_point);
	if (concav2 > concav){
	    concav = concav2;
	}
    }
    
    IVP_DOUBLE scal = this->triangle->tmp.gen.hesse.dot_product(&other_edge->triangle->tmp.gen.hesse);


    if(scal > 0.0f){
	// angle greater than 90 degrees or greater 270
	
	if( scal<1.0f-P_Pop_Scal_Eps || IVP_Inline_Math::fabsd(concav) >= P_POP_SURFACE_CONVEX_BLUR){
	    // different planes -> everything normal
	    
	    this->concavity = concav;

	    if(concav < 0){
		return 1; // real concav
	    }else{
		return 0; // real convex
	    }
	}else{
	    // same plane
	    concavity = 0.0f; // is convex (flat)
	    return 0;	
	}
    }else{
	// angle is less than 90 degrees
	this->concavity = concav;
	if (concav > 0){
		return 0; // real convex
	}
	// are triangles in the same plane ?
	if(concav < -P_Pop_Eps){
	    // different planes -> everything normal
		return 1; // real concav
	}else{
	    if(this->prev->start_point == other_edge->prev->start_point){
		CORE;
		return -1; // identical points
	    }
	    return -2;		// windschief
	}
    }
    CORE; // should not have happened
    return -12345; // dummy
}

P_Sur_2D_Triangle::P_Sur_2D_Triangle(int pn0, int pn1, int pn2)
{
    P_MEM_CLEAR(this);
    point_nums[0] = pn0;
    point_nums[1] = pn1;
    point_nums[2] = pn2;

#ifdef SUR_DEBUG
    printf("TRIANGLE GENERATED: %d, %d, %d\n",pn0, pn1, pn2);
#endif
}

P_Sur_2D_Point::P_Sur_2D_Point(int i_point_num)
{
    P_MEM_CLEAR(this);
    point_num = i_point_num;
}

P_Sur_2D_Point::~P_Sur_2D_Point()
{
    ;
}

P_Sur_2D_Line::P_Sur_2D_Line(P_Sur_2D_Point *sp, P_Sur_2D_Point *ep)
{
    P_MEM_CLEAR(this);
    start_point = sp;
    end_point = ep;

    if(sp && ep){
	this->delta_x = ep->k[0] - sp->k[0];
	this->delta_y = ep->k[1] - sp->k[1];
    }
#ifdef SUR_DEBUG
    printf("    Line generated: %d, %d\n", sp->point_num, ep->point_num);
#endif
}

P_Sur_2D_Line::~P_Sur_2D_Line()
{
    ; // end/start_points remain!
}

int P_Sur_2D_Line::point_lies_to_the_left(IVP_U_Point *i_point)
{
    IVP_DOUBLE hesse_dist = this->hesse_dist_to_point(i_point);
    if(hesse_dist <= P_DOUBLE_EPS) return 0; // on the other side
    if(hesse_dist <= P_Pop_Too_Flat_Eps) return 2; // not enough distance for triangle
    return 1;
}

int P_Sur_2D_Line::has_points(P_Sur_2D_Point *point_a, P_Sur_2D_Point *point_b)
{
    if(!point_b){
	if( (start_point==point_a) || (end_point==point_a) ) return 1;
	return 0;
    }
    
    if( (start_point==point_a)&&(end_point==point_b) ) return 1;
    if( (end_point==point_a)&&(start_point==point_b) ) return 1;
    return 0;
}

IVP_DOUBLE P_Sur_2D_Line::dist_to_point(IVP_U_Point *i_point)
{
    // att: maybe negative!
    
    IVP_DOUBLE norm = delta_y*delta_y + delta_x*delta_x;
    if(norm < P_DOUBLE_EPS){
	// line is just a point
	IVP_DOUBLE dx = this->start_point->k[0] - i_point->k[0];
	IVP_DOUBLE dy = this->start_point->k[1] - i_point->k[1];
	return dx*dx + dy*dy;
    }
    
    IVP_DOUBLE hesse_dist = delta_y * (start_point->k[0] - i_point->k[0]) +
	delta_x * (i_point->k[1] - start_point->k[1]); // not normized!

    return hesse_dist / IVP_Inline_Math::sqrtd(norm);
}

IVP_DOUBLE P_Sur_2D_Line::hesse_dist_to_point(IVP_U_Point *i_point)
{
    // att: maybe negative!
    
    IVP_DOUBLE hesse_dist = delta_y * (start_point->k[0] - i_point->k[0]) +
	delta_x * (i_point->k[1] - start_point->k[1]); // not normized!

    return hesse_dist;
}

int P_Sur_2D_Line::point_lies_in_interval(IVP_U_Point *i_point)
{
    // ATT: vorr: point lies on the extension of the line

    // try delta_x
    IVP_DOUBLE line_abs_delta = IVP_Inline_Math::fabsd(delta_x);
    if(line_abs_delta > P_DOUBLE_EPS){
	int dx = (delta_x > 0)? 1: -1;
	IVP_DOUBLE point_delta = (i_point->k[0] - start_point->k[0]) * dx;
	if(point_delta>P_CROSS_EPS && point_delta<line_abs_delta-P_CROSS_EPS){
	    return 1; // definitely inside
	}
	return 0; // outside or exactly on start/end point!!
    }

    // try delta_y
    line_abs_delta = IVP_Inline_Math::fabsd(delta_y);
    if(line_abs_delta > P_DOUBLE_EPS){
	int dy = (delta_y > 0)? 1: -1;
	IVP_DOUBLE point_delta = (i_point->k[1] - start_point->k[1]) * dy;
	if(point_delta>P_CROSS_EPS && point_delta<line_abs_delta-P_CROSS_EPS){
	    return 1; // definitely inside
	}
	return 0; // outside or exactly on start/end point!!
    }

    // line actually is a point
    return 0; // not inside
}

int P_Sur_2D_Line::overlaps_with_line(P_Sur_2D_Line *line_v)
{
#define P_OVERLAP_EPS 1E-8f   
    // ATT: vorr: lines are in a common line
    P_Sur_2D_Line *line_u = this;
    
    // try delta_x
    IVP_DOUBLE line_abs_delta = IVP_Inline_Math::fabsd(delta_x);
    if(line_abs_delta > P_OVERLAP_EPS){
	IVP_DOUBLE u_lower, u_higher;
	if(delta_x > 0.0f){
	    u_lower = line_u->start_point->k[0];
	    u_higher = line_u->end_point->k[0];
	}else{
	    u_lower = line_u->end_point->k[0];
	    u_higher = line_u->start_point->k[0];	    
	}
	u_lower += P_OVERLAP_EPS;
	u_higher -= P_OVERLAP_EPS;
	IVP_DOUBLE v_start = line_v->start_point->k[0];
	IVP_DOUBLE v_end = line_v->end_point->k[0];

	if( ((v_start<=u_lower) && (v_end<=u_lower)) ||
	    ((v_start>=u_higher) && (v_end>=u_higher)) ){
	    return 0; // no overlapping (but maybe 1 common point!)
	}
	return 1; // definitely overlapping
    }

    // try delta_y
    line_abs_delta = IVP_Inline_Math::fabsd(delta_y);
    if(line_abs_delta > P_OVERLAP_EPS){
	IVP_DOUBLE u_lower, u_higher;
	if(delta_y > 0.0f){
	    u_lower = line_u->start_point->k[1];
	    u_higher = line_u->end_point->k[1];
	}else{
	    u_lower = line_u->end_point->k[1];
	    u_higher = line_u->start_point->k[1];	    
	}
	u_lower += P_OVERLAP_EPS;
	u_higher -= P_OVERLAP_EPS;
	IVP_DOUBLE v_start = line_v->start_point->k[1];
	IVP_DOUBLE v_end = line_v->end_point->k[1];

	if( ((v_start<=u_lower) && (v_end<=u_lower)) ||
	    ((v_start>=u_higher) && (v_end>=u_higher)) ){
	    return 0; // no overlapping (but maybe 1 common point!)
	}
	return 1; // definitely overlapping
    }

    // line_u actually is a point
    return line_v->point_lies_in_interval(line_u->start_point);
#undef P_OVERLAP_EPS    
}

int P_Sur_2D_Line::is_crossing_line(P_Sur_2D_Line *line_v)
{
    // returns 1 if line_u (=this) crosses line_v, otherwise 0.

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -