entity *get_closest_mobile_entity (vec3d *pos) { entity *closest_en = NULL, *en; int range, best_range = INT_MAX; vec3d pos2, test_pos; en = get_local_entity_list (); while (en) { if (get_local_entity_int_value (en, INT_TYPE_IDENTIFY_MOBILE)) { get_local_entity_vec3d (en, VEC3D_TYPE_POSITION, &pos2); test_pos.x = pos->x - pos2.x; test_pos.y = 0.0; test_pos.z = pos->z - pos2.z; range = get_3d_vector_magnitude (&test_pos); if (range < best_range) { best_range = range; closest_en = en; if (range < 1.0) { return closest_en; } } } en = get_local_entity_succ (en); } return closest_en; }
void update_drop_camera (camera *raw) { entity *en; vec3d pos, v; // // pre-amble // ASSERT (raw); ASSERT (raw->external_view_entity); en = raw->external_view_entity; // // get camera to entity vector // get_local_entity_target_point (en, &pos); v.x = pos.x - raw->position.x; v.y = pos.y - raw->position.y; v.z = pos.z - raw->position.z; // // prevent divide by zero // if (get_3d_vector_magnitude (&v) < 0.001) { v.x = 0.0; v.y = 0.0; v.z = 1.0; } // // get camera attitude // normalise_3d_vector (&v); get_matrix3x3_from_unit_vec3d (raw->attitude, &v); }
float get_formation_member_radius (formation_types form, int member_count) { formation_type *formation_data; int loop, biggest_radius_index; float radius, sqr_radius, biggest_sqr_radius; formation_data = get_formation (form); biggest_sqr_radius = 0.0; biggest_radius_index = 0; for (loop = 0; loop < member_count; loop ++) { sqr_radius = (formation_data->sites [loop].x * formation_data->sites [loop].x) + (formation_data->sites [loop].z * formation_data->sites [loop].z); if (sqr_radius > biggest_sqr_radius) { biggest_sqr_radius = sqr_radius; biggest_radius_index = loop; } } radius = get_3d_vector_magnitude (&formation_data->sites [biggest_radius_index]); return radius; }
void insert_zbiased_smoke_trail_into_3d_scene ( int number_of_points, float zbias, int additive, screen *texture, float texture_distance, float texture_size, smoke_trail_data *points ) { smoke_trail_data *rotated_points; int count, visible; // // First, copy the ROTATED point data over to an internal 3d visual buffer ( checking for visibility ) // visible = FALSE; rotated_points = get_smoke_trail_point_data ( number_of_points ); if ( rotated_points ) { for ( count = 0; count < number_of_points; count++ ) { get_position_3d_relative_position ( &points[count].point1, &rotated_points[count].point1 ); if ( rotated_points[count].point1.z > clip_hither ) { visible = TRUE; } get_position_3d_relative_position ( &points[count].point2, &rotated_points[count].point2 ); if ( rotated_points[count].point2.z > clip_hither ) { visible = TRUE; } rotated_points[count].centre.x = ( rotated_points[count].point1.x + rotated_points[count].point2.x ) / 2; rotated_points[count].centre.y = ( rotated_points[count].point1.y + rotated_points[count].point2.y ) / 2; rotated_points[count].centre.z = ( rotated_points[count].point1.z + rotated_points[count].point2.z ) / 2; } if ( visible ) { smoke_trail_information *smoke_trail; float texture_u; // // Some part ( or all ) of the smoke trail is visible - generate a smoke trail header. // smoke_trail = get_smoke_trail_header (); if ( smoke_trail ) { smoke_trail->additive = additive; smoke_trail->texture = texture; smoke_trail->texture_size = texture_size; smoke_trail->number_of_points = number_of_points; smoke_trail->points = rotated_points; // // Go calculate the u texture coordinates // texture_u = texture_distance / texture_size; rotated_points[0].texture_u = texture_u; rotated_points[0].colour = light_smoke_colour ( points[0].colour, additive ); for ( count = 0; count < ( number_of_points - 1 ); count++ ) { vec3d centre_point1, centre_point2, length_vector; float texture_temp_distance; centre_point1.x = ( points[count].point1.x + points[count].point2.x ) / 2; centre_point1.y = ( points[count].point1.y + points[count].point2.y ) / 2; centre_point1.z = ( points[count].point1.z + points[count].point2.z ) / 2; centre_point2.x = ( points[count+1].point1.x + points[count+1].point2.x ) / 2; centre_point2.y = ( points[count+1].point1.y + points[count+1].point2.y ) / 2; centre_point2.z = ( points[count+1].point1.z + points[count+1].point2.z ) / 2; length_vector.x = centre_point2.x - centre_point1.x; length_vector.y = centre_point2.y - centre_point1.y; length_vector.z = centre_point2.z - centre_point1.z; // // Calculate the length of line connecting the two centre points // texture_temp_distance = ( get_3d_vector_magnitude ( &length_vector ) / texture_size ); texture_u += texture_temp_distance; rotated_points[count+1].texture_u = texture_u; rotated_points[count+1].colour = light_smoke_colour ( points[count+1].colour, additive ); } // // Now insert each segment dependant on it being visible or not. // for ( count = 0; count < ( number_of_points - 1 ); count++ ) { if ( ( rotated_points[count].point1.z > clip_hither ) || ( rotated_points[count].point2.z > clip_hither ) || ( rotated_points[count+1].point1.z > clip_hither ) || ( rotated_points[count+1].point1.z > clip_hither ) ) { scene_slot_drawing_list *buffer; float average_z; average_z = ( ( rotated_points[count].point1.z + rotated_points[count].point2.z ) + ( rotated_points[count+1].point1.z + rotated_points[count+1].point2.z ) ); average_z /= 4; average_z += zbias; buffer = get_3d_scene_slot (); if ( buffer ) { buffer->type = OBJECT_3D_DRAW_TYPE_SMOKE_TRAIL; buffer->z = *( ( int * ) &average_z ); buffer->smoke_trail.trail = smoke_trail; buffer->smoke_trail.segment = count; if ( points[count].point1.y > middle_scene_slot_height ) { insert_high_nonzbuffered_scene_slot_into_3d_scene ( buffer ); } else { insert_low_nonzbuffered_scene_slot_into_3d_scene ( buffer ); } } else { debug_log ( "SMOKE TRAIL OVERFLOWED OBJECT BUFFER" ); } } } } else { // // No point in freeing up the smoke trail point data, as all the headers are used up! // } } else { // // Free up the reserved smoke trail point data slots // remove_smoke_trail_point_data ( number_of_points ); } } }
void draw_3d_cloud_sector ( scene_slot_drawing_list *slot ) { int count; float current_sector_x_offset, current_sector_z_offset; double tempx, tempz; vec3d sector_centre, sector_relative_centre; cloud_3d_point cloud_points[256]; float cloud_polygon_alphas[256]; cloud_3d_textured_reference point_references[4]; // // Set the fog intensity for clouds ( NO FOG ) // current_sector_x_offset = slot->cloud_sector.x * CLOUD_3D_SECTOR_SIDE_LENGTH; current_sector_z_offset = slot->cloud_sector.z * CLOUD_3D_SECTOR_SIDE_LENGTH; sector_centre.x = current_sector_x_offset + ( CLOUD_3D_SECTOR_SIDE_LENGTH / 2 ); sector_centre.y = cloud_3d_base_height; sector_centre.z = current_sector_z_offset + ( CLOUD_3D_SECTOR_SIDE_LENGTH / 2 ); sector_centre.x -= visual_3d_vp->x; sector_centre.y -= visual_3d_vp->y; sector_centre.z -= visual_3d_vp->z; sector_relative_centre.x = ( ( sector_centre.x ) * visual_3d_vp->xv.x + ( sector_centre.y ) * visual_3d_vp->xv.y + ( sector_centre.z ) * visual_3d_vp->xv.z ); sector_relative_centre.y = ( ( sector_centre.x ) * visual_3d_vp->yv.x + ( sector_centre.y ) * visual_3d_vp->yv.y + ( sector_centre.z ) * visual_3d_vp->yv.z ); sector_relative_centre.z = ( ( sector_centre.x ) * visual_3d_vp->zv.x + ( sector_centre.y ) * visual_3d_vp->zv.y + ( sector_centre.z ) * visual_3d_vp->zv.z ); set_d3d_fog_face_intensity ( 0 ); if ( d3d_flat_only_alpha ) { int number_of_sub_sectors, number_of_points, x, z; float x_offset, z_offset, alpha; number_of_sub_sectors = 1; number_of_points = ( number_of_sub_sectors + 1 ) * ( number_of_sub_sectors + 1 ); count = 0; for ( z = 0; z <= number_of_sub_sectors; z++ ) { for ( x = 0; x <= number_of_sub_sectors; x++ ) { vec3d point_vector; float angle, distance, colour_t, dr, dg, db, r, g, b; int ir, ig, ib; x_offset = ( -CLOUD_3D_SECTOR_SIDE_LENGTH/2 ) + ( ( ( float ) x / ( float ) number_of_sub_sectors ) * CLOUD_3D_SECTOR_SIDE_LENGTH ); z_offset = ( -CLOUD_3D_SECTOR_SIDE_LENGTH/2 ) + ( ( ( float ) z / ( float ) number_of_sub_sectors ) * CLOUD_3D_SECTOR_SIDE_LENGTH ); cloud_points[count].x = x_offset; cloud_points[count].y = 0; cloud_points[count].z = z_offset; point_vector.x = sector_centre.x + x_offset; point_vector.y = 0; point_vector.z = sector_centre.z + z_offset; distance = get_3d_vector_magnitude ( &point_vector ); if ( distance > 1 ) { normalise_3d_vector_given_magnitude ( &point_vector, distance ); angle = ( ( point_vector.x * cloud_colour_blend_vector.x ) + ( point_vector.z * cloud_colour_blend_vector.z ) ); angle = bound ( angle, 0, 1 ); angle *= angle; angle *= angle; colour_t = ( distance / CLOUD_MAXIMUM_COLOUR_BLEND_DISTANCE ); colour_t = bound ( colour_t, 0, 1 ); colour_t *= angle; } else { colour_t = 0; } dr = active_3d_environment->cloud_light.object_colour.red - active_3d_environment->cloud_light.light_colour.red; dg = active_3d_environment->cloud_light.object_colour.green - active_3d_environment->cloud_light.light_colour.green; db = active_3d_environment->cloud_light.object_colour.blue - active_3d_environment->cloud_light.light_colour.blue; r = active_3d_environment->cloud_light.light_colour.red + ( colour_t * dr ); g = active_3d_environment->cloud_light.light_colour.green + ( colour_t * dg ); b = active_3d_environment->cloud_light.light_colour.blue + ( colour_t * db ); convert_float_to_int ( r * 255.0, &ir ); convert_float_to_int ( g * 255.0, &ig ); convert_float_to_int ( b * 255.0, &ib ); cloud_points[count].red = ir; cloud_points[count].green = ig; cloud_points[count].blue = ib; count++; } } count = 0; z_offset = -CLOUD_3D_SECTOR_SIDE_LENGTH/2 + ( CLOUD_3D_SECTOR_SIDE_LENGTH / ( number_of_sub_sectors * 2 ) ); for ( z = 0; z < number_of_sub_sectors; z++ ) { x_offset = -CLOUD_3D_SECTOR_SIDE_LENGTH/2 + ( CLOUD_3D_SECTOR_SIDE_LENGTH / ( number_of_sub_sectors * 2 ) ); for ( x = 0; x < number_of_sub_sectors; x++ ) { tempx = sector_centre.x + x_offset; tempz = sector_centre.z + z_offset; tempx *= tempx; tempz *= tempz; alpha = ( ( cloud_3d_blend_constant - ( tempx + tempz ) ) * cloud_3d_adjusted_blend_factor ); alpha = bound ( alpha, 0, 1 ); cloud_polygon_alphas[count] = alpha; x_offset += CLOUD_3D_SECTOR_SIDE_LENGTH / ( number_of_sub_sectors * 1 ); count++; } z_offset += CLOUD_3D_SECTOR_SIDE_LENGTH / ( number_of_sub_sectors * 1 ); } transform_cloud_points ( number_of_points, cloud_points, cloud_transformed_3d_points, §or_relative_centre ); // // Render a quad twice, for the blending between cloud textures // count = 0; z_offset = 0; for ( z = 0; z < number_of_sub_sectors; z++ ) { x_offset = 0; for ( x = 0; x < number_of_sub_sectors; x++ ) { int tmp, z_bottom_point_offset, z_top_point_offset; z_bottom_point_offset = z * ( number_of_sub_sectors + 1 ); z_top_point_offset = z_bottom_point_offset + ( number_of_sub_sectors + 1 ); if ( cloud_3d_base_height < visual_3d_vp->y ) { point_references[3].point = x + z_bottom_point_offset; point_references[3].u = x_offset; point_references[3].v = z_offset; point_references[2].point = x + z_bottom_point_offset + 1; point_references[2].u = x_offset + ( 1.0 / number_of_sub_sectors ); point_references[2].v = z_offset; point_references[1].point = x + z_top_point_offset + 1; point_references[1].u = x_offset + ( 1.0 / number_of_sub_sectors ); point_references[1].v = z_offset + ( 1.0 / number_of_sub_sectors ); point_references[0].point = x + z_top_point_offset; point_references[0].u = x_offset; point_references[0].v = z_offset + ( 1.0 / number_of_sub_sectors ); } else { point_references[0].point = x + z_bottom_point_offset; point_references[0].u = x_offset; point_references[0].v = z_offset; point_references[1].point = x + z_bottom_point_offset + 1; point_references[1].u = x_offset + ( 1.0 / number_of_sub_sectors ); point_references[1].v = z_offset; point_references[2].point = x + z_top_point_offset + 1; point_references[2].u = x_offset + ( 1.0 / number_of_sub_sectors ); point_references[2].v = z_offset + ( 1.0 / number_of_sub_sectors ); point_references[3].point = x + z_top_point_offset; point_references[3].u = x_offset; point_references[3].v = z_offset + ( 1.0 / number_of_sub_sectors ); } for ( tmp = 0; tmp < 4; tmp++ ) { cloud_points[ point_references[tmp].point ].a = cloud_polygon_alphas[count]; } if ( current_weather_texture ) { render_cloud_polygon ( 4, point_references, cloud_transformed_3d_points, cloud_points, cloud_weather_one_minus_blend_factor, current_weather_texture ); } if ( target_weather_texture ) { render_cloud_polygon ( 4, point_references, cloud_transformed_3d_points, cloud_points, cloud_weather_blend_factor, target_weather_texture ); } x_offset += ( 1.0 / number_of_sub_sectors ); count++; } z_offset += ( 1.0 / number_of_sub_sectors ); } } else { cloud_points[0].x = -CLOUD_3D_SECTOR_SIDE_LENGTH/2; cloud_points[0].y = 0; cloud_points[0].z = -CLOUD_3D_SECTOR_SIDE_LENGTH/2; cloud_points[1].x = +CLOUD_3D_SECTOR_SIDE_LENGTH/2; cloud_points[1].y = 0; cloud_points[1].z = -CLOUD_3D_SECTOR_SIDE_LENGTH/2; cloud_points[2].x = +CLOUD_3D_SECTOR_SIDE_LENGTH/2; cloud_points[2].y = 0; cloud_points[2].z = +CLOUD_3D_SECTOR_SIDE_LENGTH/2; cloud_points[3].x = -CLOUD_3D_SECTOR_SIDE_LENGTH/2; cloud_points[3].y = 0; cloud_points[3].z = +CLOUD_3D_SECTOR_SIDE_LENGTH/2; for ( count = 0; count < 4; count++ ) { vec3d point_vector; int ir, ig, ib; float colour_t, alpha, distance, angle, dr, dg, db, r, g, b; tempx = sector_centre.x + cloud_points[count].x; tempz = sector_centre.z + cloud_points[count].z; point_vector.x = tempx; point_vector.y = 0; point_vector.z = tempz; distance = get_3d_vector_magnitude ( &point_vector ); if ( distance > 1 ) { normalise_3d_vector_given_magnitude ( &point_vector, distance ); angle = ( ( point_vector.x * cloud_colour_blend_vector.x ) + ( point_vector.z * cloud_colour_blend_vector.z ) ); angle = bound ( angle, 0, 1 ); angle *= angle; angle *= angle; colour_t = ( distance / CLOUD_MAXIMUM_COLOUR_BLEND_DISTANCE ); colour_t = bound ( colour_t, 0, 1 ); colour_t *= angle; } else { colour_t = 0; } alpha = ( ( cloud_3d_blend_constant - ( distance * distance ) ) * cloud_3d_adjusted_blend_factor ); cloud_points[count].a = bound ( alpha, 0, 1 ); dr = active_3d_environment->cloud_light.object_colour.red - active_3d_environment->cloud_light.light_colour.red; dg = active_3d_environment->cloud_light.object_colour.green - active_3d_environment->cloud_light.light_colour.green; db = active_3d_environment->cloud_light.object_colour.blue - active_3d_environment->cloud_light.light_colour.blue; r = active_3d_environment->cloud_light.light_colour.red + ( colour_t * dr ); g = active_3d_environment->cloud_light.light_colour.green + ( colour_t * dg ); b = active_3d_environment->cloud_light.light_colour.blue + ( colour_t * db ); convert_float_to_int ( r * 255.0, &ir ); convert_float_to_int ( g * 255.0, &ig ); convert_float_to_int ( b * 255.0, &ib ); cloud_points[count].red = ir; cloud_points[count].green = ig; cloud_points[count].blue = ib; /* debug_log ( "( %d, %d, %d ) -> ( %d, %d, %d ) d( %d, %d, %d ) blend = %f = %d, %d, %d", active_3d_environment->cloud_light.light_colour.red * 255, active_3d_environment->cloud_light.light_colour.green * 255, active_3d_environment->cloud_light.light_colour.blue * 255, active_3d_environment->cloud_light.object_colour.red * 255, active_3d_environment->cloud_light.object_colour.green * 255, active_3d_environment->cloud_light.object_colour.blue * 255, dr * 255, dg * 255, db * 255, colour_t, ir, ig, ib ); */ } transform_cloud_points ( 4, cloud_points, cloud_transformed_3d_points, §or_relative_centre ); // // Render a quad twice, for the blending between cloud textures // if ( cloud_3d_base_height < visual_3d_vp->y ) { point_references[3].point = 0; point_references[3].u = 0; point_references[3].v = 0; point_references[2].point = 1; point_references[2].u = 1; point_references[2].v = 0; point_references[1].point = 2; point_references[1].u = 1; point_references[1].v = 1; point_references[0].point = 3; point_references[0].u = 0; point_references[0].v = 1; } else { point_references[0].point = 0; point_references[0].u = 0; point_references[0].v = 0; point_references[1].point = 1; point_references[1].u = 1; point_references[1].v = 0; point_references[2].point = 2; point_references[2].u = 1; point_references[2].v = 1; point_references[3].point = 3; point_references[3].u = 0; point_references[3].v = 1; } if ( current_weather_texture ) { render_cloud_polygon ( 4, point_references, cloud_transformed_3d_points, cloud_points, cloud_weather_one_minus_blend_factor, current_weather_texture ); } if ( target_weather_texture ) { render_cloud_polygon ( 4, point_references, cloud_transformed_3d_points, cloud_points, cloud_weather_blend_factor, target_weather_texture ); } } }
static void update_threat_warning_display (void) { entity *source, *threat; int above = FALSE, overshot, threat_active; float dx, dy, dz, theta, threat_bearing, threat_range, threat_velocity, time_to_impact, source_heading, length, cos_error; threat_types threat_type; vec3d *source_position, *threat_position, uvec_threat_to_target; matrix3x3 *attitude; clear_threat_warning_display_lamps (); if (hind_damage.threat_warning_display || hind_damage.radar_warning_system) { return; } threat = get_local_entity_first_child (get_gunship_entity (), LIST_TYPE_TARGET); if (threat) { source = get_gunship_entity (); source_position = get_local_entity_vec3d_ptr (source, VEC3D_TYPE_POSITION); source_heading = get_local_entity_float_value (source, FLOAT_TYPE_HEADING); while (threat) { entity_sub_types sub_type = get_local_entity_int_value(threat, INT_TYPE_ENTITY_SUB_TYPE); float max_range = 10.0; threat_type = (threat_types) get_local_entity_int_value (threat, INT_TYPE_THREAT_TYPE); // // check threat is active // if (get_local_entity_int_value (threat, INT_TYPE_IDENTIFY_VEHICLE)) { max_range = vehicle_database[sub_type].air_scan_range; threat_active = get_local_entity_int_value (threat, INT_TYPE_RADAR_ON); } else if (get_local_entity_int_value (threat, INT_TYPE_IDENTIFY_AIRCRAFT)) { max_range = aircraft_database[sub_type].air_scan_range; threat_active = get_local_entity_int_value (threat, INT_TYPE_RADAR_ON); } else if (get_local_entity_int_value (threat, INT_TYPE_IDENTIFY_WEAPON)) { weapon_guidance_types guidance = weapon_database[sub_type].guidance_type; threat_active = guidance == WEAPON_GUIDANCE_TYPE_ACTIVE_RADAR; if (guidance == WEAPON_GUIDANCE_TYPE_ACTIVE_RADAR || guidance == WEAPON_GUIDANCE_TYPE_SEMI_ACTIVE_RADAR) { hind_lamps.threat_warning_missile_lh_lock = 1; hind_lamps.threat_warning_missile_rh_lock = 1; } max_range = weapon_database[sub_type].max_range; } #if 0 switch (threat_type) { //////////////////////////////////////// case THREAT_TYPE_INVALID: //////////////////////////////////////// { threat_active = FALSE; break; } //////////////////////////////////////// case THREAT_TYPE_RF_MISSILE: //////////////////////////////////////// { ASSERT(get_local_entity_int_value (threat, INT_TYPE_IDENTIFY_WEAPON)); if (!hind_damage.radar_warning_system) { threat_active = TRUE; } else { threat_active = FALSE; } break; } //////////////////////////////////////// case THREAT_TYPE_IR_MISSILE: //////////////////////////////////////// { threat_active = FALSE; break; } //////////////////////////////////////// case THREAT_TYPE_LASER_MISSILE: //////////////////////////////////////// { threat_active = FALSE; break; } //////////////////////////////////////// case THREAT_TYPE_AIRBORNE_RADAR: //////////////////////////////////////// { if (!hind_damage.radar_warning_system) { threat_active = get_local_entity_int_value (threat, INT_TYPE_RADAR_ON); } else { threat_active = FALSE; } break; } //////////////////////////////////////// case THREAT_TYPE_SAM: //////////////////////////////////////// { if (!hind_damage.radar_warning_system) { threat_active = get_local_entity_int_value (threat, INT_TYPE_RADAR_ON); } else { threat_active = FALSE; } break; } //////////////////////////////////////// case THREAT_TYPE_AAA: //////////////////////////////////////// { if (!hind_damage.radar_warning_system) { threat_active = get_local_entity_int_value (threat, INT_TYPE_RADAR_ON); } else { threat_active = FALSE; } break; } //////////////////////////////////////// case THREAT_TYPE_EARLY_WARNING_RADAR: //////////////////////////////////////// { if (!hind_damage.radar_warning_system) { threat_active = get_local_entity_int_value (threat, INT_TYPE_RADAR_ON); } else { threat_active = FALSE; } break; } //////////////////////////////////////// default: //////////////////////////////////////// { debug_fatal ("Invalid threat type = %d", threat_type); break; } } #endif if (threat_active) { // // get threat direction wrt aircraft datum // threat_position = get_local_entity_vec3d_ptr (threat, VEC3D_TYPE_POSITION); dx = threat_position->x - source_position->x; dy = threat_position->y - source_position->y; dz = threat_position->z - source_position->z; threat_range = sqrt ((dx * dx) + (dy * dy) + (dz * dz)); above = dy > 0.0; threat_bearing = atan2 (dx, dz); theta = threat_bearing - source_heading; if (theta > rad (180.0)) { theta -= rad (360.0); } else if (theta < rad (-180.0)) { theta += rad (360.0); } // // if missile threat then guard against 'overshot target' to prevent spurious indications // if ((threat_type == THREAT_TYPE_RF_MISSILE) || (threat_type == THREAT_TYPE_IR_MISSILE) || (threat_type == THREAT_TYPE_LASER_MISSILE)) { threat_velocity = get_local_entity_float_value (threat, FLOAT_TYPE_VELOCITY); time_to_impact = threat_range / max (threat_velocity, 1.0f); overshot = FALSE; if (time_to_impact < 1.0) { uvec_threat_to_target.x = source_position->x - threat_position->x; uvec_threat_to_target.y = source_position->y - threat_position->y; uvec_threat_to_target.z = source_position->z - threat_position->z; length = get_3d_vector_magnitude (&uvec_threat_to_target); if (length > 1.0) { normalise_3d_vector_given_magnitude (&uvec_threat_to_target, length); attitude = get_local_entity_attitude_matrix_ptr (threat); cos_error = get_3d_unit_vector_dot_product ((vec3d *) &((*attitude) [2][0]), &uvec_threat_to_target); if (cos_error < 0.0) { overshot = TRUE; } } else { overshot = TRUE; } } if (!overshot) { light_threat_bearing_lamp (theta); light_signal_strength_lamps(threat_range, max_range); hind_lamps.threat_warning_radar_type_1 = 1; if (above) hind_lamps.threat_warning_missile_above = 1; else hind_lamps.threat_warning_missile_below = 1; } } else { light_threat_bearing_lamp (theta); light_signal_strength_lamps(threat_range, max_range); if (above) hind_lamps.threat_warning_missile_above = 1; else hind_lamps.threat_warning_missile_below = 1; if (threat_type == THREAT_TYPE_AIRBORNE_RADAR) hind_lamps.threat_warning_radar_type_1 = 1; else { if (max_range <= 4000.0) // short range hind_lamps.threat_warning_radar_type_4 = 1; else if (max_range <= 10000.0) // medium range hind_lamps.threat_warning_radar_type_3 = 1; else // long range hind_lamps.threat_warning_radar_type_2 = 1; } } } threat = get_local_entity_child_succ (threat, LIST_TYPE_TARGET); } } }
void update_3d_rain ( env_3d *env, float time, matrix3x3 view_attitude ) { int start_raindrop_number, end_raindrop_number, total_raindrop_number, start_snowdrop_number, end_snowdrop_number, total_snowdrop_number, creation_allowed, count; float displacement_magnitude, snow_displacement_magnitude, snow_fall_displacement, weather_t; vec3d distance_moved, rain_displacement, snow_drift_displacement, rain_streak_displacement, creation_vector; // // Calculate how many rain drops we should have. This is a linear scale, from 0, to TOTAL_3D_RAINDROPS. // DRY = 0 // LIGHT_RAIN = TOTAL_3D_RAINDROPS / 2 // HEAVY_RAIN = TOTAL_3D_RAINDROPS // if ( visual_3d_vp ) { if ( visual_3d_vp->position.y > get_cloud_3d_base_height () ) { creation_allowed = FALSE; } else { creation_allowed = TRUE; } } else { creation_allowed = FALSE; } start_raindrop_number = number_of_weather_particles_allowed[env->weathermode].number_of_raindrops; start_snowdrop_number = number_of_weather_particles_allowed[env->weathermode].number_of_snowdrops; end_raindrop_number = number_of_weather_particles_allowed[env->target_weathermode].number_of_raindrops; end_snowdrop_number = number_of_weather_particles_allowed[env->target_weathermode].number_of_snowdrops; weather_t = env->weather_targetdistance; if ( weather_t == 0 ) { total_raindrop_number = start_raindrop_number; total_snowdrop_number = start_snowdrop_number; } else if ( weather_t == 1 ) { total_raindrop_number = end_raindrop_number; total_snowdrop_number = end_snowdrop_number; } else { total_raindrop_number = start_raindrop_number + ( ( ( float ) ( end_raindrop_number - start_raindrop_number ) ) * weather_t ); total_snowdrop_number = start_snowdrop_number + ( ( ( float ) ( end_snowdrop_number - start_snowdrop_number ) ) * weather_t ); } // // Special snow flag stuff // if ( special_snow_flag ) { /* if ( visual_3d_vp ) { int x, z; int near_snow; float old_rain_total; near_snow = FALSE; for ( z = -1; z <= 1; z++ ) { for ( x = -1; x <= 1; x++ ) { float x_pos, z_pos; x_pos = visual_3d_vp->x + x * TERRAIN_3D_SECTOR_SIDE_LENGTH; z_pos = visual_3d_vp->z + z * TERRAIN_3D_SECTOR_SIDE_LENGTH; x_pos = bound ( x_pos, terrain_3d_min_map_x, terrain_3d_max_map_x ); z_pos = bound ( z_pos, terrain_3d_min_map_z, terrain_3d_max_map_z ); get_terrain_3d_types_in_sector ( x_pos, z_pos ); if ( terrain_types_in_sector[TERRAIN_TYPE_ALTERED_LAND3] ) { near_snow = TRUE; } } } if ( near_snow ) { old_rain_total = total_raindrop_number; total_raindrop_number = old_rain_total * 0.0; total_snowdrop_number = old_rain_total * 1.0; } } */ } // // // rain_3d_delta_time = time - time_rain_last_updated; time_rain_last_updated = time; // // Calculate the distance moved by each raindrop. // distance_moved.x = rain_3d_wind_direction.x * rain_3d_wind_speed * rain_3d_delta_time; distance_moved.y = rain_3d_wind_direction.y * rain_3d_wind_speed * rain_3d_delta_time; distance_moved.z = rain_3d_wind_direction.z * rain_3d_wind_speed * rain_3d_delta_time; rain_displacement.x = distance_moved.x; rain_displacement.y = distance_moved.y + ( rain_3d_speed * rain_3d_delta_time ); rain_displacement.z = distance_moved.z; // // Calculate the distance moved by each snowdrop. // snow_drift_displacement.x = distance_moved.x; snow_drift_displacement.y = distance_moved.y; snow_drift_displacement.z = distance_moved.z; snow_fall_displacement = ( rain_3d_speed / 4 ) * rain_3d_delta_time; snow_displacement_magnitude = get_3d_vector_magnitude ( &snow_drift_displacement ); // // Calculate the 'streak' effect - this is now NOT framerate related // rain_streak_displacement = rain_displacement; displacement_magnitude = get_3d_vector_magnitude ( &rain_streak_displacement ); if ( displacement_magnitude != 0 ) { displacement_magnitude = 1.5 / displacement_magnitude; rain_streak_displacement.x *= displacement_magnitude; rain_streak_displacement.y *= displacement_magnitude; rain_streak_displacement.z *= displacement_magnitude; } else { // // Put artificial streaking in there ( game paused ) // rain_streak_displacement.x = rain_3d_wind_direction.x * rain_3d_wind_speed * 0.05; rain_streak_displacement.y = rain_3d_wind_direction.y * rain_3d_wind_speed * 0.05 + ( rain_3d_speed * 0.05 ); rain_streak_displacement.z = rain_3d_wind_direction.z * rain_3d_wind_speed * 0.05; displacement_magnitude = get_3d_vector_magnitude ( &rain_streak_displacement ); if ( displacement_magnitude != 0 ) { displacement_magnitude = 1.5 / displacement_magnitude; rain_streak_displacement.x *= displacement_magnitude; rain_streak_displacement.y *= displacement_magnitude; rain_streak_displacement.z *= displacement_magnitude; } } // // Remove any raindrops that have strayed out of the area of effect // creation_vector.x = rain_3d_wind_direction.x * rain_3d_wind_speed * 0.5; creation_vector.y = rain_3d_wind_direction.y * rain_3d_wind_speed * 0.5 + ( rain_3d_speed * 0.5 ); creation_vector.z = rain_3d_wind_direction.z * rain_3d_wind_speed * 0.5; normalise_any_3d_vector ( &creation_vector ); for ( count = 0; count < TOTAL_3D_RAINDROPS; count++ ) { switch ( rain_3d_drops[count].type ) { case RAINDROP_RAIN: { vec3d rel; // // Update the rain position // rain_3d_drops[count].current_position.x -= rain_displacement.x; rain_3d_drops[count].current_position.y -= rain_displacement.y; rain_3d_drops[count].current_position.z -= rain_displacement.z; rel.x = rain_3d_drops[count].current_position.x - visual_3d_vp->x; rel.y = rain_3d_drops[count].current_position.y - visual_3d_vp->y; rel.z = rain_3d_drops[count].current_position.z - visual_3d_vp->z; if ( ( rel.x > RAINDROPS_AREA_WIDTH ) || ( rel.x < ( -RAINDROPS_AREA_WIDTH ) ) || ( rel.y > RAINDROPS_AREA_HEIGHT ) || ( rel.y < ( -RAINDROPS_AREA_HEIGHT ) ) || ( rel.z > RAINDROPS_AREA_DEPTH ) || ( rel.z < ( -RAINDROPS_AREA_DEPTH ) ) ) { rain_3d_raindrops_valid--; rain_3d_drops[count].type = RAINDROP_INVALID; } break; } case RAINDROP_SNOW: { vec3d snow_noise, rel; float relative_speed; // // Update the rain position // snow_noise.x = sfrand1 () * rain_3d_delta_time; //0.1 ;//snow_displacement_magnitude; snow_noise.y = sfrand1 () * rain_3d_delta_time; //0.1 ;//snow_displacement_magnitude; snow_noise.z = sfrand1 () * rain_3d_delta_time; //0.1 ;//snow_displacement_magnitude; relative_speed = rain_3d_drops[count].relative_speed; rain_3d_drops[count].current_position.x -= ( snow_drift_displacement.x + snow_noise.x ); rain_3d_drops[count].current_position.y -= ( snow_drift_displacement.y ); rain_3d_drops[count].current_position.z -= ( snow_drift_displacement.z + snow_noise.x ); rain_3d_drops[count].current_position.y -= ( snow_fall_displacement * relative_speed ); rel.x = rain_3d_drops[count].current_position.x - visual_3d_vp->x; rel.y = rain_3d_drops[count].current_position.y - visual_3d_vp->y; rel.z = rain_3d_drops[count].current_position.z - visual_3d_vp->z; if ( ( rel.x > SNOWDROPS_AREA_WIDTH ) || ( rel.x < ( -SNOWDROPS_AREA_WIDTH ) ) || ( rel.y > SNOWDROPS_AREA_HEIGHT ) || ( rel.y < ( -SNOWDROPS_AREA_HEIGHT ) ) || ( rel.z > SNOWDROPS_AREA_DEPTH ) || ( rel.z < ( -SNOWDROPS_AREA_DEPTH ) ) ) { rain_3d_snowdrops_valid--; rain_3d_drops[count].type = RAINDROP_INVALID; } break; } } if ( ( rain_3d_drops[count].type == RAINDROP_INVALID ) && ( creation_allowed ) ) { if ( rain_3d_raindrops_valid < total_raindrop_number ) { float x, y, z, creation_distance; // // Generate a new rain drop randomly // z = ( ( frand1 () * 0.8 ) + 0.2 ) * ( RAINDROPS_AREA_DEPTH / 5 ); x = sfrand1 () * ( RAINDROPS_AREA_WIDTH / 5 ); y = sfrand1 () * ( RAINDROPS_AREA_HEIGHT / 5 ); x *= z / 50; y *= z / 50; // // Now project along the motion vector // creation_distance = frand1 () * 8; x += creation_vector.x * creation_distance; y += creation_vector.y * creation_distance; z += creation_vector.z * creation_distance; // // Rotate this back into the view coordinate system // rain_3d_drops[count].current_position.x = x * view_attitude[0][0] + y * view_attitude[1][0] + z * view_attitude[2][0]; rain_3d_drops[count].current_position.y = x * view_attitude[0][1] + y * view_attitude[1][1] + z * view_attitude[2][1]; rain_3d_drops[count].current_position.z = x * view_attitude[0][2] + y * view_attitude[1][2] + z * view_attitude[2][2]; rain_3d_drops[count].current_position.x += visual_3d_vp->x; rain_3d_drops[count].current_position.y += visual_3d_vp->y; rain_3d_drops[count].current_position.z += visual_3d_vp->z; rain_3d_drops[count].type = RAINDROP_RAIN; rain_3d_raindrops_valid++; } else if ( rain_3d_snowdrops_valid < total_snowdrop_number ) { float x, y, z, creation_distance; // // Generate a new snowdrop // z = ( ( frand1 () * 0.8 ) + 0.2 ) * ( SNOWDROPS_AREA_DEPTH / 5 ); x = sfrand1 () * ( SNOWDROPS_AREA_WIDTH / 5 ); y = sfrand1 () * ( SNOWDROPS_AREA_HEIGHT / 5 ); x *= z / 50; y *= z / 50; // // Now project along the motion vector // creation_distance = frand1 () * 8; x += creation_vector.x * creation_distance; y += creation_vector.y * creation_distance; z += creation_vector.z * creation_distance; // // Rotate this back into the view coordinate system // rain_3d_drops[count].current_position.x = x * view_attitude[0][0] + y * view_attitude[1][0] + z * view_attitude[2][0]; rain_3d_drops[count].current_position.y = x * view_attitude[0][1] + y * view_attitude[1][1] + z * view_attitude[2][1]; rain_3d_drops[count].current_position.z = x * view_attitude[0][2] + y * view_attitude[1][2] + z * view_attitude[2][2]; rain_3d_drops[count].current_position.x += visual_3d_vp->x; rain_3d_drops[count].current_position.y += visual_3d_vp->y; rain_3d_drops[count].current_position.z += visual_3d_vp->z; rain_3d_drops[count].relative_speed = ( frand1() * 0.5 ) + 0.5; rain_3d_drops[count].type = RAINDROP_SNOW; rain_3d_snowdrops_valid++; } } } // // Now calculate the predicted positions for rendering // for ( count = 0; count < TOTAL_3D_RAINDROPS; count++ ) { if ( rain_3d_drops[count].type == RAINDROP_RAIN ) { rain_3d_drops[count].predicted_position.x = rain_3d_drops[count].current_position.x - rain_streak_displacement.x; rain_3d_drops[count].predicted_position.y = rain_3d_drops[count].current_position.y - rain_streak_displacement.y; rain_3d_drops[count].predicted_position.z = rain_3d_drops[count].current_position.z - rain_streak_displacement.z; } } }
void ship_vehicle_death_movement (entity *en) { ship_vehicle *raw; float speed, heading, pitch, roll; vec3d *pos, *velocity, new_pos; raw = get_local_entity_data (en); // // work out new position // velocity = get_local_entity_vec3d_ptr (en, VEC3D_TYPE_MOTION_VECTOR); pos = get_local_entity_vec3d_ptr (en, VEC3D_TYPE_POSITION); new_pos.x = pos->x + (velocity->x * get_entity_movement_delta_time()); new_pos.y = pos->y + (velocity->y * get_entity_movement_delta_time()); new_pos.z = pos->z + (velocity->z * get_entity_movement_delta_time()); // // update velocity // velocity->x -= (velocity->x * 0.2 * get_entity_movement_delta_time ()); velocity->z -= (velocity->z * 0.2 * get_entity_movement_delta_time ()); velocity->y -= (SHIP_SINK_RATE * get_entity_movement_delta_time ()); speed = get_3d_vector_magnitude (velocity); set_local_entity_float_value (en, FLOAT_TYPE_VELOCITY, speed); // // update attitude // heading = get_heading_from_attitude_matrix (raw->vh.mob.attitude); pitch = get_pitch_from_attitude_matrix (raw->vh.mob.attitude); pitch += (SHIP_SINK_DELTA_PITCH_RATE * get_entity_movement_delta_time()); roll = get_roll_from_attitude_matrix (raw->vh.mob.attitude); roll += (SHIP_SINK_DELTA_ROLL_RATE * get_entity_movement_delta_time()); get_3d_transformation_matrix (raw->vh.mob.attitude, heading, pitch, roll); // // set new position // set_local_entity_vec3d (en, VEC3D_TYPE_POSITION, &new_pos); clear_ship_fires (en, ENTITY_SUB_TYPE_EFFECT_SMOKE_LIST_FIRE); clear_ship_fires (en, ENTITY_SUB_TYPE_EFFECT_SMOKE_LIST_EXPLOSION_TRAIL); // // remove ship if totally obscured (i.e. sunk) // if (get_comms_model () == COMMS_MODEL_SERVER) { struct OBJECT_3D_BOUNDS *bounding_box; vec3d d; float obscured_altitude; bounding_box = get_object_3d_bounding_box (get_local_entity_int_value (en, INT_TYPE_OBJECT_3D_SHAPE)); d.x = bounding_box->xmax - bounding_box->xmin; d.y = bounding_box->ymax - bounding_box->ymin; d.z = bounding_box->zmax - bounding_box->zmin; obscured_altitude = -(0.5 * get_3d_vector_magnitude (&d)); if (new_pos.y < obscured_altitude) { // // ship is no longer visible // destroy_client_server_entity_family (en); } } }