ftp.nice.ch/pub/next/graphics/3d/geomview.1.4.1.s.tar.gz#/Geomview/src/lib/mg/rib/mgribdraw.c

This is mgribdraw.c in view mode; [Download] [Up]

#include "mgP.h"
#include "mgribP.h"
#include "mgribtoken.h"
#include "polylistP.h"

#define MAXCLINE 999999
void mgrib_drawPline(HPoint3 *p1, HPoint3 *p2);
void mgrib_drawCline(HPoint3 *p1, HPoint3 *p2);

void	mgrib_polygon( int nv, HPoint3 *v, int nn, Point3 *n,
	      	          int nc,ColorA *c );
void	mgrib_mesh( int wrap,int nu,int nv,HPoint3 *p, Point3 *n,ColorA *c );
void	mgrib_line( HPoint3 *p1, HPoint3 *p2 );
void	mgrib_polyline( int nv, HPoint3 *verts, int nc, ColorA *colors,
				int wrapped );
void	mgrib_polylist(  int np, Poly *p, int nv, Vertex *v, 
			     int plflags );
void	mgrib_drawnormal(HPoint3 *p, Point3 *n);
				 


/*-----------------------------------------------------------------------
 * Function:	mgrib_polygon
 * Description:	draw a polygon
 * Author:	wisdom
 * Date:	Thu Aug 26 13:46:25 CDT 1993
 * Notes:	See mg.doc.
 *
 */
void
mgrib_polygon(int nv,  HPoint3 *V, 
	     int nn,  Point3 *N, 
	     int nc,  ColorA *C)
{
  register int i;	
  register HPoint3 *v;
  register Point3 *n;
  register Color *c;
  register ColorA *c4;
  HPoint3 hpt;
  int flag;
  int shading;
  int matover;
  int ninc;

    flag = _mgc->astk->ap.flag;
    shading = _mgc->astk->ap.shading;
    matover = _mgc->astk->mat.override;
    ninc = (nn > 1);
    if ((matover & MTF_DIFFUSE) && !_mgc->astk->useshader) nc = 0;
    
    mrti(mr_polygon,mr_NULL);
    
    /* Points */
    if(nv>0 && (flag & APF_FACEDRAW)) {
	mrti(mr_P,mr_buildarray, nv*3, mr_NULL);
	for(i = 0; i < nv; i++) {
	    /* we cannot descibe a polygon using Pw, so we normalize */
	    HPt3Normalize(&V[i], &hpt);
	    mrti(mr_subarray3, &hpt, mr_NULL);
	}
    }

    /* Supply Color (explicit) */
    if (nc>0 && (flag & APF_FACEDRAW) && !(flag & APF_CONSTANT)) {
	/* note:color should already be set in case of APF_CONSTANT,no?  */
	mrti(mr_Cs, mr_buildarray, nv*3, mr_NULL);
	for(i = 0; i < nv; i++) {
	    if(nc>1) c4 = &C[i]; else c4 = C;
	    mrti(mr_subarray3, (float *)c4, mr_NULL);
	}
    }

    /* Supply Transparency */
    if(nc>0 && flag & APF_TRANSP && !(matover & MTF_ALPHA)) {
	mrti(mr_Os, mr_buildarray, nv*3, mr_NULL);
	for(i = 0; i < nv; i++) {
	    float opacity[3];
	    if(nc>1) c4 = &C[i]; else c4 = C;
	    opacity[0]=opacity[1]=opacity[2]=c4->a;
	    mrti(mr_subarray3, opacity, mr_NULL);
	}
    }
    /* Supply Normals */
    if (nn>0 && (flag & APF_FACEDRAW) && !(flag & APF_CONSTANT)) {
	mrti(mr_N, mr_buildarray, nv*3, mr_NULL); 
	for(i = 0; i < nv; i++) {
	    if(nn>1) n = &N[i]; else n = N;
	    mrti(mr_subarray3, n, mr_NULL);
	}
    }
    
    /* Draw Edges */
    if(flag & APF_EDGEDRAW) {
	c = &_mgc->astk->ap.mat->edgecolor;
	mrti(mr_attributebegin,
	    mr_surface, mr_constant, 
	    mr_color, mr_parray, 3, c,
	    mr_opacity, mr_array, 3, 1., 1., 1., mr_NULL);
	
	for(i=0;i<nv-1;i++) mgrib_drawline(&V[i],&V[i+1]);
	mgrib_drawline(&V[i],&V[0]);
	mrti(mr_attributeend, mr_NULL);
    }
    
    /* Draw Normals */
    if(flag & APF_NORMALDRAW) {
    for (n = N, v = V, i = 0; i<nv; ++i, ++v, n += ninc)
	mgrib_drawnormal(v, n);
    }
}

