Assimp和OpenGL皮肤问题

时间:2017-01-18 02:31:00

标签: java opengl lwjgl assimp

最近我一直试图为我的引擎创建一个骨架动画系统,但没有成功......

在互联网上关注了几个教程之后,我设法让一些工作变得有效,但是"""非常奇怪地... It's supposed to be a full worm

这应该是一个完整的蠕虫病毒,但只有它的起点才能得到。

以下是代码:

Mesh _ret_mesh = null;
    try {
        byte[] _data = IOUtils.toByteArray(stream);
        ByteBuffer data = BufferUtils.createByteBuffer(_data.length);
        data.put(_data);
        data.flip();

        AIScene scene = Assimp.aiImportFileFromMemory(
                data, ...
        );

        ...

        PointerBuffer meshes = scene.mMeshes();

        _ret_mesh = new Mesh();
        AIMesh mesh = AIMesh.create(meshes.get(0));

        for (int f = 0; f < mesh.mNumFaces(); f++) {
            AIFace face = mesh.mFaces().get(f);
            for (int j = 0; j < 3; j++) {
                int index = face.mIndices().get(j);

                AIColor4D color = null;
                AIVector3D norm = null;
                AIVector3D tex = null;
                AIVector3D pos = mesh.mVertices().get(index);

                Color mcolor = new Color(1, 1, 1);
                Vec3 mnorm = new Vec3(0, 0, 1);
                Vec2 mtex = new Vec2(0, 0);

                if (mesh.mNormals() != null) {
                    norm = mesh.mNormals().get(index);
                    mnorm.set(norm.x(), norm.y(), norm.z());
                }
                if (mesh.mTextureCoords(0) != null) {
                    tex = mesh.mTextureCoords(0).get(index);
                    mtex.set(tex.x(), tex.y());
                }
                if (mesh.mColors(0) != null) {
                    color = mesh.mColors(0).get();
                    mcolor.set(color.r(), color.g(), color.b(), color.a());
                }

                Vertex vert = new Vertex();
                vert.position = new Vec3(pos.x(), pos.y(), pos.z());
                vert.normal = mnorm;
                vert.texCoord = mtex;
                vert.color = mcolor;

                _ret_mesh.pushVertex(vert);
                _ret_mesh.pushIndex(index);
            }
        }

        if (mesh.mNumBones() > 0) {
            // Loads bone ids and weights
            loadBones(mesh, _ret_mesh);
            loadSkeleton(scene, _ret_mesh);
        }
        _ret_mesh.finalize();
        _ret_mesh.setSkeleton(skeleton);
    } catch (IOException e) {
        e.printStackTrace();
    }

    return _ret_mesh;
}

private void loadSkeleton(AIScene scene, Mesh mesh) {
    skeleton = new Skeleton();
    skeleton.setInverseGlobalTransform(Mat4.assimp(scene.mRootNode().mTransformation()).invert());
    AINode root = findRootBone(scene.mRootNode());
    buildSkeleton(root, null);
}

private void buildSkeleton(AINode current, Bone parent) {
    String boneName = current.mName().dataString();
    if (bone_names.contains(boneName)) {
        int bone_id = bone_name_map.get(boneName);
        Mat4 bone_trans = bind_pose_map.get(bone_id);
        Bone bone = new Bone(bone_id, bone_trans);
        Transform bone_t = new Transform(Mat4.assimp(current.mTransformation()).transpose());
        bone.setTransform(bone_t);
        if (parent == null) {
            skeleton.root = bone;
        } else {
            parent.addChild(bone);
        }
        PointerBuffer children = current.mChildren();
        for (int i = 0; i < children.remaining(); i++) {
            buildSkeleton(AINode.create(children.get(i)), bone);
        }
    }
}

private AINode findRootBone(AINode node) {
    String boneName = node.mName().dataString();
    if (bone_names.contains(boneName)) {
        return node;
    }
    AINode result = null;
    for (int i = 0; i < node.mNumChildren(); i++) {
        result = findRootBone(new AINode(node.mChildren().getByteBuffer(i, 1288)));
        if (result != null) {
            return result;
        }
    }
    return null;
}

private void loadBones(AIMesh mesh, Mesh retmesh) {
    if (mesh.mNumBones() > 0) {
        int numBones = 0;
        PointerBuffer bones = mesh.mBones();
        for (int k = 0; k < bones.remaining(); k++) {
            int bone_id = 0;
            AIBone bone = AIBone.create(bones.get(k));
            String bone_name = bone.mName().dataString();
            if (!bone_name_map.containsKey(bone_name)) {
                bone_id = numBones;
                numBones++;

                bone_name_map.put(bone_name, bone_id);
                bone_names.add(bone_name);
                bind_pose_map.put(bone_id, Mat4.assimp(bone.mOffsetMatrix()).transpose());
            } else {
                bone_id = bone_name_map.get(bone_name);
                bone_name_map.replace(bone_name, bone_id);
                bind_pose_map.replace(bone_id, Mat4.assimp(bone.mOffsetMatrix()).transpose());
            }

            for (int j = 0; j < bone.mNumWeights(); j++) {
                int vid = bone.mWeights().get(j).mVertexId();
                float weight = bone.mWeights().get(j).mWeight();

                for (int i = 0; i < WEIGHTS_PER_VERTEX; i++) {
                    Vertex vert = retmesh.getVertices().get(vid);
                    if (vert.weights.get(i) == 0.0f) {
                        vert.weights.set(i, weight);
                        vert.ids.set(i, bone_id);
                        break;
                    }
                }
            }
        }
    }
}

这是骨架更新方法:

private void readHierarchy(Bone bone, Mat4 parentTransform) {
    Mat4 boneTransform = bone.getTransform().getTransformation();
    Mat4 globalTransform = parentTransform.mul(boneTransform);
    bone.worldTransform = globalTransform;
    bone.skinnedTransform = inverseGlobalTransform.mul(globalTransform).mul(bone.bindPose);
    for (Bone c : bone.getChildren()) {
        readHierarchy(c, globalTransform);
    }
}

public void update() {
    ArrayList<Bone> bones = getBones();
    matrixMap.clear();

    int i = 0;
    while (matrixMap.size() < bones.size()) {
        matrixMap.put(bones.get(i).id, Mat4.identity());
        i++;
    }

    readHierarchy(root, Mat4.identity());
    for (Bone bone : bones) {
        matrixMap.replace(bone.id, bone.skinnedTransform);
    }
}

顶点着色器

#version 330

const int MAX_BONES = 64;
const int MAX_WEIGHTS = 4;

layout (location = 0) in vec3 v_position;
layout (location = 1) in vec3 v_normal;
layout (location = 2) in vec2 v_texco;
layout (location = 3) in vec4 v_color;
layout (location = 4) in vec4 v_bone_weights;
layout (location = 5) in vec4 v_bone_ids;

out DATA {
    vec3 normal;
    vec4 position;
    vec4 color;
    vec2 uv;
} vs_out;

uniform mat4 modelViewMatrix;
uniform mat4 projectionMatrix;
uniform mat4 normalMatrix;
uniform mat4 modelMatrix;

uniform bool hasBones;
uniform mat4 bones[MAX_BONES];

void main() {
    // Bones and Skinning
    vec4 skinned_vertex = vec4(0.0);
    vec4 skinned_normal = vec4(0.0);

    if (hasBones) {
        for (int i = 0; i < MAX_WEIGHTS; i++) {
            vec4 local_position = bones[int(v_bone_ids[i])] * vec4(v_position, 1.0);
            skinned_vertex += local_position * v_bone_weights[i];

            vec4 world_normal = bones[int(v_bone_ids[i])] * vec4(v_normal, 0.0);
            skinned_normal += world_normal * v_bone_weights[i];
        }
    } else {
        skinned_vertex = vec4(v_position, 1.0);
        skinned_normal = vec4(v_normal, 0.0);
    }
    //

    vec4 _position = modelViewMatrix * skinned_vertex;
    gl_Position = projectionMatrix * _position;

    vs_out.position = modelMatrix * skinned_vertex;
    vs_out.normal = (normalMatrix * skinned_normal).xyz;
    vs_out.color = v_color;
    vs_out.uv = v_texco;
}

我无法找到问题,我尝试了很多东西,已经过了5天。

0 个答案:

没有答案