Search in sources :

Example 6 with Plane

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

the class TestMipMapGen method simpleInitApp.

@Override
public void simpleInitApp() {
    BitmapText txt = guiFont.createLabel("Left: HW Mips");
    txt.setLocalTranslation(0, settings.getHeight() - txt.getLineHeight() * 4, 0);
    guiNode.attachChild(txt);
    txt = guiFont.createLabel("Right: AWT Mips");
    txt.setLocalTranslation(0, settings.getHeight() - txt.getLineHeight() * 3, 0);
    guiNode.attachChild(txt);
    // create a simple plane/quad
    Quad quadMesh = new Quad(1, 1);
    quadMesh.updateGeometry(1, 1, false);
    quadMesh.updateBound();
    Geometry quad1 = new Geometry("Textured Quad", quadMesh);
    Geometry quad2 = new Geometry("Textured Quad 2", quadMesh);
    Texture tex = assetManager.loadTexture("Interface/Logo/Monkey.png");
    tex.setMinFilter(Texture.MinFilter.Trilinear);
    Texture texCustomMip = tex.clone();
    Image imageCustomMip = texCustomMip.getImage().clone();
    MipMapGenerator.generateMipMaps(imageCustomMip);
    texCustomMip.setImage(imageCustomMip);
    Material mat1 = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
    mat1.setTexture("ColorMap", tex);
    Material mat2 = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
    mat2.setTexture("ColorMap", texCustomMip);
    quad1.setMaterial(mat1);
    //        quad1.setLocalTranslation(1, 0, 0);
    quad2.setMaterial(mat2);
    quad2.setLocalTranslation(1, 0, 0);
    rootNode.attachChild(quad1);
    rootNode.attachChild(quad2);
}
Also used : Geometry(com.jme3.scene.Geometry) Quad(com.jme3.scene.shape.Quad) BitmapText(com.jme3.font.BitmapText) Material(com.jme3.material.Material) Image(com.jme3.texture.Image) Texture(com.jme3.texture.Texture)

Example 7 with Plane

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

the class LightFilterTest method testSpotFiltering.

@Test
public void testSpotFiltering() {
    SpotLight sl = new SpotLight(Vector3f.ZERO, Vector3f.UNIT_Z);
    sl.setSpotRange(0);
    geom.addLight(sl);
    // Infinite spot lights are only filtered
    checkFilteredLights(1);
    // if the geometry is outside the infinite cone.
    TempVars vars = TempVars.get();
    try {
        // The spot is not touching the near plane of the camera yet, 
        // should still be culled.
        sl.setSpotRange(1f - FastMath.ZERO_TOLERANCE);
        assert !sl.intersectsFrustum(cam, vars);
        // should be culled from the geometry's PoV
        checkFilteredLights(0);
        // Now it touches the near plane.
        sl.setSpotRange(1f);
        // still culled from the geometry's PoV
        checkFilteredLights(0);
        assert sl.intersectsFrustum(cam, vars);
    } finally {
        vars.release();
    }
    // make it barely reach the geometry
    sl.setSpotRange(9f);
    checkFilteredLights(0);
    // make it reach the geometry (touching its bound)
    sl.setSpotRange(9f + FastMath.ZERO_TOLERANCE);
    checkFilteredLights(1);
    // rotate the cone a bit so it no longer faces the geom
    sl.setDirection(new Vector3f(0.316f, 0, 0.948f).normalizeLocal());
    checkFilteredLights(0);
    // extent the range much farther
    sl.setSpotRange(20);
    checkFilteredLights(0);
    // Create box of size X=10 (double the extent)
    // now, the spot will touch the box.
    geom.setMesh(new Box(5, 1, 1));
    checkFilteredLights(1);
    // ==================================
    // Tests for bounding sphere, with a radius of 1f (in the box geom)
    sl.setPosition(Vector3f.ZERO);
    sl.setDirection(Vector3f.UNIT_Z);
    geom.setLocalTranslation(Vector3f.ZERO);
    geom.setModelBound(new BoundingSphere(1f, Vector3f.ZERO));
    // Infinit spot lights are only filtered
    // if the geometry is outside the infinite cone.
    sl.setSpotRange(0);
    checkFilteredLights(1);
    //the geommetry is outside the infinit cone (cone direction going away from the geom)
    sl.setPosition(Vector3f.UNIT_Z.mult(1 + FastMath.ZERO_TOLERANCE));
    checkFilteredLights(0);
    //place the spote ligth in the corner of the box geom, (in order to test bounding sphere)
    sl.setDirection(new Vector3f(1, 1, 0).normalizeLocal());
    geom.setLocalTranslation(0, 0, 10);
    sl.setPosition(sl.getDirection().mult(-2f).add(geom.getLocalTranslation()));
    // make it barely reach the sphere, incorect with a box
    sl.setSpotRange(1f - FastMath.ZERO_TOLERANCE);
    checkFilteredLights(0);
    // make it reach the sphere
    sl.setSpotRange(1f + FastMath.ZERO_TOLERANCE);
    checkFilteredLights(1);
    // extent the range
    sl.setPosition(Vector3f.ZERO);
    sl.setDirection(Vector3f.UNIT_Z);
    sl.setSpotRange(20);
    checkFilteredLights(1);
    // rotate the cone a bit so it no longer faces the geom
    sl.setDirection(new Vector3f(0, 0.3f, 0.7f).normalizeLocal());
    checkFilteredLights(0);
    // Create sphere of size X=10 (double the radius)
    // now, the spot will touch the sphere.
    geom.setModelBound(new BoundingSphere(5f, Vector3f.ZERO));
    checkFilteredLights(1);
}
Also used : BoundingSphere(com.jme3.bounding.BoundingSphere) Vector3f(com.jme3.math.Vector3f) Box(com.jme3.scene.shape.Box) TempVars(com.jme3.util.TempVars) Test(org.junit.Test)

