Camera rotation

Have jReality programming problems or questions? Post them here.
Post Reply
Ronin
Posts: 50
Joined: Wed 9. Nov 2011, 17:22

Camera rotation

Post by Ronin » Tue 3. Jan 2012, 12:35

Is there any easy way to make the camera rotate around the content vs rotating the contents in front of the camera?
Preferrably in Ortographic view.

Ronin
Posts: 50
Joined: Wed 9. Nov 2011, 17:22

Re: Camera rotation

Post by Ronin » Fri 6. Jan 2012, 11:00

I've been trying to wrap my mind around this problem the last couple of days, anyone got any insight on how to do this?

What I've tried so far is to modify the RotateTool to get the CameraNode from the viewer and used that as the main component to rotate.
And I've used the contentNode to find the center instead of the camera center, cause I figured the rotation would go around the set center, but no luck there.

Anyone got any input on how to make the camera rotate/move around the contents instead of rotating the content itself?

Ronin
Posts: 50
Joined: Wed 9. Nov 2011, 17:22

Re: Camera rotation

Post by Ronin » Mon 9. Jan 2012, 11:41

Another failed attempt:

Code: Select all

center = center of contentNode (also tried center of rootNode)

cameraTrafo.assignFrom(camera.getTransformation());	
cameraTrafo.multiplyOnRight(center.getInverse());
cameraTrafo.multiplyOnRight(rotation);
cameraTrafo.multiplyOnRight(center);

camera.getTransformation().setMatrix(cameraTrafo.getArray());
I see in RotateTool that you applied center, then evolutionRotation and last center.inverse, which I'm not sure I understand why. Cause in my head a rotation around a set target should first translate into center of target(center.inverse), then rotate and lastly translate back along local z-axis (center).
Not that RotateTools way of doing it does any good either tho :P
Have I misunderstood something?

I also tried applying makeLookatMatrix to see if that helped:

Code: Select all

camera.getTransformation().setMatrix(Rn.inverse(null, P3.makeLookatMatrix(null, camera.getTransformation().getMatrix(), center.getArray(), 0.0, metric)));
But here I only get a nullException no matter what I put into it...

Anyone got any input at all? Getting a bit desperate here :p

Ronin
Posts: 50
Joined: Wed 9. Nov 2011, 17:22

Re: Camera rotation

Post by Ronin » Mon 16. Jan 2012, 09:24

Has noone stumbled unto this problem before?

In theory I need to translate the camera from camOrigin to center of target object(content or root), then rotate the camera while looking at the target, and lastly translate the camera out by the same amount I translated it in to targets center.

In other toolsets I have used(mostly gamedev toolsets) and in OpenGL/DirectX, this is no problem whatsoever to achive, but I can't for the life of me figure out how to do this in jReality...
So any help or suggestions are greatly appreciated, as I find myself completely stuck with this problem.

Ronin
Posts: 50
Joined: Wed 9. Nov 2011, 17:22

Re: Camera rotation

Post by Ronin » Tue 17. Jan 2012, 17:16

Had sort of a breakthrough today, still not perfect though. The rotation seems to attach itself to the first axis you rotate around or something similar.

Can someone take a look at my code and see if they can see what I'm doing wrong? I think I've turned blind to this problem after trying so many solutions the last couple weeks :P
Any help is highly appreciated!

Here's the code:

Code: Select all

public class ShiftClickRotationTool extends AbstractTool {

	static InputSlot activationSlot = InputSlot.SHIFT_RIGHT_BUTTON;
	static InputSlot evolutionSlot = InputSlot.getDevice("TrackballTransformation");

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

	private Viewer viewer;
	transient SceneGraphComponent target;
	transient SceneGraphComponent camNode;

	transient private int metric;
	
	private double[] center;

	public void activate(ToolContext tc) {
		viewer = tc.getViewer();
		target = (tc.getRootToToolComponent()).getLastComponent();
		camNode = CameraUtility.getCameraNode(viewer);

		if (camNode.getTransformation() == null)
			camNode.setTransformation(new Transformation());
		
		metric = Pn.EUCLIDEAN;

		Rectangle3D worldBox = BoundingBoxUtility.calculateBoundingBox(target);
		center = worldBox.getCenter();
	}

	transient FactoredMatrix evolution = new FactoredMatrix();
	transient FactoredMatrix camTrafo = new FactoredMatrix();

