mirror of
https://github.com/Garux/netradiant-custom.git
synced 2026-09-28 00:00:03 +02:00
* improved brush faces triangulation wrt degenerate triangles production (non -maxarea algorithm)
This commit is contained in:
@@ -176,6 +176,7 @@ Q3map2:
|
||||
-light -extlmhacksize 1024 -trisoup //gen shaders for external lms and mark as trisoup
|
||||
* generate shaders to force nomipmaps flag on external lightmap images created by lightstyles and external lms hacks
|
||||
* -nobrushsnap: disable brush vertices snapping (of drawsurfs) (experimental, keep eye on meta merge efficiency)
|
||||
* improved brush faces triangulation wrt degenerate triangles production (non -maxarea algorithm)
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -352,4 +352,32 @@ inline void ColorNormalize( Vector3& color ) {
|
||||
else{
|
||||
color *= ( 1.f / max );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
inline double angle_squared_sin( const Vector3& a, const Vector3& b, const Vector3& c ){
|
||||
const Vector3 d1 = b - a;
|
||||
const Vector3 d2 = c - a;
|
||||
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 = vector3_length_squared( d1 ) * vector3_length_squared( d2 );
|
||||
return lengthsSquared == 0? 0 : ( vector3_length_squared( normal ) / lengthsSquared );
|
||||
}
|
||||
|
||||
inline double triangle_min_angle_squared_sin( const Vector3& a, const Vector3& b, const Vector3& c ){
|
||||
const Vector3 d[3] = { b - a, c - a, c - b };
|
||||
const double l[3] = { vector3_length_squared( d[0] ), vector3_length_squared( d[1] ), vector3_length_squared( d[2] ) };
|
||||
const size_t mini = ( l[0] < l[1] ) ? ( ( l[0] < l[2] ) ? 0 : 2 ) : ( ( l[1] < l[2] ) ? 1 : 2 );
|
||||
if( l[mini] == 0 )
|
||||
return 0;
|
||||
|
||||
const size_t minj = mini == 2? 0 : mini + 1;
|
||||
const size_t mink = minj == 2? 0 : minj + 1;
|
||||
return vector3_length_squared( vector3_cross( d[minj], d[mink] ) ) / ( l[minj] * l[mink] );
|
||||
}
|
||||
|
||||
|
||||
inline double triangle_area2x( const Vector3& a, const Vector3& b, const Vector3& c ){
|
||||
return vector3_length( vector3_cross( b - a, c - a ) );
|
||||
}
|
||||
|
||||
@@ -584,18 +584,10 @@ static void ClipModel( int spawnFlags, float clipDepth, shaderInfo_t *si, const
|
||||
}
|
||||
|
||||
/* sanity check */
|
||||
{
|
||||
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 = vector3_length_squared( d1 ) * vector3_length_squared( d2 );
|
||||
if ( lengthsSquared == 0 || ( 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], modelName );
|
||||
continue;
|
||||
}
|
||||
if ( triangle_min_angle_squared_sin( points[0], points[1], points[2] ) < 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], modelName );
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1545,7 +1545,6 @@ void ClassifySurfaces( int numSurfs, mapDrawSurface_t *ds
|
||||
void ClassifyEntitySurfaces( const entity_t& e );
|
||||
void TidyEntitySurfaces( const entity_t& e );
|
||||
mapDrawSurface_t *CloneSurface( mapDrawSurface_t *src, shaderInfo_t *si );
|
||||
bool IsTriangleDegenerate( bspDrawVert_t *points, int a, int b, int c );
|
||||
void ClearSurface( mapDrawSurface_t *ds );
|
||||
mapDrawSurface_t *DrawSurfaceForSide( const entity_t& e, const brush_t& b, const side_t& s, const winding_t& w );
|
||||
mapDrawSurface_t *DrawSurfaceForMesh( const entity_t& e, parseMesh_t *p, mesh_t *mesh );
|
||||
|
||||
@@ -218,26 +218,6 @@ static mapDrawSurface_t *MakeSkyboxSurface( mapDrawSurface_t *src ){
|
||||
|
||||
|
||||
|
||||
/*
|
||||
IsTriangleDegenerate
|
||||
returns true if all three points are colinear, backwards, or the triangle is just plain bogus
|
||||
*/
|
||||
|
||||
#define TINY_AREA 1.0f
|
||||
|
||||
bool IsTriangleDegenerate( bspDrawVert_t *points, int a, int b, int c ){
|
||||
/* calcuate the area of the triangle */
|
||||
/* assume all very small or backwards triangles will cause problems */
|
||||
if ( vector3_length( vector3_cross( points[ b ].xyz - points[ a ].xyz, points[ c ].xyz - points[ a ].xyz ) ) < TINY_AREA ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
/* must be a good triangle */
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
ClearSurface() - ydnar
|
||||
clears a surface and frees any allocated memory
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
|
||||
/* dependencies */
|
||||
#include "q3map2.h"
|
||||
#include "tjunction.h"
|
||||
#include "timer.h"
|
||||
#include <map>
|
||||
#include <set>
|
||||
@@ -435,7 +436,7 @@ static void TriangulatePatchSurface( const entity_t& e, mapDrawSurface_t *ds ){
|
||||
ClassifySurfaces( 1, ds );
|
||||
}
|
||||
|
||||
#define TINY_AREA 1.0f
|
||||
#define TINY_AREA 1.0
|
||||
#define MAXAREA_MAXTRIES 8
|
||||
static int MaxAreaIndexes( bspDrawVert_t *vert, int cnt, int *indexes ){
|
||||
int r, s, t, bestR = 0, bestS = 1, bestT = 2;
|
||||
@@ -452,7 +453,7 @@ static int MaxAreaIndexes( bspDrawVert_t *vert, int cnt, int *indexes ){
|
||||
A = 0;
|
||||
for ( i = 1; i + 1 < cnt; ++i )
|
||||
{
|
||||
A += vector3_length( vector3_cross( vert[i].xyz - vert[0].xyz, vert[i + 1].xyz - vert[0].xyz ) );
|
||||
A += triangle_area2x( vert[0].xyz, vert[i].xyz, vert[i + 1].xyz );
|
||||
}
|
||||
V = 0;
|
||||
for ( i = 0; i < cnt; ++i )
|
||||
@@ -533,7 +534,7 @@ static int MaxAreaIndexes( bspDrawVert_t *vert, int cnt, int *indexes ){
|
||||
}
|
||||
// abc abc abc abc abc abc
|
||||
|
||||
bestA = vector3_length( vector3_cross( vert[bestS].xyz - vert[bestR].xyz, vert[bestT].xyz - vert[bestR].xyz ) );
|
||||
bestA = triangle_area2x( vert[bestR].xyz, vert[bestS].xyz, vert[bestT].xyz );
|
||||
}
|
||||
|
||||
if ( bestA < TINY_AREA ) {
|
||||
@@ -727,8 +728,7 @@ static void FanFaceSurface( mapDrawSurface_t *ds ){
|
||||
#define MAX_INDEXES 1024
|
||||
|
||||
void StripFaceSurface( mapDrawSurface_t *ds ){
|
||||
int i, r, least, rotate, numIndexes, ni, a, b, c, indexes[ MAX_INDEXES ];
|
||||
|
||||
int numIndexes, indexes[ MAX_INDEXES ];
|
||||
|
||||
/* try to early out */
|
||||
if ( !ds->numVerts || ( ds->type != ESurfaceType::Face && ds->type != ESurfaceType::Decal ) ) {
|
||||
@@ -745,9 +745,9 @@ void StripFaceSurface( mapDrawSurface_t *ds ){
|
||||
else
|
||||
{
|
||||
/* ydnar: find smallest coordinate */
|
||||
least = 0;
|
||||
int least = 0;
|
||||
if ( ds->shaderInfo != NULL && !ds->shaderInfo->autosprite ) {
|
||||
for ( i = 0; i < ds->numVerts; i++ )
|
||||
for ( int i = 0; i < ds->numVerts; i++ )
|
||||
{
|
||||
/* get points */
|
||||
const Vector3& v1 = ds->verts[ i ].xyz;
|
||||
@@ -768,59 +768,55 @@ void StripFaceSurface( mapDrawSurface_t *ds ){
|
||||
Error( "MAX_INDEXES exceeded for surface (%d > %d) (%d verts)", numIndexes, MAX_INDEXES, ds->numVerts );
|
||||
}
|
||||
|
||||
/* try all possible orderings of the points looking for a non-degenerate strip order */
|
||||
ni = 0;
|
||||
for ( r = 0; r < ds->numVerts; r++ )
|
||||
class TriEval
|
||||
{
|
||||
/* set rotation */
|
||||
rotate = ( r + least ) % ds->numVerts;
|
||||
const bspDrawVert_t *m_verts;
|
||||
double m_area = std::numeric_limits<double>::max(); // 2x area
|
||||
double m_angle = std::numeric_limits<double>::max(); // squared sin of the angle
|
||||
public:
|
||||
TriEval( const bspDrawVert_t *verts ) : m_verts( verts ){
|
||||
}
|
||||
void push( int a, int b, int c ){
|
||||
value_minimize( m_angle, triangle_min_angle_squared_sin( m_verts[a].xyz, m_verts[b].xyz, m_verts[c].xyz ) );
|
||||
value_minimize( m_area, triangle_area2x( m_verts[a].xyz, m_verts[b].xyz, m_verts[c].xyz ) );
|
||||
}
|
||||
bool decent() const {
|
||||
return m_angle > 1e-5 && m_area > TINY_AREA;
|
||||
}
|
||||
void reset(){
|
||||
*this = TriEval( m_verts );
|
||||
}
|
||||
} triEval( ds->verts );
|
||||
|
||||
const auto idx = [n = ds->numVerts]( int i ){ return i < 0? i + n : i < n? i : i - n; };
|
||||
|
||||
/* try all possible orderings of the points looking for a non-degenerate strip order */
|
||||
for ( int r = 0; r < ds->numVerts; ++r )
|
||||
{
|
||||
triEval.reset();
|
||||
/* walk the winding in both directions */
|
||||
for ( ni = 0, i = 0; i < ds->numVerts - 2 - i; i++ )
|
||||
for( int i = idx( r + least ), j = idx( i - 1 ), k, swap = 0, out = 0;
|
||||
( swap ^= bspDrawVert_is_tjunc( ds->verts[idx( swap? i + 1 : j - 1 )] )
|
||||
>= bspDrawVert_is_tjunc( ds->verts[idx( swap? j - 1 : i + 1 )] ) )
|
||||
? ( k = j, j = idx( --j ) ) : ( k = i, i = idx( ++i ) ), i != j; )
|
||||
{
|
||||
/* make indexes */
|
||||
a = ( ds->numVerts - 1 - i + rotate ) % ds->numVerts;
|
||||
b = ( i + rotate ) % ds->numVerts;
|
||||
c = ( ds->numVerts - 2 - i + rotate ) % ds->numVerts;
|
||||
|
||||
/* test this triangle */
|
||||
if ( ds->numVerts > 4 && IsTriangleDegenerate( ds->verts, a, b, c ) ) {
|
||||
if ( triEval.push( i, j, k ), !triEval.decent() ) {
|
||||
break;
|
||||
}
|
||||
indexes[ ni++ ] = a;
|
||||
indexes[ ni++ ] = b;
|
||||
indexes[ ni++ ] = c;
|
||||
|
||||
/* handle end case */
|
||||
if ( i + 1 != ds->numVerts - 1 - i ) {
|
||||
/* make indexes */
|
||||
a = ( ds->numVerts - 2 - i + rotate ) % ds->numVerts;
|
||||
b = ( i + rotate ) % ds->numVerts;
|
||||
c = ( i + 1 + rotate ) % ds->numVerts;
|
||||
|
||||
/* test triangle */
|
||||
if ( ds->numVerts > 4 && IsTriangleDegenerate( ds->verts, a, b, c ) ) {
|
||||
break;
|
||||
}
|
||||
indexes[ ni++ ] = a;
|
||||
indexes[ ni++ ] = b;
|
||||
indexes[ ni++ ] = c;
|
||||
}
|
||||
indexes[ out++ ] = i;
|
||||
indexes[ out++ ] = j;
|
||||
indexes[ out++ ] = k;
|
||||
}
|
||||
|
||||
/* valid strip? */
|
||||
if ( ni == numIndexes ) {
|
||||
break;
|
||||
}
|
||||
if( triEval.decent() )
|
||||
goto okej;
|
||||
}
|
||||
|
||||
/* if any triangle in the strip is degenerate, render from a centered fan point instead */
|
||||
if ( ni < numIndexes ) {
|
||||
FanFaceSurface( ds );
|
||||
return;
|
||||
}
|
||||
return FanFaceSurface( ds );
|
||||
}
|
||||
|
||||
okej:
|
||||
/* copy strip triangle indexes */
|
||||
ds->numIndexes = numIndexes;
|
||||
ds->indexes = safe_malloc( ds->numIndexes * sizeof( int ) );
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
|
||||
/* dependencies */
|
||||
#include "q3map2.h"
|
||||
#include "tjunction.h"
|
||||
|
||||
|
||||
|
||||
@@ -209,8 +210,7 @@ static void AddSurfaceEdges( mapDrawSurface_t& ds ){
|
||||
for ( int i = 0; i < ds.numVerts; i++ )
|
||||
{
|
||||
/* 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 ], ds.verts[ ( i + 1 ) % ds.numVerts ], false );
|
||||
bspDrawVert_edge_index_write( ds.verts[ i ], AddEdge( ds.verts[ i ], ds.verts[ ( i + 1 ) % ds.numVerts ], false ) );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -309,18 +309,13 @@ static void AddPatchEdges( mapDrawSurface_t& ds ) {
|
||||
*/
|
||||
#define MAX_SURFACE_VERTS 256
|
||||
static void FixSurfaceJunctions( mapDrawSurface_t& ds ) {
|
||||
int i, j, k;
|
||||
edgeLine_t *e;
|
||||
edgePoint_t *p;
|
||||
int counts[MAX_SURFACE_VERTS];
|
||||
int originals[MAX_SURFACE_VERTS];
|
||||
bspDrawVert_t verts[MAX_SURFACE_VERTS], *v1, *v2;
|
||||
int numVerts;
|
||||
float start, end, c;
|
||||
bspDrawVert_t verts[MAX_SURFACE_VERTS];
|
||||
int numVerts = 0;
|
||||
|
||||
|
||||
numVerts = 0;
|
||||
for ( i = 0; i < ds.numVerts; ++i )
|
||||
for ( int i = 0; i < ds.numVerts; ++i )
|
||||
{
|
||||
counts[i] = 0;
|
||||
|
||||
@@ -333,28 +328,20 @@ static void FixSurfaceJunctions( mapDrawSurface_t& ds ) {
|
||||
numVerts++;
|
||||
|
||||
// check to see if there are any t junctions before the next vert
|
||||
v1 = &ds.verts[i];
|
||||
v2 = &ds.verts[ ( i + 1 ) % ds.numVerts ];
|
||||
const bspDrawVert_t& v1 = ds.verts[i];
|
||||
const bspDrawVert_t& v2 = ds.verts[ ( i + 1 ) % ds.numVerts ];
|
||||
|
||||
j = (int)ds.verts[i].lightmap[ 0 ][ 0 ];
|
||||
const int j = bspDrawVert_edge_index_read( ds.verts[ i ] );
|
||||
if ( j == -1 ) {
|
||||
continue; // degenerate edge
|
||||
}
|
||||
e = &edgeLines[ j ];
|
||||
const edgeLine_t& e = edgeLines[ j ];
|
||||
|
||||
start = vector3_dot( v1->xyz - e->origin, e->dir );
|
||||
const float start = vector3_dot( v1.xyz - e.origin, e.dir );
|
||||
|
||||
end = vector3_dot( v2->xyz - e->origin, e->dir );
|
||||
const float end = vector3_dot( v2.xyz - e.origin, e.dir );
|
||||
|
||||
|
||||
if ( start < end ) {
|
||||
p = e->chain->next;
|
||||
}
|
||||
else {
|
||||
p = e->chain->prev;
|
||||
}
|
||||
|
||||
for ( ; p != e->chain; ) {
|
||||
for ( edgePoint_t *p = ( start < end )? e.chain->next : e.chain->prev; p != e.chain; p = ( start < end )? p->next : p->prev ) {
|
||||
if ( start < end ) {
|
||||
if ( p->intercept > end - ON_EPSILON ) {
|
||||
break;
|
||||
@@ -372,39 +359,36 @@ static void FixSurfaceJunctions( mapDrawSurface_t& ds ) {
|
||||
if ( numVerts == MAX_SURFACE_VERTS ) {
|
||||
Error( "MAX_SURFACE_VERTS" );
|
||||
}
|
||||
bspDrawVert_t& v = verts[ numVerts ];
|
||||
|
||||
/* take the exact intercept point */
|
||||
verts[ numVerts ].xyz = p->xyz;
|
||||
v.xyz = p->xyz;
|
||||
|
||||
/* interpolate the texture coordinates */
|
||||
const float frac = ( p->intercept - start ) / ( end - start );
|
||||
verts[ numVerts ].st = v1->st + ( v2->st - v1->st ) * frac;
|
||||
v.st = v1.st + ( v2.st - v1.st ) * frac;
|
||||
|
||||
/* copy the normal (FIXME: what about nonplanar surfaces? */
|
||||
verts[ numVerts ].normal = v1->normal;
|
||||
v.normal = v1.normal;
|
||||
|
||||
/* ydnar: interpolate the color */
|
||||
for ( k = 0; k < MAX_LIGHTMAPS; k++ )
|
||||
for ( int k = 0; k < MAX_LIGHTMAPS; ++k )
|
||||
{
|
||||
for ( j = 0; j < 4; j++ )
|
||||
for ( int j = 0; j < 4; ++j )
|
||||
{
|
||||
c = (float) v1->color[ k ][ j ] + frac * ( (float) v2->color[ k ][ j ] - (float) v1->color[ k ][ j ] );
|
||||
verts[ numVerts ].color[ k ][ j ] = color_to_byte( c );
|
||||
const float c = v1.color[ k ][ j ] + frac * ( v2.color[ k ][ j ] - v1.color[ k ][ j ] );
|
||||
v.color[ k ][ j ] = color_to_byte( c );
|
||||
}
|
||||
v.lightmap[ k ] = { 0, 0 }; // do zero init
|
||||
}
|
||||
v.lightmap[ 0 ] = vector2_mid( v1.lightmap[ 0 ], v2.lightmap[ 0 ] );
|
||||
bspDrawVert_mark_tjunc( v );
|
||||
|
||||
/* next... */
|
||||
originals[ numVerts ] = i;
|
||||
numVerts++;
|
||||
counts[ i ]++;
|
||||
}
|
||||
|
||||
if ( start < end ) {
|
||||
p = p->next;
|
||||
}
|
||||
else {
|
||||
p = p->prev;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -417,12 +401,13 @@ static void FixSurfaceJunctions( mapDrawSurface_t& ds ) {
|
||||
|
||||
// rotate the points so that the initial vertex is between
|
||||
// two non-subdivided edges
|
||||
int i;
|
||||
for ( i = 0; i < numVerts; ++i ) {
|
||||
if ( originals[ ( i + 1 ) % numVerts ] == originals[ i ] ) {
|
||||
continue;
|
||||
}
|
||||
j = ( i + numVerts - 1 ) % numVerts;
|
||||
k = ( i + numVerts - 2 ) % numVerts;
|
||||
const int j = ( i + numVerts - 1 ) % numVerts;
|
||||
const int k = ( i + numVerts - 2 ) % numVerts;
|
||||
if ( originals[ j ] == originals[ k ] ) {
|
||||
continue;
|
||||
}
|
||||
@@ -433,6 +418,7 @@ static void FixSurfaceJunctions( mapDrawSurface_t& ds ) {
|
||||
// fine the way it is
|
||||
c_natural++;
|
||||
|
||||
free( ds.verts );
|
||||
ds.numVerts = numVerts;
|
||||
ds.verts = safe_malloc( numVerts * sizeof( *ds.verts ) );
|
||||
memcpy( ds.verts, verts, numVerts * sizeof( *ds.verts ) );
|
||||
@@ -464,10 +450,11 @@ static void FixSurfaceJunctions( mapDrawSurface_t& ds ) {
|
||||
|
||||
}
|
||||
|
||||
free( ds.verts );
|
||||
ds.numVerts = numVerts;
|
||||
ds.verts = safe_malloc( numVerts * sizeof( *ds.verts ) );
|
||||
|
||||
for ( j = 0; j < ds.numVerts; ++j ) {
|
||||
for ( int j = 0; j < ds.numVerts; ++j ) {
|
||||
ds.verts[j] = verts[ ( j + i ) % ds.numVerts ];
|
||||
}
|
||||
}
|
||||
@@ -512,10 +499,14 @@ static bool FixBrokenSurface( mapDrawSurface_t& ds ){
|
||||
/* lightmap st/colors */
|
||||
for ( int k = 0; k < MAX_LIGHTMAPS; ++k )
|
||||
{
|
||||
avg.lightmap[ k ] = vector2_mid( dv1.lightmap[ k ], dv2.lightmap[ k ] );
|
||||
avg.lightmap[ k ] = { 0, 0 };
|
||||
for ( int j = 0; j < 4; ++j )
|
||||
avg.color[ k ][ j ] = (int) ( dv1.color[ k ][ j ] + dv2.color[ k ][ j ] ) >> 1;
|
||||
avg.color[ k ][ j ] = ( dv1.color[ k ][ j ] + dv2.color[ k ][ j ] ) >> 1;
|
||||
}
|
||||
avg.lightmap[ 0 ] = vector2_mid( dv1.lightmap[ 0 ], dv2.lightmap[ 0 ] );
|
||||
|
||||
if( bspDrawVert_is_tjunc( dv1 ) && bspDrawVert_is_tjunc( dv2 ) )
|
||||
bspDrawVert_mark_tjunc( avg );
|
||||
|
||||
/* ydnar: der... */
|
||||
dv1 = avg;
|
||||
@@ -602,7 +593,7 @@ void FixTJunctions( const entity_t& ent ){
|
||||
// add the non-axial edges, longest first
|
||||
// this gives the most accurate edge description
|
||||
for ( originalEdge_t& e : Span( originalEdges, numOriginalEdges ) ) { // originalEdges might not change during AddEdge( true )
|
||||
e.dv[ 0 ]->lightmap[ 0 ][ 0 ] = AddEdge( *e.dv[ 0 ], *e.dv[ 1 ], true );
|
||||
bspDrawVert_edge_index_write( *e.dv[ 0 ], AddEdge( *e.dv[ 0 ], *e.dv[ 1 ], true ) );
|
||||
}
|
||||
|
||||
Sys_FPrintf( SYS_VRB, "%9d axial edge lines\n", axialEdgeLines );
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
/* -------------------------------------------------------------------------------
|
||||
|
||||
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."
|
||||
|
||||
------------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
/* dependencies */
|
||||
#include "q3map2.h"
|
||||
|
||||
inline void bspDrawVert_edge_index_write( bspDrawVert_t& dv, int index ){
|
||||
dv.lightmap[MAX_LIGHTMAPS - 1][0] = index;
|
||||
}
|
||||
|
||||
inline int bspDrawVert_edge_index_read( const bspDrawVert_t& dv ){
|
||||
return dv.lightmap[MAX_LIGHTMAPS - 1][0];
|
||||
}
|
||||
|
||||
inline void bspDrawVert_mark_tjunc( bspDrawVert_t& dv ){
|
||||
dv.lightmap[MAX_LIGHTMAPS - 1][1] = 1;
|
||||
}
|
||||
|
||||
inline bool bspDrawVert_is_tjunc( const bspDrawVert_t& dv ){
|
||||
return dv.lightmap[MAX_LIGHTMAPS - 1][1] == 1;
|
||||
}
|
||||
Reference in New Issue
Block a user