#pragma ident "@(#)meshify.c	1.2 98/08/25 SMI"

/*
 * meshify.c
 *
 *	@(#)meshify.c 1.8 96/11/04 
 *
 * Copyright (c) 1997 by Mike M. Chow - All Rights Reserved 
 *
 *
 *      Author: Mike M. Chow 
 *
 *      This module contains generalized triangle mesh routines.
 * 
 */

#include <stdlib.h>
#include <math.h>
#include <stdio.h>
#include <assert.h>
#include "types.h"
#include "utils.h"
#include "zdebug.h"
#include "meshify.h"

#define MAX_STRIP_LEN 31    /* Maximum length of a strip run. */

extern struct timeval timeStamp;
static Facet *lastFptr;

static int head = 0;

/* Mesh Buffer is a circular queue of 16 indices. */
static int MeshBuffer[16];



/*
 * gtmeshCreate
 *
 *      Creates and initializes a new general triangle mesh.
 */

GTMesh *
gtmeshCreate()
{
  GTMesh *gtmesh;

  gtmesh = (GTMesh *) malloc(sizeof(GTMesh));
  gtmesh->triStrips = triStripsNew();
  gtmesh->headers = NULL;
  gtmesh->varray = NULL;
  gtmesh->next = NULL;
  gettimeofday(&(gtmesh->timeStamp), NULL); 
  return gtmesh;
}  /* End of gtmeshCreate */

void
gtmeshDestroy(GTMesh *gtmesh) 
{
    if (gtmesh != NULL) {
	HeaderInfo *header, *nextHeader;

	header = gtmesh->headers;
	while(header != NULL) {
	    nextHeader = header->next;
	    headerInfoDestroy(header);
	    header = nextHeader;
	}
	triStripsDestroy(gtmesh->triStrips);
	free(gtmesh);
    }
}


/*
 * meshInfoCreate
 *
 *      Creates and init a new meshInfo structure.
 */

MeshInfo *
meshInfoCreate()
{
  MeshInfo *mi;

  mi = (MeshInfo *) malloc(sizeof(MeshInfo));
  mi->gtmeshes = NULL;
  mi->meshCnt = 0;
  gettimeofday(&(mi->timeStamp), NULL); 
  return mi;
}  /* End of meshInfoCreate*/


void 
meshInfoDestroy(MeshInfo *mi) 
{
   if (mi != NULL) {
       GTMesh *gtMesh, *nextGTMesh;
       gtMesh = mi->gtmeshes;
       while (gtMesh != NULL) {
	   nextGTMesh = gtMesh->next;
	   gtmeshDestroy(gtMesh);
	   gtMesh = nextGTMesh;
       }
       free(mi);
   }
}

/*
 * meshInfoAddMesh
 *
 *     Adds a new gtmesh to meshInfo's linked list.
 */

void
meshInfoAddMesh(MeshInfo *mi, GTMesh *mesh)
{
  if (mi->gtmeshes == NULL){
    mi->gtmeshes = mesh;
    mi->meshCnt = 1;
  }
  else {
    GTMesh *gtmesh;
    /* Add to the end of list */
    for (gtmesh = mi->gtmeshes; gtmesh->next != NULL; gtmesh = gtmesh->next);
    gtmesh->next = mesh;
    mi->meshCnt++;
  }
}  /* End of meshInfoAddMesh*/





/*
 * headerInfoCreate
 *
 *     Creates a new headerInfo object.
 */

HeaderInfo *
headerInfoCreate()
{
  HeaderInfo *hinfo;
  int i;

  hinfo = (HeaderInfo *) malloc(sizeof(HeaderInfo));

  /* Strips are actually longer than 16 due to stripifying last polygon */
  hinfo->header = (VertHeader *) malloc(sizeof(VertHeader) * (MAX_STRIP_LEN + 15));
  for (i = 0; i < (MAX_STRIP_LEN + 15); i++){
    hinfo->header[i].mbp = 0;
    hinfo->header[i].mbref = -1;
  }
  hinfo->next = NULL;
  return hinfo;
}  /* End of headerInfoCreate*/


void
headerInfoDestroy(HeaderInfo *hinfo) 
{
    free(hinfo->header);
    free(hinfo);
}



/*
 * headerInfosAdd
 *
 *     Adds a new node to a list of headers.
 */

void
headerInfosAdd(HeaderInfo **node, HeaderInfo *item)
{
  if (*node == NULL){
    zdo6 printf("headerInfosAdd starting fresh. \n");
    *node = item;
  }
  else {
    HeaderInfo *h;
    /* Add to the end of list */
    for (h = *node; h->next != NULL; h = h->next);
    h->next = item; 
  }
}  /* End of headerInfosAdd*/





/*
 * meshBufferInit
 *
 *     Initializes the mesh buffer by setting all values to -1 and head to 0.
 */

int
meshBufferInit()
{
  int i;
  
  for (i = 0; i < 16; i++)
    MeshBuffer[i] = -1;
  head = 0;
  return 1;
}




/*
 * meshBufferPrint
 *
 *      Prints the content of mesh buffer (for debugging).
 */

void
meshBufferPrint(Vertex *varray)
{
  int i;
  
  for (i = 0; i < 16; i++){
    printf("mbuf[%d] %d ", i, MeshBuffer[i]);
    if (varray != NULL) 
      printPoint(varray[MeshBuffer[i]].p);
    else printf("\n");
  }
  printf("Head ptr %d \n", head);
}  /* End of meshBufferPrint*/





/*
 * mbpush
 *
 *     Pushes a value into mesh buffer.  Returns 1 if value as already in 
 *     buffer.
 */

int
mbpush(int value)
{

  zdo6 printf("mbpush[%d] = %d \n", head, value);  

  /* Must not be there already */
  if (mbufferLookup(value) != -1)
    return 1;

  /* Increment head pointer */
  MeshBuffer[head++] = value;
  if (head == 16)
    head = 0;
  return 0;
}  /* End of mbpush*/






/*
 * mbref
 *
 *     Returns the content of mesh buffer given a index.
 * e.g  buffer:  5, 9, 13, 14, 24, 4, ...
 *                          ^
 * mbref(2) will return 9, since the head = 4, 
 */

int 
mbref(int backIndex)
{
  int cnt, index;

  index = head - 1;
  if (index < 0)
    index = 15;
  cnt = 1;
  while (1) {
    if (cnt == backIndex)
      return MeshBuffer[index];
    cnt++;
    index--;
    if (index < 0)
      index = 15;
  }
}  /* End of mbref*/





/*
 * mbufferLookup
 *
 *     Looks up a value in the mesh buffer; returns the index of the buffer 
 *     value.  
 *     Return -1 if not found.
 */

int 
mbufferLookup(int value)
{
  int cnt, index;
  static int bufHasInitialized = 0;
 
  /* Initialize buffer the first time in. */
  if (!bufHasInitialized){
    meshBufferInit();
    bufHasInitialized = 1;
  }

  index = head - 1;
  if (index < 0)
    index = 15;
  cnt = 1;
  while (1) {
    if (MeshBuffer[index] == value)
      return cnt;
    cnt++;
    index--;
    if (index == head - 1)
      break;
    if (index < 0)
      index = 15;
  }
  return -1;
}  /* End of mbufferLookup */

 /* End of meshify.c */