Example 8 with Plane

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

the class MirrorModifier method apply.

@Override
public void apply(Node node, BlenderContext blenderContext) {
    if (invalid) {
        LOGGER.log(Level.WARNING, "Mirror modifier is invalid! Cannot be applied to: {0}", node.getName());
    } else {
        TemporalMesh temporalMesh = this.getTemporalMesh(node);
        if (temporalMesh != null) {
            LOGGER.log(Level.FINE, "Applying mirror modifier to: {0}", temporalMesh);
            Vector3f mirrorPlaneCenter = new Vector3f();
            if (pMirrorObject.isNotNull()) {
                Structure objectStructure;
                try {
                    objectStructure = pMirrorObject.fetchData().get(0);
                    ObjectHelper objectHelper = blenderContext.getHelper(ObjectHelper.class);
                    Node object = (Node) objectHelper.toObject(objectStructure, blenderContext);
                    if (object != null) {
                        // compute the mirror object coordinates in node's local space
                        mirrorPlaneCenter = this.getWorldMatrix(node).invertLocal().mult(object.getWorldTranslation());
                    }
                } catch (BlenderFileException e) {
                    LOGGER.log(Level.SEVERE, "Cannot load mirror''s reference object. Cause: {0}", e.getLocalizedMessage());
                    LOGGER.log(Level.SEVERE, "Mirror modifier will not be applied to node named: {0}", node.getName());
                    return;
                }
            }
            LOGGER.finest("Allocating temporal variables.");
            float d;
            Vector3f mirrorPlaneNormal = new Vector3f();
            Vector3f shiftVector = new Vector3f();
            LOGGER.fine("Mirroring mesh.");
            for (int mirrorIndex = 0; mirrorIndex < 3; ++mirrorIndex) {
                if (isMirrored[mirrorIndex]) {
                    boolean mirrorAtPoint0 = mirrorPlaneCenter.get(mirrorIndex) == 0;
                    if (!mirrorAtPoint0) {
                        // compute mirror's plane normal vector in node's space
                        mirrorPlaneNormal.set(0, 0, 0).set(mirrorIndex, Math.signum(mirrorPlaneCenter.get(mirrorIndex)));
                    }
                    TemporalMesh mirror = temporalMesh.clone();
                    for (int i = 0; i < mirror.getVertexCount(); ++i) {
                        Vector3f vertex = mirror.getVertices().get(i);
                        Vector3f normal = mirror.getNormals().get(i);
                        if (mirrorAtPoint0) {
                            d = Math.abs(vertex.get(mirrorIndex));
                            shiftVector.set(0, 0, 0).set(mirrorIndex, -vertex.get(mirrorIndex));
                        } else {
                            d = this.computeDistanceFromPlane(vertex, mirrorPlaneCenter, mirrorPlaneNormal);
                            mirrorPlaneNormal.mult(d, shiftVector);
                        }
                        if (merge && d <= tolerance) {
                            vertex.addLocal(shiftVector);
                            normal.set(mirrorIndex, 0);
                            temporalMesh.getVertices().get(i).addLocal(shiftVector);
                            temporalMesh.getNormals().get(i).set(mirrorIndex, 0);
                        } else {
                            vertex.addLocal(shiftVector.multLocal(2));
                            normal.set(mirrorIndex, -normal.get(mirrorIndex));
                        }
                    }
                    // flipping the indexes
                    for (Face face : mirror.getFaces()) {
                        face.flipIndexes();
                    }
                    for (Edge edge : mirror.getEdges()) {
                        edge.flipIndexes();
                    }
                    Collections.reverse(mirror.getPoints());
                    if (mirrorU || mirrorV) {
                        for (Face face : mirror.getFaces()) {
                            face.flipUV(mirrorU, mirrorV);
                        }
                    }
                    temporalMesh.append(mirror);
                }
            }
        } else {
            LOGGER.log(Level.WARNING, "Cannot find temporal mesh for node: {0}. The modifier will NOT be applied!", node);
        }
    }
}
Also used : TemporalMesh(com.jme3.scene.plugins.blender.meshes.TemporalMesh) ObjectHelper(com.jme3.scene.plugins.blender.objects.ObjectHelper) Vector3f(com.jme3.math.Vector3f) Node(com.jme3.scene.Node) BlenderFileException(com.jme3.scene.plugins.blender.file.BlenderFileException) Structure(com.jme3.scene.plugins.blender.file.Structure) Face(com.jme3.scene.plugins.blender.meshes.Face) Edge(com.jme3.scene.plugins.blender.meshes.Edge)