/*-----------------------------------------------------------------------
 * Function:	mgrib_line
 * Description:	draws a line
 * Author:	wisdom
 * Date:	Fri Jan 17 14:31:06 CST 1992
 * Notes:	see mg.doc
 */
void mgrib_line( HPoint3 *p1, HPoint3 *p2 )
{
    mrti(mr_attributebegin, mr_surface, mr_constant, mr_NULL);
    mgrib_drawline(p1,p2);
    mrti(mr_attributeend, mr_NULL);
}

/*-----------------------------------------------------------------------
 * Function:	mgrib_drawline, mgrib_drawPline, mgrib_drawCline, bounded
 * Description: draws a line for rman.
 * Returns:	nothing
 * Author:	wisdom, gunn, slevy, munzner
 * Date:	Tue Feb 18 14:20:29 CST 1992
 * Notes:
 */
void
mgrib_drawline(HPoint3 *p1, HPoint3 *p2)
{
	if(_mgribc->line_mode==MG_RIBPOLYGON) mgrib_drawPline(p1,p2);
	if(_mgribc->line_mode==MG_RIBCYLINDER) mgrib_drawCline(p1,p2);
	if(_mgribc->line_mode==MG_RIBPRMANLINE)
		NotImplemented("MG_RIBPRMANLINE");
}

void
mgrib_drawPline(HPoint3 *p1, HPoint3 *p2)
{
    Transform V;
    Transform P2S,O2S, O2P, P2O, S2O;
    int xsize, ysize;
    HPoint3 pnts[4], pnts2[4];
    HPoint3 s1, s2;
    int i;
    float dx,dy,k, len;

    /* This code will simulate line drawing in Photorman */
    /* create obj->proj transform */
    CamView(_mgc->cam, V);		/* world->proj */
    TmConcat(_mgc->xstk->T, V, O2P);	/* obj->proj */
    
    /* create obj->screen transform */
    WnGet(_mgc->win, WN_XSIZE, &xsize);
    WnGet(_mgc->win, WN_YSIZE, &ysize);
    TmScale(P2S, (float)xsize, (float)ysize, 1.0);
    TmConcat(O2P, P2S, O2S);
    
    /* translate & dehomogenize line endpoints from object to screen */
    HPt3TransPt3(O2S, p1, &s1);
    HPt3TransPt3(O2S, p2, &s2);

    dy = s2.y - s1.y;
    dx = s2.x - s1.x;
    len = hypot(dy,dx);
    k = _mgc->astk->ap.linewidth / len;
    
    pnts[0].x = s1.x -dy * k;
    pnts[0].y = s1.y +dx * k;
    pnts[1].x = s1.x +dy * k;
    pnts[1].y = s1.y -dx * k;
    pnts[2].x = s2.x +dy * k;
    pnts[2].y = s2.y -dx * k;
    pnts[3].x = s2.x -dy * k;
    pnts[3].y = s2.y +dx * k;
	    
    pnts[0].z = s1.z;
    pnts[1].z = s1.z;
    pnts[2].z = s2.z;
    pnts[3].z = s2.z;
    
    for (i=0; i<4; ++i) pnts[i].w = 1.0;
 	    
    /* now project back... */
    /* first, find S2O transform */
    TmInvert(O2S, S2O);
    
    /* now transform screen coords to object coords */
    
    /* DRAW HERE */
    mrti(mr_polygon, mr_P, mr_buildarray, 4*3, mr_NULL);
    for(i=0;i<4;i++) {
	HPoint3 pt;

	HPt3Transform(S2O, &pnts[i], &pt);
	HPt3Normalize(&pt, &pt);
	mrti(mr_subarray3, &pt, mr_NULL);
    }
}

