Hi
I want to fake multiple spaces/scenes by putting mob entities in one scene super far apart from mob entities in other scenes in the Y direction in @pspeed 's SimEtheral library.
To do so I added this in to update method in ZoneNetworkSystem
:
// A lot of times you can fake multiple spaces just by putting everyone super
// far apart in some standard direction (y is common).
// Then you could achieve multiple “spaces” by setting the y values to spaceId * 1000 or whatever.
// Then the normal zone filtering will make sure clients only see their ‘space’.
pos.y += (body.getSceneId().getId() * 1000);
the whole class in case:
/**
* A game system that registers a listener with the physics system and then
* forwards those events to the SimEtheral zone manager, which in turn will
* package them up for the clients in an efficient way.
*
* @author Paul Speed
*/
public class ZoneNetworkSystem extends AbstractGameSystem {
static Logger log = LoggerFactory.getLogger(ZoneNetworkSystem.class);
private ZoneManager zones;
private PhysicsObserver physicsObserver = new PhysicsObserver();
public ZoneNetworkSystem(ZoneManager zones) {
this.zones = zones;
}
@Override
protected void initialize() {
getSystem(PhysicsSystem.class).addPhysicsObjectListener(physicsObserver);
}
@Override
protected void terminate() {
getSystem(PhysicsSystem.class).removePhysicsObjectListener(physicsObserver);
}
/**
* Listens for changes in the physics objects and sends them to the zone
* manager.
*/
private class PhysicsObserver implements PhysicsObjectListener {
private Vector3f posf = new Vector3f();
private Quaternion orientf = new Quaternion();
private Vec3d pos = new Vec3d();
private Quatd orient = new Quatd();
// We probably won't have many zones, if we even have more than one.
// The physics objects do not provide any sort of accurate bounds so
// we'll guess at a size that is "big enough" for any particular mobile
// object. 2x2x2 meters should be good enough... until it isn't.
private AaBBox box = new AaBBox(1);
@Override
public void startFrame(SimTime time) {
zones.beginUpdate(time.getTime());
}
@Override
public void endFrame() {
zones.endUpdate();
}
@Override
public void added(EntityPhysicsObject object) {
// Don't really care about this
}
@Override
public void updated(EntityPhysicsObject object) {
if (object instanceof EntityRigidBody && ((EntityRigidBody) object).getMass() != 0) {
EntityRigidBody body = (EntityRigidBody) object;
// Grab the latest reference frame in our temp variables
body.getPhysicsLocation(posf);
body.getPhysicsRotation(orientf);
// Convert them to mathd values
pos.set(posf);
orient.set(orientf);
if( log.isTraceEnabled() ) {
log.trace("body:" + object.getEntityId() + " pos:" + pos);
}
// A lot of times you can fake multiple spaces just by putting everyone super
// far apart in some standard direction (y is common).
// Then you could achieve multiple “spaces” by setting the y values to spaceId * 1000 or whatever.
// Then the normal zone filtering will make sure clients only see their ‘space’.
pos.y += (body.getSceneId().getId() * 1000);
// Update the bounds so other things know
// where the object is for real
//AaBBox bounds = body.getBounds();
//bounds.setCenter(pos);
// Move the box as appropriate
// Note: we don't so much care about bounds as there won't be many zones.
// So we set it rather arbitrarily to 'big enough'.
box.setCenter(pos);
zones.updateEntity(body.getEntityId().getId(), true, pos, orient, box);
}
}
@Override
public void removed(EntityPhysicsObject object) {
zones.remove(object.getEntityId().getId());
}
}
}
and added this at ModelViewState.updateSpatial()
method :
// Transfer location from SimEtheral zone to client view.
loc.y -= (sceneId * 1000);
whole method in case:
public void updateSpatial(float tpf) {
// Grab a consistent time for this frame
long time = timeState.getTime();
// 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);
// Transfer location from SimEtheral zone to client view.
loc.y -= (sceneId * 1000);
spatial.setLocalTranslation(loc);
spatial.setLocalRotation(rotation);
setVisible(trans.getVisibility(time));
}
but after this change I am getting a jittering at entity’s Y location at client side.
here are some debug output from model position at client side before and after change:
Before:
loc.y = 1.5412678
loc.y = 1.5412679
loc.y = 1.5412678
loc.y = 1.5412679
loc.y = 1.5412679
loc.y = 1.5412679
loc.y = 1.5412679
loc.y = 1.5412679
loc.y = 1.5412679
loc.y = 1.5412679
loc.y = 1.5412679
loc.y = 1.5412679
loc.y = 1.5412679
loc.y = 1.541268
loc.y = 1.5412679
After :
loc.y = 1.53125
loc.y = 1.53125
loc.y = 1.53125
loc.y = 1.53125
loc.y = 1.53125
loc.y = 1.53125
loc.y = 1.5
loc.y = 1.53125
loc.y = 1.53125
loc.y = 1.53125
loc.y = 1.53125
loc.y = 1.53125
loc.y = 1.53125
loc.y = 1.5
loc.y = 1.53125
loc.y = 1.53125
loc.y = 1.5
loc.y = 1.53125
loc.y = 1.5
loc.y = 1.53125
loc.y = 1.5625
loc.y = 1.5625
loc.y = 1.53125
loc.y = 1.5625
loc.y = 1.53125
loc.y = 1.53125
loc.y = 1.5625
loc.y = 1.53125
loc.y = 1.53125
loc.y = 1.53125
loc.y = 1.5
loc.y = 1.53125
loc.y = 1.53125
loc.y = 1.5625
loc.y = 1.53125
It is variant from 1.50 ~ 1.56 in Y location at client side.
Note, the entity position which is published from ZoneNetworkSystem at server side is a fixed value (pos.y = 1.5409740209579468) and does not change over time, so not a problem with server-side physics system
I am curious to know why this happens and how can I fix it.
Any help is appreciated