use of org.terasology.engine.rendering.assets.skeletalmesh.Bone in project Terasology by MovingBlocks.
the class GLTFAnimationFormat method loadAnimation.
private MeshAnimationData loadAnimation(GLTF gltf, GLTFAnimation animation, List<byte[]> loadedBuffers, TIntIntMap boneIndexMapping, List<String> boneNames, TIntList boneParents, List<Bone> bones) throws IOException {
List<ChannelReader> channelReaders = new ArrayList<>();
for (GLTFChannel channel : animation.getChannels()) {
GLTFAnimationSampler sampler = animation.getSamplers().get(channel.getSampler());
TFloatList times = getFloats(gltf, loadedBuffers, sampler.getInput());
int bone = boneIndexMapping.get(channel.getTarget().getNode());
switch(channel.getTarget().getPath()) {
case TRANSLATION:
{
List<Vector3f> data = getVector3fs(gltf, loadedBuffers, sampler.getOutput());
channelReaders.add(new BufferChannelReader<>(times, data, sampler.getInterpolation()::interpolate, x -> x.getPosition(bone)));
break;
}
case ROTATION:
{
List<Quaternionf> data = getQuat4fs(gltf, loadedBuffers, sampler.getOutput());
channelReaders.add(new BufferChannelReader<>(times, data, sampler.getInterpolation()::interpolate, x -> x.getRotation(bone)));
break;
}
case SCALE:
{
List<Vector3f> data = getVector3fs(gltf, loadedBuffers, sampler.getOutput());
channelReaders.add(new BufferChannelReader<>(times, data, sampler.getInterpolation()::interpolate, x -> x.getBoneScale(bone)));
break;
}
default:
break;
}
}
int frameCount = (int) (channelReaders.stream().map(ChannelReader::endTime).reduce(Float::max).orElse(0f) / TIME_PER_FRAME) + 1;
List<MeshAnimationFrame> frames = new ArrayList<>(frameCount);
for (int i = 0; i < frameCount; i++) {
float time = i * TIME_PER_FRAME;
List<Vector3f> boneLocations = new ArrayList<>();
List<Quaternionf> boneRotations = new ArrayList<>();
List<Vector3f> boneScales = new ArrayList<>();
for (Bone bone : bones) {
boneLocations.add(new Vector3f(bone.getLocalPosition()));
boneRotations.add(new Quaternionf(bone.getLocalRotation()));
boneScales.add(new Vector3f(bone.getLocalScale()));
}
MeshAnimationFrame frame = new MeshAnimationFrame(boneLocations, boneRotations, boneScales);
channelReaders.forEach(x -> x.updateFrame(time, frame));
frames.add(frame);
}
return new MeshAnimationData(boneNames, boneParents, frames, TIME_PER_FRAME, new AABBf(0, 0, 0));
}
use of org.terasology.engine.rendering.assets.skeletalmesh.Bone in project Terasology by MovingBlocks.
the class GLTFCommonFormat method loadBones.
protected List<Bone> loadBones(GLTF gltf, GLTFSkin skin, List<byte[]> loadedBuffers) {
List<Bone> bones = new ArrayList<>();
TIntIntMap boneToJoint = new TIntIntHashMap();
List<Matrix4f> inverseMats = loadInverseMats(skin.getInverseBindMatrices(), skin.getJoints().size(), gltf, loadedBuffers);
for (int i = 0; i < skin.getJoints().size(); i++) {
int nodeIndex = skin.getJoints().get(i);
GLTFNode node = gltf.getNodes().get(nodeIndex);
Vector3f position = new Vector3f();
Quaternionf rotation = new Quaternionf();
Vector3f scale = new Vector3f(1, 1, 1);
if (node.getTranslation() != null) {
position.set(node.getTranslation());
}
if (node.getRotation() != null) {
rotation.set(node.getRotation());
}
if (node.getScale() != null) {
scale.set(node.getScale());
}
String boneName = node.getName();
if (Strings.isNullOrEmpty(boneName)) {
boneName = "bone_" + i;
}
Bone bone = new Bone(i, boneName, new Matrix4f().translationRotateScale(position, rotation, scale));
bone.setInverseBindMatrix(inverseMats.get(i));
bones.add(bone);
boneToJoint.put(nodeIndex, i);
}
for (int i = 0; i < skin.getJoints().size(); i++) {
int nodeIndex = skin.getJoints().get(i);
GLTFNode node = gltf.getNodes().get(nodeIndex);
Bone bone = bones.get(i);
TIntIterator iterator = node.getChildren().iterator();
while (iterator.hasNext()) {
bone.addChild(bones.get(boneToJoint.get(iterator.next())));
}
}
return bones;
}
use of org.terasology.engine.rendering.assets.skeletalmesh.Bone in project Terasology by MovingBlocks.
the class GLTFSkeletalMeshFormat method load.
@Override
public SkeletalMeshData load(ResourceUrn urn, List<AssetDataFile> inputs) throws IOException {
try (Reader in = new InputStreamReader(inputs.get(0).openStream())) {
GLTF gltf = gson.fromJson(in, GLTF.class);
checkVersionSupported(urn, gltf);
checkMeshPresent(urn, gltf);
GLTFSkin skin = gltf.getSkins().get(0);
GLTFMesh gltfMesh = gltf.getMeshes().get(0);
checkPrimitivePresent(urn, gltfMesh);
GLTFPrimitive gltfPrimitive = gltfMesh.getPrimitives().get(0);
List<byte[]> loadedBuffers = loadBinaryBuffers(urn, gltf);
SkeletalMeshDataBuilder builder = new SkeletalMeshDataBuilder();
List<Bone> bones = loadBones(gltf, skin, loadedBuffers);
for (Bone bone : bones) {
builder.addBone(bone);
}
List<Vector3f> positions = loadVector3fList(MeshAttributeSemantic.Position, gltfPrimitive, gltf, loadedBuffers);
List<Vector3f> normals = loadVector3fList(MeshAttributeSemantic.Normal, gltfPrimitive, gltf, loadedBuffers);
TIntList joints = readIntBuffer(MeshAttributeSemantic.Joints_0, gltfPrimitive, gltf, loadedBuffers);
TFloatList weights = readFloatBuffer(MeshAttributeSemantic.Weights_0, gltfPrimitive, gltf, loadedBuffers);
List<BoneWeight> boneWeights = new ArrayList<>();
for (int index = 0; index < positions.size(); index++) {
TIntList weightJoints = new TIntArrayList();
TFloatList weightBiases = new TFloatArrayList();
for (int i = 0; i < 4; i++) {
if (weights.get(4 * index + i) > 0) {
weightBiases.add(weights.get(4 * index + i));
weightJoints.add(joints.get(4 * index + i));
}
}
boneWeights.add(new BoneWeight(weightBiases, weightJoints));
}
builder.addVertices(positions);
builder.addNormals(normals);
builder.addWeights(boneWeights);
builder.setUvs(loadVector2fList(MeshAttributeSemantic.Texcoord_0, gltfPrimitive, gltf, loadedBuffers));
GLTFAccessor indicesAccessor = getIndicesAccessor(gltfPrimitive, gltf, urn);
if (indicesAccessor.getBufferView() == null) {
throw new IOException("Missing buffer view for indices accessor in " + urn);
}
GLTFBufferView indicesBuffer = gltf.getBufferViews().get(indicesAccessor.getBufferView());
checkIndicesBuffer(indicesBuffer);
TIntList indicies = new TIntArrayList();
readBuffer(loadedBuffers.get(indicesBuffer.getBuffer()), indicesAccessor, indicesBuffer, indicies);
builder.setIndices(indicies);
if (gltf.getSkins().isEmpty()) {
throw new IOException("Skeletal mesh '" + urn + "' missing skin");
}
return builder.build();
}
}
use of org.terasology.engine.rendering.assets.skeletalmesh.Bone in project Terasology by MovingBlocks.
the class SkeletonRenderer method newSkeleton.
@ReceiveEvent(components = { SkeletalMeshComponent.class, LocationComponent.class })
public void newSkeleton(OnActivatedComponent event, EntityRef entity) {
SkeletalMeshComponent skeleton = entity.getComponent(SkeletalMeshComponent.class);
if (skeleton.mesh == null) {
return;
}
if (skeleton.boneEntities == null) {
skeleton.boneEntities = Maps.newHashMap();
for (Bone bone : skeleton.mesh.getBones()) {
LocationComponent loc = new LocationComponent();
EntityRef boneEntity = entityManager.create(loc);
skeleton.boneEntities.put(bone.getName(), boneEntity);
}
}
for (Bone bone : skeleton.mesh.getBones()) {
EntityRef boneEntity = skeleton.boneEntities.get(bone.getName());
EntityRef parent = (bone.getParent() != null) ? skeleton.boneEntities.get(bone.getParent().getName()) : entity;
Location.attachChild(parent, boneEntity);
}
for (Bone bone : skeleton.mesh.getBones()) {
EntityRef boneEntity = skeleton.boneEntities.get(bone.getName());
LocationComponent loc = boneEntity.getComponent(LocationComponent.class);
loc.setLocalPosition(bone.getLocalPosition());
loc.setLocalRotation(bone.getLocalRotation());
loc.setLocalScale(bone.getLocalScale().x);
boneEntity.saveComponent(loc);
if (bone.getParent() == null) {
skeleton.rootBone = boneEntity;
}
}
entity.saveComponent(skeleton);
}
Aggregations