A more precise exception report about modifying the scene from another thread:

Well if you want to know where it happens:
Drop in replacment for Node, with no real runtime cost additionally, as the asserts must be actvated, and are removed at class loading time if not enabled. (The subrenderer was a bitch to fix, because I got the exact same error, but it was a internal jme state problem, not a threading one apparently.) However noticing that it was actually not my error took quite some time, wich is why this class was created.

package de.visiongamestudios.client.jme.subrenderer;

import java.io.IOException;
import java.util.Collection;
import java.util.List;
import java.util.Queue;

import com.jme3.asset.AssetKey;
import com.jme3.bounding.BoundingVolume;
import com.jme3.collision.Collidable;
import com.jme3.collision.CollisionResults;
import com.jme3.export.JmeExporter;
import com.jme3.export.JmeImporter;
import com.jme3.light.Light;
import com.jme3.light.LightList;
import com.jme3.material.Material;
import com.jme3.math.Matrix3f;
import com.jme3.math.Matrix4f;
import com.jme3.math.Quaternion;
import com.jme3.math.Transform;
import com.jme3.math.Vector3f;
import com.jme3.renderer.Camera;
import com.jme3.renderer.Camera.FrustumIntersect;
import com.jme3.renderer.RenderManager;
import com.jme3.renderer.ViewPort;
import com.jme3.renderer.queue.RenderQueue.Bucket;
import com.jme3.renderer.queue.RenderQueue.ShadowMode;
import com.jme3.scene.Node;
import com.jme3.scene.SceneGraphVisitor;
import com.jme3.scene.Spatial;
import com.jme3.scene.control.Control;

public class ThreadSaveNode extends Node {

	private Thread thread;

	public ThreadSaveNode(final String string, final Thread openGLThread) {
		super(string);
		this.thread = openGLThread;
	}

	@Override
	public int getQuantity() {
		assert Thread.currentThread() == this.thread : "Expected " + this.thread.getName() + " but got " + Thread.currentThread();
		return super.getQuantity();
	}

	@Override
	protected void setTransformRefresh() {
		assert Thread.currentThread() == this.thread : "Expected " + this.thread.getName() + " but got " + Thread.currentThread();
		super.setTransformRefresh();
	}

	@Override
	protected void setLightListRefresh() {
		assert Thread.currentThread() == this.thread : "Expected " + this.thread.getName() + " but got " + Thread.currentThread();
		super.setLightListRefresh();
	}

	@Override
	protected void updateWorldBound() {
		assert Thread.currentThread() == this.thread : "Expected " + this.thread.getName() + " but got " + Thread.currentThread();
		super.updateWorldBound();
	}

	@Override
	protected void setParent(final Node parent) {
		assert Thread.currentThread() == this.thread : "Expected " + this.thread.getName() + " but got " + Thread.currentThread();
		super.setParent(parent);
	}

	@Override
	public void updateLogicalState(final float tpf) {
		assert Thread.currentThread() == this.thread : "Expected " + this.thread.getName() + " but got " + Thread.currentThread();
		super.updateLogicalState(tpf);
	}

	@Override
	public void updateGeometricState() {
		assert Thread.currentThread() == this.thread : "Expected " + this.thread.getName() + " but got " + Thread.currentThread();
		super.updateGeometricState();
	}

	@Override
	public int getTriangleCount() {
		assert Thread.currentThread() == this.thread : "Expected " + this.thread.getName() + " but got " + Thread.currentThread();
		return super.getTriangleCount();
	}

	@Override
	public int getVertexCount() {
		assert Thread.currentThread() == this.thread : "Expected " + this.thread.getName() + " but got " + Thread.currentThread();
		return super.getVertexCount();
	}

	@Override
	public int attachChild(final Spatial child) {
		assert Thread.currentThread() == this.thread : "Expected " + this.thread.getName() + " but got " + Thread.currentThread();
		return super.attachChild(child);
	}

	@Override
	public int attachChildAt(final Spatial child, final int index) {
		assert Thread.currentThread() == this.thread : "Expected " + this.thread.getName() + " but got " + Thread.currentThread();
		return super.attachChildAt(child, index);
	}

	@Override
	public int detachChild(final Spatial child) {
		assert Thread.currentThread() == this.thread : "Expected " + this.thread.getName() + " but got " + Thread.currentThread();
		return super.detachChild(child);
	}

