Search in sources :

Example 36 with Matrix4f

use of com.jme3.math.Matrix4f in project jmonkeyengine by jMonkeyEngine.

the class SkeletonControl method applySkinning.

/**
     * Method to apply skinning transforms to a mesh's buffers
     *
     * @param mesh the mesh
     * @param offsetMatrices the offset matices to apply
     */
private void applySkinning(Mesh mesh, Matrix4f[] offsetMatrices) {
    int maxWeightsPerVert = mesh.getMaxNumWeights();
    if (maxWeightsPerVert <= 0) {
        throw new IllegalStateException("Max weights per vert is incorrectly set!");
    }
    int fourMinusMaxWeights = 4 - maxWeightsPerVert;
    // NOTE: This code assumes the vertex buffer is in bind pose
    // resetToBind() has been called this frame
    VertexBuffer vb = mesh.getBuffer(Type.Position);
    FloatBuffer fvb = (FloatBuffer) vb.getData();
    fvb.rewind();
    VertexBuffer nb = mesh.getBuffer(Type.Normal);
    FloatBuffer fnb = (FloatBuffer) nb.getData();
    fnb.rewind();
    // get boneIndexes and weights for mesh
    ByteBuffer ib = (ByteBuffer) mesh.getBuffer(Type.BoneIndex).getData();
    FloatBuffer wb = (FloatBuffer) mesh.getBuffer(Type.BoneWeight).getData();
    ib.rewind();
    wb.rewind();
    float[] weights = wb.array();
    byte[] indices = ib.array();
    int idxWeights = 0;
    TempVars vars = TempVars.get();
    float[] posBuf = vars.skinPositions;
    float[] normBuf = vars.skinNormals;
    int iterations = (int) FastMath.ceil(fvb.limit() / ((float) posBuf.length));
    int bufLength = posBuf.length;
    for (int i = iterations - 1; i >= 0; i--) {
        // read next set of positions and normals from native buffer
        bufLength = Math.min(posBuf.length, fvb.remaining());
        fvb.get(posBuf, 0, bufLength);
        fnb.get(normBuf, 0, bufLength);
        int verts = bufLength / 3;
        int idxPositions = 0;
        // iterate vertices and apply skinning transform for each effecting bone
        for (int vert = verts - 1; vert >= 0; vert--) {
            // Skip this vertex if the first weight is zero.
            if (weights[idxWeights] == 0) {
                idxPositions += 3;
                idxWeights += 4;
                continue;
            }
            float nmx = normBuf[idxPositions];
            float vtx = posBuf[idxPositions++];
            float nmy = normBuf[idxPositions];
            float vty = posBuf[idxPositions++];
            float nmz = normBuf[idxPositions];
            float vtz = posBuf[idxPositions++];
            float rx = 0, ry = 0, rz = 0, rnx = 0, rny = 0, rnz = 0;
            for (int w = maxWeightsPerVert - 1; w >= 0; w--) {
                float weight = weights[idxWeights];
                Matrix4f mat = offsetMatrices[indices[idxWeights++] & 0xff];
                rx += (mat.m00 * vtx + mat.m01 * vty + mat.m02 * vtz + mat.m03) * weight;
                ry += (mat.m10 * vtx + mat.m11 * vty + mat.m12 * vtz + mat.m13) * weight;
                rz += (mat.m20 * vtx + mat.m21 * vty + mat.m22 * vtz + mat.m23) * weight;
                rnx += (nmx * mat.m00 + nmy * mat.m01 + nmz * mat.m02) * weight;
                rny += (nmx * mat.m10 + nmy * mat.m11 + nmz * mat.m12) * weight;
                rnz += (nmx * mat.m20 + nmy * mat.m21 + nmz * mat.m22) * weight;
            }
            idxWeights += fourMinusMaxWeights;
            idxPositions -= 3;
            normBuf[idxPositions] = rnx;
            posBuf[idxPositions++] = rx;
            normBuf[idxPositions] = rny;
            posBuf[idxPositions++] = ry;
            normBuf[idxPositions] = rnz;
            posBuf[idxPositions++] = rz;
        }
        fvb.position(fvb.position() - bufLength);
        fvb.put(posBuf, 0, bufLength);
        fnb.position(fnb.position() - bufLength);
        fnb.put(normBuf, 0, bufLength);
    }
    vars.release();
    vb.updateData(fvb);
    nb.updateData(fnb);
}
Also used : Matrix4f(com.jme3.math.Matrix4f) FloatBuffer(java.nio.FloatBuffer) TempVars(com.jme3.util.TempVars) ByteBuffer(java.nio.ByteBuffer)

