Search in sources :

Example 1 with SkeletalAnimationChildObject3D

use of org.rajawali3d.animation.mesh.SkeletalAnimationChildObject3D in project Rajawali by Rajawali.

the class BlockAnimator method buildSkeleton.

// apply joint hierarchy to joint pose frames
private void buildSkeleton(BlockHeader blockHeader, long skelAddr) throws ParsingException {
    SkeletonJoint[] joints = lookupSkeleton(blockHeader, skelAddr);
    SkeletalAnimationSequence[] skelAnims = new SkeletalAnimationSequence[mAnimSet.length];
    for (int i = 0; i < mAnimSet.length; i++) skelAnims[i] = (SkeletalAnimationSequence) mAnimSet[i];
    Matrix4 scratch1 = new Matrix4();
    Matrix4 scratch2 = new Matrix4();
    for (SkeletalAnimationSequence skelSeq : skelAnims) {
        for (SkeletalAnimationFrame frame : skelSeq.getFrames()) {
            SkeletonJoint[] poses = frame.getSkeleton().getJoints();
            // apply parent transforms
            for (int i = 0; i < poses.length; i++) {
                // matrix and index already set, need parent & other attribs
                poses[i].setParentIndex(joints[i].getParentIndex());
                if (// has parent joint
                poses[i].getParentIndex() >= 0) {
                    SkeletonJoint parentPose = poses[poses[i].getParentIndex()];
                    scratch1.setAll(parentPose.getMatrix()).multiply(scratch2.setAll(poses[i].getMatrix()));
                    poses[i].setMatrix(scratch1.getDoubleValues());
                } else
                    scratch1.setAll(poses[i].getMatrix());
                // assign pos + rot from final matrix
                scratch1.getTranslation(poses[i].getPosition());
                poses[i].getOrientation().fromMatrix(scratch1);
                poses[i].getOrientation().computeW();
            }
        }
    }
    for (int i = 0; i < mTargets.length; i++) {
        SkeletalAnimationObject3D obj = (SkeletalAnimationObject3D) mTargets[i];
        // assigns INVBP, builds BP, sets joints
        obj.setJointsWithInverseBindPoseMatrices(joints);
        for (int j = 0; j < obj.getNumChildren(); j++) {
            SkeletalAnimationChildObject3D child = (SkeletalAnimationChildObject3D) obj.getChildAt(j);
            SkeletalAnimationMaterialPlugin plugin = new SkeletalAnimationMaterialPlugin(child.getNumJoints(), child.getMaxBoneWeightsPerVertex());
            child.getMaterial().addPlugin(plugin);
        }
        obj.setAnimationSequences(skelAnims);
        obj.setAnimationSequence(mActive);
        if (mAutoPlay)
            obj.play(true);
    }
}
Also used : SkeletalAnimationSequence(org.rajawali3d.animation.mesh.SkeletalAnimationSequence) SkeletonJoint(org.rajawali3d.animation.mesh.SkeletalAnimationFrame.SkeletonJoint) SkeletalAnimationFrame(org.rajawali3d.animation.mesh.SkeletalAnimationFrame) SkeletalAnimationChildObject3D(org.rajawali3d.animation.mesh.SkeletalAnimationChildObject3D) SkeletalAnimationMaterialPlugin(org.rajawali3d.materials.plugins.SkeletalAnimationMaterialPlugin) SkeletalAnimationObject3D(org.rajawali3d.animation.mesh.SkeletalAnimationObject3D) SkeletonJoint(org.rajawali3d.animation.mesh.SkeletalAnimationFrame.SkeletonJoint) Matrix4(org.rajawali3d.math.Matrix4)

Example 2 with SkeletalAnimationChildObject3D

use of org.rajawali3d.animation.mesh.SkeletalAnimationChildObject3D in project Rajawali by Rajawali.

the class BlockTriangleGeometry method parseBlock.

