The source release of the qutils.

This commit is contained in:
Travis Bradshaw
2012-01-31 15:48:05 -06:00
commit 6df9737f9c
111 changed files with 23929 additions and 0 deletions

475
qutils/VIS/FLOW.C Normal file
View File

@@ -0,0 +1,475 @@
#include "vis.h"
int c_chains;
int c_portalskip, c_leafskip;
int c_vistest, c_mighttest;
int active;
void CheckStack (leaf_t *leaf, threaddata_t *thread)
{
pstack_t *p;
for (p=thread->pstack_head.next ; p ; p=p->next)
if (p->leaf == leaf)
Error ("CheckStack: leaf recursion");
}
/*
==============
ClipToSeperators
Source, pass, and target are an ordering of portals.
Generates seperating planes canidates by taking two points from source and one
point from pass, and clips target by them.
If target is totally clipped away, that portal can not be seen through.
Normal clip keeps target on the same side as pass, which is correct if the
order goes source, pass, target. If the order goes pass, source, target then
flipclip should be set.
==============
*/
winding_t *ClipToSeperators (winding_t *source, winding_t *pass, winding_t *target, qboolean flipclip)
{
int i, j, k, l;
plane_t plane;
vec3_t v1, v2;
float d;
vec_t length;
int counts[3];
qboolean fliptest;
// check all combinations
for (i=0 ; i<source->numpoints ; i++)
{
l = (i+1)%source->numpoints;
VectorSubtract (source->points[l] , source->points[i], v1);
// fing a vertex of pass that makes a plane that puts all of the
// vertexes of pass on the front side and all of the vertexes of
// source on the back side
for (j=0 ; j<pass->numpoints ; j++)
{
VectorSubtract (pass->points[j], source->points[i], v2);
plane.normal[0] = v1[1]*v2[2] - v1[2]*v2[1];
plane.normal[1] = v1[2]*v2[0] - v1[0]*v2[2];
plane.normal[2] = v1[0]*v2[1] - v1[1]*v2[0];
// if points don't make a valid plane, skip it
length = plane.normal[0] * plane.normal[0]
+ plane.normal[1] * plane.normal[1]
+ plane.normal[2] * plane.normal[2];
if (length < ON_EPSILON)
continue;
length = 1/sqrt(length);
plane.normal[0] *= length;
plane.normal[1] *= length;
plane.normal[2] *= length;
plane.dist = DotProduct (pass->points[j], plane.normal);
//
// find out which side of the generated seperating plane has the
// source portal
//
fliptest = false;
for (k=0 ; k<source->numpoints ; k++)
{
if (k == i || k == l)
continue;
d = DotProduct (source->points[k], plane.normal) - plane.dist;
if (d < -ON_EPSILON)
{ // source is on the negative side, so we want all
// pass and target on the positive side
fliptest = false;
break;
}
else if (d > ON_EPSILON)
{ // source is on the positive side, so we want all
// pass and target on the negative side
fliptest = true;
break;
}
}
if (k == source->numpoints)
continue; // planar with source portal
//
// flip the normal if the source portal is backwards
//
if (fliptest)
{
VectorSubtract (vec3_origin, plane.normal, plane.normal);
plane.dist = -plane.dist;
}
//
// if all of the pass portal points are now on the positive side,
// this is the seperating plane
//
counts[0] = counts[1] = counts[2] = 0;
for (k=0 ; k<pass->numpoints ; k++)
{
if (k==j)
continue;
d = DotProduct (pass->points[k], plane.normal) - plane.dist;
if (d < -ON_EPSILON)
break;
else if (d > ON_EPSILON)
counts[0]++;
else
counts[2]++;
}
if (k != pass->numpoints)
continue; // points on negative side, not a seperating plane
if (!counts[0])
{
continue; // planar with seperating plane
}
//
// flip the normal if we want the back side
//
if (flipclip)
{
VectorSubtract (vec3_origin, plane.normal, plane.normal);
plane.dist = -plane.dist;
}
//
// clip target by the seperating plane
//
target = ClipWinding (target, &plane, false);
if (!target)
return NULL; // target is not visible
}
}
return target;
}
/*
==================
RecursiveLeafFlow
Flood fill through the leafs
If src_portal is NULL, this is the originating leaf
==================
*/
void RecursiveLeafFlow (int leafnum, threaddata_t *thread, pstack_t *prevstack)
{
pstack_t stack;
portal_t *p;
plane_t backplane;
winding_t *source, *target;
leaf_t *leaf;
int i, j;
long *test, *might, *vis;
qboolean more;
c_chains++;
leaf = &leafs[leafnum];
CheckStack (leaf, thread);
// mark the leaf as visible
if (! (thread->leafvis[leafnum>>3] & (1<<(leafnum&7)) ) )
{
thread->leafvis[leafnum>>3] |= 1<<(leafnum&7);
thread->base->numcansee++;
}
prevstack->next = &stack;
stack.next = NULL;
stack.leaf = leaf;
stack.portal = NULL;
stack.mightsee = malloc(bitbytes);
might = (long *)stack.mightsee;
vis = (long *)thread->leafvis;
// check all portals for flowing into other leafs
for (i=0 ; i<leaf->numportals ; i++)
{
p = leaf->portals[i];
if ( ! (prevstack->mightsee[p->leaf>>3] & (1<<(p->leaf&7)) ) )
{
c_leafskip++;
continue; // can't possibly see it
}
// if the portal can't see anything we haven't allready seen, skip it
if (p->status == stat_done)
{
c_vistest++;
test = (long *)p->visbits;
}
else
{
c_mighttest++;
test = (long *)p->mightsee;
}
more = false;
for (j=0 ; j<bitlongs ; j++)
{
might[j] = ((long *)prevstack->mightsee)[j] & test[j];
if (might[j] & ~vis[j])
more = true;
}
if (!more)
{ // can't see anything new
c_portalskip++;
continue;
}
// get plane of portal, point normal into the neighbor leaf
stack.portalplane = p->plane;
VectorSubtract (vec3_origin, p->plane.normal, backplane.normal);
backplane.dist = -p->plane.dist;
if (VectorCompare (prevstack->portalplane.normal, backplane.normal) )
continue; // can't go out a coplanar face
c_portalcheck++;
stack.portal = p;
stack.next = NULL;
target = ClipWinding (p->winding, &thread->pstack_head.portalplane, false);
if (!target)
continue;
if (!prevstack->pass)
{ // the second leaf can only be blocked if coplanar
stack.source = prevstack->source;
stack.pass = target;
RecursiveLeafFlow (p->leaf, thread, &stack);
FreeWinding (target);
continue;
}
target = ClipWinding (target, &prevstack->portalplane, false);
if (!target)
continue;
source = CopyWinding (prevstack->source);
source = ClipWinding (source, &backplane, false);
if (!source)
{
FreeWinding (target);
continue;
}
c_portaltest++;
if (testlevel > 0)
{
target = ClipToSeperators (source, prevstack->pass, target, false);
if (!target)
{
FreeWinding (source);
continue;
}
}
if (testlevel > 1)
{
target = ClipToSeperators (prevstack->pass, source, target, true);
if (!target)
{
FreeWinding (source);
continue;
}
}
if (testlevel > 2)
{
source = ClipToSeperators (target, prevstack->pass, source, false);
if (!source)
{
FreeWinding (target);
continue;
}
}
if (testlevel > 3)
{
source = ClipToSeperators (prevstack->pass, target, source, true);
if (!source)
{
FreeWinding (target);
continue;
}
}
stack.source = source;
stack.pass = target;
c_portalpass++;
// flow through it for real
RecursiveLeafFlow (p->leaf, thread, &stack);
FreeWinding (source);
FreeWinding (target);
}
free (stack.mightsee);
}
/*
===============
PortalFlow
===============
*/
void PortalFlow (portal_t *p)
{
threaddata_t data;
if (p->status != stat_working)
Error ("PortalFlow: reflowed");
p->status = stat_working;
p->visbits = malloc (bitbytes);
memset (p->visbits, 0, bitbytes);
memset (&data, 0, sizeof(data));
data.leafvis = p->visbits;
data.base = p;
data.pstack_head.portal = p;
data.pstack_head.source = p->winding;
data.pstack_head.portalplane = p->plane;
data.pstack_head.mightsee = p->mightsee;
RecursiveLeafFlow (p->leaf, &data, &data.pstack_head);
p->status = stat_done;
}
/*
===============================================================================
This is a rough first-order aproximation that is used to trivially reject some
of the final calculations.
===============================================================================
*/
byte portalsee[MAX_PORTALS];
int c_leafsee, c_portalsee;
void SimpleFlood (portal_t *srcportal, int leafnum)
{
int i;
leaf_t *leaf;
portal_t *p;
if (srcportal->mightsee[leafnum>>3] & (1<<(leafnum&7)) )
return;
srcportal->mightsee[leafnum>>3] |= (1<<(leafnum&7));
c_leafsee++;
leaf = &leafs[leafnum];
for (i=0 ; i<leaf->numportals ; i++)
{
p = leaf->portals[i];
if ( !portalsee[ p - portals ] )
continue;
SimpleFlood (srcportal, p->leaf);
}
}
/*
==============
BasePortalVis
==============
*/
void BasePortalVis (void)
{
int i, j, k;
portal_t *tp, *p;
float d;
winding_t *w;
for (i=0, p = portals ; i<numportals*2 ; i++, p++)
{
p->mightsee = malloc (bitbytes);
memset (p->mightsee, 0, bitbytes);
c_portalsee = 0;
memset (portalsee, 0, numportals*2);
for (j=0, tp = portals ; j<numportals*2 ; j++, tp++)
{
if (j == i)
continue;
w = tp->winding;
for (k=0 ; k<w->numpoints ; k++)
{
d = DotProduct (w->points[k], p->plane.normal)
- p->plane.dist;
if (d > ON_EPSILON)
break;
}
if (k == w->numpoints)
continue; // no points on front
w = p->winding;
for (k=0 ; k<w->numpoints ; k++)
{
d = DotProduct (w->points[k], tp->plane.normal)
- tp->plane.dist;
if (d < -ON_EPSILON)
break;
}
if (k == w->numpoints)
continue; // no points on front
portalsee[j] = 1;
c_portalsee++;
}
c_leafsee = 0;
SimpleFlood (p, p->leaf);
p->nummightsee = c_leafsee;
// printf ("portal:%4i c_leafsee:%4i \n", i, c_leafsee);
}
}

