void RenderVisTreeClass::initialize_clip_data() { ResetEndpointClips(); /* set two default endpoint clips (left and right sides of screen) */ { endpoint_clip_data *endpoint; endpoint= &EndpointClips[indexLEFT_SIDE_OF_SCREEN]; endpoint->flags= _clip_left; short_to_long_2d(view->untransformed_left_edge,endpoint->vector); endpoint->x= 0; endpoint= &EndpointClips[indexRIGHT_SIDE_OF_SCREEN]; endpoint->flags= _clip_right; short_to_long_2d(view->untransformed_right_edge,endpoint->vector); endpoint->x= view->screen_width; } ResetLineClips(); /* set default line clip (top and bottom of screen) */ { line_clip_data *line= &LineClips[indexTOP_AND_BOTTOM_OF_SCREEN]; line->flags= _clip_up|_clip_down; line->x0= 0; line->x1= view->screen_width; line->top_y= 0; short_to_long_2d(view->top_edge,line->top_vector); line->bottom_y= view->screen_height; short_to_long_2d(view->bottom_edge,line->bottom_vector); } // LP change: ClippingWindows.clear(); }
// Main routine void RenderVisTreeClass::build_render_tree() { assert(view); // Idiot-proofing /* initialize the queue where we remember polygons we need to fire at */ initialize_polygon_queue(); /* initialize our node list to contain the root, etc. */ initialize_render_tree(); /* reset clipping buffers */ initialize_clip_data(); // LP change: // Adjusted for long-vector handling // Using start index of list of nodes: 0 long_vector2d view_edge; short_to_long_2d( view->left_edge, view_edge ); cast_render_ray( &view_edge, NONE, &Nodes.front(), _counterclockwise_bias ); short_to_long_2d( view->right_edge, view_edge ); cast_render_ray( &view_edge, NONE, &Nodes.front(), _clockwise_bias ); /* pull polygons off the queue, fire at all their new endpoints, building the tree as we go */ while (polygon_queue_size) { auto polygon_index = PolygonQueue[ --polygon_queue_size ]; polygon_data *polygon = get_polygon_data(polygon_index); assert( !POLYGON_IS_DETACHED(polygon) ); const ix vertex_count = polygon->vertex_count; for( ix vertex_index = 0; vertex_index < vertex_count; ++vertex_index ) { const auto endpoint_index = polygon->endpoint_indexes[vertex_index]; endpoint_data *endpoint = get_endpoint_data(endpoint_index); if (TEST_RENDER_FLAG(endpoint_index, _endpoint_has_been_visited)) continue; // LP change: move toward correct handling of long distances long_vector2d _vector; /* transform all visited endpoints */ endpoint->transformed = endpoint->vertex; transform_overflow_point2d( &endpoint->transformed, (world_point2d *) &view->origin, view->yaw, &endpoint->flags ); /* calculate an outbound vector to this endpoint */ // LP: changed to do long distance correctly. _vector.i = int32( endpoint->vertex.x ) - int32( view->origin.x ); _vector.j = int32( endpoint->vertex.y ) - int32( view->origin.y ); // LP change: compose a true transformed point to replace endpoint->transformed, // and use it in the upcoming code long_vector2d transformed_endpoint; overflow_short_to_long_2d( endpoint->transformed, endpoint->flags, transformed_endpoint ); if (transformed_endpoint.i > 0) { const int32 x = view->half_screen_width + ( transformed_endpoint.j * view->world_to_screen_x ) / transformed_endpoint.i; endpoint_x_coordinates[ endpoint_index ] = static_cast< int16 >( PIN(x, INT16_MIN, INT16_MAX) ); SET_RENDER_FLAG(endpoint_index, _endpoint_has_been_transformed); } /* do two cross products to determine whether this endpoint is in our view cone or not (we don't have to cast at points outside the cone) */ const auto ri = view->right_edge.i; const auto rj = view->right_edge.j; const int32 crossprod_right = ( ri * _vector.j ) - ( rj * _vector.i ); const auto li = view->left_edge.i; const auto lj = view->left_edge.j; const int32 crossprod_left = ( li * _vector.j ) - ( lj * _vector.i ); if( crossprod_right <= 0 && crossprod_left >= 0 ) { //it's in our view, cast at it int16 endpoint_; if( ENDPOINT_IS_TRANSPARENT(endpoint) ) endpoint_ = NONE; else endpoint_ = endpoint_index; cast_render_ray(&_vector, endpoint_, &Nodes.front(), _no_bias); } SET_RENDER_FLAG(endpoint_index, _endpoint_has_been_visited); } } }