Skip to content

Commit

Permalink
Lots of physics changes
Browse files Browse the repository at this point in the history
Still a lot of work is needed. But it's a start
  • Loading branch information
kitskub committed Sep 24, 2014
1 parent 011d9ab commit 1f665cc
Show file tree
Hide file tree
Showing 14 changed files with 239 additions and 201 deletions.
3 changes: 2 additions & 1 deletion src/main/java/com/flowpowered/api/entity/Physics.java
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
import com.flowpowered.api.util.thread.annotation.Threadsafe;
import org.spout.physics.body.RigidBody;
import org.spout.physics.collision.shape.CollisionShape;
import org.spout.physics.engine.DynamicsWorld;

/**
* Component that gives the owner the characteristics to be a part of a Scene. <p> A Scene consists of {@link Transform}s which represent the snapshot state, the live state, and the rendering state.
Expand All @@ -53,7 +54,7 @@ public Physics(Entity entity) {
* @return This component, for chaining
* @throws IllegalArgumentException If mass is < 0f or shape is null
*/
public abstract Physics activate(final float mass, final CollisionShape shape);
public abstract Physics activate(final float mass, final CollisionShape shape, DynamicsWorld sim);

/**
* Deactivates this {@link com.flowpowered.api.entity.Entity}, removing it from the physics space
Expand Down
3 changes: 0 additions & 3 deletions src/main/java/com/flowpowered/api/geo/cuboid/Region.java
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@
import com.flowpowered.api.geo.World;
import com.flowpowered.api.geo.discrete.Point;
import com.flowpowered.api.util.UnloadSavable;
import org.spout.physics.engine.DynamicsWorld;

/**
* Represents a cube containing 16x16x16 Chunks (256x256x256 Blocks)
Expand Down Expand Up @@ -163,8 +162,6 @@ public boolean containsChunk(int x, int y, int z) {

public abstract List<Player> getPlayers();

public abstract DynamicsWorld getDynamicsWorld();

public Engine getEngine() {
return engine;
}
Expand Down
23 changes: 23 additions & 0 deletions src/main/java/com/flowpowered/api/geo/discrete/Point.java
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
import java.io.IOException;
import java.io.Serializable;
import java.lang.reflect.Field;
import java.util.Objects;

import com.flowpowered.api.geo.LoadOption;
import com.flowpowered.api.geo.World;
Expand Down Expand Up @@ -155,4 +156,26 @@ private static Field getWorldField() {
}
return field;
}

@Override
public int hashCode() {
int hash = 5;
hash = 83 * hash + Objects.hashCode(this.world);
hash = 83 * hash + Objects.hashCode(this.vector);
return hash;
}

@Override
public boolean equals(Object obj) {
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
final Point other = (Point) obj;
if (!Objects.equals(this.world, other.world))
return false;
if (!Objects.equals(this.vector, other.vector))
return false;
return true;
}
}
15 changes: 8 additions & 7 deletions src/main/java/com/flowpowered/engine/entity/FlowEntity.java
Original file line number Diff line number Diff line change
Expand Up @@ -39,14 +39,15 @@
import com.flowpowered.api.geo.reference.WorldReference;
import com.flowpowered.engine.geo.chunk.FlowChunk;
import com.flowpowered.engine.geo.region.FlowRegion;
import com.flowpowered.engine.geo.world.FlowWorld;

public class FlowEntity extends BaseComponentOwner implements Entity {
private final int id;
private final FlowPhysics physics;

private final EntityObserver observer;

public FlowEntity(Engine engine, int id, Transform transform) {
protected FlowEntity(Engine engine, int id, Transform transform) {
super(engine);
this.id = id;
this.physics = new FlowPhysics(this);
Expand Down Expand Up @@ -115,14 +116,14 @@ public WorldReference getWorld() {
}

void finalizeRun() {
FlowRegion regionLive = getRegion();
FlowRegion regionSnapshot = (FlowRegion) physics.getSnapshottedTransform().getPosition().getRegion(LoadOption.LOAD_GEN, getEngine().getWorldManager());
FlowWorld worldLive = (FlowWorld) getWorld().get();
FlowWorld worldSnapshot = (FlowWorld) physics.getSnapshottedTransform().getPosition().getWorld().get();
//Move entity from Region A to Region B
if (regionSnapshot != regionLive) {
regionSnapshot.getEntityManager().removeEntity(this);
if (worldSnapshot != worldLive) {
worldSnapshot.getEntityManager().removeEntity(this);
//Add entity to Region B
regionLive.getEntityManager().addEntity(this);
physics.crossInto(regionSnapshot, regionLive);
worldLive.getEntityManager().addEntity(this);
physics.crossInto(worldSnapshot, worldLive);
}

observer.update();
Expand Down
25 changes: 13 additions & 12 deletions src/main/java/com/flowpowered/engine/entity/FlowPhysics.java
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,13 @@
import com.flowpowered.api.geo.discrete.Point;
import com.flowpowered.api.geo.discrete.Transform;
import com.flowpowered.api.geo.reference.WorldReference;
import com.flowpowered.engine.geo.region.FlowRegion;
import com.flowpowered.engine.geo.world.FlowWorld;
import com.flowpowered.engine.util.math.ReactConverter;
import com.flowpowered.math.imaginary.Quaternionf;
import com.flowpowered.math.vector.Vector3f;
import org.spout.physics.body.RigidBody;
import org.spout.physics.collision.shape.CollisionShape;
import org.spout.physics.engine.DynamicsWorld;
import org.spout.physics.engine.Material;
import org.spout.physics.math.Quaternion;

Expand All @@ -44,8 +45,8 @@
*/
public class FlowPhysics extends Physics {
//Flow
private AtomicReference<Transform> snapshot = new AtomicReference<>(Transform.INVALID);
private AtomicReference<Transform> live = new AtomicReference<>(Transform.INVALID);
private final AtomicReference<Transform> snapshot = new AtomicReference<>(Transform.INVALID);
private final AtomicReference<Transform> live = new AtomicReference<>(Transform.INVALID);
//React
private RigidBody body;
private boolean activated = false;
Expand All @@ -55,33 +56,33 @@ public FlowPhysics(Entity entity) {
}

@Override
public FlowPhysics activate(final float mass, final CollisionShape shape) {
public FlowPhysics activate(final float mass, final CollisionShape shape, DynamicsWorld sim) {
if (mass < 1f) {
throw new IllegalArgumentException("Cannot activate physics with mass less than 1f");
}
if (shape == null) {
throw new IllegalArgumentException("Cannot activate physics with a null shape");
}
deactivate();
FlowRegion to = (FlowRegion) entity.getRegion();
Transform transform = live.get();
body = to.getDynamicsWorld().createRigidBody(new org.spout.physics.math.Transform(ReactConverter.toReactVector3(transform.getPosition().getVector()), new Quaternion(0, 0, 0, 1)), mass, shape);
body = sim.createRigidBody(new org.spout.physics.math.Transform(ReactConverter.toReactVector3(transform.getPosition().getVector()), new Quaternion(0, 0, 0, 1)), mass, shape);
body.setMaterial(new Material());
activated = true;
return this;
}

public void crossInto(final FlowRegion from, final FlowRegion to) {
public void crossInto(final FlowWorld from, final FlowWorld to) {
if (entity != null && from != null && body != null) {
from.getDynamicsWorld().destroyRigidBody(body);
body = to.getDynamicsWorld().createRigidBody(body.getTransform(), body.getMass(), body.getCollisionShape());
from.getPhysicsManager().queuePreUpdateTask((w) -> w.destroyRigidBody(body));
body = to.getPhysicsManager().getSimulation().createRigidBody(body.getTransform(), body.getMass(), body.getCollisionShape());
}
}

@Override
public void deactivate() {
if (entity != null && entity.getRegion() != null && body != null) {
entity.getRegion().getDynamicsWorld().destroyRigidBody(body);
FlowWorld world =(FlowWorld) entity.getWorld().get();
if (world != null && body != null) {
world.getPhysicsManager().queuePreUpdateTask((w) -> w.destroyRigidBody(body));
}
body = null;
activated = false;
Expand Down Expand Up @@ -278,7 +279,7 @@ public void onPrePhysicsTick() {
/**
* Called after the simulation was polled for an update. <p> This updates Flow's live with the transform of the body. The render transform is updated with interpolation from the body </p>
*/
public void onPostPhysicsTick(float dt) {
public void onPostPhysicsTick() {
if (body == null) {
return;
}
Expand Down
19 changes: 19 additions & 0 deletions src/main/java/com/flowpowered/engine/geo/chunk/FlowChunk.java
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,17 @@
import com.flowpowered.engine.geo.FlowBlock;
import com.flowpowered.engine.geo.region.FlowRegion;
import com.flowpowered.engine.geo.snapshot.FlowChunkSnapshot;
import com.flowpowered.engine.geo.world.FlowWorld;
import com.flowpowered.engine.util.math.ReactConverter;
import com.flowpowered.events.Cause;
import com.flowpowered.math.GenericMath;
import com.flowpowered.math.vector.Vector3f;
import gnu.trove.map.hash.TShortObjectHashMap;
import org.spout.physics.body.RigidBody;
import org.spout.physics.collision.shape.BoxShape;
import org.spout.physics.math.Quaternion;
import org.spout.physics.math.Transform;
import org.spout.physics.math.Vector3;

public class FlowChunk extends Chunk {

Expand Down Expand Up @@ -71,6 +78,18 @@ public FlowChunk(FlowRegion region, int x, int y, int z, int generationIndex, At
this.blockStore = blockStore;
this.snapshot = new FlowChunkSnapshot(region.getSnapshot(), getPosition().toInt());
this.snapshot.update(this);

// TEST CODE
if (y < 0) {
((FlowWorld) region.getWorld().get()).getPhysicsManager().queuePreUpdateTask((w) -> {
RigidBody b = w.createRigidBody(
new Transform(ReactConverter.toReactVector3(getBlockX(), getBlockY(), getBlockZ()), Quaternion.identity()),
1f,
new BoxShape(new Vector3(8f, 8f, 8f))
);
b.enableMotion(false);
});
}
}

@Override
Expand Down
69 changes: 3 additions & 66 deletions src/main/java/com/flowpowered/engine/geo/region/FlowRegion.java
Original file line number Diff line number Diff line change
Expand Up @@ -45,23 +45,18 @@
import com.flowpowered.engine.entity.EntityManager;
import com.flowpowered.engine.entity.FlowEntity;
import com.flowpowered.engine.entity.FlowEntitySnapshot;
import com.flowpowered.engine.entity.FlowPhysics;
import com.flowpowered.engine.filesystem.ChunkDataForRegion;
import com.flowpowered.engine.filesystem.ChunkFiles;
import com.flowpowered.engine.geo.FlowBlock;
import com.flowpowered.engine.geo.chunk.FlowChunk;
import com.flowpowered.engine.geo.snapshot.FlowRegionSnapshot;
import com.flowpowered.engine.geo.world.FlowServerWorld;
import com.flowpowered.engine.geo.world.FlowWorld;
import com.flowpowered.engine.physics.FlowLinkedWorldInfo;
import com.flowpowered.engine.util.math.ReactConverter;
import com.flowpowered.engine.scheduler.WorldTickStage;
import com.flowpowered.events.Cause;
import com.flowpowered.math.GenericMath;
import com.flowpowered.math.vector.Vector3f;
import org.apache.logging.log4j.Level;
import org.spout.physics.engine.DynamicsWorld;
import org.spout.physics.engine.linked.LinkedDynamicsWorld;

public class FlowRegion extends Region {
private final RegionGenerator generator;
Expand All @@ -70,10 +65,6 @@ public class FlowRegion extends Region {
*/
private final BAAWrapper chunkStore;
protected final FlowEngine engine;
/**
* Holds all of the entities to be simulated
*/
protected final EntityManager entityManager = new EntityManager();
// TODO: possibly have a SoftReference of unloaded chunks to allow for quicker loading of chunk
/**
* Chunks used for ticking.
Expand All @@ -84,17 +75,13 @@ public class FlowRegion extends Region {
*/
protected final AtomicReference<FlowChunk[]> live = new AtomicReference<>(new FlowChunk[CHUNKS.VOLUME]);
private final FlowRegionSnapshot snapshot;
private final LinkedDynamicsWorld simulation;

public FlowRegion(FlowEngine engine, FlowWorld world, int x, int y, int z, BAAWrapper chunkStore) {
super(world, x << BLOCKS.BITS, y << BLOCKS.BITS, z << BLOCKS.BITS);
this.engine = engine;
this.generator = world instanceof FlowServerWorld ? new RegionGenerator(this, 4) : null;
this.chunkStore = chunkStore;
this.snapshot = new FlowRegionSnapshot(world.getSnapshot(), getPosition().toInt());
simulation = new LinkedDynamicsWorld(ReactConverter.toReactVector3(0f, -9.81f, -0f), 1/20f, new FlowLinkedWorldInfo(this));
//simulation.addListener(new FlowCollisionListener());
simulation.start();
}

@Override
Expand Down Expand Up @@ -140,9 +127,9 @@ public FlowChunk getChunk(final int x, final int y, final int z, final LoadOptio
// If we're not waiting, then we don't care because it's async anyways
if (loadopt.isWait()) {
if (loadopt.generateIfNeeded()) {
((FlowWorld) getWorld().get()).getThread().checkStage(WorldTickStage.noneOf(WorldTickStage.COPY_SNAPSHOT, WorldTickStage.PRESNAPSHOT, WorldTickStage.LIGHTING));
getFlowWorld().getThread().checkStage(WorldTickStage.noneOf(WorldTickStage.COPY_SNAPSHOT, WorldTickStage.PRESNAPSHOT, WorldTickStage.LIGHTING));
} else if (loadopt.loadIfNeeded()) {
((FlowWorld) getWorld().get()).getThread().checkStage(WorldTickStage.noneOf(WorldTickStage.COPY_SNAPSHOT));
getFlowWorld().getThread().checkStage(WorldTickStage.noneOf(WorldTickStage.COPY_SNAPSHOT));
}
}

Expand Down Expand Up @@ -276,7 +263,7 @@ protected FlowChunk setChunk(FlowChunk newChunk, int x, int y, int z, ChunkDataF
if (dataForRegion != null) {
for (FlowEntitySnapshot snapshot : dataForRegion.loadedEntities) {
FlowEntity entity = EntityManager.createEntity(engine, snapshot.getTransform());
entityManager.addEntity(entity);
getFlowWorld().getEntityManager().addEntity(entity);
}
}
}
Expand Down Expand Up @@ -453,56 +440,11 @@ public Chunk getLocalChunk(int x, int y, int z, LoadOption loadopt) {
throw new UnsupportedOperationException("Not supported yet.");
}

public EntityManager getEntityManager() {
return entityManager;
}

public void finalizeRun() {
entityManager.finalizeRun();
}

public void preSnapshotRun() {
entityManager.preSnapshotRun();
}

public void copySnapshotRun() {
entityManager.copyAllSnapshots();
chunks.set(live.get());
snapshot.update(this);
}

public void startTickRun(int stage, long delta) {
if (stage == 0) {
updateEntities(delta);
} else if (stage == 1) {
updateDynamics(delta);
}
}


private void updateEntities(float dt) {
for (FlowEntity ent : entityManager.getAll()) {
try {
ent.tick(dt);
} catch (Exception e) {
engine.getLogger().log(Level.ERROR, "Unhandled exception during tick for " + ent.toString(), e);
}
}
}

/**
* Updates physics in this region Steps simulation forward and finally alerts the API in components.
*/
private void updateDynamics(float dt) {
for (final Entity entity : entityManager.getAll()) {
((FlowPhysics) entity.getPhysics()).onPrePhysicsTick();
}
simulation.update();
for (final Entity entity : entityManager.getAll()) {
((FlowPhysics) entity.getPhysics()).onPostPhysicsTick(dt);
}
}

public FlowWorld getFlowWorld() {
return (FlowWorld) super.getWorld().refresh(engine.getWorldManager());
}
Expand All @@ -527,9 +469,4 @@ public void setChunk(int worldChunkX, int worldChunkY, int worldChunkZ, int[] bl
}
}
}

@Override
public DynamicsWorld getDynamicsWorld() {
return simulation;
}
}
Loading

0 comments on commit 1f665cc

Please sign in to comment.