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

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

/* Copyright (c) 1992 The Geometry Center; University of Minnesota
   1300 South Second Street;  Minneapolis, MN  55454, USA;
   
This file is part of geomview/OOGL. geomview/OOGL is free software;
you can redistribute it and/or modify it only under the terms given in
the file COPYING, which you should have received along with this file.
This and other related software may be obtained via anonymous ftp from
geom.umn.edu; email: software@geom.umn.edu. */

/* Authors: Charlie Gunn, Stuart Levy, Tamara Munzner, Mark Phillips */

#include "mgP.h"
#include "mgglP.h"
#include "polylistP.h"
#include <gl/gl.h>

void	mggl_polygon( int nv, HPoint3 *v, int nn, Point3 *n,
	      	          int nc,ColorA *c );
void	mggl_mesh( int wrap,int nu,int nv,HPoint3 *p, Point3 *n,ColorA *c );
void	mggl_line( HPoint3 *p1, HPoint3 *p2 );
void	mggl_polyline( int nv, HPoint3 *verts, int nc, ColorA *colors, int wrap );
void	mggl_polylist(  int np, Poly *p, int nv, Vertex *v, 
			     int plflags );
void	mggl_drawnormal(HPoint3 *p, Point3 *n);

void	mggl_closer();
void	mggl_farther();

/*-----------------------------------------------------------------------
 * Function:	mggl_polygon
 * Description:	draw a polygon
 * Author:	mbp, munzner
 * Date:	Mon Jul 29 16:53:56 1991
 * Notes:	See mg.doc.
 *
 *              do later: Different shading cases separated into different
 *		loops for speed.
 */
void
mggl_polygon(int nv,  HPoint3 *V, 
	     int nn,  Point3 *N, 
	     int nc,  ColorA *C)
{
  register int i;	
  register HPoint3 *v;
  register Point3 *n;
  register ColorA *c;
  int cinc, ninc;
  int flag;

  flag = _mgc->astk->ap.flag;
  if ((_mgc->astk->mat.override & MTF_DIFFUSE) && !_mgc->astk->useshader)
    nc = 0;
  cinc = (nc > 1);
  ninc = (nn > 1);
  if(nc == 0)
    C = (ColorA*)&_mgc->astk->ap.mat->diffuse;


  /* reestablish correct drawing color if necessary */

  if (flag & APF_FACEDRAW) {
    lmcolor(_mgglc->lmcolor);
    bgnpolygon();
    if (nc <= 1)
	(*_mgglc->d4f)(&(_mgc->astk->ap.mat->diffuse));
    for (n = N, c = C, v = V, i = 0; i<nv; ++i, ++v) {
	if (nc) { (*_mgglc->d4f)(c); c += cinc; }
	if (nn) { (*_mgglc->n3f)(n,v); n += ninc; }
	v4f((float *)v);
    }
    endpolygon();
  }

  if( flag & (APF_EDGEDRAW|APF_NORMALDRAW) ) {
    if(_mgglc->znudge) mggl_closer();
    lmcolor(LMC_COLOR);
    if (flag & APF_EDGEDRAW) {
	c3f((float *)&_mgc->astk->ap.mat->edgecolor);
	bgnclosedline();
	for (v = V, i = 0; i<nv; ++i, ++v)
	  v4f((float *)v);
	endclosedline();
    }

    if (flag & APF_NORMALDRAW) {
	c3f((float *)&_mgc->astk->ap.mat->normalcolor);
	for (n = N, v = V, i = 0; i<nv; ++i, ++v, n += ninc) {
	    mggl_drawnormal(v, n);
	}
    }
    if(_mgglc->znudge) mggl_farther();
  }
}