	public void perform(ToolContext tc) {

		Matrix object2avatar = new Matrix((tc.getRootToToolComponent()).getInverseMatrix(null));
		if (Rn.isNan(object2avatar.getArray())) {
			return;
		}
		try {
			object2avatar.assignFrom(P3.extractOrientationMatrix(null, object2avatar.getArray(), P3.originP3, metric));
		} catch (Exception e) {
			MatrixBuilder.euclidean().assignTo(object2avatar); // set identity matrix
		}
		evolution.assignFrom(tc.getTransformationMatrix(evolutionSlot));
		evolution.conjugateBy(object2avatar);

		camTrafo.assignFrom(camNode.getTransformation());

		double[] camPos = Rn.add(null, center, new double[] { 0, 0, 22000 });
		double[] camToCenter = Rn.subtract(null, center, camPos);
		double[] camToCenterTranslation = P3.makeTranslationMatrix(null, camToCenter, metric);

		camTrafo.multiplyOnRight(camToCenterTranslation);
		camTrafo.multiplyOnRight(evolution);
		camTrafo.multiplyOnRight(Rn.inverse(null, camToCenterTranslation));
		camNode.getTransformation().setMatrix(camTrafo.getArray());
	}

	public void deactivate(ToolContext tc) {

	}
}

Ronin
Posts: 50
Joined: Wed 9. Nov 2011, 17:22

Re: Camera rotation

Post by Ronin » Fri 20. Jan 2012, 17:30

I finally found a way to do this :)
Posting the code here so others can use it if they need, might need some minor modifications though of course.

Code: Select all

public class CameraOrbitTool extends AbstractTool {

	static InputSlot activationSlot = InputSlot.SHIFT_RIGHT_BUTTON;
	static InputSlot pointerEvo = InputSlot.getDevice("PointerNDCevolution");
	
	private double[] camToCenterTranslation;
	private double xRotation, yRotation;
	private double[] center;
	private int metric;

	private FactoredMatrix rotation = new FactoredMatrix();
	private FactoredMatrix camTrafoMatrix = new FactoredMatrix();
	private Transformation camTrafo;

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

	@Override
	public void activate(ToolContext tc) {
		camNode = (CameraNode) CameraUtility.getCameraNode(tc.getViewer());
		SceneGraphComponent target = (tc.getRootToToolComponent()).getLastComponent();
		
		Rectangle3D worldBox = BoundingBoxUtility.calculateBoundingBox(target);
		center = worldBox.getCenter();
		metric = Pn.EUCLIDEAN;
		
		camTrafo = camNode.getTransformation();
		
		double[] camPos = Rn.add(null, center, new double[] { 0, 0, 22500 });
		double[] camToCenter = Rn.subtract(null, center, camPos);
		camToCenterTranslation = P3.makeTranslationMatrix(null, camToCenter, metric);
	}

	@Override
	public void perform(ToolContext tc) {
		rotation.assignFrom(tc.getTransformationMatrix(pointerEvo));
		double[] translation = rotation.getTranslation();
		xRotation -= translation[0];
		yRotation += translation[1];

		System.out.format("x: %f, y: %f\n", xRotation, yRotation);
		
		rotationChanged();
	}

	public double getxRotation() {
		return xRotation;
	}

	public double getyRotation() {
		return yRotation;
	}
	
	public void setRotation(double x, double y) {
		xRotation = x;
		yRotation = y;
		rotationChanged();
	}

	private void rotationChanged() {
		restrictRotation();
		
		double[] xRotationMatrix = P3.makeRotationMatrixX(null, yRotation);
		double[] yRotationMatrix = P3.makeRotationMatrixY(null, xRotation);

		FactoredMatrix totalRotationMatrix = new FactoredMatrix(xRotationMatrix);
		totalRotationMatrix.multiplyOnRight(yRotationMatrix);
		pcs.firePropertyChange("ROTATION", null, totalRotationMatrix);
		
		camTrafoMatrix.assignFrom(camNode.getDefaultTransformation());
		camTrafoMatrix.multiplyOnRight(camToCenterTranslation);
		camTrafoMatrix.multiplyOnRight(totalRotationMatrix);
		camTrafoMatrix.multiplyOnRight(Rn.inverse(null, camToCenterTranslation));
		camTrafo.setMatrix(camTrafoMatrix.getArray());
	}

	private void restrictRotation() {
		yRotation = Math.max(yRotation, 0);
		yRotation = Math.min(yRotation, Math.PI);
	}

	public void resetRotation() {
		if (xRotation != 0 || yRotation != 0) {
			setRotation(0, 0);			
		}
	}
}

Ronin
Posts: 50
Joined: Wed 9. Nov 2011, 17:22

Re: Camera rotation

Post by Ronin » Mon 30. Jan 2012, 11:45

