// draws the line void Tline::draw( Tsector *owner ) { coord3d x1r,y1r,x2r,y2r; coord3d t1,t2; coord2d x1,x2,x1c,x2c; Tmonotone mp,mph; Twall **w; coord3d ox1=verts[v1].x; coord3d oy1=verts[v1].y; coord3d ox2=verts[v2].x; coord3d oy2=verts[v2].y; // if the line is behind the portal, do nothing if (!infront(ox1,oy1) && !infront(ox2,oy2)) return; coord3d _portx1=portx1; coord3d _porty1=porty1; coord3d _portdx=portdx; coord3d _portdy=portdy; rotatez(ox1,oy1,&x1r,&y1r); // find the first vertex in camera space rotatez(ox2,oy2,&x2r,&y2r); // find the second vertex in camera space coord3d orx1=x1r; coord3d orx2=x2r; // calculates the vectors for the texture mapping Tvector a={x1r,y1r,view.z}; Tvector p={512*(x2r-x1r)/len,512*(y2r-y1r)/len,0}; Tvector q={0,0,512}; rotateyxv(&a); rotateyxv(&p); rotateyxv(&q); int clipfl=0; // checks if the line is visible on the screen if (y1r<=MINZ && y2r<=MINZ) { if (y1r<0 && y2r<0) return; if (x1r<0 && x2r<0) return; if (x1r>0 && x2r>0) return; if (y1r*fabs(x2r)+y2r*fabs(x1r)<0) return; x1c=x2c=0; // if the line is too close and is visible, it fills the whole screen clipfl=clLEFT|clRIGHT; } else { // if the line crosses the near plane, clip it if (y1r<MINZ || y2r<MINZ) { if (y1r<MINZ) { clipfl=clLEFT; t1=MINZ-y1r; t2=y2r-MINZ; x1r=splitab(x1r,x2r,t1,t2); y1r=MINZ; } if (y2r<MINZ) { clipfl=clRIGHT; t1=y1r-MINZ; t2=MINZ-y2r; x2r=splitab(x1r,x2r,t1,t2); y2r=MINZ; } } x1=projectx(x1r,y1r); x2=projectx(x2r,y2r); x1c=x1; x2c=x2; if (x1c<cur_clip->xmin) { x1c=cur_clip->xmin; clipfl&=~clDRAWLEFT; } if (x2c>cur_clip->xmax) { x2c=cur_clip->xmax; clipfl&=~clDRAWRIGHT; } } // if the line is perpendicular to the screen, or backfacing if (x1c>=x2c) { if (clipfl&clDRAW) { if (clipfl&clDRAWLEFT) x1c=cur_clip->xmin; if (clipfl&clDRAWRIGHT) x2c=cur_clip->xmax; if (x1c>=x2c) return; coord3d z0=(owner->getzf(ox1,oy1)*orx2-owner->getzf(ox2,oy2)*orx1)/(orx2-orx1); w=walls; for (int wi=0;wi<wallsnum;wi++,NEXTWALL(w)) { Twall *wp=*w; coord3d z1=(wp->z1c*orx2-wp->z2c*orx1)/(orx2-orx1); if (z0<=view.z && z1>=view.z) { // if there is a visible wall, fill the whole clip with it if (is_visible(wp)) goto dr; else break; } z0=z1; } return; dr: // fills the whole clip portx1=ox1; porty1=oy1; portdx=ox2-ox1; portdy=oy2-oy1; setdrawdata(&a,&p,&q); cur_clip->cut(x1c,x2c); cur_clip->clip(x1c,x2c,gymax,gymin,gymax,gymin,&mp); (*w)->draw(&mp); deltraps(mp.traps); cur_clip->last=mp.traps=new Ttrap(x2c,gymin,gymax,gymin,gymax,0,0,NULL); cur_clip->restore(mp.traps); portx1=_portx1; porty1=_porty1; portdx=_portdx; portdy=_portdy; return; } return; } portx1=ox1; porty1=oy1; portdx=ox2-ox1; portdy=oy2-oy1; // clips the line in world space (x and y in world space are needed to calculate the correct z) if (clipfl&clCLIPLEFT) { ox1=splitab(ox1,ox2,t1,t2); oy1=splitab(oy1,oy2,t1,t2); } else if (clipfl&clCLIPRIGHT) { ox2=splitab(ox1,ox2,t1,t2); oy2=splitab(oy1,oy2,t1,t2); } coord3d zf1=owner->getzf(ox1,oy1); coord3d zf2=owner->getzf(ox2,oy2); coord3d zc1=owner->getzc(ox1,oy1); coord3d zc2=owner->getzc(ox2,oy2); // finds the screen y coordinates (the screen x-es are x1c and x2c) coord2d pf1=projectz(zf1,y1r);// floor coord2d pf2=projectz(zf2,y2r); coord2d pc1=projectz(zc1,y1r);// ceiling coord2d pc2=projectz(zc2,y2r); // interpolates the z-s if the x-es are changed by cur_clip if (x1<x1c) { pf1=splitab(pf1,pf2,x1c-x1,x2-x1c); pc1=splitab(pc1,pc2,x1c-x1,x2-x1c); } if (x2>x2c) { pf2=splitab(pf1,pf2,x2c-x1c,x2-x2c); pc2=splitab(pc1,pc2,x2c-x1c,x2-x2c); } // cuts the portion of cur_clip that is over the walls cur_clip->cut(x1c,x2c); // clips the floor polygon with cur_clip cur_clip->clip(x1c,x2c,pf1,cur_clip->ymin,pf2,cur_clip->ymin,&mp); owner->draw_floor(&mp); deltraps(mp.traps); // clips the ceiling polygon with cur_clip cur_clip->clip(x1c,x2c,cur_clip->ymax,pc1,cur_clip->ymax,pc2,&mp); owner->draw_ceiling(&mp); deltraps(mp.traps); mph.traps=NULL; int wi; w=walls; // draws all the walls for (wi=0;wi<wallsnum;wi++,NEXTWALL(w)) { Twall *wp=*w; coord3d zq1=wp->z1c; coord3d zq2=wp->z2c; // interpolates z-s if necessary if (clipfl&clCLIPLEFT) zq1=splitab(zq1,zq2,t1,t2); if (clipfl&clCLIPRIGHT) zq2=splitab(zq1,zq2,t1,t2); // project the z-s coord2d pq1=projectz(zq1,y1r); coord2d pq2=projectz(zq2,y2r); // interpolates the projection if (x1<x1c) pq1=splitab(pq1,pq2,x1c-x1,x2-x1c); if (x2>x2c) pq2=splitab(pq1,pq2,x2c-x1c,x2-x2c); if (is_visible(wp)) { // if the wall is visible (wall or portal), draw it cur_clip->clip(x1c,x2c,pq1,pf1,pq2,pf2,&mp); if ((clipfl&clDRAW)) { if ((clipfl&clDRAWLEFT) && pq1>0 && pf1<0) cur_clip->addbeg(&mp); else if ((clipfl&clDRAWRIGHT) && pq2>0 && pf2<0) cur_clip->addend(&mp); } setdrawdata(&a,&p,&q); (*w)->draw(&mp); deltraps(mp.traps); } else { // if the wall is a hole, clip it only cur_clip->clip(x1c,x2c,pq1,pf1,pq2,pf2,&mph); } pf1=pq1; pf2=pq2; } // restores cur_clip if (mph.traps) { Ttrap *t; for (t=mph.traps;t->next;t=t->next); cur_clip->last=t; } else { cur_clip->last=mph.traps=new Ttrap(x2c,gymin,gymax,gymin,gymax,0,0,NULL); } cur_clip->restore(mph.traps); portx1=_portx1; porty1=_porty1; portdx=_portdx; portdy=_portdy; }
void Vector3::rotate(float rx, float ry, float rz) { rotatex(rx); rotatey(ry); rotatez(rz); }