Search in sources :

Example 1 with Skinning

use of net.drewke.tdme.engine.model.Skinning in project tdme by andreasdr.

the class TMReader method readSkinning.

/**
	 * Read skinning from input stream
	 * @param input stream
	 * @param group
	 * @throws IOException
	 */
private static void readSkinning(InputStream is, Group g) throws IOException, ModelFileIOException {
    if (readBoolean(is) == true) {
        Skinning skinning = g.createSkinning();
        skinning.setWeights(readFloatArray(is));
        Joint[] joints = new Joint[readInt(is)];
        for (int i = 0; i < joints.length; i++) {
            joints[i] = readSkinningJoint(is);
        }
        skinning.setJoints(joints);
        JointWeight[][] verticesJointsWeight = new JointWeight[readInt(is)][];
        for (int i = 0; i < verticesJointsWeight.length; i++) {
            verticesJointsWeight[i] = new JointWeight[readInt(is)];
            for (int j = 0; j < verticesJointsWeight[i].length; j++) {
                verticesJointsWeight[i][j] = readSkinningJointWeight(is);
            }
        }
        skinning.setVerticesJointsWeights(verticesJointsWeight);
    }
}
Also used : Skinning(net.drewke.tdme.engine.model.Skinning) Joint(net.drewke.tdme.engine.model.Joint) JointWeight(net.drewke.tdme.engine.model.JointWeight) Joint(net.drewke.tdme.engine.model.Joint)

Example 2 with Skinning

use of net.drewke.tdme.engine.model.Skinning in project tdme by andreasdr.

the class Object3DGroupMesh method createMesh.

/**
	 * Creates a object3d group mesh from group
	 * @param animation processing target
	 * @param group
	 * @param transformationm matrices
	 * @return object 3d group mesh
	 */
