Пример #1
0
// 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;
}
Пример #2
0
void Vector3::rotate(float rx, float ry, float rz)
{
    rotatex(rx);
    rotatey(ry);
    rotatez(rz);
}