Momoko_Fan said:
I think its okay. When you want to set the direction of the camera, you use that method.
I don't understand what the issue is?
the problem was/is that cam.setDirection(direction) doesn't set the direction correctly, it only rotates half the way between where the camera was and where the camera should be
And the camera should be in the same direction as the passed direction vector, just as cam.rotation.lookAt(direction, getUp());
if you run this example, I attempt here to setDirection of the camera such that the box is in the middle of the camera...this requires several calls to setDirection using the same unchanged `direction` vector to do exactly that.
...in the update method cam.setDirection(direction) is called (initially, if you don't press any key), it should point the camera in the direction of the blue box instantly (on the first call) but instead as you can see, it requires several calls[each call happens after 1 second] (and the `direction` vector doesn't change at all), where on each call it moves half the way from current camera position to the final camera position
That being said, I'm unsure whether this method performs as expected: even if it doesn't change the Up/Left vectors it still fails to point in the expected direction, I mean ... how can it ever point in that direction if the up/left vectors don't change ? O_o (I don't get this probably because I'm new xD)
EDIT: like, after setDirection(direction) then cam.getDirection() and `direction` don't point in the same way disregarding floating point precision
[java]package org.jme3.tests;
import com.jme3.app.SimpleApplication;
import com.jme3.font.BitmapText;
import com.jme3.input.KeyInput;
import com.jme3.input.controls.ActionListener;
import com.jme3.input.controls.KeyTrigger;
import com.jme3.material.Material;
import com.jme3.math.ColorRGBA;
import com.jme3.math.Quaternion;
import com.jme3.math.Vector3f;
import com.jme3.scene.Geometry;
import com.jme3.scene.Node;
import com.jme3.scene.shape.Box;
import com.jme3.scene.shape.Line;
import com.jme3.system.AppSettings;
public class Main5 extends SimpleApplication {
public static void main(String[] args) {
Main5 app = new Main5();
AppSettings aps = new AppSettings(true);
aps.setVSync(true);
app.setSettings(aps);
app.setShowSettings(false);
app.start();
}
private final static String mapMethod1 = "mapMethod1";
private final static String mapMethod2 = "mapMethod2";
private final static String mapMethod3 = "mapMethod3";
private final static String mapMethod4 = "mapMethod4";
private final static String mapMethod5 = "mapMethod5";
private int method = 1;
private BitmapText methodText;
private BitmapText helpText;
Geometry geom;
Node cosmos;
Node farAway;
Vector3f translationVector, translationUnityVector;
float myTimer = 0.0f;
Vector3f boxsWorldPosition;
@Override
public void simpleInitApp() {
flyCam.setMoveSpeed(800f);
Box b = new Box(Vector3f.ZERO, 100, 100, 100);
geom = new Geometry("Box", b);
// geom.updateModelBound();
Material mat = new Material(assetManager,
"Common/MatDefs/Misc/SolidColor.j3md");
mat.setColor("m_Color", ColorRGBA.Blue);
geom.setMaterial(mat);
cosmos = new Node("cosmos");
farAway = new Node("farAway");
farAway.attachChild(geom);
cosmos.attachChild(farAway);
rootNode.attachChild(cosmos);
translationVector = new Vector3f(1200.0f, 1000.0f, 1600.0f);
farAway.setLocalTranslation(translationVector);
cam.setLocation(Vector3f.ZERO.clone());
// just in case any nodes have transformations (rot/scale/trans)
boxsWorldPosition = geom.localToWorld(Vector3f.ZERO, null);
translationUnityVector = new Vector3f(boxsWorldPosition.normalize());
cam.setFrustumFar(5000.0f);
// box is on top left corner initially:
cam.setDirection(new Vector3f(0.17789759f, 0.1996023f, 0.96359295f));
// System.out.println("TansUnity Vector = " + translationUnityVector);
// System.out.println("Camera Direction = " + cam.getDirection());
initKey();
initGUI();
}
private void initGUI() {
methodText = new BitmapText(guiFont, false);
methodText.setSize(guiFont.getCharSet().getRenderedSize());
methodText.setLocalTranslation(30, 20 * methodText.getLineHeight(), 0);
guiNode.attachChild(methodText);
methodReport();
helpText = new BitmapText(guiFont, false);
helpText.setSize(guiFont.getCharSet().getRenderedSize());
helpText.setLocalTranslation(0, 23 * helpText.getLineHeight(), 0);
guiNode.attachChild(helpText);
helpText.setText("press keys from 1 to 5 to choose the method for setting camera direction towards the boxnOnly method 1 is bugged");
}
private void initKey() {
inputManager.addMapping(mapMethod1, new KeyTrigger(KeyInput.KEY_1));
inputManager.addMapping(mapMethod2, new KeyTrigger(KeyInput.KEY_2));
inputManager.addMapping(mapMethod3, new KeyTrigger(KeyInput.KEY_3));
inputManager.addMapping(mapMethod4, new KeyTrigger(KeyInput.KEY_4));
inputManager.addMapping(mapMethod5, new KeyTrigger(KeyInput.KEY_5));
inputManager.addListener(actionListener, mapMethod1, mapMethod2,
mapMethod3, mapMethod4, mapMethod5);
}
private final ActionListener actionListener = new ActionListener() {
@SuppressWarnings("synthetic-access")
@Override
public void onAction(String name, boolean isPressed, float tpf) {
do {
if (isPressed) {
if (mapMethod1 == name) {
method = 1;
break;
}
if (mapMethod2 == name) {
method = 2;
break;
}
if (mapMethod3 == name) {
method = 3;
break;
}
if (mapMethod4 == name) {
method = 4;
break;
}
if (mapMethod5 == name) {
method = 5;
break;
}
}
} while (false);
methodReport();
}
};
private void methodReport() {
switch (method) {
case 1:
methodText
.setText("- now using cam.setDirection(direction) which uses upVector==cam.getUp()");
break;
case 2:
methodText
.setText("- now using setDirection1 aka cam.rotation.lookAt(direction,cam.getUp())");
break;
case 3:
methodText
.setText("- now using setDirection2 aka the FIXED cam.setDirection(direction) which uses upVector==cam.getUp()");
break;
case 4:
methodText
.setText("- now using cam.lookAt(position,...) which uses upVector==Vector3f.UNIT_Y)");
break;
case 5:
methodText
.setText("- now using cam.lookAt(position,...) which uses upVector==cam.getUp()");
break;
default:
throw null;
}
}
private void methodUse(Vector3f direction) {
switch (method) {
case 1:
cam.setDirection(direction);
break;
case 2:
setDirection1(direction);
break;
case 3:
setDirection2(direction);
break;
case 4:
cam.lookAt(boxsWorldPosition, Vector3f.UNIT_Y);
break;
case 5:
cam.lookAt(boxsWorldPosition, cam.getUp());
break;
default:
throw null;
}
}
// XXX: should perhaps use Vector3f.UNIT_Y as upvector? unsure yet
public void setDirection1(Vector3f direction) {
// assume 'direction' wasn't normalized already
// though lookAt will normalize direction anyway, so not needed
cam.getRotation().lookAt(direction.normalize(), cam.getUp());
cam.onFrameChange();
}
// XXX: should perhaps use Vector3f.UNIT_Y as upvector? unsure yet
public void setDirection2(Vector3f direction) {
// assumed `direction` wasn't normalized:
Vector3f dir = direction.normalize();
Vector3f up = cam.getUp();// already normalized
if (!up.isUnitVector()) {
throw null;// will never happen
}
// up.normalizeLocal(); but up is already normalized
Vector3f left = up.cross(dir);// result isn't normalized!!?
// ...even though we crossed two normalized vectors
left.normalizeLocal();
if (!left.isUnitVector()) {
// this will happen if we don't manually normalize `left`
throw null;
}
// the fix comes from recalculating the `up` below:
up = dir.cross(left);// make sure new `up` is _|_ on our `dir`
if (!up.isUnitVector()) {
throw null;// will never happen
}
cam.getRotation().fromAxes(left, up, dir);
cam.onFrameChange();
}
@Override
public void simpleUpdate(float tpf) {
myTimer += tpf;
if (myTimer > 1) {// every 5 seconds
// cam.setDirection(translationUnityVector);
// setDirection1(translationUnityVector);
// direction towards to box is relative to camera position,
// thus recalculate direction just in case camera pos changed
translationUnityVector = boxsWorldPosition.subtract(
cam.getLocation()).normalizeLocal();
// now point the camera at that direction
methodUse(translationUnityVector);
// System.out.println("After five seconds: ...");
// System.out.println("TansUnity Vector = " +
// translationUnityVector);
// System.out.println("Camera Direction = " + cam.getDirection());
myTimer = 0f;
}
}
}[/java]