~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Linux Cross Reference
Tina4/src/draw/paint/tv_hidden.c

Version: ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 /**@(#)
  2 **/
  3 #include <stdio.h>
  4 #include <math.h>
  5 #include <tina/sys.h>
  6 #include <tina/sysfuncs.h>
  7 #include <tina/math.h>
  8 #include <tina/mathfuncs.h>
  9 #include <tina/vision.h>
 10 #include <tina/tv.h>
 11 #include <tina/draw.h>
 12 #include <tina/drawfuncs.h>
 13 #include <tina/tvfuncs.h>
 14 
 15 static Bool show_top = true;
 16 static Bool show_bot = true;
 17 
 18 static int *top_buff;
 19 static int *top_col;
 20 static int *bot_buff;
 21 static int *bot_col;
 22 static int width, height;
 23 
 24 void    tv_terrain_hidden_init(Tv * tv, Bool bot, Bool top)
 25 {
 26     int     i;
 27 
 28     if (tv == NULL)
 29         return;
 30 
 31     if (top_buff != NULL)
 32         ivector_free((void *) top_buff, 0);
 33     if (top_col != NULL)
 34         ivector_free((void *) top_col, 0);
 35     if (bot_buff != NULL)
 36         ivector_free((void *) bot_buff, 0);
 37     if (bot_col != NULL)
 38         ivector_free((void *) bot_col, 0);
 39 
 40     height = tv_get_height(tv);
 41     width = tv_get_width(tv);
 42     top_buff = ivector_alloc(0, width);
 43     top_col = ivector_alloc(0, width);
 44     bot_buff = ivector_alloc(0, width);
 45     bot_col = ivector_alloc(0, width);
 46 
 47     for (i = 0; i < width; ++i)
 48     {
 49         top_buff[i] = height;
 50         bot_buff[i] = 0;
 51         top_col[i] = bot_col[i] = -1;
 52     }
 53 
 54     show_bot = bot;
 55     show_top = top;
 56 }
 57 
 58 static void tv_points_between(Tv * tv, int x, int y1, int y2)
 59 {
 60     int     i, inc;
 61 
 62     if (y1 == y2)
 63     {
 64         tv_pointxy(tv, x, y1);
 65         return;
 66     }
 67     inc = (y1 < y2) ? 1 : -1;
 68 
 69     for (i = y1 + inc;; i += inc)
 70     {
 71         tv_pointxy(tv, x, i);
 72         if (i == y2)
 73             break;
 74     }
 75 }
 76 
 77 static void tv_points_between_col(Tv * tv, int x, int y1, int y2, int col)
 78 {
 79     int     i, inc;
 80 
 81     tv_set_color(tv, col);
 82     (void) tv_set_op(tv, rop_copy);
 83     if (y1 == y2)
 84         tv_pointxy(tv, x, y1);
 85     else
 86     {
 87         inc = (y1 < y2) ? 1 : -1;
 88 
 89         for (i = y1 + inc;; i += inc)
 90         {
 91             tv_pointxy(tv, x, i);
 92             if (i == y2)
 93                 break;
 94         }
 95     }
 96 }
 97 
 98 void    tv_hidden_line(Tv * tv, Ipos p1, Ipos p2, Bool fill, int col)
 99 {
100     int     x1 = ipos_x(p1), y1 = ipos_y(p1), x2 = ipos_x(p2), y2 = ipos_y(p2);
101     int     i, j;
102     float   grad;
103 
104     if ((x1 < 0 && x2 < 0) || (x1 >= width && x2 >= width) ||
105         (false && y1 < 0 && y2 < 0) || (fill == false && y1 >= width && y2 >= width))
106         return;
107 
108     if (x1 > x2)
109     {
110         SWAP(int, x1, x2);
111         SWAP(int, y1, y2);
112     }
113     if (x1 != x2)
114         grad = ((float) (y2 - y1)) / (x2 - x1);
115 
116     /* make it fit on the screen */
117     if (x1 < 0)
118     {
119         y1 = (x2 == 0) ? y2 : (int)(y1 - x1 * grad);
120         x1 = 0;
121     }
122     if (x2 >= width)
123     {
124         y2 = (x1 == width - 1) ? y1 : (int)(y2 - (x2 + 1 - width) * grad);
125         x2 = width - 1;
126     }
127     /* now display line */
128 
129     if (x2 == x1)
130     {
131         ORDER(int, y1, y2);
132         if (show_top == true && y1 < top_buff[x1])
133         {
134             if (fill && top_col[x1] != -1)
135                 tv_points_between_col(tv, x1, top_buff[x1], y1, col);
136             if (y2 <= top_buff[x1])
137                 tv_points_between(tv, x1, y1, y2);
138             else
139                 tv_points_between(tv, x1, top_buff[x1], y1);
140             top_buff[x1] = y1;
141         }
142         if (show_bot == true && y2 > bot_buff[x1])
143         {
144             if (fill && bot_col[x1] != -1)
145                 tv_points_between_col(tv, x1, bot_buff[x1], y1, col);
146             if (y1 >= bot_buff[x1])
147                 tv_points_between(tv, x1, y1, y2);
148             else
149                 tv_points_between(tv, x1, bot_buff[x1], y2);
150             bot_buff[x1] = y2;
151         }
152         if (fill)
153             top_col[x1] = bot_col[x1] = col;
154         return;
155     }
156     /* compute new horizons and display them */
157 
158     if (show_top == true)
159     {
160         if (y1 < top_buff[x1])
161         {
162             if (fill && top_col[x1] != -1)
163                 tv_points_between_col(tv, x1, top_buff[x1], y1, top_col[x1]);
164             tv_pointxy(tv, x1, y1);
165             top_buff[x1] = y1;
166         }
167         if (fill)
168             top_col[x1] = col;
169 
170         for (i = x1; i < x2; i++)
171         {
172             j = (i + 1 == x2) ? y2 : (int)(y1 + (i + 1 - x1) * grad);
173 
174             if (j < top_buff[i + 1])
175             {
176                 if (fill && top_col[i + 1] != -1)
177                     tv_points_between_col(tv, i + 1, top_buff[i + 1], j, top_col[i + 1]);
178                 top_buff[i + 1] = j;
179             }
180             if (fill)
181                 top_col[i + 1] = col;
182             tv_points_between(tv, i + 1, top_buff[i], top_buff[i + 1]);
183         }
184     }
185     if (show_bot == true)
186     {
187         if (y1 > bot_buff[x1])
188         {
189             if (fill && bot_col[x1] != -1)
190                 tv_points_between_col(tv, x1, bot_buff[x1], y1, bot_col[x1]);
191             tv_pointxy(tv, x1, y1);
192             bot_buff[x1] = y1;
193         }
194         if (fill)
195             bot_col[x1] = col;
196 
197         for (i = x1; i < x2; i++)
198         {
199             j = (i + 1 == x2) ? y2 : (int)(y1 + (i + 1 - x1) * grad);
200             if (j > bot_buff[i + 1])
201             {
202                 if (fill && bot_col[i + 1] != -1)
203                     tv_points_between_col(tv, i + 1, bot_buff[i + 1], j, bot_col[i + 1]);
204                 bot_buff[i + 1] = j;
205             }
206             if (fill)
207                 bot_col[i + 1] = col;
208             tv_points_between(tv, i + 1, bot_buff[i], bot_buff[i + 1]);
209         }
210     }
211 }
212 
213 void    tv_terrain_hidden2(Tv * tv, Ipos ** p, int m, int n, int ir, int ic)
214 /* 2D array of ipos */
215 /* m rows and n cols */
216 /* increments in row and col directions */
217 {
218     Bool    rows_first;
219     int     fx, fy, lx, ly;
220     int     i, j;
221 
222     if (p == NULL || tv == NULL)
223         return;
224 
225     fy = (ir > 0) ? 0 : m - 1;
226     ly = (ir > 0) ? m - 1 : 0;
227     fx = (ic > 0) ? 0 : n - 1;
228     lx = (ic > 0) ? n - 1 : 0;
229 
230     /* determine screen orientation of terrain image */
231 
232     if (ipos_y(p[ly][fx]) == ipos_y(p[fy][fx]))
233         rows_first = true;
234     else if (ipos_y(p[fy][lx]) == ipos_y(p[fy][fx]))
235         rows_first = false;
236     else
237     {
238         Ipos    rvec = {Ipos_id};
239         Ipos    cvec = {Ipos_id};
240         double  rtan, ctan;
241 
242         rvec = ipos_diff(p[ly][fx], p[fy][fx]);
243         rtan = fabs((double) ipos_y(rvec) / ipos_x(rvec));
244         cvec = ipos_diff(p[fy][lx], p[fy][fx]);
245         ctan = fabs((double) ipos_y(cvec) / ipos_x(cvec));
246 
247         rows_first = (rtan > ctan) ? true : false;
248     }
249 
250     if (rows_first == true)
251     {                           /* rows first then cols */
252         for (j = fx; j != lx; j += ic)  /* display bug fix: draw first
253                                          * line twice */
254             tv_hidden_line(tv, p[fy][j], p[fy][j + ic], false, -1);
255         for (i = fy;; i += ir)
256         {
257             for (j = fx; j != lx; j += ic)
258                 tv_hidden_line(tv, p[i][j], p[i][j + ic], false, -1);
259             if (i == ly)
260                 break;
261             for (j = fx;; j += ic)
262             {
263                 tv_hidden_line(tv, p[i][j], p[i + ir][j], false, -1);
264                 if (j == lx)
265                     break;
266             }
267         }
268     } else
269     {                           /* cols first then rows */
270 
271         for (i = fy; i != ly; i += ir)
272             tv_hidden_line(tv, p[i][fx], p[i + ir][fx], false, -1);
273         for (j = fx;; j += ic)
274         {
275             for (i = fy; i != ly; i += ir)
276                 tv_hidden_line(tv, p[i][j], p[i + ir][j], false, -1);
277             if (j == lx)
278                 break;
279             for (i = fy;; i += ir)
280             {
281                 tv_hidden_line(tv, p[i][j], p[i][j + ic], false, -1);
282                 if (i == ly)
283                     break;
284             }
285         }
286     }
287 }
288 
289 static Vec3 vec3_zero_z(Vec3 p)
290 {
291     vec3_z(p) = (float)0.0;
292     return (p);
293 }
294 
295 static void terrain_closest_corner2(Tv * tv, Vec3 ** p, int m, int n, int *piy, int *pix)
296 
297 /* 2D array of ipos */
298 /* m rows and n cols */
299 
300 {
301     float   depth, min_depth;
302     Vec3    c = {Vec3_id};      /* corner location */
303     int     i, j;
304 
305     *piy = 1;                   /* default values */
306     *pix = 1;
307 
308     if (tv == NULL)
309         return;
310 
311     m--;
312     n--;                        /* index last row and col */
313     c = vec3_zero_z(p[0][0]);   /* do not include local variation in
314                                  * height */
315     min_depth = (float)vec3_dot(vec3_diff(c, tv->centre3), tv->ez3);
316     for (i = 0; i < 2; ++i)
317         for (j = 0; j < 2; ++j)
318             if (i != 0 || j != 0)
319             {
320                 c = vec3_zero_z(p[i * m][j * n]);
321                 depth = (float)vec3_dot(vec3_diff(c, tv->centre3), tv->ez3);
322                 if (depth < min_depth)
323                 {
324                     *piy = (i) ? -1 : 1;
325                     *pix = (j) ? -1 : 1;
326                     min_depth = depth;
327                 }
328             }
329 }
330 
331 static void terrain_closest_corner(Tv * tv, Vec3 ** p, int m, int n, int *piy, int *pix)
332 
333 /* 2D array of ipos */
334 /* m rows and n cols */
335 
336 {
337     int     max_y;
338     int     i, j;
339 
340     *piy = 1;                   /* default values */
341     *pix = 1;
342 
343     if (tv == NULL)
344         return;
345 
346     m--;
347     n--;                        /* index last row and col */
348     max_y = ipos_y(tv_proj3(tv, vec3_zero_z(p[0][0])));
349     for (i = 0; i < 2; ++i)
350         for (j = 0; j < 2; ++j)
351             if (i != 0 || j != 0)
352             {
353                 int     y = ipos_y(tv_proj3(tv, vec3_zero_z(p[i * m][j * n])));
354 
355                 if (y > max_y)
356                 {
357                     *piy = (i) ? -1 : 1;
358                     *pix = (j) ? -1 : 1;
359                     max_y = y;
360                 }
361             }
362 }
363 
364 void    tv_terrain3_mask(Tv * tv, Vec3 ** p, char **mask, int m, int n)
365 
366 /* 2D array of x, y, z points */
367 
368 /* m rows and n cols */
369 {
370     int     i, j;
371 
372     if (p == NULL)
373         return;
374 
375     for (i = 0; i < m; ++i)
376         for (j = 0; j < n; ++j)
377         {
378             if (mask != NULL && !mask[i][j])
379                 continue;
380             if (j != n - 1 && (mask == NULL || mask[i][j + 1]))
381                 tv_line3(tv, p[i][j], p[i][j + 1]);
382             if (i != m - 1 && (mask == NULL || mask[i + 1][j]))
383                 tv_line3(tv, p[i][j], p[i + 1][j]);
384         }
385 }
386 
387 void    tv_terrain3(Tv * tv, Vec3 ** p, int m, int n)
388 
389 /* 2D array of x, y, z points */
390 /* m rows and n cols */
391 {
392     int     i, j;
393 
394     if (p == NULL)
395         return;
396 
397     for (i = 0; i < m; ++i)
398         for (j = 0; j < n; ++j)
399         {
400             if (j != n - 1)
401                 tv_line3(tv, p[i][j], p[i][j + 1]);
402             if (i != m - 1)
403                 tv_line3(tv, p[i][j], p[i + 1][j]);
404         }
405 }
406 
407 void    tv_terrain_hidden3(Tv * tv, Vec3 ** p, int m, int n)
408 
409 /* 2D array of ipos */
410 /* m rows and n cols */
411 {
412     Ipos  **ip;
413     int     i, j;
414     int     inc_x, inc_y;
415 
416     if (p == NULL)
417         return;
418 
419     ip = ts_narray_alloc(0, 0, m, n, Ipos);
420 
421     for (i = 0; i < m; ++i)
422         for (j = 0; j < n; ++j)
423             ip[i][j] = tv_proj3(tv, p[i][j]);   /* create an array of
424                                                  * Ipos */
425 
426     terrain_closest_corner2(tv, p, m, n, &inc_y, &inc_x);
427     tv_terrain_hidden2(tv, ip, m, n, inc_y, inc_x);
428     narray_free((char **) ip, 0, 0, m, n, sizeof(Ipos));
429 }
430 
431 /* ARGSUSED Quieten Lint */
432 static int tv_mean_gl(Tv * tv, Imrect * im, Vec3 ** p, int r, int c, int ir, int ic)
433 {
434     double  x = 0, y = 0;
435     int     gl;
436 
437     y = vec3_y(p[r][c]) + vec3_y(p[r + ir][c]) + vec3_y(p[r][c + ic]) + vec3_y(p[r + ir][c + ic]);
438     x = vec3_x(p[r][c]) + vec3_x(p[r + ir][c]) + vec3_x(p[r][c + ic]) + vec3_x(p[r + ir][c + ic]);
439 
440     y /= 4;
441     x /= 4;
442 
443     gl = im_sub_pix(im, y, x);
444 
445     if (gl < 0)
446         gl = 0;
447     if (gl > 255)
448         gl = 255;
449 
450     return (gl);
451 }
452 
453 static Bool use_inclusive_col(Ipos v1, Ipos v2) /* image vectors for
454                                                  * pixel boundry */
455 
456 {
457     float   t1, t2;
458 
459     if (ipos_x(v1) == 0)
460         return (true);          /* it does not matter which colour is
461                                  * used */
462     if (ipos_x(v2) == 0)
463         return ((ipos_y(v2) < 0) ? true : false);
464 
465     if (ipos_y(v1) == 0)
466         return ((ipos_y(v2) < 0) ? true : false);
467     if (ipos_y(v2) == 0)
468     {
469         if (ipos_x(v1) * ipos_x(v2) < 0)        /* oposite x directions */
470             return ((ipos_y(v1) < 0) ? true : false);
471         else
472             return ((ipos_y(v1) < 0) ? false : true);
473     }
474     if (ipos_x(v1) * ipos_x(v2) < 0)    /* oposite x directions */
475         return (true);
476 
477     t1 = (float) ipos_y(v1) / abs(ipos_x(v1));  /* kind of tangent */
478     t2 = (float) ipos_y(v2) / abs(ipos_x(v2));  /* kind of tangent */
479 
480     return ((t1 > t2) ? true : false);
481 }
482 
483 void    tv_terrain_fill3(Tv * tv, Vec3 ** p, int m, int n, Imrect * im)
484 
485 /* 2D array of ipos */
486 /* m rows and n cols */
487 
488 {
489     int     i, j;
490     int     ir, ic;
491     int     fx, fy, lx, ly;
492     Ipos    p1 = {Ipos_id};
493     Ipos    p2 = {Ipos_id};
494     Ipos    p3 = {Ipos_id};
495     Bool    rows_first;
496     int     col;
497 
498     if (tv == NULL || p == NULL)
499         return;
500 
501     tv_save_draw(tv);
502     terrain_closest_corner(tv, p, m, n, &ir, &ic);
503 
504     fy = (ir > 0) ? 0 : m - 1;
505     ly = (ir > 0) ? m - 1 : 0;
506     fx = (ic > 0) ? 0 : n - 1;
507     lx = (ic > 0) ? n - 1 : 0;
508 
509     p1 = tv_proj3(tv, vec3_zero_z(p[fy][fx]));
510     p2 = tv_proj3(tv, vec3_zero_z(p[fy][lx]));
511     p3 = tv_proj3(tv, vec3_zero_z(p[ly][fx]));
512 
513     /* determine screen orientation of terrain image */
514 
515     if (ipos_y(p3) == ipos_y(p1))
516         rows_first = true;
517     else if (ipos_y(p2) == ipos_y(p1))
518         rows_first = false;
519     else
520     {
521         Ipos    rvec = {Ipos_id};
522         Ipos    cvec = {Ipos_id};
523         double  rtan, ctan;
524 
525         rvec = ipos_diff(p3, p1);
526         rtan = fabs((double) ipos_y(rvec) / ipos_x(rvec));
527         cvec = ipos_diff(p2, p1);
528         ctan = fabs((double) ipos_y(cvec) / ipos_x(cvec));
529 
530         rows_first = (rtan > ctan) ? true : false;
531     }
532 
533     rows_first = true;
534     if (rows_first == true)
535     {
536         for (j = fx; j != lx; j += ic)
537         {                       /* fix X display bug */
538             p1 = tv_proj3(tv, p[fy][j]);
539             p2 = tv_proj3(tv, p[fy][j + ic]);
540             tv_hidden_line(tv, p1, p2, false, -1);
541         }
542 
543         for (i = fy; i != ly; i += ir)
544         {
545             for (j = fx; j != lx; j += ic)
546             {
547                 p1 = tv_proj3(tv, p[i][j]);
548                 p2 = tv_proj3(tv, p[i][j + ic]);
549                 p3 = tv_proj3(tv, p[i + ir][j]);
550 
551                 if (i == fy)
552                     col = tv_mean_gl(tv, im, p, i, j, ir, ic);
553                 else if (use_inclusive_col(ipos_diff(p2, p1), ipos_diff(p3, p1)))
554                     col = tv_mean_gl(tv, im, p, i, j, ir, ic);
555                 else
556                     col = tv_mean_gl(tv, im, p, i, j, -ir, ic);
557                 tv_hidden_line(tv, p1, p2, true, col);
558             }
559             for (j = fx;; j += ic)
560             {
561                 p1 = tv_proj3(tv, p[i][j]);
562                 if (j != lx)
563                     p2 = tv_proj3(tv, p[i][j + ic]);
564                 p3 = tv_proj3(tv, p[i + ir][j]);
565 
566                 if (j == lx)
567                     col = tv_mean_gl(tv, im, p, i, j, ir, -ic);
568                 else if (j == fx)
569                     col = tv_mean_gl(tv, im, p, i, j, ir, ic);
570                 else if (use_inclusive_col(ipos_diff(p3, p1), ipos_diff(p2, p1)))
571                     col = tv_mean_gl(tv, im, p, i, j, ir, ic);
572                 else
573                     col = tv_mean_gl(tv, im, p, i, j, ir, -ic);
574                 tv_hidden_line(tv, p1, p3, true, col);
575                 if (j == lx)
576                     break;
577             }
578         }
579         for (j = fx; j != lx; j += ic)
580         {
581             p1 = tv_proj3(tv, p[ly][j]);
582             p2 = tv_proj3(tv, p[ly][j + ic]);
583             tv_hidden_line(tv, p1, p2, true, -1);
584         }
585     } else
586     {
587         for (i = fy; i != ly; i += ir)  /* fix X display bug */
588             tv_hidden_line(tv, tv_proj3(tv, p[i][fx]), tv_proj3(tv, p[i + ir][fx]), false, -1);
589 
590         for (j = fx;; j += ic)
591         {
592             for (i = fy; i != ly; i += ir)
593             {
594                 int     col = (i == ly) ? -1 : tv_mean_gl(tv, im, p, i, j, ir, ic);
595 
596                 tv_hidden_line(tv, tv_proj3(tv, p[i][j]), tv_proj3(tv, p[i + ir][j]), true, col);
597             }
598             if (j == lx)
599                 break;
600             for (i = fy;; i += ir)
601             {
602                 int     col = (i == ly || j == lx) ? -1 : tv_mean_gl(tv, im, p, i, j, ir, ic);
603 
604                 tv_hidden_line(tv, tv_proj3(tv, p[i][j]), tv_proj3(tv, p[i][j + ic]), true, col);
605                 if (i == ly)
606                     break;
607             }
608         }
609     }
610     tv_reset_draw(tv);
611 }
612 
613 void    tv_terrain_skel(Tv * tv, Vec3 ** p, char **mask, int m, int n)
614 
615 /* 2D array of x, y, z points */
616 
617 /* m rows and n cols */
618 {
619     int     r, c;
620     int     ic, ir;
621 
622     if (tv == NULL || p == NULL)
623         return;
624 
625     ir = (m > 8) ? m / 8 : 1;
626     ic = (n > 8) ? n / 8 : 1;
627 
628     for (r = 0; r < m; r += ir)
629     {
630         for (c = 0; c < n; c += ic)
631         {
632             if (mask != NULL && !mask[r][c])
633                 continue;
634             if (r + ir < m && (mask == NULL || mask[r + ir][c]))
635                 tv_line3(tv, p[r][c], p[r + ir][c]);
636             if (c + ic < n && (mask == NULL || mask[r][c + ic]))
637                 tv_line3(tv, p[r][c], p[r][c + ic]);
638         }
639     }
640 }
641 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.