Search
lxdream.org :: lxdream/src/pvr2/rendbkg.c
lxdream 0.9.1
released Jun 29
Download Now
filename src/pvr2/rendbkg.c
changeset 223:f6c28fa9076b
prev221:cf5c6d326162
next239:e5cd6b2d4586
author nkeynes
date Tue Dec 12 09:18:47 2006 +0000 (17 years ago)
permissions -rw-r--r--
last change Disable watchpoints by default - save some cpu time and we're not really using them anyway
view annotate diff log raw
     1 /**
     2  * $Id: rendbkg.c,v 1.3 2006-09-12 12:16:36 nkeynes Exp $
     3  *
     4  * PVR2 background renderer. 
     5  *
     6  * Yes, it uses the same basic data structure. Yes, it needs to be handled
     7  * completely differently.
     8  *
     9  * Note: this would be really simple if GL did unclamped colour interpolation
    10  * but it doesn't (portably), which makes this roughly 2 orders of magnitude
    11  * more complicated than it otherwise would be.
    12  *
    13  * Copyright (c) 2005 Nathan Keynes.
    14  *
    15  * This program is free software; you can redistribute it and/or modify
    16  * it under the terms of the GNU General Public License as published by
    17  * the Free Software Foundation; either version 2 of the License, or
    18  * (at your option) any later version.
    19  *
    20  * This program is distributed in the hope that it will be useful,
    21  * but WITHOUT ANY WARRANTY; without even the implied warranty of
    22  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    23  * GNU General Public License for more details.
    24  */
    26 #include <sys/time.h>
    27 #include "pvr2/pvr2.h"
    28 #include <GL/glext.h>
    29 #include <math.h>
    31 #define MAX_CLAMP_LINES 8
    32 #define MAX_VERTEXES 256
    33 #define MAX_REGIONS  256
    35 /**
    36  * Structure to hold an unpacked vertex
    37  */
    38 struct vertex_all {
    39     float x,y,z;
    40     float u,v;
    41     float rgba[4];      /* Note - RGBA order, as preferred by GL */
    42     float spec_rgba[4];
    43 };
    45 #define FARGB_A(x) (((float)(((x)>>24)+1))/256.0)
    46 #define FARGB_R(x) (((float)((((x)>>16)&0xFF)+1))/256.0)
    47 #define FARGB_G(x) (((float)((((x)>>8)&0xFF)+1))/256.0)
    48 #define FARGB_B(x) (((float)(((x)&0xFF)+1))/256.0)
    50 /**
    51  * Compute the line where k = target_k, (where k is normally one of
    52  * r,g,b,a, or z) and determines the points at which the line intersects
    53  * the viewport (0,0,width,height).
    54  *
    55  * @param center_x the x value for the center position
    56  * @param center_y the y value for the center position
    57  * @param center_k the k value for the center position
    58  * @param width Width of the viewport (ie 640)
    59  * @param height Height of the viewport (ie 480)
    60  * @param target_k determine the line where k = this value, ie 1.0
    61  * @param detxy
    62  * @param target Array to write the resultant x,y pairs to (note this
    63  * function only sets x and y values).
    64  * @return number of vertexes written to the target.
    65  */
    66 static int compute_colour_line( float center_x, float center_y, float center_k, 
    67 		  int width, int height, float target_k,
    68 		  float detxy, float detxk, float detyk,
    69 		  struct vertex_all *target ) {
    70     int num_points = 0;
    71     float tmpk = (target_k - center_k) * detxy;
    72     float x0 = -1;
    73     float x1 = -1;
    75     if( detyk != 0 ) {
    76 	x0 = (tmpk - ((0-center_y)*detxk))/detyk + center_x; /* x where y=0 */
    77 	if( x0 >= 0.0 && x0 <= width ) {
    78 	    target[num_points].x = x0;
    79 	    target[num_points].y = 0.0;
    80 	    num_points++;
    81 	}
    83 	x1 = (tmpk - ((height-center_y)*detxk))/detyk + center_x; /* x where y=height */
    84 	if( x1 >= 0.0 && x1 <= width ) {
    85 	    target[num_points].x = x1;
    86 	    target[num_points].y = height;
    87 	    num_points++;
    88 	}
    89     }
    91     if( detxk != 0 ) {
    92 	if( x0 != 0.0 && x1 != 0.0 ) { /* If x0 == 0 or x1 == 0, then we already have this one */
    93 	    float y0 = (tmpk - ((0-center_x)*detyk))/detxk + center_y; /* y where x=0 */
    94 	    if( y0 >= 0.0 && y0 <= height ) {
    95 		target[num_points].x = 0.0;
    96 		target[num_points].y = y0;
    97 		num_points++;
    98 	    }
    99 	}
   101 	if( x0 != width && x1 != width ) {
   102 	    float y1 = (tmpk - ((width-center_x)*detyk))/detxk + center_y; /* y where x=width */
   103 	    if( y1 >= 0.0 && y1 <= height ) {
   104 		target[num_points].x = width;
   105 		target[num_points].y = y1;
   106 		num_points++;
   107 	    }
   108 	}
   109     }
   111     if( num_points == 0 || num_points == 2 ) {
   112 	/* 0 = no points - line doesn't pass through the viewport */
   113 	/* 2 = normal case - got 2 endpoints */
   114 	return num_points;
   115     } else {
   116 	ERROR( "compute_colour_line got bad number of points: %d", num_points );
   117 	return 0;
   118     }
   119 }
   121 /**
   122  * A region describes a portion of the screen, possibly subdivided by a line.
   123  * if region_left and region_right are -1, this is a terminal region that can
   124  * be rendered directly. Otherwise region_left and region_right refer two 
   125  * sub-regions that are separated by the line segment vertex1-vertex2.
   126  */
   127 struct bkg_region {
   128     /* Vertexes marking the line segment that splits this region */
   129     int vertex1;
   130     int vertex2;
   131     /* Index of the left sub-region */
   132     int region_left;
   133     /* Index of the right sub-region */
   134     int region_right;
   135 };
   137 /**
   138  * Convenience structure to bundle together the vertex and region data.
   139  */
   140 struct bkg_scene {
   141     int num_vertexes;
   142     int num_regions;
   143     struct vertex_all vertexes[MAX_VERTEXES];
   144     struct bkg_region regions[MAX_REGIONS];
   145 };
   147 void parse_vertexes( uint32_t *polygon, int num_vertexes, struct vertex_all *result )
   148 {
   149     uint32_t *vertexes = polygon + 3; 
   150     int i,m = 0;
   151     for( i=0; i<num_vertexes; i++ ) {
   152 	float *vertexf = (float *)vertexes;
   153 	result[i].x = vertexf[0];
   154 	result[i].y = vertexf[1];
   155 	result[i].z = vertexf[2];
   156 	uint32_t argb;
   157 	if( POLY1_TEXTURED(*polygon) ) {
   158 	    if( POLY1_UV16(*polygon) ) {
   159 		result[i].u = halftofloat(vertexes[m+3]>>16);
   160 		result[i].v = halftofloat(vertexes[m+3]);
   161 		argb = vertexes[m+4];
   162 		vertexes += 5;
   163 	    } else {
   164 		result[i].u = vertexf[m+3];
   165 		result[i].v = vertexf[m+4];
   166 		argb = vertexes[m+5];
   167 		vertexes += 6;
   168 	    }
   169 	} else {
   170 	    argb = vertexes[m+3];
   171 	    vertexes += 4;
   172 	}
   173 	result[i].rgba[0] = FARGB_R(argb);
   174 	result[i].rgba[1] = FARGB_G(argb);
   175         result[i].rgba[2] = FARGB_B(argb);
   176 	result[i].rgba[3] = FARGB_A(argb);
   177     }
   179 }
   181 /**
   182  * Constants returned by compute_line_intersection. Note that for these purposes,
   183  * "Left" means the point(s) result in a negative value in the line equation, while
   184  * "Right" means the points(s) result in a positive value in the line equation. The
   185  * exact meaning isn't particularly important though, as long as we're consistent
   186  * throughout this process
   187  */
   188 #define LINE_COLLINEAR 0   /* The line segments are part of the same line */
   189 #define LINE_SIDE_LEFT 1   /* The second line is entirely to the "left" of the first line */
   190 #define LINE_SIDE_RIGHT 2  /* The second line is entirely to the "right" of the first line */
   191 #define LINE_INTERSECT_FROM_LEFT 3 /* The lines intersect, and (x3,y3) is to the "left" of the first line */
   192 #define LINE_INTERSECT_FROM_RIGHT 4 /* The lines intersect, and (x3,y3) is to the "right" of the first line */
   193 #define LINE_SKEW 5        /* The line segments neither intersect nor do any of the above apply (should never happen here) */
   195 /**
   196  * Compute the intersection of two line segments, where 
   197  * (x1,y1)-(x2,y2) defines the target segment, and
   198  * (x3,y3)-(x4,y4) defines the line intersecting it.
   199  *
   200  * Based off work by Mukesh Prasad (http://www.acm.org/pubs/tog/GraphicsGems/index.html)
   201  *
   202  * @return one of the above LINE_* constants
   203  */
   204 static int compute_line_intersection( float x1, float y1,   /* First line segment */
   205 				      float x2, float y2,
   206 				      float x3, float y3,   /* Second line segment */
   207 				      float x4, float y4,
   208 				      float *x, float *y  )  /* Output value: */
   209 {
   210     float a1, a2, b1, b2, c1, c2; /* Coefficients of line eqns. */
   211     float r1, r2, r3, r4;         /* test values */
   212     float denom;     /* Intermediate values */
   214     /* Compute a1, b1, c1, where line joining points 1 and 2
   215      * is "a1 x  +  b1 y  +  c1  =  0".
   216      */
   218     a1 = y2 - y1;
   219     b1 = x1 - x2;
   220     c1 = x2 * y1 - x1 * y2;
   222     /* Compute r3 and r4. */
   224     r3 = a1 * x3 + b1 * y3 + c1;
   225     r4 = a1 * x4 + b1 * y4 + c1;
   227     /* Check signs of r3 and r4.  If both point 3 and point 4 lie on
   228      * same side of line 1, the line segments do not intersect.
   229      */
   231     if( r3 == 0 && r4 == 0 ) {
   232 	return LINE_COLLINEAR;
   233     } else if( r3 <= 0 && r4 <= 0 ) {
   234 	return LINE_SIDE_LEFT;
   235     } else if( r3 >= 0 && r4 >= 0 ) {
   236 	return LINE_SIDE_RIGHT;
   237     }
   239     /* Compute a2, b2, c2 */
   241     a2 = y4 - y3;
   242     b2 = x3 - x4;
   243     c2 = x4 * y3 - x3 * y4;
   245     /* Compute r1 and r2 */
   247     r1 = a2 * x1 + b2 * y1 + c2;
   248     r2 = a2 * x2 + b2 * y2 + c2;
   250     /* Check signs of r1 and r2.  If both point 1 and point 2 lie
   251      * on same side of second line segment, the line segments do
   252      * not intersect.
   253      */
   255     if ( r1 != 0 && r2 != 0 &&
   256          signbit(r1) == signbit(r2) ) {
   257         return LINE_SKEW; /* Should never happen */
   258     }
   260     /* Cmpute intersection point. 
   261      */
   262     denom = a1 * b2 - a2 * b1;
   263     if ( denom == 0 )
   264         return LINE_COLLINEAR; /* Should never get to this point either */
   266     *x = (b1 * c2 - b2 * c1) / denom;
   267     *y = (a2 * c1 - a1 * c2) / denom;
   269     if( r3 <= 0 && r4 >= 0 ) {
   270 	return LINE_INTERSECT_FROM_LEFT;
   271     } else {
   272 	return LINE_INTERSECT_FROM_RIGHT;
   273     }
   274 }
   276 /**
   277  * Given a set of vertexes and a line segment to use to split them, generates
   278  * two sets of vertexes representing the polygon on either side of the line
   279  * segment. This method preserves the winding direction of the input vertexes.
   280  */
   281 static void compute_subregions( struct bkg_scene *scene,
   282 				int splitv1, int splitv2,
   283 				int *vertex_in, int num_vertex_in,
   284 				int *left_vertex_out, int *num_left_vertex_out,
   285 				int *right_vertex_out, int *num_right_vertex_out )
   286 {
   287     float x1 = scene->vertexes[splitv1].x;
   288     float y1 = scene->vertexes[splitv1].y;
   289     float x2 = scene->vertexes[splitv2].x;
   290     float y2 = scene->vertexes[splitv2].y;
   292     float a1 = y2 - y1;
   293     float b1 = x1 - x2;
   294     float c1 = x2 * y1 - x1 * y2;
   295     int i;
   297     *num_left_vertex_out = 0;
   298     *num_right_vertex_out = 0;
   299     int last = 0;
   300     for( i=0; i<num_vertex_in; i++ ) {
   301 	struct vertex_all *vertex = &scene->vertexes[vertex_in[i]];
   302 	float r = a1 * vertex->x + b1 * vertex->y + c1;
   303 	if( r <= 0 ) {
   304 	    if( last == 1 ) {
   305 		/* cross-point. add the split vertexes */
   306 		int v1 = vertex_in[i-1];
   307 		int v2 = vertex_in[i];
   308 		/* Determine which point is closer to the line. Strictly speaking
   309 		 * one of them must be ON the line, but this way allows for floating
   310 		 * point inaccuracies.
   311 		 */
   312 		float a2 = scene->vertexes[v2].y - scene->vertexes[v1].y;
   313 		float b2 = scene->vertexes[v1].x - scene->vertexes[v2].x;
   314 		float c2 = scene->vertexes[v2].x * scene->vertexes[v1].y - 
   315 		    scene->vertexes[v1].x * scene->vertexes[v2].y;
   316 		float r1 = a2 * x1 + b2 * y1 + c2;
   317 		float r2 = a2 * x2 + b2 * y2 + c2;
   318 		if( fabsf(r1) > fabs(r2) ) {
   319 		    int tmp = splitv1;
   320 		    splitv1 = splitv2;
   321 		    splitv2 = tmp;
   322 		}
   323 		right_vertex_out[(*num_right_vertex_out)++] = splitv1;
   324 		right_vertex_out[(*num_right_vertex_out)++] = splitv2;
   325 		left_vertex_out[(*num_left_vertex_out)++] = splitv2;
   326 		left_vertex_out[(*num_left_vertex_out)++] = splitv1;
   327 		last = 2;
   328 	    } else if( last != 2 ) {
   329 		last = -1;
   330 	    }
   331 	    left_vertex_out[(*num_left_vertex_out)++] = vertex_in[i];
   332 	} else {
   333 	    if( last == -1 ) {
   334 		/* cross-point. add the split vertexes */
   335 		int v1 = vertex_in[i-1];
   336 		int v2 = vertex_in[i];
   337 		/* Determine which point is closer to the line. Strictly speaking
   338 		 * one of them must be ON the line, but this way allows for floating
   339 		 * point inaccuracies.
   340 		 */
   341 		float a2 = scene->vertexes[v2].y - scene->vertexes[v1].y;
   342 		float b2 = scene->vertexes[v1].x - scene->vertexes[v2].x;
   343 		float c2 = scene->vertexes[v2].x * scene->vertexes[v1].y - 
   344 		    scene->vertexes[v1].x * scene->vertexes[v2].y;
   345 		float r1 = a2 * x1 + b2 * y1 + c2;
   346 		float r2 = a2 * x2 + b2 * y2 + c2;
   347 		if( fabsf(r1) > fabs(r2) ) {
   348 		    int tmp = splitv1;
   349 		    splitv1 = splitv2;
   350 		    splitv2 = tmp;
   351 		}
   352 		left_vertex_out[(*num_left_vertex_out)++] = splitv1;
   353 		left_vertex_out[(*num_left_vertex_out)++] = splitv2;
   354 		right_vertex_out[(*num_right_vertex_out)++] = splitv2;
   355 		right_vertex_out[(*num_right_vertex_out)++] = splitv1;
   356 		last = 2;
   357 	    } else if( last != 2 ) {
   358 		last = 1;
   359 	    }
   360 	    right_vertex_out[(*num_right_vertex_out)++] = vertex_in[i];
   361 	}
   362     }
   363 }
   365 /**
   366  * Subdivide the region tree by splitting it along a given line.
   367  * 
   368  * @param scene  current bkg scene data
   369  * @param region current region under examination
   370  * @param vertex1 first vertex of the new line segment
   371  * @param vertex2 second vertex of the new line segment
   372  */
   373 static void bkg_region_subdivide( struct bkg_scene *scene, int region, int vertex1, int vertex2 ) {
   374     struct bkg_region *this_region = &scene->regions[region];
   376     if( scene->regions[region].region_left == -1 || scene->regions[region].region_right == -1 ) {
   377 	/* Reached the end of the tree. Setup new left+right regions */
   378 	int i = scene->num_regions;
   379 	scene->regions[i].region_left = scene->regions[i].region_right = -1;
   380 	scene->regions[i+1].region_left = scene->regions[i+1].region_right = -1;
   381 	this_region->region_left = i;
   382 	this_region->region_right = i+1;
   383 	this_region->vertex1 = vertex1;
   384 	this_region->vertex2 = vertex2;
   385 	scene->num_regions += 2;
   386     } else {
   387 	float x,y;
   388 	int thisv1 = this_region->vertex1;
   389 	int thisv2 = this_region->vertex2;
   390 	int vertex3;
   391 	int status = 
   392 	    compute_line_intersection( scene->vertexes[thisv1].x, scene->vertexes[thisv1].y,
   393 				       scene->vertexes[thisv2].x, scene->vertexes[thisv2].y,
   394 				       scene->vertexes[vertex1].x, scene->vertexes[vertex1].y,
   395 				       scene->vertexes[vertex2].x, scene->vertexes[vertex2].y,
   396 				       &x, &y );
   397 	switch( status ) {
   398 	case LINE_INTERSECT_FROM_LEFT:
   399 	    /* if new line segment intersects our current line segment,
   400 	     * subdivide the segment (add a new vertex) and recurse on both
   401 	     * sub trees 
   402 	     */
   403 	    /* Compute split-point vertex */
   404 	    vertex3 = scene->num_vertexes++;
   405 	    scene->vertexes[vertex3].x = x;
   406 	    scene->vertexes[vertex3].y = y;
   407 	    /* Recurse */
   408 	    bkg_region_subdivide( scene, scene->regions[region].region_left, vertex1,vertex3 );
   409 	    bkg_region_subdivide( scene, scene->regions[region].region_right, vertex3, vertex2 );
   410 	    break;
   411 	case LINE_INTERSECT_FROM_RIGHT:
   412 	    /* Same except line runs in the opposite direction */
   413 	    vertex3 = scene->num_vertexes++;
   414 	    scene->vertexes[vertex3].x = x;
   415 	    scene->vertexes[vertex3].y = y;
   416 	    /* Recurse */
   417 	    bkg_region_subdivide( scene, scene->regions[region].region_left, vertex2,vertex3 );
   418 	    bkg_region_subdivide( scene, scene->regions[region].region_right, vertex3, vertex1 );
   419 	    break;
   420 	case LINE_COLLINEAR:
   421 	case LINE_SKEW:
   422 	    /* Collinear - ignore */
   423 	    break;
   424 	case LINE_SIDE_LEFT:
   425 	    /* else if line segment passes through the left sub-region alone,
   426 	     * left-recurse only.
   427 	     */
   428 	    bkg_region_subdivide( scene, scene->regions[region].region_left, vertex1, vertex2 );
   429 	    break;
   430 	case LINE_SIDE_RIGHT:
   431 	    /* Otherwise line segment passes through the right sub-region alone,
   432 	     * so right-recurse.
   433 	     */
   434 	    bkg_region_subdivide( scene, scene->regions[region].region_right, vertex1, vertex2 );
   435 	    break;
   436 	}
   437     }
   438 }
   442 /**
   443  * Compute the values for an array of vertexes, given x,y for each
   444  * vertex and the base 3-vertex triple used to define the background
   445  * plane. Essentially the base vertexes are used to find the
   446  * plane equation for each of z,a,r,g,b,etc, which is then solved for
   447  * each of the required compute vertexes (normally the corner points).
   448  *
   449  * @param base The 3 vertexes supplied as the background definition
   450  * @param compute An array of vertexes to compute. x and y must be
   451  *   preset, other values are computed.
   452  */
   453 static void bkg_compute_scene( struct vertex_all *base, int width, int height,
   454 				struct bkg_scene *scene )
   455 {
   456     struct vertex_all center;
   457     struct vertex_all diff0, diff1;
   458     int i,k;
   460     center.x = base[1].x;
   461     center.y = base[1].y;
   462     center.z = base[1].z;
   463     diff0.x = base[0].x - base[1].x;
   464     diff0.y = base[0].y - base[1].y;
   465     diff0.z = base[0].z - base[1].z;
   466     diff1.x = base[2].x - base[1].x;
   467     diff1.y = base[2].y - base[1].y;
   468     diff1.z = base[2].z - base[1].z;
   470     float detxy = ((diff1.y) * (diff0.x)) - ((diff0.y) * (diff1.x));
   472     /* Corner points first */
   473     scene->vertexes[0].x = 0.0;
   474     scene->vertexes[0].y = 0.0;
   475     scene->vertexes[1].x = width;
   476     scene->vertexes[1].y = 0.0;
   477     scene->vertexes[2].x = width;
   478     scene->vertexes[2].y = height;
   479     scene->vertexes[3].x = 0.0;
   480     scene->vertexes[3].y = height;
   481     scene->regions[0].region_left = -1;
   482     scene->regions[0].region_right = -1;
   483     scene->num_vertexes = 4;
   484     scene->num_regions = 1;
   486     if( detxy == 0 ) {
   487 	/* The points lie on a single line - no plane for you. Use the values
   488 	 * from the 3rd point for the whole screen.
   489 	 */
   490 	for( i=0; i<4; i++ ) {
   491 	    scene->vertexes[i].rgba[0] = base[2].rgba[0];
   492 	    scene->vertexes[i].rgba[1] = base[2].rgba[1];
   493 	    scene->vertexes[i].rgba[2] = base[2].rgba[2];
   494 	    scene->vertexes[i].rgba[3] = base[2].rgba[3];
   495 	    scene->vertexes[i].u = base[2].u;
   496 	    scene->vertexes[i].v = base[2].v;
   497 	}
   498     } else {
   499 	/* Compute the colour values at each corner */
   500 	center.rgba[0] = base[1].rgba[0];
   501 	center.rgba[1] = base[1].rgba[1];
   502 	center.rgba[2] = base[1].rgba[2];
   503 	center.rgba[3] = base[1].rgba[3];
   504 	diff0.rgba[0] = base[0].rgba[0] - center.rgba[0];
   505 	diff0.rgba[1] = base[0].rgba[1] - center.rgba[1];
   506 	diff0.rgba[2] = base[0].rgba[2] - center.rgba[2];
   507 	diff0.rgba[3] = base[0].rgba[3] - center.rgba[3];
   508 	diff0.u = base[0].u - center.u;
   509 	diff0.v = base[0].v - center.v;
   510 	diff1.rgba[0] = base[2].rgba[0] - center.rgba[0];
   511 	diff1.rgba[1] = base[2].rgba[1] - center.rgba[1];
   512 	diff1.rgba[2] = base[2].rgba[2] - center.rgba[2];
   513 	diff1.rgba[3] = base[2].rgba[3] - center.rgba[3];
   514 	diff1.u = base[2].u - center.u;
   515 	diff1.v = base[2].v - center.v;
   516 	for( i=0; i<4; i++ ) {
   517 	    float t = ((scene->vertexes[i].x - center.x) * diff1.y -
   518 		       (scene->vertexes[i].y - center.y) * diff1.x) / detxy;
   519 	    float s = ((scene->vertexes[i].y - center.y) * diff0.x -
   520 		       (scene->vertexes[i].x - center.x) * diff0.y) / detxy;
   521 	    scene->vertexes[i].z = center.z + (t*diff0.z) + (s*diff1.z);
   522 	    scene->vertexes[i].rgba[0] = center.rgba[0] + (t*diff0.rgba[0]) + (s*diff1.rgba[0]);
   523 	    scene->vertexes[i].rgba[1] = center.rgba[1] + (t*diff0.rgba[1]) + (s*diff1.rgba[1]);
   524 	    scene->vertexes[i].rgba[2] = center.rgba[2] + (t*diff0.rgba[2]) + (s*diff1.rgba[2]);
   525 	    scene->vertexes[i].rgba[3] = center.rgba[3] + (t*diff0.rgba[3]) + (s*diff1.rgba[3]);
   526 	    scene->vertexes[i].u = center.u + (t*diff0.u) + (s*diff1.u);
   527 	    scene->vertexes[i].v = center.v + (t*diff0.v) + (s*diff1.v);
   528 	}
   530 	/* Check for values > 1.0 | < 0.0 */
   531 	for( k=0; k<4; k++ ) {
   532 	    float detyk = ((diff1.y) * (diff0.rgba[k])) - ((diff0.y)*(diff1.rgba[k]));
   533 	    float detxk = ((diff0.x) * (diff1.rgba[k])) - ((diff1.x)*(diff0.rgba[k]));
   534 	    if( scene->vertexes[0].rgba[k] > 1.0 || scene->vertexes[1].rgba[k] > 1.0 || 
   535 		scene->vertexes[2].rgba[k] > 1.0 || scene->vertexes[3].rgba[k] > 1.0 ) {
   536 		int v1 = scene->num_vertexes;
   537 		scene->num_vertexes += compute_colour_line(center.x, center.y, center.rgba[k],
   538 						    width, height, 1.0,
   539 						    detxy, detxk, detyk, 
   540 						    scene->vertexes+scene->num_vertexes );
   541 		if( scene->num_vertexes != v1 ) {
   542 		    bkg_region_subdivide( scene, 0, v1, v1+1 );
   543 		}
   544 	    }
   546 	    if( scene->vertexes[0].rgba[k] < 0.0 || scene->vertexes[1].rgba[k] < 0.0 || 
   547 		scene->vertexes[2].rgba[k] < 0.0 || scene->vertexes[3].rgba[k] < 0.0 ) {
   548 		int v1 = scene->num_vertexes;
   549 		scene->num_vertexes += compute_colour_line(center.x, center.y, center.rgba[k],
   550 						    width, height, 0.0,
   551 						    detxy, detxk, detyk, 
   552 						    scene->vertexes+scene->num_vertexes );
   553 		if( scene->num_vertexes != v1 ) {
   554 		    bkg_region_subdivide( scene, 0, v1, v1+1 );
   555 		}
   557 	    }
   558 	}
   560 	/* Finally compute the colour values for all vertexes 
   561 	 * (excluding the 4 we did upfront) */
   562 	for( i=4; i<scene->num_vertexes; i++ ) {
   563 	    float t = ((scene->vertexes[i].x - center.x) * diff1.y -
   564 		       (scene->vertexes[i].y - center.y) * diff1.x) / detxy;
   565 	    float s = ((scene->vertexes[i].y - center.y) * diff0.x -
   566 		       (scene->vertexes[i].x - center.x) * diff0.y) / detxy;
   567 	    scene->vertexes[i].z = center.z + (t*diff0.z) + (s*diff1.z);
   568 	    scene->vertexes[i].rgba[0] = center.rgba[0] + (t*diff0.rgba[0]) + (s*diff1.rgba[0]);
   569 	    scene->vertexes[i].rgba[1] = center.rgba[1] + (t*diff0.rgba[1]) + (s*diff1.rgba[1]);
   570 	    scene->vertexes[i].rgba[2] = center.rgba[2] + (t*diff0.rgba[2]) + (s*diff1.rgba[2]);
   571 	    scene->vertexes[i].rgba[3] = center.rgba[3] + (t*diff0.rgba[3]) + (s*diff1.rgba[3]);
   572 	    scene->vertexes[i].u = center.u + (t*diff0.u) + (s*diff1.u);
   573 	    scene->vertexes[i].v = center.v + (t*diff0.v) + (s*diff1.v);
   574 	}
   575     }
   576 }
   578 /**
   579  * Render a bkg_region.
   580  * @param scene the background scene data
   581  * @param region the region to render
   582  * @param vertexes the vertexes surrounding the region
   583  * @param num_vertexes the number of vertexes in the vertex array
   584  */
   585 void bkg_render_region( struct bkg_scene *scene, int region, int *vertexes, int num_vertexes,
   586 			uint32_t poly1 )
   587 {
   588     if( scene->regions[region].region_left == -1 && scene->regions[region].region_right == -1 ) {
   589 	/* Leaf node - render the points as given */
   590 	int i,k;
   591 	glBegin(GL_POLYGON);
   592 	for( i=0; i<num_vertexes; i++ ) {
   593 	    k = vertexes[i];
   594 	    glColor4fv(scene->vertexes[k].rgba);
   595 	    if( POLY1_TEXTURED(poly1) ) {
   596 		glTexCoord2f(scene->vertexes[k].u, scene->vertexes[k].v);
   597 	    }
   598 	    glVertex3f(scene->vertexes[k].x, scene->vertexes[k].y, scene->vertexes[k].z);
   599 	}
   600 	glEnd();
   601     } else {
   602 	/* split the region into left and right regions */
   603 	int left_vertexes[num_vertexes+1];
   604 	int right_vertexes[num_vertexes+1];
   605 	int num_left = 0;
   606 	int num_right = 0;
   607 	struct bkg_region *reg = &scene->regions[region];
   608 	compute_subregions( scene, reg->vertex1, reg->vertex2, vertexes, num_vertexes,
   609 			    left_vertexes, &num_left, right_vertexes, &num_right );
   610 	bkg_render_region( scene, reg->region_left, left_vertexes, num_left, poly1 );
   611 	bkg_render_region( scene, reg->region_right, right_vertexes, num_right, poly1 );
   612     }
   614 }
   617 void render_backplane( uint32_t *polygon, uint32_t width, uint32_t height, uint32_t mode ) {
   618     struct vertex_all vertex[3];
   619     int screen_vertexes[4] = {0,1,2,3};
   620     struct bkg_scene scene;
   621     int i,j,k, num_vertexes;
   623     parse_vertexes(polygon, 3, vertex);
   624     render_set_context(polygon, 0);
   625     glDisable(GL_CULL_FACE);
   626     glDisable(GL_DEPTH_TEST);
   627     glBlendFunc(GL_ONE, GL_ZERO); /* For now, just disable alpha blending on the bkg */
   628     bkg_compute_scene(vertex, width, height, &scene);
   629     bkg_render_region(&scene, 0, screen_vertexes, 4, *polygon);
   630 }
.