Example 37 with Matrix4f

use of com.jme3.math.Matrix4f in project jmonkeyengine by jMonkeyEngine.

the class SkeletonControl method applySkinningTangents.

/**
     * Specific method for skinning with tangents to avoid cluttering the
     * classic skinning calculation with null checks that would slow down the
     * process even if tangents don't have to be computed. Also the iteration
     * has additional indexes since tangent has 4 components instead of 3 for
     * pos and norm
     *
     * @param maxWeightsPerVert maximum number of weights per vertex
     * @param mesh the mesh
     * @param offsetMatrices the offsetMaytrices to apply
     * @param tb the tangent vertexBuffer
     */
private void applySkinningTangents(Mesh mesh, Matrix4f[] offsetMatrices, VertexBuffer tb) {
    int maxWeightsPerVert = mesh.getMaxNumWeights();
    if (maxWeightsPerVert <= 0) {
        throw new IllegalStateException("Max weights per vert is incorrectly set!");
    }
    int fourMinusMaxWeights = 4 - maxWeightsPerVert;
    // NOTE: This code assumes the vertex buffer is in bind pose
    // resetToBind() has been called this frame
    VertexBuffer vb = mesh.getBuffer(Type.Position);
    FloatBuffer fvb = (FloatBuffer) vb.getData();
    fvb.rewind();
    VertexBuffer nb = mesh.getBuffer(Type.Normal);
    FloatBuffer fnb = (FloatBuffer) nb.getData();
    fnb.rewind();
    FloatBuffer ftb = (FloatBuffer) tb.getData();
    ftb.rewind();
    // get boneIndexes and weights for mesh
    ByteBuffer ib = (ByteBuffer) mesh.getBuffer(Type.BoneIndex).getData();
    FloatBuffer wb = (FloatBuffer) mesh.getBuffer(Type.BoneWeight).getData();
    ib.rewind();
    wb.rewind();
    float[] weights = wb.array();
    byte[] indices = ib.array();
    int idxWeights = 0;
    TempVars vars = TempVars.get();
    float[] posBuf = vars.skinPositions;
    float[] normBuf = vars.skinNormals;
    float[] tanBuf = vars.skinTangents;
    int iterations = (int) FastMath.ceil(fvb.limit() / ((float) posBuf.length));
    int bufLength = 0;
    int tanLength = 0;
    for (int i = iterations - 1; i >= 0; i--) {
        // read next set of positions and normals from native buffer
        bufLength = Math.min(posBuf.length, fvb.remaining());
        tanLength = Math.min(tanBuf.length, ftb.remaining());
        fvb.get(posBuf, 0, bufLength);
        fnb.get(normBuf, 0, bufLength);
        ftb.get(tanBuf, 0, tanLength);
        int verts = bufLength / 3;
        int idxPositions = 0;
        //tangents has their own index because of the 4 components
        int idxTangents = 0;
        // iterate vertices and apply skinning transform for each effecting bone
        for (int vert = verts - 1; vert >= 0; vert--) {
            // Skip this vertex if the first weight is zero.
            if (weights[idxWeights] == 0) {
                idxTangents += 4;
                idxPositions += 3;
                idxWeights += 4;
                continue;
            }
            float nmx = normBuf[idxPositions];
            float vtx = posBuf[idxPositions++];
            float nmy = normBuf[idxPositions];
            float vty = posBuf[idxPositions++];
            float nmz = normBuf[idxPositions];
            float vtz = posBuf[idxPositions++];
            float tnx = tanBuf[idxTangents++];
            float tny = tanBuf[idxTangents++];
            float tnz = tanBuf[idxTangents++];
            // skipping the 4th component of the tangent since it doesn't have to be transformed
            idxTangents++;
            float rx = 0, ry = 0, rz = 0, rnx = 0, rny = 0, rnz = 0, rtx = 0, rty = 0, rtz = 0;
            for (int w = maxWeightsPerVert - 1; w >= 0; w--) {
                float weight = weights[idxWeights];
                Matrix4f mat = offsetMatrices[indices[idxWeights++] & 0xff];
                rx += (mat.m00 * vtx + mat.m01 * vty + mat.m02 * vtz + mat.m03) * weight;
                ry += (mat.m10 * vtx + mat.m11 * vty + mat.m12 * vtz + mat.m13) * weight;
                rz += (mat.m20 * vtx + mat.m21 * vty + mat.m22 * vtz + mat.m23) * weight;
                rnx += (nmx * mat.m00 + nmy * mat.m01 + nmz * mat.m02) * weight;
                rny += (nmx * mat.m10 + nmy * mat.m11 + nmz * mat.m12) * weight;
                rnz += (nmx * mat.m20 + nmy * mat.m21 + nmz * mat.m22) * weight;
                rtx += (tnx * mat.m00 + tny * mat.m01 + tnz * mat.m02) * weight;
                rty += (tnx * mat.m10 + tny * mat.m11 + tnz * mat.m12) * weight;
                rtz += (tnx * mat.m20 + tny * mat.m21 + tnz * mat.m22) * weight;
            }
            idxWeights += fourMinusMaxWeights;
            idxPositions -= 3;
            normBuf[idxPositions] = rnx;
            posBuf[idxPositions++] = rx;
            normBuf[idxPositions] = rny;
            posBuf[idxPositions++] = ry;
            normBuf[idxPositions] = rnz;
            posBuf[idxPositions++] = rz;
            idxTangents -= 4;
            tanBuf[idxTangents++] = rtx;
            tanBuf[idxTangents++] = rty;
            tanBuf[idxTangents++] = rtz;
            //once again skipping the 4th component of the tangent
            idxTangents++;
        }
        fvb.position(fvb.position() - bufLength);
        fvb.put(posBuf, 0, bufLength);
        fnb.position(fnb.position() - bufLength);
        fnb.put(normBuf, 0, bufLength);
        ftb.position(ftb.position() - tanLength);
        ftb.put(tanBuf, 0, tanLength);
    }
    vars.release();
    vb.updateData(fvb);
    nb.updateData(fnb);
    tb.updateData(ftb);
}
Also used : Matrix4f(com.jme3.math.Matrix4f) FloatBuffer(java.nio.FloatBuffer) TempVars(com.jme3.util.TempVars) ByteBuffer(java.nio.ByteBuffer)