146
qutils/VIS/SOUNDPVS.C Normal file
View File

@@ -0,0 +1,146 @@
#include "vis.h"
/*
Some textures (sky, water, slime, lava) are considered ambien sound emiters.
Find an aproximate distance to the nearest emiter of each class for each leaf.
*/
/*
====================
SurfaceBBox
====================
*/
void SurfaceBBox (dface_t *s, vec3_t mins, vec3_t maxs)
{
int i, j;
int e;
int vi;
float *v;
mins[0] = mins[1] = 999999;
maxs[0] = maxs[1] = -99999;
for (i=0 ; i<s->numedges ; i++)
{
e = dsurfedges[s->firstedge+i];
if (e >= 0)
vi = dedges[e].v[0];
else
vi = dedges[-e].v[1];
v = dvertexes[vi].point;
for (j=0 ; j<3 ; j++)
{
if (v[j] < mins[j])
mins[j] = v[j];
if (v[j] > maxs[j])
maxs[j] = v[j];
}
}
}
/*
====================
CalcAmbientSounds
====================
*/
void CalcAmbientSounds (void)
{
int i, j, k, l;
dleaf_t *leaf, *hit;
byte *vis;
dface_t *surf;
vec3_t mins, maxs;
float d, maxd;
int ambient_type;
texinfo_t *info;
miptex_t *miptex;
int ofs;
float dists[NUM_AMBIENTS];
float vol;
for (i=0 ; i< portalleafs ; i++)
{
leaf = &dleafs[i+1];
//
// clear ambients
//
for (j=0 ; j<NUM_AMBIENTS ; j++)
dists[j] = 1020;
vis = &uncompressed[i*bitbytes];
for (j=0 ; j< portalleafs ; j++)
{
if ( !(vis[j>>3] & (1<<(j&7))) )
continue;
//
// check this leaf for sound textures
//
hit = &dleafs[j+1];
for (k=0 ; k< hit->nummarksurfaces ; k++)
{
surf = &dfaces[dmarksurfaces[hit->firstmarksurface + k]];
info = &texinfo[surf->texinfo];
ofs = ((dmiptexlump_t *)dtexdata)->dataofs[info->miptex];
miptex = (miptex_t *)(&dtexdata[ofs]);
if ( !Q_strncasecmp (miptex->name, "*water", 6) )
ambient_type = AMBIENT_WATER;
else if ( !Q_strncasecmp (miptex->name, "sky", 3) )
ambient_type = AMBIENT_SKY;
else if ( !Q_strncasecmp (miptex->name, "*slime", 6) )
ambient_type = AMBIENT_WATER; // AMBIENT_SLIME;
else if ( !Q_strncasecmp (miptex->name, "*lava", 6) )
ambient_type = AMBIENT_LAVA;
else if ( !Q_strncasecmp (miptex->name, "*04water", 8) )
ambient_type = AMBIENT_WATER;
else
continue;
// find distance from source leaf to polygon
SurfaceBBox (surf, mins, maxs);
maxd = 0;
for (l=0 ; l<3 ; l++)
{
if (mins[l] > leaf->maxs[l])
d = mins[l] - leaf->maxs[l];
else if (maxs[l] < leaf->mins[l])
d = leaf->mins[l] - mins[l];
else
d = 0;
if (d > maxd)
maxd = d;
}
maxd = 0.25;
if (maxd < dists[ambient_type])
dists[ambient_type] = maxd;
}
}
for (j=0 ; j<NUM_AMBIENTS ; j++)
{
if (dists[j] < 100)
vol = 1.0;
else
{
vol = 1.0 - dists[2]*0.002;
if (vol < 0)
vol = 0;
}
leaf->ambient_level[j] = vol*255;
}
}
}

