Переглянути джерело

Try to fix the bounding volume of skins

Panagiotis Christopoulos Charitos 5 роки тому
батько
коміт
f3bd3bbb8a

+ 42 - 9
src/anki/scene/ModelNode.cpp

@@ -31,10 +31,40 @@ public:
 		updated = false;
 
 		const MoveComponent& move = node.getComponent<MoveComponent>();
-		if(move.getTimestamp() == node.getGlobalTimestamp())
+		const SkinComponent* skin = node.tryGetComponent<SkinComponent>();
+		if(move.getTimestamp() == node.getGlobalTimestamp()
+			|| (skin && skin->getTimestamp() == node.getGlobalTimestamp()))
 		{
 			ModelNode& mnode = static_cast<ModelNode&>(node);
-			mnode.onMoveComponentUpdate(move);
+			mnode.updateSpatialComponent(move);
+		}
+
+		return Error::NONE;
+	}
+};
+
+/// Feedback component.
+class ModelNode::SkinFeedbackComponent : public SceneComponent
+{
+public:
+	SkinFeedbackComponent()
+		: SceneComponent(SceneComponentType::NONE)
+	{
+	}
+
+	ANKI_USE_RESULT Error update(SceneNode& node, Second prevTime, Second crntTime, Bool& updated) override
+	{
+		updated = false;
+
+		const SkinComponent& skin = node.getComponent<SkinComponent>();
+		if(skin.getTimestamp() == node.getGlobalTimestamp())
+		{
+			ModelNode& mnode = static_cast<ModelNode&>(node);
+
+			const Aabb& box = skin.getBoneBoundingVolume();
+			mnode.m_obbLocal.setCenter((box.getMin() + box.getMax()) / 2.0f);
+			mnode.m_obbLocal.setExtend(box.getMax() - mnode.m_obbLocal.getCenter());
+			mnode.m_obbLocal.setRotation(Mat3x4::getIdentity());
 		}
 
 		return Error::NONE;
@@ -68,10 +98,11 @@ Error ModelNode::init(ModelResourcePtr resource, U32 modelPatchIdx)
 	if(m_model->getSkeleton().isCreated())
 	{
 		newComponent<SkinComponent>(this, m_model->getSkeleton());
+		newComponent<SkinFeedbackComponent>();
 	}
 	newComponent<MoveComponent>();
 	newComponent<MoveFeedbackComponent>();
-	newComponent<SpatialComponent>(this, &m_obb);
+	newComponent<SpatialComponent>(this, &m_obbWorld);
 	MaterialRenderComponent* rcomp =
 		newComponent<MaterialRenderComponent>(this, m_model->getModelPatches()[m_modelPatchIdx].getMaterial());
 	rcomp->setup(
@@ -82,6 +113,8 @@ Error ModelNode::init(ModelResourcePtr resource, U32 modelPatchIdx)
 		this,
 		m_mergeKey);
 
+	m_obbLocal = m_model->getModelPatches()[m_modelPatchIdx].getBoundingShape();
+
 	return Error::NONE;
 }
 
@@ -105,9 +138,9 @@ Error ModelNode::init(const CString& modelFname)
 	return Error::NONE;
 }
 
