"Breathing" style mesh deforming code
Blitz3D Forums/Blitz3D Programming/"Breathing" style mesh deforming code
| ||
I was sure this was in the code archives. I had a copy of it somewhere, but now I can't find it. I can;t remember who wrote it, but it may have been Halo/Leadworks. It was a couple of functions which deformed meshes in particular ways, to make them appear like they were pulsing/breathing... |
| ||
Do you have access to a modeller? Or even Ultimate Unwrap? You could put a bone in the model and set the vertex weights to fall-off, from the centre. Then move the bone to your needs. |
| ||
I have UU, but I suck at all that stuff :S Really. I would be easier for me to have it in code format too as it needs to be timed (I know that with 3D models this can be achieved, but it's way beyond me hehe) I'm sure I could possibly rustle something up based on some of the other mesh-deforming code, though. Il have a try :) |
| ||
It is one of "halo's" examples: Samples\Blitz 3D Samples\halo\MeshFX\ |
| ||
. |
| ||
AAhaahah! Saved! I KNEW I'd seen it! Thanks, Puki - have a doughnut! |
| ||
can u guys make this code work for anim meshes as well as .x .3ds .b3d meshes? and for only ONE mesh? not 2? |
| ||
I can try to explain how you can do it yourself? Since Sin() is used, you can indeed alter the function to work with a single mesh instead of one original, and one copy. Start off with making a backup of the original program. In case anything goes wrong. Ie: File->SaveAs->MeshFX2 1. Remove the second mesh parameter from the function Function Breath(mesh,am#) 2. Remove the second mesh from the call that is made to Breath as well: Breath(mesh,mesh2, ..) -> Breath(mesh, ..) 3. In the function Breath, remove the line surf2=GetSurface(..) 4. In the function, change every call to surf2 to surf. 5. Change the call to Breath into this: Breath(mesh,(Sin(MilliSecs()*speed)*depth/100.0)) Now, the function should operate without a 'original' copy of the mesh. Test if the program still runs. If you want to use an AnimMesh, I'm not sure how it will work out with boned meshes, but you can give it a shot. AnimMesh has a tree structure, with a 'root' parent and children. If one of the leaves of this tree structure is a mesh, it might be possible to deform them. If they are not meshes, you can't deform them, GetSurface will return an error. So, first make sure that the mesh that is passed to Breath is really a mesh and not a bone/pivot/something else. Immediately after "Function" add the line: If EntityClass(mesh)="Mesh" Then And before "End Function" add the line EndIf The entire content of the function is now only executed if the entity is a mesh. Now the function has to be called for each child of the entity. At the end of the function, before "End Function", after "End If", add the lines: For i = 1 To CountChildren(mesh) Breath(GetChild(mesh,i),am) Next Since this will call "Breath" for each child entity, any sub-children (grandchildren?) will be encountered as well. That should do it, unless I forgot something. If you want to test it, change the line mesh=LoadMesh(.. etc to mesh=LoadAnimMesh("C:\program files\blitz3d\samples\mak\anim\makbot\mak_robotic.x");test.3ds") And perhaps remove anything that is needed for the eggtube effect, such as the second mesh, the selection of the FX etc. |
| ||
thanks warner! |
| ||
for everybody who wishes to use: Function Breath(mesh,am#) If EntityClass(mesh)="Mesh" Then For k=1 To CountSurfaces(mesh) surf=GetSurface(mesh,k) For index=0 To CountVertices(surf)-1 newx#=VertexX(surf,index)+VertexNX(surf,index)*am newy#=VertexY(surf,index)+VertexNY(surf,index)*am newz#=VertexZ(surf,index)+VertexNZ(surf,index)*am VertexCoords surf,index,newx,newy,newz Next Next For i = 1 To CountChildren(mesh) Breath(GetChild(mesh,i),am) Next EndIf End Function |
| ||
Ah cool, glad it works. One thingie: the For..Next loop should be placed after EndIf. |
| ||
ah ok. very well, warner :) will do :) fixed function: Function Breath(mesh,am#) If EntityClass(mesh)="Mesh" Then For k=1 To CountSurfaces(mesh) surf=GetSurface(mesh,k) For index=0 To CountVertices(surf)-1 newx#=VertexX(surf,index)+VertexNX(surf,index)*am newy#=VertexY(surf,index)+VertexNY(surf,index)*am newz#=VertexZ(surf,index)+VertexNZ(surf,index)*am VertexCoords surf,index,newx,newy,newz Next Next EndIf For i = 1 To CountChildren(mesh) Breath(GetChild(mesh,i),am) Next End Function |
| ||
Biit late seeing this, but I doubt I'd've been much help. That's pretty neat, DSW, nice and compact too! I was sure it could be done without needing a second mesh and it''s much better to be able to! Thanks :) Just a consideration, though... Function Breathe(Mesh%,Recursive%=False,Animation%=1) If (EntityClass(Mesh)="Mesh") For k=1 To CountSurfaces(Mesh) surf=GetSurface(Mesh,k) For index=0 To CountVertices(surf)-1 newx#=VertexX(surf,index)+VertexNX(surf,index)*Animation newy#=VertexY(surf,index)+VertexNY(surf,index)*Animation newz#=VertexZ(surf,index)+VertexNZ(surf,index)*Animation VertexCoords surf,index,newx,newy,newz Next Next If (Recursive) For i = 1 To CountChildren(Mesh) Breathe(GetChild(Mesh,i),True,Animation) Next End If End If End Function |
| ||
meh. Stoopid double post. |
| ||
Malice! ur right! thanks for the contribution! if u guys could modify this code to STOP AFTER the model breathes and it changes the vertex, u COULD create a code that can grow muscles on a character! :D I thought of it last night! :D |
| ||
Also, if u could do this, like edit the code, so that u can select which joint to use the breath code, so i could like select the stomach of my model, and it would breathe. :) because the way the code is now, my model acts like a balloon... lol |
| ||
How should the function know which bone you need? By it's name, or it's handle? |
| ||
probably handle. because the name can be anything. unless theres a way to detect that.. |
| ||
I have no clue about bones and all that malarkey ;) But certainly, you should only need to call the function a set number of times to 'breathe' to a limit, effecti vely you would have somewhere: If TimeToBreathe() For f=1 to BreatheLimit Breathe(Mesh,blah,blah) Next End If Perhaps some other parameter could be introduced to specify whether "breathe in / out" ? |
| ||
hmm.. warner, what do u think? |
| ||
Ooooh Nope. Actually, that's bad. Probably better to keep a track somewhere of the "Amount Of Breathing Done" - ratehr than have for/next loops running BEFORE any rendering. |
| ||
true. warner, again, what do u think? |
| ||
Ah.. I see the am (Animation) parameter controls the direction, is that right? I p[roriginally just assumed it was something to do with animation frames! |
| ||
yes. am controls it. |
| ||
@malice, That parameter determines how much a vertex should be moved forward. "Forward" is then the direction of the vertex normal. VertexNX,NY,NZ. It is an (x,y,z) vector that indicates which direction a triangle/face faces. It is commonly used for lighting. So it is in fact the normal combined with this paramter that indicates the direction. @dsw, I was just thinking sort of out loud. In fact, a bone is assigned to a set of vertices, with a percentage that indicates how much the vertices should be affected by the bone. That information is normally not available in Blitz, not without 'hacking certain properties' (topic title). I'm not sure, and I have no model to try it on, but you could try scaling the bone. For instance, as a first step, like this: ScaleEntity bone, 2, 1, 1 That should affect the part of the vertex that is assigned to the bone. I'm not sure how it works internally, maybe the bone/vertex animations are performed in UpdateWorld, so you might need to place this scale command after 'UpdateWorld'. If that is possible, you could write something that scales the bone with a Sin(), such as this: scale# = Sin(Millisecs() / 100.0) * 0.25 + 0.5 ScaleEntity bone, scale, scale, scale It might mess things up though, since the bones are used for animation as well, and other bones might be linked to this bone, and therefore they are affected by this scaling. Still, with some effort it should be possible to create this breathing effect. |
| ||
right. which is why i think we should have the code allow for u to select MULTIPLE limbs OR a single limb, depending on which u select :) |
| ||
I don't understand that? Basically, you can't pass bones to the above function at all, since it deforms a mesh itself. I do believe that scaling a bone should be a good first step at least. |
| ||
no. i meant pass the vertex change to EACH limb, or a SELECTED limb or MULTIPLE selected limbs... |
| ||
Ah, so 'limbs' in the form of a sub-mesh, and not bones, right? Then it is more easy. At the start of the function, beside checking if the entity is a mesh, also check what the name of the entity is. Ie: If (EntityClass(mesh) = "Mesh") and (EntityName$(mesh) = "Cube01") |
| ||
well. yes. instead of changing the vertex of bones, change the vertex of the selected joint(s) depending on what u want to do :) |
| ||
I admit I don't know much at all about boned meshes and allt hat, but aren't joints just a form of pivot, i.e. they have no geometry (verts)If (EntityClass(mesh) = "Mesh") and (EntityName$(mesh) = "Cube01") I think if that' the route this idea is to take, then a 'generalised' breathe function for all becomes pretty much redundant. Perhaps looking at it the other way and selecting the individual parts of the mesh (bones or whatever) elsewhere before calling a function to just change the verts, essentially, we're back to square 1 Oversimpliified pseudo code: Function TakeBreath(Mesh) Select Mesh Case=MyMesh1 Breathe(Bone11) Breathe(Bone12) Breathe(Bone13) Exit Case=MyMesh2 Breathe(Bone21) Breathe(Bone22) Breathe(Bone23) Exit Default End Select End Function |
| ||
so what should we do? |
| ||
First, a testing model would be practical. |
| ||
use markio/mariorun.x inside the castle folder. thats what i did :) |
| ||
how did it go? |
| ||
I like the idea of using Sin, that way both the change between breathing in and out PLUS the 'limit' on how "much each breath 'is' " is taken care of with the one command. I'm still having a few issuers trying to find a reasonable coefficient multiplier though. Of course, this is all extremely dependant on the particular size of the mesh (note: not the scale, however) |
| ||
i see. so just let us know when u figure it out. |
| ||
figure it out yet? |