protected static Object3DGroupMesh createMesh(Engine.AnimationProcessingTarget animationProcessingTarget, Group group, HashMap<String, Matrix4x4> transformationMatrices) {
    Object3DGroupMesh mesh = new Object3DGroupMesh();
    // group data
    Vector3[] groupVertices = group.getVertices();
    Vector3[] groupNormals = group.getNormals();
    TextureCoordinate[] groupTextureCoordinates = group.getTextureCoordinates();
    Vector3[] groupTangents = group.getTangents();
    Vector3[] groupBitangents = group.getBitangents();
    // determine face count
    int faceCount = group.getFaceCount();
    // set up face count
    mesh.faces = faceCount;
    // animation processing target
    mesh.animationProcessingTarget = animationProcessingTarget;
    // transformations for skinned meshes
    Skinning skinning = group.getSkinning();
    mesh.skinning = skinning != null;
    // transformed mesh vertices
    mesh.transformedVertices = new Vector3[groupVertices.length];
    for (int j = 0; j < mesh.transformedVertices.length; j++) {
        mesh.transformedVertices[j] = new Vector3().set(groupVertices[j]);
    }
    // transformed mesh normals
    mesh.transformedNormals = new Vector3[groupNormals.length];
    for (int j = 0; j < mesh.transformedNormals.length; j++) {
        mesh.transformedNormals[j] = new Vector3().set(groupNormals[j]);
    }
    // texture coordinates
    if (groupTextureCoordinates != null) {
        mesh.textureCoordinates = new TextureCoordinate[groupTextureCoordinates.length];
        for (int j = 0; j < mesh.textureCoordinates.length; j++) {
            mesh.textureCoordinates[j] = new TextureCoordinate(groupTextureCoordinates[j]);
        }
    }
    // transformed mesh tangents
    if (groupTangents != null) {
        mesh.transformedTangents = new Vector3[groupTangents.length];
        for (int j = 0; j < mesh.transformedTangents.length; j++) {
            mesh.transformedTangents[j] = new Vector3().set(groupTangents[j]);
        }
    }
    // transformed mesh bitangents
    if (groupBitangents != null) {
        mesh.transformedBitangents = new Vector3[groupBitangents.length];
        for (int j = 0; j < mesh.transformedBitangents.length; j++) {
            mesh.transformedBitangents[j] = new Vector3().set(groupBitangents[j]);
        }
    }
    // indices
    int indicesCount = 0;
    for (FacesEntity facesEntity : group.getFacesEntities()) {
        indicesCount += 3 * facesEntity.getFaces().length;
    }
    mesh.indices = new short[indicesCount];
    {
        int j = 0;
        // create face vertex indices
        for (FacesEntity facesEntity : group.getFacesEntities()) for (Face face : facesEntity.getFaces()) for (int vertexIndex : face.getVertexIndices()) {
            mesh.indices[j++] = (short) vertexIndex;
        }
    }
    //
    mesh.recreatedBuffers = false;
    // create mesh upload buffers
    if (mesh.animationProcessingTarget != Engine.AnimationProcessingTarget.CPU_NORENDERING) {
        mesh.sbIndices = ByteBuffer.allocateDirect(mesh.faces * 3 * Short.SIZE / Byte.SIZE).order(ByteOrder.nativeOrder()).asShortBuffer();
        mesh.fbVertices = ByteBuffer.allocateDirect(groupVertices.length * 3 * Float.SIZE / Byte.SIZE).order(ByteOrder.nativeOrder()).asFloatBuffer();
        mesh.fbNormals = ByteBuffer.allocateDirect(groupNormals.length * 3 * Float.SIZE / Byte.SIZE).order(ByteOrder.nativeOrder()).asFloatBuffer();
        mesh.fbTextureCoordinates = groupTextureCoordinates != null ? ByteBuffer.allocateDirect(groupTextureCoordinates.length * 2 * Float.SIZE / Byte.SIZE).order(ByteOrder.nativeOrder()).asFloatBuffer() : null;
        mesh.fbTangents = groupTangents != null ? ByteBuffer.allocateDirect(groupTangents.length * 3 * Float.SIZE / Byte.SIZE).order(ByteOrder.nativeOrder()).asFloatBuffer() : null;
        mesh.fbBitangents = groupBitangents != null ? ByteBuffer.allocateDirect(groupBitangents.length * 3 * Float.SIZE / Byte.SIZE).order(ByteOrder.nativeOrder()).asFloatBuffer() : null;
        // create face vertex indices, will never be changed in engine
        for (FacesEntity facesEntity : group.getFacesEntities()) for (Face face : facesEntity.getFaces()) for (int vertexIndex : face.getVertexIndices()) {
            mesh.sbIndices.put((short) vertexIndex);
        }
        mesh.sbIndices.flip();
        // create texture coordinates buffer, will never be changed in engine
        if (mesh.fbTextureCoordinates != null) {
            // construct texture coordinates byte buffer as this will not change usually
            for (TextureCoordinate textureCoordinate : groupTextureCoordinates) {
                mesh.fbTextureCoordinates.put(textureCoordinate.getArray());
            }
            mesh.fbTextureCoordinates.flip();
        }
    }
    // group transformations matrix
    if (mesh.animationProcessingTarget == Engine.AnimationProcessingTarget.CPU || mesh.animationProcessingTarget == Engine.AnimationProcessingTarget.CPU_NORENDERING) {
        // group transformations matrix 
        mesh.cGroupTransformationsMatrix = transformationMatrices.get(group.getId());
    }
    // skinning
    if (skinning != null) {
        // skinning computation caches if computing skinning on CPU
        if (mesh.animationProcessingTarget == Engine.AnimationProcessingTarget.CPU || mesh.animationProcessingTarget == Engine.AnimationProcessingTarget.CPU_NORENDERING) {
            mesh.cSkinningJointWeight = new float[groupVertices.length][];
            mesh.cSkinningJointBindMatrices = new Matrix4x4[groupVertices.length][];
            mesh.cSkinningJointTransformationsMatrices = new Matrix4x4[groupVertices.length][];
            mesh.cTransformationsMatrix = new Matrix4x4();
            // compute joint weight caches
            Joint[] joints = skinning.getJoints();
            float[] weights = skinning.getWeights();
            JointWeight[][] jointsWeights = skinning.getVerticesJointsWeights();
            for (int vertexIndex = 0; vertexIndex < groupVertices.length; vertexIndex++) {
                int vertexJointWeights = jointsWeights[vertexIndex].length;
                if (vertexJointWeights > mesh.cSkinningMaxVertexWeights)
                    mesh.cSkinningMaxVertexWeights = vertexJointWeights;
                mesh.cSkinningJointWeight[vertexIndex] = new float[vertexJointWeights];
                mesh.cSkinningJointBindMatrices[vertexIndex] = new Matrix4x4[vertexJointWeights];
                mesh.cSkinningJointTransformationsMatrices[vertexIndex] = new Matrix4x4[vertexJointWeights];
                int jointWeightIdx = 0;
                for (JointWeight jointWeight : jointsWeights[vertexIndex]) {
                    Joint joint = joints[jointWeight.getJointIndex()];
                    // 
                    mesh.cSkinningJointWeight[vertexIndex][jointWeightIdx] = weights[jointWeight.getWeightIndex()];
                    mesh.cSkinningJointBindMatrices[vertexIndex][jointWeightIdx] = joint.getBindMatrix();
                    mesh.cSkinningJointTransformationsMatrices[vertexIndex][jointWeightIdx] = transformationMatrices.get(joint.getGroupId());
                    // next
                    jointWeightIdx++;
                }
            }
        } else // GPU setup
        if (mesh.animationProcessingTarget == Engine.AnimationProcessingTarget.GPU) {
            // create skinning buffers
            mesh.gIbSkinningVerticesJoints = ByteBuffer.allocateDirect(groupVertices.length * 1 * Float.SIZE / Byte.SIZE).order(ByteOrder.nativeOrder()).asFloatBuffer();
            mesh.gFbSkinningVerticesVertexJointsIdxs = ByteBuffer.allocateDirect(groupVertices.length * 4 * Float.SIZE / Byte.SIZE).order(ByteOrder.nativeOrder()).asFloatBuffer();
            mesh.gFbSkinningVerticesVertexJointsWeights = ByteBuffer.allocateDirect(groupVertices.length * 4 * Float.SIZE / Byte.SIZE).order(ByteOrder.nativeOrder()).asFloatBuffer();
            mesh.gFbSkinningJointsTransformationsMatrices = ByteBuffer.allocateDirect(60 * 16 * Float.SIZE / Byte.SIZE).order(ByteOrder.nativeOrder()).asFloatBuffer();
            mesh.gFbSkinningTransformationMatrix = new Matrix4x4();
            // fill skinning buffers, joint bind matrices
            mesh.skinningJoints = skinning.getJoints().length;
            mesh.gSkinningJointBindMatrices = new ArrayList<Matrix4x4>();
            for (Joint joint : skinning.getJoints()) {
                mesh.gSkinningJointBindMatrices.add(joint.getBindMatrix());
            }
            //
            JointWeight[][] jointsWeights = skinning.getVerticesJointsWeights();
            float[] weights = skinning.getWeights();
            for (int groupVertexIndex = 0; groupVertexIndex < groupVertices.length; groupVertexIndex++) {
                int vertexJoints = jointsWeights[groupVertexIndex].length;
                // put number of joints
                mesh.gIbSkinningVerticesJoints.put((float) vertexJoints);
                // vertex joint idx 1..4
                for (int i = 0; i < 4; i++) {
                    mesh.gFbSkinningVerticesVertexJointsIdxs.put((float) (vertexJoints > i ? jointsWeights[groupVertexIndex][i].getJointIndex() : -1));
                }
                // vertex joint weight 1..4
                for (int i = 0; i < 4; i++) {
                    mesh.gFbSkinningVerticesVertexJointsWeights.put(vertexJoints > i ? weights[jointsWeights[groupVertexIndex][i].getWeightIndex()] : 0.0f);
                }
            }
            // put number of joints
            mesh.gIbSkinningVerticesJoints.flip();
            // vertex joint idx 1..4
            mesh.gFbSkinningVerticesVertexJointsIdxs.flip();
            // vertex joint weight 1..4
            mesh.gFbSkinningVerticesVertexJointsWeights.flip();
        }
    }
    // temp vector3
    mesh.tmpVector3 = new Vector3();
    // issue a recreate buffer and upload to graphics board
    mesh.recreateBuffers(group);
    //
    return mesh;
}
Also used : FacesEntity(net.drewke.tdme.engine.model.FacesEntity) ArrayList(java.util.ArrayList) Vector3(net.drewke.tdme.math.Vector3) Joint(net.drewke.tdme.engine.model.Joint) JointWeight(net.drewke.tdme.engine.model.JointWeight) Joint(net.drewke.tdme.engine.model.Joint) Matrix4x4(net.drewke.tdme.math.Matrix4x4) TextureCoordinate(net.drewke.tdme.engine.model.TextureCoordinate) Skinning(net.drewke.tdme.engine.model.Skinning) Face(net.drewke.tdme.engine.model.Face)