Example 9 with Plane

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

the class BoundingSphere method collideWithTri.

private int collideWithTri(Triangle tri, CollisionResults results) {
    TempVars tvars = TempVars.get();
    try {
        // Much of this is based on adaptation from this algorithm:
        // http://realtimecollisiondetection.net/blog/?p=103
        // ...mostly the stuff about eliminating sqrts wherever
        // possible.
        // Math is done in center-relative space.
        Vector3f a = tri.get1().subtract(center, tvars.vect1);
        Vector3f b = tri.get2().subtract(center, tvars.vect2);
        Vector3f c = tri.get3().subtract(center, tvars.vect3);
        Vector3f ab = b.subtract(a, tvars.vect4);
        Vector3f ac = c.subtract(a, tvars.vect5);
        // Check the plane... if it doesn't intersect the plane
        // then it doesn't intersect the triangle.
        Vector3f n = ab.cross(ac, tvars.vect6);
        float d = a.dot(n);
        float e = n.dot(n);
        if (d * d > radius * radius * e) {
            // Can't possibly intersect
            return 0;
        }
        // We intersect the verts, or the edges, or the face...
        // First check against the face since it's the most
        // specific.
        // Calculate the barycentric coordinates of the
        // sphere center
        Vector3f v0 = ac;
        Vector3f v1 = ab;
        // a was P relative, so p.subtract(a) is just -a
        // instead of wasting a vector we'll just negate the
        // dot products below... it's all v2 is used for.
        Vector3f v2 = a;
        float dot00 = v0.dot(v0);
        float dot01 = v0.dot(v1);
        float dot02 = -v0.dot(v2);
        float dot11 = v1.dot(v1);
        float dot12 = -v1.dot(v2);
        float invDenom = 1 / (dot00 * dot11 - dot01 * dot01);
        float u = (dot11 * dot02 - dot01 * dot12) * invDenom;
        float v = (dot00 * dot12 - dot01 * dot02) * invDenom;
        if (u >= 0 && v >= 0 && (u + v) <= 1) {
            // We intersect... and we even know where
            Vector3f part1 = ac;
            Vector3f part2 = ab;
            Vector3f p = center.add(a.add(part1.mult(u)).addLocal(part2.mult(v)));
            CollisionResult r = new CollisionResult();
            Vector3f normal = n.normalize();
            // a is center relative, so -a points to center
            float dist = -normal.dot(a);
            dist = dist - radius;
            r.setDistance(dist);
            r.setContactNormal(normal);
            r.setContactPoint(p);
            results.addCollision(r);
            return 1;
        }
        // Check the edges looking for the nearest point
        // that is also less than the radius.  We don't care
        // about points that are farther away than that.
        Vector3f nearestPt = null;
        float nearestDist = radius * radius;
        Vector3f base;
        Vector3f edge;
        float t;
        // Edge AB
        base = a;
        edge = ab;
        t = -edge.dot(base) / edge.dot(edge);
        if (t >= 0 && t <= 1) {
            Vector3f Q = base.add(edge.mult(t, tvars.vect7), tvars.vect8);
            // distance squared to origin
            float distSq = Q.dot(Q);
            if (distSq < nearestDist) {
                nearestPt = Q;
                nearestDist = distSq;
            }
        }
        // Edge AC
        base = a;
        edge = ac;
        t = -edge.dot(base) / edge.dot(edge);
        if (t >= 0 && t <= 1) {
            Vector3f Q = base.add(edge.mult(t, tvars.vect7), tvars.vect9);
            // distance squared to origin
            float distSq = Q.dot(Q);
            if (distSq < nearestDist) {
                nearestPt = Q;
                nearestDist = distSq;
            }
        }
        // Edge BC
        base = b;
        Vector3f bc = c.subtract(b);
        edge = bc;
        t = -edge.dot(base) / edge.dot(edge);
        if (t >= 0 && t <= 1) {
            Vector3f Q = base.add(edge.mult(t, tvars.vect7), tvars.vect10);
            // distance squared to origin
            float distSq = Q.dot(Q);
            if (distSq < nearestDist) {
                nearestPt = Q;
                nearestDist = distSq;
            }
        }
        // done.       
        if (nearestPt != null) {
            // We have a hit
            float dist = FastMath.sqrt(nearestDist);
            Vector3f cn = nearestPt.divide(-dist);
            CollisionResult r = new CollisionResult();
            r.setDistance(dist - radius);
            r.setContactNormal(cn);
            r.setContactPoint(nearestPt.add(center));
            results.addCollision(r);
            return 1;
        }
        // Finally check each of the triangle corners
        // Vert A
        base = a;
        // distance squared to origin
        t = base.dot(base);
        if (t < nearestDist) {
            nearestDist = t;
            nearestPt = base;
        }
        // Vert B
        base = b;
        // distance squared to origin
        t = base.dot(base);
        if (t < nearestDist) {
            nearestDist = t;
            nearestPt = base;
        }
        // Vert C
        base = c;
        // distance squared to origin
        t = base.dot(base);
        if (t < nearestDist) {
            nearestDist = t;
            nearestPt = base;
        }
        if (nearestPt != null) {
            // We have a hit
            float dist = FastMath.sqrt(nearestDist);
            Vector3f cn = nearestPt.divide(-dist);
            CollisionResult r = new CollisionResult();
            r.setDistance(dist - radius);
            r.setContactNormal(cn);
            r.setContactPoint(nearestPt.add(center));
            results.addCollision(r);
            return 1;
        }
        // Nothing hit... oh, well 
        return 0;
    } finally {
        tvars.release();
    }
}
Also used : CollisionResult(com.jme3.collision.CollisionResult) TempVars(com.jme3.util.TempVars)

