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

📄 ivp_buoyancy_solver.cxx

📁 hl2 source code. Do not use it illegal.
💻 CXX
📖 第 1 页 / 共 5 页
字号:
	    edge_O_center_os.subtract(&center_of_ellipse_os, &O_os);
	    IVP_DOUBLE b = edge_O_center_os.real_length();
	    IVP_U_Float_Point edge_Q_center_os;
	    edge_Q_center_os.subtract(&center_of_ellipse_os, &Q_os);
	    IVP_DOUBLE radius_of_water_disection = IVP_Inline_Math::ivp_sqrtf(IVP_Inline_Math::fabsd(radius*radius - distance*distance));
	    IVP_DOUBLE height = IVP_Inline_Math::fabsd(b - edge_Q_center_os.real_length());

	    IVP_U_Float_Point center_of_ellipse_segment;
	    IVP_DOUBLE surface_content_up;
	    if (b < buoyancy_eps) { //safety check
		surface_content_up = 0.0f;
		center_of_ellipse_segment.set(0.0f, 0.0f, 0.0f);
	    } else {
		surface_content_up = b*radius_of_water_disection*IVP_Inline_Math::save_acosf(edge_Q_center_os.real_length() / b) - edge_Q_center_os.real_length()*(0.5f*length_p1p2);
		
		//compute center of ellipse segment above water
		IVP_DOUBLE s = 2 * IVP_Inline_Math::ivp_sqrtf(IVP_Inline_Math::fabsd(2*height*b - height*height));
		IVP_DOUBLE ellipse_arc = 2*IVP_Inline_Math::fast_asin( s/(2*b))*b;
		IVP_DOUBLE A = IVP_Inline_Math::fabsd(0.5f * (ellipse_arc * b - s*(b - height)));
		if (A < buoyancy_eps) {
		    surface_content_up = 0.0f;
		    center_of_ellipse_segment.set(0.0f, 0.0f, 0.0f);
		} else {
		    //edge_O_center_os.normize();
		    //edge_O_center_os.mult(-1);  //change direction
		    center_of_ellipse_segment.set(&center_of_ellipse_os);
		    //center_of_ellipse_segment.add_multiple(&edge_O_center_os, s*s*s / (12 * A));
		    center_of_ellipse_segment.add_multiple(&direction_up, s*s*s / (12 * A));
		}
	    }
			
			
	    /*** compute results ***/
			
	    //compute ball_projected_surface_content_under
	    ball_projected_surface_content_under = surface_content_up + surface_content_down;
	    if (ball_projected_surface_content_under < buoyancy_eps) {
		ball_projected_surface_content_under = 0.0f;
		ball_point_of_impulse.set(0.0f, 0.0f, 0.0f);
	    } else {
	    //compute ball_point_of_impulse
		ball_point_of_impulse.set_multiple(&center_of_segment_os, surface_content_down);
		ball_point_of_impulse.add_multiple(&center_of_ellipse_segment, surface_content_up);
		ball_point_of_impulse.mult(1.0f / ball_projected_surface_content_under);
	    }
			
	} else { //ball flies out of the water
			
	    //calc various ellipse specific values
	    IVP_U_Float_Point edge_O_center_os;
	    edge_O_center_os.subtract(&center_of_ellipse_os, &O_os);
	    IVP_DOUBLE b = edge_O_center_os.real_length();
	    IVP_U_Float_Point edge_Q_center_os;
	    edge_Q_center_os.subtract(&center_of_ellipse_os, &Q_os);
	    IVP_DOUBLE radius_of_water_disection = IVP_Inline_Math::ivp_sqrtf(IVP_Inline_Math::fabsd(radius*radius - distance*distance));
	    IVP_DOUBLE height = IVP_Inline_Math::fabsd(b - edge_Q_center_os.real_length());
	    //IVP_DOUBLE length_p1p2 = p1p2_os.real_length();
			
	    //calc segment of circle above water
	    IVP_U_Float_Point MQ_os;
	    MQ_os.subtract(&Q_os, geom_center_os);
	    IVP_DOUBLE h = radius - MQ_os.real_length();  //height of disected segment of circle
	    IVP_DOUBLE arc = 2*IVP_Inline_Math::fast_asin(length_p1p2 / (2.0f * radius)) * radius;  //length of arc of circle segment
	    IVP_DOUBLE surface_content_of_circle_segment = IVP_Inline_Math::fabsd(0.5f * (arc*radius - length_p1p2*(radius - h)));

	    if (surface_content_of_circle_segment < buoyancy_eps) {  //safety check
		//if this is the case then case 4 can be applied
		goto case_4;
	    }

	    //calc segment of ellipse above water
	    IVP_DOUBLE surface_content_of_ellipse_segment;
	    if (b < buoyancy_eps) { //safety check
		surface_content_of_ellipse_segment = 0.0f;
	    } else {
		surface_content_of_ellipse_segment = b*radius_of_water_disection*IVP_Inline_Math::save_acosf(edge_Q_center_os.real_length() / b) - edge_Q_center_os.real_length()*(length_p1p2 * 0.5f);
	    }
	    
	    IVP_DOUBLE part_ring_above_water = IVP_Inline_Math::fabsd(surface_content_of_circle_segment - surface_content_of_ellipse_segment);
			
	    //calc surface content under water (surface_content_circle - surface_content_ellipse - part_ring_above_water)
	    ball_projected_surface_content_under = IVP_Inline_Math::fabsd(IVP_PI*(radius*radius - radius_of_water_disection*b) - part_ring_above_water);
	    if (ball_projected_surface_content_under < buoyancy_eps) {  //safety check
		ball_projected_surface_content_under = 0.0f;
		goto calculate_impulse;
	    }
			
	    /*** calc ball_point_of_impulse ***/
	    //IVP_U_Float_Point direction;
	    //direction.set(&edge_O_center_os);
	    //direction.normize();
			
	    //calc mass center of circle segment above surface
	    IVP_U_Float_Point center_of_circle_segment;
	    center_of_circle_segment.set(geom_center_os);
	    center_of_circle_segment.add_multiple(&direction_up, length_p1p2*length_p1p2*length_p1p2 / (12*surface_content_of_circle_segment));  //safety check already above
			
	    //calc mass center of circle segment under surface
	    IVP_U_Float_Point center_of_circle_segment_under_surface;
	    center_of_circle_segment_under_surface.set_multiple(&center_of_circle_segment, -surface_content_of_circle_segment);
	    center_of_circle_segment_under_surface.add_multiple(geom_center_os, IVP_PI*radius*radius);
	    IVP_DOUBLE surface_content_of_circle_segment_under_surface = IVP_Inline_Math::fabsd(IVP_PI*radius*radius - surface_content_of_circle_segment);
	    if (surface_content_of_circle_segment_under_surface < buoyancy_eps) { //safety check
		surface_content_of_circle_segment_under_surface = 0.0f;
		center_of_circle_segment_under_surface.set(0.0f, 0.0f, 0.0f);
	    } else {
		center_of_circle_segment_under_surface.mult( 1.0f / surface_content_of_circle_segment_under_surface);
	    }
			
	    //calc mass center of ellipse segment
	    IVP_U_Float_Point center_of_ellipse_segment;
	    IVP_DOUBLE s = 2.0f * IVP_Inline_Math::ivp_sqrtf(IVP_Inline_Math::fabsd(2*height*b - height*height));
	    IVP_DOUBLE ellipse_arc = 2*IVP_Inline_Math::fast_asin(s / (2*b))*b;
	    IVP_DOUBLE A = 0.5f * (ellipse_arc * b - s*(b - height));
	    if ( (b<buoyancy_eps) || (A<buoyancy_eps) ) {  //safety check
		center_of_ellipse_segment.set(0.0f, 0.0f, 0.0f);
	    } else {
		center_of_ellipse_segment.set(&center_of_ellipse_os);
		center_of_ellipse_segment.add_multiple(&direction_up, s*s*s / (12 * A));
	    }
			
	    //calc mass center of ellipse segment under surface
	    IVP_U_Float_Point center_of_ellipse_segment_under_surface;
	    center_of_ellipse_segment_under_surface.set_multiple(&center_of_ellipse_segment, -surface_content_of_ellipse_segment);
	    center_of_ellipse_segment_under_surface.add_multiple(&center_of_ellipse_os, IVP_PI*radius_of_water_disection*b);
	    IVP_DOUBLE surface_content_of_ellipse_segment_under_surface = IVP_Inline_Math::fabsd(IVP_PI*radius_of_water_disection*b - surface_content_of_ellipse_segment);
	    if (surface_content_of_ellipse_segment_under_surface < buoyancy_eps) { //safety check
		center_of_ellipse_segment_under_surface.set(0.0f, 0.0f, 0.0f);
		surface_content_of_ellipse_segment_under_surface = 0.0f;
	    } else {
		center_of_ellipse_segment_under_surface.mult( 1.0f / surface_content_of_ellipse_segment_under_surface);
	    }
			
	    //calc ball_point_of_impulse
	    ball_point_of_impulse.set_multiple(&center_of_ellipse_segment_under_surface, -surface_content_of_ellipse_segment_under_surface);
	    ball_point_of_impulse.add_multiple(&center_of_circle_segment_under_surface, surface_content_of_circle_segment_under_surface);
	    ball_point_of_impulse.mult( 1.0f / ball_projected_surface_content_under );  //safety check above
	}
		
    }
    break;
    case 4: { //center lies under surface and speed_plane_os disects completely under surface
    case_4:
	
	//check in which direction the ball is heading
	IVP_DOUBLE factor = surface_os->dot_product(&speed_plane_os);
	if (factor <= 0.0f) {
			
	    ball_projected_surface_content_under = IVP_PI*radius*radius;  //surface content of speed_plane_os
	    ball_point_of_impulse.set(geom_center_os);
			
	} else {
			
	    //compute surface content of resulting ring
	    IVP_DOUBLE surface_content_circle = IVP_PI*radius*radius;
	    IVP_DOUBLE surface_content_ellipse = factor*IVP_PI*(radius*radius - distance*distance);
	    ball_projected_surface_content_under = IVP_Inline_Math::fabsd(surface_content_circle - surface_content_ellipse);

	    if (ball_projected_surface_content_under < buoyancy_eps) { //safety check
		ball_projected_surface_content_under = 0.0f;
		goto calculate_impulse;
	    }
			
	    //compute ball_point_of_impulse
	    IVP_U_Float_Point projected_center_on_surface_os;
	    surface_os->proj_on_plane(geom_center_os, &projected_center_on_surface_os);
	    IVP_U_Float_Point projected_center_on_ellipse_os;
	    speed_plane_os.proj_on_plane(&projected_center_on_surface_os, &projected_center_on_ellipse_os);
			
	    //compute center of resulting ring by weighed sum of both the center of the whole circle and the center of the ellipse
	    ball_point_of_impulse.set_multiple(&projected_center_on_ellipse_os, -surface_content_ellipse);
	    ball_point_of_impulse.add_multiple(geom_center_os, surface_content_circle);
	    ball_point_of_impulse.mult( 1.0f / ball_projected_surface_content_under );
			
	}
    }
    break;
    default: {
		
		
    }
    break;
    }

