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