void scan_3d_clouds ( void ) { int visual_sector_x, visual_sector_z, current_sector_x, current_sector_z, minimum_sector_x, minimum_sector_z, maximum_sector_x, maximum_sector_z; float initial_sector_x_offset, initial_sector_z_offset, current_sector_x_offset, current_sector_z_offset; weathermodes current_weathermode, target_weathermode; matrix3x3 cloud_matrix; // // Get the vector pointing to the colour blend // get_3d_transformation_matrix ( cloud_matrix, active_3d_environment->cloud_light.heading, active_3d_environment->cloud_light.pitch, 0 ); cloud_colour_blend_vector.x = cloud_matrix[2][0]; cloud_colour_blend_vector.y = 0; cloud_colour_blend_vector.z = cloud_matrix[2][2]; normalise_3d_vector ( &cloud_colour_blend_vector ); // // Adjust the cloud blend factor // if ( ( visual_3d_vp->y > ( cloud_3d_base_height - 100 ) ) && ( visual_3d_vp->y < ( cloud_3d_base_height + 100 ) ) ) { float blend; blend = ( ( fabs ( visual_3d_vp->y - cloud_3d_base_height ) ) / 100 ); if ( blend > 1 ) { blend = 1; } cloud_3d_adjusted_blend_factor = cloud_3d_blend_factor * blend; } else { cloud_3d_adjusted_blend_factor = cloud_3d_blend_factor; } // // Choose the two textures to be blending inbetween // current_weathermode = get_3d_weathermode ( active_3d_environment ); target_weathermode = get_3d_target_weathermode ( active_3d_environment ); if ( !cloud_textures[current_weathermode].valid ) { debug_fatal ( "Unable to draw clouds - no texture set for current weathermode: %d", current_weathermode ); } if ( !cloud_textures[target_weathermode].texture_index ) { debug_fatal ( "Unable to draw clouds - no texture set for target weathermode: %d", target_weathermode ); } cloud_weather_blend_factor = get_3d_target_weathermode_transitional_status ( active_3d_environment ); cloud_weather_one_minus_blend_factor = 1.0 - cloud_weather_blend_factor; if ( current_weathermode != target_weathermode ) { if ( cloud_weather_blend_factor == 1 ) { current_weather_texture = system_textures[ cloud_textures[target_weathermode].texture_index ]; target_weather_texture = NULL; cloud_weather_blend_factor = 0; cloud_weather_one_minus_blend_factor = 1.0; } else if ( cloud_weather_blend_factor == 0 ) { current_weather_texture = system_textures[ cloud_textures[current_weathermode].texture_index ]; target_weather_texture = NULL; cloud_weather_blend_factor = 0; cloud_weather_one_minus_blend_factor = 1.0; } else { current_weather_texture = system_textures[ cloud_textures[current_weathermode].texture_index ]; target_weather_texture = system_textures[ cloud_textures[target_weathermode].texture_index ]; } } else { current_weather_texture = system_textures[ cloud_textures[current_weathermode].texture_index ]; target_weather_texture = NULL; cloud_weather_blend_factor = 0; cloud_weather_one_minus_blend_factor = 1.0; } // // Now bias the blend factors, to take into account the transparency of each texture // cloud_weather_one_minus_blend_factor *= active_3d_environment->cloud_light.light_colour.alpha; cloud_weather_blend_factor *= active_3d_environment->cloud_light.light_colour.alpha; // // Get the sector the visual_3d_vp is currently in // get_cloud_3d_sector ( visual_3d_vp->x, visual_3d_vp->z, &visual_sector_x, &visual_sector_z ); minimum_sector_x = visual_sector_x - cloud_3d_sector_scan_radius; minimum_sector_z = visual_sector_z - cloud_3d_sector_scan_radius; maximum_sector_x = visual_sector_x + cloud_3d_sector_scan_radius; maximum_sector_z = visual_sector_z + cloud_3d_sector_scan_radius; initial_sector_x_offset = minimum_sector_x * CLOUD_3D_SECTOR_SIDE_LENGTH; initial_sector_z_offset = minimum_sector_z * CLOUD_3D_SECTOR_SIDE_LENGTH; current_sector_z_offset = initial_sector_z_offset; for ( current_sector_z = minimum_sector_z; current_sector_z < maximum_sector_z; current_sector_z++ ) { current_sector_x_offset = initial_sector_x_offset; for ( current_sector_x = minimum_sector_x; current_sector_x < maximum_sector_x; current_sector_x++ ) { vec3d sector_centre, sector_relative_centre; scene_slot_drawing_list *sorting_slot; 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_relative_centre.z = ( ( sector_centre.x - visual_3d_vp->x ) * visual_3d_vp->zv.x + ( sector_centre.y - visual_3d_vp->y ) * visual_3d_vp->zv.y + ( sector_centre.z - visual_3d_vp->z ) * visual_3d_vp->zv.z ); if ( ( sector_relative_centre.z + ( CLOUD_3D_SECTOR_SIDE_LENGTH * 1.4142 ) ) < clip_hither ) { // // Cloud sector is totally behind the view // } else { unsigned int outcode, outcode1, outcode2; float x_minimum_offset, x_maximum_offset, z_minimum_offset, z_maximum_offset; x_minimum_offset = current_sector_x_offset; x_maximum_offset = current_sector_x_offset + CLOUD_3D_SECTOR_SIDE_LENGTH; z_minimum_offset = current_sector_z_offset; z_maximum_offset = current_sector_z_offset + CLOUD_3D_SECTOR_SIDE_LENGTH; outcode = get_3d_point_outcodes ( x_minimum_offset, cloud_3d_base_height, z_minimum_offset ); outcode1 = outcode; outcode2 = outcode; outcode = get_3d_point_outcodes ( x_minimum_offset, cloud_3d_base_height, z_maximum_offset ); outcode1 |= outcode; outcode2 &= outcode; outcode = get_3d_point_outcodes ( x_maximum_offset, cloud_3d_base_height, z_minimum_offset ); outcode1 |= outcode; outcode2 &= outcode; outcode = get_3d_point_outcodes ( x_maximum_offset, cloud_3d_base_height, z_maximum_offset ); outcode1 |= outcode; outcode2 &= outcode; // if ( outcode2 == 0 ) { sorting_slot = get_3d_scene_slot (); if ( sorting_slot ) { sorting_slot->type = OBJECT_3D_DRAW_TYPE_CLOUD_SECTOR; // // Use the integer representation of the float value // sector_relative_centre.z += 32768; sorting_slot->z = *( ( int * ) §or_relative_centre.z ); sorting_slot->cloud_sector.x = current_sector_x; sorting_slot->cloud_sector.z = current_sector_z; insert_middle_scene_slot_into_3d_scene ( sorting_slot ); } else { debug_log ( "Run out of object slots!" ); } } } current_sector_x_offset += CLOUD_3D_SECTOR_SIDE_LENGTH; } current_sector_z_offset += CLOUD_3D_SECTOR_SIDE_LENGTH; } }
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 ); } } }
int insert_zbiased_polyline_into_3d_scene ( int number_of_points, float zbias, int lit, rgb_colour colour, vec3d *points ) { polyline_point *rotated_points; int count, visible; real_colour polyline_colour; if ( exclusive_3d_instance ) { return ( FALSE ); } // // First, ensure we have enough memory // if ( number_of_3d_polyline_points + number_of_points > MAX_POLYLINE_POINTS ) { return ( FALSE ); } if ( number_of_3d_polylines + 1 > MAX_POLYLINES ) { return ( FALSE ); } // // First, copy the ROTATED point data over to an internal 3d visual buffer ( checking for visibility ) // visible = FALSE; rotated_points = &polyline_points[number_of_3d_polyline_points]; // // Copy the colour value // polyline_colour.red = colour.r; polyline_colour.green = colour.g; polyline_colour.blue = colour.b; polyline_colour.alpha = 0; if ( rotated_points ) { visible = transform_3d_polyline_points ( number_of_points, points, rotated_points ); if ( visible ) { polyline_header *polyline; // // Some part ( or all ) of the polyline is visible // polyline = &polyline_headers[number_of_3d_polylines]; number_of_3d_polylines++; number_of_3d_polyline_points += number_of_points; polyline->number_of_points = number_of_points; polyline->points = rotated_points; polyline->colour = polyline_colour; polyline->lit = lit; // // Now insert each segment dependant on it being visible or not. // for ( count = 0; count < ( number_of_points - 1 ); count++ ) { if ( ( rotated_points[count].transformed_point.z > clip_hither ) || ( rotated_points[count+1].transformed_point.z > clip_hither ) ) { scene_slot_drawing_list *buffer; float average_z; average_z = ( rotated_points[count].transformed_point.z + rotated_points[count+1].transformed_point.z ) / 2.0; average_z += zbias; buffer = get_3d_scene_slot (); if ( buffer ) { buffer->type = OBJECT_3D_DRAW_TYPE_POLYLINE; buffer->z = *( ( int * ) &average_z ); buffer->polyline.polyline = polyline; buffer->polyline.segment = count; if ( points[count].y > middle_scene_slot_height ) { insert_high_zbuffered_scene_slot_into_3d_scene ( buffer ); } else { insert_low_zbuffered_scene_slot_into_3d_scene ( buffer ); } } } } } } return ( TRUE ); }