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

📄 ivp_buoyancy_solver.cxx

📁 hl2 source code. Do not use it illegal.
💻 CXX
📖 第 1 页 / 共 5 页
字号:
	environment->add_draw_vector(&middle,&vec4,"",2);
    }
#endif
	
	
    //compute buoyancy values
    compute_buoyancy_values_for_one_ball(decision,
					 distance,
					 radius,
					 surface_os,
					 &geom_center_os);
    
	
    //compute the volume centers and the volumes under surface_os for the pushing forces
    compute_dampening_values_for_one_ball(decision,
					  distance,
					  radius,
					  &geom_center_os,
					  rel_speed_of_current_os,
					  &speed_plane_os,
					  surface_os,
					  &p1_os,
					  &p2_os);

}


int IVP_Buoyancy_Solver::compute_disection_points_with_ball(const IVP_U_Float_Hesse *plane1_os,
							    const IVP_U_Float_Hesse *plane2_os,
							    const IVP_U_Float_Point *geom_center_os,
							    const IVP_FLOAT &radius,
							    IVP_U_Float_Point *p1_os, IVP_U_Float_Point *p2_os) {
	
    /*** convert plane2_ws from hesse form into point-direction form ***/
    IVP_U_Hesse tmp_plane2_os;
    tmp_plane2_os.set(plane2_os);
    tmp_plane2_os.hesse_val = plane2_os->hesse_val;
	
    IVP_U_Plain point_direction_form_of_plane2_os(&tmp_plane2_os);  //create point-direction form of speed_plane_ws
    
    IVP_U_Straight straight_os;
    IVP_U_Hesse non_float_plane1_os;  //IVP_U_Plain cannot handle IVP_U_Float_Points
    non_float_plane1_os.set(plane1_os);
    non_float_plane1_os.hesse_val = plane1_os->hesse_val;
	
    IVP_RETURN_TYPE is_parallel;
    is_parallel = point_direction_form_of_plane2_os.calc_intersect_with(&non_float_plane1_os, &straight_os);  //calc intersection of both planes => straight
    if (is_parallel == IVP_FAULT) {
	return 0;  //both planes are parallel, so no intersection exists between them
    }
	
    /*** calc intersection of straight with ball ***/
    IVP_U_Float_Point straight_start_point;
    straight_start_point.set(&(straight_os.start_point));  //start point of straight_os
    IVP_U_Float_Point straight_vec;
    straight_vec.set(&(straight_os.vec));  //vector of straight_os
    IVP_U_Float_Point T;
    T.subtract(&straight_start_point, geom_center_os);
	
    IVP_U_Point parameters;
    parameters.k[0] = straight_vec.k[0]*straight_vec.k[0] + straight_vec.k[1]*straight_vec.k[1] + straight_vec.k[2]*straight_vec.k[2];
    parameters.k[1] = 2*T.k[0]*straight_vec.k[0] + 2*T.k[1]*straight_vec.k[1] + 2*T.k[2]*straight_vec.k[2];
    parameters.k[2] = T.k[0]*T.k[0] +  T.k[1]*T.k[1] +  T.k[2]*T.k[2] - radius*radius;
	
    IVP_U_Point result;
    result.solve_quadratic_equation_accurate(&parameters); //solve the quadratic equation and store in result
	
    if (result.k[0] >= 0.0f) {  //solutions exist
	p1_os->set(&straight_start_point);
	p1_os->add_multiple(&straight_vec, result.k[1]);
		
	p2_os->set(&straight_start_point);
	p2_os->add_multiple(&straight_vec, result.k[2]);
		
	return 1;
    } else {  //no solution exists
	p1_os->set(0.0f, 0.0f, 0.0f);
	p2_os->set(0.0f, 0.0f, 0.0f);
		
	return 0;
    }
}


