Search in sources :

Example 6 with FbxMesh

use of com.jme3.scene.plugins.fbx.objects.FbxMesh in project jmonkeyengine by jMonkeyEngine.

the class SceneLoader method linkScene.

private void linkScene() {
    logger.log(Level.FINE, "Linking scene objects");
    long startTime = System.currentTimeMillis();
    applySkinning();
    buildAnimations();
    for (FbxMesh mesh : geomMap.values()) mesh.clearMaterials();
    // Remove bones from node structures : JME creates attach node by itself
    for (FbxNode limb : limbMap.values()) limb.node.removeFromParent();
    long estimatedTime = System.currentTimeMillis() - startTime;
    logger.log(Level.FINE, "Linking done in {0} ms", estimatedTime);
}
Also used : FbxNode(com.jme3.scene.plugins.fbx.objects.FbxNode) FbxMesh(com.jme3.scene.plugins.fbx.objects.FbxMesh)

Example 7 with FbxMesh

use of com.jme3.scene.plugins.fbx.objects.FbxMesh in project jmonkeyengine by jMonkeyEngine.

the class FbxNode method toJmeObject.

@Override
public Spatial toJmeObject() {
    Spatial spatial;
    if (nodeAttribute instanceof FbxMesh) {
        FbxMesh fbxMesh = (FbxMesh) nodeAttribute;
        IntMap<Mesh> jmeMeshes = fbxMesh.getJmeObject();
        if (jmeMeshes == null || jmeMeshes.size() == 0) {
            // No meshes found on FBXMesh (??)
            logger.log(Level.WARNING, "No meshes could be loaded. Creating empty node.");
            spatial = new Node(getName() + "-node");
        } else {
            // Multiple jME3 geometries required for a single FBXMesh.
            String nodeName;
            if (children.isEmpty()) {
                nodeName = getName() + "-mesh";
            } else {
                nodeName = getName() + "-node";
            }
            Node node = new Node(nodeName);
            boolean singleMesh = jmeMeshes.size() == 1;
            for (IntMap.Entry<Mesh> meshInfo : jmeMeshes) {
                node.attachChild(tryCreateGeometry(meshInfo.getKey(), meshInfo.getValue(), singleMesh));
            }
            spatial = node;
        }
    } else {
        if (nodeAttribute != null) {
            // Just specifies that this is a "null" node.
            nodeAttribute.getJmeObject();
        }
        // TODO: handle other node attribute types.
        //       right now everything we don't know about gets converted
        //       to jME3 Node.
        spatial = new Node(getName() + "-node");
    }
    if (!children.isEmpty()) {
        // Check uniform scale.
        // Although, if inheritType is 0 (eInheritRrSs)
        // it might not be a problem.
        Vector3f localScale = jmeLocalNodeTransform.getScale();
        if (!FastMath.approximateEquals(localScale.x, localScale.y) || !FastMath.approximateEquals(localScale.x, localScale.z)) {
            logger.log(Level.WARNING, "Non-uniform scale detected on parent node. " + "The model may appear distorted.");
        }
    }
    spatial.setLocalTransform(jmeLocalNodeTransform);
    if (visibility == 0.0) {
        spatial.setCullHint(CullHint.Always);
    }
    for (Map.Entry<String, Object> userDataEntry : userData.entrySet()) {
        spatial.setUserData(userDataEntry.getKey(), userDataEntry.getValue());
    }
    return spatial;
}
Also used : FbxMesh(com.jme3.scene.plugins.fbx.mesh.FbxMesh) FbxLimbNode(com.jme3.scene.plugins.fbx.anim.FbxLimbNode) Node(com.jme3.scene.Node) FbxAnimCurveNode(com.jme3.scene.plugins.fbx.anim.FbxAnimCurveNode) FbxMesh(com.jme3.scene.plugins.fbx.mesh.FbxMesh) Mesh(com.jme3.scene.Mesh) Spatial(com.jme3.scene.Spatial) Vector3f(com.jme3.math.Vector3f) IntMap(com.jme3.util.IntMap) FbxObject(com.jme3.scene.plugins.fbx.obj.FbxObject) IntMap(com.jme3.util.IntMap) HashMap(java.util.HashMap) Map(java.util.Map)