void
mgrib_drawCline(HPoint3 *p1, HPoint3 *p2)
{
  Pt3Coord angle,length;
  Point3 t,xn,yn,axis;
  Point3 start, end;
  HPoint3 Hstart, Hend;
  static float unitz[3] = {0.0, 0.0, 1.0};
  float radius = .005;
  float size;
  int bounded(Point3 *p);
  
    HPt3Normalize(p1, &Hstart);
    HPt3Normalize(p2, &Hend);
    
    start.x = Hstart.x;
    start.y = Hstart.y;
    start.z = Hstart.z;
    
    end.x = Hend.x;
    end.y = Hend.y;
    end.z = Hend.z;
    
    if (! Pt3Equal(&start,&end)) {
	size = radius*_mgc->astk->ap.linewidth;
	Pt3Sub(&end,&start,&t);
	length = Pt3Length(&t);
	Pt3Cross((Point3*)unitz,&t,&axis);
	Pt3Unit(&t);
	angle = Pt3Dot((Point3*)unitz,&t);
	angle = acos(angle);
	mrti(mr_transformbegin, mr_NULL);
	if (bounded(&start))
	    mrti(mr_translate,
	    	mr_float, start.x,
		mr_float, start.y,
		mr_float, start.z, mr_NULL);
	if ( (t.x == 0.0) && (t.y == 0.0) && (t.z < 0.0)) {
	    /* if along negative z axis cross product is 0
	    but rotation by 180 degrees is necessary
	    (angle is computed correctly) */
	    axis.y = 1.0;
	}
	if (bounded(&axis))
	    mrti(mr_rotate, mr_float, DEGREES(angle),
	    	mr_float, axis.x, mr_float, axis.y, mr_float, axis.z, mr_NULL);
	if (length < MAXCLINE)
	    mrti(mr_cylinder, mr_float, size, mr_float, 0.,
	    	mr_float, length, mr_float, 360., mr_NULL);
	mrti(mr_transformend, mr_NULL);
    }
}

int 
bounded(p)
Point3 *p;
{
  if (! Pt3Equal(p,&Pt3Origin)) {
    if (p->x < MAXCLINE && p->y < MAXCLINE && p->z < MAXCLINE) 
      return 1;
  } else {
    return 0;
  }
}



/*-----------------------------------------------------------------------
 * Function:	mgrib_polyline
 * Description:	draws a Polyline
 * Author:	wisdom
 * Date:	Fri Jan 17 14:31:06 CST 1992
 * Notes:	see mg.doc
 */
void mgrib_polyline( int nv, HPoint3 *v, int nc, ColorA *c, int wrapped )
{
	ColorA *color;
	
	mrti(mr_attributebegin, mr_surface, mr_constant, mr_NULL);
	if(nc==0) mrti(mr_color, mr_parray, 3,
	    &_mgc->astk->mat.edgecolor, mr_NULL);
	if(nc==1) mrti(mr_color, mr_parray, 3, c, mr_NULL);
	if(nv == 1) {
		mgrib_drawpoint(v);
	}
	else {
	    if(wrapped & 1) {
		if(nc > 1) {
		    color = c + nc - 1;
		    mrti(mr_color, mr_parray, 3, color, mr_NULL);
		}
		mgrib_drawline(v + nv - 1,v);
	    }
    
	    while(--nv > 0) {
		if(nc > 1) {
		    color = c++;
		    mrti(mr_color, mr_parray, 3, color, mr_NULL);
		}
		mgrib_drawline(v,(v+1));
		v++;
	    }
	}
	
	mrti(mr_attributeend, mr_NULL);

}

/*-----------------------------------------------------------------------
 * Function:	mgrib_drawpoint
 * Description: draws a point for rman.
 * Returns:	nothing
 * Author:	wisdom
 * Date:	Fri Mar 13 15:04:01 CST 1992	
 * Notes:
 */

void
mgrib_drawpoint(HPoint3 *p)
{
    float radius = 0.005;
    float size = radius*_mgc->astk->ap.linewidth;
    
    mrti(mr_transformbegin, mr_NULL);
    mrti(mr_translate, mr_float, p->x, mr_float, p->y, 
	 mr_float, p->z, mr_NULL);
    mrti(mr_sphere, mr_float, size, mr_float, size, mr_float, -size,
	mr_float, 360., mr_NULL);
    mrti(mr_transformend, mr_NULL);
}

/*-----------------------------------------------------------------------
 * Function:	mgrib_polylist
 * Description:	draws a Polylist: linked list of Polys
 * Author:	wisdom
 * Date:	Wed Jan 22 16:07:03 CST 1992
 * Notes:	see mg.doc
 */