public void parseBlock(AWDLittleEndianDataInputStream dis, BlockHeader blockHeader) throws Exception {
    // Lookup name
    mLookupName = dis.readVarString();
    // Count of sub geometries
    mSubGeometryCount = dis.readUnsignedShort();
    // TODO Meshes need to be joined in some fashion. This might work. Need to test it I suppose.
    // One object for each sub geometry
    mBaseObjects = new Object3D[mSubGeometryCount];
    // Debug
    if (RajLog.isDebugEnabled()) {
        RajLog.d("  Lookup Name: " + mLookupName);
        RajLog.d("  Sub Geometry Count: " + mSubGeometryCount);
    }
    // Determine the precision for the block
    final boolean geoAccuracy = (blockHeader.flags & BlockHeader.FLAG_ACCURACY_GEO) == BlockHeader.FLAG_ACCURACY_GEO;
    final short geoNr = geoAccuracy ? AWDLittleEndianDataInputStream.TYPE_FLOAT64 : AWDLittleEndianDataInputStream.TYPE_FLOAT32;
    // Read the properties
    SparseArray<Short> properties = new SparseArray<Short>();
    // Scale Texture U
    properties.put(1, geoNr);
    // Scale Texture V
    properties.put(2, geoNr);
    // TODO Apply texture scales, need example of this working.
    dis.readProperties(properties);
    // Calculate the sizes
    final int geoPrecisionSize = blockHeader.globalPrecisionGeo ? 8 : 4;
    // Read each sub mesh data
    for (int parsedSub = 0; parsedSub < mSubGeometryCount; ++parsedSub) {
        long subMeshEnd = dis.getPosition() + dis.readUnsignedInt();
        // Geometry
        float[] vertices = null;
        int[] indices = null;
        float[] uvs = null;
        float[] normals = null;
        int[] joints = null;
        float[] weights = null;
        // Skip reading of mesh properties for now (per AWD implementation)
        dis.readProperties();
        // Read each data type from the mesh
        while (dis.getPosition() < subMeshEnd) {
            int idx = 0;
            int type = dis.readUnsignedByte();
            int typeF = dis.readUnsignedByte();
            long subLength = dis.readUnsignedInt();
            long subEnd = dis.getPosition() + subLength;
            if (RajLog.isDebugEnabled())
                RajLog.d("   Mesh Data: t:" + type + " tf:" + typeF + " l:" + subLength + " ls:" + dis.getPosition() + " le:" + subEnd);
            // Process the mesh data by type
            switch((int) type) {
                case // Vertex positions
                1:
                    vertices = new float[(int) (subLength / geoPrecisionSize)];
                    while (idx < vertices.length) {
                        // X, Y, Z
                        vertices[idx++] = (float) dis.readPrecisionNumber(blockHeader.globalPrecisionGeo);
                        vertices[idx++] = (float) dis.readPrecisionNumber(blockHeader.globalPrecisionGeo);
                        vertices[idx++] = (float) -dis.readPrecisionNumber(blockHeader.globalPrecisionGeo);
                    }
                    break;
                case // Face indices
                2:
                    indices = new int[(int) (subLength / 2)];
                    while (idx < indices.length) {
                        indices[idx + 2] = dis.readUnsignedShort();
                        indices[idx + 1] = dis.readUnsignedShort();
                        indices[idx] = dis.readUnsignedShort();
                        idx += 3;
                    }
                    break;
                case // UV coordinates
                3:
                    uvs = new float[(int) (subLength / geoPrecisionSize)];
                    while (idx < uvs.length) uvs[idx++] = (float) dis.readPrecisionNumber(blockHeader.globalPrecisionGeo);
                    break;
                case // Vertex normals
                4:
                    normals = new float[(int) (subLength / geoPrecisionSize)];
                    while (idx < normals.length) {
                        normals[idx++] = (float) dis.readPrecisionNumber(blockHeader.globalPrecisionGeo);
                        normals[idx++] = (float) dis.readPrecisionNumber(blockHeader.globalPrecisionGeo);
                        normals[idx++] = (float) dis.readPrecisionNumber(blockHeader.globalPrecisionGeo);
                    }
                    break;
                case // Joint index
                6:
                    joints = new int[(int) (subLength / 2)];
                    while (idx < joints.length) joints[idx++] = dis.readUnsignedShort();
                    break;
                case // Joint weight
                7:
                    weights = new float[(int) (subLength / geoPrecisionSize)];
                    while (idx < weights.length) weights[idx++] = (float) dis.readPrecisionNumber(blockHeader.globalPrecisionGeo);
                    break;
                // Vertex tangents
                case 5:
                default:
                    // Unknown mesh data, skipping
                    dis.skip(subLength);
            }
            // Validate each mesh data ending. This is a sanity check against precision flags.
            if (dis.getPosition() != subEnd)
                throw new ParsingException("Unexpected ending. Expected " + subEnd + ". Got " + dis.getPosition());
        }
        dis.readUserAttributes(null);
        // Verify the arrays
        if (vertices == null)
            vertices = new float[0];
        if (normals == null)
            normals = new float[0];
        if (uvs == null)
            uvs = new float[0];
        if (indices == null)
            indices = new int[0];
        // FIXME This should be combining sub geometry not creating objects
        if (joints != null && joints.length > 0) {
            /*
				 * Prepares skeletal animation object as far as possible; setting mesh
				 * and skeletal weight data. The object will not yet have an actual
				 * skeleton applied to it.
				 */
            SkeletalAnimationChildObject3D obj = new SkeletalAnimationChildObject3D();
            obj.setData(vertices, normals, uvs, null, indices, false);
            int numVertices = vertices.length / 3;
            // AWD stipulates all vertices have same # bindings, possibly 0 weighted
            int weightsPerVertex = weights.length / numVertices;
            // true WPV may be out of range, so clamp
            int clampWeightsPerVertex = Math.min(weightsPerVertex, SkeletalAnimationChildObject3D.MAX_WEIGHTS_PER_VERTEX);
            // one BoneVertex per actual vertex, maps to N weights & joint indices
            BoneVertex[] bvertices = new BoneVertex[numVertices];
            ArrayList<BoneWeight> bweights = new ArrayList<BoneWeight>();
            int maxWeightsPerVertex = 0;
            int vertexWeightIndex = 0;
            for (int vert = 0; vert < numVertices; vert++) {
                BoneVertex bone = new BoneVertex();
                bvertices[vert] = bone;
                // we may ignore weights, so map to our custom list
                bone.weightIndex = bweights.size();
                // true position in raw weight array
                vertexWeightIndex = vert * weightsPerVertex;
                // only add first [clamp] non-zero weights
                for (int wgt = 0; wgt < clampWeightsPerVertex; wgt++) {
                    if (weights[vertexWeightIndex + wgt] == 0)
                        continue;
                    BoneWeight weight = new BoneWeight();
                    // joints and weights are indexed together
                    weight.jointIndex = joints[vertexWeightIndex + wgt];
                    weight.weightValue = weights[vertexWeightIndex + wgt];
                    bone.numWeights++;
                    bweights.add(weight);
                }
                maxWeightsPerVertex = Math.max(maxWeightsPerVertex, bone.numWeights);
            }
            // extract the clean BoneWeight array
            BoneWeight[] boneweights = bweights.toArray(new BoneWeight[bweights.size()]);
            obj.setMaxBoneWeightsPerVertex(maxWeightsPerVertex);
            obj.setSkeletonMeshData(bvertices, boneweights);
            //obj.setInverseZScale(true);
            mBaseObjects[parsedSub] = obj;
        } else {
            mBaseObjects[parsedSub] = new Object3D();
            mBaseObjects[parsedSub].setData(vertices, normals, uvs, null, indices, false);
        }
    }
    dis.readUserAttributes(null);
}
Also used : SkeletalAnimationChildObject3D(org.rajawali3d.animation.mesh.SkeletalAnimationChildObject3D) ArrayList(java.util.ArrayList) Object3D(org.rajawali3d.Object3D) SkeletalAnimationObject3D(org.rajawali3d.animation.mesh.SkeletalAnimationObject3D) SkeletalAnimationChildObject3D(org.rajawali3d.animation.mesh.SkeletalAnimationChildObject3D) SparseArray(android.util.SparseArray) BoneWeight(org.rajawali3d.animation.mesh.SkeletalAnimationChildObject3D.BoneWeight) ParsingException(org.rajawali3d.loader.ParsingException) BoneVertex(org.rajawali3d.animation.mesh.SkeletalAnimationChildObject3D.BoneVertex)

