Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
201 changes: 101 additions & 100 deletions jme3-examples/src/main/java/jme3test/model/anim/TestCustomAnim.java
Original file line number Diff line number Diff line change
Expand Up @@ -32,13 +32,17 @@

package jme3test.model.anim;

import com.jme3.animation.Bone;
import com.jme3.animation.Skeleton;
import com.jme3.animation.SkeletonControl;
import java.nio.ByteBuffer;
import java.nio.FloatBuffer;

import com.jme3.anim.Armature;
import com.jme3.anim.Joint;
import com.jme3.anim.SkinningControl;
import com.jme3.app.SimpleApplication;
import com.jme3.light.AmbientLight;
import com.jme3.light.DirectionalLight;
import com.jme3.math.Quaternion;
import com.jme3.math.Transform;
import com.jme3.math.Vector3f;
import com.jme3.scene.Geometry;
import com.jme3.scene.Node;
Expand All @@ -47,105 +51,102 @@
import com.jme3.scene.VertexBuffer.Type;
import com.jme3.scene.VertexBuffer.Usage;
import com.jme3.scene.shape.Box;
import java.nio.ByteBuffer;
import java.nio.FloatBuffer;

public class TestCustomAnim extends SimpleApplication {

private Bone bone;
private Skeleton skeleton;
private Quaternion rotation = new Quaternion();

public static void main(String[] args) {
TestCustomAnim app = new TestCustomAnim();
app.start();
}

@Override
public void simpleInitApp() {

AmbientLight al = new AmbientLight();
rootNode.addLight(al);

DirectionalLight dl = new DirectionalLight();
dl.setDirection(Vector3f.UNIT_XYZ.negate());
rootNode.addLight(dl);

Box box = new Box(1, 1, 1);

VertexBuffer weightsHW = new VertexBuffer(Type.HWBoneWeight);
VertexBuffer indicesHW = new VertexBuffer(Type.HWBoneIndex);
indicesHW.setUsage(Usage.CpuOnly);
weightsHW.setUsage(Usage.CpuOnly);
box.setBuffer(weightsHW);
box.setBuffer(indicesHW);

// Setup bone weight buffer
FloatBuffer weights = FloatBuffer.allocate( box.getVertexCount() * 4 );
VertexBuffer weightsBuf = new VertexBuffer(Type.BoneWeight);
weightsBuf.setupData(Usage.CpuOnly, 4, Format.Float, weights);
box.setBuffer(weightsBuf);

// Setup bone index buffer
ByteBuffer indices = ByteBuffer.allocate( box.getVertexCount() * 4 );
VertexBuffer indicesBuf = new VertexBuffer(Type.BoneIndex);
indicesBuf.setupData(Usage.CpuOnly, 4, Format.UnsignedByte, indices);
box.setBuffer(indicesBuf);

// Create bind pose buffers
box.generateBindPose();

// Create skeleton
bone = new Bone("root");
bone.setBindTransforms(Vector3f.ZERO, Quaternion.IDENTITY, Vector3f.UNIT_XYZ);
bone.setUserControl(true);
skeleton = new Skeleton(new Bone[]{ bone });

// Assign all verticies to bone 0 with weight 1
for (int i = 0; i < box.getVertexCount() * 4; i += 4){
// assign vertex to bone index 0
indices.array()[i+0] = 0;
indices.array()[i+1] = 0;
indices.array()[i+2] = 0;
indices.array()[i+3] = 0;

// set weight to 1 only for first entry
weights.array()[i+0] = 1;
weights.array()[i+1] = 0;
weights.array()[i+2] = 0;
weights.array()[i+3] = 0;
}

// Maximum number of weights per bone is 1
box.setMaxNumWeights(1);

// Create model
Geometry geom = new Geometry("box", box);
geom.setMaterial(assetManager.loadMaterial("Textures/Terrain/BrickWall/BrickWall.j3m"));
Node model = new Node("model");
model.attachChild(geom);

// Create skeleton control
SkeletonControl skeletonControl = new SkeletonControl(skeleton);
model.addControl(skeletonControl);

rootNode.attachChild(model);
}

@Override
public void simpleUpdate(float tpf){
// Rotate around X axis
Quaternion rotate = new Quaternion();
rotate.fromAngleAxis(tpf, Vector3f.UNIT_X);

// Combine rotation with previous
rotation.multLocal(rotate);

// Set new rotation into bone
bone.setUserTransforms(Vector3f.ZERO, rotation, Vector3f.UNIT_XYZ);

// After changing skeleton transforms, must update world data
skeleton.updateWorldVectors();
}
private Joint bone;
private Armature armature;
private Quaternion rotation = new Quaternion();

public static void main(String[] args) {
TestCustomAnim app = new TestCustomAnim();
app.start();
}

@Override
public void simpleInitApp() {

AmbientLight al = new AmbientLight();
rootNode.addLight(al);

DirectionalLight dl = new DirectionalLight();
dl.setDirection(Vector3f.UNIT_XYZ.negate());
rootNode.addLight(dl);

Box box = new Box(1, 1, 1);

VertexBuffer weightsHW = new VertexBuffer(Type.HWBoneWeight);
VertexBuffer indicesHW = new VertexBuffer(Type.HWBoneIndex);
indicesHW.setUsage(Usage.CpuOnly);
weightsHW.setUsage(Usage.CpuOnly);
box.setBuffer(weightsHW);
box.setBuffer(indicesHW);

// Setup bone weight buffer
FloatBuffer weights = FloatBuffer.allocate(box.getVertexCount() * 4);
VertexBuffer weightsBuf = new VertexBuffer(Type.BoneWeight);
weightsBuf.setupData(Usage.CpuOnly, 4, Format.Float, weights);
box.setBuffer(weightsBuf);

// Setup bone index buffer
ByteBuffer indices = ByteBuffer.allocate(box.getVertexCount() * 4);
VertexBuffer indicesBuf = new VertexBuffer(Type.BoneIndex);
indicesBuf.setupData(Usage.CpuOnly, 4, Format.UnsignedByte, indices);
box.setBuffer(indicesBuf);

// Create bind pose buffers
box.generateBindPose();

// Create skeleton
bone = new Joint("root");
bone.setLocalTransform(new Transform(Vector3f.ZERO, Quaternion.IDENTITY, Vector3f.UNIT_XYZ));
armature = new Armature(new Joint[] { bone });

// Assign all verticies to bone 0 with weight 1
for (int i = 0; i < box.getVertexCount() * 4; i += 4) {
// assign vertex to bone index 0
indices.array()[i + 0] = 0;
indices.array()[i + 1] = 0;
indices.array()[i + 2] = 0;
indices.array()[i + 3] = 0;

// set weight to 1 only for first entry
weights.array()[i + 0] = 1;
weights.array()[i + 1] = 0;
weights.array()[i + 2] = 0;
weights.array()[i + 3] = 0;
}

// Maximum number of weights per bone is 1
box.setMaxNumWeights(1);

// Create model
Geometry geom = new Geometry("box", box);
geom.setMaterial(assetManager.loadMaterial("Textures/Terrain/BrickWall/BrickWall.j3m"));
Node model = new Node("model");
model.attachChild(geom);

// Create skeleton control
SkinningControl skinningControl = new SkinningControl(armature);
model.addControl(skinningControl);

rootNode.attachChild(model);
}

@Override
public void simpleUpdate(float tpf) {
// Rotate around X axis
Quaternion rotate = new Quaternion();
rotate.fromAngleAxis(tpf, Vector3f.UNIT_X);

// Combine rotation with previous
rotation.multLocal(rotate);

// Set new rotation into bone
bone.setLocalTransform(new Transform(Vector3f.ZERO, rotation, Vector3f.UNIT_XYZ));

// After changing skeleton transforms, must update world data
armature.update();
}

}