Go to most recent revision | 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 | }>=><=>><>><> |