Example 3 with SkeletalAnimationChildObject3D

use of org.rajawali3d.animation.mesh.SkeletalAnimationChildObject3D in project Rajawali by Rajawali.

the class BlockTriangleGeometry method getBaseObject3D.

@Override
public Object3D getBaseObject3D() {
    if (finalObject != null)
        return finalObject;
    if (mBaseObjects[0] instanceof SkeletalAnimationChildObject3D) {
        SkeletalAnimationObject3D container = new SkeletalAnimationObject3D();
        for (int i = 0; i < mBaseObjects.length; i++) {
            SkeletalAnimationChildObject3D child = (SkeletalAnimationChildObject3D) mBaseObjects[i];
            child.setSkeleton(container);
            container.addChild(child);
        }
        finalObject = container;
    } else if (mBaseObjects.length == 1)
        finalObject = mBaseObjects[0];
    else {
        final Object3D container = new Object3D(mLookupName);
        container.isContainer(true);
        for (int i = 0; i < mBaseObjects.length; i++) container.addChild(mBaseObjects[i]);
        finalObject = container;
    }
    return finalObject;
}
Also used : SkeletalAnimationChildObject3D(org.rajawali3d.animation.mesh.SkeletalAnimationChildObject3D) SkeletalAnimationObject3D(org.rajawali3d.animation.mesh.SkeletalAnimationObject3D) Object3D(org.rajawali3d.Object3D) SkeletalAnimationObject3D(org.rajawali3d.animation.mesh.SkeletalAnimationObject3D) SkeletalAnimationChildObject3D(org.rajawali3d.animation.mesh.SkeletalAnimationChildObject3D)

