Search in sources :

Example 56 with Transform

use of com.jme3.math.Transform 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 57 with Transform

use of com.jme3.math.Transform 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 58 with Transform

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

the class RigidBodyMotionState method applyTransform.

/**
     * applies the current transform to the given jme Node if the location has been updated on the physics side
     * @param spatial
     */
public boolean applyTransform(Spatial spatial) {
    Vector3f localLocation = spatial.getLocalTranslation();
    Quaternion localRotationQuat = spatial.getLocalRotation();
    boolean physicsLocationDirty = applyTransform(motionStateId, localLocation, localRotationQuat);
    if (!physicsLocationDirty) {
        return false;
    }
    if (!applyPhysicsLocal && spatial.getParent() != null) {
        localLocation.subtractLocal(spatial.getParent().getWorldTranslation());
        localLocation.divideLocal(spatial.getParent().getWorldScale());
        tmp_inverseWorldRotation.set(spatial.getParent().getWorldRotation()).inverseLocal().multLocal(localLocation);
        //            localRotationQuat.set(worldRotationQuat);
        tmp_inverseWorldRotation.mult(localRotationQuat, localRotationQuat);
        spatial.setLocalTranslation(localLocation);
        spatial.setLocalRotation(localRotationQuat);
    } else {
        spatial.setLocalTranslation(localLocation);
        spatial.setLocalRotation(localRotationQuat);
    //            spatial.setLocalTranslation(worldLocation);
    //            spatial.setLocalRotation(worldRotationQuat);
    }
    if (vehicle != null) {
        vehicle.updateWheels();
    }
    return true;
}
Also used : Quaternion(com.jme3.math.Quaternion) Vector3f(com.jme3.math.Vector3f)

Example 59 with Transform

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

the class AnimationFactory method interpolate.

/**
     * Interpolates over the key frames for the given keyFrame array and the given type of transform
     * @param keyFrames the keyFrames array
     * @param type the type of transforms
     */
private void interpolate(Object[] keyFrames, Type type) {
    int i = 0;
    while (i < totalFrames) {
        //fetching the next keyFrame index transform in the array
        int key = getNextKeyFrame(i, keyFrames);
        if (key != -1) {
            //computing the frame span to interpolate over
            int span = key - i;
            //interating over the frames
            for (int j = i; j <= key; j++) {
                // computing interpolation value
                float val = (float) (j - i) / (float) span;
                //interpolationg depending on the transform type
                switch(type) {
                    case Translation:
                        translations[j] = FastMath.interpolateLinear(val, (Vector3f) keyFrames[i], (Vector3f) keyFrames[key]);
                        break;
                    case Rotation:
                        Quaternion rot = new Quaternion();
                        rotations[j] = rot.slerp(((Rotation) keyFrames[i]).rotation, ((Rotation) keyFrames[key]).rotation, val);
                        break;
                    case Scale:
                        scales[j] = FastMath.interpolateLinear(val, (Vector3f) keyFrames[i], (Vector3f) keyFrames[key]);
                        break;
                }
            }
            //jumping to the next keyFrame
            i = key;
        } else {
            //No more key frame, filling the array witht he last transform computed.
            for (int j = i; j < totalFrames; j++) {
                switch(type) {
                    case Translation:
                        translations[j] = ((Vector3f) keyFrames[i]).clone();
                        break;
                    case Rotation:
                        rotations[j] = ((Quaternion) ((Rotation) keyFrames[i]).rotation).clone();
                        break;
                    case Scale:
                        scales[j] = ((Vector3f) keyFrames[i]).clone();
                        break;
                }
            }
            //we're done
            i = totalFrames;
        }
    }
}
Also used : Quaternion(com.jme3.math.Quaternion) Vector3f(com.jme3.math.Vector3f)

Example 60 with Transform

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

the class SinglePassLightingLogic method updateLightListUniforms.

/**
     * Uploads the lights in the light list as two uniform arrays.<br/><br/> *
     * <p>
     * <code>uniform vec4 g_LightColor[numLights];</code><br/> //
     * g_LightColor.rgb is the diffuse/specular color of the light.<br/> //
     * g_Lightcolor.a is the type of light, 0 = Directional, 1 = Point, <br/> //
     * 2 = Spot. <br/> <br/>
     * <code>uniform vec4 g_LightPosition[numLights];</code><br/> //
     * g_LightPosition.xyz is the position of the light (for point lights)<br/>
     * // or the direction of the light (for directional lights).<br/> //
     * g_LightPosition.w is the inverse radius (1/r) of the light (for
     * attenuation) <br/> </p>
     */
