Search in sources :

Example 41 with Geometry

use of com.jme3.scene.Geometry in project jmonkeyengine by jMonkeyEngine.

the class ShadowUtil method updateShadowCamera.

/**
     * Updates the shadow camera to properly contain the given points (which
     * contain the eye camera frustum corners) and the shadow occluder objects
     * collected through the traverse of the scene hierarchy
     */
public static void updateShadowCamera(ViewPort viewPort, GeometryList receivers, Camera shadowCam, Vector3f[] points, GeometryList splitOccluders, float shadowMapSize) {
    boolean ortho = shadowCam.isParallelProjection();
    shadowCam.setProjectionMatrix(null);
    if (ortho) {
        shadowCam.setFrustum(-shadowCam.getFrustumFar(), shadowCam.getFrustumFar(), -1, 1, 1, -1);
    }
    // create transform to rotate points to viewspace        
    Matrix4f viewProjMatrix = shadowCam.getViewProjectionMatrix();
    BoundingBox splitBB = computeBoundForPoints(points, viewProjMatrix);
    TempVars vars = TempVars.get();
    BoundingBox casterBB = new BoundingBox();
    BoundingBox receiverBB = new BoundingBox();
    int casterCount = 0, receiverCount = 0;
    for (int i = 0; i < receivers.size(); i++) {
        // convert bounding box to light's viewproj space
        Geometry receiver = receivers.get(i);
        BoundingVolume bv = receiver.getWorldBound();
        BoundingVolume recvBox = bv.transform(viewProjMatrix, vars.bbox);
        if (splitBB.intersects(recvBox)) {
            //Nehon : prevent NaN and infinity values to screw the final bounding box
            if (!Float.isNaN(recvBox.getCenter().x) && !Float.isInfinite(recvBox.getCenter().x)) {
                receiverBB.mergeLocal(recvBox);
                receiverCount++;
            }
        }
    }
    // collect splitOccluders through scene recursive traverse
    OccludersExtractor occExt = new OccludersExtractor(viewProjMatrix, casterCount, splitBB, casterBB, splitOccluders, vars);
    for (Spatial scene : viewPort.getScenes()) {
        occExt.addOccluders(scene);
    }
    casterCount = occExt.casterCount;
    //Nehon 08/18/2010 this is to avoid shadow bleeding when the ground is set to only receive shadows
    if (casterCount != receiverCount) {
        casterBB.setXExtent(casterBB.getXExtent() + 2.0f);
        casterBB.setYExtent(casterBB.getYExtent() + 2.0f);
        casterBB.setZExtent(casterBB.getZExtent() + 2.0f);
    }
    Vector3f casterMin = casterBB.getMin(vars.vect1);
    Vector3f casterMax = casterBB.getMax(vars.vect2);
    Vector3f receiverMin = receiverBB.getMin(vars.vect3);
    Vector3f receiverMax = receiverBB.getMax(vars.vect4);
    Vector3f splitMin = splitBB.getMin(vars.vect5);
    Vector3f splitMax = splitBB.getMax(vars.vect6);
    splitMin.z = 0;
    //        if (!ortho) {
    //            shadowCam.setFrustumPerspective(45, 1, 1, splitMax.z);
    //        }
    Matrix4f projMatrix = shadowCam.getProjectionMatrix();
    Vector3f cropMin = vars.vect7;
    Vector3f cropMax = vars.vect8;
    // IMPORTANT: Special handling for Z values
    cropMin.x = max(max(casterMin.x, receiverMin.x), splitMin.x);
    cropMax.x = min(min(casterMax.x, receiverMax.x), splitMax.x);
    cropMin.y = max(max(casterMin.y, receiverMin.y), splitMin.y);
    cropMax.y = min(min(casterMax.y, receiverMax.y), splitMax.y);
    cropMin.z = min(casterMin.z, splitMin.z);
    cropMax.z = min(receiverMax.z, splitMax.z);
    // Create the crop matrix.
    float scaleX, scaleY, scaleZ;
    float offsetX, offsetY, offsetZ;
    scaleX = (2.0f) / (cropMax.x - cropMin.x);
    scaleY = (2.0f) / (cropMax.y - cropMin.y);
    //Shadow map stabilization approximation from shaderX 7
    //from Practical Cascaded Shadow maps adapted to PSSM
    //scale stabilization
    float halfTextureSize = shadowMapSize * 0.5f;
    if (halfTextureSize != 0 && scaleX > 0 && scaleY > 0) {
        float scaleQuantizer = 0.1f;
        scaleX = 1.0f / FastMath.ceil(1.0f / scaleX * scaleQuantizer) * scaleQuantizer;
        scaleY = 1.0f / FastMath.ceil(1.0f / scaleY * scaleQuantizer) * scaleQuantizer;
    }
    offsetX = -0.5f * (cropMax.x + cropMin.x) * scaleX;
    offsetY = -0.5f * (cropMax.y + cropMin.y) * scaleY;
    //offset stabilization
    if (halfTextureSize != 0 && scaleX > 0 && scaleY > 0) {
        offsetX = FastMath.ceil(offsetX * halfTextureSize) / halfTextureSize;
        offsetY = FastMath.ceil(offsetY * halfTextureSize) / halfTextureSize;
    }
    scaleZ = 1.0f / (cropMax.z - cropMin.z);
    offsetZ = -cropMin.z * scaleZ;
    Matrix4f cropMatrix = vars.tempMat4;
    cropMatrix.set(scaleX, 0f, 0f, offsetX, 0f, scaleY, 0f, offsetY, 0f, 0f, scaleZ, offsetZ, 0f, 0f, 0f, 1f);
    Matrix4f result = new Matrix4f();
    result.set(cropMatrix);
    result.multLocal(projMatrix);
    vars.release();
    shadowCam.setProjectionMatrix(result);
}
Also used : Geometry(com.jme3.scene.Geometry) Matrix4f(com.jme3.math.Matrix4f) Spatial(com.jme3.scene.Spatial) BoundingBox(com.jme3.bounding.BoundingBox) Vector3f(com.jme3.math.Vector3f) BoundingVolume(com.jme3.bounding.BoundingVolume) TempVars(com.jme3.util.TempVars)

