Subversion Repositories Kolibri OS

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
5098 clevermous 1
#include "zgl.h"
2
 
3
void 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
 
17
void 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
 
25
void glopEdgeFlag(GLContext * c, GLParam * p)
26
{
27
    c->current_edge_flag = p[1].i;
28
}
29
 
30
void 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
 
55
void 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
 
71
void 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 */
145
static 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
 
206
void 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
 
348
void 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
}