Files
GTASource/game/debug/colorizer.cpp
expvintl 419f2e4752 init
2025-02-23 17:40:52 +08:00

463 lines
12 KiB
C++

/////////////////////////////////////////////////////////////////////////////////
// FILE : colorizer.cpp
// PURPOSE : To provide in game visual helpers for debugging.
/////////////////////////////////////////////////////////////////////////////////
#if __BANK
#include "colorizer.h"
#include "grcore/vertexbuffer.h"
#include "grmodel/geometry.h"
#include "rmcore/drawable.h"
#include "modelInfo/PedModelInfo.h"
#include "peds/ped.h"
#include "peds/rendering/PedVariationDebug.h"
#include "scene/entity.h"
// ================================================================================================
void ColorizerUtils::GetDrawablePolyCount(const rmcDrawable* pDrawable, u32* pResult, u32 lodLevel)
{
if (!pDrawable) { return; }
const rmcLodGroup& lodGroup = pDrawable->GetLodGroup();
if(lodGroup.ContainsLod(lodLevel))
{
const rmcLod& lod = lodGroup.GetLod(lodLevel);
for(s32 i=0;i<lod.GetCount();i++)
{
const grmModel* model = lod.GetModel(i);
if (model)
{
for(s32 j=0;j<model->GetGeometryCount();j++)
{
const grmGeometry& geo = model->GetGeometry(j);
*pResult += geo.GetPrimitiveCount();
}
}
}
}
}
void ColorizerUtils::GetDrawableInfo(const rmcDrawable* pDrawable, u32* pPolyCount, u32* pVertexCount, u32* pVertexSize, u32* pIndexCount, u32* pIndexSize, u32 lodLevel)
{
if (!pDrawable) { return; }
const rmcLodGroup& lodGroup = pDrawable->GetLodGroup();
if(lodGroup.ContainsLod(lodLevel))
{
const rmcLod& lod = lodGroup.GetLod(lodLevel);
for(s32 i=0;i<lod.GetCount();i++)
{
const grmModel* model = lod.GetModel(i);
if (model)
{
for(s32 j=0;j<model->GetGeometryCount();j++)
{
grmGeometry& geo = model->GetGeometry(j);
*pPolyCount += geo.GetPrimitiveCount();
if (geo.GetType() == grmGeometry::GEOMETRYEDGE)
{
#if USE_EDGE
grmGeometryEdge& edgeGeometry = static_cast<grmGeometryEdge&>(geo);
for (s32 g = 0; g < edgeGeometry.GetBlendHeaderCount(); ++g)
{
*pVertexCount += edgeGeometry.GetEdgeGeomPpuConfigInfos()[g].spuConfigInfo.numVertexes;
*pVertexSize += edgeGeometry.GetEdgeGeomPpuConfigInfos()[g].spuConfigInfo.numVertexes * sizeof(Vector4);
*pIndexCount += edgeGeometry.GetEdgeGeomPpuConfigInfos()[g].spuConfigInfo.numIndexes;
*pIndexSize += edgeGeometry.GetEdgeGeomPpuConfigInfos()[g].spuConfigInfo.numIndexes * sizeof(u16);
}
#endif // USE_EDGE...
}
else
{
*pVertexCount += geo.GetVertexCount();
grcVertexBuffer* vb = geo.GetVertexBuffer(true);
const grcFvf* fvf = vb->GetFvf();
Assert(fvf);
if (fvf->GetDataSizeType(grcFvf::grcfcPosition) == grcFvf::grcdsHalf4 || fvf->GetDataSizeType(grcFvf::grcfcPosition) == grcFvf::grcdsHalf3)
{
*pVertexSize += geo.GetVertexCount() * sizeof(u16);
}
else if (fvf->GetDataSizeType(grcFvf::grcfcPosition) == grcFvf::grcdsFloat4 || fvf->GetDataSizeType(grcFvf::grcfcPosition) == grcFvf::grcdsFloat3)
{
*pVertexSize += geo.GetVertexCount() * sizeof(float);
}
else
{
Assert(false);
}
grcIndexBuffer* ib = geo.GetIndexBuffer(true);
*pIndexCount += ib->GetIndexCount();
*pIndexSize += ib->GetIndexCount() * sizeof(u16);
}
}
}
}
}
}
void ColorizerUtils::GetPolyCountFrag(CEntity *pEntity, CBaseModelInfo *pModelInfo, u32* pResult, u32 lodLevel)
{
const fragType* pFragType = pModelInfo->GetFragType();
if (pFragType)
{
fragDrawable* pDrawable = pFragType->GetCommonDrawable();
const CDynamicEntity* pDynamicEntity = static_cast<const CDynamicEntity*>(pEntity);
fragInst* pFragInst = pDynamicEntity->GetFragInst();
Assert(pDrawable);
if (pFragType->GetSkinned() || !pFragInst)
{
GetDrawablePolyCount(pDrawable, pResult, lodLevel);
}
else
{
u64 damagedBits;
u64 destroyedBits;
PopulateBitFields(pFragInst, damagedBits, destroyedBits);
//in this case, we have a list of entities to draw...
for (u64 child=0; child<pFragInst->GetTypePhysics()->GetNumChildren(); ++child)
{
fragTypeChild* pChildType = pFragInst->GetTypePhysics()->GetAllChildren()[child];
pDrawable = NULL;
if ((destroyedBits & ((u64)1<<child)) == 0) {
if ((damagedBits & ((u64)1<<child)) != 0)
{
//broken...
pDrawable = pChildType->GetDamagedEntity() ? pChildType->GetDamagedEntity() : pChildType->GetUndamagedEntity();
}
else
{
//not broken...
pDrawable = pChildType->GetUndamagedEntity();
}
}
GetDrawablePolyCount(pDrawable, pResult, lodLevel);
}
}
}
else
{
GetDrawablePolyCount(pEntity->GetDrawable(), pResult, lodLevel);
}
}
void ColorizerUtils::GetFragInfo(CEntity *pEntity, CBaseModelInfo *pModelInfo, u32* pPolyCount, u32* pVertexCount, u32* pVertexSize, u32* pIndexCount, u32* pIndexSize, u32 lodLevel)
{
const fragType* pFragType = NULL;
if (pEntity->GetIsTypeVehicle())
{
CVehicleModelInfo* pVMI = static_cast<CVehicleModelInfo*>(pModelInfo);
if (pVMI->GetAreHDFilesLoaded())
{
pFragType = pVMI->GetHDFragType();
}
}
if (!pFragType)
pFragType = pModelInfo->GetFragType();
if (pFragType)
{
fragDrawable* pDrawable = pFragType->GetCommonDrawable();
const CDynamicEntity* pDynamicEntity = static_cast<const CDynamicEntity*>(pEntity);
fragInst* pFragInst = pDynamicEntity->GetFragInst();
Assert(pDrawable);
if (pFragType->GetSkinned() || !pFragInst)
{
GetDrawableInfo(pDrawable, pPolyCount, pVertexCount, pVertexSize, pIndexCount, pIndexSize, lodLevel);
}
else
{
u64 damagedBits;
u64 destroyedBits;
PopulateBitFields(pFragInst, damagedBits, destroyedBits);
//in this case, we have a list of entities to draw...
for (u64 child=0; child<pFragInst->GetTypePhysics()->GetNumChildren(); ++child)
{
fragTypeChild* pChildType = pFragInst->GetTypePhysics()->GetAllChildren()[child];
pDrawable = NULL;
if ((destroyedBits & ((u64)1<<child)) == 0) {
if ((damagedBits & ((u64)1<<child)) != 0)
{
//broken...
pDrawable = pChildType->GetDamagedEntity() ? pChildType->GetDamagedEntity() : pChildType->GetUndamagedEntity();
}
else
{
//not broken...
pDrawable = pChildType->GetUndamagedEntity();
}
}
GetDrawableInfo(pDrawable, pPolyCount, pVertexCount, pVertexSize, pIndexCount, pIndexSize, lodLevel);
}
}
}
else
{
GetDrawableInfo(pEntity->GetDrawable(), pPolyCount, pVertexCount, pVertexSize, pIndexCount, pIndexSize, lodLevel);
}
}
u32 ColorizerUtils::GetPolyCount(CEntity* pEntity)
{
u32 polyCount = 0;
if (pEntity)
{
CBaseModelInfo* pModelInfo = pEntity->GetBaseModelInfo();
if(pEntity->GetIsTypePed())
{
const CPedModelInfo* pPedModelInfo = static_cast<const CPedModelInfo*>(pModelInfo);
const CPed* pPed = static_cast<const CPed*>(pEntity);
if (pPedModelInfo->GetIsStreamedGfx())
{
const CPedStreamRenderGfx* pGfxData = pPed->GetPedDrawHandler().GetConstPedRenderGfx();
if (pGfxData)
{
CPedVariationDebug::GetPolyCountPlayerInternal(pGfxData, &polyCount);
}
}
else
{
CPedVariationDebug::GetPolyCountPedInternal(pPedModelInfo, pPed->GetPedDrawHandler().GetVarData(), &polyCount);
}
}
else
{
if(pModelInfo->GetFragType())
{
GetPolyCountFrag(pEntity, pModelInfo, &polyCount);
}
else
{
rmcDrawable* pDrawable = pModelInfo->GetDrawable();
if(pDrawable)
{
GetDrawablePolyCount(pDrawable, &polyCount);
}
}
}
}
return polyCount;
}
u32 ColorizerUtils::GetBoneCount(CEntity* pEntity)
{
u32 polyCount = 0;
if (pEntity)
{
CBaseModelInfo* pModelInfo = pEntity->GetBaseModelInfo();
rmcDrawable* pDrawable = pModelInfo->GetDrawable();
if(pDrawable)
{
if(pDrawable->GetSkeletonData())
{
return pDrawable->GetSkeletonData()->GetNumBones();
}
}
}
return polyCount;
}
u32 ColorizerUtils::GetShaderCount(CEntity* pEntity)
{
u32 shaderCount = 0;
if (pEntity)
{
rmcDrawable* pDrawable = pEntity->GetDrawable();
if (pDrawable)
{
shaderCount = (u32) pDrawable->GetShaderGroup().GetCount();
}
}
return shaderCount;
}
void ColorizerUtils::GetVVRData(const rmcDrawable *drawable, float &vtxCount, float &volume)
{
const rmcLodGroup &lodGroup= drawable->GetLodGroup();
if( lodGroup.ContainsLod(LOD_HIGH) )
{
const rmcLod& lod = lodGroup.GetLod(LOD_HIGH);
for(int i=0;i<lod.GetCount();i++)
{
const grmModel* model = lod.GetModel(i);
if (model)
{
for(int j=0;j<model->GetGeometryCount();j++)
{
const grmGeometry& geo = model->GetGeometry(j);
vtxCount += (float)geo.GetVertexCount();
}
}
}
Vector3 boxMin,boxMax;
lodGroup.GetBoundingBox(boxMin,boxMax);
Vector3 lengths = boxMax - boxMin;
if( lengths.x == 0.0f || lengths.y == 0.0f || lengths.z == 0.0f )
{ // Flat volume ? let's take an area, then...
lengths.x = lengths.x == 0.0f ? 1.0f : lengths.x;
lengths.y = lengths.y == 0.0f ? 1.0f : lengths.y;
lengths.z = lengths.z == 0.0f ? 1.0f : lengths.z;
}
volume += lengths.x * lengths.y * lengths.z;
}
}
void ColorizerUtils::FragGetVVRData(const CEntity *entity, const CBaseModelInfo *modelinfo, float &vtxCount, float &volume)
{
const fragType* type = modelinfo->GetFragType();
if (type)
{
fragDrawable* toDraw = type->GetCommonDrawable();
const CDynamicEntity* pDynamicEntity = static_cast<const CDynamicEntity*>(entity);
fragInst* pFragInst = pDynamicEntity->GetFragInst();
Assert(toDraw != NULL);
if (type->GetSkinned() || pFragInst == NULL )
{
GetVVRData(toDraw, vtxCount, volume);
}
else
{
u64 damagedBits;
u64 destroyedBits;
PopulateBitFields(pFragInst, damagedBits, destroyedBits);
//in this case, we have a list of entities to draw...
for (u64 child = 0; child < pFragInst->GetTypePhysics()->GetNumChildren(); ++child)
{
fragTypeChild* childType = pFragInst->GetTypePhysics()->GetAllChildren()[child];
toDraw = NULL;
if ((destroyedBits & ((u64)1<<child)) == 0) {
if ((damagedBits & ((u64)1<<child)) != 0)
{
//broken...
toDraw = childType->GetDamagedEntity() ?
childType->GetDamagedEntity() :
childType->GetUndamagedEntity();
}
else
{
//not broken...
toDraw = childType->GetUndamagedEntity();
}
}
GetVVRData(toDraw, vtxCount, volume);
}
}
}
else
{
GetVVRData(entity->GetDrawable(), vtxCount, volume);
}
}
#if __PPU
bool ColorizerUtils::GetEdgeUseage(const rmcDrawable *drawable)
{
bool result = false;
const rmcLodGroup &lodGroup= drawable->GetLodGroup();
if( lodGroup.ContainsLod(LOD_HIGH) )
{
const rmcLod& lod = lodGroup.GetLod(LOD_HIGH);
for(int i=0;i<lod.GetCount();i++)
{
const grmModel* model = lod.GetModel(i);
if (model)
{
for(int j=0;j<model->GetGeometryCount();j++)
{
grmGeometry& geo = model->GetGeometry(j);
result |= geo.GetType() == grmGeometry::GEOMETRYEDGE;
}
}
}
}
return result;
}
bool ColorizerUtils::FragGetEdgeUseage(const CEntity *entity, const CBaseModelInfo *modelinfo)
{
const fragType* type = modelinfo->GetFragType();
if (type)
{
fragDrawable* toDraw = type->GetCommonDrawable();
const CDynamicEntity* pDynamicEntity = static_cast<const CDynamicEntity*>(entity);
fragInst* pFragInst = pDynamicEntity->GetFragInst();
Assert(toDraw != NULL);
if (type->GetSkinned() || pFragInst == NULL )
{
return GetEdgeUseage(toDraw);
}
else
{
// If its a non-skinned frag use first child to decide whether to use Edge
u64 damagedBits;
u64 destroyedBits;
PopulateBitFields(pFragInst, damagedBits, destroyedBits);
//in this case, we have a list of entities to draw...
Assertf(pFragInst->GetTypePhysics()->GetNumChildren() > 0,"This frag has no children"); // Whats the point of this entity?
fragTypeChild* childType = pFragInst->GetTypePhysics()->GetAllChildren()[0];
toDraw = NULL;
if ((destroyedBits & ((u64)BIT(0))) == 0) {
if ((damagedBits & ((u64)BIT(0))) != 0)
{
//broken...
toDraw = childType->GetDamagedEntity() ?
childType->GetDamagedEntity() :
childType->GetUndamagedEntity();
}
else
{
//not broken...
toDraw = childType->GetUndamagedEntity();
}
}
return GetEdgeUseage(toDraw);
}
}
else
{
return GetEdgeUseage(entity->GetDrawable());
}
}
#endif // __PPU
#endif // __BANK