static void AddDetailSpriteToLump( const Vector &vecOrigin, const QAngle &vecAngles, DetailModel_t const& model, float flScale ) { AddDetailSpriteToLump( vecOrigin, vecAngles, model.m_Orientation, model.m_Pos, model.m_Tex, flScale, model.m_Type, model.m_ShapeAngle, model.m_ShapeSize, model.m_SwayAmount ); }
//----------------------------------------------------------------------------- // 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 ); }
static void PlaceDetail( DetailModel_t const& model, const Vector& pt, const Vector& normal ) { // But only place it on the surface if it meets the angle constraints... float cosAngle = normal.z; // Never emit if the angle's too steep if (cosAngle < model.m_MaxCosAngle) return; // If it's between min + max, flip a coin... if (cosAngle < model.m_MinCosAngle) { float probability = (cosAngle - model.m_MaxCosAngle) / (model.m_MinCosAngle - model.m_MaxCosAngle); float t = rand() / (float)RAND_MAX; if (t > probability) return; } // Compute the orientation of the detail QAngle angles; if (model.m_Flags & MODELFLAG_UPRIGHT) { // If it's upright, we just select a random yaw angles.Init( 0, 360.0f * rand() / (float)RAND_MAX, 0.0f ); } else { // It's not upright, so it must conform to the ground. Choose // a random orientation based on the surface normal Vector zaxis; VectorCopy( normal, zaxis ); // Choose any two arbitrary axes which are perpendicular to the normal Vector xaxis( 1, 0, 0 ); if (fabs(xaxis.Dot(zaxis)) - 1.0 > -1e-3) xaxis.Init( 0, 1, 0 ); Vector yaxis; CrossProduct( zaxis, xaxis, yaxis ); CrossProduct( yaxis, zaxis, xaxis ); VMatrix matrix; matrix.SetBasisVectors( xaxis, yaxis, zaxis ); float rotAngle = 360.0f * rand() / (float)RAND_MAX; VMatrix rot = SetupMatrixAxisRot( Vector( 0, 0, 1 ), rotAngle ); matrix = matrix * rot; MatrixToAngles( matrix, angles ); } // FIXME: We may also want a purely random rotation too // Insert an element into the object dictionary if it aint there... switch ( model.m_Type ) { case DETAIL_PROP_TYPE_MODEL: AddDetailToLump( model.m_ModelName.String(), pt, angles, model.m_Orientation ); break; case DETAIL_PROP_TYPE_SPRITE: { float flScale = 1.0f; if ( model.m_flRandomScaleStdDev != 0.0f ) { flScale = fabs( RandomGaussianFloat( 1.0f, model.m_flRandomScaleStdDev ) ); } AddDetailSpriteToLump( pt, angles, model.m_Orientation, model.m_Pos, model.m_Tex, flScale ); } break; } }