+
+In order to compute the value of the translation for the current animation time, the following algorithm can be used:
+
+* Let the current animation time be given as `currentTime`.
+* Compute the next smaller and the next larger element of the *times* accessor:
+
+ `previousTime` = The largest element from the *times* accessor that is smaller than the `currentTime`
+
+ `nextTime` = The smallest element from the *times* accessor that is larger than the `currentTime`
+
+* Obtain the elements from the *translations* accessor that correspond to these times:
+
+ `previousTranslation` = The element from the *translations* accessor that corresponds to the `previousTime`
+
+ `nextTranslation` = The element from the *translations* accessor that corresponds to the `nextTime`
+
+* Compute the interpolation value. This is a value between 0.0 and 1.0 that describes the *relative* position of the `currentTime`, between the `previousTime` and the `nextTime`:
+
+ `interpolationValue = (currentTime - previousTime) / (nextTime - previousTime)`
+
+* Use the interpolation value to compute the translation for the current time:
+
+ `currentTranslation = previousTranslation + interpolationValue * (nextTranslation - previousTranslation)`
+
+
+### Example:
+
+Imagine the `currentTime` is **1.2**. The next smaller element from the *times* accessor is **0.8**. The next larger element is **1.6**. So
+
+ previousTime = 0.8
+ nextTime = 1.6
+
+The corresponding values from the *translations* accessor can be looked up:
+
+ previousTranslation = (14.0, 3.0, -2.0)
+ nextTranslation = (18.0, 1.0, 1.0)
+
+The interpolation value can be computed:
+
+ interpolationValue = (currentTime - previousTime) / (nextTime - previousTime)
+ = (1.2 - 0.8) / (1.6 - 0.8)
+ = 0.4 / 0.8
+ = 0.5
+
+From the interpolation value, the current translation can be computed:
+
+ currentTranslation = previousTranslation + interpolationValue * (nextTranslation - previousTranslation)
+ = (14.0, 3.0, -2.0) + 0.5 * ( (18.0, 1.0, 1.0) - (14.0, 3.0, -2.0) )
+ = (14.0, 3.0, -2.0) + 0.5 * (4.0, -2.0, 3.0)
+ = (16.0, 2.0, -0.5)
+
+So when the current time is **1.2**, then the `translation` of the node is **(16.0, 2.0, -0.5)**.
+
+
+
+## Animation channels
+
+The animations contain an array of [`animation.channel`](https://www.khronos.org/registry/glTF/specs/2.0/glTF-2.0.html#reference-animation-channel) objects. The channels establish the connection between the input, which is the value that is computed from the sampler, and the output, which is the animated node property. Therefore, each channel refers to one sampler, using the index of the sampler, and contains an [`animation.channel.target`](https://www.khronos.org/registry/glTF/specs/2.0/glTF-2.0.html#reference-animation-channel-target). The `target` refers to a node, using the index of the node, and contains a `path` that defines the property of the node that should be animated. The value from the sampler will be written into this property.
+
+In the example above, there are two channels for the animation. Both refer to the same node. The path of the first channel refers to the `translation` of the node, and the path of the second channel refers to the `rotation` of the node. So all objects (meshes) that are attached to the node will be translated and rotated by the animation, as shown in Image 7b.
+
+
+
+Image 7b: Animation channels.
+
+
+## Interpolation
+
+The above example only covers `LINEAR` interpolation. Animations in a glTF asset can use three interpolation modes :
+
+ - `STEP`
+ - `LINEAR`
+ - `CUBICSPLINE`
+
+### Step
+
+The `STEP` interpolation is not really an interpolation mode, it makes objects jump from keyframe to keyframe *without any sort of interpolation*. When a sampler defines a step interpolation, just apply the transformation from the keyframe corresponding to `previousTime`.
+
+### Linear
+
+Linear interpolation exactly corresponds to the above example. The general case is :
+
+Calculate the `interpolationValue`:
+
+```
+ interpolationValue = (currentTime - previousTime) / (nextTime - previousTime)
+```
+
+For scalar and vector types, use a linear interpolation (generally called `lerp` in mathematics libraries). Here's a "pseudo code" implementation for reference
+
+```
+ Point lerp(previousPoint, nextPoint, interpolationValue)
+ return previousPoint + interpolationValue * (nextPoint - previousPoint)
+```
+
+In the case of rotations expressed as quaternions, you need to perform a spherical linear interpolation (`slerp`) between the previous and next values:
+
+```
+ Quat slerp(previousQuat, nextQuat, interpolationValue)
+ var dotProduct = dot(previousQuat, nextQuat)
+
+ //make sure we take the shortest path in case dot Product is negative
+ if(dotProduct < 0.0)
+ nextQuat = -nextQuat
+ dotProduct = -dotProduct
+
+ //if the two quaternions are too close to each other, just linear interpolate between the 4D vector
+ if(dotProduct > 0.9995)
+ return normalize(previousQuat + interpolationValue(nextQuat - previousQuat))
+
+ //perform the spherical linear interpolation
+ var theta_0 = acos(dotProduct)
+ var theta = interpolationValue * theta_0
+ var sin_theta = sin(theta)
+ var sin_theta_0 = sin(theta_0)
+
+ var scalePreviousQuat = cos(theta) - dotproduct * sin_theta / sin_theta_0
+ var scaleNextQuat = sin_theta / sin_theta_0
+ return scalePreviousQuat * previousQuat + scaleNextQuat * nextQuat
+```
+
+This example implementation is inspired from this [Wikipedia article](https://en.wikipedia.org/wiki/Slerp)
+
+### Cubic Spline interpolation
+
+Cubic spline interpolation needs more data than just the previous and next keyframe time and values, it also need for each keyframe a couple of tangent vectors that act to smooth out the curve around the keyframe points.
+
+These tangent are stored in the animation channel. For each keyframe described by the animation sampler, the animation channel contains 3 elements :
+
+ - The input tangent of the keyframe
+ - The keyframe value
+ - The output tangent
+
+ The input and output tangents are normalized vectors that will need to be scaled by the duration of the keyframe, we call that the deltaTime
+
+ ```
+ deltaTime = nextTime - previousTime
+ ```
+
+ To calculate the value for `currentTime`, you will need to fetch from the animation channel :
+
+ - The output tangent direction of `previousTime` keyframe
+ - The value of `previousTime` keyframe
+ - The value of `nextTime` keyframe
+ - The input tangent direction of `nextTime` keyframe
+
+*note: the input tangent of the first keyframe and the output tangent of the last keyframe are totally ignored*
+
+To calculate the actual tangents of the keyframe, you need to multiply the direction vectors you got from the channel by `deltaTime`
+
+```
+ previousTangent = deltaTime * previousOutputTangent
+ nextTangent = deltaTime * nextInputTangent
+```
+
+The mathematical function is described in the [Appendix C](https://www.khronos.org/registry/glTF/specs/2.0/glTF-2.0.html#appendix-c-interpolation) of the glTF 2.0 specification.
+
+Here's a corresponding pseudocode snippet :
+
+```
+ Point cubicSpline(previousPoint, previousTangent, nextPoint, nextTangent, interpolationValue)
+ t = interpolationValue
+ t2 = t * t
+ t3 = t2 * t
+
+ return (2 * t3 - 3 * t2 + 1) * previousPoint + (t3 - 2 * t2 + t) * previousTangent + (-2 * t3 + 3 * t2) * nextPoint + (t3 - t2) * nextTangent;
+```
+
+
+Previous: [Simple Animation](gltfTutorial_006_SimpleAnimation.md) | [Table of Contents](README.md) | Next: [Simple Meshes](gltfTutorial_008_SimpleMeshes.md)
diff --git a/gltfTutorial_cn/gltfTutorial_008_SimpleMeshes.md b/gltfTutorial_cn/gltfTutorial_008_SimpleMeshes.md
new file mode 100644
index 0000000..3b0ef65
--- /dev/null
+++ b/gltfTutorial_cn/gltfTutorial_008_SimpleMeshes.md
@@ -0,0 +1,146 @@
+Previous: [Animations](gltfTutorial_007_Animations.md) | [Table of Contents](README.md) | Next: [Meshes](gltfTutorial_009_Meshes.md)
+
+# Simple Meshes
+
+A [`mesh`](https://www.khronos.org/registry/glTF/specs/2.0/glTF-2.0.html#reference-mesh) represents a geometric object that appears in a scene. An example of a `mesh` has already been shown in the [minimal glTF file](gltfTutorial_003_MinimalGltfFile.md). This example had a single `mesh` attached to a single `node`, and the mesh consisted of a single [`mesh.primitive`](https://www.khronos.org/registry/glTF/specs/2.0/glTF-2.0.html#reference-mesh-primitive) that contained only a single attribute—namely, the attribute for the vertex positions. But usually, the mesh primitives will contain more attributes. These attributes may, for example, be the vertex normals or texture coordinates.
+
+The following is a glTF asset that contains a simple mesh with multiple attributes, which will serve as the basis for explaining the related concepts:
+
+```javascript
+{
+ "scene": 0,
+ "scenes" : [
+ {
+ "nodes" : [ 0, 1]
+ }
+ ],
+ "nodes" : [
+ {
+ "mesh" : 0
+ },
+ {
+ "mesh" : 0,
+ "translation" : [ 1.0, 0.0, 0.0 ]
+ }
+ ],
+
+ "meshes" : [
+ {
+ "primitives" : [ {
+ "attributes" : {
+ "POSITION" : 1,
+ "NORMAL" : 2
+ },
+ "indices" : 0
+ } ]
+ }
+ ],
+
+ "buffers" : [
+ {
+ "uri" : "data:application/octet-stream;base64,AAABAAIAAAAAAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8=",
+ "byteLength" : 80
+ }
+ ],
+ "bufferViews" : [
+ {
+ "buffer" : 0,
+ "byteOffset" : 0,
+ "byteLength" : 6,
+ "target" : 34963
+ },
+ {
+ "buffer" : 0,
+ "byteOffset" : 8,
+ "byteLength" : 72,
+ "target" : 34962
+ }
+ ],
+ "accessors" : [
+ {
+ "bufferView" : 0,
+ "byteOffset" : 0,
+ "componentType" : 5123,
+ "count" : 3,
+ "type" : "SCALAR",
+ "max" : [ 2 ],
+ "min" : [ 0 ]
+ },
+ {
+ "bufferView" : 1,
+ "byteOffset" : 0,
+ "componentType" : 5126,
+ "count" : 3,
+ "type" : "VEC3",
+ "max" : [ 1.0, 1.0, 0.0 ],
+ "min" : [ 0.0, 0.0, 0.0 ]
+ },
+ {
+ "bufferView" : 1,
+ "byteOffset" : 36,
+ "componentType" : 5126,
+ "count" : 3,
+ "type" : "VEC3",
+ "max" : [ 0.0, 0.0, 1.0 ],
+ "min" : [ 0.0, 0.0, 1.0 ]
+ }
+ ],
+
+ "asset" : {
+ "version" : "2.0"
+ }
+}
+```
+
+Image 8a shows the rendered glTF asset.
+
+
+
+Image 8a: A simple mesh, attached to two nodes.
+
+
+
+## The mesh definition
+
+The given example still contains a single mesh that has a single mesh primitive. But this mesh primitive contains multiple attributes:
+
+```javascript
+ "meshes" : [
+ {
+ "primitives" : [ {
+ "attributes" : {
+ "POSITION" : 1,
+ "NORMAL" : 2
+ },
+ "indices" : 0
+ } ]
+ }
+ ],
+```
+
+In addition to the `"POSITION"` attribute, it has a `"NORMAL"` attribute. This refers to the `accessor` object that provides the vertex normals, as described in the [Buffers, BufferViews, and Accessors](gltfTutorial_005_BuffersBufferViewsAccessors.md) section.
+
+
+## The rendered mesh instances
+
+As can be seen in Image 8a, the mesh is rendered *twice*. This is accomplished by attaching the mesh to two different nodes:
+
+```javascript
+ "nodes" : [
+ {
+ "mesh" : 0
+ },
+ {
+ "mesh" : 0,
+ "translation" : [ 1.0, 0.0, 0.0 ]
+ }
+ ],
+```
+
+The `mesh` property of each node refers to the mesh that is attached to the node, using the index of the mesh. One of the nodes has a `translation` that causes the attached mesh to be rendered at a different position.
+
+The [next section](gltfTutorial_009_Meshes.md) will explain meshes and mesh primitives in more detail.
+
+
+
+Previous: [Animations](gltfTutorial_007_Animations.md) | [Table of Contents](README.md) | Next: [Meshes](gltfTutorial_009_Meshes.md)
diff --git a/gltfTutorial_cn/gltfTutorial_009_Meshes.md b/gltfTutorial_cn/gltfTutorial_009_Meshes.md
new file mode 100644
index 0000000..900f00a
--- /dev/null
+++ b/gltfTutorial_cn/gltfTutorial_009_Meshes.md
@@ -0,0 +1,88 @@
+Previous: [Simple Meshes](gltfTutorial_008_SimpleMeshes.md) | [Table of Contents](README.md) | Next: [Materials](gltfTutorial_010_Materials.md)
+
+# Meshes
+
+The [Simple Meshes](gltfTutorial_008_SimpleMeshes.md) example from the previous section showed a basic example of a [`mesh`](https://www.khronos.org/registry/glTF/specs/2.0/glTF-2.0.html#reference-mesh) with a [`mesh.primitive`](https://www.khronos.org/registry/glTF/specs/2.0/glTF-2.0.html#reference-mesh-primitive) object that contained several attributes. This section will explain the meaning and usage of mesh primitives, how meshes may be attached to nodes of the scene graph, and how they can be rendered with different materials.
+
+
+## Mesh primitives
+
+Each `mesh` contains an array of `mesh.primitive` objects. These mesh primitive objects are smaller parts or building blocks of a larger object. A mesh primitive summarizes all information about how the respective part of the object will be rendered.
+
+
+### Mesh primitive attributes
+
+A mesh primitive defines the geometry data of the object using its `attributes` dictionary. This geometry data is given by references to `accessor` objects that contain the data of vertex attributes. The details of the `accessor` concept are explained in the [Buffers, BufferViews, and Accessors](gltfTutorial_005_BuffersBufferViewsAccessors.md) section.
+
+In the given example, there are two entries in the `attributes` dictionary. The entries refer to the `positionsAccessor` and the `normalsAccessor`:
+
+```javascript
+ "meshes" : [
+ {
+ "primitives" : [ {
+ "attributes" : {
+ "POSITION" : 1,
+ "NORMAL" : 2
+ },
+ "indices" : 0
+ } ]
+ }
+ ],
+```
+
+Together, the elements of these accessors define the attributes that belong to the individual vertices, as shown in Image 9a.
+
+
+
+Image 9a: Mesh primitive accessors containing the data of vertices.
+
+
+
+### Indexed and non-indexed geometry
+
+The geometry data of a `mesh.primitive` may be either *indexed* geometry or geometry without indices. In the given example, the `mesh.primitive` contains *indexed* geometry. This is indicated by the `indices` property, which refers to the accessor with index 0, defining the data for the indices. For non-indexed geometry, this property is omitted.
+
+
+### Mesh primitive mode
+
+By default, the geometry data is assumed to describe a triangle mesh. For the case of *indexed* geometry, this means that three consecutive elements of the `indices` accessor are assumed to contain the indices of a single triangle. For non-indexed geometry, three elements of the vertex attribute accessors are assumed to contain the attributes of the three vertices of a triangle.
+
+Other rendering modes are possible: the geometry data may also describe individual points, lines, or triangle strips. This is indicated by the `mode` that may be stored in the mesh primitive. Its value is a constant that indicates how the geometry data has to be interpreted. The mode may, for example, be `0` when the geometry consists of points, or `4` when it consists of triangles. These constants correspond to the GL constants `POINTS` or `TRIANGLES`, respectively. See the [`primitive.mode` specification](https://www.khronos.org/registry/glTF/specs/2.0/glTF-2.0.html#_mesh_primitive_mode) for a list of available modes.
+
+### Mesh primitive material
+
+The mesh primitive may also refer to the `material` that should be used for rendering, using the index of this material. In the given example, no `material` is defined, causing the objects to be rendered with a default material that just defines the objects to have a uniform 50% gray color. A detailed explanation of materials and the related concepts will be given in the [Materials](gltfTutorial_010_Materials.md) section.
+
+
+## Meshes attached to nodes
+
+In the example from the [Simple Meshes](gltfTutorial_008_SimpleMeshes.md) section, there is a single `scene`, which contains two nodes, and both nodes refer to the same `mesh` instance, which has the index 0:
+
+```javascript
+ "scenes" : [
+ {
+ "nodes" : [ 0, 1]
+ }
+ ],
+ "nodes" : [
+ {
+ "mesh" : 0
+ },
+ {
+ "mesh" : 0,
+ "translation" : [ 1.0, 0.0, 0.0 ]
+ }
+ ],
+
+ "meshes" : [
+ { ... }
+ ],
+```
+
+The second node has a `translation` property. As shown in the [Scenes and Nodes](gltfTutorial_004_ScenesNodes.md) section, this will be used to compute the local transform matrix of this node. In this case, the matrix will cause a translation of 1.0 along the x-axis. The product of all local transforms of the nodes will yield the [global transform](gltfTutorial_004_ScenesNodes.md#global-transforms-of-nodes). And all elements that are attached to the nodes will be rendered with this global transform.
+
+So in this example, the mesh will be rendered twice because it is attached to two nodes: once with the global transform of the first node, which is the identity transform, and once with the global transform of the second node, which is a translation of 1.0 along the x-axis.
+
+
+
+Previous: [Simple Meshes](gltfTutorial_008_SimpleMeshes.md) | [Table of Contents](README.md) | Next: [Materials](gltfTutorial_010_Materials.md)
diff --git a/gltfTutorial_cn/gltfTutorial_010_Materials.md b/gltfTutorial_cn/gltfTutorial_010_Materials.md
new file mode 100644
index 0000000..66b0d35
--- /dev/null
+++ b/gltfTutorial_cn/gltfTutorial_010_Materials.md
@@ -0,0 +1,46 @@
+Previous: [Meshes](gltfTutorial_009_Meshes.md) | [Table of Contents](README.md) | Next: [Simple Material](gltfTutorial_011_SimpleMaterial.md)
+
+# Materials
+
+## Introduction
+
+The purpose of glTF is to define a transmission format for 3D assets. As shown in the previous sections, this includes information about the scene structure and the geometric objects that appear in the scene. But a glTF asset can also contain information about the *appearance* of the objects; that is, how these objects should be rendered on the screen.
+
+There are different possible representations for the properties of a material, and the *shading model* describes how these properties are processed. Simple shading models, like the [Phong](https://en.wikipedia.org/wiki/Phong_reflection_model) or [Blinn-Phong](https://en.wikipedia.org/wiki/Blinn%E2%80%93Phong_shading_model), are directly supported by common graphics APIs like OpenGL or WebGL. These shading models are built on a set of basic material properties. For example, the material properties involve information about the color of diffusely reflected light (often in the form of a texture), the color of specularly reflected light, and a shininess parameter. Many file formats contain exactly these parameters. For example, [Wavefront OBJ](https://en.wikipedia.org/wiki/Wavefront_.obj_file) files are combined with `MTL` files that contain this texture and color information. Renderers can read this information and render the objects accordingly. But in order to describe more realistic materials, more sophisticated shading and material models are required.
+
+## Physically-Based Rendering (PBR)
+
+To allow renderers to display objects with a realistic appearance under different lighting conditions, the shading model has to take the *physical* properties of the object surface into account. There are different representations of these physical material properties. One that is frequently used is the *metallic-roughness-model*. Here, the information about the object surface is encoded with three main parameters:
+
+- The *base color*, which is the "main" color of the object surface.
+- The *metallic* value. This is a parameter that describes how much the reflective behavior of the material resembles that of a metal.
+- The *roughness* value, indicating how rough the surface is, affecting the light scattering.
+
+The metallic-roughness model is the representation that is used in glTF. Other material representations, like the *specular-glossiness-model*, are supported via extensions.
+
+The effects of different metallic- and roughness values are illustrated in this image:
+
+
+
+Image 10a: Spheres with different metallic- and roughness values.
+
+
+The base color, metallic, and roughness properties may be given as single values and are then applied to the whole object. In order to assign different material properties to different parts of the object surface, these properties may also be given in the form of textures. This makes it possible to model a wide range of real-world materials with a realistic appearance.
+
+Depending on the shading model, additional effects can be applied to the object surface. These are usually given as a combination of a texture and a scaling factor:
+
+- An *emissive* texture describes the parts of the object surface that emit light with a certain color.
+- The *occlusion* texture can be used to simulate the effect of objects self-shadowing each other.
+- The *normal map* is a texture applied to modulate the surface normal in a way that makes it possible to simulate finer geometric details without the cost of a higher mesh resolution.
+
+glTF supports all of these additional properties, and defines sensible default values for the cases that these properties are omitted.
+
+The following sections will show how these material properties are encoded in a glTF asset, including various examples of materials:
+
+- [A Simple Material](gltfTutorial_011_SimpleMaterial.md)
+- [Textures, Images, and Samplers](gltfTutorial_012_TexturesImagesSamplers.md) that serve as a basis for defining material properties
+- [A Simple Texture](gltfTutorial_013_SimpleTexture.md) showing an example of how to use a texture for a material
+- [An Advanced Material](gltfTutorial_014_AdvancedMaterial.md) combining multiple textures to achieve a sophisticated surface appearance for the objects
+
+
+Previous: [Meshes](gltfTutorial_009_Meshes.md) | [Table of Contents](README.md) | Next: [Simple Material](gltfTutorial_011_SimpleMaterial.md)
diff --git a/gltfTutorial_cn/gltfTutorial_011_SimpleMaterial.md b/gltfTutorial_cn/gltfTutorial_011_SimpleMaterial.md
new file mode 100644
index 0000000..635bc5d
--- /dev/null
+++ b/gltfTutorial_cn/gltfTutorial_011_SimpleMaterial.md
@@ -0,0 +1,140 @@
+Previous: [Materials](gltfTutorial_010_Materials.md) | [Table of Contents](README.md) | Next: [Textures, Images, Samplers](gltfTutorial_012_TexturesImagesSamplers.md)
+
+# A Simple Material
+
+The examples of glTF assets that have been given in the previous sections contained a basic scene structure and simple geometric objects. But they did not contain information about the appearance of the objects. When no such information is given, viewers are encouraged to render the objects with a "default" material. And as shown in the screenshot of the [minimal glTF file](gltfTutorial_003_MinimalGltfFile.md), depending on the light conditions in the scene, this default material causes the object to be rendered with a uniformly white or light gray color.
+
+This section will start with an example of a very simple material and explain the effect of the different material properties.
+
+This is a minimal glTF asset with a simple material:
+
+```javascript
+{
+ "scene": 0,
+ "scenes" : [
+ {
+ "nodes" : [ 0 ]
+ }
+ ],
+
+ "nodes" : [
+ {
+ "mesh" : 0
+ }
+ ],
+
+ "meshes" : [
+ {
+ "primitives" : [ {
+ "attributes" : {
+ "POSITION" : 1
+ },
+ "indices" : 0,
+ "material" : 0
+ } ]
+ }
+ ],
+
+ "buffers" : [
+ {
+ "uri" : "data:application/octet-stream;base64,AAABAAIAAAAAAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAAAAAACAPwAAAAA=",
+ "byteLength" : 44
+ }
+ ],
+ "bufferViews" : [
+ {
+ "buffer" : 0,
+ "byteOffset" : 0,
+ "byteLength" : 6,
+ "target" : 34963
+ },
+ {
+ "buffer" : 0,
+ "byteOffset" : 8,
+ "byteLength" : 36,
+ "target" : 34962
+ }
+ ],
+ "accessors" : [
+ {
+ "bufferView" : 0,
+ "byteOffset" : 0,
+ "componentType" : 5123,
+ "count" : 3,
+ "type" : "SCALAR",
+ "max" : [ 2 ],
+ "min" : [ 0 ]
+ },
+ {
+ "bufferView" : 1,
+ "byteOffset" : 0,
+ "componentType" : 5126,
+ "count" : 3,
+ "type" : "VEC3",
+ "max" : [ 1.0, 1.0, 0.0 ],
+ "min" : [ 0.0, 0.0, 0.0 ]
+ }
+ ],
+
+ "materials" : [
+ {
+ "pbrMetallicRoughness": {
+ "baseColorFactor": [ 1.000, 0.766, 0.336, 1.0 ],
+ "metallicFactor": 0.5,
+ "roughnessFactor": 0.1
+ }
+ }
+ ],
+ "asset" : {
+ "version" : "2.0"
+ }
+}
+```
+
+When rendered, this asset will show the triangle with a new material, as shown in Image 11a.
+
+
+
+Image 11a: A triangle with a simple material.
+
+
+
+## Material definition
+
+
+A new top-level array has been added to the glTF JSON to define this material: The `materials` array contains a single element that defines the material and its properties:
+
+```javascript
+ "materials" : [
+ {
+ "pbrMetallicRoughness": {
+ "baseColorFactor": [ 1.000, 0.766, 0.336, 1.0 ],
+ "metallicFactor": 0.5,
+ "roughnessFactor": 0.1
+ }
+ }
+ ],
+```
+
+The actual definition of the [`material`](https://www.khronos.org/registry/glTF/specs/2.0/glTF-2.0.html#reference-material) here only consists of the [`pbrMetallicRoughness`](https://www.khronos.org/registry/glTF/specs/2.0/glTF-2.0.html#reference-material-pbrmetallicroughness) object, which defines the basic properties of a material in the *metallic-roughness-model*. (All other material properties will therefore have default values, which will be explained later.) The `baseColorFactor` contains the red, green, blue, and alpha components of the main color of the material - here, a bright orange color. The `metallicFactor` of 0.5 indicates that the material should have reflection characteristics between that of a metal and a non-metal material. The `roughnessFactor` causes the material to not be perfectly mirror-like, but instead scatter the reflected light a bit.
+
+## Assigning the material to objects
+
+The material is assigned to the triangle, namely to the `mesh.primitive`, by referring to the material using its index:
+
+```javascript
+ "meshes" : [
+ {
+ "primitives" : [ {
+ "attributes" : {
+ "POSITION" : 1
+ },
+ "indices" : 0,
+ "material" : 0
+ } ]
+ }
+```
+
+The next section will give a short introduction to how textures are defined in a glTF asset. The use of textures will then allow the definition of more complex and realistic materials.
+
+Previous: [Materials](gltfTutorial_010_Materials.md) | [Table of Contents](README.md) | Next: [Textures, Images, Samplers](gltfTutorial_012_TexturesImagesSamplers.md)
diff --git a/gltfTutorial_cn/gltfTutorial_012_TexturesImagesSamplers.md b/gltfTutorial_cn/gltfTutorial_012_TexturesImagesSamplers.md
new file mode 100644
index 0000000..b04de0b
--- /dev/null
+++ b/gltfTutorial_cn/gltfTutorial_012_TexturesImagesSamplers.md
@@ -0,0 +1,37 @@
+Previous: [Simple Material](gltfTutorial_011_SimpleMaterial.md) | [Table of Contents](README.md) | Next: [Simple Texture](gltfTutorial_013_SimpleTexture.md)
+
+# Textures, Images, and Samplers
+
+Textures are an important aspect of giving objects a realistic appearance. They make it possible to define the main color of the objects, as well as other characteristics that are used in the material definition in order to precisely describe what the rendered object should look like.
+
+A glTF asset may define multiple [`texture`](https://www.khronos.org/registry/glTF/specs/2.0/glTF-2.0.html#reference-texture) objects, which can be used as the textures of geometric objects during rendering, and which can be used to encode different material properties. Depending on the graphics API, there may be many features and settings that influence the process of texture mapping. Many of these details are beyond the scope of this tutorial. There are dedicated tutorials that explain the exact meaning of all the texture mapping parameters and settings; for example, on [webglfundamentals.org](https://webglfundamentals.org/webgl/lessons/webgl-3d-textures.html), [open.gl](https://open.gl/textures), and others. This section will only summarize how the information about textures is encoded in a glTF asset.
+
+There are three top-level arrays for the definition of textures in the glTF JSON. The `textures`, `samplers`, and `images` dictionaries contain [`texture`](https://www.khronos.org/registry/glTF/specs/2.0/glTF-2.0.html#reference-texture), [`sampler`](https://www.khronos.org/registry/glTF/specs/2.0/glTF-2.0.html#_texture_sampler), and [`image`](https://www.khronos.org/registry/glTF/specs/2.0/glTF-2.0.html#reference-image) objects, respectively. The following is an excerpt from the [Simple Texture](gltfTutorial_013_SimpleTexture.md) example, which will be presented in the next section:
+
+```javascript
+"textures": [
+ {
+ "source": 0,
+ "sampler": 0
+ }
+],
+"images": [
+ {
+ "uri": "testTexture.png"
+ }
+],
+"samplers": [
+ {
+ "magFilter": 9729,
+ "minFilter": 9987,
+ "wrapS": 33648,
+ "wrapT": 33648
+ }
+],
+```
+
+The `texture` itself uses indices to refer to one `sampler` and one `image`. The most important element here is the reference to the `image`. It contains a URI that links to the actual image file that will be used for the texture. Information about how to read this image data can be found in the section about [image data in `images`](gltfTutorial_002_BasicGltfStructure.md#image-data-in-images).
+
+The next section will show how such a texture definition may be used inside a material.
+
+Previous: [Simple Material](gltfTutorial_011_SimpleMaterial.md) | [Table of Contents](README.md) | Next: [Simple Texture](gltfTutorial_013_SimpleTexture.md)
diff --git a/gltfTutorial_cn/gltfTutorial_013_SimpleTexture.md b/gltfTutorial_cn/gltfTutorial_013_SimpleTexture.md
new file mode 100644
index 0000000..93026a7
--- /dev/null
+++ b/gltfTutorial_cn/gltfTutorial_013_SimpleTexture.md
@@ -0,0 +1,143 @@
+Previous: [Textures, Images, and Samplers](gltfTutorial_012_TexturesImagesSamplers.md) | [Table of Contents](README.md) | Next: [Advanced Material](gltfTutorial_014_AdvancedMaterial.md)
+
+# A Simple Texture
+
+As shown in the previous sections, the material definition in a glTF asset contains different parameters for the color of the material or the overall appearance of the material under the influence of light. These properties may be given via single values, for example, defining the color or the roughness of the object as a whole. Alternatively, these values may be provided via textures that are mapped on the object surface. The following is a glTF asset that defines a material with a simple, single texture:
+
+```javascript
+{
+ "scene": 0,
+ "scenes" : [ {
+ "nodes" : [ 0 ]
+ } ],
+ "nodes" : [ {
+ "mesh" : 0
+ } ],
+ "meshes" : [ {
+ "primitives" : [ {
+ "attributes" : {
+ "POSITION" : 1,
+ "TEXCOORD_0" : 2
+ },
+ "indices" : 0,
+ "material" : 0
+ } ]
+ } ],
+
+ "materials" : [ {
+ "pbrMetallicRoughness" : {
+ "baseColorTexture" : {
+ "index" : 0
+ },
+ "metallicFactor" : 0.0,
+ "roughnessFactor" : 1.0
+ }
+ } ],
+
+ "textures" : [ {
+ "sampler" : 0,
+ "source" : 0
+ } ],
+ "images" : [ {
+ "uri" : "testTexture.png"
+ } ],
+ "samplers" : [ {
+ "magFilter" : 9729,
+ "minFilter" : 9987,
+ "wrapS" : 33648,
+ "wrapT" : 33648
+ } ],
+
+ "buffers" : [ {
+ "uri" : "data:application/gltf-buffer;base64,AAABAAIAAQADAAIAAAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAgD8AAAAAAACAPwAAgD8AAAAAAAAAAAAAgD8AAAAAAACAPwAAgD8AAAAAAAAAAAAAAAAAAAAAAACAPwAAAAAAAAAA",
+ "byteLength" : 108
+ } ],
+ "bufferViews" : [ {
+ "buffer" : 0,
+ "byteOffset" : 0,
+ "byteLength" : 12,
+ "target" : 34963
+ }, {
+ "buffer" : 0,
+ "byteOffset" : 12,
+ "byteLength" : 96,
+ "byteStride" : 12,
+ "target" : 34962
+ } ],
+ "accessors" : [ {
+ "bufferView" : 0,
+ "byteOffset" : 0,
+ "componentType" : 5123,
+ "count" : 6,
+ "type" : "SCALAR",
+ "max" : [ 3 ],
+ "min" : [ 0 ]
+ }, {
+ "bufferView" : 1,
+ "byteOffset" : 0,
+ "componentType" : 5126,
+ "count" : 4,
+ "type" : "VEC3",
+ "max" : [ 1.0, 1.0, 0.0 ],
+ "min" : [ 0.0, 0.0, 0.0 ]
+ }, {
+ "bufferView" : 1,
+ "byteOffset" : 48,
+ "componentType" : 5126,
+ "count" : 4,
+ "type" : "VEC2",
+ "max" : [ 1.0, 1.0 ],
+ "min" : [ 0.0, 0.0 ]
+ } ],
+
+ "asset" : {
+ "version" : "2.0"
+ }
+}
+```
+
+The actual image that the texture consists of is stored as a PNG file called `"testTexture.png"` (see Image 13a).
+
+
+
+Image 13a: The image for the simple texture example.
+
+
+Bringing this all together in a renderer will result in the scene rendered in Image 13b.
+
+
+
+Image 13b: A simple texture on a unit square.
+
+
+
+## The Textured Material Definition
+
+The material definition in this example differs from the [Simple Material](gltfTutorial_011_SimpleMaterial.md) that was shown earlier. While the simple material only defined a single color for the whole object, the material definition now refers to the newly added texture:
+
+```javascript
+"materials" : [ {
+ "pbrMetallicRoughness" : {
+ "baseColorTexture" : {
+ "index" : 0
+ },
+ "metallicFactor" : 0.0,
+ "roughnessFactor" : 1.0
+ }
+} ],
+```
+
+The `baseColorTexture` is the index of the texture that will be applied to the object surface. The `metallicFactor` and `roughnessFactor` are still single values. A more complex material where these properties are also given via textures will be shown in the next section.
+
+In order to apply a texture to a mesh primitive, there must be information about the texture coordinates that should be used for each vertex. The texture coordinates are only another attribute for the vertices defined in the `mesh.primitive`. By default, a texture will use the texture coordinates that have the attribute name `TEXCOORD_0`. If there are multiple sets of texture coordinates, the one that should be used for one particular texture may be selected by adding a `texCoord` property to the texture reference:
+
+```javascript
+"baseColorTexture" : {
+ "index" : 0,
+ "texCoord": 2
+},
+```
+In this case, the texture would use the texture coordinates that are contained in the attribute called `TEXCOORD_2`.
+
+
+Previous: [Textures, Images, and Samplers](gltfTutorial_012_TexturesImagesSamplers.md) | [Table of Contents](README.md) | Next: [Advanced Material](gltfTutorial_014_AdvancedMaterial.md)
diff --git a/gltfTutorial_cn/gltfTutorial_014_AdvancedMaterial.md b/gltfTutorial_cn/gltfTutorial_014_AdvancedMaterial.md
new file mode 100644
index 0000000..156b7ec
--- /dev/null
+++ b/gltfTutorial_cn/gltfTutorial_014_AdvancedMaterial.md
@@ -0,0 +1,56 @@
+Previous: [Simple Texture](gltfTutorial_013_SimpleTexture.md) | [Table of Contents](README.md) | Next: [Simple Cameras](gltfTutorial_015_SimpleCameras.md)
+
+# An Advanced Material
+
+The [Simple Texture](gltfTutorial_013_SimpleTexture.md) example in the previous section showed a material for which the "base color" was defined using a texture. But in addition to the base color, there are other properties of a material that may be defined via textures. These properties have already been summarized in the [Materials](gltfTutorial_010_Materials.md) section:
+
+- The *base color*,
+- The *metallic* value,
+- The *roughness* of the surface,
+- The *emissive* properties,
+- An *occlusion* texture, and
+- A *normal map*.
+
+
+The effects of these properties cannot properly be demonstrated with trivial textures. Therefore, they will be shown here using one of the official Khronos PBR sample models, namely, the [WaterBottle](https://github.com/KhronosGroup/glTF-Sample-Assets/tree/main/Models/WaterBottle) model. Image 14a shows an overview of the textures that are involved in this model, and the final rendered object:
+
+
+
+Image 14a: An example of a material where the surface properties are defined via textures.
+
+
+Explaining the implementation of physically based rendering is beyond the scope of this tutorial. The official Khronos [glTF Sample Viewer](https://github.com/KhronosGroup/glTF-Sample-Viewer) contains a reference implementation of a PBR renderer based on WebGL, and provides implementation hints and background information. The following images mainly aim at demonstrating the effects of the different material property textures, under different lighting conditions.
+
+Image 14b shows the effect of the roughness texture: the main part of the bottle has a low roughness, causing it to appear shiny, compared to the cap, which has a rough surface structure.
+
+
+
+Image 14b: The influence of the roughness texture.
+
+
+Image 14c highlights the effect of the metallic texture: the bottle reflects the light from the surrounding environment map.
+
+
+
+Image 14c: The influence of the metallic texture.
+
+
+Image 14d shows the emissive part of the texture: regardless of the dark environment setting, the text, which is contained in the emissive texture, is clearly visible.
+
+
+
+Image 14d: The emissive part of the texture.
+
+
+Image 14e shows the part of the bottle cap for which a normal map is defined: the text appears to be embossed into the cap. This makes it possible to model finer geometric details on the surface, even though the model itself only has a very coarse geometric resolution.
+
+
+
+Image 14e: The effect of a normal map.
+
+
+Together, these textures and maps allow modeling a wide range of real-world materials. Thanks to the common underlying PBR model - namely, the metallic-roughness model - the objects can be rendered consistently by different renderer implementations.
+
+
+
+Previous: [Simple Texture](gltfTutorial_013_SimpleTexture.md) | [Table of Contents](README.md) | Next: [Simple Cameras](gltfTutorial_015_SimpleCameras.md)
diff --git a/gltfTutorial_cn/gltfTutorial_015_SimpleCameras.md b/gltfTutorial_cn/gltfTutorial_015_SimpleCameras.md
new file mode 100644
index 0000000..b82853f
--- /dev/null
+++ b/gltfTutorial_cn/gltfTutorial_015_SimpleCameras.md
@@ -0,0 +1,168 @@
+Previous: [Advanced Material](gltfTutorial_014_AdvancedMaterial.md) | [Table of Contents](README.md) | Next: [Cameras](gltfTutorial_016_Cameras.md)
+
+# Simple Cameras
+
+The previous sections showed how a basic scene structure with geometric objects is represented in a glTF asset, and how different materials can be applied to these objects. This did not yet include information about the view configuration that should be used for rendering the scene. This view configuration is usually described as a virtual *camera* that is contained in the scene, at a certain position, and pointing in a certain direction.
+
+The following is a simple, complete glTF asset. It is similar to the assets that have already been shown: it defines a simple `scene` containing `node` objects and a single geometric object that is given as a `mesh`, attached to one of the nodes. But this asset additionally contains two [`camera`](https://www.khronos.org/registry/glTF/specs/2.0/glTF-2.0.html#reference-camera) objects:
+
+
+```javascript
+{
+ "scene": 0,
+ "scenes" : [
+ {
+ "nodes" : [ 0, 1, 2 ]
+ }
+ ],
+ "nodes" : [
+ {
+ "rotation" : [ -0.383, 0.0, 0.0, 0.924 ],
+ "mesh" : 0
+ },
+ {
+ "translation" : [ 0.5, 0.5, 3.0 ],
+ "camera" : 0
+ },
+ {
+ "translation" : [ 0.5, 0.5, 3.0 ],
+ "camera" : 1
+ }
+ ],
+
+ "cameras" : [
+ {
+ "type": "perspective",
+ "perspective": {
+ "aspectRatio": 1.0,
+ "yfov": 0.7,
+ "zfar": 100,
+ "znear": 0.01
+ }
+ },
+ {
+ "type": "orthographic",
+ "orthographic": {
+ "xmag": 1.0,
+ "ymag": 1.0,
+ "zfar": 100,
+ "znear": 0.01
+ }
+ }
+ ],
+
+ "meshes" : [
+ {
+ "primitives" : [ {
+ "attributes" : {
+ "POSITION" : 1
+ },
+ "indices" : 0
+ } ]
+ }
+ ],
+
+ "buffers" : [
+ {
+ "uri" : "data:application/octet-stream;base64,AAABAAIAAQADAAIAAAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAgD8AAAAAAACAPwAAgD8AAAAA",
+ "byteLength" : 60
+ }
+ ],
+ "bufferViews" : [
+ {
+ "buffer" : 0,
+ "byteOffset" : 0,
+ "byteLength" : 12,
+ "target" : 34963
+ },
+ {
+ "buffer" : 0,
+ "byteOffset" : 12,
+ "byteLength" : 48,
+ "target" : 34962
+ }
+ ],
+ "accessors" : [
+ {
+ "bufferView" : 0,
+ "byteOffset" : 0,
+ "componentType" : 5123,
+ "count" : 6,
+ "type" : "SCALAR",
+ "max" : [ 3 ],
+ "min" : [ 0 ]
+ },
+ {
+ "bufferView" : 1,
+ "byteOffset" : 0,
+ "componentType" : 5126,
+ "count" : 4,
+ "type" : "VEC3",
+ "max" : [ 1.0, 1.0, 0.0 ],
+ "min" : [ 0.0, 0.0, 0.0 ]
+ }
+ ],
+
+ "asset" : {
+ "version" : "2.0"
+ }
+}
+```
+
+The geometry in this asset is a simple unit square. It is rotated by -45 degrees around the x-axis, to emphasize the effect of the different cameras. Image 15a shows three options for rendering this asset. The first examples use the cameras from the asset. The last example shows how the scene looks from an external, user-defined viewpoint.
+
+
+
+Image 15a: The effect of rendering the scene with different cameras.
+
+
+
+## Camera definitions
+
+The new top-level element of this glTF asset is the `cameras` array, which contains the [`camera`](https://www.khronos.org/registry/glTF/specs/2.0/glTF-2.0.html#reference-camera) objects:
+
+```javascript
+"cameras" : [
+ {
+ "type": "perspective",
+ "perspective": {
+ "aspectRatio": 1.0,
+ "yfov": 0.7,
+ "zfar": 100,
+ "znear": 0.01
+ }
+ },
+ {
+ "type": "orthographic",
+ "orthographic": {
+ "xmag": 1.0,
+ "ymag": 1.0,
+ "zfar": 100,
+ "znear": 0.01
+ }
+ }
+],
+```
+
+When a camera object has been defined, it may be attached to a `node`. This is accomplished by assigning the index of the camera to the `camera` property of a node. In the given example, two new nodes have been added to the scene graph, one for each camera:
+
+```javascript
+"nodes" : {
+ ...
+ {
+ "translation" : [ 0.5, 0.5, 3.0 ],
+ "camera" : 0
+ },
+ {
+ "translation" : [ 0.5, 0.5, 3.0 ],
+ "camera" : 1
+ }
+},
+```
+
+The differences between perspective and orthographic cameras and their properties, the effect of attaching the cameras to the nodes, and the management of multiple cameras will be explained in detail in the [Cameras](gltfTutorial_016_Cameras.md) section.
+
+
+
+
+Previous: [Advanced Material](gltfTutorial_014_AdvancedMaterial.md) | [Table of Contents](README.md) | Next: [Cameras](gltfTutorial_016_Cameras.md)
diff --git a/gltfTutorial_cn/gltfTutorial_016_Cameras.md b/gltfTutorial_cn/gltfTutorial_016_Cameras.md
new file mode 100644
index 0000000..bc55982
--- /dev/null
+++ b/gltfTutorial_cn/gltfTutorial_016_Cameras.md
@@ -0,0 +1,80 @@
+Previous: [Simple Cameras](gltfTutorial_015_SimpleCameras.md) | [Table of Contents](README.md) | Next: [Simple Morph Target](gltfTutorial_017_SimpleMorphTarget.md)
+
+# Cameras
+
+The example in the [Simple Cameras](gltfTutorial_017_SimpleCameras.md) section showed how to define perspective and orthographic cameras, and how they can be integrated into a scene by attaching them to nodes. This section will explain the differences between both types of cameras, and the handling of cameras in general.
+
+
+## Perspective and orthographic cameras
+
+There are two kinds of cameras: *Perspective* cameras, where the viewing volume is a truncated pyramid (often referred to as "viewing frustum"), and *orthographic* cameras, where the viewing volume is a rectangular box. The main difference is that rendering with a *perspective* camera causes a proper perspective distortion, whereas rendering with an *orthographic* camera causes a preservation of lengths and angles.
+
+The example in the [Simple Cameras](gltfTutorial_015_SimpleCameras.md) section contains one camera of each type, a perspective camera at index 0 and an orthographic camera at index 1:
+
+```javascript
+"cameras" : [
+ {
+ "type": "perspective",
+ "perspective": {
+ "aspectRatio": 1.0,
+ "yfov": 0.7,
+ "zfar": 100,
+ "znear": 0.01
+ }
+ },
+ {
+ "type": "orthographic",
+ "orthographic": {
+ "xmag": 1.0,
+ "ymag": 1.0,
+ "zfar": 100,
+ "znear": 0.01
+ }
+ }
+],
+```
+
+
+The `type` of the camera is given as a string, which can be `"perspective"` or `"orthographic"`. Depending on this type, the `camera` object contains a [`camera.perspective`](https://www.khronos.org/registry/glTF/specs/2.0/glTF-2.0.html#reference-camera-perspective) object or a [`camera.orthographic`](https://www.khronos.org/registry/glTF/specs/2.0/glTF-2.0.html#reference-camera-orthographic) object. These objects contain additional parameters that define the actual viewing volume.
+
+The `camera.perspective` object contains an `aspectRatio` property that defines the aspect ratio of the viewport. Additionally, it contains a property called `yfov`, which stands for *Field Of View in Y-direction*. It defines the "opening angle" of the camera and is given in radians.
+
+The `camera.orthographic` object contains `xmag` and `ymag` properties. These define the magnification of the camera in x- and y-direction, and basically describe the width and height of the viewing volume.
+
+Both camera types additionally contain `znear` and `zfar` properties, which are the coordinates of the near and far clipping plane. For perspective cameras, the `zfar` value is optional. When it is missing, a special "infinite projection matrix" will be used.
+
+Explaining the details of cameras, viewing, and projections is beyond the scope of this tutorial. The important point is that most graphics APIs offer methods for defining the viewing configuration that are directly based on these parameters. In general, these parameters can be used to compute a *camera matrix*. The camera matrix can be inverted to obtain the *view matrix*, which will later be post-multiplied with the *model matrix* to obtain the *model-view matrix*, which is required by the renderer.
+
+
+# Camera orientation
+
+A `camera` can be transformed to have a certain orientation and viewing direction in the scene. This is accomplished by attaching the camera to a `node`. Each [`node`](https://www.khronos.org/registry/glTF/specs/2.0/glTF-2.0.html#reference-node) may contain the index of a `camera` that is attached to it. In the simple camera example, there are two nodes for the cameras. The first node refers to the perspective camera with index 0, and the second one refers to the orthographic camera with index 1:
+
+```javascript
+"nodes" : {
+ ...
+ {
+ "translation" : [ 0.5, 0.5, 3.0 ],
+ "camera" : 0
+ },
+ {
+ "translation" : [ 0.5, 0.5, 3.0 ],
+ "camera" : 1
+ }
+},
+```
+
+As shown in the [Scenes and Nodes](gltfTutorial_004_ScenesNodes.md) section, these nodes may have properties that define the transform matrix of the node. The [global transform](gltfTutorial_004_ScenesNodes.md#global-transforms-of-nodes) of a node then defines the actual orientation of the camera in the scene. With the option to apply arbitrary [animations](gltfTutorial_007_Animations.md) to the nodes, it is even possible to define camera flights.
+
+When the global transform of the camera node is the identity matrix, then the eye point of the camera is at the origin, and the viewing direction is along the negative z-axis. In the given example, the nodes both have a `translation` about `(0.5, 0.5, 3.0)`, which causes the camera to be transformed accordingly: it is translated about 0.5 in the x- and y- direction, to look at the center of the unit square, and about 3.0 along the z-axis, to move it a bit away from the object.
+
+
+## Camera instancing and management
+
+There may be multiple cameras defined in the JSON part of a glTF. Each camera may be referred to by multiple nodes. Therefore, the cameras as they appear in the glTF asset are really "templates" for actual camera *instances*: Whenever a node refers to one camera, a new instance of this camera is created.
+
+There is no "default" camera for a glTF asset. Instead, the client application has to keep track of the currently active camera. The client application may, for example, offer a dropdown-menu that allows one to select the active camera and thus to quickly switch between predefined view configurations. With a bit more implementation effort, the client application can also define its own camera and interaction patterns for the camera control (e.g., zooming with the mouse wheel). However, the logic for the navigation and interaction has to be implemented solely by the client application in this case. [Image 15a](gltfTutorial_015_SimpleCameras.md#cameras-png) shows the result of such an implementation, where the user may select either the active camera from the ones that are defined in the glTF asset, or an "external camera" that may be controlled with the mouse.
+
+
+
+Previous: [Simple Cameras](gltfTutorial_015_SimpleCameras.md) | [Table of Contents](README.md) | Next: [Simple Morph Target](gltfTutorial_017_SimpleMorphTarget.md)
diff --git a/gltfTutorial_cn/gltfTutorial_017_SimpleMorphTarget.md b/gltfTutorial_cn/gltfTutorial_017_SimpleMorphTarget.md
new file mode 100644
index 0000000..6d4838b
--- /dev/null
+++ b/gltfTutorial_cn/gltfTutorial_017_SimpleMorphTarget.md
@@ -0,0 +1,277 @@
+Previous: [Cameras](gltfTutorial_016_Cameras.md) | [Table of Contents](README.md) | Next: [Morph Targets](gltfTutorial_018_MorphTargets.md)
+
+# A Simple Morph Target
+
+Starting with version 2.0, glTF supports the definition of *morph targets* for meshes. A morph target stores displacements or differences for certain mesh attributes. At runtime, these differences may be added to the original mesh, with different weights, in order to animate parts of the mesh. This is often used in character animations, for example, to encode different facial expressions of a virtual character.
+
+The following is a minimal example that shows a mesh with two morph targets. The new elements will be summarized here, and the broader concept of morph targets and how they are applied at runtime will be explained in the next section.
+
+
+```javascript
+{
+ "scene": 0,
+ "scenes":[
+ {
+ "nodes":[
+ 0
+ ]
+ }
+ ],
+ "nodes":[
+ {
+ "mesh":0
+ }
+ ],
+ "meshes":[
+ {
+ "primitives":[
+ {
+ "attributes":{
+ "POSITION":1
+ },
+ "targets":[
+ {
+ "POSITION":2
+ },
+ {
+ "POSITION":3
+ }
+ ],
+ "indices":0
+ }
+ ],
+ "weights":[
+ 1.0,
+ 0.5
+ ]
+ }
+ ],
+
+ "animations":[
+ {
+ "samplers":[
+ {
+ "input":4,
+ "interpolation":"LINEAR",
+ "output":5
+ }
+ ],
+ "channels":[
+ {
+ "sampler":0,
+ "target":{
+ "node":0,
+ "path":"weights"
+ }
+ }
+ ]
+ }
+ ],
+
+ "buffers":[
+ {
+ "uri":"data:application/gltf-buffer;base64,AAABAAIAAAAAAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAAA/AAAAPwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIC/AACAPwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIA/AACAPwAAAAA=",
+ "byteLength":116
+ },
+ {
+ "uri":"data:application/gltf-buffer;base64,AAAAAAAAgD8AAABAAABAQAAAgEAAAAAAAAAAAAAAAAAAAIA/AACAPwAAgD8AAIA/AAAAAAAAAAAAAAAA",
+ "byteLength":60
+ }
+ ],
+ "bufferViews":[
+ {
+ "buffer":0,
+ "byteOffset":0,
+ "byteLength":6,
+ "target":34963
+ },
+ {
+ "buffer":0,
+ "byteOffset":8,
+ "byteLength":108,
+ "byteStride":12,
+ "target":34962
+ },
+ {
+ "buffer":1,
+ "byteOffset":0,
+ "byteLength":20
+ },
+ {
+ "buffer":1,
+ "byteOffset":20,
+ "byteLength":40
+ }
+ ],
+ "accessors":[
+ {
+ "bufferView":0,
+ "byteOffset":0,
+ "componentType":5123,
+ "count":3,
+ "type":"SCALAR",
+ "max":[
+ 2
+ ],
+ "min":[
+ 0
+ ]
+ },
+ {
+ "bufferView":1,
+ "byteOffset":0,
+ "componentType":5126,
+ "count":3,
+ "type":"VEC3",
+ "max":[
+ 1.0,
+ 0.5,
+ 0.0
+ ],
+ "min":[
+ 0.0,
+ 0.0,
+ 0.0
+ ]
+ },
+ {
+ "bufferView":1,
+ "byteOffset":36,
+ "componentType":5126,
+ "count":3,
+ "type":"VEC3",
+ "max":[
+ 0.0,
+ 1.0,
+ 0.0
+ ],
+ "min":[
+ -1.0,
+ 0.0,
+ 0.0
+ ]
+ },
+ {
+ "bufferView":1,
+ "byteOffset":72,
+ "componentType":5126,
+ "count":3,
+ "type":"VEC3",
+ "max":[
+ 1.0,
+ 1.0,
+ 0.0
+ ],
+ "min":[
+ 0.0,
+ 0.0,
+ 0.0
+ ]
+ },
+ {
+ "bufferView":2,
+ "byteOffset":0,
+ "componentType":5126,
+ "count":5,
+ "type":"SCALAR",
+ "max":[
+ 4.0
+ ],
+ "min":[
+ 0.0
+ ]
+ },
+ {
+ "bufferView":3,
+ "byteOffset":0,
+ "componentType":5126,
+ "count":10,
+ "type":"SCALAR",
+ "max":[
+ 1.0
+ ],
+ "min":[
+ 0.0
+ ]
+ }
+ ],
+
+ "asset":{
+ "version":"2.0"
+ }
+}
+
+```
+
+The asset contains an animation that interpolates between the different morph targets for a single triangle. A screenshot of this asset is shown in Image 17a.
+
+
+
+Image 17a: A triangle with two morph targets.
+
+
+
+Most of the elements of this asset have already been explained in the previous sections: It contains a `scene` with a single `node` and a single `mesh`. There are two `buffer` objects, one storing the geometry data and one storing the data for the `animation`, and several `bufferView` and `accessor` objects that provide access to this data.
+
+The new elements that have been added in order to define the morph targets are contained in the `mesh` and the `animation`:
+
+
+```javascript
+ "meshes":[
+ {
+ "primitives":[
+ {
+ "attributes":{
+ "POSITION":1
+ },
+ "targets":[
+ {
+ "POSITION":2
+ },
+ {
+ "POSITION":3
+ }
+ ],
+ "indices":0
+ }
+ ],
+ "weights":[
+ 0.5,
+ 0.5
+ ]
+ }
+ ],
+
+```
+
+The `mesh.primitive` contains an array of [morph `targets`](https://www.khronos.org/registry/glTF/specs/2.0/glTF-2.0.html#_mesh_primitive_targets). Each morph target is a dictionary that maps attribute names to `accessor` objects. In the example, there are two morph targets, both mapping the `"POSITION"` attribute to accessors that contain the morphed vertex positions. The mesh also contains an array of `weights` that defines the contribution of each morph target to the final, rendered mesh. These weights are also the `channel.target` of the `animation` that is contained in the asset:
+
+```javascript
+ "animations":[
+ {
+ "samplers":[
+ {
+ "input":4,
+ "interpolation":"LINEAR",
+ "output":5
+ }
+ ],
+ "channels":[
+ {
+ "sampler":0,
+ "target":{
+ "node":0,
+ "path":"weights"
+ }
+ }
+ ]
+ }
+ ],
+
+```
+
+This means that the animation will modify the `weights` of the mesh that is referred to by the `target.node`. The result of applying the animation to these weights, and the computation of the final, rendered mesh will be explained in more detail in the next section about [Morph Targets](gltfTutorial_018_MorphTargets.md).
+
+
+
+Previous: [Cameras](gltfTutorial_016_Cameras.md) | [Table of Contents](README.md) | Next: [Morph Targets](gltfTutorial_018_MorphTargets.md)
diff --git a/gltfTutorial_cn/gltfTutorial_018_MorphTargets.md b/gltfTutorial_cn/gltfTutorial_018_MorphTargets.md
new file mode 100644
index 0000000..fdb6d22
--- /dev/null
+++ b/gltfTutorial_cn/gltfTutorial_018_MorphTargets.md
@@ -0,0 +1,80 @@
+Previous: [Simple Morph Target](gltfTutorial_017_SimpleMorphTarget.md) | [Table of Contents](README.md) | Next: [SimpleSkin](gltfTutorial_019_SimpleSkin.md)
+
+# Morph Targets
+
+The example in the previous section contains a mesh that consists of a single triangle with two morph targets:
+
+```javascript
+{
+ "meshes":[
+ {
+ "primitives":[
+ {
+ "attributes":{
+ "POSITION":1
+ },
+ "targets":[
+ {
+ "POSITION":2
+ },
+ {
+ "POSITION":3
+ }
+ ],
+ "indices":0
+ }
+ ],
+ "weights":[
+ 1.0,
+ 0.5
+ ]
+ }
+ ],
+```
+
+
+The actual base geometry of the mesh, namely the triangle geometry, is defined by the `mesh.primitive` attribute called `"POSITION"`. The morph targets of the `mesh.primitive` are dictionaries that map the attribute name `"POSITION"` to `accessor` objects that contain the *displacements* for each vertex. Image 18a shows the initial triangle geometry in black, and the displacement for the first morph target in red, and the displacement for the second morph target in green.
+
+
+
+Image 18a: The initial triangle and morph target displacements.
+
+
+The `weights` of the mesh determine how these morph target displacements are added to the initial geometry in order to obtain the current state of the geometry. The pseudocode for computing the rendered vertex positions for a mesh `primitive` is as follows:
+```
+renderedPrimitive.POSITION = primitive.POSITION +
+ weights[0] * primitive.targets[0].POSITION +
+ weights[1] * primitive.targets[1].POSITION;
+```
+
+This means that the current state of the mesh primitive is computed by taking the initial mesh primitive geometry and adding a linear combination of the morph target displacements, where the `weights` are the factors for the linear combination.
+
+The asset additionally contains an `animation` that affects the weights for the morph targets. The following table shows the key frames of the animated weights:
+
+| Time | Weights |
+|:----:|:---------:|
+| 0.0 | 0.0, 0.0 |
+| 1.0 | 0.0, 1.0 |
+| 2.0 | 1.0, 1.0 |
+| 3.0 | 1.0, 0.0 |
+| 4.0 | 0.0, 0.0 |
+
+
+Throughout the animation, the weights are interpolated linearly, and applied to the morph target displacements. At each point, the rendered state of the mesh primitive is updated accordingly. The following is an example of the state that is computed at 1.25 seconds. The weights that are provided by the animation sampler for this animation time are (0.25, 1.0), and they are used for computing the linear combination of the morph target displacements.
+
+
+
+Image 18b: An intermediate state of the morph target animation.
+
+
+
+
+
+Previous: [Simple Morph Target](gltfTutorial_017_SimpleMorphTarget.md) | [Table of Contents](README.md) | Next: [SimpleSkin](gltfTutorial_019_SimpleSkin.md)
+
+
+
+
+
+
+
diff --git a/gltfTutorial_cn/gltfTutorial_019_SimpleSkin.md b/gltfTutorial_cn/gltfTutorial_019_SimpleSkin.md
new file mode 100644
index 0000000..2b86209
--- /dev/null
+++ b/gltfTutorial_cn/gltfTutorial_019_SimpleSkin.md
@@ -0,0 +1,166 @@
+Previous: [Morph Targets](gltfTutorial_018_MorphTargets.md) | [Table of Contents](README.md) | Next: [Skins](gltfTutorial_020_Skins.md)
+
+# A Simple Skin
+
+glTF supports *vertex skinning*, which allows the geometry (vertices) of a mesh to be deformed based on the pose of a skeleton. This is essential in order to give animated geometry, for example of virtual characters, a realistic appearance. The core for the definition of vertex skinning in a glTF asset is the [`skin`](https://www.khronos.org/registry/glTF/specs/2.0/glTF-2.0.html#reference-skin), but vertex skinning in general implies several interdependencies between the elements of a glTF asset that have been presented so far.
+
+The following is a glTF asset that shows basic vertex skinning for a simple geometry. The elements of this asset will be summarized quickly in this section, referring to the previous sections where appropriate, and pointing out the new elements that have been added for the vertex skinning functionality. The details and background information for vertex skinning will be given in the next section.
+
+```javascript
+{
+ "scene" : 0,
+ "scenes" : [ {
+ "nodes" : [ 0, 1 ]
+ } ],
+
+ "nodes" : [ {
+ "skin" : 0,
+ "mesh" : 0
+ }, {
+ "children" : [ 2 ]
+ }, {
+ "translation" : [ 0.0, 1.0, 0.0 ],
+ "rotation" : [ 0.0, 0.0, 0.0, 1.0 ]
+ } ],
+
+ "meshes" : [ {
+ "primitives" : [ {
+ "attributes" : {
+ "POSITION" : 1,
+ "JOINTS_0" : 2,
+ "WEIGHTS_0" : 3
+ },
+ "indices" : 0
+ } ]
+ } ],
+
+ "skins" : [ {
+ "inverseBindMatrices" : 4,
+ "joints" : [ 1, 2 ]
+ } ],
+
+ "animations" : [ {
+ "channels" : [ {
+ "sampler" : 0,
+ "target" : {
+ "node" : 2,
+ "path" : "rotation"
+ }
+ } ],
+ "samplers" : [ {
+ "input" : 5,
+ "interpolation" : "LINEAR",
+ "output" : 6
+ } ]
+ } ],
+
+ "buffers" : [ {
+ "uri" : "data:application/gltf-buffer;base64,AAABAAMAAAADAAIAAgADAAUAAgAFAAQABAAFAAcABAAHAAYABgAHAAkABgAJAAgAAAAAvwAAAAAAAAAAAAAAPwAAAAAAAAAAAAAAvwAAAD8AAAAAAAAAPwAAAD8AAAAAAAAAvwAAgD8AAAAAAAAAPwAAgD8AAAAAAAAAvwAAwD8AAAAAAAAAPwAAwD8AAAAAAAAAvwAAAEAAAAAAAAAAPwAAAEAAAAAA",
+ "byteLength" : 168
+ }, {
+ "uri" : "data:application/gltf-buffer;base64,AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAgD8AAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAAAAAABAPwAAgD4AAAAAAAAAAAAAQD8AAIA+AAAAAAAAAAAAAAA/AAAAPwAAAAAAAAAAAAAAPwAAAD8AAAAAAAAAAAAAgD4AAEA/AAAAAAAAAAAAAIA+AABAPwAAAAAAAAAAAAAAAAAAgD8AAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAA=",
+ "byteLength" : 320
+ }, {
+ "uri" : "data:application/gltf-buffer;base64,AACAPwAAAAAAAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAAAAAAAAAAAAgD8AAAAAAAAAAAAAAAAAAAAAAACAPwAAgD8AAAAAAAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAIC/AAAAAAAAgD8=",
+ "byteLength" : 128
+ }, {
+ "uri" : "data:application/gltf-buffer;base64,AAAAAAAAAD8AAIA/AADAPwAAAEAAACBAAABAQAAAYEAAAIBAAACQQAAAoEAAALBAAAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAkxjEPkSLbD8AAAAAAAAAAPT9ND/0/TQ/AAAAAAAAAAD0/TQ/9P00PwAAAAAAAAAAkxjEPkSLbD8AAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAkxjEvkSLbD8AAAAAAAAAAPT9NL/0/TQ/AAAAAAAAAAD0/TS/9P00PwAAAAAAAAAAkxjEvkSLbD8AAAAAAAAAAAAAAAAAAIA/",
+ "byteLength" : 240
+ } ],
+
+ "bufferViews" : [ {
+ "buffer" : 0,
+ "byteLength" : 48,
+ "target" : 34963
+ }, {
+ "buffer" : 0,
+ "byteOffset" : 48,
+ "byteLength" : 120,
+ "target" : 34962
+ }, {
+ "buffer" : 1,
+ "byteLength" : 320,
+ "byteStride" : 16
+ }, {
+ "buffer" : 2,
+ "byteLength" : 128
+ }, {
+ "buffer" : 3,
+ "byteLength" : 240
+ } ],
+
+ "accessors" : [ {
+ "bufferView" : 0,
+ "componentType" : 5123,
+ "count" : 24,
+ "type" : "SCALAR"
+ }, {
+ "bufferView" : 1,
+ "componentType" : 5126,
+ "count" : 10,
+ "type" : "VEC3",
+ "max" : [ 0.5, 2.0, 0.0 ],
+ "min" : [ -0.5, 0.0, 0.0 ]
+ }, {
+ "bufferView" : 2,
+ "componentType" : 5123,
+ "count" : 10,
+ "type" : "VEC4"
+ }, {
+ "bufferView" : 2,
+ "byteOffset" : 160,
+ "componentType" : 5126,
+ "count" : 10,
+ "type" : "VEC4"
+ }, {
+ "bufferView" : 3,
+ "componentType" : 5126,
+ "count" : 2,
+ "type" : "MAT4"
+ }, {
+ "bufferView" : 4,
+ "componentType" : 5126,
+ "count" : 12,
+ "type" : "SCALAR",
+ "max" : [ 5.5 ],
+ "min" : [ 0.0 ]
+ }, {
+ "bufferView" : 4,
+ "byteOffset" : 48,
+ "componentType" : 5126,
+ "count" : 12,
+ "type" : "VEC4",
+ "max" : [ 0.0, 0.0, 0.707, 1.0 ],
+ "min" : [ 0.0, 0.0, -0.707, 0.707 ]
+ } ],
+
+ "asset" : {
+ "version" : "2.0"
+ }
+}
+```
+
+
+
+The result of rendering this asset is shown in Image 19a.
+
+
+
+Image 19a: A scene with simple vertex skinning.
+
+
+
+## Elements of the simple skin example
+
+The elements of the given example are briefly summarized here:
+
+- The `scenes` and `nodes` elements have been explained in the [Scenes and Nodes](gltfTutorial_004_ScenesNodes.md) section. For the vertex skinning, new nodes have been added: the nodes at index 1 and 2 define a new node hierarchy for the *skeleton*. These nodes can be considered the joints between the "bones" that will eventually cause the deformation of the mesh.
+- The new top-level dictionary `skins` contains a single skin in the given example. The properties of this skin object will be explained later.
+- The concepts of `animations` has been explained in the [Animations](gltfTutorial_007_Animations.md) section. In the given example, the animation refers to the *skeleton* nodes so that the effect of the vertex skinning is actually visible during the animation.
+- The [Meshes](gltfTutorial_009_Meshes.md) section already explained the contents of the `meshes` and `mesh.primitive` objects. In this example, new mesh primitive attributes have been added, which are required for vertex skinning, namely the `"JOINTS_0"` and `"WEIGHTS_0"` attributes.
+- There are several new `buffers`, `bufferViews`, and `accessors`. Their basic properties have been described in the [Buffers, BufferViews, and Accessors](gltfTutorial_005_BufferBufferViewsAccessors.md) section. In the given example, they contain the additional data required for vertex skinning.
+
+Details about how these elements are interconnected to achieve the vertex skinning will be explained in the [Skins](gltfTutorial_020_Skins.md) section.
+
+
+Previous: [Morph Targets](gltfTutorial_018_MorphTargets.md) | [Table of Contents](README.md) | Next: [Skins](gltfTutorial_020_Skins.md)
diff --git a/gltfTutorial_cn/gltfTutorial_020_Skins.md b/gltfTutorial_cn/gltfTutorial_020_Skins.md
new file mode 100644
index 0000000..e8c3b1d
--- /dev/null
+++ b/gltfTutorial_cn/gltfTutorial_020_Skins.md
@@ -0,0 +1,231 @@
+Previous: [Simple Skin](gltfTutorial_019_SimpleSkin.md) | [Table of Contents](README.md)
+
+
+# Skins
+
+The process of vertex skinning is a bit complex. It brings together nearly all elements that are contained in a glTF asset. This section will explain the basics of vertex skinning, based on the example in the [Simple Skin](gltfTutorial_019_SimpleSkin.md) section.
+
+
+## The geometry data
+
+The geometry of the vertex skinning example is an indexed triangle mesh, consisting of 8 triangles and 10 vertices. They form a rectangle in the xy-plane, with a width of 1.0 and a height of 2.0. The bottom center of the rectangle is at the origin (0,0,0). So the positions of the vertices are
+
+ -0.5, 0.0, 0.0,
+ 0.5, 0.0, 0.0,
+ -0.5, 0.5, 0.0,
+ 0.5, 0.5, 0.0,
+ -0.5, 1.0, 0.0,
+ 0.5, 1.0, 0.0,
+ -0.5, 1.5, 0.0,
+ 0.5, 1.5, 0.0,
+ -0.5, 2.0, 0.0,
+ 0.5, 2.0, 0.0
+
+and the indices of the triangles are
+
+ 0, 1, 3,
+ 0, 3, 2,
+ 2, 3, 5,
+ 2, 5, 4,
+ 4, 5, 7,
+ 4, 7, 6,
+ 6, 7, 9,
+ 6, 9, 8,
+
+The raw data is stored in the first `buffer`. The indices and vertex positions are defined by the `bufferView` objects at index 0 and 1, and the corresponding `accessor` objects at index 0 and 1 offer typed access to these buffer views. Image 20a shows this geometry with outline rendering to better show the structure.
+
+
+
+Image 20a: The geometry for the skinning example, with outline rendering, in its initial configuration.
+
+
+This geometry data is contained in the mesh primitive of the only mesh, which is attached to the main node of the scene. The mesh primitive contains additional attributes, namely the `"JOINTS_0"` and `"WEIGHTS_0"` attributes. The purpose of these attributes will be explained below.
+
+
+## The skeleton structure
+
+In the given example, there are two nodes that define the skeleton. They are referred to as "skeleton nodes", or "joint nodes", because they can be imagined as the joints between the bones of the skeleton. The `skin` refers to these nodes, by listing their indices in its `joints` property.
+
+```javascript
+ "nodes" : [
+ ...
+ {
+ "children" : [ 2 ]
+ },
+ {
+ "translation" : [ 0.0, 1.0, 0.0 ],
+ "rotation" : [ 0.0, 0.0, 0.0, 1.0 ]
+ }
+ ],
+
+```
+
+The first joint node is located at the origin, and does not contain any transformations. The second node has a `translation` property, defining a translation about 1.0 along the y-axis, and a `rotation` property that initially describes a rotation about 0 degrees (thus, no rotation at all). This rotation will later be changed by the animation to let the skeleton bend left and right and show the effect of the vertex skinning.
+
+## The skin
+
+
+The `skin` is the core element of the vertex skinning. In the example, there is a single skin:
+
+```javascript
+ "skins" : [
+ {
+ "inverseBindMatrices" : 4,
+ "joints" : [ 1, 2 ]
+ }
+ ],
+
+```
+
+The skin contains an array called `joints`, which lists the indices of the nodes that define the skeleton hierarchy. Additionally, the skin contains a reference to an accessor in the property `inverseBindMatrices`. This accessor provides one matrix for each joint. Each of these matrices transforms the geometry into the space of the respective joint. This means that each matrix is the *inverse* of the global transform of the respective joint, in its initial configuration.
+
+In the given example, joint `0` does not have an explicit transform, meaning that its global transform is the identity matrix. Therefore, the inverse bind matrix of joint `0` is also the identity matrix.
+
+Joint `1` contains a translation about 1.0 along the y-axis. The inverse bind matrix of joint `1` is therefore
+
+ 1.0 0.0 0.0 0.0
+ 0.0 1.0 0.0 -1.0
+ 0.0 0.0 1.0 0.0
+ 0.0 0.0 0.0 1.0
+
+This matrix translates the mesh about -1.0 along the y-axis, as shown Image 20b.
+
+
+
+Image 20b: The transformation of the geometry with the inverse bind matrix of joint 1.
+
+
+This transformation may look counterintuitive at first glance. But the goal of this transformation is to bring the coordinates of the skinned vertices into the same space as each joint.
+
+
+## Vertex skinning implementation
+
+Users of existing rendering libraries will hardly ever have to manually process the vertex skinning data contained in a glTF asset: the actual skinning computations usually take place in the vertex shader, which is a low-level implementation detail of the respective library. However, knowing how the vertex skinning data is supposed to be processed may help to create proper, valid models with vertex skinning. So this section will give a short summary of how the vertex skinning is applied, using some pseudocode and examples in GLSL.
+
+### The joint matrices
+
+The vertex positions of a skinned mesh are eventually computed by the vertex shader. During these computations, the vertex shader has to take into account the current pose of the skeleton in order to compute the proper vertex position. This information is passed to the vertex shader as an array of matrices, namely as the *joint matrices*. This is an array - that is, a `uniform` variable - that contains one 4×4 matrix for each joint of the skeleton. In the shader, these matrices are combined to compute the actual skinning matrix for each vertex:
+
+
+```glsl
+...
+uniform mat4 u_jointMat[2];
+
+...
+void main(void)
+{
+ mat4 skinMat =
+ a_weight.x * u_jointMat[int(a_joint.x)] +
+ a_weight.y * u_jointMat[int(a_joint.y)] +
+ a_weight.z * u_jointMat[int(a_joint.z)] +
+ a_weight.w * u_jointMat[int(a_joint.w)];
+ ....
+}
+```
+
+The joint matrix for each joint has to perform the following transformations to the vertices:
+
+- The vertices have to be transformed with the `inverseBindMatrix` of the joint node, to bring them into the same coordinate space as the joint.
+- The vertices have to be transformed with the *current* global transform of the joint node. Together with the transformation from the `inverseBindMatrix`, this will cause the vertices to be transformed only based on the current transform of the node, in the coordinate space of the current joint node.
+
+So the pseudocode for computing the joint matrix of joint `j` may look as follows:
+
+ jointMatrix(j) =
+ globalTransformOfJointNode(j) *
+ inverseBindMatrixForJoint(j);
+
+Note: Vertex skinning in other contexts often involves a matrix that is called "Bind Shape Matrix". This matrix is supposed to transform the geometry of the skinned mesh into the coordinate space of the joints. In glTF, this matrix is omitted, and it is assumed that this transform is either premultiplied with the mesh data, or postmultiplied to the inverse bind matrices.
+
+Image 20c shows the transformations that are done to the geometry in the [Simple Skin](gltfTutorial_019_SimpleSkin.md) example, using the joint matrix of joint 1. The image shows the transformation for an intermediate state of the animation, namely, when the rotation of the joint node has already been modified by the animation, to describe a rotation about 45 degrees around the z-axis.
+
+
+
+Image 20c: The transformation of the geometry done for joint 1.
+
+
+The last panel of Image 20c shows how the geometry would look like if it were *only* transformed with the joint matrix of joint 1. This state of the geometry is never really visible: The *actual* geometry that is computed in the vertex shader will *combine* the geometries as they are created from the different joint matrices, based on the joints- and weights that are explained below.
+
+
+### The skinning joints and weights
+
+As mentioned above, the mesh primitive contains new attributes that are required for the vertex skinning. Particularly, these are the `"JOINTS_0"` and the `"WEIGHTS_0"` attributes. Each attribute refers to an accessor that provides one data element for each vertex of the mesh.
+
+The `"JOINTS_0"` attribute refers to an accessor that contains the indices of the joints that should have an influence on the vertex during the skinning process. For simplicity and efficiency, these indices are usually stored as 4D vectors, limiting the number of joints that may influence a vertex to 4. In the given example, the joints information is very simple:
+
+ Vertex 0: 0, 0, 0, 0,
+ Vertex 1: 0, 0, 0, 0,
+ Vertex 2: 0, 1, 0, 0,
+ Vertex 3: 0, 1, 0, 0,
+ Vertex 4: 0, 1, 0, 0,
+ Vertex 5: 0, 1, 0, 0,
+ Vertex 6: 0, 1, 0, 0,
+ Vertex 7: 0, 1, 0, 0,
+ Vertex 8: 0, 1, 0, 0,
+ Vertex 9: 0, 1, 0, 0,
+
+This means that every vertex may be influenced by joint 0 and joint 1, except the first two vertices are influenced only by joint 0, and the last two vertices are influenced only by joint 1. The last 2 components of each vector are ignored here. If there were multiple joints, then one entry of this accessor could, for example, contain
+
+ 3, 1, 8, 4,
+
+meaning that the corresponding vertex should be influenced by the joints 3, 1, 8, and 4.
+
+The `"WEIGHTS_0"` attribute refers to an accessor that provides information about how strongly each joint should influence each vertex. In the given example, the weights are as follows:
+
+ Vertex 0: 1.00, 0.00, 0.0, 0.0,
+ Vertex 1: 1.00, 0.00, 0.0, 0.0,
+ Vertex 2: 0.75, 0.25, 0.0, 0.0,
+ Vertex 3: 0.75, 0.25, 0.0, 0.0,
+ Vertex 4: 0.50, 0.50, 0.0, 0.0,
+ Vertex 5: 0.50, 0.50, 0.0, 0.0,
+ Vertex 6: 0.25, 0.75, 0.0, 0.0,
+ Vertex 7: 0.25, 0.75, 0.0, 0.0,
+ Vertex 8: 0.00, 1.00, 0.0, 0.0,
+ Vertex 9: 0.00, 1.00, 0.0, 0.0,
+
+Again, the last two components of each entry are not relevant, because there are only two joints.
+
+Combining the `"JOINTS_0"` and `"WEIGHTS_0"` attributes yields exact information about the influence that each joint has on each vertex. For example, the given data means that vertex 6 should be influenced to 25% by joint 0 and to 75% by joint 1.
+
+In the vertex shader, this information is used to create a linear combination of the joint matrices. This matrix is called the *skin matrix* of the respective vertex. Therefore, the data of the `"JOINTS_0"` and `"WEIGHTS_0"` attributes are passed to the shader. In this example, they are given as the `a_joint` and `a_weight` attribute variable, respectively:
+
+```glsl
+...
+attribute vec4 a_joint;
+attribute vec4 a_weight;
+
+uniform mat4 u_jointMat[2];
+
+...
+void main(void)
+{
+ mat4 skinMat =
+ a_weight.x * u_jointMat[int(a_joint.x)] +
+ a_weight.y * u_jointMat[int(a_joint.y)] +
+ a_weight.z * u_jointMat[int(a_joint.z)] +
+ a_weight.w * u_jointMat[int(a_joint.w)];
+ vec4 worldPosition = skinMat * vec4(a_position,1.0);
+ vec4 cameraPosition = u_viewMatrix * worldPosition;
+ gl_Position = u_projectionMatrix * cameraPosition;
+}
+```
+The skin matrix is then used to transform the original position of the vertex into the world space. The transform of the node that the skin is attached to is ignored. The result of this transformation can be imagined as a weighted transformation of the vertices with the respective joint matrices, as shown in Image 20d.
+
+
+
+Image 20d: Computation of the skin matrix.
+
+
+The result of applying this skin matrix to the vertices for the given example is shown in Image 20e.
+
+
+
+Image 20e: The geometry for the skinning example, with outline rendering, during the animation.
+
+
+
+
+
+
+
+
+Previous: [Simple Skin](gltfTutorial_019_SimpleSkin.md) | [Table of Contents](README.md)
diff --git a/gltfTutorial_cn/images/advancedMaterial_emissive.png b/gltfTutorial_cn/images/advancedMaterial_emissive.png
new file mode 100644
index 0000000..128834c
Binary files /dev/null and b/gltfTutorial_cn/images/advancedMaterial_emissive.png differ
diff --git a/gltfTutorial_cn/images/advancedMaterial_metallic.png b/gltfTutorial_cn/images/advancedMaterial_metallic.png
new file mode 100644
index 0000000..77ae25d
Binary files /dev/null and b/gltfTutorial_cn/images/advancedMaterial_metallic.png differ
diff --git a/gltfTutorial_cn/images/advancedMaterial_normal.png b/gltfTutorial_cn/images/advancedMaterial_normal.png
new file mode 100644
index 0000000..b589c84
Binary files /dev/null and b/gltfTutorial_cn/images/advancedMaterial_normal.png differ
diff --git a/gltfTutorial_cn/images/advancedMaterial_roughness.png b/gltfTutorial_cn/images/advancedMaterial_roughness.png
new file mode 100644
index 0000000..39e90e0
Binary files /dev/null and b/gltfTutorial_cn/images/advancedMaterial_roughness.png differ
diff --git a/gltfTutorial_cn/images/animatedTriangle.gif b/gltfTutorial_cn/images/animatedTriangle.gif
new file mode 100644
index 0000000..b7de2d5
Binary files /dev/null and b/gltfTutorial_cn/images/animatedTriangle.gif differ
diff --git a/gltfTutorial_cn/images/animationChannels.png b/gltfTutorial_cn/images/animationChannels.png
new file mode 100644
index 0000000..5f59be5
Binary files /dev/null and b/gltfTutorial_cn/images/animationChannels.png differ
diff --git a/gltfTutorial_cn/images/animationChannels.svg b/gltfTutorial_cn/images/animationChannels.svg
new file mode 100644
index 0000000..6fbae10
--- /dev/null
+++ b/gltfTutorial_cn/images/animationChannels.svg
@@ -0,0 +1,2362 @@
+
+
+
+
diff --git a/gltfTutorial_cn/images/animationSamplers.png b/gltfTutorial_cn/images/animationSamplers.png
new file mode 100644
index 0000000..e0ba674
Binary files /dev/null and b/gltfTutorial_cn/images/animationSamplers.png differ
diff --git a/gltfTutorial_cn/images/animationSamplers.svg b/gltfTutorial_cn/images/animationSamplers.svg
new file mode 100644
index 0000000..d4b33ab
--- /dev/null
+++ b/gltfTutorial_cn/images/animationSamplers.svg
@@ -0,0 +1,1600 @@
+
+
+
+
diff --git a/gltfTutorial_cn/images/aos.png b/gltfTutorial_cn/images/aos.png
new file mode 100644
index 0000000..82400d0
Binary files /dev/null and b/gltfTutorial_cn/images/aos.png differ
diff --git a/gltfTutorial_cn/images/aos.svg b/gltfTutorial_cn/images/aos.svg
new file mode 100644
index 0000000..452a9bb
--- /dev/null
+++ b/gltfTutorial_cn/images/aos.svg
@@ -0,0 +1,2070 @@
+
+
+
+
diff --git a/gltfTutorial_cn/images/applications.png b/gltfTutorial_cn/images/applications.png
new file mode 100644
index 0000000..5bb63f2
Binary files /dev/null and b/gltfTutorial_cn/images/applications.png differ
diff --git a/gltfTutorial_cn/images/applications.svg b/gltfTutorial_cn/images/applications.svg
new file mode 100644
index 0000000..00d4478
--- /dev/null
+++ b/gltfTutorial_cn/images/applications.svg
@@ -0,0 +1,103 @@
+
+
+
+
diff --git a/gltfTutorial_cn/images/buffer.png b/gltfTutorial_cn/images/buffer.png
new file mode 100644
index 0000000..128ac4a
Binary files /dev/null and b/gltfTutorial_cn/images/buffer.png differ
diff --git a/gltfTutorial_cn/images/buffer.svg b/gltfTutorial_cn/images/buffer.svg
new file mode 100644
index 0000000..a1f62e2
--- /dev/null
+++ b/gltfTutorial_cn/images/buffer.svg
@@ -0,0 +1,1062 @@
+
+
diff --git a/gltfTutorial_cn/images/bufferBufferView.png b/gltfTutorial_cn/images/bufferBufferView.png
new file mode 100644
index 0000000..ff60114
Binary files /dev/null and b/gltfTutorial_cn/images/bufferBufferView.png differ
diff --git a/gltfTutorial_cn/images/bufferBufferView.svg b/gltfTutorial_cn/images/bufferBufferView.svg
new file mode 100644
index 0000000..82d5e34
--- /dev/null
+++ b/gltfTutorial_cn/images/bufferBufferView.svg
@@ -0,0 +1,2080 @@
+
+
diff --git a/gltfTutorial_cn/images/bufferBufferViewAccessor.png b/gltfTutorial_cn/images/bufferBufferViewAccessor.png
new file mode 100644
index 0000000..931a424
Binary files /dev/null and b/gltfTutorial_cn/images/bufferBufferViewAccessor.png differ
diff --git a/gltfTutorial_cn/images/bufferBufferViewAccessor.svg b/gltfTutorial_cn/images/bufferBufferViewAccessor.svg
new file mode 100644
index 0000000..088418f
--- /dev/null
+++ b/gltfTutorial_cn/images/bufferBufferViewAccessor.svg
@@ -0,0 +1,2648 @@
+
+
diff --git a/gltfTutorial_cn/images/cameras.png b/gltfTutorial_cn/images/cameras.png
new file mode 100644
index 0000000..11a098f
Binary files /dev/null and b/gltfTutorial_cn/images/cameras.png differ
diff --git a/gltfTutorial_cn/images/contentPipeline.png b/gltfTutorial_cn/images/contentPipeline.png
new file mode 100644
index 0000000..5b2446a
Binary files /dev/null and b/gltfTutorial_cn/images/contentPipeline.png differ
diff --git a/gltfTutorial_cn/images/contentPipeline.svg b/gltfTutorial_cn/images/contentPipeline.svg
new file mode 100644
index 0000000..ab1db39
--- /dev/null
+++ b/gltfTutorial_cn/images/contentPipeline.svg
@@ -0,0 +1,1402 @@
+
+
+
+
diff --git a/gltfTutorial_cn/images/contentPipelineWithGltf.png b/gltfTutorial_cn/images/contentPipelineWithGltf.png
new file mode 100644
index 0000000..be4761a
Binary files /dev/null and b/gltfTutorial_cn/images/contentPipelineWithGltf.png differ
diff --git a/gltfTutorial_cn/images/contentPipelineWithGltf.svg b/gltfTutorial_cn/images/contentPipelineWithGltf.svg
new file mode 100644
index 0000000..e557d1a
--- /dev/null
+++ b/gltfTutorial_cn/images/contentPipelineWithGltf.svg
@@ -0,0 +1,1545 @@
+
+
+
+
diff --git a/gltfTutorial_cn/images/createPng.bat b/gltfTutorial_cn/images/createPng.bat
new file mode 100644
index 0000000..1731d5f
--- /dev/null
+++ b/gltfTutorial_cn/images/createPng.bat
@@ -0,0 +1,4 @@
+
+echo Create for %1
+
+"C:\Program Files\Inkscape\inkscape.exe" -z -f "%1" -D -e "%~n1.png"
\ No newline at end of file
diff --git a/gltfTutorial_cn/images/createPngs.bat b/gltfTutorial_cn/images/createPngs.bat
new file mode 100644
index 0000000..019f1d9
--- /dev/null
+++ b/gltfTutorial_cn/images/createPngs.bat
@@ -0,0 +1,2 @@
+
+for %%i in (*.svg) do call createPng.bat %%i
diff --git a/gltfTutorial_cn/images/gltfJsonStructure.png b/gltfTutorial_cn/images/gltfJsonStructure.png
new file mode 100644
index 0000000..5710702
Binary files /dev/null and b/gltfTutorial_cn/images/gltfJsonStructure.png differ
diff --git a/gltfTutorial_cn/images/gltfJsonStructure.svg b/gltfTutorial_cn/images/gltfJsonStructure.svg
new file mode 100644
index 0000000..8f63777
--- /dev/null
+++ b/gltfTutorial_cn/images/gltfJsonStructure.svg
@@ -0,0 +1,680 @@
+
+
+
+
diff --git a/gltfTutorial_cn/images/gltfStructure.png b/gltfTutorial_cn/images/gltfStructure.png
new file mode 100644
index 0000000..456c370
Binary files /dev/null and b/gltfTutorial_cn/images/gltfStructure.png differ
diff --git a/gltfTutorial_cn/images/gltfStructure.svg b/gltfTutorial_cn/images/gltfStructure.svg
new file mode 100644
index 0000000..7e839f2
--- /dev/null
+++ b/gltfTutorial_cn/images/gltfStructure.svg
@@ -0,0 +1,755 @@
+
+
+
+
diff --git a/gltfTutorial_cn/images/materials.png b/gltfTutorial_cn/images/materials.png
new file mode 100644
index 0000000..37a3c9a
Binary files /dev/null and b/gltfTutorial_cn/images/materials.png differ
diff --git a/gltfTutorial_cn/images/matrix.png b/gltfTutorial_cn/images/matrix.png
new file mode 100644
index 0000000..8dfa36e
Binary files /dev/null and b/gltfTutorial_cn/images/matrix.png differ
diff --git a/gltfTutorial_cn/images/matrix.tex b/gltfTutorial_cn/images/matrix.tex
new file mode 100644
index 0000000..0a58768
--- /dev/null
+++ b/gltfTutorial_cn/images/matrix.tex
@@ -0,0 +1,11 @@
+\begin{align*}
+M =
+\[ \left( \begin{array}{cccc}
+ 2.0 & 0.0 & 0.0 & 10.0 \\
+ 0.0 & 0.866 & -0.25 & 20.0 \\
+ 0.0 & 0.5 & 0.433 & 30.0 \\
+ 0.0 & 0.0 & 0.0, & 1.0 \end{array}
+\right)\]
+\end{align*}
+
+
diff --git a/gltfTutorial_cn/images/meshPrimitiveAttributes.png b/gltfTutorial_cn/images/meshPrimitiveAttributes.png
new file mode 100644
index 0000000..da9c7af
Binary files /dev/null and b/gltfTutorial_cn/images/meshPrimitiveAttributes.png differ
diff --git a/gltfTutorial_cn/images/meshPrimitiveAttributes.svg b/gltfTutorial_cn/images/meshPrimitiveAttributes.svg
new file mode 100644
index 0000000..e6b980f
--- /dev/null
+++ b/gltfTutorial_cn/images/meshPrimitiveAttributes.svg
@@ -0,0 +1,945 @@
+
+
+
+
diff --git a/gltfTutorial_cn/images/metallicRoughnessSpheres.png b/gltfTutorial_cn/images/metallicRoughnessSpheres.png
new file mode 100644
index 0000000..8a60f43
Binary files /dev/null and b/gltfTutorial_cn/images/metallicRoughnessSpheres.png differ
diff --git a/gltfTutorial_cn/images/productMatrix.png b/gltfTutorial_cn/images/productMatrix.png
new file mode 100644
index 0000000..6ac7f28
Binary files /dev/null and b/gltfTutorial_cn/images/productMatrix.png differ
diff --git a/gltfTutorial_cn/images/productMatrix.tex b/gltfTutorial_cn/images/productMatrix.tex
new file mode 100644
index 0000000..4f99664
--- /dev/null
+++ b/gltfTutorial_cn/images/productMatrix.tex
@@ -0,0 +1,11 @@
+\begin{align*}
+M = T * R * S =
+\[ \left( \begin{array}{cccc}
+ 2.0 & 0.0 & 0.0 & 10.0 \\
+ 0.0 & 0.866 & -0.25 & 20.0 \\
+ 0.0 & 0.5 & 0.433 & 30.0 \\
+ 0.0 & 0.0 & 0.0, & 1.0 \end{array}
+\right)\]
+\end{align*}
+
+
diff --git a/gltfTutorial_cn/images/rotationMatrix.png b/gltfTutorial_cn/images/rotationMatrix.png
new file mode 100644
index 0000000..1a242e0
Binary files /dev/null and b/gltfTutorial_cn/images/rotationMatrix.png differ
diff --git a/gltfTutorial_cn/images/rotationMatrix.tex b/gltfTutorial_cn/images/rotationMatrix.tex
new file mode 100644
index 0000000..6ce91dc
--- /dev/null
+++ b/gltfTutorial_cn/images/rotationMatrix.tex
@@ -0,0 +1,9 @@
+\begin{align*}
+R =
+\[ \left( \begin{array}{cccc}
+ 1.0 & 0.0 & 0.0 & 0.0 \\
+ 0.0 & 0.866 & -0.5 & 0.0 \\
+ 0.0 & 0.5 & 0.866 & 0.0 \\
+ 0.0 & 0.0 & 0.0 & 1.0 \end{array}
+\right)\]
+\end{align*}
\ No newline at end of file
diff --git a/gltfTutorial_cn/images/scaleMatrix.png b/gltfTutorial_cn/images/scaleMatrix.png
new file mode 100644
index 0000000..76b106a
Binary files /dev/null and b/gltfTutorial_cn/images/scaleMatrix.png differ
diff --git a/gltfTutorial_cn/images/scaleMatrix.tex b/gltfTutorial_cn/images/scaleMatrix.tex
new file mode 100644
index 0000000..cddf68d
--- /dev/null
+++ b/gltfTutorial_cn/images/scaleMatrix.tex
@@ -0,0 +1,9 @@
+\begin{align*}
+S =
+\[ \left( \begin{array}{cccc}
+ 2.0 & 0.0 & 0.0 & 0.0 \\
+ 0.0 & 1.0 & 0.0 & 0.0 \\
+ 0.0 & 0.0 & 0.5 & 0.0 \\
+ 0.0 & 0.0 & 0.0 & 1.0 \end{array}
+\right)\]
+\end{align*}
\ No newline at end of file
diff --git a/gltfTutorial_cn/images/sceneGraph.png b/gltfTutorial_cn/images/sceneGraph.png
new file mode 100644
index 0000000..720f050
Binary files /dev/null and b/gltfTutorial_cn/images/sceneGraph.png differ
diff --git a/gltfTutorial_cn/images/sceneGraph.svg b/gltfTutorial_cn/images/sceneGraph.svg
new file mode 100644
index 0000000..927ca2b
--- /dev/null
+++ b/gltfTutorial_cn/images/sceneGraph.svg
@@ -0,0 +1,1038 @@
+
+
+
+
diff --git a/gltfTutorial_cn/images/simpleMaterial.png b/gltfTutorial_cn/images/simpleMaterial.png
new file mode 100644
index 0000000..e33bb4a
Binary files /dev/null and b/gltfTutorial_cn/images/simpleMaterial.png differ
diff --git a/gltfTutorial_cn/images/simpleMeshes.png b/gltfTutorial_cn/images/simpleMeshes.png
new file mode 100644
index 0000000..725873f
Binary files /dev/null and b/gltfTutorial_cn/images/simpleMeshes.png differ
diff --git a/gltfTutorial_cn/images/simpleMorph.png b/gltfTutorial_cn/images/simpleMorph.png
new file mode 100644
index 0000000..0143865
Binary files /dev/null and b/gltfTutorial_cn/images/simpleMorph.png differ
diff --git a/gltfTutorial_cn/images/simpleMorphInitial.png b/gltfTutorial_cn/images/simpleMorphInitial.png
new file mode 100644
index 0000000..a07dc98
Binary files /dev/null and b/gltfTutorial_cn/images/simpleMorphInitial.png differ
diff --git a/gltfTutorial_cn/images/simpleMorphInitial.svg b/gltfTutorial_cn/images/simpleMorphInitial.svg
new file mode 100644
index 0000000..509368a
--- /dev/null
+++ b/gltfTutorial_cn/images/simpleMorphInitial.svg
@@ -0,0 +1,205 @@
+
+
+
+
diff --git a/gltfTutorial_cn/images/simpleMorphIntermediate.png b/gltfTutorial_cn/images/simpleMorphIntermediate.png
new file mode 100644
index 0000000..9ed4ff0
Binary files /dev/null and b/gltfTutorial_cn/images/simpleMorphIntermediate.png differ
diff --git a/gltfTutorial_cn/images/simpleMorphIntermediate.svg b/gltfTutorial_cn/images/simpleMorphIntermediate.svg
new file mode 100644
index 0000000..a24cca5
--- /dev/null
+++ b/gltfTutorial_cn/images/simpleMorphIntermediate.svg
@@ -0,0 +1,219 @@
+
+
+
+
diff --git a/gltfTutorial_cn/images/simpleSkin.gif b/gltfTutorial_cn/images/simpleSkin.gif
new file mode 100644
index 0000000..6b161ef
Binary files /dev/null and b/gltfTutorial_cn/images/simpleSkin.gif differ
diff --git a/gltfTutorial_cn/images/simpleSkinOutline01.png b/gltfTutorial_cn/images/simpleSkinOutline01.png
new file mode 100644
index 0000000..2c4eb48
Binary files /dev/null and b/gltfTutorial_cn/images/simpleSkinOutline01.png differ
diff --git a/gltfTutorial_cn/images/simpleSkinOutline02.png b/gltfTutorial_cn/images/simpleSkinOutline02.png
new file mode 100644
index 0000000..d51a49b
Binary files /dev/null and b/gltfTutorial_cn/images/simpleSkinOutline02.png differ
diff --git a/gltfTutorial_cn/images/simpleSparseAccessor.png b/gltfTutorial_cn/images/simpleSparseAccessor.png
new file mode 100644
index 0000000..76cbc3e
Binary files /dev/null and b/gltfTutorial_cn/images/simpleSparseAccessor.png differ
diff --git a/gltfTutorial_cn/images/simpleSparseAccessorDescription.png b/gltfTutorial_cn/images/simpleSparseAccessorDescription.png
new file mode 100644
index 0000000..ff53acf
Binary files /dev/null and b/gltfTutorial_cn/images/simpleSparseAccessorDescription.png differ
diff --git a/gltfTutorial_cn/images/simpleTexture.png b/gltfTutorial_cn/images/simpleTexture.png
new file mode 100644
index 0000000..620bab4
Binary files /dev/null and b/gltfTutorial_cn/images/simpleTexture.png differ
diff --git a/gltfTutorial_cn/images/skinInverseBindMatrix.png b/gltfTutorial_cn/images/skinInverseBindMatrix.png
new file mode 100644
index 0000000..5f95786
Binary files /dev/null and b/gltfTutorial_cn/images/skinInverseBindMatrix.png differ
diff --git a/gltfTutorial_cn/images/skinInverseBindMatrix.svg b/gltfTutorial_cn/images/skinInverseBindMatrix.svg
new file mode 100644
index 0000000..b79fd49
--- /dev/null
+++ b/gltfTutorial_cn/images/skinInverseBindMatrix.svg
@@ -0,0 +1,701 @@
+
+
+
+
diff --git a/gltfTutorial_cn/images/skinJointMatrices.png b/gltfTutorial_cn/images/skinJointMatrices.png
new file mode 100644
index 0000000..100ea99
Binary files /dev/null and b/gltfTutorial_cn/images/skinJointMatrices.png differ
diff --git a/gltfTutorial_cn/images/skinJointMatrices.svg b/gltfTutorial_cn/images/skinJointMatrices.svg
new file mode 100644
index 0000000..ab8d98c
--- /dev/null
+++ b/gltfTutorial_cn/images/skinJointMatrices.svg
@@ -0,0 +1,990 @@
+
+
+
+
diff --git a/gltfTutorial_cn/images/skinSkinMatrix.png b/gltfTutorial_cn/images/skinSkinMatrix.png
new file mode 100644
index 0000000..b7de14a
Binary files /dev/null and b/gltfTutorial_cn/images/skinSkinMatrix.png differ
diff --git a/gltfTutorial_cn/images/skinSkinMatrix.svg b/gltfTutorial_cn/images/skinSkinMatrix.svg
new file mode 100644
index 0000000..222801a
--- /dev/null
+++ b/gltfTutorial_cn/images/skinSkinMatrix.svg
@@ -0,0 +1,1169 @@
+
+
+
+
diff --git a/gltfTutorial_cn/images/testTexture.png b/gltfTutorial_cn/images/testTexture.png
new file mode 100644
index 0000000..c0aeb3c
Binary files /dev/null and b/gltfTutorial_cn/images/testTexture.png differ
diff --git a/gltfTutorial_cn/images/translationMatrix.png b/gltfTutorial_cn/images/translationMatrix.png
new file mode 100644
index 0000000..f847c24
Binary files /dev/null and b/gltfTutorial_cn/images/translationMatrix.png differ
diff --git a/gltfTutorial_cn/images/translationMatrix.tex b/gltfTutorial_cn/images/translationMatrix.tex
new file mode 100644
index 0000000..6b76137
--- /dev/null
+++ b/gltfTutorial_cn/images/translationMatrix.tex
@@ -0,0 +1,9 @@
+\begin{align*}
+T =
+\[ \left( \begin{array}{cccc}
+ 1.0 & 0.0 & 0.0 & 10.0 \\
+ 0.0 & 1.0 & 0.0 & 20.0 \\
+ 0.0 & 0.0 & 1.0 & 30.0 \\
+ 0.0 & 0.0 & 0.0 & 1.0 \end{array}
+\right)\]
+\end{align*}
\ No newline at end of file
diff --git a/gltfTutorial_cn/images/triangle.png b/gltfTutorial_cn/images/triangle.png
new file mode 100644
index 0000000..89c356c
Binary files /dev/null and b/gltfTutorial_cn/images/triangle.png differ
diff --git a/gltfTutorial_cn/images/triangleWithSimpleMaterial.png b/gltfTutorial_cn/images/triangleWithSimpleMaterial.png
new file mode 100644
index 0000000..ff24ca4
Binary files /dev/null and b/gltfTutorial_cn/images/triangleWithSimpleMaterial.png differ