#pragma ident "@(#)triStrips.c 1.2 97/11/05 SMI"

/*
 * triStrips.c
 *
 *	@(#)triStrips.c 1.8 96/07/04 14:59:16
 *
 * Copyright (c) 1996, Sun Microsystems Computer Company, Mountain View, CA
 *
 *			All Rights Reserved
 *
 *	This is a program for manipulating 3D objects.  It is currently being
 *	developed by Mike M. Chow and Scott R. Nelson.
 *
 *      This module contains triangle strips algorithms.
 */


#include <stdlib.h>
#include <stdio.h>
#include <sys/time.h>
#include "types.h"
#include "triStrips.h"
#include "zdebug.h"

extern long random();

struct timeval timeStamp = { 0, 0};
static Facet *lastFptr;
#define PERCENT_HARD_EDGES 0.02
#define MAX_TRISTRIP_LEN 28
#define PUTPT(x)     triStripExtendStrip(strip, vindex[x])

/*
 * matchStrips
 *
 *     Returns the number of vertex matches between two triangle strips.
 * This is the theoretical maximum reuse of vertices from the mesh buffer. 
 */

int 
matchStrips(TriStrip *target, TriStrip *src)
{
  int i, j;
  int score;

  score = 0;
  for (i = 0; i < src->length; i++){
    for (j = 0; j < target->length; j++)
      if (target->tri[j] == src->tri[i])
	score++;
  }
  return score;
}  /* End of matchStrips*/


void
tryFacet(MeshRegion *currRegion, Facet *testFptr, TriStrip *prevStrip,
	 int *bestScore, Facet **bestFptr, 
	 Edge **bestEdge)
{
  int j, score;
  Edge *testEdge;

  /* Try each edge of this testFacet as a starting 
   * place to look for strip. 
   */

  for (j = 0; j < testFptr->numVerts; j++){
    TriStrip *testStrip;
    Facet *lastFptr;
    
    testEdge = testFptr->edges[j];
    zdo6 printf("Looking ahead from facet %x edge %x \n",
		testFptr, testEdge);
    
    /* Find the strip. */
	zdebugOff(
		  testStrip = getTriStrip(testFptr->owner, currRegion, 
					  testFptr, testEdge, 
					  &lastFptr, 7, 0, NULL);
		  )
	  if (testStrip == NULL)
	    return;
	  /* Count up the matching vertices. */
	  score = matchStrips(testStrip, prevStrip);
	  zdo6 printf("Gotten %d matches.\n", score);
	  
	  /* Update score and best facet and edge to start. */
	  if (score > *bestScore) {
	    zdo6 printf("Best so far. \n");
	    *bestFptr = testFptr;
	    *bestEdge = testEdge;
	    *bestScore = score;
	}
	  free(testStrip->tri);
	  free(testStrip);
      }
}

/*
 * meshPickNextEdge
 *
 *      Get the best facet and edge to start the next strip (maximal mesh buffer
 * usage).  For each adjacent facet to the current facet, run the stripifier on
 * it and see how many mesh buffer hits we get.  Return the best facet and edge. 
 */