-void ModelNode::onMoveComponentUpdate(const MoveComponent& move)
+void ModelNode::updateSpatialComponent(const MoveComponent& move)
 {
-	m_obb = m_model->getModelPatches()[m_modelPatchIdx].getBoundingShape().getTransformed(move.getWorldTransform());
+	m_obbWorld = m_obbLocal.getTransformed(move.getWorldTransform());
 
 	SpatialComponent& sp = getComponent<SpatialComponent>();
 	sp.markForUpdate();
@@ -213,9 +246,9 @@ void ModelNode::draw(RenderQueueDrawContext& ctx, ConstWeakArray<void*> userData
 		{
 			const ModelNode& self2 = *static_cast<const ModelNode*>(userData[i]);
 
-			const Mat3 rot = self2.m_obb.getRotation().getRotationPart();
-			const Vec4 tsl = self2.m_obb.getCenter().xyz1();
-			const Vec3 scale = self2.m_obb.getExtend().xyz();
+			const Mat3 rot = self2.m_obbWorld.getRotation().getRotationPart();
+			const Vec4 tsl = self2.m_obbWorld.getCenter().xyz1();
+			const Vec3 scale = self2.m_obbWorld.getExtend().xyz();
 
 			// Set non uniform scale. Add a margin to avoid flickering
 			Mat3 nonUniScale = Mat3::getZero();
@@ -239,7 +272,7 @@ void ModelNode::draw(RenderQueueDrawContext& ctx, ConstWeakArray<void*> userData
 
 		m_dbgDrawer.drawCubes(ConstWeakArray<Mat4>(mvps, userData.getSize()),
 			Vec4(1.0f, 0.0f, 1.0f, 1.0f),
-			1.0f,
+			2.0f,
 			ctx.m_debugDrawFlags.get(RenderQueueDebugDrawFlag::DITHERED_DEPTH_TEST_ON),
 			2.0f,
 			*ctx.m_stagingGpuAllocator,

+ 4 - 2
src/anki/scene/ModelNode.h

@@ -40,16 +40,18 @@ public:
 
 private:
 	class MoveFeedbackComponent;
+	class SkinFeedbackComponent;
 
 	ModelResourcePtr m_model; ///< The resource
 
-	Obb m_obb;
+	Obb m_obbLocal;
+	Obb m_obbWorld;
 	U64 m_mergeKey = 0;
 	U32 m_modelPatchIdx = 0;
 
 	DebugDrawer2 m_dbgDrawer;
 
-	void onMoveComponentUpdate(const MoveComponent& move);
+	void updateSpatialComponent(const MoveComponent& move);
 
 	void draw(RenderQueueDrawContext& ctx, ConstWeakArray<void*> userData) const;
 };

+ 19 - 3
src/anki/scene/components/SkinComponent.cpp

@@ -45,6 +45,9 @@ Error SkinComponent::update(SceneNode& node, Second prevTime, Second crntTime, B
 	updated = false;
 	const Second timeDiff = crntTime - prevTime;
 
+	Vec4 minExtend(MAX_F32, MAX_F32, MAX_F32, 0.0f);
+	Vec4 maxExtend(MIN_F32, MIN_F32, MIN_F32, 0.0f);
+
 	for(Track& track : m_tracks)
 	{
 		if(!track.m_anim.isCreated())
@@ -81,13 +84,21 @@ Error SkinComponent::update(SceneNode& node, Second prevTime, Second crntTime, B
 		}
 
 		// Walk the bone hierarchy to add additional transforms
-		visitBones(m_skeleton->getRootBone(), Mat4::getIdentity(), bonesAnimated);
+		visitBones(m_skeleton->getRootBone(), Mat4::getIdentity(), bonesAnimated, minExtend, maxExtend);
+	}
+
+	if(updated)
+	{
+		const Vec4 E{EPSILON, EPSILON, EPSILON, 0.0f};
+		m_boneBoundingVolume.setMin(minExtend - E);
+		m_boneBoundingVolume.setMax(maxExtend + E);
 	}
 
 	return Error::NONE;
 }
 
-void SkinComponent::visitBones(const Bone& bone, const Mat4& parentTrf, const BitSet<128>& bonesAnimated)
+void SkinComponent::visitBones(
+	const Bone& bone, const Mat4& parentTrf, const BitSet<128>& bonesAnimated, Vec4& minExtend, Vec4& maxExtend)
 {
 	Mat4 outMat;
 
@@ -102,9 +113,14 @@ void SkinComponent::visitBones(const Bone& bone, const Mat4& parentTrf, const Bi
 
 	m_boneTrfs[bone.getIndex()] = outMat * bone.getVertexTransform();
 
+	// Update volume
+	const Vec4 bonePos = outMat * Vec4(0.0f, 0.0f, 0.0f, 1.0f);
+	minExtend = minExtend.min(bonePos.xyz0());
+	maxExtend = maxExtend.max(bonePos.xyz0());
+
 	for(const Bone* child : bone.getChildren())
 	{
-		visitBones(*child, outMat, bonesAnimated);
+		visitBones(*child, outMat, bonesAnimated, minExtend, maxExtend);
 	}
 }
 

+ 12 - 1
src/anki/scene/components/SkinComponent.h

@@ -7,6 +7,7 @@
 
 #include <anki/scene/components/SceneComponent.h>
 #include <anki/resource/Forward.h>
+#include <anki/collision/Aabb.h>
 #include <anki/util/Forward.h>
 #include <anki/Math.h>
 
@@ -41,6 +42,11 @@ public:
 		return m_skeleton;
 	}
 
+	const Aabb& getBoneBoundingVolume() const
+	{
+		return m_boneBoundingVolume;
+	}
+
 private:
 	class Track
 	{
@@ -53,9 +59,14 @@ private:
 	SceneNode* m_node;
 	SkeletonResourcePtr m_skeleton;
 	DynamicArray<Mat4> m_boneTrfs;
+	Aabb m_boneBoundingVolume{Vec3(-1.0f), Vec3(1.0f)};
 	Array<Track, MAX_ANIMATION_TRACKS> m_tracks;
 
-	void visitBones(const Bone& bone, const Mat4& parentTrf, const BitSet<128, U8>& bonesAnimated);
+	void visitBones(const Bone& bone,
+		const Mat4& parentTrf,
+		const BitSet<128, U8>& bonesAnimated,
+		Vec4& minExtend,
+		Vec4& maxExtend);
 };
 /// @}