void
mggl_quads(int count,  HPoint3 *V, Point3 *N, ColorA *C)
{
  int i;	
  register int k;
  register HPoint3 *v;
  register Point3 *n;
  register ColorA *c;
  ColorA cs[4];
  int flag;

#define QUAD(stuff)  { \
		register int k = 4;		\
		bgnpolygon();			\
		do { stuff; } while(--k > 0);	\
		endpolygon();			\
	}

  if(count <= 0)
    return;
  flag = _mgc->astk->ap.flag;
  if ((_mgc->astk->mat.override & MTF_DIFFUSE) && !_mgc->astk->useshader)
    C = NULL;
  
  /* reestablish correct drawing color if necessary */

  if (flag & APF_FACEDRAW) {
    lmcolor(_mgglc->lmcolor);
    i = count;
    v = V; c = C; n = N;
    if(c) {
	if(n) {
	    do {
		QUAD( ((*_mgglc->d4f)(c++), (*_mgglc->n3f)(n++,v),
				    v4f((float*)v++)) );
	    } while(--i > 0);
	} else {
	    /* Colors, no normals */
	    do {
		QUAD( ((*_mgglc->d4f)(c++), v4f((float*)v++)) );
	    } while(--i > 0);
	}
    } else {
	c = (ColorA*)&_mgc->astk->ap.mat->diffuse;
	if(n) {
	    (*_mgglc->d4f)(c);
	    do {
		QUAD( ((*_mgglc->n3f)(n++, v), v4f((float*)v++)) );
	    } while(--i > 0);
	} else {
	    (*_mgglc->d4f)(c);
	    do {
		QUAD( (v4f((float*)v++)) );
	    } while(--i > 0);
	}
    }
  }

  if( flag & (APF_EDGEDRAW|APF_NORMALDRAW) ) {
    if(_mgglc->znudge) mggl_closer();
    lmcolor(LMC_COLOR);
    if (flag & APF_EDGEDRAW) {
	c3f((float *)&_mgc->astk->ap.mat->edgecolor);
	i = count; v = V;
	do {
	    register int k = 4;
	    bgnclosedline();
	    do { v4f((float *)v++); } while(--k > 0);
	    endclosedline();
	} while(--i > 0);
    }

    if (flag & APF_NORMALDRAW && N) {
	c3f((float *)&_mgc->astk->ap.mat->normalcolor);
	i = count*4; v = V; n = N;
	do {
	    mggl_drawnormal(v++, n++);
	} while(--i > 0);
    }
    if(_mgglc->znudge) mggl_farther();
  }
}


void mggl_line( HPoint3 *p1, HPoint3 *p2 )
{
  bgnline();
  v4f((float *)p1);
  v4f((float *)p2);
  endline();
}

void mggl_point(register HPoint3 *v)
{
  int i;
  HPoint3 a;
  register HPoint3 *p, *q;
  float vw;

  if(_mgc->astk->ap.linewidth > 1) {
    
    if(!(_mgc->has & HAS_POINT))
      mg_makepoint();
    /* Compute w component of point after projection to screen */
    vw = v->x * _mgc->O2S[0][3] + v->y * _mgc->O2S[1][3]
      + v->z * _mgc->O2S[2][3] + v->w * _mgc->O2S[3][3];
    if(vw <= 0) return;
    
#define  PUT(p)  					\
    a.x = v->x + p->x*vw; a.y = v->y + p->y*vw;	\
      a.z = v->z + p->z*vw; a.w = v->w + p->w*vw;	\
	v4f((float *)&a)
	  
	  p = VVEC(_mgc->point, HPoint3);
    q = p + VVCOUNT(_mgc->point);
    
    if(_mgglc->is_PI) {
      bgnpolygon();
      do {
	PUT(p);
      } while(++p < q);
      endpolygon();
    } else {
      bgntmesh();
      PUT(p);
      do {
	p++;
	PUT(p);
	if(p >= q) break;
	q--;
	PUT(q);
      } while(p < q);
      endtmesh();
    }
  } else {
    bgnpoint();
    v4f((float *)v);
    endpoint();
  }
}
  

void mggl_polyline( int nv, HPoint3 *v, int nc, ColorA *c, int wrapped )
{
  int remain;

  /* note we don't reset to current material color because we could be
   * in the middle of a list of lines and should inherit the color from 
   * the last color call.
   */
  
  if(!(wrapped & 2)) {
	/* First member of batch */
      if(_mgglc->znudge) mggl_closer();
      if(nc)
	  lmcolor(LMC_COLOR);
  }
  if (nv == 1) {
    if(nc > 0) c4f((float *)c);
    mggl_point(v);
  } 
  else if(nv > 0) {
    bgnline();
    if(wrapped & 1) {
      if(nc > 0) c4f((float *)(c + nc - 1));
      v4f((float *)(v + nv - 1));
    }

    for(;;) {
	remain = nv > 254 ? 254 : nv;
	nv -= remain;
	do {
	    if(--nc >= 0) c4f((float *)c++);
	    v4f((float *)v++);
	} while(--remain > 0);
	if(nv == 0)
	    break;
	if(nc > 0) c4f((float *)c);
	v4f((float *)v);
	endline();
	bgnline();
    }
    endline();
  }
  if(!(wrapped & 4) && _mgglc->znudge) mggl_farther();
}


/*-----------------------------------------------------------------------
 * Function:	mggl_polylist
 * Description:	draws a Polylist: collection of Polys
 * Author:	munzner
 * Date:	Wed Oct 16 20:21:56 1991
 * Notes:	see mg.doc
 */