void 
meshPickNextEdge (Part *part, MeshRegion *currRegion, Facet *startFptr, 
		  Facet **nextFptr, Edge **eptr, 
		  TriStrip *prevStrip)
{
  Facet *currFptr;
  int i, j;
  Facet *testFptr, *look1Fptr;
  Edge  *testEdge, *edge;
  Facet *bestFptr;
  Edge  *bestEdge;
  int   score, bestScore;

  bestScore = -1;
  bestFptr = NULL;
  bestEdge = NULL;
  currFptr = startFptr;

#if 0
  if (1){
  *nextFptr = bestFptr;
  *eptr = bestEdge;
  return;
  }
#endif

  zdo6 printf("\nMeshPickEdge Picking next starting mesh edge. \n");

  /* For each edge of this facet, get adjacent facet and test it
   * for the starting facet that maximize mesh buffer usage. */

  for (i = 0; i < currFptr->numVerts; i++){
    edge = currFptr->edges[i];

    /* Get adjacent facet */
    if (edge->f1 == currFptr)
      look1Fptr = edge->f2;
    else
      look1Fptr = edge->f1;

    zdo6 printf("L1. Checking out nbr fptr %x .\n", 
	       look1Fptr);
    
    /* If haven't seen this facet before, */
    if (look1Fptr != NULL){

      /* Stay in the same region */
      if ((currRegion != NULL) && (currRegion != look1Fptr->region))
	continue;

      if (look1Fptr->timeStamp != timeStamp.tv_sec)
	tryFacet(currRegion, look1Fptr, prevStrip, &bestScore, &bestFptr,
		 &bestEdge);

      if (currFptr->numVerts != 4)
	for (j = 0; j < look1Fptr->numVerts; j++){
	  edge = look1Fptr->edges[j];

	/* Get adjacent facet */
	if (edge->f1 == look1Fptr)
	  testFptr = edge->f2;
	else
	  testFptr = edge->f1;

	zdo6 printf("L2. Checking out nbr fptr %x .\n", 
		    testFptr);

	if (testFptr != NULL) {
	  /* Stay in the same region */
	  if ((currRegion != NULL) && (currRegion != testFptr->region))
	    continue;
	  
	  /* If haven't seen this facet before, */
	  if ((testFptr->timeStamp != timeStamp.tv_sec))
	    tryFacet(currRegion, testFptr, prevStrip, &bestScore, &bestFptr,
		     &bestEdge);
	}
      }

    }
  }
  
  /* Returns the best facet and edge to start next. */
  *nextFptr = bestFptr;
  *eptr = bestEdge;
}  /* End of meshPickNextEdge*/
	



/*
 * randomPickEdge
 *
 *     Picks a facet/edge randomly from the remaining facet pool.
 */

int
randomPickEdge(Part *part, MeshRegion *currRegion, Facet **nextFptr, Edge **eptr)
{
  Facet *fptr;
  LinkedList *lptr;


  zdo6 printf("Part %s, Ran out of hard edges. Picking at random...\n",
	     part->name);
  
  if (currRegion != NULL){
    zdo6 printf("ran pick from region %x\n", currRegion);
    zdebugOff(
    for (lptr = currRegion->flist; lptr != NULL; lptr = lptr->next)
      {
	fptr = (Facet *) lptr->current;

	if (fptr != NULL){
	  zdo fprintf(stderr, "tstamp:%ld pickNextEdge looking at facet %d time:%ld\n",
		      timeStamp.tv_sec, fptr, fptr->timeStamp);
      

	  /* Stay in the same region */
	  if ((currRegion != NULL) && (currRegion != fptr->region)){
	    printf("skipping facet (%x), not in region(%x) \n", fptr->region,
		    currRegion);
	    return -1;
	  }

      
	  if ((fptr->timeStamp != timeStamp.tv_sec) && 
	      (1 || ( random() % 3 != 9))){
	    zdo printf("Found fptr %x region %x\n", fptr, fptr->region);
	    *nextFptr = fptr;
	    lastFptr = fptr;
	    *eptr = fptr->edges[0];
	    return 1;
	  }
	  zdo6 fprintf(stderr, "seen before\n");
	}
      }
    )
      }
  else {

    if ((*nextFptr != NULL))
      for (fptr = *nextFptr; fptr != NULL; fptr = fptr->next)
	{
	  /* Stay in the same region */
	  if ((currRegion != NULL) && (currRegion != fptr->region)){
	    zdo printf("skipping facet (%x), not in region(%x) \n", fptr->region,
		    currRegion);
	    return -1;
	  }

	  if ((fptr->timeStamp != timeStamp.tv_sec)) 
	    {
	      zdo6 printf("found fptr\n");
		*nextFptr = fptr;
		lastFptr = fptr;
		*eptr = fptr->edges[0];
		return 1;
	      }
	}

    zdo6 printf("Find another starting edge \n");
    for (fptr = part->facets; fptr != NULL; fptr = fptr->next)
      {
      
      zdo6 fprintf(stderr, "tstamp:%ld pickNextEdge looking at facet %d time:%ld\n",
		   timeStamp.tv_sec, fptr, fptr->timeStamp);

      if ((fptr->timeStamp != timeStamp.tv_sec) && 
	  (( random() % 3 != 9) || 1)){
	zdo6 printf("search all facets: found fptr %x edge %x\n",
		   fptr, fptr->edges[0]);
	*nextFptr = fptr;
	lastFptr = fptr;
	*eptr = fptr->edges[0];
	return 1;
      }
       zdo6 fprintf(stderr, "seen before\n");
    }
  }

  zdo6 printf("No more edges to pick\n");
  *nextFptr = NULL;
  *eptr = NULL;
  return -1;
}  /* End of randomPickEdge*/




