1 package com.badlogic.gdx.tests.g3d;
3 import com.badlogic.gdx.Gdx;
4 import com.badlogic.gdx.Input.Keys;
5 import com.badlogic.gdx.graphics.Color;
6 import com.badlogic.gdx.graphics.GL10;
7 import com.badlogic.gdx.graphics.g3d.Model;
8 import com.badlogic.gdx.graphics.g3d.ModelBatch;
9 import com.badlogic.gdx.graphics.g3d.ModelInstance;
10 import com.badlogic.gdx.graphics.g3d.materials.BlendingAttribute;
11 import com.badlogic.gdx.graphics.g3d.model.Animation;
12 import com.badlogic.gdx.graphics.g3d.model.Node;
13 import com.badlogic.gdx.graphics.g3d.model.NodeAnimation;
14 import com.badlogic.gdx.graphics.glutils.ShapeRenderer;
15 import com.badlogic.gdx.graphics.glutils.ShapeRenderer.ShapeType;
16 import com.badlogic.gdx.math.Quaternion;
17 import com.badlogic.gdx.math.Vector3;
18 import com.badlogic.gdx.utils.Array;
19 import com.badlogic.gdx.utils.Pool;
20 import com.badlogic.gdx.utils.StringBuilder;
22 public class SkeletonTest extends BaseG3dHudTest {
23 ShapeRenderer shapeRenderer;
26 public void create () {
29 shapeRenderer = new ShapeRenderer();
30 shapeRenderer.setColor(Color.WHITE);
31 onModelClicked("g3d/knight.g3db");
34 private final static Vector3 tmpV = new Vector3();
35 private final static Pool<Vector3> vectorPool = new Pool<Vector3>() {
37 protected Vector3 newObject () {
41 private final static Quaternion tmpQ = new Quaternion();
43 protected void render (ModelBatch batch, Array<ModelInstance> instances) {
44 for (final ModelInstance instance : instances) {
45 updateAnimation(instance);
46 renderSkeleton(instance);
48 batch.render(instances);
51 public void renderSkeleton(final ModelInstance instance) {
52 shapeRenderer.setProjectionMatrix(cam.combined);
53 shapeRenderer.begin(ShapeType.Line);
54 for (Node node : instance.nodes) {
55 shapeRenderer.setColor(node.isAnimated ? Color.RED : Color.YELLOW);
56 node.globalTransform.getTranslation(tmpV);
57 shapeRenderer.box(tmpV.x, tmpV.y, tmpV.z, 0.5f, 0.5f, 0.5f);
58 for (Node child : node.children)
59 renderSkeleton(tmpV, child);
64 public void renderSkeleton(final Vector3 from, final Node node) {
65 final Vector3 pos = vectorPool.obtain();
66 node.globalTransform.getTranslation(pos);
67 shapeRenderer.setColor(node.isAnimated ? Color.RED : Color.YELLOW);
68 shapeRenderer.box(pos.x, pos.y, pos.z, 0.5f, 0.5f, 0.5f);
69 shapeRenderer.setColor(Color.WHITE);
70 shapeRenderer.line(from.x, from.y, from.z, pos.x, pos.y, pos.z);
71 for (Node child : node.children)
72 renderSkeleton(pos, child);
77 protected void getStatus (StringBuilder stringBuilder) {
78 super.getStatus(stringBuilder);
80 for (final ModelInstance instance : instances) {
81 if (instance.animations.size > 0) {
82 stringBuilder.append(" press space or menu to switch animation");
88 protected String currentlyLoading;
90 protected void onModelClicked(final String name) {
94 currentlyLoading = "data/"+name;
95 assets.load(currentlyLoading, Model.class);
100 protected void onLoaded() {
101 if (currentlyLoading == null || currentlyLoading.isEmpty())
105 final ModelInstance instance = new ModelInstance(assets.get(currentlyLoading, Model.class));
106 instance.materials.get(0).set(new BlendingAttribute(GL10.GL_SRC_ALPHA, GL10.GL_ONE_MINUS_SRC_ALPHA, 0.5f));
107 instances.add(instance);
108 currentlyLoading = null;
111 protected void switchAnimation() {
112 for (final ModelInstance instance : instances) {
113 if (instance.animations.size > 0) {
114 if (instance.currentAnimation != null) {
115 for (final NodeAnimation nodeAnim : instance.currentAnimation.nodeAnimations)
116 nodeAnim.node.isAnimated = false;
117 instance.calculateTransforms();
120 for (int i = 0; i < instance.animations.size; i++) {
121 final Animation animation = instance.animations.get(i);
122 if (instance.currentAnimation == animation) {
127 animIndex = (animIndex + 1) % (instance.animations.size + 1);
128 instance.currentAnimation = animIndex == instance.animations.size ? null : instance.animations.get(animIndex);
129 instance.currentAnimTime = 0f;
135 public boolean needsGL20 () {
140 public boolean keyUp (int keycode) {
141 if (keycode == Keys.SPACE || keycode == Keys.MENU)
143 return super.keyUp(keycode);
146 public void updateAnimation(final ModelInstance instance) {
147 if (instance.currentAnimation != null) {
148 instance.currentAnimTime = (instance.currentAnimTime + Gdx.graphics.getDeltaTime()) % instance.currentAnimation.duration;
149 for (final NodeAnimation nodeAnim : instance.currentAnimation.nodeAnimations) {
150 nodeAnim.node.isAnimated = true;
151 final int n = nodeAnim.keyframes.size - 1;
153 nodeAnim.node.localTransform.idt().
154 translate(nodeAnim.keyframes.get(0).translation).
155 rotate(nodeAnim.keyframes.get(0).rotation).
156 scl(nodeAnim.keyframes.get(0).scale);
158 for (int i = 0; i < n; i++) {
159 if (instance.currentAnimTime >= nodeAnim.keyframes.get(i).keytime && instance.currentAnimTime <= nodeAnim.keyframes.get(i+1).keytime) {
160 final float t = (instance.currentAnimTime - nodeAnim.keyframes.get(i).keytime) / (nodeAnim.keyframes.get(i+1).keytime - nodeAnim.keyframes.get(i).keytime);
161 nodeAnim.node.localTransform.idt().
162 translate(tmpV.set(nodeAnim.keyframes.get(i).translation).lerp(nodeAnim.keyframes.get(i+1).translation, t)).
163 rotate(tmpQ.set(nodeAnim.keyframes.get(i).rotation).slerp(nodeAnim.keyframes.get(i+1).rotation, t)).
164 scl(tmpV.set(nodeAnim.keyframes.get(i).scale).lerp(nodeAnim.keyframes.get(i+1).scale, t));
169 instance.calculateTransforms();