/*
 * @(#)ThreedP.h
 *
 * Copyright 1994 - 2018  David A. Bagley, bagleyd AT verizon.net
 *
 * All rights reserved.
 *
 * Permission to use, copy, modify, and distribute this software and
 * its documentation for any purpose and without fee is hereby granted,
 * provided that the above copyright notice appear in all copies and
 * that both that copyright notice and this permission notice appear in
 * supporting documentation, and that the name of the author not be
 * used in advertising or publicity pertaining to distribution of the
 * software without specific, written prior permission.
 *
 * This program is distributed in the hope that it will be "useful",
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 */

/* Private header file for Threed */

#ifndef _ThreedP_h
#define _ThreedP_h

#include "xwin.h"
#include "timer.h"
#include "Threed.h"

#ifdef WINVER
extern void destroyThreeD(HBRUSH brush);
extern void initializeThreeD(ThreeDWidget w, HBRUSH brush);
extern void exposeThreeD(ThreeDWidget w);
extern void hideThreeD(ThreeDWidget w);
extern void selectThreeD(const ThreeDWidget w, const int x, const int y);
extern void motionThreeD(const ThreeDWidget w, const int x, const int y);
extern void releaseThreeD(const ThreeDWidget w);
extern void speedThreeD(ThreeDWidget w);
extern void slowThreeD(ThreeDWidget w);
extern void soundThreeD(ThreeDWidget w);
extern void surfaceThreeD(ThreeDWidget w);
extern void objectThreeD(ThreeDWidget w);
extern void setobjectThreeD(ThreeDWidget w, int object3D);
extern void setThreed(ThreeDWidget w, int reason);

#else

#ifdef VMS
#ifndef DATAPATH
#define DATAPATH "[.]"
#endif
#else
#ifndef DATAPATH
#if 0
#define DATAPATH "/usr/share/games/xthreed"
#endif
#define DATAPATH "/usr/local/share/games/xthreed"
#endif
#endif

/* This gets around C's inability to do inheritance */
typedef struct _ThreeDClassPart {
	int ignore;
} ThreeDClassPart;

typedef struct _ThreeDClassRec {
	CoreClassPart coreClass;
	ThreeDClassPart threedClass;
} ThreeDClassRec;

extern ThreeDClassRec threedClassRec;
#endif

#ifndef BUMPSOUND
#define BUMPSOUND "bump"
#endif
#ifndef MOVESOUND
#define MOVESOUND "move"
#endif

#define SYMBOL '='

#define VIEWRATIO 4.0
#define DELTADEPTH 2
#define DELTADISTANCE 5
#define DELTADEGREES 5
#define COLORS 8
#define WHITE_BRUSH 0
#define LTGRAY_BRUSH 1
#define GRAY_BRUSH 2
#define DKGRAY_BRUSH 3
#define BLACK_BRUSH 4
#define ANOTHER_BRUSH 7
#define LTLTGRAY_BRUSH 5
#define DKDKGRAY_BRUSH 6
#define STRING_SIZE 81
#define BG_SHADES 3
#define MAX_POLYGON_VERTICES 10 /* should not be here, but its reasonably high */

typedef double Matrix4x4[4][4]; /* the standard 4x4 homogeneous matrix */
typedef double Matrix1x4[4]; /* row vector */

typedef struct _Point3D {
	double x, y, z; /* 3D vector */
#if 0
	double w; /* normalization factor or 4D? */
#endif
} Point3D, Vector3D;

typedef struct _Vertex {
	Point3D eye;
	Point screen;
} Vertex;

typedef struct _Surface {
	int     numVertices; /* number of vertices in surface plane */
	int     mapIndex; /* maps surface to first vertex */
	int	color;
/*	int     shade;
	int     shading;*/
	int     visible;
	Boolean twoSided;
	Boolean clipped;
/*	Boolean active;*/
	int     depthIndex; /* links surfaces, old use obscure */
	double  averageDepth;
/*	double  normalLength;*/
} Surface;

typedef struct _Object3D {
	int         id;
	char       *name;
	int         numVertices;
	int         numSurfaces;
	int         numEdges; /* 2 * actual edges i.e. edges of each polygon */
	Point3D    *local; /* Vertex Array */
	Point3D    *world; /* Vertex Array */
	Surface    *surface; /* Points to Surface Map */
	int        *map; /* Points to Vertex Array */
	Vertex     *vertex; /* Vertex Array */
	Boolean     convex; /* Are all polygons convex? */
	double      radius; /* Maximum radius of object */
	int         state;
	Point3D     origin; /* Origin of object in world coordinates */
} Object3D;

typedef struct _ThreeDPart {
	IntPoint3D  distance;
	IntAngle3D  deltaAngle;
	IntAngle3D  angle;
	Boolean     mono, reverse, focus, surface;
	Boolean     versionOnly;
	Boolean     sound;
	int         delay, numSlices;
	int         object, numObjects;
	char       *name;
	char      **list;
	Object3D   *objects;
	Position    size;
	Point       currentPosition, center;
	GC          frameGC, graphicsGC, borderGC;
	GC          inverseGC[BG_SHADES];
	GC          shadeGC[COLORS];
	Pixmap      bufferObjects[2];
	TimeVal     oldTime;
#ifdef WINVER
	char        bumpSound[STRING_SIZE], moveSound[STRING_SIZE];
	char        picture[STRING_SIZE];
	char        shadeChar[COLORS];
#else
	int         menu, graphicsFormat, pixmapSize;
	char       *bumpSound, *moveSound, *picture, *font;
	Boolean     install;
	Colormap    colormap, oldColormap;
	XImage     *image;
	XFontStruct *fontInfo;
	Pixel       foreground, background;
	Pixel       frameColor, borderColor;
	Pixel       shadeColor[COLORS];
	XtCallbackList select;
#endif
} ThreeDPart;

typedef struct _ThreeDRec {
	CorePart core;
	ThreeDPart threed;
} ThreeDRec;

void createVector3D(Point3D *init, Point3D *term, Point3D *result);
double magnitudeVector3D(Vector3D *v);
double dotProduct3D(Vector3D *u, Vector3D *v);
void crossProduct3D(Vector3D *u, Vector3D *v, Vector3D *normal);
double minimumObjectRadius(Object3D *obj);
double maximumObjectRadius(Object3D *obj);
void createTrigTables(void);
void rotateObject(Object3D *obj, IntAngle3D *angle);
Boolean pointInPolygon(Point *pt, Point *poly, int n);
#endif /* _ThreedP_h */