/*
 * pickNextEdge
 *
 *      Get the next edge.
 */

void pickNextEdge (Part *part, MeshRegion *currRegion, 
		   Facet **nextFptr, Edge **eptr, 
		   int shadowMeshLookaheads)
{
  Facet *fptr;
  FacetList *flptr;

  if (lastFptr == NULL)
      lastFptr = part->facets;

  /* Just randomly pick an edge */
  if (randomPickEdge(part, currRegion,
		     nextFptr, eptr) != -1)
    return;

  /* No more unseen edges */
  *nextFptr = NULL;
  *eptr = NULL;
}  /* End of pickNextEdge*/
	  
	  
  
/*
 * findTriStrips
 *
 *      Create a part's triangle strips for all its facets.       
 *
 *
 *  Algorithm in a nutshell:
 * 
 *  Pick a starting edge, e, on a facet, f
 *     p = e->p1 //Get edge point1
 *     while true 
 *      do 
 *        walkFacet(f, p, &lastp) //Get strip vertices for facet, f
 *        f = getAdjacentFacet(f, lastp)  //Get adjacent facet and keep going
 *        if f is NULL then exit loop
 *        p = lastp
 *      end 
 *   
 */

void 
findTriStrips(Part *part)
{
    Facet *fptr; /* Facet ptr */
    Edge *eptr;  /* Edge ptr */
    TriStrip *triStrip;

    timeStamp.tv_sec += 1;
    zdo6 for (fptr = part->facets; fptr->next != NULL; fptr = fptr->next);

#if 0
    fptr = part->facets;
    eptr = fptr->edges[0];
#endif
    lastFptr = NULL;
    fptr = NULL;
    eptr = NULL;

    pickNextEdge(part, NULL, &fptr, &eptr, -1);
    while (fptr != NULL){
      int i;
      Facet *lastFptr;

      zdo6 printf("entering findTriStrips while\n");

	/* No more ?*/
      if (eptr == NULL){
	zdo6 printf("no more edge\n");
	break;
      }
	
#if 0
	/* For debugging */
	fprintf(stderr, "facet ");
	for(i = 0; i < fptr->numVerts; i++){
	  fprintf(stderr, "%d ", fptr->vindex[i]);
	}
	fprintf(stderr, "\n");
#endif
	/* Get the strips from this edge */
	triStrip = getTriStrip(part, NULL, fptr, eptr, &lastFptr, 
			       MAX_TRISTRIP_LEN, 1, NULL);
	part->triStrips->triCnt += triStrip->triCnt - 2;
	triStripsAddStrip(part->triStrips, triStrip);
	
	zdo6 triStripPrint(triStrip, fptr->owner->obj->varray);
	zdo6 meshPickNextEdge(part, NULL, fptr, &fptr, &eptr, triStrip);
	zzdebug = 0;
	if (1 || (fptr == NULL)){ 	  /* Pick the next edge (hard edge) */
	  if (part->hardEdgeCount < PERCENT_HARD_EDGES * (float) part->triCnt){
	    int foundNextFptr = 0;
	    for(i = 0; i < lastFptr->numVerts; i++){
		  Edge *e1;
		  
		  e1 = lastFptr->edges[i];
		  if ((lastFptr == e1->f1) && (e1->f2 != NULL)){
		    if (e1->f2->timeStamp != timeStamp.tv_sec){
		      fptr = e1->f2;
		      eptr = e1;
		      foundNextFptr = 1;
		      break;
		    }
		  }
		  else if (e1->f1 != NULL) {
		    if (e1->f1->timeStamp != timeStamp.tv_sec){
		      fptr = e1->f1;
		      eptr = e1;
		      foundNextFptr = 1;
		      break;
		    }
		  }
	    }
	    if (foundNextFptr) 
	      zdo6 printf("Found adj edge to triStrip!\n");
	    if (!foundNextFptr)
	      randomPickEdge(part, NULL, &fptr, &eptr);
	  }
	  else 
	    pickNextEdge(part, NULL, &fptr, &eptr, -1);
	}

    }
    fflush(stdout);
	
}  /* End of makeTriStrips*/
	


