Optimize UE1 vertex normal computation.

This commit is contained in:
Marisa Kirisame 2020-07-11 12:59:14 +02:00 committed by Chronos Ouroboros
parent c8fe5bcb2e
commit 6e79209931
2 changed files with 22 additions and 14 deletions

View file

@ -13,7 +13,7 @@ public:
PT_TwoSided = 1, // like normal, but don't cull backfaces PT_TwoSided = 1, // like normal, but don't cull backfaces
PT_Translucent = 2, // additive blending PT_Translucent = 2, // additive blending
PT_Masked = 3, // draw with alpha testing PT_Masked = 3, // draw with alpha testing
PT_Modulated = 4, // overlay-like blending (rgb values below 128 darken, 128 is unchanged, and above 128 lighten) PT_Modulated = 4, // modulated blending (src*dest*2)
// types mask // types mask
PT_Type = 7, PT_Type = 7,
// flags // flags
@ -86,6 +86,8 @@ private:
struct UE1Vertex struct UE1Vertex
{ {
FVector3 Pos, Normal; FVector3 Pos, Normal;
TArray<int> P; // polys that reference this vertex, used in normal computation to save time
int nP; // count of those polys
}; };
struct UE1Poly struct UE1Poly
{ {
@ -103,7 +105,7 @@ private:
int numFrames; int numFrames;
int numPolys; int numPolys;
int numGroups; int numGroups;
int weaponPoly; // for future model attachment support, unused for now TArray<int> specialPolys; // for future model attachment support, unused for now
TArray<UE1Vertex> verts; TArray<UE1Vertex> verts;
TArray<UE1Poly> polys; TArray<UE1Poly> polys;

View file

@ -85,7 +85,6 @@ void FUE1Model::LoadGeometry()
averts = (uint32_t*)(buffer2+sizeof(a3dhead)); averts = (uint32_t*)(buffer2+sizeof(a3dhead));
dxverts = NULL; dxverts = NULL;
} }
weaponPoly = -1;
// set counters // set counters
numVerts = dhead->numverts; numVerts = dhead->numverts;
numFrames = ahead->numframes; numFrames = ahead->numframes;
@ -111,6 +110,9 @@ void FUE1Model::LoadGeometry()
unpackuvert(averts[j+i*numVerts],2), unpackuvert(averts[j+i*numVerts],2),
-unpackuvert(averts[j+i*numVerts],1)); -unpackuvert(averts[j+i*numVerts],1));
} }
// refs will be set later
Vert.P.Reset();
Vert.nP = 0;
// push vertex (without normals, will be calculated later) // push vertex (without normals, will be calculated later)
verts.Push(Vert); verts.Push(Vert);
} }
@ -132,23 +134,26 @@ void FUE1Model::LoadGeometry()
dir[0] = verts[Poly.V[1]+numVerts*j].Pos-verts[Poly.V[0]+numVerts*j].Pos; dir[0] = verts[Poly.V[1]+numVerts*j].Pos-verts[Poly.V[0]+numVerts*j].Pos;
dir[1] = verts[Poly.V[2]+numVerts*j].Pos-verts[Poly.V[0]+numVerts*j].Pos; dir[1] = verts[Poly.V[2]+numVerts*j].Pos-verts[Poly.V[0]+numVerts*j].Pos;
Poly.Normals.Push((dir[0]^dir[1]).Unit()); Poly.Normals.Push((dir[0]^dir[1]).Unit());
// since we're iterating frames, also set references for later
for ( int k=0; k<3; k++ )
{
verts[Poly.V[k]+numVerts*j].P.Push(i);
verts[Poly.V[k]+numVerts*j].nP++;
}
} }
// push // push
polys.Push(Poly); polys.Push(Poly);
} }
// compute normals for vertex arrays // compute normals for vertex arrays (average of all referenced poly normals)
// iterates through all polys and compute the average of all facet normals // since we have references listed from before, this saves a lot of time
// from those who use this vertex. not pretty, but does the job // without having to loop through the entire model each vertex (especially true for very complex models)
for ( int i=0; i<numFrames; i++ ) for ( int i=0; i<numFrames; i++ )
{ {
for ( int j=0; j<numVerts; j++ ) for ( int j=0; j<numVerts; j++ )
{ {
FVector3 nsum = FVector3(0,0,0); FVector3 nsum = FVector3(0,0,0);
for ( int k=0; k<numPolys; k++ ) for ( int k=0; k<verts[j+numVerts*i].nP; k++ )
{ nsum += polys[verts[j+numVerts*i].P[k]].Normals[i];
if ( (polys[k].V[0] != j) && (polys[k].V[1] != j) && (polys[k].V[2] != j) ) continue;
nsum += polys[k].Normals[i];
}
verts[j+numVerts*i].Normal = nsum.Unit(); verts[j+numVerts*i].Normal = nsum.Unit();
} }
} }
@ -159,8 +164,9 @@ void FUE1Model::LoadGeometry()
UE1Group Group; UE1Group Group;
for ( int i=0; i<numPolys; i++ ) for ( int i=0; i<numPolys; i++ )
{ {
// while we're at it, look for the weapon triangle // while we're at it, look for attachment triangles
if ( dpolys[i].type&PT_WeaponTriangle ) weaponPoly = i; // technically only one should exist, but we ain't following the specs 100% here
if ( dpolys[i].type&PT_WeaponTriangle ) specialPolys.Push(i);
if ( curgroup == -1 ) if ( curgroup == -1 )
{ {
// no group, create it // no group, create it
@ -197,7 +203,7 @@ void FUE1Model::LoadGeometry()
void FUE1Model::UnloadGeometry() void FUE1Model::UnloadGeometry()
{ {
mDataLoaded = false; mDataLoaded = false;
weaponPoly = -1; specialPolys.Reset();
numVerts = 0; numVerts = 0;
numFrames = 0; numFrames = 0;
numPolys = 0; numPolys = 0;