Page 1 of 1

[fixed]correct BoundingBox for SkinnedMesh

Posted: Tue Sep 30, 2008 12:58 pm
by tprochownik
Hi,

problem was in incorret calculatiing boundingbox. I think I solved this problem, in CSkinnedMesh.cpp:

Code: Select all

void CSkinnedMesh::finalize()
{
	u32 i;

	LastAnimatedFrame=-1;
	LastSkinnedFrame=-1;

	//calculate bounding box

	for (i=0; i<LocalBuffers.size(); ++i)
	{
		LocalBuffers[i]->recalculateBoundingBox();
	}

	if (AllJoints.size() || RootJoints.size())
	{
		// populate AllJoints or RootJoints, depending on which is empty
		if (!RootJoints.size())
		{

			for(u32 CheckingIdx=0; CheckingIdx < AllJoints.size(); ++CheckingIdx)
			{

				bool foundParent=false;
				for(i=0; i < AllJoints.size(); ++i)
				{
					for(u32 n=0; n < AllJoints[i]->Children.size(); ++n)
					{
						if (AllJoints[i]->Children[n] == AllJoints[CheckingIdx])
							foundParent=true;
					}
				}

				if (!foundParent)
					RootJoints.push_back(AllJoints[CheckingIdx]);
			}
		}
		else
		{
			AllJoints=RootJoints;
		}
	}

	for(i=0; i < AllJoints.size(); ++i)
	{
		AllJoints[i]->UseAnimationFrom=AllJoints[i];
	}

	//Set array sizes...

	for (i=0; i<LocalBuffers.size(); ++i)
	{
		Vertices_Moved.push_back( core::array<bool>() );
		Vertices_Moved[i].set_used(LocalBuffers[i]->getVertexCount());
	}

	//Todo: optimise keys here...

	checkForAnimation();

	if (HasAnimation)
	{
		//--- optimize and check keyframes ---
		for(i=0;i<AllJoints.size();++i)
		{
			core::array<SPositionKey> &PositionKeys =AllJoints[i]->PositionKeys;
			core::array<SScaleKey> &ScaleKeys = AllJoints[i]->ScaleKeys;
			core::array<SRotationKey> &RotationKeys = AllJoints[i]->RotationKeys;

			if (PositionKeys.size()>2)
			{
				for(u32 j=0;j<PositionKeys.size()-2;++j)
				{
					if (PositionKeys[j].position == PositionKeys[j+1].position && PositionKeys[j+1].position == PositionKeys[j+2].position)
					{
						PositionKeys.erase(j+1); //the middle key is unneeded
						--j;
					}
				}
			}

			if (PositionKeys.size()>1)
			{
				for(u32 j=0;j<PositionKeys.size()-1;++j)
				{
					if (PositionKeys[j].frame >= PositionKeys[j+1].frame) //bad frame, unneed and may cause problems
					{
						PositionKeys.erase(j+1);
						--j;
					}
				}
			}

			if (ScaleKeys.size()>2)
			{
				for(u32 j=0;j<ScaleKeys.size()-2;++j)
				{
					if (ScaleKeys[j].scale == ScaleKeys[j+1].scale && ScaleKeys[j+1].scale == ScaleKeys[j+2].scale)
					{
						ScaleKeys.erase(j+1); //the middle key is unneeded
						--j;
					}
				}
			}

			if (ScaleKeys.size()>1)
			{
				for(u32 j=0;j<ScaleKeys.size()-1;++j)
				{
					if (ScaleKeys[j].frame >= ScaleKeys[j+1].frame) //bad frame, unneed and may cause problems
					{
						ScaleKeys.erase(j+1);
						--j;
					}
				}
			}

			if (RotationKeys.size()>2)
			{
				for(u32 j=0;j<RotationKeys.size()-2;++j)
				{
					if (RotationKeys[j].rotation == RotationKeys[j+1].rotation && RotationKeys[j+1].rotation == RotationKeys[j+2].rotation)
					{
						RotationKeys.erase(j+1); //the middle key is unneeded
						--j;
					}
				}
			}

			if (RotationKeys.size()>1)
			{
				for(u32 j=0;j<RotationKeys.size()-1;++j)
				{
					if (RotationKeys[j].frame >= RotationKeys[j+1].frame) //bad frame, unneed and may cause problems
					{
						RotationKeys.erase(j+1);
						--j;
					}
				}
			}


			//Fill empty keyframe areas
			if (PositionKeys.size())
			{
				SPositionKey *Key;
				Key=&PositionKeys[0];//getFirst
				if (Key->frame!=0)
				{
					PositionKeys.push_front(*Key);
					Key=&PositionKeys[0];//getFirst
					Key->frame=0;
				}

				Key=&PositionKeys.getLast();
				if (Key->frame!=AnimationFrames)
				{
					PositionKeys.push_back(*Key);
					Key=&PositionKeys.getLast();
					Key->frame=AnimationFrames;
				}
			}

			if (ScaleKeys.size())
			{
				SScaleKey *Key;
				Key=&ScaleKeys[0];//getFirst
				if (Key->frame!=0)
				{
					ScaleKeys.push_front(*Key);
					Key=&ScaleKeys[0];//getFirst
					Key->frame=0;
				}

				Key=&ScaleKeys.getLast();
				if (Key->frame!=AnimationFrames)
				{
					ScaleKeys.push_back(*Key);
					Key=&ScaleKeys.getLast();
					Key->frame=AnimationFrames;
				}
			}

			if (RotationKeys.size())
			{
				SRotationKey *Key;
				Key=&RotationKeys[0];//getFirst
				if (Key->frame!=0)
				{
					RotationKeys.push_front(*Key);
					Key=&RotationKeys[0];//getFirst
					Key->frame=0;
				}

				Key=&RotationKeys.getLast();
				if (Key->frame!=AnimationFrames)
				{
					RotationKeys.push_back(*Key);
					Key=&RotationKeys.getLast();
					Key->frame=AnimationFrames;
				}
			}
		}
	}

	//Needed for animation and skinning...

	CalculateGlobalMatrices(0,0);

	//animateMesh(0, 1);
	//buildAll_LocalAnimatedMatrices();
	//buildAll_GlobalAnimatedMatrices();

	//rigid animation for non animated meshes
	for (i=0; i<AllJoints.size(); ++i)
	{
		for (u32 j=0; j<AllJoints[i]->AttachedMeshes.size(); ++j)
		{
			SSkinMeshBuffer* Buffer=(*SkinningBuffers)[ AllJoints[i]->AttachedMeshes[j] ];
			Buffer->Transformation=AllJoints[i]->GlobalAnimatedMatrix;
		}
	}


		// Get BoundingBox...
	if (LocalBuffers.empty())
		BoundingBox.reset(0,0,0);
	else
	{
		irr::core::aabbox3df bb(LocalBuffers[0]->BoundingBox);
		LocalBuffers[0]->Transformation.transformBoxEx(bb);
		BoundingBox.reset(bb);

		for (u32 j=1; j<LocalBuffers.size(); ++j)
		{
			bb = LocalBuffers[j]->BoundingBox;
			LocalBuffers[j]->Transformation.transformBoxEx(bb);

			BoundingBox.addInternalBox(bb);
		}
	}

	//add 5% padding to bounding box
	core::vector3df Padding=BoundingBox.getExtent()*0.05f;
	BoundingBox.MinEdge-=Padding;
	BoundingBox.MaxEdge+=Padding;
}
diffrient is location of this code and transforming local boundingbox. can be it commit on svn?

