/* ================ R_CalcInteractionFacing Determines which triangles of the surface are facing towards the light origin. The facing array should be allocated with one extra index than the number of surface triangles, which will be used to handle dangling edge silhouettes. ================ */ void R_CalcInteractionFacing( const idRenderEntityLocal *ent, const srfTriangles_t *tri, const idRenderLightLocal *light, srfCullInfo_t &cullInfo ) { idVec3 localLightOrigin; if ( cullInfo.facing != NULL ) { return; } R_GlobalPointToLocal( ent->modelMatrix, light->globalLightOrigin, localLightOrigin ); int numFaces = tri->numIndexes / 3; if ( !tri->facePlanes || !tri->facePlanesCalculated ) { R_DeriveFacePlanes( const_cast<srfTriangles_t *>(tri) ); } cullInfo.facing = (byte *) R_StaticAlloc( ( numFaces + 1 ) * sizeof( cullInfo.facing[0] ) ); // calculate back face culling float *planeSide = (float *) _alloca16( numFaces * sizeof( float ) ); // exact geometric cull against face SIMDProcessor->Dot( planeSide, localLightOrigin, tri->facePlanes, numFaces ); SIMDProcessor->CmpGE( cullInfo.facing, planeSide, 0.0f, numFaces ); cullInfo.facing[ numFaces ] = 1; // for dangling edges to reference }
/* ============== RenderBumpTriangles ============== */ static void RenderBumpTriangles( srfTriangles_t *lowMesh, renderBump_t *rb ) { int i, j; RB_SetGL2D(); qglDisable( GL_CULL_FACE ); qglColor3f( 1, 1, 1 ); qglMatrixMode( GL_PROJECTION ); qglLoadIdentity(); qglOrtho( 0, 1, 1, 0, -1, 1 ); qglDisable( GL_BLEND ); qglMatrixMode( GL_MODELVIEW ); qglLoadIdentity(); qglDisable( GL_DEPTH_TEST ); qglClearColor(1,0,0,1); qglClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); qglColor3f( 1, 1, 1 ); // create smoothed normals for the surface, which might be // different than the normals at the vertexes if the // surface uses unsmoothedNormals, which only takes the // normal from a single triangle. We need properly smoothed // normals to make sure that the traces always go off normal // to the true surface. idVec3 *lowMeshNormals = (idVec3 *)Mem_ClearedAlloc( lowMesh->numVerts * sizeof( *lowMeshNormals ) ); R_DeriveFacePlanes( lowMesh ); R_CreateSilIndexes( lowMesh ); // recreate, merging the mirrored verts back together const idPlane *planes = lowMesh->facePlanes; for ( i = 0 ; i < lowMesh->numIndexes ; i += 3, planes++ ) { for ( j = 0 ; j < 3 ; j++ ) { int index; index = lowMesh->silIndexes[i+j]; lowMeshNormals[index] += (*planes).Normal(); } } // normalize and replicate from silIndexes to all indexes for ( i = 0 ; i < lowMesh->numIndexes ; i++ ) { lowMeshNormals[lowMesh->indexes[i]] = lowMeshNormals[lowMesh->silIndexes[i]]; lowMeshNormals[lowMesh->indexes[i]].Normalize(); } // rasterize each low poly face for ( j = 0 ; j < lowMesh->numIndexes ; j+=3 ) { // pump the event loop so the window can be dragged around Sys_GenerateEvents(); RasterizeTriangle( lowMesh, lowMeshNormals, j/3, rb ); qglClearColor(1,0,0,1); qglClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); qglRasterPos2f( 0, 1 ); qglPixelZoom( glConfig.vidWidth / (float)rb->width, glConfig.vidHeight / (float)rb->height ); qglDrawPixels( rb->width, rb->height, GL_RGBA, GL_UNSIGNED_BYTE, rb->localPic ); qglPixelZoom( 1, 1 ); qglFlush(); GLimp_SwapBuffers(); } Mem_Free( lowMeshNormals ); }
/* =============== InitRenderBump =============== */ static void InitRenderBump( renderBump_t *rb ) { srfTriangles_t *mesh; idBounds bounds; int i, c; // load the ase file common->Printf( "loading %s...\n", rb->highName ); rb->highModel = renderModelManager->AllocModel(); rb->highModel->PartialInitFromFile( rb->highName ); if ( !rb->highModel ) { common->Error( "failed to load %s", rb->highName ); } // combine the high poly model into a single polyset if ( rb->highModel->NumSurfaces() != 1 ) { rb->highModel = CombineModelSurfaces( rb->highModel ); } const modelSurface_t *surf = rb->highModel->Surface( 0 ); mesh = surf->geometry; rb->mesh = mesh; R_DeriveFacePlanes( mesh ); // create a face hash table to accelerate the tracing rb->hash = CreateTriHash( mesh ); // bound the entire file R_BoundTriSurf( mesh ); bounds = mesh->bounds; // the traceDist will be the traceFrac times the larges bounds axis rb->traceDist = 0; for ( i = 0 ; i < 3 ; i++ ) { float d; d = rb->traceFrac * ( bounds[1][i] - bounds[0][i] ); if ( d > rb->traceDist ) { rb->traceDist = d; } } common->Printf( "trace fraction %4.2f = %6.2f model units\n", rb->traceFrac, rb->traceDist ); c = rb->width * rb->height * 4; // local normal map rb->localPic = (byte *)Mem_Alloc( c ); // global (object space, not surface space) normal map rb->globalPic = (byte *)Mem_Alloc( c ); // color pic for artist reference rb->colorPic = (byte *)Mem_Alloc( c ); // edgeDistance for marking outside-the-triangle traces rb->edgeDistances = (float *)Mem_Alloc( c ); for ( i = 0 ; i < c ; i+=4 ) { rb->localPic[i+0] = 128; rb->localPic[i+1] = 128; rb->localPic[i+2] = 128; rb->localPic[i+3] = 0; // the artists use this for masking traced pixels sometimes rb->globalPic[i+0] = 128; rb->globalPic[i+1] = 128; rb->globalPic[i+2] = 128; rb->globalPic[i+3] = 0; rb->colorPic[i+0] = 128; rb->colorPic[i+1] = 128; rb->colorPic[i+2] = 128; rb->colorPic[i+3] = 0; rb->edgeDistances[i/4] = -1; // not traced yet } }