Thread: Exporting & Importing Animated models

Results 1 to 2 of 2
  1. #1 Exporting & Importing Animated models 

    Join Date
    Jul 2014
    Thanks given
    Thanks received
    View profile
    Rep Power
    This is just something I explained in discord today(how to export runescape's animated models and also import models created & animated in blender or other tools to runescape's format) however there's a good chance it'll just get lost which is why i decided to also create a thread for it(it just contains the text from discord copy pasted with a little bit of formatting)
    NOTE: if you don't already understand how the runescape's animation system works which i assume u do when reading this, please read this thread where i explained it in depth:

    A bit about animations:
    There are 2 'main' types of animation:
    Skeletal animation, Keyframe animation
    With keyframe animation you simply store the model's vertices for each keyframe
    So for example:
    Keyframe 0: default pose(original vertices)
    Keyframe 5: Rotated pose(vertices where the shoulder vertices have been rotated by some amount)
    Keyframe 10: default pose(original vertices)

    However this is not ideal, and that's why skeletal animation is definitely more common nowadays

    It is not ideal because each frame of the animation is pretty much a completely new mesh

    With skeletal animation you store the bone's(basically you have an armature which is a collection of bones) position at each keyframe and the 'change' in each vertex is determined by the weight of the vertex(it's influence by that bone)

    What's a bone? it's simply a transformation and each vertex in the mesh is influenced by 1 or more bones, how much it is influenced by depends on the weight of that vertex to that bone

    What runescape uses is pretty much keyframe animation, before each frame a new model(copy of the original model) is created

    if some of that still didn't make feel free to ask and i can probably clarify

    Exporting animated rs models:
    Goal: Generate a hierarchy/armature which is just a collection of bones that can be linked (for example the shoulder bone is connected to the elbow bone and so on)

    Alright so how do we generate the hierarchy? well since i said we want to export already animated models that means that at least 1 animation has already made for that model, so we simply inspect that animation to 'infer' the hierarchy

    Well it is actually quite simple, very often(p much always) our animation affects the vertices of the whole model so we can easily build the 'perfect' hierarchy/armature

    Lets say we want to export the character model and we're inspecting the running animation
    Well the running animation mostly moves the shoulders but it also moves the body, hands(how often each part is moved or by what factor we don't care about, we just need it to transform at least once)

    So how do we infer?
    Well lets say we have the following transformations for the legs:
    'leg' is transformed
    'knee' is transformed
    'foot' is transformed

    We then check whether the 'leg' also moved all the vertices that were moved during the 'knee' transformation
    If it was then we can infer that whenever leg transforms, knee should also be transformed therefore 'knee' is a child of 'leg'
    Then for the 'knee' we do the exact same and we find that whenever the 'knee' is moved 'foot' also always moves therefore 'foot' is a child of 'knee'
    so the hierarchy is already:
    leg -> knee -> foot
    meaning if the leg moves then both knee and foot should move aswell

    the same applies for other parts (like shoulder -> elbow -> hand) and so on

    Alright so now step 1 is done which was building the hierarchy

    Now, how do we determine the weights of each vertex? lets look at a vertex that is part of the knee for example, we see that it is influenced by both the leg and knee which would indicate that the influence for both bones(leg, knee) would be 0.5, that would work but we can make this much simpler
    Instead of multiple influences we can only have 1(and it'll work perfectly) however for that we need to do some filtering on our bones

    Basically we want to assign the influenced vertices to the deepest node/bone(following child relationships) that has it

    So we check for every node/bone whether any child also has that vertex, if that is the case then we drop it, if no child has the vertex then it is the deepest one and we can keep it

    Simple right? well yes but if you think about it, it won't really work perfectly

    So we have 2 options which is to traverse them in breadth first order or only apply the new influenced vertex lists after all(all the bones) have been processed, i chose the 2nd which is to have a `Map<Bone, List<Integer>>` and set the influenced vertices of each bone after i processed all of them

    Now because each vertex is only influenced by exactly one bone we can just have each vertex have a weight of 1

    And that's it for exporting(again, if something was unclear feel free to ask and i can clarify)

    Importing animated models in blender(or some other tool) to rs:
    Goal: Given an armature(collection of bones) and the animation itself(list of keyframes) we want to convert that to runescape's format

    Lets start with the bones, remember that a bone is just a transformation and each vertex is influenced by one or more bones, the influence depends on the weight of that vertex for that bone

    Remember that in rs the skeleton is pretty much created by labels(if u don't know what those are, then check my latest thread in forums) and we can very easily create those labels by knowing which bone(s) each vertex is influenced by

    lets look at a simple example where we have a mesh with the following vertices:
    [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
    Assume that those vertices somehow define a leg where the first 5 define the upper part of the leg, the next 3 define the knee) and the last 2 define the foot

    Now lets say our leg was animated in blender and it uses 3 bones (one for the upper part of the leg, one for the knee and one for the foot)

    The influences are the following:
    1: 1
    2: 1
    3: 1
    4: 1
    5: 1
    6: 2
    7: 2
    8: 2
    9: 3
    10: 3
    which means that vertex 1-5 is influenced by bone 1, vertex 6-8 is influenced by bone 2 and vertex 9 & 10 is influenced by bone 3

    So we can easily create the labels [1, 2, 3] where vertices 1-5 use label 1, vertices 6-8 use label 2 and vertices 9 & 10 use label 3

    that is quite literally it for exporting the bones(simple init)

    Now how do we convert the animation itself we created to rs format?
    Also quite simple, our animation data in blender(and other tools) basically tells us how the bones were transformed(translated, rotated or scaled) in each frame

    Lets use the same example as above where we have 3 bones [1, 2, 3] for the leg and the default locations for the bones are:
    0, 0, 0(leg)
    0, 10, 0(knee)
    0, 20, 0(foot)
    Now to make this simpler to explain assume that vertex has a weight of 1 like before, so each vertex is only influenced by one bone

    And we have the following keyframes for the bones:
    Keyframe at 0:
    0, 0, 0
    0, 10, 0
    0, 20, 0
    Keyframe at 5:
    0, 50, 0
    0, 60, 0
    0, 80, 0
    Keyframe at 10:
    0, 0, 0
    0, 10, 0
    0, 20, 0
    Which shows that the bones were at their original position at frame 0, at frame 5 all of them moved in the y direction by 50 and then moved back to their original position at frame 10

    That gives us 2 transformations and 2 frames(as the transformations happend at different keyframes) of course usually there are more transformations in 1 frame than just one(it's just easier to explain with just 1)
    1) The whole leg is moved by 50 in the y direction
    2) The whole leg is moved by -50 in the y direction(So back to it's original position)

    In this case the bones were simply translated(in both transformations) so in rs we can create 2 new frames each with 1 group where the `type` for both is `TYPE_TRANSLATION` and the labels for both are [1, 2, 3] because we moved the whole leg and our labels for it are 1, 2, 3(1 for the upper part of the leg, 2 for the knee, 3 for the foot)

    Now lets assume that we had a transformation where the bone was actually rotated instead of translated, that means that we need a rotation origin which is defined by the type `SET_ORIGIN` in rs format
    In blender the rotation origin is simply the bone's location at that time(This is why bone location & rotation matters) and in rs it is computed by averaging a set of vertices, so what we have to do is simply create a vertex from the location of the bone and set that to be used in the `SET_ORIGIN` transformation type before the rotation for that specific bone happens

    Alright that should be it(hopefully i didn't miss anything) but now you might've realized that for each animation made in blender we create a new model as well.
    So lets say we exported the Vet'ion model and it's armature to blender and created a new animation for it using that armature(so no modifications were made to the armature or the weights)
    So even tho we used the same armature we still created a new model, which isn't ideal, so what can we do?

    Well we could for example store the label ids when exporting and use those label ids when importing and that would pretty much solve the problem right? well not quite because remember that we also had to filter the labels earlier as we needed exactly 1 influence per vertex so we would also have to undo that.
    There are multiple solutions to this problem and it is definitely solvable(one would be to use multiple influences and not filter the labels at all however the better solution here would be to simply just 'undo' the filtering as it would reduce the influences per vertex which is good and it's also very easy to do.

    Ight for whoever actually reads this, feel free to ask questions.
    Reply With Quote  

  2. #2  
    Ⱨ₳Ɽ₳₥ ₳₴ ₣Ʉ₵₭

    Owain's Avatar
    Join Date
    Sep 2014
    Thanks given
    Thanks received
    View profile
    Rep Power
    Nice one sooick

    The pioneering custom server network

    Spoiler for wat:

    Reply With Quote  

Thread Information
Users Browsing this Thread

There are currently 1 users browsing this thread. (0 members and 1 guests)

User Tag List

Similar Threads

  1. Replies: 8
    Last Post: 07-06-2021, 03:12 PM
  2. Instead of Adding Animations/Models to 317
    By Profesor Oak in forum RS2 Client
    Replies: 21
    Last Post: 09-13-2009, 07:03 PM
  3. warriors guild animator model
    By wouha in forum Help
    Replies: 0
    Last Post: 09-01-2009, 02:07 PM
  4. New animations & models?
    By iZAjz in forum RS 503+ Client & Server
    Replies: 27
    Last Post: 07-19-2009, 05:37 PM
  5. [Help] Animating models
    By Treznax in forum Models
    Replies: 8
    Last Post: 11-14-2008, 02:33 AM
Posting Permissions
  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts