Camera rotation II

Have jReality programming problems or questions? Post them here.
Post Reply

Would you like this feature?

Yes
3
100%
No
0
No votes
 
Total votes: 3

Arve
Posts: 6
Joined: Thu 29. Dec 2011, 17:33

Camera rotation II

Post by Arve » Tue 6. Mar 2012, 15:13

Hi

I'm trying to work out how I should rotate the camera around (components of) the scene. I saw Ronin's post (monologue) from January, but would like a more generic way. I am going to work on this later today.

It would be nice to have a CameraOrbitTool on which I could call setOrigin(SceneGraphNode) or setOrigin(x,y,z), to change the center of rotation, with an encompass-ish function to zoom out until everything is visible.

Mathematically, this should just be to move and rotate the camera on the surface of a sphere around the center node, though the encompassing is a bit unclear to me.

Any starting pointers or existing code will be appreciated. If this works like I want it to, you'll get another nifty tool in the jReality toolbox :-)

Arve
Posts: 6
Joined: Thu 29. Dec 2011, 17:33

Re: Camera rotation II

Post by Arve » Thu 8. Mar 2012, 09:50

Yay, it works :-) We mainly changed the panning to move the rotation center, and cleaned up the transformation.

To make this work, the camera has to be added within a CameraNode in the scene graph.

Feel free to modify this and include it in jReality. Our benefit from rotating the camera instead of the geometry, is reading out x,y,z coordinates directly from the pick system.

Code: Select all

import de.jreality.math.FactoredMatrix;
import de.jreality.math.P3;
import de.jreality.scene.SceneGraphComponent;

/**
 * A {@link SceneGraphComponent} to hold the camera. This is needed for {@link PanningTool} and {@link CameraOrbitTool} to work.
 * 
 * 
 * @author Ronny Anderssen
 * @author Arve Skogvold
 */
public class CameraNode extends SceneGraphComponent {
	private double camDistance = 10000; // We're using ortographic projection, so we just set this high

	private double zRotation, yRotation;
	
	private double[] center = {0,0,0};

	public CameraNode(SceneGraphComponent contentNode) {
		super("Camera node");
	}

	public void addPanningTransformation(FactoredMatrix m) {
		double[] trans = m.getTranslation();
		center[0] -= trans[0];
		center[1] -= trans[1];
		center[2] -= trans[2];
		
		transformCamera();
	}
	
	public void addRotation(double zAngle, double yAngle) {
		zRotation += zAngle;
		yRotation += yAngle;
		restrictRotation();
		transformCamera();
	}
	
	private void restrictRotation() {
		yRotation = Math.max(yRotation, 0);
		yRotation = Math.min(yRotation, Math.PI);
	}

	public void resetRotation() {
		if (zRotation != 0 || yRotation != 0) {
			zRotation = 0;
			yRotation = 0;
			transformCamera();
		}
	}
	
	private void transformCamera() {
		FactoredMatrix cameraTransformationMatrix = createTransformation();
		getTransformation().setMatrix(cameraTransformationMatrix.getArray());
	}

	private FactoredMatrix createTransformation() {
		FactoredMatrix cameraOutFromCenterTransformation = new FactoredMatrix();
		cameraOutFromCenterTransformation.setTranslation(0, 0, camDistance);
		
		FactoredMatrix transform = new FactoredMatrix();
		transform.setTranslation(center);
		transform.multiplyOnRight(createRotationMatrix());
		transform.multiplyOnRight(cameraOutFromCenterTransformation);
		return transform;
	}

	private FactoredMatrix createRotationMatrix() {
		double[] yRotationMatrix = P3.makeRotationMatrixX(null, yRotation);
		double[] zRotationMatrix = P3.makeRotationMatrixZ(null, zRotation);

		FactoredMatrix rotationMatrix = new FactoredMatrix(zRotationMatrix);
		rotationMatrix.multiplyOnRight(yRotationMatrix);
		return rotationMatrix;
	}
	
	public void setCenter(double[] centerXYZ) {
		center = centerXYZ.clone();
		transformCamera();
	}
}

Code: Select all

import de.jreality.math.FactoredMatrix;
import de.jreality.scene.tool.AbstractTool;
import de.jreality.scene.tool.InputSlot;
import de.jreality.scene.tool.ToolContext;
import de.jreality.util.CameraUtility;

/**
 * To use this tool, the camera must be added in a {@link CameraNode}
 * @author Ronny Anderssen
 * @author Arve Skogvold
 */
public class PanningTool extends AbstractTool {
	private boolean skip = false;
	static InputSlot activationSlot = InputSlot.SHIFT_LEFT_BUTTON;
	static InputSlot evolutionSlot = InputSlot.getDevice("PointerEvolution");

	private CameraNode camNode;

	public PanningTool() {
		super(activationSlot);
		addCurrentSlot(evolutionSlot);
	}

	public void activate(ToolContext tc) {
		camNode = (CameraNode) CameraUtility.getCameraNode(tc.getViewer());
	}

	public void perform(ToolContext tc) {
		if (skip) {
			FactoredMatrix evolution = new FactoredMatrix();			
			evolution.assignFrom(tc.getTransformationMatrix(evolutionSlot));
			camNode.addPanningTransformation(evolution);
		}
		skip = !skip; // This is because jReality prematurely calculates the next evolution
	}
}

Code: Select all

import de.jreality.math.FactoredMatrix;
import de.jreality.scene.tool.AbstractTool;
import de.jreality.scene.tool.InputSlot;
import de.jreality.scene.tool.ToolContext;
import de.jreality.util.CameraUtility;

/**
 * Handles orbiting the camera around a given center. For this to work, the camera has to be placed in a {@link CameraNode}.
 * 
 * @author Ronny Anderssen
 * @author Arve Skogvold
 */
public class CameraOrbitTool extends AbstractTool {

	static InputSlot activationSlot = InputSlot.SHIFT_RIGHT_BUTTON;
	static InputSlot pointerEvo = InputSlot.getDevice("PointerNDCevolution");
	private FactoredMatrix rotation = new FactoredMatrix();

	private CameraNode camNode;
	
	public CameraOrbitTool() {
		super(activationSlot);
		addCurrentSlot(pointerEvo);
	}

	@Override
	public void activate(ToolContext tc) {
		camNode = (CameraNode) CameraUtility.getCameraNode(tc.getViewer());
	}

	@Override
	public void perform(ToolContext tc) {
		rotation.assignFrom(tc.getTransformationMatrix(pointerEvo));
		double[] translation = rotation.getTranslation();
		camNode.addRotation(-translation[0], translation[1]);
	}
}

Post Reply