From f28efbaa87a31685401611db11ae72cc68b4dad3 Mon Sep 17 00:00:00 2001 From: vladislavbelov Date: Mon, 13 Dec 2021 19:22:27 +0000 Subject: [PATCH] Forbids using more than 64 bones for GPU skinning. Commented By: Stan Differential Revision: https://code.wildfiregames.com/D4244 This was SVN commit r26067. --- source/collada/PSAConvert.cpp | 8 +++++--- source/renderer/InstancingModelRenderer.cpp | 7 +++++++ 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/source/collada/PSAConvert.cpp b/source/collada/PSAConvert.cpp index 392720c85e..70f0d6cc80 100644 --- a/source/collada/PSAConvert.cpp +++ b/source/collada/PSAConvert.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2018 Wildfire Games. +/* Copyright (C) 2021 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -90,7 +90,9 @@ public: REQUIRE(frameCount > 0, "animation must have frames"); // (TODO: sort out the timing/looping problems) - size_t boneCount = skeleton.GetBoneCount(); + const size_t boneCount = skeleton.GetBoneCount(); + if (boneCount > 64) + Log(LOG_ERROR, "Skeleton has too many bones %zu/64", boneCount); std::vector boneTransforms; @@ -99,7 +101,7 @@ public: float time = timeStart + frameLength * frame; BoneTransform boneDefault = { { 0, 0, 0 }, { 0, 0, 0, 1 } }; - std::vector frameBoneTransforms (boneCount, boneDefault); + std::vector frameBoneTransforms(boneCount, boneDefault); // Move the model into the new animated pose // (We can't tell exactly which nodes should be animated, so diff --git a/source/renderer/InstancingModelRenderer.cpp b/source/renderer/InstancingModelRenderer.cpp index 21ab8fc2d2..14c82755d2 100644 --- a/source/renderer/InstancingModelRenderer.cpp +++ b/source/renderer/InstancingModelRenderer.cpp @@ -78,6 +78,13 @@ IModelDef::IModelDef(const CModelDefPtr& mdef, bool gpuSkinning, bool calculateT if (gpuSkinning) { + // We can't use a lot of bones because it costs uniform memory. Recommended + // number of bones per model is 32. + // Add 1 to NumBones because of the special 'root' bone. + if (mdef->GetNumBones() + 1 > 64) + LOGERROR("Model '%s' has too many bones %zu/64", mdef->GetName().string8().c_str(), mdef->GetNumBones() + 1); + ENSURE(mdef->GetNumBones() + 1 <= 64); + m_BlendJoints.type = GL_UNSIGNED_BYTE; m_BlendJoints.elems = 4; m_Array.AddAttribute(&m_BlendJoints);