963
qutils/VIS/VIS.C Normal file
View File

@@ -0,0 +1,963 @@
// vis.c
#include "vis.h"
#define MAX_THREADS 4
int numportals;
int portalleafs;
portal_t *portals;
leaf_t *leafs;
int c_portaltest, c_portalpass, c_portalcheck;
qboolean showgetleaf = true;
int leafon; // the next leaf to be given to a thread to process
#ifdef __alpha
pthread_mutex_t *my_mutex;
#endif
byte *vismap, *vismap_p, *vismap_end; // past visfile
int originalvismapsize;
byte *uncompressed; // [bitbytes*portalleafs]
int bitbytes; // (portalleafs+63)>>3
int bitlongs;
#ifdef __alpha
int numthreads = 4;
#else
int numthreads = 1;
#endif
qboolean fastvis;
qboolean verbose;
int testlevel = 2;
#if 0
void NormalizePlane (plane_t *dp)
{
vec_t ax, ay, az;
if (dp->normal[0] == -1.0)
{
dp->normal[0] = 1.0;
dp->dist = -dp->dist;
return;
}
if (dp->normal[1] == -1.0)
{
dp->normal[1] = 1.0;
dp->dist = -dp->dist;
return;
}
if (dp->normal[2] == -1.0)
{
dp->normal[2] = 1.0;
dp->dist = -dp->dist;
return;
}
ax = fabs(dp->normal[0]);
ay = fabs(dp->normal[1]);
az = fabs(dp->normal[2]);
if (ax >= ay && ax >= az)
{
if (dp->normal[0] < 0)
{
VectorSubtract (vec3_origin, dp->normal, dp->normal);
dp->dist = -dp->dist;
}
return;
}
if (ay >= ax && ay >= az)
{
if (dp->normal[1] < 0)
{
VectorSubtract (vec3_origin, dp->normal, dp->normal);
dp->dist = -dp->dist;
}
return;
}
if (dp->normal[2] < 0)
{
VectorSubtract (vec3_origin, dp->normal, dp->normal);
dp->dist = -dp->dist;
}
}
#endif
void PlaneFromWinding (winding_t *w, plane_t *plane)
{
vec3_t v1, v2;
// calc plane
VectorSubtract (w->points[2], w->points[1], v1);
VectorSubtract (w->points[0], w->points[1], v2);
CrossProduct (v2, v1, plane->normal);
VectorNormalize (plane->normal);
plane->dist = DotProduct (w->points[0], plane->normal);
}
//=============================================================================
/*
==================
NewWinding
==================
*/
winding_t *NewWinding (int points)
{
winding_t *w;
int size;
if (points > MAX_POINTS_ON_WINDING)
Error ("NewWinding: %i points", points);
size = (int)((winding_t *)0)->points[points];
w = malloc (size);
memset (w, 0, size);
return w;
}
void FreeWinding (winding_t *w)
{
if (!w->original)
free (w);
}
void pw(winding_t *w)
{
int i;
for (i=0 ; i<w->numpoints ; i++)
printf ("(%5.1f, %5.1f, %5.1f)\n",w->points[i][0], w->points[i][1],w->points[i][2]);
}
void prl(leaf_t *l)
{
int i;
portal_t *p;
plane_t pl;
for (i=0 ; i<l->numportals ; i++)
{
p = l->portals[i];
pl = p->plane;
printf ("portal %4i to leaf %4i : %7.1f : (%4.1f, %4.1f, %4.1f)\n",(int)(p-portals),p->leaf,pl.dist, pl.normal[0], pl.normal[1], pl.normal[2]);
}
}
/*
==================
CopyWinding
==================
*/
winding_t *CopyWinding (winding_t *w)
{
int size;
winding_t *c;
size = (int)((winding_t *)0)->points[w->numpoints];
c = malloc (size);
memcpy (c, w, size);
c->original = false;
return c;
}
/*
==================
ClipWinding
Clips the winding to the plane, returning the new winding on the positive side
Frees the input winding.
If keepon is true, an exactly on-plane winding will be saved, otherwise
it will be clipped away.
==================
*/
winding_t *ClipWinding (winding_t *in, plane_t *split, qboolean keepon)
{
vec_t dists[MAX_POINTS_ON_WINDING];
int sides[MAX_POINTS_ON_WINDING];
int counts[3];
vec_t dot;
int i, j;
vec_t *p1, *p2;
vec3_t mid;
winding_t *neww;
int maxpts;
counts[0] = counts[1] = counts[2] = 0;
// determine sides for each point
for (i=0 ; i<in->numpoints ; i++)
{
dot = DotProduct (in->points[i], split->normal);
dot -= split->dist;
dists[i] = dot;
if (dot > ON_EPSILON)
sides[i] = SIDE_FRONT;
else if (dot < -ON_EPSILON)
sides[i] = SIDE_BACK;
else
{
sides[i] = SIDE_ON;
}
counts[sides[i]]++;
}
sides[i] = sides[0];
dists[i] = dists[0];
if (keepon && !counts[0] && !counts[1])
return in;
if (!counts[0])
{
FreeWinding (in);
return NULL;
}
if (!counts[1])
return in;
maxpts = in->numpoints+4; // can't use counts[0]+2 because
// of fp grouping errors
neww = NewWinding (maxpts);
for (i=0 ; i<in->numpoints ; i++)
{
p1 = in->points[i];
if (sides[i] == SIDE_ON)
{
VectorCopy (p1, neww->points[neww->numpoints]);
neww->numpoints++;
continue;
}
if (sides[i] == SIDE_FRONT)
{
VectorCopy (p1, neww->points[neww->numpoints]);
neww->numpoints++;
}
if (sides[i+1] == SIDE_ON || sides[i+1] == sides[i])
continue;
// generate a split point
p2 = in->points[(i+1)%in->numpoints];
dot = dists[i] / (dists[i]-dists[i+1]);
for (j=0 ; j<3 ; j++)
{ // avoid round off error when possible
if (split->normal[j] == 1)
mid[j] = split->dist;
else if (split->normal[j] == -1)
mid[j] = -split->dist;
else
mid[j] = p1[j] + dot*(p2[j]-p1[j]);
}
VectorCopy (mid, neww->points[neww->numpoints]);
neww->numpoints++;
}
if (neww->numpoints > maxpts)
Error ("ClipWinding: points exceeded estimate");
// free the original winding
FreeWinding (in);
return neww;
}
//=============================================================================
/*
=============
GetNextPortal
Returns the next portal for a thread to work on
Returns the portals from the least complex, so the later ones can reuse
the earlier information.
=============
*/
portal_t *GetNextPortal (void)
{
int j;
portal_t *p, *tp;
int min;
LOCK;
min = 99999;
p = NULL;
for (j=0, tp = portals ; j<numportals*2 ; j++, tp++)
{
if (tp->nummightsee < min && tp->status == stat_none)
{
min = tp->nummightsee;
p = tp;
}
}
if (p)
p->status = stat_working;
UNLOCK;
return p;
}
/*
==============
LeafThread
==============
*/
#ifdef __alpha
pthread_addr_t LeafThread (pthread_addr_t thread)
#else
void *LeafThread (int thread)
#endif
{
portal_t *p;
//printf ("Begining LeafThread: %i\n",(int)thread);
do
{
p = GetNextPortal ();
if (!p)
break;
PortalFlow (p);
if (verbose)
printf ("portal:%4i mightsee:%4i cansee:%4i\n", (int)(p - portals), p->nummightsee, p->numcansee);
} while (1);
//printf ("Completed LeafThread: %i\n",(int)thread);
return NULL;
}
/*
===============
CompressRow
===============
*/
int CompressRow (byte *vis, byte *dest)
{
int j;
int rep;
int visrow;
byte *dest_p;
dest_p = dest;
visrow = (portalleafs + 7)>>3;
for (j=0 ; j<visrow ; j++)
{
*dest_p++ = vis[j];
if (vis[j])
continue;
rep = 1;
for ( j++; j<visrow ; j++)
if (vis[j] || rep == 255)
break;
else
rep++;
*dest_p++ = rep;
j--;
}
return dest_p - dest;
}
/*
===============
LeafFlow
Builds the entire visibility list for a leaf
===============
*/
int totalvis;
void LeafFlow (int leafnum)
{
leaf_t *leaf;
byte *outbuffer;
byte compressed[MAX_MAP_LEAFS/8];
int i, j;
int numvis;
byte *dest;
portal_t *p;
//
// flow through all portals, collecting visible bits
//
outbuffer = uncompressed + leafnum*bitbytes;
leaf = &leafs[leafnum];
for (i=0 ; i<leaf->numportals ; i++)
{
p = leaf->portals[i];
if (p->status != stat_done)
Error ("portal not done");
for (j=0 ; j<bitbytes ; j++)
outbuffer[j] |= p->visbits[j];
}
if (outbuffer[leafnum>>3] & (1<<(leafnum&7)))
Error ("Leaf portals saw into leaf");
outbuffer[leafnum>>3] |= (1<<(leafnum&7));
numvis = 0;
for (i=0 ; i<portalleafs ; i++)
if (outbuffer[i>>3] & (1<<(i&3)))
numvis++;
//
// compress the bit string
//
if (verbose)
printf ("leaf %4i : %4i visible\n", leafnum, numvis);
totalvis += numvis;
#if 0
i = (portalleafs+7)>>3;
memcpy (compressed, outbuffer, i);
#else
i = CompressRow (outbuffer, compressed);
#endif
dest = vismap_p;
vismap_p += i;
if (vismap_p > vismap_end)
Error ("Vismap expansion overflow");
dleafs[leafnum+1].visofs = dest-vismap; // leaf 0 is a common solid
memcpy (dest, compressed, i);
}
/*
==================
CalcPortalVis
==================
*/
void CalcPortalVis (void)
{
int i;
// fastvis just uses mightsee for a very loose bound
if (fastvis)
{
for (i=0 ; i<numportals*2 ; i++)
{
portals[i].visbits = portals[i].mightsee;
portals[i].status = stat_done;
}
return;
}
leafon = 0;
#ifdef __alpha
{
pthread_t work_threads[MAX_THREADS];
pthread_addr_t status;
pthread_attr_t attrib;
pthread_mutexattr_t mattrib;
int i;
my_mutex = malloc (sizeof(*my_mutex));
if (pthread_mutexattr_create (&mattrib) == -1)
Error ("pthread_mutex_attr_create failed");
if (pthread_mutexattr_setkind_np (&mattrib, MUTEX_FAST_NP) == -1)
Error ("pthread_mutexattr_setkind_np failed");
if (pthread_mutex_init (my_mutex, mattrib) == -1)
Error ("pthread_mutex_init failed");
if (pthread_attr_create (&attrib) == -1)
Error ("pthread_attr_create failed");
if (pthread_attr_setstacksize (&attrib, 0x100000) == -1)
Error ("pthread_attr_setstacksize failed");
for (i=0 ; i<numthreads ; i++)
{
if (pthread_create(&work_threads[i], attrib
, LeafThread, (pthread_addr_t)i) == -1)
Error ("pthread_create failed");
}
for (i=0 ; i<numthreads ; i++)
{
if (pthread_join (work_threads[i], &status) == -1)
Error ("pthread_join failed");
}
if (pthread_mutex_destroy (my_mutex) == -1)
Error ("pthread_mutex_destroy failed");
}
#else
LeafThread (0);
#endif
if (verbose)
{
printf ("portalcheck: %i portaltest: %i portalpass: %i\n",c_portalcheck, c_portaltest, c_portalpass);
printf ("c_vistest: %i c_mighttest: %i\n",c_vistest, c_mighttest);
}
}
/*
==================
CalcVis
==================
*/
void CalcVis (void)
{
int i;
BasePortalVis ();
CalcPortalVis ();
//
// assemble the leaf vis lists by oring and compressing the portal lists
//
for (i=0 ; i<portalleafs ; i++)
LeafFlow (i);
printf ("average leafs visible: %i\n", totalvis / portalleafs);
}
/*
==============================================================================
PASSAGE CALCULATION (not used yet...)
==============================================================================
*/
int count_sep;
qboolean PlaneCompare (plane_t *p1, plane_t *p2)
{
int i;
if ( fabs(p1->dist - p2->dist) > 0.01)
return false;
for (i=0 ; i<3 ; i++)
if ( fabs(p1->normal[i] - p2->normal[i] ) > 0.001)
return false;
return true;
}
sep_t *Findpassages (winding_t *source, winding_t *pass)
{
int i, j, k, l;
plane_t plane;
vec3_t v1, v2;
float d;
double length;
int counts[3];
qboolean fliptest;
sep_t *sep, *list;
list = NULL;
// check all combinations
for (i=0 ; i<source->numpoints ; i++)
{
l = (i+1)%source->numpoints;
VectorSubtract (source->points[l] , source->points[i], v1);
// fing a vertex of pass that makes a plane that puts all of the
// vertexes of pass on the front side and all of the vertexes of
// source on the back side
for (j=0 ; j<pass->numpoints ; j++)
{
VectorSubtract (pass->points[j], source->points[i], v2);
plane.normal[0] = v1[1]*v2[2] - v1[2]*v2[1];
plane.normal[1] = v1[2]*v2[0] - v1[0]*v2[2];
plane.normal[2] = v1[0]*v2[1] - v1[1]*v2[0];
// if points don't make a valid plane, skip it
length = plane.normal[0] * plane.normal[0]
+ plane.normal[1] * plane.normal[1]
+ plane.normal[2] * plane.normal[2];
if (length < ON_EPSILON)
continue;
length = 1/sqrt(length);
plane.normal[0] *= length;
plane.normal[1] *= length;
plane.normal[2] *= length;
plane.dist = DotProduct (pass->points[j], plane.normal);
//
// find out which side of the generated seperating plane has the
// source portal
//
fliptest = false;
for (k=0 ; k<source->numpoints ; k++)
{
if (k == i || k == l)
continue;
d = DotProduct (source->points[k], plane.normal) - plane.dist;
if (d < -ON_EPSILON)
{ // source is on the negative side, so we want all
// pass and target on the positive side
fliptest = false;
break;
}
else if (d > ON_EPSILON)
{ // source is on the positive side, so we want all
// pass and target on the negative side
fliptest = true;
break;
}
}
if (k == source->numpoints)
continue; // planar with source portal
//
// flip the normal if the source portal is backwards
//
if (fliptest)
{
VectorSubtract (vec3_origin, plane.normal, plane.normal);
plane.dist = -plane.dist;
}
//
// if all of the pass portal points are now on the positive side,
// this is the seperating plane
//
counts[0] = counts[1] = counts[2] = 0;
for (k=0 ; k<pass->numpoints ; k++)
{
if (k==j)
continue;
d = DotProduct (pass->points[k], plane.normal) - plane.dist;
if (d < -ON_EPSILON)
break;
else if (d > ON_EPSILON)
counts[0]++;
else
counts[2]++;
}
if (k != pass->numpoints)
continue; // points on negative side, not a seperating plane
if (!counts[0])
continue; // planar with pass portal
//
// save this out
//
count_sep++;
sep = malloc(sizeof(*sep));
sep->next = list;
list = sep;
sep->plane = plane;
}
}
return list;
}
/*
============
CalcPassages
============
*/
void CalcPassages (void)
{
int i, j, k;
int count, count2;
leaf_t *l;
portal_t *p1, *p2;
sep_t *sep;
passage_t *passages;
printf ("building passages...\n");
count = count2 = 0;
for (i=0 ; i<portalleafs ; i++)
{
l = &leafs[i];
for (j=0 ; j<l->numportals ; j++)
{
p1 = l->portals[j];
for (k=0 ; k<l->numportals ; k++)
{
if (k==j)
continue;
count++;
p2 = l->portals[k];
// definately can't see into a coplanar portal
if (PlaneCompare (&p1->plane, &p2->plane) )
continue;
count2++;
sep = Findpassages (p1->winding, p2->winding);
if (!sep)
{
// Error ("No seperating planes found in portal pair");
count_sep++;
sep = malloc(sizeof(*sep));
sep->next = NULL;
sep->plane = p1->plane;
}
passages = malloc(sizeof(*passages));
passages->planes = sep;
passages->from = p1->leaf;
passages->to = p2->leaf;
passages->next = l->passages;
l->passages = passages;
}
}
}
printf ("numpassages: %i (%i)\n", count2, count);
printf ("total passages: %i\n", count_sep);
}
//=============================================================================
/*
============
LoadPortals
============
*/
void LoadPortals (char *name)
{
int i, j;
portal_t *p;
leaf_t *l;
char magic[80];
FILE *f;
int numpoints;
winding_t *w;
int leafnums[2];
plane_t plane;
if (!strcmp(name,"-"))
f = stdin;
else
{
f = fopen(name, "r");
if (!f)
{
printf ("LoadPortals: couldn't read %s\n",name);
printf ("No vising performed.\n");
exit (1);
}
}
if (fscanf (f,"%79s\n%i\n%i\n",magic, &portalleafs, &numportals) != 3)
Error ("LoadPortals: failed to read header");
if (strcmp(magic,PORTALFILE))
Error ("LoadPortals: not a portal file");
printf ("%4i portalleafs\n", portalleafs);
printf ("%4i numportals\n", numportals);
bitbytes = ((portalleafs+63)&~63)>>3;
bitlongs = bitbytes/sizeof(long);
// each file portal is split into two memory portals
portals = malloc(2*numportals*sizeof(portal_t));
memset (portals, 0, 2*numportals*sizeof(portal_t));
leafs = malloc(portalleafs*sizeof(leaf_t));
memset (leafs, 0, portalleafs*sizeof(leaf_t));
originalvismapsize = portalleafs*((portalleafs+7)/8);
vismap = vismap_p = dvisdata;
vismap_end = vismap + MAX_MAP_VISIBILITY;
for (i=0, p=portals ; i<numportals ; i++)
{
if (fscanf (f, "%i %i %i ", &numpoints, &leafnums[0], &leafnums[1])
!= 3)
Error ("LoadPortals: reading portal %i", i);
if (numpoints > MAX_POINTS_ON_WINDING)
Error ("LoadPortals: portal %i has too many points", i);
if ( (unsigned)leafnums[0] > portalleafs
|| (unsigned)leafnums[1] > portalleafs)
Error ("LoadPortals: reading portal %i", i);
w = p->winding = NewWinding (numpoints);
w->original = true;
w->numpoints = numpoints;
for (j=0 ; j<numpoints ; j++)
{
double v[3];
int k;
// scanf into double, then assign to vec_t
if (fscanf (f, "(%lf %lf %lf ) "
, &v[0], &v[1], &v[2]) != 3)
Error ("LoadPortals: reading portal %i", i);
for (k=0 ; k<3 ; k++)
w->points[j][k] = v[k];
}
fscanf (f, "\n");
// calc plane
PlaneFromWinding (w, &plane);
// create forward portal
l = &leafs[leafnums[0]];
if (l->numportals == MAX_PORTALS_ON_LEAF)
Error ("Leaf with too many portals");
l->portals[l->numportals] = p;
l->numportals++;
p->winding = w;
VectorSubtract (vec3_origin, plane.normal, p->plane.normal);
p->plane.dist = -plane.dist;
p->leaf = leafnums[1];
p++;
// create backwards portal
l = &leafs[leafnums[1]];
if (l->numportals == MAX_PORTALS_ON_LEAF)
Error ("Leaf with too many portals");
l->portals[l->numportals] = p;
l->numportals++;
p->winding = w;
p->plane = plane;
p->leaf = leafnums[0];
p++;
}
fclose (f);
}
/*
===========
main
===========
*/
int main (int argc, char **argv)
{
char portalfile[1024];
char source[1024];
int i;
double start, end;
printf ("---- vis ----\n");
for (i=1 ; i<argc ; i++)
{
if (!strcmp(argv[i],"-threads"))
{
numthreads = atoi (argv[i+1]);
i++;
}
else if (!strcmp(argv[i], "-fast"))
{
printf ("fastvis = true\n");
fastvis = true;
}
else if (!strcmp(argv[i], "-level"))
{
testlevel = atoi(argv[i+1]);
printf ("testlevel = %i\n", testlevel);
i++;
}
else if (!strcmp(argv[i], "-v"))
{
printf ("verbose = true\n");
verbose = true;
}
else if (argv[i][0] == '-')
Error ("Unknown option \"%s\"", argv[i]);
else
break;
}
if (i != argc - 1)
Error ("usage: vis [-threads #] [-level 0-4] [-fast] [-v] bspfile");
start = I_FloatTime ();
strcpy (source, argv[i]);
StripExtension (source);
DefaultExtension (source, ".bsp");
LoadBSPFile (source);
strcpy (portalfile, argv[i]);
StripExtension (portalfile);
strcat (portalfile, ".prt");
LoadPortals (portalfile);
uncompressed = malloc(bitbytes*portalleafs);
memset (uncompressed, 0, bitbytes*portalleafs);
// CalcPassages ();
CalcVis ();
printf ("c_chains: %i\n",c_chains);
visdatasize = vismap_p - dvisdata;
printf ("visdatasize:%i compressed from %i\n", visdatasize, originalvismapsize);
CalcAmbientSounds ();
WriteBSPFile (source);
// unlink (portalfile);
end = I_FloatTime ();
printf ("%5.1f seconds elapsed\n", end-start);
return 0;
}

