//----------------------------------------------------------------------------- // Purpose: // Input : *pPatch - // *pPoints - // &vecNormal - // flArea - //----------------------------------------------------------------------------- bool CVRADDispColl::InitPatch( int iPatch, int iParentPatch, int iChild, Vector *pPoints, int *pIndices, float &flArea ) { // Get the current patch. CPatch *pPatch = &g_Patches[iPatch]; if ( !pPatch ) return false; // Clear the patch data. memset( pPatch, 0, sizeof( CPatch ) ); // Setup the parent if we are not the parent. CPatch *pParentPatch = NULL; if ( iParentPatch != g_Patches.InvalidIndex() ) { // Get the parent patch. pParentPatch = &g_Patches[iParentPatch]; if ( !pParentPatch ) return false; } // Attach the face to the correct lists. if ( !pParentPatch ) { // This is a parent. pPatch->ndxNext = g_FacePatches.Element( GetParentIndex() ); g_FacePatches[GetParentIndex()] = iPatch; pPatch->faceNumber = GetParentIndex(); } else { pPatch->ndxNext = g_Patches.InvalidIndex(); pPatch->faceNumber = pParentPatch->faceNumber; // Attach to the parent patch. if ( iChild == 0 ) { pParentPatch->child1 = iPatch; } else { pParentPatch->child2 = iPatch; } } // Initialize parent and children indices. pPatch->child1 = g_Patches.InvalidIndex(); pPatch->child2 = g_Patches.InvalidIndex(); pPatch->ndxNextClusterChild = g_Patches.InvalidIndex(); pPatch->ndxNextParent = g_Patches.InvalidIndex(); pPatch->parent = iParentPatch; // Get triangle edges. Vector vecEdges[3]; vecEdges[0] = pPoints[1] - pPoints[0]; vecEdges[1] = pPoints[2] - pPoints[0]; vecEdges[2] = pPoints[2] - pPoints[1]; // Find the longest edge. // float flEdgeLength = 0.0f; // for ( int iEdge = 0; iEdge < 3; ++iEdge ) // { // if ( flEdgeLength < vecEdges[iEdge].Length() ) // { // flEdgeLength = vecEdges[iEdge].Length(); // } // } // Calculate the triangle normal and area. Vector vecNormal = vecEdges[1].Cross( vecEdges[0] ); flArea = VectorNormalize( vecNormal ); flArea *= 0.5f; // Initialize the patch scale. pPatch->scale[0] = pPatch->scale[1] = 1.0f; // Set the patch chop - minchop (that is what the minimum area is based on). pPatch->chop = dispchop; // Displacements are not sky! pPatch->sky = false; // Copy the winding. Vector vecCenter( 0.0f, 0.0f, 0.0f ); pPatch->winding = AllocWinding( 3 ); pPatch->winding->numpoints = 3; for ( int iPoint = 0; iPoint < 3; ++iPoint ) { VectorCopy( pPoints[iPoint], pPatch->winding->p[iPoint] ); VectorAdd( pPoints[iPoint], vecCenter, vecCenter ); pPatch->indices[iPoint] = static_cast<short>( pIndices[iPoint] ); } // Set the origin and normal. VectorScale( vecCenter, ( 1.0f / 3.0f ), vecCenter ); VectorCopy( vecCenter, pPatch->origin ); VectorCopy( vecNormal, pPatch->normal ); // Create the plane. pPatch->plane = new dplane_t; if ( !pPatch->plane ) return false; VectorCopy( vecNormal, pPatch->plane->normal ); pPatch->plane->dist = vecNormal.Dot( pPoints[0] ); pPatch->plane->type = PlaneTypeForNormal( pPatch->plane->normal ); pPatch->planeDist = pPatch->plane->dist; // Set the area. pPatch->area = flArea; // Calculate the mins/maxs. Vector vecMin( FLT_MAX, FLT_MAX, FLT_MAX ); Vector vecMax( FLT_MIN, FLT_MIN, FLT_MIN ); for ( int iPoint = 0; iPoint < 3; ++iPoint ) { for ( int iAxis = 0; iAxis < 3; ++iAxis ) { vecMin[iAxis] = MIN( vecMin[iAxis], pPoints[iPoint][iAxis] ); vecMax[iAxis] = MAX( vecMax[iAxis], pPoints[iPoint][iAxis] ); } } VectorCopy( vecMin, pPatch->mins ); VectorCopy( vecMax, pPatch->maxs ); if ( !pParentPatch ) { VectorCopy( vecMin, pPatch->face_mins ); VectorCopy( vecMax, pPatch->face_maxs ); } else { VectorCopy( pParentPatch->face_mins, pPatch->face_mins ); VectorCopy( pParentPatch->face_maxs, pPatch->face_maxs ); } // Check for bumpmap. dface_t *pFace = dfaces + pPatch->faceNumber; texinfo_t *pTexInfo = &texinfo[pFace->texinfo]; pPatch->needsBumpmap = pTexInfo->flags & SURF_BUMPLIGHT ? true : false; // Misc... pPatch->m_IterationKey = 0; // Get the base light for the face. if ( !pParentPatch ) { BaseLightForFace( &g_pFaces[pPatch->faceNumber], pPatch->baselight, &pPatch->basearea, pPatch->reflectivity ); } else { VectorCopy( pParentPatch->baselight, pPatch->baselight ); pPatch->basearea = pParentPatch->basearea; pPatch->reflectivity = pParentPatch->reflectivity; } return true; }
//----------------------------------------------------------------------------- // Purpose: // Input : iPatch - // iParentPatch - // iChild - // *pPoints - // *pIndices - // &flArea - // Output : Returns true on success, false on failure. //----------------------------------------------------------------------------- bool CVRADDispColl::InitParentPatch( int iPatch, Vector *pPoints, float &flArea ) { // Get the current patch. CPatch *pPatch = &g_Patches[iPatch]; if ( !pPatch ) return false; // Clear the patch data. memset( pPatch, 0, sizeof( CPatch ) ); // This is a parent. pPatch->ndxNext = g_FacePatches.Element( GetParentIndex() ); g_FacePatches[GetParentIndex()] = iPatch; pPatch->faceNumber = GetParentIndex(); // Initialize parent and children indices. pPatch->child1 = g_Patches.InvalidIndex(); pPatch->child2 = g_Patches.InvalidIndex(); pPatch->parent = g_Patches.InvalidIndex(); pPatch->ndxNextClusterChild = g_Patches.InvalidIndex(); pPatch->ndxNextParent = g_Patches.InvalidIndex(); Vector vecEdges[2]; vecEdges[0] = pPoints[1] - pPoints[0]; vecEdges[1] = pPoints[3] - pPoints[0]; // Calculate the triangle normal and area. Vector vecNormal = vecEdges[1].Cross( vecEdges[0] ); flArea = VectorNormalize( vecNormal ); // Initialize the patch scale. pPatch->scale[0] = pPatch->scale[1] = 1.0f; // Set the patch chop - minchop (that is what the minimum area is based on). pPatch->chop = dispchop; // Displacements are not sky! pPatch->sky = false; // Copy the winding. Vector vecCenter( 0.0f, 0.0f, 0.0f ); pPatch->winding = AllocWinding( 4 ); pPatch->winding->numpoints = 4; for ( int iPoint = 0; iPoint < 4; ++iPoint ) { VectorCopy( pPoints[iPoint], pPatch->winding->p[iPoint] ); VectorAdd( pPoints[iPoint], vecCenter, vecCenter ); } // Set the origin and normal. VectorScale( vecCenter, ( 1.0f / 4.0f ), vecCenter ); VectorCopy( vecCenter, pPatch->origin ); VectorCopy( vecNormal, pPatch->normal ); // Create the plane. pPatch->plane = new dplane_t; if ( !pPatch->plane ) return false; VectorCopy( vecNormal, pPatch->plane->normal ); pPatch->plane->dist = vecNormal.Dot( pPoints[0] ); pPatch->plane->type = PlaneTypeForNormal( pPatch->plane->normal ); pPatch->planeDist = pPatch->plane->dist; // Set the area. pPatch->area = flArea; // Calculate the mins/maxs. Vector vecMin( FLT_MAX, FLT_MAX, FLT_MAX ); Vector vecMax( FLT_MIN, FLT_MIN, FLT_MIN ); for ( int iPoint = 0; iPoint < 4; ++iPoint ) { for ( int iAxis = 0; iAxis < 3; ++iAxis ) { vecMin[iAxis] = MIN( vecMin[iAxis], pPoints[iPoint][iAxis] ); vecMax[iAxis] = MAX( vecMax[iAxis], pPoints[iPoint][iAxis] ); } } VectorCopy( vecMin, pPatch->mins ); VectorCopy( vecMax, pPatch->maxs ); VectorCopy( vecMin, pPatch->face_mins ); VectorCopy( vecMax, pPatch->face_maxs ); // Check for bumpmap. dface_t *pFace = dfaces + pPatch->faceNumber; texinfo_t *pTexInfo = &texinfo[pFace->texinfo]; pPatch->needsBumpmap = pTexInfo->flags & SURF_BUMPLIGHT ? true : false; // Misc... pPatch->m_IterationKey = 0; // Calculate the base light, area, and reflectivity. BaseLightForFace( &g_pFaces[pPatch->faceNumber], pPatch->baselight, &pPatch->basearea, pPatch->reflectivity ); return true; }
//----------------------------------------------------------------------------- //----------------------------------------------------------------------------- bool CVRADDispColl::MakeParentPatch( int ndxPatch ) { #if 0 // debugging! if( !pDispFile ) { pDispFile = g_pFileSystem->Open( "vraddisp.txt", "w" ); } #endif // get the current patch patch_t *pPatch = &patches[ndxPatch]; if( pPatch ) { int ndxStart = Nodes_CalcCount( m_Power - 1 ); int ndxEnd = Nodes_CalcCount( m_Power ); for( int ndxNode = ndxStart; ndxNode < ndxEnd; ndxNode++ ) { VNode_t *pVNode = &m_pVNodes[ndxNode]; if( pVNode ) { VectorAdd( pPatch->normal, pVNode->patchNormal, pPatch->normal ); pPatch->area += pVNode->patchArea; for( int ndxAxis = 0; ndxAxis < 3; ndxAxis++ ) { if( pPatch->face_mins[ndxAxis] > pVNode->patchBounds[0][ndxAxis] ) { pPatch->face_mins[ndxAxis] = pVNode->patchBounds[0][ndxAxis]; } if( pPatch->face_maxs[ndxAxis] < pVNode->patchBounds[1][ndxAxis] ) { pPatch->face_maxs[ndxAxis] = pVNode->patchBounds[1][ndxAxis]; } } } } #if 0 // debugging! g_pFileSystem->FPrintf( pDispFile, "Parent Patch %d\n", ndxPatch ); g_pFileSystem->FPrintf( pDispFile, " Area: %lf\n", pPatch->area ); #endif // set the patch bounds to face bounds (as this is the face patch) pPatch->mins = pPatch->face_mins; pPatch->maxs = pPatch->face_maxs; VectorNormalize( pPatch->normal ); DispUVToSurfPt( Vector2D( 0.5f, 0.5f ), pPatch->origin, 0.0f ); // fill in the patch plane into given the normal and origin (have to alloc one - lame!) pPatch->plane = new dplane_t; if( pPatch->plane ) { pPatch->plane->normal = pPatch->normal; pPatch->plane->dist = pPatch->normal.Dot( pPatch->origin ); } // copy the patch origin to face_centroids for main patch VectorCopy( pPatch->origin, face_centroids[m_ndxParent] ); VectorAdd( pPatch->origin, pPatch->normal, pPatch->origin ); // approximate patch winding - used for debugging! pPatch->winding = AllocWinding( 4 ); if( pPatch->winding ) { pPatch->winding->numpoints = 4; for( int ndxPt = 0; ndxPt < 4; ndxPt++ ) { GetPoint( ndxPt, pPatch->winding->p[ndxPt] ); } } // get base face normal (stab direction is base face normal) Vector vBaseFaceNormal; GetStabDirection( vBaseFaceNormal ); int majorAxis = 0; float majorValue = vBaseFaceNormal[0]; if( vBaseFaceNormal[1] > majorValue ) { majorAxis = 1; majorValue = vBaseFaceNormal[1]; } if( vBaseFaceNormal[2] > majorValue ) { majorAxis = 2; } pPatch->normalMajorAxis = majorAxis; // get the base light for the face BaseLightForFace( &dfaces[m_ndxParent], pPatch->baselight, &pPatch->basearea, pPatch->reflectivity ); return true; } return false; }
void MakePatchForFace (int fn, winding_t *w) { dface_t *f = dfaces + fn; // No patches at all for the sky! if ( !IsSky(f) ) { float area; patch_t *patch; vec3_t light; vec3_t centroid = {0,0,0}; int i, j; texinfo_t *tx = &texinfo[f->texinfo]; area = WindingArea (w); totalarea += area; patch = &patches[num_patches]; if (num_patches == MAX_PATCHES) Error ("num_patches == MAX_PATCHES"); patch->next = face_patches[fn]; face_patches[fn] = patch; if ( texscale ) { // Compute the texture "scale" in s,t for( i=0; i<2; i++ ) { patch->scale[i] = 0.0; for( j=0; j<3; j++ ) patch->scale[i] += tx->vecs[i][j] * tx->vecs[i][j]; patch->scale[i] = sqrt( patch->scale[i] ); } } else patch->scale[0] = patch->scale[1] = 1.0; patch->area = area; patch->chop = maxchop / (int)((patch->scale[0]+patch->scale[1])/2); patch->sky = FALSE; patch->winding = w; if (f->side) patch->plane = &backplanes[f->planenum]; else patch->plane = &dplanes[f->planenum]; for (j=0 ; j<f->numedges ; j++) { int edge = dsurfedges[ f->firstedge + j ]; int edge2 = dsurfedges[ j==f->numedges-1 ? f->firstedge : f->firstedge + j + 1 ]; if (edge > 0) { VectorAdd( dvertexes[dedges[edge].v[0]].point, centroid, centroid ); VectorAdd( dvertexes[dedges[edge].v[1]].point, centroid, centroid ); } else { VectorAdd( dvertexes[dedges[-edge].v[1]].point, centroid, centroid ); VectorAdd( dvertexes[dedges[-edge].v[0]].point, centroid, centroid ); } } VectorScale( centroid, 1.0 / (f->numedges * 2), centroid ); VectorCopy( centroid, face_centroids[fn] ); // Save them for generating the patch normals later. patch->faceNumber = fn; WindingCenter (w, patch->origin); #ifdef PHONG_NORMAL_PATCHES // This seems to be a bad idea for some reason. Leave it turned off for now. VectorAdd (patch->origin, patch->plane->normal, patch->origin); GetPhongNormal( fn, patch->origin, patch->normal ); VectorSubtract (patch->origin, patch->plane->normal, patch->origin); if ( !VectorCompare( patch->plane->normal, patch->normal ) ) patch->chop = 16; // Chop it fine! #else VectorCopy( patch->plane->normal, patch->normal ); #endif VectorAdd (patch->origin, patch->normal, patch->origin); WindingBounds (w, patch->face_mins, patch->face_maxs); VectorCopy( patch->face_mins, patch->mins ); VectorCopy( patch->face_maxs, patch->maxs ); BaseLightForFace( f, light, patch->reflectivity ); VectorCopy( light, patch->totallight ); VectorCopy( light, patch->baselight ); // Chop all texlights very fine. if ( !VectorCompare( light, vec3_origin ) ) patch->chop = extra ? minchop / 2 : minchop; num_patches++; } }
void MakePatchForFace( int fn, winding_t *w ){ dface_t *f; float area; patch_t *patch; dplane_t *pl; int i; vec3_t color; dleaf_t *leaf; f = &dfaces[fn]; area = WindingArea( w ); totalarea += area; patch = &patches[num_patches]; if ( num_patches == MAX_PATCHES ) { Error( "num_patches == MAX_PATCHES" ); } patch->next = face_patches[fn]; face_patches[fn] = patch; patch->winding = w; if ( f->side ) { patch->plane = &backplanes[f->planenum]; } else{ patch->plane = &dplanes[f->planenum]; } if ( face_offset[fn][0] || face_offset[fn][1] || face_offset[fn][2] ) { // origin offset faces must create new planes if ( numplanes + fakeplanes >= MAX_MAP_PLANES ) { Error( "numplanes + fakeplanes >= MAX_MAP_PLANES" ); } pl = &dplanes[numplanes + fakeplanes]; fakeplanes++; *pl = *( patch->plane ); pl->dist += DotProduct( face_offset[fn], pl->normal ); patch->plane = pl; } WindingCenter( w, patch->origin ); VectorAdd( patch->origin, patch->plane->normal, patch->origin ); leaf = Rad_PointInLeaf( patch->origin ); patch->cluster = leaf->cluster; if ( patch->cluster == -1 ) { Sys_FPrintf( SYS_VRB, "patch->cluster == -1\n" ); } patch->area = area; if ( patch->area <= 1 ) { patch->area = 1; } patch->sky = IsSky( f ); VectorCopy( texture_reflectivity[f->texinfo], patch->reflectivity ); // non-bmodel patches can emit light if ( fn < dmodels[0].numfaces ) { BaseLightForFace( f, patch->baselight ); ColorNormalize( patch->reflectivity, color ); for ( i = 0 ; i < 3 ; i++ ) patch->baselight[i] *= color[i]; VectorCopy( patch->baselight, patch->totallight ); } num_patches++; }