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