mirror of
https://github.com/godotengine/godot-docs.git
synced 2026-01-04 14:11:02 +03:00
Merge pull request #1401 from acfaruk/typos
fix various typos and grammatical errors
This commit is contained in:
committed by
mhilbrunner
parent
d0d47ea1f8
commit
bd7f3d6171
@@ -263,7 +263,7 @@ The real strength of this system, though, is to combine levels to create more in
|
||||
|
||||
.. image:: img/environment_glow_layers2.png
|
||||
|
||||
Finally, as the highest layers are created by stretching small blurred images, it is possible that some blockyness may be visible. Enabling **Bicubic Upscaling** gets rids of the it,
|
||||
Finally, as the highest layers are created by stretching small blurred images, it is possible that some blockyness may be visible. Enabling **Bicubic Upscaling** gets rids of it,
|
||||
at a minimal performance cost.
|
||||
|
||||
.. image:: img/environment_glow_bicubic.png
|
||||
|
||||
@@ -6,43 +6,43 @@ Inverse kinematics
|
||||
This tutorial is a follow-up of :ref:`doc_working_with_3d_skeletons`.
|
||||
|
||||
Before continuing on, I'd recommend reading some theory, the simplest
|
||||
article I find is this:
|
||||
article I could find is this:
|
||||
|
||||
http://freespace.virgin.net/hugo.elias/models/m_ik2.htm
|
||||
|
||||
Initial problem
|
||||
~~~~~~~~~~~~~~~
|
||||
|
||||
Talking in Godot terminology, the task we want to solve here is position
|
||||
our 2 angles we talked about above so, that the tip of lowerarm bone is
|
||||
as close to target point, which is set by target Vector3() as possible
|
||||
Talking in Godot terminology, the task we want to solve here is to position
|
||||
our 2 angles we talked about above so, that the tip of the lowerarm bone is
|
||||
as close to the target point (which is set by the target Vector3()) as possible
|
||||
using only rotations. This task is very calculation-intensive and never
|
||||
resolved by analytical equation solve. So, it is an underconstrained
|
||||
problem, which means there is unlimited number of solutions to the
|
||||
resolved by analytical equation solving. So, it is an underconstrained
|
||||
problem, which means there is an unlimited number of solutions to the
|
||||
equation.
|
||||
|
||||
.. image:: img/inverse_kinematics.png
|
||||
|
||||
For easy calculation, for this chapter we consider target is also
|
||||
child of Skeleton. If it is not the case for your setup you can always
|
||||
For easy calculation, in this chapter we consider the target being a
|
||||
child of Skeleton. If this is not the case for your setup you can always
|
||||
reparent it in your script, as you will save on calculations if you
|
||||
do.
|
||||
do so.
|
||||
|
||||
In the picture you see angles alpha and beta. In this case we don't
|
||||
In the picture you see the angles alpha and beta. In this case we don't
|
||||
use poles and constraints, so we need to add our own. On the picture
|
||||
the angles are 2D angles living in plane which is defined by bone
|
||||
the angles are 2D angles living in a plane which is defined by bone
|
||||
base, bone tip and target.
|
||||
|
||||
The rotation axis is easily calculated using cross-product of bone
|
||||
vector and target vector. The rotation in this case will be always in
|
||||
positive direction. If t is the Transform which we get from
|
||||
The rotation axis is easily calculated using the cross-product of the bone
|
||||
vector and the target vector. The rotation in this case will be always in
|
||||
positive direction. If ``t`` is the Transform which we get from the
|
||||
get_bone_global_pose() function, the bone vector is
|
||||
|
||||
::
|
||||
|
||||
t.basis[2]
|
||||
|
||||
So we have all information here to execute our algorithm.
|
||||
So we have all the information we need to execute our algorithm.
|
||||
|
||||
In game dev it is common to resolve this problem by iteratively closing
|
||||
to the desired location, adding/subtracting small numbers to the angles
|
||||
@@ -51,19 +51,19 @@ Sounds easy enough, but there are Godot problems we need to resolve
|
||||
there to achieve our goal.
|
||||
|
||||
- **How to find coordinates of the tip of the bone?**
|
||||
- **How to find vector from bone base to target?**
|
||||
- **How to find the vector from the bone base to the target?**
|
||||
|
||||
For our goal (tip of the bone moved within area of target), we need to know
|
||||
where the tip of our IK bone is. As we don't use a leaf bone as IK bone, we
|
||||
know the coordinate of the bone base is the tip of parent bone. All these
|
||||
know the coordinate of the bone base is the tip of the parent bone. All these
|
||||
calculations are quite dependent on the skeleton's structure. You can use
|
||||
pre-calculated constants as well. You can add an extra bone for the tip of
|
||||
IK and calculate using that.
|
||||
pre-calculated constants as well. You can add an extra bone at the tip of the
|
||||
IK bone and calculate using that.
|
||||
|
||||
Implementation
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
We will just use exported variable for bone length to be easy.
|
||||
We will just use an exported variable for the bone length to make it easy.
|
||||
|
||||
::
|
||||
|
||||
@@ -71,16 +71,16 @@ We will just use exported variable for bone length to be easy.
|
||||
export var ik_bone_length = 1.0
|
||||
export var ik_error = 0.1
|
||||
|
||||
Now, we need to apply our transformations from IK bone to the base of
|
||||
chain. So we apply rotation to IK bone then move from our IK bone up to
|
||||
its parent, then apply rotation again, then move to the parent of
|
||||
Now, we need to apply our transformations from the IK bone to the base of
|
||||
the chain. So we apply a rotation to the IK bone then move from our IK bone up to
|
||||
its parent, apply rotation again, then move to the parent of the
|
||||
current bone again, etc. So we need to limit our chain somewhat.
|
||||
|
||||
::
|
||||
|
||||
export var ik_limit = 2
|
||||
|
||||
For ``_ready()`` function:
|
||||
For the ``_ready()`` function:
|
||||
|
||||
::
|
||||
|
||||
@@ -110,7 +110,7 @@ And for the ``_process()`` function:
|
||||
func _process(delta):
|
||||
pass_chain(delta)
|
||||
|
||||
Executing this script will just pass through bone chain printing bone
|
||||
Executing this script will just pass through the bone chain, printing bone
|
||||
transforms.
|
||||
|
||||
::
|
||||
@@ -140,17 +140,17 @@ transforms.
|
||||
func _process(delta):
|
||||
pass_chain(delta)
|
||||
|
||||
Now we need to actually work with target. The target should be placed
|
||||
somewhere accessible. Since "arm" is imported scene, we better place
|
||||
target node within our top level scene. But for us to work with target
|
||||
easily its Transform should be on the same level as Skeleton.
|
||||
Now we need to actually work with the target. The target should be placed
|
||||
somewhere accessible. Since "arm" is an imported scene, we better place
|
||||
the target node within our top level scene. But for us to work with target
|
||||
easily its Transform should be on the same level as the Skeleton.
|
||||
|
||||
To cope with this problem we create "target" node under our scene root
|
||||
node and at script run we will reparent it copying global transform,
|
||||
which will achieve wanted effect.
|
||||
To cope with this problem we create a "target" node under our scene root
|
||||
node and at runtime we will reparent it copying the global transform,
|
||||
which will achieve the desired effect.
|
||||
|
||||
Create new Spatial node under root node and rename it to "target".
|
||||
Then modify ``_ready()`` function to look like this:
|
||||
Create a new Spatial node under the root node and rename it to "target".
|
||||
Then modify the ``_ready()`` function to look like this:
|
||||
|
||||
::
|
||||
|
||||
|
||||
@@ -13,17 +13,17 @@ MultiMeshInstance, as the name suggests, creates multiple copies of a MeshInstan
|
||||
Setting up the nodes
|
||||
~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
The basic setup requires three nodes. Firstly, the multiMeshInstance node. Then, two MeshInstance nodes.
|
||||
The basic setup requires three nodes. Firstly, the MultiMeshInstance node. Then, two MeshInstance nodes.
|
||||
|
||||
One node is used as the target, the mesh that you want to place multiple meshes on. In the tree example, this would be the landscape.
|
||||
|
||||
Another node is used as the source, the mesh that you want to have duplicate. In the tree case, this would be the tree.
|
||||
Another node is used as the source, the mesh that you want to have duplicated. In the tree case, this would be the tree.
|
||||
|
||||
In our example, we would use a :ref:`Node <class_Node>` as the root node of the scene. Your scene tree would look like this:
|
||||
|
||||
.. image:: img/multimesh_scene_tree.png
|
||||
|
||||
.. note:: For simplification purpose, this tutorial would use built-in primitives.
|
||||
.. note:: For simplification purposes, this tutorial uses built-in primitives.
|
||||
|
||||
Now you have everything ready. Select the MultiMeshInstance node and look at the toolbar, you should see an extra button called ``MultiMesh`` next to ``View``. Click it and select *Populate surface* in the dropdown menu. A new window titled *Populate MultiMesh* will pop up.
|
||||
|
||||
|
||||
@@ -10,21 +10,21 @@ skeletal animations as a set of transformation matrices.
|
||||
Skeleton node
|
||||
-------------
|
||||
|
||||
Skeleton node can be directly added anywhere you want on scene. Usually
|
||||
The Skeleton node can be directly added anywhere you want on a scene. Usually
|
||||
mesh is a child of Skeleton, as it easier to manipulate this way, as
|
||||
Transforms within skeleton are relative to where Skeleton is. But you
|
||||
can specify Skeleton node in every MeshInstance.
|
||||
Transforms within a skeleton are relative to where the Skeleton is. But you
|
||||
can specify a Skeleton node in every MeshInstance.
|
||||
|
||||
Being obvious, Skeleton is intended to deform meshes, and consists of
|
||||
structures called "bones". Each "bone" is represented as Transform, which is
|
||||
structures called "bones". Each "bone" is represented as a Transform, which is
|
||||
applied to a group of vertices within a mesh. You can directly control a group
|
||||
of vertices from Godot. For that please reference :ref:`class_MeshDataTool`
|
||||
class, method :ref:`set_vertex_bones <class_MeshDataTool_set_vertex_bones>`.
|
||||
of vertices from Godot. For that please reference the :ref:`class_MeshDataTool`
|
||||
class and its method :ref:`set_vertex_bones <class_MeshDataTool_set_vertex_bones>`.
|
||||
This class is very powerful.
|
||||
|
||||
The "bones" are organized in hierarchy, every bone, except for root
|
||||
bone(s) have parent. Every bone have associated name you can use to
|
||||
refer to it (e.g. "root" or "hand.L", etc.). Also bones are all numbered,
|
||||
The "bones" are organized hierarchically, every bone, except for root
|
||||
bone(s) have a parent. Every bone has an associated name you can use to
|
||||
refer to it (e.g. "root" or "hand.L", etc.). Also all bones are numbered,
|
||||
these numbers are bone IDs. Bone parents are referred by their numbered
|
||||
IDs.
|
||||
|
||||
@@ -36,18 +36,18 @@ For the rest of the article we consider the following scene:
|
||||
== skel (Skeleton)
|
||||
==== mesh (MeshInstance)
|
||||
|
||||
This scene is imported from Blender. It contains arm mesh with 2 bones -
|
||||
upperarm and lowerarm, with lowerarm parented to upperarm.
|
||||
This scene is imported from Blender. It contains an arm mesh with 2 bones -
|
||||
upperarm and lowerarm, with the lowerarm bone parented to the upperarm.
|
||||
|
||||
Skeleton class
|
||||
--------------
|
||||
|
||||
You can view Godot internal help for descriptions of every function.
|
||||
You can view Godots internal help for descriptions of all functions.
|
||||
Basically all operations on bones are done using their numeric ID. You
|
||||
can convert from name to numeric ID and vise versa.
|
||||
can convert from a name to a numeric ID and vice versa.
|
||||
|
||||
**To find number of bones in skeleton we use get_bone_count()
|
||||
function**
|
||||
**To find the number of bones in a skeleton we use the get_bone_count()
|
||||
function:**
|
||||
|
||||
::
|
||||
|
||||
@@ -61,7 +61,7 @@ function**
|
||||
var parent = skel.get_bone_parent(id)
|
||||
print("bone parent id:", id)
|
||||
|
||||
**to find ID for the bone, use find_bone() function**
|
||||
**To find the ID of a bone, use the find_bone() function:**
|
||||
|
||||
::
|
||||
|
||||
@@ -73,11 +73,11 @@ function**
|
||||
var id = skel.find_bone("upperarm")
|
||||
print("bone id:", id)
|
||||
|
||||
Now, we want to do something interesting with ID except for printing it.
|
||||
Also, we might need additional information - to find bone parents to
|
||||
complete chain, etc. This all is done with get/set_bone\_\* functions.
|
||||
Now, we want to do something interesting with the ID, not just printing it.
|
||||
Also, we might need additional information - finding bone parents to
|
||||
complete chains, etc. This is done with the get/set_bone\_\* functions.
|
||||
|
||||
**To find bone parent we use get_bone_parent(id) function**
|
||||
**To find the parent of a bone we use the get_bone_parent(id) function:**
|
||||
|
||||
::
|
||||
|
||||
@@ -91,10 +91,10 @@ complete chain, etc. This all is done with get/set_bone\_\* functions.
|
||||
var parent = skel.get_bone_parent(id)
|
||||
print("bone parent id:", id)
|
||||
|
||||
Bone transforms is the thing why we're here at all. There are 3 kind of
|
||||
The bone transforms are the things of our interest here. There are 3 kind of
|
||||
transforms - local, global, custom.
|
||||
|
||||
**To find bone local Transform we use get_bone_pose(id) function**
|
||||
**To find the local Transform of a bone we use get_bone_pose(id) function:**
|
||||
|
||||
::
|
||||
|
||||
@@ -110,11 +110,11 @@ transforms - local, global, custom.
|
||||
var t = skel.get_bone_pose(id)
|
||||
print("bone transform: ", t)
|
||||
|
||||
So we see 3x4 matrix there, with first column of 1s. What can we do
|
||||
about that? It is a Transform, so we can do everything we can do with
|
||||
Transform, basically translate, rotate and scale. Also we can multiply
|
||||
transforms to have complex transforms. Remember, "bones" in Godot are
|
||||
just Transforms over a group of vertices. Also we can copy Transforms of
|
||||
So we get a 3x4 matrix there, with the first column filled with 1s. What can we do
|
||||
with this matrix? It is a Transform, so we can do everything we can do with
|
||||
Transforms, basically translate, rotate and scale. We could also multiply
|
||||
transforms to have more complex transforms. Remember, "bones" in Godot are
|
||||
just Transforms over a group of vertices. We could also copy Transforms of
|
||||
other objects there. So lets rotate our "upperarm" bone:
|
||||
|
||||
::
|
||||
@@ -139,17 +139,17 @@ other objects there. So lets rotate our "upperarm" bone:
|
||||
skel.set_bone_pose(id, t)
|
||||
|
||||
Now we can rotate individual bones. The same happens for scale and
|
||||
translate - try these on your own and see results.
|
||||
translate - try these on your own and check the results.
|
||||
|
||||
What we used now was local pose. By default all bones are not modified.
|
||||
But this Transform tells us nothing about relationship between bones.
|
||||
What we used here was the local pose. By default all bones are not modified.
|
||||
But this Transform tells us nothing about the relationship between bones.
|
||||
This information is needed for quite a number of tasks. How can we get
|
||||
it? Here comes global transform:
|
||||
it? Here the global transform comes into play:
|
||||
|
||||
**To find bone global Transform we use get_bone_global_pose(id)
|
||||
function**
|
||||
**To find the bone global Transform we use get_bone_global_pose(id)
|
||||
function:**
|
||||
|
||||
We will find global Transform for lowerarm bone:
|
||||
Let's find the global Transform for the lowerarm bone:
|
||||
|
||||
::
|
||||
|
||||
@@ -165,9 +165,9 @@ We will find global Transform for lowerarm bone:
|
||||
var t = skel.get_bone_global_pose(id)
|
||||
print("bone transform: ", t)
|
||||
|
||||
As you see, this transform is not zeroed. While being called global, it
|
||||
is actually relative to Skeleton origin. For root bone, origin is always
|
||||
at 0 if not modified. Lets print origin for our lowerarm bone:
|
||||
As you can see, this transform is not zeroed. While being called global, it
|
||||
is actually relative to the Skeleton origin. For a root bone, origin is always
|
||||
at 0 if not modified. Lets print the origin for our lowerarm bone:
|
||||
|
||||
::
|
||||
|
||||
@@ -184,24 +184,24 @@ at 0 if not modified. Lets print origin for our lowerarm bone:
|
||||
print("bone origin: ", t.origin)
|
||||
|
||||
You will see a number. What does this number mean? It is a rotation
|
||||
point of Transform. So it is base part of the bone. In Blender you can
|
||||
point of the Transform. So it is base part of the bone. In Blender you can
|
||||
go to Pose mode and try there to rotate bones - they will rotate around
|
||||
their origin. But what about tip? We can't know things like bone length,
|
||||
which we need for many things, without knowing tip location. For all
|
||||
bones in chain except for last one we can calculate tip location - it is
|
||||
simply a child bone origin. Yes, there are situations when this is not
|
||||
their origin. But what about the bone tip? We can't know things like the bone length,
|
||||
which we need for many things, without knowing the tip location. For all
|
||||
bones in a chain except for the last one we can calculate the tip location - it is
|
||||
simply a child bone's origin. Yes, there are situations when this is not
|
||||
true, for non-connected bones. But that is OK for us for now, as it is
|
||||
not important regarding Transforms. But the leaf bone tip is nowhere to
|
||||
be found. Leaf bone is a bone without children. So you don't have any
|
||||
be found. A leaf bone is a bone without children. So you don't have any
|
||||
information about its tip. But this is not a showstopper. You can
|
||||
overcome this by either adding extra bone to the chain or just
|
||||
calculating leaf bone length in Blender and store the value in your
|
||||
overcome this by either adding an extra bone to the chain or just
|
||||
calculating the length of the leaf bone in Blender and storing the value in your
|
||||
script.
|
||||
|
||||
Using 3D "bones" for mesh control
|
||||
---------------------------------
|
||||
|
||||
Now as you know basics we can apply these to make full FK-control of our
|
||||
Now as you know the basics we can apply these to make full FK-control of our
|
||||
arm (FK is forward-kinematics)
|
||||
|
||||
To fully control our arm we need the following parameters:
|
||||
@@ -220,12 +220,12 @@ Create the following node tree:
|
||||
+ DirectionLight (DirectionLight)
|
||||
+ Camera
|
||||
|
||||
Set up Camera so that arm is properly visible. Rotate DirectionLight
|
||||
so that arm is properly lit while in scene play mode.
|
||||
Set up the Camera so that the arm is properly visible. Rotate DirectionLight
|
||||
so that the arm is properly lit while in scene play mode.
|
||||
|
||||
Now we need to create new script under main:
|
||||
Now we need to create a new script under main:
|
||||
|
||||
First we setup parameters:
|
||||
First we define the setup parameters:
|
||||
|
||||
::
|
||||
|
||||
@@ -234,7 +234,7 @@ First we setup parameters:
|
||||
|
||||
Now we need to setup a way to change them. Let us use keys for that.
|
||||
|
||||
Please create 7 actions under project settings:
|
||||
Please create 7 actions under project settings -> Input Map:
|
||||
|
||||
- **selext_x** - bind to X key
|
||||
- **selext_y** - bind to Y key
|
||||
@@ -320,11 +320,11 @@ The full code for arm control is this:
|
||||
set_bone_rot("lowerarm", lowerarm_angle)
|
||||
set_bone_rot("upperarm", upperarm_angle)
|
||||
|
||||
Pressing keys 1/2 select upperarm/lowerarm, select axis by pressing x,
|
||||
Pressing keys 1/2 selects upperarm/lowerarm, select the axis by pressing x,
|
||||
y, z, rotate using numpad "+"/"-"
|
||||
|
||||
This way you fully control your arm in FK mode using 2 bones. You can
|
||||
add additional bones and/or improve "feel" of the interface by using
|
||||
add additional bones and/or improve the "feel" of the interface by using
|
||||
coefficients for the change. I recommend you play with this example a
|
||||
lot before going to next part.
|
||||
|
||||
@@ -335,7 +335,7 @@ You can clone the demo code for this chapter using
|
||||
git clone git@github.com:slapin/godot-skel3d.git
|
||||
cd demo1
|
||||
|
||||
Or you can browse it using web-interface:
|
||||
Or you can browse it using the web-interface:
|
||||
|
||||
https://github.com/slapin/godot-skel3d
|
||||
|
||||
|
||||
Reference in New Issue
Block a user