calculate_impulse:
    IVP_DOUBLE quad_length_of_speed = rel_speed_of_current_os.quad_length();
    if (quad_length_of_speed < buoyancy_eps) {
	quad_length_of_speed = 0.0f;
	rel_speed_of_current_os.set(0.0f, 1.0f, 0.0f);  //any value, is compensated by quad_length_of_speed=0
    }
    IVP_DOUBLE pressure_dampening_impulse = ball_projected_surface_content_under * quad_length_of_speed * pressure_damp_factor;
    //area content of ball where water flows around is approximated with the help of ball_projected_surface_content_under
    IVP_DOUBLE friction_dampening_impulse = (3.0f * ball_projected_surface_content_under) * quad_length_of_speed * friction_damp_factor;

    rel_speed_of_current_os.normize();
    ball_impulse_vector.set_multiple( &rel_speed_of_current_os, pressure_dampening_impulse + friction_dampening_impulse );
	
    //add the surface content that's under the water to the corresponding global variable
    object_visible_surface_content_under += ball_projected_surface_content_under;

    //calc the cross product between the impulse vector and the point of impulse and add it to the global variable
    IVP_U_Float_Point impulse_x_point;
    impulse_x_point.inline_calc_cross_product(&ball_point_of_impulse, &ball_impulse_vector);
    sum_impulse_x_point.add(&impulse_x_point);
  
    //calc the move-direction vector
    //setting it to zero value
    IVP_U_Float_Point move_direction_os; move_direction_os.set_to_zero();
  
    //calc cross product between impulse_vector and move-direction vector and add it to the global variable
    IVP_U_Float_Point impulse_x_movevector;
    impulse_x_movevector.inline_calc_cross_product(&move_direction_os, &ball_impulse_vector);
    sum_impulse_x_movevector.add(&impulse_x_movevector);
    
    //add impulse to global variable
    sum_impulse.add(&ball_impulse_vector);
}


