void draw_3d_smoke_trail ( struct OBJECT_3D_SMOKE_TRAIL *smoke ) { vertex points[6]; int segment, count, outcode, outcode2; segment = smoke->segment; set_d3d_fog_face_intensity ( 255 ); // // Copy the 3d coordinates into a local quad // points[0].x = smoke->trail->points[segment].point1.x * active_3d_environment->screen_i_scale; points[0].y = smoke->trail->points[segment].point1.y * active_3d_environment->screen_j_scale; points[0].z = smoke->trail->points[segment].point1.z; points[0].u = smoke->trail->points[segment].texture_u; points[1].x = smoke->trail->points[segment].centre.x * active_3d_environment->screen_i_scale; points[1].y = smoke->trail->points[segment].centre.y * active_3d_environment->screen_j_scale; points[1].z = smoke->trail->points[segment].centre.z; points[1].u = smoke->trail->points[segment].texture_u; points[2].x = smoke->trail->points[segment].point2.x * active_3d_environment->screen_i_scale; points[2].y = smoke->trail->points[segment].point2.y * active_3d_environment->screen_j_scale; points[2].z = smoke->trail->points[segment].point2.z; points[2].u = smoke->trail->points[segment].texture_u; points[3].x = smoke->trail->points[segment+1].point1.x * active_3d_environment->screen_i_scale; points[3].y = smoke->trail->points[segment+1].point1.y * active_3d_environment->screen_j_scale; points[3].z = smoke->trail->points[segment+1].point1.z; points[3].u = smoke->trail->points[segment+1].texture_u; points[4].x = smoke->trail->points[segment+1].centre.x * active_3d_environment->screen_i_scale; points[4].y = smoke->trail->points[segment+1].centre.y * active_3d_environment->screen_j_scale; points[4].z = smoke->trail->points[segment+1].centre.z; points[4].u = smoke->trail->points[segment+1].texture_u; points[5].x = smoke->trail->points[segment+1].point2.x * active_3d_environment->screen_i_scale; points[5].y = smoke->trail->points[segment+1].point2.y * active_3d_environment->screen_j_scale; points[5].z = smoke->trail->points[segment+1].point2.z; points[5].u = smoke->trail->points[segment+1].texture_u; // // Transform the points and outcode the quad at the same time // outcode = 0; outcode2 = CLIP_HITHER | CLIP_LEFT | CLIP_RIGHT | CLIP_TOP | CLIP_BOTTOM; for ( count = 0; count < 6; count++ ) { if ( *( ( int * ) &points[count].z ) >= *( ( int * ) &clip_hither ) ) { float oxmax, oxmin, oymax, oymin, q, i, j; int ixmax, ixmin, iymax, iymin; q = 1.0 / points[count].z; i = ( points[count].x * q ); j = ( points[count].y * q ); j = active_3d_environment->y_origin - j; i = active_3d_environment->x_origin + i; points[count].j = j; points[count].i = i; points[count].q = q; oxmax = active_viewport.x_max - i; oxmin = i - active_viewport.x_min; oymax = active_viewport.y_max - j; oymin = j - active_viewport.y_min; ixmax = *( ( int * ) &oxmax ); ixmin = *( ( int * ) &oxmin ); iymax = *( ( int * ) &oymax ); iymin = *( ( int * ) &oymin ); points[count].outcode = generate_lookup_outcode ( ixmin, iymin, ixmax, iymax ); } else { points[count].outcode = CLIP_HITHER; } outcode |= points[count].outcode; outcode2 &= points[count].outcode; } if ( outcode2 == 0 ) { points[0].u = smoke->trail->points[segment].texture_u; points[0].v = 0; points[0].colour = smoke->trail->points[segment].colour.colour; points[3].u = smoke->trail->points[segment+1].texture_u; points[3].v = 0; points[3].colour = smoke->trail->points[segment+1].colour.colour; points[4].u = smoke->trail->points[segment+1].texture_u; points[4].v = 0.5; points[4].colour = smoke->trail->points[segment+1].colour.colour; points[0].next_vertex = &points[3]; points[3].next_vertex = &points[4]; points[4].next_vertex = NULL; render_smoke_trail_polygon ( &points[0], smoke->trail->texture, smoke->trail->additive ); points[0].u = smoke->trail->points[segment].texture_u; points[0].v = 0; points[0].colour = smoke->trail->points[segment].colour.colour; points[1].u = smoke->trail->points[segment].texture_u; points[1].v = 0.5; points[1].colour = smoke->trail->points[segment].colour.colour; points[4].u = smoke->trail->points[segment+1].texture_u; points[4].v = 0.5; points[4].colour = smoke->trail->points[segment+1].colour.colour; points[0].next_vertex = &points[4]; points[4].next_vertex = &points[1]; points[1].next_vertex = NULL; render_smoke_trail_polygon ( &points[0], smoke->trail->texture, smoke->trail->additive ); points[1].u = smoke->trail->points[segment].texture_u; points[1].v = 0.5; points[1].colour = smoke->trail->points[segment].colour.colour; points[2].u = smoke->trail->points[segment].texture_u; points[2].v = 1; points[2].colour = smoke->trail->points[segment].colour.colour; points[4].u = smoke->trail->points[segment+1].texture_u; points[4].v = 0.5; points[4].colour = smoke->trail->points[segment+1].colour.colour; points[1].next_vertex = &points[4]; points[4].next_vertex = &points[2]; points[2].next_vertex = NULL; render_smoke_trail_polygon ( &points[1], smoke->trail->texture, smoke->trail->additive ); points[2].u = smoke->trail->points[segment].texture_u; points[2].v = 1; points[2].colour = smoke->trail->points[segment].colour.colour; points[4].u = smoke->trail->points[segment+1].texture_u; points[4].v = 0.5; points[4].colour = smoke->trail->points[segment+1].colour.colour; points[5].u = smoke->trail->points[segment+1].texture_u; points[5].v = 1; points[5].colour = smoke->trail->points[segment+1].colour.colour; points[2].next_vertex = &points[4]; points[4].next_vertex = &points[5]; points[5].next_vertex = NULL; render_smoke_trail_polygon ( &points[2], smoke->trail->texture, smoke->trail->additive ); } }
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 ); } } }
void draw_3d_polyline ( struct OBJECT_3D_POLYLINE *polyline ) { int segment, outcode; float average_distance; polyline_point *points; vertex *line; real_colour colour; // // Connect the two vertices up // points = polyline->polyline->points; segment = polyline->segment; points[segment].transformed_point.next_vertex = &points[segment+1].transformed_point; points[segment+1].transformed_point.next_vertex = NULL; outcode = points[segment].transformed_point.outcode; outcode |= points[segment+1].transformed_point.outcode; // // Calculate the average distance of the polyline // average_distance = ( points[segment].transformed_point.z + points[segment+1].transformed_point.z ) / 2.0; // // Set the fog value for this polyline // { float fog_intensity; int ifog_intensity; fog_intensity = get_fog_distance_value ( average_distance ); convert_float_to_int ( fog_intensity, &ifog_intensity ); set_d3d_fog_face_intensity ( ifog_intensity ); } // // Calculate the lighting if required // if ( polyline->polyline->lit ) { vec3d point1, point2, plane_normal, line_normal; float red, green, blue, ndotn, ndotp1, ndotcamera, direction_factor; light_3d_source *this_light; int ired, igreen, iblue; // // This bit is a work of a genius matey! // point1 = points[segment].world_point; point2 = points[segment+1].world_point; point1.x = ( ( point2.x - point1.x ) / 2 ) + point1.x; point1.y = ( ( point2.y - point1.y ) / 2 ) + point1.y; point1.z = ( ( point2.z - point1.z ) / 2 ) + point1.z; plane_normal.x = point2.x - point1.x; plane_normal.y = point2.y - point1.y; plane_normal.z = point2.z - point1.z; ndotn = ( ( plane_normal.x * plane_normal.x ) + ( plane_normal.y * plane_normal.y ) + ( plane_normal.z * plane_normal.z ) ); ndotp1 = ( ( point1.x * plane_normal.x ) + ( point1.y * plane_normal.y ) + ( point1.z * plane_normal.z ) ); ndotcamera = ( ( visual_3d_vp->x * plane_normal.x ) + ( visual_3d_vp->y * plane_normal.y ) + ( visual_3d_vp->z * plane_normal.z ) ); direction_factor = ( ( ndotp1 - ndotcamera ) / ndotn ); line_normal.x = visual_3d_vp->x + direction_factor * ( plane_normal.x ); line_normal.y = visual_3d_vp->y + direction_factor * ( plane_normal.y ); line_normal.z = visual_3d_vp->z + direction_factor * ( plane_normal.z ); line_normal.x = line_normal.x - point1.x; line_normal.y = line_normal.y - point1.y; line_normal.z = line_normal.z - point1.z; normalise_any_3d_vector ( &line_normal ); this_light = current_3d_lights; red = ambient_3d_light.colour.red; green = ambient_3d_light.colour.green; blue = ambient_3d_light.colour.blue; while ( this_light ) { float intensity; intensity = ( ( line_normal.x * this_light->lx ) + ( line_normal.y * this_light->ly ) + ( line_normal.z * this_light->lz ) ); if ( ( *( int * ) &intensity ) > ( *( int * ) &float_value_zero ) ) { red += intensity * this_light->colour.red; green += intensity * this_light->colour.green; blue += intensity * this_light->colour.blue; } this_light = this_light->succ; } red = bound ( red, 0, 1 ); green = bound ( green, 0, 1 ); blue = bound ( blue, 0, 1 ); red *= polyline->polyline->colour.red; green *= polyline->polyline->colour.green; blue *= polyline->polyline->colour.blue; red += FLOAT_FLOAT_FACTOR; green += FLOAT_FLOAT_FACTOR; blue += FLOAT_FLOAT_FACTOR; ired = ( *( int * ) &red ) - INTEGER_FLOAT_FACTOR; igreen = ( *( int * ) &green ) - INTEGER_FLOAT_FACTOR; iblue = ( *( int * ) &blue ) - INTEGER_FLOAT_FACTOR; colour.red = ired; colour.green = igreen; colour.blue = iblue; colour.alpha = 0; } else { colour = polyline->polyline->colour; } // // Go through all the vertices, creating lines to draw, then render them. // line = &points[segment].transformed_point; clip_3d_coord = 0; if ( outcode & CLIP_HITHER ) { line = hither_clip_3d_polygon ( line, &outcode ); } if ( line ) { if ( outcode ) { line = clip_3d_polygon ( line, outcode ); } if ( line ) { set_d3d_plain_renderstate (); draw_wbuffered_plain_line ( line, colour ); } } }
void draw_z_sorted_3d_object ( object_3d_instance *obj ) { int object_number, draw_sub_objects, count, temp, num_faces; object_3d_face *faces; light_3d_source *this_light, *prev_light, *light_ptr, *light; vec3d *pos; vec3d object_pos, object_unit_pos; polygon_buffer *translucent_buffer; object_3d_scene_database_entry *scene; // // Set the scene pointer // scene = &objects_3d_scene_database[obj->object_number]; // // Set up the texture animations for this object. // initialise_object_texture_animations ( obj ); // // Set up the object drawing global variables // object_3d_points_current_base = 0; object_3d_object_current_base = 0; object_3d_light_3d_current_base = 0; // // Set the object dissolve variables // current_object_3d_dissolve_factor = 1.0; current_object_3d_dissolve_value = 255; // // Turn lightmaps off // current_object_3d_light_maps_enabled = FALSE; // // Calculate the object's position relative to the view. // pos = &obj->view_position; { float fog_intensity; int ifog_intensity; fog_intensity = get_fog_distance_value ( pos->z ); asm_convert_float_to_int ( fog_intensity, &ifog_intensity ); set_d3d_fog_face_intensity ( ifog_intensity ); } // // Set the main objects' scaling values // object_3d_scale.x = obj->relative_scale.x; object_3d_scale.y = obj->relative_scale.y; object_3d_scale.z = obj->relative_scale.z; // // Calculate the object's rotation matrix, to transform its 3d points relative to the view. // rotation_3d[0][0] = ( obj->vp.xv.x * visual_3d_vp->xv.x + obj->vp.xv.y * visual_3d_vp->xv.y + obj->vp.xv.z * visual_3d_vp->xv.z ); rotation_3d[0][1] = ( obj->vp.xv.x * visual_3d_vp->yv.x + obj->vp.xv.y * visual_3d_vp->yv.y + obj->vp.xv.z * visual_3d_vp->yv.z ); rotation_3d[0][2] = ( obj->vp.xv.x * visual_3d_vp->zv.x + obj->vp.xv.y * visual_3d_vp->zv.y + obj->vp.xv.z * visual_3d_vp->zv.z ); rotation_3d[1][0] = ( obj->vp.yv.x * visual_3d_vp->xv.x + obj->vp.yv.y * visual_3d_vp->xv.y + obj->vp.yv.z * visual_3d_vp->xv.z ); rotation_3d[1][1] = ( obj->vp.yv.x * visual_3d_vp->yv.x + obj->vp.yv.y * visual_3d_vp->yv.y + obj->vp.yv.z * visual_3d_vp->yv.z ); rotation_3d[1][2] = ( obj->vp.yv.x * visual_3d_vp->zv.x + obj->vp.yv.y * visual_3d_vp->zv.y + obj->vp.yv.z * visual_3d_vp->zv.z ); rotation_3d[2][0] = ( obj->vp.zv.x * visual_3d_vp->xv.x + obj->vp.zv.y * visual_3d_vp->xv.y + obj->vp.zv.z * visual_3d_vp->xv.z ); rotation_3d[2][1] = ( obj->vp.zv.x * visual_3d_vp->yv.x + obj->vp.zv.y * visual_3d_vp->yv.y + obj->vp.zv.z * visual_3d_vp->yv.z ); rotation_3d[2][2] = ( obj->vp.zv.x * visual_3d_vp->zv.x + obj->vp.zv.y * visual_3d_vp->zv.y + obj->vp.zv.z * visual_3d_vp->zv.z ); rotation_3d[0][0] *= object_3d_scale.x; rotation_3d[1][0] *= object_3d_scale.y; rotation_3d[2][0] *= object_3d_scale.z; rotation_3d[0][1] *= object_3d_scale.x; rotation_3d[1][1] *= object_3d_scale.y; rotation_3d[2][1] *= object_3d_scale.z; rotation_3d[0][2] *= object_3d_scale.x; rotation_3d[1][2] *= object_3d_scale.y; rotation_3d[2][2] *= object_3d_scale.z; // // Calculate the vector from the object to the viewpoint, in the object's view system // { float x, y, z; x = ( ( visual_3d_vp->x - obj->vp.x ) * obj->vp.xv.x ); x += ( ( visual_3d_vp->y - obj->vp.y ) * obj->vp.xv.y ); x += ( ( visual_3d_vp->z - obj->vp.z ) * obj->vp.xv.z ); y = ( ( visual_3d_vp->x - obj->vp.x ) * obj->vp.yv.x ); y += ( ( visual_3d_vp->y - obj->vp.y ) * obj->vp.yv.y ); y += ( ( visual_3d_vp->z - obj->vp.z ) * obj->vp.yv.z ); z = ( ( visual_3d_vp->x - obj->vp.x ) * obj->vp.zv.x ); z += ( ( visual_3d_vp->y - obj->vp.y ) * obj->vp.zv.y ); z += ( ( visual_3d_vp->z - obj->vp.z ) * obj->vp.zv.z ); object_pos.x = x; object_pos.y = y; object_pos.z = z; object_unit_pos.x = -object_pos.x; object_unit_pos.y = -object_pos.y; object_unit_pos.z = -object_pos.z; normalise_any_3d_vector ( &object_unit_pos ); } // // Get the object number // object_number = get_object_approximation_number ( obj->object_number, pos->z, &draw_sub_objects ); // // Rotate the light source vector to be relative to the object. // light_ptr = current_3d_lights; prev_light = NULL; light = NULL; if ( light_ptr ) { light = &light_3d_array[object_3d_light_3d_current_base]; while ( light_ptr ) { float lx, ly, lz; if ( light_ptr->type == LIGHT_3D_TYPE_POINT ) { vec3d vector; float distance; // // Work out the distance from object to light source // vector.x = - light_ptr->light_position.x + obj->vp.x; vector.y = - light_ptr->light_position.y + obj->vp.y; vector.z = - light_ptr->light_position.z + obj->vp.z; lx = vector.x * vector.x; ly = vector.y * vector.y; lz = vector.z * vector.z; distance = ( lx + ly + lz ); if ( distance < light_ptr->radius ) { distance = 1 - ( distance / light_ptr->radius ); this_light = &light_3d_array[object_3d_light_3d_current_base]; object_3d_light_3d_current_base++; if ( prev_light ) { prev_light->succ = this_light; } this_light->pred = prev_light; this_light->succ = NULL; this_light->colour.red = light_ptr->colour.red * distance; this_light->colour.green = light_ptr->colour.green * distance; this_light->colour.blue = light_ptr->colour.blue * distance; // this_light->colour.intensity = light_ptr->colour.intensity * distance; normalise_any_3d_vector ( &vector ); lx = ( vector.x * obj->vp.attitude[0][0] ); lx += ( vector.y * obj->vp.attitude[0][1] ); lx += ( vector.z * obj->vp.attitude[0][2] ); ly = ( vector.x * obj->vp.attitude[1][0] ); ly += ( vector.y * obj->vp.attitude[1][1] ); ly += ( vector.z * obj->vp.attitude[1][2] ); lz = ( vector.x * obj->vp.attitude[2][0] ); lz += ( vector.y * obj->vp.attitude[2][1] ); lz += ( vector.z * obj->vp.attitude[2][2] ); this_light->lx = lx; this_light->ly = ly; this_light->lz = lz; // // Generate a highlight vector // this_light->highlight_vector.x = ( lx - object_unit_pos.x ); this_light->highlight_vector.y = ( ly - object_unit_pos.y ); this_light->highlight_vector.z = ( lz - object_unit_pos.z ); normalise_any_3d_vector ( &this_light->highlight_vector ); prev_light = this_light; } } else { this_light = &light_3d_array[object_3d_light_3d_current_base]; object_3d_light_3d_current_base++; if ( prev_light ) { prev_light->succ = this_light; } this_light->pred = prev_light; this_light->succ = NULL; this_light->colour.red = light_ptr->colour.red; this_light->colour.green = light_ptr->colour.green; this_light->colour.blue = light_ptr->colour.blue; // this_light->colour.intensity = light_ptr->colour.intensity; lx = ( light_ptr->lx * obj->vp.attitude[0][0] ); lx += ( light_ptr->ly * obj->vp.attitude[0][1] ); lx += ( light_ptr->lz * obj->vp.attitude[0][2] ); ly = ( light_ptr->lx * obj->vp.attitude[1][0] ); ly += ( light_ptr->ly * obj->vp.attitude[1][1] ); ly += ( light_ptr->lz * obj->vp.attitude[1][2] ); lz = ( light_ptr->lx * obj->vp.attitude[2][0] ); lz += ( light_ptr->ly * obj->vp.attitude[2][1] ); lz += ( light_ptr->lz * obj->vp.attitude[2][2] ); this_light->lx = lx; this_light->ly = ly; this_light->lz = lz; // // Generate a highlight vector // this_light->highlight_vector.x = ( lx - object_unit_pos.x ); this_light->highlight_vector.y = ( ly - object_unit_pos.y ); this_light->highlight_vector.z = ( lz - object_unit_pos.z ); normalise_any_3d_vector ( &this_light->highlight_vector ); prev_light = this_light; } light_ptr = light_ptr->succ; } } // // Set up this objects' object info structure // object_3d_object_base[object_3d_object_current_base].lights = light; object_3d_object_base[object_3d_object_current_base].points_base = object_3d_points_current_base; object_3d_object_base[object_3d_object_current_base].object_number = object_number; current_object_3d_object_base = &object_3d_object_base[object_3d_object_current_base]; // // Set up the face sorting variables // num_faces = objects_3d_data[object_number].number_of_faces; reset_3d_face_sorting (); // // Insert this objects' faces into the sorted list. // faces = objects_3d_data[object_number].faces; if ( objects_3d_data[object_number].number_of_points ) { object_short_3d_point *object_points; point_3d_plain_reference *plain_point_list; face_surface_description *surfaces; int surface, surface_face_count, point_reference_index, gouraud_point_index, face_normal_index, texture_point_index; surface = 0; point_reference_index = 0; gouraud_point_index = 0; face_normal_index = 0; texture_point_index = 0; object_points = objects_3d_data[object_number].points; plain_point_list = NULL; //objects_3d_data[object_number].object_faces_point_plain_list; surfaces = objects_3d_data[object_number].surfaces; surface_face_count = surfaces[surface].number_of_faces; for ( count = num_faces; count > 0; count-- ) { if ( surface_face_count == 0 ) { surface++; surface_face_count = surfaces[surface].number_of_faces; } if ( faces->number_of_points > 2 ) { float tmp; vec3d true_depth_point; { point_3d_plain_reference *point_list; point_list = &plain_point_list[point_reference_index]; true_depth_point.x = object_points[point_list[0].point].x; true_depth_point.y = object_points[point_list[0].point].y; true_depth_point.z = object_points[point_list[0].point].z; true_depth_point.x += object_points[point_list[1].point].x; true_depth_point.y += object_points[point_list[1].point].y; true_depth_point.z += object_points[point_list[1].point].z; true_depth_point.x += object_points[point_list[2].point].x; true_depth_point.y += object_points[point_list[2].point].y; true_depth_point.z += object_points[point_list[2].point].z; point_list += 3; for ( temp = faces->number_of_points; temp > 3; temp-- ) { true_depth_point.x += object_points[point_list->point].x; true_depth_point.y += object_points[point_list->point].y; true_depth_point.z += object_points[point_list->point].z; point_list++; } tmp = true_depth_point.x * rotation_3d[0][2]; tmp += true_depth_point.y * rotation_3d[1][2]; tmp += true_depth_point.z * rotation_3d[2][2]; tmp *= one_over_table[faces->number_of_points]; tmp += pos->z; // // Just use the binary representation of the float z value for z-sorting // insert_z_sorted_3d_face ( faces, *( ( int * ) &tmp ), surface, point_reference_index, gouraud_point_index, face_normal_index, texture_point_index, current_object_3d_object_base ); // insert_z_sorted_3d_face ( faces, *( ( int * ) &tmp ), surface, point_reference_index, gouraud_point_index, 0, texture_point_index, this_object_3d_info ); } } else { /* float tmp; point_3d_plain_reference *point_list; point_list = &plain_point_list[faces->point_reference_index]; depth_point = &object_points[point_list->point]; tmp = pos->z; point_list++; tmp += depth_point->x * rotation_3d[0][2]; tmp += depth_point->y * rotation_3d[1][2]; tmp += depth_point->z * rotation_3d[2][2]; // // Just use the binary representation of the float z value for z-sorting // insert_z_sorted_3d_face ( faces, * ( ( int * ) &tmp ), this_object_3d_info ); */ } point_reference_index += faces->number_of_points; if ( surfaces[surface].textured ) { texture_point_index += faces->number_of_points; } if ( surfaces[surface].smoothed ) { gouraud_point_index += faces->number_of_points; } if ( faces->number_of_points >= 3 ) { face_normal_index++; } faces++; surface_face_count--; } } faces = objects_3d_data[object_number].faces; // // Transform the object's shape data // if ( objects_3d_data[object_number].number_of_points ) { illuminate_3d_object ( &objects_3d_data[object_number], pos, light, NULL, object_3d_points_current_base ); transform_3d_object ( &objects_3d_data[object_number], pos, light, NULL, object_3d_points_current_base); } // // Adjust the memory pointers for any sub objects // object_3d_object_current_base ++; object_3d_points_current_base += objects_3d_data[object_number].number_of_points; // // Recurse down any sub objects // if ( ( draw_sub_objects ) && ( scene->number_of_sub_objects != 0 ) ) { for ( count = ( scene->number_of_sub_objects -1 ); count >= 0; count-- ) { if ( obj->sub_objects[count].visible_object ) { draw_z_sorted_sub_object ( &obj->sub_objects[count], &scene->sub_objects[count], &obj->vp, current_object_3d_object_base->lights, pos ); } } } // // Start sorting the translucent polygons // translucent_buffer = get_translucent_sorted_polygon_buffer (); // // Ok, now we're ready to draw the actual faces. // render_3d_object_faces (); if ( finalise_translucent_sorted_polygon_buffer ( translucent_buffer ) ) { // set_d3d_transparency_on (); draw_polygon_buffer ( translucent_buffer ); // set_d3d_transparency_off (); } }
void draw_3d_terrain_tree ( object_3d_instance *obj ) { int object_number; object_3d_info *this_object_3d_info; light_3d_source *this_light, *prev_light, *light_ptr, *light; vec3d *pos; vec3d object_camera_position, object_pos; // // Set up the object drawing global variables // object_3d_points_current_base = 0; object_3d_object_current_base = 0; object_3d_light_3d_current_base = 0; // // Calculate the object's position relative to the view. // pos = &obj->rel_vp.position; { float fog_intensity; int ifog_intensity; fog_intensity = get_fog_distance_value ( pos->z ); convert_float_to_int ( fog_intensity, &ifog_intensity ); set_d3d_fog_face_intensity ( ifog_intensity ); } // // Set the main objects' scaling values // object_3d_scale.x = obj->relative_scale.x; object_3d_scale.y = obj->relative_scale.y; object_3d_scale.z = obj->relative_scale.z; // // Calculate the object's rotation matrix, to transform its 3d points relative to the view. // rotation_3d[0][0] = ( obj->vp.xv.x * visual_3d_vp->xv.x + obj->vp.xv.y * visual_3d_vp->xv.y + obj->vp.xv.z * visual_3d_vp->xv.z ); rotation_3d[0][1] = ( obj->vp.xv.x * visual_3d_vp->yv.x + obj->vp.xv.y * visual_3d_vp->yv.y + obj->vp.xv.z * visual_3d_vp->yv.z ); rotation_3d[0][2] = ( obj->vp.xv.x * visual_3d_vp->zv.x + obj->vp.xv.y * visual_3d_vp->zv.y + obj->vp.xv.z * visual_3d_vp->zv.z ); rotation_3d[1][0] = ( obj->vp.yv.x * visual_3d_vp->xv.x + obj->vp.yv.y * visual_3d_vp->xv.y + obj->vp.yv.z * visual_3d_vp->xv.z ); rotation_3d[1][1] = ( obj->vp.yv.x * visual_3d_vp->yv.x + obj->vp.yv.y * visual_3d_vp->yv.y + obj->vp.yv.z * visual_3d_vp->yv.z ); rotation_3d[1][2] = ( obj->vp.yv.x * visual_3d_vp->zv.x + obj->vp.yv.y * visual_3d_vp->zv.y + obj->vp.yv.z * visual_3d_vp->zv.z ); rotation_3d[2][0] = ( obj->vp.zv.x * visual_3d_vp->xv.x + obj->vp.zv.y * visual_3d_vp->xv.y + obj->vp.zv.z * visual_3d_vp->xv.z ); rotation_3d[2][1] = ( obj->vp.zv.x * visual_3d_vp->yv.x + obj->vp.zv.y * visual_3d_vp->yv.y + obj->vp.zv.z * visual_3d_vp->yv.z ); rotation_3d[2][2] = ( obj->vp.zv.x * visual_3d_vp->zv.x + obj->vp.zv.y * visual_3d_vp->zv.y + obj->vp.zv.z * visual_3d_vp->zv.z ); rotation_3d[0][0] *= object_3d_scale.x; rotation_3d[1][0] *= object_3d_scale.y; rotation_3d[2][0] *= object_3d_scale.z; rotation_3d[0][1] *= object_3d_scale.x; rotation_3d[1][1] *= object_3d_scale.y; rotation_3d[2][1] *= object_3d_scale.z; rotation_3d[0][2] *= object_3d_scale.x; rotation_3d[1][2] *= object_3d_scale.y; rotation_3d[2][2] *= object_3d_scale.z; // // Calculate the vector from the object to the viewpoint, in the object's view system // { float x, y, z; x = ( ( visual_3d_vp->x - obj->vp.x ) * obj->vp.xv.x ); x += ( ( visual_3d_vp->y - obj->vp.y ) * obj->vp.xv.y ); x += ( ( visual_3d_vp->z - obj->vp.z ) * obj->vp.xv.z ); y = ( ( visual_3d_vp->x - obj->vp.x ) * obj->vp.yv.x ); y += ( ( visual_3d_vp->y - obj->vp.y ) * obj->vp.yv.y ); y += ( ( visual_3d_vp->z - obj->vp.z ) * obj->vp.yv.z ); z = ( ( visual_3d_vp->x - obj->vp.x ) * obj->vp.zv.x ); z += ( ( visual_3d_vp->y - obj->vp.y ) * obj->vp.zv.y ); z += ( ( visual_3d_vp->z - obj->vp.z ) * obj->vp.zv.z ); object_pos.x = x; object_pos.y = y; object_pos.z = z; } // // Get the object number // object_number = get_object_approximation_number ( obj->object_number, pos->z, &object_3d_approximation_level ); // // Rotate the light source vector to be relative to the object. // light_ptr = current_3d_lights; prev_light = NULL; light = NULL; if ( light_ptr ) { light = &light_3d_array[object_3d_light_3d_current_base]; while ( light_ptr ) { float lx, ly, lz; if ( light_ptr->type == LIGHT_3D_TYPE_POINT ) { vec3d vector; float distance; // // Work out the distance from object to light source // vector.x = - light_ptr->light_position.x + obj->vp.x; vector.y = - light_ptr->light_position.y + obj->vp.y; vector.z = - light_ptr->light_position.z + obj->vp.z; lx = vector.x * vector.x; ly = vector.y * vector.y; lz = vector.z * vector.z; distance = ( lx + ly + lz ); if ( distance < light_ptr->radius ) { distance = 1 - ( distance / light_ptr->radius ); this_light = &light_3d_array[object_3d_light_3d_current_base]; object_3d_light_3d_current_base++; if ( prev_light ) { prev_light->succ = this_light; } this_light->pred = prev_light; this_light->succ = NULL; this_light->type = light_ptr->type; this_light->colour.red = light_ptr->colour.red * distance; this_light->colour.green = light_ptr->colour.green * distance; this_light->colour.blue = light_ptr->colour.blue * distance; // this_light->colour.intensity = light_ptr->colour.intensity * distance; normalise_3d_vector ( &vector ); lx = ( vector.x * obj->vp.attitude[0][0] ); lx += ( vector.y * obj->vp.attitude[0][1] ); lx += ( vector.z * obj->vp.attitude[0][2] ); ly = ( vector.x * obj->vp.attitude[1][0] ); ly += ( vector.y * obj->vp.attitude[1][1] ); ly += ( vector.z * obj->vp.attitude[1][2] ); lz = ( vector.x * obj->vp.attitude[2][0] ); lz += ( vector.y * obj->vp.attitude[2][1] ); lz += ( vector.z * obj->vp.attitude[2][2] ); this_light->lx = lx; this_light->ly = ly; this_light->lz = lz; prev_light = this_light; } } else { this_light = &light_3d_array[object_3d_light_3d_current_base]; object_3d_light_3d_current_base++; if ( prev_light ) { prev_light->succ = this_light; } this_light->pred = prev_light; this_light->succ = NULL; this_light->type = light_ptr->type; this_light->colour.red = light_ptr->colour.red; this_light->colour.green = light_ptr->colour.green; this_light->colour.blue = light_ptr->colour.blue; // this_light->colour.intensity = light_ptr->colour.intensity; lx = ( light_ptr->lx * obj->vp.attitude[0][0] ); lx += ( light_ptr->ly * obj->vp.attitude[0][1] ); lx += ( light_ptr->lz * obj->vp.attitude[0][2] ); ly = ( light_ptr->lx * obj->vp.attitude[1][0] ); ly += ( light_ptr->ly * obj->vp.attitude[1][1] ); ly += ( light_ptr->lz * obj->vp.attitude[1][2] ); lz = ( light_ptr->lx * obj->vp.attitude[2][0] ); lz += ( light_ptr->ly * obj->vp.attitude[2][1] ); lz += ( light_ptr->lz * obj->vp.attitude[2][2] ); this_light->lx = lx; this_light->ly = ly; this_light->lz = lz; prev_light = this_light; } light_ptr = light_ptr->succ; } } { vec3d rel_pos; // // Calculate the relative camera position in the object viewspace // rel_pos.x = visual_3d_vp->x - obj->vp.x; rel_pos.y = visual_3d_vp->y - obj->vp.y; rel_pos.z = visual_3d_vp->z - obj->vp.z; object_camera_position.x = ( rel_pos.x * obj->vp.attitude[0][0] + rel_pos.y * obj->vp.attitude[1][0] + rel_pos.z * obj->vp.attitude[2][0] ); object_camera_position.y = ( rel_pos.x * obj->vp.attitude[0][1] + rel_pos.y * obj->vp.attitude[1][1] + rel_pos.z * obj->vp.attitude[2][1] ); object_camera_position.z = ( rel_pos.x * obj->vp.attitude[0][2] + rel_pos.y * obj->vp.attitude[1][2] + rel_pos.z * obj->vp.attitude[2][2] ); } // // Set up this objects' object info structure // object_3d_object_base[object_3d_object_current_base].lights = light; object_3d_object_base[object_3d_object_current_base].camera_position = object_camera_position; object_3d_object_base[object_3d_object_current_base].points_base = object_3d_points_current_base; object_3d_object_base[object_3d_object_current_base].object_number = object_number; this_object_3d_info = &object_3d_object_base[object_3d_object_current_base]; global_object_3d_info = this_object_3d_info; // // Transform the object's shape data // // // Setup the objects scaling information // { float xdistance, ydistance, zdistance; xdistance = ( objects_3d_data[object_number].bounding_box.xmax - objects_3d_data[object_number].bounding_box.xmin ) / 2; ydistance = ( objects_3d_data[object_number].bounding_box.ymax - objects_3d_data[object_number].bounding_box.ymin ) / 2; zdistance = ( objects_3d_data[object_number].bounding_box.zmax - objects_3d_data[object_number].bounding_box.zmin ) / 2; object_3d_x_middle = objects_3d_data[object_number].bounding_box.xmin + xdistance; object_3d_y_middle = objects_3d_data[object_number].bounding_box.ymin + ydistance; object_3d_z_middle = objects_3d_data[object_number].bounding_box.zmin + zdistance; object_3d_x_scale = xdistance / 32767.0; object_3d_y_scale = ydistance / 32767.0; object_3d_z_scale = zdistance / 32767.0; } /* if ( objects_3d_data[object_number].number_of_points ) { int object_outcode; object_outcode = get_object_3d_outcode ( object_number, pos ); if ( object_outcode ) { transform_3d_object ( &objects_3d_data[object_number], pos, light, object_3d_points_current_base); } else { transform_unclipped_3d_object ( &objects_3d_data[object_number], pos, light, object_3d_points_current_base); } polygon_zdistance_bias = POLYGON_ZDISTANCE_NORMAL_BIAS; set_d3d_int_state ( D3DRENDERSTATE_CULLMODE, D3DCULL_CW ); if ( object_outcode ) { draw_3d_terrain_tree_clipped_faces ( object_number, this_object_3d_info ); } else { draw_3d_terrain_tree_unclipped_faces ( object_number, this_object_3d_info ); } set_d3d_int_state ( D3DRENDERSTATE_CULLMODE, D3DCULL_CCW ); if ( object_outcode ) { draw_3d_terrain_tree_clipped_faces ( object_number, this_object_3d_info ); } else { draw_3d_terrain_tree_unclipped_faces ( object_number, this_object_3d_info ); } } */ }