Hozq

Inverse Kinematics In Mine-Imator

Recommended Posts

So, i was looking thru some posts and i came across @-StickyMations- IK april fools prank. And since i know a tad bit about Game Maker, i decided to try and actually add IK to Mine-Imator.

It worked surprisingly well, one downside is that i only managed to get it to work on one body part. It kept on crashing when i tried to put in on anything else. Since i only know a "tad" bit about Game Maker i couldn't solve this problem. I had to look up tutorials on how to make IK in Game Maker to make it work. I only have a GIF for now but i'll come with more updates soon.

Gsve2rO.gif

Edited by Hozq

Share this post


Link to post
Share on other sites

k, i kinda believe you now... sort f

I'm wondering something though...if you who knows a BUT in GM can do this, why hasn't David or Nimi done this? Not really asking you...just seems strange...

Just let it be known that i'm skeptical about this.

Share this post


Link to post
Share on other sites
1 minute ago, Spontaneous Explosions said:

k, i kinda believe you now... sort f

I'm wondering something though...if you who knows a BUT in GM can do this, why hasn't David or Nimi done this? Not really asking you...just seems strange...

Just let it be known that i'm skeptical about this.

click on the link pls https://gyazo.com/9e9ad2a917e4d6fbab5b9880dc61476b

Edited by Hozq

Share this post


Link to post
Share on other sites

I posted once a status update about Inverse Kinematics and described the maths on Discord (I had also a doubt if it should be posted in a new topic, but lastly decided to not to do it). The problem is, math is only a part of the system. There's also need to code the UI for that, I was posting the example also on the Discord.

UI

Each keyframe for the bendable object would have a bool: whether to use IK or not. If not, it's all like now. If IK is used, there's a second position tab instead of a rotation tab, to manage the IK controller (I think there should be light blue arrows and light blue sphere for that.) If the transition is between two keyframes that have IK on, the IK controller will move instead of transitioning the rotations and bending directly. If between IK and FK or between two FK, the rotations would transist directly (like now). Also, when toggling between IK and FK mode, the position of IK controller/rotations+bend of the object would be calculated automatically so the limb wouldn't move (that might be helpful in certain situations).