void IVP_Buoyancy_Solver::compute_values_for_one_ball(const IVP_Real_Object *object,
						      const IVP_U_Float_Hesse *surface_os,
						      const IVP_U_Float_Point *rel_speed_of_current_os) {
	
    //fetch some ball related values
    IVP_Ball *ball = (IVP_Ball *) object;
	
#if 0
    IVP_U_Point non_float_geom_center_ws;
    IVP_U_Float_Point geom_center_ws;  //the mass(!!!!) center in world space
    ball->get_geom_center_world_space(&non_float_geom_center_ws);
    geom_center_ws.set(&non_float_geom_center_ws);
#endif
    IVP_U_Float_Point geom_center_os; geom_center_os.set_to_zero();
    IVP_FLOAT radius = ball->get_radius();  //get radius of ball
	
    //create the plane the speed has an impact on
    IVP_U_Float_Hesse speed_plane_os;
    IVP_FLOAT scalar_speed=rel_speed_of_current_os->quad_length();
    if(scalar_speed < P_DOUBLE_EPS) {
	speed_plane_os.set(0.0f,1.0f,0.0f);	
    } else {
	speed_plane_os.set(rel_speed_of_current_os);
    }
    speed_plane_os.calc_hesse_val(&geom_center_os);
    speed_plane_os.normize();
	
    //the disection points of the straight (which results from the disection of surface_ws and speed_plane_ws) and the ball
    IVP_U_Float_Point p1_os;
    IVP_U_Float_Point p2_os;
	
    //compute whether the ball is under or above the surface
    IVP_FLOAT distance = surface_os->get_dist(&geom_center_os);  //get distance of center to surface
    int decision = -1;
	
    if (distance <= 0.0f) { //center lies above surface
	if (IVP_Inline_Math::fabsd(distance) >= radius) { //ball is completely above surface
	    return;  //nothing to do
	} else {  //ball partly under the surface, center lies above
	    int location = compute_disection_points_with_ball(surface_os, &speed_plane_os, &geom_center_os, radius, &p1_os, &p2_os);
	    if (location) {
		decision = 1;  //speed_plane_os disects ball under and above the surface
	    } else {
		decision = 2;  //speed_plane_os disects ball above the surface
	    }
	}
    } else {  //center lies under surface
	if (distance >= radius) { //speed_plane_os and/or ball is completely under surface
	    decision = 0;
	} else {  //ball partly under the surface, center lies under
	    int location = compute_disection_points_with_ball(surface_os, &speed_plane_os, &geom_center_os, radius, &p1_os, &p2_os);
	    if (location) {
		decision = 3;  //speed_plane_os disects ball under and above the surface
	    } else {
		decision = 4;  //speed_plane_os disects completely under surface
	    }
	}
    }
	
#if 0
    P_IF(1) {
	IVP_U_Float_Point geom_center_ws;
	IVP_U_Float_Hesse surface_ws;
	{
	    IVP_Cache_Object *cache_object = object->get_cache_object();
	    cache_object->transform_vector_to_world_coords(&geom_center_os, &geom_center_ws);
	    cache_object->transform_vector_to_world_coords(surface_os, &surface_ws);
	    cache_object->remove_reference();
	}
	//draw debug vectors to indicate surface (dirty!)
	IVP_U_Point middle(geom_center_ws.k[0], -(surface_ws.hesse_val), geom_center_ws.k[2]);
	IVP_U_Point vec1(-5.0f, 0.0f, 0.0f);
	IVP_U_Point vec2(5.0f, 0.0f, 0.0f);
	IVP_U_Point vec3(0.0f, 0.0f, 5.0f);
	IVP_U_Point vec4(0.0f, 0.0f, -5.0f);
	environment->add_draw_vector(&middle,&vec1,"",2);
	environment->add_draw_vector(&middle,&vec2,"",2);
	environment->add_draw_vector(&middle,&vec3,"",2);

⌨️ 快捷键说明

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