source: trunk/sys/TinyGL/src/vertex.c @ 406

Last change on this file since 406 was 1, checked in by alain, 8 years ago

First import

File size: 8.8 KB
Line 
1#include "zgl.h"
2
3void glopNormal(GLContext * c, GLParam * p)
4{
5    V3 v;
6
7    v.X = p[1].f;
8    v.Y = p[2].f;
9    v.Z = p[3].f;
10
11    c->current_normal.X = v.X;
12    c->current_normal.Y = v.Y;
13    c->current_normal.Z = v.Z;
14    c->current_normal.W = 0;
15}
16
17void glopTexCoord(GLContext * c, GLParam * p)
18{
19    c->current_tex_coord.X = p[1].f;
20    c->current_tex_coord.Y = p[2].f;
21    c->current_tex_coord.Z = p[3].f;
22    c->current_tex_coord.W = p[4].f;
23}
24
25void glopEdgeFlag(GLContext * c, GLParam * p)
26{
27    c->current_edge_flag = p[1].i;
28}
29
30void glopColor(GLContext * c, GLParam * p)
31{
32
33    c->current_color.X = p[1].f;
34    c->current_color.Y = p[2].f;
35    c->current_color.Z = p[3].f;
36    c->current_color.W = p[4].f;
37    c->longcurrent_color[0] = p[5].ui;
38    c->longcurrent_color[1] = p[6].ui;
39    c->longcurrent_color[2] = p[7].ui;
40
41    if (c->color_material_enabled) {
42        GLParam q[7];
43        q[0].op = OP_Material;
44        q[1].i = c->current_color_material_mode;
45        q[2].i = c->current_color_material_type;
46        q[3].f = p[1].f;
47        q[4].f = p[2].f;
48        q[5].f = p[3].f;
49        q[6].f = p[4].f;
50        glopMaterial(c, q);
51    }
52}
53
54
55void gl_eval_viewport(GLContext * c)
56{
57    GLViewport *v;
58    float zsize = (1 << (ZB_Z_BITS + ZB_POINT_Z_FRAC_BITS));
59
60    v = &c->viewport;
61
62    v->trans.X = ((v->xsize - 0.5) / 2.0) + v->xmin;
63    v->trans.Y = ((v->ysize - 0.5) / 2.0) + v->ymin;
64    v->trans.Z = ((zsize - 0.5) / 2.0) + ((1 << ZB_POINT_Z_FRAC_BITS)) / 2;
65
66    v->scale.X = (v->xsize - 0.5) / 2.0;
67    v->scale.Y = -(v->ysize - 0.5) / 2.0;
68    v->scale.Z = -((zsize - 0.5) / 2.0);
69}
70
71void glopBegin(GLContext * c, GLParam * p)
72{
73    int type;
74    M4 tmp;
75
76    assert(c->in_begin == 0);
77
78    type = p[1].i;
79    c->begin_type = type;
80    c->in_begin = 1;
81    c->vertex_n = 0;
82    c->vertex_cnt = 0;
83
84    if (c->matrix_model_projection_updated) {
85
86        if (c->lighting_enabled) {
87            /* precompute inverse modelview */
88            gl_M4_Inv(&tmp, c->matrix_stack_ptr[0]);
89            gl_M4_Transpose(&c->matrix_model_view_inv, &tmp);
90        } else {
91            float *m = &c->matrix_model_projection.m[0][0];
92            /* precompute projection matrix */
93            gl_M4_Mul(&c->matrix_model_projection,
94                      c->matrix_stack_ptr[1],
95                      c->matrix_stack_ptr[0]);
96            /* test to accelerate computation */
97            c->matrix_model_projection_no_w_transform = 0;
98            if (m[12] == 0.0 && m[13] == 0.0 && m[14] == 0.0)
99                c->matrix_model_projection_no_w_transform = 1;
100        }
101
102        /* test if the texture matrix is not Identity */
103        c->apply_texture_matrix = !gl_M4_IsId(c->matrix_stack_ptr[2]);
104
105        c->matrix_model_projection_updated = 0;
106    }
107    /*  viewport */
108    if (c->viewport.updated) {
109        gl_eval_viewport(c);
110        c->viewport.updated = 0;
111    }
112    /* triangle drawing functions */
113    if (c->render_mode == GL_SELECT) {
114        c->draw_triangle_front = gl_draw_triangle_select;
115        c->draw_triangle_back = gl_draw_triangle_select;
116    } else {
117        switch (c->polygon_mode_front) {
118        case GL_POINT:
119            c->draw_triangle_front = gl_draw_triangle_point;
120            break;
121        case GL_LINE:
122            c->draw_triangle_front = gl_draw_triangle_line;
123            break;
124        default:
125            c->draw_triangle_front = gl_draw_triangle_fill;
126            break;
127        }
128
129        switch (c->polygon_mode_back) {
130        case GL_POINT:
131            c->draw_triangle_back = gl_draw_triangle_point;
132            break;
133        case GL_LINE:
134            c->draw_triangle_back = gl_draw_triangle_line;
135            break;
136        default:
137            c->draw_triangle_back = gl_draw_triangle_fill;
138            break;
139        }
140    }
141}
142
143/* coords, tranformation , clip code and projection */
144/* TODO : handle all cases */
145static inline void gl_vertex_transform(GLContext * c, GLVertex * v)
146{
147    float *m;
148    V4 *n;
149
150    if (c->lighting_enabled) {
151        /* eye coordinates needed for lighting */
152
153        m = &c->matrix_stack_ptr[0]->m[0][0];
154        v->ec.X = (v->coord.X * m[0] + v->coord.Y * m[1] +
155                   v->coord.Z * m[2] + m[3]);
156        v->ec.Y = (v->coord.X * m[4] + v->coord.Y * m[5] +
157                   v->coord.Z * m[6] + m[7]);
158        v->ec.Z = (v->coord.X * m[8] + v->coord.Y * m[9] +
159                   v->coord.Z * m[10] + m[11]);
160        v->ec.W = (v->coord.X * m[12] + v->coord.Y * m[13] +
161                   v->coord.Z * m[14] + m[15]);
162
163        /* projection coordinates */
164        m = &c->matrix_stack_ptr[1]->m[0][0];
165        v->pc.X = (v->ec.X * m[0] + v->ec.Y * m[1] +
166                   v->ec.Z * m[2] + v->ec.W * m[3]);
167        v->pc.Y = (v->ec.X * m[4] + v->ec.Y * m[5] +
168                   v->ec.Z * m[6] + v->ec.W * m[7]);
169        v->pc.Z = (v->ec.X * m[8] + v->ec.Y * m[9] +
170                   v->ec.Z * m[10] + v->ec.W * m[11]);
171        v->pc.W = (v->ec.X * m[12] + v->ec.Y * m[13] +
172                   v->ec.Z * m[14] + v->ec.W * m[15]);
173
174        m = &c->matrix_model_view_inv.m[0][0];
175        n = &c->current_normal;
176
177        v->normal.X = (n->X * m[0] + n->Y * m[1] + n->Z * m[2]);
178        v->normal.Y = (n->X * m[4] + n->Y * m[5] + n->Z * m[6]);
179        v->normal.Z = (n->X * m[8] + n->Y * m[9] + n->Z * m[10]);
180
181        if (c->normalize_enabled) {
182            gl_V3_Norm(&v->normal);
183        }
184    } else {
185        /* no eye coordinates needed, no normal */
186        /* NOTE: W = 1 is assumed */
187        m = &c->matrix_model_projection.m[0][0];
188
189        v->pc.X = (v->coord.X * m[0] + v->coord.Y * m[1] +
190                   v->coord.Z * m[2] + m[3]);
191        v->pc.Y = (v->coord.X * m[4] + v->coord.Y * m[5] +
192                   v->coord.Z * m[6] + m[7]);
193        v->pc.Z = (v->coord.X * m[8] + v->coord.Y * m[9] +
194                   v->coord.Z * m[10] + m[11]);
195        if (c->matrix_model_projection_no_w_transform) {
196            v->pc.W = m[15];
197        } else {
198            v->pc.W = (v->coord.X * m[12] + v->coord.Y * m[13] +
199                       v->coord.Z * m[14] + m[15]);
200        }
201    }
202
203    v->clip_code = gl_clipcode(v->pc.X, v->pc.Y, v->pc.Z, v->pc.W);
204}
205
206void glopVertex(GLContext * c, GLParam * p)
207{
208    GLVertex *v;
209    int n, i, cnt;
210
211    assert(c->in_begin != 0);
212
213    n = c->vertex_n;
214    cnt = c->vertex_cnt;
215    cnt++;
216    c->vertex_cnt = cnt;
217
218    /* quick fix to avoid crashes on large polygons */
219    if (n >= c->vertex_max) {
220        GLVertex *newarray;
221        c->vertex_max <<= 1;    /* just double size */
222        newarray = gl_malloc(sizeof(GLVertex) * c->vertex_max);
223        if (!newarray) {
224            gl_fatal_error("unable to allocate GLVertex array.\n");
225        }
226        memcpy(newarray, c->vertex, n * sizeof(GLVertex));
227        gl_free(c->vertex);
228        c->vertex = newarray;
229    }
230    /* new vertex entry */
231    v = &c->vertex[n];
232    n++;
233
234    v->coord.X = p[1].f;
235    v->coord.Y = p[2].f;
236    v->coord.Z = p[3].f;
237    v->coord.W = p[4].f;
238
239    gl_vertex_transform(c, v);
240
241    /* color */
242
243    if (c->lighting_enabled) {
244        gl_shade_vertex(c, v);
245    } else {
246        v->color = c->current_color;
247    }
248
249    /* tex coords */
250
251    if (c->texture_2d_enabled) {
252        if (c->apply_texture_matrix) {
253            gl_M4_MulV4(&v->tex_coord, c->matrix_stack_ptr[2], &c->current_tex_coord);
254        } else {
255            v->tex_coord = c->current_tex_coord;
256        }
257    }
258    /* precompute the mapping to the viewport */
259    if (v->clip_code == 0)
260        gl_transform_to_viewport(c, v);
261
262    /* edge flag */
263
264    v->edge_flag = c->current_edge_flag;
265
266    switch (c->begin_type) {
267    case GL_POINTS:
268        gl_draw_point(c, &c->vertex[0]);
269        n = 0;
270        break;
271
272    case GL_LINES:
273        if (n == 2) {
274            gl_draw_line(c, &c->vertex[0], &c->vertex[1]);
275            n = 0;
276        }
277        break;
278    case GL_LINE_STRIP:
279    case GL_LINE_LOOP:
280        if (n == 1) {
281            c->vertex[2] = c->vertex[0];
282        } else if (n == 2) {
283            gl_draw_line(c, &c->vertex[0], &c->vertex[1]);
284            c->vertex[0] = c->vertex[1];
285            n = 1;
286        }
287        break;
288
289    case GL_TRIANGLES:
290        if (n == 3) {
291            gl_draw_triangle(c, &c->vertex[0], &c->vertex[1], &c->vertex[2]);
292            n = 0;
293        }
294        break;
295    case GL_TRIANGLE_STRIP:
296        if (cnt >= 3) {
297            if (n == 3)
298                n = 0;
299            /* needed to respect triangle orientation */
300            switch(cnt & 1) {
301            case 0:
302                gl_draw_triangle(c,&c->vertex[2],&c->vertex[1],&c->vertex[0]);
303                break;
304            default:
305            case 1:
306                gl_draw_triangle(c,&c->vertex[0],&c->vertex[1],&c->vertex[2]);
307                break;
308            }
309        }
310        break;
311    case GL_TRIANGLE_FAN:
312        if (n == 3) {
313            gl_draw_triangle(c, &c->vertex[0], &c->vertex[1], &c->vertex[2]);
314            c->vertex[1] = c->vertex[2];
315            n = 2;
316        }
317        break;
318
319    case GL_QUADS:
320        if (n == 4) {
321            c->vertex[2].edge_flag = 0;
322            gl_draw_triangle(c, &c->vertex[0], &c->vertex[1], &c->vertex[2]);
323            c->vertex[2].edge_flag = 1;
324            c->vertex[0].edge_flag = 0;
325            gl_draw_triangle(c, &c->vertex[0], &c->vertex[2], &c->vertex[3]);
326            n = 0;
327        }
328        break;
329
330    case GL_QUAD_STRIP:
331        if (n == 4) {
332            gl_draw_triangle(c, &c->vertex[0], &c->vertex[1], &c->vertex[2]);
333            gl_draw_triangle(c, &c->vertex[1], &c->vertex[3], &c->vertex[2]);
334            for (i = 0; i < 2; i++)
335                c->vertex[i] = c->vertex[i + 2];
336            n = 2;
337        }
338        break;
339    case GL_POLYGON:
340        break;
341    default:
342        gl_fatal_error("glBegin: type %x not handled\n", c->begin_type);
343    }
344
345    c->vertex_n = n;
346}
347
348void glopEnd(GLContext * c, GLParam * param)
349{
350    assert(c->in_begin == 1);
351
352    if (c->begin_type == GL_LINE_LOOP) {
353        if (c->vertex_cnt >= 3) {
354            gl_draw_line(c, &c->vertex[0], &c->vertex[2]);
355        }
356    } else if (c->begin_type == GL_POLYGON) {
357        int i = c->vertex_cnt;
358        while (i >= 3) {
359            i--;
360            gl_draw_triangle(c, &c->vertex[i], &c->vertex[0], &c->vertex[i - 1]);
361        }
362    }
363    c->in_begin = 0;
364}
Note: See TracBrowser for help on using the repository browser.