Example 38 with Matrix4f

use of com.jme3.math.Matrix4f in project jmonkeyengine by jMonkeyEngine.

the class Kernel method setArg.

public void setArg(int index, Matrix3f mat) {
    TempVars vars = TempVars.get();
    try {
        Matrix4f m = vars.tempMat4;
        m.zero();
        for (int i = 0; i < 3; ++i) {
            for (int j = 0; j < 3; ++j) {
                m.set(i, j, mat.get(i, j));
            }
        }
        setArg(index, m);
    } finally {
        vars.release();
    }
}
Also used : TempVars(com.jme3.util.TempVars)

Example 39 with Matrix4f

use of com.jme3.math.Matrix4f in project jmonkeyengine by jMonkeyEngine.

the class Camera method setClipPlane.

/**
     * Sets a clipPlane for this camera.
     * The clipPlane is used to recompute the
     * projectionMatrix using the plane as the near plane     
     * This technique is known as the oblique near-plane clipping method introduced by Eric Lengyel
     * more info here
     * <ul>
     * <li><a href="http://www.terathon.com/code/oblique.html">http://www.terathon.com/code/oblique.html</a>
     * <li><a href="http://aras-p.info/texts/obliqueortho.html">http://aras-p.info/texts/obliqueortho.html</a>
     * <li><a href="http://hacksoflife.blogspot.com/2008/12/every-now-and-then-i-come-across.html">http://hacksoflife.blogspot.com/2008/12/every-now-and-then-i-come-across.html</a>
     * </ul>
     *
     * Note that this will work properly only if it's called on each update, and be aware that it won't work properly with the sky bucket.
     * if you want to handle the sky bucket, look at how it's done in SimpleWaterProcessor.java
     * @param clipPlane the plane
     * @param side the side the camera stands from the plane
     */
