Search in sources :

Example 6 with Bone

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));
}
Also used : GLTFAnimationSampler(org.terasology.engine.rendering.gltf.model.GLTFAnimationSampler) MeshAnimationFrame(org.terasology.engine.rendering.assets.animation.MeshAnimationFrame) TIntArrayList(gnu.trove.list.array.TIntArrayList) ArrayList(java.util.ArrayList) TFloatArrayList(gnu.trove.list.array.TFloatArrayList) TFloatList(gnu.trove.list.TFloatList) GLTFChannel(org.terasology.engine.rendering.gltf.model.GLTFChannel) Quaternionf(org.joml.Quaternionf) AABBf(org.terasology.joml.geom.AABBf) Vector3f(org.joml.Vector3f) MeshAnimationData(org.terasology.engine.rendering.assets.animation.MeshAnimationData) TIntArrayList(gnu.trove.list.array.TIntArrayList) ArrayList(java.util.ArrayList) TFloatList(gnu.trove.list.TFloatList) TIntList(gnu.trove.list.TIntList) TFloatArrayList(gnu.trove.list.array.TFloatArrayList) List(java.util.List) Bone(org.terasology.engine.rendering.assets.skeletalmesh.Bone)

Example 7 with Bone

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;
}
Also used : TIntIterator(gnu.trove.iterator.TIntIterator) TIntArrayList(gnu.trove.list.array.TIntArrayList) ArrayList(java.util.ArrayList) TFloatArrayList(gnu.trove.list.array.TFloatArrayList) Quaternionf(org.joml.Quaternionf) TIntIntMap(gnu.trove.map.TIntIntMap) Matrix4f(org.joml.Matrix4f) Vector3f(org.joml.Vector3f) GLTFNode(org.terasology.engine.rendering.gltf.model.GLTFNode) Bone(org.terasology.engine.rendering.assets.skeletalmesh.Bone) TIntIntHashMap(gnu.trove.map.hash.TIntIntHashMap)

Example 8 with Bone

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();
    }
}
Also used : InputStreamReader(java.io.InputStreamReader) GLTFMesh(org.terasology.engine.rendering.gltf.model.GLTFMesh) TFloatList(gnu.trove.list.TFloatList) TIntArrayList(gnu.trove.list.array.TIntArrayList) ArrayList(java.util.ArrayList) TFloatArrayList(gnu.trove.list.array.TFloatArrayList) Reader(java.io.Reader) InputStreamReader(java.io.InputStreamReader) IOException(java.io.IOException) TIntArrayList(gnu.trove.list.array.TIntArrayList) TFloatArrayList(gnu.trove.list.array.TFloatArrayList) GLTFSkin(org.terasology.engine.rendering.gltf.model.GLTFSkin) GLTFBufferView(org.terasology.engine.rendering.gltf.model.GLTFBufferView) BoneWeight(org.terasology.engine.rendering.assets.skeletalmesh.BoneWeight) GLTF(org.terasology.engine.rendering.gltf.model.GLTF) SkeletalMeshDataBuilder(org.terasology.engine.rendering.assets.skeletalmesh.SkeletalMeshDataBuilder) Vector3f(org.joml.Vector3f) GLTFPrimitive(org.terasology.engine.rendering.gltf.model.GLTFPrimitive) Bone(org.terasology.engine.rendering.assets.skeletalmesh.Bone) TIntList(gnu.trove.list.TIntList) GLTFAccessor(org.terasology.engine.rendering.gltf.model.GLTFAccessor)

Example 9 with Bone

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);
}
Also used : Bone(org.terasology.engine.rendering.assets.skeletalmesh.Bone) LocationComponent(org.terasology.engine.logic.location.LocationComponent) EntityRef(org.terasology.engine.entitySystem.entity.EntityRef) ReceiveEvent(org.terasology.engine.entitySystem.event.ReceiveEvent)

Aggregations

Bone (org.terasology.engine.rendering.assets.skeletalmesh.Bone)9 Vector3f (org.joml.Vector3f)6 Quaternionf (org.joml.Quaternionf)5 TIntArrayList (gnu.trove.list.array.TIntArrayList)4 EntityRef (org.terasology.engine.entitySystem.entity.EntityRef)4 LocationComponent (org.terasology.engine.logic.location.LocationComponent)4 TIntList (gnu.trove.list.TIntList)3 TFloatArrayList (gnu.trove.list.array.TFloatArrayList)3 ArrayList (java.util.ArrayList)3 Matrix4f (org.joml.Matrix4f)3 TFloatList (gnu.trove.list.TFloatList)2 TIntIntMap (gnu.trove.map.TIntIntMap)2 TIntIntHashMap (gnu.trove.map.hash.TIntIntHashMap)2 IOException (java.io.IOException)2 InputStreamReader (java.io.InputStreamReader)2 Reader (java.io.Reader)2 MeshAnimationData (org.terasology.engine.rendering.assets.animation.MeshAnimationData)2 GLTF (org.terasology.engine.rendering.gltf.model.GLTF)2 GLTFSkin (org.terasology.engine.rendering.gltf.model.GLTFSkin)2 AABBf (org.terasology.joml.geom.AABBf)2