Did some modifications to handle panning of the camera too, so here's what I ended up with in the end, any input is highly appreciated especially on the DEFAULT_CAMERA_DISTANCE constant and the premature calculation of the next evolution on the ShiftClickDraggingTool.

Code: Select all

public class ShiftClickDraggingTool extends AbstractTool {
	private boolean skip = false;
	static InputSlot activationSlot = InputSlot.SHIFT_LEFT_BUTTON;
	static InputSlot evolutionSlot = InputSlot.getDevice("PointerEvolution");

	private CameraNode camNode;
	private FactoredMatrix evolution = new FactoredMatrix();

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

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

	public void perform(ToolContext tc) {
		if (skip) {
			evolution.assignFrom(tc.getTransformationMatrix(evolutionSlot));
			camNode.addPanningTransformation(evolution.getInverse());
		}
		skip = !skip; // This is because jReality prematurely calculates the next evolution any suggestions on a better way to solve this?
	}

}

Code: Select all

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]);
	}
}

Code: Select all

public class CameraNode extends SceneGraphComponent {
	private static final int DEFAULT_CAMERA_DISTANCE = 22500; // Hardcoded cause I have problems getting the Camera's current Z-position
	private Transformation defaultTransformation;
	private Matrix panningTransformation = new Matrix(Rn.identityMatrix(4));

	private final SceneGraphComponent contentNode;
	
	private double zRotation, yRotation;
	
	private PropertyChangeSupport propertyChangeSupport = new PropertyChangeSupport(this);

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

	public void setDefaultTransformation(Transformation transformation) {
		defaultTransformation = new Transformation(transformation.getMatrix());
	}

	public void addPanningTransformation(Matrix m) {
		panningTransformation.multiplyOnRight(m);
		panAndRotateCamera();
	}
	
	public void addRotation(double zAngle, double yAngle) {
		zRotation += zAngle;
		yRotation += yAngle;
		restrictRotation();
		panAndRotateCamera();
	}
	
	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;
			panAndRotateCamera();
		}
	}
	
	public void resetPanning() {
		panningTransformation.assignFrom(Rn.identityMatrix(4));
		panAndRotateCamera();
	}
	
	private void panAndRotateCamera() {
		FactoredMatrix rotationMatrix = createRotationMatrix();
		FactoredMatrix cameraTransformationMatrix = createCombinedRotationAndPanningTransformation(rotationMatrix);
		getTransformation().setMatrix(cameraTransformationMatrix.getArray());
		propertyChangeSupport.firePropertyChange("ROTATION", null, rotationMatrix);
	}

	private FactoredMatrix createCombinedRotationAndPanningTransformation(FactoredMatrix totalRotationMatrix) {
		double[] cameraToCenterTranslation = createCameraToCenterVectorTranslation();
		FactoredMatrix rotationAndPanningTransformation = new FactoredMatrix(defaultTransformation.getMatrix());
		rotationAndPanningTransformation.multiplyOnRight(panningTransformation);
		rotationAndPanningTransformation.multiplyOnRight(cameraToCenterTranslation);
		rotationAndPanningTransformation.multiplyOnRight(totalRotationMatrix);
		rotationAndPanningTransformation.multiplyOnRight(Rn.inverse(null, cameraToCenterTranslation));
		return rotationAndPanningTransformation;
	}

	private double[] createCameraToCenterVectorTranslation() {
		double[] contentCenterPosition = BoundingBoxUtility.calculateBoundingBox(contentNode).getCenter();
		double[] cameraPosition = Rn.add(null, contentCenterPosition, new double[] { 0, 0, DEFAULT_CAMERA_DISTANCE }); // TODO fix this magic constant
		double[] cameraToCenterVector = Rn.subtract(null, contentCenterPosition, cameraPosition);
		double[] cameraToCenterTranslation = P3.makeTranslationMatrix(null, cameraToCenterVector, Pn.EUCLIDEAN);
		return cameraToCenterTranslation;
	}

	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;
	}
	// Listener to send rotationinfo to other panels, in my case, a compass
	public void addRotationListener(PropertyChangeListener listener) {
		propertyChangeSupport.addPropertyChangeListener(listener);
	}
}

Ronin
Posts: 50
Joined: Wed 9. Nov 2011, 17:22

Re: Camera rotation

Post by Ronin » Mon 6. Feb 2012, 14:09

For some reason, panning gets really sluggish after I rotate the camera, it's fine before I rotate and if I zoom in/out after rotate.
Anyone got an idea why this happens? (See code in my last post)

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

Re: Camera rotation

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

Thread continues here

Post Reply