Camera rotation
Camera rotation
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.
Preferrably in Ortographic view.
Re: Camera rotation
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?
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?
Re: Camera rotation
Another failed attempt:
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
Have I misunderstood something?
I also tried applying makeLookatMatrix to see if that helped:
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
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());
Not that RotateTools way of doing it does any good either tho
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)));
Anyone got any input at all? Getting a bit desperate here :p
Re: Camera rotation
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.
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.
Re: Camera rotation
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
Any help is highly appreciated!
Here's the code:
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
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) {
}
}
Re: Camera rotation
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.
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);
}
}
}
Re: Camera rotation
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);
}
}
Re: Camera rotation
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)
Anyone got an idea why this happens? (See code in my last post)