Пример #1
0
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 );
		}
	}
}
Пример #2
0
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 ();
    }
}
Пример #3
0
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 );
		}
	}
	*/
}