	@Override
	public int detachChildNamed(final String childName) {
		assert Thread.currentThread() == this.thread : "Expected " + this.thread.getName() + " but got " + Thread.currentThread();
		return super.detachChildNamed(childName);
	}

	@Override
	public Spatial detachChildAt(final int index) {
		assert Thread.currentThread() == this.thread : "Expected " + this.thread.getName() + " but got " + Thread.currentThread();
		return super.detachChildAt(index);
	}

	@Override
	public void detachAllChildren() {
		assert Thread.currentThread() == this.thread : "Expected " + this.thread.getName() + " but got " + Thread.currentThread();
		super.detachAllChildren();
	}

	@Override
	public int getChildIndex(final Spatial sp) {
		assert Thread.currentThread() == this.thread : "Expected " + this.thread.getName() + " but got " + Thread.currentThread();
		return super.getChildIndex(sp);
	}

	@Override
	public void swapChildren(final int index1, final int index2) {
		assert Thread.currentThread() == this.thread : "Expected " + this.thread.getName() + " but got " + Thread.currentThread();
		super.swapChildren(index1, index2);
	}

	@Override
	public Spatial getChild(final int i) {
		assert Thread.currentThread() == this.thread : "Expected " + this.thread.getName() + " but got " + Thread.currentThread();
		return super.getChild(i);
	}

	@Override
	public Spatial getChild(final String name) {
		assert Thread.currentThread() == this.thread : "Expected " + this.thread.getName() + " but got " + Thread.currentThread();
		return super.getChild(name);
	}

	@Override
	public boolean hasChild(final Spatial spat) {
		assert Thread.currentThread() == this.thread : "Expected " + this.thread.getName() + " but got " + Thread.currentThread();
		return super.hasChild(spat);
	}

	@Override
	public List<Spatial> getChildren() {
		assert Thread.currentThread() == this.thread : "Expected " + this.thread.getName() + " but got " + Thread.currentThread();
		return super.getChildren();
	}

	@Override
	public void setMaterial(final Material mat) {
		assert Thread.currentThread() == this.thread : "Expected " + this.thread.getName() + " but got " + Thread.currentThread();
		super.setMaterial(mat);
	}

	@Override
	public void setLodLevel(final int lod) {
		assert Thread.currentThread() == this.thread : "Expected " + this.thread.getName() + " but got " + Thread.currentThread();
		super.setLodLevel(lod);
	}

	@Override
	public int collideWith(final Collidable other, final CollisionResults results) {
		assert Thread.currentThread() == this.thread : "Expected " + this.thread.getName() + " but got " + Thread.currentThread();
		return super.collideWith(other, results);
	}

	@Override
	public <T extends Spatial> List<T> descendantMatches(final Class<T> spatialSubclass, final String nameRegex) {
		assert Thread.currentThread() == this.thread : "Expected " + this.thread.getName() + " but got " + Thread.currentThread();
		return super.descendantMatches(spatialSubclass, nameRegex);
	}

	@Override
	public <T extends Spatial> List<T> descendantMatches(final Class<T> spatialSubclass) {
		assert Thread.currentThread() == this.thread : "Expected " + this.thread.getName() + " but got " + Thread.currentThread();
		return super.descendantMatches(spatialSubclass);
	}

	@Override
	public <T extends Spatial> List<T> descendantMatches(final String nameRegex) {
		assert Thread.currentThread() == this.thread : "Expected " + this.thread.getName() + " but got " + Thread.currentThread();
		return super.descendantMatches(nameRegex);
	}

	@Override
	public Node clone(final boolean cloneMaterials) {
		assert Thread.currentThread() == this.thread : "Expected " + this.thread.getName() + " but got " + Thread.currentThread();
		return super.clone(cloneMaterials);
	}

	@Override
	public Spatial deepClone() {
		assert Thread.currentThread() == this.thread : "Expected " + this.thread.getName() + " but got " + Thread.currentThread();
		return super.deepClone();
	}

	@Override
	public void write(final JmeExporter e) throws IOException {
		assert Thread.currentThread() == this.thread : "Expected " + this.thread.getName() + " but got " + Thread.currentThread();
		super.write(e);
	}

	@Override
	public void read(final JmeImporter e) throws IOException {
		assert Thread.currentThread() == this.thread : "Expected " + this.thread.getName() + " but got " + Thread.currentThread();
		super.read(e);
	}

