winding.cpp
来自「quake3工具源码。包括生成bsp文件」· C++ 代码 · 共 797 行 · 第 1/2 页
CPP
797 行
#include "stdafx.h"
#include <assert.h>
#include "qe3.h"
#include "winding.h"
#define BOGUS_RANGE 18000
/*
=============
Plane_Equal
=============
*/
#define NORMAL_EPSILON 0.0001
#define DIST_EPSILON 0.02
int Plane_Equal(plane_t *a, plane_t *b, int flip)
{
vec3_t normal;
float dist;
if (flip) {
normal[0] = - b->normal[0];
normal[1] = - b->normal[1];
normal[2] = - b->normal[2];
dist = - b->dist;
}
else {
normal[0] = b->normal[0];
normal[1] = b->normal[1];
normal[2] = b->normal[2];
dist = b->dist;
}
if (
fabs(a->normal[0] - normal[0]) < NORMAL_EPSILON
&& fabs(a->normal[1] - normal[1]) < NORMAL_EPSILON
&& fabs(a->normal[2] - normal[2]) < NORMAL_EPSILON
&& fabs(a->dist - dist) < DIST_EPSILON )
return true;
return false;
}
/*
============
Plane_FromPoints
============
*/
int Plane_FromPoints(vec3_t p1, vec3_t p2, vec3_t p3, plane_t *plane)
{
vec3_t v1, v2;
VectorSubtract(p2, p1, v1);
VectorSubtract(p3, p1, v2);
//CrossProduct(v2, v1, plane->normal);
CrossProduct(v1, v2, plane->normal);
if (VectorNormalize(plane->normal) < 0.1) return false;
plane->dist = DotProduct(p1, plane->normal);
return true;
}
/*
=================
Point_Equal
=================
*/
int Point_Equal(vec3_t p1, vec3_t p2, float epsilon)
{
int i;
for (i = 0; i < 3; i++)
{
if (fabs(p1[i] - p2[i]) > epsilon) return false;
}
return true;
}
/*
=================
Winding_BaseForPlane
=================
*/
winding_t *Winding_BaseForPlane (plane_t *p)
{
int i, x;
vec_t max, v;
vec3_t org, vright, vup;
winding_t *w;
// find the major axis
max = -BOGUS_RANGE;
x = -1;
for (i=0 ; i<3; i++)
{
v = fabs(p->normal[i]);
if (v > max)
{
x = i;
max = v;
}
}
if (x==-1)
Error ("Winding_BaseForPlane: no axis found");
VectorCopy (vec3_origin, vup);
switch (x)
{
case 0:
case 1:
vup[2] = 1;
break;
case 2:
vup[0] = 1;
break;
}
v = DotProduct (vup, p->normal);
VectorMA (vup, -v, p->normal, vup);
VectorNormalize (vup);
VectorScale (p->normal, p->dist, org);
CrossProduct (vup, p->normal, vright);
VectorScale (vup, BOGUS_RANGE, vup);
VectorScale (vright, BOGUS_RANGE, vright);
// project a really big axis aligned box onto the plane
w = Winding_Alloc (4);
VectorSubtract (org, vright, w->points[0]);
VectorAdd (w->points[0], vup, w->points[0]);
VectorAdd (org, vright, w->points[1]);
VectorAdd (w->points[1], vup, w->points[1]);
VectorAdd (org, vright, w->points[2]);
VectorSubtract (w->points[2], vup, w->points[2]);
VectorSubtract (org, vright, w->points[3]);
VectorSubtract (w->points[3], vup, w->points[3]);
w->numpoints = 4;
return w;
}
/*
==================
Winding_Alloc
==================
*/
winding_t *Winding_Alloc (int points)
{
winding_t *w;
int size;
if (points > MAX_POINTS_ON_WINDING)
Error ("Winding_Alloc: %i points", points);
size = (int)((winding_t *)0)->points[points];
w = (winding_t*) malloc (size);
memset (w, 0, size);
w->maxpoints = points;
return w;
}
void Winding_Free (winding_t *w)
{
free(w);
}
/*
==================
Winding_Clone
==================
*/
winding_t *Winding_Clone(winding_t *w)
{
int size;
winding_t *c;
size = (int)((winding_t *)0)->points[w->numpoints];
c = (winding_t*)qmalloc (size);
memcpy (c, w, size);
return c;
}
/*
==================
ReverseWinding
==================
*/
winding_t *Winding_Reverse(winding_t *w)
{
int i;
winding_t *c;
c = Winding_Alloc(w->numpoints);
for (i = 0; i < w->numpoints; i++)
{
VectorCopy (w->points[w->numpoints-1-i], c->points[i]);
}
c->numpoints = w->numpoints;
return c;
}
/*
==============
Winding_RemovePoint
==============
*/
void Winding_RemovePoint(winding_t *w, int point)
{
if (point < 0 || point >= w->numpoints)
Error("Winding_RemovePoint: point out of range");
if (point < w->numpoints-1)
{
memmove(&w->points[point], &w->points[point+1], (int)((winding_t *)0)->points[w->numpoints - point - 1]);
}
w->numpoints--;
}
/*
=============
Winding_InsertPoint
=============
*/
winding_t *Winding_InsertPoint(winding_t *w, vec3_t point, int spot)
{
int i, j;
winding_t *neww;
if (spot > w->numpoints)
{
Error("Winding_InsertPoint: spot > w->numpoints");
} //end if
if (spot < 0)
{
Error("Winding_InsertPoint: spot < 0");
} //end if
neww = Winding_Alloc(w->numpoints + 1);
neww->numpoints = w->numpoints + 1;
for (i = 0, j = 0; i < neww->numpoints; i++)
{
if (i == spot)
{
VectorCopy(point, neww->points[i]);
}
else
{
VectorCopy(w->points[j], neww->points[i]);
j++;
}
}
return neww;
}
/*
==============
Winding_IsTiny
==============
*/
#define EDGE_LENGTH 0.2
int Winding_IsTiny (winding_t *w)
{
int i, j;
vec_t len;
vec3_t delta;
int edges;
edges = 0;
for (i=0 ; i<w->numpoints ; i++)
{
j = i == w->numpoints - 1 ? 0 : i+1;
VectorSubtract (w->points[j], w->points[i], delta);
len = VectorLength (delta);
if (len > EDGE_LENGTH)
{
if (++edges == 3)
return false;
}
}
return true;
}
/*
==============
Winding_IsHuge
==============
*/
int Winding_IsHuge(winding_t *w)
{
int i, j;
for (i=0 ; i<w->numpoints ; i++)
{
for (j=0 ; j<3 ; j++)
if (w->points[i][j] < -BOGUS_RANGE+1 || w->points[i][j] > BOGUS_RANGE-1)
return true;
}
return false;
}
/*
=============
Winding_PlanesConcave
=============
*/
#define WCONVEX_EPSILON 0.2
int Winding_PlanesConcave(winding_t *w1, winding_t *w2,
vec3_t normal1, vec3_t normal2,
float dist1, float dist2)
{
int i;
if (!w1 || !w2) return false;
// check if one of the points of winding 1 is at the back of the plane of winding 2
for (i = 0; i < w1->numpoints; i++)
{
if (DotProduct(normal2, w1->points[i]) - dist2 > WCONVEX_EPSILON) return true;
}
// check if one of the points of winding 2 is at the back of the plane of winding 1
for (i = 0; i < w2->numpoints; i++)
{
if (DotProduct(normal1, w2->points[i]) - dist1 > WCONVEX_EPSILON) return true;
}
return false;
}
/*
==================
Winding_Clip
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 *Winding_Clip (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])
{
Winding_Free (in);
return NULL;
}
if (!counts[1])
return in;
maxpts = in->numpoints+4; // can't use counts[0]+2 because
// of fp grouping errors
neww = Winding_Alloc (maxpts);
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?