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

This is mgglmesh.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 <gl/gl.h>
#include <mgP.h>
#include <mgglP.h>

#undef P
/* ^^^ evil kludge XXX to get the P variables here to not get confused
 * with the P prototype macro. -nils */
#define	HAS_N	1
#define	HAS_C	2
#define	HAS_SMOOTH 4

int
mggl_mesh( wrap, nu, nv, P, N, C)
    int wrap;
    int nu, nv;
    HPoint3 *P;
    Point3 *N;
    ColorA *C;
{
  return mgsubmesh( wrap, nu, nv, 0, nu-1, 0, nv-1, P, N, C);
}

mgsubmesh( wrap, nu, nv, umin, umax, vmin, vmax, meshP, meshN, meshC)
    int wrap;
    int umin, umax, vmin, vmax;
    HPoint3 *meshP;
    Point3 *meshN;
    ColorA *meshC;
{
  register int u, v;
  int ucnt, vcnt;
  register HPoint3 *P;
  register Point3 *N;
  register ColorA *C;
  register int prev;
  int du;
  int douwrap;
  HPoint3  tp;
  Point3 tn;
  int i;
  int has;
  Appearance *ap;


  if(nu <= 0 || nv <= 0)
    return 0;

  ap = &_mgc->astk->ap;
  if ((_mgc->astk->mat.override & MTF_DIFFUSE) && !_mgc->astk->useshader)
    meshC = 0;

  has = 0;
  if(meshN)
    has = HAS_N;
  if(meshC)
    has |= HAS_C;
  if(ap->shading == APF_SMOOTH)
    has |= HAS_SMOOTH;


  if( ap->flag & APF_FACEDRAW ) {	/* Draw faces */

    /* We triangulate strips of (v,u) mesh points:
     *  (v,u)    (v,u+1)    (v,u+2) ...
     *  (v+1,u)  (v+1,u+1)  (v+1,u+2) ...
     * using the vertex sequence
     *  (v,u) , (v+1,u), (v,u+1), (v+1,u+1), (v,u+2), ...
     * This covers the territory from v to v+1; then repeat for other v's.
     * If we hit the 256-vertex triangle-mesh limit, the strip is spliced
     * by redrawing the latest (v,u+i),(v+1,u+i) pair of vertices.
     */

    register void (*n3func)() = _mgglc->n3f;
    register void (*d4func)() = _mgglc->d4f;

    lmcolor(_mgglc->lmcolor);
    if(!(has & HAS_C))
	(*_mgglc->d4f)(&ap->mat->diffuse);

    v = vmax - vmin + 1;
    du = umin + vmin * nu;

    if(wrap & MM_VWRAP) {
      /* V-wrapping: cur = mesh[vmin,u], prev = mesh[vmax,u] */
      prev = nu * (v - 1);
    } else {
      /* Not V-wrapping: cur = mesh[vmin+1,u], prev = mesh[vmin,u] */
      du += nu;
      prev = -nu;
      v--;	/* One less V-row, too */
    }

    do {					/* Loop over V */
     P = meshP + du;
     N = meshN + du;
     C = meshC + du;
     ucnt = umax - umin + 1;
     if(_mgglc->turbo) {
	mgglpolymeshrow(wrap, has, prev, ucnt, P,
		has&HAS_N ? N : NULL,
		has&HAS_C ? C : NULL);
     } else {
      bgntmesh();
      douwrap = (wrap & MM_UWRAP);
      do {
	/* Loop over U */
	u = ucnt < 126 ? ucnt : 126;	/* 256-vertex tmesh limit */
	ucnt -= u;

	switch( has ) {

	case 0:
	case HAS_SMOOTH:
	  do {
	    v4f((float *)P+prev);
	    v4f((float *)P);
	    P++;
	  } while(--u);
	  break;

	case HAS_C:
	  do {
	    (*d4func)(C+prev); v4f((float *)(P+prev));
	    v4f((float *)P);
	    C++; P++;
	  } while(--u);
	  break;

	case HAS_C|HAS_SMOOTH:
	  do {
	    (*d4func)(C+prev); v4f((float *)(P+prev));
	    (*d4func)(C); v4f((float *)P);
	    C++; P++;
	  } while(--u);
	  break;

	case HAS_N:
	  do {
	    (*n3func)(N+prev,P); v4f((float *)(P+prev));
	    v4f((float *)P);
	    N++; P++;
	  } while(--u);
	  break;

	case HAS_N|HAS_SMOOTH:
	  do {
	    (*n3func)(N+prev,P); v4f((float *)(P+prev));
	    (*n3func)(N,P); v4f((float *)P);
	    N++; P++;
	  } while(--u);
	  break;

	case HAS_C|HAS_N:
	  do {
	    (*d4func)(C+prev); (*n3func)(N+prev,P); v4f((float *)(P+prev));
	    v4f((float *)P);
	    C++; N++; P++;
	  } while(--u);
	  break;

	case HAS_C|HAS_N|HAS_SMOOTH:
	  do {
	    (*d4func)(C+prev);	(*n3func)(N+prev,P); v4f((float *)(P+prev));
	    (*d4func)(C);	(*n3func)(N,P);	v4f((float *)P);
	    C++; N++; P++;
	  } while(--u);
	  break;
	}

	if(ucnt == 0) {
	  if(douwrap) {
	    douwrap = 0;	/* Loop again on first vertex */
	    ucnt = 1;
	    P = meshP + du;
	    N = meshN + du;
	    C = meshC + du;
	  }
	} else {
	  endtmesh();		/* Hit tmesh limit, splice */
	  bgntmesh();
	  C--; N--; P--;	/* Redraw last vertex */
	}
      } while(ucnt);

      endtmesh();
     }
     prev = -nu;
     du += nu;
   } while(--v > 0);
  }

  if(ap->flag & (APF_EDGEDRAW|APF_NORMALDRAW)) {
    lmcolor(LMC_COLOR);
    if(_mgglc->znudge) mggl_closer();
    if(ap->flag & APF_EDGEDRAW) {			/* Draw edges */
	c3f((float *)&ap->mat->edgecolor);

	du = umin + vmin * nu;
	ucnt = umax - umin + 1;
	vcnt = vmax - vmin + 1;
	v = vcnt;
	do {
	    if(wrap & MM_UWRAP)
		bgnclosedline();
	    else
		bgnline();
	    u = ucnt;
	    P = meshP + du;
	    do {
		v4f((float *)P);
		P++;
	    } while(--u > 0);
	    if(wrap & MM_UWRAP)
		endclosedline();
	    else
		endline();
	    du += nu;
	} while(--v > 0);

	du = umin + vmin * nu;
	u = ucnt;
	do {
	    v = vcnt;
	    if(wrap & MM_VWRAP)
		bgnclosedline();
	    else
		bgnline();
	    P = meshP + du;
	    do {
		v4f((float *)P);
		P += nu;
	    } while(--v > 0);
	    if(wrap & MM_VWRAP)
		endclosedline();
	    else
		endline();
	    du++;
	} while(--u > 0);
    }

    if(ap->flag & APF_NORMALDRAW && meshN != NULL) {
	c3f((float *)&ap->mat->normalcolor);

	for (i = nu*nv, P=meshP, N=meshN; --i >= 0; P++, N++) {
	    mggl_drawnormal(P, N);
	}
    }
    if(_mgglc->znudge) mggl_farther();
  }
  return 1;
}

