Equippable Items
Blitz3D Forums/Blitz3D Programming/Equippable Items
| ||
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! |
| ||
you can only attach it to one bone. So just create clothes orientated to one bone that stays still when the character walks |
| ||
"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. |
| ||
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. |
| ||
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 |
| ||
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. |
| ||
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 |
| ||
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! |
| ||
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? |
| ||
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 |
| ||
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! |