void IVP_Buoyancy_Solver::compute_values_for_one_polygon( IVP_Real_Object *object, const IVP_U_Float_Hesse *surface_os) {
	
    //initialize buoyancy variables with zero values
    //volume_under = volume_above = 0;
    volume_under = 0;
    volume_center_under.set_to_zero();
    //volume_center_above.set(0,0,0);
	
	
    IVP_U_Float_Point s_point;  //projected center point
    {
	IVP_IF(1){
	    IVP_DOUBLE leng=surface_os->real_length();
	    IVP_DOUBLE testval=IVP_Inline_Math::fabsd(leng-1.0f);
	    IVP_ASSERT( testval < 0.001f);
	}
	s_point.set_multiple(surface_os,-surface_os->hesse_val);  //projects center onto surface_os
    }
	
    IVP_U_BigVector<IVP_Compact_Ledge> object_ledges(256); //will contain all ledges belonging to "object"
    {	//initialize object_ledges with all ledges
	IVP_SurfaceManager *surman = controller_buoyancy->attacher_buoyancy->get_buoyancy_surface( object );
	surman->get_all_terminal_ledges(&object_ledges);
    }
    {
	int index;
	for (index = object_ledges.len()-1; index>=0; index--) {
	    IVP_Compact_Ledge *tmp_ledge = object_ledges.element_at(index);
	    compute_values_for_one_ledge(object, tmp_ledge, surface_os, &s_point);
	}
    }
    
    // finish the volume center computation
    if ( volume_under > buoyancy_eps )
	volume_center_under.mult( 0.25f / volume_under );
#if 0
    if (volume_above > buoyancy_eps )
	volume_center_above.mult( 1.0f / volume_above );
#endif
}




/*****************************************************************
*  compute the volume between a triangular surface and s_point  *
*****************************************************************/

IVP_FLOAT IVP_Buoyancy_Solver::compute_pyramid_volume( const IVP_U_Float_Point *p1,
						   const IVP_U_Float_Point *p2,
						   const IVP_U_Float_Point *p3,
						   const IVP_U_Float_Point *s_point) {
	
    IVP_U_Point hesse;
    hesse.inline_set_vert_to_area_defined_by_three_points(p1,p2,p3);  //compute orthogonal vector
	
    IVP_U_Float_Point v;
    v.subtract( p1, s_point );  //compute difference vector
    return (hesse.dot_product(&v)) * ( -1.0f / 6.0f );
}



void IVP_Buoyancy_Solver::compute_values_for_one_triangle(IVP_Real_Object *object,
							  const IVP_Compact_Triangle *triangle,
							  const IVP_U_Float_Hesse *surface_os,
							  const IVP_U_Float_Point *s_point,
							  const IVP_Compact_Ledge *current_ledge) {
	
    //fetch the points defining the triangle
	IVP_U_Float_Point three_points[3];
	
	three_points[0].set(triangle->get_edge(0)->get_start_point(current_ledge));
	three_points[1].set(triangle->get_edge(1)->get_start_point(current_ledge));
	three_points[2].set(triangle->get_edge(2)->get_start_point(current_ledge));

    const IVP_U_Float_Point *triangle_points[5];
    triangle_points[0] = &three_points[0]; //p0
    triangle_points[1] = &three_points[1];
    triangle_points[2] = &three_points[2];
    triangle_points[3] = &three_points[0];
    triangle_points[4] = &three_points[1];


    //check if triangle is under/above surface
    IVP_FLOAT distance[6];     //indicates distance of the 3 vertices of the triangle
    int sum_distance = 0;   //indicates the distance of the whole triangle: completely above/under surface, if 0 or 3
    int index_positiv, index_neg;

    for (int j=2; j>=0; j--) {
	IVP_FLOAT x  = surface_os->get_dist(triangle_points[j]);
	if (x < 0.0f) {
	    index_neg = j;
	    sum_distance++;
	    //decrease distance to avoid division through zero
	    distance[j] = x - buoyancy_eps;
	    distance[j+3] = distance[j];
	} else {
	    index_positiv = j;
	    //increase distance to avoid division trough zero
	    distance[j] = x + buoyancy_eps;
	    distance[j+3] = distance[j];
	}
    }
	
    compute_volumes_and_centers_for_one_pyramid(object,
						triangle_points,
						distance,
						sum_distance,
						index_positiv,
						index_neg,
						s_point);
	
    compute_rotation_and_translation_values_for_one_triangle(object,
							     triangle,
							     triangle_points,
							     current_ledge,
							     distance,
							     sum_distance,
							     index_positiv,
							     index_neg);
	
}



