'dynamic mesh deformation' code?

Blitz3D Forums/Blitz3D Programming/'dynamic mesh deformation' code?

markcw(Posted 2005) [#1]
hello i am dumb, or just lazy, take your pick. (its dumb and lazy) anyway, i have a few questions and thought i'd ask rather than search.

if i load an .x model with multiple meshes, what command do i use to access each mesh??
i want to load the vertices data to an array, for animating. i'm too tired atm to find the stuff in the manual.

actually, if anyone wants to write the code piece for me i will include their name/nickname in the game credits, the game is a remake (free) of chaos: battle of the wizards. the code is a function to animate a single-surface mesh, as the subject suggests. it would go something like: animatemymodel(singlemesh,animatearray,frame)


Beaker(Posted 2005) [#2]
Use FindChild.
http://www.blitzbasic.com/b3ddocs/command.php?name=FindChild&ref=3d_cat

OR this is one way:
http://www.blitzbasic.com/codearcs/codearcs.php?code=796

this is another:
http://www.blitzbasic.com/codearcs/codearcs.php?code=787


BlackD(Posted 2005) [#3]
Just to let you know - you're going to run into problems.

Namely VertexCoords changes must be stacked in order to work in realtime. Okay, I'll explain it better.

Think of the VertexCoords commands, as a command which copies the model out to a separate part of memory, applies any changes to vertex positions, then copies it back as soon as ANYTHING else in the scene is worked on. Not even necessarily rendered, just worked on.

Now - the actual mesh deformation, when it's "copied out" is very quick - and changing one vertex or 200 vertices, will take approximately the same amount of time. What chews up the processor is "copying" the mesh out and back again. (Nb: this isn't actually what it's doing, but it's a good analogy to understand how important it is to stack vertexcoord commands).

Say, in a single frame, you went from model to model, changing vertices in each of them, then updating their position, etc - it would create an unusably slow 5fps. You need to reflect ALL changes to vertex positions in a single instance, otherwise your performance is going to crawl.

IE - plan out your system carefully. What you want to do, is first of all find all meshes that need animating that are in the scene, and dump all the results into an array. Find the next frames in each of them, and what NEEDs to be animated in each of them, and dump that in an array. Find out what their new positions will be, if changed, etc, and dump that in an array. THEN, find out if any models on-screen are going to be in the same animated frame at any time and cull all the duplicates, opting for copy entity (or something similar) instead, and dump that in an array.

Next, assign all the meshes that are going to be edited, with handes. AnimatedMesh(1), AnimatedMesh(2), AnimatedSurface(1), AnimatedSurface(2), etc. You want to get all the mesh and surfaces allocated BEFORE starting to use VertexCoords, because using any other 3D command in the middle of VertexCoord changes, causes the mesh to be "copied" back - the slowdown in the process. Then, without any LINEPICKing or VIEWPORTing or anything else, run through the arrays and apply all changes to all meshes on screen all at once.

Copy any entities that need to be copied, and finally, render the scene.

Even this may be too slow. You'll probably have to find ways to "cheat" the updates in between every few frames. Which is why we generally use pre-compiled animated models. I was working on a similar system recently and gave up. Good luck! :)

+BlackD


sswift(Posted 2005) [#4]
Where did you get this info?

Would a loop like this would be really slow with what you're talking about?


		For To_X = 0 To Tile_Subdivision
			
						From_X = To_X
			
						Tile_Vertex = To_Z*(Tile_Subdivision+1) + To_X
						VX# = VertexX#(Tile_Surface, Tile_Vertex)
						VZ# = VertexZ#(Tile_Surface, Tile_Vertex)
						
						Neighbor_Vertex = From_Z*(Neighbor_Subdivision+1) + From_X
						VY# = VertexY#(Neighbor_Surface, Neighbor_Vertex)
													
						VertexCoords Tile_Surface, Tile_Vertex, VX#, VY#, VZ#								

					Next



If this is true, it kinda sucks that this information wasn't made available sooner. I thought Blitz was updating the vertex positions just before I called renderworld. But I guess it makes sense that it would do it before linepick. Maybe it should do it when you call uipdateworld, though that would update the collisions, so if this is the case, maybe it needs a specific function for forcing the update at certain times so you can just do it once per loop.


BlackD(Posted 2005) [#5]
sswift.. here's an example demonstrating it. Most of the code you can ignore - the key parts are MoveVertsFast() and MoveVertsSlow(), the two last functions.

The program starts in fast mode, 1 toggles fast, and 2 toggles slow.

The difference is, in fast mode, it stores all vertex change info in an array, then applies it all at the end before the updateworld.
In slow mode, it applies the changes "while working".. in fact, the only command difference here is the CameraPick in each loop, then likewise updateworld's. In both examples it's doing at least 20 CameraPick's a frame - that's not slowing it down. It's just in slow mode - it does it between updating verts.

I get 60fps in fast mode, and 20fps in slow.



If your computer is particularly l33t and you get no speed difference, then try changing SIZE to 30, or 60.

The thing is - in this example, it's moving 3 verts for 20 tri's at random. That's ONLY updating 60verts in each frame, and you get that large a performance impact if you don't stack the updates all together in one lump. Now imagine trying to write an animation system in Blitz3D as this fellow is, where in animated models - several thousand verts are going to be updated each frame. Personally, I don't think it's possible.

I think if animating meshes in Blitz like this, it'd actually be faster to re-create the entire mesh each time rather than dynamically deform it.

+BlackD


sswift(Posted 2005) [#6]
Okay well I tried it with a 64x64 mesh and the fast version goes at like 6fps, which is what my own experience in the past was, so unless getting the vertex locations also triggers this upload I probably haven't run into this issue in my own code, because there's not many reasons to do a linepick and move vertces at the same time.

Have you tested to see if getting the vertex locations also has an impact on the speed?


BlackD(Posted 2005) [#7]
Oh absolutely sswift .. writing efficient code you wouldn't even do it the way I wrote above. That was just concept code to illustrate the point I was trying to make to SomethingFunky. That being, you have to plan your mesh animation code carefully. He was talking about using a AnimateMyModel() command to animate the meshs and I'm saying - uhuh, that's a bad idea. Such a command would be conditional on circumstances in the main loop, therefore it'd be in amongst a whole bunch of other code - and with several models being animated, and other stuff going on int he scene at once, he'd get a huge slowdown.

Hence, the scope of an AnimateMyModel() command should simply be to store references to mesh animations and not to do them then, but to store them and - as you suggested - update all the mesh's once before UPDATEWORLD (or before collisions, or whatever you want) per loop, rather than updating vertices multiple times in multiple places.

+BlackD


Ross C(Posted 2005) [#8]
Interesting information, thanks :o)


markcw(Posted 2005) [#9]
thanks for the help. i liked the example code, it was fun!

i had a quick look at the code pieces and am getting somewhere at least. the models are low-poly (about 100-500 vertices) and slow animating (about 10-50 fps) which means the fastest updates no more than 5 times a second.

i'll have to test (of course) to see if an updateallmodels() system is faster than an updatemymodel() loop, so thanks for the sound advice! and now i'm off to.. write a function or something.


Mr Snidesmin(Posted 2005) [#10]
Jellyfish Animation

My first ever 3d animation. . . (just about sort of)

I would like to be able to display at least 20 of these at a time in a game with loads of other stuff going on, but I've no idea how to store the animation, replay etc quickly.

Someone help me please! :O)


markcw(Posted 2005) [#11]
mr snidesmin, i liked that demo, so i scraped an example together this evening which shows a way to do this. you could use types but i can't understand them yet, so it uses arrays.

the biggest problem is poly count, on my system i only get 5 jellyfish comfortably and fps drops at 10000 tris. to get more you'd need to crunch less vertices, so you'd need a lod system based on distance and whether its in camera view.




BlackD(Posted 2005) [#12]
TYPEs are l33t. Learn them. :)


Damien Sturdy(Posted 2005) [#13]
I have an idea.
[edit] forgot the basic idea

To wrap all vertex commands to vertex2 counterparts,

inside the wrapped functions, instead of doing it, store a list in types

Have an Updatevertices() function to itterate the list and actually make the changes in an organised way.

Not sure if this will be faster, and theres likely parts i wont be able to do efficiently,

I'll be releasing source anyway so you lot can improve! :)
Expect an update later.


Mr Snidesmin(Posted 2005) [#14]
somethingfunky,

The code alteration looks okay, though, you don't have to save 3 different wave params per jelly fish, because that part just gives a global kind of wave effect. the same 3 parameters can be used for all jelly fish, but i suppose the time saved would be neglible anyway.

The whole thing has kind of given me an idea though - perhaps saving 4 or 5 base meshes to represent the cycle and then using tween-morphing between each one will be slightly more efficient. If the tweening was linear, I wouldn't have to use the expensive sin/cos + sqr functions, but the animation mightn't look quite as good.

Oh, and I will be switching to types - sorry, they are just way easy to get your head around than arrays!

Also, using LOD might be a genius idea too. . . but for starters I think I'll create a much lower poly mesh using 3ds Max for the jelly. I shouldn't be needing over 2000 tris for a jellyfish - now come on! :O)


Gabriel(Posted 2005) [#15]
You know, this would be a lot easier ( well faster, anyway ) if Blitz had a parameter to optionally buffer vertexcoords updates. Then you could do 2000 vertex updates by updating 1999 vertices without updating the mesh, then setting the flag to update the mesh on the 2000th mesh.

Obviously vertex shaders would be ideal, particularly since they fall back to software on videocards which don't have hardware support, but we all know that's never gonna happen.


Damien Sturdy(Posted 2005) [#16]
This functionality is coming.

http://www.blitzbasic.com/Community/posts.php?topic=51697

Coming soon to a Blitz near you!

VertexCoords2, vertexTexCoords2, Vertexcolor2,

Any more? @#!* easy for me to add them :)

I will post code when i get home for y'all to test, in the above thread.


markcw(Posted 2005) [#17]
mr snidesmin, i was curious to see how much fps would be saved by using a pre-calculated array instead of the slow sin/cos/sqr. seems quite a bit! so i thought i'd let you, or anyone else, know. the code below is a quick example just to show the speed increase.




Mr Snidesmin(Posted 2005) [#18]
somethingfunky,

I just tried that out - very VERY nice!
it's a huge improvement in performance. . . thanks!!!

:O)

[edit] I can render over 40 jellies before any signifcant loss in framerate. This is more than adequate considering the mesh is going to be much much fewer verts.

I'll probably be able to render near 100 of them with a small mesh!

Yay!