Example 10 with Plane

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

the class Intersection method intersect.

//    private boolean axisTest(float a, float b, float fa, float fb, Vector3f v0, Vector3f v1, )
//    private boolean axisTestX01(float a, float b, float fa, float fb,
//                             Vector3f center, Vector3f ext,
//                             Vector3f v1, Vector3f v2, Vector3f v3){
//	float p0 = a * v0.y - b * v0.z;
//	float p2 = a * v2.y - b * v2.z;
//        if(p0 < p2){
//            min = p0;
//            max = p2;
//        } else {
//            min = p2;
//            max = p0;
//        }
//	float rad = fa * boxhalfsize.y + fb * boxhalfsize.z;
//	if(min > rad || max < -rad)
//            return false;
//    }
public static boolean intersect(BoundingBox bbox, Vector3f v1, Vector3f v2, Vector3f v3) {
    //  use separating axis theorem to test overlap between triangle and box
    //  need to test for overlap in these directions:
    //  1) the {x,y,z}-directions (actually, since we use the AABB of the triangle
    //     we do not even need to test these)
    //  2) normal of the triangle
    //  3) crossproduct(edge from tri, {x,y,z}-directin)
    //       this gives 3x3=9 more tests
    TempVars vars = TempVars.get();
    Vector3f tmp0 = vars.vect1, tmp1 = vars.vect2, tmp2 = vars.vect3;
    Vector3f e0 = vars.vect4, e1 = vars.vect5, e2 = vars.vect6;
    Vector3f center = bbox.getCenter();
    Vector3f extent = bbox.getExtent(null);
    //   float min,max,p0,p1,p2,rad,fex,fey,fez;
    //   float normal[3]
    // This is the fastest branch on Sun
    // move everything so that the boxcenter is in (0,0,0)
    v1.subtract(center, tmp0);
    v2.subtract(center, tmp1);
    v3.subtract(center, tmp2);
    // compute triangle edges
    // tri edge 0
    tmp1.subtract(tmp0, e0);
    // tri edge 1
    tmp2.subtract(tmp1, e1);
    // tri edge 2
    tmp0.subtract(tmp2, e2);
    // Bullet 3:
    //  test the 9 tests first (this was faster)
    float min, max;
    float p0, p1, p2, rad;
    float fex = FastMath.abs(e0.x);
    float fey = FastMath.abs(e0.y);
    float fez = FastMath.abs(e0.z);
    //AXISTEST_X01(e0[Z], e0[Y], fez, fey);
    p0 = e0.z * tmp0.y - e0.y * tmp0.z;
    p2 = e0.z * tmp2.y - e0.y * tmp2.z;
    min = min(p0, p2);
    max = max(p0, p2);
    rad = fez * extent.y + fey * extent.z;
    if (min > rad || max < -rad) {
        vars.release();
        return false;
    }
    //   AXISTEST_Y02(e0[Z], e0[X], fez, fex);
    p0 = -e0.z * tmp0.x + e0.x * tmp0.z;
    p2 = -e0.z * tmp2.x + e0.x * tmp2.z;
    min = min(p0, p2);
    max = max(p0, p2);
    rad = fez * extent.x + fex * extent.z;
    if (min > rad || max < -rad) {
        vars.release();
        return false;
    }
    // AXISTEST_Z12(e0[Y], e0[X], fey, fex);
    p1 = e0.y * tmp1.x - e0.x * tmp1.y;
    p2 = e0.y * tmp2.x - e0.x * tmp2.y;
    min = min(p1, p2);
    max = max(p1, p2);
    rad = fey * extent.x + fex * extent.y;
    if (min > rad || max < -rad) {
        vars.release();
        return false;
    }
    fex = FastMath.abs(e1.x);
    fey = FastMath.abs(e1.y);
    fez = FastMath.abs(e1.z);
    //        AXISTEST_X01(e1[Z], e1[Y], fez, fey);
    p0 = e1.z * tmp0.y - e1.y * tmp0.z;
    p2 = e1.z * tmp2.y - e1.y * tmp2.z;
    min = min(p0, p2);
    max = max(p0, p2);
    rad = fez * extent.y + fey * extent.z;
    if (min > rad || max < -rad) {
        vars.release();
        return false;
    }
    //   AXISTEST_Y02(e1[Z], e1[X], fez, fex);
    p0 = -e1.z * tmp0.x + e1.x * tmp0.z;
    p2 = -e1.z * tmp2.x + e1.x * tmp2.z;
    min = min(p0, p2);
    max = max(p0, p2);
    rad = fez * extent.x + fex * extent.z;
    if (min > rad || max < -rad) {
        vars.release();
        return false;
    }
    // AXISTEST_Z0(e1[Y], e1[X], fey, fex);
    p0 = e1.y * tmp0.x - e1.x * tmp0.y;
    p1 = e1.y * tmp1.x - e1.x * tmp1.y;
    min = min(p0, p1);
    max = max(p0, p1);
    rad = fey * extent.x + fex * extent.y;
    if (min > rad || max < -rad) {
        vars.release();
        return false;
    }
    //
    fex = FastMath.abs(e2.x);
    fey = FastMath.abs(e2.y);
    fez = FastMath.abs(e2.z);
    // AXISTEST_X2(e2[Z], e2[Y], fez, fey);
    p0 = e2.z * tmp0.y - e2.y * tmp0.z;
    p1 = e2.z * tmp1.y - e2.y * tmp1.z;
    min = min(p0, p1);
    max = max(p0, p1);
    rad = fez * extent.y + fey * extent.z;
    if (min > rad || max < -rad) {
        vars.release();
        return false;
    }
    // AXISTEST_Y1(e2[Z], e2[X], fez, fex);
    p0 = -e2.z * tmp0.x + e2.x * tmp0.z;
    p1 = -e2.z * tmp1.x + e2.x * tmp1.z;
    min = min(p0, p1);
    max = max(p0, p1);
    rad = fez * extent.x + fex * extent.y;
    if (min > rad || max < -rad) {
        vars.release();
        return false;
    }
    //   AXISTEST_Z12(e2[Y], e2[X], fey, fex);
    p1 = e2.y * tmp1.x - e2.x * tmp1.y;
    p2 = e2.y * tmp2.x - e2.x * tmp2.y;
    min = min(p1, p2);
    max = max(p1, p2);
    rad = fey * extent.x + fex * extent.y;
    if (min > rad || max < -rad) {
        vars.release();
        return false;
    }
    //  Bullet 1:
    //  first test overlap in the {x,y,z}-directions
    //  find min, max of the triangle each direction, and test for overlap in
    //  that direction -- this is equivalent to testing a minimal AABB around
    //  the triangle against the AABB
    Vector3f minMax = vars.vect7;
    // test in X-direction
    findMinMax(tmp0.x, tmp1.x, tmp2.x, minMax);
    if (minMax.x > extent.x || minMax.y < -extent.x) {
        vars.release();
        return false;
    }
    // test in Y-direction
    findMinMax(tmp0.y, tmp1.y, tmp2.y, minMax);
    if (minMax.x > extent.y || minMax.y < -extent.y) {
        vars.release();
        return false;
    }
    // test in Z-direction
    findMinMax(tmp0.z, tmp1.z, tmp2.z, minMax);
    if (minMax.x > extent.z || minMax.y < -extent.z) {
        vars.release();
        return false;
    }
    //       // Bullet 2:
    //       //  test if the box intersects the plane of the triangle
    //       //  compute plane equation of triangle: normal * x + d = 0
    //        Vector3f normal = new Vector3f();
    //        e0.cross(e1, normal);
    Plane p = vars.plane;
    p.setPlanePoints(v1, v2, v3);
    if (bbox.whichSide(p) == Plane.Side.Negative) {
        vars.release();
        return false;
    }
    //
    //        if(!planeBoxOverlap(normal,v0,boxhalfsize)) return false;
    vars.release();
    return true;
/* box and triangle overlaps */
}
Also used : Plane(com.jme3.math.Plane) Vector3f(com.jme3.math.Vector3f) TempVars(com.jme3.util.TempVars)

Aggregations

Vector3f (com.jme3.math.Vector3f)20 Plane (com.jme3.math.Plane)9 Sphere (com.jme3.scene.shape.Sphere)7 TempVars (com.jme3.util.TempVars)7 RigidBodyControl (com.jme3.bullet.control.RigidBodyControl)6 Material (com.jme3.material.Material)6 Geometry (com.jme3.scene.Geometry)6 Node (com.jme3.scene.Node)6 BulletAppState (com.jme3.bullet.BulletAppState)4 Quad (com.jme3.scene.shape.Quad)4 MeshCollisionShape (com.jme3.bullet.collision.shapes.MeshCollisionShape)3 Box (com.jme3.scene.shape.Box)3 CollisionResult (com.jme3.collision.CollisionResult)2 AmbientLight (com.jme3.light.AmbientLight)2 DirectionalLight (com.jme3.light.DirectionalLight)2 Triangle (com.jme3.math.Triangle)2 Camera (com.jme3.renderer.Camera)2 Spatial (com.jme3.scene.Spatial)2 Structure (com.jme3.scene.plugins.blender.file.Structure)2 Texture (com.jme3.texture.Texture)2