GEOMETRY.C

Go to the documentation of this file.
00001 // file GEOMETRY.CPP
00002 
00003 
00004 #define MODULE_GEO
00005 
00006 #include "render.h"
00007 
00008 
00009 static unsigned char *AllocateShadowBuffer(void);
00010 static void ApplyVertexEffect(long effect, vertex *v, long N, double time,
00011                               double vmin[], double vmax[], ivector Og);
00012 static void FixUpMapEdge(GLfloat a[]);
00013 static void NewPoint(double plane, vector p1, vector p2, vector p, 
00014                      vector2, vector2, vector2);
00015 
00016 
00017 
00018 static void NewPoint(double dp, vector v1, vector v2, vector p, 
00019                                vector2 uv1, vector2 uv2, vector2 uv){
00020  double mu;
00021  mu=(v2[1]-v1[1]);
00022  if(fabs(mu) < 1.0)mu=0.0;
00023  else mu=(dp-v1[1])/mu;
00024  p[1]=dp;
00025  p[0]=v1[0]+mu*(v2[0]-v1[0]);
00026  p[2]=v1[2]+mu*(v2[2]-v1[2]);
00027  uv[0] = uv1[0]+mu*(uv2[0]-uv1[0]);
00028  uv[1] = uv1[1]+mu*(uv2[1]-uv1[1]);
00029 }
00030 
00031 static void  NewMapPoint(double dp, vector a1, vector a2, 
00032                          double u1, double u2, 
00033                          double v1, double v2,
00034                          double w1, double w2, 
00035                          vector r){
00036  double mu;
00037  mu=(a2[1]-a1[1]);
00038  if(fabs(mu) < 1.0)mu=0.0;
00039  else mu=(dp-a1[1])/mu;
00040  r[0] = u1 + mu*(u2 - u1);
00041  r[1] = v1 + mu*(v2 - v1);
00042  r[2] = w1 + mu*(w2 - w1);
00043 }
00044 
00045 short ClipObject(long O){
00046   vertex   *v;
00047   face     *f;
00048   double y1,y2,y3,dp;
00049   long i,i1,i2,i3,xv,xf,sz,vp,fp;
00050   vector2 uv1,uv2,uva,uvb;
00051   vector  a,b;
00052 /* any faces that span the projection plane have to be turned into
00053    three faces with new vertices on the projection plane.
00054 */
00055 //  dp=1.000;
00056   dp=FRONT_CLIPPING_PLANE;
00057   xv=0; xf=0;
00058   v=Object[O].Vbase;
00059   f=Object[O].Fbase;
00060   for(i=0;i<Object[O].NoFaces;i++){
00061      i1= -1;
00062      y1=v[f[i].V[0]].p[1];
00063      y2=v[f[i].V[1]].p[1];
00064      y3=v[f[i].V[2]].p[1];
00065      if     (y1 <= dp && y2 <=dp && y3 >  dp)i1 = 2;
00066      else if(y1 <= dp && y2 > dp && y3 <= dp)i1 = 1;
00067      else if(y1 <= dp && y2 > dp && y3 >  dp)i1 = 0;
00068      else if(y1 >  dp && y2 <=dp && y3 <= dp)i1 = 0;
00069      else if(y1 >  dp && y2 <=dp && y3 >  dp)i1 = 1;
00070      else if(y1 >  dp && y2 > dp && y3 <= dp)i1 = 2;
00071      if(i1 >= 0){ /* calculate number of extra faces and vertices */
00072        xv += 2; xf += 2;
00073      }
00074   }
00075   if(xv == 0)return OK;  /* no clipping necessary */
00076   //if(debug != NULL)fprintf(debug,"Clipping necessary extra vertices %ld faces %ld\n",xv,xf);
00077 #if 0
00078 fprintf(debug,"extra v=%ld face=%ld\n",xv,xf);
00079 for(i=0;i<Object[O].NoFaces;i++){
00080 int j;
00081 fprintf(debug,"Face %ld vertices (%ld %ld %ld)\n",i,(f+i)->V[0],(f+i)->V[1],(f+i)->V[2]);
00082 for(j=0;j<3;j++){
00083 fprintf(debug,"(Vvert %8.1lf %8.1lf %8.1lf) (mapping  %lf %lf)\n",
00084 (v+(f+i)->V[j])->p[0],(v+(f+i)->V[j])->p[1],(v+(f+i)->V[j])->p[2],
00085 (f+i)->uu[j],(f+i)->vv[j]);
00086 }
00087 }
00088 #endif
00089   /* resize the arrays and do it */
00090   sz=(Object[O].NoVertices+xv)*(long)sizeof(vertex);
00091   if((v=(vertex  *)X__Realloc(Object[O].Vbase,sz)) == NULL)goto X__ERROR;
00092   Object[O].Vbase=v;
00093   sz=(Object[O].NoFaces+xf)*(long)sizeof(face);
00094   if((f=(face  *)X__Realloc(Object[O].Fbase,sz)) == NULL)goto X__ERROR;
00095   Object[O].Fbase=f;
00096   vp=Object[O].NoVertices;
00097   fp=Object[O].NoFaces;
00098   for(i=0;i<Object[O].NoFaces;i++){
00099      i1= -1; i2= -1; i3= -1;
00100      y1=v[f[i].V[0]].p[1];
00101      y2=v[f[i].V[1]].p[1];
00102      y3=v[f[i].V[2]].p[1];
00103      if     (y1 <= dp && y2 <=dp && y3 >  dp){i1 = 2; i2=0; i3=1;}
00104      else if(y1 <= dp && y2 > dp && y3 <= dp){i1 = 1; i2=0; i3=2;}
00105      else if(y1 <= dp && y2 > dp && y3 >  dp){i1 = 0; i2=1; i3=2;}
00106      else if(y1 >  dp && y2 <=dp && y3 <= dp){i1 = 0; i2=1; i3=2;}
00107      else if(y1 >  dp && y2 <=dp && y3 >  dp){i1 = 1; i2=0; i3=2;}
00108      else if(y1 >  dp && y2 > dp && y3 <= dp){i1 = 2; i2=0; i3=1;}
00109      if(i1 >= 0){ /* calculate the new vertex positions on viewing plane */
00110        v[vp].x=v[vp].y=v[vp+1].x=v[vp+1].y=0.0; 
00111         /* calculate intersection point between points i1 - i2 and i1 - i3
00112            and place new vertices to interpolated position on viewing plane*/
00113        uv1[0]=v[f[i].V[i1]].u; uv1[1]=v[f[i].V[i1]].v;
00114        uv2[0]=v[f[i].V[i2]].u; uv2[1]=v[f[i].V[i2]].v;
00115        NewPoint(dp,v[f[i].V[i1]].p,v[f[i].V[i2]].p,v[vp].p,uv1,uv2,uva);
00116        v[vp].u=uva[0]; v[vp].v=uva[1];
00117 
00118        uv1[0]=v[f[i].V[i1]].u; uv1[1]=v[f[i].V[i1]].v;
00119        uv2[0]=v[f[i].V[i3]].u; uv2[1]=v[f[i].V[i3]].v;
00120        NewPoint(dp,v[f[i].V[i1]].p,v[f[i].V[i3]].p,v[vp+1].p,uv1,uv2,uvb);
00121        v[vp+1].u=uvb[0]; v[vp+1].v=uvb[1];
00122 
00123        NewMapPoint(dp,v[f[i].V[i1]].p,v[f[i].V[i2]].p,
00124                       f[i].uu[i1],f[i].uu[i2],
00125                       f[i].vv[i1],f[i].vv[i2],
00126                       f[i].ww[i1],f[i].ww[i2],a);
00127        NewMapPoint(dp,v[f[i].V[i1]].p,v[f[i].V[i3]].p,
00128                       f[i].uu[i1],f[i].uu[i3],
00129                       f[i].vv[i1],f[i].vv[i3],
00130                       f[i].ww[i1],f[i].ww[i3],b);
00131 //fprintf(debug,"Splint face %ld  (%ld %ld %ld) between [%ld %ld] and [%ld %ld] \n",i,i1,i2,i3, f[i].V[i1],f[i].V[i2],
00132 //f[i].V[i1],f[i].V[i3]); 
00133 //fprintf(debug,"New mapping a %lf %lf\n",a[0],a[1]);
00134 //fprintf(debug,"New mapping b %lf %lf\n",b[0],b[1]);
00135 
00136        f[fp].V[0]=vp;
00137        f[fp].V[1]=f[i].V[i2];
00138        f[fp].V[2]=f[i].V[i3];
00139        f[fp].uu[0]=a[0]; f[fp].vv[0]=a[1]; f[fp].ww[0]=a[2]; 
00140        f[fp].uu[1]=f[i].uu[i2]; f[fp].vv[1]=f[i].vv[i2]; f[fp].ww[1]=f[i].ww[i2]; 
00141        f[fp].uu[2]=f[i].uu[i3]; f[fp].vv[2]=f[i].vv[i3]; f[fp].ww[2]=f[i].ww[i3]; 
00142        
00143        f[fp+1].V[0]=vp;
00144        f[fp+1].V[1]=f[i].V[i3];
00145        f[fp+1].V[2]=vp+1;
00146        f[fp+1].uu[0]=a[0]; f[fp+1].vv[0]=a[1]; f[fp+1].ww[0]=a[2]; 
00147        f[fp+1].uu[1]=f[i].uu[i3]; f[fp+1].vv[1]=f[i].vv[i3]; f[fp+1].ww[1]=f[i].ww[i3]; 
00148        f[fp+1].uu[2]=b[0]; f[fp+1].vv[2]=b[1]; f[fp+1].ww[2]=b[2]; 
00149 
00150        f[i].V[i2]=vp;
00151        f[i].V[i3]=vp+1;
00152        f[i].uu[i2]=a[0]; f[i].vv[i2]=a[1]; f[i].ww[i2]=a[2]; 
00153        f[i].uu[i3]=b[0]; f[i].vv[i3]=b[1]; f[i].ww[i3]=b[2]; 
00154        f[fp+1].color[0]=f[fp].color[0]=f[i].color[0];
00155        f[fp+1].color[1]=f[fp].color[1]=f[i].color[1];
00156        f[fp+1].color[2]=f[fp].color[2]=f[i].color[2];
00157        f[fp+1].ffmap=f[fp].ffmap=f[i].ffmap;
00158        f[fp+1].ffmat=f[fp].ffmat=f[i].ffmat;
00159        f[fp+1].bFmc=f[fp].bFmc=f[i].bFmc;
00160        f[fp+1].bShiny=f[fp].bShiny=f[i].bShiny;
00161        f[fp+1].bSmooth=f[fp].bSmooth=f[i].bSmooth;
00162        f[fp+1].pn[0][0] = f[fp].pn[0][0] = f[i].pn[0][0];
00163        f[fp+1].pn[0][1] = f[fp].pn[0][1] = f[i].pn[0][1];
00164        f[fp+1].pn[0][2] = f[fp].pn[0][2] = f[i].pn[0][2];
00165        f[fp+1].pn[1][0] = f[fp].pn[1][0] = f[i].pn[1][0];
00166        f[fp+1].pn[1][1] = f[fp].pn[1][1] = f[i].pn[1][1];
00167        f[fp+1].pn[1][2] = f[fp].pn[1][2] = f[i].pn[1][2];
00168        f[fp+1].pn[2][0] = f[fp].pn[2][0] = f[i].pn[2][0];
00169        f[fp+1].pn[2][1] = f[fp].pn[2][1] = f[i].pn[2][1];
00170        f[fp+1].pn[2][2] = f[fp].pn[2][2] = f[i].pn[2][2];
00171        f[fp].c=f[fp+1].c=0.0;
00172        f[fp].n[0]=f[fp].n[1]=f[fp].n[2]=f[fp+1].n[0]
00173                  =f[fp+1].n[1]=f[fp+1].n[2]=0.0;
00174        vp += 2; fp += 2;
00175      }
00176   }
00177   Object[O].NoVertices = vp;
00178   Object[O].NoFaces = fp;
00179 #if 0
00180 fprintf(debug,"After v=%ld face=%ld\n",Object[O].NoVertices,Object[O].NoFaces);
00181 for(i=0;i<Object[O].NoFaces;i++){
00182 int j;
00183 fprintf(debug,"Face %ld vertices (%ld %ld %ld)\n",i,(f+i)->V[0],(f+i)->V[1],(f+i)->V[2]);
00184 for(j=0;j<3;j++){
00185 fprintf(debug,"(Vvert %8.1lf %8.1lf %8.1lf) (mapping  %lf %lf)\n",
00186 (v+(f+i)->V[j])->p[0],(v+(f+i)->V[j])->p[1],(v+(f+i)->V[j])->p[2],
00187 (f+i)->uu[j],(f+i)->vv[j]);
00188 }
00189 } 
00190 #endif
00191   return OK;
00192   X__ERROR:
00193   Render_Message(4,0,NULL);
00194   return FAIL;
00195 }
00196 
00197 long IShadow(long scanline, long v1x, long v1y, long v2x, long v2y,
00198              long *xi){
00199  double doff,ddxy;
00200  long dx,dy,off,dxy;
00201  if((v1y < scanline)  && (v2y < scanline))return 0;
00202  if((v1y > scanline)  && (v2y > scanline))return 0;
00203  dy = (v2y) - (v1y);
00204  if(dy == 0)return 0;
00205  dx = (v2x) - (v1x);
00206  off=scanline - v1y;
00207  doff=off;
00208  ddxy=dx*doff/dy;
00209  dxy=ddxy;
00210  *xi=(v1x)+dxy;
00211  return 1;
00212 }
00213 
00214 void ShadowFillLine(long scanline, long vx[3], long vy[3],
00215                       long *leftedge, long *rightedge){
00216  long x1,x2,x3,i1,i2,i3;
00217  i1=IShadow(scanline,vx[0],vy[0],vx[1],vy[1],&x1);
00218  i2=IShadow(scanline,vx[1],vy[1],vx[2],vy[2],&x2);
00219  i3=IShadow(scanline,vx[2],vy[2],vx[0],vy[0],&x3);
00220  if((i1 == 1) && (i2 == 1) && (i3 == 1))
00221  {*leftedge = min(min(x1,x2),x3);
00222   *rightedge= max(max(x1,x2),x3);}
00223  else if((i1 == 1) && (i2 == 1))
00224  {*leftedge = min(x1,x2);
00225   *rightedge= max(x1,x2);}
00226  else if((i2 == 1) && (i3 == 1))
00227  {*leftedge = min(x2,x3);
00228   *rightedge= max(x2,x3);}
00229  else if((i3 == 1) && (i1 == 1))
00230  {*leftedge = min(x3,x1);
00231   *rightedge= max(x3,x1);}
00232  else {
00233    Render_Message(5,0,NULL);
00234    return;
00235  }
00236  *leftedge  = max(0,min(XMAX-1,*leftedge));
00237  *rightedge = min(XMAX-1,max(0,*rightedge));
00238  return;
00239 }
00240 
00241 static unsigned char *AllocateShadowBuffer(void){
00242  long i,screensize;
00243  unsigned char *s,*screen;
00244  screensize = (long)XMAX * (long)YMAX;
00245  if((s = (unsigned char *)X__Malloc(screensize)) == NULL){
00246    Render_Message(14,0,NULL);
00247    return NULL;
00248  }
00249  screen=s; for(i=0;i<screensize;i++)*screen++ = 0;
00250  return s;
00251 }
00252 
00253 void ShadowGround(void){
00254  long i,j,k,l,m;
00255  long vi[3];
00256  long xx[3],yy[3],xxmin,xxmax,yymin,yymax;
00257  face    *f;
00258  vertex  *v;
00259  matl    *mat;
00260  unsigned char mattr;
00261  vector p,t1;
00262  double mu,nu,de,temp4;
00263  UCHAR  *screen;
00264  if((VGA_screen=AllocateShadowBuffer()) == NULL)return;
00265  screen=VGA_screen;
00266  for(k=0;k<Nlights;k++){
00267    if(Lights[k].type == NORMAL || Lights[k].type == SHADOWS){
00268      for(i=0;i<ObjectCount;i++){
00269        if(!Object[i].in_use)continue;
00270        if(!Object[i].cast_shadow)continue;
00271        v=Object[i].Vbase;
00272        f=Object[i].Fbase;
00273        mat=Object[i].Tbase;
00274        for(j=0;j<Object[i].NoFaces;j++){
00275          if((f+j)->ffmat >= 0 && (f+j)->ffmat < Object[i].NoMats){
00276            if(mat != NULL)mattr=(mat + f->ffmat)->transp;
00277            else mattr=0;
00278          } else mattr=0;
00279          if(mattr > 0)continue; /* glass no shadow */
00280          vi[0]=(f+j)->V[0];
00281          vi[1]=(f+j)->V[1];
00282          vi[2]=(f+j)->V[2];
00283          for(l=0;l<3;l++){ /* project each vertex to shadow plane */
00284            p[0]=(v+vi[l])->p[0];
00285            p[1]=(v+vi[l])->p[1];
00286            p[2]=(v+vi[l])->p[2];
00287            vecsub(Ground.p,Lights[k].p,t1);
00288            nu=dot(Ground.n,t1);
00289            vecsub(p,Lights[k].p,t1);
00290            de=dot(Ground.n,t1);
00291            if(fabs(de) < 1.e-5)goto FACEBREAK;
00292            mu=nu/de;
00293            if(mu < 1.0)goto FACEBREAK;
00294            vecsub(p,Lights[k].p,t1);
00295            vecscale(mu,t1,t1);
00296            vecsum(Lights[k].p,t1,t1);
00297            if(t1[1] > 1.000){
00298              temp4=(long)(scalex*t1[0]/(t1[1]));
00299              xx[l]=Xcentre+temp4;
00300              temp4=(long)(scaley*t1[2]/(t1[1]));
00301              yy[l]=Ycentre-temp4;
00302            }
00303            else goto FACEBREAK;
00304          }
00305          xxmin=min(xx[0],min(xx[1],xx[2]));
00306          xxmax=max(xx[0],max(xx[1],xx[2]));
00307          yymin=min(yy[0],min(yy[1],yy[2]));
00308          yymax=max(yy[0],max(yy[1],yy[2]));
00309          if((yymax > yymin) && (xxmax > xxmin))
00310          for(l=max(0,yymin);l<=min(yymax,YMAX-1);l++){
00311            ShadowFillLine(l,xx,yy,&xxmin,&xxmax);
00312            for(m=xxmin;m<=xxmax;m++) *(screen+l*(long)XMAX+m) = 1;
00313          }
00314          FACEBREAK: continue;
00315        }
00316      }
00317    }
00318  }
00319  return;
00320 }
00321 
00322 #define TOL 1.e-4;
00323 
00324 double hitpoint(vector n, vector x, vector y, vector pb, vector pf,
00325                 double * a, double * b){
00326  /* n        is normal to plane of map
00327     x & y    are vectors along the edges of the map  x= left y = down
00328     pb       is position vector to base point on map
00329     fp       is position vector to vertex to be mapped
00330     a & b    are output of mapping coordinates [0 - 1]
00331  */
00332  int k;
00333  vector v1,p;
00334  double mu,dm,detmax,det1,det2,det3,ve1,ve2,ve3,vp1,vp2,vp3,p1,p2,p3;
00335  VECSUB(pb,pf,v1)
00336  mu=DOT(n,v1);
00337  VECSCALE(mu,n,v1)
00338  VECSUM(pf,v1,p)
00339  ve1=x[0]; ve2=x[1]; ve3=x[2];
00340  vp1=y[0]; vp2=y[1]; vp3=y[2];
00341  p1=p[0]-pb[0];
00342  p2=p[1]-pb[1];
00343  p3=p[2]-pb[2];
00344  det1=ve1*vp2-vp1*ve2;
00345  det2=ve1*vp3-vp1*ve3;
00346  det3=ve2*vp3-vp2*ve3;
00347  k=0; detmax=TOL;
00348  if((dm=fabs(det1)) > detmax){k=1; detmax=dm;}
00349  if((dm=fabs(det2)) > detmax){k=2; detmax=dm;}
00350  if((dm=fabs(det3)) > detmax){k=3; detmax=dm;}
00351  if(k == 1){
00352    *a=( vp2*p1-vp1*p2)/det1;
00353    *b=(-ve2*p1+ve1*p2)/det1;
00354  }
00355  else if(k == 2){
00356    *a=( vp3*p1-vp1*p3)/det2;
00357    *b=(-ve3*p1+ve1*p3)/det2;
00358  }
00359  else if(k == 3){
00360    *a=( vp3*p2-vp2*p3)/det3;
00361    *b=(-ve3*p2+ve2*p3)/det3;
00362  }
00363  else {
00364    *a = *b = 0.0;
00365  }
00366  return mu;
00367 }
00368 
00369 BOOL hitpoint2(vector n, vector x, vector y, vector pb, vector pf,
00370                 double * a, double * b){
00371  /* n        is normal to plane of map
00372     x & y    are vectors along the edges of the map  x= left y = down
00373     pb       is position vector to base point on map
00374     fp       is position vector to vertex to be mapped
00375     a & b    are output of mapping coordinates [0 - 1]
00376  */
00377  // an alternative hitpoint function that assumes that the point of
00378  // intersection pf lies in the plane !!
00379  vector c;
00380  double dd,xx,yy,xy,cx,cy;
00381  VECSUB(pb,pf,c)
00382  xx=DOT(x,x);
00383  yy=DOT(y,y);
00384  xy=DOT(x,y);
00385  cy=DOT(c,y);
00386  cx=DOT(c,x);
00387  dd=xx*yy-xy*xy;
00388  if(fabs(dd) < 1.e-10){
00389    *a = *b = 0.0;
00390    return FALSE;
00391  }
00392  dd = 1.0/dd;
00393  *a=(cx*yy-cy*xy)*dd;
00394  *b=(cy*xx-cx*xy)*dd;
00395  return TRUE;
00396 }
00397 
00398 #define RTD 0.159154943
00399 
00400 #ifdef _SUNSTYLE
00401 double hitcylinder(n,x,y,p0,p,a,b) vector n; vector x; vector y;
00402 vector p0; vector p; double *a; double *b; {
00403 #else
00404 double hitcylinder(vector n, vector x, vector y, vector p0, vector p,
00405                 double * a, double * b){
00406 #endif
00407   double psi,theta,ddt;
00408   vector p1,q,p2;
00409   vecsub(p,p0,p1);
00410   psi =dot(p1,y)/dot(y,y);
00411   *b = psi;
00412   p2[0] = psi*y[0];     p2[1] = psi*y[1];      p2[2] = psi*y[2];
00413   q[0] = p1[0] - p2[0];  q[1] = p1[1] - p2[1];  q[2] = p1[2] - p2[2];
00414   normalize(q);
00415   ddt=DOT(q,n);
00416   if     (ddt >  1.0)ddt =  1.0;
00417   else if(ddt < -1.0)ddt = -1.0;
00418   theta=acos(ddt)*RTD;
00419   cross(q,n,p1);
00420   if(dot(p1,y) <= 0.0){
00421     if(theta <= 0.25) *a = (0.25 - theta);
00422     else  *a = (1.25 - theta);
00423   }
00424   else    *a = (0.25 + theta);
00425   return psi;
00426 }
00427 
00428 double hitsphere(vector y, vector dx, vector dy, vector p0, vector p,
00429                 double * a, double * b){
00430   /* p0    is at centre of map
00431      dx    is vector in direction of seam
00432      dy    is directed to south pole
00433      p     is point of vertex to be assigned mapping coordinates
00434      a     is  phi  [0 - 1] (0 along x axis)
00435      b     is theta [0 - 1] (0  at north pole)
00436   */
00437   vector x,z,r;
00438   VECCOPY(dx,x)
00439   normalize(x);
00440   VECSCALE(-1.0,dy,z)
00441   normalize(z);
00442   VECSUB(p,p0,r)
00443   normalize(r);
00444   *b = acos(DOT(r,z))*0.3183;              /*  theta/pi                    */
00445   *a = atan2(DOT(r,y),DOT(r,x))*0.1592;    /*  phi/(2 pi)    0   < a < 0.5 */
00446   if(*a < 0.0) *a = 1.0 + *a;              /*                0.5 < a < 1.0 */
00447   return 0.0;
00448 }
00449 
00450 #define UpdateNoGlassBuffer(f,i,d,id,O) {                       \
00451   Zdepth[i]=d; Zbuffer[i]=id; Zobject[i]=O;                     \
00452 }                                                               \
00453 
00454 #if NGLASS == 1
00455 #error BADGLASS1
00456 #define UpdateGlassBuffer(f,i,d,id,O,mattr) {                   \
00457      if(mattr > 0){                                             \
00458        if(d < Zglassd[0][i]){                                   \
00459          Zglassd[0][i]=d; Zglass[0][i]=id; ZglassO[0][i]=O;     \
00460        }                                                        \
00461      }                                                          \
00462      else{                                                      \
00463        if(d <= Zglassd[0][i])Zglass[0][i] = -1;                 \
00464        Zdepth[i]=d; Zbuffer[i]=id; Zobject[i]=O;                \
00465      }                                                          \
00466 }
00467 #elif NGLASS == 2
00468 #error BADGLASS2
00469 #define UpdateGlassBuffer(f,i,d,id,O,mattr) {                   \
00470      if(mattr > 0){                                             \
00471        if(d < Zglassd[0][i]-600.0){                             \
00472          if(O != ZglassO[0][i] || id != Zglass[0][i]){          \
00473            Zglassd[1][i]=Zglassd[0][i];                         \
00474            ZglassO[1][i]=ZglassO[0][i];                         \
00475            Zglass[1][i]=Zglass[0][i];                           \
00476          }                                                      \
00477          Zglassd[0][i]=d; Zglass[0][i]=id; ZglassO[0][i]=O;     \
00478        }                                                        \
00479        else if(d > Zglassd[0][i]+600.0 &&                       \
00480                d < Zglassd[1][i]-600.0){                        \
00481          Zglassd[1][i]=d; Zglass[1][i]=id; ZglassO[1][i]=O;     \
00482        }                                                        \
00483      }                                                          \
00484      else{                                                      \
00485        if(d <= Zglassd[0][i]){                                  \
00486          Zglass[0][i] = -1;  Zglassd[0][i]=FARAWAY;             \
00487          Zglass[1][i] = -1;  Zglassd[1][i]=FARAWAY;             \
00488        }                                                        \
00489        else if(d < Zglassd[1][i]){                              \
00490          Zglass[1][i] = -1;                                     \
00491          Zglassd[1][i]=FARAWAY;                                 \
00492        }                                                        \
00493        Zdepth[i]=d; Zbuffer[i]=id; Zobject[i]=O;                \
00494      }                                                          \
00495 }
00496 #elif NGLASS == 4
00497 #define UpdateGlassBuffer(f,i,d,id,O,mattr) {                   \
00498      if(mattr > 0){                                             \
00499        if(d < Zglassd[0][i]-600.0){                             \
00500          if(O != ZglassO[0][i] || id != Zglass[0][i]){          \
00501            Zglassd[3][i]=Zglassd[2][i];                         \
00502            ZglassO[3][i]=ZglassO[2][i];                         \
00503            Zglass[3][i]=Zglass[2][i];                           \
00504            Zglassd[2][i]=Zglassd[1][i];                         \
00505            ZglassO[2][i]=ZglassO[1][i];                         \
00506            Zglass[2][i]=Zglass[1][i];                           \
00507            Zglassd[1][i]=Zglassd[0][i];                         \
00508            ZglassO[1][i]=ZglassO[0][i];                         \
00509            Zglass[1][i]=Zglass[0][i];                           \
00510          }                                                      \
00511          Zglassd[0][i]=d; Zglass[0][i]=id; ZglassO[0][i]=O;     \
00512        }                                                        \
00513        else if(d > Zglassd[0][i]+600.0 &&                       \
00514                d < Zglassd[1][i]-600.0){                        \
00515          if(O != ZglassO[1][i] || id != Zglass[1][i]){          \
00516            Zglassd[3][i]=Zglassd[2][i];                         \
00517            ZglassO[3][i]=ZglassO[2][i];                         \
00518            Zglass[3][i]=Zglass[2][i];                           \
00519            Zglassd[2][i]=Zglassd[1][i];                         \
00520            ZglassO[2][i]=ZglassO[1][i];                         \
00521            Zglass[2][i]=Zglass[1][i];                           \
00522          }                                                      \
00523          Zglassd[1][i]=d; Zglass[1][i]=id; ZglassO[1][i]=O;     \
00524        }                                                        \
00525        else if(d > Zglassd[1][i]+600.0 &&                       \
00526                d < Zglassd[2][i]-600.0){                        \
00527          if(O != ZglassO[2][i] || id != Zglass[2][i]){          \
00528            Zglassd[3][i]=Zglassd[2][i];                         \
00529            ZglassO[3][i]=ZglassO[2][i];                         \
00530            Zglass[3][i]=Zglass[2][i];                           \
00531          }                                                      \
00532          Zglassd[2][i]=d; Zglass[2][i]=id; ZglassO[2][i]=O;     \
00533        }                                                        \
00534        else if(d > Zglassd[2][i]+600.0 &&                       \
00535                d < Zglassd[3][i]-600.0){                        \
00536          Zglassd[3][i]=d; Zglass[3][i]=id; ZglassO[3][i]=O;     \
00537        }                                                        \
00538      }                                                          \
00539      else{                                                      \
00540        if(d <= Zglassd[0][i]){                                  \
00541          Zglass[0][i] = -1;  Zglassd[0][i]=FARAWAY;             \
00542          Zglass[1][i] = -1;  Zglassd[1][i]=FARAWAY;             \
00543          Zglass[2][i] = -1;  Zglassd[2][i]=FARAWAY;             \
00544          Zglass[3][i] = -1;  Zglassd[3][i]=FARAWAY;             \
00545        }                                                        \
00546        else if(d < Zglassd[1][i]){                              \
00547          Zglass[1][i] = -1;  Zglassd[1][i]=FARAWAY;             \
00548          Zglass[2][i] = -1;  Zglassd[2][i]=FARAWAY;             \
00549          Zglass[3][i] = -1;  Zglassd[3][i]=FARAWAY;             \
00550        }                                                        \
00551        else if(d < Zglassd[2][i]){                              \
00552          Zglass[2][i] = -1;  Zglassd[2][i]=FARAWAY;             \
00553          Zglass[3][i] = -1;  Zglassd[3][i]=FARAWAY;             \
00554        }                                                        \
00555        else if(d < Zglassd[3][i]){                              \
00556          Zglass[3][i] = -1;  Zglassd[3][i]=FARAWAY;             \
00557        }                                                        \
00558        Zdepth[i]=d; Zbuffer[i]=id; Zobject[i]=O;                \
00559      }                                                          \
00560 }
00561 #else
00562 #error BADGLASS0
00563 #endif
00564 
00565 void UpdateGlassScanBuffers(double xl, double xr, long id, long O,  // used with NOT tracing refractions
00566                        face  *f, double d2,
00567                        long *Zglass[], long *ZglassO[], double *Zglassd[],
00568                        long *Zbuffer, long *Zobject,
00569                        double *Zdepth, double *Zposn){
00570  long i,ixl,ixr,mapID;
00571  double depth,bL,bR,aL,aR,dL,dR;
00572  unsigned char mattr;
00573  if((mapID=f->ffmap) >= 0 && mapID < Object[O].NoMaps &&  // this face has a transparency map
00574      Object[O].Mbase[mapID].tp > 0)mattr=255;             // and we need to flag the glass buffers
00575  else if(f->ffmat < 0 || f->ffmat >= Object[O].NoMats)mattr=0;
00576  else   mattr=(Object[O].Tbase + f->ffmat)->transp;
00577 /* xl += 0.0001; too small
00578    xr -= 0.0001;
00579    xl += 0.01;  too big
00580    xr -= 0.01;  */
00581  xl += 0.001;
00582  xr -= 0.001;
00583  ixl = (long)xl;
00584  ixr = (long)xr;
00585  if(ixl == ixr){
00586    dL = xl - (double)Xcentre; dL/=scalex;
00587    dR = xr - (double)Xcentre; dR/=scalex;
00588    bL = f->n[0]*dL + f->n[2]*d2 + f->n[1];
00589    aL = (f->c)/bL;
00590    bR = f->n[0]*dR + f->n[2]*d2 + f->n[1];
00591    aR = (f->c)/bR;
00592    depth=min(aL,aR);
00593    if(depth > 1.000 && depth <= Zdepth[ixl]){
00594      UpdateGlassBuffer(f,ixl,depth,id,O,mattr)
00595      Zposn[ixl]=(xr+xl)/2.0;
00596    }
00597    return;
00598  }
00599  else{
00600    dL = xl - (double)Xcentre; dL/=scalex;
00601    bL = f->n[0]*dL + f->n[2]*d2 + f->n[1];
00602    aL = (f->c)/bL;
00603    bR = f->n[0]*DR[ixl] + f->n[2]*d2 + f->n[1];
00604    aR = (f->c)/bR;
00605    depth=min(aL,aR);
00606    if(depth > 1.000 && depth <= Zdepth[ixl]){
00607      UpdateGlassBuffer(f,ixl,depth,id,O,mattr)
00608      Zposn[ixl]=xl;
00609    }
00610    bL = f->n[0]*DL[ixr] + f->n[2]*d2 + f->n[1];
00611    aL = (f->c)/bL;
00612    dR = xr - (double)Xcentre; dR/=scalex;
00613    bR = f->n[0]*dR + f->n[2]*d2 + f->n[1];
00614    aR = (f->c)/bR;
00615    depth=min(aL,aR);
00616    if(depth > 1.000 && depth <= Zdepth[ixr]){
00617      UpdateGlassBuffer(f,ixr,depth,id,O,mattr)
00618      Zposn[ixr]=xr;
00619    }
00620  }
00621  if(ixr-ixl  > 1)for(i=ixl+1;i<ixr;i++)
00622  {
00623    bL = f->n[0]*DL[i] + f->n[2]*d2 + f->n[1];
00624    aL = (f->c)/bL;
00625    bR = f->n[0]*DR[i] + f->n[2]*d2 + f->n[1];
00626    aR = (f->c)/bR;
00627    depth=min(aL,aR);
00628    if(depth > 1.000 && depth <= Zdepth[i]){
00629      UpdateGlassBuffer(f,i,depth,id,O,mattr)
00630      Zposn[i]=(double)i+0.5;
00631    }
00632  }
00633 }
00634 
00635 void UpdateNoGlassScanBuffers(double xl, double xr, long id, long O,   // used with tracing refractions
00636                        face  *f, double d2,
00637                        long *Zglass[], long *ZglassO[], double *Zglassd[],
00638                        long *Zbuffer, long *Zobject,
00639                        double *Zdepth, double *Zposn){
00640  long i,ixl,ixr;
00641  double depth,bL,bR,aL,aR,dL,dR;
00642  unsigned char mattr;
00643  if(f->ffmat < 0 || f->ffmat >= Object[O].NoMats)mattr=0;
00644  else   mattr=(Object[O].Tbase + f->ffmat)->transp;
00645 /* xl += 0.0001; too small
00646    xr -= 0.0001;
00647    xl += 0.01;  too big
00648    xr -= 0.01;  */
00649  xl += 0.001;
00650  xr -= 0.001;
00651  ixl = (long)xl;
00652  ixr = (long)xr;
00653  if(ixl == ixr){
00654    dL = xl - (double)Xcentre; dL/=scalex;
00655    dR = xr - (double)Xcentre; dR/=scalex;
00656    bL = f->n[0]*dL + f->n[2]*d2 + f->n[1];
00657    aL = (f->c)/bL;
00658    bR = f->n[0]*dR + f->n[2]*d2 + f->n[1];
00659    aR = (f->c)/bR;
00660    depth=min(aL,aR);
00661    if(depth > 1.000 && depth <= Zdepth[ixl]){
00662      UpdateNoGlassBuffer(f,ixl,depth,id,O)
00663      Zposn[ixl]=(xr+xl)/2.0;
00664    }
00665    return;
00666  }
00667  else{
00668    dL = xl - (double)Xcentre; dL/=scalex;
00669    bL = f->n[0]*dL + f->n[2]*d2 + f->n[1];
00670    aL = (f->c)/bL;
00671    bR = f->n[0]*DR[ixl] + f->n[2]*d2 + f->n[1];
00672    aR = (f->c)/bR;
00673    depth=min(aL,aR);
00674    if(depth > 1.000 && depth <= Zdepth[ixl]){
00675      UpdateNoGlassBuffer(f,ixl,depth,id,O)
00676      Zposn[ixl]=xl;
00677    }
00678    bL = f->n[0]*DL[ixr] + f->n[2]*d2 + f->n[1];
00679    aL = (f->c)/bL;
00680    dR = xr - (double)Xcentre; dR/=scalex;
00681    bR = f->n[0]*dR + f->n[2]*d2 + f->n[1];
00682    aR = (f->c)/bR;
00683    depth=min(aL,aR);
00684    if(depth > 1.000 && depth <= Zdepth[ixr]){
00685      UpdateNoGlassBuffer(f,ixr,depth,id,O)
00686      Zposn[ixr]=xr;
00687    }
00688  }
00689  if(ixr-ixl  > 1)for(i=ixl+1;i<ixr;i++)
00690  {
00691    bL = f->n[0]*DL[i] + f->n[2]*d2 + f->n[1];
00692    aL = (f->c)/bL;
00693    bR = f->n[0]*DR[i] + f->n[2]*d2 + f->n[1];
00694    aR = (f->c)/bR;
00695    depth=min(aL,aR);
00696    if(depth > 1.000 && depth <= Zdepth[i]){
00697      UpdateNoGlassBuffer(f,i,depth,id,O)
00698      Zposn[i]=(double)i+0.5;
00699    }
00700  }
00701 }
00702 
00703 long Intersect(long scanline, vertex  *v1, vertex  *v2,
00704                 double *xi){
00705  double ddx,ddy,doff,ddxy;
00706  if((v1->y < (double)scanline)  && (v2->y < (double)scanline))return 0;
00707  if((v1->y > (double)scanline)  && (v2->y > (double)scanline))return 0;
00708  ddy = (v2->y) - (v1->y);
00709  if(fabs(ddy) < 0.0001)return 0;
00710  ddx = (v2->x) - (v1->x);
00711  doff=(double)scanline - v1->y;
00712  ddxy=ddx*doff/ddy;
00713  *xi=(v1->x)+ddxy;
00714  return 1;
00715 }
00716 
00717 long Active(long scanline, vertex  *v, face  *f,
00718                       double *leftedge, double *rightedge){
00719  long v1,v2,v3
00720      ,i1,i2,i3;
00721  double x1,x2,x3;
00722  if(f->top > scanline)       return 0;
00723  if(f->bottom < scanline)    return 0;
00724  v1=f->V[0];
00725  v2=f->V[1];
00726  v3=f->V[2];
00727  i1=Intersect(scanline,(v+v1),(v+v2),&x1);
00728  i2=Intersect(scanline,(v+v2),(v+v3),&x2);
00729  i3=Intersect(scanline,(v+v3),(v+v1),&x3);
00730  if((i1 == 1) && (i2 == 1) && (i3 == 1))
00731  {*leftedge = min(min(x1,x2),x3);
00732   *rightedge= max(max(x1,x2),x3);}
00733  else if((i2 == 1) && (i3 == 1))
00734  {*leftedge = min(x2,x3);
00735   *rightedge= max(x2,x3);}
00736  else if((i3 == 1) && (i1 == 1))
00737  {*leftedge = min(x3,x1);
00738   *rightedge= max(x3,x1);}
00739  else if((i1 == 1) && (i2 == 1))
00740  {*leftedge = min(x1,x2);
00741   *rightedge= max(x1,x2);}
00742  else return 0;
00743  if(*leftedge >= (double)XMAX-0.002)return 0;
00744  else *leftedge  = max(0,*leftedge);
00745  if(*rightedge < (double)XMIN+0.002)return 0;
00746  *rightedge = min((double)XMAX-0.01,*rightedge);
00747  return 1;
00748 }
00749 
00750 void SetPerspectiveView(long StereoLeft){  
00751  double t1[4][4],t2[4][4],t3[4][4],t4[4][4];
00752  double lenz=50.0;
00753  if(ResolutionX > ResolutionY)
00754    scalex=scaley=(double)ResolutionX/2.0/21.22*lenz;
00755  else
00756    scalex=scaley=(double)ResolutionY/2.0/21.22*lenz;
00757  if(ResolutionX <= 320 && ResolutionY <= 200)
00758    scaley /= 1.2;     /* 3ds uses  *0.82 = /1.21 but this seems wrong */
00759  if(anti_alias == LOW)   {scalex *= 2;}
00760  if(anti_alias == MEDIUM){scalex *= 2; scaley *= 2;}
00761  if(anti_alias == HIGH)  {scalex *= 3; scaley *= 2;}
00762  if(anti_alias == ULTRA) {scalex *= 3; scaley *= 3;}
00763  CamTheta *= PI/180.0;
00764  CamPhi   *= PI/180.0;
00765  CamAlpha *= PI/180.0;
00766  scalex *= CamSx;  /* apply any more scaling or aspect ration */
00767  scaley *= CamSy;
00768  R_tram(t1,-ViewPoint[0],-ViewPoint[1],-ViewPoint[2]);
00769  R_rotz(t2,-CamPhi);
00770  R_m4by4(t2,t1,t3);
00771  R_rotx(t1,-CamAlpha);
00772  R_m4by4(t1,t3,t2);
00773  R_roty(t1,-CamTheta);   /* bank on axis */
00774  R_m4by4(t1,t2,ViewTransform);
00775  R_roty(t1,CamTheta);    /* for reflection maps get a transform back to */
00776  R_rotx(t2,CamAlpha);    /* co-ordinate system without camera,          */
00777  R_m4by4(t2,t1,t3);      /* but this is easier to compute               */
00778  R_rotz(t1,CamPhi);
00779  R_m4by4(t1,t3,AntiCamera);
00780  R_rotz(t1,CamPhi);      /* for sky environment map                     */
00781  R_rotx(t2,CamAlpha);
00782  // R_m4by4(t1,t2,CameraRotate);  // use this on its own for NO bank    */
00783  R_roty(t3,CamTheta);
00784  R_m4by4(t2,t3,t4);
00785  R_m4by4(t1,t4,CameraRotate);  // Camera Rotation matrix
00786  // The AntiCamera matrix ordered to accomodate the OpenFX to OpenGL 
00787  // coordinate differences. This does not include the Transpose required
00788  // when writing to the OpenGL transformation matrix.
00789  if(StereoRenderingON == YES){
00790    double tStereo[4][4],rStereo[4][4];
00791    double r,d;
00792    r=atan2(CamStereoSeparation/2.0,CamParallaxDepth);
00793    d=CamStereoSeparation/2.0*CamRuler;
00794    if(StereoLeft == 1){
00795      R_tram(tStereo,d,0.0,0.0);
00796      R_rotz(rStereo,r); 
00797    }
00798    else{
00799      R_tram(tStereo,-d,0.0,0.0);
00800      R_rotz(rStereo,-r); 
00801    }
00802    R_m4by4(rStereo,ViewTransform,t1);
00803    R_m4by4(tStereo,t1,ViewTransform);
00804    R_m4by4(rStereo,AntiCamera,t1);
00805    R_c4to4(t1,AntiCamera);
00806    R_m4by4(rStereo,CameraRotate,t1);
00807    R_c4to4(t1,CameraRotate);
00808  }
00809  AntiCameraGL[0][0]= AntiCamera[0][0];
00810  AntiCameraGL[0][1]= AntiCamera[0][2];
00811  AntiCameraGL[0][2]=-AntiCamera[0][1];
00812  AntiCameraGL[1][0]= AntiCamera[2][0];
00813  AntiCameraGL[1][1]= AntiCamera[2][2];
00814  AntiCameraGL[1][2]=-AntiCamera[2][1];
00815  AntiCameraGL[2][0]=-AntiCamera[1][0];
00816  AntiCameraGL[2][1]=-AntiCamera[1][2];
00817  AntiCameraGL[2][2]= AntiCamera[1][1];
00818  return;
00819 }
00820 
00821 /*  perform geometry transformations   */
00822 void ApplyViewingTransformToPoint(vector vin, vector vout){
00823  double x1,y1,z1;
00824  R_m4by1(ViewTransform,vin[0],vin[1],vin[2],&x1,&y1,&z1);
00825  vout[0]=x1;    vout[1]=y1;    vout[2]=z1;
00826 }
00827 
00828 void BendNormal(vector nin, vector dn, vector nout){
00829  double x1,y1,z1,x2,y2,z2;
00830  R_m3by1(AntiCamera,nin[0],nin[1],nin[2],&x1,&y1,&z1);
00831  x2=x1+dn[0]; y2=y1+dn[1]; z2=z1+dn[2];
00832  R_m3by1(ViewTransform,x2,y2,z2,&nout[0],&nout[1],&nout[2]);
00833 }
00834 
00835 void MakeObjectTransformation(
00836              double fi, double theta, double alpha, // orientation
00837              short im, double ima,                  // internal rotations
00838              double sx, double sy, double sz,       // scales
00839              vector Centre,                         // centre point offset  
00840              vector Position,                       // Object Position in World
00841              double trpos[4][4],     // output the object transform (include view
00842              double trset[4][4],     // exclude the view transform 
00843              double trinv[4][4]){    // undos the whole transform (include view)
00844  double t1[4][4],t2[4][4],t3[4][4],t4[4][4];
00845  fi    *= PI/180.0;
00846  theta *= PI/180.0;
00847  alpha *= PI/180.0;
00848  R_tram(t2,-(double)Centre[0],-(double)Centre[1],-(double)Centre[2]);
00849  R_scal(t3,sx,sy,sz);
00850  R_m4by4(t3,t2,t1);
00851  if(im > 0){
00852    if(im == 1)R_rotz(t3,ima*PI/180.0);
00853    if(im == 2)R_rotx(t3,ima*PI/180.0);
00854    if(im == 3)R_roty(t3,ima*PI/180.0);
00855    R_m4by4(t3,t1,t2);
00856    R_roty(t1,theta);
00857    R_m4by4(t1,t2,t3);
00858  }
00859  else{
00860    R_roty(t2,theta);
00861    R_m4by4(t2,t1,t3);
00862  }
00863  R_rotx(t1,alpha);
00864  R_m4by4(t1,t3,t2);
00865  R_rotz(t1,fi);
00866  R_m4by4(t1,t2,t3);
00867  R_tram(t1,Position[0],Position[1],Position[2]);
00868  R_m4by4(t1,t3,trset);                 // excluding the viewing transform
00869  R_m4by4(ViewTransform,trset,trpos);   // including the viewing transform
00870 
00871  /* Get the inverse object transformation */
00872 
00873  R_tram(t1,-Position[0],-Position[1],-Position[2]);
00874  R_rotz(t2,-fi);
00875  R_m4by4(t2,t1,t3);
00876  R_rotx(t1,-alpha);
00877  R_m4by4(t1,t3,t2);
00878  if(im > 0){
00879    R_roty(t1,-theta);
00880    if(im == 1)R_rotz(t3,-ima*PI/180.0);
00881    if(im == 2)R_rotx(t3,-ima*PI/180.0);
00882    if(im == 3)R_roty(t3,-ima*PI/180.0);
00883    R_m4by4(t3,t1,t4);
00884  }
00885  else{
00886    R_roty(t4,-theta);
00887  }
00888  R_m4by4(t4,t2,t1);
00889  R_scal(t2,1.0/sx,1.0/sy,1.0/sz);
00890  R_m4by4(t2,t1,t3);
00891  R_tram(t2,(double)Centre[0],(double)Centre[1],(double)Centre[2]);
00892  R_m4by4(t2,t3,t1);
00893  R_m4by4(t1,AntiCamera,trinv);
00894  return;
00895 }
00896 
00897 void TransformMappingRectangle(
00898                     double  trpos[4][4], vector  P, vector  X, vector Y,
00899                     vector  p, vector  x, vector y, vector n){
00900   R_m4by1(trpos,P[0],P[1],P[2],&p[0],&p[1],&p[2]);
00901   R_m4by1(trpos,X[0],X[1],X[2],&x[0],&x[1],&x[2]);
00902   R_m4by1(trpos,Y[0],Y[1],Y[2],&y[0],&y[1],&y[2]);
00903   vecsub(x,p,x);
00904   vecsub(y,p,y);
00905   cross (x,y,n);
00906   if(normalize(n)){ /* bad axis just set up unit */
00907     x[0]=1.0; x[1]=0.0; x[2]=0.0;
00908     y[0]=0.0; y[1]=1.0; y[2]=0.0;
00909     cross(x,y,n);
00910   }
00911 }
00912 
00913 
00914 void R_rotz(double tr[4][4], double ang){
00915  long i,j;
00916  for(i=0;i<4;i++)
00917  for(j=0;j<4;j++)
00918  {
00919   tr[i][j]=0.0;
00920   if(i == j)tr[i][j]=1.0;
00921  }
00922   tr[0][0] =  cos(ang);
00923   tr[0][1] = -sin(ang);
00924   tr[1][0] =  sin(ang);
00925   tr[1][1] =  cos(ang);
00926   return;
00927 }
00928 
00929 #ifdef _SUNSTYLE
00930 void R_rotx(tr,ang) double tr[4][4]; double ang; {
00931 #else
00932 void R_rotx(double tr[4][4], double ang){
00933 #endif
00934  long i,j;
00935  for(i=0;i<4;i++)
00936  for(j=0;j<4;j++)
00937  {
00938   tr[i][j]=0.0;
00939   if(i == j)tr[i][j]=1.0;
00940  }
00941   tr[1][1] =  cos(ang);
00942   tr[1][2] = -sin(ang);
00943   tr[2][1] =  sin(ang);
00944   tr[2][2] =  cos(ang);
00945   return;
00946 }
00947 
00948 void R_roty(double tr[4][4], double ang){
00949  long i,j;
00950  for(i=0;i<4;i++)
00951  for(j=0;j<4;j++)
00952  {
00953   tr[i][j]=0.0;
00954   if(i == j)tr[i][j]=1.0;
00955  }
00956   tr[0][0] =  cos(ang);
00957   tr[0][2] = -sin(ang);
00958   tr[2][0] =  sin(ang);
00959   tr[2][2] =  cos(ang);
00960   return;
00961 }
00962 
00963 void R_tram(double t[4][4], double dx, double dy, double dz){
00964  long i,j;
00965  for(i=0;i<4;i++)
00966  for(j=0;j<4;j++)
00967  {
00968   t[i][j]=0.0;
00969   if(i == j)t[i][j]=1.0;
00970  }
00971  t[0][3]=dx;
00972  t[1][3]=dy;
00973  t[2][3]=dz;
00974  t[3][3]=1;
00975  return;
00976 }
00977 
00978 void R_scal(double t[4][4], double sx, double sy, double sz){
00979  long i,j;
00980  for(i=0;i<4;i++)
00981  for(j=0;j<4;j++)
00982  {
00983   t[i][j]=0.0;
00984   if(i == j)t[i][j]=1.0;
00985  }
00986  t[0][0]=sx;
00987  t[1][1]=sy;
00988  t[2][2]=sz;
00989  t[3][3]=1;
00990  return;
00991 }
00992 
00993 void R_m4by4(double t1[4][4], double t2[4][4], double tr[4][4]){
00994  long i,j,k;
00995  for(i=0;i<4;i++)
00996  for(j=0;j<4;j++)
00997  {
00998   tr[i][j]=0.0;
00999   for(k=0;k<4;k++)tr[i][j]=tr[i][j]+t1[i][k]*t2[k][j];
01000  }
01001  return;
01002 }
01003 
01004 void R_c4to4(double tin[4][4], double tout[4][4]){
01005  int i,j;
01006  for(i=0;i<4;i++)
01007  for(j=0;j<4;j++)
01008  tout[i][j]=tin[i][j];
01009  return;
01010 }
01011 
01012 void R_null_transform(double t[4][4]){
01013  short i,j;
01014  for(i=0;i<4;i++)
01015  for(j=0;j<4;j++)
01016  if(i == j)t[i][j]=1.0;
01017  else      t[i][j]=0.0;
01018 }
01019 
01020 void R_m4by1(double t4[4][4], double x, double y, double z,
01021            double *xx, double *yy, double *zz){
01022    *xx=t4[0][0]*x+t4[0][1]*y+t4[0][2]*z+t4[0][3];
01023    *yy=t4[1][0]*x+t4[1][1]*y+t4[1][2]*z+t4[1][3];
01024    *zz=t4[2][0]*x+t4[2][1]*y+t4[2][2]*z+t4[2][3];
01025  return;
01026 }
01027 
01028 void R_m3by1(double t4[4][4], double x, double y, double z,
01029            double *xx, double *yy, double *zz){
01030    *xx=t4[0][0]*x+t4[0][1]*y+t4[0][2]*z;
01031    *yy=t4[1][0]*x+t4[1][1]*y+t4[1][2]*z;
01032    *zz=t4[2][0]*x+t4[2][1]*y+t4[2][2]*z;
01033  return;
01034 }
01035 
01036 
01037 #ifdef _SUNSTYLE
01038 void R_reflect(t,p,n) double t[4][4]; vector p; vector n; {
01039 #else
01040 void R_reflect(double t[4][4], vector p, vector n){
01041 #endif
01042  /* p is point in reflection plane  */
01043  /* n is normal to reflection plane */
01044  long i,j;
01045  double dxy,phi,theta;
01046  double t1[4][4],t2[4][4],t3[4][4];
01047 //{
01048 //char temp[256];
01049 //sprintf(temp,"n= %lf %lf %lf p=%lf %lf %lf",n[0],n[1],n[2],p[0],p[1],p[2]);
01050 //MessageBox(NULL,temp,"Debug",MB_OK);
01051 //}
01052  dxy=n[0]*n[0]+n[1]*n[1];
01053  R_tram(t1,-p[0],-p[1],-p[2]);
01054  if(fabs(n[2]) > 0.7071){
01055 //MessageBox(NULL,"transform to Z","Debug",MB_OK);
01056   if(fabs(n[2]) > 0.998){ /* vertical so just reflect in XY plane and return */
01057 // MessageBox(NULL,"Vertical","Debug",MB_OK);
01058      for(i=0;i<4;i++)for(j=0;j<4;j++){
01059        if(i == j)t2[i][j]=1.0;
01060        else      t2[i][j]=0.0;
01061      }
01062      t2[2][2]=-1.0;
01063      R_m4by4(t2,t1,t3);
01064      R_tram(t1,p[0],p[1],p[2]);
01065      R_m4by4(t1,t3,t);
01066      return;
01067    }
01068    dxy=sqrt(dxy);
01069    if     (fabs(n[0]) < 1.e-6 && n[1] > 0.0)phi =  1.570796;
01070    else if(fabs(n[0]) < 1.e-6 && n[1] < 0.0)phi = -1.570796;
01071    else phi = atan2(n[1],n[0]);
01072    if(n[2] > 0.0)theta =  1.570796-atan2(n[2],dxy);
01073    else          theta = -1.570796-atan2(n[2],dxy);
01074    R_rotz(t2, -phi);
01075    R_m4by4(t2,t1,t3);
01076    R_roty(t2, theta);
01077    R_m4by4(t2,t3,t1);
01078    for(i=0;i<4;i++)for(j=0;j<4;j++){
01079      if(i == j)t2[i][j]=1.0;
01080      else      t2[i][j]=0.0;
01081    }
01082    t2[2][2]=-1.0;  /* reflect in XY plane - perpend`r to Z axis */
01083    R_m4by4(t2,t1,t3);
01084    R_roty(t2,-theta);
01085    R_m4by4(t2,t3,t1);
01086    R_rotz(t2,phi);
01087    R_m4by4(t2,t1,t3);
01088    R_tram(t1,p[0],p[1],p[2]);
01089    R_m4by4(t1,t3,t);
01090  }
01091  else{
01092    dxy=sqrt(dxy);
01093    if     (fabs(n[0]) < 1.e-6 && n[1] > 0.0)phi =  1.570796;
01094    else if(fabs(n[0]) < 1.e-6 && n[1] < 0.0)phi = -1.570796;
01095    else phi = atan2(n[1],n[0]);
01096    theta = atan2(n[2],dxy);
01097    R_rotz(t2, -phi);
01098    R_m4by4(t2,t1,t3);
01099    R_roty(t2, -theta);
01100    R_m4by4(t2,t3,t1);
01101    for(i=0;i<4;i++)for(j=0;j<4;j++){
01102      if(i == j)t2[i][j]=1.0;
01103      else      t2[i][j]=0.0;
01104    }
01105    t2[0][0]=-1.0;  /* reflect in YZ plane - perpend`r to X axis */
01106    R_m4by4(t2,t1,t3);
01107    R_roty(t2,theta);
01108    R_m4by4(t2,t3,t1);
01109    R_rotz(t2,phi);
01110    R_m4by4(t2,t1,t3);
01111    R_tram(t1,p[0],p[1],p[2]);
01112    R_m4by4(t1,t3,t);
01113  }
01114  return;
01115 }
01116 
01117 void veccopy(vector v1, vector r){
01118  r[0] = v1[0];
01119  r[1] = v1[1];
01120  r[2] = v1[2];
01121 }
01122 
01123 void vecsub(vector v1, vector v2, vector r){
01124  r[0] = v1[0] - v2[0];
01125  r[1] = v1[1] - v2[1];
01126  r[2] = v1[2] - v2[2];
01127 }
01128 
01129 void vecsum(vector v1,vector v2, vector r){
01130  r[0] = v1[0] + v2[0];
01131  r[1] = v1[1] + v2[1];
01132  r[2] = v1[2] + v2[2];
01133 }
01134 
01135 void vecscale(double s, vector v, vector r){
01136  r[0] = s * v[0];
01137  r[1] = s * v[1];
01138  r[2] = s * v[2];
01139 }
01140 
01141 short normalize(vector v){
01142  double n,nn;
01143  n= (double)((v[0]*v[0]) + (v[1]*v[1]) + (v[2]*v[2]));
01144  if(n < 1.e-10)return 1;
01145  nn=sqrt(n);
01146  n = 1.0 / nn;
01147  vecscale(n,v,v);
01148  return 0;
01149 }
01150 
01151 double R_length(vector v){
01152  double n,nn;
01153  n= (double)((v[0]*v[0]) + (v[1]*v[1]) + (v[2]*v[2]));
01154  nn=sqrt(n);
01155  return (nn);
01156 }
01157 
01158 void cross(vector v1,vector v2, vector r){
01159  r[0] = (v1[1]*v2[2]) - (v2[1]*v1[2]);
01160  r[1] = (v1[2]*v2[0]) - (v1[0]*v2[2]);
01161  r[2] = (v1[0]*v2[1]) - (v2[0]*v1[1]);
01162 }
01163 
01164 double dot(vector v1, vector v2){
01165  double result;
01166  result  = v1[0] * v2[0];
01167  result += v1[1] * v2[1];
01168  result += v1[2] * v2[2];
01169  return result;
01170 }
01171 
01172 void AssignMappingCoordinatesToVertices(object *O){
01173  vertex *Vbase=O->Vbase;
01174  face   *f,*Fbase=O->Fbase;
01175  imap   *m,*Mbase=O->Mbase;
01176  matl   *Tbase=O->Tbase;
01177  axis   *a;
01178  long nfaces=O->NoFaces;
01179  long nvert=O->NoVertices;
01180  long nmaps=O->NoMaps;
01181  long nmats=O->NoMats;
01182  long i,j,mapid,matid;
01183  double alpha,beta,gamma,alphav[3],betav[3];
01184  if(nmaps > 0)for(i=0,m=Mbase;i<nmaps;i++,m++){
01185  //  m->map=m->mapin;
01186    vecsub(m->xin,m->pin,m->x);
01187    vecsub(m->yin,m->pin,m->y);
01188    cross(m->x,m->y,m->n);
01189    if(normalize(m->n)){ /* bad axis just set up unit */
01190      m->x[0]=1.0; m->x[1]=0.0; m->x[2]=0.0;
01191      m->y[0]=0.0; m->y[1]=1.0; m->y[2]=0.0;
01192      cross(m->x,m->y,m->n);
01193    }
01194  }
01195  for(i = -1; i<nmats; i++){ // for axes 
01196    if(i == -1)a = &(O->Abase);        // default axis for object
01197    else       a = &((Tbase+i)->ax);   // material axes
01198    vecsub(a->buin,a->boin,a->bu);
01199    vecsub(a->bvin,a->boin,a->bv);
01200    cross(a->bu,a->bv,a->bn);
01201    normalize(a->bn);
01202    a->tl=max(1.0,R_length(a->bu));
01203    a->tv=max(1.0,R_length(a->bv));
01204    vecscale(1.0/a->tl,a->bu,a->bu_norm);
01205    vecscale(1.0/a->tv,a->bv,a->bv_norm);
01206  }
01207  for(i=0,f=Fbase;i<nfaces;i++,f++){
01208    if(f->bFmc){;} // face has mapping coords from the designer - do nothing
01209    else if(f->ffmap >= 0){ // if mapped, assign surface coordinates from the map
01210      mapid=f->ffmap;
01211      if(mapid < nmaps){
01212        if((m=(Mbase+mapid))->map != MAP_BY_VERTEX){
01213          for(j=0;j<3;j++){
01214            if(m->map == CYLINDER){
01215               hitcylinder(m->n,m->x,m->y,m->p,
01216                     (Vbase+(f->V[j]))->p,&(alphav[j]),&(betav[j]));
01217            }
01218            else if(m->map == MAP_SPHERICAL){
01219              hitsphere(m->n,m->x,m->y,m->p
01220                     ,(Vbase+(f->V[j]))->p,&(alphav[j]),&(betav[j]));
01221            }
01222            else    /* assume planar map */
01223              hitpoint(m->n,m->x,m->y,m->p
01224                     ,(Vbase+(f->V[j]))->p,&(alphav[j]),&(betav[j]));
01225          }  
01226          if(m->map == CYLINDER || m->map == MAP_SPHERICAL)FixUpMapEdge(alphav);
01227          for(j=0;j<3;j++){
01228            if(m->map == CYLINDER)alphav[j] *= m->angle; // scale for multiple rotations
01229            f->uu[j]=alphav[j];
01230            f->vv[j]=betav[j];
01231            f->ww[j]=0.5;
01232           //if(debug != NULL)fprintf(debug,"Calculating  map coords for face %ld %ld (%lf %lf)\n",i,j,f->uu[j],f->vv[j]);
01233          }
01234        }
01235      }
01236    }
01237    else{ // if not mapped, assign texture coordinated from the shader axis
01238      for(j=0;j<3;j++){
01239        matid=f->ffmat;
01240        if(matid >= 0 && matid < nmats)a = &((Tbase+matid)->ax);
01241        else                           a = &(O->Abase);
01242        gamma=hitpoint(a->bn,
01243                       a->bu,
01244                       a->bv,
01245                       a->bo,
01246                      (Vbase+(f->V[j]))->p,&alpha,&beta);
01247        gamma /= max(1.0,a->tl);
01248        f->uu[j]=alpha;
01249        f->vv[j]=beta;
01250        f->ww[j]=gamma;
01251      }    
01252    }
01253  }
01254  // Reset to use mapping coords for all faces
01255  if(nmaps > 0)for(i=0,m=Mbase;i<nmaps;i++,m++){
01256    m->map = MAP_BY_VERTEX;
01257  }
01258 }
01259 
01260 #define MAPDELTA 0.33333
01261 
01262 static void FixUpMapEdge(GLfloat a[]){
01263  if(a[0] < MAPDELTA){if(a[1] >= 1.0-MAPDELTA)a[1] -= 1.0; if(a[2] >= 1.0-MAPDELTA)a[2] -= 1.0; return;}
01264  if(a[1] < MAPDELTA){if(a[2] >= 1.0-MAPDELTA)a[2] -= 1.0; if(a[0] >= 1.0-MAPDELTA)a[0] -= 1.0; return;}
01265  if(a[2] < MAPDELTA){if(a[0] >= 1.0-MAPDELTA)a[0] -= 1.0; if(a[1] >= 1.0-MAPDELTA)a[1] -= 1.0; return;}
01266 }

Generated on Sun Apr 27 14:20:13 2014 for OpenFX by  doxygen 1.5.6