Example 42 with Geometry

use of com.jme3.scene.Geometry in project jmonkeyengine by jMonkeyEngine.

the class InstancedGeometry method swap.

private void swap(int idx1, int idx2) {
    Geometry g = geometries[idx1];
    geometries[idx1] = geometries[idx2];
    geometries[idx2] = g;
    if (geometries[idx1] != null) {
        InstancedNode.setGeometryStartIndex2(geometries[idx1], idx1);
    }
    if (geometries[idx2] != null) {
        InstancedNode.setGeometryStartIndex2(geometries[idx2], idx2);
    }
}
Also used : Geometry(com.jme3.scene.Geometry)

Example 43 with Geometry

use of com.jme3.scene.Geometry in project jmonkeyengine by jMonkeyEngine.

the class InstancedNode method addToInstancedGeometry.

private void addToInstancedGeometry(Geometry geom) {
    Material material = geom.getMaterial();
    MatParam param = material.getParam("UseInstancing");
    if (param == null || !((Boolean) param.getValue()).booleanValue()) {
        throw new IllegalStateException("You must set the 'UseInstancing' " + "parameter to true on the material prior " + "to adding it to InstancedNode");
    }
    InstancedGeometry ig = lookUpByGeometry(geom);
    igByGeom.put(geom, ig);
    geom.associateWithGroupNode(this, 0);
    ig.addInstance(geom);
}
Also used : MatParam(com.jme3.material.MatParam) Material(com.jme3.material.Material)

Example 44 with Geometry

use of com.jme3.scene.Geometry in project jmonkeyengine by jMonkeyEngine.

the class Cylinder method updateGeometry.