125
qutils/VIS/VIS.H Normal file
View File

@@ -0,0 +1,125 @@
// vis.h
#include "cmdlib.h"
#include "mathlib.h"
#include "bspfile.h"
#define MAX_PORTALS 32768
#define PORTALFILE "PRT1"
#define ON_EPSILON 0.1
typedef struct
{
vec3_t normal;
float dist;
} plane_t;
typedef struct
{
qboolean original; // don't free, it's part of the portal
int numpoints;
vec3_t points[8]; // variable sized
} winding_t;
#define MAX_POINTS_ON_WINDING 64
winding_t *NewWinding (int points);
void FreeWinding (winding_t *w);
winding_t *ClipWinding (winding_t *in, plane_t *split, qboolean keepon);
winding_t *CopyWinding (winding_t *w);
typedef enum {stat_none, stat_working, stat_done} vstatus_t;
typedef struct
{
plane_t plane; // normal pointing into neighbor
int leaf; // neighbor
winding_t *winding;
vstatus_t status;
byte *visbits;
byte *mightsee;
int nummightsee;
int numcansee;
} portal_t;
typedef struct seperating_plane_s
{
struct seperating_plane_s *next;
plane_t plane; // from portal is on positive side
} sep_t;
typedef struct passage_s
{
struct passage_s *next;
int from, to; // leaf numbers
sep_t *planes;
} passage_t;
#define MAX_PORTALS_ON_LEAF 128
typedef struct leaf_s
{
int numportals;
passage_t *passages;
portal_t *portals[MAX_PORTALS_ON_LEAF];
} leaf_t;
typedef struct pstack_s
{
struct pstack_s *next;
leaf_t *leaf;
portal_t *portal; // portal exiting
winding_t *source, *pass;
plane_t portalplane;
byte *mightsee; // bit string
} pstack_t;
typedef struct
{
byte *leafvis; // bit string
portal_t *base;
pstack_t pstack_head;
} threaddata_t;
#ifdef __alpha
#include <pthread.h>
extern pthread_mutex_t *my_mutex;
#define LOCK pthread_mutex_lock (my_mutex)
#define UNLOCK pthread_mutex_unlock (my_mutex)
#else
#define LOCK
#define UNLOCK
#endif
extern int numportals;
extern int portalleafs;
extern portal_t *portals;
extern leaf_t *leafs;
extern int c_portaltest, c_portalpass, c_portalcheck;
extern int c_portalskip, c_leafskip;
extern int c_vistest, c_mighttest;
extern int c_chains;
extern byte *vismap, *vismap_p, *vismap_end; // past visfile
extern qboolean showgetleaf;
extern int testlevel;
extern byte *uncompressed;
extern int bitbytes;
extern int bitlongs;
void LeafFlow (int leafnum);
void BasePortalVis (void);
void PortalFlow (portal_t *p);
void CalcAmbientSounds (void);