void
partFindTriStrips(Part *part)
{ 
   if (part->facets != NULL){
      TriStrip *s;
      int numStrips = 0, totalLen = 0;
      float aveStripLen = 0;

      findFacetAdjacency(part);
      findTriStrips(part);
      numStrips = 0;
      totalLen = 0;
      for (s = part->triStrips->strips; s != NULL; s = s->next){
	numStrips++;
	totalLen += s->length;
      }
      part->aveStripLen = (int) ((float) totalLen / (float) numStrips);
      zdo6 printf("Part ave strip len:%d .\n", aveStripLen);
    }
}


/*
 * getTriStrip
 *  
 *      Find a triangle strip extending from the given facet and edge.
 * 
 *      The algorithm walks across the current facet and generates the 
 *      triangle strip points.  From the last edge of the facet, we start
 *      the next facet and generate the strip points for that and so on.
 * 
 * 
 *         The algorithm assumes that the hardware swaps the orders of the
 * 	edge vertices for each triangle.  So, to maintain CW order of
 * 	output vertices, we must make sure that the first two vertices
 * 	of each facet is in CCW order, not CW.  For example, all of the
 * 	cases below, the first vertices (1 and 0) are output in CCW order.
 * 
 * 	The algorithm stops whenever it finishes an facet with an edge vertices
 * 	in CCW order (that means the adjacent edge will start off CW order,
 * 	which is wrong).
 * 
 *        even, odd (quad, tri)
 *      0 -----2\
 * 	 |     | \ 
 * 	 |_____|__\
 * 	1      3   4
 * 
 * 	even, even  (quad, quad)
 *      0 -----2-----4
 * 	 |     |     |
 * 	 |_____|_____|
 * 	 1     3     5
 * 
 * 	odd, odd (tri, tri)
 * 
 * 	1 __3
 * 	 |\ |
 * 	 |_\|
 * 	0   2
 * 
 * 	odd, odd (tri, quad)
 * 
 * 	1 ______3
 * 	 |\    |
 * 	 |_\___|
 * 	0   2  4
 * 
 * 
 * 
 */

TriStrip *
getTriStrip (Part *part, MeshRegion *currRegion, 
	     Facet *startFptr, Edge *eptr, 
	     Facet **lastFptr,
	     int maxLen, int markSeenFacet, FacetList **stripFacets)
{
    int p, q;  /* p and q are indices of verticies on an edge. 
		  p is put before q  */
    Vertex *varray;
    VertIndex *vindex;
    int replP;
    TriStrip *strip;
    Facet *fptr;

    zzdebug = 0;
    fptr = startFptr;
    /* Stay on the same region */
    if ((currRegion != NULL) && (fptr->region != currRegion)){
      printf("Error! getTriStrip starts on facet of wrong region!\n");
      return NULL;
    }

    varray = part->obj->varray;
    vindex = fptr->vindex;
    replP = 1;
    if (eptr->f1 == fptr)
	{
	    p = eptr->f1p1;
	    q = eptr->f1p2;
	}
    else
	{
	    p = eptr->f2p1;
	    q = eptr->f2p2;
	}

    zdo6 printf("getTriStrip testing: %d\n", markSeenFacet);
    zdo fprintf(stderr, "\n starting on facet %d\n", fptr);
    zdo fprintf(stderr, "starting putting with %d %d \n", vindex[p], vindex[q]);

    strip = triStripCreate();

    if (strip == NULL)
      return NULL;

    /* Put the starting points in CCW order*/
    triStripExtendStrip(strip, vindex[p]);
    triStripExtendStrip(strip, vindex[q]);
    
    
    while (1) {

      if (markSeenFacet) 
	fptr->timeStamp = timeStamp.tv_sec;
      
      zdo facetPrint(fptr);
      walkFacet(part, fptr, &p, &q, &replP, strip);

      /* Add current facet to facet list for this strip. */
      if (stripFacets != NULL)
	flistAddFacet(stripFacets, fptr);

      zdo fprintf(stderr, "walkFacet returns edge %d %d \n", 
		  fptr->vindex[p] , fptr->vindex[q]);
      
	/* Get next facet to walk and generate triangle points */
      *lastFptr = fptr;

#if 0
      if (fptr->numVerts > 5){
	zdo fprintf(stderr, "Skipping big poly facet %x sides %d\n", 
		    fptr, fptr->numVerts);
	break;
      }
#endif

      fptr = getAdjacentFacet(fptr, &p, &q, &replP);


      /* If no more or touched before, exit */
      if (fptr == NULL) {
	zdo fprintf(stderr, "getAdjacentFacet returns NULL facet, break.\n");
	break;
      }

      /* Stay on the same region */
      if ((currRegion != NULL) && (fptr->region != currRegion))
	break;


      if (fptr->timeStamp == timeStamp.tv_sec) {
	zdo fprintf(stderr, "getAdjacentFacet returns SEEN facet, break.\n");
	break;
      }

      if (strip->length > maxLen)
	break;

      zdo fprintf(stderr, "getAdjacentFacet returns facet %x edge %d %d replP %d\n", fptr, 
		  fptr->vindex[p], fptr->vindex[q],
		  replP);

      /* If q, p is clockwise and replacement is on q, then punt!*/ 
       	  
      if (!replP){
	zdo printf("got p %d q %d replP %d, PUTPT(vindex[p])\n",
		   p, q, replP);
	
      }

    }

    return strip;
}

  /* End of getTriStrip */