	@Override
	public void setModelBound(final BoundingVolume modelBound) {
		assert Thread.currentThread() == this.thread : "Expected " + this.thread.getName() + " but got " + Thread.currentThread();
		super.setModelBound(modelBound);
	}

	@Override
	public void updateModelBound() {
		assert Thread.currentThread() == this.thread : "Expected " + this.thread.getName() + " but got " + Thread.currentThread();
		super.updateModelBound();
	}

	@Override
	public void depthFirstTraversal(final SceneGraphVisitor visitor) {
		assert Thread.currentThread() == this.thread : "Expected " + this.thread.getName() + " but got " + Thread.currentThread();
		super.depthFirstTraversal(visitor);
	}

	@Override
	protected void breadthFirstTraversal(final SceneGraphVisitor visitor, final Queue<Spatial> queue) {
		assert Thread.currentThread() == this.thread : "Expected " + this.thread.getName() + " but got " + Thread.currentThread();
		super.breadthFirstTraversal(visitor, queue);
	}

	@Override
	public void setKey(final AssetKey key) {
		assert Thread.currentThread() == this.thread : "Expected " + this.thread.getName() + " but got " + Thread.currentThread();
		super.setKey(key);
	}

	@Override
	public AssetKey getKey() {
		assert Thread.currentThread() == this.thread : "Expected " + this.thread.getName() + " but got " + Thread.currentThread();
		return super.getKey();
	}

	@Override
	protected void setRequiresUpdates(final boolean f) {
		if (this.thread != null) {
			assert Thread.currentThread() == this.thread : "Expected " + this.thread.getName() + " but got " + Thread.currentThread();
		}
		super.setRequiresUpdates(f);
	}

	@Override
	protected void setBoundRefresh() {
		assert Thread.currentThread() == this.thread : "Expected " + this.thread.getName() + " but got " + Thread.currentThread();
		super.setBoundRefresh();
	}

	@Override
	public void forceRefresh(final boolean transforms, final boolean bounds, final boolean lights) {
		assert Thread.currentThread() == this.thread : "Expected " + this.thread.getName() + " but got " + Thread.currentThread();
		super.forceRefresh(transforms, bounds, lights);
	}

	@Override
	public boolean checkCulling(final Camera cam) {
		assert Thread.currentThread() == this.thread : "Expected " + this.thread.getName() + " but got " + Thread.currentThread();
		return super.checkCulling(cam);
	}

	@Override
	public void setName(final String name) {
		assert Thread.currentThread() == this.thread : "Expected " + this.thread.getName() + " but got " + Thread.currentThread();
		super.setName(name);
	}

	@Override
	public String getName() {
		assert Thread.currentThread() == this.thread : "Expected " + this.thread.getName() + " but got " + Thread.currentThread();
		return super.getName();
	}

	@Override
	public LightList getLocalLightList() {
		assert Thread.currentThread() == this.thread : "Expected " + this.thread.getName() + " but got " + Thread.currentThread();
		return super.getLocalLightList();
	}

	@Override
	public LightList getWorldLightList() {
		assert Thread.currentThread() == this.thread : "Expected " + this.thread.getName() + " but got " + Thread.currentThread();
		return super.getWorldLightList();
	}

	@Override
	public Quaternion getWorldRotation() {
		assert Thread.currentThread() == this.thread : "Expected " + this.thread.getName() + " but got " + Thread.currentThread();
		return super.getWorldRotation();
	}

	@Override
	public Vector3f getWorldTranslation() {
		assert Thread.currentThread() == this.thread : "Expected " + this.thread.getName() + " but got " + Thread.currentThread();
		return super.getWorldTranslation();
	}

	@Override
	public Vector3f getWorldScale() {
		assert Thread.currentThread() == this.thread : "Expected " + this.thread.getName() + " but got " + Thread.currentThread();
		return super.getWorldScale();
	}

	@Override
	public Transform getWorldTransform() {
		assert Thread.currentThread() == this.thread : "Expected " + this.thread.getName() + " but got " + Thread.currentThread();
		return super.getWorldTransform();
	}

	@Override
	public void rotateUpTo(final Vector3f newUp) {
		assert Thread.currentThread() == this.thread : "Expected " + this.thread.getName() + " but got " + Thread.currentThread();
		super.rotateUpTo(newUp);
	}

	@Override
	public void lookAt(final Vector3f position, final Vector3f upVector) {
		assert Thread.currentThread() == this.thread : "Expected " + this.thread.getName() + " but got " + Thread.currentThread();
		super.lookAt(position, upVector);
	}

