Cam.getDirection() not working for setting shooting direction

I’ve been playing around with the tutorials a little. Lately I attempted to add the ball shooting from Hello Physics to the Hello Collision tutorial. I’m trying to use cam.getDirection() to set the direction that the balls shoot in. It works over a certain arc (usually about 135 degrees of the full 360), but after that it’s as though the “gun” hits a wall and won’t rotate further. The “player” will continue turning, but the balls keep shooting in the same direction where the gun rotation stopped. If you rotate your view direction far enough, the balls will be firing to your rear. I don’t understand why the walk direction gets properly set using the same camera method, but the ball direction is not working. I’ve included what should be the relevant section of code. I’ve tried processing the “shoot” action from both the listener and in the update loop with very similar results. Anyone have any ideas what could be causing this? Hopefully I explained what’s happening well enough…

[java]

/**

  • These are our custom actions triggered by key presses. We do not walk
  • yet, we just keep track of the direction the user pressed.

    */

    public void onAction(String binding, boolean value, float tpf)

    {

    if ( binding.equals("Lefts") )

    {

    left = value;

    }

    else if ( binding.equals("Rights") )

    {

    right = value;

    }

    else if ( binding.equals("Ups") )

    {

    up = value;

    }

    else if ( binding.equals("Downs") )

    {

    down = value;

    }

    else if ( binding.equals("Jumps") )

    {

    player.jump();

    }

    else if (binding.equals("Shoot") )

    {

    shoot = value;

    }

    }





    /**
  • This method creates one individual physical cannon ball. By default, the
  • ball is accelerated and flies from the camera position in the camera
  • direction.

    /

    public void makeCannonBall()

    {

    /
    * Create a cannon ball geometry and attach to scene graph. /

    Geometry ball_geo = new Geometry("cannon ball", sphere);

    ball_geo.setMaterial(stone_mat);

    rootNode.attachChild(ball_geo);

    /
    * Position the cannon ball and activate shadows /

    ball_geo.setLocalTranslation(player.getPhysicsLocation());

    ball_geo.setShadowMode(ShadowMode.CastAndReceive);

    /
    * Make the ball physcial with a mass > 0.0f /

    ball_phy = new RigidBodyControl(5f);

    /
    * Add physical ball to physics space. */

    ball_geo.addControl(ball_phy);

    bulletAppState.getPhysicsSpace().add(ball_phy);

    }







    /**
  • This is the main event loop–walking happens here. We check in which
  • direction the player is walking by interpreting the camera direction
  • forward (camDir) and to the side (camLeft). The setWalkDirection()
  • command is what lets a physics-controlled player walk. We also make sure
  • here that the camera moves with player.

    */

    @Override

    public void simpleUpdate(float tpf)

    {

    Vector3f camDir = cam.getDirection().clone().multLocal(2.3f);

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

    walkDirection.set(0, 0, 0);



    if ( left )

    {

    walkDirection.addLocal(camLeft);

    }



    if ( right )

    {

    walkDirection.addLocal(camLeft.negate());

    }



    if ( up )

    {

    walkDirection.addLocal(camDir);

    }



    if ( down )

    {

    walkDirection.addLocal(camDir.negate());

    }



    if ( shoot )

    {

    audioRenderer.playSource(audio_gun); // play once!

    makeCannonBall();

    ball_phy.setLinearVelocity(cam.getDirection().mult(75));

    shoot = false;

    }



    player.setWalkDirection(walkDirection);

    cam.setLocation(player.getPhysicsLocation());

    }

    [/java]

Look at the PhysicsTestHelper class, it also creates such a shooter for multiple tests and it works fine in all of them, so its a problem with your code. Maybe you create a collision shape at some point that the ball bounces into. Maybe the ‘players’ collision shape?

Try changing cam.getDirection().mult(75) to cam.getDirection().clone().multLocal(75)



You’re probably changing the direction of the camera as well as the ball when you do your current call.



EDIT: Nevermind, on reading up about mult and multLocal, it appears what you have now should work fine. I dont know, but I’d bet it has something to do with that call. Try outputting debugging information around that call, such as what the camera’s direction vector is, and what the resultant ball’s direction vector is. I dont think that mult is doing what you want it to do.

No, mult() should return a new Vector3f. multLocal() would work on the direction vector…

mhhh do you use the chase cam?