Example 3 with Skinning

use of net.drewke.tdme.engine.model.Skinning in project tdme by andreasdr.

the class Object3DGroupMesh method computeTransformations.

/**
	 * Computes mesh transformations
	 * @param group
	 */
protected void computeTransformations(Group group) {
    Vector3[] groupVertices = group.getVertices();
    Vector3[] groupNormals = group.getNormals();
    Vector3[] groupTangent = group.getTangents();
    Vector3[] groupBitangent = group.getBitangents();
    // transformations for skinned meshes
    Skinning skinning = group.getSkinning();
    if (skinning != null) {
        // compute skinning on CPU if required
        if (animationProcessingTarget == Engine.AnimationProcessingTarget.CPU || animationProcessingTarget == Engine.AnimationProcessingTarget.CPU_NORENDERING) {
            JointWeight[][] jointsWeights = skinning.getVerticesJointsWeights();
            Vector3 vertex;
            Vector3 transformedVertex;
            Vector3 normal;
            Vector3 transformedNormal;
            Vector3 tangent;
            Vector3 transformedTangent;
            Vector3 bitangent;
            Vector3 transformedBitangent;
            float totalWeights;
            float weightNormalized;
            for (int vertexIndex = 0; vertexIndex < groupVertices.length; vertexIndex++) {
                // do vertices
                vertex = groupVertices[vertexIndex];
                transformedVertex = transformedVertices[vertexIndex].set(0f, 0f, 0f);
                normal = groupNormals[vertexIndex];
                transformedNormal = transformedNormals[vertexIndex].set(0f, 0f, 0f);
                tangent = groupTangent != null ? groupTangent[vertexIndex] : null;
                transformedTangent = transformedTangents != null ? transformedTangents[vertexIndex].set(0f, 0f, 0f) : null;
                bitangent = groupTangent != null ? groupBitangent[vertexIndex] : null;
                transformedBitangent = transformedBitangents != null ? transformedBitangents[vertexIndex].set(0f, 0f, 0f) : null;
                // compute every influence on vertex and vertex normals
                totalWeights = 0f;
                for (int vertexJointWeightIdx = 0; vertexJointWeightIdx < jointsWeights[vertexIndex].length; vertexJointWeightIdx++) {
                    float weight = cSkinningJointWeight[vertexIndex][vertexJointWeightIdx];
                    // 
                    cTransformationsMatrix.set(cSkinningJointBindMatrices[vertexIndex][vertexJointWeightIdx]);
                    cTransformationsMatrix.multiply(cSkinningJointTransformationsMatrices[vertexIndex][vertexJointWeightIdx]);
                    // vertex
                    transformedVertex.add(cTransformationsMatrix.multiply(vertex, tmpVector3).scale(weight));
                    // normals
                    transformedNormal.add(cTransformationsMatrix.multiplyNoTranslation(normal, tmpVector3).scale(weight));
                    // tangent
                    if (tangent != null) {
                        transformedTangent.add(cTransformationsMatrix.multiplyNoTranslation(tangent, tmpVector3).scale(weight));
                    }
                    // bitangent
                    if (bitangent != null) {
                        transformedBitangent.add(cTransformationsMatrix.multiplyNoTranslation(bitangent, tmpVector3).scale(weight));
                    }
                    //
                    totalWeights += weight;
                }
                // scale to full weight
                if (totalWeights != 1f) {
                    weightNormalized = 1f / totalWeights;
                    // vertex
                    transformedVertex.scale(weightNormalized);
                    // normals
                    transformedNormal.scale(weightNormalized);
                    // tangent
                    if (transformedTangent != null) {
                        transformedTangent.scale(weightNormalized);
                    }
                    // bitangent
                    if (transformedBitangent != null) {
                        transformedBitangent.scale(weightNormalized);
                    }
                }
                // normalize normal
                transformedNormal.normalize();
            }
            // recreate buffers
            recreateBuffers(group);
        }
    } else {
        if (animationProcessingTarget == Engine.AnimationProcessingTarget.CPU_NORENDERING) {
            //	vertices
            for (int vertexIndex = 0; vertexIndex < groupVertices.length; vertexIndex++) {
                transformedVertices[vertexIndex].set(cGroupTransformationsMatrix.multiply(groupVertices[vertexIndex], tmpVector3));
            }
            //	normals
            for (int normalIndex = 0; normalIndex < groupNormals.length; normalIndex++) {
                transformedNormals[normalIndex].set(cGroupTransformationsMatrix.multiplyNoTranslation(groupNormals[normalIndex], tmpVector3).normalize());
            }
            // recreate buffers
            recreateBuffers(group);
        }
    }
}
Also used : Vector3(net.drewke.tdme.math.Vector3) Skinning(net.drewke.tdme.engine.model.Skinning) Joint(net.drewke.tdme.engine.model.Joint)