Code: Select all

		// Get BoundingBox...
	if (LocalBuffers.empty())
		BoundingBox.reset(0,0,0);
	else
	{
		irr::core::aabbox3df bb(LocalBuffers[0]->BoundingBox);
		LocalBuffers[0]->Transformation.transformBoxEx(bb);
		BoundingBox.reset(bb);

		for (u32 j=1; j<LocalBuffers.size(); ++j)
		{
			bb = LocalBuffers[j]->BoundingBox;
			LocalBuffers[j]->Transformation.transformBoxEx(bb);

			BoundingBox.addInternalBox(bb);
		}
	}

Posted: Tue Sep 30, 2008 2:41 pm
by hybrid
Yes, looks reasonable.

Posted: Tue Sep 30, 2008 4:29 pm
by tprochownik
hybrid wrote:Yes, looks reasonable.
I saw, you commit to svn, but this is not resolving problem, You only moved code to another place, but solution is LocalBuffers[0]->Transformation.transformBoxEx for each boundingbox......

Code: Select all

     // Get BoundingBox... 
   if (LocalBuffers.empty()) 
      BoundingBox.reset(0,0,0); 
   else 
   { 
      irr::core::aabbox3df bb(LocalBuffers[0]->BoundingBox); 
      LocalBuffers[0]->Transformation.transformBoxEx(bb); 
      BoundingBox.reset(bb); 

      for (u32 j=1; j<LocalBuffers.size(); ++j) 
      { 
         bb = LocalBuffers[j]->BoundingBox; 
         LocalBuffers[j]->Transformation.transformBoxEx(bb); 

         BoundingBox.addInternalBox(bb); 
      } 
   } 