it looks like a gimbal lock, but I don’t get why the cam would go on rotating…

normen said:
Look at the PhysicsTestHelper class, it also creates such a shooter for multiple tests and it works fine in all of them, so its a problem with your code. Maybe you create a collision shape at some point that the ball bounces into. Maybe the 'players' collision shape?


That actually sounds kind of like what I'm seeing. When I shoot within the arc where the ball goes straight out, the ball doesn't have any sidespin. But when I rotate so that the ball is shooting off to the side, it definitely has a sidespin that seems to get faster as I rotate further. Also, I noticed if I make the mass of the ball large, I can see the shooter's position get knocked slightly to the side as it shoots in that over-rotated position. Also, when the ball is coming out in a direction behind the camera's field of view, it comes out slow and , as though it has knocked into something that impeded it. The closer the ball direction gets to straight behind me, the slower it seems to come out (once I spin around to see it).

I've tried replacing some of my code with similar code from the PhysicsTestHelper, but no change as of yet. I also tried reducing the radius of the capsule collision shape of my player, but also no change except I seem to be able to shoot properly in about a 180 degree arc now. No luck getting it any better than that, though. I'm still puzzled as to why this doesn't work, though. I pulled most of the code straight out of the tutorials with only minor changes. I guess I'll have to keep working through it.

BTW, how does one use that physics test helper class? Is it as simple as just creating an app and calling the various static methods directly?
nehon said:
mhhh do you use the chase cam?
it looks like a gimbal lock, but I don't get why the cam would go on rotating...


I'm using the flycam. At least I assume that's what I'm using. In my simpleInitApp I have:

flyCam.setMoveSpeed(100);

Not sure that line is even necessary, but it's there.

What is gimbal lock?

The camera definitely rotates well. I can spin to my heart's content, move, etc, smooth as butter. Just can't shoot in certain directions.

Gimbal lock → http://en.wikipedia.org/wiki/Gimbal_lock



But it can’t be that if you use the flycam.



maybe look at the TestWalkingChar example, it does pretty much what you want to do

nehon said:
Gimbal lock -> http://en.wikipedia.org/wiki/Gimbal_lock

But it can't be that if you use the flycam.

maybe look at the TestWalkingChar example, it does pretty much what you want to do


Having read a little of that link, I don't think that's what I'm seeing. You've obviously already figured that out because I'm using the flycam, but maybe I wasn't very clear before about what's happening. Let me try to put it another way - perhaps a light will come on for someone reading. Currently I've got about a 180 degree firing arc (it got a little bigger when I reduced the radius of the CapsuleCollisionShape representing my player). In any case, let's say I'm facing straight north. I can rotate myself 360 degrees about the Z axis with no problem. I can fire the gun and have the ball track the line I'm facing as long as the direction I'm facing has any northerly vector to it. As soon as I hit a facing of straight east or west, the gun will stop rotating with me and keep aiming straight east or west if I keep shooting. It will continue shooting straight east or west as long as my facing has any southerly vector. If I spin back around to a northerly facing, the gun begins to track and fire in the direction I'm facing again. Additionally, the further south I face, the slower the ball seems to emerge. The emerging balls also begin to show a sidespin once I've got a southerly facing, sidespinning faster the further south I face. It's as though the ball glances off some invisible thing which sets it spinning, hitting harder if I'm facing more directly south. Whatever it's hitting imparts the sidespin and slows it down. At least that's my working theory. Could the ball be getting created all or partially inside the CapsuleCollisionShape? Maybe I'll try to figure out how to get the initial position of the ball out in front a little further. It's currently being created right at the cam location. Perhaps that's the problem.

Note that I cannot control which 180 degree arc I can shoot straight in. It's not simply north vs south - I just used those directions to illustrate. Usually the arc is the same from run to run, but sometimes it changes a little. I think it depends a little bit on where I am on the map. Hard to say, though. I think I'm going to start simplifying my code until I get down to a working program. Perhaps then I'll be able to figure out exactly what I'm doing that creates this problem.

Update: Problem solved! I just changed the spot where the ball was created like this:



Vector3f camLocation = app.getCamera().getLocation();

ball_geo.setLocalTranslation(app.getCamera().getDirection().scaleAdd(3, camLocation));



Ball shoots perfectly straight all the way around. Looks like normen had the problem pegged right off the bat. Thanks for the help!

2 Likes