/*======================================================================*/
/* 3DLib								*/
/*									*/
/* Ray header file							*/
/*									*/
/* AUTHOR:	Gabor Nagy						*/
/* DATE:	1996-Oct-02 23:30:36					*/
/*									*/
/* 3DLib(TM) Copyright (C) 1995 by Gabor Nagy. All rights reserved.	*/
/*======================================================================*/
#ifndef _E3DRay_h
#define _E3DRay_h


#ifndef _E3DPolygon_h
#include <E3D/Polygon.h>
#endif


#if defined (__cplusplus) && (!(defined (__CPLUSLIBS)))
extern "C" {
#endif


#ifndef _E3dRay
#define _E3dRay
typedef struct E3dRay_S	E3dRay;			// Forward-define E3dRay
#endif


struct E3dRay_S
{
 E3dCoordinate	X, Y, Z,
		DirX, DirY, DirZ;
 E3dCoordinate	LastT;				// t value at the last intersection


// Voxel-walking 3D-DDA
//
 int		GridX, GridY, GridZ,
		GridStepX, GridStepY, GridStepZ,
		GridOutX, GridOutY, GridOutZ;
 E3dCoordinate	GridNextX, GridNextY, GridNextZ,
		GridDeltaX, GridDeltaY, GridDeltaZ;

 E3dCoordinate	HitX, HitY, HitZ;
 E3dCoordinate	U, V;				// Barycentric coordinates at hit point



// Transparency stuff
//
 E3dMaterial**	MaterialStack;			// Materials 
 unsigned int	MaterialIndex;			// Index to current Material in MaterialStack.
						// When ray hits a front-face (entering a Material), the Material of that face is stored in MaterialStack and MaterialIndex is incremented.
						// When ray hits a back-face (exiting a Material), the Material MaterialIndex is decremented.

// For ray-stacking
//
 float		IntensityR, IntensityG, IntensityB;
 void*		ExcludeFace;
 int		IterationsLeft;


 EBool		FrontFaceHit;			// The last intersection was with a front-facing primitive
};


/*--------------------------------------------------------------*/
/* Function prototypes						*/
/*--------------------------------------------------------------*/
extern int	E3d_RayIntersectWithTriangleE(E3dRay* LRay, E3dCoordinate* LV0, E3dCoordinate* LEdge1, E3dCoordinate* LEdge2, E3dCoordinate* LURet, E3dCoordinate* LVRet);
extern int	E3d_RayIntersectWithTriangleENoUV(E3dRay* LRay, E3dCoordinate* LVertex0, E3dCoordinate* LEdge1, E3dCoordinate* LEdge2);

extern int	E3d_RayIntersectWithTriangleFrontBackE(E3dRay* LRay, E3dCoordinate* LVertex0, E3dCoordinate* LEdge1, E3dCoordinate* LEdge2, E3dCoordinate* LURet, E3dCoordinate* LVRet);
extern int	E3d_RayIntersectWithTriangleBackCullE(E3dRay* LRay, E3dCoordinate* LVertex0, E3dCoordinate* LEdge1, E3dCoordinate* LEdge2, E3dCoordinate* LURet, E3dCoordinate* LVRet);
extern int	E3d_RayIntersectWithTriangleBackCullENoUV(E3dRay* LRay, E3dCoordinate* LVertex0, E3dCoordinate* LEdge1, E3dCoordinate* LEdge2);

extern E3dCoordinate	E3d_RayClosestPointOnSegment(E3dRay* LRay, E3dCoordinate LX0, E3dCoordinate LY0, E3dCoordinate LZ0, E3dCoordinate LX1, E3dCoordinate LY1, E3dCoordinate LZ1, E3d3DPosition* LResult, E3dCoordinate* LUPtr);



// Old versions with separate LRayOrig and LRayDir
//
extern int	E3d_RayIntersectWithTriangleEO(E3d3DPosition* LRayOrig, E3d3DPosition* LRayDir, E3dCoordinate* LVertex0, E3dCoordinate* LEdge1, E3dCoordinate* LEdge2, E3dCoordinate* LTRet);
extern int	E3d_RayIntersectWithTriangleBackCullEO(E3d3DPosition* LRayOrig, E3d3DPosition* LRayDir, E3dCoordinate* LVertex0, E3dCoordinate* LEdge1, E3dCoordinate* LEdge2, E3dCoordinate* LTRet);

#if defined (__cplusplus) && (!(defined (__CPLUSLIBS)))
}	// Close scope of 'extern "C"' declaration which encloses file.
#endif

#endif	// _E3DRay_h