288
qutils/VIS/VIS.MAK Normal file
View File

@@ -0,0 +1,288 @@
# Microsoft Developer Studio Generated NMAKE File, Format Version 4.00
# ** DO NOT EDIT **
# TARGTYPE "Win32 (x86) Console Application" 0x0103
!IF "$(CFG)" == ""
CFG=vis - Win32 Debug
!MESSAGE No configuration specified. Defaulting to vis - Win32 Debug.
!ENDIF
!IF "$(CFG)" != "vis - Win32 Release" && "$(CFG)" != "vis - Win32 Debug"
!MESSAGE Invalid configuration "$(CFG)" specified.
!MESSAGE You can specify a configuration when running NMAKE on this makefile
!MESSAGE by defining the macro CFG on the command line. For example:
!MESSAGE
!MESSAGE NMAKE /f "vis.mak" CFG="vis - Win32 Debug"
!MESSAGE
!MESSAGE Possible choices for configuration are:
!MESSAGE
!MESSAGE "vis - Win32 Release" (based on "Win32 (x86) Console Application")
!MESSAGE "vis - Win32 Debug" (based on "Win32 (x86) Console Application")
!MESSAGE
!ERROR An invalid configuration is specified.
!ENDIF
!IF "$(OS)" == "Windows_NT"
NULL=
!ELSE
NULL=nul
!ENDIF
################################################################################
# Begin Project
# PROP Target_Last_Scanned "vis - Win32 Debug"
CPP=cl.exe
RSC=rc.exe
!IF "$(CFG)" == "vis - Win32 Release"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 0
# PROP BASE Output_Dir "Release"
# PROP BASE Intermediate_Dir "Release"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 0
# PROP Output_Dir "Release"
# PROP Intermediate_Dir "Release"
# PROP Target_Dir ""
OUTDIR=.\Release
INTDIR=.\Release
ALL : "$(OUTDIR)\vis.exe"
CLEAN :
-@erase ".\Release\vis.exe"
-@erase ".\Release\soundpvs.obj"
-@erase ".\Release\vis.obj"
-@erase ".\Release\bspfile.obj"
-@erase ".\Release\flow.obj"
-@erase ".\Release\cmdlib.obj"
-@erase ".\Release\mathlib.obj"
"$(OUTDIR)" :
if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /YX /c
# ADD CPP /nologo /GX /O2 /I "..\common" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /YX /c
CPP_PROJ=/nologo /ML /GX /O2 /I "..\common" /D "WIN32" /D "NDEBUG" /D\
"_CONSOLE" /Fp"$(INTDIR)/vis.pch" /YX /Fo"$(INTDIR)/" /c
CPP_OBJS=.\Release/
CPP_SBRS=
# ADD BASE RSC /l 0x409 /d "NDEBUG"
# ADD RSC /l 0x409 /d "NDEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
BSC32_FLAGS=/nologo /o"$(OUTDIR)/vis.bsc"
BSC32_SBRS=
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib\
advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib\
odbccp32.lib /nologo /subsystem:console /incremental:no\
/pdb:"$(OUTDIR)/vis.pdb" /machine:I386 /out:"$(OUTDIR)/vis.exe"
LINK32_OBJS= \
"$(INTDIR)/soundpvs.obj" \
"$(INTDIR)/vis.obj" \
"$(INTDIR)/bspfile.obj" \
"$(INTDIR)/flow.obj" \
"$(INTDIR)/cmdlib.obj" \
"$(INTDIR)/mathlib.obj"
"$(OUTDIR)\vis.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
$(LINK32) @<<
$(LINK32_FLAGS) $(LINK32_OBJS)
<<
!ELSEIF "$(CFG)" == "vis - Win32 Debug"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 1
# PROP BASE Output_Dir "Debug"
# PROP BASE Intermediate_Dir "Debug"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 1
# PROP Output_Dir "Debug"
# PROP Intermediate_Dir "Debug"
# PROP Target_Dir ""
OUTDIR=.\Debug
INTDIR=.\Debug
ALL : "$(OUTDIR)\vis.exe"
CLEAN :
-@erase ".\Debug\vc40.pdb"
-@erase ".\Debug\vc40.idb"
-@erase ".\Debug\vis.exe"
-@erase ".\Debug\mathlib.obj"
-@erase ".\Debug\vis.obj"
-@erase ".\Debug\cmdlib.obj"
-@erase ".\Debug\flow.obj"
-@erase ".\Debug\bspfile.obj"
-@erase ".\Debug\soundpvs.obj"
-@erase ".\Debug\vis.ilk"
-@erase ".\Debug\vis.pdb"
"$(OUTDIR)" :
if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /YX /c
# ADD CPP /nologo /Gm /GX /Zi /Od /I "..\common" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /YX /c
CPP_PROJ=/nologo /MLd /Gm /GX /Zi /Od /I "..\common" /D "WIN32" /D "_DEBUG" /D\
"_CONSOLE" /Fp"$(INTDIR)/vis.pch" /YX /Fo"$(INTDIR)/" /Fd"$(INTDIR)/" /c
CPP_OBJS=.\Debug/
CPP_SBRS=
# ADD BASE RSC /l 0x409 /d "_DEBUG"
# ADD RSC /l 0x409 /d "_DEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
BSC32_FLAGS=/nologo /o"$(OUTDIR)/vis.bsc"
BSC32_SBRS=
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386
LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib\
advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib\
odbccp32.lib /nologo /subsystem:console /incremental:yes\
/pdb:"$(OUTDIR)/vis.pdb" /debug /machine:I386 /out:"$(OUTDIR)/vis.exe"
LINK32_OBJS= \
"$(INTDIR)/mathlib.obj" \
"$(INTDIR)/vis.obj" \
"$(INTDIR)/cmdlib.obj" \
"$(INTDIR)/flow.obj" \
"$(INTDIR)/bspfile.obj" \
"$(INTDIR)/soundpvs.obj"
"$(OUTDIR)\vis.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
$(LINK32) @<<
$(LINK32_FLAGS) $(LINK32_OBJS)
<<
!ENDIF
.c{$(CPP_OBJS)}.obj:
$(CPP) $(CPP_PROJ) $<
.cpp{$(CPP_OBJS)}.obj:
$(CPP) $(CPP_PROJ) $<
.cxx{$(CPP_OBJS)}.obj:
$(CPP) $(CPP_PROJ) $<
.c{$(CPP_SBRS)}.sbr:
$(CPP) $(CPP_PROJ) $<
.cpp{$(CPP_SBRS)}.sbr:
$(CPP) $(CPP_PROJ) $<
.cxx{$(CPP_SBRS)}.sbr:
$(CPP) $(CPP_PROJ) $<
################################################################################
# Begin Target
# Name "vis - Win32 Release"
# Name "vis - Win32 Debug"
!IF "$(CFG)" == "vis - Win32 Release"
!ELSEIF "$(CFG)" == "vis - Win32 Debug"
!ENDIF
################################################################################
# Begin Source File
SOURCE=.\vis.c
DEP_CPP_VIS_C=\
".\vis.h"\
".\..\common\cmdlib.h"\
".\..\common\mathlib.h"\
".\..\common\bspfile.h"\
"$(INTDIR)\vis.obj" : $(SOURCE) $(DEP_CPP_VIS_C) "$(INTDIR)"
# End Source File
################################################################################
# Begin Source File
SOURCE=.\soundpvs.c
DEP_CPP_SOUND=\
".\vis.h"\
".\..\common\cmdlib.h"\
".\..\common\mathlib.h"\
".\..\common\bspfile.h"\
"$(INTDIR)\soundpvs.obj" : $(SOURCE) $(DEP_CPP_SOUND) "$(INTDIR)"
# End Source File
################################################################################
# Begin Source File
SOURCE=.\flow.c
DEP_CPP_FLOW_=\
".\vis.h"\
".\..\common\cmdlib.h"\
".\..\common\mathlib.h"\
".\..\common\bspfile.h"\
"$(INTDIR)\flow.obj" : $(SOURCE) $(DEP_CPP_FLOW_) "$(INTDIR)"
# End Source File
################################################################################
# Begin Source File
SOURCE=\quake\utils2\common\cmdlib.c
DEP_CPP_CMDLI=\
".\..\common\cmdlib.h"\
{$(INCLUDE)}"\sys\TYPES.H"\
{$(INCLUDE)}"\sys\STAT.H"\
"$(INTDIR)\cmdlib.obj" : $(SOURCE) $(DEP_CPP_CMDLI) "$(INTDIR)"
$(CPP) $(CPP_PROJ) $(SOURCE)
# End Source File
################################################################################
# Begin Source File
SOURCE=\quake\utils2\common\bspfile.c
DEP_CPP_BSPFI=\
".\..\common\cmdlib.h"\
".\..\common\mathlib.h"\
".\..\common\bspfile.h"\
"$(INTDIR)\bspfile.obj" : $(SOURCE) $(DEP_CPP_BSPFI) "$(INTDIR)"
$(CPP) $(CPP_PROJ) $(SOURCE)
# End Source File
################################################################################
# Begin Source File
SOURCE=\quake\utils2\common\mathlib.c
DEP_CPP_MATHL=\
".\..\common\cmdlib.h"\
".\..\common\mathlib.h"\
"$(INTDIR)\mathlib.obj" : $(SOURCE) $(DEP_CPP_MATHL) "$(INTDIR)"
$(CPP) $(CPP_PROJ) $(SOURCE)
# End Source File
# End Target
# End Project
################################################################################

BIN
qutils/VIS/VIS.MDP Normal file

Binary file not shown.

BIN
qutils/VIS/VIS.NCB Normal file

Binary file not shown.