/* geom.h,v 1.1.1.1 1995/02/27 07:38:33 explorer Exp */

/*
 * Copyright (C) 1989, 1991, Craig E. Kolb
 * All rights reserved.
 *
 * This software may be freely copied, modified, and redistributed
 * provided that this copyright notice is preserved on all copies.
 *
 * You may not distribute this software, in whole or in part, as part of
 * any commercial product without the express consent of the authors.
 *
 * There is no warranty or other guarantee of fitness of this software
 * for any purpose.  It is provided solely "as is".
 *
 */

#ifndef OBJECT_H
#define OBJECT_H

#include "libcommon/common.h"
#include "libcommon/transform.h"
#include "bounds.h"

/*
 * Constants for enter flag in HitNode.
 */
#define EXITING		1
#define ENTERING	2

#define MAXMODELDEPTH	32		/* Maximum height of DAG. */

typedef char * GeomRef;

typedef GeomRef GeomCreateFunc();

/*
 * If the object has a normal method, it's a primitive
 * otherwise it's an aggregate (or an instance)
 */
#define IsAggregate(o)		((o)->methods->normal == NULL)

/*
 * several forward references, because everything in here points to damn near
 * everything else...
 */
typedef struct Geom Geom;
/*
 * Array of hit information.  Stores a path through an object DAG,
 * as well as the ray in 'model' (object) space and the distance from
 * the ray origin to the point of intersection.
 */
typedef struct HitNode {
  Geom *obj;			/* Geom hit */
  Ray	ray;			/* Ray */
  Float	mindist;		/* Amount of ray to ignore */
  Float	dist;			/* Distance from ray origin to hit */
  short	enter;			/* Enter (TRUE) or Leave (FALSE) obj */
  short	dotrans;		/* transformations non-identity? */
  Trans	trans;			/* parent-->obj and inverse trans */
} HitNode;

/*
 * Structure holding a list of HitNodes.  A maximum of MAXMODELDEPTH
 * nodes can be referenced.
 */
typedef struct HitList {
  int nodes;
  HitNode data[MAXMODELDEPTH];
} HitList;

/*
 * Geom methods.
 * (p) means applies only to primitive objects
 * (a) means applies only to aggregate objects
 */
typedef struct Methods {
  /* Geom name */
#define NAME_PROTO _PROTO((void))
  char		   *(*name) NAME_PROTO;

#if 0
  /* Create and return ref [is this ever USED?!?] */
  GeomRef	   (*create) _PROTO(());
#endif
  
  /* Ray/obj intersection */
#define INTERSECT_PROTO _PROTO((GeomRef, Ray *, HitList *, Float, Float *))
  int		   (*intersect) INTERSECT_PROTO;
  
  /* Geom normal (p) */
#define NORMAL_PROTO _PROTO((GeomRef, Vector *, Vector *, Vector *))
  int		   (*normal) NORMAL_PROTO;
  
  /* Ray enter or exit? (p) */
#define ENTER_PROTO _PROTO((GeomRef, Ray *, Float, Float))
  int		   (*enter) ENTER_PROTO;
  
  /* Convert from list (a) */
#define CONVERT_PROTO _PROTO((GeomRef, Geom *))
  int		   (*convert) CONVERT_PROTO;
  
  /* 2D mapping (p) */
#define UV_PROTO _PROTO((GeomRef, Vector *, Vector *, Vec2d *, Vector *, Vector *))
  void		   (*uv) UV_PROTO;
  
  /* Statistics */
#define STATS_PROTO _PROTO((unsigned long *, unsigned long *))
  void		   (*stats) STATS_PROTO;
  
  /* Bounding volume */
#define BOUNDS_PROTO _PROTO((GeomRef, Float[2][3]))
  void             (*bounds) BOUNDS_PROTO;
  
  /* User-defined method [I have no idea what to put here for a prototype] */
  void	           (*user) _PROTO(());

  /* object methods func. */
#define METHODS_PROTO _PROTO((void))
  struct Methods   *(*methods) METHODS_PROTO;

  /* check bbox before int.? */
  char		checkbounds;

  /* properly closed? */
  char		closed;
} Methods;

typedef void (*UserMethodType) _PROTO(());

/*
 * Geom definition
 */
struct Geom {
  char *name;			/* Geom name, if any. */
  GeomRef obj;			/* Pointer to object info. */
  Methods *methods;
  unsigned long prims;		/* sum of # primitive objects */
  Float bounds[2][3];		/* Bounding box */
  Float timenow;		/* Geom's idea of what time it is */
  short int animtrans;		/* transformation is animated */
  short int frame;		/* frame for which obj is inited */
  struct Surface *surf;		/* surface, if any */
  struct Trans *trans;		/* Transformation information */
  struct Trans *transtail;	/* Double linked list end */
  struct Texture *texture;	/* Texture mapping info. */
#ifdef SHAREDMEM
  unsigned long *counter;	/* Geoms are shared, counters aren't */
#else
  unsigned long counter;	/* "mailbox" for grid intersection */
#endif
  struct Geom *next;		/* Next object. */
};

/*
 * Linked list of pointers to objects.
 */
typedef struct GeomList {
  Geom *obj;
  struct GeomList *next;
} GeomList;

extern Geom	*GeomCreate _PROTO((GeomRef, Methods *));
extern Geom     *GeomCopy _PROTO((Geom *));
extern void     AggregatePrintInfo _PROTO((Geom *, FILE *));
extern int	AggregateConvert _PROTO((Geom *, Geom *));
extern char	*GeomName _PROTO((Geom *));
extern void     GeomStats _PROTO((Geom *, unsigned long *, unsigned long *));
extern GeomList	*GeomStackPush _PROTO((Geom *, GeomList *));
extern GeomList *GeomStackPop _PROTO((GeomList *));
extern Methods	*MethodsCreate _PROTO((void));
extern void 	PrimUV _PROTO((Geom *, Vector *, Vector *, Vec2d *,
			       Vector *, Vector *));
extern int      PrimNormal _PROTO((Geom *, Vector *, Vector *, Vector *));
extern int      PrimEnter _PROTO((Geom *, Ray *, Float, Float));
extern Geom     *GeomComputeAggregateBounds _PROTO((Geom **, Geom *,
						    Float[2][3]));
extern int      FirstAnimatedGeom _PROTO((HitList *));
extern void     GeomComputeBounds _PROTO((Geom *));

/*
 * in libshade/objdef.c I see...
 */
extern Geom     *GeomCopyNamed _PROTO(());
extern int      TraceRay _PROTO(());	/* application-provided */

/*
 * in intersect.c
 */
extern void     IntersectStats _PROTO((unsigned long *));
extern int      intersect _PROTO((Geom *, Ray *, HitList *, Float, Float *));

#endif /* OBJECT_H */
