rewrite q3map2 math in c++

This commit is contained in:
Garux
2021-02-25 19:41:43 +03:00
parent 820dd5e21f
commit 4ce944444d
55 changed files with 3630 additions and 4643 deletions
-1
View File
@@ -540,7 +540,6 @@ $(INSTALLDIR)/q3map2.$(EXE): \
tools/quake3/common/miniz.o \
tools/quake3/q3map2/autopk3.o \
tools/quake3/q3map2/brush.o \
tools/quake3/q3map2/brush_primit.o \
tools/quake3/q3map2/bspfile_abstract.o \
tools/quake3/q3map2/bspfile_ibsp.o \
tools/quake3/q3map2/bspfile_rbsp.o \
+2 -1
View File
@@ -26,7 +26,8 @@
template<typename Element> class BasicVector3;
typedef BasicVector3<float> Vector3;
class Plane3;
template<typename T> class Plane3___;
typedef Plane3___<double> Plane3;
class Matrix4;
class AABB;
class Segment;
+2 -1
View File
@@ -281,7 +281,8 @@ inline SelectionTestable* Instance_getSelectionTestable( scene::Instance& instan
}
class Plane3;
template<typename T> class Plane3___;
typedef Plane3___<double> Plane3;
typedef Callback1<const Plane3&> PlaneCallback;
class SelectedPlanes
+22
View File
@@ -103,6 +103,11 @@ Element* data(){
const Element* data() const {
return m_elements;
}
BasicVector3& set( const Element value ){
x() = y() = z() = value;
return *this;
}
};
/// \brief A 4-element vector.
@@ -171,8 +176,25 @@ Element* data(){
const Element* data() const {
return m_elements;
}
BasicVector3<Element>& vec3(){
return reinterpret_cast<BasicVector3<Element>&>( x() );
}
const BasicVector3<Element>& vec3() const {
return reinterpret_cast<const BasicVector3<Element>&>( x() );
}
BasicVector4& set( const Element value ){
x() = y() = z() = w() = value;
return *this;
}
};
template<typename Element>
inline BasicVector2<Element> vector2_from_array( const Element* array ){
return BasicVector2<Element>( array[0], array[1] );
}
template<typename Element>
inline BasicVector3<Element> vector3_from_array( const Element* array ){
return BasicVector3<Element>( array[0], array[1], array[2] );
+25 -19
View File
@@ -27,36 +27,41 @@
#include "math/matrix.h"
/// \brief A plane equation stored in double-precision floating-point.
class Plane3
template<typename T>
class Plane3___
{
public:
double a, b, c, d;
T a, b, c, d;
Plane3(){
Plane3___(){
}
Plane3( double _a, double _b, double _c, double _d )
Plane3___( double _a, double _b, double _c, double _d )
: a( _a ), b( _b ), c( _c ), d( _d ){
}
template<typename Element>
Plane3( const BasicVector3<Element>& normal, double dist )
Plane3___( const BasicVector3<Element>& normal, double dist )
: a( normal.x() ), b( normal.y() ), c( normal.z() ), d( dist ){
}
BasicVector3<double>& normal(){
return reinterpret_cast<BasicVector3<double>&>( *this );
BasicVector3<T>& normal(){
return reinterpret_cast<BasicVector3<T>&>( *this );
}
const BasicVector3<double>& normal() const {
return reinterpret_cast<const BasicVector3<double>&>( *this );
const BasicVector3<T>& normal() const {
return reinterpret_cast<const BasicVector3<T>&>( *this );
}
double& dist(){
T& dist(){
return d;
}
const double& dist() const {
const T& dist() const {
return d;
}
};
/// \brief A plane equation stored in double-precision floating-point.
using Plane3 = Plane3___<double>;
/// \brief A plane equation stored in single-precision floating-point.
using Plane3f = Plane3___<float>;
inline Plane3 plane3_normalised( const Plane3& plane ){
double rmagnitude = 1.0 / sqrt( plane.a * plane.a + plane.b * plane.b + plane.c * plane.c );
return Plane3(
@@ -105,8 +110,9 @@ inline Plane3 plane3_transformed_affine_full( const Plane3& plane, const Matrix4
return Plane3( normal, vector3_dot( normal, anchor ) );
}
inline Plane3 plane3_flipped( const Plane3& plane ){
return Plane3( vector3_negated( plane.normal() ), -plane.dist() );
template<typename T>
inline Plane3___<T> plane3_flipped( const Plane3___<T>& plane ){
return Plane3___<T>( vector3_negated( plane.normal() ), -plane.dist() );
}
const double c_PLANE_NORMAL_EPSILON = 0.0001f;
@@ -148,8 +154,8 @@ inline Plane3 plane3_for_points( const BasicVector3<Element> planepts[3] ){
return plane3_for_points( planepts[0], planepts[1], planepts[2] );
}
template<typename T>
inline double plane3_distance_to_point( const Plane3& plane, const BasicVector3<T>& point ){
template<typename P, typename V>
inline double plane3_distance_to_point( const Plane3___<P>& plane, const BasicVector3<V>& point ){
return vector3_dot( point, plane.normal() ) - plane.dist();
}
@@ -160,9 +166,9 @@ inline BasicVector3<T> plane3_project_point( const Plane3& plane, const BasicVec
return point + direction * d;
}
template<typename T>
inline BasicVector3<T> plane3_project_point( const Plane3& plane, const BasicVector3<T>& point ){
return ( point - plane.normal() * vector3_dot( point, plane.normal() ) + plane.normal() * plane.dist() );
template<typename P, typename V>
inline BasicVector3<V> plane3_project_point( const Plane3___<P>& plane, const BasicVector3<V>& point ){
return point - plane.normal() * plane3_distance_to_point( plane, point );
}
#endif
+10 -17
View File
@@ -289,19 +289,18 @@ inline void vector2_normalise( BasicVector2<Element>& self ){
self = vector2_normalised( self );
}
template<typename Element>
inline BasicVector2<Element> vector2_mid( const BasicVector2<Element>& begin, const BasicVector2<Element>& end ){
return vector2_scaled( vector2_added( begin, end ), 0.5 );
}
const Vector3 g_vector3_identity( 0, 0, 0 );
const Vector3 g_vector3_max = Vector3( FLT_MAX, FLT_MAX, FLT_MAX );
const Vector3 g_vector3_axis_x( 1, 0, 0 );
const Vector3 g_vector3_axis_y( 0, 1, 0 );
const Vector3 g_vector3_axis_z( 0, 0, 1 );
#ifdef __GNUC__
#define VARIABLE_IS_NOT_USED __attribute__ ((unused))
#else
#define VARIABLE_IS_NOT_USED
#endif
const Vector3 VARIABLE_IS_NOT_USED g_vector3_axes[3] = { g_vector3_axis_x, g_vector3_axis_y, g_vector3_axis_z };
const Vector3 g_vector3_axes[3] = { g_vector3_axis_x, g_vector3_axis_y, g_vector3_axis_z };
template<typename Element, typename OtherElement>
inline void vector3_swap( BasicVector3<Element>& self, BasicVector3<OtherElement>& other ){
@@ -560,20 +559,14 @@ inline Vector3 vector3_for_spherical( double theta, double phi ){
template<typename Element>
inline std::size_t vector3_max_abs_component_index( const BasicVector3<Element>& self ){
std::size_t maxi = 0;
for( std::size_t i = 1; i < 3; ++i )
if( fabs( self[i] ) > fabs( self[maxi] ) )
maxi = i;
return maxi;
const std::size_t maxi = ( fabs( self[1] ) > fabs( self[0] ) )? 1 : 0;
return ( fabs( self[2] ) > fabs( self[maxi] ) )? 2 : maxi;;
}
template<typename Element>
inline std::size_t vector3_min_abs_component_index( const BasicVector3<Element>& self ){
std::size_t mini = 0;
for( std::size_t i = 1; i < 3; ++i )
if( fabs( self[i] ) < fabs( self[mini] ) )
mini = i;
return mini;
const std::size_t mini = ( fabs( self[1] ) < fabs( self[0] ) )? 1 : 0;
return ( fabs( self[2] ) < fabs( self[mini] ) )? 2 : mini;
}
+2 -1
View File
@@ -90,7 +90,8 @@ float Texdef_getDefaultTextureScale();
class texdef_t;
struct Winding;
class Matrix4;
class Plane3;
template<typename T> class Plane3___;
typedef Plane3___<double> Plane3;
void Normal_GetTransform( const Vector3& normal, Matrix4& transform );
-1
View File
@@ -29,7 +29,6 @@
// replaced qprintf with Sys_Printf
#include "cmdlib.h"
#include "mathlib.h"
#include "inout.h"
#include <sys/types.h>
#include <sys/stat.h>
+4 -3
View File
@@ -30,6 +30,7 @@
#include "inout.h"
#include <sys/types.h>
#include <sys/stat.h>
#include "generic/vector.h"
#ifdef WIN32
#include <direct.h>
@@ -56,7 +57,7 @@ xmlDocPtr doc;
xmlNodePtr tree;
// some useful stuff
xmlNodePtr xml_NodeForVec( vec3_t v ){
xmlNodePtr xml_NodeForVec( const Vector3& v ){
xmlNodePtr ret;
char buf[1024];
@@ -166,7 +167,7 @@ void xml_Select( const char *msg, int entitynum, int brushnum, bool bError ){
}
}
void xml_Point( const char *msg, vec3_t pt ){
void xml_Point( const char *msg, const Vector3& pt ){
xmlNodePtr node, point;
char buf[1024];
char level[2];
@@ -188,7 +189,7 @@ void xml_Point( const char *msg, vec3_t pt ){
}
#define WINDING_BUFSIZE 2048
void xml_Winding( const char *msg, vec3_t p[], int numpoints, bool die ){
void xml_Winding( const char *msg, const Vector3 p[], int numpoints, bool die ){
xmlNodePtr node, winding;
char buf[WINDING_BUFSIZE];
char smlbuf[128];
+6 -4
View File
@@ -24,18 +24,20 @@
// inout is the only stuff relying on xml, include the headers there
#include "libxml/tree.h"
#include "mathlib.h"
template<typename Element> class BasicVector3;
typedef BasicVector3<float> Vector3;
// some useful xml routines
xmlNodePtr xml_NodeForVec( vec3_t v );
xmlNodePtr xml_NodeForVec( const Vector3& v );
void xml_SendNode( xmlNodePtr node );
// print a message in q3map output and send the corresponding select information down the xml stream
// bError: do we end with an error on this one or do we go ahead?
void xml_Select( const char *msg, int entitynum, int brushnum, bool bError );
// end q3map with an error message and send a point information in the xml stream
// note: we might want to add a boolean to use this as a warning or an error thing..
void xml_Winding( const char *msg, vec3_t p[], int numpoints, bool die );
void xml_Point( const char *msg, vec3_t pt );
void xml_Winding( const char *msg, const Vector3 p[], int numpoints, bool die );
void xml_Point( const char *msg, const Vector3& pt );
void Broadcast_Setup( const char *dest );
void Broadcast_Shutdown();
+5
View File
@@ -0,0 +1,5 @@
#pragma once
#define MIN_WORLD_COORD ( -65536 )
#define MAX_WORLD_COORD ( 65536 )
#define WORLD_SIZE ( MAX_WORLD_COORD - MIN_WORLD_COORD )
+183 -251
View File
@@ -23,11 +23,9 @@
#include <stddef.h>
#include "cmdlib.h"
#include "mathlib.h"
#include "inout.h"
#include "polylib.h"
#include "qfiles.h"
#include "maxworld.h"
#define BOGUS_RANGE WORLD_SIZE
@@ -105,21 +103,16 @@ void FreeWindingAccu( winding_accu_t *w ){
*/
void RemoveColinearPoints( winding_t *w ){
int i, j, k;
vec3_t v1, v2;
int nump;
vec3_t p[MAX_POINTS_ON_WINDING];
Vector3 p[MAX_POINTS_ON_WINDING];
nump = 0;
for ( i = 0 ; i < w->numpoints ; i++ )
{
j = ( i + 1 ) % w->numpoints;
k = ( i + w->numpoints - 1 ) % w->numpoints;
VectorSubtract( w->p[j], w->p[i], v1 );
VectorSubtract( w->p[i], w->p[k], v2 );
VectorNormalize( v1,v1 );
VectorNormalize( v2,v2 );
if ( DotProduct( v1, v2 ) < 0.999 ) {
VectorCopy( w->p[i], p[nump] );
if ( vector3_dot( VectorNormalized( w->p[j] - w->p[i] ), VectorNormalized( w->p[j] - w->p[k] ) ) < 0.999 ) {
p[nump] = w->p[i];
nump++;
}
}
@@ -137,15 +130,10 @@ void RemoveColinearPoints( winding_t *w ){
WindingPlane
============
*/
void WindingPlane( winding_t *w, vec3_t normal, vec_t *dist ){
vec3_t v1, v2;
VectorSubtract( w->p[1], w->p[0], v1 );
VectorSubtract( w->p[2], w->p[0], v2 );
CrossProduct( v2, v1, normal );
VectorNormalize( normal, normal );
*dist = DotProduct( w->p[0], normal );
Plane3f WindingPlane( const winding_t *w ){
Plane3f plane;
PlaneFromPoints( plane, w->p[0], w->p[1], w->p[2] );
return plane;
}
/*
@@ -153,42 +141,23 @@ void WindingPlane( winding_t *w, vec3_t normal, vec_t *dist ){
WindingArea
=============
*/
vec_t WindingArea( winding_t *w ){
int i;
vec3_t d1, d2, cross;
vec_t total;
float WindingArea( const winding_t *w ){
float total = 0;
total = 0;
for ( i = 2 ; i < w->numpoints ; i++ )
for ( int i = 2 ; i < w->numpoints ; i++ )
{
VectorSubtract( w->p[i - 1], w->p[0], d1 );
VectorSubtract( w->p[i], w->p[0], d2 );
CrossProduct( d1, d2, cross );
total += 0.5 * VectorLength( cross );
total += 0.5 * vector3_length( vector3_cross( w->p[i - 1] - w->p[0], w->p[i] - w->p[0] ) );
}
return total;
}
void WindingBounds( winding_t *w, vec3_t mins, vec3_t maxs ){
vec_t v;
int i,j;
mins[0] = mins[1] = mins[2] = 99999;
maxs[0] = maxs[1] = maxs[2] = -99999;
for ( i = 0 ; i < w->numpoints ; i++ )
MinMax WindingBounds( const winding_t *w ){
MinMax minmax;
for ( int i = 0 ; i < w->numpoints ; i++ )
{
for ( j = 0 ; j < 3 ; j++ )
{
v = w->p[i][j];
if ( v < mins[j] ) {
mins[j] = v;
}
if ( v > maxs[j] ) {
maxs[j] = v;
}
}
minmax.extend( w->p[i] );
}
return minmax;
}
/*
@@ -196,16 +165,13 @@ void WindingBounds( winding_t *w, vec3_t mins, vec3_t maxs ){
WindingCenter
=============
*/
void WindingCenter( winding_t *w, vec3_t center ){
int i;
float scale;
Vector3 WindingCenter( const winding_t *w ){
Vector3 center( 0, 0, 0 );
VectorCopy( vec3_origin, center );
for ( i = 0 ; i < w->numpoints ; i++ )
VectorAdd( w->p[i], center, center );
scale = 1.0 / w->numpoints;
VectorScale( center, scale, center );
for ( int i = 0 ; i < w->numpoints ; i++ )
center += w->p[i];
return center / w->numpoints;
}
/*
@@ -213,7 +179,7 @@ void WindingCenter( winding_t *w, vec3_t center ){
BaseWindingForPlaneAccu
=================
*/
winding_accu_t *BaseWindingForPlaneAccu( vec3_t normal, vec_t dist ){
winding_accu_t *BaseWindingForPlaneAccu( const Plane3f& inplane ){
// The goal in this function is to replicate the behavior of the original BaseWindingForPlane()
// function (see below) but at the same time increasing accuracy substantially.
@@ -228,8 +194,9 @@ winding_accu_t *BaseWindingForPlaneAccu( vec3_t normal, vec_t dist ){
// of 2) than the winding polygon in the original function.
int x, i;
vec_t max, v;
vec3_accu_t vright, vup, org, normalAccu;
float max, v;
DoubleVector3 vright, vup, org;
const Plane3 plane( inplane.normal(), inplane.dist() );
winding_accu_t *w;
// One of the components of normal must have a magnitiude greater than this value,
@@ -239,7 +206,7 @@ winding_accu_t *BaseWindingForPlaneAccu( vec3_t normal, vec_t dist ){
x = -1;
for ( i = 0; i < 3; i++ ) {
v = (vec_t) fabs( normal[i] );
v = fabs( plane.normal()[i] );
if ( v > max ) {
x = i;
max = v;
@@ -252,14 +219,14 @@ winding_accu_t *BaseWindingForPlaneAccu( vec3_t normal, vec_t dist ){
switch ( x ) {
case 0: // Fall through to next case.
case 1:
vright[0] = (vec_accu_t) -normal[1];
vright[1] = (vec_accu_t) normal[0];
vright[0] = -plane.normal()[1];
vright[1] = plane.normal()[0];
vright[2] = 0;
break;
case 2:
vright[0] = 0;
vright[1] = (vec_accu_t) -normal[2];
vright[2] = (vec_accu_t) normal[1];
vright[1] = -plane.normal()[2];
vright[2] = plane.normal()[1];
break;
}
@@ -276,19 +243,18 @@ winding_accu_t *BaseWindingForPlaneAccu( vec3_t normal, vec_t dist ){
// We're relying on the fact that MAX_WORLD_COORD is a power of 2 to keep
// our calculation precise and relatively free of floating point error.
// [However, the code will still work fine if that's not the case.]
VectorScaleAccu( vright, ( (vec_accu_t) MAX_WORLD_COORD ) * 4.0, vright );
vright *= ( (double) MAX_WORLD_COORD ) * 4.0;
// At time time of this writing, MAX_WORLD_COORD was 65536 (2^16). Therefore
// the length of vright at this point is at least 185364. In comparison, a
// corner of the world at location (65536, 65536, 65536) is distance 113512
// away from the origin.
VectorCopyRegularToAccu( normal, normalAccu );
CrossProductAccu( normalAccu, vright, vup );
vup = vector3_cross( plane.normal(), vright );
// vup now has length equal to that of vright.
VectorScaleAccu( normalAccu, (vec_accu_t) dist, org );
org = plane.normal() * plane.dist();
// org is now a point on the plane defined by normal and dist. Furthermore,
// org, vright, and vup are pairwise perpendicular. Now, the 4 vectors
@@ -304,17 +270,10 @@ winding_accu_t *BaseWindingForPlaneAccu( vec3_t normal, vec_t dist ){
w = AllocWindingAccu( 4 );
VectorSubtractAccu( org, vright, w->p[0] );
VectorAddAccu( w->p[0], vup, w->p[0] );
VectorAddAccu( org, vright, w->p[1] );
VectorAddAccu( w->p[1], vup, w->p[1] );
VectorAddAccu( org, vright, w->p[2] );
VectorSubtractAccu( w->p[2], vup, w->p[2] );
VectorSubtractAccu( org, vright, w->p[3] );
VectorSubtractAccu( w->p[3], vup, w->p[3] );
w->p[0] = org - vright + vup;
w->p[1] = org + vright + vup;
w->p[2] = org + vright - vup;
w->p[3] = org - vright - vup;
w->numpoints = 4;
@@ -336,10 +295,10 @@ winding_accu_t *BaseWindingForPlaneAccu( vec3_t normal, vec_t dist ){
error, and can lead to all sorts of disappearing triangle problems.
=================
*/
winding_t *BaseWindingForPlane( vec3_t normal, vec_t dist ){
winding_t *BaseWindingForPlane( const Plane3f& plane ){
int i, x;
vec_t max, v;
vec3_t org, vright, vup;
float max, v;
Vector3 org, vright, vup;
winding_t *w;
// find the major axis
@@ -348,7 +307,7 @@ winding_t *BaseWindingForPlane( vec3_t normal, vec_t dist ){
x = -1;
for ( i = 0 ; i < 3; i++ )
{
v = fabs( normal[i] );
v = fabs( plane.normal()[i] );
if ( v > max ) {
x = i;
max = v;
@@ -358,7 +317,7 @@ winding_t *BaseWindingForPlane( vec3_t normal, vec_t dist ){
Error( "BaseWindingForPlane: no axis found" );
}
VectorCopy( vec3_origin, vup );
vup.set( 0 );
switch ( x )
{
case 0:
@@ -370,34 +329,26 @@ winding_t *BaseWindingForPlane( vec3_t normal, vec_t dist ){
break;
}
v = DotProduct( vup, normal );
VectorMA( vup, -v, normal, vup );
VectorNormalize( vup, vup );
vup -= plane.normal() * vector3_dot( vup, plane.normal() );
VectorNormalize( vup );
VectorScale( normal, dist, org );
org = plane.normal() * plane.dist();
CrossProduct( vup, normal, vright );
vright = vector3_cross( vup, plane.normal() );
// LordHavoc: this has to use *2 because otherwise some created points may
// be inside the world (think of a diagonal case), and any brush with such
// points should be removed, failure to detect such cases is disasterous
VectorScale( vup, MAX_WORLD_COORD * 2, vup );
VectorScale( vright, MAX_WORLD_COORD * 2, vright );
vup *= MAX_WORLD_COORD * 2;
vright *= MAX_WORLD_COORD * 2;
// project a really big axis aligned box onto the plane
w = AllocWinding( 4 );
VectorSubtract( org, vright, w->p[0] );
VectorAdd( w->p[0], vup, w->p[0] );
VectorAdd( org, vright, w->p[1] );
VectorAdd( w->p[1], vup, w->p[1] );
VectorAdd( org, vright, w->p[2] );
VectorSubtract( w->p[2], vup, w->p[2] );
VectorSubtract( org, vright, w->p[3] );
VectorSubtract( w->p[3], vup, w->p[3] );
w->p[0] = org - vright + vup;
w->p[1] = org + vright + vup;
w->p[2] = org + vright - vup;
w->p[3] = org - vright - vup;
w->numpoints = 4;
@@ -448,7 +399,7 @@ winding_t *CopyWindingAccuToRegular( const winding_accu_t *w ){
c->numpoints = w->numpoints;
for ( i = 0; i < c->numpoints; i++ )
{
VectorCopyAccuToRegular( w->p[i], c->p[i] );
c->p[i] = w->p[i];
}
return c;
}
@@ -458,14 +409,14 @@ winding_t *CopyWindingAccuToRegular( const winding_accu_t *w ){
ReverseWinding
==================
*/
winding_t *ReverseWinding( winding_t *w ){
winding_t *ReverseWinding( const winding_t *w ){
int i;
winding_t *c;
c = AllocWinding( w->numpoints );
for ( i = 0 ; i < w->numpoints ; i++ )
{
VectorCopy( w->p[w->numpoints - 1 - i], c->p[i] );
c->p[i] = w->p[w->numpoints - 1 - i];
}
c->numpoints = w->numpoints;
return c;
@@ -477,15 +428,12 @@ winding_t *ReverseWinding( winding_t *w ){
ClipWindingEpsilon
=============
*/
void ClipWindingEpsilonStrict( winding_t *in, vec3_t normal, vec_t dist,
vec_t epsilon, winding_t **front, winding_t **back ){
vec_t dists[MAX_POINTS_ON_WINDING + 4];
int sides[MAX_POINTS_ON_WINDING + 4];
void ClipWindingEpsilonStrict( winding_t *in, const Plane3f& plane,
float epsilon, winding_t **front, winding_t **back ){
float dists[MAX_POINTS_ON_WINDING + 4];
EPlaneSide sides[MAX_POINTS_ON_WINDING + 4];
int counts[3];
static vec_t dot; // VC 4.2 optimizer bug if not static
int i, j;
vec_t *p1, *p2;
vec3_t mid;
winding_t *f, *b;
int maxpts;
@@ -495,18 +443,16 @@ void ClipWindingEpsilonStrict( winding_t *in, vec3_t normal, vec_t dist,
for ( i = 0 ; i < in->numpoints ; i++ )
{
dot = DotProduct( in->p[i], normal );
dot -= dist;
dists[i] = dot;
if ( dot > epsilon ) {
sides[i] = SIDE_FRONT;
dists[i] = plane3_distance_to_point( plane, in->p[i] );
if ( dists[i] > epsilon ) {
sides[i] = eSideFront;
}
else if ( dot < -epsilon ) {
sides[i] = SIDE_BACK;
else if ( dists[i] < -epsilon ) {
sides[i] = eSideBack;
}
else
{
sides[i] = SIDE_ON;
sides[i] = eSideOn;
}
counts[sides[i]]++;
}
@@ -535,49 +481,49 @@ void ClipWindingEpsilonStrict( winding_t *in, vec3_t normal, vec_t dist,
for ( i = 0 ; i < in->numpoints ; i++ )
{
p1 = in->p[i];
const Vector3& p1 = in->p[i];
if ( sides[i] == SIDE_ON ) {
VectorCopy( p1, f->p[f->numpoints] );
if ( sides[i] == eSideOn ) {
f->p[f->numpoints] = p1;
f->numpoints++;
VectorCopy( p1, b->p[b->numpoints] );
b->p[b->numpoints] = p1;
b->numpoints++;
continue;
}
if ( sides[i] == SIDE_FRONT ) {
VectorCopy( p1, f->p[f->numpoints] );
if ( sides[i] == eSideFront ) {
f->p[f->numpoints] = p1;
f->numpoints++;
}
if ( sides[i] == SIDE_BACK ) {
VectorCopy( p1, b->p[b->numpoints] );
if ( sides[i] == eSideBack ) {
b->p[b->numpoints] = p1;
b->numpoints++;
}
if ( sides[i + 1] == SIDE_ON || sides[i + 1] == sides[i] ) {
if ( sides[i + 1] == eSideOn || sides[i + 1] == sides[i] ) {
continue;
}
// generate a split point
p2 = in->p[( i + 1 ) % in->numpoints];
dot = dists[i] / ( dists[i] - dists[i + 1] );
const Vector3& p2 = in->p[( i + 1 ) % in->numpoints];
const double dot = dists[i] / ( dists[i] - dists[i + 1] );
Vector3 mid;
for ( j = 0 ; j < 3 ; j++ )
{ // avoid round off error when possible
if ( normal[j] == 1 ) {
mid[j] = dist;
if ( plane.normal()[j] == 1 ) {
mid[j] = plane.dist();
}
else if ( normal[j] == -1 ) {
mid[j] = -dist;
else if ( plane.normal()[j] == -1 ) {
mid[j] = -plane.dist();
}
else{
mid[j] = p1[j] + dot * ( p2[j] - p1[j] );
}
}
VectorCopy( mid, f->p[f->numpoints] );
f->p[f->numpoints] = mid;
f->numpoints++;
VectorCopy( mid, b->p[b->numpoints] );
b->p[b->numpoints] = mid;
b->numpoints++;
}
@@ -589,9 +535,9 @@ void ClipWindingEpsilonStrict( winding_t *in, vec3_t normal, vec_t dist,
}
}
void ClipWindingEpsilon( winding_t *in, vec3_t normal, vec_t dist,
vec_t epsilon, winding_t **front, winding_t **back ){
ClipWindingEpsilonStrict( in, normal, dist, epsilon, front, back );
void ClipWindingEpsilon( winding_t *in, const Plane3f& plane,
float epsilon, winding_t **front, winding_t **back ){
ClipWindingEpsilonStrict( in, plane, epsilon, front, back );
/* apparently most code expects that in the winding-on-plane case, the back winding is the original winding */
if ( !*front && !*back ) {
*back = CopyWinding( in );
@@ -599,22 +545,26 @@ void ClipWindingEpsilon( winding_t *in, vec3_t normal, vec_t dist,
}
// Smallest positive value for vec_t such that 1.0 + VEC_SMALLEST_EPSILON_AROUND_ONE != 1.0.
// In the case of 32 bit floats (which is almost certainly the case), it's 0.00000011921.
// Don't forget that your epsilons should depend on the possible range of values,
// because for example adding VEC_SMALLEST_EPSILON_AROUND_ONE to 1024.0 will have no effect.
#define VEC_SMALLEST_EPSILON_AROUND_ONE FLT_EPSILON
/*
=============
ChopWindingInPlaceAccu
=============
*/
void ChopWindingInPlaceAccu( winding_accu_t **inout, vec3_t normal, vec_t dist, vec_t crudeEpsilon ){
void ChopWindingInPlaceAccu( winding_accu_t **inout, const Plane3f& plane, float crudeEpsilon ){
winding_accu_t *in;
int counts[3];
int i, j;
vec_accu_t dists[MAX_POINTS_ON_WINDING + 1];
int sides[MAX_POINTS_ON_WINDING + 1];
double dists[MAX_POINTS_ON_WINDING + 1];
EPlaneSide sides[MAX_POINTS_ON_WINDING + 1];
int maxpts;
winding_accu_t *f;
vec_accu_t *p1, *p2;
vec_accu_t w;
vec3_accu_t mid, normalAccu;
double w;
// We require at least a very small epsilon. It's a good idea for several reasons.
// First, we will be dividing by a potentially very small distance below. We don't
@@ -634,12 +584,12 @@ void ChopWindingInPlaceAccu( winding_accu_t **inout, vec3_t normal, vec_t dist,
// So this minimum epsilon is quite similar to casting the higher resolution numbers to
// the lower resolution and comparing them in the lower resolution mode. We explicitly
// choose the minimum epsilon as something around the vec_t epsilon of one because we
// want the resolution of vec_accu_t to have a large resolution around the epsilon.
// want the resolution of double to have a large resolution around the epsilon.
// Some of that leftover resolution even goes away after we scale to points far away.
// Here is a further discussion regarding the choice of smallestEpsilonAllowed.
// In the 32 float world (we can assume vec_t is that), the "epsilon around 1.0" is
// 0.00000011921. In the 64 bit float world (we can assume vec_accu_t is that), the
// 0.00000011921. In the 64 bit float world (we can assume double is that), the
// "epsilon around 1.0" is 0.00000000000000022204. (By the way these two epsilons
// are defined as VEC_SMALLEST_EPSILON_AROUND_ONE VEC_ACCU_SMALLEST_EPSILON_AROUND_ONE
// respectively.) If you divide the first by the second, you get approximately
@@ -648,23 +598,24 @@ void ChopWindingInPlaceAccu( winding_accu_t **inout, vec3_t normal, vec_t dist,
// VEC_SMALLEST_EPSILON_AROUND_ONE, you would be guaranteed at least 2000 "ticks" in
// 64-bit land inside of the epsilon for all numbers we're dealing with.
static const vec_accu_t smallestEpsilonAllowed = ( (vec_accu_t) VEC_SMALLEST_EPSILON_AROUND_ONE ) * 0.5;
const vec_accu_t fineEpsilon = ( crudeEpsilon < smallestEpsilonAllowed )? smallestEpsilonAllowed : (vec_accu_t) crudeEpsilon;
static const double smallestEpsilonAllowed = ( (double) VEC_SMALLEST_EPSILON_AROUND_ONE ) * 0.5;
const double fineEpsilon = ( crudeEpsilon < smallestEpsilonAllowed )? smallestEpsilonAllowed : (double) crudeEpsilon;
in = *inout;
counts[0] = counts[1] = counts[2] = 0;
VectorCopyRegularToAccu( normal, normalAccu );
for ( i = 0; i < in->numpoints; i++ )
{
dists[i] = DotProductAccu( in->p[i], normalAccu ) - dist;
dists[i] = plane3_distance_to_point( plane, in->p[i] );
if ( dists[i] > fineEpsilon ) {
sides[i] = SIDE_FRONT;
sides[i] = eSideFront;
}
else if ( dists[i] < -fineEpsilon ) {
sides[i] = SIDE_BACK;
sides[i] = eSideBack;
}
else{
sides[i] = eSideOn;
}
else{sides[i] = SIDE_ON; }
counts[sides[i]]++;
}
sides[i] = sides[0];
@@ -673,26 +624,26 @@ void ChopWindingInPlaceAccu( winding_accu_t **inout, vec3_t normal, vec_t dist,
// I'm wondering if whatever code that handles duplicate planes is robust enough
// that we never get a case where two nearly equal planes result in 2 NULL windings
// due to the 'if' statement below. TODO: Investigate this.
if ( !counts[SIDE_FRONT] ) {
if ( !counts[eSideFront] ) {
FreeWindingAccu( in );
*inout = NULL;
return;
}
if ( !counts[SIDE_BACK] ) {
if ( !counts[eSideBack] ) {
return; // Winding is unmodified.
}
// NOTE: The least number of points that a winding can have at this point is 2.
// In that case, one point is SIDE_FRONT and the other is SIDE_BACK.
maxpts = counts[SIDE_FRONT] + 2; // We dynamically expand if this is too small.
maxpts = counts[eSideFront] + 2; // We dynamically expand if this is too small.
f = AllocWindingAccu( maxpts );
for ( i = 0; i < in->numpoints; i++ )
{
p1 = in->p[i];
const DoubleVector3& p1 = in->p[i];
if ( sides[i] == SIDE_ON || sides[i] == SIDE_FRONT ) {
if ( sides[i] == eSideOn || sides[i] == eSideFront ) {
if ( f->numpoints >= MAX_POINTS_ON_WINDING ) {
Error( "ChopWindingInPlaceAccu: MAX_POINTS_ON_WINDING" );
}
@@ -701,31 +652,31 @@ void ChopWindingInPlaceAccu( winding_accu_t **inout, vec3_t normal, vec_t dist,
f = CopyWindingAccuIncreaseSizeAndFreeOld( f );
maxpts++;
}
VectorCopyAccu( p1, f->p[f->numpoints] );
f->p[f->numpoints] = p1;
f->numpoints++;
if ( sides[i] == SIDE_ON ) {
if ( sides[i] == eSideOn ) {
continue;
}
}
if ( sides[i + 1] == SIDE_ON || sides[i + 1] == sides[i] ) {
if ( sides[i + 1] == eSideOn || sides[i + 1] == sides[i] ) {
continue;
}
// Generate a split point.
p2 = in->p[( ( i + 1 ) == in->numpoints ) ? 0 : ( i + 1 )];
const DoubleVector3& p2 = in->p[( ( i + 1 ) == in->numpoints ) ? 0 : ( i + 1 )];
// The divisor's absolute value is greater than the dividend's absolute value.
// w is in the range (0,1).
w = dists[i] / ( dists[i] - dists[i + 1] );
DoubleVector3 mid;
for ( j = 0; j < 3; j++ )
{
// Avoid round-off error when possible. Check axis-aligned normal.
if ( normal[j] == 1 ) {
mid[j] = dist;
if ( plane.normal()[j] == 1 ) {
mid[j] = plane.dist();
}
else if ( normal[j] == -1 ) {
mid[j] = -dist;
else if ( plane.normal()[j] == -1 ) {
mid[j] = -plane.dist();
}
else{mid[j] = p1[j] + ( w * ( p2[j] - p1[j] ) ); }
}
@@ -737,7 +688,7 @@ void ChopWindingInPlaceAccu( winding_accu_t **inout, vec3_t normal, vec_t dist,
f = CopyWindingAccuIncreaseSizeAndFreeOld( f );
maxpts++;
}
VectorCopyAccu( mid, f->p[f->numpoints] );
f->p[f->numpoints] = mid;
f->numpoints++;
}
@@ -750,15 +701,12 @@ void ChopWindingInPlaceAccu( winding_accu_t **inout, vec3_t normal, vec_t dist,
ChopWindingInPlace
=============
*/
void ChopWindingInPlace( winding_t **inout, vec3_t normal, vec_t dist, vec_t epsilon ){
void ChopWindingInPlace( winding_t **inout, const Plane3f& plane, float epsilon ){
winding_t *in;
vec_t dists[MAX_POINTS_ON_WINDING + 4];
int sides[MAX_POINTS_ON_WINDING + 4];
float dists[MAX_POINTS_ON_WINDING + 4];
EPlaneSide sides[MAX_POINTS_ON_WINDING + 4];
int counts[3];
static vec_t dot; // VC 4.2 optimizer bug if not static
int i, j;
vec_t *p1, *p2;
vec3_t mid;
winding_t *f;
int maxpts;
@@ -768,18 +716,16 @@ void ChopWindingInPlace( winding_t **inout, vec3_t normal, vec_t dist, vec_t eps
// determine sides for each point
for ( i = 0 ; i < in->numpoints ; i++ )
{
dot = DotProduct( in->p[i], normal );
dot -= dist;
dists[i] = dot;
if ( dot > epsilon ) {
sides[i] = SIDE_FRONT;
dists[i] = plane3_distance_to_point( plane, in->p[i] );
if ( dists[i] > epsilon ) {
sides[i] = eSideFront;
}
else if ( dot < -epsilon ) {
sides[i] = SIDE_BACK;
else if ( dists[i] < -epsilon ) {
sides[i] = eSideBack;
}
else
{
sides[i] = SIDE_ON;
sides[i] = eSideOn;
}
counts[sides[i]]++;
}
@@ -802,41 +748,42 @@ void ChopWindingInPlace( winding_t **inout, vec3_t normal, vec_t dist, vec_t eps
for ( i = 0 ; i < in->numpoints ; i++ )
{
p1 = in->p[i];
const Vector3& p1 = in->p[i];
if ( sides[i] == SIDE_ON ) {
VectorCopy( p1, f->p[f->numpoints] );
if ( sides[i] == eSideOn ) {
f->p[f->numpoints] = p1;
f->numpoints++;
continue;
}
if ( sides[i] == SIDE_FRONT ) {
VectorCopy( p1, f->p[f->numpoints] );
if ( sides[i] == eSideFront ) {
f->p[f->numpoints] = p1;
f->numpoints++;
}
if ( sides[i + 1] == SIDE_ON || sides[i + 1] == sides[i] ) {
if ( sides[i + 1] == eSideOn || sides[i + 1] == sides[i] ) {
continue;
}
// generate a split point
p2 = in->p[( i + 1 ) % in->numpoints];
const Vector3& p2 = in->p[( i + 1 ) % in->numpoints];
dot = dists[i] / ( dists[i] - dists[i + 1] );
const double dot = dists[i] / ( dists[i] - dists[i + 1] );
Vector3 mid;
for ( j = 0 ; j < 3 ; j++ )
{ // avoid round off error when possible
if ( normal[j] == 1 ) {
mid[j] = dist;
if ( plane.normal()[j] == 1 ) {
mid[j] = plane.dist();
}
else if ( normal[j] == -1 ) {
mid[j] = -dist;
else if ( plane.normal()[j] == -1 ) {
mid[j] = -plane.dist();
}
else{
mid[j] = p1[j] + dot * ( p2[j] - p1[j] );
}
}
VectorCopy( mid, f->p[f->numpoints] );
f->p[f->numpoints] = mid;
f->numpoints++;
}
@@ -860,10 +807,10 @@ void ChopWindingInPlace( winding_t **inout, vec3_t normal, vec_t dist, vec_t eps
of the cliping plane. The original is freed.
=================
*/
winding_t *ChopWinding( winding_t *in, vec3_t normal, vec_t dist ){
winding_t *ChopWinding( winding_t *in, const Plane3f& plane ){
winding_t *f, *b;
ClipWindingEpsilon( in, normal, dist, ON_EPSILON, &f, &b );
ClipWindingEpsilon( in, plane, ON_EPSILON, &f, &b );
FreeWinding( in );
if ( b ) {
FreeWinding( b );
@@ -880,11 +827,9 @@ winding_t *ChopWinding( winding_t *in, vec3_t normal, vec_t dist ){
*/
void CheckWinding( winding_t *w ){
int i, j;
vec_t *p1, *p2;
vec_t d, edgedist;
vec3_t dir, edgenormal, facenormal;
vec_t area;
vec_t facedist;
float d, edgedist;
Vector3 dir, edgenormal;
float area;
if ( w->numpoints < 3 ) {
Error( "CheckWinding: %i points",w->numpoints );
@@ -895,11 +840,11 @@ void CheckWinding( winding_t *w ){
Error( "CheckWinding: %f area", area );
}
WindingPlane( w, facenormal, &facedist );
const Plane3f faceplane = WindingPlane( w );
for ( i = 0 ; i < w->numpoints ; i++ )
{
p1 = w->p[i];
const Vector3& p1 = w->p[i];
for ( j = 0 ; j < 3 ; j++ )
if ( p1[j] > MAX_WORLD_COORD || p1[j] < MIN_WORLD_COORD ) {
@@ -909,23 +854,21 @@ void CheckWinding( winding_t *w ){
j = i + 1 == w->numpoints ? 0 : i + 1;
// check the point is on the face plane
d = DotProduct( p1, facenormal ) - facedist;
d = plane3_distance_to_point( faceplane, p1 );
if ( d < -ON_EPSILON || d > ON_EPSILON ) {
Error( "CheckWinding: point off plane" );
}
// check the edge isnt degenerate
p2 = w->p[j];
VectorSubtract( p2, p1, dir );
const Vector3& p2 = w->p[j];
dir = p2 - p1;
if ( VectorLength( dir ) < ON_EPSILON ) {
if ( vector3_length( dir ) < ON_EPSILON ) {
Error( "CheckWinding: degenerate edge" );
}
CrossProduct( facenormal, dir, edgenormal );
VectorNormalize( edgenormal, edgenormal );
edgedist = DotProduct( p1, edgenormal );
edgedist += ON_EPSILON;
edgenormal = VectorNormalized( vector3_cross( faceplane.normal(), dir ) );
edgedist = vector3_dot( p1, edgenormal ) + ON_EPSILON;
// all other points must be on front side
for ( j = 0 ; j < w->numpoints ; j++ )
@@ -933,7 +876,7 @@ void CheckWinding( winding_t *w ){
if ( j == i ) {
continue;
}
d = DotProduct( w->p[j], edgenormal );
d = vector3_dot( w->p[j], edgenormal );
if ( d > edgedist ) {
Error( "CheckWinding: non-convex" );
}
@@ -947,26 +890,22 @@ void CheckWinding( winding_t *w ){
WindingOnPlaneSide
============
*/
int WindingOnPlaneSide( winding_t *w, vec3_t normal, vec_t dist ){
bool front, back;
int i;
vec_t d;
front = false;
back = false;
for ( i = 0 ; i < w->numpoints ; i++ )
EPlaneSide WindingOnPlaneSide( const winding_t *w, const Plane3f& plane ){
bool front = false;
bool back = false;
for ( int i = 0 ; i < w->numpoints ; i++ )
{
d = DotProduct( w->p[i], normal ) - dist;
const double d = plane3_distance_to_point( plane, w->p[i] );
if ( d < -ON_EPSILON ) {
if ( front ) {
return SIDE_CROSS;
return eSideCross;
}
back = true;
continue;
}
if ( d > ON_EPSILON ) {
if ( back ) {
return SIDE_CROSS;
return eSideCross;
}
front = true;
continue;
@@ -974,12 +913,12 @@ int WindingOnPlaneSide( winding_t *w, vec3_t normal, vec_t dist ){
}
if ( back ) {
return SIDE_BACK;
return eSideBack;
}
if ( front ) {
return SIDE_FRONT;
return eSideFront;
}
return SIDE_ON;
return eSideOn;
}
@@ -991,42 +930,36 @@ int WindingOnPlaneSide( winding_t *w, vec3_t normal, vec_t dist ){
=================
*/
#define MAX_HULL_POINTS 128
void AddWindingToConvexHull( winding_t *w, winding_t **hull, vec3_t normal ) {
void AddWindingToConvexHull( winding_t *w, winding_t **hull, const Vector3& normal ) {
int i, j, k;
float *p, *copy;
vec3_t dir;
float d;
int numHullPoints, numNew;
vec3_t hullPoints[MAX_HULL_POINTS];
vec3_t newHullPoints[MAX_HULL_POINTS];
vec3_t hullDirs[MAX_HULL_POINTS];
Vector3 hullPoints[MAX_HULL_POINTS];
Vector3 newHullPoints[MAX_HULL_POINTS];
Vector3 hullDirs[MAX_HULL_POINTS];
bool hullSide[MAX_HULL_POINTS];
bool outside;
if ( !*hull ) {
if ( *hull == nullptr ) {
*hull = CopyWinding( w );
return;
}
numHullPoints = ( *hull )->numpoints;
memcpy( hullPoints, ( *hull )->p, numHullPoints * sizeof( vec3_t ) );
memcpy( hullPoints, ( *hull )->p, numHullPoints * sizeof( Vector3 ) );
for ( i = 0 ; i < w->numpoints ; i++ ) {
p = w->p[i];
const Vector3 &p = w->p[i];
// calculate hull side vectors
for ( j = 0 ; j < numHullPoints ; j++ ) {
k = ( j + 1 ) % numHullPoints;
VectorSubtract( hullPoints[k], hullPoints[j], dir );
VectorNormalize( dir, dir );
CrossProduct( normal, dir, hullDirs[j] );
hullDirs[j] = vector3_cross( normal, VectorNormalized( hullPoints[k] - hullPoints[j] ) );
}
outside = false;
for ( j = 0 ; j < numHullPoints ; j++ ) {
VectorSubtract( p, hullPoints[j], dir );
d = DotProduct( dir, hullDirs[j] );
const double d = vector3_dot( p - hullPoints[j], hullDirs[j] );
if ( d >= ON_EPSILON ) {
outside = true;
}
@@ -1049,7 +982,7 @@ void AddWindingToConvexHull( winding_t *w, winding_t **hull, vec3_t normal )
}
// insert the point here
VectorCopy( p, newHullPoints[0] );
newHullPoints[0] = p;
numNew = 1;
// copy over all points that aren't double fronts
@@ -1058,18 +991,17 @@ void AddWindingToConvexHull( winding_t *w, winding_t **hull, vec3_t normal )
if ( hullSide[ ( j + k ) % numHullPoints ] && hullSide[ ( j + k + 1 ) % numHullPoints ] ) {
continue;
}
copy = hullPoints[ ( j + k + 1 ) % numHullPoints ];
VectorCopy( copy, newHullPoints[numNew] );
newHullPoints[numNew] = hullPoints[ ( j + k + 1 ) % numHullPoints ];
numNew++;
}
numHullPoints = numNew;
memcpy( hullPoints, newHullPoints, numHullPoints * sizeof( vec3_t ) );
memcpy( hullPoints, newHullPoints, numHullPoints * sizeof( Vector3 ) );
}
FreeWinding( *hull );
w = AllocWinding( numHullPoints );
w->numpoints = numHullPoints;
*hull = w;
memcpy( w->p, hullPoints, numHullPoints * sizeof( vec3_t ) );
memcpy( w->p, hullPoints, numHullPoints * sizeof( Vector3 ) );
}
+29 -18
View File
@@ -19,11 +19,14 @@
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#pragma once
#include "qmath.h"
struct winding_t
{
int numpoints;
vec3_t p[];
Vector3 p[];
};
#define MAX_POINTS_ON_WINDING 512
@@ -33,27 +36,35 @@ struct winding_t
#define ON_EPSILON 0.1
#endif
enum EPlaneSide
{
eSideFront = 0, //! in front of plane ---->| *
eSideBack = 1, //! behind the plane -*-->|
eSideOn = 2,
eSideCross = 3,
};
winding_t *AllocWinding( int points );
vec_t WindingArea( winding_t *w );
void WindingCenter( winding_t *w, vec3_t center );
void ClipWindingEpsilon( winding_t *in, vec3_t normal, vec_t dist,
vec_t epsilon, winding_t **front, winding_t **back );
void ClipWindingEpsilonStrict( winding_t *in, vec3_t normal, vec_t dist,
vec_t epsilon, winding_t **front, winding_t **back );
winding_t *ChopWinding( winding_t *in, vec3_t normal, vec_t dist );
float WindingArea( const winding_t *w );
Vector3 WindingCenter( const winding_t *w );
void ClipWindingEpsilon( winding_t *in, const Plane3f& plane,
float epsilon, winding_t **front, winding_t **back );
void ClipWindingEpsilonStrict( winding_t *in, const Plane3f& plane,
float epsilon, winding_t **front, winding_t **back );
winding_t *ChopWinding( winding_t *in, const Plane3f& plane );
winding_t *CopyWinding( const winding_t *w );
winding_t *ReverseWinding( winding_t *w );
winding_t *BaseWindingForPlane( vec3_t normal, vec_t dist );
winding_t *ReverseWinding( const winding_t *w );
winding_t *BaseWindingForPlane( const Plane3f& plane );
void CheckWinding( winding_t *w );
void WindingPlane( winding_t *w, vec3_t normal, vec_t *dist );
Plane3f WindingPlane( const winding_t *w );
void RemoveColinearPoints( winding_t *w );
int WindingOnPlaneSide( winding_t *w, vec3_t normal, vec_t dist );
EPlaneSide WindingOnPlaneSide( const winding_t *w, const Plane3f& plane );
void FreeWinding( winding_t *w );
void WindingBounds( winding_t *w, vec3_t mins, vec3_t maxs );
MinMax WindingBounds( const winding_t *w );
void AddWindingToConvexHull( winding_t *w, winding_t **hull, vec3_t normal );
void AddWindingToConvexHull( winding_t *w, winding_t **hull, const Vector3& normal );
void ChopWindingInPlace( winding_t **w, vec3_t normal, vec_t dist, vec_t epsilon );
void ChopWindingInPlace( winding_t **w, const Plane3f& plane, float epsilon );
// frees the original if clipped
void pw( winding_t *w );
@@ -67,10 +78,10 @@ void pw( winding_t *w );
struct winding_accu_t
{
int numpoints;
vec3_accu_t p[];
DoubleVector3 p[];
};
winding_accu_t *BaseWindingForPlaneAccu( vec3_t normal, vec_t dist );
void ChopWindingInPlaceAccu( winding_accu_t **w, vec3_t normal, vec_t dist, vec_t epsilon );
winding_accu_t *BaseWindingForPlaneAccu( const Plane3f& plane );
void ChopWindingInPlaceAccu( winding_accu_t **w, const Plane3f& plane, float epsilon );
winding_t *CopyWindingAccuToRegular( const winding_accu_t *w );
void FreeWindingAccu( winding_accu_t *w );
+303
View File
@@ -0,0 +1,303 @@
#pragma once
#include "bytebool.h"
#include "math/vector.h"
#include "math/plane.h"
#define VectorSet( v, a, b, c ) ( ( v )[0] = ( a ),( v )[1] = ( b ),( v )[2] = ( c ) )
#define VectorCopy( a,b ) ( ( b )[0] = ( a )[0],( b )[1] = ( a )[1],( b )[2] = ( a )[2] )
#define RGBTOGRAY( x ) ( (float)( ( x )[0] ) * 0.2989f + (float)( ( x )[1] ) * 0.5870f + (float)( ( x )[2] ) * 0.1140f )
#define VectorFastNormalize VectorNormalize
template<typename T>
struct MinMax___
{
BasicVector3<T> mins;
BasicVector3<T> maxs;
MinMax___(){
clear();
}
template<typename U>
MinMax___( const BasicVector3<U>& min, const BasicVector3<U>& max ) : mins( min ), maxs( max ){
}
void clear(){
mins.x() = mins.y() = mins.z() = std::numeric_limits<T>::max();
maxs.x() = maxs.y() = maxs.z() = std::numeric_limits<T>::lowest();
}
template<typename U>
void extend( const BasicVector3<U>& point ){
for ( size_t i = 0; i < 3; ++i ){
const auto val = point[i];
if ( val < mins[i] ) {
mins[i] = val;
}
if ( val > maxs[i] ) {
maxs[i] = val;
}
}
}
template<typename U>
void extend( const MinMax___<U>& other ){
extend( other.mins );
extend( other.maxs );
}
template<typename U>
bool test( const BasicVector3<U>& point ) const {
return point.x() >= mins.x() && point.y() >= mins.y() && point.z() >= mins.z()
&& point.x() <= maxs.x() && point.y() <= maxs.y() && point.z() <= maxs.z();
}
// true, if there is an intersection
template<typename U>
bool test( const MinMax___<U>& other ) const {
return other.maxs.x() >= mins.x() && other.maxs.y() >= mins.y() && other.maxs.z() >= mins.z()
&& other.mins.x() <= maxs.x() && other.mins.y() <= maxs.y() && other.mins.z() <= maxs.z();
}
BasicVector3<T> origin() const {
return ( mins + maxs ) * 0.5;
}
};
using MinMax = MinMax___<float>;
template<typename T>
struct Color4___ : public BasicVector4<T>
{
using BasicVector4<T>::BasicVector4;
Color4___( const BasicVector4<T>& vector ) : BasicVector4<T>( vector ){
}
BasicVector3<T>& rgb(){
return this->vec3();
}
const BasicVector3<T>& rgb() const {
return this->vec3();
}
T& alpha(){
return this->w();
}
const T& alpha() const {
return this->w();
}
};
using Color4f = Color4___<float>;
using Color4b = Color4___<byte>;
template<typename T>
T VectorNormalize( BasicVector3<T>& vector ) {
const double length = vector3_length( DoubleVector3( vector ) );
if ( length == 0 ) {
vector.set( 0 );
return 0;
}
vector /= length;
return length;
}
template<typename T>
BasicVector3<T> VectorNormalized( const BasicVector3<T>& vector ) {
BasicVector3<T> vec( vector );
VectorNormalize( vec );
return vec;
}
const float EQUAL_EPSILON = 0.001;
inline bool VectorCompare( const Vector3& v1, const Vector3& v2 ){
return vector3_equal_epsilon( v1, v2, EQUAL_EPSILON );
}
template<typename T>
T VectorMax( const BasicVector3<T>& v ){
return ( v[0] > v[1] ) ? ( ( v[0] > v[2] ) ? v[0] : v[2] ) : ( ( v[1] > v[2] ) ? v[1] : v[2] );
}
inline bool VectorIsOnAxis( const Vector3& v ){
int zeroComponentCount = 0;
for ( int i = 0; i < 3; ++i )
{
if ( v[i] == 0.0 ) {
zeroComponentCount++;
}
}
return zeroComponentCount > 1; // The zero vector will be on axis.
}
/*
=====================
PlaneFromPoints
Returns false if the triangle is degenrate.
The normal will point out of the clock for clockwise ordered points
=====================
*/
template<typename P, typename V>
bool PlaneFromPoints( Plane3___<P>& plane, const BasicVector3<V>& p0, const BasicVector3<V>& p1, const BasicVector3<V>& p2 ) {
plane.normal() = vector3_cross( p2 - p0, p1 - p0 );
if ( VectorNormalize( plane.normal() ) == 0 ) {
return false;
}
plane.dist() = vector3_dot( p0, plane.normal() );
return true;
}
template<typename P, typename V>
bool PlaneFromPoints( Plane3___<P>& plane, const BasicVector3<V> planepts[3] ) {
return PlaneFromPoints( plane, planepts[0], planepts[1], planepts[2] );
}
/*
ComputeAxisBase()
computes the base texture axis for brush primitive texturing
note: ComputeAxisBase here and in editor code must always BE THE SAME!
warning: special case behaviour of atan2( y, x ) <-> atan( y / x ) might not be the same everywhere when x == 0
rotation by (0,RotY,RotZ) assigns X to normal
*/
template <typename Element, typename OtherElement>
inline void ComputeAxisBase( const BasicVector3<Element>& normal, BasicVector3<OtherElement>& texS, BasicVector3<OtherElement>& texT ){
#if 1
const BasicVector3<Element> up( 0, 0, 1 );
const BasicVector3<Element> down( 0, 0, -1 );
if ( vector3_equal_epsilon( normal, up, Element(1e-6) ) ) {
texS = BasicVector3<OtherElement>( 0, 1, 0 );
texT = BasicVector3<OtherElement>( 1, 0, 0 );
}
else if ( vector3_equal_epsilon( normal, down, Element(1e-6) ) ) {
texS = BasicVector3<OtherElement>( 0, 1, 0 );
texT = BasicVector3<OtherElement>( -1, 0, 0 );
}
else
{
texS = vector3_normalised( vector3_cross( normal, up ) );
texT = vector3_normalised( vector3_cross( normal, texS ) );
vector3_negate( texS );
}
#else
/* do some cleaning */
if ( fabs( normal[ 0 ] ) < 1e-6 ) {
normal[ 0 ] = 0.0f;
}
if ( fabs( normal[ 1 ] ) < 1e-6 ) {
normal[ 1 ] = 0.0f;
}
if ( fabs( normal[ 2 ] ) < 1e-6 ) {
normal[ 2 ] = 0.0f;
}
/* compute the two rotations around y and z to rotate x to normal */
const float RotY = -atan2( normal[ 2 ], sqrt( normal[ 1 ] * normal[ 1 ] + normal[ 0 ] * normal[ 0 ] ) );
const float RotZ = atan2( normal[ 1 ], normal[ 0 ] );
/* rotate (0,1,0) and (0,0,1) to compute texS and texT */
texS[ 0 ] = -sin( RotZ );
texS[ 1 ] = cos( RotZ );
texS[ 2 ] = 0;
/* the texT vector is along -z (t texture coorinates axis) */
texT[ 0 ] = -sin( RotY ) * cos( RotZ );
texT[ 1 ] = -sin( RotY ) * sin( RotZ );
texT[ 2 ] = -cos( RotY );
#endif
}
/*
================
MakeNormalVectors
Given a normalized forward vector, create two
other perpendicular vectors
================
*/
inline void MakeNormalVectors( const Vector3& forward, Vector3& right, Vector3& up ){
// this rotate and negate guarantees a vector
// not colinear with the original
right[1] = -forward[0];
right[2] = forward[1];
right[0] = forward[2];
right = VectorNormalized( right - forward * vector3_dot( right, forward ) );
up = vector3_cross( right, forward );
}
/*
** NormalToLatLong
**
** We use two byte encoded normals in some space critical applications.
** Lat = 0 at (1,0,0) to 360 (-1,0,0), encoded in 8-bit sine table format
** Lng = 0 at (0,0,1) to 180 (0,0,-1), encoded in 8-bit sine table format
**
*/
inline void NormalToLatLong( const Vector3& normal, byte bytes[2] ) {
// check for singularities
if ( normal[0] == 0 && normal[1] == 0 ) {
if ( normal[2] > 0 ) {
bytes[0] = 0;
bytes[1] = 0; // lat = 0, long = 0
}
else {
bytes[0] = 128;
bytes[1] = 0; // lat = 0, long = 128
}
}
else {
const int a = radians_to_degrees( atan2( normal[1], normal[0] ) ) * ( 255.0 / 360.0 );
const int b = radians_to_degrees( acos( normal[2] ) ) * ( 255.0 / 360.0 );
bytes[0] = b & 0xff; // longitude
bytes[1] = a & 0xff; // lattitude
}
}
// plane types are used to speed some tests
// 0-2 are axial planes
enum EPlaneType : int
{
ePlaneX = 0,
ePlaneY = 1,
ePlaneZ = 2,
ePlaneNonAxial = 3
};
inline EPlaneType PlaneTypeForNormal( const Vector3& normal ) {
if ( normal[0] == 1.0 || normal[0] == -1.0 ) {
return ePlaneX;
}
if ( normal[1] == 1.0 || normal[1] == -1.0 ) {
return ePlaneY;
}
if ( normal[2] == 1.0 || normal[2] == -1.0 ) {
return ePlaneZ;
}
return ePlaneNonAxial;
}
inline void ColorNormalize( Vector3& color ) {
const float max = VectorMax( color );
if ( max == 0 ) {
color.set( 1 );
}
else{
color *= ( 1.f / max );
}
}
+6 -7
View File
@@ -22,7 +22,6 @@
// scriplib.c
#include "cmdlib.h"
#include "mathlib.h"
#include "inout.h"
#include "scriplib.h"
#include "vfs.h"
@@ -365,7 +364,7 @@ void MatchToken( const char *match ) {
}
void Parse1DMatrix( int x, vec_t *m ) {
void Parse1DMatrix( int x, float *m ) {
int i;
MatchToken( "(" );
@@ -378,7 +377,7 @@ void Parse1DMatrix( int x, vec_t *m ) {
MatchToken( ")" );
}
void Parse2DMatrix( int y, int x, vec_t *m ) {
void Parse2DMatrix( int y, int x, float *m ) {
int i;
MatchToken( "(" );
@@ -390,7 +389,7 @@ void Parse2DMatrix( int y, int x, vec_t *m ) {
MatchToken( ")" );
}
void Parse3DMatrix( int z, int y, int x, vec_t *m ) {
void Parse3DMatrix( int z, int y, int x, float *m ) {
int i;
MatchToken( "(" );
@@ -403,7 +402,7 @@ void Parse3DMatrix( int z, int y, int x, vec_t *m ) {
}
void Write1DMatrix( FILE *f, int x, vec_t *m ) {
void Write1DMatrix( FILE *f, int x, float *m ) {
int i;
fprintf( f, "( " );
@@ -418,7 +417,7 @@ void Write1DMatrix( FILE *f, int x, vec_t *m ) {
fprintf( f, ")" );
}
void Write2DMatrix( FILE *f, int y, int x, vec_t *m ) {
void Write2DMatrix( FILE *f, int y, int x, float *m ) {
int i;
fprintf( f, "( " );
@@ -430,7 +429,7 @@ void Write2DMatrix( FILE *f, int y, int x, vec_t *m ) {
}
void Write3DMatrix( FILE *f, int z, int y, int x, vec_t *m ) {
void Write3DMatrix( FILE *f, int z, int y, int x, float *m ) {
int i;
fprintf( f, "(\n" );
+6 -9
View File
@@ -24,9 +24,6 @@
#ifndef __CMDLIB__
#include "../common/cmdlib.h"
#endif
#ifndef __MATHLIB__
#include "mathlib.h"
#endif
#define MAXTOKEN 1024
@@ -47,10 +44,10 @@ bool TokenAvailable( void );
void MatchToken( const char *match );
void Parse1DMatrix( int x, vec_t *m );
void Parse2DMatrix( int y, int x, vec_t *m );
void Parse3DMatrix( int z, int y, int x, vec_t *m );
void Parse1DMatrix( int x, float *m );
void Parse2DMatrix( int y, int x, float *m );
void Parse3DMatrix( int z, int y, int x, float *m );
void Write1DMatrix( FILE *f, int x, vec_t *m );
void Write2DMatrix( FILE *f, int y, int x, vec_t *m );
void Write3DMatrix( FILE *f, int z, int y, int x, vec_t *m );
void Write1DMatrix( FILE *f, int x, float *m );
void Write2DMatrix( FILE *f, int y, int x, float *m );
void Write3DMatrix( FILE *f, int z, int y, int x, float *m );
-1
View File
@@ -27,7 +27,6 @@
#endif
#include "cmdlib.h"
#include "mathlib.h"
#include "inout.h"
#include "qthreads.h"
-1
View File
@@ -47,7 +47,6 @@
#include "cmdlib.h"
#include "filematch.h"
#include "mathlib.h"
#include "inout.h"
#include "vfs.h"
#include "unzip.h"
+46 -72
View File
@@ -179,7 +179,7 @@ bool BoundBrush( brush_t *brush ){
winding_t *w;
ClearBounds( brush->mins, brush->maxs );
brush->minmax.clear();
for ( i = 0; i < brush->numsides; i++ )
{
w = brush->sides[ i ].winding;
@@ -187,12 +187,12 @@ bool BoundBrush( brush_t *brush ){
continue;
}
for ( j = 0; j < w->numpoints; j++ )
AddPointToBounds( w->p[ j ], brush->mins, brush->maxs );
brush->minmax.extend( w->p[ j ] );
}
for ( i = 0; i < 3; i++ )
{
if ( brush->mins[ i ] < MIN_WORLD_COORD || brush->maxs[ i ] > MAX_WORLD_COORD || brush->mins[i] >= brush->maxs[ i ] ) {
if ( brush->minmax.mins[ i ] < MIN_WORLD_COORD || brush->minmax.maxs[ i ] > MAX_WORLD_COORD || brush->minmax.mins[i] >= brush->minmax.maxs[ i ] ) {
return false;
}
}
@@ -205,28 +205,23 @@ bool BoundBrush( brush_t *brush ){
/*
SnapWeldVector() - ydnar
welds two vec3_t's into a third, taking into account nearest-to-integer
welds two Vector3's into a third, taking into account nearest-to-integer
instead of averaging
*/
#define SNAP_EPSILON 0.01
void SnapWeldVector( vec3_t a, vec3_t b, vec3_t out ){
void SnapWeldVector( const Vector3& a, const Vector3& b, Vector3& out ){
int i;
vec_t ai, bi, outi;
float ai, bi, outi;
/* dummy check */
if ( a == NULL || b == NULL || out == NULL ) {
return;
}
/* do each element */
for ( i = 0; i < 3; i++ )
{
/* round to integer */
ai = Q_rint( a[ i ] );
bi = Q_rint( b[ i ] );
ai = std::rint( a[ i ] );
bi = std::rint( b[ i ] );
/* prefer exact integer */
if ( ai == a[ i ] ) {
@@ -245,7 +240,7 @@ void SnapWeldVector( vec3_t a, vec3_t b, vec3_t out ){
}
/* snap */
outi = Q_rint( out[ i ] );
outi = std::rint( out[ i ] );
if ( fabs( outi - out[ i ] ) <= SNAP_EPSILON ) {
out[ i ] = outi;
}
@@ -260,7 +255,7 @@ void SnapWeldVector( vec3_t a, vec3_t b, vec3_t out ){
instead of averaging.
==================
*/
void SnapWeldVectorAccu( vec3_accu_t a, vec3_accu_t b, vec3_accu_t out ){
void SnapWeldVectorAccu( const DoubleVector3& a, const DoubleVector3& b, DoubleVector3& out ){
// I'm just preserving what I think was the intended logic of the original
// SnapWeldVector(). I'm not actually sure where this function should even
// be used. I'd like to know which kinds of problems this function addresses.
@@ -270,16 +265,12 @@ void SnapWeldVectorAccu( vec3_accu_t a, vec3_accu_t b, vec3_accu_t out ){
// be snapping to the nearest 1/8 unit instead?
int i;
vec_accu_t ai, bi, ad, bd;
if ( a == NULL || b == NULL || out == NULL ) {
Error( "SnapWeldVectorAccu: NULL argument" );
}
double ai, bi, ad, bd;
for ( i = 0; i < 3; i++ )
{
ai = Q_rintAccu( a[i] );
bi = Q_rintAccu( b[i] );
ai = std::rint( a[i] );
bi = std::rint( b[i] );
ad = fabs( ai - a[i] );
bd = fabs( bi - b[i] );
@@ -310,7 +301,7 @@ void SnapWeldVectorAccu( vec3_accu_t a, vec3_accu_t b, vec3_accu_t out ){
bool FixWinding( winding_t *w ){
bool valid = true;
int i, j, k;
vec3_t vec;
Vector3 vec;
float dist;
@@ -331,22 +322,21 @@ bool FixWinding( winding_t *w ){
j = ( i + 1 ) % w->numpoints;
/* degenerate edge? */
VectorSubtract( w->p[ i ], w->p[ j ], vec );
dist = VectorLength( vec );
dist = vector3_length( w->p[ i ] - w->p[ j ] );
if ( dist < DEGENERATE_EPSILON ) {
valid = false;
//Sys_FPrintf( SYS_WRN | SYS_VRBflag, "WARNING: Degenerate winding edge found, fixing...\n" );
/* create an average point (ydnar 2002-01-26: using nearest-integer weld preference) */
SnapWeldVector( w->p[ i ], w->p[ j ], vec );
VectorCopy( vec, w->p[ i ] );
w->p[ i ] = vec;
//VectorAdd( w->p[ i ], w->p[ j ], vec );
//VectorScale( vec, 0.5, w->p[ i ] );
/* move the remaining verts */
for ( k = i + 2; k < w->numpoints; k++ )
{
VectorCopy( w->p[ k ], w->p[ k - 1 ] );
w->p[ k - 1 ] = w->p[ k ];
}
w->numpoints--;
}
@@ -375,8 +365,6 @@ bool FixWinding( winding_t *w ){
*/
bool FixWindingAccu( winding_accu_t *w ){
int i, j, k;
vec3_accu_t vec;
vec_accu_t dist;
bool done, altered;
if ( w == NULL ) {
@@ -395,19 +383,18 @@ bool FixWindingAccu( winding_accu_t *w ){
{
j = ( ( ( i + 1 ) == w->numpoints ) ? 0 : ( i + 1 ) );
VectorSubtractAccu( w->p[i], w->p[j], vec );
dist = VectorLengthAccu( vec );
if ( dist < DEGENERATE_EPSILON ) {
DoubleVector3 vec = w->p[i] - w->p[j];
if ( vector3_length( vec ) < DEGENERATE_EPSILON ) {
// TODO: I think the "snap weld vector" was written before
// some of the math precision fixes, and its purpose was
// probably to address math accuracy issues. We can think
// about changing the logic here. Maybe once plane distance
// gets 64 bits, we can look at it then.
SnapWeldVectorAccu( w->p[i], w->p[j], vec );
VectorCopyAccu( vec, w->p[i] );
w->p[i] = vec;
for ( k = j + 1; k < w->numpoints; k++ )
{
VectorCopyAccu( w->p[k], w->p[k - 1] );
w->p[k - 1] = w->p[k];
}
w->numpoints--;
altered = true;
@@ -456,9 +443,9 @@ bool CreateBrushWindings( brush_t *brush ){
/* make huge winding */
#if Q3MAP2_EXPERIMENTAL_HIGH_PRECISION_MATH_FIXES
w = BaseWindingForPlaneAccu( plane->normal, plane->dist );
w = BaseWindingForPlaneAccu( plane->plane );
#else
w = BaseWindingForPlane( plane->normal, plane->dist );
w = BaseWindingForPlane( plane->plane );
#endif
/* walk the list of brush sides */
@@ -475,9 +462,9 @@ bool CreateBrushWindings( brush_t *brush ){
}
plane = &mapplanes[ brush->sides[ j ].planenum ^ 1 ];
#if Q3MAP2_EXPERIMENTAL_HIGH_PRECISION_MATH_FIXES
ChopWindingInPlaceAccu( &w, plane->normal, plane->dist, 0 );
ChopWindingInPlaceAccu( &w, plane->plane, 0 );
#else
ChopWindingInPlace( &w, plane->normal, plane->dist, 0 ); // CLIP_EPSILON );
ChopWindingInPlace( &w, plane->plane, 0 ); // CLIP_EPSILON );
#endif
/* ydnar: fix broken windings that would generate trifans */
@@ -523,24 +510,20 @@ bool CreateBrushWindings( brush_t *brush ){
Creates a new axial brush
==================
*/
brush_t *BrushFromBounds( vec3_t mins, vec3_t maxs ){
brush_t *BrushFromBounds( const Vector3& mins, const Vector3& maxs ){
brush_t *b;
int i;
vec3_t normal;
vec_t dist;
float dist;
b = AllocBrush( 6 );
b->numsides = 6;
for ( i = 0 ; i < 3 ; i++ )
{
VectorClear( normal );
normal[i] = 1;
dist = maxs[i];
b->sides[i].planenum = FindFloatPlane( normal, dist, 1, (vec3_t*) &maxs );
b->sides[i].planenum = FindFloatPlane( g_vector3_axes[i], dist, 1, &maxs );
normal[i] = -1;
dist = -mins[i];
b->sides[3 + i].planenum = FindFloatPlane( normal, dist, 1, (vec3_t*) &mins );
b->sides[3 + i].planenum = FindFloatPlane( -g_vector3_axes[i], dist, 1, &mins );
}
CreateBrushWindings( b );
@@ -554,12 +537,11 @@ brush_t *BrushFromBounds( vec3_t mins, vec3_t maxs ){
==================
*/
vec_t BrushVolume( brush_t *brush ){
float BrushVolume( brush_t *brush ){
int i;
winding_t *w;
vec3_t corner;
vec_t d, area, volume;
plane_t *plane;
Vector3 corner;
float volume;
if ( !brush ) {
return 0;
@@ -578,7 +560,7 @@ vec_t BrushVolume( brush_t *brush ){
if ( !w ) {
return 0;
}
VectorCopy( w->p[0], corner );
corner = w->p[0];
// make tetrahedrons to all other faces
@@ -589,10 +571,7 @@ vec_t BrushVolume( brush_t *brush ){
if ( !w ) {
continue;
}
plane = &mapplanes[brush->sides[i].planenum];
d = -( DotProduct( corner, plane->normal ) - plane->dist );
area = WindingArea( w );
volume += d * area;
volume += -plane3_distance_to_point( mapplanes[brush->sides[i].planenum].plane, corner ) * WindingArea( w );
}
volume /= 3;
@@ -627,7 +606,7 @@ void WriteBSPBrushMap( const char *name, brush_t *list ){
{
// TODO: See if we can use a smaller winding to prevent resolution loss.
// Is WriteBSPBrushMap() used only to decompile maps?
w = BaseWindingForPlane( mapplanes[s->planenum].normal, mapplanes[s->planenum].dist );
w = BaseWindingForPlane( mapplanes[s->planenum].plane );
fprintf( f, "( %i %i %i ) ", (int)w->p[0][0], (int)w->p[0][1], (int)w->p[0][2] );
fprintf( f, "( %i %i %i ) ", (int)w->p[1][0], (int)w->p[1][1], (int)w->p[1][2] );
@@ -791,7 +770,7 @@ void FilterStructuralBrushesIntoTree( entity_t *e, tree_t *tree ) {
*/
tree_t *AllocTree( void ){
tree_t *tree = safe_calloc( sizeof( *tree ) );
ClearBounds( tree->mins, tree->maxs );
tree->minmax.clear();
return tree;
}
@@ -821,17 +800,12 @@ bool WindingIsTiny( winding_t *w ){
return false;
*/
int i, j;
vec_t len;
vec3_t delta;
int edges;
int edges = 0;
edges = 0;
for ( i = 0 ; i < w->numpoints ; i++ )
{
j = i == w->numpoints - 1 ? 0 : i + 1;
VectorSubtract( w->p[j], w->p[i], delta );
len = VectorLength( delta );
if ( len > EDGE_LENGTH ) {
if ( vector3_length( w->p[j] - w->p[i] ) > EDGE_LENGTH ) {
if ( ++edges == 3 ) {
return false;
}
@@ -872,7 +846,7 @@ bool WindingIsHuge( winding_t *w ){
int BrushMostlyOnSide( brush_t *brush, plane_t *plane ){
int i, j;
winding_t *w;
vec_t d, max;
float max;
int side;
max = 0;
@@ -885,7 +859,7 @@ int BrushMostlyOnSide( brush_t *brush, plane_t *plane ){
}
for ( j = 0 ; j < w->numpoints ; j++ )
{
d = DotProduct( w->p[j], plane->normal ) - plane->dist;
const double d = plane3_distance_to_point( plane->plane, w->p[j] );
if ( d > max ) {
max = d;
side = PSIDE_FRONT;
@@ -912,7 +886,7 @@ void SplitBrush( brush_t *brush, int planenum, brush_t **front, brush_t **back )
winding_t *w, *cw[2], *midwinding;
plane_t *plane, *plane2;
side_t *s, *cs;
float d, d_front, d_back;
float d_front, d_back;
*front = NULL;
@@ -929,7 +903,7 @@ void SplitBrush( brush_t *brush, int planenum, brush_t **front, brush_t **back )
}
for ( j = 0 ; j < w->numpoints ; j++ )
{
d = DotProduct( w->p[j], plane->normal ) - plane->dist;
const double d = plane3_distance_to_point( plane->plane, w->p[j] );
if ( d > 0 && d > d_front ) {
d_front = d;
}
@@ -952,11 +926,11 @@ void SplitBrush( brush_t *brush, int planenum, brush_t **front, brush_t **back )
}
// create a new winding from the split plane
w = BaseWindingForPlane( plane->normal, plane->dist );
w = BaseWindingForPlane( plane->plane );
for ( i = 0 ; i < brush->numsides && w ; i++ )
{
plane2 = &mapplanes[brush->sides[i].planenum ^ 1];
ChopWindingInPlace( &w, plane2->normal, plane2->dist, 0 ); // PLANESIDE_EPSILON);
ChopWindingInPlace( &w, plane2->plane, 0 ); // PLANESIDE_EPSILON);
}
if ( !w || WindingIsTiny( w ) ) { // the brush isn't really split
@@ -998,7 +972,7 @@ void SplitBrush( brush_t *brush, int planenum, brush_t **front, brush_t **back )
if ( !w ) {
continue;
}
ClipWindingEpsilonStrict( w, plane->normal, plane->dist,
ClipWindingEpsilonStrict( w, plane->plane,
0 /*PLANESIDE_EPSILON*/, &cw[0], &cw[1] ); /* strict, in parallel case we get the face back because it also is the midwinding */
for ( j = 0 ; j < 2 ; j++ )
{
@@ -1060,7 +1034,7 @@ void SplitBrush( brush_t *brush, int planenum, brush_t **front, brush_t **back )
}
{
vec_t v1;
float v1;
int i;
-78
View File
@@ -1,78 +0,0 @@
/* -------------------------------------------------------------------------------
Copyright (C) 1999-2007 id Software, Inc. and contributors.
For a list of contributors, see the accompanying CONTRIBUTORS file.
This file is part of GtkRadiant.
GtkRadiant is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
GtkRadiant is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GtkRadiant; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
----------------------------------------------------------------------------------
This code has been altered significantly from its original form, to support
several games based on the Quake III Arena engine, in the form of "Q3Map2."
------------------------------------------------------------------------------- */
/* dependencies */
#include "q3map2.h"
/* -------------------------------------------------------------------------------
functions
------------------------------------------------------------------------------- */
/*
ComputeAxisBase()
computes the base texture axis for brush primitive texturing
note: ComputeAxisBase here and in editor code must always BE THE SAME!
warning: special case behaviour of atan2( y, x ) <-> atan( y / x ) might not be the same everywhere when x == 0
rotation by (0,RotY,RotZ) assigns X to normal
*/
void ComputeAxisBase( vec3_t normal, vec3_t texX, vec3_t texY ){
vec_t RotY, RotZ;
/* do some cleaning */
if ( fabs( normal[ 0 ] ) < 1e-6 ) {
normal[ 0 ] = 0.0f;
}
if ( fabs( normal[ 1 ] ) < 1e-6 ) {
normal[ 1 ] = 0.0f;
}
if ( fabs( normal[ 2 ] ) < 1e-6 ) {
normal[ 2 ] = 0.0f;
}
/* compute the two rotations around y and z to rotate x to normal */
RotY = -atan2( normal[ 2 ], sqrt( normal[ 1 ] * normal[ 1 ] + normal[ 0 ] * normal[ 0 ] ) );
RotZ = atan2( normal[ 1 ], normal[ 0 ] );
/* rotate (0,1,0) and (0,0,1) to compute texX and texY */
texX[ 0 ] = -sin( RotZ );
texX[ 1 ] = cos( RotZ );
texX[ 2 ] = 0;
/* the texY vector is along -z (t texture coorinates axis) */
texY[ 0 ] = -sin( RotY ) * cos( RotZ );
texY[ 1 ] = -sin( RotY ) * sin( RotZ );
texY[ 2 ] = -cos( RotY );
}
+9 -10
View File
@@ -125,7 +125,7 @@ static void ProcessAdvertisements( void ) {
// store the normal for use at run time.. all ad verts are assumed to
// have identical normals (because they should be a simple rectangle)
// so just use the first vert's normal
VectorCopy( bspDrawVerts[adSurface->firstVert].normal, bspAds[numBSPAds].normal );
bspAds[numBSPAds].normal = bspDrawVerts[adSurface->firstVert].normal;
// store the ad quad for quick use at run time
if ( adSurface->surfaceType == MST_PATCH ) {
@@ -133,10 +133,10 @@ static void ProcessAdvertisements( void ) {
int v1 = adSurface->firstVert + adSurface->numVerts - 1;
int v2 = adSurface->firstVert + adSurface->numVerts - adSurface->patchWidth;
int v3 = adSurface->firstVert;
VectorCopy( bspDrawVerts[v0].xyz, bspAds[numBSPAds].rect[0] );
VectorCopy( bspDrawVerts[v1].xyz, bspAds[numBSPAds].rect[1] );
VectorCopy( bspDrawVerts[v2].xyz, bspAds[numBSPAds].rect[2] );
VectorCopy( bspDrawVerts[v3].xyz, bspAds[numBSPAds].rect[3] );
bspAds[numBSPAds].rect[0] = bspDrawVerts[v0].xyz;
bspAds[numBSPAds].rect[1] = bspDrawVerts[v1].xyz;
bspAds[numBSPAds].rect[2] = bspDrawVerts[v2].xyz;
bspAds[numBSPAds].rect[3] = bspDrawVerts[v3].xyz;
}
else {
Error( "Ad cell %d has an unsupported Ad Surface type.", bspAds[numBSPAds].cellId );
@@ -441,7 +441,7 @@ void ProcessWorldModel( void ){
for ( const auto& light : entities )
{
entity_t *target;
vec3_t origin, targetOrigin, normal, color;
Vector3 origin, targetOrigin, normal, color;
/* get light */
if ( light.classname_is( "light" ) ) {
@@ -459,13 +459,12 @@ void ProcessWorldModel( void ){
target = FindTargetEntity( value );
if ( target != NULL ) {
target->vectorForKey( "origin", targetOrigin );
VectorSubtract( targetOrigin, origin, normal );
VectorNormalize( normal, normal );
normal = VectorNormalized( targetOrigin - origin );
}
}
else{
//% VectorClear( normal );
VectorSet( normal, 0, 0, -1 );
//% normal.set( 0 );
normal = -g_vector3_axis_z;
}
if ( colorsRGB ) {
+1 -1
View File
@@ -755,7 +755,7 @@ bool entity_t::read_keyvalue_( float &float_value, std::initializer_list<const c
}
return false;
}
bool entity_t::read_keyvalue_( float (&vector3_value)[3], std::initializer_list<const char*>&& keys ) const {
bool entity_t::read_keyvalue_( Vector3& vector3_value, std::initializer_list<const char*>&& keys ) const {
for( const char* key : keys ){
const char* value = valueForKey( key );
if( !strEmpty( value ) ){
+31 -49
View File
@@ -145,8 +145,8 @@ struct ibspDrawSurface_t
int lightmapX, lightmapY;
int lightmapWidth, lightmapHeight;
vec3_t lightmapOrigin;
vec3_t lightmapVecs[ 3 ];
Vector3 lightmapOrigin;
Vector3 lightmapVecs[ 3 ];
int patchWidth;
int patchHeight;
@@ -194,10 +194,10 @@ static void CopyDrawSurfacesLump( ibspHeader_t *header ){
out->lightmapWidth = in->lightmapWidth;
out->lightmapHeight = in->lightmapHeight;
VectorCopy( in->lightmapOrigin, out->lightmapOrigin );
VectorCopy( in->lightmapVecs[ 0 ], out->lightmapVecs[ 0 ] );
VectorCopy( in->lightmapVecs[ 1 ], out->lightmapVecs[ 1 ] );
VectorCopy( in->lightmapVecs[ 2 ], out->lightmapVecs[ 2 ] );
out->lightmapOrigin = in->lightmapOrigin;
out->lightmapVecs[ 0 ] = in->lightmapVecs[ 0 ];
out->lightmapVecs[ 1 ] = in->lightmapVecs[ 1 ];
out->lightmapVecs[ 2 ] = in->lightmapVecs[ 2 ];
out->patchWidth = in->patchWidth;
out->patchHeight = in->patchHeight;
@@ -237,10 +237,10 @@ static void AddDrawSurfacesLump( FILE *file, ibspHeader_t *header ){
out->lightmapWidth = in->lightmapWidth;
out->lightmapHeight = in->lightmapHeight;
VectorCopy( in->lightmapOrigin, out->lightmapOrigin );
VectorCopy( in->lightmapVecs[ 0 ], out->lightmapVecs[ 0 ] );
VectorCopy( in->lightmapVecs[ 1 ], out->lightmapVecs[ 1 ] );
VectorCopy( in->lightmapVecs[ 2 ], out->lightmapVecs[ 2 ] );
out->lightmapOrigin = in->lightmapOrigin;
out->lightmapVecs[ 0 ] = in->lightmapVecs[ 0 ];
out->lightmapVecs[ 1 ] = in->lightmapVecs[ 1 ];
out->lightmapVecs[ 2 ] = in->lightmapVecs[ 2 ];
out->patchWidth = in->patchWidth;
out->patchHeight = in->patchHeight;
@@ -261,11 +261,11 @@ static void AddDrawSurfacesLump( FILE *file, ibspHeader_t *header ){
/* drawverts */
struct ibspDrawVert_t
{
vec3_t xyz;
float st[ 2 ];
float lightmap[ 2 ];
vec3_t normal;
byte color[ 4 ];
Vector3 xyz;
Vector2 st;
Vector2 lightmap;
Vector3 normal;
Color4b color;
};
@@ -284,20 +284,11 @@ static void CopyDrawVertsLump( ibspHeader_t *header ){
out = bspDrawVerts;
for ( i = 0; i < numBSPDrawVerts; i++ )
{
VectorCopy( in->xyz, out->xyz );
out->st[ 0 ] = in->st[ 0 ];
out->st[ 1 ] = in->st[ 1 ];
out->lightmap[ 0 ][ 0 ] = in->lightmap[ 0 ];
out->lightmap[ 0 ][ 1 ] = in->lightmap[ 1 ];
VectorCopy( in->normal, out->normal );
out->color[ 0 ][ 0 ] = in->color[ 0 ];
out->color[ 0 ][ 1 ] = in->color[ 1 ];
out->color[ 0 ][ 2 ] = in->color[ 2 ];
out->color[ 0 ][ 3 ] = in->color[ 3 ];
out->xyz = in->xyz;
out->st = in->st;
out->lightmap[ 0 ] = in->lightmap;
out->normal = in->normal;
out->color[ 0 ] = in->color;
in++;
out++;
}
@@ -319,20 +310,11 @@ static void AddDrawVertsLump( FILE *file, ibspHeader_t *header ){
out = buffer;
for ( i = 0; i < numBSPDrawVerts; i++ )
{
VectorCopy( in->xyz, out->xyz );
out->st[ 0 ] = in->st[ 0 ];
out->st[ 1 ] = in->st[ 1 ];
out->lightmap[ 0 ] = in->lightmap[ 0 ][ 0 ];
out->lightmap[ 1 ] = in->lightmap[ 0 ][ 1 ];
VectorCopy( in->normal, out->normal );
out->color[ 0 ] = in->color[ 0 ][ 0 ];
out->color[ 1 ] = in->color[ 0 ][ 1 ];
out->color[ 2 ] = in->color[ 0 ][ 2 ];
out->color[ 3 ] = in->color[ 0 ][ 3 ];
out->xyz = in->xyz;
out->st = in->st;
out->lightmap = in->lightmap[ 0 ];
out->normal = in->normal;
out->color = in->color[ 0 ];
in++;
out++;
}
@@ -349,8 +331,8 @@ static void AddDrawVertsLump( FILE *file, ibspHeader_t *header ){
/* light grid */
struct ibspGridPoint_t
{
byte ambient[ 3 ];
byte directed[ 3 ];
Vector3b ambient;
Vector3b directed;
byte latLong[ 2 ];
};
@@ -374,8 +356,8 @@ static void CopyLightGridLumps( ibspHeader_t *header ){
{
for ( j = 0; j < MAX_LIGHTMAPS; j++ )
{
VectorCopy( in->ambient, out->ambient[ j ] );
VectorCopy( in->directed, out->directed[ j ] );
out->ambient[ j ] = in->ambient;
out->directed[ j ] = in->directed;
out->styles[ j ] = LS_NONE;
}
@@ -409,8 +391,8 @@ static void AddLightGridLumps( FILE *file, ibspHeader_t *header ){
out = buffer;
for ( i = 0; i < numBSPGridPoints; i++ )
{
VectorCopy( in->ambient[ 0 ], out->ambient );
VectorCopy( in->directed[ 0 ], out->directed );
out->ambient = in->ambient[ 0 ];
out->directed = in->directed[ 0 ];
out->latLong[ 0 ] = in->latLong[ 0 ];
out->latLong[ 1 ] = in->latLong[ 1 ];
+5 -8
View File
@@ -41,10 +41,9 @@
int numLightmapsASE = 0;
static void ConvertSurface( FILE *f, bspModel_t *model, int modelNum, bspDrawSurface_t *ds, int surfaceNum, vec3_t origin, const int* lmIndices ){
static void ConvertSurface( FILE *f, bspModel_t *model, int modelNum, bspDrawSurface_t *ds, int surfaceNum, const Vector3& origin, const int* lmIndices ){
int i, v, face, a, b, c;
bspDrawVert_t *dv;
vec3_t normal;
char name[ 1024 ];
@@ -102,10 +101,8 @@ static void ConvertSurface( FILE *f, bspModel_t *model, int modelNum, bspDrawSur
a = bspDrawIndexes[ i + ds->firstIndex ];
b = bspDrawIndexes[ i + ds->firstIndex + 1 ];
c = bspDrawIndexes[ i + ds->firstIndex + 2 ];
VectorCopy( bspDrawVerts[ a ].normal, normal );
VectorAdd( normal, bspDrawVerts[ b ].normal, normal );
VectorAdd( normal, bspDrawVerts[ c ].normal, normal );
if ( VectorNormalize( normal, normal ) ) {
Vector3 normal = bspDrawVerts[ a ].normal + bspDrawVerts[ b ].normal + bspDrawVerts[ c ].normal;
if ( VectorNormalize( normal ) != 0 ) {
fprintf( f, "\t\t\t*MESH_FACENORMAL\t%d\t%f\t%f\t%f\r\n", face, normal[ 0 ], normal[ 1 ], normal[ 2 ] );
}
}
@@ -188,7 +185,7 @@ static void ConvertSurface( FILE *f, bspModel_t *model, int modelNum, bspDrawSur
exports a bsp model to an ase chunk
*/
static void ConvertModel( FILE *f, bspModel_t *model, int modelNum, vec3_t origin, const int* lmIndices ){
static void ConvertModel( FILE *f, bspModel_t *model, int modelNum, const Vector3& origin, const int* lmIndices ){
int i, s;
bspDrawSurface_t *ds;
@@ -404,7 +401,7 @@ int ConvertBSPToASE( char *bspName ){
model = &bspModels[ modelNum ];
/* get entity origin */
vec3_t origin;
Vector3 origin;
e->vectorForKey( "origin", origin );
/* convert model */
+46 -83
View File
@@ -325,16 +325,16 @@ int BSPInfo( int count, char **fileNames ){
}
static void ExtrapolateTexcoords( const float *axyz, const float *ast, const float *bxyz, const float *bst, const float *cxyz, const float *cst, const float *axyz_new, float *ast_out, const float *bxyz_new, float *bst_out, const float *cxyz_new, float *cst_out ){
vec4_t scoeffs, tcoeffs;
float md;
m4x4_t solvematrix;
static void ExtrapolateTexcoords( const float *axyz, const float *ast,
const float *bxyz, const float *bst,
const float *cxyz, const float *cst,
const Vector3& axyz_new, Vector2& ast_out,
const Vector3& bxyz_new, Vector2& bst_out,
const Vector3& cxyz_new, Vector2& cst_out ){
Vector4 scoeffs, tcoeffs;
Matrix4 solvematrix;
vec3_t norm;
vec3_t dab, dac;
VectorSubtract( bxyz, axyz, dab );
VectorSubtract( cxyz, axyz, dac );
CrossProduct( dab, dac, norm );
const Vector3 norm = vector3_cross( vector3_from_array( bxyz ) - vector3_from_array( axyz ), vector3_from_array( cxyz ) - vector3_from_array( axyz ) );
// assume:
// s = f(x, y, z)
@@ -365,24 +365,24 @@ static void ExtrapolateTexcoords( const float *axyz, const float *ast, const flo
solvematrix[11] = norm[2];
solvematrix[15] = 0;
md = m4_det( solvematrix );
const double md = matrix4_determinant( solvematrix );
if ( md * md < 1e-10 ) {
Sys_Printf( "Cannot invert some matrix, some texcoords aren't extrapolated!" );
return;
}
m4x4_invert( solvematrix );
matrix4_full_invert( solvematrix );
scoeffs[0] = ast[0];
scoeffs[1] = bst[0];
scoeffs[2] = cst[0];
scoeffs[3] = 0;
m4x4_transform_vec4( solvematrix, scoeffs );
matrix4_transform_vector4( solvematrix, scoeffs );
tcoeffs[0] = ast[1];
tcoeffs[1] = bst[1];
tcoeffs[2] = cst[1];
tcoeffs[3] = 0;
m4x4_transform_vec4( solvematrix, tcoeffs );
matrix4_transform_vector4( solvematrix, tcoeffs );
ast_out[0] = scoeffs[0] * axyz_new[0] + scoeffs[1] * axyz_new[1] + scoeffs[2] * axyz_new[2] + scoeffs[3];
ast_out[1] = tcoeffs[0] * axyz_new[0] + tcoeffs[1] * axyz_new[1] + tcoeffs[2] * axyz_new[2] + tcoeffs[3];
@@ -400,8 +400,8 @@ static void ExtrapolateTexcoords( const float *axyz, const float *ast, const flo
int ScaleBSPMain( int argc, char **argv ){
int i, j;
float f, a;
vec3_t scale;
vec3_t vec;
Vector3 scale;
Vector3 vec;
char str[ 1024 ];
int uniform, axis;
bool texscale;
@@ -469,9 +469,7 @@ int ScaleBSPMain( int argc, char **argv ){
if ( entities[i].classname_prefixed( "info_player_" ) ) {
vec[2] += spawn_ref;
}
vec[0] *= scale[0];
vec[1] *= scale[1];
vec[2] *= scale[2];
vec *= scale;
if ( entities[i].classname_prefixed( "info_player_" ) ) {
vec[2] -= spawn_ref;
}
@@ -483,7 +481,7 @@ int ScaleBSPMain( int argc, char **argv ){
if ( a == -1 || a == -2 ) { // z scale
axis = 2;
}
else if ( fabs( sin( DEG2RAD( a ) ) ) < 0.707 ) {
else if ( fabs( sin( degrees_to_radians( a ) ) ) < 0.707 ) {
axis = 0;
}
else{
@@ -510,34 +508,22 @@ int ScaleBSPMain( int argc, char **argv ){
/* scale models */
for ( i = 0; i < numBSPModels; i++ )
{
bspModels[ i ].mins[0] *= scale[0];
bspModels[ i ].mins[1] *= scale[1];
bspModels[ i ].mins[2] *= scale[2];
bspModels[ i ].maxs[0] *= scale[0];
bspModels[ i ].maxs[1] *= scale[1];
bspModels[ i ].maxs[2] *= scale[2];
bspModels[ i ].minmax.mins *= scale;
bspModels[ i ].minmax.maxs *= scale;
}
/* scale nodes */
for ( i = 0; i < numBSPNodes; i++ )
{
bspNodes[ i ].mins[0] *= scale[0];
bspNodes[ i ].mins[1] *= scale[1];
bspNodes[ i ].mins[2] *= scale[2];
bspNodes[ i ].maxs[0] *= scale[0];
bspNodes[ i ].maxs[1] *= scale[1];
bspNodes[ i ].maxs[2] *= scale[2];
bspNodes[ i ].minmax.mins *= scale;
bspNodes[ i ].minmax.maxs *= scale;
}
/* scale leafs */
for ( i = 0; i < numBSPLeafs; i++ )
{
bspLeafs[ i ].mins[0] *= scale[0];
bspLeafs[ i ].mins[1] *= scale[1];
bspLeafs[ i ].mins[2] *= scale[2];
bspLeafs[ i ].maxs[0] *= scale[0];
bspLeafs[ i ].maxs[1] *= scale[1];
bspLeafs[ i ].maxs[2] *= scale[2];
bspLeafs[ i ].minmax.mins *= scale;
bspLeafs[ i ].minmax.maxs *= scale;
}
if ( texscale ) {
@@ -562,7 +548,7 @@ int ScaleBSPMain( int argc, char **argv ){
bspDrawVerts[i].normal[0] /= scale[0];
bspDrawVerts[i].normal[1] /= scale[1];
bspDrawVerts[i].normal[2] /= scale[2];
VectorNormalize( bspDrawVerts[i].normal, bspDrawVerts[i].normal );
VectorNormalize( bspDrawVerts[i].normal );
}
if ( texscale ) {
@@ -600,29 +586,25 @@ int ScaleBSPMain( int argc, char **argv ){
if ( uniform ) {
for ( i = 0; i < numBSPPlanes; i++ )
{
bspPlanes[ i ].dist *= scale[0];
bspPlanes[ i ].dist() *= scale[0];
}
}
else
{
for ( i = 0; i < numBSPPlanes; i++ )
{
bspPlanes[ i ].normal[0] /= scale[0];
bspPlanes[ i ].normal[1] /= scale[1];
bspPlanes[ i ].normal[2] /= scale[2];
f = 1 / VectorLength( bspPlanes[i].normal );
VectorScale( bspPlanes[i].normal, f, bspPlanes[i].normal );
bspPlanes[ i ].dist *= f;
bspPlanes[i].normal() /= scale;
const double len = vector3_length( bspPlanes[i].normal() );
bspPlanes[i].normal() /= len;
bspPlanes[i].dist() /= len;
}
}
/* scale gridsize */
if ( !entities[ 0 ].read_keyvalue( vec, "gridsize" ) ) {
VectorCopy( gridSize, vec );
vec = gridSize;
}
vec[0] *= scale[0];
vec[1] *= scale[1];
vec[2] *= scale[2];
vec *= scale;
sprintf( str, "%f %f %f", vec[ 0 ], vec[ 1 ], vec[ 2 ] );
entities[ 0 ].setKeyValue( "gridsize", str );
@@ -647,8 +629,8 @@ int ScaleBSPMain( int argc, char **argv ){
int ShiftBSPMain( int argc, char **argv ){
int i, j;
vec3_t scale;
vec3_t vec;
Vector3 scale;
Vector3 vec;
char str[ 1024 ];
float spawn_ref = 0;
@@ -704,9 +686,7 @@ int ShiftBSPMain( int argc, char **argv ){
if ( e.classname_prefixed( "info_player_" ) ) {
vec[2] += spawn_ref;
}
vec[0] += scale[0];
vec[1] += scale[1];
vec[2] += scale[2];
vec += scale;
if ( e.classname_prefixed( "info_player_" ) ) {
vec[2] -= spawn_ref;
}
@@ -719,65 +699,48 @@ int ShiftBSPMain( int argc, char **argv ){
/* shift models */
for ( i = 0; i < numBSPModels; i++ )
{
bspModels[ i ].mins[0] += scale[0];
bspModels[ i ].mins[1] += scale[1];
bspModels[ i ].mins[2] += scale[2];
bspModels[ i ].maxs[0] += scale[0];
bspModels[ i ].maxs[1] += scale[1];
bspModels[ i ].maxs[2] += scale[2];
bspModels[ i ].minmax.mins += scale;
bspModels[ i ].minmax.maxs += scale;
}
/* shift nodes */
for ( i = 0; i < numBSPNodes; i++ )
{
bspNodes[ i ].mins[0] += scale[0];
bspNodes[ i ].mins[1] += scale[1];
bspNodes[ i ].mins[2] += scale[2];
bspNodes[ i ].maxs[0] += scale[0];
bspNodes[ i ].maxs[1] += scale[1];
bspNodes[ i ].maxs[2] += scale[2];
bspNodes[ i ].minmax.mins += scale;
bspNodes[ i ].minmax.maxs += scale;
}
/* shift leafs */
for ( i = 0; i < numBSPLeafs; i++ )
{
bspLeafs[ i ].mins[0] += scale[0];
bspLeafs[ i ].mins[1] += scale[1];
bspLeafs[ i ].mins[2] += scale[2];
bspLeafs[ i ].maxs[0] += scale[0];
bspLeafs[ i ].maxs[1] += scale[1];
bspLeafs[ i ].maxs[2] += scale[2];
bspLeafs[ i ].minmax.mins += scale;
bspLeafs[ i ].minmax.maxs += scale;
}
/* shift drawverts */
for ( i = 0; i < numBSPDrawVerts; i++ )
{
bspDrawVerts[i].xyz[0] += scale[0];
bspDrawVerts[i].xyz[1] += scale[1];
bspDrawVerts[i].xyz[2] += scale[2];
bspDrawVerts[i].xyz += scale;
}
/* shift planes */
vec3_t point;
for ( i = 0; i < numBSPPlanes; i++ )
{
//find point on plane
Vector3 point;
for ( j=0; j<3; j++ ){
//point[j] = bspPlanes[ i ].dist * bspPlanes[ i ].normal[j];
if ( fabs( bspPlanes[ i ].normal[j] ) > 0.5 ){
point[j] = bspPlanes[ i ].dist / bspPlanes[ i ].normal[j];
if ( fabs( bspPlanes[ i ].normal()[j] ) > 0.5 ){
point[j] = bspPlanes[ i ].dist() / bspPlanes[ i ].normal()[j];
point[(j+1)%3] = point[(j+2)%3] = 0;
break;
}
}
//shift point
for ( j=0; j<3; j++ ){
point[j] += scale[j];
}
point += scale;
//calc new plane dist
bspPlanes[ i ].dist = DotProduct( point, bspPlanes[ i ].normal );
bspPlanes[ i ].dist() = vector3_dot( point, bspPlanes[ i ].normal() );
}
/* scale gridsize */
+74 -98
View File
@@ -38,11 +38,9 @@
exports a map brush
*/
typedef vec_t vec2_t[2];
static vec_t Det3x3( vec_t a00, vec_t a01, vec_t a02,
vec_t a10, vec_t a11, vec_t a12,
vec_t a20, vec_t a21, vec_t a22 ){
static float Det3x3( float a00, float a01, float a02,
float a10, float a11, float a12,
float a20, float a21, float a22 ){
return
a00 * ( a11 * a22 - a12 * a21 )
- a01 * ( a10 * a22 - a12 * a20 )
@@ -53,10 +51,8 @@ void GetBestSurfaceTriangleMatchForBrushside( side_t *buildSide, bspDrawVert_t *
bspDrawSurface_t *s;
int i;
int t;
vec_t best = 0;
vec_t thisarea;
vec3_t normdiff;
vec3_t v1v0, v2v0, norm;
float best = 0;
float thisarea;
bspDrawVert_t *vert[3];
winding_t *polygon;
plane_t *buildPlane = &mapplanes[buildSide->planenum];
@@ -80,16 +76,13 @@ void GetBestSurfaceTriangleMatchForBrushside( side_t *buildSide, bspDrawVert_t *
vert[1] = &bspDrawVerts[s->firstVert + bspDrawIndexes[s->firstIndex + t + 1]];
vert[2] = &bspDrawVerts[s->firstVert + bspDrawIndexes[s->firstIndex + t + 2]];
if ( s->surfaceType == MST_PLANAR && VectorCompare( vert[0]->normal, vert[1]->normal ) && VectorCompare( vert[1]->normal, vert[2]->normal ) ) {
VectorSubtract( vert[0]->normal, buildPlane->normal, normdiff );
if ( VectorLength( normdiff ) >= normalEpsilon ) {
if ( vector3_length( vert[0]->normal - buildPlane->normal() ) >= normalEpsilon ) {
continue;
}
VectorSubtract( vert[1]->normal, buildPlane->normal, normdiff );
if ( VectorLength( normdiff ) >= normalEpsilon ) {
if ( vector3_length( vert[1]->normal - buildPlane->normal() ) >= normalEpsilon ) {
continue;
}
VectorSubtract( vert[2]->normal, buildPlane->normal, normdiff );
if ( VectorLength( normdiff ) >= normalEpsilon ) {
if ( vector3_length( vert[2]->normal - buildPlane->normal() ) >= normalEpsilon ) {
continue;
}
}
@@ -97,23 +90,20 @@ void GetBestSurfaceTriangleMatchForBrushside( side_t *buildSide, bspDrawVert_t *
{
// this is more prone to roundoff errors, but with embedded
// models, there is no better way
VectorSubtract( vert[1]->xyz, vert[0]->xyz, v1v0 );
VectorSubtract( vert[2]->xyz, vert[0]->xyz, v2v0 );
CrossProduct( v2v0, v1v0, norm );
VectorNormalize( norm, norm );
VectorSubtract( norm, buildPlane->normal, normdiff );
if ( VectorLength( normdiff ) >= normalEpsilon ) {
Plane3f plane;
PlaneFromPoints( plane, vert[0]->xyz, vert[1]->xyz, vert[2]->xyz );
if ( vector3_length( plane.normal() - buildPlane->normal() ) >= normalEpsilon ) {
continue;
}
}
// fixme? better distance epsilon
if ( abs( DotProduct( vert[0]->xyz, buildPlane->normal ) - buildPlane->dist ) > 1 ) {
if ( abs( plane3_distance_to_point( buildPlane->plane, vert[0]->xyz ) ) > 1 ) {
continue;
}
if ( abs( DotProduct( vert[1]->xyz, buildPlane->normal ) - buildPlane->dist ) > 1 ) {
if ( abs( plane3_distance_to_point( buildPlane->plane, vert[1]->xyz ) ) > 1 ) {
continue;
}
if ( abs( DotProduct( vert[2]->xyz, buildPlane->normal ) - buildPlane->dist ) > 1 ) {
if ( abs( plane3_distance_to_point( buildPlane->plane, vert[2]->xyz ) ) > 1 ) {
continue;
}
// Okay. Correct surface type, correct shader, correct plane. Let's start with the business...
@@ -123,16 +113,12 @@ void GetBestSurfaceTriangleMatchForBrushside( side_t *buildSide, bspDrawVert_t *
// 0: 1, 2
// 1: 2, 0
// 2; 0, 1
vec3_t *v1 = &vert[( i + 1 ) % 3]->xyz;
vec3_t *v2 = &vert[( i + 2 ) % 3]->xyz;
vec3_t triNormal;
vec_t triDist;
vec3_t sideDirection;
// we now need to generate triNormal and triDist so that they represent the plane spanned by normal and (v2 - v1).
VectorSubtract( *v2, *v1, sideDirection );
CrossProduct( sideDirection, buildPlane->normal, triNormal );
triDist = DotProduct( *v1, triNormal );
ChopWindingInPlace( &polygon, triNormal, triDist, distanceEpsilon );
const Vector3& v1 = vert[( i + 1 ) % 3]->xyz;
const Vector3& v2 = vert[( i + 2 ) % 3]->xyz;
// we now need to generate the plane spanned by normal and (v2 - v1).
Plane3f plane( vector3_cross( v2 - v1, buildPlane->normal() ), 0 );
plane.dist() = vector3_dot( v1, plane.normal() );
ChopWindingInPlace( &polygon, plane, distanceEpsilon );
if ( !polygon ) {
goto exwinding;
}
@@ -157,7 +143,7 @@ exwinding:
}
#define FRAC( x ) ( ( x ) - floor( x ) )
static void ConvertOriginBrush( FILE *f, int num, vec3_t origin, bool brushPrimitives ){
static void ConvertOriginBrush( FILE *f, int num, const Vector3& origin, bool brushPrimitives ){
int originSize = 256;
char pattern[6][7][4] = {
@@ -217,14 +203,14 @@ static void ConvertOriginBrush( FILE *f, int num, vec3_t origin, bool brushPrimi
fprintf( f, "\t}\n\n" );
}
static void ConvertBrushFast( FILE *f, int num, bspBrush_t *brush, vec3_t origin, bool brushPrimitives ){
static void ConvertBrushFast( FILE *f, int num, bspBrush_t *brush, const Vector3& origin, bool brushPrimitives ){
int i;
bspBrushSide_t *side;
side_t *buildSide;
bspShader_t *shader;
const char *texture;
plane_t *buildPlane;
vec3_t pts[ 3 ];
Vector3 pts[ 3 ];
/* clear out build brush */
@@ -325,12 +311,11 @@ static void ConvertBrushFast( FILE *f, int num, bspBrush_t *brush, vec3_t origin
}
{
vec3_t vecs[ 2 ];
MakeNormalVectors( buildPlane->normal, vecs[ 0 ], vecs[ 1 ] );
VectorMA( vec3_origin, buildPlane->dist, buildPlane->normal, pts[ 0 ] );
VectorAdd( pts[ 0 ], origin, pts[ 0 ] );
VectorMA( pts[ 0 ], 256.0f, vecs[ 0 ], pts[ 1 ] );
VectorMA( pts[ 0 ], 256.0f, vecs[ 1 ], pts[ 2 ] );
Vector3 vecs[ 2 ];
MakeNormalVectors( buildPlane->normal(), vecs[ 0 ], vecs[ 1 ] );
pts[ 0 ] = buildPlane->normal() * buildPlane->dist() + origin;
pts[ 1 ] = pts[ 0 ] + vecs[ 0 ] * 256.0f;
pts[ 2 ] = pts[ 0 ] + vecs[ 1 ] * 256.0f;
}
{
@@ -366,14 +351,14 @@ static void ConvertBrushFast( FILE *f, int num, bspBrush_t *brush, vec3_t origin
fprintf( f, "\t}\n\n" );
}
static void ConvertBrush( FILE *f, int num, bspBrush_t *brush, vec3_t origin, bool brushPrimitives ){
static void ConvertBrush( FILE *f, int num, bspBrush_t *brush, const Vector3& origin, bool brushPrimitives ){
int i, j;
bspBrushSide_t *side;
side_t *buildSide;
bspShader_t *shader;
const char *texture;
plane_t *buildPlane;
vec3_t pts[ 3 ];
Vector3 pts[ 3 ];
bspDrawVert_t *vert[3];
@@ -469,8 +454,8 @@ static void ConvertBrush( FILE *f, int num, bspBrush_t *brush, vec3_t origin, bo
// st-texcoords -> texMat block
// start out with dummy
VectorSet( buildSide->texMat[0], 1 / 32.0, 0, 0 );
VectorSet( buildSide->texMat[1], 0, 1 / 32.0, 0 );
buildSide->texMat[0] = { 1 / 32.0, 0, 0 };
buildSide->texMat[1] = { 0, 1 / 32.0, 0 };
// find surface for this side (by brute force)
// surface format:
@@ -490,11 +475,11 @@ static void ConvertBrush( FILE *f, int num, bspBrush_t *brush, vec3_t origin, bo
/* recheck and fix winding points, fails occur somehow */
int match = 0;
for ( j = 0; j < buildSide->winding->numpoints; j++ ){
if ( fabs( DotProduct( buildSide->winding->p[ j ], buildPlane->normal ) - buildPlane->dist ) >= distanceEpsilon ) {
if ( fabs( plane3_distance_to_point( buildPlane->plane, buildSide->winding->p[ j ] ) ) >= distanceEpsilon ) {
continue;
}
else{
VectorCopy( buildSide->winding->p[ j ], pts[ match ] );
pts[ match ] = buildSide->winding->p[ j ];
match++;
/* got 3 fine points? */
if( match > 2 )
@@ -504,9 +489,9 @@ static void ConvertBrush( FILE *f, int num, bspBrush_t *brush, vec3_t origin, bo
if( match > 2 ){
//Sys_Printf( "pointsKK " );
vec4_t testplane;
if ( PlaneFromPoints( testplane, pts[0], pts[1], pts[2] ) ){
if( !PlaneEqual( buildPlane, testplane, testplane[3] ) ){
Plane3f testplane;
if ( PlaneFromPoints( testplane, pts ) ){
if( !PlaneEqual( buildPlane, testplane ) ){
//Sys_Printf( "1: %f %f %f %f\n2: %f %f %f %f\n", buildPlane->normal[0], buildPlane->normal[1], buildPlane->normal[2], buildPlane->dist, testplane[0], testplane[1], testplane[2], testplane[3] );
match--;
//Sys_Printf( "planentEQ " );
@@ -522,34 +507,33 @@ static void ConvertBrush( FILE *f, int num, bspBrush_t *brush, vec3_t origin, bo
//Sys_Printf( "ok " );
/* offset by origin */
for ( j = 0; j < 3; j++ )
VectorAdd( pts[ j ], origin, pts[ j ] );
pts[ j ] += origin;
}
else{
vec3_t vecs[ 2 ];
MakeNormalVectors( buildPlane->normal, vecs[ 0 ], vecs[ 1 ] );
VectorMA( vec3_origin, buildPlane->dist, buildPlane->normal, pts[ 0 ] );
VectorAdd( pts[ 0 ], origin, pts[ 0 ] );
VectorMA( pts[ 0 ], 256.0f, vecs[ 0 ], pts[ 1 ] );
VectorMA( pts[ 0 ], 256.0f, vecs[ 1 ], pts[ 2 ] );
Vector3 vecs[ 2 ];
MakeNormalVectors( buildPlane->normal(), vecs[ 0 ], vecs[ 1 ] );
pts[ 0 ] = buildPlane->normal() * buildPlane->dist() + origin;
pts[ 1 ] = pts[ 0 ] + vecs[ 0 ] * 256.0f;
pts[ 2 ] = pts[ 0 ] + vecs[ 1 ] * 256.0f;
//Sys_Printf( "not\n" );
}
if ( vert[0] && vert[1] && vert[2] ) {
if ( brushPrimitives ) {
int i;
vec3_t texX, texY;
vec2_t xyI, xyJ, xyK;
vec2_t stI, stJ, stK;
vec_t D, D0, D1, D2;
Vector3 texX, texY;
float xyI[2], xyJ[2], xyK[2];
float stI[2], stJ[2], stK[2];
float D, D0, D1, D2;
ComputeAxisBase( buildPlane->normal, texX, texY );
ComputeAxisBase( buildPlane->normal(), texX, texY );
xyI[0] = DotProduct( vert[0]->xyz, texX );
xyI[1] = DotProduct( vert[0]->xyz, texY );
xyJ[0] = DotProduct( vert[1]->xyz, texX );
xyJ[1] = DotProduct( vert[1]->xyz, texY );
xyK[0] = DotProduct( vert[2]->xyz, texX );
xyK[1] = DotProduct( vert[2]->xyz, texY );
xyI[0] = vector3_dot( vert[0]->xyz, texX );
xyI[1] = vector3_dot( vert[0]->xyz, texY );
xyJ[0] = vector3_dot( vert[1]->xyz, texX );
xyJ[1] = vector3_dot( vert[1]->xyz, texY );
xyK[0] = vector3_dot( vert[2]->xyz, texX );
xyK[1] = vector3_dot( vert[2]->xyz, texY );
stI[0] = vert[0]->st[0]; stI[1] = vert[0]->st[1];
stJ[0] = vert[1]->st[0]; stJ[1] = vert[1]->st[1];
stK[0] = vert[2]->st[0]; stK[1] = vert[2]->st[1];
@@ -581,12 +565,12 @@ static void ConvertBrush( FILE *f, int num, bspBrush_t *brush, vec3_t origin, bo
xyJ[0], xyJ[1], stJ[i],
xyK[0], xyK[1], stK[i]
);
VectorSet( buildSide->texMat[i], D0 / D, D1 / D, D2 / D );
buildSide->texMat[i] = { D0 / D, D1 / D, D2 / D };
}
}
else{
fprintf( stderr, "degenerate triangle found when solving texMat equations for\n(%f %f %f) (%f %f %f) (%f %f %f)\n( %f %f %f )\n( %f %f %f ) -> ( %f %f )\n( %f %f %f ) -> ( %f %f )\n( %f %f %f ) -> ( %f %f )\n",
buildPlane->normal[0], buildPlane->normal[1], buildPlane->normal[2],
buildPlane->normal()[0], buildPlane->normal()[1], buildPlane->normal()[2],
vert[0]->normal[0], vert[0]->normal[1], vert[0]->normal[2],
texX[0], texX[1], texX[2], texY[0], texY[1], texY[2],
vert[0]->xyz[0], vert[0]->xyz[1], vert[0]->xyz[2], xyI[0], xyI[1],
@@ -611,13 +595,13 @@ static void ConvertBrush( FILE *f, int num, bspBrush_t *brush, vec3_t origin, bo
{
// invert QuakeTextureVecs
int i;
vec3_t vecs[2];
Vector3 vecs[2];
int sv, tv;
vec2_t stI, stJ, stK;
vec3_t sts[2];
vec2_t shift, scale;
vec_t rotate;
vec_t D, D0, D1, D2;
float stI[2], stJ[2], stK[2];
Vector3 sts[2];
float shift[2], scale[2];
float rotate;
float D, D0, D1, D2;
TextureAxisFromPlane( buildPlane, vecs[0], vecs[1] );
if ( vecs[0][0] ) {
@@ -666,18 +650,18 @@ static void ConvertBrush( FILE *f, int num, bspBrush_t *brush, vec3_t origin, bo
vert[1]->xyz[sv], vert[1]->xyz[tv], stJ[i],
vert[2]->xyz[sv], vert[2]->xyz[tv], stK[i]
);
VectorSet( sts[i], D0 / D, D1 / D, D2 / D );
sts[i] = { D0 / D, D1 / D, D2 / D };
//Sys_Printf( "%.3f %.3f %.3f \n", sts[i][0], sts[i][1], sts[i][2] );
}
}
else{
fprintf( stderr, "degenerate triangle found when solving texDef equations\n" ); // FIXME add stuff here
VectorSet( sts[0], 2.f, 0.f, 0.f );
VectorSet( sts[1], 0.f, -2.f, 0.f );
sts[0] = { 2.f, 0.f, 0.f };
sts[1] = { 0.f, -2.f, 0.f };
}
// now we must solve:
// // now we must invert:
// ang = rotate / 180 * Q_PI;
// ang = degrees_to_radians( rotate );
// sinv = sin(ang);
// cosv = cos(ang);
// ns = cosv * vecs[0][sv];
@@ -690,7 +674,7 @@ static void ConvertBrush( FILE *f, int num, bspBrush_t *brush, vec3_t origin, bo
// vecsrotscaled[1][tv] = nt / scale[1];
scale[0] = 1.0 / sqrt( sts[0][0] * sts[0][0] + sts[0][1] * sts[0][1] );
scale[1] = 1.0 / sqrt( sts[1][0] * sts[1][0] + sts[1][1] * sts[1][1] );
rotate = atan2( sts[0][1] * vecs[0][sv] - sts[1][0] * vecs[1][tv], sts[0][0] * vecs[0][sv] + sts[1][1] * vecs[1][tv] ) * ( 180.0f / Q_PI );
rotate = radians_to_degrees( atan2( sts[0][1] * vecs[0][sv] - sts[1][0] * vecs[1][tv], sts[0][0] * vecs[0][sv] + sts[1][1] * vecs[1][tv] ) );
shift[0] = buildSide->shaderInfo->shaderWidth * FRAC( sts[0][2] / buildSide->shaderInfo->shaderWidth );
shift[1] = buildSide->shaderInfo->shaderHeight * FRAC( sts[1][2] / buildSide->shaderInfo->shaderHeight );
@@ -708,7 +692,6 @@ static void ConvertBrush( FILE *f, int num, bspBrush_t *brush, vec3_t origin, bo
}
else
{
//vec3_t vecs[ 2 ];
if ( !striEqualPrefix( buildSide->shaderInfo->shader, "textures/common/" ) ) {
if ( !strEqual( buildSide->shaderInfo->shader, "noshader" ) ) {
if ( !strEqual( buildSide->shaderInfo->shader, "default" ) ) {
@@ -717,12 +700,7 @@ static void ConvertBrush( FILE *f, int num, bspBrush_t *brush, vec3_t origin, bo
}
}
}
/*
MakeNormalVectors( buildPlane->normal, vecs[ 0 ], vecs[ 1 ] );
VectorMA( vec3_origin, buildPlane->dist, buildPlane->normal, pts[ 0 ] );
VectorMA( pts[ 0 ], 256.0f, vecs[ 1 ], pts[ 2 ] );
VectorMA( pts[ 0 ], 256.0f, vecs[ 0 ], pts[ 1 ] );
*/
if ( brushPrimitives ) {
fprintf( f, "\t\t( %.3f %.3f %.3f ) ( %.3f %.3f %.3f ) ( %.3f %.3f %.3f ) ( ( %.8f %.8f %.8f ) ( %.8f %.8f %.8f ) ) %s %d 0 0\n",
pts[ 0 ][ 0 ], pts[ 0 ][ 1 ], pts[ 0 ][ 2 ],
@@ -828,12 +806,11 @@ for ( i = 0; i < brush->numSides; i++ )
*/
static void ConvertPatch( FILE *f, int num, bspDrawSurface_t *ds, vec3_t origin ){
static void ConvertPatch( FILE *f, int num, bspDrawSurface_t *ds, const Vector3& origin ){
int x, y;
bspShader_t *shader;
const char *texture;
bspDrawVert_t *dv;
vec3_t xyz;
/* only patches */
@@ -877,7 +854,7 @@ static void ConvertPatch( FILE *f, int num, bspDrawSurface_t *ds, vec3_t origin
dv = &bspDrawVerts[ ds->firstVert + ( y * ds->patchWidth ) + x ];
/* offset it */
VectorAdd( origin, dv->xyz, xyz );
const Vector3 xyz = dv->xyz + origin;
/* print vertex */
fprintf( f, " ( %f %f %f %f %f )", xyz[ 0 ], xyz[ 1 ], xyz[ 2 ], dv->st[ 0 ], dv->st[ 1 ] );
@@ -900,7 +877,7 @@ static void ConvertPatch( FILE *f, int num, bspDrawSurface_t *ds, vec3_t origin
exports a bsp model to a map file
*/
static void ConvertModel( FILE *f, bspModel_t *model, int modelNum, vec3_t origin, bool brushPrimitives ){
static void ConvertModel( FILE *f, bspModel_t *model, int modelNum, const Vector3& origin, bool brushPrimitives ){
int i, num;
bspBrush_t *brush;
bspDrawSurface_t *ds;
@@ -911,9 +888,8 @@ static void ConvertModel( FILE *f, bspModel_t *model, int modelNum, vec3_t origi
AUTOEXPAND_BY_REALLOC( mapplanes, nummapplanes, allocatedmapplanes, 1024 );
for ( i = 0; i < numBSPPlanes; i++ )
{
VectorCopy( bspPlanes[ i ].normal, mapplanes[ i ].normal );
mapplanes[ i ].dist = bspPlanes[ i ].dist;
mapplanes[ i ].type = PlaneTypeForNormal( mapplanes[ i ].normal );
mapplanes[ i ].plane = bspPlanes[ i ];
mapplanes[ i ].type = PlaneTypeForNormal( mapplanes[ i ].normal() );
mapplanes[ i ].hash_chain = 0;
}
@@ -1048,7 +1024,7 @@ int ConvertBSPToMap_Ext( char *bspName, bool brushPrimitives ){
model = &bspModels[ modelNum ];
/* get entity origin */
vec3_t origin;
Vector3 origin;
e->vectorForKey( "origin", origin );
/* convert model */
+3 -3
View File
@@ -44,7 +44,7 @@ int lastLightmap = -1;
int objVertexCount = 0;
int objLastShaderNum = -1;
static void ConvertSurfaceToOBJ( FILE *f, bspModel_t *model, int modelNum, bspDrawSurface_t *ds, int surfaceNum, vec3_t origin, const int* lmIndices ){
static void ConvertSurfaceToOBJ( FILE *f, bspModel_t *model, int modelNum, bspDrawSurface_t *ds, int surfaceNum, const Vector3& origin, const int* lmIndices ){
int i, v, a, b, c;
bspDrawVert_t *dv;
@@ -127,7 +127,7 @@ static void ConvertSurfaceToOBJ( FILE *f, bspModel_t *model, int modelNum, bspDr
exports a bsp model to an ase chunk
*/
static void ConvertModelToOBJ( FILE *f, bspModel_t *model, int modelNum, vec3_t origin, const int* lmIndices ){
static void ConvertModelToOBJ( FILE *f, bspModel_t *model, int modelNum, const Vector3& origin, const int* lmIndices ){
int i, s;
bspDrawSurface_t *ds;
@@ -358,7 +358,7 @@ int ConvertBSPToOBJ( char *bspName ){
model = &bspModels[ modelNum ];
/* get entity origin */
vec3_t origin;
Vector3 origin;
e->vectorForKey( "origin", origin );
/* convert model */
+108 -168
View File
@@ -38,12 +38,12 @@
struct decalProjector_t
{
shaderInfo_t *si;
vec3_t mins, maxs;
vec3_t center;
MinMax minmax;
Vector3 center;
float radius, radius2;
int numPlanes; /* either 5 or 6, for quad or triangle projectors */
vec4_t planes[ 6 ];
vec4_t texMat[ 2 ];
Plane3f planes[ 6 ];
Vector4 texMat[ 2 ];
};
static int numProjectors = 0;
@@ -51,37 +51,10 @@ static decalProjector_t projectors[ MAX_PROJECTORS ];
static int numDecalSurfaces = 0;
static vec3_t entityOrigin;
static Vector3 entityOrigin;
/*
DVectorNormalize()
normalizes a vector, returns the length, operates using doubles
*/
typedef double dvec_t;
typedef dvec_t dvec3_t[ 3 ];
dvec_t DVectorNormalize( dvec3_t in, dvec3_t out ){
dvec_t len, ilen;
len = (dvec_t) sqrt( in[ 0 ] * in[ 0 ] + in[ 1 ] * in[ 1 ] + in[ 2 ] * in[ 2 ] );
if ( len == 0.0 ) {
VectorClear( out );
return 0.0;
}
ilen = 1.0 / len;
out[ 0 ] = in[ 0 ] * ilen;
out[ 1 ] = in[ 1 ] * ilen;
out[ 2 ] = in[ 2 ] * ilen;
return len;
}
/*
MakeTextureMatrix()
@@ -91,21 +64,18 @@ dvec_t DVectorNormalize( dvec3_t in, dvec3_t out ){
#define Vector2Subtract( a,b,c ) ( ( c )[ 0 ] = ( a )[ 0 ] - ( b )[ 0 ], ( c )[ 1 ] = ( a )[ 1 ] - ( b )[ 1 ] )
static bool MakeTextureMatrix( decalProjector_t *dp, vec4_t projection, bspDrawVert_t *a, bspDrawVert_t *b, bspDrawVert_t *c ){
static bool MakeTextureMatrix( decalProjector_t *dp, const Plane3f& projection, bspDrawVert_t *a, bspDrawVert_t *b, bspDrawVert_t *c ){
int i, j;
double bb, s, t, d;
dvec3_t pa, pb, pc;
dvec3_t bary, xyz;
dvec3_t vecs[ 3 ], axis[ 3 ], lengths;
double bb, s, t;
DoubleVector3 pa, pb, pc;
DoubleVector3 bary, xyz;
DoubleVector3 vecs[ 3 ], axis[ 3 ], lengths;
/* project triangle onto plane of projection */
d = DotProduct( a->xyz, projection ) - projection[ 3 ];
VectorMA( a->xyz, -d, projection, pa );
d = DotProduct( b->xyz, projection ) - projection[ 3 ];
VectorMA( b->xyz, -d, projection, pb );
d = DotProduct( c->xyz, projection ) - projection[ 3 ];
VectorMA( c->xyz, -d, projection, pc );
pa = plane3_project_point( projection, a->xyz );
pb = plane3_project_point( projection, b->xyz );
pc = plane3_project_point( projection, c->xyz );
/* two methods */
#if 1
@@ -142,8 +112,8 @@ static bool MakeTextureMatrix( decalProjector_t *dp, vec4_t projection, bspDrawV
xyz[ 1 ] = bary[ 0 ] * pa[ 1 ] + bary[ 1 ] * pb[ 1 ] + bary[ 2 ] * pc[ 1 ];
xyz[ 2 ] = bary[ 0 ] * pa[ 2 ] + bary[ 1 ] * pb[ 2 ] + bary[ 2 ] * pc[ 2 ];
//% VectorSubtract( xyz, origin, vecs[ 0 ] );
VectorSubtract( xyz, pa, vecs[ 0 ] );
//% vecs[ 0 ] = xyz - origin;
vecs[ 0 ] = xyz - pa;
/* calculate t vector */
s = a->st[ 0 ] + 0.0;
@@ -156,29 +126,31 @@ static bool MakeTextureMatrix( decalProjector_t *dp, vec4_t projection, bspDrawV
xyz[ 1 ] = bary[ 0 ] * pa[ 1 ] + bary[ 1 ] * pb[ 1 ] + bary[ 2 ] * pc[ 1 ];
xyz[ 2 ] = bary[ 0 ] * pa[ 2 ] + bary[ 1 ] * pb[ 2 ] + bary[ 2 ] * pc[ 2 ];
//% VectorSubtract( xyz, origin, vecs[ 1 ] );
VectorSubtract( xyz, pa, vecs[ 1 ] );
//% vecs[ 1 ] = xyz - origin;
vecs[ 1 ] = xyz - pa;
/* calcuate r vector */
VectorScale( projection, -1.0, vecs[ 2 ] );
vecs[ 2 ] = -projection.normal();
/* calculate transform axis */
for ( i = 0; i < 3; i++ )
lengths[ i ] = DVectorNormalize( vecs[ i ], axis[ i ] );
for ( i = 0; i < 3; i++ ){
axis[ i ] = vecs[ i ];
lengths[ i ] = VectorNormalize( axis[ i ] );
}
for ( i = 0; i < 2; i++ )
for ( j = 0; j < 3; j++ )
dp->texMat[ i ][ j ] = lengths[ i ] > 0.0 ? ( axis[ i ][ j ] / lengths[ i ] ) : 0.0;
dp->texMat[ i ][ j ] = lengths[ i ] != 0.0 ? ( axis[ i ][ j ] / lengths[ i ] ) : 0.0;
//% dp->texMat[ i ][ j ] = fabs( vecs[ i ][ j ] ) > 0.0 ? (1.0 / vecs[ i ][ j ]) : 0.0;
//% dp->texMat[ i ][ j ] = axis[ i ][ j ] > 0.0 ? (1.0 / axis[ i ][ j ]) : 0.0;
/* calculalate translation component */
dp->texMat[ 0 ][ 3 ] = a->st[ 0 ] - DotProduct( a->xyz, dp->texMat[ 0 ] );
dp->texMat[ 1 ][ 3 ] = a->st[ 1 ] - DotProduct( a->xyz, dp->texMat[ 1 ] );
dp->texMat[ 0 ][ 3 ] = a->st[ 0 ] - vector3_dot( a->xyz, dp->texMat[ 0 ].vec3() );
dp->texMat[ 1 ][ 3 ] = a->st[ 1 ] - vector3_dot( a->xyz, dp->texMat[ 1 ].vec3() );
}
#else
{
int k;
dvec3_t origin, deltas[ 3 ];
DoubleVector3 deltas[ 3 ];
double texDeltas[ 3 ][ 2 ];
double delta, texDelta;
@@ -186,9 +158,9 @@ static bool MakeTextureMatrix( decalProjector_t *dp, vec4_t projection, bspDrawV
/* new code */
/* calculate deltas */
VectorSubtract( pa, pb, deltas[ 0 ] );
VectorSubtract( pa, pc, deltas[ 1 ] );
VectorSubtract( pb, pc, deltas[ 2 ] );
deltas[ 0 ] = pa - pb;
deltas[ 1 ] = pa - pc;
deltas[ 2 ] = pb - pc;
Vector2Subtract( a->st, b->st, texDeltas[ 0 ] );
Vector2Subtract( a->st, c->st, texDeltas[ 1 ] );
Vector2Subtract( b->st, c->st, texDeltas[ 2 ] );
@@ -223,42 +195,42 @@ static bool MakeTextureMatrix( decalProjector_t *dp, vec4_t projection, bspDrawV
}
/* set translation component */
dp->texMat[ i ][ 3 ] = a->st[ i ] - DotProduct( pa, dp->texMat[ i ] );
dp->texMat[ i ][ 3 ] = a->st[ i ] - vector3_dot( pa, dp->texMat[ i ].vec3() );
}
}
#endif
/* debug code */
#if 1
Sys_Printf( "Mat: [ %f %f %f %f ] [ %f %f %f %f ] Theta: %f (%f)\n",
Sys_Printf( "Mat: [ %f %f %f %f ] [ %f %f %f %f ] Theta: %lf (%lf)\n",
dp->texMat[ 0 ][ 0 ], dp->texMat[ 0 ][ 1 ], dp->texMat[ 0 ][ 2 ], dp->texMat[ 0 ][ 3 ],
dp->texMat[ 1 ][ 0 ], dp->texMat[ 1 ][ 1 ], dp->texMat[ 1 ][ 2 ], dp->texMat[ 1 ][ 3 ],
RAD2DEG( acos( DotProduct( dp->texMat[ 0 ], dp->texMat[ 1 ] ) ) ),
RAD2DEG( acos( DotProduct( axis[ 0 ], axis[ 1 ] ) ) ) );
radians_to_degrees( acos( vector3_dot( dp->texMat[ 0 ].vec3(), dp->texMat[ 1 ].vec3() ) ) ),
radians_to_degrees( acos( vector3_dot( axis[ 0 ], axis[ 1 ] ) ) ) );
Sys_Printf( "XYZ: %f %f %f ST: %f %f ST(t): %f %f\n",
a->xyz[ 0 ], a->xyz[ 1 ], a->xyz[ 2 ],
a->st[ 0 ], a->st[ 1 ],
DotProduct( a->xyz, dp->texMat[ 0 ] ) + dp->texMat[ 0 ][ 3 ], DotProduct( a->xyz, dp->texMat[ 1 ] ) + dp->texMat[ 1 ][ 3 ] );
vector3_dot( a->xyz, dp->texMat[ 0 ].vec3() ) + dp->texMat[ 0 ][ 3 ], vector3_dot( a->xyz, dp->texMat[ 1 ].vec3() ) + dp->texMat[ 1 ][ 3 ] );
#endif
/* test texture matrix */
s = DotProduct( a->xyz, dp->texMat[ 0 ] ) + dp->texMat[ 0 ][ 3 ];
t = DotProduct( a->xyz, dp->texMat[ 1 ] ) + dp->texMat[ 1 ][ 3 ];
s = vector3_dot( a->xyz, dp->texMat[ 0 ].vec3() ) + dp->texMat[ 0 ][ 3 ];
t = vector3_dot( a->xyz, dp->texMat[ 1 ].vec3() ) + dp->texMat[ 1 ][ 3 ];
if ( fabs( s - a->st[ 0 ] ) > 0.01 || fabs( t - a->st[ 1 ] ) > 0.01 ) {
Sys_Printf( "Bad texture matrix! (A) (%f, %f) != (%f, %f)\n",
s, t, a->st[ 0 ], a->st[ 1 ] );
//% return false;
}
s = DotProduct( b->xyz, dp->texMat[ 0 ] ) + dp->texMat[ 0 ][ 3 ];
t = DotProduct( b->xyz, dp->texMat[ 1 ] ) + dp->texMat[ 1 ][ 3 ];
s = vector3_dot( b->xyz, dp->texMat[ 0 ].vec3() ) + dp->texMat[ 0 ][ 3 ];
t = vector3_dot( b->xyz, dp->texMat[ 1 ].vec3() ) + dp->texMat[ 1 ][ 3 ];
if ( fabs( s - b->st[ 0 ] ) > 0.01 || fabs( t - b->st[ 1 ] ) > 0.01 ) {
Sys_Printf( "Bad texture matrix! (B) (%f, %f) != (%f, %f)\n",
s, t, b->st[ 0 ], b->st[ 1 ] );
//% return false;
}
s = DotProduct( c->xyz, dp->texMat[ 0 ] ) + dp->texMat[ 0 ][ 3 ];
t = DotProduct( c->xyz, dp->texMat[ 1 ] ) + dp->texMat[ 1 ][ 3 ];
s = vector3_dot( c->xyz, dp->texMat[ 0 ].vec3() ) + dp->texMat[ 0 ][ 3 ];
t = vector3_dot( c->xyz, dp->texMat[ 1 ].vec3() ) + dp->texMat[ 1 ][ 3 ];
if ( fabs( s - c->st[ 0 ] ) > 0.01 || fabs( t - c->st[ 1 ] ) > 0.01 ) {
Sys_Printf( "Bad texture matrix! (C) (%f, %f) != (%f, %f)\n",
s, t, c->st[ 0 ], c->st[ 1 ] );
@@ -277,7 +249,7 @@ static bool MakeTextureMatrix( decalProjector_t *dp, vec4_t projection, bspDrawV
note: non-normalized axes will screw up the plane transform
*/
static void TransformDecalProjector( decalProjector_t *in, vec3_t axis[ 3 ], vec3_t origin, decalProjector_t *out ){
static void TransformDecalProjector( decalProjector_t *in, Vector3 axis[ 3 ], const Vector3& origin, decalProjector_t *out ){
int i;
@@ -286,28 +258,28 @@ static void TransformDecalProjector( decalProjector_t *in, vec3_t axis[ 3 ], vec
out->numPlanes = in->numPlanes;
/* translate bounding box and sphere (note: rotated projector bounding box will be invalid!) */
VectorSubtract( in->mins, origin, out->mins );
VectorSubtract( in->maxs, origin, out->maxs );
VectorSubtract( in->center, origin, out->center );
out->minmax.mins = in->minmax.mins - origin;
out->minmax.maxs = in->minmax.maxs - origin;
out->center = in->center - origin;
out->radius = in->radius;
out->radius2 = in->radius2;
/* translate planes */
for ( i = 0; i < in->numPlanes; i++ )
{
out->planes[ i ][ 0 ] = DotProduct( in->planes[ i ], axis[ 0 ] );
out->planes[ i ][ 1 ] = DotProduct( in->planes[ i ], axis[ 1 ] );
out->planes[ i ][ 2 ] = DotProduct( in->planes[ i ], axis[ 2 ] );
out->planes[ i ][ 3 ] = in->planes[ i ][ 3 ] - DotProduct( out->planes[ i ], origin );
out->planes[ i ].a = vector3_dot( in->planes[ i ].normal(), axis[ 0 ] );
out->planes[ i ].b = vector3_dot( in->planes[ i ].normal(), axis[ 1 ] );
out->planes[ i ].c = vector3_dot( in->planes[ i ].normal(), axis[ 2 ] );
out->planes[ i ].d = in->planes[ i ].dist() - vector3_dot( out->planes[ i ].normal(), origin );
}
/* translate texture matrix */
for ( i = 0; i < 2; i++ )
{
out->texMat[ i ][ 0 ] = DotProduct( in->texMat[ i ], axis[ 0 ] );
out->texMat[ i ][ 1 ] = DotProduct( in->texMat[ i ], axis[ 1 ] );
out->texMat[ i ][ 2 ] = DotProduct( in->texMat[ i ], axis[ 2 ] );
out->texMat[ i ][ 3 ] = in->texMat[ i ][ 3 ] + DotProduct( out->texMat[ i ], origin );
out->texMat[ i ][ 0 ] = vector3_dot( in->texMat[ i ].vec3(), axis[ 0 ] );
out->texMat[ i ][ 1 ] = vector3_dot( in->texMat[ i ].vec3(), axis[ 1 ] );
out->texMat[ i ][ 2 ] = vector3_dot( in->texMat[ i ].vec3(), axis[ 2 ] );
out->texMat[ i ][ 3 ] = vector3_dot( out->texMat[ i ].vec3(), origin ) + in->texMat[ i ][ 3 ];
}
}
@@ -318,10 +290,9 @@ static void TransformDecalProjector( decalProjector_t *in, vec3_t axis[ 3 ], vec
creates a new decal projector from a triangle
*/
static int MakeDecalProjector( shaderInfo_t *si, vec4_t projection, float distance, int numVerts, bspDrawVert_t **dv ){
static int MakeDecalProjector( shaderInfo_t *si, const Plane3f& projection, float distance, int numVerts, bspDrawVert_t **dv ){
int i, j;
decalProjector_t *dp;
vec3_t xyz;
/* dummy check */
@@ -349,19 +320,16 @@ static int MakeDecalProjector( shaderInfo_t *si, vec4_t projection, float distan
}
/* bound the projector */
ClearBounds( dp->mins, dp->maxs );
dp->minmax.clear();
for ( i = 0; i < numVerts; i++ )
{
AddPointToBounds( dv[ i ]->xyz, dp->mins, dp->maxs );
VectorMA( dv[ i ]->xyz, distance, projection, xyz );
AddPointToBounds( xyz, dp->mins, dp->maxs );
dp->minmax.extend( dv[ i ]->xyz );
dp->minmax.extend( dv[ i ]->xyz + projection.normal() * distance );
}
/* make bouding sphere */
VectorAdd( dp->mins, dp->maxs, dp->center );
VectorScale( dp->center, 0.5f, dp->center );
VectorSubtract( dp->maxs, dp->center, xyz );
dp->radius = VectorLength( xyz );
dp->center = dp->minmax.origin();
dp->radius = vector3_length( dp->minmax.maxs - dp->center );
dp->radius2 = dp->radius * dp->radius;
/* make the front plane */
@@ -370,16 +338,14 @@ static int MakeDecalProjector( shaderInfo_t *si, vec4_t projection, float distan
}
/* make the back plane */
VectorSubtract( vec3_origin, dp->planes[ 0 ], dp->planes[ 1 ] );
VectorMA( dv[ 0 ]->xyz, distance, projection, xyz );
dp->planes[ 1 ][ 3 ] = DotProduct( xyz, dp->planes[ 1 ] );
dp->planes[ 1 ].normal() = -dp->planes[ 0 ].normal();
dp->planes[ 1 ].dist() = vector3_dot( dv[ 0 ]->xyz + projection.normal() * distance, dp->planes[ 1 ].normal() );
/* make the side planes */
for ( i = 0; i < numVerts; i++ )
{
j = ( i + 1 ) % numVerts;
VectorMA( dv[ i ]->xyz, distance, projection, xyz );
if ( !PlaneFromPoints( dp->planes[ i + 2 ], dv[ j ]->xyz, dv[ i ]->xyz, xyz ) ) {
if ( !PlaneFromPoints( dp->planes[ i + 2 ], dv[ j ]->xyz, dv[ i ]->xyz, dv[ i ]->xyz + projection.normal() * distance ) ) {
return -1;
}
}
@@ -401,8 +367,7 @@ static int MakeDecalProjector( shaderInfo_t *si, vec4_t projection, float distan
void ProcessDecals( void ){
int j, x, y, pw[ 5 ], r, iterations;
float distance;
vec4_t projection, plane;
vec3_t origin, target, delta;
Plane3f projection, plane;
entity_t *e2;
parseMesh_t *p;
mesh_t *mesh, *subdivided;
@@ -439,20 +404,18 @@ void ProcessDecals( void ){
for ( p = e.patches; p != NULL; p = e.patches )
{
/* setup projector */
if ( VectorCompare( e.origin, vec3_origin ) ) {
VectorAdd( p->eMins, p->eMaxs, origin );
VectorScale( origin, 0.5f, origin );
Vector3 origin;
if ( VectorCompare( e.origin, g_vector3_identity ) ) {
origin = p->eMinmax.origin();
}
else{
VectorCopy( e.origin, origin );
origin = e.origin;
}
VectorCopy( e2->origin, target );
VectorSubtract( target, origin, delta );
/* setup projection plane */
distance = VectorNormalize( delta, projection );
projection[ 3 ] = DotProduct( origin, projection );
projection.normal() = e2->origin - origin;
distance = VectorNormalize( projection.normal() );
projection.dist() = vector3_dot( origin, projection.normal() );
/* create projectors */
if ( distance > 0.125f ) {
@@ -467,7 +430,7 @@ void ProcessDecals( void ){
/* offset by projector origin */
for ( j = 0; j < ( mesh->width * mesh->height ); j++ )
VectorAdd( mesh->verts[ j ].xyz, e.origin, mesh->verts[ j ].xyz );
mesh->verts[ j ].xyz += e.origin;
/* iterate through the mesh quads */
for ( y = 0; y < ( mesh->height - 1 ); y++ )
@@ -491,9 +454,8 @@ void ProcessDecals( void ){
dv[ 3 ] = &mesh->verts[ pw[ r + 3 ] ];
/* planar? (nuking this optimization as it doesn't work on non-rectangular quads) */
plane[ 0 ] = 0.0f; /* stupid msvc */
if ( 0 && PlaneFromPoints( plane, dv[ 0 ]->xyz, dv[ 1 ]->xyz, dv[ 2 ]->xyz ) &&
fabs( DotProduct( dv[ 1 ]->xyz, plane ) - plane[ 3 ] ) <= PLANAR_EPSILON ) {
fabs( plane3_distance_to_point( plane, dv[ 1 ]->xyz ) ) <= PLANAR_EPSILON ) {
/* make a quad projector */
MakeDecalProjector( p->shaderInfo, projection, distance, 4, dv );
}
@@ -542,7 +504,7 @@ static void ProjectDecalOntoWinding( decalProjector_t *dp, mapDrawSurface_t *ds,
winding_t *front, *back;
mapDrawSurface_t *ds2;
bspDrawVert_t *dv;
vec4_t plane;
Plane3f plane;
/* dummy check */
@@ -553,7 +515,7 @@ static void ProjectDecalOntoWinding( decalProjector_t *dp, mapDrawSurface_t *ds,
/* offset by entity origin */
for ( i = 0; i < w->numpoints; i++ )
VectorAdd( w->p[ i ], entityOrigin, w->p[ i ] );
w->p[ i ] += entityOrigin;
/* make a plane from the winding */
if ( !PlaneFromPoints( plane, w->p[ 0 ], w->p[ 1 ], w->p[ 2 ] ) ) {
@@ -562,8 +524,7 @@ static void ProjectDecalOntoWinding( decalProjector_t *dp, mapDrawSurface_t *ds,
}
/* backface check */
d = DotProduct( dp->planes[ 0 ], plane );
if ( d < -0.0001f ) {
if ( vector3_dot( dp->planes[ 0 ].normal(), plane.normal() ) < -0.0001f ) {
FreeWinding( w );
return;
}
@@ -572,7 +533,7 @@ static void ProjectDecalOntoWinding( decalProjector_t *dp, mapDrawSurface_t *ds,
for ( i = 0; i < dp->numPlanes; i++ )
{
/* chop winding by the plane */
ClipWindingEpsilonStrict( w, dp->planes[ i ], dp->planes[ i ][ 3 ], 0.0625f, &front, &back ); /* strict, if identical plane we don't want to keep it */
ClipWindingEpsilonStrict( w, dp->planes[ i ], 0.0625f, &front, &back ); /* strict, if identical plane we don't want to keep it */
FreeWinding( w );
/* lose the front fragment */
@@ -618,8 +579,8 @@ static void ProjectDecalOntoWinding( decalProjector_t *dp, mapDrawSurface_t *ds,
dv = &ds2->verts[ i ];
/* set alpha */
d = DotProduct( w->p[ i ], dp->planes[ 0 ] ) - dp->planes[ 0 ][ 3 ];
d2 = DotProduct( w->p[ i ], dp->planes[ 1 ] ) - dp->planes[ 1 ][ 3 ];
d = plane3_distance_to_point( dp->planes[ 0 ], w->p[ i ] );
d2 = plane3_distance_to_point( dp->planes[ 1 ], w->p[ i ] );
alpha = 255.0f * d2 / ( d + d2 );
if ( alpha > 255 ) {
alpha = 255;
@@ -629,18 +590,15 @@ static void ProjectDecalOntoWinding( decalProjector_t *dp, mapDrawSurface_t *ds,
}
/* set misc */
VectorSubtract( w->p[ i ], entityOrigin, dv->xyz );
VectorCopy( plane, dv->normal );
dv->st[ 0 ] = DotProduct( dv->xyz, dp->texMat[ 0 ] ) + dp->texMat[ 0 ][ 3 ];
dv->st[ 1 ] = DotProduct( dv->xyz, dp->texMat[ 1 ] ) + dp->texMat[ 1 ][ 3 ];
dv->xyz = w->p[ i ] - entityOrigin;
dv->normal = plane.normal();
dv->st[ 0 ] = vector3_dot( dv->xyz, dp->texMat[ 0 ].vec3() ) + dp->texMat[ 0 ][ 3 ];
dv->st[ 1 ] = vector3_dot( dv->xyz, dp->texMat[ 1 ].vec3() ) + dp->texMat[ 1 ][ 3 ];
/* set color */
for ( j = 0; j < MAX_LIGHTMAPS; j++ )
{
dv->color[ j ][ 0 ] = 255;
dv->color[ j ][ 1 ] = 255;
dv->color[ j ][ 2 ] = 255;
dv->color[ j ][ 3 ] = alpha;
dv->color[ j ] = { 255, 255, 255, alpha };
}
}
}
@@ -653,11 +611,6 @@ static void ProjectDecalOntoWinding( decalProjector_t *dp, mapDrawSurface_t *ds,
*/
static void ProjectDecalOntoFace( decalProjector_t *dp, mapDrawSurface_t *ds ){
vec4_t plane;
float d;
winding_t *w;
/* dummy check */
if ( ds->sideRef == NULL || ds->sideRef->side == NULL ) {
return;
@@ -665,16 +618,15 @@ static void ProjectDecalOntoFace( decalProjector_t *dp, mapDrawSurface_t *ds ){
/* backface check */
if ( ds->planar ) {
VectorCopy( mapplanes[ ds->planeNum ].normal, plane );
plane[ 3 ] = mapplanes[ ds->planeNum ].dist + DotProduct( plane, entityOrigin );
d = DotProduct( dp->planes[ 0 ], plane );
if ( d < -0.0001f ) {
Plane3f plane = mapplanes[ ds->planeNum ].plane;
plane.dist() += vector3_dot( plane.normal(), entityOrigin );
if ( vector3_dot( dp->planes[ 0 ].normal(), plane.normal() ) < -0.0001f ) {
return;
}
}
/* generate decal */
w = WindingFromDrawSurf( ds );
winding_t *w = WindingFromDrawSurf( ds );
ProjectDecalOntoWinding( dp, ds, w );
}
@@ -687,18 +639,15 @@ static void ProjectDecalOntoFace( decalProjector_t *dp, mapDrawSurface_t *ds ){
static void ProjectDecalOntoPatch( decalProjector_t *dp, mapDrawSurface_t *ds ){
int x, y, pw[ 5 ], r, iterations;
vec4_t plane;
float d;
mesh_t src, *mesh, *subdivided;
winding_t *w;
/* backface check */
if ( ds->planar ) {
VectorCopy( mapplanes[ ds->planeNum ].normal, plane );
plane[ 3 ] = mapplanes[ ds->planeNum ].dist + DotProduct( plane, entityOrigin );
d = DotProduct( dp->planes[ 0 ], plane );
if ( d < -0.0001f ) {
Plane3f plane = mapplanes[ ds->planeNum ].plane;
plane.dist() += vector3_dot( plane.normal(), entityOrigin );
if ( vector3_dot( dp->planes[ 0 ].normal(), plane.normal() ) < -0.0001f ) {
return;
}
}
@@ -733,17 +682,17 @@ static void ProjectDecalOntoPatch( decalProjector_t *dp, mapDrawSurface_t *ds ){
/* generate decal for first triangle */
w = AllocWinding( 3 );
w->numpoints = 3;
VectorCopy( mesh->verts[ pw[ r + 0 ] ].xyz, w->p[ 0 ] );
VectorCopy( mesh->verts[ pw[ r + 1 ] ].xyz, w->p[ 1 ] );
VectorCopy( mesh->verts[ pw[ r + 2 ] ].xyz, w->p[ 2 ] );
w->p[ 0 ] = mesh->verts[ pw[ r + 0 ] ].xyz;
w->p[ 1 ] = mesh->verts[ pw[ r + 1 ] ].xyz;
w->p[ 2 ] = mesh->verts[ pw[ r + 2 ] ].xyz;
ProjectDecalOntoWinding( dp, ds, w );
/* generate decal for second triangle */
w = AllocWinding( 3 );
w->numpoints = 3;
VectorCopy( mesh->verts[ pw[ r + 0 ] ].xyz, w->p[ 0 ] );
VectorCopy( mesh->verts[ pw[ r + 2 ] ].xyz, w->p[ 1 ] );
VectorCopy( mesh->verts[ pw[ r + 3 ] ].xyz, w->p[ 2 ] );
w->p[ 0 ] = mesh->verts[ pw[ r + 0 ] ].xyz;
w->p[ 1 ] = mesh->verts[ pw[ r + 2 ] ].xyz;
w->p[ 2 ] = mesh->verts[ pw[ r + 3 ] ].xyz;
ProjectDecalOntoWinding( dp, ds, w );
}
}
@@ -760,12 +709,7 @@ static void ProjectDecalOntoPatch( decalProjector_t *dp, mapDrawSurface_t *ds ){
*/
static void ProjectDecalOntoTriangles( decalProjector_t *dp, mapDrawSurface_t *ds ){
int i;
vec4_t plane;
float d;
winding_t *w;
/* triangle surfaces without shaders don't get marks by default */
if ( ds->type == ESurfaceType::Triangles && ds->shaderInfo->shaderText == NULL ) {
return;
@@ -773,23 +717,22 @@ static void ProjectDecalOntoTriangles( decalProjector_t *dp, mapDrawSurface_t *d
/* backface check */
if ( ds->planar ) {
VectorCopy( mapplanes[ ds->planeNum ].normal, plane );
plane[ 3 ] = mapplanes[ ds->planeNum ].dist + DotProduct( plane, entityOrigin );
d = DotProduct( dp->planes[ 0 ], plane );
if ( d < -0.0001f ) {
Plane3f plane = mapplanes[ ds->planeNum ].plane;
plane.dist() += vector3_dot( plane.normal(), entityOrigin );
if ( vector3_dot( dp->planes[ 0 ].normal(), plane.normal() ) < -0.0001f ) {
return;
}
}
/* iterate through triangles */
for ( i = 0; i < ds->numIndexes; i += 3 )
for ( int i = 0; i < ds->numIndexes; i += 3 )
{
/* generate decal */
w = AllocWinding( 3 );
winding_t *w = AllocWinding( 3 );
w->numpoints = 3;
VectorCopy( ds->verts[ ds->indexes[ i ] ].xyz, w->p[ 0 ] );
VectorCopy( ds->verts[ ds->indexes[ i + 1 ] ].xyz, w->p[ 1 ] );
VectorCopy( ds->verts[ ds->indexes[ i + 2 ] ].xyz, w->p[ 2 ] );
w->p[ 0 ] = ds->verts[ ds->indexes[ i ] ].xyz;
w->p[ 1 ] = ds->verts[ ds->indexes[ i + 1 ] ].xyz;
w->p[ 2 ] = ds->verts[ ds->indexes[ i + 2 ] ].xyz;
ProjectDecalOntoWinding( dp, ds, w );
}
}
@@ -805,17 +748,14 @@ void MakeEntityDecals( entity_t *e ){
int i, j, k, f, fOld, start;
decalProjector_t dp;
mapDrawSurface_t *ds;
vec3_t identityAxis[ 3 ] = { { 1, 0, 0 }, { 0, 1, 0 }, { 0, 0, 1 } };
Vector3 identityAxis[ 3 ] = { g_vector3_axis_x, g_vector3_axis_y, g_vector3_axis_z };
/* note it */
Sys_FPrintf( SYS_VRB, "--- MakeEntityDecals ---\n" );
/* set entity origin */
VectorCopy( e->origin, entityOrigin );
/* transform projector instead of geometry */
VectorClear( entityOrigin );
entityOrigin.set( 0 );
/* init pacifier */
fOld = -1;
@@ -850,8 +790,8 @@ void MakeEntityDecals( entity_t *e ){
/* bounds check */
for ( k = 0; k < 3; k++ )
if ( ds->mins[ k ] >= ( dp.center[ k ] + dp.radius ) ||
ds->maxs[ k ] <= ( dp.center[ k ] - dp.radius ) ) {
if ( ds->minmax.mins[ k ] >= ( dp.center[ k ] + dp.radius ) ||
ds->minmax.maxs[ k ] <= ( dp.center[ k ] - dp.radius ) ) {
break;
}
if ( k < 3 ) {
+25 -34
View File
@@ -71,11 +71,8 @@ static void SelectSplitPlaneNum( node_t *node, face_t *list, int *splitPlaneNum,
face_t *check;
face_t *bestSplit;
int splits, facing, front, back;
int side;
plane_t *plane;
int value, bestValue;
int i;
vec3_t normal;
float dist;
int planenum;
float sizeBias;
@@ -96,11 +93,9 @@ static void SelectSplitPlaneNum( node_t *node, face_t *list, int *splitPlaneNum,
if ( blockSize[ i ] <= 0 ) {
continue;
}
dist = blockSize[ i ] * ( floor( node->mins[ i ] / blockSize[ i ] ) + 1 );
if ( node->maxs[ i ] > dist ) {
VectorClear( normal );
normal[ i ] = 1;
planenum = FindFloatPlane( normal, dist, 0, NULL );
dist = blockSize[ i ] * ( floor( node->minmax.mins[ i ] / blockSize[ i ] ) + 1 );
if ( node->minmax.maxs[ i ] > dist ) {
planenum = FindFloatPlane( g_vector3_axes[i], dist, 0, NULL );
*splitPlaneNum = planenum;
return;
}
@@ -120,7 +115,7 @@ static void SelectSplitPlaneNum( node_t *node, face_t *list, int *splitPlaneNum,
//if ( split->checked )
// continue;
plane = &mapplanes[ split->planenum ];
const plane_t& plane = mapplanes[ split->planenum ];
splits = 0;
facing = 0;
front = 0;
@@ -131,14 +126,14 @@ static void SelectSplitPlaneNum( node_t *node, face_t *list, int *splitPlaneNum,
//check->checked = true; // won't need to test this plane again
continue;
}
side = WindingOnPlaneSide( check->w, plane->normal, plane->dist );
if ( side == SIDE_CROSS ) {
const EPlaneSide side = WindingOnPlaneSide( check->w, plane.plane );
if ( side == eSideCross ) {
splits++;
}
else if ( side == SIDE_FRONT ) {
else if ( side == eSideFront ) {
front++;
}
else if ( side == SIDE_BACK ) {
else if ( side == eSideBack ) {
back++;
}
}
@@ -151,7 +146,7 @@ static void SelectSplitPlaneNum( node_t *node, face_t *list, int *splitPlaneNum,
//Base score = 20000 perfectly balanced
value = 20000 - ( abs( front - back ) );
value -= plane->counter; // If we've already used this plane sometime in the past try not to use it again
value -= plane.counter; // If we've already used this plane sometime in the past try not to use it again
value -= facing ; // if we're going to have alot of other surfs use this plane, we want to get it in quickly.
value -= splits * 5; //more splits = bad
value += sizeBias * 10; //We want a huge score bias based on plane size
@@ -159,7 +154,7 @@ static void SelectSplitPlaneNum( node_t *node, face_t *list, int *splitPlaneNum,
else
{
value = 5 * facing - 5 * splits; // - abs(front-back);
if ( plane->type < 3 ) {
if ( plane.type < ePlaneNonAxial ) {
value += 5; // axial is better
}
}
@@ -231,8 +226,6 @@ int CountFaceList( face_t *list ){
void BuildFaceTree_r( node_t *node, face_t *list ){
face_t *split;
face_t *next;
int side;
plane_t *plane;
face_t *newFace;
face_t *childLists[2];
winding_t *frontWinding, *backWinding;
@@ -261,7 +254,7 @@ void BuildFaceTree_r( node_t *node, face_t *list ){
node->planenum = splitPlaneNum;
node->compileFlags = compileFlags;
node->has_structural_children = !( compileFlags & C_DETAIL ) && !node->opaque;
plane = &mapplanes[ splitPlaneNum ];
const plane_t& plane = mapplanes[ splitPlaneNum ];
childLists[0] = NULL;
childLists[1] = NULL;
@@ -283,11 +276,11 @@ void BuildFaceTree_r( node_t *node, face_t *list ){
#endif
/* determine which side the face falls on */
side = WindingOnPlaneSide( split->w, plane->normal, plane->dist );
const EPlaneSide side = WindingOnPlaneSide( split->w, plane.plane );
/* switch on side */
if ( side == SIDE_CROSS ) {
ClipWindingEpsilonStrict( split->w, plane->normal, plane->dist, CLIP_EPSILON * 2,
if ( side == eSideCross ) {
ClipWindingEpsilonStrict( split->w, plane.plane, CLIP_EPSILON * 2,
&frontWinding, &backWinding ); /* strict; if no winding is left, we have a "virtually identical" plane and don't want to split by it */
if ( frontWinding ) {
newFace = AllocBspFace();
@@ -309,11 +302,11 @@ void BuildFaceTree_r( node_t *node, face_t *list ){
}
FreeBspFace( split );
}
else if ( side == SIDE_FRONT ) {
else if ( side == eSideFront ) {
split->next = childLists[0];
childLists[0] = split;
}
else if ( side == SIDE_BACK ) {
else if ( side == eSideBack ) {
split->next = childLists[1];
childLists[1] = split;
}
@@ -324,19 +317,18 @@ void BuildFaceTree_r( node_t *node, face_t *list ){
for ( i = 0 ; i < 2 ; i++ ) {
node->children[i] = AllocNode();
node->children[i]->parent = node;
VectorCopy( node->mins, node->children[i]->mins );
VectorCopy( node->maxs, node->children[i]->maxs );
node->children[i]->minmax = node->minmax;
}
for ( i = 0 ; i < 3 ; i++ ) {
if ( plane->normal[i] == 1 ) {
node->children[0]->mins[i] = plane->dist;
node->children[1]->maxs[i] = plane->dist;
if ( plane.normal()[i] == 1 ) {
node->children[0]->minmax.mins[i] = plane.dist();
node->children[1]->minmax.maxs[i] = plane.dist();
break;
}
if ( plane->normal[i] == -1 ) {
node->children[0]->maxs[i] = -plane->dist;
node->children[1]->mins[i] = -plane->dist;
if ( plane.normal()[i] == -1 ) {
node->children[0]->minmax.maxs[i] = -plane.dist();
node->children[1]->minmax.mins[i] = -plane.dist();
break;
}
}
@@ -386,7 +378,7 @@ tree_t *FaceBSP( face_t *list ) {
count++;
for ( i = 0; i < face->w->numpoints; i++ )
{
AddPointToBounds( face->w->p[ i ], tree->mins, tree->maxs );
tree->minmax.extend( face->w->p[ i ] );
}
}
Sys_FPrintf( SYS_VRB, "%9d faces\n", count );
@@ -397,8 +389,7 @@ tree_t *FaceBSP( face_t *list ) {
}
tree->headnode = AllocNode();
VectorCopy( tree->mins, tree->headnode->mins );
VectorCopy( tree->maxs, tree->headnode->maxs );
tree->headnode->minmax = tree->minmax;
c_faceLeafs = 0;
BuildFaceTree_r( tree->headnode, list );
+31 -71
View File
@@ -63,7 +63,7 @@ mesh_t *DrawSurfToMesh( mapDrawSurface_t *ds ){
chops a mesh by a plane
*/
void SplitMeshByPlane( mesh_t *in, vec3_t normal, float dist, mesh_t **front, mesh_t **back ){
void SplitMeshByPlane( mesh_t *in, const Plane3f& plane, mesh_t **front, mesh_t **back ){
int w, h, split;
float d[MAX_PATCH_SIZE][MAX_PATCH_SIZE];
bspDrawVert_t *dv, *v1, *v2;
@@ -80,7 +80,7 @@ void SplitMeshByPlane( mesh_t *in, vec3_t normal, float dist, mesh_t **front, me
c_on = 0;
for ( h = 0 ; h < in->height ; h++ ) {
for ( w = 0 ; w < in->width ; w++, dv++ ) {
d[h][w] = DotProduct( dv->xyz, normal ) - dist;
d[h][w] = plane3_distance_to_point( plane, dv->xyz );
if ( d[h][w] > ON_EPSILON ) {
c_front++;
}
@@ -247,7 +247,6 @@ void SplitMeshByPlane( mesh_t *in, vec3_t normal, float dist, mesh_t **front, me
bool ChopPatchSurfaceByBrush( entity_t *e, mapDrawSurface_t *ds, brush_t *b ){
int i, j;
side_t *s;
plane_t *plane;
mesh_t *outside[MAX_BRUSH_SIDES];
int numOutside;
mesh_t *m, *front, *back;
@@ -261,9 +260,9 @@ bool ChopPatchSurfaceByBrush( entity_t *e, mapDrawSurface_t *ds, brush_t *b ){
for ( i = 4 ; i <= 5 ; i++ ) {
s = &b->sides[ i ];
plane = &mapplanes[ s->planenum ];
const plane_t& plane = mapplanes[ s->planenum ];
SplitMeshByPlane( m, plane->normal, plane->dist, &front, &back );
SplitMeshByPlane( m, plane.plane, &front, &back );
if ( !back ) {
// nothing actually contained inside
@@ -340,14 +339,14 @@ winding_t *WindingFromDrawSurf( mapDrawSurface_t *ds ){
// (actually send the whole draw surface would be cool?)
if ( ds->numVerts >= MAX_POINTS_ON_WINDING ) {
int max = ds->numVerts;
vec3_t p[256];
Vector3 p[256];
if ( max > 256 ) {
max = 256;
}
for ( i = 0 ; i < max ; i++ ) {
VectorCopy( ds->verts[i].xyz, p[i] );
p[i] = ds->verts[i].xyz;
}
xml_Winding( "WindingFromDrawSurf failed: MAX_POINTS_ON_WINDING exceeded", p, max, true );
@@ -356,7 +355,7 @@ winding_t *WindingFromDrawSurf( mapDrawSurface_t *ds ){
w = AllocWinding( ds->numVerts );
w->numpoints = ds->numVerts;
for ( i = 0 ; i < ds->numVerts ; i++ ) {
VectorCopy( ds->verts[i].xyz, w->p[i] );
w->p[i] = ds->verts[i].xyz;
}
return w;
}
@@ -371,7 +370,6 @@ winding_t *WindingFromDrawSurf( mapDrawSurface_t *ds ){
bool ChopFaceSurfaceByBrush( entity_t *e, mapDrawSurface_t *ds, brush_t *b ){
int i, j;
side_t *s;
plane_t *plane;
winding_t *w;
winding_t *front, *back;
winding_t *outside[ MAX_BRUSH_SIDES ];
@@ -393,7 +391,7 @@ bool ChopFaceSurfaceByBrush( entity_t *e, mapDrawSurface_t *ds, brush_t *b ){
{
/* get brush side and plane */
s = &b->sides[ i ];
plane = &mapplanes[ s->planenum ];
const plane_t& plane = mapplanes[ s->planenum ];
/* handle coplanar outfacing (don't fog) */
if ( ds->sideRef->side->planenum == s->planenum ) {
@@ -406,7 +404,7 @@ bool ChopFaceSurfaceByBrush( entity_t *e, mapDrawSurface_t *ds, brush_t *b ){
}
/* general case */
ClipWindingEpsilonStrict( w, plane->normal, plane->dist, ON_EPSILON, &front, &back ); /* strict; if plane is "almost identical" to face, both ways to continue can be wrong, so we better not fog it */
ClipWindingEpsilonStrict( w, plane.plane, ON_EPSILON, &front, &back ); /* strict; if plane is "almost identical" to face, both ways to continue can be wrong, so we better not fog it */
FreeWinding( w );
if ( back == NULL ) {
@@ -468,10 +466,9 @@ bool ChopFaceSurfaceByBrush( entity_t *e, mapDrawSurface_t *ds, brush_t *b ){
*/
void FogDrawSurfaces( entity_t *e ){
int i, j, k, fogNum;
int i, j, fogNum;
fog_t *fog;
mapDrawSurface_t *ds;
vec3_t mins, maxs;
int fogged, numFogged;
int numBaseDrawSurfs;
@@ -512,24 +509,13 @@ void FogDrawSurfaces( entity_t *e ){
else
{
/* find drawsurface bounds */
ClearBounds( mins, maxs );
MinMax minmax;
for ( j = 0; j < ds->numVerts; j++ )
AddPointToBounds( ds->verts[ j ].xyz, mins, maxs );
minmax.extend( ds->verts[ j ].xyz );
/* check against the fog brush */
for ( k = 0; k < 3; k++ )
{
if ( mins[ k ] > fog->brush->maxs[ k ] ) {
break;
}
if ( maxs[ k ] < fog->brush->mins[ k ] ) {
break;
}
}
/* no intersection? */
if ( k < 3 ) {
continue;
if( !minmax.test( fog->brush->minmax ) ){
continue; /* no intersection */
}
/* ydnar: gs mods: handle the various types of surfaces */
@@ -580,12 +566,10 @@ void FogDrawSurfaces( entity_t *e ){
gets the fog number for a point in space
*/
int FogForPoint( vec3_t point, float epsilon ){
int FogForPoint( const Vector3& point, float epsilon ){
int fogNum, i, j;
float dot;
bool inside;
brush_t *brush;
plane_t *plane;
/* start with bogus fog num */
@@ -607,10 +591,7 @@ int FogForPoint( vec3_t point, float epsilon ){
inside = true;
for ( j = 0; j < brush->numsides && inside; j++ )
{
plane = &mapplanes[ brush->sides[ j ].planenum ]; /* note usage of map planes here */
dot = DotProduct( point, plane->normal );
dot -= plane->dist;
if ( dot > epsilon ) {
if ( plane3_distance_to_point( mapplanes[ brush->sides[ j ].planenum ].plane, point ) > epsilon ) {
inside = false;
}
}
@@ -633,18 +614,14 @@ int FogForPoint( vec3_t point, float epsilon ){
gets the fog number for a bounding box
*/
int FogForBounds( vec3_t mins, vec3_t maxs, float epsilon ){
int fogNum, i, j;
float highMin, lowMax, volume, bestVolume;
vec3_t fogMins, fogMaxs, overlap;
brush_t *brush;
int FogForBounds( const MinMax& minmax, float epsilon ){
int fogNum, i;
/* start with bogus fog num */
fogNum = defaultFogNum;
/* init */
bestVolume = 0.0f;
float bestVolume = 0.0f;
/* walk the list of fog volumes */
for ( i = 0; i < numMapFogs; i++ )
@@ -656,37 +633,21 @@ int FogForBounds( vec3_t mins, vec3_t maxs, float epsilon ){
}
/* get fog brush */
brush = mapFogs[ i ].brush;
brush_t *brush = mapFogs[ i ].brush;
/* get bounds */
fogMins[ 0 ] = brush->mins[ 0 ] - epsilon;
fogMins[ 1 ] = brush->mins[ 1 ] - epsilon;
fogMins[ 2 ] = brush->mins[ 2 ] - epsilon;
fogMaxs[ 0 ] = brush->maxs[ 0 ] + epsilon;
fogMaxs[ 1 ] = brush->maxs[ 1 ] + epsilon;
fogMaxs[ 2 ] = brush->maxs[ 2 ] + epsilon;
const MinMax fogMinmax( brush->minmax.mins - Vector3( epsilon, epsilon, epsilon ),
brush->minmax.maxs + Vector3( epsilon, epsilon, epsilon ) );
/* check against bounds */
for ( j = 0; j < 3; j++ )
{
if ( mins[ j ] > fogMaxs[ j ] || maxs[ j ] < fogMins[ j ] ) {
break;
}
highMin = mins[ j ] > fogMins[ j ] ? mins[ j ] : fogMins[ j ];
lowMax = maxs[ j ] < fogMaxs[ j ] ? maxs[ j ] : fogMaxs[ j ];
overlap[ j ] = lowMax - highMin;
if ( overlap[ j ] < 1.0f ) {
overlap[ j ] = 1.0f;
}
}
/* no overlap */
if ( j < 3 ) {
continue;
if( !minmax.test( fogMinmax ) ){
continue; /* no overlap */
}
const Vector3 overlap( std::max( 1.f, std::min( minmax.maxs[0], fogMinmax.maxs[0] ) - std::max( minmax.mins[0], fogMinmax.mins[0] ) ),
std::max( 1.f, std::min( minmax.maxs[1], fogMinmax.maxs[1] ) - std::max( minmax.mins[1], fogMinmax.mins[1] ) ),
std::max( 1.f, std::min( minmax.maxs[2], fogMinmax.maxs[2] ) - std::max( minmax.mins[2], fogMinmax.mins[2] ) ) );
/* get volume */
volume = overlap[ 0 ] * overlap[ 1 ] * overlap[ 2 ];
const float volume = overlap[0] * overlap[1] * overlap[2];
/* test against best volume */
if ( volume > bestVolume ) {
@@ -710,7 +671,6 @@ void CreateMapFogs( void ){
int j;
brush_t *brush;
fog_t *fog;
vec3_t invFogDir;
/* skip? */
@@ -744,14 +704,14 @@ void CreateMapFogs( void ){
fog->visibleSide = -1;
/* if shader specifies an explicit direction, then find a matching brush side with an opposed normal */
if ( VectorLength( fog->si->fogDir ) ) {
if ( vector3_length( fog->si->fogDir ) ) {
/* flip it */
VectorScale( fog->si->fogDir, -1.0f, invFogDir );
const Vector3 invFogDir = -fog->si->fogDir;
/* find the brush side */
for ( j = 0; j < brush->numsides; j++ )
{
if ( VectorCompare( invFogDir, mapplanes[ brush->sides[ j ].planenum ].normal ) ) {
if ( VectorCompare( invFogDir, mapplanes[ brush->sides[ j ].planenum ].normal() ) ) {
fog->visibleSide = j;
//% Sys_Printf( "Brush num: %d Side num: %d\n", fog->brushNum, fog->visibleSide );
break;
+2 -2
View File
@@ -55,7 +55,7 @@
=============
*/
xmlNodePtr LeakFile( tree_t *tree ){
vec3_t mid;
Vector3 mid;
FILE *linefile;
node_t *node;
int count;
@@ -97,7 +97,7 @@ xmlNodePtr LeakFile( tree_t *tree ){
}
}
node = nextnode;
WindingCenter( nextportal->winding, mid );
mid = WindingCenter( nextportal->winding );
fprintf( linefile, "%f %f %f\n", mid[0], mid[1], mid[2] );
point = xml_NodeForVec( mid );
xmlAddChild( xml_node, point );
+132 -158
View File
@@ -41,7 +41,7 @@
static void CreateSunLight( sun_t *sun ){
int i;
float photons, d, angle, elevation, da, de;
vec3_t direction;
Vector3 direction;
light_t *light;
@@ -63,7 +63,7 @@ static void CreateSunLight( sun_t *sun ){
{
/* calculate sun direction */
if ( i == 0 ) {
VectorCopy( sun->direction, direction );
direction = sun->direction;
}
else
{
@@ -92,7 +92,7 @@ static void CreateSunLight( sun_t *sun ){
elevation += de;
/* debug code */
//% Sys_Printf( "%d: Angle: %3.4f Elevation: %3.3f\n", sun->numSamples, (angle / Q_PI * 180.0f), (elevation / Q_PI * 180.0f) );
//% Sys_Printf( "%d: Angle: %3.4lf Elevation: %3.3lf\n", sun->numSamples, radians_to_degrees( angle ), radians_to_degrees( elevation ) );
/* create new vector */
direction[ 0 ] = cos( angle ) * cos( elevation );
@@ -115,14 +115,14 @@ static void CreateSunLight( sun_t *sun ){
light->style = noStyles ? LS_NORMAL : sun->style;
/* set the light's position out to infinity */
VectorMA( vec3_origin, ( MAX_WORLD_COORD * 8.0f ), direction, light->origin ); /* MAX_WORLD_COORD * 2.0f */
light->origin = -direction * ( MAX_WORLD_COORD * 8.0f ); /* MAX_WORLD_COORD * 2.0f */
/* set the facing to be the inverse of the sun direction */
VectorScale( direction, -1.0, light->normal );
light->dist = DotProduct( light->origin, light->normal );
light->normal = -direction;
light->dist = vector3_dot( light->origin, light->normal );
/* set color and photons */
VectorCopy( sun->color, light->color );
light->color = sun->color;
light->photons = photons * skyScale;
}
@@ -139,7 +139,7 @@ static void CreateSunLight( sun_t *sun ){
simulates sky light with multiple suns
*/
static void CreateSkyLights( vec3_t color, float value, int iterations, float filterRadius, int style ){
static void CreateSkyLights( const Vector3& color, float value, int iterations, float filterRadius, int style ){
int i, j, numSuns;
int angleSteps, elevationSteps;
float angle, elevation;
@@ -153,7 +153,7 @@ static void CreateSkyLights( vec3_t color, float value, int iterations, float fi
}
/* basic sun setup */
VectorCopy( color, sun.color );
sun.color = color;
sun.deviance = 0.0f;
sun.filterRadius = filterRadius;
sun.numSamples = 1;
@@ -164,8 +164,8 @@ static void CreateSkyLights( vec3_t color, float value, int iterations, float fi
elevationSteps = iterations - 1;
angleSteps = elevationSteps * 4;
angle = 0.0f;
elevationStep = DEG2RAD( 90.0f / iterations ); /* skip elevation 0 */
angleStep = DEG2RAD( 360.0f / angleSteps );
elevationStep = degrees_to_radians( 90.0f / iterations ); /* skip elevation 0 */
angleStep = degrees_to_radians( 360.0f / angleSteps );
/* calc individual sun brightness */
numSuns = angleSteps * elevationSteps + 1;
@@ -195,7 +195,7 @@ static void CreateSkyLights( vec3_t color, float value, int iterations, float fi
}
/* create vertical sun */
VectorSet( sun.direction, 0.0f, 0.0f, 1.0f );
sun.direction = g_vector3_axis_z;
CreateSunLight( &sun );
/* short circuit */
@@ -371,11 +371,11 @@ void CreateEntityLights( void ){
light->color[2] = Image_LinearFloatFromsRGBFloat( light->color[2] );
}
if ( !( light->flags & LightFlags::Unnormalized ) ) {
ColorNormalize( light->color, light->color );
ColorNormalize( light->color );
}
}
else{
VectorSet( light->color, 1.f, 1.f, 1.f );
light->color.set( 1 );
}
@@ -406,10 +406,10 @@ void CreateEntityLights( void ){
numSpotLights++;
/* make a spotlight */
vec3_t dest;
Vector3 dest;
e2->vectorForKey( "origin", dest );
VectorSubtract( dest, light->origin, light->normal );
float dist = VectorNormalize( light->normal, light->normal );
light->normal = dest - light->origin;
float dist = VectorNormalize( light->normal );
float radius = e->floatForKey( "radius" );
if ( !radius ) {
radius = 64;
@@ -435,10 +435,10 @@ void CreateEntityLights( void ){
/* make a sun */
sun_t sun;
VectorScale( light->normal, -1.0f, sun.direction );
VectorCopy( light->color, sun.color );
sun.direction = -light->normal;
sun.color = light->color;
sun.photons = intensity;
sun.deviance = deviance / 180.0f * Q_PI;
sun.deviance = degrees_to_radians( deviance );
sun.numSamples = numSamples;
sun.style = noStyles ? LS_NORMAL : light->style;
sun.next = NULL;
@@ -504,7 +504,6 @@ void CreateSurfaceLights( void ){
shaderInfo_t *si;
light_t *light;
float subdivide;
vec3_t origin;
clipWork_t cw;
@@ -540,10 +539,6 @@ void CreateSurfaceLights( void ){
/* autosprite shaders become point lights */
if ( si->autosprite ) {
/* create an average xyz */
VectorAdd( info->mins, info->maxs, origin );
VectorScale( origin, 0.5f, origin );
/* create a light */
light = safe_calloc( sizeof( *light ) );
light->next = lights;
@@ -555,8 +550,8 @@ void CreateSurfaceLights( void ){
light->photons = si->value * pointScale;
light->fade = 1.0f;
light->si = si;
VectorCopy( origin, light->origin );
VectorCopy( si->color, light->color );
light->origin = info->minmax.origin();
light->color = si->color;
light->falloffTolerance = falloffTolerance;
light->style = si->lightStyle;
@@ -622,7 +617,7 @@ void SetEntityOrigins( void ){
dm = &bspModels[ modelnum ];
/* get entity origin */
vec3_t origin = { 0.f, 0.f, 0.f };
Vector3 origin( 0, 0, 0 );
if ( !e.read_keyvalue( origin, "origin" ) ) {
continue;
}
@@ -637,7 +632,7 @@ void SetEntityOrigins( void ){
for ( k = 0; k < ds->numVerts; k++ )
{
f = ds->firstVert + k;
VectorAdd( origin, bspDrawVerts[ f ].xyz, yDrawVerts[ f ].xyz );
yDrawVerts[ f ].xyz = origin + bspDrawVerts[ f ].xyz;
}
}
}
@@ -656,10 +651,9 @@ void SetEntityOrigins( void ){
#define ONE_OVER_2PI 0.159154942f //% (1.0f / (2.0f * 3.141592657f))
float PointToPolygonFormFactor( const vec3_t point, const vec3_t normal, const winding_t *w ){
vec3_t triVector, triNormal;
float PointToPolygonFormFactor( const Vector3& point, const Vector3& normal, const winding_t *w ){
int i, j;
vec3_t dirs[ MAX_POINTS_ON_WINDING ];
Vector3 dirs[ MAX_POINTS_ON_WINDING ];
float total;
float dot, angle, facing;
@@ -667,12 +661,12 @@ float PointToPolygonFormFactor( const vec3_t point, const vec3_t normal, const w
/* this is expensive */
for ( i = 0; i < w->numpoints; i++ )
{
VectorSubtract( w->p[ i ], point, dirs[ i ] );
VectorFastNormalize( dirs[ i ], dirs[ i ] );
dirs[ i ] = w->p[ i ] - point;
VectorFastNormalize( dirs[ i ] );
}
/* duplicate first vertex to avoid mod operation */
VectorCopy( dirs[ 0 ], dirs[ i ] );
dirs[ i ] = dirs[ 0 ];
/* calculcate relative area */
total = 0.0f;
@@ -680,7 +674,7 @@ float PointToPolygonFormFactor( const vec3_t point, const vec3_t normal, const w
{
/* get a triangle */
j = i + 1;
dot = DotProduct( dirs[ i ], dirs[ j ] );
dot = vector3_dot( dirs[ i ], dirs[ j ] );
/* roundoff can cause slight creep, which gives an IND from acos */
if ( dot > 1.0f ) {
@@ -693,12 +687,12 @@ float PointToPolygonFormFactor( const vec3_t point, const vec3_t normal, const w
/* get the angle */
angle = acos( dot );
CrossProduct( dirs[ i ], dirs[ j ], triVector );
if ( VectorFastNormalize( triVector, triNormal ) < 0.0001f ) {
Vector3 triNormal = vector3_cross( dirs[ i ], dirs[ j ] );
if ( VectorFastNormalize( triNormal ) < 0.0001f ) {
continue;
}
facing = DotProduct( normal, triNormal );
facing = vector3_dot( normal, triNormal );
total += facing * angle;
/* ydnar: this was throwing too many errors with radiosity + crappy maps. ignoring it. */
@@ -735,9 +729,9 @@ int LightContributionToSample( trace_t *trace ){
/* clear color */
trace->forceSubsampling = 0.0f; /* to make sure */
VectorClear( trace->color );
VectorClear( trace->colorNoShadow );
VectorClear( trace->directionContribution );
trace->color.set( 0 );
trace->colorNoShadow.set( 0 );
trace->directionContribution.set( 0 );
colorBrightness = RGBTOGRAY( light->color ) * ( 1.0f / 255.0f );
@@ -750,7 +744,7 @@ int LightContributionToSample( trace_t *trace ){
if ( light->type != ELightType::Sun ) {
/* MrE: if the light is behind the surface */
if ( !trace->twoSided ) {
if ( DotProduct( light->origin, trace->normal ) - DotProduct( trace->origin, trace->normal ) < 0.0f ) {
if ( vector3_dot( light->origin, trace->normal ) - vector3_dot( trace->origin, trace->normal ) < 0.0f ) {
return 0;
}
}
@@ -765,10 +759,10 @@ int LightContributionToSample( trace_t *trace ){
if ( light->type == ELightType::Area ) {
float factor;
float d;
vec3_t pushedOrigin;
Vector3 pushedOrigin;
/* project sample point into light plane */
d = DotProduct( trace->origin, light->normal ) - light->dist;
d = vector3_dot( trace->origin, light->normal ) - light->dist;
if ( d < 3.0f ) {
/* sample point behind plane? */
if ( !( light->flags & LightFlags::Twosided ) && d < -1.0f ) {
@@ -776,7 +770,7 @@ int LightContributionToSample( trace_t *trace ){
}
/* sample plane coincident? */
if ( d > -3.0f && DotProduct( trace->normal, light->normal ) > 0.9f ) {
if ( d > -3.0f && vector3_dot( trace->normal, light->normal ) > 0.9f ) {
return 0;
}
}
@@ -784,14 +778,14 @@ int LightContributionToSample( trace_t *trace ){
/* nudge the point so that it is clearly forward of the light */
/* so that surfaces meeting a light emitter don't get black edges */
if ( d > -8.0f && d < 8.0f ) {
VectorMA( trace->origin, ( 8.0f - d ), light->normal, pushedOrigin );
pushedOrigin = trace->origin + light->normal * ( 8.0f - d );
}
else{
VectorCopy( trace->origin, pushedOrigin );
pushedOrigin = trace->origin;
}
/* get direction and distance */
VectorCopy( light->origin, trace->end );
trace->end = light->origin;
dist = SetupTrace( trace );
if ( dist >= light->envelope ) {
return 0;
@@ -800,7 +794,7 @@ int LightContributionToSample( trace_t *trace ){
/* ptpff approximation */
if ( faster ) {
/* angle attenuation */
angle = DotProduct( trace->normal, trace->direction );
angle = vector3_dot( trace->normal, trace->direction );
/* twosided lighting */
if ( trace->twoSided && angle < 0 ) {
@@ -811,7 +805,7 @@ int LightContributionToSample( trace_t *trace ){
}
/* attenuate */
angle *= -DotProduct( light->normal, trace->direction );
angle *= -vector3_dot( light->normal, trace->direction );
if ( angle == 0.0f ) {
return 0;
}
@@ -853,7 +847,7 @@ int LightContributionToSample( trace_t *trace ){
factor = -factor;
/* push light origin to other side of the plane */
VectorMA( light->origin, -2.0f, light->normal, trace->end );
trace->end = light->origin - light->normal * 2.f;
dist = SetupTrace( trace );
if ( dist >= light->envelope ) {
return 0;
@@ -868,7 +862,7 @@ int LightContributionToSample( trace_t *trace ){
}
/* also don't deluxe if the direction is on the wrong side */
if ( DotProduct( trace->normal, trace->direction ) < 0 ) {
if ( vector3_dot( trace->normal, trace->direction ) < 0 ) {
/* no deluxemap contribution from "other side" light */
doAddDeluxe = false;
}
@@ -885,7 +879,7 @@ int LightContributionToSample( trace_t *trace ){
/* point/spot lights */
else if ( light->type == ELightType::Point || light->type == ELightType::Spot ) {
/* get direction and distance */
VectorCopy( light->origin, trace->end );
trace->end = light->origin;
dist = SetupTrace( trace );
if ( dist >= light->envelope ) {
return 0;
@@ -900,7 +894,7 @@ int LightContributionToSample( trace_t *trace ){
/* angle attenuation */
if ( light->flags & LightFlags::AttenAngle ) {
/* standard Lambert attenuation */
float dot = DotProduct( trace->normal, trace->direction );
float dot = vector3_dot( trace->normal, trace->direction );
/* twosided lighting */
if ( trace->twoSided && dot < 0 ) {
@@ -980,18 +974,15 @@ int LightContributionToSample( trace_t *trace ){
/* handle spotlights */
if ( light->type == ELightType::Spot ) {
float distByNormal, radiusAtDist, sampleRadius;
vec3_t pointAtDist, distToSample;
/* do cone calculation */
distByNormal = -DotProduct( trace->displacement, light->normal );
const float distByNormal = -vector3_dot( trace->displacement, light->normal );
if ( distByNormal < 0.0f ) {
return 0;
}
VectorMA( light->origin, distByNormal, light->normal, pointAtDist );
radiusAtDist = light->radiusByDist * distByNormal;
VectorSubtract( trace->origin, pointAtDist, distToSample );
sampleRadius = VectorLength( distToSample );
const Vector3 pointAtDist = light->origin + light->normal * distByNormal;
const float radiusAtDist = light->radiusByDist * distByNormal;
const Vector3 distToSample = trace->origin - pointAtDist;
const float sampleRadius = vector3_length( distToSample );
/* outside the cone */
if ( sampleRadius >= radiusAtDist ) {
@@ -1017,13 +1008,13 @@ int LightContributionToSample( trace_t *trace ){
/* ydnar: sunlight */
else if ( light->type == ELightType::Sun ) {
/* get origin and direction */
VectorAdd( trace->origin, light->origin, trace->end );
trace->end = trace->origin + light->origin;
dist = SetupTrace( trace );
/* angle attenuation */
if ( light->flags & LightFlags::AttenAngle ) {
/* standard Lambert attenuation */
float dot = DotProduct( trace->normal, trace->direction );
float dot = vector3_dot( trace->normal, trace->direction );
/* twosided lighting */
if ( trace->twoSided && dot < 0 ) {
@@ -1074,7 +1065,7 @@ int LightContributionToSample( trace_t *trace ){
}
/* VorteX: set noShadow color */
VectorScale( light->color, add, trace->colorNoShadow );
trace->colorNoShadow = light->color * add;
addDeluxe *= colorBrightness;
@@ -1085,11 +1076,11 @@ int LightContributionToSample( trace_t *trace ){
}
}
VectorScale( trace->direction, addDeluxe, trace->directionContribution );
trace->directionContribution = trace->direction * addDeluxe;
/* setup trace */
trace->testAll = true;
VectorScale( light->color, add, trace->color );
trace->color = light->color * add;
/* trace to point */
if ( trace->testOcclusion && !trace->forceSunlight ) {
@@ -1097,8 +1088,8 @@ int LightContributionToSample( trace_t *trace ){
TraceLine( trace );
trace->forceSubsampling *= add;
if ( !( trace->compileFlags & C_SKY ) || trace->opaque ) {
VectorClear( trace->color );
VectorClear( trace->directionContribution );
trace->color.set( 0 );
trace->directionContribution.set( 0 );
return -1;
}
@@ -1112,7 +1103,7 @@ int LightContributionToSample( trace_t *trace ){
}
/* VorteX: set noShadow color */
VectorScale( light->color, add, trace->colorNoShadow );
trace->colorNoShadow = light->color * add;
/* ydnar: changed to a variable number */
if ( add <= 0.0f || ( add <= light->falloffTolerance && ( light->flags & LightFlags::FastActual ) ) ) {
@@ -1142,19 +1133,19 @@ int LightContributionToSample( trace_t *trace ){
}
if ( doAddDeluxe ) {
VectorScale( trace->direction, addDeluxe, trace->directionContribution );
trace->directionContribution = trace->direction * addDeluxe;
}
/* setup trace */
trace->testAll = false;
VectorScale( light->color, add, trace->color );
trace->color = light->color * add;
/* raytrace */
TraceLine( trace );
trace->forceSubsampling *= add;
if ( trace->passSolid || trace->opaque ) {
VectorClear( trace->color );
VectorClear( trace->directionContribution );
trace->color.set( 0 );
trace->directionContribution.set( 0 );
return -1;
}
@@ -1170,13 +1161,13 @@ int LightContributionToSample( trace_t *trace ){
determines the amount of light reaching a sample (luxel or vertex)
*/
void LightingAtSample( trace_t *trace, byte styles[ MAX_LIGHTMAPS ], vec3_t colors[ MAX_LIGHTMAPS ] ){
void LightingAtSample( trace_t *trace, byte styles[ MAX_LIGHTMAPS ], Vector3 (&colors)[ MAX_LIGHTMAPS ] ){
int i, lightmapNum;
/* clear colors */
for ( lightmapNum = 0; lightmapNum < MAX_LIGHTMAPS; lightmapNum++ )
VectorClear( colors[ lightmapNum ] );
colors[ lightmapNum ].set( 0 );
/* ydnar: normalmap */
if ( normalmap ) {
@@ -1188,7 +1179,7 @@ void LightingAtSample( trace_t *trace, byte styles[ MAX_LIGHTMAPS ], vec3_t colo
/* ydnar: don't bounce ambient all the time */
if ( !bouncing ) {
VectorCopy( ambientColor, colors[ 0 ] );
colors[ 0 ] = ambientColor;
}
/* ydnar: trace to all the list of lights pre-stored in tw */
@@ -1219,14 +1210,14 @@ void LightingAtSample( trace_t *trace, byte styles[ MAX_LIGHTMAPS ], vec3_t colo
/* handle negative light */
if ( trace->light->flags & LightFlags::Negative ) {
VectorScale( trace->color, -1.0f, trace->color );
vector3_negate( trace->color );
}
/* set style */
styles[ lightmapNum ] = trace->light->style;
/* add it */
VectorAdd( colors[ lightmapNum ], trace->color, colors[ lightmapNum ] );
colors[ lightmapNum ] += trace->color;
/* cheap mode */
if ( cheap &&
@@ -1255,7 +1246,7 @@ bool LightContributionToPoint( trace_t *trace ){
light = trace->light;
/* clear color */
VectorClear( trace->color );
trace->color.set( 0 );
/* ydnar: early out */
if ( !( light->flags & LightFlags::Grid ) || light->envelope <= 0.0f ) {
@@ -1276,19 +1267,17 @@ bool LightContributionToPoint( trace_t *trace ){
}
/* ydnar: check origin against light's pvs envelope */
if ( trace->origin[ 0 ] > light->maxs[ 0 ] || trace->origin[ 0 ] < light->mins[ 0 ] ||
trace->origin[ 1 ] > light->maxs[ 1 ] || trace->origin[ 1 ] < light->mins[ 1 ] ||
trace->origin[ 2 ] > light->maxs[ 2 ] || trace->origin[ 2 ] < light->mins[ 2 ] ) {
if ( !light->minmax.test( trace->origin ) ) {
gridBoundsCulled++;
return false;
}
/* set light origin */
if ( light->type == ELightType::Sun ) {
VectorAdd( trace->origin, light->origin, trace->end );
trace->end = trace->origin + light->origin;
}
else{
VectorCopy( light->origin, trace->end );
trace->end = light->origin;
}
/* set direction */
@@ -1315,11 +1304,11 @@ bool LightContributionToPoint( trace_t *trace ){
/* exact point to polygon form factor */
else if ( light->type == ELightType::Area ) {
float factor, d;
vec3_t pushedOrigin;
Vector3 pushedOrigin;
/* see if the point is behind the light */
d = DotProduct( trace->origin, light->normal ) - light->dist;
d = vector3_dot( trace->origin, light->normal ) - light->dist;
if ( !( light->flags & LightFlags::Twosided ) && d < -1.0f ) {
return false;
}
@@ -1327,10 +1316,10 @@ bool LightContributionToPoint( trace_t *trace ){
/* nudge the point so that it is clearly forward of the light */
/* so that surfaces meeting a light emiter don't get black edges */
if ( d > -8.0f && d < 8.0f ) {
VectorMA( trace->origin, ( 8.0f - d ), light->normal, pushedOrigin );
pushedOrigin = trace->origin + light->normal * ( 8.0f - d );
}
else{
VectorCopy( trace->origin, pushedOrigin );
pushedOrigin = trace->origin;
}
/* calculate the contribution (ydnar 2002-10-21: [bug 642] bad normal calc) */
@@ -1372,19 +1361,15 @@ bool LightContributionToPoint( trace_t *trace ){
/* handle spotlights */
if ( light->type == ELightType::Spot ) {
float distByNormal, radiusAtDist, sampleRadius;
vec3_t pointAtDist, distToSample;
/* do cone calculation */
distByNormal = -DotProduct( trace->displacement, light->normal );
const float distByNormal = -vector3_dot( trace->displacement, light->normal );
if ( distByNormal < 0.0f ) {
return false;
}
VectorMA( light->origin, distByNormal, light->normal, pointAtDist );
radiusAtDist = light->radiusByDist * distByNormal;
VectorSubtract( trace->origin, pointAtDist, distToSample );
sampleRadius = VectorLength( distToSample );
const Vector3 pointAtDist = light->origin + light->normal * distByNormal;
const float radiusAtDist = light->radiusByDist * distByNormal;
const Vector3 distToSample = trace->origin - pointAtDist;
const float sampleRadius = vector3_length( distToSample );
/* outside the cone */
if ( sampleRadius >= radiusAtDist ) {
@@ -1408,14 +1393,14 @@ bool LightContributionToPoint( trace_t *trace ){
/* setup trace */
trace->testAll = true;
VectorScale( light->color, add, trace->color );
trace->color = light->color * add;
/* trace to point */
if ( trace->testOcclusion && !trace->forceSunlight ) {
/* trace */
TraceLine( trace );
if ( !( trace->compileFlags & C_SKY ) || trace->opaque ) {
VectorClear( trace->color );
trace->color.set( 0 );
return false;
}
}
@@ -1436,12 +1421,12 @@ bool LightContributionToPoint( trace_t *trace ){
/* setup trace */
trace->testAll = false;
VectorScale( light->color, add, trace->color );
trace->color = light->color * add;
/* trace */
TraceLine( trace );
if ( trace->passSolid ) {
VectorClear( trace->color );
trace->color.set( 0 );
return false;
}
@@ -1461,16 +1446,16 @@ bool LightContributionToPoint( trace_t *trace ){
struct contribution_t
{
vec3_t dir;
vec3_t color;
vec3_t ambient;
Vector3 dir;
Vector3 color;
Vector3 ambient;
int style;
};
void TraceGrid( int num ){
int i, j, x, y, z, mod, numCon, numStyles;
float d, step;
vec3_t baseOrigin, cheapColor, color, thisdir;
Vector3 cheapColor, thisdir;
rawGridPoint_t *gp;
bspGridPoint_t *bgp;
contribution_t contributions[ MAX_CONTRIBUTIONS ];
@@ -1507,10 +1492,10 @@ void TraceGrid( int num ){
trace.cluster = ClusterForPointExt( trace.origin, GRID_EPSILON );
if ( trace.cluster < 0 ) {
/* try to nudge the origin around to find a valid point */
VectorCopy( trace.origin, baseOrigin );
const Vector3 baseOrigin( trace.origin );
for ( step = 0; ( step += 0.005 ) <= 1.0; )
{
VectorCopy( baseOrigin, trace.origin );
trace.origin = baseOrigin;
trace.origin[ 0 ] += step * ( Random() - 0.5 ) * gridSize[0];
trace.origin[ 1 ] += step * ( Random() - 0.5 ) * gridSize[1];
trace.origin[ 2 ] += step * ( Random() - 0.5 ) * gridSize[2];
@@ -1539,7 +1524,7 @@ void TraceGrid( int num ){
/* clear */
numCon = 0;
VectorClear( cheapColor );
cheapColor.set( 0 );
/* trace to all the lights, find the major light direction, and divide the
total light between that along the direction and the remaining in the ambient */
@@ -1555,19 +1540,19 @@ void TraceGrid( int num ){
/* handle negative light */
if ( trace.light->flags & LightFlags::Negative ) {
VectorScale( trace.color, -1.0f, trace.color );
vector3_negate( trace.color );
}
/* add a contribution */
VectorCopy( trace.color, contributions[ numCon ].color );
VectorCopy( trace.direction, contributions[ numCon ].dir );
VectorClear( contributions[ numCon ].ambient );
contributions[ numCon ].color = trace.color;
contributions[ numCon ].dir = trace.direction;
contributions[ numCon ].ambient.set( 0 );
contributions[ numCon ].style = trace.light->style;
numCon++;
/* push average direction around */
addSize = VectorLength( trace.color );
VectorMA( gp->dir, addSize, trace.direction, gp->dir );
addSize = vector3_length( trace.color );
gp->dir += trace.direction * addSize;
/* stop after a while */
if ( numCon >= ( MAX_CONTRIBUTIONS - 1 ) ) {
@@ -1575,7 +1560,7 @@ void TraceGrid( int num ){
}
/* ydnar: cheap mode */
VectorAdd( cheapColor, trace.color, cheapColor );
cheapColor += trace.color;
if ( cheapgrid && cheapColor[ 0 ] >= 255.0f && cheapColor[ 1 ] >= 255.0f && cheapColor[ 2 ] >= 255.0f ) {
break;
}
@@ -1586,7 +1571,7 @@ void TraceGrid( int num ){
if ( floodlighty ) {
int k;
float addSize, f;
vec3_t dir = { 0, 0, 1 };
Vector3 dir = g_vector3_axis_z;
float ambientFrac = 0.25f;
trace.testOcclusion = true;
@@ -1597,37 +1582,27 @@ void TraceGrid( int num ){
for ( k = 0; k < 2; k++ )
{
if ( k == 0 ) { // upper hemisphere
trace.normal[0] = 0;
trace.normal[1] = 0;
trace.normal[2] = 1;
trace.normal = g_vector3_axis_z;
}
else //lower hemisphere
{
trace.normal[0] = 0;
trace.normal[1] = 0;
trace.normal[2] = -1;
trace.normal = -g_vector3_axis_z;
}
f = FloodLightForSample( &trace, floodlightDistance, floodlight_lowquality );
/* add a fraction as pure ambient, half as top-down direction */
contributions[ numCon ].color[0] = floodlightRGB[0] * floodlightIntensity * f * ( 1.0f - ambientFrac );
contributions[ numCon ].color[1] = floodlightRGB[1] * floodlightIntensity * f * ( 1.0f - ambientFrac );
contributions[ numCon ].color[2] = floodlightRGB[2] * floodlightIntensity * f * ( 1.0f - ambientFrac );
contributions[ numCon ].color = floodlightRGB * ( floodlightIntensity * f * ( 1.0f - ambientFrac ) );
contributions[ numCon ].ambient[0] = floodlightRGB[0] * floodlightIntensity * f * ambientFrac;
contributions[ numCon ].ambient[1] = floodlightRGB[1] * floodlightIntensity * f * ambientFrac;
contributions[ numCon ].ambient[2] = floodlightRGB[2] * floodlightIntensity * f * ambientFrac;
contributions[ numCon ].ambient = floodlightRGB * ( floodlightIntensity * f * ambientFrac );
contributions[ numCon ].dir[0] = dir[0];
contributions[ numCon ].dir[1] = dir[1];
contributions[ numCon ].dir[2] = dir[2];
contributions[ numCon ].dir = dir;
contributions[ numCon ].style = 0;
/* push average direction around */
addSize = VectorLength( contributions[ numCon ].color );
VectorMA( gp->dir, addSize, dir, gp->dir );
addSize = vector3_length( contributions[ numCon ].color );
gp->dir += dir * addSize;
numCon++;
}
@@ -1635,7 +1610,7 @@ void TraceGrid( int num ){
/////////////////////
/* normalize to get primary light direction */
VectorNormalize( gp->dir, thisdir );
thisdir = VectorNormalized( gp->dir );
/* now that we have identified the primary light direction,
go back and separate all the light into directed and ambient */
@@ -1644,7 +1619,7 @@ void TraceGrid( int num ){
for ( i = 0; i < numCon; i++ )
{
/* get relative directed strength */
d = DotProduct( contributions[ i ].dir, thisdir );
d = vector3_dot( contributions[ i ].dir, thisdir );
/* we map 1 to gridDirectionality, and 0 to gridAmbientDirectionality */
d = gridAmbientDirectionality + d * ( gridDirectionality - gridAmbientDirectionality );
if ( d < 0.0f ) {
@@ -1676,7 +1651,7 @@ void TraceGrid( int num ){
}
/* add the directed color */
VectorMA( gp->directed[ j ], d, contributions[ i ].color, gp->directed[ j ] );
gp->directed[ j ] += contributions[ i ].color * d;
/* ambient light will be at 1/4 the value of directed light */
/* (ydnar: nuke this in favor of more dramatic lighting?) */
@@ -1684,9 +1659,9 @@ void TraceGrid( int num ){
// d = 0.25f;
/* (Hobbes: always setting it to .25 is hardly any better) */
d = 0.25f * ( 1.0f - d );
VectorMA( gp->ambient[ j ], d, contributions[ i ].color, gp->ambient[ j ] );
gp->ambient[ j ] += contributions[ i ].color * d;
VectorAdd( gp->ambient[ j ], contributions[ i ].ambient, gp->ambient[ j ] );
gp->ambient[ j ] += contributions[ i ].ambient;
/*
* div0:
@@ -1714,7 +1689,7 @@ void TraceGrid( int num ){
#endif
/* set minimum light and copy off to bytes */
VectorCopy( gp->ambient[ i ], color );
Vector3 color = gp->ambient[ i ];
for ( j = 0; j < 3; j++ )
if ( color[ j ] < minGridLight[ j ] ) {
color[ j ] = minGridLight[ j ];
@@ -1731,7 +1706,7 @@ void TraceGrid( int num ){
*/
if( bgp->ambient[i][0] + bgp->ambient[i][1] + bgp->ambient[i][2] == 0
&& bgp->directed[i][0] + bgp->directed[i][1] + bgp->directed[i][2] != 0 )
VectorSet( bgp->ambient[i], 1, 1, 1 );
bgp->ambient[i].set( 1 );
}
/* debug code */
@@ -1756,7 +1731,6 @@ void TraceGrid( int num ){
void SetupGrid( void ){
int i, j;
vec3_t maxs, oldGridSize;
char temp[ 64 ];
@@ -1769,7 +1743,7 @@ void SetupGrid( void ){
entities[ 0 ].read_keyvalue( gridSize, "gridsize" );
/* quantize it */
VectorCopy( gridSize, oldGridSize );
const Vector3 oldGridSize = gridSize;
for ( i = 0; i < 3; i++ )
gridSize[ i ] = gridSize[ i ] >= 8.0f ? floor( gridSize[ i ] ) : 8.0f;
@@ -1781,9 +1755,9 @@ void SetupGrid( void ){
/* get world bounds */
for ( i = 0; i < 3; i++ )
{
gridMins[ i ] = gridSize[ i ] * ceil( bspModels[ 0 ].mins[ i ] / gridSize[ i ] );
maxs[ i ] = gridSize[ i ] * floor( bspModels[ 0 ].maxs[ i ] / gridSize[ i ] );
gridBounds[ i ] = ( maxs[ i ] - gridMins[ i ] ) / gridSize[ i ] + 1;
gridMins[ i ] = gridSize[ i ] * ceil( bspModels[ 0 ].minmax.mins[ i ] / gridSize[ i ] );
const float max = gridSize[ i ] * floor( bspModels[ 0 ].minmax.maxs[ i ] / gridSize[ i ] );
gridBounds[ i ] = ( max - gridMins[ i ] ) / gridSize[ i ] + 1;
}
/* set grid size */
@@ -1818,7 +1792,7 @@ void SetupGrid( void ){
for ( i = 0; i < numRawGridPoints; i++ )
{
for ( j = 0; j < MAX_LIGHTMAPS; j++ )
VectorCopy( ambientColor, rawGridPoints[ i ].ambient[ j ] );
rawGridPoints[ i ].ambient[ j ] = ambientColor;
rawGridPoints[ i ].styles[ 0 ] = LS_NORMAL;
bspGridPoints[ i ].styles[ 0 ] = LS_NORMAL;
@@ -1841,7 +1815,7 @@ void SetupGrid( void ){
*/
void LightWorld( bool fastAllocate ){
vec3_t color;
Vector3 color;
float f;
int b, bt;
bool minVertex, minGrid;
@@ -1860,31 +1834,31 @@ void LightWorld( bool fastAllocate ){
color[1] = Image_LinearFloatFromsRGBFloat( color[1] );
color[2] = Image_LinearFloatFromsRGBFloat( color[2] );
}
if ( VectorLength( color ) == 0.0f ) {
VectorSet( color, 1.0, 1.0, 1.0 );
if ( vector3_length( color ) == 0.0f ) {
color.set( 1 );
}
/* ambient */
f = entities[ 0 ].floatForKey( "_ambient", "ambient" );
VectorScale( color, f, ambientColor );
ambientColor = color * f;
/* minvertexlight */
if ( ( minVertex = entities[ 0 ].read_keyvalue( f, "_minvertexlight" ) ) ) {
VectorScale( color, f, minVertexLight );
minVertexLight = color * f;
}
/* mingridlight */
if ( ( minGrid = entities[ 0 ].read_keyvalue( f, "_mingridlight" ) ) ) {
VectorScale( color, f, minGridLight );
minGridLight = color * f;
}
/* minlight */
if ( entities[ 0 ].read_keyvalue( f, "_minlight" ) ) {
VectorScale( color, f, minLight );
minLight = color * f;
if ( !minVertex )
VectorScale( color, f, minVertexLight );
minVertexLight = color * f;
if ( !minGrid )
VectorScale( color, f, minGridLight );
minGridLight = color * f;
}
/* maxlight */
@@ -1982,7 +1956,7 @@ void LightWorld( bool fastAllocate ){
/* flag bouncing */
bouncing = true;
VectorClear( ambientColor );
ambientColor.set( 0 );
floodlighty = false;
/* generate diffuse lights */
+112 -148
View File
@@ -65,13 +65,13 @@ void RadFreeLights( void ){
based off the regular clip winding code
*/
static void RadClipWindingEpsilon( radWinding_t *in, vec3_t normal, vec_t dist,
vec_t epsilon, radWinding_t *front, radWinding_t *back, clipWork_t *cw ){
vec_t *dists;
int *sides;
static void RadClipWindingEpsilon( radWinding_t *in, const Vector3& normal, float dist,
float epsilon, radWinding_t *front, radWinding_t *back, clipWork_t *cw ){
float *dists;
EPlaneSide *sides;
int counts[ 3 ];
vec_t dot; /* ydnar: changed from static b/c of threading */ /* VC 4.2 optimizer bug if not static? */
int i, j, k;
float dot; /* ydnar: changed from static b/c of threading */ /* VC 4.2 optimizer bug if not static? */
int i, k;
radVert_t *v1, *v2, mid;
int maxPoints;
@@ -86,17 +86,15 @@ static void RadClipWindingEpsilon( radWinding_t *in, vec3_t normal, vec_t dist,
/* determine sides for each point */
for ( i = 0; i < in->numVerts; i++ )
{
dot = DotProduct( in->verts[ i ].xyz, normal );
dot -= dist;
dists[ i ] = dot;
if ( dot > epsilon ) {
sides[ i ] = SIDE_FRONT;
dists[ i ] = vector3_dot( in->verts[ i ].xyz, normal ) - dist;
if ( dists[ i ] > epsilon ) {
sides[ i ] = eSideFront;
}
else if ( dot < -epsilon ) {
sides[ i ] = SIDE_BACK;
else if ( dists[ i ] < -epsilon ) {
sides[ i ] = eSideBack;
}
else{
sides[ i ] = SIDE_ON;
sides[ i ] = eSideOn;
}
counts[ sides[ i ] ]++;
}
@@ -125,21 +123,21 @@ static void RadClipWindingEpsilon( radWinding_t *in, vec3_t normal, vec_t dist,
/* do simple vertex copies first */
v1 = &in->verts[ i ];
if ( sides[ i ] == SIDE_ON ) {
if ( sides[ i ] == eSideOn ) {
memcpy( &front->verts[ front->numVerts++ ], v1, sizeof( radVert_t ) );
memcpy( &back->verts[ back->numVerts++ ], v1, sizeof( radVert_t ) );
continue;
}
if ( sides[ i ] == SIDE_FRONT ) {
if ( sides[ i ] == eSideFront ) {
memcpy( &front->verts[ front->numVerts++ ], v1, sizeof( radVert_t ) );
}
if ( sides[ i ] == SIDE_BACK ) {
if ( sides[ i ] == eSideBack ) {
memcpy( &back->verts[ back->numVerts++ ], v1, sizeof( radVert_t ) );
}
if ( sides[ i + 1 ] == SIDE_ON || sides[ i + 1 ] == sides[ i ] ) {
if ( sides[ i + 1 ] == eSideOn || sides[ i + 1 ] == sides[ i ] ) {
continue;
}
@@ -149,30 +147,20 @@ static void RadClipWindingEpsilon( radWinding_t *in, vec3_t normal, vec_t dist,
dot = dists[ i ] / ( dists[ i ] - dists[ i + 1 ] );
/* average vertex values */
for ( j = 0; j < 4; j++ )
{
/* color */
if ( j < 4 ) {
for ( k = 0; k < MAX_LIGHTMAPS; k++ )
mid.color[ k ][ j ] = v1->color[ k ][ j ] + dot * ( v2->color[ k ][ j ] - v1->color[ k ][ j ] );
}
/* xyz, normal */
if ( j < 3 ) {
mid.xyz[ j ] = v1->xyz[ j ] + dot * ( v2->xyz[ j ] - v1->xyz[ j ] );
mid.normal[ j ] = v1->normal[ j ] + dot * ( v2->normal[ j ] - v1->normal[ j ] );
}
/* st, lightmap */
if ( j < 2 ) {
mid.st[ j ] = v1->st[ j ] + dot * ( v2->st[ j ] - v1->st[ j ] );
for ( k = 0; k < MAX_LIGHTMAPS; k++ )
mid.lightmap[ k ][ j ] = v1->lightmap[ k ][ j ] + dot * ( v2->lightmap[ k ][ j ] - v1->lightmap[ k ][ j ] );
}
/* color */
for ( k = 0; k < MAX_LIGHTMAPS; k++ ){
mid.color[ k ] = v1->color[ k ] + ( v2->color[ k ] - v1->color[ k ] ) * dot;
}
/* xyz, normal */
mid.xyz = v1->xyz + ( v2->xyz - v1->xyz ) * dot;
mid.normal = v1->normal + ( v2->normal - v1->normal ) * dot;
/* st, lightmap */
mid.st = v1->st + ( v2->st - v1->st ) * dot;
for ( k = 0; k < MAX_LIGHTMAPS; k++ )
mid.lightmap[ k ] = v1->lightmap[ k ] + ( v2->lightmap[ k ] - v1->lightmap[ k ] ) * dot;
/* normalize the averaged normal */
VectorNormalize( mid.normal, mid.normal );
VectorNormalize( mid.normal );
/* copy the midpoint to both windings */
memcpy( &front->verts[ front->numVerts++ ], &mid, sizeof( radVert_t ) );
@@ -201,11 +189,11 @@ float Modulo1IfNegative( float f ){
returns false if pixels are bad
*/
bool RadSampleImage( byte *pixels, int width, int height, float st[ 2 ], float color[ 4 ] ){
bool RadSampleImage( byte *pixels, int width, int height, const Vector2& st, Color4f& color ){
int x, y;
/* clear color first */
color[ 0 ] = color[ 1 ] = color[ 2 ] = color[ 3 ] = 255;
color.set( 255 );
/* dummy check */
if ( pixels == NULL || width < 1 || height < 1 ) {
@@ -220,8 +208,8 @@ bool RadSampleImage( byte *pixels, int width, int height, float st[ 2 ], float c
/* get pixel */
pixels += ( y * width * 4 ) + ( x * 4 );
VectorCopy( pixels, color );
color[ 3 ] = pixels[ 3 ];
VectorCopy( pixels, color.rgb() );
color.alpha() = pixels[ 3 ];
if ( texturesRGB ) {
color[0] = Image_LinearFloatFromsRGBFloat( color[0] * ( 1.0 / 255.0 ) ) * 255.0;
@@ -243,22 +231,20 @@ bool RadSampleImage( byte *pixels, int width, int height, float st[ 2 ], float c
#define MAX_SAMPLES 150
#define SAMPLE_GRANULARITY 6
static void RadSample( int lightmapNum, bspDrawSurface_t *ds, rawLightmap_t *lm, shaderInfo_t *si, radWinding_t *rw, vec3_t average, vec3_t gradient, int *style ){
int i, j, k, l, v, x, y, samples, avgcolor;
vec3_t color, mins, maxs;
vec4_t textureColor;
float alpha, alphaI, bf;
vec3_t blend;
float st[ 2 ], lightmap[ 2 ], *radLuxel;
static void RadSample( int lightmapNum, bspDrawSurface_t *ds, rawLightmap_t *lm, shaderInfo_t *si, radWinding_t *rw, Vector3& average, Vector3& gradient, int *style ){
int i, j, k, l, v, x, y, samples;
Vector3 color;
MinMax minmax;
Color4f textureColor;
float alpha, alphaI;
radVert_t *rv[ 3 ];
if (!bouncing)
if ( !bouncing )
Sys_Printf( "BUG: RadSample: !bouncing shouldn't happen\n" );
/* initial setup */
ClearBounds( mins, maxs );
VectorClear( average );
VectorClear( gradient );
average.set( 0 );
gradient.set( 0 );
alpha = 0;
/* dummy check */
@@ -275,19 +261,18 @@ static void RadSample( int lightmapNum, bspDrawSurface_t *ds, rawLightmap_t *lm,
{
/* multiply by texture color */
if ( !RadSampleImage( si->lightImage->pixels, si->lightImage->width, si->lightImage->height, rw->verts[ samples ].st, textureColor ) ) {
VectorCopy( si->averageColor, textureColor );
textureColor[ 3 ] = 255.0f;
textureColor.rgb() = si->averageColor.rgb();
textureColor.alpha() = 255.0f;
}
avgcolor = ( textureColor[ 0 ] + textureColor[ 1 ] + textureColor[ 2 ] ) / 3;
for ( i = 0; i < 3; i++ )
color[ i ] = ( ( textureColor[ i ] * bounceColorRatio + ( avgcolor * ( 1 - bounceColorRatio ) ) ) / 255 ) * ( rw->verts[ samples ].color[ lightmapNum ][ i ] / 255.0f );
// color[ i ] = ( textureColor[ i ] / 255 ) * ( rw->verts[ samples ].color[ lightmapNum ][ i ] / 255.0f );
const float avgcolor = ( textureColor[ 0 ] + textureColor[ 1 ] + textureColor[ 2 ] ) / 3;
color = ( ( textureColor.rgb() * bounceColorRatio + Vector3().set( avgcolor * ( 1 - bounceColorRatio ) ) ) / 255 ) * ( rw->verts[ samples ].color[ lightmapNum ].rgb() / 255.0f );
// color = ( textureColor.rgb / 255 ) * ( rw->verts[ samples ].color[ lightmapNum ].rgb / 255.0f );
AddPointToBounds( color, mins, maxs );
VectorAdd( average, color, average );
minmax.extend( color );
average += color;
/* get alpha */
alpha += ( textureColor[ 3 ] / 255.0f ) * ( rw->verts[ samples ].color[ lightmapNum ][ 3 ] / 255.0f );
alpha += ( textureColor.alpha() / 255.0f ) * ( rw->verts[ samples ].color[ lightmapNum ].alpha() / 255.0f );
}
/* set style */
@@ -313,23 +298,18 @@ static void RadSample( int lightmapNum, bspDrawSurface_t *ds, rawLightmap_t *lm,
for ( k = 1; k < SAMPLE_GRANULARITY && samples < MAX_SAMPLES; k++ )
{
/* create a blend vector (barycentric coordinates) */
blend[ 0 ] = i;
blend[ 1 ] = j;
blend[ 2 ] = k;
bf = ( 1.0 / ( blend[ 0 ] + blend[ 1 ] + blend[ 2 ] ) );
VectorScale( blend, bf, blend );
DoubleVector3 blend( i, j, k );
blend *= 1.0 / ( blend[ 0 ] + blend[ 1 ] + blend[ 2 ] );
/* create a blended sample */
st[ 0 ] = st[ 1 ] = 0.0f;
lightmap[ 0 ] = lightmap[ 1 ] = 0.0f;
Vector2 st( 0, 0 );
Vector2 lightmap( 0, 0 );
alphaI = 0.0f;
for ( l = 0; l < 3; l++ )
{
st[ 0 ] += ( rv[ l ]->st[ 0 ] * blend[ l ] );
st[ 1 ] += ( rv[ l ]->st[ 1 ] * blend[ l ] );
lightmap[ 0 ] += ( rv[ l ]->lightmap[ lightmapNum ][ 0 ] * blend[ l ] );
lightmap[ 1 ] += ( rv[ l ]->lightmap[ lightmapNum ][ 1 ] * blend[ l ] );
alphaI += ( rv[ l ]->color[ lightmapNum ][ 3 ] * blend[ l ] );
st += rv[ l ]->st * blend[ l ];
lightmap += rv[ l ]->lightmap[ lightmapNum ] * blend[ l ];
alphaI += rv[ l ]->color[ lightmapNum ].alpha() * blend[ l ];
}
/* get lightmap xy coords */
@@ -349,7 +329,7 @@ static void RadSample( int lightmapNum, bspDrawSurface_t *ds, rawLightmap_t *lm,
}
/* get radiosity luxel */
radLuxel = RAD_LUXEL( lightmapNum, x, y );
const Vector3& radLuxel = lm->getRadLuxel( lightmapNum, x, y );
/* ignore unlit/unused luxels */
if ( radLuxel[ 0 ] < 0.0f ) {
@@ -361,19 +341,17 @@ static void RadSample( int lightmapNum, bspDrawSurface_t *ds, rawLightmap_t *lm,
/* multiply by texture color */
if ( !RadSampleImage( si->lightImage->pixels, si->lightImage->width, si->lightImage->height, st, textureColor ) ) {
VectorCopy( si->averageColor, textureColor );
textureColor[ 3 ] = 255;
textureColor.rgb() = si->averageColor.rgb();
textureColor.alpha() = 255;
}
avgcolor = ( textureColor[ 0 ] + textureColor[ 1 ] + textureColor[ 2 ] ) / 3;
for ( l = 0; l < 3; l++ ){
color[ l ] = ( ( textureColor[ l ] * bounceColorRatio + ( avgcolor * ( 1 - bounceColorRatio ) ) ) / 255 ) * ( radLuxel[ l ] / 255 );
//Sys_Printf( "%i %i %i %i %i \n", (int) textureColor[ 0 ], (int) textureColor[ 1 ], (int) textureColor[ 2 ], (int) avgcolor, (int) color[ i ] );
}
AddPointToBounds( color, mins, maxs );
VectorAdd( average, color, average );
const float avgcolor = ( textureColor[ 0 ] + textureColor[ 1 ] + textureColor[ 2 ] ) / 3;
color = ( ( textureColor.rgb() * bounceColorRatio + Vector3().set( avgcolor * ( 1 - bounceColorRatio ) ) ) / 255 ) * ( radLuxel / 255 );
//Sys_Printf( "%i %i %i %i %i \n", (int) textureColor.rgb[ 0 ], (int) textureColor.rgb[ 1 ], (int) textureColor.rgb[ 2 ], (int) avgcolor, (int) color[ i ] );
minmax.extend( color );
average += color;
/* get alpha */
alpha += ( textureColor[ 3 ] / 255 ) * ( alphaI / 255 );
alpha += ( textureColor.alpha() / 255 ) * ( alphaI / 255 );
}
}
}
@@ -389,19 +367,18 @@ static void RadSample( int lightmapNum, bspDrawSurface_t *ds, rawLightmap_t *lm,
}
/* average the color */
VectorScale( average, ( 1.0 / samples ), average );
average *= ( 1.0 / samples );
/* create the color gradient */
//% VectorSubtract( maxs, mins, delta );
//% VectorSubtract( minmax.maxs, minmax.mins, delta );
/* new: color gradient will always be 0-1.0, expressed as the range of light relative to overall light */
//% gradient[ 0 ] = maxs[ 0 ] > 0.0f ? (maxs[ 0 ] - mins[ 0 ]) / maxs[ 0 ] : 0.0f;
//% gradient[ 1 ] = maxs[ 1 ] > 0.0f ? (maxs[ 1 ] - mins[ 1 ]) / maxs[ 1 ] : 0.0f;
//% gradient[ 2 ] = maxs[ 2 ] > 0.0f ? (maxs[ 2 ] - mins[ 2 ]) / maxs[ 2 ] : 0.0f;
//% gradient[ 0 ] = minmax.maxs[ 0 ] > 0.0f ? (minmax.maxs[ 0 ] - minmax.mins[ 0 ]) / minmax.maxs[ 0 ] : 0.0f;
//% gradient[ 1 ] = minmax.maxs[ 1 ] > 0.0f ? (minmax.maxs[ 1 ] - minmax.mins[ 1 ]) / minmax.maxs[ 1 ] : 0.0f;
//% gradient[ 2 ] = minmax.maxs[ 2 ] > 0.0f ? (minmax.maxs[ 2 ] - minmax.mins[ 2 ]) / minmax.maxs[ 2 ] : 0.0f;
/* newer: another contrast function */
for ( i = 0; i < 3; i++ )
gradient[ i ] = ( maxs[ i ] - mins[ i ] ) * maxs[ i ];
gradient = ( minmax.maxs - minmax.mins ) * minmax.maxs;
}
@@ -422,7 +399,7 @@ static void RadSubdivideDiffuseLight( int lightmapNum, bspDrawSurface_t *ds, raw
float scale, float subdivide, radWinding_t *rw, clipWork_t *cw ){
int i, style = 0;
float dist, area, value;
vec3_t mins, maxs, normal, d1, d2, cross, color, gradient;
Vector3 normal, color, gradient;
light_t *light, *splash;
winding_t *w, *splash_w;
@@ -433,24 +410,22 @@ static void RadSubdivideDiffuseLight( int lightmapNum, bspDrawSurface_t *ds, raw
}
/* get bounds for winding */
ClearBounds( mins, maxs );
MinMax minmax;
for ( i = 0; i < rw->numVerts; i++ )
AddPointToBounds( rw->verts[ i ].xyz, mins, maxs );
minmax.extend( rw->verts[ i ].xyz );
/* subdivide if necessary */
for ( i = 0; i < 3; i++ )
{
if ( maxs[ i ] - mins[ i ] > subdivide ) {
if ( minmax.maxs[ i ] - minmax.mins[ i ] > subdivide ) {
auto front = std::make_unique<radWinding_t>();
auto back = std::make_unique<radWinding_t>();
/* make axial plane */
VectorClear( normal );
normal[ i ] = 1;
dist = ( maxs[ i ] + mins[ i ] ) * 0.5f;
dist = ( minmax.maxs[ i ] + minmax.mins[ i ] ) * 0.5f;
/* clip the winding */
RadClipWindingEpsilon( rw, normal, dist, RADIOSITY_CLIP_EPSILON, front.get(), back.get(), cw );
RadClipWindingEpsilon( rw, g_vector3_axes[i], dist, RADIOSITY_CLIP_EPSILON, front.get(), back.get(), cw );
/* recurse */
RadSubdivideDiffuseLight( lightmapNum, ds, lm, si, scale, subdivide, front.get(), cw );
@@ -463,10 +438,7 @@ static void RadSubdivideDiffuseLight( int lightmapNum, bspDrawSurface_t *ds, raw
area = 0.0f;
for ( i = 2; i < rw->numVerts; i++ )
{
VectorSubtract( rw->verts[ i - 1 ].xyz, rw->verts[ 0 ].xyz, d1 );
VectorSubtract( rw->verts[ i ].xyz, rw->verts[ 0 ].xyz, d2 );
CrossProduct( d1, d2, cross );
area += 0.5f * VectorLength( cross );
area += 0.5f * vector3_length( vector3_cross( rw->verts[ i - 1 ].xyz - rw->verts[ 0 ].xyz, rw->verts[ i ].xyz - rw->verts[ 0 ].xyz ) );
}
if ( area < 1.0f || area > 20000000.0f ) {
return;
@@ -488,24 +460,24 @@ static void RadSubdivideDiffuseLight( int lightmapNum, bspDrawSurface_t *ds, raw
/* create a regular winding and an average normal */
w = AllocWinding( rw->numVerts );
w->numpoints = rw->numVerts;
VectorClear( normal );
normal.set( 0 );
for ( i = 0; i < rw->numVerts; i++ )
{
VectorCopy( rw->verts[ i ].xyz, w->p[ i ] );
VectorAdd( normal, rw->verts[ i ].normal, normal );
w->p[ i ] = rw->verts[ i ].xyz;
normal += rw->verts[ i ].normal;
}
VectorScale( normal, ( 1.0f / rw->numVerts ), normal );
if ( VectorNormalize( normal, normal ) == 0.0f ) {
normal /= rw->numVerts;
if ( VectorNormalize( normal ) == 0.0f ) {
return;
}
/* early out? */
if ( bouncing && VectorLength( color ) < RADIOSITY_MIN ) {
if ( bouncing && vector3_length( color ) < RADIOSITY_MIN ) {
return;
}
/* debug code */
//% Sys_Printf( "Size: %d %d %d\n", (int) (maxs[ 0 ] - mins[ 0 ]), (int) (maxs[ 1 ] - mins[ 1 ]), (int) (maxs[ 2 ] - mins[ 2 ]) );
//% Sys_Printf( "Size: %d %d %d\n", (int) (minmax.maxs[ 0 ] - minmax.mins[ 0 ]), (int) (minmax.maxs[ 1 ] - minmax.mins[ 1 ]), (int) (minmax.maxs[ 2 ] - minmax.mins[ 2 ]) );
//% Sys_Printf( "Grad: %f %f %f\n", gradient[ 0 ], gradient[ 1 ], gradient[ 2 ] );
/* increment counts */
@@ -553,21 +525,20 @@ static void RadSubdivideDiffuseLight( int lightmapNum, bspDrawSurface_t *ds, raw
value = si->value;
light->photons = value * area * areaScale;
light->add = value * formFactorValueScale * areaScale;
VectorCopy( si->color, light->color );
VectorScale( light->color, light->add, light->emitColor );
light->color = si->color;
light->emitColor = light->color * light->add;
light->style = noStyles ? LS_NORMAL : si->lightStyle;
if ( light->style < LS_NORMAL || light->style >= LS_NONE ) {
light->style = LS_NORMAL;
}
/* set origin */
VectorAdd( mins, maxs, light->origin );
VectorScale( light->origin, 0.5f, light->origin );
light->origin = minmax.origin();
/* nudge it off the plane a bit */
VectorCopy( normal, light->normal );
VectorMA( light->origin, 1.0f, light->normal, light->origin );
light->dist = DotProduct( light->origin, normal );
light->normal = normal;
light->origin += light->normal;
light->dist = vector3_dot( light->origin, normal );
#if 0
/* optionally create a point backsplash light */
@@ -587,8 +558,8 @@ static void RadSubdivideDiffuseLight( int lightmapNum, bspDrawSurface_t *ds, raw
splash->fade = 1.0f;
splash->si = si;
VectorMA( light->origin, si->backsplashDistance, normal, splash->origin );
VectorCopy( si->color, splash->color );
splash->origin = normal * si->backsplashDistance + light->origin;
splash->color = si->color;
splash->falloffTolerance = falloffTolerance;
splash->style = noStyles ? LS_NORMAL : light->style;
@@ -616,8 +587,8 @@ static void RadSubdivideDiffuseLight( int lightmapNum, bspDrawSurface_t *ds, raw
splash->add = light->add * 7.0f * si->backsplashFraction;
splash->fade = 1.0f;
splash->si = si;
VectorCopy( si->color, splash->color );
VectorScale( splash->color, splash->add, splash->emitColor );
splash->color = si->color;
splash->emitColor = splash->color * splash->add;
splash->falloffTolerance = falloffTolerance;
splash->style = noStyles ? LS_NORMAL : si->lightStyle;
if ( splash->style < LS_NORMAL || splash->style >= LS_NONE ) {
@@ -628,12 +599,12 @@ static void RadSubdivideDiffuseLight( int lightmapNum, bspDrawSurface_t *ds, raw
splash_w = AllocWinding( rw->numVerts );
splash_w->numpoints = rw->numVerts;
for ( i = 0; i < rw->numVerts; i++ )
VectorMA( rw->verts[rw->numVerts - 1 - i].xyz, si->backsplashDistance, normal, splash_w->p[ i ] );
splash_w->p[ i ] = normal * si->backsplashDistance + rw->verts[rw->numVerts - 1 - i].xyz;
splash->w = splash_w;
VectorMA( light->origin, si->backsplashDistance, normal, splash->origin );
VectorNegate( normal, splash->normal );
splash->dist = DotProduct( splash->origin, splash->normal );
splash->origin = normal * si->backsplashDistance + light->origin;
splash->normal = -normal;
splash->dist = vector3_dot( splash->origin, splash->normal );
// splash->flags |= LightFlags::Twosided;
}
@@ -646,20 +617,20 @@ static void RadSubdivideDiffuseLight( int lightmapNum, bspDrawSurface_t *ds, raw
value = RADIOSITY_VALUE * si->bounceScale * 0.375f;
light->photons = value * area * bounceScale;
light->add = value * formFactorValueScale * bounceScale;
VectorCopy( color, light->color );
VectorScale( light->color, light->add, light->emitColor );
light->color = color;
light->emitColor = light->color * light->add;
light->style = noStyles ? LS_NORMAL : style;
if ( light->style < LS_NORMAL || light->style >= LS_NONE ) {
light->style = LS_NORMAL;
}
/* set origin */
WindingCenter( w, light->origin );
light->origin = WindingCenter( w );
/* nudge it off the plane a bit */
VectorCopy( normal, light->normal );
VectorMA( light->origin, 1.0f, light->normal, light->origin );
light->dist = DotProduct( light->origin, normal );
light->normal = normal;
light->origin += light->normal;
light->dist = vector3_dot( light->origin, normal );
}
if (light->photons < 0 || light->add < 0 || light->color[0] < 0 || light->color[1] < 0 || light->color[2] < 0)
@@ -685,7 +656,6 @@ static void RadSubdivideDiffuseLight( int lightmapNum, bspDrawSurface_t *ds, raw
void RadLightForTriangles( int num, int lightmapNum, rawLightmap_t *lm, shaderInfo_t *si, float scale, float subdivide, clipWork_t *cw ){
int i, j, k, v;
bspDrawSurface_t *ds;
float *radVertexLuxel;
radWinding_t rw;
@@ -708,9 +678,8 @@ void RadLightForTriangles( int num, int lightmapNum, rawLightmap_t *lm, shaderIn
/* fix colors */
for ( k = 0; k < MAX_LIGHTMAPS; k++ )
{
radVertexLuxel = RAD_VERTEX_LUXEL( k, ds->firstVert + bspDrawIndexes[ ds->firstIndex + i + j ] );
VectorCopy( radVertexLuxel, rw.verts[ j ].color[ k ] );
rw.verts[ j ].color[ k ][ 3 ] = yDrawVerts[ v ].color[ k ][ 3 ];
rw.verts[ j ].color[ k ].rgb() = getRadVertexLuxel( k, ds->firstVert + bspDrawIndexes[ ds->firstIndex + i + j ] );
rw.verts[ j ].color[ k ].alpha() = yDrawVerts[ v ].color[ k ].alpha();
}
}
@@ -735,9 +704,6 @@ void RadLightForPatch( int num, int lightmapNum, rawLightmap_t *lm, shaderInfo_t
bspDrawVert_t *bogus;
bspDrawVert_t *dv[ 4 ];
mesh_t src, *subdivided, *mesh;
float *radVertexLuxel;
float dist;
vec4_t plane;
bool planar;
radWinding_t rw;
@@ -798,10 +764,10 @@ void RadLightForPatch( int num, int lightmapNum, rawLightmap_t *lm, shaderInfo_t
dv[ 3 ] = &mesh->verts[ pw[ r + 3 ] ];
/* planar? */
Plane3f plane;
planar = PlaneFromPoints( plane, dv[ 0 ]->xyz, dv[ 1 ]->xyz, dv[ 2 ]->xyz );
if ( planar ) {
dist = DotProduct( dv[ 1 ]->xyz, plane ) - plane[ 3 ];
if ( fabs( dist ) > PLANAR_EPSILON ) {
if ( fabs( plane3_distance_to_point( plane, dv[ 1 ]->xyz ) ) > PLANAR_EPSILON ) {
planar = false;
}
}
@@ -817,9 +783,8 @@ void RadLightForPatch( int num, int lightmapNum, rawLightmap_t *lm, shaderInfo_t
/* fix colors */
for ( i = 0; i < MAX_LIGHTMAPS; i++ )
{
radVertexLuxel = RAD_VERTEX_LUXEL( i, ds->firstVert + dv[ v ]->color[ 0 ][ 0 ] );
VectorCopy( radVertexLuxel, rw.verts[ v ].color[ i ] );
rw.verts[ v ].color[ i ][ 3 ] = dv[ v ]->color[ i ][ 3 ];
rw.verts[ v ].color[ i ].rgb() = getRadVertexLuxel( i, ds->firstVert + dv[ v ]->color[ 0 ][ 0 ] );
rw.verts[ v ].color[ i ].alpha() = dv[ v ]->color[ i ].alpha();
}
}
@@ -846,9 +811,8 @@ void RadLightForPatch( int num, int lightmapNum, rawLightmap_t *lm, shaderInfo_t
/* fix colors */
for ( i = 0; i < MAX_LIGHTMAPS; i++ )
{
radVertexLuxel = RAD_VERTEX_LUXEL( i, ds->firstVert + dv[ v ]->color[ 0 ][ 0 ] );
VectorCopy( radVertexLuxel, rw.verts[ v ].color[ i ] );
rw.verts[ v ].color[ i ][ 3 ] = dv[ v ]->color[ i ][ 3 ];
rw.verts[ v ].color[ i ].rgb() = getRadVertexLuxel( i, ds->firstVert + dv[ v ]->color[ 0 ][ 0 ] );
rw.verts[ v ].color[ i ].alpha() = dv[ v ]->color[ i ].alpha();
}
}
+132 -147
View File
@@ -38,7 +38,6 @@
#define Vector2Copy( a, b ) ( ( b )[ 0 ] = ( a )[ 0 ], ( b )[ 1 ] = ( a )[ 1 ] )
#define Vector4Copy( a, b ) ( ( b )[ 0 ] = ( a )[ 0 ], ( b )[ 1 ] = ( a )[ 1 ], ( b )[ 2 ] = ( a )[ 2 ], ( b )[ 3 ] = ( a )[ 3 ] )
#define MAX_NODE_ITEMS 5
#define MAX_NODE_TRIANGLES 5
@@ -60,8 +59,8 @@
struct traceVert_t
{
vec3_t xyz;
float st[ 2 ];
Vector3 xyz;
Vector2 st;
};
struct traceInfo_t
@@ -73,14 +72,14 @@ struct traceInfo_t
struct traceWinding_t
{
vec4_t plane;
Plane3f plane;
int infoNum, numVerts;
traceVert_t v[ MAX_TW_VERTS ];
};
struct traceTriangle_t
{
vec3_t edge1, edge2;
Vector3 edge1, edge2;
int infoNum;
traceVert_t v[ 3 ];
};
@@ -88,8 +87,8 @@ struct traceTriangle_t
struct traceNode_t
{
int type;
vec4_t plane;
vec3_t mins, maxs;
Plane3f plane;
MinMax minmax;
int children[ 2 ];
int numItems, maxItems;
int *items;
@@ -165,7 +164,7 @@ static int AllocTraceNode( void ){
/* add the node */
memset( &traceNodes[ numTraceNodes ], 0, sizeof( traceNode_t ) );
traceNodes[ numTraceNodes ].type = TRACE_LEAF;
ClearBounds( traceNodes[ numTraceNodes ].mins, traceNodes[ numTraceNodes ].maxs );
traceNodes[ numTraceNodes ].minmax.clear();
/* Sys_Printf("alloc node %d\n", numTraceNodes); */
@@ -233,8 +232,8 @@ static int AddTraceTriangle( traceTriangle_t *tt ){
}
/* find vectors for two edges sharing the first vert */
VectorSubtract( tt->v[ 1 ].xyz, tt->v[ 0 ].xyz, tt->edge1 );
VectorSubtract( tt->v[ 2 ].xyz, tt->v[ 0 ].xyz, tt->edge2 );
tt->edge1 = tt->v[ 1 ].xyz - tt->v[ 0 ].xyz;
tt->edge2 = tt->v[ 2 ].xyz - tt->v[ 0 ].xyz;
/* add the triangle */
memcpy( &traceTriangles[ num ], tt, sizeof( *traceTriangles ) );
@@ -302,28 +301,25 @@ static int AddItemToTraceNode( traceNode_t *node, int num ){
static int SetupTraceNodes_r( int bspNodeNum ){
int i, nodeNum, bspLeafNum, newNode;
bspPlane_t *plane;
bspNode_t *bspNode;
/* get bsp node and plane */
bspNode = &bspNodes[ bspNodeNum ];
plane = &bspPlanes[ bspNode->planeNum ];
const bspNode_t& bspNode = bspNodes[ bspNodeNum ];
const bspPlane_t& plane = bspPlanes[ bspNode.planeNum ];
/* allocate a new trace node */
nodeNum = AllocTraceNode();
/* setup trace node */
traceNodes[ nodeNum ].type = PlaneTypeForNormal( plane->normal );
VectorCopy( plane->normal, traceNodes[ nodeNum ].plane );
traceNodes[ nodeNum ].plane[ 3 ] = plane->dist;
traceNodes[ nodeNum ].type = PlaneTypeForNormal( plane.normal() );
traceNodes[ nodeNum ].plane = plane;
/* setup children */
for ( i = 0; i < 2; i++ )
{
/* leafnode */
if ( bspNode->children[ i ] < 0 ) {
bspLeafNum = -bspNode->children[ i ] - 1;
if ( bspNode.children[ i ] < 0 ) {
bspLeafNum = -bspNode.children[ i ] - 1;
/* new code */
newNode = AllocTraceNode();
@@ -338,7 +334,7 @@ static int SetupTraceNodes_r( int bspNodeNum ){
/* normal node */
else
{
newNode = SetupTraceNodes_r( bspNode->children[ i ] );
newNode = SetupTraceNodes_r( bspNode.children[ i ] );
traceNodes[ nodeNum ].children[ i ] = newNode;
}
@@ -362,9 +358,10 @@ static int SetupTraceNodes_r( int bspNodeNum ){
#define TW_ON_EPSILON 0.25f
void ClipTraceWinding( traceWinding_t *tw, vec4_t plane, traceWinding_t *front, traceWinding_t *back ){
void ClipTraceWinding( traceWinding_t *tw, const Plane3f& plane, traceWinding_t *front, traceWinding_t *back ){
int i, j, k;
int sides[ MAX_TW_VERTS ], counts[ 3 ] = { 0, 0, 0 };
EPlaneSide sides[ MAX_TW_VERTS ];
int counts[ 3 ] = { 0, 0, 0 };
float dists[ MAX_TW_VERTS ];
float frac;
traceVert_t *a, *b, mid;
@@ -377,26 +374,26 @@ void ClipTraceWinding( traceWinding_t *tw, vec4_t plane, traceWinding_t *front,
/* classify points */
for ( i = 0; i < tw->numVerts; i++ )
{
dists[ i ] = DotProduct( tw->v[ i ].xyz, plane ) - plane[ 3 ];
dists[ i ] = plane3_distance_to_point( plane, tw->v[ i ].xyz );
if ( dists[ i ] < -TW_ON_EPSILON ) {
sides[ i ] = SIDE_BACK;
sides[ i ] = eSideBack;
}
else if ( dists[ i ] > TW_ON_EPSILON ) {
sides[ i ] = SIDE_FRONT;
sides[ i ] = eSideFront;
}
else{
sides[ i ] = SIDE_ON;
sides[ i ] = eSideOn;
}
counts[ sides[ i ] ]++;
}
/* entirely on front? */
if ( counts[ SIDE_BACK ] == 0 ) {
if ( counts[ eSideBack ] == 0 ) {
memcpy( front, tw, sizeof( *front ) );
}
/* entirely on back? */
else if ( counts[ SIDE_FRONT ] == 0 ) {
else if ( counts[ eSideFront ] == 0 ) {
memcpy( back, tw, sizeof( *back ) );
}
@@ -422,21 +419,21 @@ void ClipTraceWinding( traceWinding_t *tw, vec4_t plane, traceWinding_t *front,
/* handle points on the splitting plane */
switch ( sides[ i ] )
{
case SIDE_FRONT:
case eSideFront:
if ( front->numVerts >= MAX_TW_VERTS ) {
Error( "MAX_TW_VERTS (%d) exceeded", MAX_TW_VERTS );
}
front->v[ front->numVerts++ ] = *a;
break;
case SIDE_BACK:
case eSideBack:
if ( back->numVerts >= MAX_TW_VERTS ) {
Error( "MAX_TW_VERTS (%d) exceeded", MAX_TW_VERTS );
}
back->v[ back->numVerts++ ] = *a;
break;
case SIDE_ON:
case eSideOn:
if ( front->numVerts >= MAX_TW_VERTS || back->numVerts >= MAX_TW_VERTS ) {
Error( "MAX_TW_VERTS (%d) exceeded", MAX_TW_VERTS );
}
@@ -446,7 +443,7 @@ void ClipTraceWinding( traceWinding_t *tw, vec4_t plane, traceWinding_t *front,
}
/* check next point to see if we need to split the edge */
if ( sides[ j ] == SIDE_ON || sides[ j ] == sides[ i ] ) {
if ( sides[ j ] == eSideOn || sides[ j ] == sides[ i ] ) {
continue;
}
@@ -460,19 +457,18 @@ void ClipTraceWinding( traceWinding_t *tw, vec4_t plane, traceWinding_t *front,
for ( k = 0; k < 3; k++ )
{
/* minimize fp precision errors */
if ( plane[ k ] == 1.0f ) {
mid.xyz[ k ] = plane[ 3 ];
if ( plane.normal()[ k ] == 1.0f ) {
mid.xyz[ k ] = plane.dist();
}
else if ( plane[ k ] == -1.0f ) {
mid.xyz[ k ] = -plane[ 3 ];
else if ( plane.normal()[ k ] == -1.0f ) {
mid.xyz[ k ] = -plane.dist();
}
else{
mid.xyz[ k ] = a->xyz[ k ] + frac * ( b->xyz[ k ] - a->xyz[ k ] );
}
}
/* set texture coordinates */
mid.st[ 0 ] = a->st[ 0 ] + frac * ( b->st[ 0 ] - a->st[ 0 ] );
mid.st[ 1 ] = a->st[ 1 ] + frac * ( b->st[ 1 ] - a->st[ 1 ] );
mid.st = a->st + ( b->st - a->st ) * frac;
/* copy midpoint to front and back polygons */
front->v[ front->numVerts++ ] = mid;
@@ -490,7 +486,7 @@ void ClipTraceWinding( traceWinding_t *tw, vec4_t plane, traceWinding_t *front,
static void FilterTraceWindingIntoNodes_r( traceWinding_t *tw, int nodeNum ){
int num;
vec4_t plane1, plane2, reverse;
Plane3f plane1, plane2, reverse;
traceNode_t *node;
traceWinding_t front, back;
@@ -518,23 +514,22 @@ static void FilterTraceWindingIntoNodes_r( traceWinding_t *tw, int nodeNum ){
}
/* get node plane */
Vector4Copy( node->plane, plane1 );
plane1 = node->plane;
/* get winding plane */
Vector4Copy( tw->plane, plane2 );
plane2 = tw->plane;
/* invert surface plane */
VectorSubtract( vec3_origin, plane2, reverse );
reverse[ 3 ] = -plane2[ 3 ];
reverse = plane3_flipped( plane2 );
/* front only */
if ( DotProduct( plane1, plane2 ) > 0.999f && fabs( plane1[ 3 ] - plane2[ 3 ] ) < 0.001f ) {
if ( vector3_dot( plane1.normal(), plane2.normal() ) > 0.999f && fabs( plane1.dist() - plane2.dist() ) < 0.001f ) {
FilterTraceWindingIntoNodes_r( tw, node->children[ 0 ] );
return;
}
/* back only */
if ( DotProduct( plane1, reverse ) > 0.999f && fabs( plane1[ 3 ] - reverse[ 3 ] ) < 0.001f ) {
if ( vector3_dot( plane1.normal(), reverse.normal() ) > 0.999f && fabs( plane1.dist() - reverse.dist() ) < 0.001f ) {
FilterTraceWindingIntoNodes_r( tw, node->children[ 1 ] );
return;
}
@@ -568,9 +563,7 @@ static void FilterTraceWindingIntoNodes_r( traceWinding_t *tw, int nodeNum ){
static void SubdivideTraceNode_r( int nodeNum, int depth ){
int i, j, count, num, frontNum, backNum, type;
vec3_t size;
float dist;
double average[ 3 ];
traceNode_t *node, *frontNode, *backNode;
traceWinding_t *tw, front, back;
@@ -602,8 +595,8 @@ static void SubdivideTraceNode_r( int nodeNum, int depth ){
}
/* bound the node */
ClearBounds( node->mins, node->maxs );
VectorClear( average );
node->minmax.clear();
DoubleVector3 average( 0, 0, 0 );
count = 0;
for ( i = 0; i < node->numItems; i++ )
{
@@ -613,10 +606,8 @@ static void SubdivideTraceNode_r( int nodeNum, int depth ){
/* walk its verts */
for ( j = 0; j < tw->numVerts; j++ )
{
AddPointToBounds( tw->v[ j ].xyz, node->mins, node->maxs );
average[ 0 ] += tw->v[ j ].xyz[ 0 ];
average[ 1 ] += tw->v[ j ].xyz[ 1 ];
average[ 2 ] += tw->v[ j ].xyz[ 2 ];
node->minmax.extend( tw->v[ j ].xyz );
average += tw->v[ j ].xyz;
count++;
}
}
@@ -630,15 +621,15 @@ static void SubdivideTraceNode_r( int nodeNum, int depth ){
}
/* the largest dimension of the bounding box will be the split axis */
VectorSubtract( node->maxs, node->mins, size );
const Vector3 size = node->minmax.maxs - node->minmax.mins;
if ( size[ 0 ] >= size[ 1 ] && size[ 0 ] >= size[ 2 ] ) {
type = PLANE_X;
type = ePlaneX;
}
else if ( size[ 1 ] >= size[ 0 ] && size[ 1 ] >= size[ 2 ] ) {
type = PLANE_Y;
type = ePlaneY;
}
else{
type = PLANE_Z;
type = ePlaneZ;
}
/* don't split small nodes */
@@ -657,8 +648,8 @@ static void SubdivideTraceNode_r( int nodeNum, int depth ){
dist = floor( average[ type ] / count );
/* dummy check it */
if ( dist <= node->mins[ type ] || dist >= node->maxs[ type ] ) {
dist = floor( 0.5f * ( node->mins[ type ] + node->maxs[ type ] ) );
if ( dist <= node->minmax.mins[ type ] || dist >= node->minmax.maxs[ type ] ) {
dist = floor( 0.5f * ( node->minmax.mins[ type ] + node->minmax.maxs[ type ] ) );
}
/* allocate child nodes */
@@ -672,8 +663,8 @@ static void SubdivideTraceNode_r( int nodeNum, int depth ){
/* attach children */
node->type = type;
node->plane[ type ] = 1.0f;
node->plane[ 3 ] = dist;
node->plane.normal()[ type ] = 1.0f;
node->plane.dist() = dist;
node->children[ 0 ] = frontNum;
node->children[ 1 ] = backNum;
@@ -802,8 +793,8 @@ static int TriangulateTraceNode_r( int nodeNum ){
tt.v[ 2 ] = tw->v[ j + 1 ];
/* find vectors for two edges sharing the first vert */
VectorSubtract( tt.v[ 1 ].xyz, tt.v[ 0 ].xyz, tt.edge1 );
VectorSubtract( tt.v[ 2 ].xyz, tt.v[ 0 ].xyz, tt.edge2 );
tt.edge1 = tt.v[ 1 ].xyz - tt.v[ 0 ].xyz;
tt.edge2 = tt.v[ 2 ].xyz - tt.v[ 0 ].xyz;
/* add it to the node */
num = AddTraceTriangle( &tt );
@@ -831,7 +822,7 @@ static int TriangulateTraceNode_r( int nodeNum ){
filters a bsp model's surfaces into the raytracing tree
*/
static void PopulateWithBSPModel( bspModel_t *model, m4x4_t transform ){
static void PopulateWithBSPModel( bspModel_t *model, const Matrix4& transform ){
int i, j, x, y, pw[ 5 ], r, nodeNum;
bspDrawSurface_t *ds;
surfaceInfo_t *info;
@@ -843,7 +834,7 @@ static void PopulateWithBSPModel( bspModel_t *model, m4x4_t transform ){
/* dummy check */
if ( model == NULL || transform == NULL ) {
if ( model == NULL ) {
return;
}
@@ -943,27 +934,27 @@ static void PopulateWithBSPModel( bspModel_t *model, m4x4_t transform ){
r = ( x + y ) & 1;
/* make first triangle */
VectorCopy( verts[ pw[ r + 0 ] ].xyz, tw.v[ 0 ].xyz );
Vector2Copy( verts[ pw[ r + 0 ] ].st, tw.v[ 0 ].st );
VectorCopy( verts[ pw[ r + 1 ] ].xyz, tw.v[ 1 ].xyz );
Vector2Copy( verts[ pw[ r + 1 ] ].st, tw.v[ 1 ].st );
VectorCopy( verts[ pw[ r + 2 ] ].xyz, tw.v[ 2 ].xyz );
Vector2Copy( verts[ pw[ r + 2 ] ].st, tw.v[ 2 ].st );
m4x4_transform_point( transform, tw.v[ 0 ].xyz );
m4x4_transform_point( transform, tw.v[ 1 ].xyz );
m4x4_transform_point( transform, tw.v[ 2 ].xyz );
tw.v[ 0 ].xyz = verts[ pw[ r + 0 ] ].xyz;
tw.v[ 0 ].st = verts[ pw[ r + 0 ] ].st;
tw.v[ 1 ].xyz = verts[ pw[ r + 1 ] ].xyz;
tw.v[ 1 ].st = verts[ pw[ r + 1 ] ].st;
tw.v[ 2 ].xyz = verts[ pw[ r + 2 ] ].xyz;
tw.v[ 2 ].st = verts[ pw[ r + 2 ] ].st;
matrix4_transform_point( transform, tw.v[ 0 ].xyz );
matrix4_transform_point( transform, tw.v[ 1 ].xyz );
matrix4_transform_point( transform, tw.v[ 2 ].xyz );
FilterTraceWindingIntoNodes_r( &tw, nodeNum );
/* make second triangle */
VectorCopy( verts[ pw[ r + 0 ] ].xyz, tw.v[ 0 ].xyz );
Vector2Copy( verts[ pw[ r + 0 ] ].st, tw.v[ 0 ].st );
VectorCopy( verts[ pw[ r + 2 ] ].xyz, tw.v[ 1 ].xyz );
Vector2Copy( verts[ pw[ r + 2 ] ].st, tw.v[ 1 ].st );
VectorCopy( verts[ pw[ r + 3 ] ].xyz, tw.v[ 2 ].xyz );
Vector2Copy( verts[ pw[ r + 3 ] ].st, tw.v[ 2 ].st );
m4x4_transform_point( transform, tw.v[ 0 ].xyz );
m4x4_transform_point( transform, tw.v[ 1 ].xyz );
m4x4_transform_point( transform, tw.v[ 2 ].xyz );
tw.v[ 0 ].xyz = verts[ pw[ r + 0 ] ].xyz;
tw.v[ 0 ].st = verts[ pw[ r + 0 ] ].st;
tw.v[ 1 ].xyz = verts[ pw[ r + 2 ] ].xyz;
tw.v[ 1 ].st = verts[ pw[ r + 2 ] ].st;
tw.v[ 2 ].xyz = verts[ pw[ r + 3 ] ].xyz;
tw.v[ 2 ].st = verts[ pw[ r + 3 ] ].st;
matrix4_transform_point( transform, tw.v[ 0 ].xyz );
matrix4_transform_point( transform, tw.v[ 1 ].xyz );
matrix4_transform_point( transform, tw.v[ 2 ].xyz );
FilterTraceWindingIntoNodes_r( &tw, nodeNum );
}
}
@@ -982,15 +973,15 @@ static void PopulateWithBSPModel( bspModel_t *model, m4x4_t transform ){
/* walk the triangle list */
for ( j = 0; j < ds->numIndexes; j += 3 )
{
VectorCopy( verts[ indexes[ j ] ].xyz, tw.v[ 0 ].xyz );
Vector2Copy( verts[ indexes[ j ] ].st, tw.v[ 0 ].st );
VectorCopy( verts[ indexes[ j + 1 ] ].xyz, tw.v[ 1 ].xyz );
Vector2Copy( verts[ indexes[ j + 1 ] ].st, tw.v[ 1 ].st );
VectorCopy( verts[ indexes[ j + 2 ] ].xyz, tw.v[ 2 ].xyz );
Vector2Copy( verts[ indexes[ j + 2 ] ].st, tw.v[ 2 ].st );
m4x4_transform_point( transform, tw.v[ 0 ].xyz );
m4x4_transform_point( transform, tw.v[ 1 ].xyz );
m4x4_transform_point( transform, tw.v[ 2 ].xyz );
tw.v[ 0 ].xyz = verts[ indexes[ j ] ].xyz;
tw.v[ 0 ].st = verts[ indexes[ j ] ].st;
tw.v[ 1 ].xyz = verts[ indexes[ j + 1 ] ].xyz;
tw.v[ 1 ].st = verts[ indexes[ j + 1 ] ].st;
tw.v[ 2 ].xyz = verts[ indexes[ j + 2 ] ].xyz;
tw.v[ 2 ].st = verts[ indexes[ j + 2 ] ].st;
matrix4_transform_point( transform, tw.v[ 0 ].xyz );
matrix4_transform_point( transform, tw.v[ 1 ].xyz );
matrix4_transform_point( transform, tw.v[ 2 ].xyz );
FilterTraceWindingIntoNodes_r( &tw, nodeNum );
}
break;
@@ -1009,18 +1000,17 @@ static void PopulateWithBSPModel( bspModel_t *model, m4x4_t transform ){
filters a picomodel's surfaces into the raytracing tree
*/
static void PopulateWithPicoModel( int castShadows, picoModel_t *model, m4x4_t transform ){
static void PopulateWithPicoModel( int castShadows, picoModel_t *model, const Matrix4& transform ){
int i, j, k, numSurfaces, numIndexes;
picoSurface_t *surface;
picoShader_t *shader;
picoVec_t *xyz, *st;
picoIndex_t *indexes;
traceInfo_t ti;
traceWinding_t tw;
/* dummy check */
if ( model == NULL || transform == NULL ) {
if ( model == NULL ) {
return;
}
@@ -1080,11 +1070,9 @@ static void PopulateWithPicoModel( int castShadows, picoModel_t *model, m4x4_t t
{
for ( k = 0; k < 3; k++ )
{
xyz = PicoGetSurfaceXYZ( surface, indexes[ k ] );
st = PicoGetSurfaceST( surface, 0, indexes[ k ] );
VectorCopy( xyz, tw.v[ k ].xyz );
Vector2Copy( st, tw.v[ k ].st );
m4x4_transform_point( transform, tw.v[ k ].xyz );
tw.v[ k ].xyz = vector3_from_array( PicoGetSurfaceXYZ( surface, indexes[ k ] ) );
tw.v[ k ].st = vector2_from_array( PicoGetSurfaceST( surface, 0, indexes[ k ] ) );
matrix4_transform_point( transform, tw.v[ k ].xyz );
}
FilterTraceWindingIntoNodes_r( &tw, headNodeNum );
}
@@ -1105,8 +1093,7 @@ static void PopulateTraceNodes( void ){
/* add worldspawn triangles */
m4x4_t transform;
m4x4_identity( transform );
Matrix4 transform( g_matrix4_identity );
PopulateWithBSPModel( &bspModels[ 0 ], transform );
/* walk each entity list */
@@ -1125,24 +1112,24 @@ static void PopulateTraceNodes( void ){
}
/* get entity origin */
vec3_t origin;
Vector3 origin;
e->vectorForKey( "origin", origin );
/* get scale */
vec3_t scale = { 1.f, 1.f, 1.f };
Vector3 scale = { 1.f, 1.f, 1.f };
if( !e->read_keyvalue( scale, "modelscale_vec" ) )
if( e->read_keyvalue( scale[0], "modelscale" ) )
scale[1] = scale[2] = scale[0];
/* get "angle" (yaw) or "angles" (pitch yaw roll), store as (roll pitch yaw) */
vec3_t angles = { 0.f, 0.f, 0.f };
Vector3 angles = { 0.f, 0.f, 0.f };
if ( !e->read_keyvalue( value, "angles" ) ||
3 != sscanf( value, "%f %f %f", &angles[ 1 ], &angles[ 2 ], &angles[ 0 ] ) )
e->read_keyvalue( angles[ 2 ], "angle" );
/* set transform matrix (thanks spog) */
m4x4_identity( transform );
m4x4_pivoted_transform_by_vec3( transform, origin, angles, eXYZ, scale, vec3_origin );
transform = g_matrix4_identity;
matrix4_transform_by_euler_xyz_degrees( transform, origin, angles, scale );
/* hack: Stable-1_2 and trunk have differing row/column major matrix order
this transpose is necessary with Stable-1_2
@@ -1320,7 +1307,7 @@ void SetupTraceNodes( void ){
bool TraceTriangle( traceInfo_t *ti, traceTriangle_t *tt, trace_t *trace ){
int i;
float tvec[ 3 ], pvec[ 3 ], qvec[ 3 ];
Vector3 tvec, pvec, qvec;
float det, invDet, depth;
float u, v, w, s, t;
int is, it;
@@ -1366,10 +1353,10 @@ bool TraceTriangle( traceInfo_t *ti, traceTriangle_t *tt, trace_t *trace ){
}
/* begin calculating determinant - also used to calculate u parameter */
CrossProduct( trace->direction, tt->edge2, pvec );
pvec = vector3_cross( trace->direction, tt->edge2 );
/* if determinant is near zero, trace lies in plane of triangle */
det = DotProduct( tt->edge1, pvec );
det = vector3_dot( tt->edge1, pvec );
/* the non-culling branch */
if ( fabs( det ) < COPLANAR_EPSILON ) {
@@ -1378,25 +1365,25 @@ bool TraceTriangle( traceInfo_t *ti, traceTriangle_t *tt, trace_t *trace ){
invDet = 1.0f / det;
/* calculate distance from first vertex to ray origin */
VectorSubtract( trace->origin, tt->v[ 0 ].xyz, tvec );
tvec = trace->origin - tt->v[ 0 ].xyz;
/* calculate u parameter and test bounds */
u = DotProduct( tvec, pvec ) * invDet;
u = vector3_dot( tvec, pvec ) * invDet;
if ( u < -BARY_EPSILON || u > ( 1.0f + BARY_EPSILON ) ) {
return false;
}
/* prepare to test v parameter */
CrossProduct( tvec, tt->edge1, qvec );
qvec = vector3_cross( tvec, tt->edge1 );
/* calculate v parameter and test bounds */
v = DotProduct( trace->direction, qvec ) * invDet;
v = vector3_dot( trace->direction, qvec ) * invDet;
if ( v < -BARY_EPSILON || ( u + v ) > ( 1.0f + BARY_EPSILON ) ) {
return false;
}
/* calculate t (depth) */
depth = DotProduct( tt->edge2, qvec ) * invDet;
depth = vector3_dot( tt->edge2, qvec ) * invDet;
if ( depth <= trace->inhibitRadius || depth >= trace->distance ) {
return false;
}
@@ -1423,8 +1410,8 @@ bool TraceTriangle( traceInfo_t *ti, traceTriangle_t *tt, trace_t *trace ){
/* most surfaces are completely opaque */
if ( !( si->compileFlags & ( C_ALPHASHADOW | C_LIGHTFILTER ) ) ||
si->lightImage == NULL || si->lightImage->pixels == NULL ) {
VectorMA( trace->origin, depth, trace->direction, trace->hit );
VectorClear( trace->color );
trace->hit = trace->origin + trace->direction * depth;
trace->color.set( 0 );
trace->opaque = true;
return true;
}
@@ -1483,8 +1470,8 @@ bool TraceTriangle( traceInfo_t *ti, traceTriangle_t *tt, trace_t *trace ){
/* check filter for opaque */
if ( trace->color[ 0 ] <= 0.001f && trace->color[ 1 ] <= 0.001f && trace->color[ 2 ] <= 0.001f ) {
VectorClear( trace->color );
VectorMA( trace->origin, depth, trace->direction, trace->hit );
trace->color.set( 0 );
trace->hit = trace->origin + trace->direction * depth;
trace->opaque = true;
return true;
}
@@ -1517,8 +1504,8 @@ bool TraceWinding( traceWinding_t *tw, trace_t *trace ){
tt.v[ 2 ] = tw->v[ i + 1 ];
/* find vectors for two edges sharing the first vert */
VectorSubtract( tt.v[ 1 ].xyz, tt.v[ 0 ].xyz, tt.edge1 );
VectorSubtract( tt.v[ 2 ].xyz, tt.v[ 0 ].xyz, tt.edge2 );
tt.edge1 = tt.v[ 1 ].xyz - tt.v[ 0 ].xyz;
tt.edge2 = tt.v[ 2 ].xyz - tt.v[ 0 ].xyz;
/* trace it */
if ( TraceTriangle( &traceInfos[ tt.infoNum ], &tt, trace ) ) {
@@ -1543,26 +1530,25 @@ bool TraceWinding( traceWinding_t *tw, trace_t *trace ){
#define TRACELINE_R_HALF_ITERATIVE 1
#if TRACELINE_R_HALF_ITERATIVE
static bool TraceLine_r( int nodeNum, const vec3_t start, const vec3_t end, trace_t *trace )
static bool TraceLine_r( int nodeNum, const Vector3& start, const Vector3& end, trace_t *trace )
#else
static bool TraceLine_r( int nodeNum, const vec3_t origin, const vec3_t end, trace_t *trace )
static bool TraceLine_r( int nodeNum, const Vector3& origin, const Vector3& end, trace_t *trace )
#endif
{
traceNode_t *node;
int side;
float front, back, frac;
vec3_t mid;
Vector3 mid;
#if TRACELINE_R_HALF_ITERATIVE
vec3_t origin;
VectorCopy( start, origin );
Vector3 origin( start );
while ( 1 )
#endif
{
/* bogus node number means solid, end tracing unless testing all */
if ( nodeNum < 0 ) {
VectorCopy( origin, trace->hit );
trace->hit = origin;
trace->passSolid = true;
return true;
}
@@ -1572,7 +1558,7 @@ static bool TraceLine_r( int nodeNum, const vec3_t origin, const vec3_t end, tra
/* solid? */
if ( node->type == TRACE_LEAF_SOLID ) {
VectorCopy( origin, trace->hit );
trace->hit = origin;
trace->passSolid = true;
return true;
}
@@ -1594,24 +1580,24 @@ static bool TraceLine_r( int nodeNum, const vec3_t origin, const vec3_t end, tra
/* classify beginning and end points */
switch ( node->type )
{
case PLANE_X:
front = origin[ 0 ] - node->plane[ 3 ];
back = end[ 0 ] - node->plane[ 3 ];
case ePlaneX:
front = origin[ 0 ] - node->plane.dist();
back = end[ 0 ] - node->plane.dist();
break;
case PLANE_Y:
front = origin[ 1 ] - node->plane[ 3 ];
back = end[ 1 ] - node->plane[ 3 ];
case ePlaneY:
front = origin[ 1 ] - node->plane.dist();
back = end[ 1 ] - node->plane.dist();
break;
case PLANE_Z:
front = origin[ 2 ] - node->plane[ 3 ];
back = end[ 2 ] - node->plane[ 3 ];
case ePlaneZ:
front = origin[ 2 ] - node->plane.dist();
back = end[ 2 ] - node->plane.dist();
break;
default:
front = DotProduct( origin, node->plane ) - node->plane[ 3 ];
back = DotProduct( end, node->plane ) - node->plane[ 3 ];
front = plane3_distance_to_point( node->plane, origin );
back = plane3_distance_to_point( node->plane, end );
break;
}
@@ -1640,14 +1626,12 @@ static bool TraceLine_r( int nodeNum, const vec3_t origin, const vec3_t end, tra
/* calculate intercept point */
frac = front / ( front - back );
mid[ 0 ] = origin[ 0 ] + ( end[ 0 ] - origin[ 0 ] ) * frac;
mid[ 1 ] = origin[ 1 ] + ( end[ 1 ] - origin[ 1 ] ) * frac;
mid[ 2 ] = origin[ 2 ] + ( end[ 2 ] - origin[ 2 ] ) * frac;
mid = origin + ( end - origin ) * frac;
/* fixme: check inhibit radius, then solid nodes and ignore */
/* set trace hit here */
//% VectorCopy( mid, trace->hit );
//% trace->hit = mid;
/* trace first side */
if ( TraceLine_r( node->children[ side ], origin, mid, trace ) ) {
@@ -1657,7 +1641,7 @@ static bool TraceLine_r( int nodeNum, const vec3_t origin, const vec3_t end, tra
/* trace other side */
#if TRACELINE_R_HALF_ITERATIVE
nodeNum = node->children[ !side ];
VectorCopy( mid, origin );
origin = mid;
#else
return TraceLine_r( node->children[ !side ], mid, end, trace );
#endif
@@ -1737,8 +1721,9 @@ void TraceLine( trace_t *trace ){
*/
float SetupTrace( trace_t *trace ){
VectorSubtract( trace->end, trace->origin, trace->displacement );
trace->distance = VectorFastNormalize( trace->displacement, trace->direction );
VectorCopy( trace->origin, trace->hit );
trace->displacement = trace->end - trace->origin;
trace->direction = trace->displacement;
trace->distance = VectorFastNormalize( trace->direction );
trace->hit = trace->origin;
return trace->distance;
}
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+130 -194
View File
@@ -54,23 +54,20 @@ int c_structural;
ydnar: replaced with variable epsilon for djbob
*/
bool PlaneEqual( plane_t *p, vec3_t normal, vec_t dist ){
float ne, de;
bool PlaneEqual( const plane_t *p, const Plane3f& plane ){
/* get local copies */
ne = normalEpsilon;
de = distanceEpsilon;
const float ne = normalEpsilon;
const float de = distanceEpsilon;
/* compare */
// We check equality of each component since we're using '<', not '<='
// (the epsilons may be zero). We want to use '<' instead of '<=' to be
// consistent with the true meaning of "epsilon", and also because other
// parts of the code uses this inequality.
if ( ( p->dist == dist || fabs( p->dist - dist ) < de ) &&
( p->normal[0] == normal[0] || fabs( p->normal[0] - normal[0] ) < ne ) &&
( p->normal[1] == normal[1] || fabs( p->normal[1] - normal[1] ) < ne ) &&
( p->normal[2] == normal[2] || fabs( p->normal[2] - normal[2] ) < ne ) ) {
if ( ( p->dist() == plane.dist() || fabs( p->dist() - plane.dist() ) < de ) &&
( p->normal()[0] == plane.normal()[0] || fabs( p->normal()[0] - plane.normal()[0] ) < ne ) &&
( p->normal()[1] == plane.normal()[1] || fabs( p->normal()[1] - plane.normal()[1] ) < ne ) &&
( p->normal()[2] == plane.normal()[2] || fabs( p->normal()[2] - plane.normal()[2] ) < ne ) ) {
return true;
}
@@ -88,7 +85,7 @@ void AddPlaneToHash( plane_t *p ){
int hash;
hash = ( PLANE_HASHES - 1 ) & (int) fabs( p->dist );
hash = ( PLANE_HASHES - 1 ) & (int) fabs( p->dist() );
p->hash_chain = planehash[hash];
planehash[hash] = p - mapplanes + 1;
@@ -99,10 +96,9 @@ void AddPlaneToHash( plane_t *p ){
CreateNewFloatPlane
================
*/
int CreateNewFloatPlane( vec3_t normal, vec_t dist ){
plane_t *p, temp;
int CreateNewFloatPlane( const Plane3f& plane ){
if ( VectorLength( normal ) < 0.5 ) {
if ( vector3_length( plane.normal() ) < 0.5 ) {
Sys_Printf( "FloatPlane: bad normal\n" );
return -1;
}
@@ -110,23 +106,18 @@ int CreateNewFloatPlane( vec3_t normal, vec_t dist ){
// create a new plane
AUTOEXPAND_BY_REALLOC( mapplanes, nummapplanes + 1, allocatedmapplanes, 1024 );
p = &mapplanes[nummapplanes];
VectorCopy( normal, p->normal );
p->dist = dist;
p->type = ( p + 1 )->type = PlaneTypeForNormal( p->normal );
VectorSubtract( vec3_origin, normal, ( p + 1 )->normal );
( p + 1 )->dist = -dist;
plane_t *p = &mapplanes[nummapplanes];
p->plane = plane;
( p + 1 )->plane = plane3_flipped( plane );
p->type = ( p + 1 )->type = PlaneTypeForNormal( p->normal() );
nummapplanes += 2;
// always put axial planes facing positive first
if ( p->type < 3 ) {
if ( p->normal[0] < 0 || p->normal[1] < 0 || p->normal[2] < 0 ) {
if ( p->type < ePlaneNonAxial ) {
if ( p->normal()[0] < 0 || p->normal()[1] < 0 || p->normal()[2] < 0 ) {
// flip order
temp = *p;
*p = *( p + 1 );
*( p + 1 ) = temp;
std::swap( *p, *( p + 1 ) );
AddPlaneToHash( p );
AddPlaneToHash( p + 1 );
@@ -147,7 +138,7 @@ int CreateNewFloatPlane( vec3_t normal, vec_t dist ){
Returns true if and only if the normal was adjusted.
*/
bool SnapNormal( vec3_t normal ){
bool SnapNormal( Vector3& normal ){
#if Q3MAP2_EXPERIMENTAL_SNAP_NORMAL_FIX
int i;
bool adjusted = false;
@@ -163,15 +154,15 @@ bool SnapNormal( vec3_t normal ){
//they cause precision errors
if ( ( normal[0] != 0.0 || normal[1] != 0.0 ) && fabs(normal[0]) < 0.00025 && fabs(normal[1]) < 0.00025){
if ( ( normal[0] != 0.0 || normal[1] != 0.0 ) && fabs( normal[0] ) < 0.00025 && fabs( normal[1] ) < 0.00025){
normal[0] = normal[1] = 0.0;
adjusted = true;
}
else if ( ( normal[0] != 0.0 || normal[2] != 0.0 ) && fabs(normal[0]) < 0.00025 && fabs(normal[2]) < 0.00025){
else if ( ( normal[0] != 0.0 || normal[2] != 0.0 ) && fabs( normal[0] ) < 0.00025 && fabs( normal[2] ) < 0.00025){
normal[0] = normal[2] = 0.0;
adjusted = true;
}
else if ( ( normal[2] != 0.0 || normal[1] != 0.0 ) && fabs(normal[2]) < 0.00025 && fabs(normal[1]) < 0.00025){
else if ( ( normal[2] != 0.0 || normal[1] != 0.0 ) && fabs( normal[2] ) < 0.00025 && fabs( normal[1] ) < 0.00025){
normal[2] = normal[1] = 0.0;
adjusted = true;
}
@@ -206,7 +197,7 @@ bool SnapNormal( vec3_t normal ){
}
if ( adjusted ) {
VectorNormalize( normal, normal );
VectorNormalize( normal );
return true;
}
return false;
@@ -249,12 +240,12 @@ bool SnapNormal( vec3_t normal ){
for ( i = 0; i < 3; i++ )
{
if ( fabs( normal[ i ] - 1 ) < normalEpsilon ) {
VectorClear( normal );
normal.set( 0 );
normal[ i ] = 1;
return true;
}
if ( fabs( normal[ i ] - -1 ) < normalEpsilon ) {
VectorClear( normal );
normal.set( 0 );
normal[ i ] = -1;
return true;
}
@@ -270,7 +261,7 @@ bool SnapNormal( vec3_t normal ){
snaps a plane to normal/distance epsilons
*/
void SnapPlane( vec3_t normal, vec_t *dist ){
void SnapPlane( Plane3f& plane ){
// SnapPlane disabled by LordHavoc because it often messes up collision
// brushes made from triangles of embedded models, and it has little effect
// on anything else (axial planes are usually derived from snapped points)
@@ -278,7 +269,7 @@ void SnapPlane( vec3_t normal, vec_t *dist ){
SnapPlane reenabled by namespace because of multiple reports of
q3map2-crashes which were triggered by this patch.
*/
SnapNormal( normal );
SnapNormal( plane.normal() );
// TODO: Rambetter has some serious comments here as well. First off,
// in the case where a normal is non-axial, there is nothing special
@@ -301,8 +292,8 @@ void SnapPlane( vec3_t normal, vec_t *dist ){
// solve so that we can better engineer it (I'm not saying that SnapPlane()
// should be removed altogether). Fix all this snapping code at some point!
if ( fabs( *dist - Q_rint( *dist ) ) < distanceEpsilon ) {
*dist = Q_rint( *dist );
if ( fabs( plane.dist() - std::rint( plane.dist() ) ) < distanceEpsilon ) {
plane.dist() = std::rint( plane.dist() );
}
}
@@ -310,30 +301,26 @@ void SnapPlane( vec3_t normal, vec_t *dist ){
SnapPlaneImproved()
snaps a plane to normal/distance epsilons, improved code
*/
void SnapPlaneImproved( vec3_t normal, vec_t *dist, int numPoints, const vec3_t *points ){
int i;
vec3_t center;
vec_t distNearestInt;
if ( SnapNormal( normal ) ) {
void SnapPlaneImproved( Plane3f& plane, int numPoints, const Vector3 *points ){
if ( SnapNormal( plane.normal() ) ) {
if ( numPoints > 0 ) {
// Adjust the dist so that the provided points don't drift away.
VectorClear( center );
for ( i = 0; i < numPoints; i++ )
Vector3 center( 0, 0, 0 );
for ( int i = 0; i < numPoints; i++ )
{
VectorAdd( center, points[i], center );
center += points[i];
}
for ( i = 0; i < 3; i++ ) { center[i] = center[i] / numPoints; }
*dist = DotProduct( normal, center );
center /= numPoints;
plane.dist() = vector3_dot( plane.normal(), center );
}
}
if ( VectorIsOnAxis( normal ) ) {
if ( VectorIsOnAxis( plane.normal() ) ) {
// Only snap distance if the normal is an axis. Otherwise there
// is nothing "natural" about snapping the distance to an integer.
distNearestInt = Q_rint( *dist );
if ( -distanceEpsilon < *dist - distNearestInt && *dist - distNearestInt < distanceEpsilon ) {
*dist = distNearestInt;
const float distNearestInt = std::rint( plane.dist() );
if ( -distanceEpsilon < plane.dist() - distNearestInt && plane.dist() - distNearestInt < distanceEpsilon ) {
plane.dist() = distNearestInt;
}
}
}
@@ -346,25 +333,22 @@ void SnapPlaneImproved( vec3_t normal, vec_t *dist, int numPoints, const vec3_t
must be within an epsilon distance of the plane
*/
int FindFloatPlane( vec3_t innormal, vec_t dist, int numPoints, vec3_t *points ) // NOTE: this has a side effect on the normal. Good or bad?
int FindFloatPlane( const Plane3f& inplane, int numPoints, const Vector3 *points ) // NOTE: this has a side effect on the normal. Good or bad?
#ifdef USE_HASHING
{
int i, j, hash, h;
int pidx;
plane_t *p;
vec_t d;
vec3_t normal;
Plane3f plane( inplane );
VectorCopy( innormal, normal );
#if Q3MAP2_EXPERIMENTAL_SNAP_PLANE_FIX
SnapPlaneImproved( normal, &dist, numPoints, (const vec3_t *) points );
SnapPlaneImproved( plane, numPoints, points );
#else
SnapPlane( normal, &dist );
SnapPlane( plane );
#endif
/* hash the plane */
hash = ( PLANE_HASHES - 1 ) & (int) fabs( dist );
hash = ( PLANE_HASHES - 1 ) & (int) fabs( plane.dist() );
/* search the border bins as well */
for ( i = -1; i <= 1; i++ )
@@ -372,10 +356,10 @@ int FindFloatPlane( vec3_t innormal, vec_t dist, int numPoints, vec3_t *points )
h = ( hash + i ) & ( PLANE_HASHES - 1 );
for ( pidx = planehash[ h ] - 1; pidx != -1; pidx = mapplanes[pidx].hash_chain - 1 )
{
p = &mapplanes[pidx];
plane_t *p = &mapplanes[pidx];
/* do standard plane compare */
if ( !PlaneEqual( p, normal, dist ) ) {
if ( !PlaneEqual( p, plane ) ) {
continue;
}
@@ -390,8 +374,7 @@ int FindFloatPlane( vec3_t innormal, vec_t dist, int numPoints, vec3_t *points )
// very small when world coordinates extend to 2^16. Making the
// dot product here in 64 bit land will not really help the situation
// because the error will already be carried in dist.
d = DotProduct( points[ j ], p->normal ) - p->dist;
d = fabs( d );
const double d = fabs( plane3_distance_to_point( p->plane, points[ j ] ) );
if ( d != 0.0 && d >= distanceEpsilon ) {
break; // Point is too far from plane.
}
@@ -405,25 +388,24 @@ int FindFloatPlane( vec3_t innormal, vec_t dist, int numPoints, vec3_t *points )
}
/* none found, so create a new one */
return CreateNewFloatPlane( normal, dist );
return CreateNewFloatPlane( plane );
}
#else
{
int i;
int i, j;
plane_t *p;
vec3_t normal;
Plane3f plane( innormal, dist );
VectorCopy( innormal, normal );
#if Q3MAP2_EXPERIMENTAL_SNAP_PLANE_FIX
SnapPlaneImproved( normal, &dist, numPoints, (const vec3_t *) points );
SnapPlaneImproved( plane, numPoints, points );
#else
SnapPlane( normal, &dist );
SnapPlane( plane );
#endif
for ( i = 0, p = mapplanes; i < nummapplanes; i++, p++ )
{
if ( !PlaneEqual( p, normal, dist ) ) {
if ( !PlaneEqual( p, plane ) ) {
continue;
}
@@ -433,8 +415,7 @@ int FindFloatPlane( vec3_t innormal, vec_t dist, int numPoints, vec3_t *points )
/* ydnar: test supplied points against this plane */
for ( j = 0; j < numPoints; j++ )
{
d = DotProduct( points[ j ], p->normal ) - p->dist;
if ( fabs( d ) > distanceEpsilon ) {
if ( fabs( plane3_distance_to_point( p->plane, points[ j ] ) ) > distanceEpsilon ) {
break;
}
}
@@ -448,7 +429,7 @@ int FindFloatPlane( vec3_t innormal, vec_t dist, int numPoints, vec3_t *points )
// is unmaintained because nobody sets USE_HASHING to off.
}
return CreateNewFloatPlane( normal, dist );
return CreateNewFloatPlane( plane );
}
#endif
@@ -460,44 +441,18 @@ int FindFloatPlane( vec3_t innormal, vec_t dist, int numPoints, vec3_t *points )
takes 3 points and finds the plane they lie in
*/
int MapPlaneFromPoints( vec3_t *p ){
int MapPlaneFromPoints( Vector3 p[3] ){
#if Q3MAP2_EXPERIMENTAL_HIGH_PRECISION_MATH_FIXES
vec3_accu_t paccu[3];
vec3_accu_t t1, t2, normalAccu;
vec3_t normal;
vec_t dist;
VectorCopyRegularToAccu( p[0], paccu[0] );
VectorCopyRegularToAccu( p[1], paccu[1] );
VectorCopyRegularToAccu( p[2], paccu[2] );
VectorSubtractAccu( paccu[0], paccu[1], t1 );
VectorSubtractAccu( paccu[2], paccu[1], t2 );
CrossProductAccu( t1, t2, normalAccu );
VectorNormalizeAccu( normalAccu, normalAccu );
Plane3 plane;
PlaneFromPoints( plane, DoubleVector3( p[0] ), DoubleVector3( p[1] ), DoubleVector3( p[2] ) );
// TODO: A 32 bit float for the plane distance isn't enough resolution
// if the plane is 2^16 units away from the origin (the "epsilon" approaches
// 0.01 in that case).
dist = (vec_t) DotProductAccu( paccu[0], normalAccu );
VectorCopyAccuToRegular( normalAccu, normal );
return FindFloatPlane( normal, dist, 3, p );
return FindFloatPlane( Plane3f( plane.normal(), plane.dist() ), 3, p );
#else
vec3_t t1, t2, normal;
vec_t dist;
/* calc plane normal */
VectorSubtract( p[ 0 ], p[ 1 ], t1 );
VectorSubtract( p[ 2 ], p[ 1 ], t2 );
CrossProduct( t1, t2, normal );
VectorNormalize( normal, normal );
/* calc plane distance */
dist = DotProduct( p[ 0 ], normal );
/* store the plane */
return FindFloatPlane( normal, dist, 3, p );
Plane3f plane;
PlaneFromPoints( plane, p );
return FindFloatPlane( plane, 3, p );
#endif
}
@@ -628,9 +583,8 @@ void AddBrushBevels( void ){
side_t sidetemp;
side_t *s, *s2;
winding_t *w, *w2;
vec3_t normal;
float dist;
vec3_t vec, vec2;
Plane3f plane;
Vector3 vec, vec2;
float d, minBack;
int surfaceFlagsMask = game->brushBevelsSurfaceFlagsMask;
@@ -646,18 +600,18 @@ void AddBrushBevels( void ){
/* ydnar: testing disabling of mre code */
#if 0
if ( dir > 0 ) {
if ( mapplanes[s->planenum].normal[axis] >= 0.9999f ) {
if ( mapplanes[s->planenum].normal()[axis] >= 0.9999f ) {
break;
}
}
else {
if ( mapplanes[s->planenum].normal[axis] <= -0.9999f ) {
if ( mapplanes[s->planenum].normal()[axis] <= -0.9999f ) {
break;
}
}
#else
if ( ( dir > 0 && mapplanes[ s->planenum ].normal[ axis ] == 1.0f ) ||
( dir < 0 && mapplanes[ s->planenum ].normal[ axis ] == -1.0f ) ) {
if ( ( dir > 0 && mapplanes[ s->planenum ].normal()[ axis ] == 1.0f ) ||
( dir < 0 && mapplanes[ s->planenum ].normal()[ axis ] == -1.0f ) ) {
break;
}
#endif
@@ -670,30 +624,30 @@ void AddBrushBevels( void ){
}
memset( s, 0, sizeof( *s ) );
buildBrush->numsides++;
VectorClear( normal );
normal[axis] = dir;
plane.normal().set( 0 );
plane.normal()[axis] = dir;
if ( dir == 1 ) {
/* ydnar: adding bevel plane snapping for fewer bsp planes */
if ( bevelSnap > 0 ) {
dist = floor( buildBrush->maxs[ axis ] / bevelSnap ) * bevelSnap;
plane.dist() = floor( buildBrush->minmax.maxs[ axis ] / bevelSnap ) * bevelSnap;
}
else{
dist = buildBrush->maxs[ axis ];
plane.dist() = buildBrush->minmax.maxs[ axis ];
}
}
else
{
/* ydnar: adding bevel plane snapping for fewer bsp planes */
if ( bevelSnap > 0 ) {
dist = -ceil( buildBrush->mins[ axis ] / bevelSnap ) * bevelSnap;
plane.dist() = -ceil( buildBrush->minmax.mins[ axis ] / bevelSnap ) * bevelSnap;
}
else{
dist = -buildBrush->mins[ axis ];
plane.dist() = -buildBrush->minmax.mins[ axis ];
}
}
s->planenum = FindFloatPlane( normal, dist, 0, NULL );
s->planenum = FindFloatPlane( plane, 0, NULL );
s->contentFlags = buildBrush->sides[ 0 ].contentFlags;
/* handle bevel surfaceflags for topmost one only: assuming that only walkable ones are meaningful */
if( axis == 2 && dir == 1 ){
@@ -704,7 +658,7 @@ void AddBrushBevels( void ){
continue;
}
for ( k = 0; k < w->numpoints; k++ ) {
if ( fabs( dist - w->p[k][axis] ) < .1f ) {
if ( fabs( plane.dist() - w->p[k][axis] ) < .1f ) {
s->surfaceFlags |= ( s2->surfaceFlags & surfaceFlagsMask );
break;
}
@@ -740,8 +694,8 @@ void AddBrushBevels( void ){
}
for ( j = 0; j < w->numpoints; j++ ) {
k = ( j + 1 ) % w->numpoints;
VectorSubtract( w->p[j], w->p[k], vec );
if ( VectorNormalize( vec, vec ) < 0.5f ) {
vec = w->p[j] - w->p[k];
if ( VectorNormalize( vec ) < 0.5f ) {
continue;
}
SnapNormal( vec );
@@ -761,20 +715,20 @@ void AddBrushBevels( void ){
for ( axis = 0; axis < 3; axis++ ) {
for ( dir = -1; dir <= 1; dir += 2 ) {
// construct a plane
VectorClear( vec2 );
vec2.set( 0 );
vec2[axis] = dir;
CrossProduct( vec, vec2, normal );
if ( VectorNormalize( normal, normal ) < 0.5f ) {
plane.normal() = vector3_cross( vec, vec2 );
if ( VectorNormalize( plane.normal() ) < 0.5f ) {
continue;
}
dist = DotProduct( w->p[j], normal );
plane.dist() = vector3_dot( w->p[j], plane.normal() );
// if all the points on all the sides are
// behind this plane, it is a proper edge bevel
for ( k = 0; k < buildBrush->numsides; k++ ) {
// if this plane has allready been used, skip it
if ( PlaneEqual( &mapplanes[buildBrush->sides[k].planenum], normal, dist ) ) {
if ( PlaneEqual( &mapplanes[buildBrush->sides[k].planenum], plane ) ) {
if( buildBrush->sides[k].bevel ){ /* handle bevel surfaceflags */
buildBrush->sides[k].surfaceFlags |= ( s->surfaceFlags & surfaceFlagsMask );
}
@@ -787,7 +741,7 @@ void AddBrushBevels( void ){
}
minBack = 0.0f;
for ( l = 0; l < w2->numpoints; l++ ) {
d = DotProduct( w2->p[l], normal ) - dist;
d = plane3_distance_to_point( plane, w2->p[l] );
if ( d > 0.1f ) {
break; // point in front
}
@@ -822,7 +776,7 @@ void AddBrushBevels( void ){
buildBrush->numsides++;
memset( s2, 0, sizeof( *s2 ) );
s2->planenum = FindFloatPlane( normal, dist, 1, &w->p[ j ] );
s2->planenum = FindFloatPlane( plane, 1, &w->p[ j ] );
s2->contentFlags = buildBrush->sides[0].contentFlags;
s2->surfaceFlags = ( s->surfaceFlags & surfaceFlagsMask ); /* handle bevel surfaceflags */
s2->bevel = true;
@@ -841,16 +795,14 @@ void AddBrushBevels( void ){
and links it to the current entity
*/
static void MergeOrigin( entity_t *ent, vec3_t origin ){
vec3_t adjustment;
static void MergeOrigin( entity_t *ent, const Vector3& origin ){
char string[128];
/* we have not parsed the brush completely yet... */
ent->vectorForKey( "origin", ent->origin );
VectorMA( origin, -1, ent->originbrush_origin, adjustment );
VectorAdd( adjustment, ent->origin, ent->origin );
VectorCopy( origin, ent->originbrush_origin );
ent->origin += origin - ent->originbrush_origin;
ent->originbrush_origin = origin;
sprintf( string, "%f %f %f", ent->origin[0], ent->origin[1], ent->origin[2] );
ent->setKeyValue( "origin", string );
@@ -868,8 +820,6 @@ brush_t *FinishBrush( bool noCollapseGroups ){
/* origin brushes are removed, but they set the rotation origin for the rest of the brushes in the entity.
after the entire entity is parsed, the planenums and texinfos will be adjusted for the origin brush */
if ( buildBrush->compileFlags & C_ORIGIN ) {
vec3_t origin;
Sys_Printf( "Entity %i (%s), Brush %i: origin brush detected\n",
mapEnt->mapEntityNum, mapEnt->classname(), entitySourceBrushes );
@@ -879,10 +829,7 @@ brush_t *FinishBrush( bool noCollapseGroups ){
return NULL;
}
VectorAdd( buildBrush->mins, buildBrush->maxs, origin );
VectorScale( origin, 0.5, origin );
MergeOrigin( &entities.back(), origin );
MergeOrigin( &entities.back(), buildBrush->minmax.origin() );
/* don't keep this brush */
return NULL;
@@ -946,7 +893,7 @@ brush_t *FinishBrush( bool noCollapseGroups ){
(must be identical in radiant!)
*/
vec3_t baseaxis[18] =
Vector3 baseaxis[18] =
{
{0,0,1}, {1,0,0}, {0,-1,0}, // floor
{0,0,-1}, {1,0,0}, {0,-1,0}, // ceiling
@@ -956,25 +903,21 @@ vec3_t baseaxis[18] =
{0,-1,0}, {1,0,0}, {0,0,-1} // north wall
};
void TextureAxisFromPlane( plane_t *pln, vec3_t xv, vec3_t yv ){
int bestaxis;
vec_t dot,best;
int i;
void TextureAxisFromPlane( const plane_t *pln, Vector3& xv, Vector3& yv ){
float best = 0;
int bestaxis = 0;
best = 0;
bestaxis = 0;
for ( i = 0 ; i < 6 ; i++ )
for ( int i = 0 ; i < 6 ; i++ )
{
dot = DotProduct( pln->normal, baseaxis[i * 3] );
const float dot = vector3_dot( pln->normal(), baseaxis[i * 3] );
if ( dot > best + 0.0001f ) { /* ydnar: bug 637 fix, suggested by jmonroe */
best = dot;
bestaxis = i;
}
}
VectorCopy( baseaxis[bestaxis * 3 + 1], xv );
VectorCopy( baseaxis[bestaxis * 3 + 2], yv );
xv = baseaxis[bestaxis * 3 + 1];
yv = baseaxis[bestaxis * 3 + 2];
}
@@ -984,12 +927,12 @@ void TextureAxisFromPlane( plane_t *pln, vec3_t xv, vec3_t yv ){
creates world-to-texture mapping vecs for crappy quake plane arrangements
*/
void QuakeTextureVecs( plane_t *plane, vec_t shift[ 2 ], vec_t rotate, vec_t scale[ 2 ], vec_t mappingVecs[ 2 ][ 4 ] ){
vec3_t vecs[2];
void QuakeTextureVecs( const plane_t *plane, float shift[ 2 ], float rotate, float scale[ 2 ], Vector4 mappingVecs[ 2 ] ){
Vector3 vecs[2];
int sv, tv;
vec_t ang, sinv, cosv;
vec_t ns, nt;
int i, j;
float ang, sinv, cosv;
float ns, nt;
int i;
TextureAxisFromPlane( plane, vecs[0], vecs[1] );
@@ -1016,7 +959,7 @@ void QuakeTextureVecs( plane_t *plane, vec_t shift[ 2 ], vec_t rotate, vec_t sca
}
else
{
ang = rotate / 180 * Q_PI;
ang = degrees_to_radians( rotate );
sinv = sin( ang );
cosv = cos( ang );
}
@@ -1049,8 +992,7 @@ void QuakeTextureVecs( plane_t *plane, vec_t shift[ 2 ], vec_t rotate, vec_t sca
}
for ( i = 0 ; i < 2 ; i++ )
for ( j = 0 ; j < 3 ; j++ )
mappingVecs[i][j] = vecs[i][j] / scale[i];
mappingVecs[i].vec3() = vecs[i] / scale[i];
mappingVecs[0][3] = shift[0];
mappingVecs[1][3] = shift[1];
@@ -1074,12 +1016,12 @@ void QuakeTextureVecs( plane_t *plane, vec_t shift[ 2 ], vec_t rotate, vec_t sca
static void ParseRawBrush( bool onlyLights ){
side_t *side;
vec3_t planePoints[ 3 ];
Vector3 planePoints[ 3 ];
int planenum;
shaderInfo_t *si;
vec_t shift[ 2 ];
vec_t rotate = 0;
vec_t scale[ 2 ];
float shift[ 2 ];
float rotate = 0;
float scale[ 2 ];
int flags;
@@ -1128,13 +1070,13 @@ static void ParseRawBrush( bool onlyLights ){
buildBrush->numsides++;
/* read the three point plane definition */
Parse1DMatrix( 3, planePoints[ 0 ] );
Parse1DMatrix( 3, planePoints[ 1 ] );
Parse1DMatrix( 3, planePoints[ 2 ] );
Parse1DMatrix( 3, planePoints[ 0 ].data() );
Parse1DMatrix( 3, planePoints[ 1 ].data() );
Parse1DMatrix( 3, planePoints[ 2 ].data() );
/* bp: read the texture matrix */
if ( g_brushType == EBrushType::Bp ) {
Parse2DMatrix( 2, 3, (float*) side->texMat );
Parse2DMatrix( 2, 3, side->texMat->data() );
}
/* read shader name */
@@ -1187,8 +1129,7 @@ static void ParseRawBrush( bool onlyLights ){
if ( !scale[0] ) scale[0] = 1.f;
if ( !scale[1] ) scale[1] = 1.f;
for ( axis = 0; axis < 2; ++axis )
for ( comp = 0; comp < 3; ++comp )
side->vecs[axis][comp] /= scale[axis];
side->vecs[axis].vec3() /= scale[axis];
}
/* set default flags and values */
@@ -1373,9 +1314,9 @@ void MoveBrushesToWorld( entity_t *ent ){
parseMesh_t *pm;
/* we need to undo the common/origin adjustment, and instead shift them by the entity key origin */
VectorScale( ent->origin, -1, ent->originbrush_origin );
ent->originbrush_origin = -ent->origin;
AdjustBrushesForOrigin( ent );
VectorClear( ent->originbrush_origin );
ent->originbrush_origin.set( 0 );
/* move brushes */
for ( b = ent->brushes; b != NULL; b = next )
@@ -1431,7 +1372,7 @@ void AdjustBrushesForOrigin( entity_t *ent ){
int i;
side_t *s;
vec_t newdist;
float newdist;
brush_t *b;
parseMesh_t *p;
@@ -1445,10 +1386,10 @@ void AdjustBrushesForOrigin( entity_t *ent ){
s = &b->sides[ i ];
/* offset side plane */
newdist = mapplanes[ s->planenum ].dist - DotProduct( mapplanes[ s->planenum ].normal, ent->originbrush_origin );
newdist = -plane3_distance_to_point( mapplanes[ s->planenum ].plane, ent->originbrush_origin );
/* find a new plane */
s->planenum = FindFloatPlane( mapplanes[ s->planenum ].normal, newdist, 0, NULL );
s->planenum = FindFloatPlane( mapplanes[ s->planenum ].normal(), newdist, 0, NULL );
}
/* rebuild brush windings (ydnar: just offsetting the winding above should be fine) */
@@ -1459,7 +1400,7 @@ void AdjustBrushesForOrigin( entity_t *ent ){
for ( p = ent->patches; p != NULL; p = p->next )
{
for ( i = 0; i < ( p->mesh.width * p->mesh.height ); i++ )
VectorSubtract( p->mesh.verts[ i ].xyz, ent->originbrush_origin, p->mesh.verts[ i ].xyz );
p->mesh.verts[ i ].xyz -= ent->originbrush_origin;
}
}
@@ -1474,36 +1415,32 @@ void SetEntityBounds( entity_t *e ){
int i;
brush_t *b;
parseMesh_t *p;
vec3_t mins, maxs;
MinMax minmax;
/* walk the entity's brushes/patches and determine bounds */
ClearBounds( mins, maxs );
for ( b = e->brushes; b; b = b->next )
{
AddPointToBounds( b->mins, mins, maxs );
AddPointToBounds( b->maxs, mins, maxs );
minmax.extend( b->minmax );
}
for ( p = e->patches; p; p = p->next )
{
for ( i = 0; i < ( p->mesh.width * p->mesh.height ); i++ )
AddPointToBounds( p->mesh.verts[ i ].xyz, mins, maxs );
minmax.extend( p->mesh.verts[ i ].xyz );
}
/* try to find explicit min/max key */
e->read_keyvalue( mins, "min" );
e->read_keyvalue( maxs, "max" );
e->read_keyvalue( minmax.mins, "min" );
e->read_keyvalue( minmax.maxs, "max" );
/* store the bounds */
for ( b = e->brushes; b; b = b->next )
{
VectorCopy( mins, b->eMins );
VectorCopy( maxs, b->eMaxs );
b->eMinmax = minmax;
}
for ( p = e->patches; p; p = p->next )
{
VectorCopy( mins, p->eMins );
VectorCopy( maxs, p->eMaxs );
p->eMinmax = minmax;
}
}
@@ -1897,11 +1834,10 @@ void LoadMapFile( char *filename, bool onlyLights, bool noCollapseGroups ){
else
{
/* set map bounds */
ClearBounds( mapMins, mapMaxs );
g_mapMinmax.clear();
for ( b = entities[ 0 ].brushes; b; b = b->next )
{
AddPointToBounds( b->mins, mapMins, mapMaxs );
AddPointToBounds( b->maxs, mapMins, mapMaxs );
g_mapMinmax.extend( b->minmax );
}
/* get brush counts */
@@ -1920,8 +1856,8 @@ void LoadMapFile( char *filename, bool onlyLights, bool noCollapseGroups ){
Sys_FPrintf( SYS_VRB, "%9d planes\n", nummapplanes );
Sys_Printf( "%9d areaportals\n", c_areaportals );
Sys_Printf( "Size: %5.0f, %5.0f, %5.0f to %5.0f, %5.0f, %5.0f\n",
mapMins[ 0 ], mapMins[ 1 ], mapMins[ 2 ],
mapMaxs[ 0 ], mapMaxs[ 1 ], mapMaxs[ 2 ] );
g_mapMinmax.mins[0], g_mapMinmax.mins[1], g_mapMinmax.mins[2],
g_mapMinmax.maxs[0], g_mapMinmax.maxs[1], g_mapMinmax.maxs[2] );
/* write bogus map */
if ( fakemap ) {
+78 -148
View File
@@ -38,35 +38,24 @@
returns an 50/50 interpolated vert
*/
void LerpDrawVert( bspDrawVert_t *a, bspDrawVert_t *b, bspDrawVert_t *out ){
int k;
void LerpDrawVert( const bspDrawVert_t *a, const bspDrawVert_t *b, bspDrawVert_t *out ){
out->xyz = vector3_mid( a->xyz, b->xyz );
out->st = vector2_mid( a->st, b->st );
out->xyz[ 0 ] = 0.5 * ( a->xyz[ 0 ] + b->xyz[ 0 ] );
out->xyz[ 1 ] = 0.5 * ( a->xyz[ 1 ] + b->xyz[ 1 ] );
out->xyz[ 2 ] = 0.5 * ( a->xyz[ 2 ] + b->xyz[ 2 ] );
out->st[ 0 ] = 0.5 * ( a->st[ 0 ] + b->st[ 0 ] );
out->st[ 1 ] = 0.5 * ( a->st[ 1 ] + b->st[ 1 ] );
for ( k = 0; k < MAX_LIGHTMAPS; k++ )
for ( int k = 0; k < MAX_LIGHTMAPS; k++ )
{
out->lightmap[ k ][ 0 ] = 0.5f * ( a->lightmap[ k ][ 0 ] + b->lightmap[ k ][ 0 ] );
out->lightmap[ k ][ 1 ] = 0.5f * ( a->lightmap[ k ][ 1 ] + b->lightmap[ k ][ 1 ] );
out->color[ k ][ 0 ] = ( a->color[ k ][ 0 ] + b->color[ k ][ 0 ] ) >> 1;
out->color[ k ][ 1 ] = ( a->color[ k ][ 1 ] + b->color[ k ][ 1 ] ) >> 1;
out->color[ k ][ 2 ] = ( a->color[ k ][ 2 ] + b->color[ k ][ 2 ] ) >> 1;
out->color[ k ][ 3 ] = ( a->color[ k ][ 3 ] + b->color[ k ][ 3 ] ) >> 1;
out->lightmap[ k ] = vector2_mid( a->lightmap[ k ], b->lightmap[ k ] );
for( int i = 0; i < 4; ++i )
out->color[ k ][ i ] = ( a->color[ k ][ i ] + b->color[ k ][ i ] ) >> 1;
}
/* ydnar: added normal interpolation */
out->normal[ 0 ] = 0.5f * ( a->normal[ 0 ] + b->normal[ 0 ] );
out->normal[ 1 ] = 0.5f * ( a->normal[ 1 ] + b->normal[ 1 ] );
out->normal[ 2 ] = 0.5f * ( a->normal[ 2 ] + b->normal[ 2 ] );
out->normal = vector3_mid( a->normal, b->normal );
/* if the interpolant created a bogus normal, just copy the normal from a */
if ( VectorNormalize( out->normal, out->normal ) == 0 ) {
VectorCopy( a->normal, out->normal );
if ( VectorNormalize( out->normal ) == 0 ) {
out->normal = a->normal;
}
}
@@ -78,33 +67,23 @@ void LerpDrawVert( bspDrawVert_t *a, bspDrawVert_t *b, bspDrawVert_t *out ){
*/
void LerpDrawVertAmount( bspDrawVert_t *a, bspDrawVert_t *b, float amount, bspDrawVert_t *out ){
int k;
out->xyz = a->xyz + ( b->xyz - a->xyz ) * amount;
out->xyz[ 0 ] = a->xyz[ 0 ] + amount * ( b->xyz[ 0 ] - a->xyz[ 0 ] );
out->xyz[ 1 ] = a->xyz[ 1 ] + amount * ( b->xyz[ 1 ] - a->xyz[ 1 ] );
out->xyz[ 2 ] = a->xyz[ 2 ] + amount * ( b->xyz[ 2 ] - a->xyz[ 2 ] );
out->st = a->st + ( b->st - a->st ) * amount;
out->st[ 0 ] = a->st[ 0 ] + amount * ( b->st[ 0 ] - a->st[ 0 ] );
out->st[ 1 ] = a->st[ 1 ] + amount * ( b->st[ 1 ] - a->st[ 1 ] );
for ( k = 0; k < MAX_LIGHTMAPS; k++ )
for ( int k = 0; k < MAX_LIGHTMAPS; k++ )
{
out->lightmap[ k ][ 0 ] = a->lightmap[ k ][ 0 ] + amount * ( b->lightmap[ k ][ 0 ] - a->lightmap[ k ][ 0 ] );
out->lightmap[ k ][ 1 ] = a->lightmap[ k ][ 1 ] + amount * ( b->lightmap[ k ][ 1 ] - a->lightmap[ k ][ 1 ] );
out->color[ k ][ 0 ] = a->color[ k ][ 0 ] + amount * ( b->color[ k ][ 0 ] - a->color[ k ][ 0 ] );
out->color[ k ][ 1 ] = a->color[ k ][ 1 ] + amount * ( b->color[ k ][ 1 ] - a->color[ k ][ 1 ] );
out->color[ k ][ 2 ] = a->color[ k ][ 2 ] + amount * ( b->color[ k ][ 2 ] - a->color[ k ][ 2 ] );
out->color[ k ][ 3 ] = a->color[ k ][ 3 ] + amount * ( b->color[ k ][ 3 ] - a->color[ k ][ 3 ] );
out->lightmap[ k ] = a->lightmap[ k ] + ( b->lightmap[ k ] - a->lightmap[ k ] ) * amount;
for( int i = 0; i < 4; ++i )
out->color[ k ][ i ] = a->color[ k ][ i ] + amount * ( b->color[ k ][ i ] - a->color[ k ][ i ] );
}
out->normal[ 0 ] = a->normal[ 0 ] + amount * ( b->normal[ 0 ] - a->normal[ 0 ] );
out->normal[ 1 ] = a->normal[ 1 ] + amount * ( b->normal[ 1 ] - a->normal[ 1 ] );
out->normal[ 2 ] = a->normal[ 2 ] + amount * ( b->normal[ 2 ] - a->normal[ 2 ] );
out->normal = a->normal + ( b->normal - a->normal ) * amount;
/* if the interpolant created a bogus normal, just copy the normal from a */
if ( VectorNormalize( out->normal, out->normal ) == 0 ) {
VectorCopy( a->normal, out->normal );
if ( VectorNormalize( out->normal ) == 0 ) {
out->normal = a->normal;
}
}
@@ -191,17 +170,12 @@ void InvertMesh( mesh_t *in ) {
*/
void MakeMeshNormals( mesh_t in ){
int i, j, k, dist;
vec3_t normal;
vec3_t sum;
int count;
vec3_t base;
vec3_t delta;
int x, y;
bspDrawVert_t *dv;
vec3_t around[8], temp;
Vector3 around[8];
bool good[8];
bool wrapWidth, wrapHeight;
float len;
int neighbors[8][2] =
{
{0,1}, {1,1}, {1,0}, {1,-1}, {0,-1}, {-1,-1}, {-1,0}, {-1,1}
@@ -210,10 +184,7 @@ void MakeMeshNormals( mesh_t in ){
wrapWidth = false;
for ( i = 0 ; i < in.height ; i++ ) {
VectorSubtract( in.verts[i * in.width].xyz,
in.verts[i * in.width + in.width - 1].xyz, delta );
len = VectorLength( delta );
if ( len > 1.0 ) {
if ( vector3_length( in.verts[i * in.width].xyz - in.verts[i * in.width + in.width - 1].xyz ) > 1.0 ) {
break;
}
}
@@ -223,10 +194,7 @@ void MakeMeshNormals( mesh_t in ){
wrapHeight = false;
for ( i = 0 ; i < in.width ; i++ ) {
VectorSubtract( in.verts[i].xyz,
in.verts[i + ( in.height - 1 ) * in.width].xyz, delta );
len = VectorLength( delta );
if ( len > 1.0 ) {
if ( vector3_length( in.verts[i].xyz - in.verts[i + ( in.height - 1 ) * in.width].xyz ) > 1.0 ) {
break;
}
}
@@ -239,9 +207,9 @@ void MakeMeshNormals( mesh_t in ){
for ( j = 0 ; j < in.height ; j++ ) {
count = 0;
dv = &in.verts[j * in.width + i];
VectorCopy( dv->xyz, base );
const Vector3 base( dv->xyz );
for ( k = 0 ; k < 8 ; k++ ) {
VectorClear( around[k] );
around[k].set( 0 );
good[k] = false;
for ( dist = 1 ; dist <= 3 ; dist++ ) {
@@ -267,35 +235,35 @@ void MakeMeshNormals( mesh_t in ){
if ( x < 0 || x >= in.width || y < 0 || y >= in.height ) {
break; // edge of patch
}
VectorSubtract( in.verts[y * in.width + x].xyz, base, temp );
if ( VectorNormalize( temp, temp ) == 0 ) {
Vector3 temp = in.verts[y * in.width + x].xyz - base;
if ( VectorNormalize( temp ) == 0 ) {
continue; // degenerate edge, get more dist
}
else {
good[k] = true;
VectorCopy( temp, around[k] );
around[k] = temp;
break; // good edge
}
}
}
VectorClear( sum );
Vector3 sum( 0, 0, 0 );
for ( k = 0 ; k < 8 ; k++ ) {
if ( !good[k] || !good[( k + 1 ) & 7] ) {
continue; // didn't get two points
}
CrossProduct( around[( k + 1 ) & 7], around[k], normal );
if ( VectorNormalize( normal, normal ) == 0 ) {
Vector3 normal = vector3_cross( around[( k + 1 ) & 7], around[k] );
if ( VectorNormalize( normal ) == 0 ) {
continue;
}
VectorAdd( normal, sum, sum );
sum += normal;
count++;
}
if ( count == 0 ) {
//Sys_Printf("bad normal\n");
count = 1;
}
VectorNormalize( sum, dv->normal );
dv->normal = VectorNormalized( sum );
}
}
}
@@ -307,55 +275,40 @@ void MakeMeshNormals( mesh_t in ){
*/
void PutMeshOnCurve( mesh_t in ) {
int i, j, l, m;
float prev, next;
int i, j, m;
// put all the aproximating points on the curve
for ( i = 0 ; i < in.width ; i++ ) {
for ( j = 1 ; j < in.height ; j += 2 ) {
for ( l = 0 ; l < 3 ; l++ ) {
prev = ( in.verts[j * in.width + i].xyz[l] + in.verts[( j + 1 ) * in.width + i].xyz[l] ) * 0.5;
next = ( in.verts[j * in.width + i].xyz[l] + in.verts[( j - 1 ) * in.width + i].xyz[l] ) * 0.5;
in.verts[j * in.width + i].xyz[l] = ( prev + next ) * 0.5;
/* ydnar: interpolating st coords */
if ( l < 2 ) {
prev = ( in.verts[j * in.width + i].st[l] + in.verts[( j + 1 ) * in.width + i].st[l] ) * 0.5;
next = ( in.verts[j * in.width + i].st[l] + in.verts[( j - 1 ) * in.width + i].st[l] ) * 0.5;
in.verts[j * in.width + i].st[l] = ( prev + next ) * 0.5;
for ( m = 0; m < MAX_LIGHTMAPS; m++ )
{
prev = ( in.verts[j * in.width + i].lightmap[ m ][l] + in.verts[( j + 1 ) * in.width + i].lightmap[ m ][l] ) * 0.5;
next = ( in.verts[j * in.width + i].lightmap[ m ][l] + in.verts[( j - 1 ) * in.width + i].lightmap[ m ][l] ) * 0.5;
in.verts[j * in.width + i].lightmap[ m ][l] = ( prev + next ) * 0.5;
}
}
const int idx = j * in.width + i;
const int idprev = ( j + 1 ) * in.width + i;
const int idnext = ( j - 1 ) * in.width + i;
in.verts[idx].xyz = vector3_mid( vector3_mid( in.verts[idx].xyz, in.verts[idprev].xyz ),
vector3_mid( in.verts[idx].xyz, in.verts[idnext].xyz ) );
/* ydnar: interpolating st coords */
in.verts[idx].st = vector2_mid( vector2_mid( in.verts[idx].st, in.verts[idprev].st ),
vector2_mid( in.verts[idx].st, in.verts[idnext].st ) );
for ( m = 0; m < MAX_LIGHTMAPS; m++ )
{
in.verts[idx].lightmap[ m ] = vector2_mid( vector2_mid( in.verts[idx].lightmap[ m ], in.verts[idprev].lightmap[ m ] ),
vector2_mid( in.verts[idx].lightmap[ m ], in.verts[idnext].lightmap[ m ] ) );
}
}
}
for ( j = 0 ; j < in.height ; j++ ) {
for ( i = 1 ; i < in.width ; i += 2 ) {
for ( l = 0 ; l < 3 ; l++ ) {
prev = ( in.verts[j * in.width + i].xyz[l] + in.verts[j * in.width + i + 1].xyz[l] ) * 0.5;
next = ( in.verts[j * in.width + i].xyz[l] + in.verts[j * in.width + i - 1].xyz[l] ) * 0.5;
in.verts[j * in.width + i].xyz[l] = ( prev + next ) * 0.5;
/* ydnar: interpolating st coords */
if ( l < 2 ) {
prev = ( in.verts[j * in.width + i].st[l] + in.verts[j * in.width + i + 1].st[l] ) * 0.5;
next = ( in.verts[j * in.width + i].st[l] + in.verts[j * in.width + i - 1].st[l] ) * 0.5;
in.verts[j * in.width + i].st[l] = ( prev + next ) * 0.5;
for ( m = 0; m < MAX_LIGHTMAPS; m++ )
{
prev = ( in.verts[j * in.width + i].lightmap[ m ][l] + in.verts[j * in.width + i + 1].lightmap[ m ][l] ) * 0.5;
next = ( in.verts[j * in.width + i].lightmap[ m ][l] + in.verts[j * in.width + i - 1].lightmap[ m ][l] ) * 0.5;
in.verts[j * in.width + i].lightmap[ m ][l] = ( prev + next ) * 0.5;
}
}
const int idx = j * in.width + i;
in.verts[idx].xyz = vector3_mid( vector3_mid( in.verts[idx].xyz, in.verts[idx + 1].xyz ),
vector3_mid( in.verts[idx].xyz, in.verts[idx - 1].xyz ) );
/* ydnar: interpolating st coords */
in.verts[idx].st = vector2_mid( vector2_mid( in.verts[idx].st, in.verts[idx + 1].st ),
vector2_mid( in.verts[idx].st, in.verts[idx - 1].st ) );
for ( m = 0; m < MAX_LIGHTMAPS; m++ )
{
in.verts[idx].lightmap[ m ] = vector2_mid( vector2_mid( in.verts[idx].lightmap[ m ], in.verts[idx + 1].lightmap[ m ] ),
vector2_mid( in.verts[idx].lightmap[ m ], in.verts[idx - 1].lightmap[ m ] ) );
}
}
}
@@ -369,11 +322,9 @@ void PutMeshOnCurve( mesh_t in ) {
=================
*/
mesh_t *SubdivideMesh( mesh_t in, float maxError, float minLength ){
int i, j, k, l;
int i, j, k;
bspDrawVert_t prev, next, mid;
vec3_t prevxyz, nextxyz, midxyz;
vec3_t delta;
float len;
Vector3 prevxyz, nextxyz, midxyz;
mesh_t out;
bspDrawVert_t expand[MAX_EXPANDED_AXIS][MAX_EXPANDED_AXIS];
@@ -392,23 +343,18 @@ mesh_t *SubdivideMesh( mesh_t in, float maxError, float minLength ){
for ( j = 0 ; j + 2 < out.width ; j += 2 ) {
// check subdivided midpoints against control points
for ( i = 0 ; i < out.height ; i++ ) {
for ( l = 0 ; l < 3 ; l++ ) {
prevxyz[l] = expand[i][j + 1].xyz[l] - expand[i][j].xyz[l];
nextxyz[l] = expand[i][j + 2].xyz[l] - expand[i][j + 1].xyz[l];
midxyz[l] = ( expand[i][j].xyz[l] + expand[i][j + 1].xyz[l] * 2
+ expand[i][j + 2].xyz[l] ) * 0.25;
}
prevxyz = expand[i][j + 1].xyz - expand[i][j].xyz;
nextxyz = expand[i][j + 2].xyz - expand[i][j + 1].xyz;
midxyz = ( expand[i][j].xyz + expand[i][j + 1].xyz * 2 + expand[i][j + 2].xyz ) * 0.25;
// if the span length is too long, force a subdivision
if ( VectorLength( prevxyz ) > minLength
|| VectorLength( nextxyz ) > minLength ) {
if ( vector3_length( prevxyz ) > minLength
|| vector3_length( nextxyz ) > minLength ) {
break;
}
// see if this midpoint is off far enough to subdivide
VectorSubtract( expand[i][j + 1].xyz, midxyz, delta );
len = VectorLength( delta );
if ( len > maxError ) {
if ( vector3_length( expand[i][j + 1].xyz - midxyz ) > maxError ) {
break;
}
}
@@ -446,22 +392,17 @@ mesh_t *SubdivideMesh( mesh_t in, float maxError, float minLength ){
for ( j = 0 ; j + 2 < out.height ; j += 2 ) {
// check subdivided midpoints against control points
for ( i = 0 ; i < out.width ; i++ ) {
for ( l = 0 ; l < 3 ; l++ ) {
prevxyz[l] = expand[j + 1][i].xyz[l] - expand[j][i].xyz[l];
nextxyz[l] = expand[j + 2][i].xyz[l] - expand[j + 1][i].xyz[l];
midxyz[l] = ( expand[j][i].xyz[l] + expand[j + 1][i].xyz[l] * 2
+ expand[j + 2][i].xyz[l] ) * 0.25;
}
prevxyz = expand[j + 1][i].xyz - expand[j][i].xyz;
nextxyz = expand[j + 2][i].xyz - expand[j + 1][i].xyz;
midxyz = ( expand[j][i].xyz + expand[j + 1][i].xyz * 2 + expand[j + 2][i].xyz ) * 0.25;
// if the span length is too long, force a subdivision
if ( VectorLength( prevxyz ) > minLength
|| VectorLength( nextxyz ) > minLength ) {
if ( vector3_length( prevxyz ) > minLength
|| vector3_length( nextxyz ) > minLength ) {
break;
}
// see if this midpoint is off far enough to subdivide
VectorSubtract( expand[j + 1][i].xyz, midxyz, delta );
len = VectorLength( delta );
if ( len > maxError ) {
if ( vector3_length( expand[j + 1][i].xyz - midxyz ) > maxError ) {
break;
}
}
@@ -626,14 +567,11 @@ mesh_t *SubdivideMesh2( mesh_t in, int iterations ){
ProjectPointOntoVector
================
*/
void ProjectPointOntoVector( vec3_t point, vec3_t vStart, vec3_t vEnd, vec3_t vProj ){
vec3_t pVec, vec;
VectorSubtract( point, vStart, pVec );
VectorSubtract( vEnd, vStart, vec );
VectorNormalize( vec, vec );
Vector3 ProjectPointOntoVector( const Vector3& point, const Vector3& vStart, const Vector3& vEnd ){
const Vector3 pVec = point - vStart;
const Vector3 vec = VectorNormalized( vEnd - vStart );
// project onto the directional vector for this segment
VectorMA( vStart, DotProduct( pVec, vec ), vec, vProj );
return ( vStart + vec * vector3_dot( pVec, vec ) );
}
/*
@@ -644,7 +582,6 @@ void ProjectPointOntoVector( vec3_t point, vec3_t vStart, vec3_t vEnd, vec3_t vP
mesh_t *RemoveLinearMeshColumnsRows( mesh_t *in ) {
int i, j, k;
float len, maxLength;
vec3_t proj, dir;
mesh_t out;
bspDrawVert_t expand[MAX_EXPANDED_AXIS][MAX_EXPANDED_AXIS];
@@ -662,9 +599,7 @@ mesh_t *RemoveLinearMeshColumnsRows( mesh_t *in ) {
for ( j = 1 ; j < out.width - 1; j++ ) {
maxLength = 0;
for ( i = 0 ; i < out.height ; i++ ) {
ProjectPointOntoVector( expand[i][j].xyz, expand[i][j - 1].xyz, expand[i][j + 1].xyz, proj );
VectorSubtract( expand[i][j].xyz, proj, dir );
len = VectorLength( dir );
len = vector3_length( expand[i][j].xyz - ProjectPointOntoVector( expand[i][j].xyz, expand[i][j - 1].xyz, expand[i][j + 1].xyz ) );
if ( len > maxLength ) {
maxLength = len;
}
@@ -682,9 +617,7 @@ mesh_t *RemoveLinearMeshColumnsRows( mesh_t *in ) {
for ( j = 1 ; j < out.height - 1; j++ ) {
maxLength = 0;
for ( i = 0 ; i < out.width ; i++ ) {
ProjectPointOntoVector( expand[j][i].xyz, expand[j - 1][i].xyz, expand[j + 1][i].xyz, proj );
VectorSubtract( expand[j][i].xyz, proj, dir );
len = VectorLength( dir );
len = vector3_length( expand[j][i].xyz - ProjectPointOntoVector( expand[j][i].xyz, expand[j - 1][i].xyz, expand[j + 1][i].xyz ) );
if ( len > maxLength ) {
maxLength = len;
}
@@ -717,7 +650,6 @@ mesh_t *RemoveLinearMeshColumnsRows( mesh_t *in ) {
*/
mesh_t *SubdivideMeshQuads( mesh_t *in, float minLength, int maxsize, int *widthtable, int *heighttable ){
int i, j, k, w, h, maxsubdivisions, subdivisions;
vec3_t dir;
float length, maxLength, amount;
mesh_t out;
bspDrawVert_t expand[MAX_EXPANDED_AXIS][MAX_EXPANDED_AXIS];
@@ -742,8 +674,7 @@ mesh_t *SubdivideMeshQuads( mesh_t *in, float minLength, int maxsize, int *width
for ( w = 0, j = 0 ; w < in->width - 1; w++, j += subdivisions + 1 ) {
maxLength = 0;
for ( i = 0 ; i < out.height ; i++ ) {
VectorSubtract( expand[i][j + 1].xyz, expand[i][j].xyz, dir );
length = VectorLength( dir );
length = vector3_length( expand[i][j + 1].xyz - expand[i][j].xyz );
if ( length > maxLength ) {
maxLength = length;
}
@@ -778,9 +709,8 @@ mesh_t *SubdivideMeshQuads( mesh_t *in, float minLength, int maxsize, int *width
for ( h = 0, j = 0 ; h < in->height - 1; h++, j += subdivisions + 1 ) {
maxLength = 0;
for ( i = 0 ; i < out.width ; i++ ) {
VectorSubtract( expand[j + 1][i].xyz, expand[j][i].xyz, dir );
length = VectorLength( dir );
if ( length > maxLength ) {
length = vector3_length( expand[j + 1][i].xyz - expand[j][i].xyz );
if ( length > maxLength ) {
maxLength = length;
}
}
+27 -34
View File
@@ -45,29 +45,29 @@ struct minimap_t
float boost, brightness, contrast;
float *data1f;
float *sharpendata1f;
vec3_t mins, size;
Vector3 mins, size;
};
static minimap_t minimap;
bool BrushIntersectionWithLine( bspBrush_t *brush, vec3_t start, vec3_t dir, float *t_in, float *t_out ){
bool BrushIntersectionWithLine( bspBrush_t *brush, const Vector3& start, const Vector3& dir, float *t_in, float *t_out ){
int i;
bool in = false, out = false;
bspBrushSide_t *sides = &bspBrushSides[brush->firstSide];
for ( i = 0; i < brush->numSides; ++i )
{
bspPlane_t *p = &bspPlanes[sides[i].planeNum];
float sn = DotProduct( start, p->normal );
float dn = DotProduct( dir, p->normal );
const bspPlane_t& p = bspPlanes[sides[i].planeNum];
float sn = vector3_dot( start, p.normal() );
float dn = vector3_dot( dir, p.normal() );
if ( dn == 0 ) {
if ( sn > p->dist ) {
if ( sn > p.dist() ) {
return false; // outside!
}
}
else
{
float t = ( p->dist - sn ) / dn;
float t = ( p.dist() - sn ) / dn;
if ( dn < 0 ) {
if ( !in || t > *t_in ) {
*t_in = t;
@@ -95,7 +95,6 @@ bool BrushIntersectionWithLine( bspBrush_t *brush, vec3_t start, vec3_t dir, flo
}
static float MiniMapSample( float x, float y ){
vec3_t org, dir;
int i, bi;
float t0, t1;
float samp;
@@ -103,12 +102,8 @@ static float MiniMapSample( float x, float y ){
bspBrushSide_t *s;
int cnt;
org[0] = x;
org[1] = y;
org[2] = 0;
dir[0] = 0;
dir[1] = 0;
dir[2] = 1;
const Vector3 org( x, y, 0 );
const Vector3 dir( g_vector3_axis_z );
cnt = 0;
samp = 0;
@@ -120,16 +115,16 @@ static float MiniMapSample( float x, float y ){
// sort out mins/maxs of the brush
s = &bspBrushSides[b->firstSide];
if ( x < -bspPlanes[s[0].planeNum].dist ) {
if ( x < -bspPlanes[s[0].planeNum].dist() ) {
continue;
}
if ( x > +bspPlanes[s[1].planeNum].dist ) {
if ( x > +bspPlanes[s[1].planeNum].dist() ) {
continue;
}
if ( y < -bspPlanes[s[2].planeNum].dist ) {
if ( y < -bspPlanes[s[2].planeNum].dist() ) {
continue;
}
if ( y > +bspPlanes[s[3].planeNum].dist ) {
if ( y > +bspPlanes[s[3].planeNum].dist() ) {
continue;
}
@@ -281,16 +276,16 @@ static void MiniMapBrightnessContrast( int y ){
}
}
void MiniMapMakeMinsMaxs( vec3_t mins_in, vec3_t maxs_in, float border, bool keepaspect ){
vec3_t mins, maxs, extend;
VectorCopy( mins_in, mins );
VectorCopy( maxs_in, maxs );
void MiniMapMakeMinsMaxs( const Vector3& mins_in, const Vector3& maxs_in, float border, bool keepaspect ){
Vector3 mins = mins_in;
Vector3 maxs = maxs_in;
Vector3 extend;
// line compatible to nexuiz mapinfo
Sys_Printf( "size %f %f %f %f %f %f\n", mins[0], mins[1], mins[2], maxs[0], maxs[1], maxs[2] );
if ( keepaspect ) {
VectorSubtract( maxs, mins, extend );
extend = maxs - mins;
if ( extend[1] > extend[0] ) {
mins[0] -= ( extend[1] - extend[0] ) * 0.5;
maxs[0] += ( extend[1] - extend[0] ) * 0.5;
@@ -305,14 +300,13 @@ void MiniMapMakeMinsMaxs( vec3_t mins_in, vec3_t maxs_in, float border, bool kee
/* border: amount of black area around the image */
/* input: border, 1-2*border, border but we need border/(1-2*border) */
VectorSubtract( maxs, mins, extend );
VectorScale( extend, border / ( 1 - 2 * border ), extend );
extend = ( maxs - mins ) * ( border / ( 1 - 2 * border ) );
VectorSubtract( mins, extend, mins );
VectorAdd( maxs, extend, maxs );
mins -= extend;
maxs += extend;
VectorCopy( mins, minimap.mins );
VectorSubtract( maxs, mins, minimap.size );
minimap.mins = mins;
minimap.size = maxs - mins;
// line compatible to nexuiz mapinfo
Sys_Printf( "size_texcoords %f %f %f %f %f %f\n", mins[0], mins[1], mins[2], maxs[0], maxs[1], maxs[2] );
@@ -468,7 +462,6 @@ int MiniMapBSPMain( int argc, char **argv ){
int x, y;
int i;
EMiniMapMode mode;
vec3_t mins, maxs;
bool keepaspect;
/* arg checking */
@@ -486,10 +479,10 @@ int MiniMapBSPMain( int argc, char **argv ){
LoadBSPFile( source );
minimap.model = &bspModels[0];
VectorCopy( minimap.model->mins, mins );
VectorCopy( minimap.model->maxs, maxs );
Vector3 mins = minimap.model->minmax.mins;
Vector3 maxs = minimap.model->minmax.maxs;
*minimapFilename = 0;
strClear( minimapFilename );
minimapSharpen = game->miniMapSharpen;
minimap.width = minimap.height = game->miniMapSize;
border = game->miniMapBorder;
@@ -598,7 +591,7 @@ int MiniMapBSPMain( int argc, char **argv ){
MiniMapMakeMinsMaxs( mins, maxs, border, keepaspect );
if ( !*minimapFilename ) {
if ( strEmpty( minimapFilename ) ) {
ExtractFileBase( source, basename );
ExtractFilePath( source, path );
sprintf( relativeMinimapFilename, game->miniMapNameFormat, basename );
+198 -264
View File
@@ -205,9 +205,9 @@ picoModel_t *LoadModel( const char *name, int frame ){
adds a picomodel into the bsp
*/
void InsertModel( const char *name, int skin, int frame, m4x4_t transform, const std::list<remap_t> *remaps, shaderInfo_t *celShader, int eNum, int castShadows, int recvShadows, int spawnFlags, float lightmapScale, int lightmapSampleSize, float shadeAngle, float clipDepth ){
void InsertModel( const char *name, int skin, int frame, const Matrix4& transform, const std::list<remap_t> *remaps, shaderInfo_t *celShader, int eNum, int castShadows, int recvShadows, int spawnFlags, float lightmapScale, int lightmapSampleSize, float shadeAngle, float clipDepth ){
int i, j, s, k, numSurfaces;
m4x4_t identity, nTransform;
const Matrix4 nTransform( matrix4_for_normal_transform( transform ) );
picoModel_t *model;
picoSurface_t *surface;
shaderInfo_t *si;
@@ -291,24 +291,11 @@ void InsertModel( const char *name, int skin, int frame, m4x4_t transform, const
free( skinfilecontent );
}
/* handle null matrix */
if ( transform == NULL ) {
m4x4_identity( identity );
transform = identity;
}
/* hack: Stable-1_2 and trunk have differing row/column major matrix order
this transpose is necessary with Stable-1_2
uncomment the following line with old m4x4_t (non 1.3/spog_branch) code */
//% m4x4_transpose( transform );
/* create transform matrix for normals */
memcpy( nTransform, transform, sizeof( m4x4_t ) );
if ( m4x4_invert( nTransform ) ) {
Sys_FPrintf( SYS_WRN | SYS_VRBflag, "WARNING: Can't invert model transform matrix, using transpose instead\n" );
}
m4x4_transpose( nTransform );
/* fix bogus lightmap scale */
if ( lightmapScale <= 0.0f ) {
lightmapScale = 1.0f;
@@ -442,24 +429,23 @@ void InsertModel( const char *name, int skin, int frame, m4x4_t transform, const
/* xyz and normal */
xyz = PicoGetSurfaceXYZ( surface, i );
VectorCopy( xyz, dv->xyz );
m4x4_transform_point( transform, dv->xyz );
matrix4_transform_point( transform, dv->xyz );
normal = PicoGetSurfaceNormal( surface, i );
VectorCopy( normal, dv->normal );
m4x4_transform_normal( nTransform, dv->normal );
VectorNormalize( dv->normal, dv->normal );
matrix4_transform_direction( nTransform, dv->normal );
VectorNormalize( dv->normal );
/* ydnar: tek-fu celshading support for flat shaded shit */
if ( flat ) {
dv->st[ 0 ] = si->stFlat[ 0 ];
dv->st[ 1 ] = si->stFlat[ 1 ];
dv->st = si->stFlat;
}
/* ydnar: gs mods: added support for explicit shader texcoord generation */
else if ( si->tcGen ) {
/* project the texture */
dv->st[ 0 ] = DotProduct( si->vecs[ 0 ], dv->xyz );
dv->st[ 1 ] = DotProduct( si->vecs[ 1 ], dv->xyz );
dv->st[ 0 ] = vector3_dot( si->vecs[ 0 ], dv->xyz );
dv->st[ 1 ] = vector3_dot( si->vecs[ 1 ], dv->xyz );
}
/* normal texture coordinates */
@@ -477,17 +463,11 @@ void InsertModel( const char *name, int skin, int frame, m4x4_t transform, const
dv->lightmap[ j ][ 0 ] = 0.0f;
dv->lightmap[ j ][ 1 ] = 0.0f;
if ( spawnFlags & 32 ) { // spawnflag 32: model color -> alpha hack
dv->color[ j ][ 0 ] = 255.0f;
dv->color[ j ][ 1 ] = 255.0f;
dv->color[ j ][ 2 ] = 255.0f;
dv->color[ j ][ 3 ] = RGBTOGRAY( color );
dv->color[ j ] = { 255, 255, 255, RGBTOGRAY( color ) };
}
else
{
dv->color[ j ][ 0 ] = color[ 0 ];
dv->color[ j ][ 1 ] = color[ 1 ];
dv->color[ j ][ 2 ] = color[ 2 ];
dv->color[ j ][ 3 ] = color[ 3 ];
dv->color[ j ] = { color[0], color[1], color[2], color[3] };
}
}
}
@@ -522,12 +502,12 @@ void InsertModel( const char *name, int skin, int frame, m4x4_t transform, const
( spf == 5632 ) || //EXTRUDE_DOWNWARDS+EXTRUDE_UPWARDS+AXIAL_BACKPLANE
( spf == 3072 ) || //EXTRUDE_UPWARDS+MAX_EXTRUDE
( spf == 5120 ) ){ //EXTRUDE_UPWARDS+AXIAL_BACKPLANE
vec3_t points[ 4 ], cnt, bestNormal, nrm, Vnorm[3], Enorm[3];
vec4_t plane, reverse, p[3];
Vector3 points[ 4 ], cnt, bestNormal, nrm, Vnorm[3], Enorm[3];
Plane3f plane, reverse, p[3];
double normalEpsilon_save;
bool snpd;
vec3_t min = { 999999, 999999, 999999 }, max = { -999999, -999999, -999999 };
vec3_t avgDirection = { 0, 0, 0 };
MinMax minmax;
Vector3 avgDirection( 0, 0, 0 );
int axis;
#define nonax_clip_dbg 0
@@ -549,41 +529,27 @@ void InsertModel( const char *name, int skin, int frame, m4x4_t transform, const
for ( j = 0; j < 3; j++ )
{
dv = &ds->verts[ ds->indexes[ i + j ] ];
VectorCopy( dv->xyz, points[ j ] );
points[ j ] = dv->xyz;
}
if ( PlaneFromPoints( plane, points[ 0 ], points[ 1 ], points[ 2 ] ) ){
if ( spawnFlags & 16 ) VectorAdd( avgDirection, plane, avgDirection ); //calculate average mesh facing direction
if ( PlaneFromPoints( plane, points ) ){
if ( spawnFlags & 16 )
avgDirection += plane.normal(); //calculate average mesh facing direction
//get min/max
for ( k = 2; k > -1; k-- ){
if ( plane[k] > 0 ){
for ( j = 0; j < 3; j++ ){ if ( points[j][k] < min[k] ) min[k] = points[j][k]; }
}
else if ( plane[k] < 0 ){
for ( j = 0; j < 3; j++ ){ if ( points[j][k] > max[k] ) max[k] = points[j][k]; }
}
//if EXTRUDE_DOWNWARDS or EXTRUDE_UPWARDS
if ( ( spawnFlags & 512 ) || ( spawnFlags & 1024 ) ){
break;
}
for ( j = 0; j < 3; ++j ){
minmax.extend( points[j] );
}
}
}
//unify avg direction
if ( spawnFlags & 16 ){
for ( j = 0; j < 3; j++ ){
if ( fabs(avgDirection[j]) > fabs(avgDirection[(j+1)%3]) ){
avgDirection[(j+1)%3] = 0.0;
axis = j;
}
else {
avgDirection[j] = 0.0;
}
if ( vector3_length( avgDirection ) != 0 ){
axis = vector3_max_abs_component_index( avgDirection );
}
if ( VectorNormalize( avgDirection, avgDirection ) == 0 ){
else{
axis = 2;
VectorSet( avgDirection, 0, 0, 1 );
}
avgDirection = avgDirection[axis] >= 0? g_vector3_axes[axis] : -g_vector3_axes[axis];
}
}
@@ -600,11 +566,11 @@ void InsertModel( const char *name, int skin, int frame, m4x4_t transform, const
dv = &ds->verts[ ds->indexes[ i + j ] ];
/* copy xyz */
VectorCopy( dv->xyz, points[ j ] );
points[ j ] = dv->xyz;
}
/* make plane for triangle */
if ( PlaneFromPoints( plane, points[ 0 ], points[ 1 ], points[ 2 ] ) ) {
if ( PlaneFromPoints( plane, points ) ) {
/* build a brush */
buildBrush = AllocBrush( 48 );
@@ -621,11 +587,10 @@ void InsertModel( const char *name, int skin, int frame, m4x4_t transform, const
snpd = false;
for ( j=0; j<3; j++ )
{
if ( fabs(plane[j]) < 0.00025 && fabs(plane[(j+1)%3]) < 0.00025 && ( plane[j] != 0.0 || plane[(j+1)%3] != 0.0 ) ){
VectorAdd( points[ 0 ], points[ 1 ], cnt );
VectorAdd( cnt, points[ 2 ], cnt );
VectorScale( cnt, 0.3333333333333f, cnt );
points[0][(j+2)%3]=points[1][(j+2)%3]=points[2][(j+2)%3]=cnt[(j+2)%3];
if ( fabs( plane.normal()[j] ) < 0.00025 && fabs( plane.normal()[(j+1)%3] ) < 0.00025
&& ( plane.normal()[j] != 0.0 || plane.normal()[(j+1)%3] != 0.0 ) ){
cnt = ( points[0] + points[1] + points[2] ) / 3.0;
points[0][(j+2)%3] = points[1][(j+2)%3] = points[2][(j+2)%3] = cnt[(j+2)%3];
snpd = true;
break;
}
@@ -634,8 +599,7 @@ void InsertModel( const char *name, int skin, int frame, m4x4_t transform, const
//snap pairs of points to prevent bad side planes
for ( j=0; j<3; j++ )
{
VectorSubtract( points[j], points[(j+1)%3], nrm );
VectorNormalize( nrm, nrm );
nrm = VectorNormalized( points[j] - points[(j+1)%3] );
for ( k=0; k<3; k++ )
{
if ( nrm[k] != 0.0 && fabs(nrm[k]) < 0.00025 ){
@@ -648,19 +612,18 @@ void InsertModel( const char *name, int skin, int frame, m4x4_t transform, const
}
if ( snpd ) {
PlaneFromPoints( plane, points[ 0 ], points[ 1 ], points[ 2 ] );
PlaneFromPoints( plane, points );
snpd = false;
}
//vector-is-close-to-be-on-axis check again, happens after previous code sometimes
for ( j=0; j<3; j++ )
{
if ( fabs(plane[j]) < 0.00025 && fabs(plane[(j+1)%3]) < 0.00025 && ( plane[j] != 0.0 || plane[(j+1)%3] != 0.0 ) ){
VectorAdd( points[ 0 ], points[ 1 ], cnt );
VectorAdd( cnt, points[ 2 ], cnt );
VectorScale( cnt, 0.3333333333333f, cnt );
points[0][(j+2)%3]=points[1][(j+2)%3]=points[2][(j+2)%3]=cnt[(j+2)%3];
PlaneFromPoints( plane, points[ 0 ], points[ 1 ], points[ 2 ] );
if ( fabs( plane.normal()[j] ) < 0.00025 && fabs( plane.normal()[(j+1)%3] ) < 0.00025
&& ( plane.normal()[j] != 0.0 || plane.normal()[(j+1)%3] != 0.0 ) ){
cnt = ( points[0] + points[1] + points[2] ) / 3.0;
points[0][(j+2)%3] = points[1][(j+2)%3] = points[2][(j+2)%3] = cnt[(j+2)%3];
PlaneFromPoints( plane, points );
break;
}
}
@@ -668,25 +631,23 @@ void InsertModel( const char *name, int skin, int frame, m4x4_t transform, const
//snap single snappable normal components
for ( j=0; j<3; j++ )
{
if ( plane[j] != 0.0 && fabs(plane[j]) < 0.00005 ){
plane[j]=0.0;
if ( plane.normal()[j] != 0.0 && fabs( plane.normal()[j] ) < 0.00005 ){
plane.normal()[j]=0.0;
snpd = true;
}
}
//adjust plane dist
if ( snpd ) {
VectorAdd( points[ 0 ], points[ 1 ], cnt );
VectorAdd( cnt, points[ 2 ], cnt );
VectorScale( cnt, 0.3333333333333f, cnt );
VectorNormalize( plane, plane );
plane[3] = DotProduct( plane, cnt );
cnt = ( points[0] + points[1] + points[2] ) / 3.0;
VectorNormalize( plane.normal() );
plane.dist() = vector3_dot( plane.normal(), cnt );
//project points to resulting plane to keep intersections precision
for ( j=0; j<3; j++ )
{
//Sys_Printf( "b4 %i (%6.7f %6.7f %6.7f)\n", j, points[j][0], points[j][1], points[j][2] );
VectorMA( points[j], plane[3] - DotProduct( plane, points[j]), plane, points[j] );
points[j] = plane3_project_point( plane, points[j] );
//Sys_Printf( "sn %i (%6.7f %6.7f %6.7f)\n", j, points[j][0], points[j][1], points[j][2] );
}
//Sys_Printf( "sn pln (%6.7f %6.7f %6.7f %6.7f)\n", plane[0], plane[1], plane[2], plane[3] );
@@ -696,15 +657,15 @@ void InsertModel( const char *name, int skin, int frame, m4x4_t transform, const
/* sanity check */
{
vec3_t d1, d2, normaL;
VectorSubtract( points[1], points[0], d1 );
VectorSubtract( points[2], points[0], d2 );
CrossProduct( d2, d1, normaL );
const Vector3 d1 = points[1] - points[0];
const Vector3 d2 = points[2] - points[0];
const Vector3 normaL = vector3_cross( d2, d1 );
/* https://en.wikipedia.org/wiki/Cross_product#Geometric_meaning
cross( a, b ).length = a.length b.length sin( angle ) */
const double lengthsSquared = ( d1[0] * d1[0] + d1[1] * d1[1] + d1[2] * d1[2] ) * ( d2[0] * d2[0] + d2[1] * d2[1] + d2[2] * d2[2] );
if ( lengthsSquared == 0 || fabs( ( normaL[0] * normaL[0] + normaL[1] * normaL[1] + normaL[2] * normaL[2] ) / lengthsSquared ) < 1e-8 ) {
Sys_Warning( "triangle (%6.0f %6.0f %6.0f) (%6.0f %6.0f %6.0f) (%6.0f %6.0f %6.0f) of %s was not autoclipped: points on line\n", points[0][0], points[0][1], points[0][2], points[1][0], points[1][1], points[1][2], points[2][0], points[2][1], points[2][2], name );
const double lengthsSquared = vector3_length_squared( d1 ) * vector3_length_squared( d2 );
if ( lengthsSquared == 0 || fabs( vector3_length_squared( normaL ) / lengthsSquared ) < 1e-8 ) {
Sys_Warning( "triangle (%6.0f %6.0f %6.0f) (%6.0f %6.0f %6.0f) (%6.0f %6.0f %6.0f) of %s was not autoclipped: points on line\n",
points[0][0], points[0][1], points[0][2], points[1][0], points[1][1], points[1][2], points[2][0], points[2][1], points[2][2], name );
continue;
}
}
@@ -714,13 +675,13 @@ void InsertModel( const char *name, int skin, int frame, m4x4_t transform, const
for ( j=0; j<3; j++ )
{
if ( fabs(plane[j]) < 0.05 && fabs(plane[(j+1)%3]) < 0.05 ){ //no way, close to lay on two axises
if ( fabs( plane.normal()[j] ) < 0.05 && fabs( plane.normal()[(j+1)%3] ) < 0.05 ){ //no way, close to lay on two axes
goto default_CLIPMODEL;
}
}
// best axial normal
VectorCopy( plane, bestNormal );
bestNormal = plane.normal();
for ( j = 0; j < 3; j++ ){
if ( fabs(bestNormal[j]) > fabs(bestNormal[(j+1)%3]) ){
bestNormal[(j+1)%3] = 0.0;
@@ -730,7 +691,7 @@ void InsertModel( const char *name, int skin, int frame, m4x4_t transform, const
bestNormal[j] = 0.0;
}
}
VectorNormalize( bestNormal, bestNormal );
VectorNormalize( bestNormal );
float bestdist, currdist, bestangle, currangle, mindist = 999999;
@@ -738,13 +699,13 @@ void InsertModel( const char *name, int skin, int frame, m4x4_t transform, const
for ( j = 0; j < 3; j++ ){//planes
bestdist = 999999;
bestangle = 1;
for ( k = 0; k < 3; k++ ){//axises
VectorSubtract( points[ (j+1)%3 ], points[ j ], nrm );
for ( k = 0; k < 3; k++ ){//axes
nrm = points[(j+1)%3] - points[j];
if ( k == axis ){
CrossProduct( bestNormal, nrm, reverse );
reverse.normal() = vector3_cross( bestNormal, nrm );
}
else{
VectorClear( Vnorm[0] );
Vnorm[0].set( 0 );
if ( (k+1)%3 == axis ){
if ( nrm[ (k+2)%3 ] == 0 ) continue;
Vnorm[0][ (k+2)%3 ] = nrm[ (k+2)%3 ];
@@ -753,20 +714,19 @@ void InsertModel( const char *name, int skin, int frame, m4x4_t transform, const
if ( nrm[ (k+1)%3 ] == 0 ) continue;
Vnorm[0][ (k+1)%3 ] = nrm[ (k+1)%3 ];
}
CrossProduct( bestNormal, Vnorm[0], Enorm[0] );
CrossProduct( Enorm[0], nrm, reverse );
Enorm[0] = vector3_cross( bestNormal, Vnorm[0] );
reverse.normal() = vector3_cross( Enorm[0], nrm );
}
VectorNormalize( reverse, reverse );
reverse[3] = DotProduct( points[ j ], reverse );
VectorNormalize( reverse.normal() );
reverse.dist() = vector3_dot( points[ j ], reverse.normal() );
//check facing, thickness
currdist = reverse[3] - DotProduct( reverse, points[ (j+2)%3 ] );
currangle = DotProduct( reverse, plane );
currdist = reverse.dist() - vector3_dot( reverse.normal(), points[ (j+2)%3 ] );
currangle = vector3_dot( reverse.normal(), plane.normal() );
if ( ( ( currdist > 0.1 ) && ( currdist < bestdist ) && ( currangle < 0 ) ) ||
( ( currangle >= 0 ) && ( currangle <= bestangle ) ) ){
bestangle = currangle;
if ( currangle < 0 ) bestdist = currdist;
VectorCopy( reverse, p[j] );
p[j][3] = reverse[3];
p[j] = reverse;
}
}
//if ( bestdist == 999999 && bestangle == 1 ) Sys_Printf("default_CLIPMODEL\n");
@@ -800,12 +760,12 @@ void InsertModel( const char *name, int skin, int frame, m4x4_t transform, const
buildBrush->sides[ j ].shaderInfo = NULL; // don't emit these faces as draw surfaces, should make smaller BSPs; hope this works
}
}
VectorCopy( points[0], points[3] ); // for cyclic usage
points[3] = points[0]; // for cyclic usage
buildBrush->sides[ 0 ].planenum = FindFloatPlane( plane, plane[ 3 ], 3, points );
buildBrush->sides[ 1 ].planenum = FindFloatPlane( p[0], p[0][ 3 ], 2, &points[ 0 ] ); // p[0] contains points[0] and points[1]
buildBrush->sides[ 2 ].planenum = FindFloatPlane( p[1], p[1][ 3 ], 2, &points[ 1 ] ); // p[1] contains points[1] and points[2]
buildBrush->sides[ 3 ].planenum = FindFloatPlane( p[2], p[2][ 3 ], 2, &points[ 2 ] ); // p[2] contains points[2] and points[0] (copied to points[3]
buildBrush->sides[ 0 ].planenum = FindFloatPlane( plane, 3, points );
buildBrush->sides[ 1 ].planenum = FindFloatPlane( p[0], 2, &points[ 0 ] ); // p[0] contains points[0] and points[1]
buildBrush->sides[ 2 ].planenum = FindFloatPlane( p[1], 2, &points[ 1 ] ); // p[1] contains points[1] and points[2]
buildBrush->sides[ 3 ].planenum = FindFloatPlane( p[2], 2, &points[ 2 ] ); // p[2] contains points[2] and points[0] (copied to points[3]
}
@@ -824,22 +784,21 @@ void InsertModel( const char *name, int skin, int frame, m4x4_t transform, const
( spf == 5120 ) ){ //EXTRUDE_UPWARDS+AXIAL_BACKPLANE
if ( spawnFlags & 16 ){ //autodirection
VectorCopy( avgDirection, bestNormal );
bestNormal = avgDirection;
}
else{
axis = 2;
if ( ( spawnFlags & 1536 ) == 1536 ){ //up+down
VectorSet( bestNormal, 0, 0, ( plane[2] >= 0 ? 1 : -1 ) );
bestNormal = plane.normal()[2] >= 0? g_vector3_axis_z : -g_vector3_axis_z;
}
else if ( spawnFlags & 512 ){ //down
VectorSet( bestNormal, 0, 0, 1 );
bestNormal = g_vector3_axis_z;
}
else if ( spawnFlags & 1024 ){ //up
VectorSet( bestNormal, 0, 0, -1 );
bestNormal = -g_vector3_axis_z;
}
else{ // best axial normal
VectorCopy( plane, bestNormal );
bestNormal = plane.normal();
for ( j = 0; j < 3; j++ ){
if ( fabs(bestNormal[j]) > fabs(bestNormal[(j+1)%3]) ){
bestNormal[(j+1)%3] = 0.0;
@@ -849,11 +808,11 @@ void InsertModel( const char *name, int skin, int frame, m4x4_t transform, const
bestNormal[j] = 0.0;
}
}
VectorNormalize( bestNormal, bestNormal );
VectorNormalize( bestNormal );
}
}
if ( DotProduct( plane, bestNormal ) < 0.05 ){
if ( vector3_dot( plane.normal(), bestNormal ) < 0.05 ){
goto default_CLIPMODEL;
}
@@ -861,69 +820,65 @@ void InsertModel( const char *name, int skin, int frame, m4x4_t transform, const
/* make side planes */
for ( j = 0; j < 3; j++ )
{
VectorSubtract( points[(j+1)%3], points[ j ], nrm );
CrossProduct( bestNormal, nrm, p[ j ] );
VectorNormalize( p[ j ], p[ j ] );
p[j][3] = DotProduct( points[j], p[j] );
p[j].normal() = VectorNormalized( vector3_cross( bestNormal, points[(j+1)%3] - points[j] ) );
p[j].dist() = vector3_dot( points[j], p[j].normal() );
}
/* make back plane */
if ( spawnFlags & 2048 ){ //max extrude
VectorScale( bestNormal, -1.0f, reverse );
reverse.normal() = -bestNormal;
if ( bestNormal[axis] > 0 ){
reverse[3] = -min[axis] + clipDepth;
reverse.dist() = -minmax.mins[axis] + clipDepth;
}
else{
reverse[3] = max[axis] + clipDepth;
reverse.dist() = minmax.maxs[axis] + clipDepth;
}
}
else if ( spawnFlags & 4096 ){ //axial backplane
VectorScale( bestNormal, -1.0f, reverse );
reverse[3] = points[0][axis];
reverse.normal() = -bestNormal;
reverse.dist() = points[0][axis];
if ( bestNormal[axis] > 0 ){
for ( j = 1; j < 3; j++ ){
if ( points[j][axis] < reverse[3] ){
reverse[3] = points[j][axis];
if ( points[j][axis] < reverse.dist() ){
reverse.dist() = points[j][axis];
}
}
reverse[3] = -reverse[3] + clipDepth;
reverse.dist() = -reverse.dist() + clipDepth;
}
else{
for ( j = 1; j < 3; j++ ){
if ( points[j][axis] > reverse[3] ){
reverse[3] = points[j][axis];
if ( points[j][axis] > reverse.dist() ){
reverse.dist() = points[j][axis];
}
}
reverse[3] += clipDepth;
reverse.dist() += clipDepth;
}
if (limDepth != 0.0){
VectorCopy( points[0], cnt );
if ( limDepth != 0.0 ){
cnt = points[0];
if ( bestNormal[axis] > 0 ){
for ( j = 1; j < 3; j++ ){
if ( points[j][axis] > cnt[axis] ){
VectorCopy( points[j], cnt );
cnt = points[j];
}
}
}
else {
for ( j = 1; j < 3; j++ ){
if ( points[j][axis] < cnt[axis] ){
VectorCopy( points[j], cnt );
cnt = points[j];
}
}
}
VectorMA( cnt, reverse[3] - DotProduct( reverse, cnt ), reverse, cnt );
if ( ( plane[3] - DotProduct( plane, cnt ) ) > limDepth ){
VectorScale( plane, -1.0f, reverse );
reverse[ 3 ] = -plane[ 3 ];
reverse[3] += clipDepth;
cnt = plane3_project_point( reverse, cnt );
if ( -plane3_distance_to_point( plane, cnt ) > limDepth ){
reverse = plane3_flipped( plane );
reverse.dist() += clipDepth;
}
}
}
else{ //normal backplane
VectorScale( plane, -1.0f, reverse );
reverse[ 3 ] = -plane[ 3 ];
reverse[3] += clipDepth;
reverse = plane3_flipped( plane );
reverse.dist() += clipDepth;
}
#if nonax_clip_dbg
for ( j = 0; j < 3; j++ )
@@ -949,13 +904,13 @@ void InsertModel( const char *name, int skin, int frame, m4x4_t transform, const
buildBrush->sides[ j ].shaderInfo = NULL; // don't emit these faces as draw surfaces, should make smaller BSPs; hope this works
}
}
VectorCopy( points[0], points[3] ); // for cyclic usage
points[3] = points[0]; // for cyclic usage
buildBrush->sides[ 0 ].planenum = FindFloatPlane( plane, plane[ 3 ], 3, points );
buildBrush->sides[ 1 ].planenum = FindFloatPlane( p[0], p[0][ 3 ], 2, &points[ 0 ] ); // p[0] contains points[0] and points[1]
buildBrush->sides[ 2 ].planenum = FindFloatPlane( p[1], p[1][ 3 ], 2, &points[ 1 ] ); // p[1] contains points[1] and points[2]
buildBrush->sides[ 3 ].planenum = FindFloatPlane( p[2], p[2][ 3 ], 2, &points[ 2 ] ); // p[2] contains points[2] and points[0] (copied to points[3]
buildBrush->sides[ 4 ].planenum = FindFloatPlane( reverse, reverse[ 3 ], 0, NULL );
buildBrush->sides[ 0 ].planenum = FindFloatPlane( plane, 3, points );
buildBrush->sides[ 1 ].planenum = FindFloatPlane( p[0], 2, &points[ 0 ] ); // p[0] contains points[0] and points[1]
buildBrush->sides[ 2 ].planenum = FindFloatPlane( p[1], 2, &points[ 1 ] ); // p[1] contains points[1] and points[2]
buildBrush->sides[ 3 ].planenum = FindFloatPlane( p[2], 2, &points[ 2 ] ); // p[2] contains points[2] and points[0] (copied to points[3]
buildBrush->sides[ 4 ].planenum = FindFloatPlane( reverse, 0, NULL );
}
@@ -964,36 +919,31 @@ void InsertModel( const char *name, int skin, int frame, m4x4_t transform, const
//45 degrees normals for side planes
for ( j = 0; j < 3; j++ )
{
VectorSubtract( points[(j+1)%3], points[ j ], nrm );
CrossProduct( plane, nrm, Enorm[ j ] );
VectorNormalize( Enorm[ j ], Enorm[ j ] );
VectorAdd( plane, Enorm[ j ], Enorm[ j ] );
VectorNormalize( Enorm[ j ], Enorm[ j ] );
nrm = points[(j+1)%3] - points[ j ];
Enorm[ j ] = VectorNormalized( vector3_cross( plane.normal(), nrm ) );
Enorm[ j ] += plane.normal();
VectorNormalize( Enorm[ j ] );
/* make side planes */
CrossProduct( Enorm[ j ], nrm, p[ j ] );
VectorNormalize( p[ j ], p[ j ] );
p[j][3] = DotProduct( points[j], p[j] );
p[j].normal() = VectorNormalized( vector3_cross( Enorm[ j ], nrm ) );
p[j].dist() = vector3_dot( points[j], p[j].normal() );
//snap nearly axial side planes
snpd = false;
for ( k = 0; k < 3; k++ )
{
if ( fabs(p[j][k]) < 0.00025 && p[j][k] != 0.0 ){
p[j][k] = 0.0;
if ( fabs( p[j].normal()[k] ) < 0.00025 && p[j].normal()[k] != 0.0 ){
p[j].normal()[k] = 0.0;
snpd = true;
}
}
if ( snpd ){
VectorNormalize( p[j], p[j] );
VectorAdd( points[j], points[(j+1)%3], cnt );
VectorScale( cnt, 0.5f, cnt );
p[j][3] = DotProduct( cnt, p[j] );
VectorNormalize( p[j].normal() );
p[j].dist() = vector3_dot( ( points[j] + points[(j+1)%3] ) / 2.0, p[j].normal() );
}
}
/* make back plane */
VectorScale( plane, -1.0f, reverse );
reverse[ 3 ] = -plane[ 3 ];
reverse[3] += clipDepth;
reverse = plane3_flipped( plane );
reverse.dist() += clipDepth;
/* set up brush sides */
buildBrush->numsides = 5;
@@ -1008,13 +958,13 @@ void InsertModel( const char *name, int skin, int frame, m4x4_t transform, const
buildBrush->sides[ j ].shaderInfo = NULL; // don't emit these faces as draw surfaces, should make smaller BSPs; hope this works
}
}
VectorCopy( points[0], points[3] ); // for cyclic usage
points[3] = points[0]; // for cyclic usage
buildBrush->sides[ 0 ].planenum = FindFloatPlane( plane, plane[ 3 ], 3, points );
buildBrush->sides[ 1 ].planenum = FindFloatPlane( p[0], p[0][ 3 ], 2, &points[ 0 ] ); // p[0] contains points[0] and points[1]
buildBrush->sides[ 2 ].planenum = FindFloatPlane( p[1], p[1][ 3 ], 2, &points[ 1 ] ); // p[1] contains points[1] and points[2]
buildBrush->sides[ 3 ].planenum = FindFloatPlane( p[2], p[2][ 3 ], 2, &points[ 2 ] ); // p[2] contains points[2] and points[0] (copied to points[3]
buildBrush->sides[ 4 ].planenum = FindFloatPlane( reverse, reverse[ 3 ], 0, NULL );
buildBrush->sides[ 0 ].planenum = FindFloatPlane( plane, 3, points );
buildBrush->sides[ 1 ].planenum = FindFloatPlane( p[0], 2, &points[ 0 ] ); // p[0] contains points[0] and points[1]
buildBrush->sides[ 2 ].planenum = FindFloatPlane( p[1], 2, &points[ 1 ] ); // p[1] contains points[1] and points[2]
buildBrush->sides[ 3 ].planenum = FindFloatPlane( p[2], 2, &points[ 2 ] ); // p[2] contains points[2] and points[0] (copied to points[3]
buildBrush->sides[ 4 ].planenum = FindFloatPlane( reverse, 0, NULL );
}
@@ -1026,21 +976,18 @@ void InsertModel( const char *name, int skin, int frame, m4x4_t transform, const
/* get vertex */
dv = &ds->verts[ ds->indexes[ i + j ] ];
/* copy normal */
VectorCopy( dv->normal, Vnorm[ j ] );
Vnorm[ j ] = dv->normal;
}
//avg normals for side planes
for ( j = 0; j < 3; j++ )
{
VectorAdd( Vnorm[ j ], Vnorm[ (j+1)%3 ], Enorm[ j ] );
VectorNormalize( Enorm[ j ], Enorm[ j ] );
Enorm[ j ] = VectorNormalized( Vnorm[ j ] + Vnorm[ (j+1)%3 ] );
//check fuer bad ones
VectorSubtract( points[(j+1)%3], points[ j ], cnt );
CrossProduct( plane, cnt, nrm );
VectorNormalize( nrm, nrm );
nrm = VectorNormalized( vector3_cross( plane.normal(), points[(j+1)%3] - points[ j ] ) );
//check for negative or outside direction
if ( DotProduct( Enorm[ j ], plane ) > 0.1 ){
if ( ( DotProduct( Enorm[ j ], nrm ) > -0.2 ) || ( spawnFlags & 256 ) ){
if ( vector3_dot( Enorm[ j ], plane.normal() ) > 0.1 ){
if ( ( vector3_dot( Enorm[ j ], nrm ) > -0.2 ) || ( spawnFlags & 256 ) ){
//ok++;
continue;
}
@@ -1048,41 +995,36 @@ void InsertModel( const char *name, int skin, int frame, m4x4_t transform, const
//notok++;
//Sys_Printf( "faulty Enormal %i/%i\n", notok, ok );
//use 45 normal
VectorAdd( plane, nrm, Enorm[ j ] );
VectorNormalize( Enorm[ j ], Enorm[ j ] );
Enorm[ j ] = plane.normal() + nrm;
VectorNormalize( Enorm[ j ] );
}
/* make side planes */
for ( j = 0; j < 3; j++ )
{
VectorSubtract( points[(j+1)%3], points[ j ], nrm );
CrossProduct( Enorm[ j ], nrm, p[ j ] );
VectorNormalize( p[ j ], p[ j ] );
p[j][3] = DotProduct( points[j], p[j] );
p[j].normal() = VectorNormalized( vector3_cross( Enorm[ j ], points[(j+1)%3] - points[j] ) );
p[j].dist() = vector3_dot( points[j], p[j].normal() );
//snap nearly axial side planes
snpd = false;
for ( k = 0; k < 3; k++ )
{
if ( fabs(p[j][k]) < 0.00025 && p[j][k] != 0.0 ){
if ( fabs( p[j].normal()[k] ) < 0.00025 && p[j].normal()[k] != 0.0 ){
//Sys_Printf( "init plane %6.8f %6.8f %6.8f %6.8f\n", p[j][0], p[j][1], p[j][2], p[j][3]);
p[j][k] = 0.0;
p[j].normal()[k] = 0.0;
snpd = true;
}
}
if ( snpd ){
VectorNormalize( p[j], p[j] );
VectorNormalize( p[j].normal() );
//Sys_Printf( "nrm plane %6.8f %6.8f %6.8f %6.8f\n", p[j][0], p[j][1], p[j][2], p[j][3]);
VectorAdd( points[j], points[(j+1)%3], cnt );
VectorScale( cnt, 0.5f, cnt );
p[j][3] = DotProduct( cnt, p[j] );
p[j].dist() = vector3_dot( ( points[j] + points[(j+1)%3] ) / 2.0, p[j].normal() );
//Sys_Printf( "dst plane %6.8f %6.8f %6.8f %6.8f\n", p[j][0], p[j][1], p[j][2], p[j][3]);
}
}
/* make back plane */
VectorScale( plane, -1.0f, reverse );
reverse[ 3 ] = -plane[ 3 ];
reverse[3] += clipDepth;
reverse = plane3_flipped( plane );
reverse.dist() += clipDepth;
/* set up brush sides */
buildBrush->numsides = 5;
@@ -1097,13 +1039,13 @@ void InsertModel( const char *name, int skin, int frame, m4x4_t transform, const
buildBrush->sides[ j ].shaderInfo = NULL; // don't emit these faces as draw surfaces, should make smaller BSPs; hope this works
}
}
VectorCopy( points[0], points[3] ); // for cyclic usage
points[3] = points[0]; // for cyclic usage
buildBrush->sides[ 0 ].planenum = FindFloatPlane( plane, plane[ 3 ], 3, points );
buildBrush->sides[ 1 ].planenum = FindFloatPlane( p[0], p[0][ 3 ], 2, &points[ 0 ] ); // p[0] contains points[0] and points[1]
buildBrush->sides[ 2 ].planenum = FindFloatPlane( p[1], p[1][ 3 ], 2, &points[ 1 ] ); // p[1] contains points[1] and points[2]
buildBrush->sides[ 3 ].planenum = FindFloatPlane( p[2], p[2][ 3 ], 2, &points[ 2 ] ); // p[2] contains points[2] and points[0] (copied to points[3]
buildBrush->sides[ 4 ].planenum = FindFloatPlane( reverse, reverse[ 3 ], 0, NULL );
buildBrush->sides[ 0 ].planenum = FindFloatPlane( plane, 3, points );
buildBrush->sides[ 1 ].planenum = FindFloatPlane( p[0], 2, &points[ 0 ] ); // p[0] contains points[0] and points[1]
buildBrush->sides[ 2 ].planenum = FindFloatPlane( p[1], 2, &points[ 1 ] ); // p[1] contains points[1] and points[2]
buildBrush->sides[ 3 ].planenum = FindFloatPlane( p[2], 2, &points[ 2 ] ); // p[2] contains points[2] and points[0] (copied to points[3]
buildBrush->sides[ 4 ].planenum = FindFloatPlane( reverse, 0, NULL );
}
@@ -1112,34 +1054,30 @@ void InsertModel( const char *name, int skin, int frame, m4x4_t transform, const
/* make side planes */
for ( j = 0; j < 3; j++ )
{
VectorSubtract( points[(j+1)%3], points[ j ], nrm );
CrossProduct( plane, nrm, p[ j ] );
VectorNormalize( p[ j ], p[ j ] );
p[j][3] = DotProduct( points[j], p[j] );
p[j].normal() = VectorNormalized( vector3_cross( plane.normal(), points[(j+1)%3] - points[j] ) );
p[j].dist() = vector3_dot( points[j], p[j].normal() );
//snap nearly axial side planes
snpd = false;
for ( k = 0; k < 3; k++ )
{
if ( fabs(p[j][k]) < 0.00025 && p[j][k] != 0.0 ){
if ( fabs( p[j].normal()[k] ) < 0.00025 && p[j].normal()[k] != 0.0 ){
//Sys_Printf( "init plane %6.8f %6.8f %6.8f %6.8f\n", p[j][0], p[j][1], p[j][2], p[j][3]);
p[j][k] = 0.0;
p[j].normal()[k] = 0.0;
snpd = true;
}
}
if ( snpd ){
VectorNormalize( p[j], p[j] );
VectorNormalize( p[j].normal() );
//Sys_Printf( "nrm plane %6.8f %6.8f %6.8f %6.8f\n", p[j][0], p[j][1], p[j][2], p[j][3]);
VectorAdd( points[j], points[(j+1)%3], cnt );
VectorScale( cnt, 0.5f, cnt );
p[j][3] = DotProduct( cnt, p[j] );
cnt = ( points[j] + points[(j+1)%3] ) / 2.0;
p[j].dist() = vector3_dot( cnt, p[j].normal() );
//Sys_Printf( "dst plane %6.8f %6.8f %6.8f %6.8f\n", p[j][0], p[j][1], p[j][2], p[j][3]);
}
}
/* make back plane */
VectorScale( plane, -1.0f, reverse );
reverse[ 3 ] = -plane[ 3 ];
reverse[3] += clipDepth;
reverse = plane3_flipped( plane );
reverse.dist() += clipDepth;
#if nonax_clip_dbg
for ( j = 0; j < 3; j++ )
{
@@ -1165,25 +1103,23 @@ void InsertModel( const char *name, int skin, int frame, m4x4_t transform, const
buildBrush->sides[ j ].shaderInfo = NULL; // don't emit these faces as draw surfaces, should make smaller BSPs; hope this works
}
}
VectorCopy( points[0], points[3] ); // for cyclic usage
points[3] = points[0]; // for cyclic usage
buildBrush->sides[ 0 ].planenum = FindFloatPlane( plane, plane[ 3 ], 3, points );
buildBrush->sides[ 1 ].planenum = FindFloatPlane( p[0], p[0][ 3 ], 2, &points[ 0 ] ); // p[0] contains points[0] and points[1]
buildBrush->sides[ 2 ].planenum = FindFloatPlane( p[1], p[1][ 3 ], 2, &points[ 1 ] ); // p[1] contains points[1] and points[2]
buildBrush->sides[ 3 ].planenum = FindFloatPlane( p[2], p[2][ 3 ], 2, &points[ 2 ] ); // p[2] contains points[2] and points[0] (copied to points[3]
buildBrush->sides[ 4 ].planenum = FindFloatPlane( reverse, reverse[ 3 ], 0, NULL );
buildBrush->sides[ 0 ].planenum = FindFloatPlane( plane, 3, points );
buildBrush->sides[ 1 ].planenum = FindFloatPlane( p[0], 2, &points[ 0 ] ); // p[0] contains points[0] and points[1]
buildBrush->sides[ 2 ].planenum = FindFloatPlane( p[1], 2, &points[ 1 ] ); // p[1] contains points[1] and points[2]
buildBrush->sides[ 3 ].planenum = FindFloatPlane( p[2], 2, &points[ 2 ] ); // p[2] contains points[2] and points[0] (copied to points[3]
buildBrush->sides[ 4 ].planenum = FindFloatPlane( reverse, 0, NULL );
}
else if ( spf == 256 ){ //PYRAMIDAL_CLIP
/* calculate center */
VectorAdd( points[ 0 ], points[ 1 ], cnt );
VectorAdd( cnt, points[ 2 ], cnt );
VectorScale( cnt, 0.3333333333333f, cnt );
cnt = ( points[0] + points[1] + points[2] ) / 3.0;
/* make back pyramid point */
VectorMA( cnt, -clipDepth, plane, cnt );
cnt -= plane.normal() * clipDepth;
/* make 3 more planes */
if( PlaneFromPoints( p[0], points[ 2 ], points[ 1 ], cnt ) &&
@@ -1191,16 +1127,16 @@ void InsertModel( const char *name, int skin, int frame, m4x4_t transform, const
PlaneFromPoints( p[2], points[ 0 ], points[ 2 ], cnt ) ) {
//check for dangerous planes
while( (( p[0][0] != 0.0 || p[0][1] != 0.0 ) && fabs(p[0][0]) < 0.00025 && fabs(p[0][1]) < 0.00025) ||
(( p[0][0] != 0.0 || p[0][2] != 0.0 ) && fabs(p[0][0]) < 0.00025 && fabs(p[0][2]) < 0.00025) ||
(( p[0][2] != 0.0 || p[0][1] != 0.0 ) && fabs(p[0][2]) < 0.00025 && fabs(p[0][1]) < 0.00025) ||
(( p[1][0] != 0.0 || p[1][1] != 0.0 ) && fabs(p[1][0]) < 0.00025 && fabs(p[1][1]) < 0.00025) ||
(( p[1][0] != 0.0 || p[1][2] != 0.0 ) && fabs(p[1][0]) < 0.00025 && fabs(p[1][2]) < 0.00025) ||
(( p[1][2] != 0.0 || p[1][1] != 0.0 ) && fabs(p[1][2]) < 0.00025 && fabs(p[1][1]) < 0.00025) ||
(( p[2][0] != 0.0 || p[2][1] != 0.0 ) && fabs(p[2][0]) < 0.00025 && fabs(p[2][1]) < 0.00025) ||
(( p[2][0] != 0.0 || p[2][2] != 0.0 ) && fabs(p[2][0]) < 0.00025 && fabs(p[2][2]) < 0.00025) ||
(( p[2][2] != 0.0 || p[2][1] != 0.0 ) && fabs(p[2][2]) < 0.00025 && fabs(p[2][1]) < 0.00025) ) {
VectorMA( cnt, -0.1f, plane, cnt );
while( (( p[0].a != 0.0 || p[0].b != 0.0 ) && fabs( p[0].a ) < 0.00025 && fabs( p[0].b ) < 0.00025) ||
(( p[0].a != 0.0 || p[0].c != 0.0 ) && fabs( p[0].a ) < 0.00025 && fabs( p[0].c ) < 0.00025) ||
(( p[0].c != 0.0 || p[0].b != 0.0 ) && fabs( p[0].c ) < 0.00025 && fabs( p[0].b ) < 0.00025) ||
(( p[1].a != 0.0 || p[1].b != 0.0 ) && fabs( p[1].a ) < 0.00025 && fabs( p[1].b ) < 0.00025) ||
(( p[1].a != 0.0 || p[1].c != 0.0 ) && fabs( p[1].a ) < 0.00025 && fabs( p[1].c ) < 0.00025) ||
(( p[1].c != 0.0 || p[1].b != 0.0 ) && fabs( p[1].c ) < 0.00025 && fabs( p[1].b ) < 0.00025) ||
(( p[2].a != 0.0 || p[2].b != 0.0 ) && fabs( p[2].a ) < 0.00025 && fabs( p[2].b ) < 0.00025) ||
(( p[2].a != 0.0 || p[2].c != 0.0 ) && fabs( p[2].a ) < 0.00025 && fabs( p[2].c ) < 0.00025) ||
(( p[2].c != 0.0 || p[2].b != 0.0 ) && fabs( p[2].c ) < 0.00025 && fabs( p[2].b ) < 0.00025) ) {
cnt -= plane.normal() * 0.1f;
// Sys_Printf( "shifting pyramid point\n" );
PlaneFromPoints( p[0], points[ 2 ], points[ 1 ], cnt );
PlaneFromPoints( p[1], points[ 1 ], points[ 0 ], cnt );
@@ -1230,16 +1166,17 @@ void InsertModel( const char *name, int skin, int frame, m4x4_t transform, const
buildBrush->sides[ j ].shaderInfo = NULL; // don't emit these faces as draw surfaces, should make smaller BSPs; hope this works
}
}
VectorCopy( points[0], points[3] ); // for cyclic usage
points[3] = points[0]; // for cyclic usage
buildBrush->sides[ 0 ].planenum = FindFloatPlane( plane, plane[ 3 ], 3, points );
buildBrush->sides[ 1 ].planenum = FindFloatPlane( p[0], p[0][ 3 ], 2, &points[ 1 ] ); // p[0] contains points[1] and points[2]
buildBrush->sides[ 2 ].planenum = FindFloatPlane( p[1], p[1][ 3 ], 2, &points[ 0 ] ); // p[1] contains points[0] and points[1]
buildBrush->sides[ 3 ].planenum = FindFloatPlane( p[2], p[2][ 3 ], 2, &points[ 2 ] ); // p[2] contains points[2] and points[0] (copied to points[3]
buildBrush->sides[ 0 ].planenum = FindFloatPlane( plane, 3, points );
buildBrush->sides[ 1 ].planenum = FindFloatPlane( p[0], 2, &points[ 1 ] ); // p[0] contains points[1] and points[2]
buildBrush->sides[ 2 ].planenum = FindFloatPlane( p[1], 2, &points[ 0 ] ); // p[1] contains points[0] and points[1]
buildBrush->sides[ 3 ].planenum = FindFloatPlane( p[2], 2, &points[ 2 ] ); // p[2] contains points[2] and points[0] (copied to points[3]
}
else
{
Sys_Warning( "triangle (%6.0f %6.0f %6.0f) (%6.0f %6.0f %6.0f) (%6.0f %6.0f %6.0f) of %s was not autoclipped\n", points[0][0], points[0][1], points[0][2], points[1][0], points[1][1], points[1][2], points[2][0], points[2][1], points[2][2], name );
Sys_Warning( "triangle (%6.0f %6.0f %6.0f) (%6.0f %6.0f %6.0f) (%6.0f %6.0f %6.0f) of %s was not autoclipped\n",
points[0][0], points[0][1], points[0][2], points[1][0], points[1][1], points[1][2], points[2][0], points[2][1], points[2][2], name );
free( buildBrush );
continue;
}
@@ -1250,7 +1187,7 @@ void InsertModel( const char *name, int skin, int frame, m4x4_t transform, const
default_CLIPMODEL:
// axial normal
VectorCopy( plane, bestNormal );
bestNormal = plane.normal();
for ( j = 0; j < 3; j++ ){
if ( fabs(bestNormal[j]) > fabs(bestNormal[(j+1)%3]) ){
bestNormal[(j+1)%3] = 0.0;
@@ -1259,21 +1196,18 @@ void InsertModel( const char *name, int skin, int frame, m4x4_t transform, const
bestNormal[j] = 0.0;
}
}
VectorNormalize( bestNormal, bestNormal );
VectorNormalize( bestNormal );
/* make side planes */
for ( j = 0; j < 3; j++ )
{
VectorSubtract( points[(j+1)%3], points[ j ], nrm );
CrossProduct( bestNormal, nrm, p[ j ] );
VectorNormalize( p[ j ], p[ j ] );
p[j][3] = DotProduct( points[j], p[j] );
p[j].normal() = VectorNormalized( vector3_cross( bestNormal, points[(j+1)%3] - points[j] ) );
p[j].dist() = vector3_dot( points[j], p[j].normal() );
}
/* make back plane */
VectorScale( plane, -1.0f, reverse );
reverse[ 3 ] = -plane[ 3 ];
reverse[3] += DotProduct( bestNormal, plane ) * clipDepth;
reverse = plane3_flipped( plane );
reverse.dist() += vector3_dot( bestNormal, plane.normal() ) * clipDepth;
#if nonax_clip_dbg
for ( j = 0; j < 3; j++ )
{
@@ -1298,13 +1232,13 @@ void InsertModel( const char *name, int skin, int frame, m4x4_t transform, const
buildBrush->sides[ j ].shaderInfo = NULL; // don't emit these faces as draw surfaces, should make smaller BSPs; hope this works
}
}
VectorCopy( points[0], points[3] ); // for cyclic usage
points[3] = points[0]; // for cyclic usage
buildBrush->sides[ 0 ].planenum = FindFloatPlane( plane, plane[ 3 ], 3, points );
buildBrush->sides[ 1 ].planenum = FindFloatPlane( p[0], p[0][ 3 ], 2, &points[ 0 ] ); // p[0] contains points[0] and points[1]
buildBrush->sides[ 2 ].planenum = FindFloatPlane( p[1], p[1][ 3 ], 2, &points[ 1 ] ); // p[1] contains points[1] and points[2]
buildBrush->sides[ 3 ].planenum = FindFloatPlane( p[2], p[2][ 3 ], 2, &points[ 2 ] ); // p[2] contains points[2] and points[0] (copied to points[3]
buildBrush->sides[ 4 ].planenum = FindFloatPlane( reverse, reverse[ 3 ], 0, NULL );
buildBrush->sides[ 0 ].planenum = FindFloatPlane( plane, 3, points );
buildBrush->sides[ 1 ].planenum = FindFloatPlane( p[0], 2, &points[ 0 ] ); // p[0] contains points[0] and points[1]
buildBrush->sides[ 2 ].planenum = FindFloatPlane( p[1], 2, &points[ 1 ] ); // p[1] contains points[1] and points[2]
buildBrush->sides[ 3 ].planenum = FindFloatPlane( p[2], 2, &points[ 2 ] ); // p[2] contains points[2] and points[0] (copied to points[3]
buildBrush->sides[ 4 ].planenum = FindFloatPlane( reverse, 0, NULL );
}
@@ -1317,7 +1251,8 @@ void InsertModel( const char *name, int skin, int frame, m4x4_t transform, const
entities[ mapEntityNum ].numBrushes++;
}
else{
Sys_Warning( "triangle (%6.0f %6.0f %6.0f) (%6.0f %6.0f %6.0f) (%6.0f %6.0f %6.0f) of %s was not autoclipped\n", points[0][0], points[0][1], points[0][2], points[1][0], points[1][1], points[1][2], points[2][0], points[2][1], points[2][2], name );
Sys_Warning( "triangle (%6.0f %6.0f %6.0f) (%6.0f %6.0f %6.0f) (%6.0f %6.0f %6.0f) of %s was not autoclipped\n",
points[0][0], points[0][1], points[0][2], points[1][0], points[1][1], points[1][2], points[2][0], points[2][1], points[2][2], name );
free( buildBrush );
}
}
@@ -1395,27 +1330,26 @@ void AddTriangleModels( entity_t *eparent ){
const int spawnFlags = e->intForKey( "spawnflags" );
/* get origin */
vec3_t origin;
Vector3 origin;
e->vectorForKey( "origin", origin );
VectorSubtract( origin, eparent->origin, origin ); /* offset by parent */
origin -= eparent->origin; /* offset by parent */
/* get scale */
vec3_t scale = { 1.f, 1.f, 1.f };
Vector3 scale( 1, 1, 1 );
if( !e->read_keyvalue( scale, "modelscale_vec" ) )
if( e->read_keyvalue( scale[0], "modelscale" ) )
scale[1] = scale[2] = scale[0];
/* get "angle" (yaw) or "angles" (pitch yaw roll), store as (roll pitch yaw) */
const char *value;
vec3_t angles = { 0.f, 0.f, 0.f };
Vector3 angles( 0, 0, 0 );
if ( !e->read_keyvalue( value, "angles" ) ||
3 != sscanf( value, "%f %f %f", &angles[ 1 ], &angles[ 2 ], &angles[ 0 ] ) )
e->read_keyvalue( angles[ 2 ], "angle" );
/* set transform matrix (thanks spog) */
m4x4_t transform;
m4x4_identity( transform );
m4x4_pivoted_transform_by_vec3( transform, origin, angles, eXYZ, scale, vec3_origin );
Matrix4 transform( g_matrix4_identity );
matrix4_transform_by_euler_xyz_degrees( transform, origin, angles, scale );
/* get shader remappings */
std::list<remap_t> remaps;
+59 -79
View File
@@ -40,51 +40,49 @@
#define APPROX_SUBDIVISION 8
static void ExpandLongestCurve( float *longestCurve, vec3_t a, vec3_t b, vec3_t c ){
static void ExpandLongestCurve( float *longestCurve, const Vector3& a, const Vector3& b, const Vector3& c ){
int i;
float t, len;
vec3_t ab, bc, ac, pt, last, delta;
Vector3 ab, bc, ac, pt, last, delta;
/* calc vectors */
VectorSubtract( b, a, ab );
if ( VectorNormalize( ab, ab ) < 0.125f ) {
ab = b - a;
if ( VectorNormalize( ab ) < 0.125f ) {
return;
}
VectorSubtract( c, b, bc );
if ( VectorNormalize( bc, bc ) < 0.125f ) {
bc = c - b;
if ( VectorNormalize( bc ) < 0.125f ) {
return;
}
VectorSubtract( c, a, ac );
if ( VectorNormalize( ac, ac ) < 0.125f ) {
ac = c - a;
if ( VectorNormalize( ac ) < 0.125f ) {
return;
}
/* if all 3 vectors are the same direction, then this edge is linear, so we ignore it */
if ( DotProduct( ab, bc ) > 0.99f && DotProduct( ab, ac ) > 0.99f ) {
if ( vector3_dot( ab, bc ) > 0.99f && vector3_dot( ab, ac ) > 0.99f ) {
return;
}
/* recalculate vectors */
VectorSubtract( b, a, ab );
VectorSubtract( c, b, bc );
ab = b - a;
bc = c - b;
/* determine length */
VectorCopy( a, last );
last = a;
for ( i = 0, len = 0.0f, t = 0.0f; i < APPROX_SUBDIVISION; i++, t += ( 1.0f / APPROX_SUBDIVISION ) )
{
/* calculate delta */
delta[ 0 ] = ( ( 1.0f - t ) * ab[ 0 ] ) + ( t * bc[ 0 ] );
delta[ 1 ] = ( ( 1.0f - t ) * ab[ 1 ] ) + ( t * bc[ 1 ] );
delta[ 2 ] = ( ( 1.0f - t ) * ab[ 2 ] ) + ( t * bc[ 2 ] );
delta = ab * ( 1.0f - t ) + bc * t;
/* add to first point and calculate pt-pt delta */
VectorAdd( a, delta, pt );
VectorSubtract( pt, last, delta );
pt = a + delta;
delta = pt - last;
/* add it to length and store last point */
len += VectorLength( delta );
VectorCopy( pt, last );
len += vector3_length( delta );
last = pt;
}
/* longer? */
@@ -100,19 +98,18 @@ static void ExpandLongestCurve( float *longestCurve, vec3_t a, vec3_t b, vec3_t
determines how many iterations a quadratic curve needs to be subdivided with to fit the specified error
*/
static void ExpandMaxIterations( int *maxIterations, int maxError, vec3_t a, vec3_t b, vec3_t c ){
static void ExpandMaxIterations( int *maxIterations, int maxError, const Vector3& a, const Vector3& b, const Vector3& c ){
int i, j;
vec3_t prev, next, mid, delta, delta2;
float len, len2;
Vector3 prev, next, mid;
int numPoints, iterations;
vec3_t points[ MAX_EXPANDED_AXIS ];
Vector3 points[ MAX_EXPANDED_AXIS ];
/* initial setup */
numPoints = 3;
VectorCopy( a, points[ 0 ] );
VectorCopy( b, points[ 1 ] );
VectorCopy( c, points[ 2 ] );
points[ 0 ] = a;
points[ 1 ] = b;
points[ 2 ] = c;
/* subdivide */
for ( i = 0; i + 2 < numPoints; i += 2 )
@@ -123,17 +120,12 @@ static void ExpandMaxIterations( int *maxIterations, int maxError, vec3_t a, vec
}
/* calculate new curve deltas */
for ( j = 0; j < 3; j++ )
{
prev[ j ] = points[ i + 1 ][ j ] - points[ i ][ j ];
next[ j ] = points[ i + 2 ][ j ] - points[ i + 1 ][ j ];
mid[ j ] = ( points[ i ][ j ] + points[ i + 1 ][ j ] * 2.0f + points[ i + 2 ][ j ] ) * 0.25f;
}
prev = points[ i + 1 ] - points[ i ];
next = points[ i + 2 ] - points[ i + 1 ];
mid = ( points[ i ] + points[ i + 1 ] * 2.0f + points[ i + 2 ] ) * 0.25f;
/* see if this midpoint is off far enough to subdivide */
VectorSubtract( points[ i + 1 ], mid, delta );
len = VectorLength( delta );
if ( len < maxError ) {
if ( vector3_length( points[ i + 1 ] - mid ) < maxError ) {
continue;
}
@@ -141,21 +133,18 @@ static void ExpandMaxIterations( int *maxIterations, int maxError, vec3_t a, vec
numPoints += 2;
/* create new points */
for ( j = 0; j < 3; j++ )
{
prev[ j ] = 0.5f * ( points[ i ][ j ] + points[ i + 1 ][ j ] );
next[ j ] = 0.5f * ( points[ i + 1 ][ j ] + points[ i + 2 ][ j ] );
mid[ j ] = 0.5f * ( prev[ j ] + next[ j ] );
}
prev = ( points[ i ] + points[ i + 1 ] ) * 0.5f;
next = ( points[ i + 1 ] + points[ i + 2 ] ) * 0.5f;
mid = ( prev + next ) * 0.5f;
/* push points out */
for ( j = numPoints - 1; j > i + 3; j-- )
VectorCopy( points[ j - 2 ], points[ j ] );
points[ j ] = points[ j - 2 ];
/* insert new points */
VectorCopy( prev, points[ i + 1 ] );
VectorCopy( mid, points[ i + 2 ] );
VectorCopy( next, points[ i + 3 ] );
points[ i + 1 ] = prev;
points[ i + 2 ] = mid;
points[ i + 3 ] = next;
/* back up and recheck this set again, it may need more subdivision */
i -= 2;
@@ -164,27 +153,24 @@ static void ExpandMaxIterations( int *maxIterations, int maxError, vec3_t a, vec
/* put the line on the curve */
for ( i = 1; i < numPoints; i += 2 )
{
for ( j = 0; j < 3; j++ )
{
prev[ j ] = 0.5f * ( points[ i ][ j ] + points[ i + 1 ][ j ] );
next[ j ] = 0.5f * ( points[ i ][ j ] + points[ i - 1 ][ j ] );
points[ i ][ j ] = 0.5f * ( prev[ j ] + next[ j ] );
}
prev = ( points[ i ] + points[ i + 1 ] ) * 0.5f;
next = ( points[ i ] + points[ i - 1 ] ) * 0.5f;
points[ i ] = ( prev + next ) * 0.5f;
}
/* eliminate linear sections */
for ( i = 0; i + 2 < numPoints; i++ )
{
/* create vectors */
VectorSubtract( points[ i + 1 ], points[ i ], delta );
len = VectorNormalize( delta, delta );
VectorSubtract( points[ i + 2 ], points[ i + 1 ], delta2 );
len2 = VectorNormalize( delta2, delta2 );
Vector3 delta = points[ i + 1 ] - points[ i ];
const float len = VectorNormalize( delta );
Vector3 delta2 = points[ i + 2 ] - points[ i + 1 ];
const float len2 = VectorNormalize( delta2 );
/* if either edge is degenerate, then eliminate it */
if ( len < 0.0625f || len2 < 0.0625f || DotProduct( delta, delta2 ) >= 1.0f ) {
if ( len < 0.0625f || len2 < 0.0625f || vector3_dot( delta, delta2 ) >= 1.0f ) {
for ( j = i + 1; j + 1 < numPoints; j++ )
VectorCopy( points[ j + 1 ], points[ j ] );
points[ j ] = points[ j + 1 ];
numPoints--;
continue;
}
@@ -213,12 +199,11 @@ static void ExpandMaxIterations( int *maxIterations, int maxError, vec3_t a, vec
*/
void ParsePatch( bool onlyLights ){
vec_t info[ 5 ];
float info[ 5 ];
int i, j, k;
parseMesh_t *pm;
mesh_t m;
bspDrawVert_t *verts;
vec4_t delta, delta2, delta3;
bool degenerate;
float longestCurve;
int maxIterations;
@@ -244,15 +229,12 @@ void ParsePatch( bool onlyLights ){
MatchToken( "(" );
for ( i = 0; i < m.height ; i++ )
{
Parse1DMatrix( 5, verts[ i * m.width + j ].xyz );
Parse1DMatrix( 5, verts[ i * m.width + j ].xyz.data() );
/* ydnar: fix colors */
for ( k = 0; k < MAX_LIGHTMAPS; k++ )
{
verts[ i * m.width + j ].color[ k ][ 0 ] = 255;
verts[ i * m.width + j ].color[ k ][ 1 ] = 255;
verts[ i * m.width + j ].color[ k ][ 2 ] = 255;
verts[ i * m.width + j ].color[ k ][ 3 ] = 255;
verts[ i * m.width + j ].color[ k ].set( 255 );
}
}
MatchToken( ")" );
@@ -280,15 +262,14 @@ void ParsePatch( bool onlyLights ){
/* ydnar: delete and warn about degenerate patches */
j = ( m.width * m.height );
VectorClear( delta );
delta[ 3 ] = 0;
Vector4 delta( 0, 0, 0, 0 );
degenerate = true;
/* find first valid vector */
for ( i = 1; i < j && delta[ 3 ] == 0; i++ )
{
VectorSubtract( m.verts[ 0 ].xyz, m.verts[ i ].xyz, delta );
delta[ 3 ] = VectorNormalize( delta, delta );
delta.vec3() = m.verts[ 0 ].xyz - m.verts[ i ].xyz;
delta[ 3 ] = VectorNormalize( delta.vec3() );
}
/* secondary degenerate test */
@@ -300,16 +281,15 @@ void ParsePatch( bool onlyLights ){
/* if all vectors match this or are zero, then this is a degenerate patch */
for ( i = 1; i < j && degenerate; i++ )
{
VectorSubtract( m.verts[ 0 ].xyz, m.verts[ i ].xyz, delta2 );
delta2[ 3 ] = VectorNormalize( delta2, delta2 );
Vector4 delta2( m.verts[ 0 ].xyz - m.verts[ i ].xyz, 0 );
delta2[ 3 ] = VectorNormalize( delta2.vec3() );
if ( delta2[ 3 ] != 0 ) {
/* create inverse vector */
VectorCopy( delta2, delta3 );
delta3[ 3 ] = delta2[ 3 ];
VectorInverse( delta3 );
Vector4 delta3( delta2 );
vector3_negate( delta3.vec3() );
/* compare */
if ( !VectorCompare( delta, delta2 ) && !VectorCompare( delta, delta3 ) ) {
if ( !VectorCompare( delta.vec3(), delta2.vec3() ) && !VectorCompare( delta.vec3(), delta3.vec3() ) ) {
degenerate = false;
}
}
@@ -413,7 +393,7 @@ void PatchMapDrawSurfs( entity_t *e ){
mapDrawSurface_t *ds;
int patchCount, groupCount;
bspDrawVert_t *v1, *v2;
vec3_t bounds[ 2 ];
MinMax bounds;
byte *bordering;
parseMesh_t *meshes[ MAX_MAP_DRAW_SURFS ];
@@ -491,7 +471,8 @@ void PatchMapDrawSurfs( entity_t *e ){
GrowGroup_r( scan, i, patchCount, meshes, bordering, group );
/* bound them */
ClearBounds( bounds[ 0 ], bounds[ 1 ] );
bounds.clear();
for ( j = 0; j < patchCount; j++ )
{
if ( group[ j ] ) {
@@ -500,7 +481,7 @@ void PatchMapDrawSurfs( entity_t *e ){
c1 = check->mesh.width * check->mesh.height;
v1 = check->mesh.verts;
for ( k = 0; k < c1; k++, v1++ )
AddPointToBounds( v1->xyz, bounds[ 0 ], bounds[ 1 ] );
bounds.extend( v1->xyz );
}
}
@@ -510,8 +491,7 @@ void PatchMapDrawSurfs( entity_t *e ){
/* create drawsurf */
scan->grouped = true;
ds = DrawSurfaceForMesh( e, scan, NULL ); /* ydnar */
VectorCopy( bounds[ 0 ], ds->bounds[ 0 ] );
VectorCopy( bounds[ 1 ], ds->bounds[ 1 ] );
ds->bounds = bounds;
}
/* emit some statistics */
+35 -56
View File
@@ -175,10 +175,10 @@ void PrintPortal( portal_t *p ){
*/
#define SIDESPACE 8
void MakeHeadnodePortals( tree_t *tree ){
vec3_t bounds[2];
Vector3 bounds[2];
int i, j, n;
portal_t *p, *portals[6];
plane_t bplanes[6], *pl;
plane_t bplanes[6];
node_t *node;
node = tree->headnode;
@@ -186,8 +186,8 @@ void MakeHeadnodePortals( tree_t *tree ){
// pad with some space so there will never be null volume leafs
for ( i = 0 ; i < 3 ; i++ )
{
bounds[0][i] = tree->mins[i] - SIDESPACE;
bounds[1][i] = tree->maxs[i] + SIDESPACE;
bounds[0][i] = tree->minmax.mins[i] - SIDESPACE;
bounds[1][i] = tree->minmax.maxs[i] + SIDESPACE;
if ( bounds[0][i] >= bounds[1][i] ) {
Error( "Backwards tree volume" );
}
@@ -206,19 +206,19 @@ void MakeHeadnodePortals( tree_t *tree ){
p = AllocPortal();
portals[n] = p;
pl = &bplanes[n];
plane_t *pl = &bplanes[n];
memset( pl, 0, sizeof( *pl ) );
if ( j ) {
pl->normal[i] = -1;
pl->dist = -bounds[j][i];
pl->normal()[i] = -1;
pl->dist() = -bounds[j][i];
}
else
{
pl->normal[i] = 1;
pl->dist = bounds[j][i];
pl->normal()[i] = 1;
pl->dist() = bounds[j][i];
}
p->plane = *pl;
p->winding = BaseWindingForPlane( pl->normal, pl->dist );
p->winding = BaseWindingForPlane( pl->plane );
AddPortalToNodes( p, node, &tree->outside_node );
}
@@ -230,7 +230,7 @@ void MakeHeadnodePortals( tree_t *tree ){
if ( j == i ) {
continue;
}
ChopWindingInPlace( &portals[i]->winding, bplanes[j].normal, bplanes[j].dist, ON_EPSILON );
ChopWindingInPlace( &portals[i]->winding, bplanes[j].plane, ON_EPSILON );
}
}
}
@@ -249,26 +249,20 @@ void MakeHeadnodePortals( tree_t *tree ){
winding_t *BaseWindingForNode( node_t *node ){
winding_t *w;
node_t *n;
plane_t *plane;
vec3_t normal;
vec_t dist;
w = BaseWindingForPlane( mapplanes[node->planenum].normal
, mapplanes[node->planenum].dist );
w = BaseWindingForPlane( mapplanes[node->planenum].plane );
// clip by all the parents
for ( n = node->parent ; n && w ; )
{
plane = &mapplanes[n->planenum];
const plane_t& plane = mapplanes[n->planenum];
if ( n->children[0] == node ) { // take front
ChopWindingInPlace( &w, plane->normal, plane->dist, BASE_WINDING_EPSILON );
ChopWindingInPlace( &w, plane.plane, BASE_WINDING_EPSILON );
}
else
{ // take back
VectorSubtract( vec3_origin, plane->normal, normal );
dist = -plane->dist;
ChopWindingInPlace( &w, normal, dist, BASE_WINDING_EPSILON );
ChopWindingInPlace( &w, plane3_flipped( plane.plane ), BASE_WINDING_EPSILON );
}
node = n;
n = n->parent;
@@ -290,8 +284,6 @@ winding_t *BaseWindingForNode( node_t *node ){
void MakeNodePortal( node_t *node ){
portal_t *new_portal, *p;
winding_t *w;
vec3_t normal;
float dist;
int side;
w = BaseWindingForNode( node );
@@ -301,19 +293,16 @@ void MakeNodePortal( node_t *node ){
{
if ( p->nodes[0] == node ) {
side = 0;
VectorCopy( p->plane.normal, normal );
dist = p->plane.dist;
ChopWindingInPlace( &w, p->plane.plane, CLIP_EPSILON );
}
else if ( p->nodes[1] == node ) {
side = 1;
VectorSubtract( vec3_origin, p->plane.normal, normal );
dist = -p->plane.dist;
ChopWindingInPlace( &w, plane3_flipped( p->plane.plane ), CLIP_EPSILON );
}
else{
Error( "CutNodePortals_r: mislinked portal" );
}
ChopWindingInPlace( &w, normal, dist, CLIP_EPSILON );
}
if ( !w ) {
@@ -357,10 +346,9 @@ void SplitNodePortals( node_t *node ){
portal_t *p, *next_portal, *new_portal;
node_t *f, *b, *other_node;
int side;
plane_t *plane;
winding_t *frontwinding, *backwinding;
plane = &mapplanes[node->planenum];
const plane_t& plane = mapplanes[node->planenum];
f = node->children[0];
b = node->children[1];
@@ -384,16 +372,16 @@ void SplitNodePortals( node_t *node ){
//
// cut the portal into two portals, one on each side of the cut plane
//
ClipWindingEpsilon( p->winding, plane->normal, plane->dist,
ClipWindingEpsilon( p->winding, plane.plane,
SPLIT_WINDING_EPSILON, &frontwinding, &backwinding ); /* not strict, we want to always keep one of them even if coplanar */
if ( frontwinding && WindingIsTiny( frontwinding ) ) {
if ( !f->tinyportals ) {
VectorCopy( frontwinding->p[0], f->referencepoint );
f->referencepoint = frontwinding->p[0];
}
f->tinyportals++;
if ( !other_node->tinyportals ) {
VectorCopy( frontwinding->p[0], other_node->referencepoint );
other_node->referencepoint = frontwinding->p[0];
}
other_node->tinyportals++;
@@ -404,11 +392,11 @@ void SplitNodePortals( node_t *node ){
if ( backwinding && WindingIsTiny( backwinding ) ) {
if ( !b->tinyportals ) {
VectorCopy( backwinding->p[0], b->referencepoint );
b->referencepoint = backwinding->p[0];
}
b->tinyportals++;
if ( !other_node->tinyportals ) {
VectorCopy( backwinding->p[0], other_node->referencepoint );
other_node->referencepoint = backwinding->p[0];
}
other_node->tinyportals++;
@@ -475,12 +463,12 @@ void CalcNodeBounds( node_t *node ){
int i;
// calc mins/maxs for both leafs and nodes
ClearBounds( node->mins, node->maxs );
node->minmax.clear();
for ( p = node->portals ; p ; p = p->next[s] )
{
s = ( p->nodes[1] == node );
for ( i = 0 ; i < p->winding->numpoints ; i++ )
AddPointToBounds( p->winding->p[i], node->mins, node->maxs );
node->minmax.extend( p->winding->p[i] );
}
}
@@ -493,7 +481,7 @@ void MakeTreePortals_r( node_t *node ){
int i;
CalcNodeBounds( node );
if ( node->mins[0] >= node->maxs[0] ) {
if ( node->minmax.mins[0] >= node->minmax.maxs[0] ) {
Sys_Warning( "node without a volume\n"
"node has %d tiny portals\n"
"node reference point %1.2f %1.2f %1.2f\n",
@@ -505,7 +493,7 @@ void MakeTreePortals_r( node_t *node ){
for ( i = 0 ; i < 3 ; i++ )
{
if ( node->mins[i] < MIN_WORLD_COORD || node->maxs[i] > MAX_WORLD_COORD ) {
if ( node->minmax.mins[i] < MIN_WORLD_COORD || node->minmax.maxs[i] > MAX_WORLD_COORD ) {
if ( node->portals && node->portals->winding ) {
xml_Winding( "WARNING: Node With Unbounded Volume", node->portals->winding->p, node->portals->winding->numpoints, false );
}
@@ -587,19 +575,14 @@ void FloodPortals( node_t *node, bool skybox ){
=============
*/
bool PlaceOccupant( node_t *headnode, vec3_t origin, const entity_t *occupant, bool skybox ){
vec_t d;
bool PlaceOccupant( node_t *headnode, const Vector3& origin, const entity_t *occupant, bool skybox ){
node_t *node;
plane_t *plane;
// find the leaf to start in
node = headnode;
while ( node->planenum != PLANENUM_LEAF )
{
plane = &mapplanes[ node->planenum ];
d = DotProduct( origin, plane->normal ) - plane->dist;
if ( d >= 0 ) {
if ( plane3_distance_to_point( mapplanes[ node->planenum ].plane, origin ) >= 0 ) {
node = node->children[ 0 ];
}
else{
@@ -644,11 +627,11 @@ EFloodEntities FloodEntities( tree_t *tree ){
const entity_t& e = entities[ i ];
/* get origin */
vec3_t origin;
Vector3 origin;
e.vectorForKey( "origin", origin );
#if 0 // 0 = allow maps with only point entity@( 0, 0, 0 ); assuming that entities, containing no primitives are point ones
/* as a special case, allow origin-less entities */
if ( VectorCompare( origin, vec3_origin ) ) {
if ( VectorCompare( origin, g_vector3_identity ) ) {
continue;
}
#endif
@@ -661,25 +644,21 @@ EFloodEntities FloodEntities( tree_t *tree ){
if ( e.classname_is( "_skybox" ) ) {
skybox = true;
/* invert origin */
vec3_t offset;
VectorScale( origin, -1.0f, offset );
/* get scale */
vec3_t scale = { 64.0f, 64.0f, 64.0f };
Vector3 scale( 64, 64, 64 );
if( !e.read_keyvalue( scale, "_scale" ) )
if( e.read_keyvalue( scale[0], "_scale" ) )
scale[1] = scale[2] = scale[0];
/* get "angle" (yaw) or "angles" (pitch yaw roll), store as (roll pitch yaw) */
vec3_t angles = { 0.f, 0.f, 0.f };
Vector3 angles( 0, 0, 0 );
if ( !e.read_keyvalue( value, "angles" ) ||
3 != sscanf( value, "%f %f %f", &angles[ 1 ], &angles[ 2 ], &angles[ 0 ] ) )
e.read_keyvalue( angles[ 2 ], "angle" );
/* set transform matrix (thanks spog) */
m4x4_identity( skyboxTransform );
m4x4_pivoted_transform_by_vec3( skyboxTransform, offset, angles, eXYZ, scale, origin );
skyboxTransform = g_matrix4_identity;
matrix4_pivoted_transform_by_euler_xyz_degrees( skyboxTransform, -origin, angles, scale, origin );
}
else{
skybox = false;
+4 -8
View File
@@ -50,9 +50,9 @@ int num_visclusters; // clusters the player can be in
int num_visportals;
int num_solidfaces;
void WriteFloat( FILE *f, vec_t v ){
if ( fabs( v - Q_rint( v ) ) < 0.001 ) {
fprintf( f, "%i ", (int)Q_rint( v ) );
void WriteFloat( FILE *f, float v ){
if ( fabs( v - std::rint( v ) ) < 0.001 ) {
fprintf( f, "%li ", std::lrint( v ) );
}
else{
fprintf( f, "%f ", v );
@@ -100,8 +100,6 @@ void WritePortalFile_r( node_t *node ){
int i, s, flags;
portal_t *p;
winding_t *w;
vec3_t normal;
vec_t dist;
// decision node
if ( node->planenum != PLANENUM_LEAF ) {
@@ -132,9 +130,7 @@ void WritePortalFile_r( node_t *node ){
// the changeover point between different axis. interpret the
// plane the same way vis will, and flip the side orders if needed
// FIXME: is this still relevent?
WindingPlane( w, normal, &dist );
if ( DotProduct( p->plane.normal, normal ) < 0.99 ) { // backwards...
if ( vector3_dot( p->plane.normal(), WindingPlane( w ).normal() ) < 0.99 ) { // backwards...
fprintf( pf, "%i %i %i ", w->numpoints, p->nodes[1]->cluster, p->nodes[0]->cluster );
}
else{
+236 -188
View File
@@ -69,7 +69,6 @@
#include "version.h" /* ttimo: might want to guard that if built outside of the GtkRadiant tree */
#include "cmdlib.h"
#include "mathlib.h"
#include "md5lib.h"
#include "ddslib.h"
@@ -88,20 +87,12 @@
#include "stream/stringstream.h"
#include "bitflags.h"
#include <list>
#include "qmath.h"
#include <stddef.h>
#include <stdlib.h>
/* -------------------------------------------------------------------------------
port-related hacks
------------------------------------------------------------------------------- */
/* macro version */
#define VectorMA( a, s, b, c ) ( ( c )[ 0 ] = ( a )[ 0 ] + ( s ) * ( b )[ 0 ], ( c )[ 1 ] = ( a )[ 1 ] + ( s ) * ( b )[ 1 ], ( c )[ 2 ] = ( a )[ 2 ] + ( s ) * ( b )[ 2 ] )
#include "maxworld.h"
/* -------------------------------------------------------------------------------
@@ -241,33 +232,8 @@ enum class EBrushType
#define CLUSTER_OCCLUDED -2
#define CLUSTER_FLOODED -3
#define VERTEX_LUXEL_SIZE 3
#define BSP_LUXEL_SIZE 3
#define RAD_LUXEL_SIZE 3
#define SUPER_LUXEL_SIZE 4
#define SUPER_FLAG_SIZE 4
#define FLAG_FORCE_SUBSAMPLING 1
#define FLAG_ALREADY_SUBSAMPLED 2
#define SUPER_ORIGIN_SIZE 3
#define SUPER_NORMAL_SIZE 4
#define SUPER_DELUXEL_SIZE 3
#define BSP_DELUXEL_SIZE 3
#define SUPER_FLOODLIGHT_SIZE 4
#define VERTEX_LUXEL( s, v ) ( vertexLuxels[ s ] + ( ( v ) * VERTEX_LUXEL_SIZE ) )
#define RAD_VERTEX_LUXEL( s, v )( radVertexLuxels[ s ] + ( ( v ) * VERTEX_LUXEL_SIZE ) )
#define BSP_LUXEL( s, x, y ) ( lm->bspLuxels[ s ] + ( ( ( ( y ) * lm->w ) + ( x ) ) * BSP_LUXEL_SIZE ) )
#define RAD_LUXEL( s, x, y ) ( lm->radLuxels[ s ] + ( ( ( ( y ) * lm->w ) + ( x ) ) * RAD_LUXEL_SIZE ) )
#define SUPER_LUXEL( s, x, y ) ( lm->superLuxels[ s ] + ( ( ( ( y ) * lm->sw ) + ( x ) ) * SUPER_LUXEL_SIZE ) )
#define SUPER_FLAG( x, y ) ( lm->superFlags + ( ( ( ( y ) * lm->sw ) + ( x ) ) * SUPER_FLAG_SIZE ) )
#define SUPER_DELUXEL( x, y ) ( lm->superDeluxels + ( ( ( ( y ) * lm->sw ) + ( x ) ) * SUPER_DELUXEL_SIZE ) )
#define BSP_DELUXEL( x, y ) ( lm->bspDeluxels + ( ( ( ( y ) * lm->w ) + ( x ) ) * BSP_DELUXEL_SIZE ) )
#define SUPER_CLUSTER( x, y ) ( lm->superClusters + ( ( ( y ) * lm->sw ) + ( x ) ) )
#define SUPER_ORIGIN( x, y ) ( lm->superOrigins + ( ( ( ( y ) * lm->sw ) + ( x ) ) * SUPER_ORIGIN_SIZE ) )
#define SUPER_NORMAL( x, y ) ( lm->superNormals + ( ( ( ( y ) * lm->sw ) + ( x ) ) * SUPER_NORMAL_SIZE ) )
#define SUPER_DIRT( x, y ) ( lm->superNormals + ( ( ( ( y ) * lm->sw ) + ( x ) ) * SUPER_NORMAL_SIZE ) + 3 ) /* stash dirtyness in normal[ 3 ] */
#define SUPER_FLOODLIGHT( x, y ) ( lm->superFloodLight + ( ( ( ( y ) * lm->sw ) + ( x ) ) * SUPER_FLOODLIGHT_SIZE ) )
/* -------------------------------------------------------------------------------
@@ -308,9 +274,8 @@ enum class EBrushType
#define LIGHTMAP_WIDTH 128
#define LIGHTMAP_HEIGHT 128
#define MIN_WORLD_COORD ( -65536 )
#define MAX_WORLD_COORD ( 65536 )
#define WORLD_SIZE ( MAX_WORLD_COORD - MIN_WORLD_COORD )
using Vector3b = BasicVector3<byte>;
typedef void ( *bspFunc )( const char * );
@@ -333,7 +298,7 @@ struct bspHeader_t
struct bspModel_t
{
float mins[ 3 ], maxs[ 3 ];
MinMax minmax;
int firstBSPSurface, numBSPSurfaces;
int firstBSPBrush, numBSPBrushes;
};
@@ -349,19 +314,14 @@ struct bspShader_t
/* planes x^1 is always the opposite of plane x */
struct bspPlane_t
{
float normal[ 3 ];
float dist;
};
using bspPlane_t = Plane3f;
struct bspNode_t
{
int planeNum;
int children[ 2 ]; /* negative numbers are -(leafs+1), not nodes */
int mins[ 3 ]; /* for frustum culling */
int maxs[ 3 ];
MinMax___<int> minmax; /* for frustum culling */
};
@@ -370,8 +330,7 @@ struct bspLeaf_t
int cluster; /* -1 = opaque cluster (do I still store these?) */
int area;
int mins[ 3 ]; /* for frustum culling */
int maxs[ 3 ];
MinMax___<int> minmax; /* for frustum culling */
int firstBSPLeafSurface;
int numBSPLeafSurfaces;
@@ -407,11 +366,11 @@ struct bspFog_t
struct bspDrawVert_t
{
vec3_t xyz;
float st[ 2 ];
float lightmap[ MAX_LIGHTMAPS ][ 2 ]; /* RBSP */
vec3_t normal;
byte color[ MAX_LIGHTMAPS ][ 4 ]; /* RBSP */
Vector3 xyz;
Vector2 st;
Vector2 lightmap[ MAX_LIGHTMAPS ]; /* RBSP */
Vector3 normal;
Color4b color[ MAX_LIGHTMAPS ]; /* RBSP */
};
@@ -428,8 +387,8 @@ enum bspSurfaceType_t
struct bspGridPoint_t
{
byte ambient[ MAX_LIGHTMAPS ][ 3 ];
byte directed[ MAX_LIGHTMAPS ][ 3 ];
Vector3b ambient[ MAX_LIGHTMAPS ];
Vector3b directed[ MAX_LIGHTMAPS ];
byte styles[ MAX_LIGHTMAPS ];
byte latLong[ 2 ];
};
@@ -453,8 +412,8 @@ struct bspDrawSurface_t
int lightmapX[ MAX_LIGHTMAPS ], lightmapY[ MAX_LIGHTMAPS ]; /* RBSP */
int lightmapWidth, lightmapHeight;
vec3_t lightmapOrigin;
vec3_t lightmapVecs[ 3 ]; /* on patches, [ 0 ] and [ 1 ] are lodbounds */
Vector3 lightmapOrigin;
Vector3 lightmapVecs[ 3 ]; /* on patches, [ 0 ] and [ 1 ] are lodbounds */
int patchWidth;
int patchHeight;
@@ -465,8 +424,8 @@ struct bspDrawSurface_t
struct bspAdvertisement_t
{
int cellId;
vec3_t normal;
vec3_t rect[4];
Vector3 normal;
Vector3 rect[4];
char model[ MAX_QPATH ];
};
@@ -553,7 +512,7 @@ struct image_t
struct sun_t
{
sun_t *next;
vec3_t direction, color;
Vector3 direction, color;
float photons, deviance, filterRadius;
int numSamples, style;
};
@@ -579,7 +538,7 @@ struct foliage_t
struct foliageInstance_t
{
vec3_t xyz, normal;
Vector3 xyz, normal;
};
@@ -613,7 +572,7 @@ struct colorMod_t
{
colorMod_t *next;
EColorMod type;
vec_t data[ 16 ];
float data[ 16 ];
};
@@ -657,7 +616,7 @@ struct shaderInfo_t
float offset; /* ydnar: offset in units */
float shadeAngleDegrees; /* ydnar: breaking angle for smooth shading (degrees) */
vec3_t mins, maxs; /* ydnar: for particle studio vertexDeform move support */
MinMax minmax; /* ydnar: for particle studio vertexDeform move support */
bool legacyTerrain; /* ydnar: enable legacy terrain crutches */
bool indexed; /* ydnar: attempt to use indexmap (terrain alphamap style) */
@@ -667,9 +626,9 @@ struct shaderInfo_t
bool invert; /* ydnar: reverse facing */
bool nonplanar; /* ydnar: for nonplanar meta surface merging */
bool tcGen; /* ydnar: has explicit texcoord generation */
vec3_t vecs[ 2 ]; /* ydnar: explicit texture vectors for [0,1] texture space */
Vector3 vecs[ 2 ]; /* ydnar: explicit texture vectors for [0,1] texture space */
tcMod_t mod; /* ydnar: q3map_tcMod matrix for djbob :) */
vec3_t lightmapAxis; /* ydnar: explicit lightmap axis projection */
Vector3 lightmapAxis; /* ydnar: explicit lightmap axis projection */
colorMod_t *colorMod; /* ydnar: q3map_rgb/color/alpha/Set/Mod support */
int furNumLayers; /* ydnar: number of fur layers */
@@ -714,13 +673,13 @@ struct shaderInfo_t
int skyLightIterations; /* ydnar */
sun_t *sun; /* ydnar */
vec3_t color; /* normalized color */
vec4_t averageColor;
Vector3 color; /* normalized color */
Color4f averageColor;
byte lightStyle;
/* vortex: per-surface floodlight */
float floodlightDirectionScale;
vec3_t floodlightRGB;
Vector3 floodlightRGB;
float floodlightIntensity;
float floodlightDistance;
@@ -730,9 +689,9 @@ struct shaderInfo_t
float lmFilterRadius; /* ydnar: lightmap filtering/blurring radius for this shader (default: 0) */
int shaderWidth, shaderHeight; /* ydnar */
float stFlat[ 2 ];
Vector2 stFlat;
vec3_t fogDir; /* ydnar */
Vector3 fogDir; /* ydnar */
char *shaderText; /* ydnar */
bool custom;
@@ -760,9 +719,20 @@ struct face_t
struct plane_t
{
vec3_t normal;
vec_t dist;
int type;
Plane3f plane;
Vector3& normal(){
return plane.normal();
}
const Vector3& normal() const {
return plane.normal();
}
float& dist(){
return plane.dist();
}
const float& dist() const {
return plane.dist();
}
EPlaneType type;
int counter;
int hash_chain;
};
@@ -774,8 +744,8 @@ struct side_t
int outputNum; /* set when the side is written to the file list */
float texMat[ 2 ][ 3 ]; /* brush primitive texture matrix */
float vecs[ 2 ][ 4 ]; /* old-style texture coordinate mapping */
Vector3 texMat[ 2 ]; /* brush primitive texture matrix */
Vector4 vecs[ 2 ]; /* old-style texture coordinate mapping */
winding_t *winding;
winding_t *visibleHull; /* convex hull of all visible fragments */
@@ -830,7 +800,7 @@ struct brush_t
int lightmapSampleSize; /* jal : entity based _lightmapsamplesize */
float lightmapScale;
float shadeAngleDegrees; /* jal : entity based _shadeangle */
vec3_t eMins, eMaxs;
MinMax eMinmax;
indexMap_t *im;
int contentFlags;
@@ -840,7 +810,7 @@ struct brush_t
int portalareas[ 2 ];
vec3_t mins, maxs;
MinMax minmax;
int numsides;
side_t sides[]; /* variably sized */
@@ -879,7 +849,7 @@ struct parseMesh_t
/* ydnar: gs mods */
int lightmapSampleSize; /* jal : entity based _lightmapsamplesize */
float lightmapScale;
vec3_t eMins, eMaxs;
MinMax eMinmax;
indexMap_t *im;
/* grouping */
@@ -963,8 +933,8 @@ struct mapDrawSurface_t
int *indexes;
int planeNum;
vec3_t lightmapOrigin; /* also used for flares */
vec3_t lightmapVecs[ 3 ]; /* also used for flares */
Vector3 lightmapOrigin; /* also used for flares */
Vector3 lightmapVecs[ 3 ]; /* also used for flares */
int lightStyle; /* used for flares */
/* ydnar: per-surface (per-entity, actually) lightmap sample size scaling */
@@ -974,8 +944,8 @@ struct mapDrawSurface_t
float shadeAngleDegrees;
/* ydnar: surface classification */
vec3_t mins, maxs;
vec3_t lightmapAxis;
MinMax minmax;
Vector3 lightmapAxis;
int sampleSize;
/* ydnar: shadow group support */
@@ -989,7 +959,7 @@ struct mapDrawSurface_t
float longestCurve;
int maxIterations;
int patchWidth, patchHeight;
vec3_t bounds[ 2 ];
MinMax bounds;
/* ydnar/sd: for foliage */
int numFoliageInstances;
@@ -1014,8 +984,8 @@ struct metaTriangle_t
side_t *side;
int entityNum, surfaceNum, planeNum, fogNum, sampleSize, castShadows, recvShadows;
float shadeAngleDegrees;
vec4_t plane;
vec3_t lightmapAxis;
Plane3f plane;
Vector3 lightmapAxis;
int indexes[ 3 ];
};
@@ -1028,13 +998,13 @@ struct epair_t
struct entity_t
{
vec3_t origin;
Vector3 origin;
brush_t *brushes, *lastBrush, *colorModBrushes;
parseMesh_t *patches;
int mapEntityNum, firstDrawSurf;
int firstBrush, numBrushes; /* only valid during BSP compile */
std::list<epair_t> epairs;
vec3_t originbrush_origin;
Vector3 originbrush_origin;
void setKeyValue( const char *key, const char *value );
const char *valueForKey( const char *key ) const;
@@ -1057,9 +1027,9 @@ struct entity_t
read_keyvalue_( float_value, { keys ... } );
return float_value;
}
void vectorForKey( const char *key, vec3_t& vec ) const {
void vectorForKey( const char *key, Vector3& vec ) const {
if( !read_keyvalue_( vec, { key } ) )
VectorClear( vec );
vec.set( 0 );
}
const char *classname() const {
@@ -1083,7 +1053,7 @@ private:
bool read_keyvalue_( bool &bool_value, std::initializer_list<const char*>&& keys ) const;
bool read_keyvalue_( int &int_value, std::initializer_list<const char*>&& keys ) const;
bool read_keyvalue_( float &float_value, std::initializer_list<const char*>&& keys ) const;
bool read_keyvalue_( float (&vector3_value)[3], std::initializer_list<const char*>&& keys ) const;
bool read_keyvalue_( Vector3& vector3_value, std::initializer_list<const char*>&& keys ) const;
bool read_keyvalue_( char (&string_value)[1024], std::initializer_list<const char*>&& keys ) const;
bool read_keyvalue_( const char *&string_ptr_value, std::initializer_list<const char*>&& keys ) const;
};
@@ -1094,7 +1064,7 @@ struct node_t
/* both leafs and nodes */
int planenum; /* -1 = leaf node */
node_t *parent;
vec3_t mins, maxs; /* valid after portalization */
MinMax minmax; /* valid after portalization */
brush_t *volume; /* one for each leaf/node */
/* nodes only */
@@ -1102,7 +1072,7 @@ struct node_t
node_t *children[ 2 ];
int compileFlags; /* ydnar: hint, antiportal */
int tinyportals;
vec3_t referencepoint;
Vector3 referencepoint;
/* leafs only */
bool opaque; /* view can never be inside */
@@ -1141,7 +1111,7 @@ struct tree_t
{
node_t *headnode;
node_t outside_node;
vec3_t mins, maxs;
MinMax minmax;
};
@@ -1152,17 +1122,13 @@ struct tree_t
------------------------------------------------------------------------------- */
struct visPlane_t
{
vec3_t normal;
float dist;
};
using visPlane_t = Plane3f;
struct fixedWinding_t
{
int numpoints;
vec3_t points[ MAX_POINTS_ON_FIXED_WINDING ]; /* variable sized */
Vector3 points[ MAX_POINTS_ON_FIXED_WINDING ]; /* variable sized */
};
@@ -1190,7 +1156,7 @@ struct vportal_t
visPlane_t plane; /* normal pointing into neighbor */
int leaf; /* neighbor */
vec3_t origin; /* for fast clip testing */
Vector3 origin; /* for fast clip testing */
float radius;
fixedWinding_t *winding;
@@ -1287,13 +1253,13 @@ struct light_t
LightFlags flags; /* ydnar: condensed all the booleans into one flags int */
shaderInfo_t *si;
vec3_t origin;
vec3_t normal; /* for surfaces, spotlights, and suns */
Vector3 origin;
Vector3 normal; /* for surfaces, spotlights, and suns */
float dist; /* plane location along normal */
float photons;
int style;
vec3_t color;
Vector3 color;
float radiusByDist; /* for spotlights */
float fade; /* ydnar: from wolf, for linear lights */
float angleScale; /* ydnar: stolen from vlight for K */
@@ -1302,11 +1268,11 @@ struct light_t
float add; /* ydnar: used for area lights */
float envelope; /* ydnar: units until falloff < tolerance */
float envelope2; /* ydnar: envelope squared (tiny optimization) */
vec3_t mins, maxs; /* ydnar: pvs envelope */
MinMax minmax; /* ydnar: pvs envelope */
int cluster; /* ydnar: cluster light falls into */
winding_t *w;
vec3_t emitColor; /* full out-of-gamut value */
Vector3 emitColor; /* full out-of-gamut value */
float falloffTolerance; /* ydnar: minimum attenuation threshold */
float filterRadius; /* ydnar: lightmap filter radius in world units, 0 == default */
@@ -1329,28 +1295,28 @@ struct trace_t
/* per-sample input */
int cluster;
vec3_t origin, normal;
vec_t inhibitRadius; /* sphere in which occluding geometry is ignored */
Vector3 origin, normal;
float inhibitRadius; /* sphere in which occluding geometry is ignored */
/* per-light input */
light_t *light;
vec3_t end;
Vector3 end;
/* calculated input */
vec3_t displacement, direction;
vec_t distance;
Vector3 displacement, direction;
float distance;
/* input and output */
vec3_t color; /* starts out at full color, may be reduced if transparent surfaces are crossed */
vec3_t colorNoShadow; /* result color with no shadow casting */
vec3_t directionContribution; /* result contribution to the deluxe map */
Vector3 color; /* starts out at full color, may be reduced if transparent surfaces are crossed */
Vector3 colorNoShadow; /* result color with no shadow casting */
Vector3 directionContribution; /* result contribution to the deluxe map */
/* output */
vec3_t hit;
Vector3 hit;
int compileFlags; /* for determining surface compile flags traced through */
bool passSolid;
bool opaque;
vec_t forceSubsampling; /* needs subsampling (alphashadow), value = max color contribution possible from it */
float forceSubsampling; /* needs subsampling (alphashadow), value = max color contribution possible from it */
/* working data */
int numTestNodes;
@@ -1358,15 +1324,14 @@ struct trace_t
};
/* must be identical to bspDrawVert_t except for float color! */
struct radVert_t
{
vec3_t xyz;
float st[ 2 ];
float lightmap[ MAX_LIGHTMAPS ][ 2 ];
vec3_t normal;
float color[ MAX_LIGHTMAPS ][ 4 ];
Vector3 xyz;
Vector2 st;
Vector2 lightmap[ MAX_LIGHTMAPS ];
Vector3 normal;
Color4f color[ MAX_LIGHTMAPS ];
};
@@ -1380,8 +1345,8 @@ struct radWinding_t
/* crutch for poor local allocations in win32 smp */
struct clipWork_t
{
vec_t dists[ MAX_POINTS_ON_WINDING + 4 ];
int sides[ MAX_POINTS_ON_WINDING + 4 ];
float dists[ MAX_POINTS_ON_WINDING + 4 ];
EPlaneSide sides[ MAX_POINTS_ON_WINDING + 4 ];
};
@@ -1395,10 +1360,19 @@ struct outLightmap_t
int numShaders;
shaderInfo_t *shaders[ MAX_LIGHTMAP_SHADERS ];
byte *lightBits;
byte *bspLightBytes;
byte *bspDirBytes;
Vector3b *bspLightBytes;
Vector3b *bspDirBytes;
};
struct SuperLuxel{
Vector3 value;
float count;
};
struct SuperFloodLight{
Vector3 value;
float scale;
};
struct rawLightmap_t
{
@@ -1414,18 +1388,19 @@ struct rawLightmap_t
/* vortex: per-surface floodlight */
float floodlightDirectionScale;
vec3_t floodlightRGB;
Vector3 floodlightRGB;
float floodlightIntensity;
float floodlightDistance;
int entityNum;
int recvShadows;
vec3_t mins, maxs, axis, origin, *vecs;
float *plane;
MinMax minmax;
Vector3 axis, origin, *vecs;
Plane3f *plane;
int w, h, sw, sh, used;
bool solid[ MAX_LIGHTMAPS ];
vec3_t solidColor[ MAX_LIGHTMAPS ];
Vector3 solidColor[ MAX_LIGHTMAPS ];
int numStyledTwins;
rawLightmap_t *twins[ MAX_LIGHTMAPS ];
@@ -1434,25 +1409,92 @@ struct rawLightmap_t
int twinNums[ MAX_LIGHTMAPS ];
int lightmapX[ MAX_LIGHTMAPS ], lightmapY[ MAX_LIGHTMAPS ];
byte styles[ MAX_LIGHTMAPS ];
float *bspLuxels[ MAX_LIGHTMAPS ];
float *radLuxels[ MAX_LIGHTMAPS ];
float *superLuxels[ MAX_LIGHTMAPS ];
unsigned char *superFlags;
float *superOrigins;
float *superNormals;
Vector3 *bspLuxels[ MAX_LIGHTMAPS ];
Vector3 *radLuxels[ MAX_LIGHTMAPS ];
SuperLuxel *superLuxels[ MAX_LIGHTMAPS ];
byte *superFlags;
Vector3 *superOrigins;
Vector3 *superNormals;
float *superDirt;
int *superClusters;
float *superDeluxels; /* average light direction */
float *bspDeluxels;
float *superFloodLight;
Vector3 *superDeluxels; /* average light direction */
Vector3 *bspDeluxels;
SuperFloodLight *superFloodLight;
Vector3& getBspLuxel( int lightmapNum, int x, int y ){
return bspLuxels[ lightmapNum ][y * w + x];
}
const Vector3& getBspLuxel( int lightmapNum, int x, int y ) const {
return bspLuxels[ lightmapNum ][y * w + x];
}
Vector3& getRadLuxel( int lightmapNum, int x, int y ){
return radLuxels[ lightmapNum ][y * w + x];
}
const Vector3& getRadLuxel( int lightmapNum, int x, int y ) const {
return radLuxels[ lightmapNum ][y * w + x];
}
SuperLuxel& getSuperLuxel( int lightmapNum, int x, int y ){
return superLuxels[ lightmapNum ][y * sw + x];
}
const SuperLuxel& getSuperLuxel( int lightmapNum, int x, int y ) const {
return superLuxels[ lightmapNum ][y * sw + x];
}
const byte& getSuperFlag( int x, int y ) const {
return superFlags[y * sw + x];
}
byte& getSuperFlag( int x, int y ){
return superFlags[y * sw + x];
}
Vector3& getSuperOrigin( int x, int y ){
return superOrigins[y * sw + x];
}
const Vector3& getSuperOrigin( int x, int y ) const {
return superOrigins[y * sw + x];
}
Vector3& getSuperNormal( int x, int y ){
return superNormals[y * sw + x];
}
const Vector3& getSuperNormal( int x, int y ) const {
return superNormals[y * sw + x];
}
float& getSuperDirt( int x, int y ){
return superDirt[y * sw + x];
}
const float& getSuperDirt( int x, int y ) const {
return superDirt[y * sw + x];
}
int& getSuperCluster( int x, int y ){
return superClusters[y * sw + x];
}
const int& getSuperCluster( int x, int y ) const {
return superClusters[y * sw + x];
}
Vector3& getSuperDeluxel( int x, int y ){
return superDeluxels[y * sw + x];
}
const Vector3& getSuperDeluxel( int x, int y ) const {
return superDeluxels[y * sw + x];
}
Vector3& getBspDeluxel( int x, int y ){
return bspDeluxels[y * w + x];
}
const Vector3& getBspDeluxel( int x, int y ) const {
return bspDeluxels[y * w + x];
}
SuperFloodLight& getSuperFloodLight( int x, int y ){
return superFloodLight[y * sw + x];
}
const SuperFloodLight& getSuperFloodLight( int x, int y ) const {
return superFloodLight[y * sw + x];
}
};
struct rawGridPoint_t
{
vec3_t ambient[ MAX_LIGHTMAPS ];
vec3_t directed[ MAX_LIGHTMAPS ];
vec3_t dir;
Vector3 ambient[ MAX_LIGHTMAPS ];
Vector3 directed[ MAX_LIGHTMAPS ];
Vector3 dir;
byte styles[ MAX_LIGHTMAPS ];
};
@@ -1465,8 +1507,9 @@ struct surfaceInfo_t
int parentSurfaceNum, childSurfaceNum;
int entityNum, castShadows, recvShadows, sampleSize, patchIterations;
float longestCurve;
float *plane;
vec3_t axis, mins, maxs;
Plane3f *plane;
Vector3 axis;
MinMax minmax;
bool hasLightmap, approximated;
int firstSurfaceCluster, numSurfaceClusters;
};
@@ -1477,8 +1520,8 @@ struct surfaceInfo_t
------------------------------------------------------------------------------- */
static inline vec_t Random( void ){ /* returns a pseudorandom number between 0 and 1 */
return (vec_t) rand() / RAND_MAX;
inline float Random( void ){ /* returns a pseudorandom number between 0 and 1 */
return (float) rand() / RAND_MAX;
}
/* help.c */
@@ -1524,15 +1567,15 @@ void FreeBrush( brush_t *brushes );
void FreeBrushList( brush_t *brushes );
brush_t *CopyBrush( const brush_t *brush );
bool BoundBrush( brush_t *brush );
void SnapWeldVector( const Vector3& a, const Vector3& b, Vector3& out );
bool CreateBrushWindings( brush_t *brush );
brush_t *BrushFromBounds( vec3_t mins, vec3_t maxs );
vec_t BrushVolume( brush_t *brush );
brush_t *BrushFromBounds( const Vector3& mins, const Vector3& maxs );
float BrushVolume( brush_t *brush );
void WriteBSPBrushMap( const char *name, brush_t *list );
void FilterDetailBrushesIntoTree( entity_t *e, tree_t *tree );
void FilterStructuralBrushesIntoTree( entity_t *e, tree_t *tree );
int BoxOnPlaneSide( vec3_t mins, vec3_t maxs, plane_t *plane );
bool WindingIsTiny( winding_t *w );
void SplitBrush( brush_t *brush, int planenum, brush_t **front, brush_t **back );
@@ -1542,7 +1585,7 @@ node_t *AllocNode( void );
/* mesh.c */
void LerpDrawVert( bspDrawVert_t *a, bspDrawVert_t *b, bspDrawVert_t *out );
void LerpDrawVert( const bspDrawVert_t *a, const bspDrawVert_t *b, bspDrawVert_t *out );
void LerpDrawVertAmount( bspDrawVert_t *a, bspDrawVert_t *b, float amount, bspDrawVert_t *out );
void FreeMesh( mesh_t *m );
mesh_t *CopyMesh( mesh_t *mesh );
@@ -1560,9 +1603,11 @@ void PutMeshOnCurve( mesh_t in );
/* map.c */
void LoadMapFile( char *filename, bool onlyLights, bool noCollapseGroups );
int FindFloatPlane( vec3_t normal, vec_t dist, int numPoints, vec3_t *points );
bool PlaneEqual( plane_t *p, vec3_t normal, vec_t dist );
int PlaneTypeForNormal( vec3_t normal );
int FindFloatPlane( const Plane3f& plane, int numPoints, const Vector3 *points );
inline int FindFloatPlane( const Vector3& normal, float dist, int numPoints, const Vector3 *points ){
return FindFloatPlane( Plane3f( normal, dist ), numPoints, points );
}
bool PlaneEqual( const plane_t *p, const Plane3f& plane );
void AddBrushBevels( void );
brush_t *FinishBrush( bool noCollapseGroups );
@@ -1634,8 +1679,8 @@ void FixTJunctions( entity_t *e );
/* fog.c */
winding_t *WindingFromDrawSurf( mapDrawSurface_t *ds );
void FogDrawSurfaces( entity_t *e );
int FogForPoint( vec3_t point, float epsilon );
int FogForBounds( vec3_t mins, vec3_t maxs, float epsilon );
int FogForPoint( const Vector3& point, float epsilon );
int FogForBounds( const MinMax& minmax, float epsilon );
void CreateMapFogs( void );
@@ -1650,7 +1695,7 @@ void PicoPrintFunc( int level, const char *str );
void PicoLoadFileFunc( const char *name, byte **buffer, int *bufSize );
picoModel_t *FindModel( const char *name, int frame );
picoModel_t *LoadModel( const char *name, int frame );
void InsertModel( const char *name, int skin, int frame, m4x4_t transform, const std::list<remap_t> *remaps, shaderInfo_t *celShader, int eNum, int castShadows, int recvShadows, int spawnFlags, float lightmapScale, int lightmapSampleSize, float shadeAngle, float clipDepth );
void InsertModel( const char *name, int skin, int frame, const Matrix4& transform, const std::list<remap_t> *remaps, shaderInfo_t *celShader, int eNum, int castShadows, int recvShadows, int spawnFlags, float lightmapScale, int lightmapSampleSize, float shadeAngle, float clipDepth );
void AddTriangleModels( entity_t *e );
@@ -1660,7 +1705,7 @@ void FinishSurface( mapDrawSurface_t *ds );
void StripFaceSurface( mapDrawSurface_t *ds );
void MaxAreaFaceSurface( mapDrawSurface_t *ds );
bool CalcSurfaceTextureRange( mapDrawSurface_t *ds );
bool CalcLightmapAxis( vec3_t normal, vec3_t axis );
bool CalcLightmapAxis( const Vector3& normal, Vector3& axis );
void ClassifySurfaces( int numSurfs, mapDrawSurface_t *ds );
void ClassifyEntitySurfaces( entity_t *e );
void TidyEntitySurfaces( entity_t *e );
@@ -1671,7 +1716,7 @@ void ClearSurface( mapDrawSurface_t *ds );
void AddEntitySurfaceModels( entity_t *e );
mapDrawSurface_t *DrawSurfaceForSide( entity_t *e, brush_t *b, side_t *s, winding_t *w );
mapDrawSurface_t *DrawSurfaceForMesh( entity_t *e, parseMesh_t *p, mesh_t *mesh );
mapDrawSurface_t *DrawSurfaceForFlare( int entNum, vec3_t origin, vec3_t normal, vec3_t color, const char *flareShader, int lightStyle );
mapDrawSurface_t *DrawSurfaceForFlare( int entNum, const Vector3& origin, const Vector3& normal, const Vector3& color, const char *flareShader, int lightStyle );
mapDrawSurface_t *DrawSurfaceForShader( const char *shader );
void ClipSidesIntoTree( entity_t *e, tree_t *tree );
void MakeDebugPortalSurfs( tree_t *tree );
@@ -1715,7 +1760,7 @@ int GetSurfaceExtraRecvShadows( int num );
int GetSurfaceExtraSampleSize( int num );
int GetSurfaceExtraMinSampleSize( int num );
float GetSurfaceExtraLongestCurve( int num );
void GetSurfaceExtraLightmapAxis( int num, vec3_t lightmapAxis );
void GetSurfaceExtraLightmapAxis( int num, Vector3& lightmapAxis );
void WriteSurfaceExtraFile( const char *path );
void LoadSurfaceExtraFile( const char *path );
@@ -1726,11 +1771,7 @@ void ProcessDecals( void );
void MakeEntityDecals( entity_t *e );
/* map.c */
void TextureAxisFromPlane( plane_t *pln, vec3_t xv, vec3_t yv );
/* brush_primit.c */
void ComputeAxisBase( vec3_t normal, vec3_t texX, vec3_t texY );
void TextureAxisFromPlane( const plane_t *pln, Vector3& xv, Vector3& yv );
/* vis.c */
fixedWinding_t *NewFixedWinding( int points );
@@ -1749,9 +1790,9 @@ void PassagePortalFlow( int portalnum );
/* light.c */
float PointToPolygonFormFactor( const vec3_t point, const vec3_t normal, const winding_t *w );
float PointToPolygonFormFactor( const Vector3& point, const Vector3& normal, const winding_t *w );
int LightContributionToSample( trace_t *trace );
void LightingAtSample( trace_t * trace, byte styles[ MAX_LIGHTMAPS ], vec3_t colors[ MAX_LIGHTMAPS ] );
void LightingAtSample( trace_t * trace, byte styles[ MAX_LIGHTMAPS ], Vector3 (&colors)[ MAX_LIGHTMAPS ] );
bool LightContributionToPoint( trace_t *trace );
int LightMain( int argc, char **argv );
@@ -1763,7 +1804,7 @@ float SetupTrace( trace_t *trace );
/* light_bounce.c */
bool RadSampleImage( byte * pixels, int width, int height, float st[ 2 ], float color[ 4 ] );
bool RadSampleImage( byte * pixels, int width, int height, const Vector2& st, Color4f& color );
void RadLightForTriangles( int num, int lightmapNum, rawLightmap_t *lm, shaderInfo_t *si, float scale, float subdivide, clipWork_t *cw );
void RadLightForPatch( int num, int lightmapNum, rawLightmap_t *lm, shaderInfo_t *si, float scale, float subdivide, clipWork_t *cw );
void RadCreateDiffuseLights( void );
@@ -1771,7 +1812,7 @@ void RadFreeLights();
/* light_ydnar.c */
void ColorToBytes( const float *color, byte *colorBytes, float scale );
void ColorToBytes( const Vector3& color, Vector3b& colorBytes, float scale );
void SmoothNormals( void );
void MapRawLightmap( int num );
@@ -1793,14 +1834,14 @@ void SetupBrushesFlags( int mask_any, int test_any, int m
void SetupBrushes( void );
void SetupClusters( void );
bool ClusterVisible( int a, int b );
bool ClusterVisibleToPoint( vec3_t point, int cluster );
int ClusterForPoint( vec3_t point );
int ClusterForPointExt( vec3_t point, float epsilon );
int ClusterForPointExtFilter( vec3_t point, float epsilon, int numClusters, int *clusters );
int ShaderForPointInLeaf( vec3_t point, int leafNum, float epsilon, int wantContentFlags, int wantSurfaceFlags, int *contentFlags, int *surfaceFlags );
bool ClusterVisibleToPoint( const Vector3& point, int cluster );
int ClusterForPoint( const Vector3& point );
int ClusterForPointExt( const Vector3& point, float epsilon );
int ClusterForPointExtFilter( const Vector3& point, float epsilon, int numClusters, int *clusters );
int ShaderForPointInLeaf( const Vector3& point, int leafNum, float epsilon, int wantContentFlags, int wantSurfaceFlags, int *contentFlags, int *surfaceFlags );
void SetupEnvelopes( bool forGrid, bool fastFlag );
void FreeTraceLights( trace_t *trace );
void CreateTraceLightsForBounds( vec3_t mins, vec3_t maxs, vec3_t normal, int numClusters, int *clusters, LightFlags flags, trace_t *trace );
void CreateTraceLightsForBounds( const MinMax& minmax, const Vector3 *normal, int numClusters, int *clusters, LightFlags flags, trace_t *trace );
void CreateTraceLightsForSurface( int num, trace_t *trace );
@@ -1829,7 +1870,7 @@ image_t *ImageLoad( const char *filename );
/* shaders.c */
void ColorMod( colorMod_t *am, int numVerts, bspDrawVert_t *drawVerts );
void TCMod( tcMod_t mod, float st[ 2 ] );
void TCMod( tcMod_t mod, Vector2& st );
void TCModIdentity( tcMod_t mod );
void TCModMultiply( tcMod_t a, tcMod_t b, tcMod_t out );
void TCModTranslate( tcMod_t mod, float s, float t );
@@ -2085,7 +2126,7 @@ Q_EXTERN plane_t *mapplanes Q_ASSIGN( NULL ); /* mapplanes[ num ^ 1
Q_EXTERN int nummapplanes Q_ASSIGN( 0 ); /* nummapplanes will always be even */
Q_EXTERN int allocatedmapplanes Q_ASSIGN( 0 );
Q_EXTERN int numMapPatches;
Q_EXTERN vec3_t mapMins, mapMaxs;
Q_EXTERN MinMax g_mapMinmax;
Q_EXTERN int defaultFogNum Q_ASSIGN( -1 ); /* ydnar: cleaner fog handling */
Q_EXTERN int numMapFogs Q_ASSIGN( 0 );
@@ -2114,7 +2155,7 @@ Q_EXTERN int numRedundantIndexes;
Q_EXTERN int numSurfaceModels Q_ASSIGN( 0 );
Q_EXTERN byte debugColors[ 12 ][ 3 ]
Q_EXTERN Vector3b debugColors[ 12 ]
#ifndef MAIN_C
;
#else
@@ -2136,7 +2177,7 @@ Q_EXTERN byte debugColors[ 12 ][ 3 ]
#endif
Q_EXTERN int skyboxArea Q_ASSIGN( -1 );
Q_EXTERN m4x4_t skyboxTransform;
Q_EXTERN Matrix4 skyboxTransform;
@@ -2255,7 +2296,7 @@ Q_EXTERN float dirtGain Q_ASSIGN( 1.0f );
Q_EXTERN bool debugnormals Q_ASSIGN( false );
Q_EXTERN bool floodlighty Q_ASSIGN( false );
Q_EXTERN bool floodlight_lowquality Q_ASSIGN( false );
Q_EXTERN vec3_t floodlightRGB;
Q_EXTERN Vector3 floodlightRGB;
Q_EXTERN float floodlightIntensity Q_ASSIGN( 512.0f );
Q_EXTERN float floodlightDistance Q_ASSIGN( 1024.0f );
Q_EXTERN float floodlightDirectionScale Q_ASSIGN( 1.0f );
@@ -2343,15 +2384,15 @@ Q_EXTERN FILE *dumpFile;
Q_EXTERN int defaultLightSubdivide Q_ASSIGN( 999 );
Q_EXTERN vec3_t ambientColor;
Q_EXTERN vec3_t minLight, minVertexLight, minGridLight;
Q_EXTERN Vector3 ambientColor;
Q_EXTERN Vector3 minLight, minVertexLight, minGridLight;
Q_EXTERN float maxLight Q_ASSIGN( 255.f );
Q_EXTERN int *entitySurface;
Q_EXTERN vec3_t *surfaceOrigin;
Q_EXTERN Vector3 *surfaceOrigin;
Q_EXTERN vec3_t sunDirection;
Q_EXTERN vec3_t sunLight;
Q_EXTERN Vector3 sunDirection;
Q_EXTERN Vector3 sunLight;
/* ydnar: light optimization */
Q_EXTERN float subdivideThreshold Q_ASSIGN( DEFAULT_SUBDIVIDE_THRESHOLD );
@@ -2392,8 +2433,15 @@ Q_EXTERN rawLightmap_t *rawLightmaps Q_ASSIGN( NULL );
Q_EXTERN int *sortLightmaps Q_ASSIGN( NULL );
/* vertex luxels */
Q_EXTERN float *vertexLuxels[ MAX_LIGHTMAPS ];
Q_EXTERN float *radVertexLuxels[ MAX_LIGHTMAPS ];
Q_EXTERN Vector3 *vertexLuxels[ MAX_LIGHTMAPS ];
Q_EXTERN Vector3 *radVertexLuxels[ MAX_LIGHTMAPS ];
inline Vector3& getVertexLuxel( int lightmapNum, int vertexNum ){
return vertexLuxels[lightmapNum][vertexNum];
}
inline Vector3& getRadVertexLuxel( int lightmapNum, int vertexNum ){
return radVertexLuxels[lightmapNum][vertexNum];
}
/* bsp lightmaps */
Q_EXTERN int numLightmapShaders Q_ASSIGN( 0 );
@@ -2426,9 +2474,9 @@ Q_EXTERN int numLuxelsIlluminated Q_ASSIGN( 0 );
Q_EXTERN int numVertsIlluminated Q_ASSIGN( 0 );
/* lightgrid */
Q_EXTERN vec3_t gridMins;
Q_EXTERN Vector3 gridMins;
Q_EXTERN int gridBounds[ 3 ];
Q_EXTERN vec3_t gridSize
Q_EXTERN Vector3 gridSize
#ifndef MAIN_C
;
#else
+67 -80
View File
@@ -41,7 +41,7 @@
void ColorMod( colorMod_t *cm, int numVerts, bspDrawVert_t *drawVerts ){
int i, j, k;
float c;
vec4_t mult, add;
Vector4 mult, add;
bspDrawVert_t *dv;
colorMod_t *cm2;
@@ -62,17 +62,16 @@ void ColorMod( colorMod_t *cm, int numVerts, bspDrawVert_t *drawVerts ){
for ( cm2 = cm; cm2 != NULL; cm2 = cm2->next )
{
/* default */
VectorSet( mult, 1.0f, 1.0f, 1.0f );
mult[ 3 ] = 1.0f;
VectorSet( add, 0.0f, 0.0f, 0.0f );
add[ 3 ] = 0.0f;
mult.set( 1 );
add.set( 0 );
const Vector3 cm2_data = vector3_from_array( cm2->data );
/* switch on type */
switch ( cm2->type )
{
case EColorMod::ColorSet:
VectorClear( mult );
VectorScale( cm2->data, 255.0f, add );
mult.vec3().set( 0 );
add.vec3() = cm2_data * 255.0f;
break;
case EColorMod::AlphaSet:
@@ -81,7 +80,7 @@ void ColorMod( colorMod_t *cm, int numVerts, bspDrawVert_t *drawVerts ){
break;
case EColorMod::ColorScale:
VectorCopy( cm2->data, mult );
mult.vec3() = cm2_data;
break;
case EColorMod::AlphaScale:
@@ -89,46 +88,46 @@ void ColorMod( colorMod_t *cm, int numVerts, bspDrawVert_t *drawVerts ){
break;
case EColorMod::ColorDotProduct:
c = DotProduct( dv->normal, cm2->data );
VectorSet( mult, c, c, c );
c = vector3_dot( dv->normal, cm2_data );
mult.vec3().set( c );
break;
case EColorMod::ColorDotProductScale:
c = DotProduct( dv->normal, cm2->data );
c = vector3_dot( dv->normal, cm2_data );
c = ( c - cm2->data[3] ) / ( cm2->data[4] - cm2->data[3] );
VectorSet( mult, c, c, c );
mult.vec3().set( c );
break;
case EColorMod::AlphaDotProduct:
mult[ 3 ] = DotProduct( dv->normal, cm2->data );
mult[ 3 ] = vector3_dot( dv->normal, cm2_data );
break;
case EColorMod::AlphaDotProductScale:
c = DotProduct( dv->normal, cm2->data );
c = vector3_dot( dv->normal, cm2_data );
c = ( c - cm2->data[3] ) / ( cm2->data[4] - cm2->data[3] );
mult[ 3 ] = c;
break;
case EColorMod::ColorDotProduct2:
c = DotProduct( dv->normal, cm2->data );
c = vector3_dot( dv->normal, cm2_data );
c *= c;
VectorSet( mult, c, c, c );
mult.vec3().set( c );
break;
case EColorMod::ColorDotProduct2Scale:
c = DotProduct( dv->normal, cm2->data );
c = vector3_dot( dv->normal, cm2_data );
c *= c;
c = ( c - cm2->data[3] ) / ( cm2->data[4] - cm2->data[3] );
VectorSet( mult, c, c, c );
mult.vec3().set( c );
break;
case EColorMod::AlphaDotProduct2:
mult[ 3 ] = DotProduct( dv->normal, cm2->data );
mult[ 3 ] = vector3_dot( dv->normal, cm2_data );
mult[ 3 ] *= mult[ 3 ];
break;
case EColorMod::AlphaDotProduct2Scale:
c = DotProduct( dv->normal, cm2->data );
c = vector3_dot( dv->normal, cm2_data );
c *= c;
c = ( c - cm2->data[3] ) / ( cm2->data[4] - cm2->data[3] );
mult[ 3 ] = c;
@@ -164,7 +163,7 @@ void ColorMod( colorMod_t *cm, int numVerts, bspDrawVert_t *drawVerts ){
routines for dealing with a 3x3 texture mod matrix
*/
void TCMod( tcMod_t mod, float st[ 2 ] ){
void TCMod( tcMod_t mod, Vector2& st ){
float old[ 2 ];
@@ -215,7 +214,7 @@ void TCModRotate( tcMod_t mod, float euler ){
memcpy( old, mod, sizeof( tcMod_t ) );
TCModIdentity( temp );
radians = euler / 180 * Q_PI;
radians = degrees_to_radians( euler );
sinv = sin( radians );
cosv = cos( radians );
@@ -663,8 +662,7 @@ static shaderInfo_t *AllocShaderInfo( void ){
void FinishShader( shaderInfo_t *si ){
int x, y;
float st[ 2 ], o[ 2 ], dist, bestDist;
vec4_t color, delta;
Vector2 st;
/* don't double-dip */
@@ -682,28 +680,26 @@ void FinishShader( shaderInfo_t *si ){
if ( si->legacyTerrain && !si->tcGen ) {
/* set xy texture projection */
si->tcGen = true;
VectorSet( si->vecs[ 0 ], ( 1.0f / ( si->shaderWidth * 0.5f ) ), 0, 0 );
VectorSet( si->vecs[ 1 ], 0, ( 1.0f / ( si->shaderHeight * 0.5f ) ), 0 );
si->vecs[ 0 ] = { ( 1.0f / ( si->shaderWidth * 0.5f ) ), 0, 0 };
si->vecs[ 1 ] = { 0, ( 1.0f / ( si->shaderHeight * 0.5f ) ), 0 };
}
/* find pixel coordinates best matching the average color of the image */
bestDist = 99999999;
o[ 0 ] = 1.0f / si->shaderImage->width;
o[ 1 ] = 1.0f / si->shaderImage->height;
float bestDist = 99999999;
const Vector2 o( 1.0f / si->shaderImage->width, 1.0f / si->shaderImage->height );
for ( y = 0, st[ 1 ] = 0.0f; y < si->shaderImage->height; y++, st[ 1 ] += o[ 1 ] )
{
for ( x = 0, st[ 0 ] = 0.0f; x < si->shaderImage->width; x++, st[ 0 ] += o[ 0 ] )
{
/* sample the shader image */
Color4f color;
RadSampleImage( si->shaderImage->pixels, si->shaderImage->width, si->shaderImage->height, st, color );
/* determine error squared */
VectorSubtract( color, si->averageColor, delta );
delta[ 3 ] = color[ 3 ] - si->averageColor[ 3 ];
dist = delta[ 0 ] * delta[ 0 ] + delta[ 1 ] * delta[ 1 ] + delta[ 2 ] * delta[ 2 ] + delta[ 3 ] * delta[ 3 ];
const Color4f delta = color - si->averageColor;
const float dist = vector4_dot( delta, delta );
if ( dist < bestDist ) {
si->stFlat[ 0 ] = st[ 0 ];
si->stFlat[ 1 ] = st[ 1 ];
si->stFlat = st;
}
}
}
@@ -725,9 +721,6 @@ void FinishShader( shaderInfo_t *si ){
*/
static void LoadShaderImages( shaderInfo_t *si ){
int i, count;
float color[ 4 ];
/* nodraw shaders don't need images */
if ( si->compileFlags & C_NODRAW ) {
@@ -779,10 +772,9 @@ static void LoadShaderImages( shaderInfo_t *si ){
}
/* create default and average colors */
count = si->lightImage->width * si->lightImage->height;
VectorClear( color );
color[ 3 ] = 0.0f;
for ( i = 0; i < count; i++ )
const int count = si->lightImage->width * si->lightImage->height;
Color4f color( 0, 0, 0, 0 );
for ( int i = 0; i < count; i++ )
{
color[ 0 ] += si->lightImage->pixels[ i * 4 + 0 ];
color[ 1 ] += si->lightImage->pixels[ i * 4 + 1 ];
@@ -790,15 +782,15 @@ static void LoadShaderImages( shaderInfo_t *si ){
color[ 3 ] += si->lightImage->pixels[ i * 4 + 3 ];
}
if ( VectorLength( si->color ) <= 0.0f ) {
ColorNormalize( color, si->color );
VectorScale( color, ( 1.0f / count ), si->averageColor );
si->averageColor[ 3 ] = color[ 3 ] / count;
if ( vector3_length( si->color ) == 0.0f ) {
si->color = color.rgb();
ColorNormalize( si->color );
si->averageColor = color / count;
}
else
{
VectorCopy( si->color, si->averageColor );
si->averageColor[ 3 ] = 1.0f;
si->averageColor.rgb() = si->color;
si->averageColor.alpha() = 1.0f;
}
}
@@ -921,14 +913,12 @@ bool GetTokenAppend( char *buffer, bool crossline ){
}
void Parse1DMatrixAppend( char *buffer, int x, vec_t *m ){
int i;
void Parse1DMatrixAppend( char *buffer, int x, float *m ){
if ( !GetTokenAppend( buffer, true ) || !strEqual( token, "(" ) ) {
Error( "Parse1DMatrixAppend(): line %d: ( not found!\nFile location be: %s\n", scriptline, g_strLoadedFileLocation );
}
for ( i = 0; i < x; i++ )
for ( int i = 0; i < x; i++ )
{
if ( !GetTokenAppend( buffer, false ) ) {
Error( "Parse1DMatrixAppend(): line %d: Number not found!\nFile location be: %s\n", scriptline, g_strLoadedFileLocation );
@@ -968,7 +958,7 @@ static void ParseShaderFile( const char *filename ){
if ( si != NULL && !strEmpty( shaderText ) ) {
strcat( shaderText, "\n" );
si->shaderText = copystring( shaderText );
//% if( VectorLength( si->vecs[ 0 ] ) )
//% if( vector3_length( si->vecs[ 0 ] ) )
//% Sys_Printf( "%s\n", shaderText );
}
@@ -1119,7 +1109,7 @@ static void ParseShaderFile( const char *filename ){
/* deformVertexes move <x> <y> <z> <func> <base> <amplitude> <phase> <freq> (ydnar: for particle studio support) */
if ( striEqual( token, "move" ) ) {
vec3_t amt, mins, maxs;
Vector3 amt;
float base, amp;
@@ -1136,10 +1126,10 @@ static void ParseShaderFile( const char *filename ){
GetTokenAppend( shaderText, false ); amp = atof( token );
/* calculate */
VectorScale( amt, base, mins );
VectorMA( mins, amp, amt, maxs );
VectorAdd( si->mins, mins, si->mins );
VectorAdd( si->maxs, maxs, si->maxs );
const Vector3 mins = amt * base;
const Vector3 maxs = amt * amp + mins;
si->minmax.mins += mins;
si->minmax.maxs += maxs;
}
}
@@ -1271,7 +1261,7 @@ static void ParseShaderFile( const char *filename ){
}
/* normalize it */
ColorNormalize( sun->color, sun->color );
ColorNormalize( sun->color );
/* scale color by brightness */
GetTokenAppend( shaderText, false );
@@ -1279,12 +1269,10 @@ static void ParseShaderFile( const char *filename ){
/* get sun angle/elevation */
GetTokenAppend( shaderText, false );
a = atof( token );
a = a / 180.0f * Q_PI;
a = degrees_to_radians( atof( token ) );
GetTokenAppend( shaderText, false );
b = atof( token );
b = b / 180.0f * Q_PI;
b = degrees_to_radians( atof( token ) );
sun->direction[ 0 ] = cos( a ) * cos( b );
sun->direction[ 1 ] = sin( a ) * cos( b );
@@ -1296,8 +1284,7 @@ static void ParseShaderFile( const char *filename ){
/* ydnar: get sun angular deviance/samples */
if ( ext && TokenAvailable() ) {
GetTokenAppend( shaderText, false );
sun->deviance = atof( token );
sun->deviance = sun->deviance / 180.0f * Q_PI;
sun->deviance = degrees_to_radians( atof( token ) );
GetTokenAppend( shaderText, false );
sun->numSamples = atoi( token );
@@ -1436,7 +1423,7 @@ static void ParseShaderFile( const char *filename ){
/* wolf: q3map_lightRGB <red> <green> <blue> */
else if ( striEqual( token, "q3map_lightRGB" ) ) {
VectorClear( si->color );
si->color.set( 0 );
GetTokenAppend( shaderText, false );
si->color[ 0 ] = atof( token );
GetTokenAppend( shaderText, false );
@@ -1448,7 +1435,7 @@ static void ParseShaderFile( const char *filename ){
si->color[1] = Image_LinearFloatFromsRGBFloat( si->color[1] );
si->color[2] = Image_LinearFloatFromsRGBFloat( si->color[2] );
}
ColorNormalize( si->color, si->color );
ColorNormalize( si->color );
}
/* q3map_lightSubdivide <value> */
@@ -1485,7 +1472,7 @@ static void ParseShaderFile( const char *filename ){
si->floodlightRGB[1] = Image_LinearFloatFromsRGBFloat( si->floodlightRGB[1] );
si->floodlightRGB[2] = Image_LinearFloatFromsRGBFloat( si->floodlightRGB[2] );
}
ColorNormalize( si->floodlightRGB, si->floodlightRGB );
ColorNormalize( si->floodlightRGB );
}
/* jal: q3map_nodirty : skip dirty */
@@ -1517,18 +1504,18 @@ static void ParseShaderFile( const char *filename ){
else if ( striEqual( token, "q3map_lightmapAxis" ) ) {
GetTokenAppend( shaderText, false );
if ( striEqual( token, "x" ) ) {
VectorSet( si->lightmapAxis, 1, 0, 0 );
si->lightmapAxis = g_vector3_axis_x;
}
else if ( striEqual( token, "y" ) ) {
VectorSet( si->lightmapAxis, 0, 1, 0 );
si->lightmapAxis = g_vector3_axis_y;
}
else if ( striEqual( token, "z" ) ) {
VectorSet( si->lightmapAxis, 0, 0, 1 );
si->lightmapAxis = g_vector3_axis_z;
}
else
{
Sys_Warning( "Unknown value for lightmap axis: %s\n", token );
VectorClear( si->lightmapAxis );
si->lightmapAxis.set( 0 );
}
}
@@ -1636,7 +1623,7 @@ static void ParseShaderFile( const char *filename ){
si->nonplanar = true;
si->forceMeta = true;
si->shadeAngleDegrees = 179.0f;
//% VectorSet( si->lightmapAxis, 0, 0, 1 ); /* ydnar 2002-09-21: turning this off for better lightmapping of cliff faces */
//% si->lightmapAxis = g_vector3_axis_z; /* ydnar 2002-09-21: turning this off for better lightmapping of cliff faces */
}
/* ydnar: picomodel: q3map_forceMeta (forces brush faces and/or triangle models to go through the metasurface pipeline) */
@@ -1665,14 +1652,14 @@ static void ParseShaderFile( const char *filename ){
/* q3map_tcGen vector <s vector> <t vector> */
if ( striEqual( token, "vector" ) ) {
Parse1DMatrixAppend( shaderText, 3, si->vecs[ 0 ] );
Parse1DMatrixAppend( shaderText, 3, si->vecs[ 1 ] );
Parse1DMatrixAppend( shaderText, 3, si->vecs[ 0 ].data() );
Parse1DMatrixAppend( shaderText, 3, si->vecs[ 1 ].data() );
}
/* q3map_tcGen ivector <1.0/s vector> <1.0/t vector> (inverse vector, easier for mappers to understand) */
else if ( striEqual( token, "ivector" ) ) {
Parse1DMatrixAppend( shaderText, 3, si->vecs[ 0 ] );
Parse1DMatrixAppend( shaderText, 3, si->vecs[ 1 ] );
Parse1DMatrixAppend( shaderText, 3, si->vecs[ 0 ].data() );
Parse1DMatrixAppend( shaderText, 3, si->vecs[ 1 ].data() );
for ( i = 0; i < 3; i++ )
{
si->vecs[ 0 ][ i ] = si->vecs[ 0 ][ i ] ? 1.0 / si->vecs[ 0 ][ i ] : 0;
@@ -1682,8 +1669,8 @@ static void ParseShaderFile( const char *filename ){
else
{
Sys_Warning( "Unknown q3map_tcGen method: %s\n", token );
VectorClear( si->vecs[ 0 ] );
VectorClear( si->vecs[ 1 ] );
si->vecs[ 0 ].set( 0 );
si->vecs[ 1 ].set( 0 );
}
}
@@ -1825,8 +1812,8 @@ static void ParseShaderFile( const char *filename ){
/* q3map_fogDir (direction a fog shader fades from transparent to opaque) */
else if ( striEqual( token, "q3map_fogDir" ) ) {
Parse1DMatrixAppend( shaderText, 3, si->fogDir );
VectorNormalize( si->fogDir, si->fogDir );
Parse1DMatrixAppend( shaderText, 3, si->fogDir.data() );
VectorNormalize( si->fogDir );
}
/* q3map_globaltexture */
File diff suppressed because it is too large Load Diff
+5 -5
View File
@@ -48,7 +48,7 @@ struct surfaceExtra_t
int castShadows, recvShadows;
int sampleSize;
float longestCurve;
vec3_t lightmapAxis;
Vector3 lightmapAxis;
};
#define GROW_SURFACE_EXTRAS 1024
@@ -117,7 +117,7 @@ void SetSurfaceExtra( mapDrawSurface_t *ds, int num ){
se->recvShadows = ds->recvShadows;
se->sampleSize = ds->sampleSize;
se->longestCurve = ds->longestCurve;
VectorCopy( ds->lightmapAxis, se->lightmapAxis );
se->lightmapAxis = ds->lightmapAxis;
/* debug code */
//% Sys_FPrintf( SYS_VRB, "SetSurfaceExtra(): entityNum = %d\n", ds->entityNum );
@@ -180,9 +180,9 @@ float GetSurfaceExtraLongestCurve( int num ){
}
void GetSurfaceExtraLightmapAxis( int num, vec3_t lightmapAxis ){
void GetSurfaceExtraLightmapAxis( int num, Vector3& lightmapAxis ){
surfaceExtra_t *se = GetSurfaceExtra( num );
VectorCopy( se->lightmapAxis, lightmapAxis );
lightmapAxis = se->lightmapAxis;
}
@@ -402,7 +402,7 @@ void LoadSurfaceExtraFile( const char *path ){
/* lightmap axis vector */
else if ( striEqual( token, "lightmapAxis" ) ) {
Parse1DMatrix( 3, se->lightmapAxis );
Parse1DMatrix( 3, se->lightmapAxis.data() );
}
/* ignore all other tokens on the line */
+16 -26
View File
@@ -57,8 +57,7 @@ static void SubdivideFoliageTriangle_r( mapDrawSurface_t *ds, const foliage_t& f
/* plane test */
{
vec4_t plane;
Plane3f plane;
/* make a plane */
if ( !PlaneFromPoints( plane, tri[ 0 ]->xyz, tri[ 1 ]->xyz, tri[ 2 ]->xyz ) ) {
@@ -66,7 +65,7 @@ static void SubdivideFoliageTriangle_r( mapDrawSurface_t *ds, const foliage_t& f
}
/* if normal is too far off vertical, then don't place an instance */
if ( plane[ 2 ] < 0.5f ) {
if ( plane.normal().z() < 0.5f ) {
return;
}
}
@@ -74,7 +73,7 @@ static void SubdivideFoliageTriangle_r( mapDrawSurface_t *ds, const foliage_t& f
/* subdivide calc */
{
int i;
float *a, *b, dx, dy, dz, dist, maxDist;
float dx, dy, dz, dist, maxDist;
foliageInstance_t *fi;
@@ -84,13 +83,13 @@ static void SubdivideFoliageTriangle_r( mapDrawSurface_t *ds, const foliage_t& f
/* find the longest edge and split it */
max = -1;
maxDist = 0.0f;
VectorClear( fi->xyz );
VectorClear( fi->normal );
fi->xyz.set( 0 );
fi->normal.set( 0 );
for ( i = 0; i < 3; i++ )
{
/* get verts */
a = tri[ i ]->xyz;
b = tri[ ( i + 1 ) % 3 ]->xyz;
const Vector3& a = tri[ i ]->xyz;
const Vector3& b = tri[ ( i + 1 ) % 3 ]->xyz;
/* get dists */
dx = a[ 0 ] - b[ 0 ];
@@ -105,8 +104,8 @@ static void SubdivideFoliageTriangle_r( mapDrawSurface_t *ds, const foliage_t& f
}
/* add to centroid */
VectorAdd( fi->xyz, tri[ i ]->xyz, fi->xyz );
VectorAdd( fi->normal, tri[ i ]->normal, fi->normal );
fi->xyz += tri[ i ]->xyz;
fi->normal += tri[ i ]->normal;
}
/* is the triangle small enough? */
@@ -120,7 +119,7 @@ static void SubdivideFoliageTriangle_r( mapDrawSurface_t *ds, const foliage_t& f
}
else
{
alpha = ( (float) tri[ 0 ]->color[ 0 ][ 3 ] + (float) tri[ 1 ]->color[ 0 ][ 3 ] + (float) tri[ 2 ]->color[ 0 ][ 3 ] ) / 765.0f;
alpha = ( (float) tri[ 0 ]->color[ 0 ].alpha() + (float) tri[ 1 ]->color[ 0 ].alpha() + (float) tri[ 2 ]->color[ 0 ].alpha() ) / 765.0f;
if ( foliage.inverseAlpha == 1 ) {
alpha = 1.0f - alpha;
}
@@ -137,8 +136,8 @@ static void SubdivideFoliageTriangle_r( mapDrawSurface_t *ds, const foliage_t& f
}
/* scale centroid */
VectorScale( fi->xyz, 0.33333333f, fi->xyz );
if ( VectorNormalize( fi->normal, fi->normal ) == 0.0f ) {
fi->xyz *= 0.33333333f;
if ( VectorNormalize( fi->normal ) == 0.0f ) {
return;
}
@@ -175,8 +174,6 @@ void Foliage( mapDrawSurface_t *src ){
shaderInfo_t *si;
mesh_t srcMesh, *subdivided, *mesh;
bspDrawVert_t *verts, *dv[ 3 ], *fi;
vec3_t scale;
m4x4_t transform;
/* get shader */
@@ -270,12 +267,8 @@ void Foliage( mapDrawSurface_t *src ){
/* remember surface count */
oldNumMapDrawSurfs = numMapDrawSurfs;
/* set transform matrix */
VectorSet( scale, foliage.scale, foliage.scale, foliage.scale );
m4x4_scale_for_vec3( transform, scale );
/* add the model to the bsp */
InsertModel( foliage.model.c_str(), 0, 0, transform, NULL, NULL, src->entityNum, src->castShadows, src->recvShadows, 0, src->lightmapScale, 0, 0, clipDepthGlobal );
InsertModel( foliage.model.c_str(), 0, 0, matrix4_scale_for_vec3( Vector3().set( foliage.scale ) ), NULL, NULL, src->entityNum, src->castShadows, src->recvShadows, 0, src->lightmapScale, 0, 0, clipDepthGlobal );
/* walk each new surface */
for ( i = oldNumMapDrawSurfs; i < numMapDrawSurfs; i++ )
@@ -307,16 +300,13 @@ void Foliage( mapDrawSurface_t *src ){
fi = &ds->verts[ ds->numVerts + j ];
/* copy xyz and normal */
VectorCopy( foliageInstances[ j ].xyz, fi->xyz );
VectorCopy( foliageInstances[ j ].normal, fi->normal );
fi->xyz = foliageInstances[ j ].xyz;
fi->normal = foliageInstances[ j ].normal;
/* ydnar: set color */
for ( k = 0; k < MAX_LIGHTMAPS; k++ )
{
fi->color[ k ][ 0 ] = 255;
fi->color[ k ][ 1 ] = 255;
fi->color[ k ][ 2 ] = 255;
fi->color[ k ][ 3 ] = 255;
fi->color[ k ].set( 255 );
}
}
+6 -14
View File
@@ -73,10 +73,10 @@ void Fur( mapDrawSurface_t *ds ){
dv = &ds->verts[ j ];
/* offset is scaled by original vertex alpha */
a = (float) dv->color[ 0 ][ 3 ] / 255.0;
a = (float) dv->color[ 0 ].alpha() / 255.0;
/* offset it */
VectorMA( dv->xyz, ( offset * a ), dv->normal, dv->xyz );
dv->xyz += dv->normal * ( offset * a );
}
/* wash, rinse, repeat */
@@ -98,27 +98,19 @@ void Fur( mapDrawSurface_t *ds ){
dv = &ds->verts[ j ];
/* offset is scaled by original vertex alpha */
a = (float) dv->color[ 0 ][ 3 ] / 255.0;
a = (float) dv->color[ 0 ].alpha() / 255.0;
/* get fur vert */
dv = &fur->verts[ j ];
/* offset it */
VectorMA( dv->xyz, ( offset * a * i ), dv->normal, dv->xyz );
dv->xyz += dv->normal * ( offset * a * i );
/* fade alpha */
for ( k = 0; k < MAX_LIGHTMAPS; k++ )
{
a = (float) dv->color[ k ][ 3 ] - fade;
if ( a > 255.0f ) {
dv->color[ k ][ 3 ] = 255;
}
else if ( a < 0 ) {
dv->color[ k ][ 3 ] = 0;
}
else{
dv->color[ k ][ 3 ] = a;
}
a = (float) dv->color[ k ].alpha() - fade;
dv->color[ k ].alpha() = ( a > 255.0f )? 255 : ( a < 0 )? 0 : a;
}
}
}
+97 -150
View File
@@ -123,21 +123,15 @@ static int AddMetaTriangle( void ){
int FindMetaTriangle( metaTriangle_t *src, bspDrawVert_t *a, bspDrawVert_t *b, bspDrawVert_t *c, int planeNum ){
int triIndex;
vec3_t dir;
/* detect degenerate triangles fixme: do something proper here */
VectorSubtract( a->xyz, b->xyz, dir );
if ( VectorLength( dir ) < 0.125f ) {
if ( vector3_length( a->xyz - b->xyz ) < 0.125f ) {
return -1;
}
VectorSubtract( b->xyz, c->xyz, dir );
if ( VectorLength( dir ) < 0.125f ) {
if ( vector3_length( b->xyz - c->xyz ) < 0.125f ) {
return -1;
}
VectorSubtract( c->xyz, a->xyz, dir );
if ( VectorLength( dir ) < 0.125f ) {
if ( vector3_length( c->xyz - a->xyz ) < 0.125f ) {
return -1;
}
@@ -145,8 +139,7 @@ int FindMetaTriangle( metaTriangle_t *src, bspDrawVert_t *a, bspDrawVert_t *b, b
if ( planeNum >= 0 ) {
/* because of precision issues with small triangles, try to use the specified plane */
src->planeNum = planeNum;
VectorCopy( mapplanes[ planeNum ].normal, src->plane );
src->plane[ 3 ] = mapplanes[ planeNum ].dist;
src->plane = mapplanes[ planeNum ].plane;
}
else
{
@@ -158,14 +151,14 @@ int FindMetaTriangle( metaTriangle_t *src, bspDrawVert_t *a, bspDrawVert_t *b, b
}
/* ydnar 2002-10-03: repair any bogus normals (busted ase import kludge) */
if ( VectorLength( a->normal ) <= 0.0f ) {
VectorCopy( src->plane, a->normal );
if ( vector3_length( a->normal ) == 0.0f ) {
a->normal = src->plane.normal();
}
if ( VectorLength( b->normal ) <= 0.0f ) {
VectorCopy( src->plane, b->normal );
if ( vector3_length( b->normal ) == 0.0f ) {
b->normal = src->plane.normal();
}
if ( VectorLength( c->normal ) <= 0.0f ) {
VectorCopy( src->plane, c->normal );
if ( vector3_length( c->normal ) == 0.0f ) {
c->normal = src->plane.normal();
}
/* ydnar 2002-10-04: set lightmap axis if not already set */
@@ -173,12 +166,12 @@ int FindMetaTriangle( metaTriangle_t *src, bspDrawVert_t *a, bspDrawVert_t *b, b
src->lightmapAxis[ 0 ] == 0.0f && src->lightmapAxis[ 1 ] == 0.0f && src->lightmapAxis[ 2 ] == 0.0f ) {
/* the shader can specify an explicit lightmap axis */
if ( src->si->lightmapAxis[ 0 ] || src->si->lightmapAxis[ 1 ] || src->si->lightmapAxis[ 2 ] ) {
VectorCopy( src->si->lightmapAxis, src->lightmapAxis );
src->lightmapAxis = src->si->lightmapAxis;
}
/* new axis-finding code */
else{
CalcLightmapAxis( src->plane, src->lightmapAxis );
CalcLightmapAxis( src->plane.normal(), src->lightmapAxis );
}
}
@@ -261,7 +254,7 @@ static void SurfaceToMetaTriangles( mapDrawSurface_t *ds ){
src.fogNum = ds->fogNum;
src.sampleSize = ds->sampleSize;
src.shadeAngleDegrees = ds->shadeAngleDegrees;
VectorCopy( ds->lightmapAxis, src.lightmapAxis );
src.lightmapAxis = ds->lightmapAxis;
/* copy drawverts */
memcpy( &a, &ds->verts[ ds->indexes[ i ] ], sizeof( a ) );
@@ -385,7 +378,6 @@ int MaxAreaIndexes( bspDrawVert_t *vert, int cnt, int *indexes ){
int r, s, t, bestR = 0, bestS = 1, bestT = 2;
int i, j;
double A, bestA = -1, V, bestV = -1;
vec3_t ab, ac, bc, cross;
bspDrawVert_t *buf;
double shiftWidth;
@@ -397,16 +389,12 @@ int MaxAreaIndexes( bspDrawVert_t *vert, int cnt, int *indexes ){
A = 0;
for ( i = 1; i + 1 < cnt; ++i )
{
VectorSubtract( vert[i].xyz, vert[0].xyz, ab );
VectorSubtract( vert[i + 1].xyz, vert[0].xyz, ac );
CrossProduct( ab, ac, cross );
A += VectorLength( cross );
A += vector3_length( vector3_cross( vert[i].xyz - vert[0].xyz, vert[i + 1].xyz - vert[0].xyz ) );
}
V = 0;
for ( i = 0; i < cnt; ++i )
{
VectorSubtract( vert[( i + 1 ) % cnt].xyz, vert[i].xyz, ab );
V += VectorLength( ab );
V += vector3_length( vert[( i + 1 ) % cnt].xyz - vert[i].xyz );
}
/* calculate shift width from the area sensibly, assuming the polygon
@@ -429,13 +417,12 @@ int MaxAreaIndexes( bspDrawVert_t *vert, int cnt, int *indexes ){
for ( s = r + 1; s + 1 < cnt; ++s )
for ( t = s + 1; t < cnt; ++t )
{
VectorSubtract( vert[s].xyz, vert[r].xyz, ab );
VectorSubtract( vert[t].xyz, vert[r].xyz, ac );
VectorSubtract( vert[t].xyz, vert[s].xyz, bc );
CrossProduct( ab, ac, cross );
A = VectorLength( cross );
const Vector3 ab = vert[s].xyz - vert[r].xyz;
const Vector3 ac = vert[t].xyz - vert[r].xyz;
const Vector3 bc = vert[t].xyz - vert[s].xyz;
A = vector3_length( vector3_cross( ab, ac ) );
V = A - ( VectorLength( ab ) - VectorLength( ac ) - VectorLength( bc ) ) * shiftWidth;
V = A - ( vector3_length( ab ) - vector3_length( ac ) - vector3_length( bc ) ) * shiftWidth;
/* value = A - circumference * shiftWidth, i.e. we back out by shiftWidth units from each side, to prevent too acute triangles */
/* this kind of simulates "number of shiftWidth*shiftWidth fragments in the triangle not touched by an edge" */
@@ -483,10 +470,7 @@ int MaxAreaIndexes( bspDrawVert_t *vert, int cnt, int *indexes ){
}
// abc abc abc abc abc abc
VectorSubtract( vert[bestS].xyz, vert[bestR].xyz, ab );
VectorSubtract( vert[bestT].xyz, vert[bestR].xyz, ac );
CrossProduct( ab, ac, cross );
bestA = VectorLength( cross );
bestA = vector3_length( vector3_cross( vert[bestS].xyz - vert[bestR].xyz, vert[bestT].xyz - vert[bestR].xyz ) );
}
if ( bestA < TINY_AREA ) {
@@ -599,7 +583,9 @@ void MaxAreaFaceSurface( mapDrawSurface_t *ds ){
void FanFaceSurface( mapDrawSurface_t *ds ){
int i, j, k, a, b, c;
int color[ MAX_LIGHTMAPS ][ 4 ] = {{0}};
BasicVector4<int> color[ MAX_LIGHTMAPS ];
for ( k = 0; k < MAX_LIGHTMAPS; k++ )
color[k].set( 0 );
bspDrawVert_t *verts, *centroid, *dv;
double iv;
@@ -620,37 +606,28 @@ void FanFaceSurface( mapDrawSurface_t *ds ){
centroid = &verts[ 0 ];
for ( i = 1, dv = &verts[ 1 ]; i < ( ds->numVerts + 1 ); i++, dv++ )
{
VectorAdd( centroid->xyz, dv->xyz, centroid->xyz );
VectorAdd( centroid->normal, dv->normal, centroid->normal );
for ( j = 0; j < 4; j++ )
{
for ( k = 0; k < MAX_LIGHTMAPS; k++ )
color[ k ][ j ] += dv->color[ k ][ j ];
if ( j < 2 ) {
centroid->st[ j ] += dv->st[ j ];
for ( k = 0; k < MAX_LIGHTMAPS; k++ )
centroid->lightmap[ k ][ j ] += dv->lightmap[ k ][ j ];
}
centroid->xyz += dv->xyz;
centroid->normal += dv->normal;
centroid->st += dv->st;
for ( k = 0; k < MAX_LIGHTMAPS; k++ ){
color[ k ] += dv->color[ k ];
centroid->lightmap[ k ] += dv->lightmap[ k ];
}
}
/* average the centroid */
iv = 1.0f / ds->numVerts;
VectorScale( centroid->xyz, iv, centroid->xyz );
if ( VectorNormalize( centroid->normal, centroid->normal ) <= 0 ) {
VectorCopy( verts[ 1 ].normal, centroid->normal );
centroid->xyz *= iv;
if ( VectorNormalize( centroid->normal ) == 0 ) {
centroid->normal = verts[ 1 ].normal;
}
for ( j = 0; j < 4; j++ )
{
for ( k = 0; k < MAX_LIGHTMAPS; k++ )
centroid->st *= iv;
for ( k = 0; k < MAX_LIGHTMAPS; k++ ){
centroid->lightmap[ k ] *= iv;
for ( j = 0; j < 4; j++ )
{
color[ k ][ j ] /= ds->numVerts;
centroid->color[ k ][ j ] = ( color[ k ][ j ] < 255.0f ? color[ k ][ j ] : 255 );
}
if ( j < 2 ) {
centroid->st[ j ] *= iv;
for ( k = 0; k < MAX_LIGHTMAPS; k++ )
centroid->lightmap[ k ][ j ] *= iv;
centroid->color[ k ][ j ] = ( color[ k ][ j ] < 255 ? color[ k ][ j ] : 255 );
}
}
@@ -690,7 +667,6 @@ void FanFaceSurface( mapDrawSurface_t *ds ){
void StripFaceSurface( mapDrawSurface_t *ds ){
int i, r, least, rotate, numIndexes, ni, a, b, c, indexes[ MAX_INDEXES ];
vec_t *v1, *v2;
/* try to early out */
@@ -711,8 +687,8 @@ void StripFaceSurface( mapDrawSurface_t *ds ){
for ( i = 0; i < ds->numVerts; i++ )
{
/* get points */
v1 = ds->verts[ i ].xyz;
v2 = ds->verts[ least ].xyz;
const Vector3& v1 = ds->verts[ i ].xyz;
const Vector3& v2 = ds->verts[ least ].xyz;
/* compare */
if ( v1[ 0 ] < v2[ 0 ] ||
@@ -912,38 +888,30 @@ void MakeEntityMetaTriangles( entity_t *e ){
struct edge_t
{
vec3_t origin;
vec4_t edge;
vec_t length, kingpinLength;
Vector3 origin;
Plane3f edge;
float length, kingpinLength;
int kingpin;
vec4_t plane;
Plane3f plane;
};
void CreateEdge( vec4_t plane, vec3_t a, vec3_t b, edge_t *edge ){
void CreateEdge( const Plane3f& plane, const Vector3& a, const Vector3& b, edge_t *edge ){
/* copy edge origin */
VectorCopy( a, edge->origin );
edge->origin = a;
/* create vector aligned with winding direction of edge */
VectorSubtract( b, a, edge->edge );
edge->edge.normal() = b - a;
if ( fabs( edge->edge[ 0 ] ) > fabs( edge->edge[ 1 ] ) && fabs( edge->edge[ 0 ] ) > fabs( edge->edge[ 2 ] ) ) {
edge->kingpin = 0;
}
else if ( fabs( edge->edge[ 1 ] ) > fabs( edge->edge[ 0 ] ) && fabs( edge->edge[ 1 ] ) > fabs( edge->edge[ 2 ] ) ) {
edge->kingpin = 1;
}
else{
edge->kingpin = 2;
}
edge->kingpinLength = edge->edge[ edge->kingpin ];
edge->kingpin = vector3_max_abs_component_index( edge->edge.normal() );
edge->kingpinLength = edge->edge.normal()[ edge->kingpin ];
VectorNormalize( edge->edge, edge->edge );
edge->edge[ 3 ] = DotProduct( a, edge->edge );
edge->length = DotProduct( b, edge->edge ) - edge->edge[ 3 ];
VectorNormalize( edge->edge.normal() );
edge->edge.dist() = vector3_dot( a, edge->edge.normal() );
edge->length = plane3_distance_to_point( edge->edge, b );
/* create perpendicular plane that edge lies in */
CrossProduct( plane, edge->edge, edge->plane );
edge->plane[ 3 ] = DotProduct( a, edge->plane );
edge->plane.normal() = vector3_cross( plane.normal(), edge->edge.normal() );
edge->plane.dist() = vector3_dot( a, edge->plane.normal() );
}
@@ -962,9 +930,8 @@ void FixMetaTJunctions( void ){
metaTriangle_t *tri, *newTri;
shaderInfo_t *si;
bspDrawVert_t *a, *b, *c, junc;
float dist, amount;
vec3_t pt;
vec4_t plane;
float amount;
Plane3f plane;
edge_t edges[ 3 ];
@@ -999,8 +966,7 @@ void FixMetaTJunctions( void ){
}
/* calculate planes */
VectorCopy( tri->plane, plane );
plane[ 3 ] = tri->plane[ 3 ];
plane = tri->plane;
CreateEdge( plane, metaVerts[ tri->indexes[ 0 ] ].xyz, metaVerts[ tri->indexes[ 1 ] ].xyz, &edges[ 0 ] );
CreateEdge( plane, metaVerts[ tri->indexes[ 1 ] ].xyz, metaVerts[ tri->indexes[ 2 ] ].xyz, &edges[ 1 ] );
CreateEdge( plane, metaVerts[ tri->indexes[ 2 ] ].xyz, metaVerts[ tri->indexes[ 0 ] ].xyz, &edges[ 2 ] );
@@ -1009,11 +975,10 @@ void FixMetaTJunctions( void ){
for ( j = 0; j < numMetaVerts; j++ )
{
/* get vert */
VectorCopy( metaVerts[ j ].xyz, pt );
const Vector3 pt = metaVerts[ j ].xyz;
/* determine if point lies in the triangle's plane */
dist = DotProduct( pt, plane ) - plane[ 3 ];
if ( fabs( dist ) > TJ_PLANE_EPSILON ) {
if ( fabs( plane3_distance_to_point( plane, pt ) ) > TJ_PLANE_EPSILON ) {
continue;
}
@@ -1039,8 +1004,7 @@ void FixMetaTJunctions( void ){
}
/* determine if point lies on the edge */
dist = DotProduct( pt, edges[ k ].plane ) - edges[ k ].plane[ 3 ];
if ( fabs( dist ) > TJ_EDGE_EPSILON ) {
if ( fabs( plane3_distance_to_point( edges[ k ].plane, pt ) ) > TJ_EDGE_EPSILON ) {
continue;
}
@@ -1051,7 +1015,7 @@ void FixMetaTJunctions( void ){
}
#if 0
dist = DotProduct( pt, edges[ k ].edge ) - edges[ k ].edge[ 3 ];
dist = plane3_distance_to_point( edges[ k ].edge, pt );
if ( dist <= -0.0f || dist >= edges[ k ].length ) {
continue;
}
@@ -1065,7 +1029,7 @@ void FixMetaTJunctions( void ){
/* make new vert */
LerpDrawVertAmount( a, b, amount, &junc );
VectorCopy( pt, junc.xyz );
junc.xyz = pt;
/* compare against existing verts */
if ( VectorCompare( junc.xyz, a->xyz ) || VectorCompare( junc.xyz, b->xyz ) || VectorCompare( junc.xyz, c->xyz ) ) {
@@ -1109,9 +1073,7 @@ void FixMetaTJunctions( void ){
CreateEdge( plane, metaVerts[ tri->indexes[ 2 ] ].xyz, metaVerts[ tri->indexes[ 0 ] ].xyz, &edges[ 2 ] );
/* debug code */
metaVerts[ vertIndex ].color[ 0 ][ 0 ] = 255;
metaVerts[ vertIndex ].color[ 0 ][ 1 ] = 204;
metaVerts[ vertIndex ].color[ 0 ][ 2 ] = 0;
metaVerts[ vertIndex ].color[ 0 ].rgb() = { 255, 204, 0 };
/* add to counter and end processing of this vert */
numTJuncs++;
@@ -1136,7 +1098,7 @@ void FixMetaTJunctions( void ){
#define MAX_SAMPLES 256
#define THETA_EPSILON 0.000001
#define EQUAL_NORMAL_EPSILON 0.01
#define EQUAL_NORMAL_EPSILON 0.01f
void SmoothMetaTriangles( void ){
int i, j, k, f, fOld, start, numVerts, numVotes, numSmoothed;
@@ -1144,9 +1106,9 @@ void SmoothMetaTriangles( void ){
metaTriangle_t *tri;
float *shadeAngles;
byte *smoothed;
vec3_t average, diff;
Vector3 average;
int indexes[ MAX_SAMPLES ];
vec3_t votes[ MAX_SAMPLES ];
Vector3 votes[ MAX_SAMPLES ];
/* note it */
Sys_FPrintf( SYS_VRB, "--- SmoothMetaTriangles ---\n" );
@@ -1158,7 +1120,7 @@ void SmoothMetaTriangles( void ){
smoothed = safe_calloc( ( numMetaVerts / 8 ) + 1 );
/* set default shade angle */
defaultShadeAngle = DEG2RAD( npDegrees );
defaultShadeAngle = degrees_to_radians( npDegrees );
maxShadeAngle = 0.0f;
/* run through every surface and flag verts belonging to non-lightmapped surfaces
@@ -1169,11 +1131,11 @@ void SmoothMetaTriangles( void ){
/* get shade angle from shader */
if ( tri->si->shadeAngleDegrees > 0.0f ) {
shadeAngle = DEG2RAD( tri->si->shadeAngleDegrees );
shadeAngle = degrees_to_radians( tri->si->shadeAngleDegrees );
}
/* get shade angle from entity */
else if ( tri->shadeAngleDegrees > 0.0f ) {
shadeAngle = DEG2RAD( tri->shadeAngleDegrees );
shadeAngle = degrees_to_radians( tri->shadeAngleDegrees );
}
if ( shadeAngle <= 0.0f ) {
@@ -1223,7 +1185,7 @@ void SmoothMetaTriangles( void ){
}
/* clear */
VectorClear( average );
average.set( 0 );
numVerts = 0;
numVotes = 0;
@@ -1244,7 +1206,7 @@ void SmoothMetaTriangles( void ){
shadeAngle = ( shadeAngles[ i ] < shadeAngles[ j ] ? shadeAngles[ i ] : shadeAngles[ j ] );
/* check shade angle */
dot = DotProduct( metaVerts[ i ].normal, metaVerts[ j ].normal );
dot = vector3_dot( metaVerts[ i ].normal, metaVerts[ j ].normal );
if ( dot > 1.0 ) {
dot = 1.0;
}
@@ -1265,18 +1227,15 @@ void SmoothMetaTriangles( void ){
/* see if this normal has already been voted */
for ( k = 0; k < numVotes; k++ )
{
VectorSubtract( metaVerts[ j ].normal, votes[ k ], diff );
if ( fabs( diff[ 0 ] ) < EQUAL_NORMAL_EPSILON &&
fabs( diff[ 1 ] ) < EQUAL_NORMAL_EPSILON &&
fabs( diff[ 2 ] ) < EQUAL_NORMAL_EPSILON ) {
if ( vector3_equal_epsilon( metaVerts[ j ].normal, votes[ k ], EQUAL_NORMAL_EPSILON ) ) {
break;
}
}
/* add a new vote? */
if ( k == numVotes && numVotes < MAX_SAMPLES ) {
VectorAdd( average, metaVerts[ j ].normal, average );
VectorCopy( metaVerts[ j ].normal, votes[ numVotes ] );
average += metaVerts[ j ].normal;
votes[ numVotes ] = metaVerts[ j ].normal;
numVotes++;
}
}
@@ -1287,10 +1246,10 @@ void SmoothMetaTriangles( void ){
}
/* average normal */
if ( VectorNormalize( average, average ) > 0 ) {
if ( VectorNormalize( average ) != 0 ) {
/* smooth */
for ( j = 0; j < numVerts; j++ )
VectorCopy( average, metaVerts[ indexes[ j ] ].normal );
metaVerts[ indexes[ j ] ].normal = average;
numSmoothed++;
}
}
@@ -1340,7 +1299,7 @@ int AddMetaVertToSurface( mapDrawSurface_t *ds, bspDrawVert_t *dv1, int *coincid
if ( dv1->st[ 0 ] != dv2->st[ 0 ] || dv1->st[ 1 ] != dv2->st[ 1 ] ) {
continue;
}
if ( dv1->color[ 0 ][ 3 ] != dv2->color[ 0 ][ 3 ] ) {
if ( dv1->color[ 0 ].alpha() != dv2->color[ 0 ].alpha() ) {
continue;
}
@@ -1384,10 +1343,8 @@ int AddMetaVertToSurface( mapDrawSurface_t *ds, bspDrawVert_t *dv1, int *coincid
#define GOOD_SCORE ( metaGoodScore >= 0 ? metaGoodScore : DEFAULT_GOOD_SCORE )
static int AddMetaTriangleToSurface( mapDrawSurface_t *ds, metaTriangle_t *tri, bool testAdd ){
vec3_t p;
int i, score, coincident, ai, bi, ci, oldTexRange[ 2 ];
float lmMax;
vec3_t mins, maxs;
bool inTexRange;
mapDrawSurface_t old;
@@ -1410,14 +1367,14 @@ static int AddMetaTriangleToSurface( mapDrawSurface_t *ds, metaTriangle_t *tri,
#if 0
if ( !( ds->shaderInfo->compileFlags & C_VERTEXLIT ) &&
//% !VectorCompare( ds->lightmapAxis, tri->lightmapAxis ) )
DotProduct( ds->lightmapAxis, tri->plane ) < 0.25f ) {
vector3_dot( ds->lightmapAxis, tri->plane.normal() ) < 0.25f ) {
return 0;
}
#endif
/* planar surfaces will only merge with triangles in the same plane */
if ( npDegrees == 0.0f && !ds->shaderInfo->nonplanar && ds->planeNum >= 0 ) {
if ( !VectorCompare( mapplanes[ ds->planeNum ].normal, tri->plane ) || mapplanes[ ds->planeNum ].dist != tri->plane[ 3 ] ) {
if ( !VectorCompare( mapplanes[ ds->planeNum ].normal(), tri->plane.normal() ) || mapplanes[ ds->planeNum ].dist() != tri->plane.dist() ) {
return 0;
}
if ( tri->planeNum >= 0 && tri->planeNum != ds->planeNum ) {
@@ -1429,21 +1386,15 @@ static int AddMetaTriangleToSurface( mapDrawSurface_t *ds, metaTriangle_t *tri,
if ( metaMaxBBoxDistance >= 0 ) {
if ( ds->numIndexes > 0 ) {
VectorCopy( ds->mins, mins );
VectorCopy( ds->maxs, maxs );
mins[0] -= metaMaxBBoxDistance;
mins[1] -= metaMaxBBoxDistance;
mins[2] -= metaMaxBBoxDistance;
maxs[0] += metaMaxBBoxDistance;
maxs[1] += metaMaxBBoxDistance;
maxs[2] += metaMaxBBoxDistance;
const Vector3 mins = ds->minmax.mins - Vector3( metaMaxBBoxDistance, metaMaxBBoxDistance, metaMaxBBoxDistance );
const Vector3 maxs = ds->minmax.maxs + Vector3( metaMaxBBoxDistance, metaMaxBBoxDistance, metaMaxBBoxDistance );
#define CHECK_1D( mins, v, maxs ) ( ( mins ) <= ( v ) && ( v ) <= ( maxs ) )
#define CHECK_3D( mins, v, maxs ) ( CHECK_1D( ( mins )[0], ( v )[0], ( maxs )[0] ) && CHECK_1D( ( mins )[1], ( v )[1], ( maxs )[1] ) && CHECK_1D( ( mins )[2], ( v )[2], ( maxs )[2] ) )
VectorCopy( metaVerts[ tri->indexes[ 0 ] ].xyz, p );
Vector3 p = metaVerts[ tri->indexes[ 0 ] ].xyz;
if ( !CHECK_3D( mins, p, maxs ) ) {
VectorCopy( metaVerts[ tri->indexes[ 1 ] ].xyz, p );
p = metaVerts[ tri->indexes[ 1 ] ].xyz;
if ( !CHECK_3D( mins, p, maxs ) ) {
VectorCopy( metaVerts[ tri->indexes[ 2 ] ].xyz, p );
p = metaVerts[ tri->indexes[ 2 ] ].xyz;
if ( !CHECK_3D( mins, p, maxs ) ) {
return 0;
}
@@ -1462,7 +1413,7 @@ static int AddMetaTriangleToSurface( mapDrawSurface_t *ds, metaTriangle_t *tri,
score += AXIS_SCORE;
}
else{
score += AXIS_SCORE * DotProduct( ds->lightmapAxis, tri->plane );
score += AXIS_SCORE * vector3_dot( ds->lightmapAxis, tri->plane.normal() );
}
/* preserve old drawsurface if this fails */
@@ -1484,23 +1435,22 @@ static int AddMetaTriangleToSurface( mapDrawSurface_t *ds, metaTriangle_t *tri,
score += ( coincident * VERT_SCORE );
/* add new vertex bounds to mins/maxs */
VectorCopy( ds->mins, mins );
VectorCopy( ds->maxs, maxs );
AddPointToBounds( metaVerts[ tri->indexes[ 0 ] ].xyz, mins, maxs );
AddPointToBounds( metaVerts[ tri->indexes[ 1 ] ].xyz, mins, maxs );
AddPointToBounds( metaVerts[ tri->indexes[ 2 ] ].xyz, mins, maxs );
MinMax minmax( ds->minmax );
minmax.extend( metaVerts[ tri->indexes[ 0 ] ].xyz );
minmax.extend( metaVerts[ tri->indexes[ 1 ] ].xyz );
minmax.extend( metaVerts[ tri->indexes[ 2 ] ].xyz );
/* check lightmap bounds overflow (after at least 1 triangle has been added) */
if ( !( ds->shaderInfo->compileFlags & C_VERTEXLIT ) &&
ds->numIndexes > 0 && VectorLength( ds->lightmapAxis ) > 0.0f &&
( !VectorCompare( ds->mins, mins ) || !VectorCompare( ds->maxs, maxs ) ) ) {
ds->numIndexes > 0 && vector3_length( ds->lightmapAxis ) != 0.0f &&
( !VectorCompare( ds->minmax.mins, minmax.mins ) || !VectorCompare( ds->minmax.maxs, minmax.maxs ) ) ) {
/* set maximum size before lightmap scaling (normally 2032 units) */
/* 2004-02-24: scale lightmap test size by 2 to catch larger brush faces */
/* 2004-04-11: reverting to actual lightmap size */
lmMax = ( ds->sampleSize * ( ds->shaderInfo->lmCustomWidth - 1 ) );
for ( i = 0; i < 3; i++ )
{
if ( ( maxs[ i ] - mins[ i ] ) > lmMax ) {
if ( ( minmax.maxs[ i ] - minmax.mins[ i ] ) > lmMax ) {
memcpy( ds, &old, sizeof( *ds ) );
return 0;
}
@@ -1595,8 +1545,7 @@ static int AddMetaTriangleToSurface( mapDrawSurface_t *ds, metaTriangle_t *tri,
else
{
/* copy bounds back to surface */
VectorCopy( mins, ds->mins );
VectorCopy( maxs, ds->maxs );
ds->minmax = minmax;
/* mark triangle as used */
tri->si = NULL;
@@ -1655,10 +1604,10 @@ static void MetaTrianglesToSurface( int numPossibles, metaTriangle_t *possibles,
ds->shadeAngleDegrees = seed->shadeAngleDegrees;
ds->verts = verts;
ds->indexes = indexes;
VectorCopy( seed->lightmapAxis, ds->lightmapAxis );
ds->lightmapAxis = seed->lightmapAxis;
ds->sideRef = AllocSideRef( seed->side, NULL );
ClearBounds( ds->mins, ds->maxs );
ds->minmax.clear();
/* clear verts/indexes */
memset( verts, 0, sizeof( *verts ) * maxSurfaceVerts );
@@ -1756,8 +1705,6 @@ static void MetaTrianglesToSurface( int numPossibles, metaTriangle_t *possibles,
static int CompareMetaTriangles( const void *a, const void *b ){
int i, j, av, bv;
vec3_t aMins, bMins;
/* shader first */
if ( ( (const metaTriangle_t*) a )->si < ( (const metaTriangle_t*) b )->si ) {
@@ -1809,8 +1756,8 @@ static int CompareMetaTriangles( const void *a, const void *b ){
/* then position in world */
/* find mins */
VectorSet( aMins, 999999, 999999, 999999 );
VectorSet( bMins, 999999, 999999, 999999 );
Vector3 aMins( 999999, 999999, 999999 );
Vector3 bMins( 999999, 999999, 999999 );
for ( i = 0; i < 3; i++ )
{
av = ( (const metaTriangle_t*) a )->indexes[ i ];
+79 -88
View File
@@ -37,20 +37,20 @@
struct edgePoint_t
{
float intercept;
vec3_t xyz;
Vector3 xyz;
struct edgePoint_t *prev, *next;
};
struct edgeLine_t
{
vec3_t normal1;
Vector3 normal1;
float dist1;
vec3_t normal2;
Vector3 normal2;
float dist2;
vec3_t origin;
vec3_t dir;
Vector3 origin;
Vector3 dir;
edgePoint_t *chain; // unused element of doubly linked list
};
@@ -86,17 +86,15 @@ int c_natural, c_rotate, c_cant;
InsertPointOnEdge
====================
*/
void InsertPointOnEdge( vec3_t v, edgeLine_t *e ) {
vec3_t delta;
void InsertPointOnEdge( const Vector3 &v, edgeLine_t *e ) {
float d;
edgePoint_t *p, *scan;
VectorSubtract( v, e->origin, delta );
d = DotProduct( delta, e->dir );
d = vector3_dot( v - e->origin, e->dir );
p = safe_malloc( sizeof( edgePoint_t ) );
p->intercept = d;
VectorCopy( v, p->xyz );
p->xyz = v;
if ( e->chain->next == e->chain ) {
e->chain->next = e->chain->prev = p;
@@ -135,14 +133,16 @@ void InsertPointOnEdge( vec3_t v, edgeLine_t *e ) {
AddEdge
====================
*/
int AddEdge( vec3_t v1, vec3_t v2, bool createNonAxial ) {
int AddEdge( bspDrawVert_t& dv1, bspDrawVert_t& dv2, bool createNonAxial ) {
int i;
edgeLine_t *e;
float d;
vec3_t dir;
Vector3 dir;
const Vector3& v1 = dv1.xyz;
const Vector3& v2 = dv2.xyz;
VectorSubtract( v2, v1, dir );
d = VectorNormalize( dir, dir );
dir = v2 - v1;
d = VectorNormalize( dir );
if ( d < 0.1 ) {
// if we added a 0 length vector, it would make degenerate planes
c_degenerateEdges++;
@@ -152,8 +152,8 @@ int AddEdge( vec3_t v1, vec3_t v2, bool createNonAxial ) {
if ( !createNonAxial ) {
if ( fabs( dir[0] + dir[1] + dir[2] ) != 1.0 ) {
AUTOEXPAND_BY_REALLOC( originalEdges, numOriginalEdges, allocatedOriginalEdges, 1024 );
originalEdges[ numOriginalEdges ].dv[0] = (bspDrawVert_t *)v1;
originalEdges[ numOriginalEdges ].dv[1] = (bspDrawVert_t *)v2;
originalEdges[ numOriginalEdges ].dv[0] = &dv1;
originalEdges[ numOriginalEdges ].dv[1] = &dv2;
originalEdges[ numOriginalEdges ].length = d;
numOriginalEdges++;
return -1;
@@ -163,20 +163,20 @@ int AddEdge( vec3_t v1, vec3_t v2, bool createNonAxial ) {
for ( i = 0 ; i < numEdgeLines ; i++ ) {
e = &edgeLines[i];
d = DotProduct( v1, e->normal1 ) - e->dist1;
d = vector3_dot( v1, e->normal1 ) - e->dist1;
if ( d < -POINT_ON_LINE_EPSILON || d > POINT_ON_LINE_EPSILON ) {
continue;
}
d = DotProduct( v1, e->normal2 ) - e->dist2;
d = vector3_dot( v1, e->normal2 ) - e->dist2;
if ( d < -POINT_ON_LINE_EPSILON || d > POINT_ON_LINE_EPSILON ) {
continue;
}
d = DotProduct( v2, e->normal1 ) - e->dist1;
d = vector3_dot( v2, e->normal1 ) - e->dist1;
if ( d < -POINT_ON_LINE_EPSILON || d > POINT_ON_LINE_EPSILON ) {
continue;
}
d = DotProduct( v2, e->normal2 ) - e->dist2;
d = vector3_dot( v2, e->normal2 ) - e->dist2;
if ( d < -POINT_ON_LINE_EPSILON || d > POINT_ON_LINE_EPSILON ) {
continue;
}
@@ -196,12 +196,12 @@ int AddEdge( vec3_t v1, vec3_t v2, bool createNonAxial ) {
e->chain = safe_malloc( sizeof( edgePoint_t ) );
e->chain->next = e->chain->prev = e->chain;
VectorCopy( v1, e->origin );
VectorCopy( dir, e->dir );
e->origin = v1;
e->dir = dir;
MakeNormalVectors( e->dir, e->normal1, e->normal2 );
e->dist1 = DotProduct( e->origin, e->normal1 );
e->dist2 = DotProduct( e->origin, e->normal2 );
e->dist1 = vector3_dot( e->origin, e->normal1 );
e->dist2 = vector3_dot( e->origin, e->normal2 );
InsertPointOnEdge( v1, e );
InsertPointOnEdge( v2, e );
@@ -221,7 +221,7 @@ void AddSurfaceEdges( mapDrawSurface_t *ds ){
{
/* save the edge number in the lightmap field so we don't need to look it up again */
ds->verts[i].lightmap[ 0 ][ 0 ] =
AddEdge( ds->verts[ i ].xyz, ds->verts[ ( i + 1 ) % ds->numVerts ].xyz, false );
AddEdge( ds->verts[ i ], ds->verts[ ( i + 1 ) % ds->numVerts ], false );
}
}
@@ -232,21 +232,20 @@ void AddSurfaceEdges( mapDrawSurface_t *ds ){
determines if an edge is colinear
*/
bool ColinearEdge( vec3_t v1, vec3_t v2, vec3_t v3 ){
vec3_t midpoint, dir, offset, on;
bool ColinearEdge( const Vector3& v1, const Vector3& v2, const Vector3& v3 ){
Vector3 midpoint, dir, offset, on;
float d;
VectorSubtract( v2, v1, midpoint );
VectorSubtract( v3, v1, dir );
d = VectorNormalize( dir, dir );
if ( d == 0 ) {
midpoint = v2 - v1;
dir = v3 - v1;
if ( VectorNormalize( dir ) == 0 ) {
return false; // degenerate
}
d = DotProduct( midpoint, dir );
VectorScale( dir, d, on );
VectorSubtract( midpoint, on, offset );
d = VectorLength( offset );
d = vector3_dot( midpoint, dir );
on = dir * d;
offset = midpoint - on;
d = vector3_length( offset );
if ( d < 0.1 ) {
return true;
@@ -267,45 +266,50 @@ bool ColinearEdge( vec3_t v1, vec3_t v2, vec3_t v3 ){
*/
void AddPatchEdges( mapDrawSurface_t *ds ) {
int i;
float *v1, *v2, *v3;
for ( i = 0 ; i < ds->patchWidth - 2; i += 2 ) {
v1 = ds->verts[ i ].xyz;
v2 = ds->verts[ i + 1 ].xyz;
v3 = ds->verts[ i + 2 ].xyz;
{
bspDrawVert_t& v1 = ds->verts[ i ];
bspDrawVert_t& v2 = ds->verts[ i + 1 ];
bspDrawVert_t& v3 = ds->verts[ i + 2 ];
// if v2 is the midpoint of v1 to v3, add an edge from v1 to v3
if ( ColinearEdge( v1, v2, v3 ) ) {
AddEdge( v1, v3, false );
// if v2 is the midpoint of v1 to v3, add an edge from v1 to v3
if ( ColinearEdge( v1.xyz, v2.xyz, v3.xyz ) ) {
AddEdge( v1, v3, false );
}
}
{
bspDrawVert_t& v1 = ds->verts[ ( ds->patchHeight - 1 ) * ds->patchWidth + i ];
bspDrawVert_t& v2 = ds->verts[ ( ds->patchHeight - 1 ) * ds->patchWidth + i + 1 ];
bspDrawVert_t& v3 = ds->verts[ ( ds->patchHeight - 1 ) * ds->patchWidth + i + 2 ];
v1 = ds->verts[ ( ds->patchHeight - 1 ) * ds->patchWidth + i ].xyz;
v2 = ds->verts[ ( ds->patchHeight - 1 ) * ds->patchWidth + i + 1 ].xyz;
v3 = ds->verts[ ( ds->patchHeight - 1 ) * ds->patchWidth + i + 2 ].xyz;
// if v2 is on the v1 to v3 line, add an edge from v1 to v3
if ( ColinearEdge( v1, v2, v3 ) ) {
AddEdge( v1, v3, false );
// if v2 is on the v1 to v3 line, add an edge from v1 to v3
if ( ColinearEdge( v1.xyz, v2.xyz, v3.xyz ) ) {
AddEdge( v1, v3, false );
}
}
}
for ( i = 0 ; i < ds->patchHeight - 2 ; i += 2 ) {
v1 = ds->verts[ i * ds->patchWidth ].xyz;
v2 = ds->verts[ ( i + 1 ) * ds->patchWidth ].xyz;
v3 = ds->verts[ ( i + 2 ) * ds->patchWidth ].xyz;
{
bspDrawVert_t& v1 = ds->verts[ i * ds->patchWidth ];
bspDrawVert_t& v2 = ds->verts[ ( i + 1 ) * ds->patchWidth ];
bspDrawVert_t& v3 = ds->verts[ ( i + 2 ) * ds->patchWidth ];
// if v2 is the midpoint of v1 to v3, add an edge from v1 to v3
if ( ColinearEdge( v1, v2, v3 ) ) {
AddEdge( v1, v3, false );
// if v2 is the midpoint of v1 to v3, add an edge from v1 to v3
if ( ColinearEdge( v1.xyz, v2.xyz, v3.xyz ) ) {
AddEdge( v1, v3, false );
}
}
{
bspDrawVert_t& v1 = ds->verts[ ( ds->patchWidth - 1 ) + i * ds->patchWidth ];
bspDrawVert_t& v2 = ds->verts[ ( ds->patchWidth - 1 ) + ( i + 1 ) * ds->patchWidth ];
bspDrawVert_t& v3 = ds->verts[ ( ds->patchWidth - 1 ) + ( i + 2 ) * ds->patchWidth ];
v1 = ds->verts[ ( ds->patchWidth - 1 ) + i * ds->patchWidth ].xyz;
v2 = ds->verts[ ( ds->patchWidth - 1 ) + ( i + 1 ) * ds->patchWidth ].xyz;
v3 = ds->verts[ ( ds->patchWidth - 1 ) + ( i + 2 ) * ds->patchWidth ].xyz;
// if v2 is the midpoint of v1 to v3, add an edge from v1 to v3
if ( ColinearEdge( v1, v2, v3 ) ) {
AddEdge( v1, v3, false );
// if v2 is the midpoint of v1 to v3, add an edge from v1 to v3
if ( ColinearEdge( v1.xyz, v2.xyz, v3.xyz ) ) {
AddEdge( v1, v3, false );
}
}
}
@@ -327,8 +331,7 @@ void FixSurfaceJunctions( mapDrawSurface_t *ds ) {
int originals[MAX_SURFACE_VERTS];
bspDrawVert_t verts[MAX_SURFACE_VERTS], *v1, *v2;
int numVerts;
float start, end, frac, c;
vec3_t delta;
float start, end, c;
numVerts = 0;
@@ -354,11 +357,9 @@ void FixSurfaceJunctions( mapDrawSurface_t *ds ) {
}
e = &edgeLines[ j ];
VectorSubtract( v1->xyz, e->origin, delta );
start = DotProduct( delta, e->dir );
start = vector3_dot( v1->xyz - e->origin, e->dir );
VectorSubtract( v2->xyz, e->origin, delta );
end = DotProduct( delta, e->dir );
end = vector3_dot( v2->xyz - e->origin, e->dir );
if ( start < end ) {
@@ -389,17 +390,14 @@ void FixSurfaceJunctions( mapDrawSurface_t *ds ) {
}
/* take the exact intercept point */
VectorCopy( p->xyz, verts[ numVerts ].xyz );
verts[ numVerts ].xyz = p->xyz;
/* interpolate the texture coordinates */
frac = ( p->intercept - start ) / ( end - start );
for ( j = 0 ; j < 2 ; j++ ) {
verts[ numVerts ].st[j] = v1->st[j] +
frac * ( v2->st[j] - v1->st[j] );
}
const float frac = ( p->intercept - start ) / ( end - start );
verts[ numVerts ].st = v1->st + ( v2->st - v1->st ) * frac;
/* copy the normal (FIXME: what about nonplanar surfaces? */
VectorCopy( v1->normal, verts[ numVerts ].normal );
verts[ numVerts ].normal = v1->normal;
/* ydnar: interpolate the color */
for ( k = 0; k < MAX_LIGHTMAPS; k++ )
@@ -500,8 +498,6 @@ void FixSurfaceJunctions( mapDrawSurface_t *ds ) {
returns false if the surface is broken
*/
extern void SnapWeldVector( vec3_t a, vec3_t b, vec3_t out );
#define DEGENERATE_EPSILON 0.1
int c_broken = 0;
@@ -509,7 +505,6 @@ int c_broken = 0;
bool FixBrokenSurface( mapDrawSurface_t *ds ){
bspDrawVert_t *dv1, *dv2, avg;
int i, j, k;
float dist;
/* dummy check */
@@ -528,24 +523,20 @@ bool FixBrokenSurface( mapDrawSurface_t *ds ){
dv2 = &ds->verts[ ( i + 1 ) % ds->numVerts ];
/* degenerate edge? */
VectorSubtract( dv1->xyz, dv2->xyz, avg.xyz );
dist = VectorLength( avg.xyz );
if ( dist < DEGENERATE_EPSILON ) {
avg.xyz = dv1->xyz - dv2->xyz;
if ( vector3_length( avg.xyz ) < DEGENERATE_EPSILON ) {
Sys_FPrintf( SYS_WRN | SYS_VRBflag, "WARNING: Degenerate T-junction edge found, fixing...\n" );
/* create an average drawvert */
/* ydnar 2002-01-26: added nearest-integer welding preference */
SnapWeldVector( dv1->xyz, dv2->xyz, avg.xyz );
VectorAdd( dv1->normal, dv2->normal, avg.normal );
VectorNormalize( avg.normal, avg.normal );
avg.st[ 0 ] = ( dv1->st[ 0 ] + dv2->st[ 0 ] ) * 0.5f;
avg.st[ 1 ] = ( dv1->st[ 1 ] + dv2->st[ 1 ] ) * 0.5f;
avg.normal = VectorNormalized( dv1->normal + dv2->normal );
avg.st = vector2_mid( dv1->st, dv2->st );
/* lightmap st/colors */
for ( k = 0; k < MAX_LIGHTMAPS; k++ )
{
avg.lightmap[ k ][ 0 ] = ( dv1->lightmap[ k ][ 0 ] + dv2->lightmap[ k ][ 0 ] ) * 0.5f;
avg.lightmap[ k ][ 1 ] = ( dv1->lightmap[ k ][ 1 ] + dv2->lightmap[ k ][ 1 ] ) * 0.5f;
avg.lightmap[ k ] = vector2_mid( dv1->lightmap[ k ], dv2->lightmap[ k ] );
for ( j = 0; j < 4; j++ )
avg.color[ k ][ j ] = (int) ( dv1->color[ k ][ j ] + dv2->color[ k ][ j ] ) >> 1;
}
@@ -670,7 +661,7 @@ void FixTJunctions( entity_t *ent ){
for ( i = 0 ; i < numOriginalEdges ; i++ ) {
e = &originalEdges[i];
dv = e->dv[0]; // e might change during AddEdge
dv->lightmap[ 0 ][ 0 ] = AddEdge( e->dv[ 0 ]->xyz, e->dv[ 1 ]->xyz, true );
dv->lightmap[ 0 ][ 0 ] = AddEdge( *e->dv[ 0 ], *e->dv[ 1 ], true );
}
Sys_FPrintf( SYS_VRB, "%9d axial edge lines\n", axialEdgeLines );
+4 -9
View File
@@ -36,15 +36,10 @@
void RemovePortalFromNode( portal_t *portal, node_t *l );
node_t *NodeForPoint( node_t *node, vec3_t origin ){
plane_t *plane;
vec_t d;
node_t *NodeForPoint( node_t *node, const Vector3& origin ){
while ( node->planenum != PLANENUM_LEAF )
{
plane = &mapplanes[node->planenum];
d = DotProduct( origin, plane->normal ) - plane->dist;
if ( d >= 0 ) {
if ( plane3_distance_to_point( mapplanes[node->planenum].plane, origin ) >= 0 ) {
node = node->children[0];
}
else{
@@ -143,8 +138,8 @@ void PrintTree_r( node_t *node, int depth ){
plane = &mapplanes[node->planenum];
Sys_Printf( "#%d (%5.2f %5.2f %5.2f):%5.2f\n", node->planenum,
plane->normal[0], plane->normal[1], plane->normal[2],
plane->dist );
plane->normal()[0], plane->normal()[1], plane->normal()[2],
plane->dist() );
PrintTree_r( node->children[0], depth + 1 );
PrintTree_r( node->children[1], depth + 1 );
}
+46 -64
View File
@@ -34,15 +34,11 @@
void PlaneFromWinding( fixedWinding_t *w, visPlane_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->normal );
plane->dist = DotProduct( w->points[0], plane->normal );
visPlane_t PlaneFromWinding( const fixedWinding_t *w ){
// calc plane
visPlane_t plane;
PlaneFromPoints( plane, w->points[0], w->points[1], w->points[2] );
return plane;
}
@@ -70,7 +66,7 @@ void prl( leaf_t *l ){
{
p = l->portals[i];
pl = p->plane;
Sys_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] );
Sys_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] );
}
}
@@ -374,30 +370,27 @@ void CalcVis( void ){
*/
void SetPortalSphere( vportal_t *p ){
int i;
vec3_t total, dist;
Vector3 total( 0, 0, 0 );
fixedWinding_t *w;
float r, bestr;
w = p->winding;
VectorCopy( vec3_origin, total );
for ( i = 0 ; i < w->numpoints ; i++ )
{
VectorAdd( total, w->points[i], total );
total += w->points[i];
}
for ( i = 0 ; i < 3 ; i++ )
total[i] /= w->numpoints;
total /= w->numpoints;
bestr = 0;
for ( i = 0 ; i < w->numpoints ; i++ )
{
VectorSubtract( w->points[i], total, dist );
r = VectorLength( dist );
r = vector3_length( w->points[i] - total );
if ( r > bestr ) {
bestr = r;
}
}
VectorCopy( total, p->origin );
p->origin = total;
p->radius = bestr;
}
@@ -408,9 +401,8 @@ void SetPortalSphere( vportal_t *p ){
*/
#define WCONVEX_EPSILON 0.2
static bool Winding_PlanesConcave( fixedWinding_t *w1, fixedWinding_t *w2,
vec3_t normal1, vec3_t normal2,
float dist1, float dist2 ){
static bool Winding_PlanesConcave( const fixedWinding_t *w1, const fixedWinding_t *w2,
const Plane3f& plane1, const Plane3f& plane2 ){
int i;
if ( !w1 || !w2 ) {
@@ -420,14 +412,14 @@ static bool Winding_PlanesConcave( fixedWinding_t *w1, fixedWinding_t *w2,
// check if one of the points of winding 1 is at the front of the plane of winding 2
for ( i = 0; i < w1->numpoints; i++ )
{
if ( DotProduct( normal2, w1->points[i] ) - dist2 > WCONVEX_EPSILON ) {
if ( plane3_distance_to_point( plane2, w1->points[i] ) > WCONVEX_EPSILON ) {
return true;
}
}
// check if one of the points of winding 2 is at the front of the plane of winding 1
for ( i = 0; i < w2->numpoints; i++ )
{
if ( DotProduct( normal1, w2->points[i] ) - dist1 > WCONVEX_EPSILON ) {
if ( plane3_distance_to_point( plane1, w2->points[i] ) > WCONVEX_EPSILON ) {
return true;
}
}
@@ -442,7 +434,6 @@ static bool Winding_PlanesConcave( fixedWinding_t *w1, fixedWinding_t *w2,
*/
static bool TryMergeLeaves( int l1num, int l2num ){
int i, j, k, n, numportals;
visPlane_t plane1, plane2;
leaf_t *l1, *l2;
vportal_t *p1, *p2;
vportal_t *portals[MAX_PORTALS_ON_LEAF];
@@ -464,7 +455,9 @@ static bool TryMergeLeaves( int l1num, int l2num ){
if ( n ) {
l2 = &leafs[l2num];
}
else{l2 = &faceleafs[l2num]; }
else{
l2 = &faceleafs[l2num];
}
for ( j = 0; j < l2->numportals; j++ )
{
p2 = l2->portals[j];
@@ -472,9 +465,7 @@ static bool TryMergeLeaves( int l1num, int l2num ){
continue;
}
//
plane1 = p1->plane;
plane2 = p2->plane;
if ( Winding_PlanesConcave( p1->winding, p2->winding, plane1.normal, plane2.normal, plane1.dist, plane2.dist ) ) {
if ( Winding_PlanesConcave( p1->winding, p2->winding, p1->plane, p2->plane ) ) {
return false;
}
}
@@ -599,12 +590,12 @@ void MergeLeaves( void ){
*/
#define CONTINUOUS_EPSILON 0.005
fixedWinding_t *TryMergeWinding( fixedWinding_t *f1, fixedWinding_t *f2, vec3_t planenormal ){
vec_t *p1, *p2, *p3, *p4, *back;
fixedWinding_t *TryMergeWinding( fixedWinding_t *f1, fixedWinding_t *f2, const Vector3& planenormal ){
const Vector3 *p1, *p2, *p3, *p4, *back;
fixedWinding_t *newf;
int i, j, k, l;
vec3_t normal, delta;
vec_t dot;
Vector3 normal;
float dot;
bool keep1, keep2;
@@ -616,18 +607,18 @@ fixedWinding_t *TryMergeWinding( fixedWinding_t *f1, fixedWinding_t *f2, vec3_t
for ( i = 0; i < f1->numpoints; i++ )
{
p1 = f1->points[i];
p2 = f1->points[( i + 1 ) % f1->numpoints];
p1 = &f1->points[i];
p2 = &f1->points[( i + 1 ) % f1->numpoints];
for ( j = 0; j < f2->numpoints; j++ )
{
p3 = f2->points[j];
p4 = f2->points[( j + 1 ) % f2->numpoints];
p3 = &f2->points[j];
p4 = &f2->points[( j + 1 ) % f2->numpoints];
for ( k = 0; k < 3; k++ )
{
if ( fabs( p1[k] - p4[k] ) > 0.1 ) { //EQUAL_EPSILON) //ME
if ( fabs( (*p1)[k] - (*p4)[k] ) > 0.1 ) { //EQUAL_EPSILON) //ME
break;
}
if ( fabs( p2[k] - p3[k] ) > 0.1 ) { //EQUAL_EPSILON) //ME
if ( fabs( (*p2)[k] - (*p3)[k] ) > 0.1 ) { //EQUAL_EPSILON) //ME
break;
}
} //end for
@@ -648,27 +639,21 @@ fixedWinding_t *TryMergeWinding( fixedWinding_t *f1, fixedWinding_t *f2, vec3_t
// check slope of connected lines
// if the slopes are colinear, the point can be removed
//
back = f1->points[( i + f1->numpoints - 1 ) % f1->numpoints];
VectorSubtract( p1, back, delta );
CrossProduct( planenormal, delta, normal );
VectorNormalize( normal, normal );
back = &f1->points[( i + f1->numpoints - 1 ) % f1->numpoints];
normal = VectorNormalized( vector3_cross( planenormal, *p1 - *back ) );
back = f2->points[( j + 2 ) % f2->numpoints];
VectorSubtract( back, p1, delta );
dot = DotProduct( delta, normal );
back = &f2->points[( j + 2 ) % f2->numpoints];
dot = vector3_dot( *back - *p1, normal );
if ( dot > CONTINUOUS_EPSILON ) {
return NULL; // not a convex polygon
}
keep1 = ( dot < -CONTINUOUS_EPSILON );
back = f1->points[( i + 2 ) % f1->numpoints];
VectorSubtract( back, p2, delta );
CrossProduct( planenormal, delta, normal );
VectorNormalize( normal, normal );
back = &f1->points[( i + 2 ) % f1->numpoints];
normal = VectorNormalized( vector3_cross( planenormal, *back - *p2 ) );
back = f2->points[( j + f2->numpoints - 1 ) % f2->numpoints];
VectorSubtract( back, p2, delta );
dot = DotProduct( delta, normal );
back = &f2->points[( j + f2->numpoints - 1 ) % f2->numpoints];
dot = vector3_dot( *back - *p2, normal );
if ( dot > CONTINUOUS_EPSILON ) {
return NULL; // not a convex polygon
}
@@ -686,7 +671,7 @@ fixedWinding_t *TryMergeWinding( fixedWinding_t *f1, fixedWinding_t *f2, vec3_t
continue;
}
VectorCopy( f1->points[k], newf->points[newf->numpoints] );
newf->points[newf->numpoints] = f1->points[k];
newf->numpoints++;
}
@@ -696,7 +681,7 @@ fixedWinding_t *TryMergeWinding( fixedWinding_t *f1, fixedWinding_t *f2, vec3_t
if ( l == ( j + 1 ) % f2->numpoints && !keep1 ) {
continue;
}
VectorCopy( f2->points[l], newf->points[newf->numpoints] );
newf->points[newf->numpoints] = f2->points[l];
newf->numpoints++;
}
@@ -735,7 +720,7 @@ void MergeLeafPortals( void ){
continue;
}
if ( p1->leaf == p2->leaf ) {
w = TryMergeWinding( p1->winding, p2->winding, p1->plane.normal );
w = TryMergeWinding( p1->winding, p2->winding, p1->plane.normal() );
if ( w ) {
free( p1->winding ); //% FreeWinding(p1->winding);
p1->winding = w;
@@ -793,7 +778,7 @@ int CountActivePortals( void ){
WritePortals
============
*/
void WriteFloat( FILE *f, vec_t v );
void WriteFloat( FILE *f, float v );
void WritePortals( char *filename ){
int i, j, num;
@@ -877,7 +862,6 @@ void LoadPortals( char *name ){
int numpoints;
fixedWinding_t *w;
int leafnums[2];
visPlane_t plane;
if ( strEqual( name, "-" ) ) {
f = stdin;
@@ -963,7 +947,7 @@ void LoadPortals( char *name ){
}
// calc plane
PlaneFromWinding( w, &plane );
const visPlane_t plane = PlaneFromWinding( w );
// create forward portal
l = &leafs[leafnums[0]];
@@ -977,8 +961,7 @@ void LoadPortals( char *name ){
p->hint = ((flags & 1) != 0);
p->sky = ((flags & 2) != 0);
p->winding = w;
VectorSubtract( vec3_origin, plane.normal, p->plane.normal );
p->plane.dist = -plane.dist;
p->plane = plane3_flipped( plane );
p->leaf = leafnums[1];
SetPortalSphere( p );
p++;
@@ -997,7 +980,7 @@ void LoadPortals( char *name ){
p->winding->numpoints = w->numpoints;
for ( j = 0 ; j < w->numpoints ; j++ )
{
VectorCopy( w->points[w->numpoints - 1 - j], p->winding->points[j] );
p->winding->points[j] = w->points[w->numpoints - 1 - j];
}
p->plane = plane;
@@ -1038,7 +1021,7 @@ void LoadPortals( char *name ){
}
// calc plane
PlaneFromWinding( w, &plane );
const visPlane_t plane = PlaneFromWinding( w );
l = &faceleafs[leafnums[0]];
l->merged = -1;
@@ -1051,8 +1034,7 @@ void LoadPortals( char *name ){
p->num = i + 1;
p->winding = w;
// normal pointing out of the leaf
VectorSubtract( vec3_origin, plane.normal, p->plane.normal );
p->plane.dist = -plane.dist;
p->plane = plane3_flipped( plane );
p->leaf = -1;
SetPortalSphere( p );
p++;
+90 -170
View File
@@ -122,14 +122,13 @@ void FreeStackWinding( fixedWinding_t *w, pstack_t *stack ){
==============
*/
fixedWinding_t *VisChopWinding( fixedWinding_t *in, pstack_t *stack, visPlane_t *split ){
vec_t dists[128];
int sides[128];
fixedWinding_t *VisChopWinding( fixedWinding_t *in, pstack_t *stack, const visPlane_t& split ){
float dists[128];
EPlaneSide sides[128];
int counts[3];
vec_t dot;
float dot;
int i, j;
vec_t *p1, *p2;
vec3_t mid;
Vector3 mid;
fixedWinding_t *neww;
counts[0] = counts[1] = counts[2] = 0;
@@ -137,18 +136,16 @@ fixedWinding_t *VisChopWinding( fixedWinding_t *in, pstack_t *stack, visPlane_t
// 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;
dists[i] = plane3_distance_to_point( split, in->points[i] );
if ( dists[i] > ON_EPSILON ) {
sides[i] = eSideFront;
}
else if ( dot < -ON_EPSILON ) {
sides[i] = SIDE_BACK;
else if ( dists[i] < -ON_EPSILON ) {
sides[i] = eSideBack;
}
else
{
sides[i] = SIDE_ON;
sides[i] = eSideOn;
}
counts[sides[i]]++;
}
@@ -171,25 +168,25 @@ fixedWinding_t *VisChopWinding( fixedWinding_t *in, pstack_t *stack, visPlane_t
for ( i = 0 ; i < in->numpoints ; i++ )
{
p1 = in->points[i];
const Vector3& p1 = in->points[i];
if ( neww->numpoints == MAX_POINTS_ON_FIXED_WINDING ) {
FreeStackWinding( neww, stack );
return in; // can't chop -- fall back to original
}
if ( sides[i] == SIDE_ON ) {
VectorCopy( p1, neww->points[neww->numpoints] );
if ( sides[i] == eSideOn ) {
neww->points[neww->numpoints] = p1;
neww->numpoints++;
continue;
}
if ( sides[i] == SIDE_FRONT ) {
VectorCopy( p1, neww->points[neww->numpoints] );
if ( sides[i] == eSideFront ) {
neww->points[neww->numpoints] = p1;
neww->numpoints++;
}
if ( sides[i + 1] == SIDE_ON || sides[i + 1] == sides[i] ) {
if ( sides[i + 1] == eSideOn || sides[i + 1] == sides[i] ) {
continue;
}
@@ -199,23 +196,23 @@ fixedWinding_t *VisChopWinding( fixedWinding_t *in, pstack_t *stack, visPlane_t
}
// generate a split point
p2 = in->points[( i + 1 ) % in->numpoints];
const Vector3& 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;
if ( split.normal()[j] == 1 ) {
mid[j] = split.dist();
}
else 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->points[neww->numpoints] = mid;
neww->numpoints++;
}
@@ -243,10 +240,7 @@ fixedWinding_t *VisChopWinding( fixedWinding_t *in, pstack_t *stack, visPlane_t
*/
fixedWinding_t *ClipToSeperators( fixedWinding_t *source, fixedWinding_t *pass, fixedWinding_t *target, bool flipclip, pstack_t *stack ){
int i, j, k, l;
visPlane_t plane;
vec3_t v1, v2;
float d;
vec_t length;
int counts[3];
bool fliptest;
@@ -254,37 +248,18 @@ fixedWinding_t *ClipToSeperators( fixedWinding_t *source, fixedWinding_t *pass,
for ( i = 0 ; i < source->numpoints ; i++ )
{
l = ( i + 1 ) % source->numpoints;
VectorSubtract( source->points[l], source->points[i], v1 );
// find 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];
visPlane_t plane;
// 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 ) {
if ( !PlaneFromPoints( plane, source->points[i], pass->points[j], source->points[l] ) ) {
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
@@ -296,7 +271,7 @@ fixedWinding_t *ClipToSeperators( fixedWinding_t *source, fixedWinding_t *pass,
if ( k == i || k == l ) {
continue;
}
d = DotProduct( source->points[k], plane.normal ) - plane.dist;
d = plane3_distance_to_point( plane, source->points[k] );
if ( d < -ON_EPSILON ) { // source is on the negative side, so we want all
// pass and target on the positive side
fliptest = false;
@@ -318,8 +293,7 @@ fixedWinding_t *ClipToSeperators( fixedWinding_t *source, fixedWinding_t *pass,
// flip the normal if the source portal is backwards
//
if ( fliptest ) {
VectorSubtract( vec3_origin, plane.normal, plane.normal );
plane.dist = -plane.dist;
plane = plane3_flipped( plane );
}
#if 1
//
@@ -332,7 +306,7 @@ fixedWinding_t *ClipToSeperators( fixedWinding_t *source, fixedWinding_t *pass,
if ( k == j ) {
continue;
}
d = DotProduct( pass->points[k], plane.normal ) - plane.dist;
d = plane3_distance_to_point( plane, pass->points[k] );
if ( d < -ON_EPSILON ) {
break;
}
@@ -352,12 +326,12 @@ fixedWinding_t *ClipToSeperators( fixedWinding_t *source, fixedWinding_t *pass,
}
#else
k = ( j + 1 ) % pass->numpoints;
d = DotProduct( pass->points[k], plane.normal ) - plane.dist;
d = plane3_distance_to_point( plane, pass->points[k] );
if ( d < -ON_EPSILON ) {
continue;
}
k = ( j + pass->numpoints - 1 ) % pass->numpoints;
d = DotProduct( pass->points[k], plane.normal ) - plane.dist;
d = plane3_distance_to_point( plane, pass->points[k] );
if ( d < -ON_EPSILON ) {
continue;
}
@@ -366,8 +340,7 @@ fixedWinding_t *ClipToSeperators( fixedWinding_t *source, fixedWinding_t *pass,
// flip the normal if we want the back side
//
if ( flipclip ) {
VectorSubtract( vec3_origin, plane.normal, plane.normal );
plane.dist = -plane.dist;
plane = plane3_flipped( plane );
}
#ifdef SEPERATORCACHE
@@ -377,7 +350,7 @@ fixedWinding_t *ClipToSeperators( fixedWinding_t *source, fixedWinding_t *pass,
}
#endif
//MrE: fast check first
d = DotProduct( stack->portal->origin, plane.normal ) - plane.dist;
d = plane3_distance_to_point( plane, stack->portal->origin );
//if completely at the back of the seperator plane
if ( d < -stack->portal->radius ) {
return NULL;
@@ -390,7 +363,7 @@ fixedWinding_t *ClipToSeperators( fixedWinding_t *source, fixedWinding_t *pass,
//
// clip target by the seperating plane
//
target = VisChopWinding( target, stack, &plane );
target = VisChopWinding( target, stack, plane );
if ( !target ) {
return NULL; // target is not visible
@@ -495,8 +468,7 @@ void RecursiveLeafFlow( int leafnum, threaddata_t *thread, pstack_t *prevstack )
// 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;
backplane = plane3_flipped( p->plane );
stack.portal = p;
stack.next = NULL;
@@ -506,10 +478,7 @@ void RecursiveLeafFlow( int leafnum, threaddata_t *thread, pstack_t *prevstack )
#if 1
{
float d;
d = DotProduct( p->origin, thread->pstack_head.portalplane.normal );
d -= thread->pstack_head.portalplane.dist;
const float d = plane3_distance_to_point( thread->pstack_head.portalplane, p->origin );
if ( d < -p->radius ) {
continue;
}
@@ -518,7 +487,7 @@ void RecursiveLeafFlow( int leafnum, threaddata_t *thread, pstack_t *prevstack )
}
else
{
stack.pass = VisChopWinding( p->winding, &stack, &thread->pstack_head.portalplane );
stack.pass = VisChopWinding( p->winding, &stack, thread->pstack_head.portalplane );
if ( !stack.pass ) {
continue;
}
@@ -534,10 +503,7 @@ void RecursiveLeafFlow( int leafnum, threaddata_t *thread, pstack_t *prevstack )
#if 1
{
float d;
d = DotProduct( thread->base->origin, p->plane.normal );
d -= p->plane.dist;
const float d = plane3_distance_to_point( p->plane, thread->base->origin );
//MrE: vis-bug fix
//if (d > p->radius)
if ( d > thread->base->radius ) {
@@ -550,7 +516,7 @@ void RecursiveLeafFlow( int leafnum, threaddata_t *thread, pstack_t *prevstack )
}
else
{
stack.source = VisChopWinding( prevstack->source, &stack, &backplane );
stack.source = VisChopWinding( prevstack->source, &stack, backplane );
//FIXME: shouldn't we create a new source origin and radius for fast checks?
if ( !stack.source ) {
continue;
@@ -558,7 +524,7 @@ void RecursiveLeafFlow( int leafnum, threaddata_t *thread, pstack_t *prevstack )
}
}
#else
stack.source = VisChopWinding( prevstack->source, &stack, &backplane );
stack.source = VisChopWinding( prevstack->source, &stack, backplane );
if ( !stack.source ) {
continue;
}
@@ -577,7 +543,7 @@ void RecursiveLeafFlow( int leafnum, threaddata_t *thread, pstack_t *prevstack )
if ( stack.numseperators[0] ) {
for ( n = 0; n < stack.numseperators[0]; n++ )
{
stack.pass = VisChopWinding( stack.pass, &stack, &stack.seperators[0][n] );
stack.pass = VisChopWinding( stack.pass, &stack, stack.seperators[0][n] );
if ( !stack.pass ) {
break; // target is not visible
}
@@ -601,7 +567,7 @@ void RecursiveLeafFlow( int leafnum, threaddata_t *thread, pstack_t *prevstack )
if ( stack.numseperators[1] ) {
for ( n = 0; n < stack.numseperators[1]; n++ )
{
stack.pass = VisChopWinding( stack.pass, &stack, &stack.seperators[1][n] );
stack.pass = VisChopWinding( stack.pass, &stack, stack.seperators[1][n] );
if ( !stack.pass ) {
break; // target is not visible
}
@@ -884,8 +850,7 @@ void RecursivePassagePortalFlow( vportal_t *portal, threaddata_t *thread, pstack
// 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;
backplane = plane3_flipped( p->plane );
stack.portal = p;
stack.next = NULL;
@@ -895,10 +860,7 @@ void RecursivePassagePortalFlow( vportal_t *portal, threaddata_t *thread, pstack
#if 1
{
float d;
d = DotProduct( p->origin, thread->pstack_head.portalplane.normal );
d -= thread->pstack_head.portalplane.dist;
const float d = plane3_distance_to_point( thread->pstack_head.portalplane, p->origin );
if ( d < -p->radius ) {
continue;
}
@@ -907,14 +869,14 @@ void RecursivePassagePortalFlow( vportal_t *portal, threaddata_t *thread, pstack
}
else
{
stack.pass = VisChopWinding( p->winding, &stack, &thread->pstack_head.portalplane );
stack.pass = VisChopWinding( p->winding, &stack, thread->pstack_head.portalplane );
if ( !stack.pass ) {
continue;
}
}
}
#else
stack.pass = VisChopWinding( p->winding, &stack, &thread->pstack_head.portalplane );
stack.pass = VisChopWinding( p->winding, &stack, thread->pstack_head.portalplane );
if ( !stack.pass ) {
continue;
}
@@ -923,10 +885,7 @@ void RecursivePassagePortalFlow( vportal_t *portal, threaddata_t *thread, pstack
#if 1
{
float d;
d = DotProduct( thread->base->origin, p->plane.normal );
d -= p->plane.dist;
const float d = plane3_distance_to_point( p->plane, thread->base->origin );
//MrE: vis-bug fix
//if (d > p->radius)
if ( d > thread->base->radius ) {
@@ -939,7 +898,7 @@ void RecursivePassagePortalFlow( vportal_t *portal, threaddata_t *thread, pstack
}
else
{
stack.source = VisChopWinding( prevstack->source, &stack, &backplane );
stack.source = VisChopWinding( prevstack->source, &stack, backplane );
//FIXME: shouldn't we create a new source origin and radius for fast checks?
if ( !stack.source ) {
continue;
@@ -947,7 +906,7 @@ void RecursivePassagePortalFlow( vportal_t *portal, threaddata_t *thread, pstack
}
}
#else
stack.source = VisChopWinding( prevstack->source, &stack, &backplane );
stack.source = VisChopWinding( prevstack->source, &stack, backplane );
if ( !stack.source ) {
continue;
}
@@ -966,7 +925,7 @@ void RecursivePassagePortalFlow( vportal_t *portal, threaddata_t *thread, pstack
if ( stack.numseperators[0] ) {
for ( n = 0; n < stack.numseperators[0]; n++ )
{
stack.pass = VisChopWinding( stack.pass, &stack, &stack.seperators[0][n] );
stack.pass = VisChopWinding( stack.pass, &stack, stack.seperators[0][n] );
if ( !stack.pass ) {
break; // target is not visible
}
@@ -990,7 +949,7 @@ void RecursivePassagePortalFlow( vportal_t *portal, threaddata_t *thread, pstack
if ( stack.numseperators[1] ) {
for ( n = 0; n < stack.numseperators[1]; n++ )
{
stack.pass = VisChopWinding( stack.pass, &stack, &stack.seperators[1][n] );
stack.pass = VisChopWinding( stack.pass, &stack, stack.seperators[1][n] );
if ( !stack.pass ) {
break; // target is not visible
}
@@ -1065,14 +1024,13 @@ void PassagePortalFlow( int portalnum ){
*/
}
fixedWinding_t *PassageChopWinding( fixedWinding_t *in, fixedWinding_t *out, visPlane_t *split ){
vec_t dists[128];
int sides[128];
fixedWinding_t *PassageChopWinding( fixedWinding_t *in, fixedWinding_t *out, const visPlane_t& split ){
float dists[128];
EPlaneSide sides[128];
int counts[3];
vec_t dot;
float dot;
int i, j;
vec_t *p1, *p2;
vec3_t mid;
Vector3 mid;
fixedWinding_t *neww;
counts[0] = counts[1] = counts[2] = 0;
@@ -1080,18 +1038,16 @@ fixedWinding_t *PassageChopWinding( fixedWinding_t *in, fixedWinding_t *out, vis
// 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;
dists[i] = plane3_distance_to_point( split, in->points[i] );
if ( dists[i] > ON_EPSILON ) {
sides[i] = eSideFront;
}
else if ( dot < -ON_EPSILON ) {
sides[i] = SIDE_BACK;
else if ( dists[i] < -ON_EPSILON ) {
sides[i] = eSideBack;
}
else
{
sides[i] = SIDE_ON;
sides[i] = eSideOn;
}
counts[sides[i]]++;
}
@@ -1113,24 +1069,24 @@ fixedWinding_t *PassageChopWinding( fixedWinding_t *in, fixedWinding_t *out, vis
for ( i = 0 ; i < in->numpoints ; i++ )
{
p1 = in->points[i];
const Vector3& p1 = in->points[i];
if ( neww->numpoints == MAX_POINTS_ON_FIXED_WINDING ) {
return in; // can't chop -- fall back to original
}
if ( sides[i] == SIDE_ON ) {
VectorCopy( p1, neww->points[neww->numpoints] );
if ( sides[i] == eSideOn ) {
neww->points[neww->numpoints] = p1;
neww->numpoints++;
continue;
}
if ( sides[i] == SIDE_FRONT ) {
VectorCopy( p1, neww->points[neww->numpoints] );
if ( sides[i] == eSideFront ) {
neww->points[neww->numpoints] = p1;
neww->numpoints++;
}
if ( sides[i + 1] == SIDE_ON || sides[i + 1] == sides[i] ) {
if ( sides[i + 1] == eSideOn || sides[i + 1] == sides[i] ) {
continue;
}
@@ -1139,23 +1095,23 @@ fixedWinding_t *PassageChopWinding( fixedWinding_t *in, fixedWinding_t *out, vis
}
// generate a split point
p2 = in->points[( i + 1 ) % in->numpoints];
const Vector3& 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;
if ( split.normal()[j] == 1 ) {
mid[j] = split.dist();
}
else 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->points[neww->numpoints] = mid;
neww->numpoints++;
}
@@ -1169,10 +1125,6 @@ fixedWinding_t *PassageChopWinding( fixedWinding_t *in, fixedWinding_t *out, vis
*/
int AddSeperators( fixedWinding_t *source, fixedWinding_t *pass, bool flipclip, visPlane_t *seperators, int maxseperators ){
int i, j, k, l;
visPlane_t plane;
vec3_t v1, v2;
float d;
vec_t length;
int counts[3], numseperators;
bool fliptest;
@@ -1181,37 +1133,18 @@ int AddSeperators( fixedWinding_t *source, fixedWinding_t *pass, bool flipclip,
for ( i = 0 ; i < source->numpoints ; i++ )
{
l = ( i + 1 ) % source->numpoints;
VectorSubtract( source->points[l], source->points[i], v1 );
// find 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];
visPlane_t plane;
// 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 ) {
if ( !PlaneFromPoints( plane, source->points[i], pass->points[j], source->points[l] ) ) {
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
@@ -1223,7 +1156,7 @@ int AddSeperators( fixedWinding_t *source, fixedWinding_t *pass, bool flipclip,
if ( k == i || k == l ) {
continue;
}
d = DotProduct( source->points[k], plane.normal ) - plane.dist;
const double d = plane3_distance_to_point( plane, source->points[k] );
if ( d < -ON_EPSILON ) { // source is on the negative side, so we want all
// pass and target on the positive side
fliptest = false;
@@ -1245,8 +1178,7 @@ int AddSeperators( fixedWinding_t *source, fixedWinding_t *pass, bool flipclip,
// flip the normal if the source portal is backwards
//
if ( fliptest ) {
VectorSubtract( vec3_origin, plane.normal, plane.normal );
plane.dist = -plane.dist;
plane = plane3_flipped( plane );
}
#if 1
//
@@ -1259,7 +1191,7 @@ int AddSeperators( fixedWinding_t *source, fixedWinding_t *pass, bool flipclip,
if ( k == j ) {
continue;
}
d = DotProduct( pass->points[k], plane.normal ) - plane.dist;
const double d = plane3_distance_to_point( plane, pass->points[k] );
if ( d < -ON_EPSILON ) {
break;
}
@@ -1279,12 +1211,12 @@ int AddSeperators( fixedWinding_t *source, fixedWinding_t *pass, bool flipclip,
}
#else
k = ( j + 1 ) % pass->numpoints;
d = DotProduct( pass->points[k], plane.normal ) - plane.dist;
d = vector3_dot( pass->points[k], plane.normal ) - plane.dist;
if ( d < -ON_EPSILON ) {
continue;
}
k = ( j + pass->numpoints - 1 ) % pass->numpoints;
d = DotProduct( pass->points[k], plane.normal ) - plane.dist;
d = vector3_dot( pass->points[k], plane.normal ) - plane.dist;
if ( d < -ON_EPSILON ) {
continue;
}
@@ -1293,8 +1225,7 @@ int AddSeperators( fixedWinding_t *source, fixedWinding_t *pass, bool flipclip,
// flip the normal if we want the back side
//
if ( flipclip ) {
VectorSubtract( vec3_origin, plane.normal, plane.normal );
plane.dist = -plane.dist;
plane = plane3_flipped( plane );
}
if ( numseperators >= maxseperators ) {
@@ -1319,7 +1250,6 @@ int AddSeperators( fixedWinding_t *source, fixedWinding_t *pass, bool flipclip,
*/
void CreatePassages( int portalnum ){
int i, j, k, n, numseperators, numsee;
float d;
vportal_t *portal, *p, *target;
leaf_t *leaf;
passage_t *passage, *lastpassage;
@@ -1377,18 +1307,15 @@ void CreatePassages( int portalnum ){
}
for ( k = 0; k < numseperators; k++ )
{
//
d = DotProduct( p->origin, seperators[k].normal ) - seperators[k].dist;
//if completely at the back of the seperator plane
if ( d < -p->radius + ON_EPSILON ) {
if ( plane3_distance_to_point( seperators[k], p->origin ) < -p->radius + ON_EPSILON ) {
break;
}
w = p->winding;
for ( n = 0; n < w->numpoints; n++ )
{
d = DotProduct( w->points[n], seperators[k].normal ) - seperators[k].dist;
//if at the front of the seperator
if ( d > ON_EPSILON ) {
if ( plane3_distance_to_point( seperators[k], w->points[n] ) > ON_EPSILON ) {
break;
}
}
@@ -1407,7 +1334,7 @@ void CreatePassages( int portalnum ){
/* ydnar: prefer correctness to stack overflow */
//% memcpy( &in, p->winding, (int)((fixedWinding_t *)0)->points[p->winding->numpoints] );
if ( p->winding->numpoints <= MAX_POINTS_ON_FIXED_WINDING ) {
memcpy( &in, p->winding, (size_t)((fixedWinding_t *)0)->points[p->winding->numpoints] );
memcpy( &in, p->winding, (size_t)&( ( (fixedWinding_t *)0 )->points[p->winding->numpoints] ) );
// memcpy( &in, p->winding, offsetof( fixedWinding_t, points[p->winding->numpoints] ) );
}
else{
@@ -1423,7 +1350,7 @@ void CreatePassages( int portalnum ){
in.numpoints = MAX_POINTS_ON_FIXED_WINDING;
}
res = PassageChopWinding( &in, &out, &seperators[ k ] );
res = PassageChopWinding( &in, &out, seperators[ k ] );
if ( res == &out ) {
memcpy( &in, &out, sizeof( fixedWinding_t ) );
}
@@ -1557,9 +1484,7 @@ void SimpleFlood( vportal_t *srcportal, int leafnum ){
void BasePortalVis( int portalnum ){
int j, k;
vportal_t *tp, *p;
float d;
fixedWinding_t *w;
vec3_t dir;
p = portals + portalnum;
@@ -1593,13 +1518,12 @@ void BasePortalVis( int portalnum ){
*/
if ( !p->sky && !tp->sky && farPlaneDist != 0.0f ) {
VectorSubtract( p->origin, tp->origin, dir );
if( farPlaneDistMode == 'o' ){
if( VectorLength( dir ) > farPlaneDist )
if( vector3_length( p->origin - tp->origin ) > farPlaneDist )
continue;
}
else if( farPlaneDistMode == 'e' ){
if( VectorLength( dir ) + p->radius + tp->radius > 2.0f * farPlaneDist )
if( vector3_length( p->origin - tp->origin ) + p->radius + tp->radius > 2.0f * farPlaneDist )
continue;
}
else if( farPlaneDistMode == 'r' ){
@@ -1607,7 +1531,7 @@ void BasePortalVis( int portalnum ){
continue;
}
else{ /* ydnar: this is known-to-be-working farplane code */
if ( VectorLength( dir ) - p->radius - tp->radius > farPlaneDist )
if ( vector3_length( p->origin - tp->origin ) - p->radius - tp->radius > farPlaneDist )
continue;
}
@@ -1617,9 +1541,7 @@ void BasePortalVis( int portalnum ){
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 ) {
if ( plane3_distance_to_point( p->plane, w->points[k] ) > ON_EPSILON ) {
break;
}
}
@@ -1630,9 +1552,7 @@ void BasePortalVis( int portalnum ){
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 ) {
if ( plane3_distance_to_point( tp->plane, w->points[k] ) < -ON_EPSILON ) {
break;
}
}
+22 -43
View File
@@ -111,19 +111,12 @@ int EmitShader( const char *shader, int *contentFlags, int *surfaceFlags ){
*/
void EmitPlanes( void ){
int i;
bspPlane_t *bp;
plane_t *mp;
/* walk plane list */
mp = mapplanes;
for ( i = 0; i < nummapplanes; i++, mp++ )
plane_t *mp = mapplanes;
for ( int i = 0; i < nummapplanes; i++, mp++ )
{
AUTOEXPAND_BY_REALLOC_BSP( Planes, 1024 );
bp = &bspPlanes[ numBSPPlanes ];
VectorCopy( mp->normal, bp->normal );
bp->dist = mp->dist;
bspPlanes[ numBSPPlanes ] = mp->plane;
numBSPPlanes++;
}
@@ -156,8 +149,8 @@ void EmitLeaf( node_t *node ){
leaf_p->area = node->area;
/* emit bounding box */
VectorCopy( node->mins, leaf_p->mins );
VectorCopy( node->maxs, leaf_p->maxs );
leaf_p->minmax.maxs = node->minmax.maxs;
leaf_p->minmax.mins = node->minmax.mins;
/* emit leaf brushes */
leaf_p->firstBSPLeafBrush = numBSPLeafBrushes;
@@ -218,8 +211,8 @@ int EmitDrawNode_r( node_t *node ){
n = &bspNodes[ n0 ];
numBSPNodes++;
VectorCopy( node->mins, n->mins );
VectorCopy( node->maxs, n->maxs );
n->minmax.mins = node->minmax.mins;
n->minmax.maxs = node->minmax.maxs;
if ( node->planenum & 1 ) {
Error( "WriteDrawNodes_r: odd planenum" );
@@ -534,66 +527,52 @@ void EmitFogs( void ){
*/
void BeginModel( void ){
bspModel_t *mod;
brush_t *b;
entity_t *e;
vec3_t mins, maxs;
vec3_t lgMins, lgMaxs; /* ydnar: lightgrid mins/maxs */
parseMesh_t *p;
int i;
MinMax minmax;
MinMax lgMinmax; /* ydnar: lightgrid mins/maxs */
/* test limits */
AUTOEXPAND_BY_REALLOC_BSP( Models, 256 );
/* get model and entity */
mod = &bspModels[ numBSPModels ];
e = &entities[ mapEntityNum ];
/* ydnar: lightgrid mins/maxs */
ClearBounds( lgMins, lgMaxs );
bspModel_t *mod = &bspModels[ numBSPModels ];
const entity_t& e = entities[ mapEntityNum ];
/* bound the brushes */
ClearBounds( mins, maxs );
for ( b = e->brushes; b; b = b->next )
for ( const brush_t *b = e.brushes; b; b = b->next )
{
/* ignore non-real brushes (origin, etc) */
if ( b->numsides == 0 ) {
continue;
}
AddPointToBounds( b->mins, mins, maxs );
AddPointToBounds( b->maxs, mins, maxs );
minmax.extend( b->minmax );
/* ydnar: lightgrid bounds */
if ( b->compileFlags & C_LIGHTGRID ) {
AddPointToBounds( b->mins, lgMins, lgMaxs );
AddPointToBounds( b->maxs, lgMins, lgMaxs );
lgMinmax.extend( b->minmax );
}
}
/* bound patches */
for ( p = e->patches; p; p = p->next )
for ( const parseMesh_t *p = e.patches; p; p = p->next )
{
for ( i = 0; i < ( p->mesh.width * p->mesh.height ); i++ )
AddPointToBounds( p->mesh.verts[i].xyz, mins, maxs );
for ( int i = 0; i < ( p->mesh.width * p->mesh.height ); i++ )
minmax.extend( p->mesh.verts[i].xyz );
}
/* ydnar: lightgrid mins/maxs */
if ( lgMins[ 0 ] < 99999 ) {
if ( lgMinmax.mins[ 0 ] < 99999 ) {
/* use lightgrid bounds */
VectorCopy( lgMins, mod->mins );
VectorCopy( lgMaxs, mod->maxs );
mod->minmax = lgMinmax;
}
else
{
/* use brush/patch bounds */
VectorCopy( mins, mod->mins );
VectorCopy( maxs, mod->maxs );
mod->minmax = minmax;
}
/* note size */
Sys_FPrintf( SYS_VRB, "BSP bounds: { %f %f %f } { %f %f %f }\n", mins[ 0 ], mins[ 1 ], mins[ 2 ], maxs[ 0 ], maxs[ 1 ], maxs[ 2 ] );
Sys_FPrintf( SYS_VRB, "Lightgrid bounds: { %f %f %f } { %f %f %f }\n", lgMins[ 0 ], lgMins[ 1 ], lgMins[ 2 ], lgMaxs[ 0 ], lgMaxs[ 1 ], lgMaxs[ 2 ] );
Sys_FPrintf( SYS_VRB, "BSP bounds: { %f %f %f } { %f %f %f }\n", minmax.mins[0], minmax.mins[1], minmax.mins[2], minmax.maxs[0], minmax.maxs[1], minmax.maxs[2] );
Sys_FPrintf( SYS_VRB, "Lightgrid bounds: { %f %f %f } { %f %f %f }\n", lgMinmax.mins[0], lgMinmax.mins[1], lgMinmax.mins[2], lgMinmax.maxs[0], lgMinmax.maxs[1], lgMinmax.maxs[2] );
/* set firsts */
mod->firstBSPSurface = numBSPDrawSurfaces;