Simsilica / SimMath

A double-based math package similar to JME's float-based math classes.
BSD 3-Clause "New" or "Revised" License
7 stars 4 forks source link

NullPointerException at PositionTransition.getFrameVelocity #1

Closed Ali-RS closed 5 years ago

Ali-RS commented 5 years ago
java.lang.NullPointerException
    at com.simsilica.mathd.trans.PositionTransition.getFrameVelocity(PositionTransition.java:121) ~[sim-math-1.2.0.jar:?]
    at com.otm.app.state.view.ModelViewState$Mob.updateSpatial(ModelViewState.java:356) ~[main/:?]
    at com.otm.app.state.view.ModelViewState.update(ModelViewState.java:180) ~[main/:?]
    at com.jme3.app.state.AppStateManager.update(AppStateManager.java:303) ~[jme3-core-3.3.0-SNAPSHOT.jar:3.3-6716]
    at com.jme3.app.SimpleApplication.update(SimpleApplication.java:253) ~[jme3-core-3.3.0-SNAPSHOT.jar:3.3-6716]
    at com.jme3.system.lwjgl.LwjglWindow.runLoop(LwjglWindow.java:499) ~[jme3-lwjgl3-3.3.0-SNAPSHOT.jar:3.3-6703]
    at com.jme3.system.lwjgl.LwjglWindow.run(LwjglWindow.java:581) ~[jme3-lwjgl3-3.3.0-SNAPSHOT.jar:3.3-6703]
    at com.jme3.system.lwjgl.LwjglWindow.create(LwjglWindow.java:423) ~[jme3-lwjgl3-3.3.0-SNAPSHOT.jar:3.3-6703]
    at com.jme3.app.LegacyApplication.start(LegacyApplication.java:463) ~[jme3-core-3.3.0-SNAPSHOT.jar:3.3-6716]
    at com.jme3.app.LegacyApplication.start(LegacyApplication.java:424) ~[jme3-core-3.3.0-SNAPSHOT.jar:3.3-6716]
    at com.jme3.app.SimpleApplication.start(SimpleApplication.java:125) ~[jme3-core-3.3.0-SNAPSHOT.jar:3.3-6716]
    at com.overthemoon.main.Main.main(Main.java:123) ~[main/:?]

happens in updateSpatial method in ModelViewstate


public void updateSpatial(long time) {

            // Look back in the brief history that we've kept and
            // pull an interpolated value.  To do this, we grab the
            // span of time that contains the time we want.  PositionTransition
            // represents a starting and an ending pos+rot over a span of time.
            PositionTransition trans = buffer.getTransition(time, true);
            if (trans != null) {
                Vector3f loc = trans.getPosition(time, true);
                Quaternion rotation = trans.getRotation(time, true);

                // TODO: Transfer location from SimEtheral zone to client view (root node)
                // loc.y -= (sceneId * 1000);

                spatial.setLocalTranslation(loc);
                spatial.setLocalRotation(rotation);
                setVisible(trans.getVisibility(time));

                // Update MobPositionAdapter
                mpa.location.set(loc);
                mpa.rotation.set(rotation);

                // Extrapolate the real velocity using tpf
                float tpf = (trans.getEndTime() - trans.getStartTime()) / 1000000000.0f; // in second
                mpa.velocity.set(trans.getFrameVelocity()).divideLocal(tpf);

                System.out.println("MobVelocity "+ entity + ": " + mpa.velocity);
            }
        }

I can work around it by adding a check

if (trans.getStartTime() > 0)

@pspeed42 should PositionTransition take care of it internally ?

pspeed42 commented 5 years ago

I'm thinking PositionTransition maybe shouldn't even have this method on it... else it needs to be much more complicated to deal with whether the caller wants to clamp or just return null, etc..

Not sure anymore what velocity is being used for in this case but it would have been easy enough for this code to calculate it from what it had.

pspeed42 commented 5 years ago

Also the name itself is not accurate since the time has to be inverted for it to even count as a velocity. At best it's a frame delta unless we build the time calculation into the call.

pspeed42 commented 5 years ago

Oh... this is your code. Are you using it for Mob animation? If so you may want to use the amount the spatial has actually moved instead. Hard to say. (It's what I do but I know there will be occasional glitches with either approach.)

Ali-RS commented 5 years ago

Yep, it's my code. and yes I am using it for MobAnimationState and I am using MobPositionAdapter as a way to let my tweens to have access to entity's velocity.

Based on your comment and because my game is networked game I thought to use PositionTransition which should solve this problem out of the box.

// Because we aren't interpolating over known good physics frames
// like we would in a network app, we have the possibility of seeing
// the same position in two visual frames even if the object is moving.

If so you may want to use the amount the spatial has actually moved instead. Hard to say. (It's what I do but I know there will be occasional glitches with either approach.)

Okay I will use Spatial to calculate velocity just like you did in MobAnimationState.

pspeed42 commented 5 years ago

I mean, it solves one problem but presents another... you might be getting the interpolated position at the very beginning or very end of a network frame. It's not at all clear to me that the velocity of that network frame should apply equally to the animation speed over the whole frame. But maybe that's just my paranoia.

In the end, you will want some kind of speed smoothing anyway. I don't remember exactly what I put that comment so I don't know if it's related to the low pass filtering or not.

pspeed42 commented 5 years ago

Actually, that comment seems only related to non PositionTransition code where we only see discrete jumps in position since we aren't interpolating. It's unrelated to when spatials are sampled and more about catching two visual frames before a new physics frame.

In a network app or even in a non-network app properly using PositionTransition, it's not an issue.

Ali-RS commented 5 years ago

Yep, it wont be an issue for me because my spatials are already getting interpolated with PositionTransition. Actually that getFrameVelocity() tricked me and I thought it's just easy to get from there instead of calculation it from spatial in visual frame.

I am going to base it on spatial data as you said.

So I think I can close this.

Ali-RS commented 5 years ago

@pspeed42 in case you want you can reopen this if you think that NullPointerException should be handled or getFrameVelocity() should be removed in PositionTransition .

pspeed42 commented 5 years ago

I may just remove the method or rename it. I think it's probably not used... I'm checking my own code.