mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2025-02-17 01:11:45 +00:00
bring in OpenQuartz's extentions (except -ikmap: got tired:)
go back to id's lighting model being default. LordHavoc's is selectable via --attentuation havoc. Also selectable on a per-light basis.
This commit is contained in:
parent
31aca31d17
commit
5ee1b1d9ca
9 changed files with 346 additions and 36 deletions
|
@ -33,6 +33,19 @@
|
|||
#define DEFAULTLIGHTLEVEL 300
|
||||
#define DEFAULTFALLOFF 1.0f
|
||||
|
||||
// Open Quartz - attenuation types
|
||||
#define LIGHT_LINEAR 0 // regular attenuation (light - distance)
|
||||
#define LIGHT_RADIUS 1 // light * (distance - radius) / radius
|
||||
#define LIGHT_INVERSE 2 // light / distance
|
||||
#define LIGHT_REALISTIC 3 // light / (distance * distance)
|
||||
#define LIGHT_NO_ATTEN 4 // no attenuation
|
||||
#define LIGHT_LH 5 // LordHavocs version of realistic
|
||||
|
||||
// Open Quartz - noise type flags
|
||||
#define NOISE_RANDOM 0 // completely random noise (default)
|
||||
#define NOISE_SMOOTH 1 // low res noise with interpolation
|
||||
#define NOISE_PERLIN 2 // combines several noise frequencies
|
||||
|
||||
typedef struct epair_s {
|
||||
struct epair_s *next;
|
||||
const char *key;
|
||||
|
@ -57,6 +70,17 @@ typedef struct entity_s {
|
|||
// the visdata for the leaf this light
|
||||
// is in
|
||||
int style;
|
||||
|
||||
// Open Quartz - special light feilds
|
||||
int noisetype; // random noise type
|
||||
float noise; // noise intensity
|
||||
float resolution; // noise blockiness
|
||||
float persistence; // perlin noise decay per octave
|
||||
int attenuation; // light attenuation type
|
||||
float radius; // the light's maximum range, minimum
|
||||
// of cutoff range and _radius key, 0
|
||||
// for no maximum
|
||||
|
||||
const char *target;
|
||||
const char *targetname;
|
||||
struct epair_s *epairs;
|
||||
|
|
5
tools/qflight/include/noise.h
Normal file
5
tools/qflight/include/noise.h
Normal file
|
@ -0,0 +1,5 @@
|
|||
float noise3d (vec3_t v, int num);
|
||||
float noiseXYZ (float x, float y, float z, int num);
|
||||
float noise_scaled (vec3_t v, float s, int num);
|
||||
float noise_perlin (vec3_t v, float p, int num);
|
||||
void snap_vector (vec3_t v_old, vec3_t v_new, float scale);
|
|
@ -36,10 +36,13 @@ typedef struct {
|
|||
int threads;
|
||||
int novis;
|
||||
int extrabit;
|
||||
int attenuation;
|
||||
vec_t extrascale;
|
||||
vec_t distance;
|
||||
vec_t range;
|
||||
vec_t globallightscale;
|
||||
vec_t noise;
|
||||
vec_t cutoff;
|
||||
const char *lightsfilename;
|
||||
} options_t;
|
||||
|
||||
|
|
|
@ -17,7 +17,7 @@ endif
|
|||
bin_PROGRAMS= $(qflight)
|
||||
EXTRA_PROGRAMS= qflight
|
||||
|
||||
qflight_SOURCES= entities.c ltface.c options.c qflight.c threads.c trace.c vis.c
|
||||
qflight_SOURCES= entities.c ltface.c noise.c options.c qflight.c threads.c trace.c vis.c
|
||||
|
||||
qflight_LDFLAGS= $(PTHREAD_LDFLAGS)
|
||||
qflight_LDADD= $(QFLIGHT_LIBS)
|
||||
|
|
|
@ -172,6 +172,8 @@ LoadEntities (void)
|
|||
entity_t *entity;
|
||||
epair_t *epair;
|
||||
int i;
|
||||
float cutoff_range;
|
||||
float intensity;
|
||||
|
||||
data = bsp->entdata;
|
||||
|
||||
|
@ -202,6 +204,7 @@ LoadEntities (void)
|
|||
entity->falloff = DEFAULTFALLOFF * DEFAULTFALLOFF;
|
||||
entity->lightradius = 0;
|
||||
entity->lightoffset = LIGHTDISTBIAS;
|
||||
entity->attenuation = options.attenuation;
|
||||
|
||||
// go through all the keys in this entity
|
||||
while (1) {
|
||||
|
@ -295,15 +298,53 @@ LoadEntities (void)
|
|||
temp = 1.0 / temp;
|
||||
VectorScale (vec, temp, color2);
|
||||
}
|
||||
// Open Quartz - new keys
|
||||
else if (!strcmp(key, "_attenuation")) {
|
||||
if (!strcmp(com_token, "linear"))
|
||||
entity->attenuation = LIGHT_LINEAR;
|
||||
else if (!strcmp(com_token, "radius"))
|
||||
entity->attenuation = LIGHT_RADIUS;
|
||||
else if (!strcmp(com_token, "inverse"))
|
||||
entity->attenuation = LIGHT_INVERSE;
|
||||
else if (!strcmp(com_token, "realistic"))
|
||||
entity->attenuation = LIGHT_REALISTIC;
|
||||
else if (!strcmp(com_token, "none"))
|
||||
entity->attenuation = LIGHT_NO_ATTEN;
|
||||
else if (!strcmp(com_token, "havoc"))
|
||||
entity->attenuation = LIGHT_REALISTIC;
|
||||
else
|
||||
entity->attenuation = atoi (com_token);
|
||||
} else if (!strcmp(key, "_radius"))
|
||||
entity->radius = atof (com_token);
|
||||
else if (!strcmp(key, "_noise"))
|
||||
entity->noise = atof (com_token);
|
||||
else if (!strcmp(key, "_noisetype")) {
|
||||
if (!strcmp(com_token, "random"))
|
||||
entity->noisetype = NOISE_RANDOM;
|
||||
else if (!strcmp(com_token, "smooth"))
|
||||
entity->noisetype = NOISE_SMOOTH;
|
||||
else if (!strcmp(com_token, "perlin"))
|
||||
entity->noisetype = NOISE_PERLIN;
|
||||
else
|
||||
entity->noisetype = atoi (com_token);
|
||||
} else if (!strcmp(key, "_persistence"))
|
||||
entity->persistence = atof (com_token);
|
||||
else if (!strcmp(key, "_resolution"))
|
||||
entity->resolution = atof (com_token);
|
||||
}
|
||||
|
||||
if (entity->targetname)
|
||||
printf ("%s %d %d\n", entity->targetname, entity->light, entity->style);
|
||||
|
||||
// all fields have been parsed
|
||||
if (entity->classname && !strncmp (entity->classname, "light", 5))
|
||||
if (entity->classname && !strncmp (entity->classname, "light", 5)) {
|
||||
if (!entity->light)
|
||||
entity->light = DEFAULTLIGHTLEVEL;
|
||||
if (!entity->noise)
|
||||
entity->noise = options.noise;
|
||||
if (!entity->persistence)
|
||||
entity->persistence = 1;
|
||||
}
|
||||
|
||||
if (entity->light) {
|
||||
// convert to subtraction to the brightness for the whole light,
|
||||
|
@ -322,6 +363,38 @@ LoadEntities (void)
|
|||
+ LIGHTDISTBIAS);
|
||||
if (entity->subbrightness < (1.0 / 1048576.0))
|
||||
entity->subbrightness = (1.0 / 1048576.0);
|
||||
|
||||
intensity = entity->light;
|
||||
if (intensity < 0)
|
||||
intensity = -intensity;
|
||||
switch (entity->attenuation) {
|
||||
case LIGHT_RADIUS:
|
||||
// default radius is intensity (same as LIGHT_LINEAR)
|
||||
if (!entity->radius)
|
||||
entity->radius = intensity;
|
||||
break;
|
||||
case LIGHT_LINEAR:
|
||||
// don't allow radius to be greater than intensity
|
||||
if (entity->radius > intensity || entity->radius == 0)
|
||||
entity->radius = intensity;
|
||||
break;
|
||||
case LIGHT_REALISTIC:
|
||||
if (options.cutoff) {
|
||||
// approximate limit for faster lighting
|
||||
cutoff_range = sqrt (intensity / options.cutoff);
|
||||
if (!entity->radius || cutoff_range < entity->radius)
|
||||
entity->radius = cutoff_range;
|
||||
}
|
||||
break;
|
||||
case LIGHT_INVERSE:
|
||||
if (options.cutoff) {
|
||||
// approximate limit for faster lighting
|
||||
cutoff_range = intensity / options.cutoff;
|
||||
if (!entity->radius || cutoff_range < entity->radius)
|
||||
entity->radius = cutoff_range;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (entity->classname && !strcmp (entity->classname, "light")) {
|
||||
|
|
|
@ -57,6 +57,7 @@ static __attribute__ ((unused)) const char rcsid[] =
|
|||
|
||||
#include "light.h"
|
||||
#include "entities.h"
|
||||
#include "noise.h"
|
||||
#include "options.h"
|
||||
#include "threads.h"
|
||||
|
||||
|
@ -275,7 +276,8 @@ SingleLightFace (entity_t *light, lightinfo_t *l)
|
|||
int mapnum, i;
|
||||
qboolean hit;
|
||||
vec3_t incoming, spotvec;
|
||||
vec_t add, dist, idist, lightfalloff, lightsubtract, spotcone;
|
||||
vec_t add, angle, dist, idist, lightfalloff, lightsubtract, spotcone;
|
||||
vec_t intensity;
|
||||
lightpoint_t *point;
|
||||
lightsample_t *sample;
|
||||
|
||||
|
@ -290,17 +292,14 @@ SingleLightFace (entity_t *light, lightinfo_t *l)
|
|||
lightsubtract = light->subbrightness;
|
||||
|
||||
// don't bother with light too far away
|
||||
#if 0
|
||||
if (dist > light->light) {
|
||||
if (light->radius && dist > light->radius) {
|
||||
c_culldistplane++;
|
||||
return;
|
||||
}
|
||||
#else
|
||||
if (lightsubtract > (1.0 / (dist * dist * lightfalloff + LIGHTDISTBIAS))) {
|
||||
c_culldistplane++;
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
for (mapnum = 0; mapnum < MAXLIGHTMAPS; mapnum++) {
|
||||
if (l->lightstyles[mapnum] == light->style)
|
||||
|
@ -330,41 +329,96 @@ SingleLightFace (entity_t *light, lightinfo_t *l)
|
|||
idist = 1.0 / dist;
|
||||
VectorScale (incoming, idist, incoming);
|
||||
|
||||
if (light->radius && dist > light->radius)
|
||||
continue;
|
||||
|
||||
// spotlight cutoff
|
||||
if (spotcone > 0 && DotProduct (spotvec, incoming) > spotcone)
|
||||
continue;
|
||||
#if 0
|
||||
|
||||
angle = DotProduct (incoming, l->facenormal);
|
||||
angle = (1.0 - scalecos) + scalecos * angle;
|
||||
add = light->light - dist;
|
||||
add *= angle;
|
||||
if (add < 0)
|
||||
continue;
|
||||
lightsamp[c] += add;
|
||||
if (lightsamp[c] > 1)
|
||||
// ignore real tiny lights
|
||||
hit = true;
|
||||
#else
|
||||
// LordHavoc: changed to be more realistic (entirely different
|
||||
// lighting model)
|
||||
// LordHavoc: use subbrightness on all lights, simply to have
|
||||
//some distance culling
|
||||
add = (1.0 / (dist * dist * lightfalloff + LIGHTDISTBIAS)
|
||||
- lightsubtract);
|
||||
|
||||
switch (light->attenuation) {
|
||||
case LIGHT_LINEAR:
|
||||
add = light->light - dist;
|
||||
break;
|
||||
case LIGHT_RADIUS:
|
||||
add = light->light * (light->radius - dist) / light->radius;
|
||||
break;
|
||||
case LIGHT_INVERSE:
|
||||
add = light->light / dist;
|
||||
break;
|
||||
case LIGHT_REALISTIC:
|
||||
add = light->light / (dist * dist);
|
||||
break;
|
||||
case LIGHT_LH:
|
||||
add = 1 / (dist * dist * lightfalloff + LIGHTDISTBIAS);
|
||||
// LordHavoc: changed to be more realistic (entirely different
|
||||
// lighting model)
|
||||
// LordHavoc: use subbrightness on all lights, simply to have
|
||||
//some distance culling
|
||||
add -= lightsubtract;
|
||||
break;
|
||||
}
|
||||
|
||||
if (light->noise) {
|
||||
int seed = light - entities;
|
||||
vec3_t snap;
|
||||
lightpoint_t *noise_point = point;
|
||||
if (options.extrascale) {
|
||||
// FIXME not correct for extrascale > 2
|
||||
// We don't want to oversample noise because that just
|
||||
// waters it down. So we "undersample" noise by using
|
||||
// the same surf coord for every group of 4 lightmap pixels
|
||||
// ("undersampling", "pixelation", "anti-interpolation" :-)
|
||||
int width = (l->texsize[0] + 1) * 2;
|
||||
int x = i % width;
|
||||
int y = i / width;
|
||||
|
||||
if (x % 2 && y % 2)
|
||||
noise_point -= width * 3 + 3;
|
||||
else if (y % 2)
|
||||
noise_point -= width * 3;
|
||||
else if (x % 2)
|
||||
noise_point -= 3;
|
||||
}
|
||||
if (light->noisetype == NOISE_SMOOTH)
|
||||
snap_vector (noise_point->v, snap, 0);
|
||||
else
|
||||
snap_vector (noise_point->v, snap, light->resolution);
|
||||
|
||||
|
||||
if (light->noisetype == NOISE_RANDOM)
|
||||
intensity = noise3d (snap, seed);
|
||||
if (light->noisetype == NOISE_SMOOTH)
|
||||
intensity = noise_scaled (snap, light->resolution, seed);
|
||||
if (light->noisetype == NOISE_PERLIN)
|
||||
intensity = noise_perlin (snap, light->persistence, seed);
|
||||
|
||||
add *= intensity * light->noise + 1.0 - light->noise;
|
||||
}
|
||||
|
||||
if (add <= 0)
|
||||
continue;
|
||||
if (!TestLine (l, point->v, light->origin))
|
||||
continue;
|
||||
|
||||
// LordHavoc: FIXME: decide this 0.5 bias based on shader properties
|
||||
// (some are dull, some are shiny)
|
||||
add *= (DotProduct (incoming, l->facenormal) * 0.5 + 0.5);
|
||||
if (light->attenuation == LIGHT_LH) {
|
||||
// LordHavoc: FIXME: decide this 0.5 bias based on shader
|
||||
// properties (some are dull, some are shiny)
|
||||
add *= angle * 0.5 + 0.5;
|
||||
} else {
|
||||
add *= angle;
|
||||
}
|
||||
add *= options.extrascale;
|
||||
|
||||
if (light->light < 0)
|
||||
add *= -1; // negative light
|
||||
|
||||
sample = &l->sample[mapnum][point->samplepos];
|
||||
VectorMultAdd (sample->c, add, light->color, sample->c);
|
||||
if (!hit && ((sample->c[0] + sample->c[1] + sample->c[2]) >= 1))
|
||||
hit = true;
|
||||
#endif
|
||||
}
|
||||
|
||||
// if the style has some data now, make sure it is in the list
|
||||
|
|
107
tools/qflight/source/noise.c
Normal file
107
tools/qflight/source/noise.c
Normal file
|
@ -0,0 +1,107 @@
|
|||
|
||||
#include <math.h>
|
||||
|
||||
#include "QF/qtypes.h"
|
||||
|
||||
#include "noise.h"
|
||||
|
||||
// returns the 3D noise value for a point in space
|
||||
float
|
||||
noise3d (vec3_t v, int num)
|
||||
{
|
||||
int n;
|
||||
|
||||
n = floor (v[0]) + floor (v[1]) * 57 + floor (v[2]) * 3251;
|
||||
n = (n << 13) ^ n;
|
||||
n = n * (n * n * 15731 + 789221) + 1376312589;
|
||||
return (n & 0x7fffffff) / 2147483648.0;
|
||||
}
|
||||
|
||||
// a variation of Noise3D that takes 3 floats
|
||||
float
|
||||
noiseXYZ (float x, float y, float z, int num)
|
||||
{
|
||||
vec3_t v;
|
||||
|
||||
v[0] = x;
|
||||
v[1] = y;
|
||||
v[2] = z;
|
||||
return noise3d (v, num);
|
||||
}
|
||||
|
||||
// returns a noise value from a scaled up noise pattern
|
||||
//
|
||||
// Actually created by sampling points on a certain grid
|
||||
// and interpolating the inbetween value, making the noise smooth
|
||||
float
|
||||
noise_scaled (vec3_t v, float s, int num)
|
||||
{
|
||||
float n = 0;
|
||||
vec3_t a, b, c, d;
|
||||
|
||||
a[0] = floor (v[0] / s) * s;
|
||||
b[0] = a[0] + s;
|
||||
c[0] = (v[0] - a[0]) / s;
|
||||
d[0] = 1 - c[0];
|
||||
a[1] = floor (v[1] / s) * s;
|
||||
b[1] = a[1] + s;
|
||||
c[1] = (v[1] - a[1]) / s;
|
||||
d[1] = 1 - c[1];
|
||||
a[2] = floor (v[2] / s) * s;
|
||||
b[2] = a[2] + s;
|
||||
c[2] = (v[2] - a[2]) / s;
|
||||
d[2] = 1 - c[2];
|
||||
|
||||
n += noiseXYZ (a[0], a[1], a[2], num) * d[0] * d[1] * d[2];
|
||||
n += noiseXYZ (a[0], a[1], b[2], num) * d[0] * d[1] * c[2];
|
||||
n += noiseXYZ (a[0], b[1], a[2], num) * d[0] * c[1] * d[2];
|
||||
n += noiseXYZ (a[0], b[1], b[2], num) * d[0] * c[1] * c[2];
|
||||
n += noiseXYZ (b[0], a[1], a[2], num) * c[0] * d[1] * d[2];
|
||||
n += noiseXYZ (b[0], a[1], b[2], num) * c[0] * d[1] * c[2];
|
||||
n += noiseXYZ (b[0], b[1], a[2], num) * c[0] * c[1] * d[2];
|
||||
n += noiseXYZ (b[0], b[1], b[2], num) * c[0] * c[1] * c[2];
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
// returns a Perlin noise value for a point in 3D space
|
||||
//
|
||||
// This noise function combines noise at several different scales
|
||||
// which makes it slower than just using one layer of noise
|
||||
float
|
||||
noise_perlin (vec3_t v, float p, int num)
|
||||
{
|
||||
float n = 0;
|
||||
|
||||
n += noise_scaled (v, 1024, num);
|
||||
n += 0.5 + (noise_scaled (v, 256, num) - 0.5) * p;
|
||||
n += 0.5 + (noise_scaled (v, 64, num) - 0.5) * p * p;
|
||||
n += 0.5 + (noise_scaled (v, 16, num) - 0.5) * p * p * p;
|
||||
|
||||
return n / 2 - 0.5;
|
||||
}
|
||||
|
||||
// Use to create low-res noise patterns without interpolation
|
||||
// A good strategy for avoiding seams on terrain and curves
|
||||
// when called with a scale value of about 32
|
||||
//
|
||||
// This is because surfaces have some texture pixels which are
|
||||
// actually not in the polygon at all so their edges don't
|
||||
// perfectly fit together.
|
||||
//
|
||||
// Creates a random pattern of light and dark squares on flat
|
||||
// axis aligned surfaces, which is usually not what you want
|
||||
// but it may have interesting applications
|
||||
void
|
||||
snap_vector (vec3_t v_old, vec3_t v_new, float scale)
|
||||
{
|
||||
if (scale <= 0) {
|
||||
v_new[0] = v_old[0];
|
||||
v_new[1] = v_old[1];
|
||||
v_new[2] = v_old[2];
|
||||
} else {
|
||||
v_new[0] = floor (v_old[0] / scale + 0.5) * scale;
|
||||
v_new[1] = floor (v_old[1] / scale + 0.5) * scale;
|
||||
v_new[2] = floor (v_old[2] / scale + 0.5) * scale;
|
||||
}
|
||||
}
|
|
@ -45,6 +45,7 @@ static __attribute__ ((unused)) const char rcsid[] =
|
|||
|
||||
#include "compat.h"
|
||||
|
||||
#include "entities.h"
|
||||
#include "options.h"
|
||||
|
||||
const char *this_program;
|
||||
|
@ -55,6 +56,9 @@ static struct option const long_options[] = {
|
|||
{"help", no_argument, 0, 'h'},
|
||||
{"version", no_argument, 0, 'V'},
|
||||
{"threads", required_argument, 0, 't'},
|
||||
{"attenuation", required_argument, 0, 'a'},
|
||||
{"noise", required_argument, 0, 'n'},
|
||||
{"cutoff", required_argument, 0, 'c'},
|
||||
{"extra", required_argument, 0, 'e'},
|
||||
{"novis", no_argument, 0, 'N'},
|
||||
{"distance", required_argument, 0, 'd'},
|
||||
|
@ -70,6 +74,9 @@ static const char *short_options =
|
|||
"V" // version
|
||||
"N" // novis
|
||||
"t:" // threads
|
||||
"a:" // attenuation
|
||||
"n:" // noise
|
||||
"c:" // cutoff
|
||||
"e:" // extra sampling
|
||||
"d:" // scale distance
|
||||
"r:" // scale range
|
||||
|
@ -92,6 +99,10 @@ usage (int status)
|
|||
" -e, --extra [num] Apply extra sampling\n"
|
||||
" -d, --distance [scale] Scale distance\n"
|
||||
" -r, --range [scale] Scale range\n"
|
||||
" -a, --attenuation [type] linear,radius,inverse,realistic,none,\n"
|
||||
" havoc\n"
|
||||
" -n, --noise [factor] Scale noise. 0 (default) to disable\n"
|
||||
" -c, --cutoff [scale] Scale cutoff. 0 to disable\n"
|
||||
" -f, --file [bspfile] BSP file\n\n");
|
||||
exit (status);
|
||||
}
|
||||
|
@ -108,6 +119,8 @@ DecodeArgs (int argc, char **argv)
|
|||
options.distance = 1.0;
|
||||
options.range = 0.5;
|
||||
options.globallightscale = 1.0;
|
||||
options.cutoff = 1.0;
|
||||
options.attenuation = LIGHT_LINEAR;
|
||||
bspfile = NULL;
|
||||
|
||||
while ((c = getopt_long (argc, argv, short_options, long_options, 0))
|
||||
|
@ -134,6 +147,37 @@ DecodeArgs (int argc, char **argv)
|
|||
if (eptr == optarg || *eptr)
|
||||
usage (1);
|
||||
break;
|
||||
case 'a':
|
||||
if (!strcmp(optarg, "linear"))
|
||||
options.attenuation = LIGHT_LINEAR;
|
||||
else if (!strcmp(optarg, "radius"))
|
||||
options.attenuation = LIGHT_RADIUS;
|
||||
else if (!strcmp(optarg, "inverse"))
|
||||
options.attenuation = LIGHT_INVERSE;
|
||||
else if (!strcmp(optarg, "realistic"))
|
||||
options.attenuation = LIGHT_REALISTIC;
|
||||
else if (!strcmp(optarg, "none"))
|
||||
options.attenuation = LIGHT_NO_ATTEN;
|
||||
else if (!strcmp(optarg, "havoc"))
|
||||
options.attenuation = LIGHT_REALISTIC;
|
||||
else {
|
||||
options.attenuation = strtol (optarg, &eptr, 10);
|
||||
if (eptr == optarg || *eptr)
|
||||
usage (1);
|
||||
}
|
||||
break;
|
||||
case 'n': // noise
|
||||
options.noise = strtod (optarg, &eptr);
|
||||
if (eptr == optarg || *eptr)
|
||||
usage (1);
|
||||
options.noise = bound (0, options.extrabit, 2);
|
||||
break;
|
||||
case 'c': // cutoff
|
||||
options.cutoff = strtod (optarg, &eptr);
|
||||
if (eptr == optarg || *eptr)
|
||||
usage (1);
|
||||
options.cutoff = bound (0, options.extrabit, 2);
|
||||
break;
|
||||
case 'e': // extra
|
||||
options.extrabit = strtol (optarg, &eptr, 10);
|
||||
if (eptr == optarg || *eptr)
|
||||
|
|
|
@ -55,17 +55,17 @@ static __attribute__ ((unused)) const char rcsid[] =
|
|||
#include "light.h"
|
||||
|
||||
typedef struct {
|
||||
int type;
|
||||
vec3_t normal;
|
||||
float dist;
|
||||
int children[2];
|
||||
int pad;
|
||||
int type;
|
||||
vec3_t normal;
|
||||
float dist;
|
||||
int children[2];
|
||||
int pad;
|
||||
} tnode_t;
|
||||
|
||||
typedef struct {
|
||||
vec3_t backpt;
|
||||
int side;
|
||||
int node;
|
||||
vec3_t backpt;
|
||||
int side;
|
||||
int node;
|
||||
} tracestack_t;
|
||||
|
||||
tnode_t *tnodes, *tnode_p;
|
||||
|
|
Loading…
Reference in a new issue