void mgrib_polylist( int np, Poly *P, int nv, Vertex *V, int plflags )
{
  register int i,j;
  register Poly *p;
  register Vertex **v, *vp;
  register Point3 *n;
  HPoint3 hpt;
  int flag,shading,matover;
  Color *color;
  ColorA *colorA;
  
  
  flag = _mgc->astk->ap.flag;
  shading = _mgc->astk->ap.shading;
  matover = _mgc->astk->mat.override;

  if((matover & MTF_DIFFUSE) && !_mgc->astk->useshader)
    plflags &= ~(PL_HASVCOL | PL_HASPCOL);
  
  if (shading & APF_CONSTANT) plflags &= ~(PL_HASVN|PL_HASPN);
  else if (shading & APF_FLAT) plflags &= ~PL_HASVN;
  else if (shading & APF_SMOOTH) plflags &= ~PL_HASPN;

  if (flag & APF_FACEDRAW) {
    mrti(mr_attributebegin, mr_NULL);
    for (p = P, i = 0; i < np; i++, p++) {
      
      /* per polygon color */
      if (plflags & PL_HASPCOL) {
	mrti(mr_color, mr_parray, 3, &p->pcol, mr_NULL);
	/* then per-polygon transparency, if defined */
	if (flag & APF_TRANSP && !(matover & MTF_ALPHA)) {
	  mrti(mr_Os, mr_array, 3, 
	       p->pcol.a, p->pcol.a, p->pcol.a, mr_NULL);
	}
      }
      switch (p->n_vertices) {
      case 1:
	v = p->v;
	mrti(mr_attributebegin, mr_NULL);
	if(plflags & PL_HASVCOL) 
	  mrti(mr_color, mr_parray, 3, &(*v)->vcol, mr_NULL);	      
	mrti(mr_surface, mr_constant,
	     mr_opacity, mr_array, 3, 1., 1., 1., mr_NULL);
	mgrib_drawpoint((HPoint3 *)(*v));
	mrti(mr_attributeend, mr_NULL);
	break;
      case 2:
	v = p->v;
	mrti(mr_attributebegin, mr_NULL);
	if(plflags & PL_HASVCOL)
	  mrti(mr_color, mr_parray, 3, &(*v)->vcol, mr_NULL);	      
	mrti(mr_surface, mr_constant,
	     mr_opacity, mr_array, 3, 1., 1., 1., mr_NULL);
	mgrib_drawline((HPoint3 *)*v,(HPoint3*)*(v+1));
	mrti(mr_attributeend, mr_NULL);
	break;
      default:
	mrti(mr_polygon, mr_NULL);
	
	/* do points */
	mrti(mr_P, mr_buildarray, p->n_vertices*3, mr_NULL);
	for (j=0, v=p->v; j < p->n_vertices; j++, v++) {
	  HPt3Normalize(&(*v)->pt, &hpt);
	  mrti(mr_subarray3, &hpt, mr_NULL);
	}
	
	/* colors, if supplied */
	if(plflags & PL_HASVCOL) {
	  mrti(mr_Cs, mr_buildarray, p->n_vertices*3, mr_NULL);
	  for (j=0, v=p->v; j < p->n_vertices; j++, v++) {
	    mrti(mr_subarray3, &(*v)->vcol, mr_NULL);
	  }
	  /* then per-vertex transparency, if defined */
	  if(flag & APF_TRANSP && !(matover & MTF_ALPHA)) {
	    mrti(mr_Os, mr_buildarray, p->n_vertices*3, mr_NULL);
	    for (j=0, v=p->v; j < p->n_vertices; j++, v++) {
	      float opacity[3];
	      opacity[0]=opacity[1]=opacity[2]=(*v)->vcol.a;
	      mrti(mr_subarray3, opacity, mr_NULL);
	    }
	  }
	}
	
	/* now normals, if supplied */
	if(plflags & PL_HASVN) {
	  mrti(mr_N, mr_buildarray, p->n_vertices*3, mr_NULL);
	  for (j=0, v=p->v; j < p->n_vertices; j++, v++) {
	    mrti(mr_subarray3, &((*v)->vn), mr_NULL);
	  }
	} else if(plflags & PL_HASPN) {
	  mrti(mr_N, mr_buildarray, p->n_vertices*3, mr_NULL);
	  for(j=0, v=p->v; j< p->n_vertices; j++, v++) {
	    mrti(mr_subarray3, &(p->pn), mr_NULL);
	  }
	}
	break;
      }
    }
    mrti(mr_attributeend, mr_NULL);
  }    
  if (flag & APF_EDGEDRAW) {
    color = &_mgc->astk->ap.mat->edgecolor;
    mrti(mr_attributebegin, mr_surface, mr_constant,
	 mr_color, mr_parray, 3, color,
	 mr_opacity, mr_array, 3, 1., 1., 1., mr_NULL);
    
    for (p = P, i = 0; i < np; i++, p++) {	
      for (j=0, v=p->v; j < (p->n_vertices-1); j++, v++) {
	mgrib_drawline((HPoint3 *)*v,(HPoint3*)*(v+1));
      }
      mgrib_drawline((HPoint3 *)*v,(HPoint3 *)*(p->v));
    }
    mrti(mr_attributeend,mr_NULL);
  }
  
  
  if (flag & APF_NORMALDRAW) {
    /* since mg_drawnormal handles attributes and stacking, we do nothing here */
    if (plflags & PL_HASPN) {
      for (p = P, i = 0; i < np; i++, p++) {
	for (j=0, v=p->v; j < p->n_vertices; j++, v++) {
	  mgrib_drawnormal(&(*v)->pt, &p->pn);
	}
      }
    } else if (plflags & PL_HASVN) {
      for (vp = V, i = 0; i < nv; i++, vp++) {
	mgrib_drawnormal(&vp->pt, &vp->vn);
      }
    }
  }
  
}