/*
 * Draw a single row of a mesh, using polygons.
 * This routine is needed to work around a bug in Turbo PI graphics:
 * lighted tmesh primitives are not shaded properly.
 * Polygons are OK though, so on Turbo machines we use them.
 */
mgglpolymeshrow(wrap, has, off, count, P, N, C)
    int wrap;
    int has;
    register int off;
    register HPoint3 *P;
    register Point3 *N;
    register ColorA *C;
{
    int k;
    void (*n3func)() = _mgglc->n3f;
    void (*d4func)() = _mgglc->d4f;

    if(wrap & MM_UWRAP) {
	k = count-1;
	bgnpolygon();
	if(C) (*d4func)(C+off+k);
	if(N) (*n3func)(N+off+k,P);
	v4f((float *)(P+off+k));
	if(has&HAS_SMOOTH) {
	    if(C) (*d4func)(C+k);
	    if(N) (*n3func)(N+k,P);
	}
	v4f((float *)(P+k));
	if(has&HAS_SMOOTH) {
	    if(C) (*d4func)(C);
	    if(N) (*n3func)(N,P);
	}
	v4f((float *)P);
	if(has&HAS_SMOOTH) {
	    if(C) (*d4func)(C+off);
	    if(N) (*n3func)(N+off,P);
	}
	v4f((float *)(P+off));
	endpolygon();
    }
    k = count;
    do {
	bgnpolygon();
	if(C) (*d4func)(C+off);
	if(N) (*n3func)(N+off,P);
	v4f((float *)(P+off));
	if(has&HAS_SMOOTH) {
	    if(C) (*d4func)(C+off);
	    if(N) (*n3func)(N+off,P);
	    v4f((float *)(P+off));
	    if(C) (*d4func)(C++);
	    if(N) (*n3func)(N++,P);
	    v4f((float *)P++);
	    if(C) (*d4func)(C);
	    if(N) (*n3func)(N,P);
	    v4f((float *)P);
	    if(C) (*d4func)(C+off);
	    if(N) (*n3func)(N+off,P);
	    v4f((float *)(P+off));
	} else {
	    v4f((float *)(P+off));
	    if(C) C++;
	    if(N) N++;
	    v4f((float *)(P++));
	    v4f((float *)P);
	    v4f((float *)(P+off));
	}
	endpolygon();
    } while(--k > 1);
}

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