blob: fe8fa3814dfc7fc93ee33774c064548006b44f5b [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2018 Agence spatiale canadienne / Canadian Space Agency
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Pierre Allard,
* Regent L'Archeveque,
* Sebastien Gemme - initial API and implementation
*
* SPDX-License-Identifier: EPL-1.0
*
*******************************************************************************/
package org.eclipse.apogy.common.topology.ui.jme3.scene_objects;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;
import javax.vecmath.Matrix4d;
import javax.vecmath.Vector3d;
import org.eclipse.apogy.common.topology.ApogyCommonTopologyPackage;
import org.eclipse.apogy.common.topology.Node;
import org.eclipse.apogy.common.topology.PositionNode;
import org.eclipse.apogy.common.topology.RotationNode;
import org.eclipse.apogy.common.topology.TransformNode;
import org.eclipse.apogy.common.topology.ui.adapters.TransformNodeSceneObject;
import org.eclipse.apogy.common.topology.ui.jme3.JME3RenderEngineDelegate;
import org.eclipse.apogy.common.topology.ui.jme3.JME3Utilities;
import org.eclipse.emf.common.notify.Adapter;
import org.eclipse.emf.common.notify.Notification;
import org.eclipse.emf.common.notify.Notifier;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.jme3.asset.AssetManager;
import com.jme3.math.Transform;
import com.jme3.scene.Geometry;
public abstract class AbstractTransformationJME3SceneObject<T extends Node> extends DefaultJME3SceneObject<T>
implements TransformNodeSceneObject, Adapter {
private static final Logger Logger = LoggerFactory.getLogger(AbstractTransformationJME3SceneObject.class);
private float previousAxisLength = 1.0f;
private boolean axisVisible = true;
private Geometry axisGeometry = null;
private final AssetManager assetManager;
public AbstractTransformationJME3SceneObject(T topologyNode, JME3RenderEngineDelegate jme3RenderEngineDelegate) {
super(topologyNode, jme3RenderEngineDelegate);
this.assetManager = this.jme3Application.getAssetManager();
// Register to the node.
registerListener(topologyNode);
// Creates the 3DAxis.
this.axisGeometry = JME3Utilities.createAxis3D(1.0f, this.assetManager);
// Attaches the 3DAxis if required.
if (this.axisVisible)
getAttachmentNode().attachChild(this.axisGeometry);
// Updates the transform.
requestUpdate();
}
@Override
public void updateGeometry(float tpf) {
Matrix4d transformMatrix = new Matrix4d();
transformMatrix.setIdentity();
if (getTopologyNode() instanceof TransformNode) {
TransformNode transformNode = (TransformNode) getTopologyNode();
if (transformNode.asMatrix4d() != null)
transformMatrix = transformNode.asMatrix4d();
} else if (getTopologyNode() instanceof PositionNode) {
PositionNode positionNode = (PositionNode) getTopologyNode();
if (positionNode.getPosition() != null) {
transformMatrix.set(new Vector3d(positionNode.getPosition().asTuple3d()));
}
} else if (getTopologyNode() instanceof RotationNode) {
RotationNode rotationNode = (RotationNode) getTopologyNode();
if (rotationNode.getRotationMatrix() != null) {
transformMatrix.set(rotationNode.getRotationMatrix().asMatrix3d());
}
}
Transform transform = JME3Utilities.createTransform(transformMatrix);
getAttachmentNode().setLocalTransform(transform);
}
@Override
public void dispose() {
// Removes listener from topology node.
if (getTopologyNode() != null) {
unRegisterListener(getTopologyNode());
}
super.dispose();
}
@Override
public List<Geometry> getGeometries() {
List<Geometry> geometries = new ArrayList<Geometry>();
if (this.axisGeometry != null)
geometries.add(this.axisGeometry);
return geometries;
}
@Override
public void setAxisVisible(final boolean visible) {
Logger.info("Setting axis visible to <" + visible + ">");
this.axisVisible = visible;
this.jme3Application.enqueue(new Callable<Object>() {
@Override
public Object call() throws Exception {
if (AbstractTransformationJME3SceneObject.this.axisVisible) {
getAttachmentNode().attachChild(AbstractTransformationJME3SceneObject.this.axisGeometry);
} else {
getAttachmentNode().detachChild(AbstractTransformationJME3SceneObject.this.axisGeometry);
}
return null;
}
});
}
@Override
public void setAxisLength(double length) {
Logger.info("Setting axis length to <" + length + ">");
this.jme3Application.enqueue(new Callable<Object>() {
@Override
public Object call() throws Exception {
try {
float scale = (float) Math.abs(length)
/ AbstractTransformationJME3SceneObject.this.previousAxisLength;
// Scales existing axis.
if (AbstractTransformationJME3SceneObject.this.axisGeometry != null)
AbstractTransformationJME3SceneObject.this.axisGeometry.scale(scale);
AbstractTransformationJME3SceneObject.this.previousAxisLength = (float) length;
} catch (Throwable t) {
Logger.error("Failed to setAxisLength(" + length + ")", t);
}
return null;
}
});
}
@Override
public void notifyChanged(Notification notification) {
if (notification.getNotifier() instanceof TransformNode) {
int featureId = notification.getFeatureID(TransformNode.class);
if (featureId == ApogyCommonTopologyPackage.TRANSFORM_NODE__POSITION) {
// Unregister from previous position
if (notification.getOldValue() instanceof org.eclipse.apogy.common.math.Tuple3d) {
org.eclipse.apogy.common.math.Tuple3d oldValue = (org.eclipse.apogy.common.math.Tuple3d) notification
.getOldValue();
oldValue.eAdapters().remove(this);
}
requestUpdate();
// Register to new position.
if (notification.getNewValue() instanceof org.eclipse.apogy.common.math.Tuple3d) {
org.eclipse.apogy.common.math.Tuple3d newValue = (org.eclipse.apogy.common.math.Tuple3d) notification
.getNewValue();
newValue.eAdapters().add(this);
}
} else if (featureId == ApogyCommonTopologyPackage.TRANSFORM_NODE__ROTATION_MATRIX) {
// Unregister from previous matrix
if (notification.getOldValue() instanceof org.eclipse.apogy.common.math.Matrix3x3) {
org.eclipse.apogy.common.math.Matrix3x3 oldValue = (org.eclipse.apogy.common.math.Matrix3x3) notification
.getOldValue();
oldValue.eAdapters().remove(this);
}
requestUpdate();
// Register to new matrix.
if (notification.getNewValue() instanceof org.eclipse.apogy.common.math.Matrix3x3) {
org.eclipse.apogy.common.math.Matrix3x3 newValue = (org.eclipse.apogy.common.math.Matrix3x3) notification
.getNewValue();
newValue.eAdapters().add(this);
}
}
} else if (notification.getNotifier() instanceof RotationNode) {
int featureId = notification.getFeatureID(RotationNode.class);
if (featureId == ApogyCommonTopologyPackage.ROTATION_NODE__ROTATION_MATRIX) {
// Unregister from previous matrix
if (notification.getOldValue() instanceof org.eclipse.apogy.common.math.Matrix3x3) {
org.eclipse.apogy.common.math.Matrix3x3 oldValue = (org.eclipse.apogy.common.math.Matrix3x3) notification
.getOldValue();
oldValue.eAdapters().remove(this);
}
requestUpdate();
// Register to new matrix.
if (notification.getNewValue() instanceof org.eclipse.apogy.common.math.Matrix3x3) {
org.eclipse.apogy.common.math.Matrix3x3 newValue = (org.eclipse.apogy.common.math.Matrix3x3) notification
.getNewValue();
newValue.eAdapters().add(this);
}
}
} else if (notification.getNotifier() instanceof PositionNode) {
int featureId = notification.getFeatureID(PositionNode.class);
if (featureId == ApogyCommonTopologyPackage.POSITION_NODE__POSITION) {
// Unregister from previous position
if (notification.getOldValue() instanceof org.eclipse.apogy.common.math.Tuple3d) {
org.eclipse.apogy.common.math.Tuple3d oldValue = (org.eclipse.apogy.common.math.Tuple3d) notification
.getOldValue();
oldValue.eAdapters().remove(this);
}
requestUpdate();
// Register to new position.
if (notification.getNewValue() instanceof org.eclipse.apogy.common.math.Tuple3d) {
org.eclipse.apogy.common.math.Tuple3d newValue = (org.eclipse.apogy.common.math.Tuple3d) notification
.getNewValue();
newValue.eAdapters().add(this);
}
}
} else if (notification.getNotifier() instanceof org.eclipse.apogy.common.math.Tuple3d) {
requestUpdate();
} else if (notification.getNotifier() instanceof org.eclipse.apogy.common.math.Matrix3x3) {
requestUpdate();
}
}
@Override
public Notifier getTarget() {
return null;
}
@Override
public void setTarget(Notifier newTarget) {
}
@Override
public boolean isAdapterForType(Object type) {
return false;
}
protected void registerListener(T topologyNode) {
topologyNode.eAdapters().add(this);
if (topologyNode instanceof TransformNode) {
TransformNode transformNode = (TransformNode) topologyNode;
if (transformNode.getRotationMatrix() != null)
transformNode.getRotationMatrix().eAdapters().add(this);
if (transformNode.getPosition() != null)
transformNode.getPosition().eAdapters().add(this);
} else if (topologyNode instanceof RotationNode) {
RotationNode rotationNode = (RotationNode) topologyNode;
if (rotationNode.getRotationMatrix() != null)
rotationNode.getRotationMatrix().eAdapters().add(this);
} else if (topologyNode instanceof PositionNode) {
PositionNode positionNode = (PositionNode) topologyNode;
if (positionNode.getPosition() != null)
positionNode.getPosition().eAdapters().add(this);
}
}
protected void unRegisterListener(T topologyNode) {
topologyNode.eAdapters().add(this);
if (topologyNode instanceof TransformNode) {
TransformNode transformNode = (TransformNode) topologyNode;
if (transformNode.getRotationMatrix() != null)
transformNode.getRotationMatrix().eAdapters().remove(this);
if (transformNode.getPosition() != null)
transformNode.getPosition().eAdapters().remove(this);
} else if (topologyNode instanceof RotationNode) {
RotationNode rotationNode = (RotationNode) topologyNode;
if (rotationNode.getRotationMatrix() != null)
rotationNode.getRotationMatrix().eAdapters().remove(this);
} else if (topologyNode instanceof PositionNode) {
PositionNode positionNode = (PositionNode) topologyNode;
if (positionNode.getPosition() != null)
positionNode.getPosition().eAdapters().remove(this);
}
}
}