/* There is a basic problem now with 4-d points and 3-d normal vectors.
For now, we'll just ignore the 4-th coordinate of the point when 
computing the tip of the normal vector.  This will work OK with all
existing models, but for genuine 4-d points it won't work.  But,
come to think of it, what is the correct interpretation of the
normal vector when the points live in 4-d?
*/
void
mgrib_drawnormal(HPoint3 *p, Point3 *n) {	
    HPoint3 end, tp;
    float scale;
    Color *color;
    
    if (p->w <= 0.0) return;
    scale = p->w * _mgc->astk->ap.nscale;
    end.x = p->x + scale*n->x;
    end.y = p->y + scale*n->y;
    end.z = p->z + scale*n->z;
    end.w = p->w;

    color = &_mgc->astk->mat.normalcolor;
    mrti(mr_attributebegin, mr_surface, mr_constant,
	 mr_color, mr_parray, 3, color,
	 mr_opacity, mr_array, 3, 1., 1., 1., mr_NULL);
    mgrib_drawline(&tp,&end);
    mrti(mr_attributeend, mr_NULL);
    
}

void
mgrib_bezier( int du, int dv, int dimn, float *CtrlPnts, float *txmapst, ColorA *c )
{
    int i, ip, nu, nv;
    static float *uknot=NULL, *vknot=NULL;
    static size_t ulen=0,vlen=0;
    size_t nulen=0, nvlen=0;
    int  flag = _mgc->astk->ap.flag;
    int  matover = _mgc->astk->mat.override;

    du += 1;
    dv += 1;
    nu = du;
    nv = dv;
    ip = nu * nv * dimn; 

    if(!uknot) {
    	ulen=nu+du;
	uknot=(float *)malloc(ulen*sizeof(float));
    }
    if(!vknot) {
    	vlen=nv+dv;
	vknot=(float *)malloc(vlen*sizeof(float));
    }
    nulen=nu+du;
    nvlen=nv+dv;
    if(nulen>ulen) uknot=(float *)realloc(uknot,(ulen=nulen)*sizeof(float));
    if(nvlen>vlen) vknot=(float *)realloc(vknot,(vlen=nvlen)*sizeof(float));
    
    /* uknot = (float *)malloc((nu+du)*sizeof(float)); */
    for(i=0;i<nu;i++) uknot[i] = 0;
    for(i=nu;i<(nu+du);i++) uknot[i] = 1;
    
    /* vknot = (float *)malloc((nv+dv)*sizeof(float)); */
    for(i=0;i<nv;i++) vknot[i] = 0;
    for(i=nv;i<(nv+dv);i++) vknot[i] = 1;

    mrti(mr_nupatch, mr_int, nu, mr_int, du, mr_NULL);
    mrti(mr_parray, (nu+du), uknot, mr_NULL);
    mrti(mr_int, 0, mr_int, (nu-1), mr_int, nv, mr_int, dv, mr_NULL);
    mrti(mr_parray, (nv+dv), vknot, mr_NULL);
    mrti(mr_int, 0, mr_int, nv -1, mr_NULL);
    
    mrti(dimn == 3 ? mr_P : mr_Pw,
	mr_parray, ip, CtrlPnts, mr_NULL);
    
    /* free(uknot); */
    /* free(vknot); */
    
    if(c && !( (matover & MTF_DIFFUSE) && !_mgc->astk->useshader) ) {
        mrti(mr_Cs, mr_buildarray,  12, mr_NULL);
	for (i = 0; i < 4; i++) {
	    mrti(mr_subarray3, (float *)&c[i], mr_NULL);
	}
	if(flag & APF_TRANSP && !(matover & MTF_ALPHA)) {
	    float opacity[3];
	    opacity[0]=opacity[1]=opacity[2]=c[i].a;
	    mrti(mr_Os, mr_buildarray, 12, mr_NULL);
	    for (i = 0; i < 4; i++) {
	        mrti(mr_subarray3, opacity, mr_NULL);
	    }
	}
    }
    
    if(txmapst) {
        mrti(mr_nl, mr_st, mr_parray, 8, txmapst, mr_NULL);
    }
}

These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.