/**
     * Rebuilds the cylinder based on a new set of parameters.
     *
     * @param axisSamples the number of samples along the axis.
     * @param radialSamples the number of samples around the radial.
     * @param radius the radius of the bottom of the cylinder.
     * @param radius2 the radius of the top of the cylinder.
     * @param height the cylinder's height.
     * @param closed should the cylinder have top and bottom surfaces.
     * @param inverted is the cylinder is meant to be viewed from the inside.
     */
public void updateGeometry(int axisSamples, int radialSamples, float radius, float radius2, float height, boolean closed, boolean inverted) {
    this.axisSamples = axisSamples;
    this.radialSamples = radialSamples;
    this.radius = radius;
    this.radius2 = radius2;
    this.height = height;
    this.closed = closed;
    this.inverted = inverted;
    //        VertexBuffer pvb = getBuffer(Type.Position);
    //        VertexBuffer nvb = getBuffer(Type.Normal);
    //        VertexBuffer tvb = getBuffer(Type.TexCoord);
    axisSamples += (closed ? 2 : 0);
    // Vertices
    int vertCount = axisSamples * (radialSamples + 1) + (closed ? 2 : 0);
    setBuffer(Type.Position, 3, createVector3Buffer(getFloatBuffer(Type.Position), vertCount));
    // Normals
    setBuffer(Type.Normal, 3, createVector3Buffer(getFloatBuffer(Type.Normal), vertCount));
    // Texture co-ordinates
    setBuffer(Type.TexCoord, 2, createVector2Buffer(vertCount));
    int triCount = ((closed ? 2 : 0) + 2 * (axisSamples - 1)) * radialSamples;
    setBuffer(Type.Index, 3, createShortBuffer(getShortBuffer(Type.Index), 3 * triCount));
    // generate geometry
    float inverseRadial = 1.0f / radialSamples;
    float inverseAxisLess = 1.0f / (closed ? axisSamples - 3 : axisSamples - 1);
    float inverseAxisLessTexture = 1.0f / (axisSamples - 1);
    float halfHeight = 0.5f * height;
    // Generate points on the unit circle to be used in computing the mesh
    // points on a cylinder slice.
    float[] sin = new float[radialSamples + 1];
    float[] cos = new float[radialSamples + 1];
    for (int radialCount = 0; radialCount < radialSamples; radialCount++) {
        float angle = FastMath.TWO_PI * inverseRadial * radialCount;
        cos[radialCount] = FastMath.cos(angle);
        sin[radialCount] = FastMath.sin(angle);
    }
    sin[radialSamples] = sin[0];
    cos[radialSamples] = cos[0];
    // calculate normals
    Vector3f[] vNormals = null;
    Vector3f vNormal = Vector3f.UNIT_Z;
    if ((height != 0.0f) && (radius != radius2)) {
        vNormals = new Vector3f[radialSamples];
        Vector3f vHeight = Vector3f.UNIT_Z.mult(height);
        Vector3f vRadial = new Vector3f();
        for (int radialCount = 0; radialCount < radialSamples; radialCount++) {
            vRadial.set(cos[radialCount], sin[radialCount], 0.0f);
            Vector3f vRadius = vRadial.mult(radius);
            Vector3f vRadius2 = vRadial.mult(radius2);
            Vector3f vMantle = vHeight.subtract(vRadius2.subtract(vRadius));
            Vector3f vTangent = vRadial.cross(Vector3f.UNIT_Z);
            vNormals[radialCount] = vMantle.cross(vTangent).normalize();
        }
    }
    FloatBuffer nb = getFloatBuffer(Type.Normal);
    FloatBuffer pb = getFloatBuffer(Type.Position);
    FloatBuffer tb = getFloatBuffer(Type.TexCoord);
    // generate the cylinder itself
    Vector3f tempNormal = new Vector3f();
    for (int axisCount = 0, i = 0; axisCount < axisSamples; axisCount++, i++) {
        float axisFraction;
        float axisFractionTexture;
        int topBottom = 0;
        if (!closed) {
            // in [0,1]
            axisFraction = axisCount * inverseAxisLess;
            axisFractionTexture = axisFraction;
        } else {
            if (axisCount == 0) {
                // bottom
                topBottom = -1;
                axisFraction = 0;
                axisFractionTexture = inverseAxisLessTexture;
            } else if (axisCount == axisSamples - 1) {
                // top
                topBottom = 1;
                axisFraction = 1;
                axisFractionTexture = 1 - inverseAxisLessTexture;
            } else {
                axisFraction = (axisCount - 1) * inverseAxisLess;
                axisFractionTexture = axisCount * inverseAxisLessTexture;
            }
        }
        // compute center of slice
        float z = -halfHeight + height * axisFraction;
        Vector3f sliceCenter = new Vector3f(0, 0, z);
        // compute slice vertices with duplication at end point
        int save = i;
        for (int radialCount = 0; radialCount < radialSamples; radialCount++, i++) {
            // in [0,1)
            float radialFraction = radialCount * inverseRadial;
            tempNormal.set(cos[radialCount], sin[radialCount], 0.0f);
            if (vNormals != null) {
                vNormal = vNormals[radialCount];
            } else if (radius == radius2) {
                vNormal = tempNormal;
            }
            if (topBottom == 0) {
                if (!inverted)
                    nb.put(vNormal.x).put(vNormal.y).put(vNormal.z);
                else
                    nb.put(-vNormal.x).put(-vNormal.y).put(-vNormal.z);
            } else {
                nb.put(0).put(0).put(topBottom * (inverted ? -1 : 1));
            }
            tempNormal.multLocal((radius - radius2) * axisFraction + radius2).addLocal(sliceCenter);
            pb.put(tempNormal.x).put(tempNormal.y).put(tempNormal.z);
            tb.put((inverted ? 1 - radialFraction : radialFraction)).put(axisFractionTexture);
        }
        BufferUtils.copyInternalVector3(pb, save, i);
        BufferUtils.copyInternalVector3(nb, save, i);
        tb.put((inverted ? 0.0f : 1.0f)).put(axisFractionTexture);
    }
    if (closed) {
        // bottom center
        pb.put(0).put(0).put(-halfHeight);
        nb.put(0).put(0).put(-1 * (inverted ? -1 : 1));
        tb.put(0.5f).put(0);
        // top center
        pb.put(0).put(0).put(halfHeight);
        nb.put(0).put(0).put(1 * (inverted ? -1 : 1));
        tb.put(0.5f).put(1);
    }
    IndexBuffer ib = getIndexBuffer();
    int index = 0;
    // Connectivity
    for (int axisCount = 0, axisStart = 0; axisCount < axisSamples - 1; axisCount++) {
        int i0 = axisStart;
        int i1 = i0 + 1;
        axisStart += radialSamples + 1;
        int i2 = axisStart;
        int i3 = i2 + 1;
        for (int i = 0; i < radialSamples; i++) {
            if (closed && axisCount == 0) {
                if (!inverted) {
                    ib.put(index++, i0++);
                    ib.put(index++, vertCount - 2);
                    ib.put(index++, i1++);
                } else {
                    ib.put(index++, i0++);
                    ib.put(index++, i1++);
                    ib.put(index++, vertCount - 2);
                }
            } else if (closed && axisCount == axisSamples - 2) {
                ib.put(index++, i2++);
                ib.put(index++, inverted ? vertCount - 1 : i3++);
                ib.put(index++, inverted ? i3++ : vertCount - 1);
            } else {
                ib.put(index++, i0++);
                ib.put(index++, inverted ? i2 : i1);
                ib.put(index++, inverted ? i1 : i2);
                ib.put(index++, i1++);
                ib.put(index++, inverted ? i2++ : i3++);
                ib.put(index++, inverted ? i3++ : i2++);
            }
        }
    }
    updateBound();
    setStatic();
}
Also used : IndexBuffer(com.jme3.scene.mesh.IndexBuffer) Vector3f(com.jme3.math.Vector3f) FloatBuffer(java.nio.FloatBuffer)