	@Override
	protected void updateWorldLightList() {
		assert Thread.currentThread() == this.thread : "Expected " + this.thread.getName() + " but got " + Thread.currentThread();
		super.updateWorldLightList();
	}

	@Override
	protected void updateWorldTransforms() {
		assert Thread.currentThread() == this.thread : "Expected " + this.thread.getName() + " but got " + Thread.currentThread();
		super.updateWorldTransforms();
	}

	@Override
	public void runControlRender(final RenderManager rm, final ViewPort vp) {
		assert Thread.currentThread() == this.thread : "Expected " + this.thread.getName() + " but got " + Thread.currentThread();
		super.runControlRender(rm, vp);
	}

	@Override
	public void addControl(final Control control) {
		assert Thread.currentThread() == this.thread : "Expected " + this.thread.getName() + " but got " + Thread.currentThread();
		super.addControl(control);
	}

	@Override
	public void removeControl(final Class<? extends Control> controlType) {
		assert Thread.currentThread() == this.thread : "Expected " + this.thread.getName() + " but got " + Thread.currentThread();
		super.removeControl(controlType);
	}

	@Override
	public boolean removeControl(final Control control) {
		assert Thread.currentThread() == this.thread : "Expected " + this.thread.getName() + " but got " + Thread.currentThread();
		return super.removeControl(control);
	}

	@Override
	public <T extends Control> T getControl(final Class<T> controlType) {
		assert Thread.currentThread() == this.thread : "Expected " + this.thread.getName() + " but got " + Thread.currentThread();
		return super.getControl(controlType);
	}

	@Override
	public Control getControl(final int index) {
		assert Thread.currentThread() == this.thread : "Expected " + this.thread.getName() + " but got " + Thread.currentThread();
		return super.getControl(index);
	}

	@Override
	public int getNumControls() {
		assert Thread.currentThread() == this.thread : "Expected " + this.thread.getName() + " but got " + Thread.currentThread();
		return super.getNumControls();
	}

	@Override
	public Vector3f localToWorld(final Vector3f in, final Vector3f store) {
		assert Thread.currentThread() == this.thread : "Expected " + this.thread.getName() + " but got " + Thread.currentThread();
		return super.localToWorld(in, store);
	}

	@Override
	public Vector3f worldToLocal(final Vector3f in, final Vector3f store) {
		assert Thread.currentThread() == this.thread : "Expected " + this.thread.getName() + " but got " + Thread.currentThread();
		return super.worldToLocal(in, store);
	}

	@Override
	public Node getParent() {
		assert Thread.currentThread() == this.thread : "Expected " + this.thread.getName() + " but got " + Thread.currentThread();
		return super.getParent();
	}

	@Override
	public boolean removeFromParent() {
		assert Thread.currentThread() == this.thread : "Expected " + this.thread.getName() + " but got " + Thread.currentThread();
		return super.removeFromParent();
	}

	@Override
	public boolean hasAncestor(final Node ancestor) {
		assert Thread.currentThread() == this.thread : "Expected " + this.thread.getName() + " but got " + Thread.currentThread();
		return super.hasAncestor(ancestor);
	}

	@Override
	public Quaternion getLocalRotation() {
		assert Thread.currentThread() == this.thread : "Expected " + this.thread.getName() + " but got " + Thread.currentThread();
		return super.getLocalRotation();
	}

	@Override
	public void setLocalRotation(final Matrix3f rotation) {
		assert Thread.currentThread() == this.thread : "Expected " + this.thread.getName() + " but got " + Thread.currentThread();
		super.setLocalRotation(rotation);
	}

	@Override
	public void setLocalRotation(final Quaternion quaternion) {
		assert Thread.currentThread() == this.thread : "Expected " + this.thread.getName() + " but got " + Thread.currentThread();
		super.setLocalRotation(quaternion);
	}

	@Override
	public Vector3f getLocalScale() {
		assert Thread.currentThread() == this.thread : "Expected " + this.thread.getName() + " but got " + Thread.currentThread();
		return super.getLocalScale();
	}

	@Override
	public void setLocalScale(final float localScale) {
		assert Thread.currentThread() == this.thread : "Expected " + this.thread.getName() + " but got " + Thread.currentThread();
		super.setLocalScale(localScale);
	}

