Several First-Person camera pitfalls (speed and angle) [jME3]

Hello,



I recently started using JMonkeyEngine, though following the tutorials has been easy and cleared up some things there are some pitfalls I’ve encountered while creating a first-person game:



The first one is that for some reason the setMovementSpeed method of the flyCam doesn’t seem to actually affect the actual movement speed of the player. Take for example the code in the HelloCollision tutorial, I tried changing the setMovementSpeed value but no matter which value I passed the camera still moved at the same speed.



The second one is how to actually restrict the camera angle to prevent the “player” to do a 360 degree flip, which is something not explained in the tutorials. There seems not to be a documented good practice on how to do this and it also seems (by a quick forum search) to be a topic people have doubts about but no definite or recommended answer is available, at least for version 3 of the SDK.



These are just some observations that I hope people with more experience with the engine than me could give some input on them.



Thank you.

Well i can get you started… for your first question set movementSpeed has no effect… I believe that you are linking the camera to a player control, and then the camera is following that player, so the player walk speed is the only thing that effects the speed of the camera…



Think of it this way, if you hooked a car to a tow truck, it doesn’t matter what speed the car is set to, it will always have the speed of the tow truck… its the speed of the playerControl that you want to adjust…

1 Like

@kbender88 Thanks a lot for your answer.



Actually that is something I was thinking about, that somehow the CharacterController must has its speed changed. I think it is a misunderstanding that the HelloCollision tutorial should clear up, since it states that you set the speed using that method of setMovementSpeed though is actually a multiplication (cam.getDirection().clone().multLocal) in the directional vectors that actually modifies it when moving the player/camera.

As for the second one the only simple way I found to solve the problem was doing the following:

public void simpleUpdate(float tpf) {
if(cam.getUp().y < 0)
{
cam.lookAtDirection( new Vector3f(0,cam.getDirection().y,0),new Vector3f(cam.getUp().x,0, cam.getUp().z));
}
}

Once again I don’t know how efficient this is.

The problem with the previous code is that I am using cam.getDirection() to set the walkingDirection of the player towards where the camera is facing but in order to keep the player moving forward regardless of the camera angle in Y, I set the Y component in the variable storing the camera’s direction to zero and normalizing the vector. This causes a problem if, as in the previous code, I limit the Y component of the Up Vector to stop when reaching zero (camera totally facing upwards). What happens is that when the player is looking totally upward: Up = cam.getUp().x, 0, cam.getUp().z Direction = 0, cam.getDirection().y, 0 The forward and backward movement is erratic, it goes sideways sometimes instead of going completely straight. I don’t have any idea in how to fix this behavior and I’ll appreciate if someone could give me a clue of how to solve this.



Update code:





public void simpleUpdate(float tpf) {

Vector3f camDir = cam.getDirection().clone();

Vector3f camLeft = cam.getLeft().clone().multLocal(0.1f);



if(cam.getUp().y < 0)

{

cam.lookAtDirection( new Vector3f(0,cam.getDirection().y,0),new Vector3f(cam.getUp().x,0, cam.getUp().z));

}

walkDirection.set(0, 0, 0);

camDir.setY(0);

camDir = camDir.normalize().multLocal(0.2f);

if (left) { walkDirection.addLocal(camLeft); }

if (right) { walkDirection.addLocal(camLeft.negate()); }

if (up) { walkDirection.addLocal(camDir); }

if (down) { walkDirection.addLocal(camDir.negate()); }

player.setWalkDirection(walkDirection);

cam.setLocation(player.getPhysicsLocation());

}

The code and what you describe don’t fit. And the code doesn’t make quite sense to me, you take the y component of the up-vector of the cam? Why? +Y is up, +X is right and +Z is towards you.

I take the Y component of the up vector to validate: if it’s below zero, that means the camera is facing upwards or downwards (the Y component of the up vector is 1 when the camera is looking straight, -1 when looking straight upside down and 0 when looking up or down), then I use cam.lookAtDirection to “force” to look upwards or downwards (this depends of the value of cam.getDirection().y), specifying the up vector to be: cam.getUp().x,0, cam.getUp().z, and never go beyond that point.