/*
 * getAdjacentFacet
 *
 *      Get the adjacent facet for the current facet and edge.
 *      On entry, p and q are in CW and same upon exiting.
 */

Facet *
getAdjacentFacet(Facet *fptr, int *p, int *q, int *replP)
{
    int n;           /* Total facet pts */
    Edge *e;         /* Edge ptr */
    
    n = fptr->numVerts;
    e = facetGetEdge(fptr, *p, *q);
    if (e == NULL){
      zdo fprintf(stderr, "getAdjacentFacet found a NULL edge p-->q. \n");
      return NULL;
    }

    zdo fprintf(stderr, "getAdjacentFacet looking at edge %x f1 %x (%d %d) f2 %x (%d %d)\n",
	       e, e->f1, e->f1p1, e->f1p2, e->f2, e->f2p1, e->f2p2);
    zdo printf("fptr %x vindex[p] %d vindex[q] %d edge vid1 %d vid2 %d\n",
	       fptr, fptr->vindex[*p], fptr->vindex[*q], e->vid1, e->vid2);
    if ((e->f1 == NULL) ||
	(e->f2 == NULL)) {
      zdo fprintf(stderr, "Other facet is NULL \n");
      return NULL;
    }

    if (!((e->f1->vindex[e->f1p1] == e->f2->vindex[e->f2p2]) &&
	  (e->f1->vindex[e->f1p2] == e->f2->vindex[e->f2p1]))){
      zdo printf("Bad edge! Facet indices don't match!\n");
      return NULL;
    }
      
    
    /* Now return the next facet and that facet's indices */
    if ((e->f1 == fptr) && (e->f2 != NULL)
	&& (e->f2->timeStamp != timeStamp.tv_sec))
	{
	  /* Facet2 is it */
	  if 	 
	    (fptr->vindex[*p] == 
	     e->f2->vindex[e->f2p2]){
	    *replP = !*replP;
	    zdo printf("flip replP, replP = %d \n", *replP);
	  }
	  *p = e->f2p1;
	  *q = e->f2p2;
	  return e->f2;
	}
    else 
      if ((e->f2 == fptr) && (e->f1 != NULL)
	     && (e->f1->timeStamp != timeStamp.tv_sec))
	{
	  if (fptr->vindex[*p] == 
	      e->f1->vindex[e->f1p2]){
	    *replP = !*replP;
	    zdo printf("flip replP, replP = %d \n", *replP);
	  }
	  
	  *p = e->f1p1;
	  *q = e->f1p2;
	  return e->f1;
	}
    else {
      zdo6 fprintf(stderr, "Other facet is seen \n");
      return NULL;
    }
}  /* End of getAdjacentFacet*/




/* 
 * walkFacet
 * 
 *      Given a facet and a starting point, generate the partial triangle strip.
 * 
 *      The algorithm alternately extends a strip using the points from 
 *      both ends of the starting point.  It stops when there is no more
 *      points on the facet to extend and returns the last extended point.
 * 
 */

