//----------------------------------------------------------------------------- // Purpose: Finds or adds a texdata for the specified name // Input : *pName - texture name // Output : int index into dtexdata array //----------------------------------------------------------------------------- int FindTexData( const char *pName_ ) { char *pName = ( char * )_alloca( strlen( pName_ ) + 1 ); strcpy( pName, pName_ ); int i, output; bool found; dtexdata_t *pTexData; MaterialSystemMaterial_t matID; for ( i = 0; i < numtexdata; i++ ) { char const *tableName = TexDataStringTable_GetString( GetTexData( i )->nameStringTableID ); if ( !strcmp( pName, tableName ) ) { return i; } } output = numtexdata; if ( numtexdata >= MAX_MAP_TEXDATA ) { Error( "MAX_MAP_TEXDATA" ); } pTexData = GetTexData( output ); numtexdata++; // Save the name of the material. pTexData->nameStringTableID = TexDataStringTable_AddOrFindString( pName ); // Get the width, height, view_width, view_height, and reflectivity from the material system. matID = FindOriginalMaterial( pName, &found ); if( matID == MATERIAL_NOT_FOUND || (!found) ) { qprintf( "WARNING: material not found: \"%s\"\n", pName ); return -1; } GetMaterialDimensions( matID, &pTexData->width, &pTexData->height ); pTexData->view_width = pTexData->width; // undone: what is this? pTexData->view_height = pTexData->height; // undone: what is this? GetMaterialReflectivity( matID, pTexData->reflectivity.Base() ); g_SurfaceProperties[output] = GetSurfaceProperties( matID, pName ); #if 0 Msg( "reflectivity: %f %f %f\n", pTexData->reflectivity[0], pTexData->reflectivity[1], pTexData->reflectivity[2] ); #endif return output; }
int AddCloneTexData( dtexdata_t *pExistingTexData, char const *cloneTexDataName ) { int existingIndex = pExistingTexData - GetTexData( 0 ); dtexdata_t *pNewTexData = GetTexData( numtexdata ); int newIndex = numtexdata; numtexdata++; *pNewTexData = *pExistingTexData; pNewTexData->nameStringTableID = TexDataStringTable_AddOrFindString( cloneTexDataName ); g_SurfaceProperties[newIndex] = g_SurfaceProperties[existingIndex]; return newIndex; }
//----------------------------------------------------------------------------- // Purpose: Takes the texinfo_t referenced by the .vmt and the computed depth for the // surface and looks up or creates a texdata/texinfo for the mangled one-off water .vmt file // Input : *pBaseInfo - // depth - // Output : int //----------------------------------------------------------------------------- int FindOrCreateWaterTexInfo( texinfo_t *pBaseInfo, float depth ) { char fullname[ 512 ]; char materialname[ 512 ]; // Get the base texture/material name char const *name = TexDataStringTable_GetString( GetTexData( pBaseInfo->texdata )->nameStringTableID ); GetWaterTextureName( mapbase, name, (int)depth, fullname ); // See if we already have an entry for this depth WaterTexInfo lookup; lookup.m_FullName = fullname; int idx = g_WaterTexInfos.Find( lookup ); // If so, return the existing entry texinfo index if ( idx != g_WaterTexInfos.InvalidIndex() ) { return g_WaterTexInfos[ idx ].m_nTexInfo; } // Otherwise, fill in the rest of the data lookup.m_nWaterDepth = (int)depth; // Remember the current material name sprintf( materialname, "%s", name ); strlwr( materialname ); lookup.m_MaterialName = materialname; texinfo_t ti; // Make a copy ti = *pBaseInfo; // Create a texdata that is based on the underlying existing entry ti.texdata = FindAliasedTexData( fullname, GetTexData( pBaseInfo->texdata ) ); // Find or create a new index lookup.m_nTexInfo = FindOrCreateTexInfo( ti ); // Add the new texinfo to the RB tree idx = g_WaterTexInfos.Insert( lookup ); // Msg( "created texinfo for %s\n", lookup.m_FullName.String() ); // Go ahead and create the new vmt file. EmitWaterMaterialFile( &g_WaterTexInfos[idx] ); // Return the new texinfo return g_WaterTexInfos[ idx ].m_nTexInfo; }
MaterialSystemMaterial_t GetMatIDFromDisp( mapdispinfo_t *pMapDisp ) { texinfo_t *pTexInfo = &texinfo[pMapDisp->face.texinfo]; dtexdata_t *pTexData = GetTexData( pTexInfo->texdata ); MaterialSystemMaterial_t matID = FindOriginalMaterial( TexDataStringTable_GetString( pTexData->nameStringTableID ), NULL, true ); return matID; }
//----------------------------------------------------------------------------- // Purpose: Finds or adds a texdata for the specified name ( same as below except // instead of finding the named texture, copies the settings from the passed // in sourceTexture. ) // Used for creation of one off .vmt files for water surface textures // Input : *pName - texture name // Output : int index into dtexdata array //----------------------------------------------------------------------------- int FindAliasedTexData( const char *pName_, dtexdata_t *sourceTexture ) { char *pName = ( char * )_alloca( strlen( pName_ ) + 1 ); strcpy( pName, pName_ ); strlwr( pName ); int i, output; bool found; dtexdata_t *pTexData; MaterialSystemMaterial_t matID; for ( i = 0; i < numtexdata; i++ ) { if ( !strcmp( pName, TexDataStringTable_GetString( GetTexData( i )->nameStringTableID ) ) ) return i; } output = numtexdata; if ( numtexdata >= MAX_MAP_TEXDATA ) { Error( "Too many unique texture mappings, max = %d\n", MAX_MAP_TEXDATA ); } pTexData = GetTexData( output ); numtexdata++; // Save the name of the material. pTexData->nameStringTableID = TexDataStringTable_AddOrFindString( pName ); // Get the width, height, view_width, view_height, and reflectivity from the material system. matID = FindOriginalMaterial( TexDataStringTable_GetString( sourceTexture->nameStringTableID ), &found, false ); if( matID == MATERIAL_NOT_FOUND || (!found) ) { qprintf( "WARNING: material not found: \"%s\"\n", pName ); return -1; } GetMaterialDimensions( matID, &pTexData->width, &pTexData->height ); pTexData->view_width = pTexData->width; // undone: what is this? pTexData->view_height = pTexData->height; // undone: what is this? GetMaterialReflectivity( matID, pTexData->reflectivity.Base() ); g_SurfaceProperties[output] = GetSurfaceProperties( matID, pName ); return output; }
const char *GetShaderNameForTexInfo( int iTexInfo ) { texinfo_t *pTexInfo = &texinfo[iTexInfo]; dtexdata_t *pTexData = GetTexData( pTexInfo->texdata ); const char *pMaterialName = TexDataStringTable_GetString( pTexData->nameStringTableID ); MaterialSystemMaterial_t hMaterial = FindMaterial( pMaterialName, NULL, false ); const char *pShaderName = GetMaterialShaderName( hMaterial ); return pShaderName; }
//----------------------------------------------------------------------------- // Builds a list of all texdatas which need fixing up //----------------------------------------------------------------------------- void Cubemap_InitCubemapSideData( void ) { // This tree is used to prevent re-parsing material vars multiple times CUtlRBTree<CubemapInfo_t> lookup( 0, nummapbrushsides, CubemapLessFunc ); // Fill in specular data. for ( int iSide = 0; iSide < nummapbrushsides; ++iSide ) { side_t *pSide = &brushsides[iSide]; if ( !pSide ) continue; if ( pSide->texinfo == TEXINFO_NODE ) continue; texinfo_t *pTex = &texinfo[pSide->texinfo]; if ( !pTex ) continue; dtexdata_t *pTexData = GetTexData( pTex->texdata ); if ( !pTexData ) continue; CubemapInfo_t info; info.m_nTableId = pTexData->nameStringTableID; // Have we encountered this materal? If so, then copy the data we cached off before int i = lookup.Find( info ); if ( i != lookup.InvalidIndex() ) { s_aCubemapSideData[iSide].bHasEnvMapInMaterial = lookup[i].m_bSpecular; continue; } // First time we've seen this material. Figure out if it uses env_cubemap const char *pPatchedMaterialName = TexDataStringTable_GetString( pTexData->nameStringTableID ); info.m_bSpecular = DoesMaterialOrDependentsUseEnvmap( pPatchedMaterialName ); s_aCubemapSideData[ iSide ].bHasEnvMapInMaterial = info.m_bSpecular; lookup.Insert( info ); } // Fill in cube map data. for ( int iCubemap = 0; iCubemap < g_nCubemapSamples; ++iCubemap ) { IntVector_t &sideList = s_EnvCubemapToBrushSides[iCubemap]; int nSideCount = sideList.Count(); for ( int iSide = 0; iSide < nSideCount; ++iSide ) { int nSideID = sideList[iSide]; int nIndex = SideIDToIndex( nSideID ); if ( nIndex < 0 ) continue; s_aCubemapSideData[nIndex].bManuallyPickedByAnEnvCubemap = true; } } }
int CreateBrushVersionOfWorldVertexTransitionMaterial( int originalTexInfo ) { // Don't make cubemap tex infos for nodes if ( originalTexInfo == TEXINFO_NODE ) return originalTexInfo; texinfo_t *pTexInfo = &texinfo[originalTexInfo]; dtexdata_t *pTexData = GetTexData( pTexInfo->texdata ); const char *pOriginalMaterialName = TexDataStringTable_GetString( pTexData->nameStringTableID ); // Get out of here if the originalTexInfo is already a patched wvt material if ( Q_stristr( pOriginalMaterialName, "_wvt_patch" ) ) return originalTexInfo; char patchedMaterialName[1024]; GeneratePatchedMaterialName( pOriginalMaterialName, patchedMaterialName, 1024 ); // Warning( "GeneratePatchedMaterialName: %s %s\n", pMaterialName, patchedMaterialName ); // Make sure the texdata doesn't already exist. int nTexDataID = FindTexData( patchedMaterialName ); bool bHasTexData = (nTexDataID != -1); if( !bHasTexData ) { // Create the new vmt material file CreateWorldVertexTransitionPatchedMaterial( pOriginalMaterialName, patchedMaterialName ); // Make a new texdata nTexDataID = AddCloneTexData( pTexData, patchedMaterialName ); } Assert( nTexDataID != -1 ); texinfo_t newTexInfo; newTexInfo = *pTexInfo; newTexInfo.texdata = nTexDataID; int nTexInfoID = -1; // See if we need to make a new texinfo bool bHasTexInfo = false; if( bHasTexData ) { nTexInfoID = FindTexInfo( newTexInfo ); bHasTexInfo = (nTexInfoID != -1); } // Make a new texinfo if we need to. if( !bHasTexInfo ) { nTexInfoID = texinfo.AddToTail( newTexInfo ); } Assert( nTexInfoID != -1 ); return nTexInfoID; }
//----------------------------------------------------------------------------- // Finds a texdata for the specified name, returns -1 if not found //----------------------------------------------------------------------------- int FindTexData( const char *pName ) { // Make sure the texdata doesn't already exist. for( int i = 0; i < numtexdata; i++ ) { char const *pTexDataName = TexDataStringTable_GetString( GetTexData( i )->nameStringTableID ); if ( !Q_stricmp( pTexDataName, pName ) ) return i; } return -1; }
//----------------------------------------------------------------------------- // Purpose: Finds or adds a texdata for the specified name // Input : *pName - texture name // Output : int index into dtexdata array //----------------------------------------------------------------------------- int FindOrCreateTexData( const char *pName_ ) { char *pName = ( char * )_alloca( strlen( pName_ ) + 1 ); strcpy( pName, pName_ ); int nOutput = FindTexData( pName ); if ( nOutput >= 0 ) return nOutput; // Didn't find it, add a new one nOutput = numtexdata; if ( numtexdata >= MAX_MAP_TEXDATA ) { Error( "Too many unique texture mappings, max = %d\n", MAX_MAP_TEXDATA ); } dtexdata_t *pTexData = GetTexData( nOutput ); numtexdata++; // Save the name of the material. pTexData->nameStringTableID = TexDataStringTable_AddOrFindString( pName ); // Get the width, height, view_width, view_height, and reflectivity from the material system. bool bFound; MaterialSystemMaterial_t matID = FindOriginalMaterial( pName, &bFound ); if ( matID == MATERIAL_NOT_FOUND || (!bFound) ) { qprintf( "WARNING: material not found: \"%s\"\n", pName ); return nOutput; } GetMaterialDimensions( matID, &pTexData->width, &pTexData->height ); pTexData->view_width = pTexData->width; // undone: what is this? pTexData->view_height = pTexData->height; // undone: what is this? GetMaterialReflectivity( matID, pTexData->reflectivity.Base() ); g_SurfaceProperties[nOutput] = GetSurfaceProperties( matID, pName ); #if 0 Msg( "reflectivity: %f %f %f\n", pTexData->reflectivity[0], pTexData->reflectivity[1], pTexData->reflectivity[2] ); #endif return nOutput; }
/* ================== MakeTreePortals_r ================== */ void MakeTreePortals_r (node_t *node) { int i; CalcNodeBounds (node); if (node->mins[0] >= node->maxs[0]) { Warning("WARNING: node without a volume\n"); } for (i=0 ; i<3 ; i++) { if (node->mins[i] < (MIN_COORD_INTEGER-SIDESPACE) || node->maxs[i] > (MAX_COORD_INTEGER+SIDESPACE)) { const char *pMatName = "<NO BRUSH>"; // split by brush side if ( node->side ) { texinfo_t *pTexInfo = &texinfo[node->side->texinfo]; dtexdata_t *pTexData = GetTexData( pTexInfo->texdata ); pMatName = TexDataStringTable_GetString( pTexData->nameStringTableID ); } Vector point = node->portals->winding->p[0]; Warning("WARNING: BSP node with unbounded volume (material: %s, near %s)\n", pMatName, VecToString(point) ); break; } } if (node->planenum == PLANENUM_LEAF) return; MakeNodePortal (node); SplitNodePortals (node); MakeTreePortals_r (node->children[0]); MakeTreePortals_r (node->children[1]); }
//----------------------------------------------------------------------------- // Create a VMT to override the specified texinfo which references the cubemap entity at the specified origin. // Returns the index of the new (or preexisting) texinfo referencing that VMT. // // Also adds the new cubemap VTF filename to s_DefaultCubemapNames so it can copy the // default (skybox) cubemap into this file so the cubemap doesn't have the pink checkerboard at // runtime before they run buildcubemaps. //----------------------------------------------------------------------------- static int Cubemap_CreateTexInfo( int originalTexInfo, int origin[3] ) { // Don't make cubemap tex infos for nodes if ( originalTexInfo == TEXINFO_NODE ) return originalTexInfo; texinfo_t *pTexInfo = &texinfo[originalTexInfo]; dtexdata_t *pTexData = GetTexData( pTexInfo->texdata ); const char *pMaterialName = TexDataStringTable_GetString( pTexData->nameStringTableID ); if ( g_IsCubemapTexData[pTexInfo->texdata] ) { Warning("Multiple references for cubemap on texture %s!!!\n", pMaterialName ); return originalTexInfo; } // Get out of here if the originalTexInfo is already a generated material for this position. char pStringToSearchFor[512]; Q_snprintf( pStringToSearchFor, 512, "_%d_%d_%d", origin[0], origin[1], origin[2] ); if ( Q_stristr( pMaterialName, pStringToSearchFor ) ) return originalTexInfo; // Package up information needed to generate patch names PatchInfo_t info; info.m_pMapName = mapbase; info.m_pOrigin[0] = origin[0]; info.m_pOrigin[1] = origin[1]; info.m_pOrigin[2] = origin[2]; // Generate the name of the patched material char pGeneratedTexDataName[1024]; GeneratePatchedName( pMaterialName, info, true, pGeneratedTexDataName, 1024 ); // Make sure the texdata doesn't already exist. int nTexDataID = FindTexData( pGeneratedTexDataName ); bool bHasTexData = (nTexDataID != -1); if( !bHasTexData ) { // Generate the new "$envmap" texture name. char pTextureName[1024]; GeneratePatchedName( "c", info, false, pTextureName, 1024 ); // Hook the texture into the material and all dependent materials // but if no hooking was necessary, exit out if ( !PatchEnvmapForMaterialAndDependents( pMaterialName, info, pTextureName ) ) return originalTexInfo; // Store off the name of the cubemap that we need to create since we successfully patched char pFileName[1024]; int nLen = Q_snprintf( pFileName, 1024, "materials/%s.vtf", pTextureName ); int id = s_DefaultCubemapNames.AddToTail(); s_DefaultCubemapNames[id] = new char[ nLen + 1 ]; strcpy( s_DefaultCubemapNames[id], pFileName ); // Make a new texdata nTexDataID = AddCloneTexData( pTexData, pGeneratedTexDataName ); g_IsCubemapTexData[nTexDataID] = true; } Assert( nTexDataID != -1 ); texinfo_t newTexInfo; newTexInfo = *pTexInfo; newTexInfo.texdata = nTexDataID; int nTexInfoID = -1; // See if we need to make a new texinfo bool bHasTexInfo = false; if( bHasTexData ) { nTexInfoID = FindTexInfo( newTexInfo ); bHasTexInfo = (nTexInfoID != -1); } // Make a new texinfo if we need to. if( !bHasTexInfo ) { nTexInfoID = texinfo.AddToTail( newTexInfo ); } Assert( nTexInfoID != -1 ); return nTexInfoID; }
//----------------------------------------------------------------------------- // Places Detail Objects in the level //----------------------------------------------------------------------------- void EmitDetailModels() { StartPacifier("Placing detail props : "); // Place stuff on each face dface_t* pFace = dfaces; for (int j = 0; j < numfaces; ++j) { UpdatePacifier( (float)j / (float)numfaces ); // Get at the material associated with this face texinfo_t* pTexInfo = &texinfo[pFace[j].texinfo]; dtexdata_t* pTexData = GetTexData( pTexInfo->texdata ); // Try to get at the material bool found; MaterialSystemMaterial_t handle = FindOriginalMaterial( TexDataStringTable_GetString( pTexData->nameStringTableID ), &found, false ); if (!found) continue; // See if its got any detail objects on it const char* pDetailType = GetMaterialVar( handle, "%detailtype" ); if (!pDetailType) continue; // Get the detail type... DetailObject_t search; search.m_Name = pDetailType; int objectType = s_DetailObjectDict.Find(search); if (objectType < 0) { Warning("Material %s uses unknown detail object type %s!\n", TexDataStringTable_GetString( pTexData->nameStringTableID ), pDetailType); continue; } // Emit objects on a particular face DetailObject_t& detail = s_DetailObjectDict[objectType]; if (pFace[j].dispinfo < 0) { EmitDetailObjectsOnFace( &pFace[j], detail ); } else { // Get a CCoreDispInfo. All we need is the triangles and lightmap texture coordinates. mapdispinfo_t *pMapDisp = &mapdispinfo[pFace[j].dispinfo]; CCoreDispInfo coreDispInfo; DispMapToCoreDispInfo( pMapDisp, &coreDispInfo, &pFace[j] ); EmitDetailObjectsOnDisplacementFace( &pFace[j], detail, coreDispInfo ); } } // Emit specifically specified detail props Vector origin; QAngle angles; Vector2D pos[2]; Vector2D tex[2]; for (int i = 0; i < num_entities; ++i) { char* pEntity = ValueForKey(&entities[i], "classname"); if (!strcmp(pEntity, "detail_prop") || !strcmp(pEntity, "prop_detail")) { GetVectorForKey( &entities[i], "origin", origin ); GetAnglesForKey( &entities[i], "angles", angles ); char* pModelName = ValueForKey( &entities[i], "model" ); int nOrientation = IntForKey( &entities[i], "detailOrientation" ); AddDetailToLump( pModelName, origin, angles, nOrientation ); // strip this ent from the .bsp file entities[i].epairs = 0; continue; } if (!strcmp(pEntity, "prop_detail_sprite")) { GetVectorForKey( &entities[i], "origin", origin ); GetAnglesForKey( &entities[i], "angles", angles ); int nOrientation = IntForKey( &entities[i], "detailOrientation" ); GetVector2DForKey( &entities[i], "position_ul", pos[0] ); GetVector2DForKey( &entities[i], "position_lr", pos[1] ); GetVector2DForKey( &entities[i], "tex_ul", tex[0] ); GetVector2DForKey( &entities[i], "tex_size", tex[1] ); float flTextureSize = FloatForKey( &entities[i], "tex_total_size" ); tex[1].x += tex[0].x - 0.5f; tex[1].y += tex[0].y - 0.5f; tex[0].x += 0.5f; tex[0].y += 0.5f; tex[0] /= flTextureSize; tex[1] /= flTextureSize; AddDetailSpriteToLump( origin, angles, nOrientation, pos, tex, 1.0f ); // strip this ent from the .bsp file entities[i].epairs = 0; continue; } } EndPacifier( true ); }
void Disp_BuildVirtualMesh( int contentsMask ) { CUtlVector<CPhysCollide *> virtualMeshes; virtualMeshes.EnsureCount( g_CoreDispInfos.Count() ); for ( int i = 0; i < g_CoreDispInfos.Count(); i++ ) { CCoreDispInfo *pDispInfo = g_CoreDispInfos[ i ]; mapdispinfo_t *pMapDisp = &mapdispinfo[ i ]; virtualMeshes[i] = NULL; // not solid for this pass if ( !(pMapDisp->contents & contentsMask) ) continue; // Build a triangle list. This shares the tesselation code with the engine. CUtlVector<unsigned short> indices; CVBSPTesselateHelper helper; helper.m_pIndices = &indices; helper.m_pActiveVerts = pDispInfo->GetAllowedVerts().Base(); helper.m_pPowerInfo = pDispInfo->GetPowerInfo(); ::TesselateDisplacement( &helper ); // validate the collision data if ( 1 ) { int triCount = indices.Count() / 3; for ( int j = 0; j < triCount; j++ ) { int index = j * 3; Vector v0 = pDispInfo->GetVert( indices[index+0] ); Vector v1 = pDispInfo->GetVert( indices[index+1] ); Vector v2 = pDispInfo->GetVert( indices[index+2] ); if ( v0 == v1 || v1 == v2 || v2 == v0 ) { Warning( "Displacement %d has bad geometry near %.2f %.2f %.2f\n", i, v0.x, v0.y, v0.z ); texinfo_t *pTexInfo = &texinfo[pMapDisp->face.texinfo]; dtexdata_t *pTexData = GetTexData( pTexInfo->texdata ); const char *pMatName = TexDataStringTable_GetString( pTexData->nameStringTableID ); Error( "Can't compile displacement physics, exiting. Texture is %s\n", pMatName ); } } } CDispMeshEvent meshHandler( indices.Base(), indices.Count(), pDispInfo ); virtualmeshparams_t params; params.buildOuterHull = true; params.pMeshEventHandler = &meshHandler; params.userData = &meshHandler; virtualMeshes[i] = physcollision->CreateVirtualMesh( params ); } unsigned int totalSize = 0; CUtlBuffer buf; dphysdisp_t header; header.numDisplacements = g_CoreDispInfos.Count(); buf.PutObjects( &header ); CUtlVector<char> dispBuf; for ( int i = 0; i < header.numDisplacements; i++ ) { if ( virtualMeshes[i] ) { unsigned int testSize = physcollision->CollideSize( virtualMeshes[i] ); totalSize += testSize; buf.PutShort( testSize ); } else { buf.PutShort( -1 ); } } for ( int i = 0; i < header.numDisplacements; i++ ) { if ( virtualMeshes[i] ) { unsigned int testSize = physcollision->CollideSize( virtualMeshes[i] ); dispBuf.RemoveAll(); dispBuf.EnsureCount(testSize); unsigned int outSize = physcollision->CollideWrite( dispBuf.Base(), virtualMeshes[i], false ); Assert( outSize == testSize ); buf.Put( dispBuf.Base(), outSize ); } } g_PhysDispSize = totalSize + sizeof(dphysdisp_t) + (sizeof(unsigned short) * header.numDisplacements); Assert( buf.TellMaxPut() == g_PhysDispSize ); g_PhysDispSize = buf.TellMaxPut(); g_pPhysDisp = new byte[g_PhysDispSize]; Q_memcpy( g_pPhysDisp, buf.Base(), g_PhysDispSize ); }