This actually works, it restricts the camera to a 180 degree angle over the Y axis. The problem comes when walking, as it is seen in the code I set to zero the camera direction clone and normalize it so that, regardless of the camera angle in the Y axis, the camera speed stays the same. But when I attempt to look completely upwards or downwards (cam.getUp().y < 0) the walking goes sideways. This is probably because I’m setting the direction to be 0 in the X and Z component when the condition (cam.getUp().y < 0) happens, but I’m at a loss on how to solve this problem.



My original question was: is there any right way to restrict the first person camera rotation over the Y axis?



Thank you very much.

What do you mean by “first person camera”? Just the camera? As you move the camera yourself using a CamControl that is completely in your hands.

I’m using the default camera, that is the ‘cam’ variable that comes when extending the SimpleApplication class. The only part where I am using it is in the simpleUpdate method I posted earlier.

Thats the FlyCamControl, you can disable the default FlyCam with the FlyCamAppState.

I think what he wants is to use fly cam but he’d like it to behave properly with respect to looking up or down too far. Even Mythruna suffers from this problem where players can walk around upside down because I haven’t bothered to fix this in my own code. :slight_smile:



I think the easier way is to write your own camera similar to fly cam and instead of accumulating quaternions, just keep the yaw and pitch separately. Let the mouse modify the yaw and pitch (properly clamped) and then derive the camera rotation from that.

1 Like

@pspeed, yes that’s exactly what I want, the camera moves perfectly but restricting the up-down rotation has been a real hassle and I was asking how to do this properly (sorry if I wasn’t clear enough :frowning: ). So could you please point me to the correct documentation for building a custom camera?

Open FlyByCamera.java. Select all. Press Ctrl-C. Open a new file called MyImprovedFlyByCamera.java. Press Ctrl-V. Rename class and change package. Fix rotation code.



:slight_smile:

@pspeed said:
Open FlyByCamera.java. Select all. Press Ctrl-C. Open a new file called MyImprovedFlyByCamera.java. Press Ctrl-V. Rename class and change package. Fix rotation code.

:)

If happy with it submit improved code back to JME as ConstrainedFlyByCamera. :D

Make a diff patch please, not a new class

I’m sure there is a better way to do it, but I check the cam.getUp().y value to see if its < 0 and then restrict the rotation in the rotateCamera() method of FlyByCamera if it is. I’m sure pspeed will find 100 things wrong I’ve done ^_^. I modified the existing HelloCollision tutorial (diff also below), and it works very well together :). The axis is limited, so you cannot go upside down anymore. The movement is fluid in all directions and you wont “fly” if you look at the sky and move forward. Not bothered if you accept it or not, but you asked for a diff, i rose to the occasion and here it is :stuck_out_tongue:



