/* ================= HashTriangles Removes triangles that are degenerated or flipped backwards ================= */ void HashTriangles(optimizeGroup_t *groupList) { mapTri_t *a; int vert; int i; optimizeGroup_t *group; // clear the hash tables memset(hashVerts, 0, sizeof(hashVerts)); numHashVerts = 0; numTotalVerts = 0; // bound all the triangles to determine the bucket size hashBounds.Clear(); for (group = groupList ; group ; group = group->nextGroup) { for (a = group->triList ; a ; a = a->next) { hashBounds.AddPoint(a->v[0].xyz); hashBounds.AddPoint(a->v[1].xyz); hashBounds.AddPoint(a->v[2].xyz); } } // spread the bounds so it will never have a zero size for (i = 0 ; i < 3 ; i++) { hashBounds[0][i] = floor(hashBounds[0][i] - 1); hashBounds[1][i] = ceil(hashBounds[1][i] + 1); hashIntMins[i] = hashBounds[0][i] * SNAP_FRACTIONS; hashScale[i] = (hashBounds[1][i] - hashBounds[0][i]) / HASH_BINS; hashIntScale[i] = hashScale[i] * SNAP_FRACTIONS; if (hashIntScale[i] < 1) { hashIntScale[i] = 1; } } // add all the points to the hash buckets for (group = groupList ; group ; group = group->nextGroup) { // don't create tjunctions against discrete surfaces (blood decals, etc) if (group->material != NULL && group->material->IsDiscrete()) { continue; } for (a = group->triList ; a ; a = a->next) { for (vert = 0 ; vert < 3 ; vert++) { a->hashVert[vert] = GetHashVert(a->v[vert].xyz); } } } }
/* ================== FixGlobalTjunctions ================== */ void FixGlobalTjunctions( uEntity_t *e ) { mapTri_t *a; int vert; int i; optimizeGroup_t *group; int areaNum; common->Printf( "----- FixGlobalTjunctions -----\n" ); // clear the hash tables memset( hashVerts, 0, sizeof( hashVerts ) ); numHashVerts = 0; numTotalVerts = 0; // bound all the triangles to determine the bucket size hashBounds.Clear(); for ( areaNum = 0 ; areaNum < e->numAreas ; areaNum++ ) { for ( group = e->areas[areaNum].groups ; group ; group = group->nextGroup ) { for ( a = group->triList ; a ; a = a->next ) { hashBounds.AddPoint( a->v[0].xyz ); hashBounds.AddPoint( a->v[1].xyz ); hashBounds.AddPoint( a->v[2].xyz ); } } } // spread the bounds so it will never have a zero size for ( i = 0 ; i < 3 ; i++ ) { hashBounds[0][i] = floor( hashBounds[0][i] - 1 ); hashBounds[1][i] = ceil( hashBounds[1][i] + 1 ); hashIntMins[i] = hashBounds[0][i] * SNAP_FRACTIONS; hashScale[i] = ( hashBounds[1][i] - hashBounds[0][i] ) / HASH_BINS; hashIntScale[i] = hashScale[i] * SNAP_FRACTIONS; if ( hashIntScale[i] < 1 ) { hashIntScale[i] = 1; } } // add all the points to the hash buckets for ( areaNum = 0 ; areaNum < e->numAreas ; areaNum++ ) { for ( group = e->areas[areaNum].groups ; group ; group = group->nextGroup ) { // don't touch discrete surfaces if ( group->material != NULL && group->material->IsDiscrete() ) { continue; } for ( a = group->triList ; a ; a = a->next ) { for ( vert = 0 ; vert < 3 ; vert++ ) { a->hashVert[vert] = GetHashVert( a->v[vert].xyz ); } } } } // add all the func_static model vertexes to the hash buckets // optionally inline some of the func_static models if ( dmapGlobals.entityNum == 0 ) { for ( int eNum = 1 ; eNum < dmapGlobals.num_entities ; eNum++ ) { uEntity_t *entity = &dmapGlobals.uEntities[eNum]; const char *className = entity->mapEntity->epairs.GetString( "classname" ); if ( idStr::Icmp( className, "func_static" ) ) { continue; } const char *modelName = entity->mapEntity->epairs.GetString( "model" ); if ( !modelName ) { continue; } if ( !strstr( modelName, ".lwo" ) && !strstr( modelName, ".ase" ) && !strstr( modelName, ".ma" ) ) { continue; } idRenderModel *model = renderModelManager->FindModel( modelName ); // common->Printf( "adding T junction verts for %s.\n", entity->mapEntity->epairs.GetString( "name" ) ); idMat3 axis; // get the rotation matrix in either full form, or single angle form if ( !entity->mapEntity->epairs.GetMatrix( "rotation", "1 0 0 0 1 0 0 0 1", axis ) ) { float angle = entity->mapEntity->epairs.GetFloat( "angle" ); if ( angle != 0.0f ) { axis = idAngles( 0.0f, angle, 0.0f ).ToMat3(); } else { axis.Identity(); } } idVec3 origin = entity->mapEntity->epairs.GetVector( "origin" ); for ( i = 0 ; i < model->NumSurfaces() ; i++ ) { const modelSurface_t *surface = model->Surface( i ); const srfTriangles_t *tri = surface->geometry; mapTri_t mapTri; memset( &mapTri, 0, sizeof( mapTri ) ); mapTri.material = surface->shader; // don't let discretes (autosprites, etc) merge together if ( mapTri.material->IsDiscrete() ) { mapTri.mergeGroup = (void *)surface; } for ( int j = 0 ; j < tri->numVerts ; j += 3 ) { idVec3 v = tri->verts[j].xyz * axis + origin; GetHashVert( v ); } } } } // now fix each area for ( areaNum = 0 ; areaNum < e->numAreas ; areaNum++ ) { for ( group = e->areas[areaNum].groups ; group ; group = group->nextGroup ) { // don't touch discrete surfaces if ( group->material != NULL && group->material->IsDiscrete() ) { continue; } mapTri_t *newList = NULL; for ( mapTri_t *tri = group->triList ; tri ; tri = tri->next ) { mapTri_t *fixed = FixTriangleAgainstHash( tri ); newList = MergeTriLists( newList, fixed ); } FreeTriList( group->triList ); group->triList = newList; } } // done FreeTJunctionHash(); }