Example 45 with Geometry

use of com.jme3.scene.Geometry in project jmonkeyengine by jMonkeyEngine.

the class Torus method setGeometryData.

private void setGeometryData() {
    // allocate vertices
    int vertCount = (circleSamples + 1) * (radialSamples + 1);
    FloatBuffer fpb = BufferUtils.createVector3Buffer(vertCount);
    setBuffer(Type.Position, 3, fpb);
    // allocate normals if requested
    FloatBuffer fnb = BufferUtils.createVector3Buffer(vertCount);
    setBuffer(Type.Normal, 3, fnb);
    // allocate texture coordinates
    FloatBuffer ftb = BufferUtils.createVector2Buffer(vertCount);
    setBuffer(Type.TexCoord, 2, ftb);
    // generate geometry
    float inverseCircleSamples = 1.0f / circleSamples;
    float inverseRadialSamples = 1.0f / radialSamples;
    int i = 0;
    // generate the cylinder itself
    Vector3f radialAxis = new Vector3f(), torusMiddle = new Vector3f(), tempNormal = new Vector3f();
    for (int circleCount = 0; circleCount < circleSamples; circleCount++) {
        // compute center point on torus circle at specified angle
        float circleFraction = circleCount * inverseCircleSamples;
        float theta = FastMath.TWO_PI * circleFraction;
        float cosTheta = FastMath.cos(theta);
        float sinTheta = FastMath.sin(theta);
        radialAxis.set(cosTheta, sinTheta, 0);
        radialAxis.mult(outerRadius, torusMiddle);
        // compute slice vertices with duplication at end point
        int iSave = i;
        for (int radialCount = 0; radialCount < radialSamples; radialCount++) {
            float radialFraction = radialCount * inverseRadialSamples;
            // in [0,1)
            float phi = FastMath.TWO_PI * radialFraction;
            float cosPhi = FastMath.cos(phi);
            float sinPhi = FastMath.sin(phi);
            tempNormal.set(radialAxis).multLocal(cosPhi);
            tempNormal.z += sinPhi;
            fnb.put(tempNormal.x).put(tempNormal.y).put(tempNormal.z);
            tempNormal.multLocal(innerRadius).addLocal(torusMiddle);
            fpb.put(tempNormal.x).put(tempNormal.y).put(tempNormal.z);
            ftb.put(radialFraction).put(circleFraction);
            i++;
        }
        BufferUtils.copyInternalVector3(fpb, iSave, i);
        BufferUtils.copyInternalVector3(fnb, iSave, i);
        ftb.put(1.0f).put(circleFraction);
        i++;
    }
    // duplicate the cylinder ends to form a torus
    for (int iR = 0; iR <= radialSamples; iR++, i++) {
        BufferUtils.copyInternalVector3(fpb, iR, i);
        BufferUtils.copyInternalVector3(fnb, iR, i);
        BufferUtils.copyInternalVector2(ftb, iR, i);
        ftb.put(i * 2 + 1, 1.0f);
    }
}
Also used : Vector3f(com.jme3.math.Vector3f) FloatBuffer(java.nio.FloatBuffer)

Aggregations

Geometry (com.jme3.scene.Geometry)246 Material (com.jme3.material.Material)175 Vector3f (com.jme3.math.Vector3f)116 Box (com.jme3.scene.shape.Box)92 DirectionalLight (com.jme3.light.DirectionalLight)56 Node (com.jme3.scene.Node)54 Sphere (com.jme3.scene.shape.Sphere)49 Spatial (com.jme3.scene.Spatial)41 Quaternion (com.jme3.math.Quaternion)39 Quad (com.jme3.scene.shape.Quad)33 Texture (com.jme3.texture.Texture)30 RigidBodyControl (com.jme3.bullet.control.RigidBodyControl)26 Mesh (com.jme3.scene.Mesh)25 KeyTrigger (com.jme3.input.controls.KeyTrigger)24 AmbientLight (com.jme3.light.AmbientLight)24 ColorRGBA (com.jme3.math.ColorRGBA)21 FilterPostProcessor (com.jme3.post.FilterPostProcessor)21 PointLight (com.jme3.light.PointLight)20 Vector2f (com.jme3.math.Vector2f)17 FloatBuffer (java.nio.FloatBuffer)17