Math (you might not understand nothing below, don't complain to me if so :P)

To make IK working, there should be equations for calculating the limb positions though. The main things we need to calculate first are the distance between the object root point (rotation point) and IK controller and the angle between these points.

You can use this pseudocode for reference:

#pseudocode

// Expectations:
// Because of Mine-imator limitations, only two-bone implementation will be demonstrated here.
// Object position will be (0, 0, 0), because it's easier and we have a reference points (all points declared below are relative to object root position).

// BELOW THERE ARE VARIABLES THAT SHOULD BE COPIED/USED FROM EXISTING MINE-IMATOR CODE.
var cPos = {x = 0, y = -6, z = 0} // IK controller position
var bones = {3, 3} // two bones, because we have one bending point, therefore we can have support for multiple bendings in various positions in the future

// BELOW THERE ARE FUNCTIONS THAT ARE JUST HELPING DOING MATHS AND DOES NOT AFFECT DIRECTLY INTO INVERSE KINEMATICS SIMULATION.
func diagonal(x, y) {
// Simple Pythagorean theorem...
return(((x ^ 2) + (y ^ 2)) !^ 2)
}

func angleToPoint(x, y) {
// An angle between the point (0, 0) and the point (x, y) in degrees.
[...]
}

func add(array) {
// Example: if array = {0, 5, -3, 666}, the output will be 0 + 5 + -3 + 666 = 668.
localvar total = 0
for i = 0, bones.length {
total += bones[i]
}
return(total)
}

// BELOW THERE IS CODE THAT IS NECESSARY TO CALCULATE BENDINGS/ROTATIONS IN MINE-IMATOR.
// THAT CODE SHOULD BE EXECUTED EVERY FRAME TO WORK PROPERLY.
var limbLength = add(bones) // It's basically addition of all numbers in "bones" variable.
var desiredLen = diagonal(diagonal(cPos[0], cPos[1]), cPos[2]) // Length between the object position and the controller position.
var desiredRot = {x = angleToPoint(cPos[1], cPos[2]), y = angleToPoint(cPos[0], cPos[2]), z = angleToPoint(cPos[0], cPos[1])} // Rotations in each axis between the object position and the controller position.

var stretching = desiredLen > limbLength // If it's true, the bone will be stretched. Because I think it looks fancy, I think stretching wouldn't be necessary there.

// Now that's there the magic happens.
// We can imagine a triangle where we have its three sides, and we need to calculate the angles between each side.
/*

  R
  |\
  |x\ b
a |  \
  | y/
  |z/ c
  |/
  C

where:
a = distance between the root and IK controller (given)
b, c = bone lengths (given)
x = the object rotation (we should calculate this)
y = the bending angle (we should calculate this)
z = calculating the 3rd angle isn't necessary
R = the object root position (here: (0, 0, 0))
C = the IK controller position (given)
*/
//
if !stretching {
}

To Be Edited soon, again.

Edited by jakubg1
Code update

Share this post


Link to post
Share on other sites
1 hour ago, jakubg1 said:

         -snip-


#pseudocode

// Object position will be (0, 0, 0), because it's easier and we have a reference points (all points declared below are relative to object root position).
var cPos = {x = 0, y = -6, z = 0} // IK controller position
var bones = {3, 3} // two bones, because we have one bending point, therefore we can have support for multiple bendings in various positions
var desiredLen = diagonal(diagonal(cPos[0], cPos[1]), cPos[2]) // Length between the object position and the controller position.
var desiredRot = {x = angleToPoint(cPos[1], cPos[2]), y = angleToPoint(cPos[0], cPos[2]), z = angleToPoint(cPos[0], cPos[1])} // Rotations in each axis between the object position and the controller position.

func diagonal(x, y) {
// Simple Pythagorean theorem...
return(((x ^ 2) + (y ^ 2)) !^ 2)
}

func angleToPoint(x, y) {
// An angle between the point (0, 0) and the point (x, y) in degrees.
[...]
}

func limbLength() {
// in example: 6
var total = 0
for i = 0, bones.length {
total += bones[i]
}
return(total)
}

 To Be Edited soon.

That went over my head but it sounds good!

Edited by MikTRF

Share this post


Link to post
Share on other sites
On 7/7/2018 at 8:11 PM, jakubg1 said:

I posted once a status update about Inverse Kinematics and described the maths on Discord (I had also a doubt if it should be posted in a new topic, but lastly decided to not to do it). The problem is, math is only a part of the system. There's also need to code the UI for that, I was posting the example also on the Discord.

UI

Each keyframe for the bendable object would have a bool: whether to use IK or not. If not, it's all like now. If IK is used, there's a second position tab instead of a rotation tab, to manage the IK controller (I think there should be light blue arrows and light blue sphere for that.) If the transition is between two keyframes that have IK on, the IK controller will move instead of transitioning the rotations and bending directly. If between IK and FK or between two FK, the rotations would transist directly (like now). Also, when toggling between IK and FK mode, the position of IK controller/rotations+bend of the object would be calculated automatically so the limb wouldn't move (that might be helpful in certain situations).

Math (you might not understand nothing below, don't complain to me if so :P)

To make IK working, there should be equations for calculating the limb positions though. The main things we need to calculate first are the distance between the object root point (rotation point) and IK controller and the angle between these points.

You can use this pseudocode for reference:


#pseudocode

// Object position will be (0, 0, 0), because it's easier and we have a reference points (all points declared below are relative to object root position).
var cPos = {x = 0, y = -6, z = 0} // IK controller position
var bones = {3, 3} // two bones, because we have one bending point, therefore we can have support for multiple bendings in various positions
var desiredLen = diagonal(diagonal(cPos[0], cPos[1]), cPos[2]) // Length between the object position and the controller position.
var desiredRot = {x = angleToPoint(cPos[1], cPos[2]), y = angleToPoint(cPos[0], cPos[2]), z = angleToPoint(cPos[0], cPos[1])} // Rotations in each axis between the object position and the controller position.

func diagonal(x, y) {
// Simple Pythagorean theorem...
return(((x ^ 2) + (y ^ 2)) !^ 2)
}

func angleToPoint(x, y) {
// An angle between the point (0, 0) and the point (x, y) in degrees.
[...]
}

func limbLength() {
// in example: 6
var total = 0
for i = 0, bones.length {
total += bones[i]
}
return(total)
}

To Be Edited soon.

i have no idea what you are talking about but i hope this goes well :D

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

  • Recently Browsing   0 members

    No registered users viewing this page.