• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*******************************************************************************
2  * Copyright 2011 See AUTHORS file.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *   http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  ******************************************************************************/
16 
17 package com.badlogic.gdx.tests;
18 
19 import com.badlogic.gdx.Gdx;
20 import com.badlogic.gdx.graphics.GL20;
21 import com.badlogic.gdx.graphics.OrthographicCamera;
22 import com.badlogic.gdx.graphics.glutils.ShapeRenderer;
23 import com.badlogic.gdx.graphics.glutils.ShapeRenderer.ShapeType;
24 import com.badlogic.gdx.math.Vector2;
25 import com.badlogic.gdx.math.Vector3;
26 import com.badlogic.gdx.tests.utils.GdxTest;
27 
28 public class InverseKinematicsTest extends GdxTest {
29 
30 	static class Bone {
31 		final float len;
32 		final Vector3 position = new Vector3();
33 		final Vector3 inertia = new Vector3();
34 
35 		public String name;
36 
Bone(String name, float x, float y, float len)37 		public Bone (String name, float x, float y, float len) {
38 			this.name = name;
39 			this.position.set(x, y, 0);
40 			this.len = len;
41 		}
42 
toString()43 		public String toString () {
44 			return "bone " + name + ": " + position + ", " + len;
45 		}
46 	}
47 
48 	static final float GRAVITY = 0;
49 	OrthographicCamera camera;
50 	ShapeRenderer renderer;
51 	Bone[] bones;
52 	Vector3 globalCoords = new Vector3();
53 	Vector3 endPoint = new Vector3();
54 	Vector2 diff = new Vector2();
55 
56 	@Override
create()57 	public void create () {
58 		float aspect = Gdx.graphics.getWidth() / (float)Gdx.graphics.getHeight();
59 		camera = new OrthographicCamera(15 * aspect, 15);
60 		camera.update();
61 		renderer = new ShapeRenderer();
62 		renderer.setProjectionMatrix(camera.combined);
63 
64 		bones = new Bone[] {new Bone("bone0", 0, 0, 0), new Bone("bone1", 0, 2, 2), new Bone("bone2", 0, 4, 2),
65 			new Bone("bone3", 0, 6, 2), new Bone("end", 0, 8, 2)};
66 		globalCoords.set(bones[0].position);
67 	}
68 
69 	@Override
dispose()70 	public void dispose () {
71 		renderer.dispose();
72 	}
73 
74 	@Override
render()75 	public void render () {
76 		Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
77 
78 		camera.update();
79 		renderer.setProjectionMatrix(camera.combined);
80 
81 		if (Gdx.input.isTouched()) camera.unproject(globalCoords.set(Gdx.input.getX(), Gdx.input.getY(), 0));
82 		solveFakeIK(globalCoords);
83 		renderBones();
84 	}
85 
renderBones()86 	private void renderBones () {
87 		renderer.begin(ShapeType.Line);
88 		renderer.setColor(0, 1, 0, 1);
89 		for (int i = 0; i < bones.length - 1; i++) {
90 			renderer.line(bones[i].position.x, bones[i].position.y, bones[i + 1].position.x, bones[i + 1].position.y);
91 		}
92 		renderer.end();
93 
94 		renderer.begin(ShapeType.Point);
95 		renderer.setColor(1, 0, 0, 1);
96 		for (int i = 0; i < bones.length; i++) {
97 			renderer.point(bones[i].position.x, bones[i].position.y, 0);
98 		}
99 		renderer.end();
100 	}
101 
solveFakeIK(Vector3 target)102 	public void solveFakeIK (Vector3 target) {
103 		float gravity = Gdx.graphics.getDeltaTime() * GRAVITY;
104 
105 		endPoint.set(target);
106 		bones[0].position.set(endPoint);
107 
108 		for (int i = 0; i < bones.length - 1; i++) {
109 			Bone bone = bones[i];
110 			endPoint.set(bone.position);
111 
112 			diff.set(endPoint.x, endPoint.y).sub(bones[i + 1].position.x, bones[i + 1].position.y);
113 			diff.add(0, gravity);
114 			diff.add(bones[i + 1].inertia.x, bones[i + 1].inertia.y);
115 			diff.nor().scl(bones[i + 1].len);
116 
117 			float x = endPoint.x - diff.x;
118 			float y = endPoint.y - diff.y;
119 			float delta = Gdx.graphics.getDeltaTime();
120 			bones[i + 1].inertia.add((bones[i + 1].position.x - x) * delta, (bones[i + 1].position.y - y) * delta, 0).scl(0.99f);
121 			bones[i + 1].position.set(x, y, 0);
122 		}
123 	}
124 }
125