	@Override
	public void setLocalScale(final float x, final float y, final float z) {
		assert Thread.currentThread() == this.thread : "Expected " + this.thread.getName() + " but got " + Thread.currentThread();
		super.setLocalScale(x, y, z);
	}

	@Override
	public void setLocalScale(final Vector3f localScale) {
		assert Thread.currentThread() == this.thread : "Expected " + this.thread.getName() + " but got " + Thread.currentThread();
		super.setLocalScale(localScale);
	}

	@Override
	public Vector3f getLocalTranslation() {
		assert Thread.currentThread() == this.thread : "Expected " + this.thread.getName() + " but got " + Thread.currentThread();
		return super.getLocalTranslation();
	}

	@Override
	public void setLocalTranslation(final Vector3f localTranslation) {
		assert Thread.currentThread() == this.thread : "Expected " + this.thread.getName() + " but got " + Thread.currentThread();
		super.setLocalTranslation(localTranslation);
	}

	@Override
	public void setLocalTranslation(final float x, final float y, final float z) {
		assert Thread.currentThread() == this.thread : "Expected " + this.thread.getName() + " but got " + Thread.currentThread();
		super.setLocalTranslation(x, y, z);
	}

	@Override
	public void setLocalTransform(final Transform t) {
		assert Thread.currentThread() == this.thread : "Expected " + this.thread.getName() + " but got " + Thread.currentThread();
		super.setLocalTransform(t);
	}

	@Override
	public Transform getLocalTransform() {
		assert Thread.currentThread() == this.thread : "Expected " + this.thread.getName() + " but got " + Thread.currentThread();
		return super.getLocalTransform();
	}

	@Override
	public void addLight(final Light light) {
		assert Thread.currentThread() == this.thread : "Expected " + this.thread.getName() + " but got " + Thread.currentThread();
		super.addLight(light);
	}

	@Override
	public void removeLight(final Light light) {
		assert Thread.currentThread() == this.thread : "Expected " + this.thread.getName() + " but got " + Thread.currentThread();
		super.removeLight(light);
	}

	@Override
	public Spatial move(final float x, final float y, final float z) {
		assert Thread.currentThread() == this.thread : "Expected " + this.thread.getName() + " but got " + Thread.currentThread();
		return super.move(x, y, z);
	}

	@Override
	public Spatial move(final Vector3f offset) {
		assert Thread.currentThread() == this.thread : "Expected " + this.thread.getName() + " but got " + Thread.currentThread();
		return super.move(offset);
	}

	@Override
	public Spatial scale(final float s) {
		assert Thread.currentThread() == this.thread : "Expected " + this.thread.getName() + " but got " + Thread.currentThread();
		return super.scale(s);
	}

	@Override
	public Spatial scale(final float x, final float y, final float z) {
		assert Thread.currentThread() == this.thread : "Expected " + this.thread.getName() + " but got " + Thread.currentThread();
		return super.scale(x, y, z);
	}

	@Override
	public Spatial rotate(final Quaternion rot) {
		assert Thread.currentThread() == this.thread : "Expected " + this.thread.getName() + " but got " + Thread.currentThread();
		return super.rotate(rot);
	}

	@Override
	public Spatial rotate(final float xAngle, final float yAngle, final float zAngle) {
		assert Thread.currentThread() == this.thread : "Expected " + this.thread.getName() + " but got " + Thread.currentThread();
		return super.rotate(xAngle, yAngle, zAngle);
	}

	@Override
	public Spatial center() {
		assert Thread.currentThread() == this.thread : "Expected " + this.thread.getName() + " but got " + Thread.currentThread();
		return super.center();
	}

	@Override
	public CullHint getCullHint() {
		assert Thread.currentThread() == this.thread : "Expected " + this.thread.getName() + " but got " + Thread.currentThread();
		return super.getCullHint();
	}

	@Override
	public BatchHint getBatchHint() {
		assert Thread.currentThread() == this.thread : "Expected " + this.thread.getName() + " but got " + Thread.currentThread();
		return super.getBatchHint();
	}

	@Override
	public Bucket getQueueBucket() {
		assert Thread.currentThread() == this.thread : "Expected " + this.thread.getName() + " but got " + Thread.currentThread();
		return super.getQueueBucket();
	}

	@Override
	public ShadowMode getShadowMode() {
		assert Thread.currentThread() == this.thread : "Expected " + this.thread.getName() + " but got " + Thread.currentThread();
		return super.getShadowMode();
	}