protected int updateLightListUniforms(Shader shader, Geometry g, LightList lightList, int numLights, RenderManager rm, int startIndex) {
    if (numLights == 0) {
        // this shader does not do lighting, ignore.
        return 0;
    }
    Uniform lightData = shader.getUniform("g_LightData");
    //8 lights * max 3
    lightData.setVector4Length(numLights * 3);
    Uniform ambientColor = shader.getUniform("g_AmbientLightColor");
    if (startIndex != 0) {
        // apply additive blending for 2nd and future passes
        rm.getRenderer().applyRenderState(ADDITIVE_LIGHT);
        ambientColor.setValue(VarType.Vector4, ColorRGBA.Black);
    } else {
        ambientColor.setValue(VarType.Vector4, getAmbientColor(lightList, true, ambientLightColor));
    }
    int lightDataIndex = 0;
    TempVars vars = TempVars.get();
    Vector4f tmpVec = vars.vect4f1;
    int curIndex;
    int endIndex = numLights + startIndex;
    for (curIndex = startIndex; curIndex < endIndex && curIndex < lightList.size(); curIndex++) {
        Light l = lightList.get(curIndex);
        if (l.getType() == Light.Type.Ambient) {
            endIndex++;
            continue;
        }
        ColorRGBA color = l.getColor();
        //Color
        lightData.setVector4InArray(color.getRed(), color.getGreen(), color.getBlue(), l.getType().getId(), lightDataIndex);
        lightDataIndex++;
        switch(l.getType()) {
            case Directional:
                DirectionalLight dl = (DirectionalLight) l;
                Vector3f dir = dl.getDirection();
                //Data directly sent in view space to avoid a matrix mult for each pixel
                tmpVec.set(dir.getX(), dir.getY(), dir.getZ(), 0.0f);
                rm.getCurrentCamera().getViewMatrix().mult(tmpVec, tmpVec);
                //                        tmpVec.divideLocal(tmpVec.w);
                //                        tmpVec.normalizeLocal();
                lightData.setVector4InArray(tmpVec.getX(), tmpVec.getY(), tmpVec.getZ(), -1, lightDataIndex);
                lightDataIndex++;
                //PADDING
                lightData.setVector4InArray(0, 0, 0, 0, lightDataIndex);
                lightDataIndex++;
                break;
            case Point:
                PointLight pl = (PointLight) l;
                Vector3f pos = pl.getPosition();
                float invRadius = pl.getInvRadius();
                tmpVec.set(pos.getX(), pos.getY(), pos.getZ(), 1.0f);
                rm.getCurrentCamera().getViewMatrix().mult(tmpVec, tmpVec);
                //tmpVec.divideLocal(tmpVec.w);
                lightData.setVector4InArray(tmpVec.getX(), tmpVec.getY(), tmpVec.getZ(), invRadius, lightDataIndex);
                lightDataIndex++;
                //PADDING
                lightData.setVector4InArray(0, 0, 0, 0, lightDataIndex);
                lightDataIndex++;
                break;
            case Spot:
                SpotLight sl = (SpotLight) l;
                Vector3f pos2 = sl.getPosition();
                Vector3f dir2 = sl.getDirection();
                float invRange = sl.getInvSpotRange();
                float spotAngleCos = sl.getPackedAngleCos();
                tmpVec.set(pos2.getX(), pos2.getY(), pos2.getZ(), 1.0f);
                rm.getCurrentCamera().getViewMatrix().mult(tmpVec, tmpVec);
                // tmpVec.divideLocal(tmpVec.w);
                lightData.setVector4InArray(tmpVec.getX(), tmpVec.getY(), tmpVec.getZ(), invRange, lightDataIndex);
                lightDataIndex++;
                //We transform the spot direction in view space here to save 5 varying later in the lighting shader
                //one vec4 less and a vec4 that becomes a vec3
                //the downside is that spotAngleCos decoding happens now in the frag shader.
                tmpVec.set(dir2.getX(), dir2.getY(), dir2.getZ(), 0.0f);
                rm.getCurrentCamera().getViewMatrix().mult(tmpVec, tmpVec);
                tmpVec.normalizeLocal();
                lightData.setVector4InArray(tmpVec.getX(), tmpVec.getY(), tmpVec.getZ(), spotAngleCos, lightDataIndex);
                lightDataIndex++;
                break;
            case Probe:
                break;
            default:
                throw new UnsupportedOperationException("Unknown type of light: " + l.getType());
        }
    }
    vars.release();
    //Padding of unsued buffer space
    while (lightDataIndex < numLights * 3) {
        lightData.setVector4InArray(0f, 0f, 0f, 0f, lightDataIndex);
        lightDataIndex++;
    }
    return curIndex;
}
Also used : Vector4f(com.jme3.math.Vector4f) ColorRGBA(com.jme3.math.ColorRGBA) DirectionalLight(com.jme3.light.DirectionalLight) SpotLight(com.jme3.light.SpotLight) Light(com.jme3.light.Light) PointLight(com.jme3.light.PointLight) DirectionalLight(com.jme3.light.DirectionalLight) Vector3f(com.jme3.math.Vector3f) Uniform(com.jme3.shader.Uniform) TempVars(com.jme3.util.TempVars) PointLight(com.jme3.light.PointLight) SpotLight(com.jme3.light.SpotLight)

Aggregations

Vector3f (com.jme3.math.Vector3f)29 Transform (com.jme3.math.Transform)26 TempVars (com.jme3.util.TempVars)24 Quaternion (com.jme3.math.Quaternion)11 Matrix4f (com.jme3.math.Matrix4f)10 Bone (com.jme3.animation.Bone)9 BoundingBox (com.jme3.bounding.BoundingBox)6 BoneContext (com.jme3.scene.plugins.blender.animations.BoneContext)5 PointLight (com.jme3.light.PointLight)4 Spatial (com.jme3.scene.Spatial)4 FloatBuffer (java.nio.FloatBuffer)4 Transform (com.bulletphysics.linearmath.Transform)3 ChildCollisionShape (com.jme3.bullet.collision.shapes.infos.ChildCollisionShape)3 DirectionalLight (com.jme3.light.DirectionalLight)3 Light (com.jme3.light.Light)3 SpotLight (com.jme3.light.SpotLight)3 CompoundShape (com.bulletphysics.collision.shapes.CompoundShape)2 BoneTrack (com.jme3.animation.BoneTrack)2 SpatialTrack (com.jme3.animation.SpatialTrack)2 BoundingVolume (com.jme3.bounding.BoundingVolume)2