/* ================ ParseSurface ================ */ static void ParseSurface( const idMapPatch *patch, const idSurface *surface, const idMaterial *material ) { int i; mapTri_t *tri; primitive_t *prim; prim = (primitive_t *)Mem_Alloc( sizeof( *prim ) ); memset( prim, 0, sizeof( *prim ) ); prim->next = uEntity->primitives; uEntity->primitives = prim; for ( i = 0; i < surface->GetNumIndexes(); i += 3 ) { tri = AllocTri(); tri->v[2] = (*surface)[surface->GetIndexes()[i+0]]; tri->v[1] = (*surface)[surface->GetIndexes()[i+2]]; tri->v[0] = (*surface)[surface->GetIndexes()[i+1]]; tri->material = material; tri->next = prim->tris; prim->tris = tri; } // set merge groups if needed, to prevent multiple sides from being // merged into a single surface in the case of gui shaders, mirrors, and autosprites if ( material->IsDiscrete() ) { for ( tri = prim->tris ; tri ; tri = tri->next ) { tri->mergeGroup = (void *)patch; } } }
/* ==================== RegenerateTriangles Add new triangles to the group's regeneratedTris ==================== */ static void RegenerateTriangles( optIsland_t* island ) { optTri_t* optTri; mapTri_t* tri; int c_out; c_out = 0; for( optTri = island->tris ; optTri ; optTri = optTri->next ) { if( !optTri->filled ) { continue; } // create a new mapTri_t tri = AllocTri(); tri->material = island->group->material; tri->mergeGroup = island->group->mergeGroup; tri->v[0] = optTri->v[0]->v; tri->v[1] = optTri->v[1]->v; tri->v[2] = optTri->v[2]->v; idPlane plane; PlaneForTri( tri, plane ); if( plane.Normal() * dmapGlobals.mapPlanes[ island->group->planeNum ].Normal() <= 0 ) { // this can happen reasonably when a triangle is nearly degenerate in // optimization planar space, and winds up being degenerate in 3D space common->Printf( "WARNING: backwards triangle generated!\n" ); // discard it FreeTri( tri ); continue; } c_out++; tri->next = island->group->regeneratedTris; island->group->regeneratedTris = tri; } FreeOptTriangles( island ); if( dmapGlobals.verbose ) { common->Printf( "%6i tris out\n", c_out ); } }
/* ================ WindingToTriList Generates a new list of triangles with proper texcoords from a winding created by clipping the originalTri OriginalTri can be NULL if you don't care about texCoords ================ */ mapTri_t *WindingToTriList( const idWinding *w, const mapTri_t *originalTri ) { mapTri_t *tri; mapTri_t *triList; int i, j; const idVec3 *vec; if ( !w ) { return NULL; } triList = NULL; for ( i = 2 ; i < w->GetNumPoints() ; i++ ) { tri = AllocTri(); if ( !originalTri ) { memset( tri, 0, sizeof( *tri ) ); } else { *tri = *originalTri; } tri->next = triList; triList = tri; for ( j = 0 ; j < 3 ; j++ ) { if ( j == 0 ) { vec = &((*w)[0]).ToVec3(); } else if ( j == 1 ) { vec = &((*w)[i-1]).ToVec3(); } else { vec = &((*w)[i]).ToVec3(); } VectorCopy( *vec, tri->v[j].xyz ); } if ( originalTri ) { TriVertsFromOriginal( tri, originalTri ); } } return triList; }
mapTri_t *TriListForSide( const side_t *s, const idWinding *w ) { int i, j; idDrawVert *dv; mapTri_t *tri, *triList; const idVec3 *vec; const idMaterial *si; si = s->material; // skip any generated faces if ( !si ) { return NULL; } // don't create faces for non-visible sides if ( !si->SurfaceCastsShadow() && !si->IsDrawn() ) { return NULL; } if ( 1 ) { // triangle fan using only the outer verts // this gives the minimum triangle count, // but may have some very distended triangles triList = NULL; for ( i = 2 ; i < w->GetNumPoints() ; i++ ) { tri = AllocTri(); tri->material = si; tri->next = triList; triList = tri; for ( j = 0 ; j < 3 ; j++ ) { if ( j == 0 ) { vec = &((*w)[0]).ToVec3(); } else if ( j == 1 ) { vec = &((*w)[i-1]).ToVec3(); } else { vec = &((*w)[i]).ToVec3(); } dv = tri->v + j; #if 0 // round the xyz to a given precision for ( k = 0 ; k < 3 ; k++ ) { dv->xyz[k] = SNAP_INT_TO_FLOAT * floor( vec[k] * SNAP_FLOAT_TO_INT + 0.5 ); } #else VectorCopy( *vec, dv->xyz ); #endif // calculate texture s/t from brush primitive texture matrix dv->st[0] = DotProduct( dv->xyz, s->texVec.v[0] ) + s->texVec.v[0][3]; dv->st[1] = DotProduct( dv->xyz, s->texVec.v[1] ) + s->texVec.v[1][3]; // copy normal dv->normal = dmapGlobals.mapPlanes[s->planenum].Normal(); if ( dv->normal.Length() < 0.9 || dv->normal.Length() > 1.1 ) { common->Error( "Bad normal in TriListForSide" ); } } } } else { // triangle fan from central point, more verts and tris, but less distended // I use this when debugging some tjunction problems triList = NULL; for ( i = 0 ; i < w->GetNumPoints() ; i++ ) { idVec3 midPoint; tri = AllocTri(); tri->material = si; tri->next = triList; triList = tri; for ( j = 0 ; j < 3 ; j++ ) { if ( j == 0 ) { vec = &midPoint; midPoint = w->GetCenter(); } else if ( j == 1 ) { vec = &((*w)[i]).ToVec3(); } else { vec = &((*w)[(i+1)%w->GetNumPoints()]).ToVec3(); } dv = tri->v + j; VectorCopy( *vec, dv->xyz ); // calculate texture s/t from brush primitive texture matrix dv->st[0] = DotProduct( dv->xyz, s->texVec.v[0] ) + s->texVec.v[0][3]; dv->st[1] = DotProduct( dv->xyz, s->texVec.v[1] ) + s->texVec.v[1][3]; // copy normal dv->normal = dmapGlobals.mapPlanes[s->planenum].Normal(); if ( dv->normal.Length() < 0.9f || dv->normal.Length() > 1.1f ) { common->Error( "Bad normal in TriListForSide" ); } } } } // set merge groups if needed, to prevent multiple sides from being // merged into a single surface in the case of gui shaders, mirrors, and autosprites if ( s->material->IsDiscrete() ) { for ( tri = triList ; tri ; tri = tri->next ) { tri->mergeGroup = (void *)s; } } return triList; }