void mggl_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;
  struct mgastk *ma = _mgc->astk;
  void (*n3func)() = _mgglc->n3f;
  int flag,shading;
  int nonsurf = -1;
  flag = ma->ap.flag;
  shading = ma->ap.shading;

  switch(shading) {
  case APF_FLAT: plflags &= ~PL_HASVN; break;
  case APF_SMOOTH: plflags &= ~PL_HASPN; break;
  default: plflags &= ~(PL_HASVN|PL_HASPN); break;
  }

  if((_mgc->astk->mat.override & MTF_DIFFUSE) && !_mgc->astk->useshader)
    plflags &= ~(PL_HASVCOL | PL_HASPCOL);

  if (flag & APF_FACEDRAW) {
    lmcolor(_mgglc->lmcolor);
    /* reestablish correct drawing color if necessary*/
    if (!(plflags & (PL_HASPCOL | PL_HASVCOL)))
	(*_mgglc->d4f)(&(ma->ap.mat->diffuse));

    for (p = _p, i = 0; i < np; i++, p++) {
	if (plflags & PL_HASPCOL)
	    (*_mgglc->d4f)(&p->pcol);
	if (plflags & PL_HASPN)
	    (*n3func)(&p->pn, &(*p->v)->pt);
	v = p->v;
	if((j = p->n_vertices) <= 2) {
	    nonsurf = i;
	} else {
	    bgnpolygon();
	    do {
		if (plflags & PL_HASVCOL) (*_mgglc->d4f)(&(*v)->vcol);
		if (plflags & PL_HASVN) (*n3func)(&(*v)->vn, &(*v)->pt);
		v4f((float *)&(*v)->pt);
		v++;
	    } while(--j > 0);
	    endpolygon();
	}
    }
  }

  if (flag & (APF_EDGEDRAW|APF_NORMALDRAW) || nonsurf >= 0) {
    if(_mgglc->znudge) mggl_closer();
    lmcolor(LMC_COLOR);

    if (flag & APF_EDGEDRAW) {
	c3f((float *)&_mgc->astk->ap.mat->edgecolor);
	for (p = _p, i = 0; i < np; i++, p++) {
	    bgnclosedline();
	    for (j=0, v=p->v; j < p->n_vertices; j++, v++) {
		v4f((float *)&(*v)->pt);
	    }
	    endclosedline();
	}
    }

    if (flag & APF_NORMALDRAW) {
	c3f((float *)&_mgc->astk->ap.mat->normalcolor);
	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++)
		  mggl_drawnormal(&(*v)->pt, &p->pn);
	    }
	} else if (plflags & PL_HASVN) {
	    for (vp = V, i = 0; i < nv; i++, vp++) {
		mggl_drawnormal(&vp->pt, &vp->vn);
	    }
	}
    }


    if (nonsurf >= 0) {
      /* reestablish correct drawing color if necessary*/
      if (!(plflags & (PL_HASPCOL | PL_HASVCOL)))
	(*_mgglc->d4f)(&(ma->ap.mat->diffuse));
      
      for(p = _p, i = 0; i <= nonsurf; p++, i++) {
	if (plflags & PL_HASPCOL)
	  (*_mgglc->d4f)(&p->pcol);
	v = p->v;
	switch(j = p->n_vertices) {
	case 1:
	  if(plflags & PL_HASVCOL) c4f((float *)&(*v)->vcol);
	  mggl_point(&(*v)->pt);
	  break;
	case 2:
	  bgnline();
	  do {
	    if(plflags & PL_HASVCOL) c4f((float *)&(*v)->vcol);
	    v4f((float *)&(*v)->pt);
	    v++;
	  } while(--j > 0);
	  endline();
	  break;
	}
      }
    }
    if(_mgglc->znudge) mggl_farther();
  }
}

/*
 * Z-shift routines: for moving edges closer than faces, etc.
 */
mggl_init_zrange()
{
  register struct mgglcontext *gl = _mgglc;

  gl->znudge = _mgc->zfnudge * (gl->zmax - gl->zmin);

  gl->znear = gl->zmin + abs(gl->znudge * MAXZNUDGE);
  gl->zfar = gl->zmax - abs(gl->znudge * MAXZNUDGE);
  lsetdepth(gl->znear, gl->zfar);
}

void
mggl_closer()
{
  lsetdepth( _mgglc->znear -= _mgglc->znudge, _mgglc->zfar -= _mgglc->znudge );
}
void
mggl_farther()
{
  lsetdepth( _mgglc->znear += _mgglc->znudge, _mgglc->zfar += _mgglc->znudge );
}

/* 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
mggl_drawnormal(register HPoint3 *p, Point3 *n)
{
  Point3 end, tp;
  float scale;

  if (p->w <= 0.0) return;
  if(p->w != 1) {
    HPt3ToPt3(p, &tp);
    p = (HPoint3 *)&tp;
  }

  scale = _mgc->astk->ap.nscale;
  if(_mgc->astk->ap.flag & APF_EVERT) {
    register Point3 *cp = &_mgc->cpos;
    if(!(_mgc->has & HAS_CPOS))
	mg_findcam();
    if((p->x-cp->x) * n->x + (p->y-cp->y) * n->y + (p->z-cp->z) * n->z > 0)
	scale = -scale;
  }

  end.x = p->x + scale*n->x;
  end.y = p->y + scale*n->y;
  end.z = p->z + scale*n->z;
  bgnline();
  v3f((float *)p);
  v3f((float *)&end);
  endline();
}

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