Search in sources :

Example 1 with MeshAnimationFrame

use of org.terasology.engine.rendering.assets.animation.MeshAnimationFrame 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 2 with MeshAnimationFrame

use of org.terasology.engine.rendering.assets.animation.MeshAnimationFrame in project Terasology by MovingBlocks.

the class SkeletonRenderer method updateSkeletalMeshOfEntity.

private void updateSkeletalMeshOfEntity(EntityRef entity, float delta) {
    SkeletalMeshComponent skeletalMeshComp = entity.getComponent(SkeletalMeshComponent.class);
    if (skeletalMeshComp.mesh == null) {
        return;
    }
    if (skeletalMeshComp.animation == null && skeletalMeshComp.animationPool != null) {
        skeletalMeshComp.animation = randomAnimationData(skeletalMeshComp, random);
    }
    if (skeletalMeshComp.animation == null) {
        return;
    }
    if (skeletalMeshComp.animation.getFrameCount() < 1) {
        return;
    }
    skeletalMeshComp.animationTime += delta * skeletalMeshComp.animationRate;
    float animationDuration = getDurationOfAnimation(skeletalMeshComp);
    while (skeletalMeshComp.animationTime >= animationDuration) {
        MeshAnimation newAnimation;
        if (!skeletalMeshComp.loop) {
            newAnimation = null;
        } else if (skeletalMeshComp.animationPool != null && !skeletalMeshComp.animationPool.isEmpty()) {
            newAnimation = randomAnimationData(skeletalMeshComp, random);
        } else {
            newAnimation = skeletalMeshComp.animation;
        }
        if (newAnimation == null) {
            MeshAnimation finishedAnimation = skeletalMeshComp.animation;
            skeletalMeshComp.animationTime = animationDuration;
            MeshAnimationFrame frame = skeletalMeshComp.animation.getFrame(skeletalMeshComp.animation.getFrameCount() - 1);
            updateSkeleton(skeletalMeshComp, frame, frame, 1.0f);
            // Set animation to null so that AnimEndEvent fires only once
            skeletalMeshComp.animation = null;
            entity.saveComponent(skeletalMeshComp);
            entity.send(new AnimEndEvent(finishedAnimation));
            return;
        }
        skeletalMeshComp.animationTime -= animationDuration;
        if (skeletalMeshComp.animationTime < 0) {
            // In case the float calculation wasn't exact:
            skeletalMeshComp.animationTime = 0;
        }
        skeletalMeshComp.animation = newAnimation;
        animationDuration = getDurationOfAnimation(skeletalMeshComp);
    }
    float framePos = skeletalMeshComp.animationTime / skeletalMeshComp.animation.getTimePerFrame();
    int frameAId = (int) framePos;
    int frameBId = frameAId + 1;
    if (frameBId >= skeletalMeshComp.animation.getFrameCount()) {
        // In case the float calcuation wasn't exact:
        frameBId = skeletalMeshComp.animation.getFrameCount() - 1;
    }
    MeshAnimationFrame frameA = skeletalMeshComp.animation.getFrame(frameAId);
    MeshAnimationFrame frameB = skeletalMeshComp.animation.getFrame(frameBId);
    updateSkeleton(skeletalMeshComp, frameA, frameB, framePos - frameAId);
    entity.saveComponent(skeletalMeshComp);
}
Also used : MeshAnimationFrame(org.terasology.engine.rendering.assets.animation.MeshAnimationFrame) MeshAnimation(org.terasology.engine.rendering.assets.animation.MeshAnimation)

Aggregations

MeshAnimationFrame (org.terasology.engine.rendering.assets.animation.MeshAnimationFrame)2 TFloatList (gnu.trove.list.TFloatList)1 TIntList (gnu.trove.list.TIntList)1 TFloatArrayList (gnu.trove.list.array.TFloatArrayList)1 TIntArrayList (gnu.trove.list.array.TIntArrayList)1 ArrayList (java.util.ArrayList)1 List (java.util.List)1 Quaternionf (org.joml.Quaternionf)1 Vector3f (org.joml.Vector3f)1 MeshAnimation (org.terasology.engine.rendering.assets.animation.MeshAnimation)1 MeshAnimationData (org.terasology.engine.rendering.assets.animation.MeshAnimationData)1 Bone (org.terasology.engine.rendering.assets.skeletalmesh.Bone)1 GLTFAnimationSampler (org.terasology.engine.rendering.gltf.model.GLTFAnimationSampler)1 GLTFChannel (org.terasology.engine.rendering.gltf.model.GLTFChannel)1 AABBf (org.terasology.joml.geom.AABBf)1