MuckyFoot-UrbanChaos/fallen/Headers/light.h
2017-05-20 11:14:17 +10:00

296 lines
5.7 KiB
C

#ifndef LIGHTG_H
#define LIGHTG_H
//
// Do we want coloured lights?
//
#define LIGHT_COLOURED 1
//
// A structure that describes a light.
//
typedef struct
{
SLONG x;
SLONG y;
SLONG z;
UBYTE red;
UBYTE green;
UBYTE blue;
UBYTE range;
UBYTE type;
UBYTE param;
UWORD dummy;
} LIGHT_Save;
//
// A light colour.
//
#if LIGHT_COLOURED
typedef struct
{
UBYTE red;
UBYTE green;
UBYTE blue;
} LIGHT_Colour;
#else
typedef UBYTE LIGHT_Colour;
#endif
//
// UBYTE values of lights go from 0 to LIGHT_MAX_BRIGHT, all values above
// LIGHT_MAX_BRIGHT are at maximum brightness.
//
#define LIGHT_MAX_BRIGHT 64
//
// The maximum range of the light in world coords.
//
#define LIGHT_MAX_RANGE 0x600
//
// So the light module can work with any sort of height field.
// The LIGHT_Map you pass can be on the stack because the
// function takes a copy of it.
//
typedef struct
{
SLONG width;
SLONG height;
SLONG (*get_height)(SLONG x, SLONG z); // 0 <= x < width, 0 <= z < height
LIGHT_Colour (*get_light) (SLONG x, SLONG z);
void (*set_light) (SLONG x, SLONG z, LIGHT_Colour light);
} LIGHT_Map;
void LIGHT_set_hf(LIGHT_Map *map);
//
// Sets the ambient light used. The normal of the light should have
// a length of 255.
//
extern LIGHT_Colour LIGHT_amb_colour; // DONT SET THESE VALUES, USE THE FUNCTION BELOW!
extern SLONG LIGHT_amb_norm_x;
extern SLONG LIGHT_amb_norm_y;
extern SLONG LIGHT_amb_norm_z;
void LIGHT_set_ambient(
LIGHT_Colour amb_colour,
SLONG amb_norm_x,
SLONG amb_norm_y,
SLONG amb_norm_z);
//
// Removes all lights and removes all cached light info.
//
void LIGHT_init(void);
//
// Where building-point lighting goes.
//
extern LIGHT_Colour LIGHT_building_point[RMAX_PRIM_POINTS];
//
// Recalcs all lighting on the current height-field and puts values in the
// LIGHT_building_point[] array for the lights on the building prim points.
//
void LIGHT_recalc_hf(void);
//
// Lights...
//
typedef UWORD LIGHT_Index;
//
// Creates a new light. The meaning of 'param' depends on
// the type of light.
//
#define LIGHT_TYPE_NORMAL 1
#define LIGHT_TYPE_BROKEN 2 // param is how often the light flickers off.
#define LIGHT_TYPE_PULSE 3 // param is the speed of flashing.
#define LIGHT_TYPE_FADE 4 // param is how long the light lasts.
LIGHT_Index LIGHT_create(
GameCoord where,
LIGHT_Colour colour,
UBYTE range,
UBYTE type,
UBYTE param);
void LIGHT_destroy(LIGHT_Index l_index);
//
// Gets/sets a light's position.
//
GameCoord LIGHT_pos_get(LIGHT_Index l_index);
void LIGHT_pos_set(LIGHT_Index l_index, GameCoord pos);
//
// Processes all the lights.
//
void LIGHT_process(void);
//
// Returns a value that identifies the lighting context of the given thing.
// If the lighting context changes then that thing needs to be re-lit. The
// position and orientation of the actual thing is not taken into account
// in the context. You have to check for that yourself.
//
SLONG LIGHT_get_context(THING_INDEX t_index);
//
// Returns the colour of light at the given point. It only uses light found
// in the last call to LIGHT_get_context.
//
LIGHT_Colour LIGHT_get_point(SLONG x, SLONG y, SLONG z);
//
// Lights the given prim. It puts the light values in the LIGHT_point_colour array.
// Uses the prim_normal array... make sure you've called calc_prim_normals();
//
void LIGHT_prim (THING_INDEX t_index);
void LIGHT_prim_use_normals(THING_INDEX t_index);
//
// Lights a building. It puts the light values in the LIGHT_point_colour array.
//
void LIGHT_building_use_normals(THING_INDEX t_index);
//
// The array in which the colours of the points will be returned.
//
#define LIGHT_MAX_POINTS 2560
extern LIGHT_Colour LIGHT_point_colour[LIGHT_MAX_POINTS];
extern SLONG LIGHT_point_colour_upto;
//
// Returns a D3D colour from a LIGHT_Colour.
//
#if LIGHT_COLOURED
inline void LIGHT_get_d3d_colour(LIGHT_Colour col, ULONG *colour, ULONG *specular)
{
SLONG red = col.red;
SLONG green = col.green;
SLONG blue = col.blue;
SLONG wred = 0;
SLONG wgreen = 0;
SLONG wblue = 0;
red *= (256 / LIGHT_MAX_BRIGHT);
green *= (256 / LIGHT_MAX_BRIGHT);
blue *= (256 / LIGHT_MAX_BRIGHT);
if (red > 255) {wred = red - 255 >> 1; red = 255; if (wred > 255) {wred = 255;}}
if (green > 255) {wgreen = green - 255 >> 1; green = 255; if (wgreen > 255) {wgreen = 255;}}
if (blue > 255) {wblue = blue - 255 >> 1; blue = 255; if (wblue > 255) {wblue = 255;}}
*colour = (red << 16) | (green << 8) | (blue << 0);
*specular = (wred << 16) | (wgreen << 8) | (wblue << 0);
}
inline ULONG LIGHT_get_glide_colour(LIGHT_Colour col)
{
SLONG red = col.red;
SLONG green = col.green;
SLONG blue = col.blue;
SLONG alpha = 0;
red *= (256 / LIGHT_MAX_BRIGHT);
green *= (256 / LIGHT_MAX_BRIGHT);
blue *= (256 / LIGHT_MAX_BRIGHT);
if (red > 255) {alpha += red - 255; red = 255;}
if (green > 255) {alpha += green - 255; green = 255;}
if (blue > 255) {alpha += blue - 255; blue = 255;}
if (alpha > 255) {alpha = 255;}
return (alpha << 24) | (red << 16) | (green << 8) | (blue << 0);
}
#else
inline void LIGHT_get_d3d_colour(LIGHT_Colour col, ULONG *colour, ULONG *specular)
{
SLONG whiteout;
SLONG bright;
bright = col * (256 / LIGHT_MAX_BRIGHT);
//
// Once we go over fully-bright, we get into saturated colour.
//
if (bright > 255)
{
whiteout = bright - 255 >> 1;
bright = 255;
if (whiteout > 255) {whiteout = 255;}
}
else
{
whiteout = 0;
}
*colour = (bright << 0) | (bright << 8) | (bright << 16);
*specular = (whiteout << 0) | (whiteout << 8) | (whiteout << 16);
}
#endif
#endif