Example 4 with Skinning

use of net.drewke.tdme.engine.model.Skinning in project tdme by andreasdr.

the class Object3DGroup method createGroups.

/**
	 * Creates a object 3d groups recursively for given group and it sub groups
	 * @param object 3D base
	 * @param object 3D groups
	 * @param groups
	 * @param animated
	 * @param use mesh manager
	 */
private static void createGroups(Object3DBase object3D, ArrayList<Object3DGroup> object3DGroups, HashMap<String, Group> groups, boolean animated, boolean useMeshManager, Engine.AnimationProcessingTarget animationProcessingTarget) {
    for (Group group : groups.getValuesIterator()) {
        // skip on joints
        if (group.isJoint() == true) {
            continue;
        }
        // determine face count
        int faceCount = group.getFaceCount();
        // skip on groups without faces
        if (faceCount > 0) {
            // create group render data
            Object3DGroup object3DGroup = new Object3DGroup();
            // add it to group render data list
            object3DGroups.add(object3DGroup);
            // determine mesh id
            object3DGroup.id = group.getModel().getId() + ":" + group.getId() + ":" + animationProcessingTarget.toString().toLowerCase();
            if (animated == true && (animationProcessingTarget == AnimationProcessingTarget.CPU || animationProcessingTarget == AnimationProcessingTarget.CPU_NORENDERING)) {
                //
                object3DGroup.id += ":" + (counter++);
            }
            object3DGroup.object = object3D;
            object3DGroup.group = group;
            object3DGroup.animated = animated;
            if (useMeshManager == true) {
                MeshManager meshManager = Engine.getInstance().getMeshManager();
                object3DGroup.mesh = meshManager.getMesh(object3DGroup.id);
                if (object3DGroup.mesh == null) {
                    object3DGroup.mesh = Object3DGroupMesh.createMesh(animationProcessingTarget, group, object3D.transformationsMatrices);
                    meshManager.addMesh(object3DGroup.id, object3DGroup.mesh);
                }
            } else {
                object3DGroup.mesh = Object3DGroupMesh.createMesh(animationProcessingTarget, group, object3D.transformationsMatrices);
            }
            object3DGroup.materialDiffuseTextureIdsByEntities = new int[group.getFacesEntities().length];
            object3DGroup.dynamicDiffuseTextureIdsByEntities = new int[group.getFacesEntities().length];
            object3DGroup.materialSpecularTextureIdsByEntities = new int[group.getFacesEntities().length];
            object3DGroup.materialDisplacementTextureIdsByEntities = new int[group.getFacesEntities().length];
            object3DGroup.materialNormalTextureIdsByEntities = new int[group.getFacesEntities().length];
            for (int j = 0; j < group.getFacesEntities().length; j++) {
                object3DGroup.materialDiffuseTextureIdsByEntities[j] = GLTEXTUREID_NONE;
                object3DGroup.dynamicDiffuseTextureIdsByEntities[j] = GLTEXTUREID_NONE;
                object3DGroup.materialSpecularTextureIdsByEntities[j] = GLTEXTUREID_NONE;
                object3DGroup.materialDisplacementTextureIdsByEntities[j] = GLTEXTUREID_NONE;
                object3DGroup.materialNormalTextureIdsByEntities[j] = GLTEXTUREID_NONE;
            }
            // determine renderer
            object3DGroup.renderer = new Object3DGroupVBORenderer(object3DGroup);
            // skinning
            Skinning skinning = group.getSkinning();
            if (skinning != null) {
                object3DGroup.groupTransformationsMatricesVector = new ArrayList<Matrix4x4>();
                for (Joint joint : skinning.getJoints()) {
                    object3DGroup.groupTransformationsMatricesVector.add(object3D.transformationsMatrices.get(joint.getGroupId()));
                }
            } else {
                object3DGroup.groupTransformationsMatricesVector = null;
            }
            //
            object3DGroup.groupTransformationsMatrix = object3D.transformationsMatrices.get(group.getId());
        }
        // but still check sub groups
        createGroups(object3D, object3DGroups, group.getSubGroups(), animated, useMeshManager, animationProcessingTarget);
    }
}
Also used : Group(net.drewke.tdme.engine.model.Group) Skinning(net.drewke.tdme.engine.model.Skinning) Joint(net.drewke.tdme.engine.model.Joint) MeshManager(net.drewke.tdme.engine.subsystems.manager.MeshManager) Joint(net.drewke.tdme.engine.model.Joint) Matrix4x4(net.drewke.tdme.math.Matrix4x4)