public void setClipPlane(Plane clipPlane, Plane.Side side) {
    float sideFactor = 1;
    if (side == Plane.Side.Negative) {
        sideFactor = -1;
    }
    //we are on the other side of the plane no need to clip anymore.
    if (clipPlane.whichSide(location) == side) {
        return;
    }
    TempVars vars = TempVars.get();
    try {
        Matrix4f p = projectionMatrixOverride.set(projectionMatrix);
        Matrix4f ivm = viewMatrix;
        Vector3f point = clipPlane.getNormal().mult(clipPlane.getConstant(), vars.vect1);
        Vector3f pp = ivm.mult(point, vars.vect2);
        Vector3f pn = ivm.multNormal(clipPlane.getNormal(), vars.vect3);
        Vector4f clipPlaneV = vars.vect4f1.set(pn.x * sideFactor, pn.y * sideFactor, pn.z * sideFactor, -(pp.dot(pn)) * sideFactor);
        Vector4f v = vars.vect4f2.set(0, 0, 0, 0);
        v.x = (Math.signum(clipPlaneV.x) + p.m02) / p.m00;
        v.y = (Math.signum(clipPlaneV.y) + p.m12) / p.m11;
        v.z = -1.0f;
        v.w = (1.0f + p.m22) / p.m23;
        //clipPlaneV.x * v.x + clipPlaneV.y * v.y + clipPlaneV.z * v.z + clipPlaneV.w * v.w;
        float dot = clipPlaneV.dot(v);
        Vector4f c = clipPlaneV.multLocal(2.0f / dot);
        p.m20 = c.x - p.m30;
        p.m21 = c.y - p.m31;
        p.m22 = c.z - p.m32;
        p.m23 = c.w - p.m33;
        setProjectionMatrix(p);
    } finally {
        vars.release();
    }
}
Also used : TempVars(com.jme3.util.TempVars)

Example 40 with Matrix4f

use of com.jme3.math.Matrix4f in project jmonkeyengine by jMonkeyEngine.

the class TestOpenCLLibraries method testMatrix4f.

