/** Given the Avatar character, create and set it's collision controller. */ private void setCollisionController(WlAvatarCharacter avatar) { // Create a spatial that represents the bounds of the avatar to use // for collision. These are hardcoded values for now. Vector3f origin = new Vector3f(0f, 0.57f, 0.0f); float radius = 0.25f; if (selectedForInput) { Spatial collisionGraph = new Sphere("AvatarCollision", origin, 10, 10, radius); collisionGraph.setModelBound(new BoundingBox()); collisionGraph.updateModelBound(); // Fetch the JME Collision system using the server manager of the Cell // to which this renderer is attached. ServerSessionManager manager = cell.getCellCache().getSession().getSessionManager(); CollisionSystem collisionSystem = ClientContextJME.getCollisionSystem(manager, "Default"); // Create a new collision controller, and set on the avatar CollisionController controller = new CollisionController(collisionGraph, (JMECollisionSystem) collisionSystem); collisionChangeRequestListener.setCollisionController(controller); AvatarController ac = (AvatarController) avatar.getContext().getController(); ac.setCollisionController(controller); if (collisionListener == null) { collisionListener = new WLCollisionListener(); } ac.addCollisionListener(collisionListener); } else { AvatarController ac = (AvatarController) avatar.getContext().getController(); ac.setCollisionController(null); ac.removeCollisionListener(collisionListener); } }
public static void setTranslucent(Spatial spatial) { MaterialState rs = (MaterialState) doRemoveRenderState(spatial, StateType.Material); if (rs != null) { materials.put(spatial.getName(), rs); MaterialState newState = DisplaySystem.getDisplaySystem().getRenderer().createMaterialState(); ColorRGBA ambient = rs.getAmbient(); ambient.a = .5f; ColorRGBA diffuse = rs.getDiffuse(); diffuse.a = .5f; ColorRGBA emissive = rs.getEmissive(); emissive.a = .5f; ColorRGBA specular = rs.getSpecular(); specular.a = .5f; newState.setAmbient(ambient); newState.setColorMaterial(rs.getColorMaterial()); newState.setDiffuse(diffuse); newState.setEmissive(emissive); newState.setMaterialFace(rs.getMaterialFace()); newState.setShininess(rs.getShininess()); newState.setSpecular(specular); } spatial.updateRenderState(); if (spatial instanceof Node && ((Node) spatial).getChildren() != null) { for (int i = 0; i < ((Node) spatial).getChildren().size(); i++) { colorStripper(((Node) spatial).getChildren().get(i)); } } }
/** * Sets an object to animate. The object's index is <code>index</code> and it's parent index is * <code>parentIndex</code>. A parent index of -1 indicates it has no parent. * * @param objChange The spatial that will be updated by this SpatialTransformer. * @param index The index of that spatial in this transformer's array * @param parentIndex The parentIndex in this transformer's array for this Spatial */ public void setObject(Spatial objChange, int index, int parentIndex) { toChange[index] = objChange; pivots[index].setTranslation(objChange.getLocalTranslation()); pivots[index].setScale(objChange.getLocalScale()); pivots[index].setRotationQuaternion(objChange.getLocalRotation()); parentIndexes[index] = parentIndex; }
public boolean validate(float x1, float z1, float x2, float z2, Spatial spatial) { // generate the start and destination points Vector3f start = new Vector3f(x1, EStats.SnowballHeight.getValue(), z1); Vector3f destination = new Vector3f(x2, EStats.SnowballHeight.getValue(), z2); // convert points to world coordinate system spatial.localToWorld(start, start); spatial.localToWorld(destination, destination); // generate Ray for intersection detection Vector3f direction = destination.subtract(start).normalizeLocal(); Ray moveRay = new Ray(start, direction); // calculate the intersection between the move ray and the spatial Vector3f hitPoint = getIntersection(moveRay, spatial, null, false); // if there is no hit point, it is a valid throw if (hitPoint == null) return true; // if there is a hit point, compare the distances. float distance1 = start.distanceSquared(destination); float distance2 = start.distanceSquared(hitPoint); if (distance1 <= distance2) return true; else return false; }
/** {@inheritDoc} */ public Vector3f getIntersection(Ray ray, Spatial parent, Vector3f store, boolean local) { if (store == null) { store = new Vector3f(); } TrianglePickResults results = new TrianglePickResults(); results.setCheckDistance(true); Vector3f[] vertices = new Vector3f[3]; parent.findPick(ray, results); boolean hit = false; if (results.getNumber() > 0) { PickData data = results.getPickData(0); ArrayList<Integer> triangles = data.getTargetTris(); if (!triangles.isEmpty()) { TriMesh mesh = (TriMesh) data.getTargetMesh(); mesh.getTriangle(triangles.get(0).intValue(), vertices); for (int j = 0; j < vertices.length; j++) { mesh.localToWorld(vertices[j], vertices[j]); } hit = ray.intersectWhere(vertices[0], vertices[1], vertices[2], store); if (hit && local) { parent.worldToLocal(store, store); return store; } else if (hit && !local) { return store; } } } return null; }
/** * <code>performAction</code> moves the camera along the negative left vector for a given distance * of speed * time. * * @see com.jme.input.action.KeyInputAction#performAction(InputActionEvent) */ public void performAction(InputActionEvent evt) { Vector3f loc = node.getLocalTranslation(); loc = loc.addLocal( node.getLocalRotation().getRotationColumn(0, tempVa).multLocal(-speed * evt.getTime())); node.setLocalTranslation(loc); }
private static RenderState doRemoveRenderState(Spatial s, StateType state) { if (s.getRenderState(state) != null) { RenderState rs = s.getRenderState(state); s.clearRenderState(state); return rs; } return null; }
/** @param skinRegion null means match any (including no) skin region */ public boolean hasSkinGeometry(String geoName, String skinRegion) { if (skins == null) return false; validateSkins(); for (Spatial child : skins.getChildren()) if (child.getName().equals(geoName) && (skinRegion == null || (geometryRegions.containsKey(geoName) && geometryRegions.get(geoName).equals(skinRegion)))) return true; return false; }
/** * Validates that the 'skins' node is either null or contains only Geometry children. * * @throws IllegalStateException if 'skins' contains a non-Geometry child. */ protected void validateSkins() { if (skins == null || skins.getQuantity() < 1) return; for (Spatial child : skins.getChildren()) if (!(child instanceof Geometry)) throw new IllegalStateException( "'skins' contains non-Geometry child: " + child.getName() + " of type " + child.getClass().getName()); }
public void frameUpdate(float timePerFrame) { // TODO Auto-generated method stub // TODO Play Frame, when in the right time => Sync-Playback-rate /* * // Put A Frame according to its Framerate * TODO: Declare private long controller; private long frameWait; private long starttime; private int iteration; Initialize starttime = System.currentTimeMillis(); controller = System.currentTimeMillis(); frameWait = 1000 / perf.getFramerate(); iteration = 0; This one into the update function: if (System.currentTimeMillis() >= (controller + frameWait)){ controller = System.currentTimeMillis(); System.out.println("There you go: " + System.currentTimeMillis()); drawFrame(); iteration++; } if (System.currentTimeMillis() > (starttime + (iteration*frameWait)+frameWait)) { // skip Frame iteration += 2; System.out.println("Look ma, no hands: " + iteration); } */ // timer.getTimePerFrame(); if (oggDecoder.isReady()) { oggDecoder.readBody(); TextureManager.releaseTexture(texture.getTextureKey()); texture = TextureManager.loadTexture( Toolkit.getDefaultToolkit().createImage(oggDecoder.getYUVBuffer()), MinificationFilter.BilinearNearestMipMap, MagnificationFilter.Bilinear, true); if (texture != null) { if (textureState != null) textureState = DisplaySystem.getDisplaySystem().getRenderer().createTextureState(); textureState.setTexture(texture); quad.setRenderState(textureState); quad.updateRenderState(); } } }
public static void lookForRenderState(Spatial s, StateType stateType) { if (s.getRenderState(stateType) != null) { System.out.println(s.getName() + " has " + stateType.toString()); } else { System.out.println(s.getName() + " lacks " + stateType.toString()); } if (s instanceof Node && ((Node) s).getChildren() != null) { for (int i = 0; i < ((Node) s).getChildren().size(); i++) { lookForRenderState(((Node) s).getChildren().get(i), stateType); } } }
public static void completeColorStripper(Spatial spatial) { spatial.clearRenderState(StateType.Material); spatial.clearRenderState(StateType.Texture); spatial.clearRenderState(StateType.Shade); spatial.clearRenderState(StateType.Light); spatial.updateRenderState(); if (spatial instanceof Node && ((Node) spatial).getChildren() != null) { for (int i = 0; i < ((Node) spatial).getChildren().size(); i++) { colorStripper(((Node) spatial).getChildren().get(i)); } } }
/** * <code>performAction</code> rotates the camera about it's up vector or lock axis at a speed of * movement speed * time. Where time is the time between frames and 1 corresponds to 1 second. * * @see com.jme.input.action.KeyInputAction#performAction(InputActionEvent) */ public void performAction(InputActionEvent evt) { incr.loadIdentity(); if (lockAxis == null) { node.getLocalRotation().getRotationColumn(1, tempVa); tempVa.normalizeLocal(); incr.fromAngleNormalAxis(-speed * evt.getTime(), tempVa); } else { incr.fromAngleNormalAxis(-speed * evt.getTime(), lockAxis); } node.getLocalRotation() .fromRotationMatrix(incr.mult(node.getLocalRotation().toRotationMatrix(tempMa), tempMb)); node.getLocalRotation().normalize(); }
public static void replaceMaterials(Spatial s) { MaterialState ms = materials.remove(s.getName()); if (ms != null) { s.setRenderState(ms); } s.updateRenderState(); if (s instanceof Node) { if (((Node) s).getChildren() != null) { for (Spatial child : ((Node) s).getChildren()) { replaceMaterials(child); } } } }
/** * Applies color to a Spatial in the form of a <code>MaterialState</code>. * * @param spatial * @param diffuseColor * @param ambientColor * @see MaterialState */ public static MaterialState applyColor( Spatial spatial, ColorRGBA diffuseColor, ColorRGBA ambientColor) { colorStripper(spatial); MaterialState targetMaterial = DisplaySystem.getDisplaySystem().getRenderer().createMaterialState(); targetMaterial.setDiffuse(diffuseColor); targetMaterial.setAmbient(ambientColor); spatial.setRenderState(targetMaterial); spatial.updateRenderState(); if (workingState != null) { MaterialState ms = (MaterialState) workingState; workingState = null; return ms; } else return null; }
public static void deepRotate(Spatial s, int x, int y, int z) { Quaternion q = s.getLocalRotation(); // only transform objects with non-zero rotation if (q.x != 0 || q.y != 0 || q.z != 0 || q.w != 1) { s.setLocalRotation(q.addLocal(Rotator.fromThreeAngles(x, y, z))); } if (s instanceof Node) { if (((Node) s).getChildren() != null) { for (Spatial child : ((Node) s).getChildren()) { deepRotate(child, x, y, z); } } } }
public static void printStructure(Spatial s) { if (s.getParent() != null) { logger.debug( s.getParent().getName() + "." + s.getName() + " (" + s.getClass().getName() + ")"); } else { logger.debug("Printing Structure of " + s.getName()); } if (s instanceof Node) { if (((Node) s).getChildren() != null) { for (Spatial child : ((Node) s).getChildren()) { printStructure(child); } } } }
public static void printModelOrigins(Spatial s) { if (s instanceof Node) { logger.info( "Node \"" + s.getName() + "\" located at " + s.getLocalTranslation().getX() + ", " + s.getLocalTranslation().getY() + ", " + s.getLocalTranslation().getZ()); for (Spatial child : ((Node) s).getChildren()) { printModelOrigins(child); } } }
/** * Retrieve the spatial with given reference class. * * @param root The root <code>Node</code> to stop check at. * @param spatial The <code>Spatial</code> to check. * @param reference The <code>Class</code> reference of the expected object. * @return The <code>Spatial</code> that is of the given reference <code>Class</code>. */ private Spatial validateClass(Node root, Spatial spatial, Class<? extends Spatial> reference) { if (spatial.getClass().equals(reference)) { return spatial; } else { while (spatial.getParent() != null) { spatial = spatial.getParent(); if (spatial == root) { return null; // TODO Should throw an exception here saying reached parent. } else if (spatial.getClass().equals(reference)) { return spatial; } } // TODO Should throw an exception here saying that cannot find the referencing class. } return null; }
/** * Walks through the scenegraph beneath the supplied {@link Spatial} and indicates to any attached * textures that the data should be stored internally rather than in the file. Original image file * locations are saved and returned. * * @param s The object to perform this action on * @param textureFiles - used for recursion; pass in null * @return The locations of all located textures */ public static List<URL> setupTextureStorage(Spatial s, List<URL> textureFiles) { if (textureFiles == null) { textureFiles = new ArrayList<URL>(); } if (s instanceof Node) { // a Node shouldn't have a texture state attached to it, but in case it does: if (s.getRenderState(StateType.Texture) != null) { TextureState ts = (TextureState) s.getRenderState(StateType.Texture); for (int i = 0; i < ts.getNumberOfSetTextures(); i++) { Texture tex = ts.getTexture(i); if (tex != null) { try { textureFiles.add(new URL(tex.getImageLocation())); } catch (MalformedURLException e) { e.printStackTrace(); } tex.setStoreTexture(true); } } } if (((Node) s).getChildren() != null) { Iterator<Spatial> it = ((Node) s).getChildren().iterator(); while (it.hasNext()) { setupTextureStorage(it.next(), textureFiles); } } } else { if (s.getRenderState(StateType.Texture) != null) { TextureState ts = (TextureState) s.getRenderState(StateType.Texture); for (int i = 0; i < ts.getNumberOfSetTextures(); i++) { Texture tex = ts.getTexture(i); if (tex != null) { try { textureFiles.add(new URL(tex.getImageLocation())); } catch (MalformedURLException e) { e.printStackTrace(); } tex.setStoreTexture(true); } } } } return textureFiles; }
public static void colorStripper(Spatial spatial) { // exception for the nodes used for building edit function if (spatial.getName().startsWith("$editorWidget")) { // logger.info(spatial.getName() + " is a editor widget"); return; } // logger.info(spatial.getName() + " is not editor widget"); MaterialState rs = (MaterialState) doRemoveRenderState(spatial, StateType.Material); if (rs != null) { materials.put(spatial.getName(), rs); } spatial.updateRenderState(); if (spatial instanceof Node && ((Node) spatial).getChildren() != null) { for (int i = 0; i < ((Node) spatial).getChildren().size(); i++) { colorStripper(((Node) spatial).getChildren().get(i)); } } }
/** * Strips a specified RenderState from a Spatial and all of its children if there are any. * * @param s The spatial to strip * @param state The RenderState to be removed * @see RenderState */ public static void removeRenderState(Spatial s, StateType state) { doRemoveRenderState(s, state); if (s instanceof Node && ((Node) s).getChildren() != null) { for (int i = 0; i < ((Node) s).getChildren().size(); i++) { removeRenderState(((Node) s).getChildren().get(i), state); } } s.updateRenderState(); }
/** * We can't control how skin Geometries are removed, so we must cull unused region mappings before * we use it. * * <p>Note that we never cull an entry unless the named Geometry is missing. We will not cull * because the skin region has not been loaded, or if the indicated Geometry is not a * SkinTransferNode Geometry (in both cases, we have no way of knowing). */ protected void cullRegionMappings() { if (skins == null || skins.getQuantity() < 1) { geometryRegions.clear(); return; } Set<String> zapKeys = new HashSet<String>(); // We can't use getChild(), descendantMatches(), etc., since we only // want to check direct children, not grandchildren, etc. EACH_KEY: for (String key : geometryRegions.keySet()) { for (Spatial child : skins.getChildren()) if (child.getName().equals(key)) continue EACH_KEY; // There is no active skin with name of this key zapKeys.add(key); } for (String key : zapKeys) { geometryRegions.remove(key); logger.log(Level.FINE, "Culled region mapping for ''{0}''", key); } }
public void update(float time) { // //TODO: We only take care of walking at the moment // 2 events ?? why ? super.update(time); // TODO: Take this out and register individual actions ! Vector3f location = player.getLocalTranslation(); Quaternion rotation = player.getLocalRotation(); boolean forward = KeyBindingManager.getKeyBindingManager().isValidCommand(PROP_KEY_FORWARD); boolean backward = KeyBindingManager.getKeyBindingManager().isValidCommand(PROP_KEY_BACKWARD); int moveStatus = ClientPlayerData.getInstance().getPlayer().getMoveStatus(); // TODO: Refactor ! if (!(forward && backward)) { if (!forward && (moveStatus == Globals.WALKING || moveStatus == Globals.RUNNING)) { sendMovementEvent(Globals.STANDING, EventTypes.MOVEMENT_STOP_WALK, location, rotation); } else if (forward && moveStatus != Globals.WALKING) { sendMovementEvent(Globals.WALKING, EventTypes.MOVEMENT_START_WALK, location, rotation); } else if (!backward && moveStatus == Globals.WALKING_BACKWARD) { sendMovementEvent(Globals.STANDING, EventTypes.MOVEMENT_STOP_WALK, location, rotation); } else if (backward && moveStatus != Globals.WALKING_BACKWARD) { sendMovementEvent( Globals.WALKING_BACKWARD, EventTypes.MOVEMENT_START_WALK_BACKWARDS, location, rotation); } } boolean turnLeft = KeyBindingManager.getKeyBindingManager().isValidCommand(PROP_KEY_LEFT); boolean turnRight = KeyBindingManager.getKeyBindingManager().isValidCommand(PROP_KEY_RIGHT); if (!(turnRight && turnLeft)) { int turnStatus = ClientPlayerData.getInstance().getPlayer().getTurnStatus(); if (turnLeft && turnStatus != Globals.TURN_LEFT) { sendTurnMovementEvent( Globals.TURN_LEFT, EventTypes.MOVEMENT_START_TURN_LEFT, location, rotation); } else if (!turnLeft && turnStatus == Globals.TURN_LEFT) { sendTurnMovementEvent(Globals.NO_TURN, EventTypes.MOVEMENT_STOP_TURN, location, rotation); } else if (turnRight && turnStatus != Globals.TURN_RIGHT) { sendTurnMovementEvent( Globals.TURN_RIGHT, EventTypes.MOVEMENT_START_TURN_RIGHT, location, rotation); } else if (!turnRight && turnStatus == Globals.TURN_RIGHT) { sendTurnMovementEvent(Globals.NO_TURN, EventTypes.MOVEMENT_STOP_TURN, location, rotation); } } }
public Vector3f getDestination(float x1, float z1, float x2, float z2, Spatial spatial) { // generate the start and destination points Vector3f start = new Vector3f(x1, EStats.SnowmanHeight.getValue() / 2.0f, z1); Vector3f destination = new Vector3f(x2, EStats.SnowmanHeight.getValue() / 2.0f, z2); // convert points to world coordinate system spatial.localToWorld(start, start); spatial.localToWorld(destination, destination); // generate Ray for intersection detection Vector3f direction = destination.subtract(start).normalizeLocal(); Ray moveRay = new Ray(start, direction); // calculate the intersection between the move ray and the spatial Vector3f hitPoint = getIntersection(moveRay, spatial, null, false); // if there are no obstacles, return the destination directly if (hitPoint == null) { spatial.worldToLocal(destination, destination); return destination; } else { float originalDistance = destination.distance(start); float newDistance = hitPoint.distance(start); if (originalDistance > newDistance - EStats.BackoffDistance.getValue()) { // we are either trying to go through a hit point // or got too close to one direction.multLocal(EStats.BackoffDistance.getValue()); Vector3f newDestination = hitPoint.subtractLocal(direction); spatial.worldToLocal(newDestination, newDestination); return newDestination; } else { // destination is not close to any hit points so // we can just return it directly spatial.worldToLocal(destination, destination); return destination; } } }
public static boolean checkForRenderState(Spatial s, StateType stateType) { if (s.getRenderState(stateType) != null) { return true; } else { if (s instanceof Node && ((Node) s).getChildren() != null) { for (int i = 0; i < ((Node) s).getChildren().size(); i++) { if (checkForRenderState(((Node) s).getChildren().get(i), stateType)) { return true; } } } } return false; }
public Enemy(String id, Renderer renderer) { super(id, null); URL model = getClass().getClassLoader().getResource("fokker.jme"); Spatial ship = null; try { ship = (Spatial) BinaryImporter.getInstance().load(model.openStream()); } catch (IOException e) { e.printStackTrace(); } ship.setLocalScale(.2f); TextureState ts = renderer.createTextureState(); ts.setEnabled(true); ts.setTexture( TextureManager.loadTexture( getClass().getClassLoader().getResource("fokker.jpg"), Texture.MinificationFilter.Trilinear, Texture.MagnificationFilter.Bilinear)); ship.setRenderState(ts); ship.setNormalsMode(NormalsMode.AlwaysNormalize); ship.setModelBound(new BoundingBox()); ship.updateModelBound(); // ship.setLocalRotation(new Quaternion().fromAngleAxis(FastMath.PI, Vector3f.UNIT_Z)); setModel(ship); Vector3f[] points = new Vector3f[6]; points[0] = new Vector3f(110, 0, 110); points[1] = new Vector3f(110, 0, 50); points[2] = new Vector3f(-20, 0, 10); points[3] = new Vector3f(20, 0, -20); points[4] = new Vector3f(-90, 0, -90); points[5] = new Vector3f(0, 0, 110); endPoint = points[5]; CatmullRomCurve curve = new CatmullRomCurve("Curve", points); curve.setSteps(512); // ship.setLocalTranslation(points[0]); // curve.setCullHint(CullHint.Always); CurveController curveController = new CurveController(curve, ship); ship.addController(curveController); curveController.setRepeatType(Controller.RT_CLAMP); curveController.setSpeed(0.05f); curveController.setAutoRotation(true); curveController.setUpVector(new Vector3f(0, 0.5f, 0)); attachChild(curve); ExplosionFactory.warmup(); }
/** * Nudges an entire object in the given direction through manipulation of its vertices rather than * position of the Spatial itself. * * @param s The Spatial to move. * @param x The amount of x units to move the object. * @param y The amount of y units to move the object. * @param z The amount of z units to move the object. */ public static void adjustObject(Spatial s, float x, float y, float z) { logger.info("Moving " + s.getName() + " " + x + "," + y + "," + z); if (s instanceof TriMesh) { FloatBuffer vb = ((TriMesh) s).getVertexBuffer(); vb.rewind(); float[] floatArray = new float[vb.capacity()]; for (int i = 0; i < ((TriMesh) s).getTriangleCount(); i++) { floatArray[i * 3] = vb.get(i * 3) + x; floatArray[i * 3] = vb.get(i * 3 + 1) + y; floatArray[i * 3] = vb.get(i * 3 + 2) + z; } FloatBuffer newBuffer = FloatBuffer.allocate(vb.capacity()); newBuffer.put(floatArray); ((TriMesh) s).setVertexBuffer(newBuffer); } if (s instanceof QuadMesh) { FloatBuffer vb = ((QuadMesh) s).getVertexBuffer(); vb.rewind(); float[] floatArray = new float[vb.capacity()]; for (int i = 0; i < ((QuadMesh) s).getQuadCount(); i++) { floatArray[i * 4] = vb.get(i * 4) + x; floatArray[i * 4] = vb.get(i * 4 + 1) + y; floatArray[i * 4] = vb.get(i * 4 + 2) + z; } FloatBuffer newBuffer = FloatBuffer.allocate(vb.capacity()); newBuffer.put(floatArray); ((QuadMesh) s).setVertexBuffer(newBuffer); } if (s instanceof Node) { if (((Node) s).getChildren() != null) { for (Spatial child : ((Node) s).getChildren()) { adjustObject(child, x, y, z); } } } }
private void createShape() { quad = new Quad("texturedQuad", Scale.fromMeter(25), Scale.fromMeter(25)); // quad = new Box("", new Vector3f(), Scale.fromMeter(25), Scale.fromMeter(25), // Scale.fromMeter(25)); // quad.setLocalTranslation(new Vector3f(0,0,-400)); texture = TextureManager.loadTexture( "data/foliage/A_Bush_1.png", MinificationFilter.BilinearNearestMipMap, MagnificationFilter.Bilinear); if (texture != null) { textureState = DisplaySystem.getDisplaySystem().getRenderer().createTextureState(); textureState.setTexture(texture); quad.setRenderState(textureState); } // rootNode.attachChild(quad); }
/** * Sets the MaterialFaces for a given object. By using the applyToFront and applyToBack * parameters, each desired combination of face settings can be produced (None, Front, Back, * Both). * * @param spatial The spatial for which to set the MaterialFace * @param applyToFront True if the front face should have the material applied * @param applyToBack True if the back face should have the material applied * @see MaterialFace */ public static void setMaterialFaceApplication( Spatial spatial, boolean applyToFront, boolean applyToBack) { if (applyToFront && applyToBack) { if (spatial.getRenderState(StateType.Material) != null) ((MaterialState) spatial.getRenderState(StateType.Material)) .setMaterialFace(MaterialFace.FrontAndBack); } else if (applyToFront) { if (spatial.getRenderState(StateType.Material) != null) ((MaterialState) spatial.getRenderState(StateType.Material)) .setMaterialFace(MaterialFace.Front); } else if (applyToBack) { if (spatial.getRenderState(StateType.Material) != null) ((MaterialState) spatial.getRenderState(StateType.Material)) .setMaterialFace(MaterialFace.Back); } if (spatial instanceof Node) { if (((Node) spatial).getChildren() != null) { for (Spatial child : ((Node) spatial).getChildren()) { setMaterialFaceApplication(child, applyToFront, applyToBack); } } } }