static void
walkFacet(Part *part, Facet *fptr, int *a, int *b, int *replP, TriStrip *strip)
{
    /* a and b are starting indices on this facet in CW order 
     *  assume they have been done */
    
    int i;             /* Counter */
    int p, q;          /* p and q are indices of points on both ends
		        * of starting point*/
    int n;             /* Number of points */
    Vertex *varray;    /* Pointer to array of verticies */
    VertIndex *vindex; /* Pointer to array of indexes of varray */
    int starti;
    int prevpt, 
	currpt;        /* prevpt and currpt keep track of last two points 
			* visited */ 

    p = *a;
    q = *b;
    
    /* Get arrays */
    varray = part->obj->varray;
    vindex = fptr->vindex;
    n = fptr->numVerts;

    i = 2;
    while (i++  < n) {
      if ((*replP)) {
	p = p - 1;
	if (p < 0)
	  p = n + p;
	*replP = 0;
	PUTPT(p);
	zdo printf("replP %d\n", *replP);
      }
      else {
	q = (q + 1) % n;
	*replP = 1;
	PUTPT(q);
	zdo printf("replP %d\n", *replP);
      }
    }
    *a = p;
    *b = q;
}  /* End of walkFacet*/
 

static void
walkFacetBack(Part *part, Facet *fptr, int *a, int *b, int *replP, TriStrip *strip)
{
    /* a and b are starting indices on this facet in CW order 
     *  assume they have been done */
    
    int i;             /* Counter */
    int p, q;          /* p and q are indices of points on both ends
		        * of starting point*/
    int n;             /* Number of points */
    Vertex *varray;    /* Pointer to array of verticies */
    VertIndex *vindex; /* Pointer to array of indexes of varray */
    int starti;
    int prevpt, 
	currpt;        /* prevpt and currpt keep track of last two points 
			* visited */ 

    fptr->timeStamp = timeStamp.tv_sec;
    p = *a;
    q = *b;
    
    /* Get arrays */
    varray = part->obj->varray;
    vindex = fptr->vindex;
    n = fptr->numVerts;

    i = 2;
    while (i++  < n) {
      if (*replP) {
	q = (q + 1) % n;
	*replP = 0;
	PUTPT(q);
      }
      else {
	p = p - 1;
	if (p < 0)
	  p = n + p;
	*replP = 1;
	PUTPT(p);
      }
    }
    *a = p;
    *b = q;
}  /* End of walkFacet*/
 
static void
walkFacet2(Part *part, Facet *fptr, int *a, int *b, TriStrip *strip)
{
    /* a and b are starting indices on this facet in CW order 
     *  assume they have been done */
    
    int i;             /* Counter */
    int p, q;          /* p and q are indices of points on both ends
		        * of starting point*/
    int n;             /* Number of points */
    Vertex *varray;    /* Pointer to array of verticies */
    VertIndex *vindex; /* Pointer to array of indexes of varray */
    int starti;
    int prevpt, 
	currpt;        /* prevpt and currpt keep track of last two points 
			* visited */ 

    fptr->timeStamp = timeStamp.tv_sec;
    p = *a;
    q = *b;
    starti = q;
    /* Get arrays */
    varray = part->obj->varray;
    vindex = fptr->vindex;
    n = fptr->numVerts;

/* Assuming first two points are done, 
 * Put third point of triangle strip.
 * The third point is the one opposite from the last put point 
 * on this facet (Clockwise).
 * For a triangle, this is enough.
 */


    prevpt = p;
    currpt = (starti + 1) % n;
    zdo6 fprintf(stderr, "starti:%d n:%d currpt:%d\n", starti, n, currpt);
    zdo6 fprintf(stderr, "have put: %d %d %d\n", vindex[p], vindex[q], vindex[currpt]);
    PUTPT(currpt);
    
    i = 2;
    while (i <= (int) n / 2) /* While there is  more points */
    {
	/* Put p and q opposite each other */
	p = (starti + i) % n;
	q = (starti - i);
	if (q < 0)
	    q = n + q;

	prevpt = currpt;
	currpt = q;
	/* Add one more point to triangle strip */
	PUTPT(currpt);

	/* If p isn't q then also put q's point */
	if (p != q)
	    {
		prevpt = currpt;
		currpt = p;
		PUTPT(currpt);
	    }
	i++;
    }

    *a = prevpt;
    *b = currpt;   
}  /* End of walkFacet*/
    

 /* End of TriStrips.c*/