Posted: Tue Sep 30, 2008 6:46 pm
by hybrid
In that case you should start using a proper patch tool, or comment your changes exactly. Please also post a bug tracker ticket at the SF trackers next time:
https://sourceforge.net/tracker/?group_id=74339
Oh, and please also don't put [fixed] to your message, that's what added once we've fixed the issue in the library.

Posted: Tue Sep 30, 2008 7:00 pm
by rogerborg
And a simple standalone test case is always nice.

THAT SAID: thanks for posting this, it does look like it should address the BB problem. Although a test case would help to demonstrate that. ;)

Posted: Wed Oct 01, 2008 7:18 am
by tprochownik
Ok, next time I do that, but is possible to do commit with this boundingbox patch?

Posted: Wed Oct 01, 2008 7:46 am
by hybrid
Well, this makes the code a little more involved, so I have to check the things more thoroughly. But yes, probably it's possible sometime later.

Hmm, I just tested latest SVN trunk and found that there is no bounding box at all anymore. At least nothing's displayed in the meshviewer. Did anyone else also have this problem, and are there any assumptions when or why this changed (broke)?

Posted: Wed Oct 01, 2008 1:34 pm
by hybrid
Ok, the missing bboxes are fixed - the methods are currently dawing with alpha 0, which seems to lead to completely transparent lines in the used render state. Fixed it to alpha 255 for now, I'll check the render states later (was OpenGL, FYI).
I didn't see any problems with the transformed boxes, so far, but I also didn't find any meshes which work better. Do you have a simple example?

Posted: Wed Oct 01, 2008 7:49 pm
by tprochownik
yes, a have a example, not only for this mesh
http://biostorm.eu/editor.zip or http://annis.ovh.org/editor.zip

when You click on the (unfortunately around) object it sets m_Node->setDebugDataVisible(EDS_BBOX_ALL);

EDS_BBOX_BUFFERS are correctly, but EDS_BBOX not. if You need source code of this editor I can sent You too....

Posted: Wed Oct 01, 2008 9:15 pm
by hybrid
Ok, that does convince me :D already commited as rev 1611.

Posted: Thu Oct 02, 2008 9:27 am
by Luke
missed this, thanks for the fix.

only a few x meshes are using meshbuffer transformation, but still very good to fix. I won't go into the other problems with meshbuffer transformation here, but would like to remove or fix this.