Example 8 with FbxMesh

use of com.jme3.scene.plugins.fbx.objects.FbxMesh in project jmonkeyengine by jMonkeyEngine.

the class FbxNode method getPreferredParent.

/**
     * If this geometry node is deformed by a skeleton, this
     * returns the node containing the skeleton.
     * 
     * In jME3, a mesh can be deformed by a skeleton only if it is 
     * a child of the node containing the skeleton. However, this
     * is not a requirement in FBX, so we have to modify the scene graph
     * of the loaded model to adjust for this.
     * This happens automatically in 
     * {@link #createScene(com.jme3.scene.plugins.fbx.node.FbxNode)}.
     * 
     * @return The model this node would like to be a child of, or null
     * if no preferred parent.
     */
public FbxNode getPreferredParent() {
    if (!(nodeAttribute instanceof FbxMesh)) {
        return null;
    }
    FbxMesh fbxMesh = (FbxMesh) nodeAttribute;
    FbxSkinDeformer deformer = fbxMesh.getSkinDeformer();
    FbxNode preferredParent = null;
    if (deformer != null) {
        for (FbxCluster cluster : deformer.getJmeObject()) {
            FbxLimbNode limb = cluster.getLimb();
            if (preferredParent == null) {
                preferredParent = limb.getSkeletonHolder();
            } else if (preferredParent != limb.getSkeletonHolder()) {
                logger.log(Level.WARNING, "A mesh is being deformed by multiple skeletons. " + "Only one skeleton will work, ignoring other skeletons.");
            }
        }
    }
    return preferredParent;
}
Also used : FbxCluster(com.jme3.scene.plugins.fbx.anim.FbxCluster) FbxMesh(com.jme3.scene.plugins.fbx.mesh.FbxMesh) FbxSkinDeformer(com.jme3.scene.plugins.fbx.anim.FbxSkinDeformer) FbxLimbNode(com.jme3.scene.plugins.fbx.anim.FbxLimbNode)

Example 9 with FbxMesh

use of com.jme3.scene.plugins.fbx.objects.FbxMesh in project jmonkeyengine by jMonkeyEngine.

the class FbxSkin method generateBoneData.

