blob: 9a0c4b461deea57f023b4c490e94d1cc1bdcbbce [file] [log] [blame]
package org.eclipse.apogy.addons.sensors.fov.ui.jme3.utils;
/*******************************************************************************
* 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 - initial API and implementation
* Regent L'Archeveque
* SPDX-License-Identifier: EPL-1.0
*******************************************************************************/
import java.awt.image.BufferedImage;
import javax.vecmath.Matrix3d;
import javax.vecmath.Matrix4d;
import javax.vecmath.Vector3d;
import org.eclipse.apogy.addons.sensors.fov.ui.jme3.scene_objects.ProjectorData;
import org.eclipse.apogy.common.topology.ApogyCommonTopologyFacade;
import org.eclipse.apogy.common.topology.Node;
import org.eclipse.apogy.common.topology.ui.jme3.JME3Application;
import org.eclipse.apogy.common.topology.ui.jme3.JME3Utilities;
import com.jme3.math.Quaternion;
import com.jme3.math.Vector3f;
import com.jme3.post.MultiTextureProjectorRenderer;
import com.jme3.post.MultiTextureProjectorRenderer.CombineMode;
import com.jme3.post.SimpleTextureProjector;
import com.jme3.renderer.Camera;
import com.jme3.renderer.RenderManager;
import com.jme3.renderer.ViewPort;
import com.jme3.scene.Spatial;
import com.jme3.scene.control.AbstractControl;
import com.jme3.scene.debug.WireFrustum;
import com.jme3.texture.Texture;
import com.jme3.texture.Texture2D;
public abstract class ImageProjectorControl<T extends Node> extends AbstractControl {
protected T fieldOfView;
protected JME3Application jm3Application;
private ProjectorData projectorData;
public MultiTextureProjectorRenderer multiTextureProjectorRenderer;
public ImageProjectorControl(JME3Application jm3Application, T node) {
this.jm3Application = jm3Application;
this.fieldOfView = node;
}
@Override
public void setSpatial(Spatial spatial) {
super.setSpatial(spatial);
}
@Override
public void setEnabled(boolean enabled) {
if (enabled) {
if (!this.jm3Application.getViewPort().getProcessors().contains(getMultiTextureProjectorRenderer())) {
this.jm3Application.getViewPort().addProcessor(getMultiTextureProjectorRenderer());
}
} else {
if (this.jm3Application.getViewPort().getProcessors().contains(getMultiTextureProjectorRenderer())) {
this.jm3Application.getViewPort().removeProcessor(getMultiTextureProjectorRenderer());
}
}
super.setEnabled(enabled);
}
public void dispose() {
setEnabled(false);
// Removes the processor.
this.jm3Application.getViewPort().removeProcessor(getMultiTextureProjectorRenderer());
}
public abstract float getHorizontalFOVAngleDegrees();
public abstract float getTextureHtoVRatio();
public abstract BufferedImage getProjectedImage();
public abstract void updateProjectorFOVSettings();
@Override
protected void controlRender(RenderManager arg0, ViewPort arg1) {
}
@Override
protected void controlUpdate(float arg0) {
if (isEnabled()) {
// Updates the geometrie onto which to project.
if (getMultiTextureProjectorRenderer().getTargetGeometryList() == null) {
getMultiTextureProjectorRenderer().setTargetGeometryList(
JME3FovUtilities.createGeometryListForImageProjection(this.jm3Application));
} else {
JME3FovUtilities.updateGeometryListForImageProjection(this.jm3Application.getJMERenderEngineDelegate(),
getMultiTextureProjectorRenderer().getTargetGeometryList());
}
// Updates position and orientation of projector camera.
Camera projectorCamera = getProjectorData().projector.getProjectorCamera();
projectorCamera.setLocation(getProjectorLocation());
projectorCamera.setRotation(getProjectorRotation());
}
}
protected MultiTextureProjectorRenderer getMultiTextureProjectorRenderer() {
if (this.multiTextureProjectorRenderer == null) {
this.multiTextureProjectorRenderer = new MultiTextureProjectorRenderer(
this.jm3Application.getAssetManager());
this.multiTextureProjectorRenderer
.setTargetGeometryList(JME3FovUtilities.createGeometryListForImageProjection(this.jm3Application));
this.multiTextureProjectorRenderer.getTextureProjectors().add(getProjectorData().projector);
}
return this.multiTextureProjectorRenderer;
}
protected ProjectorData getProjectorData() {
if (this.projectorData == null) {
this.projectorData = new ProjectorData();
Texture2D texture2D = createTexture();
int textureWidth = texture2D.getImage().getWidth();
int textureHeight = texture2D.getImage().getHeight();
float textureAspectRatio = ((float) textureWidth) / ((float) textureHeight);
this.projectorData.projector = new SimpleTextureProjector(texture2D);
this.projectorData.projector.setFallOffDistance(1000f);
this.projectorData.projector.setFallOffPower(4f);
this.projectorData.projector.setParameter("CombineMode", CombineMode.BLEND_COLOR_ADD_ALPHA);
Camera projectorCamera = this.projectorData.projector.getProjectorCamera();
projectorCamera.setLocation(getProjectorLocation());
projectorCamera.setRotation(getProjectorRotation());
// Ensure nothing crashes if the Horizontal FOV is 0 or less.
if (getHorizontalFOVAngleDegrees() > 0) {
projectorCamera.setFrustumPerspective(getHorizontalFOVAngleDegrees(), textureAspectRatio, 1f, 5f);
} else {
projectorCamera.setFrustumPerspective(0.1f, textureAspectRatio, 1f, 5f);
}
projectorCamera.setParallelProjection(false);
this.projectorData.frustumPoints = new Vector3f[8];
for (int i = 0; i < 8; i++) {
this.projectorData.frustumPoints[i] = new Vector3f();
}
this.projectorData.projector.updateFrustumPoints(this.projectorData.frustumPoints);
this.projectorData.frustum = new WireFrustum(this.projectorData.frustumPoints);
}
return this.projectorData;
}
protected Texture2D createTexture() {
BufferedImage image = getProjectedImage();
Texture2D texture2D = JME3Utilities.createTexture2D(image, this.jm3Application.getAssetManager());
texture2D.setMinFilter(Texture.MinFilter.Trilinear);
texture2D.setMagFilter(Texture.MagFilter.Bilinear);
texture2D.setAnisotropicFilter(16);
texture2D.setWrap(Texture.WrapMode.BorderClamp);
return texture2D;
}
protected Quaternion getProjectorRotation() {
Matrix4d m = ApogyCommonTopologyFacade.INSTANCE.expressNodeInRootFrame(this.fieldOfView);
Matrix3d rot = new Matrix3d();
m.get(rot);
Quaternion q = JME3Utilities.createQuaternion(rot);
return q;
}
protected Vector3f getProjectorLocation() {
Matrix4d m = ApogyCommonTopologyFacade.INSTANCE.expressNodeInRootFrame(this.fieldOfView);
Vector3d v = new Vector3d();
m.get(v);
Vector3f location = JME3Utilities.convertToVector3f(v);
return location;
}
}