version 2.8
vertex.c
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  gl_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  gl_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  (void) param;
351  gl_assert(c->in_begin == 1);
352 
353  if (c->begin_type == GL_LINE_LOOP) {
354  if (c->vertex_cnt >= 3) {
355  gl_draw_line(c, &c->vertex[0], &c->vertex[2]);
356  }
357  } else if (c->begin_type == GL_POLYGON) {
358  int i = c->vertex_cnt;
359  while (i >= 3) {
360  i--;
361  gl_draw_triangle(c, &c->vertex[i], &c->vertex[0], &c->vertex[i - 1]);
362  }
363  }
364  c->in_begin = 0;
365 }