Example 4 with SkeletalAnimationChildObject3D

use of org.rajawali3d.animation.mesh.SkeletalAnimationChildObject3D in project Rajawali by Rajawali.

the class LoaderMD5Mesh method createObjects.

private void createObjects() throws TextureException, ParsingException, SkeletalAnimationException {
    SkeletalAnimationObject3D root = new SkeletalAnimationObject3D();
    root.uBoneMatrix = mBindPoseMatrix;
    root.mInverseBindPoseMatrix = mInverseBindPoseMatrix;
    root.setJoints(mJoints);
    mRootObject = root;
    for (int i = 0; i < mNumMeshes; ++i) {
        SkeletonMeshData mesh = mMeshes[i];
        SkeletalAnimationChildObject3D o = new SkeletalAnimationChildObject3D();
        o.setData(mesh.vertices, GLES20.GL_STREAM_DRAW, mesh.normals, GLES20.GL_STREAM_DRAW, mesh.textureCoordinates, GLES20.GL_STATIC_DRAW, null, GLES20.GL_STATIC_DRAW, mesh.indices, GLES20.GL_STATIC_DRAW, false);
        o.setMaxBoneWeightsPerVertex(mesh.maxBoneWeightsPerVertex);
        o.setSkeletonMeshData(mesh.numVertices, mesh.boneVertices, mesh.numWeights, mesh.boneWeights);
        o.setName("MD5Mesh_" + i);
        o.setSkeleton(mRootObject);
        o.setInverseZScale(true);
        boolean hasTexture = mesh.textureName != null && mesh.textureName.length() > 0;
        Material mat = new Material();
        mat.addPlugin(new SkeletalAnimationMaterialPlugin(mNumJoints, mesh.maxBoneWeightsPerVertex));
        mat.enableLighting(true);
        mat.setDiffuseMethod(new DiffuseMethod.Lambert());
        o.setMaterial(mat);
        if (!hasTexture) {
            o.setColor(0xff000000 + (int) (Math.random() * 0xffffff));
        } else {
            int identifier = mResources.getIdentifier(mesh.textureName, "drawable", mResources.getResourcePackageName(mResourceId));
            if (identifier == 0) {
                throw new ParsingException("Couldn't find texture " + mesh.textureName);
            }
            mat.setColorInfluence(0);
            mat.addTexture(new Texture("md5tex" + i, identifier));
        }
        mRootObject.addChild(o);
        mesh.destroy();
        mesh = null;
    }
}
Also used : SkeletalAnimationChildObject3D(org.rajawali3d.animation.mesh.SkeletalAnimationChildObject3D) ParsingException(org.rajawali3d.loader.ParsingException) SkeletalAnimationMaterialPlugin(org.rajawali3d.materials.plugins.SkeletalAnimationMaterialPlugin) DiffuseMethod(org.rajawali3d.materials.methods.DiffuseMethod) SkeletalAnimationObject3D(org.rajawali3d.animation.mesh.SkeletalAnimationObject3D) Material(org.rajawali3d.materials.Material) Texture(org.rajawali3d.materials.textures.Texture) SkeletonJoint(org.rajawali3d.animation.mesh.SkeletalAnimationFrame.SkeletonJoint)

Aggregations

SkeletalAnimationChildObject3D (org.rajawali3d.animation.mesh.SkeletalAnimationChildObject3D)4 SkeletalAnimationObject3D (org.rajawali3d.animation.mesh.SkeletalAnimationObject3D)4 Object3D (org.rajawali3d.Object3D)2 SkeletonJoint (org.rajawali3d.animation.mesh.SkeletalAnimationFrame.SkeletonJoint)2 ParsingException (org.rajawali3d.loader.ParsingException)2 SkeletalAnimationMaterialPlugin (org.rajawali3d.materials.plugins.SkeletalAnimationMaterialPlugin)2 SparseArray (android.util.SparseArray)1 ArrayList (java.util.ArrayList)1 BoneVertex (org.rajawali3d.animation.mesh.SkeletalAnimationChildObject3D.BoneVertex)1 BoneWeight (org.rajawali3d.animation.mesh.SkeletalAnimationChildObject3D.BoneWeight)1 SkeletalAnimationFrame (org.rajawali3d.animation.mesh.SkeletalAnimationFrame)1 SkeletalAnimationSequence (org.rajawali3d.animation.mesh.SkeletalAnimationSequence)1 Material (org.rajawali3d.materials.Material)1 DiffuseMethod (org.rajawali3d.materials.methods.DiffuseMethod)1 Texture (org.rajawali3d.materials.textures.Texture)1 Matrix4 (org.rajawali3d.math.Matrix4)1