private boolean testMatrix4f(Context clContext, CommandQueue clQueue) {
    try {
        String code = "" + "#import \"Common/OpenCL/Matrix4f.clh\"\n" + "\n" + "__kernel void TestMatrix4f_1(mat4 m1, __global char* result)\n" + "{\n" + "  mat4 id = mat4Identity();\n" + "  mat4 m1Inv = mat4Invert(m1);\n" + "  mat4 m1Res = mat4Mult(m1, m1Inv);\n" + "  result[0] = mat4Equals(id, m1Res, 0.0001f) ? 1 : 0;\n" + "}\n" + "\n" + "__kernel void TestMatrix4f_2(mat4 m1, float d, mat4 m2, mat4 m3, __global char* result)\n" + "{\n" + "  float d2 = mat4Determinant(m1);\n" + "  result[0] = fabs(d - d2) < 0.0001f ? 1 : 0;\n" + "  mat4 res = mat4Transpose(m1);\n" + "  result[1] = mat4Equals(res, m2, 0.0001f) ? 1 : 0;\n" + "  res = mat4Adjoint(m1);\n" + "  result[2] = mat4Equals(res, m3, 0.0001f) ? 1 : 0;\n" + "}\n";
        Program program = clContext.createProgramFromSourceCodeWithDependencies(code, assetManager);
        program.build();
        com.jme3.opencl.Buffer buffer = clContext.createBuffer(3);
        Random rand = new Random(1561);
        Kernel testMatrix4fKernel1 = program.createKernel("TestMatrix4f_1");
        Matrix4f m1 = new Matrix4f();
        do {
            for (int i = 0; i < 4; ++i) {
                for (int j = 0; j < 4; ++j) {
                    m1.set(i, j, rand.nextFloat() * 20 - 10);
                }
            }
        } while (FastMath.abs(m1.determinant()) < 0.00001f);
        testMatrix4fKernel1.Run1NoEvent(clQueue, new Kernel.WorkSize(1), m1, buffer);
        ByteBuffer bb = buffer.map(clQueue, MappingAccess.MAP_READ_ONLY);
        if (bb.get() == 0) {
            LOG.severe("Matrix inversion failed");
            return false;
        }
        buffer.unmap(clQueue, bb);
        testMatrix4fKernel1.release();
        Kernel testMatrix4fKernel2 = program.createKernel("TestMatrix4f_2");
        for (int i = 0; i < 4; ++i) {
            for (int j = 0; j < 4; ++j) {
                m1.set(i, j, rand.nextFloat() * 20 - 10);
            }
        }
        testMatrix4fKernel2.Run1NoEvent(clQueue, new Kernel.WorkSize(1), m1, m1.determinant(), m1.transpose(), m1.adjoint(), buffer);
        bb = buffer.map(clQueue, MappingAccess.MAP_READ_ONLY);
        if (bb.get() == 0) {
            LOG.severe("Matrix determinant computation failed");
            return false;
        }
        if (bb.get() == 0) {
            LOG.severe("Matrix transposing failed");
            return false;
        }
        if (bb.get() == 0) {
            LOG.severe("Matrix adjoint computation failed");
            return false;
        }
        buffer.unmap(clQueue, bb);
        testMatrix4fKernel2.release();
        buffer.release();
    } catch (AssertionError ex) {
        LOG.log(Level.SEVERE, "matrix4f test failed with an assertion error");
        return false;
    } catch (Exception ex) {
        LOG.log(Level.SEVERE, "matrix4f test failed with:", ex);
        return false;
    }
    return true;
}
Also used : com.jme3.opencl(com.jme3.opencl) Matrix4f(com.jme3.math.Matrix4f) Random(java.util.Random)

Aggregations

Matrix4f (com.jme3.math.Matrix4f)36 TempVars (com.jme3.util.TempVars)24 Vector3f (com.jme3.math.Vector3f)15 FloatBuffer (java.nio.FloatBuffer)7 BoundingBox (com.jme3.bounding.BoundingBox)6 Transform (com.jme3.math.Transform)6 Bone (com.jme3.animation.Bone)4 CollisionResult (com.jme3.collision.CollisionResult)3 Spatial (com.jme3.scene.Spatial)3 BoundingVolume (com.jme3.bounding.BoundingVolume)2 Material (com.jme3.material.Material)2 Quaternion (com.jme3.math.Quaternion)2 Geometry (com.jme3.scene.Geometry)2 BoneContext (com.jme3.scene.plugins.blender.animations.BoneContext)2 Structure (com.jme3.scene.plugins.blender.file.Structure)2 FbxId (com.jme3.scene.plugins.fbx.file.FbxId)2 FrameBuffer (com.jme3.texture.FrameBuffer)2 Texture2D (com.jme3.texture.Texture2D)2 Picture (com.jme3.ui.Picture)2 ByteBuffer (java.nio.ByteBuffer)2