[Solved] World3DModel setPosition(), setRotation(), moveto() do not show out while added to a player world?

  • Maybe, I miss something, but it seems to me that the World3DModel methods setRotation(), setPosition() and moveto() have an issue quite similar to the one described here and already solved (thanks again, @red51!).


    Simply put, if those methods are called after the model has been added to a player's world (player.addWorldElement(model);), they have no visible effects. But if, contextually or afterwards, the model is removed and re-added, the changes show up. Note that any of these code snippets work correctly and they all seem equivalent:


    Java
    model.setPosition(modelPos);
    model.setRotation(modelRot);
    player.removeWorldElement(model);
    player.addWorldElement(model);

    where first model properties are changed and then the model is removed and added back. OR:


    Java
    player.removeWorldElement(model);
    model.setPosition(modelPos);
    model.setRotation(modelRot);
    player.addWorldElement(model);

    where model properties are changed while the model is removed. And even:


    Code
    player.removeWorldElement(model);
    player.addWorldElement(model);
    model.setPosition(modelPos);
    model.setRotation(modelRot);

    where the model is removed and added back before changing its properties (which greatly surprises me :S , but probably the various operations are queued, rather than blocking).


    I have tried moving the model changes to a separate thread (one never knows...) but it seems to make no difference.


    Exemplifying moveto() is less easy, as the remove, change and add back need to be at different moments (to give moveto() time to go on), but it follows the same pattern.


    Note: I have only tried the Vector3f and Quaternion overloads of those methods, so I do not know if the overloads with separate values work differently, but I do not expect they do.


    Am I overlooking something or there is actually an issue?

  • UPDATE ABOUT moveto():


    More experiments with Model.moveto(). It turns out that, as described above, the following has no visible effect, i.e. the model remains in its position:

    Code
    Vector3f pos = model.getPosition();
    pos.y += (up ? +10 : -10);
    model.moveTo(pos, 0.01f);

    If however, later on, the model is removed from the player's world and added back, it appears in the correct, moved to, position. So, it seems an issue with the player context not updating its scene.


    With any of the following, the model jumps instantaneously at the final position (I have no idea of the scale of the speed parameter, but I assume 0.01 should be a rather slow speed):

    Code
    Vector3f pos = model.getPosition();
    pos.y += (up ? +10 : -10);
    player.removeWorldElement(model);
    player.addWorldElement(model);
    model.moveTo(pos, 0.01f);
    Code
    Vector3f pos = model.getPosition();
    pos.y += (up ? +10 : -10);
    player.removeWorldElement(model);
    model.moveTo(pos, 0.01f);
    player.addWorldElement(model);
    Code
    Vector3f pos = model.getPosition();
    pos.y += (up ? +10 : -10);
    model.moveTo(pos, 0.01f);
    player.removeWorldElement(model);
    player.addWorldElement(model);

    In practice, there seems no way to have a visible moveto() effect.


    In addition, while for Model.setPosition() and Model.setRotation(), the remove from world - add back trick seems to work, having to keep track of to how many players (and which ones) have been added each of the models and toggle each model off/on from each of its players for each model movement becomes rather inconvenient: shouldn't the API take case of this?


    Just FYI, I am trying to implement elevators, where a number of elevators are present, individually moving and visible to/usable by a variable number of players...

  • Unfortunately I wasn't able to look into this issue yet :| But I will finally do that within the next days.
    About the moveTo method: When removing the model before it arrived at the final destination, and then re-adding it, it will jump to the final destination instantly. Right now the moveTo() only happens clientside (so the server only see's the final destination). If it's necessary to have a exact position serverside, we will implement it of course :)

  • Unfortunately I wasn't able to look into this issue yet :| But I will finally do that within the next days.

    Thank you for your reply (and, yes, I knew I was kind of pushing, but this point is a show stopper for me at the moment).

    About the moveTo method: When removing the model before it arrived at the final destination, and then re-adding it, it will jump to the final destination instantly. Right now the moveTo() only happens clientside (so the server only see's the final destination)

    Ok, this explains the jump and makes sense. The question is that, unless I have overlooked something very obvious, I can have either the jump (with the remove-then-add-back trick) or no movement at all (with no 'tricks'), with nothing in between. I tried speeds 1, 0.1 and 0.01, hoping one of them would be in the right range to see some movement, but so far with no luck.

    If it's necessary to have a exact position serverside, we will implement it of course :)

    If this means that only the player originating the movement will see it, this might be a problem for a model visible to all players. As far as I can imagine things right now, a very precise movement sync across the different players is not necessary, but a general consistency among the various points of view might be important.


    An example can be doors: I do not think an opening door starts and ends rotating exactly at the same frame (or tick or whatever) for all the players looking at it, nor that it has exactly the same intermediate angle at any frame for all the players. Still, it seems that all the players see generally the same process generally at the same time (of course, network latency has a part in that, unavoidably).


    This is the kind of consistency which would be useful to have. Whether this can be achieved by broadcasting all the intermediate positions to all clients or just the moveto() parameters letting each client to interpolate by its own or in whichever other mean, you surely have more elements to decide that I do.


    As we are wishing, however, a detail which would be useful, is some sort of notification to let the plug-in know once the moveto() is over.


    Thanks!

  • The question is that, unless I have overlooked something very obvious, I can have either the jump (with the remove-then-add-back trick) or no movement at all (with no 'tricks'), with nothing in between

    If you want to move the element to the target position instantly, you can just use the "setPosition()" method, otherwise "moveTo()" for smooth movement. Apparently adding/removing the model to the client causes the issues you were having (I will look into this now). As a workaround, you may try to add a small delay to the moveTo() command (i.e. by using a timer), so add the element to the particular player, and trigger a timer to move it with a delay of 0.5 seconds, for example (just for testing purposes).


    As far as I can imagine things right now, a very precise movement sync across the different players is not necessary

    It's not even possible*, especially due to the network latency (a player with a ping of 10 ms will receive the "moveTo()" message much earlier than a player with a latency of 100 ms, or image a player suddenly has a lag which causes a delay of a few seconds), but also things like framerate are relevant (the movement itself is framerate-independent, but it affects the processing of network messages [if the client receives a moveTo message, it will be processed in the next tick, in order to keep it synchronized with the rendering]... so a player with 200 fps will start processing the moveTo() message quicker than a player who only has 5 fps).


    *Precision could be increased if the server keeps sending the current location of the model to the client, but this may cause a lot of traffic. I'm not sure if the result is worth it.


    This is the kind of consistency which would be useful to have

    Well, if the server calculates the moveTo() position as well, this wouldn't necessarily increase consistency (at least among different players), it would only be helpful if a plugin actually needs to now the exact position after calling the moveTo() method ;)

  • So finally I did some tests about that, unfortunately I wasn't able to reproduce the issue 8| I tested all scenarios, i.e. setting position/rotation before adding the model, setting position/rotation after adding the model, calling moveTo() before/after adding the model etc.


    Although I just tested it in singleplayer (and LAN). Do you run it in multiplayer eventually? I didn't test the behaviour when there is a latency between the server and the client.


    Otherwise I have no idea why it doesn't work on your side... only thing I noticed is that the speed in the moveTo Method is quite slow, so when providing 0.01, the element barely moves. I guess we may change that. But everything else worked as intended.


    Can you maybe provide a test-case or alternatively send me the code via PM?

  • Thanks for spending time on this, I appreciate. For moveto() speed I tried 1, 0.1 and 0.01 and there is no difference: no movement at all.


    I did all my tests in mulitplayer on a local dedicated server (as it is easier to set a debug session with it). I'll try in single player AND I'll provide a sample plug-in.

  • Hmmm... things are getting more and more "interesting"...


    I made a very simple, test plug-in and, indeed, everything works as advertised. In a slightly more complex one, however, I see no effect effect of Wordl3DModel.setPosition(), .setRotation() and .moveto(). I am still trying to understand where the difference is.

  • Oh my!!!


    I got it! The problem was that I supposed WorldElement.getPosition() returned a copy of the position vector and I used something like this:

    Code
    Vector3f pos = model.getPosition();
    pos.y += (up ? +10 : -10);
    model.moveTo(pos, 1.0f);


    But apparently the returned vector is a reference to the internal WorldElement position vector itself, so modifying it is not a good think! On the other hand, the following works correctly:


    Code
    Vector3f pos = model.getPosition();
    Vector3f newPos = new Vector3f(pos.x, pos.y + (up ? +10 : -10), pos.z);
    model.moveTo(newPos, 1.0f);

    (not the most efficient way, but the clearest, I think).


    I apologise for the time you have spent on this! I should have thought more beforehand, but I have been probably confused by the lack of something like the C++ const qualifier in Java...

Participate now!

Don’t have an account yet? Create a new account now and be part of our community!