Equippable Items

Blitz3D Forums/Blitz3D Programming/Equippable Items

YellBellzDotCom(Posted 2006) [#1]
Hello,

I've been attempting this for quite some time and just cant seem to get it right.

I understand how to equip weapons and single bone attachable items. The one thing that I cant figure out is how to equip an item that will cover multiple bones. For instance a shirt covers the torso which contains 5 bones, the upperarms and the forearms. I have tried again and again to make my shirt mesh attach to my char model but cannot get it to work properly.

I have a char model with the above mentioned bones.

I created a shirt model, used the same biped from char model, attached the vertices, deleted any animations. Deleted the unused bones that werent parents to critical bones.

I tried cycling through the entity names and EntityParent each bone from the shirt to the model and it all attaches until it gets to L_Clavicle then I have a problem. I have the custom function stop before it got to L_clavicle just to see how the first items attached and how it looked. Which with some tweaking may work.

I was just curious to see what others have done to make this sort of RPG equippable system and if anyone is willing to share their thoughts and code, hehehehe.

Thanks for any help here!


slenkar(Posted 2006) [#2]
you can only attach it to one bone.

So just create clothes orientated to one bone that stays still when the character walks


YellBellzDotCom(Posted 2006) [#3]
"you can only attach it to one bone."

I have a char model with 9 bones that make up the torso.

I have a shirt model with 9 bones.

Both models have the same named bones.

I cycle through the names of the bones of the shirt and if the char model has a bone with the same name, it will parententity to it. This works great for the first 6 bones, but once it gets to the 7th bone, which is the Left Clavicle bone, the program errors out saying "Entity cannot be parented to itself!" I cant understand why its saying that for this bone, when it clearly parents the other bones.

I was checking in to see if I was on the right track here, or if someone has a link, tutorial, code or any recommendations.

I appreciate the reply Slunkar, hopefully my response will shed some light on what I'm attempting. Thank you.


OrcSlayer(Posted 2006) [#4]
My artisit and I tried this once. We were able to pull it off, but we needed to do some hackish stuff to make it work. It's not as simple as it sounds, which I found out the hard way.

Try doing this:
Mesh1 = Base mesh.
Mesh2 = Clothing mesh.

For each bone in mesh2, MANUALLY attach it to the bone of the same name in mesh1. Don't try using a function to do it, it never seemed to work for us.

The best way to do this is set it up so that when the two meshes are loaded, they are already positioned in such a way that the bones can be parented right off, before you apply any animations to the base mesh.

As I said, we got this to work...but it wasn't terribly easy.


Danny(Posted 2006) [#5]
Hi Xyle, that's a pretty clever idea.
But I don't completely understand from your post if it worked or not. I do know that you can re-parent each bone to something else without much problem, so I see no reason why this shouldn't work!

One thing you have to keep in mind: If you re-parent every bone of the shirt-mesh, you ALSO have to parent the SHIRT MESH itself to something! (ie. the entity handle returned by LoadAnimMesh) If you don't do this, the character will walk away with your shirt, BUT the mesh's pivot will remain at 0,0,0! And when the mesh's pivot is off-camera Bitz will HIDE the shirt (thinking it doesn't need rendering).

So to fix this simply parent the shirt mesh to your character's mesh - or you can even parent it to one of the shirt's own bones!! This way the mesh-pivot will remain with the shirt/character and thus in-camera and visible ;)

Hope this makes sense :))

Danny


Danny(Posted 2006) [#6]
Perhaps it would help if you first unparent each shirt-bone (parent to 0) BEFORE re-parenting it to the body bones?

I can imagine that if you use a function and just cycle through each bone (child ent) that you might produce some recursive hierarchy - and thus blitz giving that error.

By unparenting each shirt-bone first, you remove the shirt's internal bone-hierarchy and should prevent a possible recursive loop while knitting the shirt to the body?! But not sure if this works, just making it up :)

hope this helps,

Danny.


YellBellzDotCom(Posted 2006) [#7]
Ok,

OrcSlayer, I have tried to parent each shirt bone to each char bone manually, It will allow me to do the spine bone, but then it tells me that the entity doesnt exist when I try the spine1 bone. I've commented out each failure, but from Spine1 down the line, they each error out. The only bone I can manually parent is the spine bone. Thanks for the advice.

Danny, I did unparent each bone in the shirt, then parented it to the corresponding bone in the char model. I still get a problem though when it gets to the L_CLavicle bone. Im wondering if I have a problem in the model itself. I create the model in max7, export it as q3d dx file. Open in Unwrap3d, save it as milkshape file, open in milkshape and export to b3d. Wheeew. Its the only way I've found I can export max files to b3d. I couldnt get animated .x files to work using panda or q3d, nor 3ds files.

If anyone wants they can download the files and mess around with em. Here...
http://www.hilbily-works.com/Downloads1/Blitz3d_Models.zip

and heres the code I use to entityparent the bones...
mesh_3ds=LoadAnimMesh( "models\MaleWalk_Forward2.b3d" )
RotateEntity mesh_3ds,0,180,0 
PositionEntity mesh_3ds,-15,-15,0

mesh_Shirt1=LoadAnimMesh( "models\clothing\Shirta.b3d" )	
RotateEntity mesh_Shirt1,0,180,0 
PositionEntity mesh_Shirt1,-15,-15,0

pivot=CreatePivot()
cam=CreateCamera( pivot )
PositionEntity cam,0,-10,-100

lit=CreateLight()
RotateEntity lit,45,45,0

a = 1
ent = mesh_Shirt1
While ent
	
	ent = NextChild(ent)
	ent1 = mesh_3ds	
	If a > 2 And a < 16
		EntityParent ent,0
		While ent1
			ent1 = NextChild(ent1)
			If EntityName(ent) = EntityName(ent1)				
				DebugLog "Mesh_3ds "+EntityName(ent1)
				DebugLog "MeshShirt1 "+EntityName(ent)
				PositionEntity  ent,EntityX(ent1,True),EntityY(ent1,True),EntityZ(ent1,True)
				EntityParent ent,ent1
				Exit
			EndIf
		Wend
	EndIf
	a = a + 1
Wend

Function NextChild(ent)
	If CountChildren(ent)>0
		Return GetChild(ent,1)
	EndIf

	Local foundunused=False
	Local foundent = 0, parent,sibling
	While foundunused=False And ent<>0
		parent = GetParent(ent)
		If parent<>0
			If CountChildren(parent)>1
				If GetChild(parent,CountChildren(parent))<>ent
					For siblingcnt = 1 To CountChildren(parent)
						sibling = GetChild(parent,siblingcnt)
						If sibling=ent
							foundunused = True
							foundent = GetChild(parent,siblingcnt+1)
						EndIf
					Next
				EndIf
			EndIf
		EndIf
		ent = parent
	Wend
	Return foundent
End Function



YellBellzDotCom(Posted 2006) [#8]
Wow!

That was a combined total of about 20 hours to get this down!

I originally tried to manually assign the shirt to the char model, bone by bone, but after a few short turns at it, I quickly gave up and went for the customized function that someone on these forums made. After all these hours, and with OrcSlayers insight reminding me to try out the manual method again. I finally got it working. I did download the Ultimate Unwrap 3d plugins for Max and Blitz, which eliminated at least 1 cross conversion. I cleaned up the bone names in UU3d and exported the models to .b3d format.

Its finally working! Now, if I can just miss work tomorrow...

hehehehe.

Thanks for the help! Oh, heres the code, lol. You have to know which bones are in each model and which ones are childs of what, which UU3d gives that info.

Global info1$="Animation demo"
Global info2$="Hold down <return> to run"
Global info3$="Hit <space> to toggle transitions"

Graphics3D 800,600,16,0
SetBuffer BackBuffer()
AmbientLight 120,120,90

mesh_3ds=LoadAnimMesh( "C:\The Docs\3d Modeling and Games\My Stuff\Models\Human Male\Male B\688 Poly\Animations\MaleWalk_ForwardUU3d.b3d" )	;anim seq 0	
RotateEntity mesh_3ds,0,180,0 
PositionEntity mesh_3ds,-15,-15,0

mesh_Shirt1=LoadAnimMesh( "C:\The Docs\3d Modeling and Games\My Stuff\Models\Human Male\Male B\688 Poly\Clothing\Shirt.b3d" )	;anim seq 0
RotateEntity mesh_Shirt1,0,180,0 
PositionEntity mesh_Shirt1,-15,-15,0


pivot=CreatePivot()
cam=CreateCamera( pivot )
PositionEntity cam,0,-10,-100

lit=CreateLight()
RotateEntity lit,45,45,0

Spine = FindChild(mesh_3ds,"Bip01 Spine")
SpineB = FindChild(mesh_Shirt1,"Bip01 Spine")
;PositionEntity  SpineB,EntityX(Spine,True),EntityY(Spine,True),EntityZ(Spine,True)
EntityParent SpineB,Spine

Spine1 = FindChild(Spine,"Bip01 Spine1")
SpineB1 = FindChild(SpineB,"Bip01 Spine1")
;PositionEntity  SpineB1,EntityX(Spine1,True),EntityY(Spine1,True),EntityZ(Spine1,True)
EntityParent SpineB1,Spine1

Spine2 = FindChild(Spine1,"Bip01 Spine2")
SpineB2 = FindChild(SpineB1,"Bip01 Spine2")
;PositionEntity  SpineB2,EntityX(Spine2,True),EntityY(Spine2,True),EntityZ(Spine2,True)
EntityParent SpineB2,Spine2

Neck = FindChild(Spine2,"Bip01 Neck")
Neck1 = FindChild(SpineB2,"Bip01 Neck")
;PositionEntity  LClavB,EntityX(LClav,True),EntityY(LClav,True),EntityZ(LClav,True)
EntityParent Neck1,Neck

LClav = FindChild(Neck,"Bip01 L Clavicle")
LClavB = FindChild(Neck1,"Bip01 L Clavicle")
;PositionEntity  LClavB,EntityX(LClav,True),EntityY(LClav,True),EntityZ(LClav,True)
EntityParent LClavB,LClav

LUArm = FindChild(LClav,"Bip01 L UpperArm")
LUArmB = FindChild(LClavB,"Bip01 L UpperArm")
;PositionEntity  LUArmB,EntityX(LUArm,True),EntityY(LUArm,True),EntityZ(LUArm,True)
EntityParent LUArmB,LUArm

LFArm= FindChild(LUArm,"Bip01 L Forearm")
LFArmB = FindChild(LUArmB,"Bip01 L Forearm")
;PositionEntity  LFArmB,EntityX(LFArm,True),EntityY(LFArm,True),EntityZ(LFArm,True)
EntityParent LFArmB,LFArm

RClav = FindChild(Neck,"Bip01 R Clavicle")
RClavB = FindChild(Neck1,"Bip01 R Clavicle")
;PositionEntity  RClavB,EntityX(RClav,True),EntityY(RClav,True),EntityZ(RClav,True)
EntityParent RClavB,RClav

RUArm = FindChild(RClav,"Bip01 R UpperArm")
RUArmB = FindChild(RClavB,"Bip01 R UpperArm")
;PositionEntity  RUArmB,EntityX(RUArm,True),EntityY(RUArm,True),EntityZ(RUArm,True)
EntityParent RUArmB,RUArm

RFArm= FindChild(RUArm,"Bip01 R Forearm")
RFArmB = FindChild(RUArmB,"Bip01 R Forearm")
;PositionEntity  RFArmB,EntityX(RFArm,True),EntityY(RFArm,True),EntityZ(RFArm,True)
EntityParent RFArmB,RFArm




Animate mesh_3ds,1

trans=10
KeyNum = 0

While Not KeyHit(1)
	

	If KeyHit(57)
		If trans > 0 trans=10-1
		If trans = 0 trans = 10
		KeyNum = 57
	EndIf

	If KeyDown(28)
		If AnimSeq(mesh_3ds)=0 Animate mesh_3ds,1,.5,1,trans
		KeyNum = 28
	Else
		If AnimSeq(mesh_3ds)=1 Animate mesh_3ds,2,1,0,trans
	EndIf
	
	If KeyDown(30) 
		MoveEntity cam,0,0,10
		KeyNum = 30
	EndIf
	If KeyDown(44) 
		MoveEntity cam,0,0,-10
		KeyNum = 44
	EndIf
	If KeyDown(203) 
		TurnEntity pivot,0,3,0
		KeyNum = 203
	EndIf
	If KeyDown(205) 
		TurnEntity pivot,0,-3,0
		KeyNum = 205
	EndIf

	UpdateWorld
	RenderWorld
	Text 0,FontHeight()*1,"Anim len: "+AnimLength( mesh_3ds )
	Text 0,FontHeight()*2,"Anim time:"+AnimTime( mesh_3ds )
	Text 0,FontHeight()*8,"Transition time="+trans
	Text 0,290,"Number of CHildren="+CountChildren(mesh_3ds)
	Text 0,300,"KeyNum ="+KeyNum

	
	Flip
	
Wend



and the new updated files...
http://www.hilbily-works.com/Downloads1/NewBlitz3d_Models.zip

now to try and make a new function routine to do this automagically!


(tu) sinu(Posted 2006) [#9]
couldn't you just parent the main bone from the shirt to the same one on the mesh and then just update the shirts bones rotations with the same ones on the mesh excluding the one you parented?


Danny(Posted 2006) [#10]
eh eh... try the function below.. just call "DressAnimMesh(mesh_3ds, mesh_shirt1)" after loading the models.

The main trick was to do the for..next loop in reverse. Since you're changing the 'amount of children' during the for-loop by re-parenting entities it will skip children (I also had the Clavicle problem like you - on the right arm actually ;).

Also, you don't have to position the shirt manually AT ALL. Since the function resets the bones to their 0,0,0 LOCAL position/rotation, so the parent bones take care of it automatically...

By the way, it also automatically SCALES the shirt bones to the same size as the parent bones so if you scale or even squash and stretch the main model, the shirt goes along with it perfectly! very cool! :)

Hope this helps dude,

Function DressAnimMesh( BodyMesh, clothMesh, isFirst=True )
	
	;recursively parse through the hierarchy
	For i = CountChildren(clothMesh) To 1 Step -1
		DressAnimMesh(BodyMesh, GetChild(clothMesh,i),False)
	Next
		
	;when children are done, set this entity
	partName$ = EntityName$(clothMesh)
	parent = FindChild(bodyMesh,partName$)
	If parent <> 0 Then
		EntityParent clothMesh, parent
		PositionEntity clothMesh, 0,0,0, 0
		RotateEntity clothMesh, 0,0,0, 0
		ScaleEntity clothMesh, 1,1,1, 0
	Else
		DebugLog "WARNING: Unable to find entity <"+partName$+"> in main BodyMesh"
	EndIf

	;parent the mesh itself
	If isFirst Then
		EntityParent clothMesh,BodyMesh
		PositionEntity clothMesh, 0,0,0, 0
		RotateEntity clothMesh, 0,0,0, 0
		ScaleEntity clothMesh, 1,1,1, 0
	EndIf

End Function



YellBellzDotCom(Posted 2006) [#11]
Wow, Awesome job there Danny. Mucho thanks for that. I will play around with it.

Sinu, I dont know if you could do that or not and how complicated it would be. This is about my 10th day with Blitz3d so I'm not to savy with the command reference.

Thanks for all the input and help!