//================================================================
// E3D
//
// Light sources
//
// AUTHOR:  Gabor Nagy
// DATE:    2024-Aug-18 01:31:54
//
// Copyright (C) 1996-2026 by Gabor Nagy. All rights reserved.
//================================================================
#ifndef _E3D_Light_h
#define _E3D_Light_h


#ifndef _E3D_Object_h
#include <E3D/Object.h>
#endif


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

enum
{
	E3dLightPOINT = 1,
	E3dLightSPOT,
	E3dLightINFINITE,
	E3dLightSUN
};

#ifndef _E3dLight
#define _E3dLight
typedef struct E3dLight_S  E3dLight;
#endif


#define E3dShadowMapCore\
	uint8_t*      DepthBuffer;\
	unsigned int  DepthBufferSize;    /* Size in bytes  */\
	EInt32_2      Size

typedef struct
{
	E3dShadowMapCore;
} E3dShadowMap;


// Global ShadowMap settings
//
typedef struct
{
	int    ShadowMapSizeX, DepthBias;
	EBool  DrawFrustum;
} E3dHWShadowMapSettings;


// Lights can be instantiated from Models
//
struct E3dLight_S
{
	E3dObjectCore;

	int            Type;                // Light source type
	EcColor        Color;               // Color of the light source
	float          DiffuseFactor, SpecularFactor;

	float          SpotAngle,
	               SpotPenumbraAngle,   // Fall off to 0 this much beyond SpotAngle
	               SpotExponent,
	               AttenuationConstant,
	               AttenuationLinear,
	               AttenuationQuadratic,
	               ShadowBrightness;    // If a point is in shadow from this light, its diffuse color will be multiplied by this value
};


#define E3dLightSampleCore\
	float      Radiance[EcMAX_NUM_OF_SPECTRAL_SAMPLES];\
	E3dCoord3  Position, Normal

// Area light sample
//
typedef struct
{
	E3dLightSampleCore;
} E3dLightSample;


// A structure for holding area-light information for rendering
//
typedef struct
{
	EObjectCore(EObject);

	EObject*       Shadeable;         // The E3dRPolyGroup, etc. that is represented by this AreaLight

	float          Radiance[EcMAX_NUM_OF_SPECTRAL_SAMPLES];
	
//float          CutoffAngle;
//float          CutoffAngleCos;
	E3dCoordinate  Area;
} E3dAreaLight;



typedef struct
{
	E3dCoordinate*	Elements;

// Width of the sub-matrix
	int   Width;

// Total size of the sub-matrix in multiples of doubles
	int   Size;

// Value to shift incoming matrix indices by
	int   m_Shift;
} E3dSHSubMatrix;


typedef struct
{
// Number of bands stored
	int              NBands;

// Sub-matrix for each band
	E3dSHSubMatrix*  Matrices;

// Element array for each sub-matrix
	E3dCoordinate*   Elements;
} E3dSHRotateMatrix;



/*----------------------------------------------------------------------*/

extern E3dObjectClass  E3dLight_class[];
extern EObjectClass    E3dAreaLight_class[];


EList(extern, E3dCoord2**, E3d_SamplingTiles);


//----------------------------------------------------------------
// Function prototypes
//----------------------------------------------------------------

extern void  E3d_SHMatrixInit(E3dSHRotateMatrix* PM, const int PNumOfBands);
extern void  E3d_SHMatrixClear(E3dSHRotateMatrix* PM);
extern void  E3d_SHMatrixTransform(E3dSHRotateMatrix* PM, E3dCoordinate* PSource, E3dCoordinate* PDestination, const int PNumOfBands);
extern void  E3d_SHRotate(E3dSHRotateMatrix* PShRotationMatrix, const E3dMatrix PRotationMatrix);
extern void  E3d_SHPrintRotation(const E3dSHRotateMatrix* PM);

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

#endif	// _E3D_Light_h

