public override void FinishSurfaces()
{
if(this.Disposed == true)
{
throw new ObjectDisposedException(this.GetType().Name);
}
_purged = false;
// make sure we don't have a huge bounds even if we don't finish everything
_bounds = idBounds.Zero;
if(_surfaces.Count == 0)
{
return;
}
// renderBump doesn't care about most of this
if(_fastLoad == true)
{
_bounds = idBounds.Zero;
foreach(RenderModelSurface surf in _surfaces)
{
idHelper.BoundTriangleSurface(surf.Geometry);
_bounds.AddBounds(surf.Geometry.Bounds);
}
return;
}
// cleanup all the final surfaces, but don't create sil edges
int totalVerts = 0;
int totalIndexes = 0;
// decide if we are going to merge all the surfaces into one shadower
int numOriginalSurfaces = _surfaces.Count;
// make sure there aren't any NULL shaders or geometry
for(int i = 0; i < numOriginalSurfaces; i++)
{
RenderModelSurface surf = _surfaces[i];
if((surf.Geometry == null) || (surf.Material == null))
{
MakeDefault();
idConsole.Error("Model {0}, surface {1} had NULL goemetry", this.Name, i);
}
if(surf.Material == null)
{
MakeDefault();
idConsole.Error("Model {0}, surface {1} had NULL material", this.Name, i);
}
}
// duplicate and reverse triangles for two sided bump mapped surfaces
// note that this won't catch surfaces that have their shaders dynamically
// changed, and won't work with animated models.
// It is better to create completely separate surfaces, rather than
// add vertexes and indexes to the existing surface, because the
// tangent generation wouldn't like the acute shared edges
for(int i = 0; i < numOriginalSurfaces; i++)
{
RenderModelSurface surf = _surfaces[i];
if(surf.Material.ShouldCreateBackSides == true)
{
idConsole.Warning("TODO: should create back sides");
/*srfTriangles_t *newTri;
newTri = R_CopyStaticTriSurf( surf->geometry );
R_ReverseTriangles( newTri );
modelSurface_t newSurf;
newSurf.shader = surf->shader;
newSurf.geometry = newTri;
AddSurface( newSurf );*/
}
}
// clean the surfaces
// TODO: clean surfaces
/*for ( i = 0 ; i < surfaces.Num() ; i++ ) {
const modelSurface_t *surf = &surfaces[i];
R_CleanupTriangles( surf->geometry, surf->geometry->generateNormals, true, surf->shader->UseUnsmoothedTangents() );
if ( surf->shader->SurfaceCastsShadow() ) {
totalVerts += surf->geometry->numVerts;
totalIndexes += surf->geometry->numIndexes;
}
}*/
// add up the total surface area for development information
// TODO: surf dev info
/*for ( i = 0 ; i < surfaces.Num() ; i++ ) {
const modelSurface_t *surf = &surfaces[i];
srfTriangles_t *tri = surf->geometry;
for ( int j = 0 ; j < tri->numIndexes ; j += 3 ) {
float area = idWinding::TriangleArea( tri->verts[tri->indexes[j]].xyz,
tri->verts[tri->indexes[j+1]].xyz, tri->verts[tri->indexes[j+2]].xyz );
const_cast<idMaterial *>(surf->shader)->AddToSurfaceArea( area );
}
}*/
// calculate the bounds
int surfaceCount = _surfaces.Count;
if(surfaceCount == 0)
{
_bounds = idBounds.Zero;
}
else
{
_bounds.Clear();
for(int i = 0; i < surfaceCount; i++)
{
RenderModelSurface surf = _surfaces[i];
// if the surface has a deformation, increase the bounds
// the amount here is somewhat arbitrary, designed to handle
// autosprites and flares, but could be done better with exact
// deformation information.
// Note that this doesn't handle deformations that are skinned in
// at run time...
if(surf.Material.Deform != DeformType.None)
{
idConsole.Warning("TODO: deform");
/*srfTriangles_t *tri = surf->geometry;
idVec3 mid = ( tri->bounds[1] + tri->bounds[0] ) * 0.5f;
float radius = ( tri->bounds[0] - mid ).Length();
radius += 20.0f;
tri->bounds[0][0] = mid[0] - radius;
tri->bounds[0][1] = mid[1] - radius;
tri->bounds[0][2] = mid[2] - radius;
tri->bounds[1][0] = mid[0] + radius;
tri->bounds[1][1] = mid[1] + radius;
tri->bounds[1][2] = mid[2] + radius;*/
}
// add to the model bounds
_bounds.AddBounds(surf.Geometry.Bounds);
}
}
}