	@Override
	public Spatial clone() {
		assert Thread.currentThread() == this.thread : "Expected " + this.thread.getName() + " but got " + Thread.currentThread();
		return super.clone();
	}

	@Override
	public void setUserData(final String key, final Object data) {
		assert Thread.currentThread() == this.thread : "Expected " + this.thread.getName() + " but got " + Thread.currentThread();
		super.setUserData(key, data);
	}

	@Override
	public <T> T getUserData(final String key) {
		assert Thread.currentThread() == this.thread : "Expected " + this.thread.getName() + " but got " + Thread.currentThread();
		return super.getUserData(key);
	}

	@Override
	public Collection<String> getUserDataKeys() {
		assert Thread.currentThread() == this.thread : "Expected " + this.thread.getName() + " but got " + Thread.currentThread();
		return super.getUserDataKeys();
	}

	@Override
	public boolean matches(final Class<? extends Spatial> spatialSubclass, final String nameRegex) {
		assert Thread.currentThread() == this.thread : "Expected " + this.thread.getName() + " but got " + Thread.currentThread();
		return super.matches(spatialSubclass, nameRegex);
	}

	@Override
	public BoundingVolume getWorldBound() {
		assert Thread.currentThread() == this.thread : "Expected " + this.thread.getName() + " but got " + Thread.currentThread();
		return super.getWorldBound();
	}

	@Override
	public void setCullHint(final CullHint hint) {
		assert Thread.currentThread() == this.thread : "Expected " + this.thread.getName() + " but got " + Thread.currentThread();
		super.setCullHint(hint);
	}

	@Override
	public void setBatchHint(final BatchHint hint) {
		assert Thread.currentThread() == this.thread : "Expected " + this.thread.getName() + " but got " + Thread.currentThread();
		super.setBatchHint(hint);
	}

	@Override
	public CullHint getLocalCullHint() {
		assert Thread.currentThread() == this.thread : "Expected " + this.thread.getName() + " but got " + Thread.currentThread();
		return super.getLocalCullHint();
	}

	@Override
	public BatchHint getLocalBatchHint() {
		assert Thread.currentThread() == this.thread : "Expected " + this.thread.getName() + " but got " + Thread.currentThread();
		return super.getLocalBatchHint();
	}

	@Override
	public Bucket getLocalQueueBucket() {
		assert Thread.currentThread() == this.thread : "Expected " + this.thread.getName() + " but got " + Thread.currentThread();
		return super.getLocalQueueBucket();
	}

	@Override
	public ShadowMode getLocalShadowMode() {
		assert Thread.currentThread() == this.thread : "Expected " + this.thread.getName() + " but got " + Thread.currentThread();
		return super.getLocalShadowMode();
	}

	@Override
	public FrustumIntersect getLastFrustumIntersection() {
		assert Thread.currentThread() == this.thread : "Expected " + this.thread.getName() + " but got " + Thread.currentThread();
		return super.getLastFrustumIntersection();
	}

	@Override
	public void setLastFrustumIntersection(final FrustumIntersect intersects) {
		assert Thread.currentThread() == this.thread : "Expected " + this.thread.getName() + " but got " + Thread.currentThread();
		super.setLastFrustumIntersection(intersects);
	}

	@Override
	public Matrix4f getLocalToWorldMatrix(final Matrix4f store) {
		assert Thread.currentThread() == this.thread : "Expected " + this.thread.getName() + " but got " + Thread.currentThread();
		return super.getLocalToWorldMatrix(store);
	}

	@Override
	public void setQueueBucket(final Bucket queueBucket) {
		assert Thread.currentThread() == this.thread : "Expected " + this.thread.getName() + " but got " + Thread.currentThread();
		super.setQueueBucket(queueBucket);
	}

	@Override
	public void setShadowMode(final ShadowMode shadowMode) {
		assert Thread.currentThread() == this.thread : "Expected " + this.thread.getName() + " but got " + Thread.currentThread();
		super.setShadowMode(shadowMode);
	}

	@Override
	public String toString() {
		assert Thread.currentThread() == this.thread : "Expected " + this.thread.getName() + " but got " + Thread.currentThread();
		return super.toString();
	}

	@Override
	public void breadthFirstTraversal(final SceneGraphVisitor visitor) {
		assert Thread.currentThread() == this.thread : "Expected " + this.thread.getName() + " but got " + Thread.currentThread();
		super.breadthFirstTraversal(visitor);
	}

}
1 Like