private int generateBoneData(Mesh mesh, FbxMesh fbxMesh) {
    // Create bone buffers
    FloatBuffer boneWeightData = BufferUtils.createFloatBuffer(fbxMesh.vCount * 4);
    ByteBuffer boneIndicesData = BufferUtils.createByteBuffer(fbxMesh.vCount * 4);
    mesh.setBuffer(VertexBuffer.Type.BoneWeight, 4, boneWeightData);
    mesh.setBuffer(VertexBuffer.Type.BoneIndex, 4, boneIndicesData);
    mesh.getBuffer(VertexBuffer.Type.BoneWeight).setUsage(Usage.CpuOnly);
    mesh.getBuffer(VertexBuffer.Type.BoneIndex).setUsage(Usage.CpuOnly);
    VertexBuffer weightsHW = new VertexBuffer(Type.HWBoneWeight);
    VertexBuffer indicesHW = new VertexBuffer(Type.HWBoneIndex);
    // Setting usage to CpuOnly so that the buffer is not send empty to the GPU
    indicesHW.setUsage(Usage.CpuOnly);
    weightsHW.setUsage(Usage.CpuOnly);
    mesh.setBuffer(weightsHW);
    mesh.setBuffer(indicesHW);
    int bonesLimitExceeded = 0;
    // Accumulate skin bones influence into mesh buffers
    for (FbxNode limb : bones) {
        FbxCluster cluster = limb.skinToCluster.get(id);
        if (cluster == null || cluster.indexes == null || cluster.weights == null || cluster.indexes.length != cluster.weights.length)
            continue;
        if (limb.boneIndex > 255)
            throw new AssetLoadException("Bone index can't be packed into byte");
        for (int i = 0; i < cluster.indexes.length; ++i) {
            int vertexIndex = cluster.indexes[i];
            if (vertexIndex >= fbxMesh.reverseVertexMap.size())
                throw new AssetLoadException("Invalid skinning vertex index. Unexpected index lookup " + vertexIndex + " from " + fbxMesh.reverseVertexMap.size());
            List<Integer> dstVertices = fbxMesh.reverseVertexMap.get(vertexIndex);
            for (int j = 0; j < dstVertices.size(); ++j) {
                int v = dstVertices.get(j);
                // Append bone index and weight to vertex
                int offset;
                int smalestOffset = 0;
                float w = 0;
                float smalestW = Float.MAX_VALUE;
                for (offset = v * 4; offset < v * 4 + 4; ++offset) {
                    w = boneWeightData.get(offset);
                    if (w == 0)
                        break;
                    if (w < smalestW) {
                        smalestW = w;
                        smalestOffset = offset;
                    }
                }
                if (w == 0) {
                    boneWeightData.put(offset, (float) cluster.weights[i]);
                    boneIndicesData.put(offset, (byte) limb.boneIndex);
                } else {
                    if ((float) cluster.weights[i] > smalestW) {
                        // If current weight more than smallest, discard smallest
                        boneWeightData.put(smalestOffset, (float) cluster.weights[i]);
                        boneIndicesData.put(smalestOffset, (byte) limb.boneIndex);
                    }
                    bonesLimitExceeded++;
                }
            }
        }
    }
    if (bonesLimitExceeded > 0)
        scene.warning("Skinning support max 4 bone per vertex. Exceeding data of " + bonesLimitExceeded + " weights in mesh bones will be discarded");
    // Postprocess bones weights
    int maxWeightsPerVert = 0;
    boneWeightData.rewind();
    for (int v = 0; v < fbxMesh.vCount; v++) {
        float w0 = boneWeightData.get();
        float w1 = boneWeightData.get();
        float w2 = boneWeightData.get();
        float w3 = boneWeightData.get();
        if (w3 != 0) {
            maxWeightsPerVert = Math.max(maxWeightsPerVert, 4);
        } else if (w2 != 0) {
            maxWeightsPerVert = Math.max(maxWeightsPerVert, 3);
        } else if (w1 != 0) {
            maxWeightsPerVert = Math.max(maxWeightsPerVert, 2);
        } else if (w0 != 0) {
            maxWeightsPerVert = Math.max(maxWeightsPerVert, 1);
        }
        float sum = w0 + w1 + w2 + w3;
        if (sum != 1f) {
            // normalize weights
            float mult = (sum != 0) ? (1f / sum) : 0;
            boneWeightData.position(v * 4);
            boneWeightData.put(w0 * mult);
            boneWeightData.put(w1 * mult);
            boneWeightData.put(w2 * mult);
            boneWeightData.put(w3 * mult);
        }
    }
    return maxWeightsPerVert;
}
Also used : VertexBuffer(com.jme3.scene.VertexBuffer) FloatBuffer(java.nio.FloatBuffer) ByteBuffer(java.nio.ByteBuffer) AssetLoadException(com.jme3.asset.AssetLoadException)

Aggregations

FbxMesh (com.jme3.scene.plugins.fbx.mesh.FbxMesh)3 Vector3f (com.jme3.math.Vector3f)2 Mesh (com.jme3.scene.Mesh)2 FbxLimbNode (com.jme3.scene.plugins.fbx.anim.FbxLimbNode)2 FbxElement (com.jme3.scene.plugins.fbx.file.FbxElement)2 FbxObject (com.jme3.scene.plugins.fbx.obj.FbxObject)2 FbxMesh (com.jme3.scene.plugins.fbx.objects.FbxMesh)2 FbxNode (com.jme3.scene.plugins.fbx.objects.FbxNode)2 Bone (com.jme3.animation.Bone)1 AssetLoadException (com.jme3.asset.AssetLoadException)1 Material (com.jme3.material.Material)1 Quaternion (com.jme3.math.Quaternion)1 Geometry (com.jme3.scene.Geometry)1 Node (com.jme3.scene.Node)1 Spatial (com.jme3.scene.Spatial)1 CullHint (com.jme3.scene.Spatial.CullHint)1 VertexBuffer (com.jme3.scene.VertexBuffer)1 IrMesh (com.jme3.scene.plugins.IrMesh)1 IrPolygon (com.jme3.scene.plugins.IrPolygon)1 IrVertex (com.jme3.scene.plugins.IrVertex)1