refactor mesh_t

This commit is contained in:
Garux
2025-11-06 19:30:15 +05:00
parent 0bbd529a76
commit d19c89224a
14 changed files with 352 additions and 500 deletions
+29 -45
View File
@@ -410,40 +410,34 @@ void ProcessDecals(){
/* create projectors */
if ( distance > 0.125f ) {
/* tesselate the patch */
const int iterations = IterationsForCurve( p.longestCurve, patchSubdivisions );
mesh_t *subdivided = SubdivideMesh2( p.mesh, iterations );
/* fit it to the curve and remove colinear verts on rows/columns */
PutMeshOnCurve( *subdivided );
mesh_t *mesh = RemoveLinearMeshColumnsRows( subdivided );
FreeMesh( subdivided );
mesh_t mesh = TessellatedMesh( p.mesh, IterationsForCurve( p.longestCurve, patchSubdivisions ) );
/* offset by projector origin */
for ( bspDrawVert_t& vert : Span( mesh->verts, mesh->width * mesh->height ) )
for ( bspDrawVert_t& vert : Span( mesh.verts, mesh.numVerts() ) )
vert.xyz += e.origin;
/* iterate through the mesh quads */
for ( int y = 0; y < ( mesh->height - 1 ); ++y )
for ( int y = 0; y < ( mesh.height - 1 ); ++y )
{
for ( int x = 0; x < ( mesh->width - 1 ); ++x )
for ( int x = 0; x < ( mesh.width - 1 ); ++x )
{
/* set indexes */
const int pw[ 5 ] = {
x + ( y * mesh->width ),
x + ( ( y + 1 ) * mesh->width ),
x + 1 + ( ( y + 1 ) * mesh->width ),
x + 1 + ( y * mesh->width ),
x + ( y * mesh->width ) /* same as pw[ 0 ] */
x + ( y * mesh.width ),
x + ( ( y + 1 ) * mesh.width ),
x + 1 + ( ( y + 1 ) * mesh.width ),
x + 1 + ( y * mesh.width ),
x + ( y * mesh.width ) /* same as pw[ 0 ] */
};
/* set radix */
const int r = ( x + y ) & 1;
/* get drawverts */
const bspDrawVert_t *dv[ 4 ] = {
&mesh->verts[ pw[ r + 0 ] ],
&mesh->verts[ pw[ r + 1 ] ],
&mesh->verts[ pw[ r + 2 ] ],
&mesh->verts[ pw[ r + 3 ] ]
&mesh.verts[ pw[ r + 0 ] ],
&mesh.verts[ pw[ r + 1 ] ],
&mesh.verts[ pw[ r + 2 ] ],
&mesh.verts[ pw[ r + 3 ] ]
};
/* planar? (nuking this optimization as it doesn't work on non-rectangular quads) */
if ( 0 && PlaneFromPoints( plane, dv[ 0 ]->xyz, dv[ 1 ]->xyz, dv[ 2 ]->xyz ) &&
@@ -465,7 +459,7 @@ void ProcessDecals(){
}
/* clean up */
free( mesh );
mesh.freeVerts();
}
}
/* remove patches from entity */
@@ -611,52 +605,42 @@ static void ProjectDecalOntoPatch( decalProjector_t& dp, mapDrawSurface_t& ds ){
return;
/* tesselate the patch */
mesh_t src;
src.width = ds.patchWidth;
src.height = ds.patchHeight;
src.verts = ds.verts.data();
const int iterations = IterationsForCurve( ds.longestCurve, patchSubdivisions );
mesh_t *subdivided = SubdivideMesh2( src, iterations );
/* fit it to the curve and remove colinear verts on rows/columns */
PutMeshOnCurve( *subdivided );
mesh_t *mesh = RemoveLinearMeshColumnsRows( subdivided );
FreeMesh( subdivided );
mesh_t mesh = TessellatedMesh( mesh_t( ds.patchWidth, ds.patchHeight, ds.verts.data() ), IterationsForCurve( ds.longestCurve, patchSubdivisions ) );
/* iterate through the mesh quads */
for ( int y = 0; y < ( mesh->height - 1 ); ++y )
for ( int y = 0; y < ( mesh.height - 1 ); ++y )
{
for ( int x = 0; x < ( mesh->width - 1 ); ++x )
for ( int x = 0; x < ( mesh.width - 1 ); ++x )
{
/* set indexes */
const int pw[ 5 ] = {
x + ( y * mesh->width ),
x + ( ( y + 1 ) * mesh->width ),
x + 1 + ( ( y + 1 ) * mesh->width ),
x + 1 + ( y * mesh->width ),
x + ( y * mesh->width ) /* same as pw[ 0 ] */
x + ( y * mesh.width ),
x + ( ( y + 1 ) * mesh.width ),
x + 1 + ( ( y + 1 ) * mesh.width ),
x + 1 + ( y * mesh.width ),
x + ( y * mesh.width ) /* same as pw[ 0 ] */
};
/* set radix */
const int r = ( x + y ) & 1;
/* generate decal for first triangle */
winding_t w{
mesh->verts[ pw[ r + 0 ] ].xyz,
mesh->verts[ pw[ r + 1 ] ].xyz,
mesh->verts[ pw[ r + 2 ] ].xyz };
mesh.verts[ pw[ r + 0 ] ].xyz,
mesh.verts[ pw[ r + 1 ] ].xyz,
mesh.verts[ pw[ r + 2 ] ].xyz };
ProjectDecalOntoWinding( dp, ds, w );
/* generate decal for second triangle */
winding_t w2{
mesh->verts[ pw[ r + 0 ] ].xyz,
mesh->verts[ pw[ r + 2 ] ].xyz,
mesh->verts[ pw[ r + 3 ] ].xyz };
mesh.verts[ pw[ r + 0 ] ].xyz,
mesh.verts[ pw[ r + 2 ] ].xyz,
mesh.verts[ pw[ r + 3 ] ].xyz };
ProjectDecalOntoWinding( dp, ds, w2 );
}
}
/* clean up */
free( mesh );
mesh.freeVerts();
}
+70 -92
View File
@@ -30,6 +30,7 @@
/* dependencies */
#include "q3map2.h"
#include <optional>
@@ -43,13 +44,10 @@ static int numFogPatchFragments;
converts a patch drawsurface to a mesh_t
*/
static mesh_t *DrawSurfToMesh( const mapDrawSurface_t& ds ){
mesh_t *m = safe_malloc( sizeof( *m ) );
m->width = ds.patchWidth;
m->height = ds.patchHeight;
m->verts = safe_malloc( sizeof( m->verts[ 0 ] ) * m->width * m->height );
memcpy( m->verts, ds.verts.data(), sizeof( m->verts[ 0 ] ) * m->width * m->height );
static mesh_t DrawSurfToMesh( const mapDrawSurface_t& ds ){
const size_t size = sizeof( ds.verts[ 0 ] ) * ds.patchWidth * ds.patchHeight;
mesh_t m( ds.patchWidth, ds.patchHeight, safe_malloc( size ) );
memcpy( m.verts, ds.verts.data(), size );
return m;
}
@@ -59,24 +57,24 @@ static mesh_t *DrawSurfToMesh( const mapDrawSurface_t& ds ){
SplitMeshByPlane()
chops a mesh by a plane
*/
static void SplitMeshByPlane( mesh_t *in, const Plane3f& plane, mesh_t **front, mesh_t **back ){
/// \returns either {front, back} or {front, {}} or {{}, back}
/// frees or reuses \param in
static std::pair<std::optional<mesh_t>, std::optional<mesh_t>> SplitMeshByPlane( mesh_t& in, const Plane3f& plane ){
int w, h, split;
float d[MAX_PATCH_SIZE][MAX_PATCH_SIZE];
bspDrawVert_t *dv, *v1, *v2;
int c_front, c_back, c_on;
mesh_t *f, *b;
int i;
float frac;
int frontAprox, backAprox;
for ( i = 0; i < 2; ++i ) {
dv = in->verts;
dv = in.verts;
c_front = 0;
c_back = 0;
c_on = 0;
for ( h = 0; h < in->height; ++h ) {
for ( w = 0; w < in->width; ++w, ++dv ) {
for ( h = 0; h < in.height; ++h ) {
for ( w = 0; w < in.width; ++w, ++dv ) {
d[h][w] = plane3_distance_to_point( plane, dv->xyz );
if ( d[h][w] > ON_EPSILON ) {
c_front++;
@@ -90,21 +88,16 @@ static void SplitMeshByPlane( mesh_t *in, const Plane3f& plane, mesh_t **front,
}
}
*front = nullptr;
*back = nullptr;
if ( !c_front ) {
*back = in;
return;
return { {}, in };
}
if ( !c_back ) {
*front = in;
return;
return { in, {} };
}
// find a split point
split = -1;
for ( w = 0; w < in->width - 1; ++w ) {
for ( w = 0; w < in.width - 1; ++w ) {
if ( ( d[0][w] < 0 ) != ( d[0][w + 1] < 0 ) ) {
if ( split == -1 ) {
split = w;
@@ -116,30 +109,27 @@ static void SplitMeshByPlane( mesh_t *in, const Plane3f& plane, mesh_t **front,
if ( split == -1 ) {
if ( i == 1 ) {
Sys_FPrintf( SYS_WRN | SYS_VRBflag, "No crossing points in patch\n" );
*front = in;
return;
return { in, {} };
}
in = TransposeMesh( in );
TransposeMesh( in );
InvertMesh( in );
continue;
}
// make sure the split point stays the same for all other rows
for ( h = 1; h < in->height; ++h ) {
for ( w = 0; w < in->width - 1; ++w ) {
for ( h = 1; h < in.height; ++h ) {
for ( w = 0; w < in.width - 1; ++w ) {
if ( ( d[h][w] < 0 ) != ( d[h][w + 1] < 0 ) ) {
if ( w != split ) {
Sys_Printf( "multiple crossing points for patch -- can't clip\n" );
*front = in;
return;
return { in, {} };
}
}
}
if ( ( d[h][split] < 0 ) == ( d[h][split + 1] < 0 ) ) {
Sys_Printf( "differing crossing points for patch -- can't clip\n" );
*front = in;
return;
return { in, {} };
}
}
@@ -148,63 +138,49 @@ static void SplitMeshByPlane( mesh_t *in, const Plane3f& plane, mesh_t **front,
// create two new meshes
f = safe_malloc( sizeof( *f ) );
f->width = split + 2;
if ( !( f->width & 1 ) ) {
f->width++;
mesh_t f( split + 2, in.height, nullptr ), b( in.width - split, in.height, nullptr );
if ( !( f.width & 1 ) ) {
f.width++;
frontAprox = 1;
}
else {
frontAprox = 0;
}
if ( f->width > MAX_PATCH_SIZE ) {
if ( f.width > MAX_PATCH_SIZE ) {
Error( "MAX_PATCH_SIZE after split" );
}
f->height = in->height;
f->verts = safe_malloc( sizeof( f->verts[0] ) * f->width * f->height );
f.verts = safe_malloc( sizeof( f.verts[0] ) * f.numVerts() );
b = safe_malloc( sizeof( *b ) );
b->width = in->width - split;
if ( !( b->width & 1 ) ) {
b->width++;
if ( !( b.width & 1 ) ) {
b.width++;
backAprox = 1;
}
else {
backAprox = 0;
}
if ( b->width > MAX_PATCH_SIZE ) {
if ( b.width > MAX_PATCH_SIZE ) {
Error( "MAX_PATCH_SIZE after split" );
}
b->height = in->height;
b->verts = safe_malloc( sizeof( b->verts[0] ) * b->width * b->height );
if ( d[0][0] > 0 ) {
*front = f;
*back = b;
}
else {
*front = b;
*back = f;
}
b.verts = safe_malloc( sizeof( b.verts[0] ) * b.numVerts() );
// distribute the points
for ( w = 0; w < in->width; ++w ) {
for ( h = 0; h < in->height; ++h ) {
for ( w = 0; w < in.width; ++w ) {
for ( h = 0; h < in.height; ++h ) {
if ( w <= split ) {
f->verts[ h * f->width + w ] = in->verts[ h * in->width + w ];
f.verts[ h * f.width + w ] = in.verts[ h * in.width + w ];
}
else {
b->verts[ h * b->width + w - split + backAprox ] = in->verts[ h * in->width + w ];
b.verts[ h * b.width + w - split + backAprox ] = in.verts[ h * in.width + w ];
}
}
}
// clip the crossing line
for ( h = 0; h < in->height; ++h )
for ( h = 0; h < in.height; ++h )
{
dv = &f->verts[ h * f->width + split + 1 ];
v1 = &in->verts[ h * in->width + split ];
v2 = &in->verts[ h * in->width + split + 1 ];
dv = &f.verts[ h * f.width + split + 1 ];
v1 = &in.verts[ h * in.width + split ];
v2 = &in.verts[ h * in.width + split + 1 ];
frac = d[h][split] / ( d[h][split] - d[h][split + 1] );
@@ -215,24 +191,28 @@ static void SplitMeshByPlane( mesh_t *in, const Plane3f& plane, mesh_t **front,
LerpDrawVertAmount( v1, v2, frac, dv );
if ( frontAprox ) {
f->verts[ h * f->width + split + 2 ] = *dv;
f.verts[ h * f.width + split + 2 ] = *dv;
}
b->verts[ h * b->width ] = *dv;
b.verts[ h * b.width ] = *dv;
if ( backAprox ) {
b->verts[ h * b->width + 1 ] = *dv;
b.verts[ h * b.width + 1 ] = *dv;
}
}
/*
PrintMesh( in );
Sys_Printf( "\n" );
PrintMesh( f );
Sys_Printf( "\n" );
PrintMesh( b );
Sys_Printf( "\n" );
*/
FreeMesh( in );
in.freeVerts();
if ( d[0][0] > 0 )
return { f, b };
else
return { b, f };
}
@@ -242,74 +222,72 @@ static void SplitMeshByPlane( mesh_t *in, const Plane3f& plane, mesh_t **front,
*/
static bool ChopPatchSurfaceByBrush( mapDrawSurface_t& ds, const brush_t *b ){
int i, j;
mesh_t *outside[MAX_BRUSH_SIDES];
int numOutside;
mesh_t *m, *front, *back;
mesh_t outside[MAX_BRUSH_SIDES];
int numOutside = 0;
m = DrawSurfToMesh( ds );
numOutside = 0;
mesh_t m = DrawSurfToMesh( ds );
// only split by the top and bottom planes to avoid
// some messy patch clipping issues
for ( i = 4; i <= 5; ++i ) {
for ( int i = 4; i <= 5; ++i ) {
const plane_t& plane = mapplanes[ b->sides[ i ].planenum ];
SplitMeshByPlane( m, plane.plane, &front, &back );
auto [front, back] = SplitMeshByPlane( m, plane.plane );
if ( !back ) {
// nothing actually contained inside
for ( j = 0; j < numOutside; ++j ) {
FreeMesh( outside[j] );
for ( int j = 0; j < numOutside; ++j ) {
outside[j].freeVerts();
}
front->freeVerts();
return false;
}
m = back;
m = *back;
if ( front ) {
if ( numOutside == MAX_BRUSH_SIDES ) {
Error( "MAX_BRUSH_SIDES" );
}
outside[ numOutside ] = front;
outside[ numOutside ] = *front;
numOutside++;
}
}
/* all of outside fragments become separate drawsurfs */
numFogPatchFragments += numOutside;
for ( i = 0; i < numOutside; ++i )
for ( int i = 0; i < numOutside; ++i )
{
/* transpose and invert the chopped patch (fixes potential crash. fixme: why?) */
outside[ i ] = TransposeMesh( outside[ i ] );
TransposeMesh( outside[ i ] );
InvertMesh( outside[ i ] );
/* ydnar: do this the hacky right way */
mapDrawSurface_t& newds = AllocDrawSurface( ESurfaceType::Patch );
newds = ds;
newds.patchWidth = outside[ i ]->width;
newds.patchHeight = outside[ i ]->height;
newds.verts.assign( outside[ i ]->verts, outside[ i ]->verts + newds.patchWidth * newds.patchHeight );
newds.patchWidth = outside[ i ].width;
newds.patchHeight = outside[ i ].height;
newds.verts.assign( outside[ i ].verts, outside[ i ].verts + outside[ i ].numVerts() );
/* free the source mesh */
FreeMesh( outside[ i ] );
outside[ i ].freeVerts();
}
/* only rejigger this patch if it was chopped */
//% Sys_Printf( "Inside: %d x %d\n", m->width, m->height );
//% Sys_Printf( "Inside: %d x %d\n", m.width, m.height );
if ( numOutside > 0 ) {
/* transpose and invert the chopped patch (fixes potential crash. fixme: why?) */
m = TransposeMesh( m );
TransposeMesh( m );
InvertMesh( m );
/* replace ds with m */
ds.patchWidth = m->width;
ds.patchHeight = m->height;
ds.verts.assign( m->verts, m->verts + ds.patchWidth * ds.patchHeight );
ds.patchWidth = m.width;
ds.patchHeight = m.height;
ds.verts.assign( m.verts, m.verts + m.numVerts() );
}
/* free the source mesh and return */
FreeMesh( m );
m.freeVerts();
return true;
}
+14 -23
View File
@@ -648,22 +648,13 @@ void RadLightForPatch( int num, int lightmapNum, rawLightmap_t *lm, const shader
/* build a subdivided mesh identical to shadow facets for this patch */
/* this MUST MATCH FacetsForPatch() identically! */
mesh_t src;
src.width = ds.patchWidth;
src.height = ds.patchHeight;
src.verts = bogus;
//% mesh_t *subdivided = SubdivideMesh( src, 8, 512 );
mesh_t *subdivided = SubdivideMesh2( src, info.patchIterations );
PutMeshOnCurve( *subdivided );
//% MakeMeshNormals( *subdivided );
mesh_t *mesh = RemoveLinearMeshColumnsRows( subdivided );
FreeMesh( subdivided );
mesh_t mesh = TessellatedMesh( mesh_t( ds.patchWidth, ds.patchHeight, bogus ), info.patchIterations );
free( bogus );
/* FIXME: build interpolation table into color[ 1 ] */
/* fix up color indexes */
for ( bspDrawVert_t& vert : Span( mesh->verts, mesh->width * mesh->height ) )
for ( bspDrawVert_t& vert : Span( mesh.verts, mesh.numVerts() ) )
{
if ( vert.color[ 0 ][ 0 ] >= ds.numVerts ) {
vert.color[ 0 ][ 0 ] = ds.numVerts - 1;
@@ -671,27 +662,27 @@ void RadLightForPatch( int num, int lightmapNum, rawLightmap_t *lm, const shader
}
/* iterate through the mesh quads */
for ( int y = 0; y < ( mesh->height - 1 ); ++y )
for ( int y = 0; y < ( mesh.height - 1 ); ++y )
{
for ( int x = 0; x < ( mesh->width - 1 ); ++x )
for ( int x = 0; x < ( mesh.width - 1 ); ++x )
{
/* set indexes */
const int pw[ 5 ] = {
x + ( y * mesh->width ),
x + ( ( y + 1 ) * mesh->width ),
x + 1 + ( ( y + 1 ) * mesh->width ),
x + 1 + ( y * mesh->width ),
x + ( y * mesh->width ) /* same as pw[ 0 ] */
x + ( y * mesh.width ),
x + ( ( y + 1 ) * mesh.width ),
x + 1 + ( ( y + 1 ) * mesh.width ),
x + 1 + ( y * mesh.width ),
x + ( y * mesh.width ) /* same as pw[ 0 ] */
};
/* set radix */
const int r = ( x + y ) & 1;
/* get drawverts */
const bspDrawVert_t *dv[ 4 ] = {
&mesh->verts[ pw[ r + 0 ] ],
&mesh->verts[ pw[ r + 1 ] ],
&mesh->verts[ pw[ r + 2 ] ],
&mesh->verts[ pw[ r + 3 ] ]
&mesh.verts[ pw[ r + 0 ] ],
&mesh.verts[ pw[ r + 1 ] ],
&mesh.verts[ pw[ r + 2 ] ],
&mesh.verts[ pw[ r + 3 ] ]
};
/* planar? */
Plane3f plane;
@@ -756,7 +747,7 @@ void RadLightForPatch( int num, int lightmapNum, rawLightmap_t *lm, const shader
}
/* free the mesh */
FreeMesh( mesh );
mesh.freeVerts();
}
+21 -34
View File
@@ -891,56 +891,43 @@ static void PopulateWithBSPModel( const bspModel_t& model, const Matrix4& transf
case MST_PATCH:
{
/* subdivide the surface */
mesh_t srcMesh;
srcMesh.width = ds.patchWidth;
srcMesh.height = ds.patchHeight;
srcMesh.verts = &bspDrawVerts[ ds.firstVert ];
//% mesh_t *subdivided = SubdivideMesh( srcMesh, 8, 512 );
mesh_t *subdivided = SubdivideMesh2( srcMesh, info.patchIterations );
/* fit it to the curve and remove colinear verts on rows/columns */
PutMeshOnCurve( *subdivided );
mesh_t *mesh = RemoveLinearMeshColumnsRows( subdivided );
FreeMesh( subdivided );
/* set verts */
const bspDrawVert_t *verts = mesh->verts;
mesh_t mesh = TessellatedMesh( mesh_t( ds.patchWidth, ds.patchHeight, &bspDrawVerts[ ds.firstVert ] ), info.patchIterations );
/* subdivide each quad to place the models */
for ( int y = 0; y < ( mesh->height - 1 ); ++y )
for ( int y = 0; y < ( mesh.height - 1 ); ++y )
{
for ( int x = 0; x < ( mesh->width - 1 ); ++x )
for ( int x = 0; x < ( mesh.width - 1 ); ++x )
{
/* set indexes */
const int pw[ 5 ] = {
x + ( y * mesh->width ),
x + ( ( y + 1 ) * mesh->width ),
x + 1 + ( ( y + 1 ) * mesh->width ),
x + 1 + ( y * mesh->width ),
x + ( y * mesh->width ) /* same as pw[ 0 ] */
x + ( y * mesh.width ),
x + ( ( y + 1 ) * mesh.width ),
x + 1 + ( ( y + 1 ) * mesh.width ),
x + 1 + ( y * mesh.width ),
x + ( y * mesh.width ) /* same as pw[ 0 ] */
};
/* set radix */
const int r = ( x + y ) & 1;
/* make first triangle */
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;
tw.v[ 0 ].xyz = mesh.verts[ pw[ r + 0 ] ].xyz;
tw.v[ 0 ].st = mesh.verts[ pw[ r + 0 ] ].st;
tw.v[ 1 ].xyz = mesh.verts[ pw[ r + 1 ] ].xyz;
tw.v[ 1 ].st = mesh.verts[ pw[ r + 1 ] ].st;
tw.v[ 2 ].xyz = mesh.verts[ pw[ r + 2 ] ].xyz;
tw.v[ 2 ].st = mesh.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 */
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;
tw.v[ 0 ].xyz = mesh.verts[ pw[ r + 0 ] ].xyz;
tw.v[ 0 ].st = mesh.verts[ pw[ r + 0 ] ].st;
tw.v[ 1 ].xyz = mesh.verts[ pw[ r + 2 ] ].xyz;
tw.v[ 1 ].st = mesh.verts[ pw[ r + 2 ] ].st;
tw.v[ 2 ].xyz = mesh.verts[ pw[ r + 3 ] ].xyz;
tw.v[ 2 ].st = mesh.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 );
@@ -949,7 +936,7 @@ static void PopulateWithBSPModel( const bspModel_t& model, const Matrix4& transf
}
/* free the subdivided mesh */
FreeMesh( mesh );
mesh.freeVerts();
break;
}
/* handle triangle surfaces */
+32 -45
View File
@@ -1218,20 +1218,7 @@ void MapRawLightmap( int rawLightmapNum ){
case MST_PATCH:
{
/* make a mesh from the drawsurf */
mesh_t src;
src.width = ds.patchWidth;
src.height = ds.patchHeight;
src.verts = &yDrawVerts[ ds.firstVert ];
//% mesh_t *subdivided = SubdivideMesh( src, 8, 512 );
mesh_t *subdivided = SubdivideMesh2( src, info->patchIterations );
/* fit it to the curve and remove colinear verts on rows/columns */
PutMeshOnCurve( *subdivided );
mesh_t *mesh = RemoveLinearMeshColumnsRows( subdivided );
FreeMesh( subdivided );
/* get verts */
const bspDrawVert_t *verts = mesh->verts;
mesh_t mesh = TessellatedMesh( mesh_t( ds.patchWidth, ds.patchHeight, &yDrawVerts[ ds.firstVert ] ), info->patchIterations );
/* debug code */
#if 0
@@ -1248,59 +1235,59 @@ void MapRawLightmap( int rawLightmapNum ){
for ( mapNonAxial = 0; mapNonAxial < 2; ++mapNonAxial )
{
for ( y = 0; y < ( mesh->height - 1 ); ++y )
for ( y = 0; y < ( mesh.height - 1 ); ++y )
{
for ( x = 0; x < ( mesh->width - 1 ); ++x )
for ( x = 0; x < ( mesh.width - 1 ); ++x )
{
/* set indexes */
const int pw[ 5 ] = {
x + ( y * mesh->width ),
x + ( ( y + 1 ) * mesh->width ),
x + 1 + ( ( y + 1 ) * mesh->width ),
x + 1 + ( y * mesh->width ),
x + ( y * mesh->width ) /* same as pw[ 0 ] */
x + ( y * mesh.width ),
x + ( ( y + 1 ) * mesh.width ),
x + 1 + ( ( y + 1 ) * mesh.width ),
x + 1 + ( y * mesh.width ),
x + ( y * mesh.width ) /* same as pw[ 0 ] */
};
/* set radix */
const int r = ( x + y ) & 1;
/* get drawverts and map first triangle */
MapTriangle( lm, info, TriRef{
&verts[ pw[ r + 0 ] ],
&verts[ pw[ r + 1 ] ],
&verts[ pw[ r + 2 ] ] }, mapNonAxial );
&mesh.verts[ pw[ r + 0 ] ],
&mesh.verts[ pw[ r + 1 ] ],
&mesh.verts[ pw[ r + 2 ] ] }, mapNonAxial );
/* get drawverts and map second triangle */
MapTriangle( lm, info, TriRef{
&verts[ pw[ r + 0 ] ],
&verts[ pw[ r + 2 ] ],
&verts[ pw[ r + 3 ] ] }, mapNonAxial );
&mesh.verts[ pw[ r + 0 ] ],
&mesh.verts[ pw[ r + 2 ] ],
&mesh.verts[ pw[ r + 3 ] ] }, mapNonAxial );
}
}
}
#else
for ( y = 0; y < ( mesh->height - 1 ); ++y )
for ( y = 0; y < ( mesh.height - 1 ); ++y )
{
for ( x = 0; x < ( mesh->width - 1 ); ++x )
for ( x = 0; x < ( mesh.width - 1 ); ++x )
{
/* set indexes */
const int pw[ 5 ] = {
x + ( y * mesh->width ),
x + ( ( y + 1 ) * mesh->width ),
x + 1 + ( ( y + 1 ) * mesh->width ),
x + 1 + ( y * mesh->width ),
x + ( y * mesh->width ) /* same as pw[ 0 ] */
x + ( y * mesh.width ),
x + ( ( y + 1 ) * mesh.width ),
x + 1 + ( ( y + 1 ) * mesh.width ),
x + 1 + ( y * mesh.width ),
x + ( y * mesh.width ) /* same as pw[ 0 ] */
};
/* set radix */
const int r = ( x + y ) & 1;
/* attempt to map quad first */
if ( MapQuad( lm, info, QuadRef{
&verts[ pw[ r + 0 ] ],
&verts[ pw[ r + 1 ] ],
&verts[ pw[ r + 2 ] ],
&verts[ pw[ r + 3 ] ] } ) ) {
&mesh.verts[ pw[ r + 0 ] ],
&mesh.verts[ pw[ r + 1 ] ],
&mesh.verts[ pw[ r + 2 ] ],
&mesh.verts[ pw[ r + 3 ] ] } ) ) {
continue;
}
@@ -1308,15 +1295,15 @@ void MapRawLightmap( int rawLightmapNum ){
{
/* get drawverts and map first triangle */
MapTriangle( lm, info, TriRef{
&verts[ pw[ r + 0 ] ],
&verts[ pw[ r + 1 ] ],
&verts[ pw[ r + 2 ] ] }, mapNonAxial );
&mesh.verts[ pw[ r + 0 ] ],
&mesh.verts[ pw[ r + 1 ] ],
&mesh.verts[ pw[ r + 2 ] ] }, mapNonAxial );
/* get drawverts and map second triangle */
MapTriangle( lm, info, TriRef{
&verts[ pw[ r + 0 ] ],
&verts[ pw[ r + 2 ] ],
&verts[ pw[ r + 3 ] ] }, mapNonAxial );
&mesh.verts[ pw[ r + 0 ] ],
&mesh.verts[ pw[ r + 2 ] ],
&mesh.verts[ pw[ r + 3 ] ] }, mapNonAxial );
}
}
}
@@ -1324,7 +1311,7 @@ void MapRawLightmap( int rawLightmapNum ){
#endif
/* free the mesh */
FreeMesh( mesh );
mesh.freeVerts();
break;
}
default:
+30 -55
View File
@@ -452,7 +452,6 @@ static void FinishRawLightmap( rawLightmap_t& lm ){
*/
static bool AddPatchToRawLightmap( int num, rawLightmap_t& lm ){
bspDrawVert_t *verts, *a, *b;
float sBasis, tBasis, s, t;
float length, widthTable[ MAX_EXPANDED_AXIS ] = {0}, heightTable[ MAX_EXPANDED_AXIS ] = {0};
@@ -465,43 +464,32 @@ static bool AddPatchToRawLightmap( int num, rawLightmap_t& lm ){
const surfaceInfo_t& info = surfaceInfos[ num ];
/* make a temporary mesh from the drawsurf */
mesh_t src;
src.width = ds.patchWidth;
src.height = ds.patchHeight;
src.verts = &yDrawVerts[ ds.firstVert ];
//% mesh_t *subdivided = SubdivideMesh( src, 8, 512 );
mesh_t *subdivided = SubdivideMesh2( src, info.patchIterations );
/* fit it to the curve and remove colinear verts on rows/columns */
PutMeshOnCurve( *subdivided );
mesh_t *mesh = RemoveLinearMeshColumnsRows( subdivided );
FreeMesh( subdivided );
mesh_t mesh = TessellatedMesh( mesh_t( ds.patchWidth, ds.patchHeight, &yDrawVerts[ ds.firstVert ] ), info.patchIterations );
/* find the longest distance on each row/column */
verts = mesh->verts;
for ( int y = 0; y < mesh->height; ++y )
for ( int y = 0; y < mesh.height; ++y )
{
for ( int x = 0; x < mesh->width; ++x )
for ( int x = 0; x < mesh.width; ++x )
{
/* get width */
if ( x + 1 < mesh->width ) {
a = &verts[ ( y * mesh->width ) + x ];
b = &verts[ ( y * mesh->width ) + x + 1 ];
value_maximize( widthTable[ x ], (float)vector3_length( a->xyz - b->xyz ) );
if ( x + 1 < mesh.width ) {
const bspDrawVert_t& a = mesh.verts[ ( y * mesh.width ) + x ];
const bspDrawVert_t& b = mesh.verts[ ( y * mesh.width ) + x + 1 ];
value_maximize( widthTable[ x ], (float)vector3_length( a.xyz - b.xyz ) );
}
/* get height */
if ( y + 1 < mesh->height ) {
a = &verts[ ( y * mesh->width ) + x ];
b = &verts[ ( ( y + 1 ) * mesh->width ) + x ];
value_maximize( heightTable[ y ], (float)vector3_length( a->xyz - b->xyz ) );
if ( y + 1 < mesh.height ) {
const bspDrawVert_t& a = mesh.verts[ ( y * mesh.width ) + x ];
const bspDrawVert_t& b = mesh.verts[ ( ( y + 1 ) * mesh.width ) + x ];
value_maximize( heightTable[ y ], (float)vector3_length( a.xyz - b.xyz ) );
}
}
}
/* determine lightmap width */
length = 0;
for ( int x = 0; x < ( mesh->width - 1 ); ++x )
for ( int x = 0; x < ( mesh.width - 1 ); ++x )
length += widthTable[ x ];
lm.w = lm.sampleSize != 0 ? ceil( length / lm.sampleSize ) + 1 : 0;
value_maximize( lm.w, ds.patchWidth );
@@ -510,7 +498,7 @@ static bool AddPatchToRawLightmap( int num, rawLightmap_t& lm ){
/* determine lightmap height */
length = 0;
for ( int y = 0; y < ( mesh->height - 1 ); ++y )
for ( int y = 0; y < ( mesh.height - 1 ); ++y )
length += heightTable[ y ];
lm.h = lm.sampleSize != 0 ? ceil( length / lm.sampleSize ) + 1 : 0;
value_maximize( lm.h, ds.patchHeight );
@@ -518,12 +506,12 @@ static bool AddPatchToRawLightmap( int num, rawLightmap_t& lm ){
tBasis = (float) ( lm.h - 1 ) / ( ds.patchHeight - 1 );
/* free the temporary mesh */
FreeMesh( mesh );
mesh.freeVerts();
/* set the lightmap texture coordinates in yDrawVerts */
lm.wrap[ 0 ] = true;
lm.wrap[ 1 ] = true;
verts = &yDrawVerts[ ds.firstVert ];
bspDrawVert_t *verts = &yDrawVerts[ ds.firstVert ];
for ( int y = 0; y < ds.patchHeight; ++y )
{
t = ( tBasis * y ) + 0.5f;
@@ -1675,56 +1663,43 @@ static bool ApproximateLightmap( rawLightmap_t *lm ){
case MST_PATCH:
{
/* make a mesh from the drawsurf */
mesh_t src;
src.width = ds.patchWidth;
src.height = ds.patchHeight;
src.verts = &yDrawVerts[ ds.firstVert ];
//% mesh_t *subdivided = SubdivideMesh( src, 8, 512 );
mesh_t *subdivided = SubdivideMesh2( src, info.patchIterations );
/* fit it to the curve and remove colinear verts on rows/columns */
PutMeshOnCurve( *subdivided );
mesh_t *mesh = RemoveLinearMeshColumnsRows( subdivided );
FreeMesh( subdivided );
/* get verts */
const bspDrawVert_t *verts = mesh->verts;
mesh_t mesh = TessellatedMesh( mesh_t( ds.patchWidth, ds.patchHeight, &yDrawVerts[ ds.firstVert ] ), info.patchIterations );
/* map the mesh quads */
info.approximated = true;
for ( int y = 0; y < ( mesh->height - 1 ) && info.approximated; ++y )
for ( int y = 0; y < ( mesh.height - 1 ) && info.approximated; ++y )
{
for ( int x = 0; x < ( mesh->width - 1 ) && info.approximated; ++x )
for ( int x = 0; x < ( mesh.width - 1 ) && info.approximated; ++x )
{
/* set indexes */
const int pw[ 5 ] = {
x + ( y * mesh->width ),
x + ( ( y + 1 ) * mesh->width ),
x + 1 + ( ( y + 1 ) * mesh->width ),
x + 1 + ( y * mesh->width ),
x + ( y * mesh->width ) /* same as pw[ 0 ] */
x + ( y * mesh.width ),
x + ( ( y + 1 ) * mesh.width ),
x + 1 + ( ( y + 1 ) * mesh.width ),
x + 1 + ( y * mesh.width ),
x + ( y * mesh.width ) /* same as pw[ 0 ] */
};
/* set radix */
const int r = ( x + y ) & 1;
/* get drawverts and map first triangle */
info.approximated = ApproximateTriangle_r( lm, TriRef{
&verts[ pw[ r + 0 ] ],
&verts[ pw[ r + 1 ] ],
&verts[ pw[ r + 2 ] ] } );
&mesh.verts[ pw[ r + 0 ] ],
&mesh.verts[ pw[ r + 1 ] ],
&mesh.verts[ pw[ r + 2 ] ] } );
/* get drawverts and map second triangle */
if ( info.approximated ) {
info.approximated = ApproximateTriangle_r( lm, TriRef{
&verts[ pw[ r + 0 ] ],
&verts[ pw[ r + 2 ] ],
&verts[ pw[ r + 3 ] ] } );
&mesh.verts[ pw[ r + 0 ] ],
&mesh.verts[ pw[ r + 2 ] ],
&mesh.verts[ pw[ r + 3 ] ] } );
}
}
}
/* free the mesh */
FreeMesh( mesh );
mesh.freeVerts();
break;
}
default:
+2 -2
View File
@@ -1240,7 +1240,7 @@ static void AdjustBrushesForOrigin( entity_t& ent ){
/* walk patch list */
for ( parseMesh_t& p : ent.patches )
{
for ( bspDrawVert_t& vert : Span( p.mesh.verts, p.mesh.width * p.mesh.height ) )
for ( bspDrawVert_t& vert : Span( p.mesh.verts, p.mesh.numVerts() ) )
vert.xyz -= ent.originbrush_origin;
}
}
@@ -1303,7 +1303,7 @@ static void SetEntityBounds( entity_t& e ){
}
for ( const parseMesh_t& p : e.patches )
{
for ( const bspDrawVert_t& vert : Span( p.mesh.verts, p.mesh.width * p.mesh.height ) )
for ( const bspDrawVert_t& vert : Span( p.mesh.verts, p.mesh.numVerts() ) )
minmax.extend( vert.xyz );
}
+71 -100
View File
@@ -91,33 +91,24 @@ void LerpDrawVertAmount( bspDrawVert_t *a, bspDrawVert_t *b, float amount, bspDr
}
void FreeMesh( mesh_t *m ) {
free( m->verts );
free( m );
}
void PrintMesh( mesh_t *m ) {
for ( int i = 0; i < m->height; ++i ) {
for ( int j = 0; j < m->width; ++j ) {
void PrintMesh( const mesh_t m ) {
for ( int i = 0; i < m.height; ++i ) {
for ( int j = 0; j < m.width; ++j ) {
Sys_Printf( "(%5.2f %5.2f %5.2f) "
, m->verts[i * m->width + j].xyz[0]
, m->verts[i * m->width + j].xyz[1]
, m->verts[i * m->width + j].xyz[2] );
, m.verts[i * m.width + j].xyz[0]
, m.verts[i * m.width + j].xyz[1]
, m.verts[i * m.width + j].xyz[2] );
}
Sys_Printf( "\n" );
}
Sys_Printf( "\n" );
}
mesh_t *CopyMesh( mesh_t *mesh ) {
mesh_t *out = safe_malloc( sizeof( *out ) );
out->width = mesh->width;
out->height = mesh->height;
const size_t size = out->width * out->height * sizeof( *out->verts );
out->verts = safe_malloc( size );
memcpy( out->verts, mesh->verts, size );
mesh_t CopyMesh( const mesh_t m ) {
const size_t size = m.numVerts() * sizeof( *m.verts );
mesh_t out( m.width, m.height, safe_malloc( size ) );
memcpy( out.verts, m.verts, size );
return out;
}
@@ -127,29 +118,25 @@ mesh_t *CopyMesh( mesh_t *mesh ) {
returns a transposed copy of the mesh, freeing the original
*/
mesh_t *TransposeMesh( mesh_t *in ) {
mesh_t *out = safe_malloc( sizeof( *out ) );
out->width = in->height;
out->height = in->width;
out->verts = safe_malloc( out->width * out->height * sizeof( bspDrawVert_t ) );
void TransposeMesh( mesh_t& m ) {
mesh_t out( m.height, m.width, safe_malloc( m.numVerts() * sizeof( *m.verts ) ) ); // swap width/height
for ( int h = 0; h < in->height; ++h ) {
for ( int w = 0; w < in->width; ++w ) {
out->verts[ w * in->height + h ] = in->verts[ h * in->width + w ];
for ( int h = 0; h < m.height; ++h ) {
for ( int w = 0; w < m.width; ++w ) {
out.verts[ w * m.height + h ] = m.verts[ h * m.width + w ];
}
}
FreeMesh( in );
return out;
m.freeVerts();
m = out;
}
void InvertMesh( mesh_t *in ) {
for ( int h = 0; h < in->height; ++h ) {
for ( int w = 0; w < in->width / 2; ++w ) {
void InvertMesh( mesh_t& m ) {
for ( int h = 0; h < m.height; ++h ) {
for ( int w = 0; w < m.width / 2; ++w ) {
std::swap(
in->verts[ h * in->width + w ],
in->verts[ h * in->width + in->width - 1 - w ]
m.verts[ h * m.width + w ],
m.verts[ h * m.width + m.width - 1 - w ]
);
}
}
@@ -161,7 +148,7 @@ void InvertMesh( mesh_t *in ) {
=================
*/
void MakeMeshNormals( mesh_t in ){
void MakeMeshNormals( mesh_t& in ){
int i, j, k, dist;
int count;
int x, y;
@@ -267,7 +254,7 @@ void MakeMeshNormals( mesh_t in ){
drops the aproximating points onto the curve
*/
void PutMeshOnCurve( mesh_t in ) {
void PutMeshOnCurve( mesh_t& in ) {
const auto lerp3 = []( const bspDrawVert_t& prev, bspDrawVert_t& mid, const bspDrawVert_t& next ){
mid.xyz = ( prev.xyz + mid.xyz * 2 + next.xyz ) * .25;
/* ydnar: interpolating st coords */
@@ -296,19 +283,13 @@ void PutMeshOnCurve( mesh_t in ) {
=================
*/
mesh_t *SubdivideMesh( mesh_t in, float maxError, float minLength ){
mesh_t out;
mesh_t SubdivideMesh( const mesh_t in, float maxError, float minLength ){
bspDrawVert_t expand[MAX_EXPANDED_AXIS][MAX_EXPANDED_AXIS];
mesh_t out( in.width, in.height, expand[0] );
out.width = in.width;
out.height = in.height;
for ( int i = 0; i < in.width; ++i ) {
for ( int j = 0; j < in.height; ++j ) {
expand[j][i] = in.verts[j * in.width + i];
}
}
for ( int h = 0; h < in.height; ++h )
std::copy_n( &in.verts[h * in.width], in.width, expand[h] );
// horizontal subdivisions
for ( int i, j = 0; j + 2 < out.width; j += 2 ) {
@@ -399,12 +380,11 @@ mesh_t *SubdivideMesh( mesh_t in, float maxError, float minLength ){
// collapse the verts
out.verts = &expand[0][0];
for ( int i = 1; i < out.height; ++i ) {
memmove( &out.verts[i * out.width], expand[i], out.width * sizeof( bspDrawVert_t ) );
}
return CopyMesh( &out );
return CopyMesh( out );
}
@@ -438,19 +418,14 @@ int IterationsForCurve( float len, int subdivisions ){
subdivides each mesh quad a specified number of times
*/
mesh_t *SubdivideMesh2( mesh_t in, int iterations ){
mesh_t out;
mesh_t SubdivideMesh2( const mesh_t in, int iterations ){
bspDrawVert_t expand[ MAX_EXPANDED_AXIS ][ MAX_EXPANDED_AXIS ];
mesh_t out( in.width, in.height, expand[0] );
/* initial setup */
out.width = in.width;
out.height = in.height;
for ( int i = 0; i < in.width; ++i )
{
for ( int j = 0; j < in.height; ++j )
expand[ j ][ i ] = in.verts[ j * in.width + i ];
}
for ( int h = 0; h < in.height; ++h )
std::copy_n( &in.verts[h * in.width], in.width, expand[h] );
/* keep chopping */
for ( ; iterations > 0; --iterations )
@@ -499,12 +474,11 @@ mesh_t *SubdivideMesh2( mesh_t in, int iterations ){
}
/* collapse the verts */
out.verts = &expand[ 0 ][ 0 ];
for ( int i = 1; i < out.height; ++i )
memmove( &out.verts[ i * out.width ], expand[ i ], out.width * sizeof( bspDrawVert_t ) );
/* return to sender */
return CopyMesh( &out );
return CopyMesh( out );
}
@@ -530,46 +504,38 @@ inline Vector3 ProjectPointOntoVector( const Vector3& point, const Vector3& vSta
RemoveLinearMeshColumsRows
================
*/
mesh_t *RemoveLinearMeshColumnsRows( mesh_t *in ) {
int i, j, k;
mesh_t out;
mesh_t RemoveLinearMeshColumnsRows( const mesh_t in ) {
bspDrawVert_t expand[MAX_EXPANDED_AXIS][MAX_EXPANDED_AXIS];
mesh_t out( in.width, in.height, expand[0] );
out.width = in->width;
out.height = in->height;
for ( int h = 0; h < in.height; ++h )
std::copy_n( &in.verts[h * in.width], in.width, expand[h] );
for ( i = 0; i < in->width; ++i ) {
for ( j = 0; j < in->height; ++j ) {
expand[j][i] = in->verts[j * in->width + i];
}
}
for ( j = 1; j < out.width - 1; ++j ) {
for ( int j = 1; j < out.width - 1; ++j ) {
double maxLength = 0;
for ( i = 0; i < out.height; ++i ) {
for ( int i = 0; i < out.height; ++i ) {
value_maximize( maxLength, vector3_length( expand[i][j].xyz - ProjectPointOntoVector( expand[i][j].xyz, expand[i][j - 1].xyz, expand[i][j + 1].xyz ) ) );
}
if ( maxLength < 0.1 ) {
out.width--;
for ( i = 0; i < out.height; ++i ) {
for ( k = j; k < out.width; ++k ) {
for ( int i = 0; i < out.height; ++i ) {
for ( int k = j; k < out.width; ++k ) {
expand[i][k] = expand[i][k + 1];
}
}
j--;
}
}
for ( j = 1; j < out.height - 1; ++j ) {
for ( int j = 1; j < out.height - 1; ++j ) {
double maxLength = 0;
for ( i = 0; i < out.width; ++i ) {
for ( int i = 0; i < out.width; ++i ) {
value_maximize( maxLength, vector3_length( expand[j][i].xyz - ProjectPointOntoVector( expand[j][i].xyz, expand[j - 1][i].xyz, expand[j + 1][i].xyz ) ) );
}
if ( maxLength < 0.1 ) {
out.height--;
for ( i = 0; i < out.width; ++i ) {
for ( k = j; k < out.height; ++k ) {
for ( int i = 0; i < out.width; ++i ) {
for ( int k = j; k < out.height; ++k ) {
expand[k][i] = expand[k + 1][i];
}
}
@@ -577,34 +543,40 @@ mesh_t *RemoveLinearMeshColumnsRows( mesh_t *in ) {
}
}
// collapse the verts
out.verts = &expand[0][0];
for ( i = 1; i < out.height; ++i ) {
for ( int i = 1; i < out.height; ++i ) {
memmove( &out.verts[i * out.width], expand[i], out.width * sizeof( bspDrawVert_t ) );
}
return CopyMesh( &out );
return CopyMesh( out );
}
mesh_t TessellatedMesh( const mesh_t in, int iterations ){
//% mesh_t subdivided = SubdivideMesh( in, 8, 512 );
mesh_t subdivided = SubdivideMesh2( in, iterations );
/* fit it to the curve and remove colinear verts on rows/columns */
PutMeshOnCurve( subdivided );
mesh_t mesh = RemoveLinearMeshColumnsRows( subdivided );
subdivided.freeVerts();
//% MakeMeshNormals( mesh );
return mesh;
}
/*
=================
SubdivideMeshQuads
=================
*/
static mesh_t *SubdivideMeshQuads( mesh_t *in, float minLength, int maxsize, int *widthtable, int *heighttable ){
static mesh_t SubdivideMeshQuads( const mesh_t in, float minLength, int maxsize, int *widthtable, int *heighttable ){
int i, j, k, w, h, maxsubdivisions, subdivisions;
mesh_t out;
bspDrawVert_t expand[MAX_EXPANDED_AXIS][MAX_EXPANDED_AXIS];
mesh_t out( in.width, in.height, expand[0] );
out.width = in->width;
out.height = in->height;
for ( i = 0; i < in->width; ++i ) {
for ( j = 0; j < in->height; ++j ) {
expand[j][i] = in->verts[j * in->width + i];
}
}
for ( int h = 0; h < in.height; ++h )
std::copy_n( &in.verts[h * in.width], in.width, expand[h] );
if ( maxsize > MAX_EXPANDED_AXIS ) {
Error( "SubdivideMeshQuads: maxsize > MAX_EXPANDED_AXIS" );
@@ -612,9 +584,9 @@ static mesh_t *SubdivideMeshQuads( mesh_t *in, float minLength, int maxsize, int
// horizontal subdivisions
maxsubdivisions = ( maxsize - in->width ) / ( in->width - 1 );
maxsubdivisions = ( maxsize - in.width ) / ( in.width - 1 );
for ( w = 0, j = 0; w < in->width - 1; ++w, j += subdivisions + 1 ) {
for ( w = 0, j = 0; w < in.width - 1; ++w, j += subdivisions + 1 ) {
double maxLength = 0;
for ( i = 0; i < out.height; ++i ) {
value_maximize( maxLength, vector3_length( expand[i][j + 1].xyz - expand[i][j].xyz ) );
@@ -641,9 +613,9 @@ static mesh_t *SubdivideMeshQuads( mesh_t *in, float minLength, int maxsize, int
}
}
maxsubdivisions = ( maxsize - in->height ) / ( in->height - 1 );
maxsubdivisions = ( maxsize - in.height ) / ( in.height - 1 );
for ( h = 0, j = 0; h < in->height - 1; ++h, j += subdivisions + 1 ) {
for ( h = 0, j = 0; h < in.height - 1; ++h, j += subdivisions + 1 ) {
double maxLength = 0;
for ( i = 0; i < out.width; ++i ) {
value_maximize( maxLength, vector3_length( expand[j + 1][i].xyz - expand[j][i].xyz ) );
@@ -671,10 +643,9 @@ static mesh_t *SubdivideMeshQuads( mesh_t *in, float minLength, int maxsize, int
}
// collapse the verts
out.verts = &expand[0][0];
for ( i = 1; i < out.height; ++i ) {
memmove( &out.verts[i * out.width], expand[i], out.width * sizeof( bspDrawVert_t ) );
}
return CopyMesh( &out );
return CopyMesh( out );
}
+8 -8
View File
@@ -210,8 +210,8 @@ void ParsePatch( bool onlyLights, entity_t& mapEnt, int mapPrimitiveNum ){
Parse1DMatrix( 5, info );
m.width = info[0];
m.height = info[1];
const int size = ( m.width * m.height );
bspDrawVert_t *verts = m.verts = safe_malloc( size * sizeof( m.verts[0] ) );
const int numVerts = m.numVerts();
bspDrawVert_t *verts = m.verts = safe_malloc( numVerts * sizeof( m.verts[0] ) );
if ( m.width < 0 || m.width > MAX_PATCH_SIZE || m.height < 0 || m.height > MAX_PATCH_SIZE ) {
Error( "ParsePatch: bad size" );
@@ -259,7 +259,7 @@ void ParsePatch( bool onlyLights, entity_t& mapEnt, int mapPrimitiveNum ){
degenerate = true;
/* find first valid vector */
for ( int i = 1; i < size && delta[ 3 ] == 0; ++i )
for ( int i = 1; i < numVerts && delta[ 3 ] == 0; ++i )
{
delta.vec3() = m.verts[ 0 ].xyz - m.verts[ i ].xyz;
delta[ 3 ] = VectorNormalize( delta.vec3() );
@@ -272,7 +272,7 @@ void ParsePatch( bool onlyLights, entity_t& mapEnt, int mapPrimitiveNum ){
else
{
/* if all vectors match this or are zero, then this is a degenerate patch */
for ( int i = 1; i < size && degenerate; ++i )
for ( int i = 1; i < numVerts && degenerate; ++i )
{
Vector4 delta2( m.verts[ 0 ].xyz - m.verts[ i ].xyz, 0 );
delta2[ 3 ] = VectorNormalize( delta2.vec3() );
@@ -292,7 +292,7 @@ void ParsePatch( bool onlyLights, entity_t& mapEnt, int mapPrimitiveNum ){
/* warn and select degenerate patch */
if ( degenerate ) {
xml_Select( "degenerate patch", mapEnt.mapEntityNum, mapPrimitiveNum, false );
free( m.verts );
m.freeVerts();
return;
}
@@ -400,8 +400,8 @@ void PatchMapDrawSurfs( entity_t& e ){
meshes[m1].bordering[m2] =
meshes[m2].bordering[m1] =
std::ranges::any_of( Span( mesh1.verts, mesh1.width * mesh1.height ), [mesh2]( const bspDrawVert_t& v1 ){
return std::ranges::any_of( Span( mesh2.verts, mesh2.width * mesh2.height ), [v1]( const bspDrawVert_t& v2 ){
std::ranges::any_of( Span( mesh1.verts, mesh1.numVerts() ), [mesh2]( const bspDrawVert_t& v1 ){
return std::ranges::any_of( Span( mesh2.verts, mesh2.numVerts() ), [v1]( const bspDrawVert_t& v2 ){
return vector3_equal_epsilon( v1.xyz, v2.xyz, 1.f );
} );
} );
@@ -428,7 +428,7 @@ void PatchMapDrawSurfs( entity_t& e ){
{
if ( m.group ) {
m.grouped = true;
std::for_each_n( m.mesh.mesh.verts, m.mesh.mesh.width * m.mesh.mesh.height,
std::for_each_n( m.mesh.mesh.verts, m.mesh.mesh.numVerts(),
[&bounds]( const bspDrawVert_t& v ){ bounds.extend( v.xyz ); } );
}
}
+19 -10
View File
@@ -762,6 +762,15 @@ struct mesh_t
{
int width, height;
bspDrawVert_t *verts;
mesh_t() = default;
mesh_t( int width, int height, bspDrawVert_t *verts ) : width( width ), height( height ), verts( verts ){}
size_t numVerts() const {
return width * height;
}
void freeVerts(){
free( verts );
}
};
@@ -1513,17 +1522,17 @@ bool WindingIsTiny( const winding_t& w );
/* mesh.c */
bspDrawVert_t LerpDrawVert( const bspDrawVert_t& a, const bspDrawVert_t& b );
void LerpDrawVertAmount( bspDrawVert_t *a, bspDrawVert_t *b, float amount, bspDrawVert_t *out );
void FreeMesh( mesh_t *m );
mesh_t *CopyMesh( mesh_t *mesh );
void PrintMesh( mesh_t *m );
mesh_t *TransposeMesh( mesh_t *in );
void InvertMesh( mesh_t *m );
mesh_t *SubdivideMesh( mesh_t in, float maxError, float minLength );
mesh_t CopyMesh( const mesh_t m );
void PrintMesh( const mesh_t m );
void TransposeMesh( mesh_t& m );
void InvertMesh( mesh_t& m );
mesh_t SubdivideMesh( const mesh_t in, float maxError, float minLength );
int IterationsForCurve( float len, int subdivisions );
mesh_t *SubdivideMesh2( mesh_t in, int iterations );
mesh_t *RemoveLinearMeshColumnsRows( mesh_t *in );
void MakeMeshNormals( mesh_t in );
void PutMeshOnCurve( mesh_t in );
mesh_t SubdivideMesh2( const mesh_t in, int iterations );
mesh_t RemoveLinearMeshColumnsRows( const mesh_t in );
mesh_t TessellatedMesh( const mesh_t in, int iterations );
void MakeMeshNormals( mesh_t& in );
void PutMeshOnCurve( mesh_t& in );
/* map.c */
+24 -36
View File
@@ -773,7 +773,6 @@ mapDrawSurface_t *DrawSurfaceForSide( const entity_t& e, const brush_t& b, const
mapDrawSurface_t *DrawSurfaceForMesh( const entity_t& e, parseMesh_t& p, mesh_t *mesh ){
Plane3f plane;
shaderInfo_t *si, *parent;
mesh_t *copy;
byte shaderIndexes[ MAX_EXPANDED_AXIS * MAX_EXPANDED_AXIS ];
float offsets[ MAX_EXPANDED_AXIS * MAX_EXPANDED_AXIS ];
@@ -788,35 +787,35 @@ mapDrawSurface_t *DrawSurfaceForMesh( const entity_t& e, parseMesh_t& p, mesh_t
}
/* get vertex count */
const int numVerts = mesh->width * mesh->height;
const int numVerts = mesh->numVerts();
/* to make valid normals for patches with degenerate edges,
we need to make a copy of the mesh and put the aproximating
points onto the curve */
/* create a copy of the mesh */
copy = CopyMesh( mesh );
mesh_t copy = CopyMesh( *mesh );
/* store off the original (potentially bad) normals */
MakeMeshNormals( *copy );
MakeMeshNormals( copy );
for ( int i = 0; i < numVerts; ++i )
mesh->verts[ i ].normal = copy->verts[ i ].normal;
mesh->verts[ i ].normal = copy.verts[ i ].normal;
/* put the mesh on the curve */
PutMeshOnCurve( *copy );
PutMeshOnCurve( copy );
/* find new normals (to take into account degenerate/flipped edges */
MakeMeshNormals( *copy );
MakeMeshNormals( copy );
for ( int i = 0; i < numVerts; ++i )
{
/* ydnar: only copy normals that are significantly different from the originals */
if ( vector3_dot( copy->verts[ i ].normal, mesh->verts[ i ].normal ) < 0.75f ) {
mesh->verts[ i ].normal = copy->verts[ i ].normal;
if ( vector3_dot( copy.verts[ i ].normal, mesh->verts[ i ].normal ) < 0.75f ) {
mesh->verts[ i ].normal = copy.verts[ i ].normal;
}
}
/* free the old mesh */
FreeMesh( copy );
copy.freeVerts();
/* ydnar: gs mods: check for indexed shader */
const bool indexed = ( si->indexed && p.im != nullptr );
@@ -2844,40 +2843,29 @@ static int AddSurfaceModels( mapDrawSurface_t& ds, entity_t& entity ){
case ESurfaceType::Patch:
{
/* subdivide the surface */
mesh_t src;
src.width = ds.patchWidth;
src.height = ds.patchHeight;
src.verts = ds.verts.data();
//% mesh_t *subdivided = SubdivideMesh( src, 8.0f, 512 );
const int iterations = IterationsForCurve( ds.longestCurve, patchSubdivisions );
mesh_t *subdivided = SubdivideMesh2( src, iterations );
/* fit it to the curve and remove colinear verts on rows/columns */
PutMeshOnCurve( *subdivided );
mesh_t *mesh = RemoveLinearMeshColumnsRows( subdivided );
FreeMesh( subdivided );
mesh_t mesh = TessellatedMesh( mesh_t( ds.patchWidth, ds.patchHeight, ds.verts.data() ), IterationsForCurve( ds.longestCurve, patchSubdivisions ) );
/* subdivide each quad to place the models */
for ( int y = 0; y < ( mesh->height - 1 ); ++y )
for ( int y = 0; y < ( mesh.height - 1 ); ++y )
{
for ( int x = 0; x < ( mesh->width - 1 ); ++x )
for ( int x = 0; x < ( mesh.width - 1 ); ++x )
{
/* set indexes */
const int pw[ 5 ] = {
x + ( y * mesh->width ),
x + ( ( y + 1 ) * mesh->width ),
x + 1 + ( ( y + 1 ) * mesh->width ),
x + 1 + ( y * mesh->width ),
x + ( y * mesh->width ), /* same as pw[ 0 ] */
x + ( y * mesh.width ),
x + ( ( y + 1 ) * mesh.width ),
x + 1 + ( ( y + 1 ) * mesh.width ),
x + 1 + ( y * mesh.width ),
x + ( y * mesh.width ), /* same as pw[ 0 ] */
};
/* set radix */
const int r = ( x + y ) & 1;
/* triangle 1 */
const int n = AddSurfaceModelsToTriangle_r( ds, model, TriRef{
&mesh->verts[ pw[ r + 0 ] ],
&mesh->verts[ pw[ r + 1 ] ],
&mesh->verts[ pw[ r + 2 ] ] }, entity );
&mesh.verts[ pw[ r + 0 ] ],
&mesh.verts[ pw[ r + 1 ] ],
&mesh.verts[ pw[ r + 2 ] ] }, entity );
if ( n < 0 ) {
return n;
}
@@ -2885,9 +2873,9 @@ static int AddSurfaceModels( mapDrawSurface_t& ds, entity_t& entity ){
/* triangle 2 */
const int n2 = AddSurfaceModelsToTriangle_r( ds, model, TriRef{
&mesh->verts[ pw[ r + 0 ] ],
&mesh->verts[ pw[ r + 2 ] ],
&mesh->verts[ pw[ r + 3 ] ] }, entity );
&mesh.verts[ pw[ r + 0 ] ],
&mesh.verts[ pw[ r + 2 ] ],
&mesh.verts[ pw[ r + 3 ] ] }, entity );
if ( n2 < 0 ) {
return n2;
}
@@ -2896,7 +2884,7 @@ static int AddSurfaceModels( mapDrawSurface_t& ds, entity_t& entity ){
}
/* free the subdivided mesh */
FreeMesh( mesh );
mesh.freeVerts();
break;
}
/* handle triangle surfaces */
+19 -25
View File
@@ -186,53 +186,47 @@ void Foliage( mapDrawSurface_t& src, entity_t& entity ){
case ESurfaceType::Patch:
{
/* make a mesh from the drawsurf */
mesh_t srcMesh;
srcMesh.width = src.patchWidth;
srcMesh.height = src.patchHeight;
srcMesh.verts = src.verts.data();
mesh_t *subdivided = SubdivideMesh( srcMesh, 8, 512 );
mesh_t srcMesh( src.patchWidth, src.patchHeight, src.verts.data() );
mesh_t subdivided = SubdivideMesh( srcMesh, 8, 512 );
/* fit it to the curve and remove colinear verts on rows/columns */
PutMeshOnCurve( *subdivided );
mesh_t *mesh = RemoveLinearMeshColumnsRows( subdivided );
FreeMesh( subdivided );
/* get verts */
const bspDrawVert_t *verts = mesh->verts;
PutMeshOnCurve( subdivided );
mesh_t mesh = RemoveLinearMeshColumnsRows( subdivided );
subdivided.freeVerts();
/* map the mesh quads */
for ( int y = 0; y < ( mesh->height - 1 ); ++y )
for ( int y = 0; y < ( mesh.height - 1 ); ++y )
{
for ( int x = 0; x < ( mesh->width - 1 ); ++x )
for ( int x = 0; x < ( mesh.width - 1 ); ++x )
{
/* set indexes */
const int pw[ 5 ] = {
x + ( y * mesh->width ),
x + ( ( y + 1 ) * mesh->width ),
x + 1 + ( ( y + 1 ) * mesh->width ),
x + 1 + ( y * mesh->width ),
x + ( y * mesh->width ) /* same as pw[ 0 ] */
x + ( y * mesh.width ),
x + ( ( y + 1 ) * mesh.width ),
x + 1 + ( ( y + 1 ) * mesh.width ),
x + 1 + ( y * mesh.width ),
x + ( y * mesh.width ) /* same as pw[ 0 ] */
};
/* set radix */
const int r = ( x + y ) & 1;
/* get drawverts and map first triangle */
SubdivideFoliageTriangle_r( foliage, TriRef{
&verts[ pw[ r + 0 ] ],
&verts[ pw[ r + 1 ] ],
&verts[ pw[ r + 2 ] ]
&mesh.verts[ pw[ r + 0 ] ],
&mesh.verts[ pw[ r + 1 ] ],
&mesh.verts[ pw[ r + 2 ] ]
} );
/* get drawverts and map second triangle */
SubdivideFoliageTriangle_r( foliage, TriRef{
&verts[ pw[ r + 0 ] ],
&verts[ pw[ r + 2 ] ],
&verts[ pw[ r + 3 ] ]
&mesh.verts[ pw[ r + 0 ] ],
&mesh.verts[ pw[ r + 2 ] ],
&mesh.verts[ pw[ r + 3 ] ]
} );
}
}
/* free the mesh */
FreeMesh( mesh );
mesh.freeVerts();
break;
}
default:
+12 -24
View File
@@ -361,12 +361,6 @@ static void TriangulatePatchSurface( const entity_t& e, mapDrawSurface_t& ds ){
if ( ds.verts.empty() || ds.type != ESurfaceType::Patch || ( !patchMeta && !forcePatchMeta ) ) {
return;
}
/* make a mesh from the drawsurf */
mesh_t src;
src.width = ds.patchWidth;
src.height = ds.patchHeight;
src.verts = ds.verts.data();
//% mesh_t *subdivided = SubdivideMesh( src, 8, 999 );
int iterations;
if ( int patchSubdivision; e.read_keyvalue( patchSubdivision, "_patchSubdivide", "patchSubdivide" ) ) {
@@ -376,14 +370,8 @@ static void TriangulatePatchSurface( const entity_t& e, mapDrawSurface_t& ds ){
const int patchQuality = e.intForKey( "_patchQuality", "patchQuality" );
iterations = IterationsForCurve( ds.longestCurve, patchSubdivisions / ( patchQuality == 0? 1 : patchQuality ) );
}
mesh_t *subdivided = SubdivideMesh2( src, iterations ); //% ds.maxIterations
/* fit it to the curve and remove colinear verts on rows/columns */
PutMeshOnCurve( *subdivided );
mesh_t *mesh = RemoveLinearMeshColumnsRows( subdivided );
FreeMesh( subdivided );
//% MakeMeshNormals( mesh );
/* make a mesh from the drawsurf */
mesh_t mesh = TessellatedMesh( mesh_t( ds.patchWidth, ds.patchHeight, ds.verts.data() ), iterations ); //% ds.maxIterations
/* make a copy of the drawsurface */
mapDrawSurface_t& dsNew = AllocDrawSurface( ESurfaceType::Meta );
@@ -397,23 +385,23 @@ static void TriangulatePatchSurface( const entity_t& e, mapDrawSurface_t& ds ){
/* basic transmogrification */
dsNew.type = ESurfaceType::Meta;
dsNew.indexes.clear();
dsNew.indexes.reserve( ( mesh->width - 1 ) * ( mesh->height - 1 ) * 6 );
dsNew.indexes.reserve( ( mesh.width - 1 ) * ( mesh.height - 1 ) * 6 );
/* copy the verts in */
dsNew.verts.assign( mesh->verts, mesh->verts + mesh->width * mesh->height );
dsNew.verts.assign( mesh.verts, mesh.verts + mesh.numVerts() );
/* iterate through the mesh quads */
for ( int y = 0; y < ( mesh->height - 1 ); ++y )
for ( int y = 0; y < ( mesh.height - 1 ); ++y )
{
for ( int x = 0; x < ( mesh->width - 1 ); ++x )
for ( int x = 0; x < ( mesh.width - 1 ); ++x )
{
/* set indexes */
const int pw[ 5 ] = {
x + ( y * mesh->width ),
x + ( ( y + 1 ) * mesh->width ),
x + 1 + ( ( y + 1 ) * mesh->width ),
x + 1 + ( y * mesh->width ),
x + ( y * mesh->width ) /* same as pw[ 0 ] */
x + ( y * mesh.width ),
x + ( ( y + 1 ) * mesh.width ),
x + 1 + ( ( y + 1 ) * mesh.width ),
x + 1 + ( y * mesh.width ),
x + ( y * mesh.width ) /* same as pw[ 0 ] */
};
/* set radix */
const int r = ( x + y ) & 1;
@@ -430,7 +418,7 @@ static void TriangulatePatchSurface( const entity_t& e, mapDrawSurface_t& ds ){
}
}
FreeMesh( mesh );
mesh.freeVerts();
/* add to count */
numPatchMetaSurfaces++;
+1 -1
View File
@@ -495,7 +495,7 @@ void BeginModel( const entity_t& e ){
/* bound patches */
for ( const parseMesh_t& p : e.patches )
{
for ( const bspDrawVert_t& vert : Span( p.mesh.verts, p.mesh.width * p.mesh.height ) )
for ( const bspDrawVert_t& vert : Span( p.mesh.verts, p.mesh.numVerts() ) )
minmax.extend( vert.xyz );
}