void IVP_Buoyancy_Solver::compute_volumes_and_centers_for_one_pyramid(IVP_Real_Object *object,
								      const IVP_U_Float_Point *triangle_points[5],
								      const IVP_FLOAT distance[6],
								      const int &decision,
								      const int &index_positiv,
								      const int &index_neg,
								      const IVP_U_Float_Point *s_point) {
	
    
    switch (decision){
    case 0: { //triangle is completely under the surface
		
	IVP_DOUBLE volume_pyramid_under = compute_pyramid_volume( triangle_points[0], triangle_points[1], triangle_points[2], s_point );
	volume_under += volume_pyramid_under;
		
	//compute the volume center of the pyramid
	IVP_U_Float_Point volume_center_pyramid;	//volume center of the pyramid
	volume_center_pyramid.add(triangle_points[0], triangle_points[1]);
	volume_center_pyramid.add(triangle_points[2]);
	volume_center_pyramid.add(s_point);
	volume_center_pyramid.mult( volume_pyramid_under); //compute the volume center and weigh it with the corresponding volume
		
	//save results to class variables
	volume_center_under.add(&volume_center_pyramid);
    }
    break;
#if 0
    case 3: {//triangle is completely above the surface
		
	volume_pyramid_above = compute_pyramid_volume( triangle_points[0], triangle_points[1], triangle_points[2], &s_point );
	volume_above += volume_pyramid_above;
		
	//compute the volume center of the pyramid
	volume_center_pyramid.set(triangle_points[0]);
	volume_center_pyramid.add(triangle_points[1]);
	volume_center_pyramid.add(triangle_points[2]);
	volume_center_pyramid.add(&s_point);
	volume_center_pyramid.mult( 0.25f  * volume_pyramid_above);  //weight the volume center of this part of the object with its volume
		
	//save results to class variables
	volume_center_above.add(&volume_center_pyramid);
    }
    break;
#endif
    case 1: { //the vertex with index "index_neg" is above the surface

	//compute the first disection point on the surface 
	IVP_DOUBLE factor1 = -distance[index_neg] / (distance[index_neg+1] - distance[index_neg]);  //division by zero not possible, because distance[index_neg] < 0 and buoyancy_eps is added to each
		
	//compute the second disection point on the surface
	IVP_DOUBLE factor2 = -distance[index_neg] / (distance[index_neg+2] - distance[index_neg]);  //division by zero not possible, because distance[index_neg] < 0 and buoyancy_eps is added to each
		
	IVP_IF(1){
	    IVP_U_Float_Point sp1, sp2;
	    IVP_U_Point sp1_ws, sp2_ws;
	    sp1.set_interpolate(triangle_points[index_neg], triangle_points[index_neg+1], factor1);
	    sp2.set_interpolate(triangle_points[index_neg], triangle_points[index_neg+2], factor2);
			
	    IVP_Cache_Object *cache_object = object->get_cache_object();  //needed to transform coordinates into other coord. systems
	    cache_object->transform_position_to_world_coords(&sp1, &sp1_ws);
	    cache_object->transform_position_to_world_coords(&sp2, &sp2_ws);
	    cache_object->remove_reference();
			
			
	    IVP_U_Float_Point edge12;
	    edge12.subtract(&sp1_ws, &sp2_ws);
	    IVP_U_Point tmp_sp2_ws;
	    tmp_sp2_ws.set(&sp2_ws);
	    environment->add_draw_vector(&tmp_sp2_ws, &edge12,"",4);
	}
		
	       		
	/*** compute the volumes ***/
		
	//compute volume of whole pyramid triangle is part of
	IVP_DOUBLE volume_pyramid = compute_pyramid_volume( triangle_points[0], triangle_points[1], triangle_points[2], s_point );
		
	//compute volume of pyramid above the surface
	IVP_DOUBLE volume_pyramid_above = volume_pyramid * factor1 * factor2;
		
	//save results to class variables
	volume_under += (volume_pyramid - volume_pyramid_above);
		
		
	/*** compute the volume centers ***/
		
	//compute the area center of the whole triangle (Ce = (A+B+C)/3)

⌨️ 快捷键说明

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