# This patch file was generated by NetBeans IDE<br />
# It uses platform neutral UTF-8 encoding and n newlines.<br />
--- Base (BASE)<br />
+++ Locally Modified (Based On LOCAL)<br />
@@ -29,7 +29,6 @@<br />
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS<br />
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.<br />
*/<br />
-<br />
package com.jme3.input;<br />
<br />
import com.jme3.collision.MotionAllowedListener;<br />
@@ -58,20 +57,16 @@<br />
&quot;FLYCAM_Right&quot;,<br />
&quot;FLYCAM_Up&quot;,<br />
&quot;FLYCAM_Down&quot;,<br />
-<br />
&quot;FLYCAM_StrafeLeft&quot;,<br />
&quot;FLYCAM_StrafeRight&quot;,<br />
&quot;FLYCAM_Forward&quot;,<br />
&quot;FLYCAM_Backward&quot;,<br />
-<br />
&quot;FLYCAM_ZoomIn&quot;,<br />
&quot;FLYCAM_ZoomOut&quot;,<br />
&quot;FLYCAM_RotateDrag&quot;,<br />
-<br />
&quot;FLYCAM_Rise&quot;,<br />
&quot;FLYCAM_Lower&quot;<br />
};<br />
-<br />
protected Camera cam;<br />
protected Vector3f initialUpVec;<br />
protected float rotationSpeed = 1f;<br />
@@ -81,12 +76,13 @@<br />
protected boolean dragToRotate = false;<br />
protected boolean canRotate = false;<br />
protected InputManager inputManager;<br />
+    protected boolean firstPersonConstraint = false;<br />
<br />
/**<br />
* Creates a new FlyByCamera to control the given Camera object.<br />
* @param cam<br />
*/<br />
-    public FlyByCamera(Camera cam){<br />
+    public FlyByCamera(Camera cam) {<br />
this.cam = cam;<br />
initialUpVec = cam.getUp().clone();<br />
}<br />
@@ -99,7 +95,7 @@<br />
initialUpVec.set(upVec);<br />
}<br />
<br />
-    public void setMotionAllowedListener(MotionAllowedListener listener){<br />
+    public void setMotionAllowedListener(MotionAllowedListener listener) {<br />
this.motionAllowed = listener;<br />
}<br />
<br />
@@ -107,7 +103,7 @@<br />
* Sets the move speed. The speed is given in world units per second.<br />
* @param moveSpeed<br />
*/<br />
-    public void setMoveSpeed(float moveSpeed){<br />
+    public void setMoveSpeed(float moveSpeed) {<br />
this.moveSpeed = moveSpeed;<br />
}<br />
<br />
@@ -115,7 +111,7 @@<br />
* Gets the move speed. The speed is given in world units per second.<br />
* @return moveSpeed<br />
*/<br />
-    public float getMoveSpeed(){<br />
+    public float getMoveSpeed() {<br />
return moveSpeed;<br />
}<br />
<br />
@@ -123,7 +119,7 @@<br />
* Sets the rotation speed.<br />
* @param rotationSpeed<br />
*/<br />
-    public void setRotationSpeed(float rotationSpeed){<br />
+    public void setRotationSpeed(float rotationSpeed) {<br />
this.rotationSpeed = rotationSpeed;<br />
}<br />
<br />
@@ -131,16 +127,16 @@<br />
* Gets the move speed. The speed is given in world units per second.<br />
* @return rotationSpeed<br />
*/<br />
-    public float getRotationSpeed(){<br />
+    public float getRotationSpeed() {<br />
return rotationSpeed;<br />
}<br />
<br />
/**<br />
* @param enable If false, the camera will ignore input.<br />
*/<br />
-    public void setEnabled(boolean enable){<br />
-        if (enabled &amp;&amp; !enable){<br />
-            if (inputManager!= null &amp;&amp; (!dragToRotate || (dragToRotate &amp;&amp; canRotate))){<br />
+    public void setEnabled(boolean enable) {<br />
+        if (enabled &amp;&amp; !enable) {<br />
+            if (inputManager != null &amp;&amp; (!dragToRotate || (dragToRotate &amp;&amp; canRotate))) {<br />
inputManager.setCursorVisible(true);<br />
}<br />
}<br />
@@ -151,7 +147,7 @@<br />
* @return If enabled<br />
* @see FlyByCamera#setEnabled(boolean)<br />
*/<br />
-    public boolean isEnabled(){<br />
+    public boolean isEnabled() {<br />
return enabled;<br />
}<br />
<br />
@@ -183,11 +179,27 @@<br />
}<br />
<br />
/**<br />
+     * @param firstPersonConstraint True to constraint along X axis of view<br />
+     */<br />
+    public void setConstraint(boolean firstPersonConstraint) {<br />
+        this.firstPersonConstraint = firstPersonConstraint;<br />
+    }<br />
+<br />
+    /**<br />
+     * @return If constrained rotatation is enabled.<br />
+     *<br />
+     * @see FlyByCamera#setConstraint(boolean)<br />
+     */<br />
+    public boolean isConstrained() {<br />
+        return firstPersonConstraint;<br />
+    }<br />
+<br />
+    /**<br />
* Registers the FlyByCamera to receive input events from the provided<br />
* Dispatcher.<br />
* @param inputManager<br />
*/<br />
-    public void registerWithInput(InputManager inputManager){<br />
+    public void registerWithInput(InputManager inputManager) {<br />
this.inputManager = inputManager;<br />
<br />
// both mouse and button - rotation of cam<br />
@@ -220,7 +232,7 @@<br />
inputManager.setCursorVisible(dragToRotate || !isEnabled());<br />
<br />
Joystick[] joysticks = inputManager.getJoysticks();<br />
-        if (joysticks != null &amp;&amp; joysticks.length &gt; 0){<br />
+        if (joysticks != null &amp;&amp; joysticks.length &gt; 0) {<br />
Joystick joystick = joysticks[0];<br />
joystick.assignAxis(&quot;FLYCAM_StrafeRight&quot;, &quot;FLYCAM_StrafeLeft&quot;, JoyInput.AXIS_POV_X);<br />
joystick.assignAxis(&quot;FLYCAM_Forward&quot;, &quot;FLYCAM_Backward&quot;, JoyInput.AXIS_POV_Y);<br />
@@ -234,7 +246,7 @@<br />
* Dispatcher.<br />
* @param inputManager<br />
*/<br />
-    public void unregisterInput(){<br />
+    public void unregisterInput() {<br />
<br />
if (inputManager == null) {<br />
return;<br />
@@ -242,7 +254,7 @@<br />
<br />
for (String s : mappings) {<br />
if (inputManager.hasMapping(s)) {<br />
-                inputManager.deleteMapping( s );<br />
+                inputManager.deleteMapping(s);<br />
}<br />
}<br />
<br />
@@ -250,18 +262,18 @@<br />
inputManager.setCursorVisible(!dragToRotate);<br />
<br />
Joystick[] joysticks = inputManager.getJoysticks();<br />
-        if (joysticks != null &amp;&amp; joysticks.length &gt; 0){<br />
+        if (joysticks != null &amp;&amp; joysticks.length &gt; 0) {<br />
Joystick joystick = joysticks[0];<br />
<br />
// No way to unassing axis<br />
}<br />
}<br />
<br />
-    protected void rotateCamera(float value, Vector3f axis){<br />
-        if (dragToRotate){<br />
-            if (canRotate){<br />
+    protected void rotateCamera(float value, Vector3f axis) {<br />
+        if (dragToRotate) {<br />
+            if (canRotate) {<br />
//                value = -value;<br />
-            }else{<br />
+            } else {<br />
return;<br />
}<br />
}<br />
@@ -277,6 +289,10 @@<br />
mat.mult(left, left);<br />
mat.mult(dir, dir);<br />
<br />
+        if (firstPersonConstraint &amp;&amp; up.getY() &lt; 0) {<br />
+            return;<br />
+        }<br />
+<br />
Quaternion q = new Quaternion();<br />
q.fromAxes(left, up, dir);<br />
q.normalizeLocal();<br />
@@ -284,7 +300,7 @@<br />
cam.setAxes(q);<br />
}<br />
<br />
-    protected void zoomCamera(float value){<br />
+    protected void zoomCamera(float value) {<br />
// derive fovY value<br />
float h = cam.getFrustumTop();<br />
float w = cam.getFrustumRight();<br />
@@ -296,7 +312,7 @@<br />
/ (FastMath.DEG_TO_RAD * .5f);<br />
fovY += value * 0.1f;<br />
<br />
-        h = FastMath.tan( fovY * FastMath.DEG_TO_RAD * .5f) * near;<br />
+        h = FastMath.tan(fovY * FastMath.DEG_TO_RAD * .5f) * near;<br />
w = h * aspect;<br />
<br />
cam.setFrustumTop(h);<br />
@@ -305,76 +321,79 @@<br />
cam.setFrustumRight(w);<br />
}<br />
<br />
-    protected void riseCamera(float value){<br />
+    protected void riseCamera(float value) {<br />
Vector3f vel = new Vector3f(0, value * moveSpeed, 0);<br />
Vector3f pos = cam.getLocation().clone();<br />
<br />
-        if (motionAllowed != null)<br />
+        if (motionAllowed != null) {<br />
motionAllowed.checkMotionAllowed(pos, vel);<br />
-        else<br />
+        } else {<br />
pos.addLocal(vel);<br />
+        }<br />
<br />
cam.setLocation(pos);<br />
}<br />
<br />
-    protected void moveCamera(float value, boolean sideways){<br />
+    protected void moveCamera(float value, boolean sideways) {<br />
Vector3f vel = new Vector3f();<br />
Vector3f pos = cam.getLocation().clone();<br />
<br />
-        if (sideways){<br />
+        if (sideways) {<br />
cam.getLeft(vel);<br />
-        }else{<br />
+        } else {<br />
cam.getDirection(vel);<br />
}<br />
vel.multLocal(value * moveSpeed);<br />
<br />
-        if (motionAllowed != null)<br />
+        if (motionAllowed != null) {<br />
motionAllowed.checkMotionAllowed(pos, vel);<br />
-        else<br />
+        } else {<br />
pos.addLocal(vel);<br />
+        }<br />
<br />
cam.setLocation(pos);<br />
}<br />
<br />
public void onAnalog(String name, float value, float tpf) {<br />
-        if (!enabled)<br />
+        if (!enabled) {<br />
return;<br />
+        }<br />
<br />
-        if (name.equals(&quot;FLYCAM_Left&quot;)){<br />
+        if (name.equals(&quot;FLYCAM_Left&quot;)) {<br />
rotateCamera(value, initialUpVec);<br />
-        }else if (name.equals(&quot;FLYCAM_Right&quot;)){<br />
+        } else if (name.equals(&quot;FLYCAM_Right&quot;)) {<br />
rotateCamera(-value, initialUpVec);<br />
-        }else if (name.equals(&quot;FLYCAM_Up&quot;)){<br />
+        } else if (name.equals(&quot;FLYCAM_Up&quot;)) {<br />
rotateCamera(-value, cam.getLeft());<br />
-        }else if (name.equals(&quot;FLYCAM_Down&quot;)){<br />
+        } else if (name.equals(&quot;FLYCAM_Down&quot;)) {<br />
rotateCamera(value, cam.getLeft());<br />
-        }else if (name.equals(&quot;FLYCAM_Forward&quot;)){<br />
+        } else if (name.equals(&quot;FLYCAM_Forward&quot;)) {<br />
moveCamera(value, false);<br />
-        }else if (name.equals(&quot;FLYCAM_Backward&quot;)){<br />
+        } else if (name.equals(&quot;FLYCAM_Backward&quot;)) {<br />
moveCamera(-value, false);<br />
-        }else if (name.equals(&quot;FLYCAM_StrafeLeft&quot;)){<br />
+        } else if (name.equals(&quot;FLYCAM_StrafeLeft&quot;)) {<br />
moveCamera(value, true);<br />
-        }else if (name.equals(&quot;FLYCAM_StrafeRight&quot;)){<br />
+        } else if (name.equals(&quot;FLYCAM_StrafeRight&quot;)) {<br />
moveCamera(-value, true);<br />
-        }else if (name.equals(&quot;FLYCAM_Rise&quot;)){<br />
+        } else if (name.equals(&quot;FLYCAM_Rise&quot;)) {<br />
riseCamera(value);<br />
-        }else if (name.equals(&quot;FLYCAM_Lower&quot;)){<br />
+        } else if (name.equals(&quot;FLYCAM_Lower&quot;)) {<br />
riseCamera(-value);<br />
-        }else if (name.equals(&quot;FLYCAM_ZoomIn&quot;)){<br />
+        } else if (name.equals(&quot;FLYCAM_ZoomIn&quot;)) {<br />
zoomCamera(value);<br />
-        }else if (name.equals(&quot;FLYCAM_ZoomOut&quot;)){<br />
+        } else if (name.equals(&quot;FLYCAM_ZoomOut&quot;)) {<br />
zoomCamera(-value);<br />
}<br />
}<br />
<br />
public void onAction(String name, boolean value, float tpf) {<br />
-        if (!enabled)<br />
+        if (!enabled) {<br />
return;<br />
+        }<br />
<br />
-        if (name.equals(&quot;FLYCAM_RotateDrag&quot;) &amp;&amp; dragToRotate){<br />
+        if (name.equals(&quot;FLYCAM_RotateDrag&quot;) &amp;&amp; dragToRotate) {<br />
canRotate = value;<br />
inputManager.setCursorVisible(!value);<br />
}<br />
}<br />
-<br />
}<br />
[/patch]<br />
<br />
Added [java]flyCam.setConstraint(true)[/java] and [java]walkDirection.setY(0).normalizeLocal();[/java] to prevent the player from "flying"<br />
<br />
HelloCollision.java<br />
[patch]<br />
# This patch file was generated by NetBeans IDE<br />
# It uses platform neutral UTF-8 encoding and n newlines.<br />
--- Base (BASE)<br />
+++ Locally Modified (Based On LOCAL)<br />
@@ -1,5 +1,5 @@<br />
/*<br />
- * Copyright (c) 2009-2010 jMonkeyEngine<br />
+ * Copyright (c) 2009-2012 jMonkeyEngine<br />
* All rights reserved.<br />
*<br />
* Redistribution and use in source and binary forms, with or without<br />
@@ -29,7 +29,6 @@<br />
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS<br />
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.<br />
*/<br />
-<br />
package jme3test.helloworld;<br />
<br />
import com.jme3.app.SimpleApplication;<br />
@@ -71,6 +70,9 @@<br />
}<br />
<br />
public void simpleInitApp() {<br />
+<br />
+        flyCam.setConstraint(true);<br />
+<br />
/** Set up Physics */<br />
bulletAppState = new BulletAppState();<br />
stateManager.attach(bulletAppState);<br />
@@ -144,13 +146,29 @@<br />
* We do not walk yet, we just keep track of the direction the user pressed. */<br />
public void onAction(String binding, boolean value, float tpf) {<br />
if (binding.equals(&quot;Left&quot;)) {<br />
-      if (value) { left = true; } else { left = false; }<br />
+            if (value) {<br />
+                left = true;<br />
+            } else {<br />
+                left = false;<br />
+            }<br />
} else if (binding.equals(&quot;Right&quot;)) {<br />
-      if (value) { right = true; } else { right = false; }<br />
+            if (value) {<br />
+                right = true;<br />
+            } else {<br />
+                right = false;<br />
+            }<br />
} else if (binding.equals(&quot;Up&quot;)) {<br />
-      if (value) { up = true; } else { up = false; }<br />
+            if (value) {<br />
+                up = true;<br />
+            } else {<br />
+                up = false;<br />
+            }<br />
} else if (binding.equals(&quot;Down&quot;)) {<br />
-      if (value) { down = true; } else { down = false; }<br />
+            if (value) {<br />
+                down = true;<br />
+            } else {<br />
+                down = false;<br />
+            }<br />
} else if (binding.equals(&quot;Jump&quot;)) {<br />
player.jump();<br />
}<br />
@@ -167,11 +185,22 @@<br />
public void simpleUpdate(float tpf) {<br />
Vector3f camDir = cam.getDirection().clone().multLocal(0.6f);<br />
Vector3f camLeft = cam.getLeft().clone().multLocal(0.4f);<br />
+<br />
walkDirection.set(0, 0, 0);<br />
-    if (left)  { walkDirection.addLocal(camLeft); }<br />
-    if (right) { walkDirection.addLocal(camLeft.negate()); }<br />
-    if (up)    { walkDirection.addLocal(camDir); }<br />
-    if (down)  { walkDirection.addLocal(camDir.negate()); }<br />
+        if (left) {<br />
+            walkDirection.addLocal(camLeft);<br />
+        }<br />
+        if (right) {<br />
+            walkDirection.addLocal(camLeft.negate());<br />
+        }<br />
+        if (up) {<br />
+            walkDirection.addLocal(camDir);<br />
+        }<br />
+        if (down) {<br />
+            walkDirection.addLocal(camDir.negate());<br />
+        }<br />
+<br />
+        walkDirection.setY(0).normalizeLocal();<br />
player.setWalkDirection(walkDirection);<br />
cam.setLocation(player.getPhysicsLocation());<br />
}<br />
<br />

I don’t have time to find the real changes among the formatting changes. Maybe I’ll have time later.

yh it seems no one ALT+SHIFT+F it :P. The things i changed were:



[java]protected boolean firstPersonConstraint = false; //everything else was protected so just did it to be consistent



/*

  • @param firstPersonConstraint True to constraint along X axis of view

    */

    public void setConstraint(boolean firstPersonConstraint) {

    this.firstPersonConstraint = firstPersonConstraint;

    }



    /**
  • @return If constrained rotatation is enabled.

    *
  • @see FlyByCamera#setConstraint(boolean)

    */

    public boolean isConstrained() {

    return firstPersonConstraint;

    }



    [/java]



    And then inside rotateCamera(); i added



    [java]if (firstPersonConstraint && up.getY() < 0) {

    return;

    }[/java]



    before the quaternion was applied to the camera to make it move

I think the weird part of that solution is that if you are moving really fast then it will stop you sooner than if you are moving slow. I suspect that will feel really weird to some folks.

@zarch said:

If happy with it submit improved code back to JME as ConstrainedFlyByCamera. :smiley:

hi :slight_smile: i never could find anyone who did this. and i really needed it for my poject, so i made it! and i hope you dont mind but im using your name idea :slight_smile: i mentioned you in the post:
http://hub.jmonkeyengine.org/forum/topic/constrainedflybycamera/

check it out if you want

and thanks for the name suggestion :slight_smile:

1 Like