1 /*
2   XBlockOut a 3D Tetris
3 
4   Copyright (C) 1992,1993,1994,2001  Thierry EXCOFFIER
5 
6   This program is free software; you can redistribute it and/or modify
7   it under the terms of the GNU General Public License as published by
8   the Free Software Foundation; either version 1, or (at your option)
9   any later version.
10 
11   This program is distributed in the hope that it will be useful,
12   but WITHOUT ANY WARRANTY; without even the implied warranty of
13   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14   GNU General Public License for more details.
15 
16   You should have received a copy of the GNU General Public License
17   along with this program; if not, write to the Free Software
18   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 
20   Contact: Thierry.EXCOFFIER@liris.univ-lyon1.fr
21 */
22 #include <stdio.h>
23 #include <X11/Xlib.h>
24 #include "transfo.h"
25 #include "view.h"
26 #include "define.h"
27 #include "movingbloc.h"
28 #if HAVE_STDLIB_H
29 #include <stdlib.h>
30 #endif
31 #include <memory.h>
32 
33 #ifdef HAVE_MALLOC_H
34 #include "malloc.h"
35 #endif
36 
37 #ifndef abs
38 #define abs(X) ( X>0?X:-(X) )
39 #endif
40 
41 /* This structure is redondant, the problem is that in many cases
42    the XDrawLines is slower than XDrawSegments */
43 #define USESEGMENTS
44 
45 #define MEMO_SEG (64*12)
46 
47 struct polypolyline
48 {
49   int	maxnbpoints ;		/* Max size of "points" table */
50 #ifdef USESEGMENTS
51   int	nbpoints ;
52   XSegment *segment ;		/* The segments */
53 #else
54   int	*nbpoints ;		/* Table of points number by polyline */
55   XPoint  *points ;		/* All the points */
56 #endif
57 } ;
58 
59 /* Contain last draw line bloc */
60 static struct polypolyline lastlinebloc = {0,0, NULL} ;
61 
62 /* Definition of a bloc : a string
63 
64 y
65 ^
66 |
67 |
68 /------> x
69 /
70 V
71 z
72 l : x--
73 r : x++
74 d : y--
75 u : y++
76 f : z++
77 b : z--
78 */
createbloc(char * def)79 struct bloc *createbloc(char *def)
80 {
81   int xmin,xmax,ymin,ymax,zmin,zmax ;
82   int x,y,z ;
83   char *pc ;
84   struct bloc *b ;
85 
86   xmin = ymin = zmin = xmax = ymax = zmax = x = y = z =0 ;
87 
88   pc = def ;
89   while( *pc )
90     switch( *pc++ )
91       {
92       case 'l' : x-- ; if ( x<xmin ) xmin=x ;
93 	break ;
94       case 'r' : x++ ; if ( x>xmax ) xmax=x ;
95 	break ;
96       case 'd' : y-- ; if ( y<ymin ) ymin=y ;
97 	break ;
98       case 'u' : y++ ; if ( y>ymax ) ymax=y ;
99 	break ;
100       case 'b' : z-- ; if ( z<zmin ) zmin=z ;
101 	break ;
102       case 'f' : z++ ; if ( z>zmax ) zmax=z ;
103 	break ;
104       default  : fprintf(stderr,"Bad Description %s\n",def) ;
105 	exit(1) ;
106       }
107 
108   b = allocbloc(xmax-xmin+1,ymax-ymin+1,zmax-zmin+1) ;
109 
110 
111   pc = def ;
112   x = y = z = 0 ;
113   do
114     {
115       notecube(b,z-zmin,y-ymin,x-xmin) ;
116       switch( *pc )
117 	{
118 	case 'l' : x-- ; break ;
119 	case 'r' : x++ ; break ;
120 	case 'd' : y-- ; break ;
121 	case 'u' : y++ ; break ;
122 	case 'b' : z-- ; break ;
123 	case 'f' : z++ ; break ;
124 	}
125     }
126   while( *pc++ ) ;
127 
128   b->name = def ;
129   b->world = 0 ;
130 
131   createsegments(b) ;
132 
133   return(b) ;
134 }
135 
createsegments(struct bloc * b)136 void createsegments(struct bloc *b)
137 {
138   int i,j ;
139   int nbtmp ;
140   struct edge *tmp,swap ;
141   struct point *start,*end,*sw ;
142 
143   nbtmp = 0 ;
144   tmp = (struct edge*) malloc( b->nbedges*sizeof(*tmp) ) ;
145 
146   start = end = NULL ; /* Only to remove a GCC warning */
147 
148   /* First stage : concatenate lines */
149   for(i=0;i<b->nbedges;i++)
150     {
151       if ( b->edge[i].nb_acces!=2 && b->edge[i].nb_acces!=4 )
152 	{
153 	  for ( j=0;j<nbtmp;j++ )
154 	    {
155 	      if ( tmp[j].start==b->edge[i].start )
156 		{
157 		  start = tmp[j].end ;
158 		  end   = b->edge[i].end ;
159 		}
160 	      else
161 		if ( tmp[j].start==b->edge[i].end )
162 		  {
163 		    start = tmp[j].end ;
164 		    end   = b->edge[i].start ;
165 		  }
166 		else
167 		  if ( tmp[j].end==b->edge[i].end )
168 		    {
169 		      start = tmp[j].start ;
170 		      end   = b->edge[i].start ;
171 		    }
172 		  else
173 		    if ( tmp[j].end==b->edge[i].start )
174 		      {
175 			start = tmp[j].start ;
176 			end   = b->edge[i].end ;
177 		      }
178 		    else continue ;
179 
180 	      /* Two points in a row */
181 	      if ( start->coord[0]==end->coord[0] )
182 		{
183 		  if ( start->coord[1]==end->coord[1] ) break ;
184 		  if ( start->coord[2]==end->coord[2] ) break ;
185 		}
186 	      if ( start->coord[1]==end->coord[1] )
187 		{
188 		  if ( start->coord[2]==end->coord[2] ) break ;
189 		}
190 	    }
191 	  if ( j==nbtmp )
192 	    {
193 	      /* Not stretch an existing line */
194 	      tmp[j].start = b->edge[i].start ;
195 	      tmp[j].end   = b->edge[i].end ;
196 	      nbtmp++ ;
197 	    }
198 	  else    {
199 	    /* Stretch an existing line */
200 	    tmp[j].start = start ;
201 	    tmp[j].end   = end ;
202 	  }
203 	}
204     }
205   /* Second stage : change order, for create polyline */
206   for(i=0;i<nbtmp;i++)
207     for(j=nbtmp-1;j>i;j--)
208       {
209 	if ( tmp[i].end==tmp[j].start )
210 	  {
211 	    swap = tmp[j] ;
212 	    tmp[j] = tmp[i+1] ;
213 	    tmp[i+1] = swap ;
214 	    break ;
215 	  }
216 	if ( tmp[i].end==tmp[j].end )
217 	  {
218 	    swap = tmp[j] ;
219 	    sw = swap.start ;
220 	    swap.start = swap.end ;
221 	    swap.end = sw ;
222 	    tmp[j] = tmp[i+1] ;
223 	    tmp[i+1] = swap ;
224 	    break ;
225 	  }
226       }
227 
228   if ( b->segments ) free( (void*)b->segments ) ;
229   b->nbsegments = nbtmp ;
230   b->segments = tmp ;
231 }
232 
233 
234 
notecube(struct bloc * b,int z,int y,int x)235 void notecube(struct bloc *b, int z, int y, int x)
236 {
237   int i,j,k ;
238 
239   if ( b->t[z][y][x]!=0 ) return ;
240   b->t[z][y][x] = 1 ;
241   b->nbcubes++ ;
242 
243   for(i=0;i<8;i++)
244     for(j=i+1;j<8;j++)
245       {
246 	k = i^j ;
247 	if ( k==1 || k==2 || k==4 )
248 	  createedge(b,z+(i&1),y+((i/2)&1),x+((i/4)&1),
249 		     z+(j&1),y+((j/2)&1),x+((j/4)&1)  ) ;
250       }
251 }
252 
noteface(struct bloc * b,int x1,int y1,int z1,int x2,int y2,int z2,int x3,int y3,int z3,int x4,int y4,int z4,int l)253 void noteface(struct bloc *b, int x1, int y1, int z1, int x2, int y2, int z2, int x3, int y3, int z3, int x4, int y4, int z4, int l)
254 {
255   b->face[b->nbfaces].p[0] = createpoint(b,z1,y1,x1) ;
256   b->face[b->nbfaces].p[1] = createpoint(b,z2,y2,x2) ;
257   b->face[b->nbfaces].p[2] = createpoint(b,z3,y3,x3) ;
258   b->face[b->nbfaces].p[3] = createpoint(b,z4,y4,x4) ;
259   b->face[b->nbfaces].level = b->dz-l-1 ;
260   b->nbfaces++ ;
261 }
262 
263 
createfaces(struct bloc * b)264 void createfaces(struct bloc *b)
265 {
266   int i,j,k,l ;
267   if ( b->face==NULL )
268     b->face = (struct face*)
269       malloc( 6*b->dx*b->dy*b->dz*sizeof(struct face) ) ;
270   b->nbfaces = 0 ;
271   for(k=b->dz-1;k>=0;k--)
272     for(l=0;l<3;l++)
273       for(i=0;i<b->dx;i++)
274 	for(j=0;j<b->dy;j++)
275 	  if ( b->t[k][j][i] )
276 	    {
277 	      switch(l)
278 		{
279 		case 2 :
280 		  if ( k==0 || b->t[k-1][j][i]=='\0' )
281 		    noteface(b,i,j,k,i+1,j,k,i+1,j+1,k,i,j+1,k ,k) ;
282 		  break ;
283 		case 1 :
284 		  if ( i==0 || b->t[k][j][i-1]=='\0' )
285 		    noteface(b,i,j,k,i,j+1,k,i,j+1,k+1,i,j,k+1 ,k) ;
286 		  if ( j==0 || b->t[k][j-1][i]=='\0' )
287 		    noteface(b,i,j,k,i,j,k+1,i+1,j,k+1,i+1,j,k ,k) ;
288 		  if ( i==b->dx-1 || b->t[k][j][i+1]=='\0' )
289 		    noteface(b,i+1,j,k,i+1,j,k+1,i+1,j+1,k+1,i+1,j+1,k ,k) ;
290 		  if ( j==b->dy-1 || b->t[k][j+1][i]=='\0' )
291 		    noteface(b,i,j+1,k,i+1,j+1,k,i+1,j+1,k+1,i,j+1,k+1 ,k) ;
292 		  break ;
293 		case 0 :
294 		  if ( k==b->dz-1 || b->t[k+1][j][i]=='\0' )
295 		    noteface(b,i,j,k+1,i,j+1,k+1,i+1,j+1,k+1,i+1,j,k+1 ,k) ;
296 		  break ;
297 		}
298 	    }
299 }
300 
301 
createedge(struct bloc * b,int z1,int y1,int x1,int z2,int y2,int x2)302 void createedge(struct bloc *b, int z1, int y1, int x1, int z2, int y2, int x2)
303 {
304   struct point *start,*end ;
305   struct edge *e ;
306 
307   start = createpoint(b,z1,y1,x1) ;
308   end   = createpoint(b,z2,y2,x2) ;
309 
310   e = start->edge ;
311   while( e )
312     {
313       if ( e->end==end ) break ;
314       e = e->next ;
315     }
316 
317   if ( e == NULL )
318     {
319       b->edge[b->nbedges].start = start ;
320       b->edge[b->nbedges].end   = end ;
321       b->edge[b->nbedges].nb_acces = 1 ;
322       b->edge[b->nbedges].next  = start->edge ;
323       start->edge = &b->edge[b->nbedges] ;
324       b->nbedges++ ;
325     }
326   else e->nb_acces++ ;
327 }
328 
createpoint(struct bloc * b,int z,int y,int x)329 struct point *createpoint(struct bloc *b, int z, int y, int x)
330 {
331   int i ;
332 
333   i = ((z*(b->dy+1))+y)*(b->dx+1) + x ;
334 
335   if ( i>=b->nbpoints ) fprintf(stderr,"BUG : Impossible case\n") ;
336 
337   if ( ! b->point[i].in_a_bloc )
338     {
339       b->point[i].coord[0] = x ;
340       b->point[i].coord[1] = y ;
341       b->point[i].coord[2] = z ;
342       b->point[i].next = b->firstpoint ;
343       b->point[i].edge = NULL ;
344       b->point[i].in_a_bloc = 1 ;
345       b->firstpoint = &b->point[i] ;
346     }
347   return( &b->point[i] ) ;
348 }
349 
350 
allocbloc(int dx,int dy,int dz)351 struct bloc *allocbloc(int dx, int dy, int dz)
352 {
353   struct bloc *b ;
354   int i,j ;
355   char *pc ;
356 
357   b = (struct bloc*) malloc( sizeof(struct bloc) ) ;
358   b->dx = dx ;
359   b->dy = dy ;
360   b->dz = dz ;
361   b->nbedges = 0 ;
362   b->nbfaces = 0 ;
363   b->nbcubes = 0 ;
364   b->edge = (struct edge*)
365     malloc( (b->dz+1)*(b->dy+1)*(b->dx+1)*3*sizeof(struct edge) ) ;
366   b->nbpoints = (b->dz+1)*(b->dy+1)*(b->dx+1) ;
367   b->point = (struct point*)
368     malloc( b->nbpoints*sizeof(struct point) ) ;
369   b->face = NULL ;
370   b->segments = NULL ;
371   for(i=0;i<b->nbpoints;i++)
372     {
373       b->point[i].next = NULL ;
374       b->point[i].edge = NULL ;
375       b->point[i].in_a_bloc = 0 ;
376     }
377   b->firstpoint = NULL ;
378 
379   b->t = (char***) malloc( b->dz*sizeof(char **) ) ;
380   pc   = (char*) malloc( (unsigned)(b->dz*b->dy*b->dx) ) ;
381   memset( (void*)pc , '\0' , b->dz*b->dy*b->dx ) ;
382   for(i=0;i<b->dz;i++)
383     {
384       b->t[i] = (char**) malloc( b->dy*sizeof(char*) ) ;
385       for(j=0;j<b->dy;j++)
386 	{
387 	  b->t[i][j] = pc ;
388 	  pc += b->dx ;
389 	}
390     }
391   return(b) ;
392 }
393 
394 
freebloc(struct bloc * b)395 void freebloc(struct bloc *b)
396 {
397   int i ;
398 
399   free( (void*)b->t[0][0] ) ;
400   for(i=0;i<b->dz;i++) free( (void*)b->t[i] ) ;
401   free( (void*)b->t ) ;
402   free( (void*)b->edge ) ;
403   free( (void*)b->point ) ;
404   if ( b->face ) free( (void*)b->face ) ;
405   if ( b->segments ) free( (void*)b->segments ) ;
406   free( (void*)b ) ;
407 }
408 
409 
410 
411 /*--------------------------*/
412 /* Utility for polypolyline */
413 /*--------------------------*/
newpolypolyline(struct polypolyline * oldone,int nbpoints)414 void newpolypolyline(struct polypolyline *oldone, int nbpoints)
415 {
416   if ( nbpoints<=oldone->maxnbpoints ) return ; /* Nothing to do */
417   if ( oldone->maxnbpoints!=0 )
418     {
419 #ifndef USESEGMENTS
420       free( (void*)oldone->nbpoints ) ;
421       free( (void*)oldone->points ) ;
422 #else
423       free( (void*)oldone->segment ) ;
424 #endif
425     }
426 #ifndef USESEGMENTS
427   oldone->nbpoints = (int *) malloc(2*nbpoints*sizeof( *(oldone->nbpoints) ) ) ;
428   oldone->points   = (XPoint *) malloc(2*nbpoints*sizeof( *(oldone->points) ) ) ;
429   oldone->nbpoints[0] = 0 ;
430 #else
431   oldone->segment  = (XSegment *) malloc(nbpoints*sizeof( *(oldone->segment) ) ) ;
432   oldone->nbpoints = 0 ;
433 #endif
434   oldone->maxnbpoints = nbpoints ;
435 }
drawpolypolyline(Display * disp,Drawable d,GC gc,struct polypolyline * ppl)436 void drawpolypolyline(Display *disp, Drawable d, GC gc, struct polypolyline *ppl)
437 {
438 #ifndef USESEGMENTS
439   int i,j ;
440 #endif
441 
442   if ( ppl->maxnbpoints==0 ) return ;
443 #ifndef USESEGMENTS
444   i = 0 ;
445   j = 0 ;
446   while( ppl->nbpoints[i] )
447     {
448       XDrawLines(disp,d,gc,&ppl->points[j],ppl->nbpoints[i],CoordModeOrigin) ;
449       j += ppl->nbpoints[i] ;
450       i++ ;
451     }
452 #else
453   XDrawSegments(disp,d,gc,ppl->segment,ppl->nbpoints) ;
454 #endif
455 }
456 /* Copy second into first */
copypolypolyline(struct polypolyline * ppl1,struct polypolyline * ppl2)457 void copypolypolyline(struct polypolyline *ppl1, struct polypolyline *ppl2)
458 {
459   int i ;
460 #ifndef USESEGMENTS
461   int j,k ;
462 #endif
463 
464   newpolypolyline(ppl1,ppl2->maxnbpoints) ;
465 #ifndef USESEGMENTS
466   i = 0 ;
467   k = 0 ;
468   while( ppl2->nbpoints[i] )
469     {
470       ppl1->nbpoints[i] = ppl2->nbpoints[i] ;
471       for(j=0;j<ppl1->nbpoints[i];j++)
472 	{
473 	  ppl1->points[k] =  ppl2->points[k] ;
474 	  k++ ;
475 	}
476       i++ ;
477     }
478   ppl1->nbpoints[i] = 0 ;
479 #else
480   for(i=0;i<ppl2->nbpoints;i++) ppl1->segment[i] = ppl2->segment[i] ;
481   ppl1->nbpoints = ppl2->nbpoints ;
482 #endif
483 }
484 /*--------------------------*/
485 
drawlinebloc(Display * disp,Drawable d,GC gc,struct bloc * b,struct transfo * t,struct viewtransfo * view,struct point * min,struct point * max)486 void drawlinebloc(Display *disp, Drawable d, GC gc, struct bloc *b, struct transfo *t, struct viewtransfo *view, struct point *min, struct point *max)
487 {
488   int i ;
489 #ifndef USESEGMENTS
490   int l,k ;
491 #endif
492 
493   newpolypolyline( &lastlinebloc,b->nbsegments*2 ) ;
494   transfopoint(b,t,view,min,max) ;
495 #ifndef USESEGMENTS
496   k = 0 ;
497   l = 0 ;
498   for(i=0;i<b->nbsegments;i++)
499     {
500       j = l ;
501       lastlinebloc.points[l].x = b->segments[i].start->x ;
502       lastlinebloc.points[l].y = b->segments[i].start->y ;
503       while( b->segments[i].end == b->segments[i+1].start &&
504 	     i+1<b->nbsegments)
505 	{
506 	  i++ ; l++ ;
507 	  lastlinebloc.points[l].x = b->segments[i].start->x ;
508 	  lastlinebloc.points[l].y = b->segments[i].start->y ;
509 	}
510       l++ ;
511       lastlinebloc.points[l].x = b->segments[i].end->x ;
512       lastlinebloc.points[l].y = b->segments[i].end->y ;
513       l++ ;
514       lastlinebloc.nbpoints[k++] = l-j ;
515     }
516   lastlinebloc.nbpoints[k] = 0 ;
517 #else
518   for(i=0;i<b->nbsegments;i++)
519     {
520       lastlinebloc.segment[i].x1 = b->segments[i].start->x ;
521       lastlinebloc.segment[i].y1 = b->segments[i].start->y ;
522       lastlinebloc.segment[i].x2 = b->segments[i].end->x ;
523       lastlinebloc.segment[i].y2 = b->segments[i].end->y ;
524     }
525   lastlinebloc.nbpoints = b->nbsegments ;
526 #endif
527   drawpolypolyline(disp,d,gc,&lastlinebloc) ;
528 }
529 
clearlinebloc(Display * disp,Drawable d,GC gc)530 int clearlinebloc(Display *disp, Drawable d, GC gc)
531 {
532 #ifndef USESEGMENTS
533   if ( lastlinebloc.nbpoints[0]!=0 )
534 #else
535     if ( lastlinebloc.nbpoints!=0 )
536 #endif
537       {
538 	drawpolypolyline(disp,d,gc,&lastlinebloc) ;
539 #ifndef USESEGMENTS
540 	lastlinebloc.nbpoints[0] = 0 ;
541 #else
542 	lastlinebloc.nbpoints = 0 ;
543 #endif
544 	return(1) ;
545       }
546   return(0) ;
547 }
548 
clearlastline(Display * disp,Drawable d,GC gc)549 void clearlastline(Display *disp, Drawable d, GC gc)
550 {
551   static struct polypolyline memo = {0,0,NULL} ;
552   drawpolypolyline(disp,d,gc,&memo) ;
553   copypolypolyline(&memo,&lastlinebloc) ;
554 }
555 
forgetlinebloc(void)556 void forgetlinebloc(void)
557 {
558 #ifndef USESEGMENTS
559   lastlinebloc.nbpoints[0] = 0 ;
560 #else
561   lastlinebloc.nbpoints = 0 ;
562 #endif
563 }
564 
565 
drawfacebloc(Display * disp,Drawable d,GC * gc,GC gcl,struct bloc * b,struct transfo * t,struct viewtransfo * view,struct point * min,struct point * max)566 void drawfacebloc(Display *disp, Drawable d, GC *gc, GC gcl, struct bloc *b, struct transfo *t, struct viewtransfo *view, struct point *min, struct point *max)
567 {
568   int i,j,vx1,vy1,vx2,vy2,pv ;
569   XPoint p[5] ;
570 
571   transfopoint(b,t,view,min,max) ;
572   for(i=0;i<b->nbfaces;i++)
573     {
574       for(j=0;j<4;j++)
575 	{
576 	  p[j].x = b->face[i].p[j]->x ;
577 	  p[j].y = b->face[i].p[j]->y ;
578 	}
579       vx1 = p[1].x - p[0].x ;
580       vy1 = p[1].y - p[0].y ;
581       vx2 = p[2].x - p[1].x ;
582       vy2 = p[2].y - p[1].y ;
583       pv = vx1*vy2-vx2*vy1 ;
584       if ( pv>0 )
585 	{
586 	  XFillPolygon( disp,d,gc[b->face[i].level%FACECOLOR],
587 			p,4,Convex,CoordModeOrigin ) ;
588 	  p[4] = p[0] ;
589 	  XDrawLines( disp,d,gcl,p,5,CoordModeOrigin ) ;
590 	}
591     }
592 }
593 
drawtranspbloc(Display * disp,Drawable d,GC gc,GC gcl,struct bloc * b,struct transfo * t,struct viewtransfo * view,struct point * min,struct point * max)594 void drawtranspbloc(Display *disp, Drawable d, GC gc, GC gcl, struct bloc *b, struct transfo *t, struct viewtransfo *view, struct point *min, struct point *max)
595 {
596   int i,j,k,vx1,vy1,vx2,vy2,pv ;
597   XSegment s[MEMO_SEG] ;
598   XPoint p[5] ;
599 
600   transfopoint(b,t,view,min,max) ;
601 
602   for(i=0;i<b->nbfaces;i++)
603     {
604       for(j=0;j<4;j++)
605 	{
606 	  p[j].x = b->face[i].p[j]->x ;
607 	  p[j].y = b->face[i].p[j]->y ;
608 	}
609       vx1 = p[1].x - p[0].x ;
610       vy1 = p[1].y - p[0].y ;
611       vx2 = p[2].x - p[1].x ;
612       vy2 = p[2].y - p[1].y ;
613       pv = vx1*vy2-vx2*vy1 ;
614       if ( pv>0 )
615 	XFillPolygon( disp,d,gc,
616 		      p,4,Convex,CoordModeOrigin ) ;
617     }
618 
619   k = 0 ;
620   for(i=0;i<b->nbfaces;i++)
621     {
622       for(j=0;j<4;j++)
623 	{
624 	  s[k].x1 = b->face[i].p[j]->x ;
625 	  s[k].y1 = b->face[i].p[j]->y ;
626 	  s[k].x2 = b->face[i].p[(j+1)%4]->x ;
627 	  s[k].y2 = b->face[i].p[(j+1)%4]->y ;
628 	  if ( s[k].x1 > s[k].x2 ||
629 	       ( s[k].x1 == s[k].x2 && s[k].y1 > s[k].y2 )
630 	       )
631 	    {
632 	      if ( k<MEMO_SEG ) k++ ;
633 	      else fprintf(stderr,"Too many seg %s:%d\n",
634 			   __FILE__,__LINE__) ;
635 	    }
636 	}
637     }
638   XDrawSegments(disp,d,gcl,s,k) ;
639 
640 }
641 
642 
643 /* Compute all point position of the bloc, even if point are not used */
transfopoint(struct bloc * b,struct transfo * t,struct viewtransfo * view,struct point * min,struct point * max)644 void transfopoint(struct bloc *b, struct transfo *t, struct viewtransfo *view, struct point *min, struct point *max)
645 {
646   float curx[3],cury[3],curz[3],dirx[3],diry[3],dirz[3],v[3] ;
647   struct point *p ;
648   int i,j,k,l,m ;
649 
650   if ( b->world==1 ) return ; /* The world doesn't move */
651   p = b->point ;
652   m = 0 ;
653 
654   for(i=0;i<3;i++)
655     {
656       curz[i] = 0. ;
657       dirx[i] = t->mat[i][0] ;
658       diry[i] = t->mat[i][1] ;
659       dirz[i] = t->mat[i][2] ;
660     }
661 
662   for(k=0;k<=b->dz;k++)
663     {
664       cury[0] = curz[0] ;
665       cury[1] = curz[1] ;
666       cury[2] = curz[2] ;
667       for(j=0;j<=b->dy;j++)
668 	{
669 	  curx[0] = cury[0] ;
670 	  curx[1] = cury[1] ;
671 	  curx[2] = cury[2] ;
672 
673 	  l = b->dx ;
674 	  if ( !b->world ) while( l>=0 && !p[l].in_a_bloc ) l-- ;
675 
676 	  for(i=0;i<=l;i++)
677 	    {
678 	      if ( p->in_a_bloc || b->world ) /* All point in world */
679 		{
680 		  v[0] = curx[0] + t->vec[0] ;
681 		  v[1] = curx[1] + t->vec[1] ;
682 		  v[2] = curx[2] + t->vec[2] ;
683 		  p->x = (int)(((v[0]+view->eye_distance)/v[2]-view->eye_distance/PERSP)*view->xprod) ;
684 		  if ( view->eye_distance*view->cross_eyed > 0 )
685 		    p->x += 3*view->xcenter/2 ;
686 		  else
687 		    if ( view->eye_distance*view->cross_eyed < 0 )
688 		      p->x += view->xcenter/2 ;
689 		    else p->x += view->xcenter ;
690 
691 		  p->y = (int)(v[1]/v[2]*view->yprod)+view->ycenter ;
692 		  if ( m==0 )
693 		    {
694 		      m = 1 ;
695 		      min->x = max->x = p->x ;
696 		      min->y = max->y = p->y ;
697 		    }
698 		  else
699 		    {
700 		      if ( p->x<min->x ) min->x = p->x ;
701 		      else
702 			if ( p->x>max->x ) max->x = p->x ;
703 		      if ( p->y<min->y ) min->y = p->y ;
704 		      else
705 			if ( p->y>max->y ) max->y = p->y ;
706 		    }
707 		}
708 	      curx[0] += dirx[0] ;
709 	      curx[1] += dirx[1] ;
710 	      curx[2] += dirx[2] ;
711 
712 	      p++ ;
713 	    }
714 	  p += b->dx - l ;
715 	  cury[0] += diry[0] ;
716 	  cury[1] += diry[1] ;
717 	  cury[2] += diry[2] ;
718 	}
719       curz[0] += dirz[0] ;
720       curz[1] += dirz[1] ;
721       curz[2] += dirz[2] ;
722     }
723 
724   max->x++ ;
725   max->y++ ;
726 
727   if ( min->x<0 ) min->x = 0 ;
728   if ( min->y<0 ) min->y = 0 ;
729   if ( b->world ) b->world = 1 ; /* No more compute for world points */
730 }
731