Example 5 with Skinning

use of net.drewke.tdme.engine.model.Skinning in project tdme by andreasdr.

the class DAEReader method readVisualSceneInstanceController.

/**
	 * Reads a instance controller
	 * @param authoring tool
	 * @param path name
	 * @param model
	 * @param parent group
	 * @param xml root
	 * @param xml node
	 * @return Group
	 * @throws Exception
	 */
private static Group readVisualSceneInstanceController(AuthoringTool authoringTool, String pathName, Model model, Group parentGroup, Element xmlRoot, Element xmlNode) throws Exception {
    StringTokenizer t;
    String xmlNodeId = xmlNode.getAttribute("id");
    String xmlNodeName = xmlNode.getAttribute("name");
    HashMap<String, String> materialSymbols = new HashMap<String, String>();
    // geometry id
    String xmlGeometryId = null;
    // parse library controllers, find our controller
    List<Element> xmlInstanceControllers = getChildrenByTagName(xmlNode, "instance_controller");
    Element xmlSkin = null;
    Element xmlInstanceController = xmlInstanceControllers.get(0);
    // parse material symbols
    for (Element xmlBindMaterial : getChildrenByTagName(xmlInstanceController, "bind_material")) for (Element xmlTechniqueCommon : getChildrenByTagName(xmlBindMaterial, "technique_common")) for (Element xmlInstanceMaterial : getChildrenByTagName(xmlTechniqueCommon, "instance_material")) {
        materialSymbols.put(xmlInstanceMaterial.getAttribute("symbol"), xmlInstanceMaterial.getAttribute("target"));
    }
    String xmlInstanceControllerId = xmlInstanceController.getAttribute("url").substring(1);
    Element xmlLibraryControllers = getChildrenByTagName(xmlRoot, "library_controllers").get(0);
    for (Element xmlLibraryController : getChildrenByTagName(xmlLibraryControllers, "controller")) {
        // our controller ?
        if (xmlLibraryController.getAttribute("id").equals(xmlInstanceControllerId)) {
            // parse skin
            List<Element> xmlSkins = getChildrenByTagName(xmlLibraryController, "skin");
            if (xmlSkins.isEmpty() == false) {
                xmlSkin = xmlSkins.get(0);
            }
        }
    }
    // check for xml skin
    if (xmlSkin == null) {
        throw new ModelFileIOException("skin not found for instance controller " + xmlNodeId);
    }
    // get geometry id
    xmlGeometryId = xmlSkin.getAttribute("source").substring(1);
    // parse bind shape matrix
    String xmlMatrix = getChildrenByTagName(xmlSkin, "bind_shape_matrix").get(0).getTextContent();
    t = new StringTokenizer(xmlMatrix, " \n\r");
    // 
    Matrix4x4 bindShapeMatrix = new Matrix4x4(Float.parseFloat(t.nextToken()), Float.parseFloat(t.nextToken()), Float.parseFloat(t.nextToken()), Float.parseFloat(t.nextToken()), Float.parseFloat(t.nextToken()), Float.parseFloat(t.nextToken()), Float.parseFloat(t.nextToken()), Float.parseFloat(t.nextToken()), Float.parseFloat(t.nextToken()), Float.parseFloat(t.nextToken()), Float.parseFloat(t.nextToken()), Float.parseFloat(t.nextToken()), Float.parseFloat(t.nextToken()), Float.parseFloat(t.nextToken()), Float.parseFloat(t.nextToken()), Float.parseFloat(t.nextToken())).transpose();
    // tdme model definitions
    Group group = new Group(model, parentGroup, xmlNodeId, xmlNodeName);
    // create skinning
    Skinning skinning = group.createSkinning();
    // parse geometry
    readGeometry(authoringTool, pathName, model, group, xmlRoot, xmlGeometryId, materialSymbols);
    // parse joints
    String xmlJointsSource = null;
    String xmlJointsInverseBindMatricesSource = null;
    Element xmlJoints = getChildrenByTagName(xmlSkin, "joints").get(0);
    for (Element xmlJointsInput : getChildrenByTagName(xmlJoints, "input")) {
        if (xmlJointsInput.getAttribute("semantic").equals("JOINT")) {
            xmlJointsSource = xmlJointsInput.getAttribute("source").substring(1);
        } else if (xmlJointsInput.getAttribute("semantic").equals("INV_BIND_MATRIX")) {
            xmlJointsInverseBindMatricesSource = xmlJointsInput.getAttribute("source").substring(1);
        }
    }
    // check for joints sources
    if (xmlJointsSource == null) {
        throw new ModelFileIOException("joint source not found for instance controller " + xmlNodeId);
    }
    // parse joint ids
    ArrayList<Joint> joints = new ArrayList<Joint>();
    for (Element xmlSkinSource : getChildrenByTagName(xmlSkin, "source")) {
        if (xmlSkinSource.getAttribute("id").equals(xmlJointsSource)) {
            t = new StringTokenizer(getChildrenByTagName(xmlSkinSource, "Name_array").get(0).getTextContent(), " \n\r");
            while (t.hasMoreTokens()) {
                joints.add(new Joint(t.nextToken()));
            }
        }
    }
    skinning.setJoints(joints);
    // check for inverse bind matrices source
    if (xmlJointsInverseBindMatricesSource == null) {
        throw new ModelFileIOException("inverse bind matrices source not found for instance controller " + xmlNodeId);
    }
    // Create joints bind matrices
    for (Element xmlSkinSource : getChildrenByTagName(xmlSkin, "source")) {
        if (xmlSkinSource.getAttribute("id").equals(xmlJointsInverseBindMatricesSource)) {
            t = new StringTokenizer(getChildrenByTagName(xmlSkinSource, "float_array").get(0).getTextContent(), " \n\r");
            Joint[] _joints = skinning.getJoints();
            for (int i = 0; i < _joints.length; i++) {
                _joints[i].getBindMatrix().multiply(bindShapeMatrix);
                _joints[i].getBindMatrix().multiply(// The transformation to the local space of the joint is called the inverse bind matrix
                new Matrix4x4(Float.parseFloat(t.nextToken()), Float.parseFloat(t.nextToken()), Float.parseFloat(t.nextToken()), Float.parseFloat(t.nextToken()), Float.parseFloat(t.nextToken()), Float.parseFloat(t.nextToken()), Float.parseFloat(t.nextToken()), Float.parseFloat(t.nextToken()), Float.parseFloat(t.nextToken()), Float.parseFloat(t.nextToken()), Float.parseFloat(t.nextToken()), Float.parseFloat(t.nextToken()), Float.parseFloat(t.nextToken()), Float.parseFloat(t.nextToken()), Float.parseFloat(t.nextToken()), Float.parseFloat(t.nextToken())).transpose());
            }
        }
    }
    // read vertex influences
    ArrayList<Float> weights = new ArrayList<Float>();
    int xmlJointOffset = -1;
    int xmlWeightOffset = -1;
    String xmlWeightsSource = null;
    Element xmlVertexWeights = getChildrenByTagName(xmlSkin, "vertex_weights").get(0);
    List<Element> xmlVertexWeightInputs = getChildrenByTagName(xmlVertexWeights, "input");
    for (Element xmlVertexWeightInput : xmlVertexWeightInputs) {
        if (xmlVertexWeightInput.getAttribute("semantic").equals("JOINT")) {
            if (xmlVertexWeightInput.getAttribute("source").substring(1).equals(xmlJointsSource) == false) {
                throw new ModelFileIOException("joint inverse bind matrices source do not match");
            }
            xmlJointOffset = Integer.parseInt(xmlVertexWeightInput.getAttribute("offset"));
        } else if (xmlVertexWeightInput.getAttribute("semantic").equals("WEIGHT")) {
            xmlWeightOffset = Integer.parseInt(xmlVertexWeightInput.getAttribute("offset"));
            xmlWeightsSource = xmlVertexWeightInput.getAttribute("source").substring(1);
        }
    }
    // check for vertex weight parameter 
    if (xmlJointOffset == -1) {
        throw new ModelFileIOException("xml vertex weight joint offset missing for node " + xmlNodeId);
    }
    if (xmlWeightOffset == -1) {
        throw new ModelFileIOException("xml vertex weight weight offset missing for node " + xmlNodeId);
    }
    if (xmlWeightsSource == null) {
        throw new ModelFileIOException("xml vertex weight weight source missing for node " + xmlNodeId);
    }
    // parse weights
    for (Element xmlSkinSource : getChildrenByTagName(xmlSkin, "source")) {
        if (xmlSkinSource.getAttribute("id").equals(xmlWeightsSource)) {
            t = new StringTokenizer(getChildrenByTagName(xmlSkinSource, "float_array").get(0).getTextContent(), " \n\r");
            while (t.hasMoreTokens()) {
                weights.add(new Float(Float.parseFloat(t.nextToken())));
            }
        }
    }
    skinning.setWeights(weights);
    // actually do parse joint influences of each vertex
    int xmlVertexWeightInputCount = xmlVertexWeightInputs.size();
    String vertexJointsInfluenceCountString = getChildrenByTagName(xmlVertexWeights, "vcount").get(0).getTextContent();
    String vertexJointsInfluencesString = getChildrenByTagName(xmlVertexWeights, "v").get(0).getTextContent();
    t = new StringTokenizer(vertexJointsInfluenceCountString, " \n\r");
    StringTokenizer t2 = new StringTokenizer(vertexJointsInfluencesString, " \n\r");
    int offset = 0;
    ArrayList<ArrayList<JointWeight>> verticesJointsWeights = new ArrayList<ArrayList<JointWeight>>();
    while (t.hasMoreTokens()) {
        // read joint influences for current vertex
        int vertexJointsInfluencesCount = Integer.parseInt(t.nextToken());
        ArrayList<JointWeight> vertexJointsWeights = new ArrayList<JointWeight>();
        for (int i = 0; i < vertexJointsInfluencesCount; i++) {
            int vertexJoint = -1;
            int vertexWeight = -1;
            while (vertexJoint == -1 || vertexWeight == -1) {
                int value = Integer.parseInt(t2.nextToken());
                if (offset % xmlVertexWeightInputCount == xmlJointOffset) {
                    vertexJoint = value;
                } else if (offset % xmlVertexWeightInputCount == xmlWeightOffset) {
                    vertexWeight = value;
                }
                offset++;
            }
            vertexJointsWeights.add(new JointWeight(vertexJoint, vertexWeight));
        }
        verticesJointsWeights.add(vertexJointsWeights);
    }
    skinning.setVerticesJointsWeights(verticesJointsWeights);
    return group;
}
Also used : Group(net.drewke.tdme.engine.model.Group) HashMap(net.drewke.tdme.utils.HashMap) Element(org.w3c.dom.Element) ArrayList(java.util.ArrayList) Joint(net.drewke.tdme.engine.model.Joint) JointWeight(net.drewke.tdme.engine.model.JointWeight) Matrix4x4(net.drewke.tdme.math.Matrix4x4) Joint(net.drewke.tdme.engine.model.Joint) StringTokenizer(java.util.StringTokenizer) Skinning(net.drewke.tdme.engine.model.Skinning)

Aggregations

Joint (net.drewke.tdme.engine.model.Joint)5 Skinning (net.drewke.tdme.engine.model.Skinning)5 JointWeight (net.drewke.tdme.engine.model.JointWeight)3 Matrix4x4 (net.drewke.tdme.math.Matrix4x4)3 ArrayList (java.util.ArrayList)2 Group (net.drewke.tdme.engine.model.Group)2 Vector3 (net.drewke.tdme.math.Vector3)2 StringTokenizer (java.util.StringTokenizer)1 Face (net.drewke.tdme.engine.model.Face)1 FacesEntity (net.drewke.tdme.engine.model.FacesEntity)1 TextureCoordinate (net.drewke.tdme.engine.model.TextureCoordinate)1 MeshManager (net.drewke.tdme.engine.subsystems.manager.MeshManager)1 HashMap (net.drewke.tdme.utils.HashMap)1 Element (org.w3c.dom.Element)1