微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

卡住了,尝试使用lwjgl

如何解决卡住了,尝试使用lwjgl

我跟随this online tutorial使用asimp导入模型并对它们进行动画处理。我能够使用他的方法为它们设置动画。

但是,没有插值。所以我用this code来调整我已经写的东西。我有插值的工作方式,但是模型都很奇怪。

我花了几个小时遍历代码的每一行,并比较了从薄矩阵代码到gitbooks代码中矩阵乘法的矩阵乘法。

我已经比较了骨骼和节点的偏移矩阵(这很混乱,我知道我只是想让它正常工作)我已经遍历了插值代码我已经遍历了转换骨骼的代码转换成矩阵。我已经检查了代码,以确保正确的骨骼转换位于相应的索引处(关键帧类的骨骼转换数组的索引是骨骼ID)。

一切似乎都是正确的,但我无法使其正确进行动画处理。我花了几个小时来检查所有代码,但对其中的每个部分如何结合以及应该如何工作有了深刻的了解。但是对于我的一生,我找不到我做错的事情。

    public class AnimMeshesLoader_Test extends StaticmeshesLoader {
    
    public static AnimGameItem_Test loadAnimGameItem(String resourcePath,String texturesDir) throws Exception {
        return loadAnimGameItem(resourcePath,texturesDir,aiProcess_GenSmoothnormals 
                | aiProcess_JoinIdenticalVertices 
                | aiProcess_Triangulate 
                | aiProcess_FixInfacingnormals 
                | aiProcess_LimitBoneWeights);
    }
    
    public static AnimGameItem_Test loadAnimGameItem(String resourcePath,String texturesDir,int flags) throws Exception {
        AIScene aiScene = aiImportFile(resourcePath,flags);
        
        if(aiScene == null) {
            throw new Exception("Error loading model");
        }
        
        int numMaterials = aiScene.mNumMaterials();
        PointerBuffer aimaterials = aiScene.mMaterials();
        List<Material> materials = new ArrayList<Material>();
        
        for(int i = 0; i < numMaterials; i++) {
            aimaterial aimaterial = aimaterial.create(aimaterials.get(i));
            processMaterial(aimaterial,materials,texturesDir);
        }
        
        List<Bone> boneList = new ArrayList<Bone>();
        int numMeshes = aiScene.mNumMeshes();
        PointerBuffer aimeshes = aiScene.mMeshes();
        Mesh[] meshes = new Mesh[numMeshes];
        
        for(int i = 0; i < numMeshes; i++) {
            aimesh aimesh = aimesh.create(aimeshes.get(i));
            Mesh mesh = processMesh(aimesh,boneList);
            meshes[i] = mesh;
        }
        
        AINode aiRootNode = aiScene.mRootNode();
        Matrix4f roottransformation = AnimMeshesLoader_Test.toMatrix(aiRootNode.mTransformation());
        Node_Test rootNode = processNodesHierarchy(aiRootNode,null);
        Map<String,Animation_Test> animations = processAnimations(aiScene,boneList,rootNode,roottransformation);
        AnimGameItem_Test item = new AnimGameItem_Test(meshes,animations,roottransformation);
        
        return item;
    }
    
    private static Mesh processMesh(aimesh aimesh,List<Material> materials,List<Bone> boneList) {
        List<Float> vertices = new ArrayList<Float>();
        List<Float> textures = new ArrayList<>();
        List<Float> normals = new ArrayList<>();
        List<Integer> indices = new ArrayList<>();
        List<Integer> boneIds = new ArrayList<>();
        List<Float> weights = new ArrayList<>();
        
        processvertices(aimesh,vertices);
        processnormals(aimesh,normals);
        processtextCoords(aimesh,textures);
        processIndices(aimesh,indices);
        processBones(aimesh,boneIds,weights);
        
     // Texture coordinates may not have been populated. We need at least the empty slots
        if ( textures.size() == 0) {
            int numElements = (vertices.size() / 3) * 2;
            for (int i=0; i<numElements; i++) {
                textures.add(0.0f);
            }
        }
        
        Mesh mesh = new Mesh(Utils.listToArray(vertices),Utils.listToArray(normals),Utils.listToArray(textures),Utils.listIntToArray(indices),Utils.listIntToArray(boneIds),Utils.listToArray(weights));
        Material material;
        
        int materialIdx = aimesh.mMaterialIndex();
        if(materialIdx >= 0 && materialIdx < materials.size()) {
            material = materials.get(materialIdx);
        } else {
            material = new Material();
        }
        
        mesh.setMaterial(material);
        
        return mesh;
    }
    
    private static void processBones(aimesh aimesh,List<Bone> boneList,List<Integer> boneIds,List<Float> weights) {
        Map<Integer,List<VertexWeight>> weightSet = new HashMap<Integer,List<VertexWeight>>();
        int numBones = aimesh.mNumBones();
        PointerBuffer aiBones = aimesh.mBones();
        for(int i = 0; i < numBones; i++) {
            AIBone aiBone = AIBone.create(aiBones.get(i));
            int id = boneList.size();
            Bone bone = new Bone(id,aiBone.mName().dataString(),toMatrix(aiBone.mOffsetMatrix()));
            boneList.add(bone);
            
            int numWeights = aiBone.mNumWeights();
            AIVertexWeight.Buffer aiWeights = aiBone.mWeights();
            for(int j = 0; j < numWeights; j++) {
                AIVertexWeight aiWeight = aiWeights.get(j);
                VertexWeight vw = new VertexWeight(bone.getBoneId(),aiWeight.mVertexId(),aiWeight.mWeight());
                List<VertexWeight> vertexWeightList = weightSet.get(vw.getVertexId());
                
                if(vertexWeightList == null) {
                    vertexWeightList = new ArrayList<VertexWeight>();
                    weightSet.put(vw.getVertexId(),vertexWeightList);
                }
                vertexWeightList.add(vw);
            }
        }
        
        int numVertices = aimesh.mNumVertices();
        for(int i = 0; i < numVertices; i++) {
            List<VertexWeight> vertexWeightList = weightSet.get(i);
            int size = vertexWeightList != null ? vertexWeightList.size() : 0;
            for(int j = 0; j < Mesh.MAX_WEIGHTS; j++) {
                if(j < size) {
                    VertexWeight vw = vertexWeightList.get(j);
                    weights.add(vw.getWeight());
                    boneIds.add(vw.getBoneId());
                } else {
                    weights.add(0.0f);
                    boneIds.add(0);
                }
            }
        }
    }
    
    private static Node_Test processNodesHierarchy(AINode aiNode,Node_Test parentNode) {
        String nodeName = aiNode.mName().dataString();
        Node_Test node = new Node_Test(nodeName,parentNode);
        
        int numChildren = aiNode.mNumChildren();
        PointerBuffer aiChildren = aiNode.mChildren();
        for(int i = 0; i < numChildren; i++) {
            AINode aiChildNode = AINode.create(aiChildren.get(i));
            Node_Test childNode = processNodesHierarchy(aiChildNode,node);
            node.addChild(childNode);
        }
        
        return node;
    }
    
    private static Map<String,Animation_Test> processAnimations(AIScene aiScene,Node_Test rootNode,Matrix4f roottransformation) {
        Map<String,Animation_Test> animations = new HashMap<String,Animation_Test>();
        
        //Process all animations
        int numAnimations = aiScene.mNumAnimations();
        PointerBuffer aiAnimations = aiScene.mAnimations();
        for(int i = 0; i < numAnimations; i++) {
            AIAnimation aiAnimation = AIAnimation.create(aiAnimations.get(i));
            
            //Calculate transformation matrices for each node
            int numChannels = aiAnimation.mNumChannels();
            PointerBuffer aiChannels = aiAnimation.mChannels();
            for(int j = 0; j < numChannels; j++) {
                AINodeAnim aiNodeAnim = AINodeAnim.create(aiChannels.get(j));
                String nodeName = aiNodeAnim.mNodeName().dataString();
                Node_Test node = rootNode.findByName(nodeName);
                buildTransformationMatrices(aiNodeAnim,node);
            }
            
            Keyframe[] keyframes = orderKeyframes(boneList,roottransformation);
            Animation_Test animation = new Animation_Test(aiAnimation.mName().dataString(),keyframes,aiAnimation.mDuration());
            animations.put(animation.getName(),animation);
        }
        return animations;
    }
    
    private static void buildTransformationMatrices(AINodeAnim aiNodeAnim,Node_Test node) {
        int numFrames = aiNodeAnim.mNumPositionKeys();
        AIVectorKey.Buffer positionKeys = aiNodeAnim.mPositionKeys();
        AIVectorKey.Buffer scalingKeys = aiNodeAnim.mScalingKeys();
        AIQuatKey.Buffer rotationKeys = aiNodeAnim.mRotationKeys();
        
        for(int i = 0; i < numFrames; i++) {
            AIVectorKey aiVecKey = positionKeys.get(i);
            AIVector3D vec = aiVecKey.mValue();
            
            AIQuatKey quatKey = rotationKeys.get(i);
            AIQuaternion aiQuat = quatKey.mValue();
            Quaternionf quat = new Quaternionf(aiQuat.x(),aiQuat.y(),aiQuat.z(),aiQuat.w());
            
            if(i < aiNodeAnim.mNumScalingKeys()) {
                aiVecKey = scalingKeys.get(i);
                vec = aiVecKey.mValue();
            }
            
            double timeStamp = aiVecKey.mTime();
            BoneTransformation boneTransformation = new BoneTransformation(new Vector3f(vec.x(),vec.y(),vec.z()),quat,new Vector3f(vec.x(),vec.z()));
            
            node.addTransformation(boneTransformation);
            node.addKeyTime(timeStamp);
        }
    }
    
    private static Keyframe[] orderKeyframes(List<Bone> boneList,Matrix4f roottransformation) {
        //.getAnimationFrames() might need to be tweaked
        int numKeyframes = rootNode.getAnimationFrames();
        Keyframe[] keyframeList = new Keyframe[numKeyframes];
        for(int i = 0; i < numKeyframes; i++) {
            Keyframe keyframe = new Keyframe();
            keyframeList[i] = keyframe;
            
            int numBones = boneList.size();
            for(int j = 0; j < numBones; j++) {
                Bone bone = boneList.get(j);
                Node_Test node = rootNode.findByName(bone.getBoneName());
                node.addBoneId(j);
                node.addBoneOffsetMatrix(bone.getoffsetMatrix());
                BoneTransformation boneTransformation = Node_Test.getBoneTransformation(node,i);
                double keyTime = Node_Test.getKeyTime(node,i);
                keyframe.setBoneTransformation(j,boneTransformation);
                keyframe.setTimeStamp(keyTime);
            }
        }
        
        return keyframeList;
    }
    
    private static Matrix4f toMatrix(aimatrix4x4 aimatrix4x4) {
        Matrix4f result = new Matrix4f();
        result.m00(aimatrix4x4.a1());
        result.m10(aimatrix4x4.a2());
        result.m20(aimatrix4x4.a3());
        result.m30(aimatrix4x4.a4());
        result.m01(aimatrix4x4.b1());
        result.m11(aimatrix4x4.b2());
        result.m21(aimatrix4x4.b3());
        result.m31(aimatrix4x4.b4());
        result.m02(aimatrix4x4.c1());
        result.m12(aimatrix4x4.c2());
        result.m22(aimatrix4x4.c3());
        result.m32(aimatrix4x4.c4());
        result.m03(aimatrix4x4.d1());
        result.m13(aimatrix4x4.d2());
        result.m23(aimatrix4x4.d3());
        result.m33(aimatrix4x4.d4());

        return result;
    }
    
}

    public class BoneTransformation {
    
    private Vector3f position;
    private Quaternionf rotation;
    private Vector3f scaling;
    
    public BoneTransformation(Vector3f position,Quaternionf rotation,Vector3f scaling) {
        this.position = position;
        this.rotation = rotation;
        this.scaling = scaling;
    }
    
    protected static BoneTransformation interpolate(BoneTransformation frameA,BoneTransformation frameB,float progression) {
        Vector3f pos = interpolate(frameA.getPosition(),frameB.getPosition(),progression);
        Quaternionf rot = interpolate(frameA.getRotation(),frameB.getRotation(),progression);
        Vector3f scale = interpolate(frameA.getScaling(),frameB.getScaling(),progression);
        return new BoneTransformation(pos,rot,scale);
    }
    
    private static Vector3f interpolate(Vector3f start,Vector3f end,float progression) {
        float x = start.x + (end.x - start.x) * progression;
        float y = start.y + (end.y - start.y) * progression;
        float z = start.z + (end.z - start.z) * progression;
        return new Vector3f(x,y,z);
    }
    
    private static Quaternionf interpolate(Quaternionf start,Quaternionf end,float progression) {
        Quaternionf result = new Quaternionf(0,1);
        float dot = start.w * end.w + start.x * end.x + start.y * end.y + start.z * end.z;
        float progressionI = 1.0f - progression;
        if(dot < 0) {
            result.w = progressionI * start.w + progression * -end.w;
            result.x = progressionI * start.x + progression * -end.x;
            result.y = progressionI * start.y + progression * -end.y;
            result.z = progressionI * start.z + progression * -end.z;
        } else {
            result.w = progressionI * start.w + progression * end.w;
            result.x = progressionI * start.x + progression * end.x;
            result.y = progressionI * start.y + progression * end.y;
            result.z = progressionI * start.z + progression * end.z;
        }
        result.normalize();
        return result;
    }
    
    protected Matrix4f createLocalTransformation() {
        Matrix4f matrix = new Matrix4f();
        matrix.translate(position)
            .rotate(rotation)
            .scale(scaling);
        return matrix;
    }
    
    public Vector3f getPosition() {
        return position;
    }
    
    public Quaternionf getRotation() {
        return rotation;
    }
    
    public Vector3f getScaling() {
        return scaling;
    }
}


    public class Animator {
    
    private final AnimGameItem_Test animGameItem;
    
    private Animation_Test currentAnimation;
    private AnimatedFrame currentAnimatedFrame;
    private float animationTime;
    
    public Animator(AnimGameItem_Test animGameItem) {
        this.animGameItem = animGameItem;
    }
    
    public void doAnimation(Animation_Test animation) {
        this.animationTime = 0.0f;
        this.currentAnimation = animation;
    }
    
    public void update(float interval) {
        if(currentAnimation == null) {
            return;
        }
        
        increaseAnimationTime(interval);
        //get current and next keyframe and interpolate between them
        Map<Integer,Matrix4f> currentLocalPose = calculateCurrentAnimationPose();
        Map<Integer,Matrix4f> currentGlobalPose = new HashMap<Integer,Matrix4f>();
        buildGlobalPose(currentLocalPose,animGameItem.getRootNode(),animGameItem.getRootNodeTransformation(),currentGlobalPose);
        //buildGlobalPose(currentLocalPose,new Matrix4f(),currentGlobalPose);
        currentAnimatedFrame = buildAnimatedFrame(currentGlobalPose);
    }
    
    private Map<Integer,Matrix4f> calculateCurrentAnimationPose() {
        Keyframe[] keyframes = getPrevIoUsAndNextKeyframes();
        float progression = calculateProgression(keyframes[0],keyframes[1]);
        return interpolatePoses(keyframes[0],keyframes[1],progression);
    }
    
    private Keyframe[] getPrevIoUsAndNextKeyframes() {
        Keyframe[] allKeyframes = currentAnimation.getKeyframes();
        Keyframe prevIoUsKeyframe = allKeyframes[0];
        Keyframe nextKeyframe = allKeyframes[0];
        for(int i = 1; i < allKeyframes.length; i++) {
            nextKeyframe = allKeyframes[i];
            if(nextKeyframe.getTimeStamp() > animationTime) {
                break;
            }
            prevIoUsKeyframe = allKeyframes[i];
        }
        
        return new Keyframe[] { prevIoUsKeyframe,nextKeyframe };
    }
    
    private void increaseAnimationTime(float interval) {
        animationTime += interval;
        if(animationTime > (float)currentAnimation.getDuration()) {
            this.animationTime %= currentAnimation.getDuration();
        }
    }
    
    private float calculateProgression(Keyframe prevIoUsKeyframe,Keyframe nextKeyframe) {
        float totalTime = nextKeyframe.getTimeStamp() - prevIoUsKeyframe.getTimeStamp();
        float currentTime = animationTime - prevIoUsKeyframe.getTimeStamp();
        return currentTime / totalTime;
    }
    
    private Map<Integer,Matrix4f> interpolatePoses(Keyframe prevIoUsKeyframe,Keyframe nextKeyframe,float progression) {
        Map<Integer,Matrix4f> currentLocalPose = new HashMap<Integer,Matrix4f>();
        for(int i = 0; i < prevIoUsKeyframe.getBoneTransformations().length; i++) {
            BoneTransformation prevIoUsBoneTransformation = prevIoUsKeyframe.getBoneTransformations()[i];
            BoneTransformation nextBoneTransformation = nextKeyframe.getBoneTransformations()[i];
            BoneTransformation currentBoneTransformation = BoneTransformation.interpolate(prevIoUsBoneTransformation,nextBoneTransformation,progression);
            currentLocalPose.put(i,currentBoneTransformation.createLocalTransformation());
        }
        
        return currentLocalPose;
    }
    
    private void buildGlobalPose(Map<Integer,Matrix4f> currentLocalPose,Node_Test node,Matrix4f parentTransformation,Map<Integer,Matrix4f> globalPose) {
        Matrix4f currentLocalTransformation = null;
        Matrix4f currentGlobalTransformation = null;
        
        if(node.getBoneId() != -1) {
            currentLocalTransformation = currentLocalPose.get(node.getBoneId());
            currentGlobalTransformation = parentTransformation.mul(currentLocalTransformation);
        } else {
            currentGlobalTransformation = parentTransformation;
        }
        
        for(Node_Test childNode : node.getChildren()) {
            buildGlobalPose(currentLocalPose,childNode,new Matrix4f(currentGlobalTransformation),globalPose);
        }
        
        if(node.getBoneId() != -1) {
            currentGlobalTransformation = currentGlobalTransformation.mul(node.getBoneOffsetMatrix());
            globalPose.put(node.getBoneId(),currentGlobalTransformation);
        }
        
    }
    
    
    private AnimatedFrame buildAnimatedFrame(Map<Integer,Matrix4f> currentGlobalPose) {
        AnimatedFrame animatedFrame = new AnimatedFrame();
        for(Map.Entry<Integer,Matrix4f> matrixEntry : currentGlobalPose.entrySet()) {
            int boneId = matrixEntry.getKey();
            Matrix4f matrix = matrixEntry.getValue();
            animatedFrame.setMatrix(boneId,matrix);
        }
        
        return animatedFrame;
    }
    
    public AnimatedFrame getCurrentAnimatedFrame() {
        return currentAnimatedFrame;
    }
    
    private Matrix4f copyMatrix(Matrix4f source) {
        Matrix4f matrix = new Matrix4f();
        matrix.m00(source.m00());
        matrix.m01(source.m01());
        matrix.m02(source.m02());
        matrix.m03(source.m03());

        matrix.m10(source.m10());
        matrix.m11(source.m11());
        matrix.m12(source.m12());
        matrix.m13(source.m13());

        matrix.m20(source.m20());
        matrix.m21(source.m21());
        matrix.m22(source.m22());
        matrix.m23(source.m23());

        matrix.m30(source.m30());
        matrix.m31(source.m31());
        matrix.m32(source.m32());
        matrix.m33(source.m33());
        
        return matrix;
    }
}

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。