Skip to content

Commit

Permalink
Merge branch 'simulation_orechestration' into nordale
Browse files Browse the repository at this point in the history
  • Loading branch information
cam72cam committed Oct 4, 2023
2 parents 75b6b32 + 4a2df72 commit 38c4b9f
Show file tree
Hide file tree
Showing 6 changed files with 95 additions and 109 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -229,17 +229,23 @@ public final void setCoupledUUID(CouplerType coupler, UUID id) {
.sendToObserving(this);
}

EntityCoupleableRollingStock coupled = id != null ? findByUUID(id) : null;

switch (coupler) {
case FRONT:
coupledFront = id;
if (coupledFront == null) {
lastKnownFront = null;
} else if (coupled != null){
lastKnownFront = new Vec3i(coupled.getPosition());
}
break;
case BACK:
coupledBack = id;
if (coupledBack == null) {
lastKnownRear = null;
} else if (coupled != null){
lastKnownFront = new Vec3i(coupled.getPosition());
}
break;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -469,6 +469,8 @@ public static Map<UUID, SimulationState> iterate(Map<UUID, SimulationState> stat
// Propagate dirty flag
boolean canBeUnloaded = consist.stream().allMatch(p -> p.state.velocity == 0 && state.forcesNewtons() < state.frictionNewtons());
consist.forEach(p -> p.state.canBeUnloaded = canBeUnloaded);
List<UUID> ids = consist.stream().map(x -> x.state.config.id).collect(Collectors.toList());
consist.forEach(p -> p.state.consist = ids);

boolean dirty = consist.stream().anyMatch(p -> p.state.dirty);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,73 +75,16 @@ public static void simulate(World world) {
state.update(entity);
stateMaps.get(i).put(entity.getUUID(), state);
if (state.dirty) {
dirty.add(entity.getUUID());
dirty.addAll(state.consist);
}
}
}
if (i < 40) {
stateMaps.get(i).get(entity.getUUID()).dirty = true;
dirty.addAll(stateMaps.get(i).get(entity.getUUID()).consist);
}
}
}

// This finds the full list of dirty stock that needs to be recomputed.
// It is *highly* optimized to run in under 0.5ms per 100 pieces of stock.
// It could be tuned further, but I suspect this is good enough for now
for (int i = 0; i < allStock.size(); i++) {
int lastSize = dirty.size();

for (UUID uuid : stateMaps.get(0).keySet()) {
boolean isDirty = dirty.contains(uuid);

// This makes an assumption that stock only has a single value for a coupler in 40 ticks
// Worst case is the potential for a missed dirty flag which will interact with the Mismatch check
UUID front = null;
UUID rear = null;

for (Map<UUID, SimulationState> stateMap : stateMaps) {
if (front != null && rear != null) {
break;
}

SimulationState state = stateMap.get(uuid);
if (state != null) {
if (front == null && state.interactingFront != null) {
front = state.interactingFront;
}
if (rear == null && state.interactingRear != null) {
rear = state.interactingRear;
}
}
}

if (!isDirty) {
if (front != null && dirty.contains(front)) {
dirty.add(uuid);
isDirty = true;
}
}
if (!isDirty) {
if (rear != null && dirty.contains(rear)) {
dirty.add(uuid);
isDirty = true;
}
}

if (isDirty) {
if (front != null && !dirty.contains(front)) {
dirty.add(front);
}
if (rear != null && !dirty.contains(rear)) {
dirty.add(rear);
}
}
}
if (lastSize == dirty.size()) {
break;
}
}

for (UUID uuid : dirty) {
SimulationState state = stateMaps.get(0).get(uuid);
if (state != null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ public class SimulationState {
public boolean frontPulling;
public boolean rearPushing;
public boolean rearPulling;
public List<UUID> consist;

public static class Configuration {
public UUID id;
Expand Down Expand Up @@ -199,6 +200,8 @@ public SimulationState(EntityCoupleableRollingStock stock) {

calculateBlockCollisions(Collections.emptyList());
blocksToBreak = Collections.emptyList();

consist = Collections.singletonList(config.id);
}

private SimulationState(SimulationState prev) {
Expand Down Expand Up @@ -229,6 +232,8 @@ private SimulationState(SimulationState prev) {
interferingResistance = prev.interferingResistance;
blocksToBreak = Collections.emptyList();
directResistance = prev.directResistance;

consist = prev.consist;
}

public void calculateCouplerPositions() {
Expand Down Expand Up @@ -348,14 +353,6 @@ private void moveAlongTrack(double distance) {
}
}

// Fix bogeys pointing in opposite directions
if (DegreeFuncs.delta(yawFront, yaw) > 90) {
yawFront = yaw;
}
if (DegreeFuncs.delta(yawRear, yaw) > 90) {
yawRear = yaw;
}

boolean isReversed = distance < 0;
if (isReversed) {
distance = -distance;
Expand Down Expand Up @@ -391,6 +388,12 @@ private void moveAlongTrack(double distance) {
yawFront = yaw;
yawRear = yaw;
}

// Fix bogeys pointing in opposite directions
if (DegreeFuncs.delta(yawFront, yaw) > 90 || DegreeFuncs.delta(yawFront, yawRear) > 90) {
yawFront = yaw;
yawRear = yaw;
}
}

public double forcesNewtons() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,26 +67,61 @@ public <T extends Freight> void postRender(T stock, RenderState state) {


for (ModelComponent comp : components) {
double itemsX = comp.length();
double itemsY = comp.height();
double itemsZ = comp.width();

double modelVolume = itemsX * itemsY * itemsZ;
int cargoVolume = (int) Math.ceil(stock.cargoItems.getSlotCount() * modelVolume/totalVolume);

double volumeRatio = Math.pow(cargoVolume / modelVolume, 0.3333);
itemsY = Math.ceil(itemsY * volumeRatio);
double xSize = comp.length();
double ySize = comp.height();
double zSize = comp.width();

double modelVolume = xSize * ySize * zSize;
int cargoSlots = (int) Math.ceil(stock.cargoItems.getSlotCount() * modelVolume/totalVolume);

// Goal: We want the biggest cubes to fill in the space
// Define fitment: How close each of the dimensions are to their reference given a specific scale
// These numbers are small enough that we can test each permutation.

// The "ideal" storage ratio
double ratio = Math.pow(cargoSlots / modelVolume, 0.33333);
double xItemsIdeal = ratio * xSize;
double yItemsIdeal = ratio * ySize;
double zItemsIdeal = ratio * zSize;

double bestFit = Double.MAX_VALUE;
int xItems = (int)Math.round(xItemsIdeal);
int yItems = (int)Math.round(yItemsIdeal);
int zItems = (int)Math.round(zItemsIdeal);

for (int x = 1; x < cargoSlots; x++) {
for (int y = 1; y < cargoSlots; y++) {
for (int z = 1; z < cargoSlots; z++) {
int currentSlots = x * y * z;
if (currentSlots < cargoSlots) {
continue;
}
double fitSize = Math.abs(1 - x / xItemsIdeal) + Math.abs(1 - y / yItemsIdeal) + Math.abs(1 - z / zItemsIdeal);
double fitRatio = Math.max(xSize / x, Math.max(ySize / y, zSize / z));
int fitItems = Math.abs(1 - currentSlots / cargoSlots);
double fit = fitSize + fitItems + fitRatio;
if (fit < bestFit) {
bestFit = fit;
xItems = x;
yItems = y;
zItems = z;
}
}
}
}

modelVolume = itemsX * itemsY * itemsZ;
volumeRatio = Math.pow(cargoVolume / modelVolume, 0.3333);
itemsZ = Math.ceil(itemsZ * volumeRatio);
double xScale = xSize / xItems;
double yScale = ySize / yItems;
double zScale = zSize / zItems;
if (!comp.key.contains("STRETCHED")) {
xScale = yScale = zScale = Math.min(xScale, Math.min(yScale, zScale));
}

modelVolume = itemsX * itemsY * itemsZ;
volumeRatio = cargoVolume / modelVolume;
itemsX = Math.ceil(itemsX * volumeRatio);
// Center X, Z
Vec3d offset = comp.min.add((xSize - xItems * xScale)/2,0,(zSize - zItems * zScale)/2);

int renderSlot = 0;
for (int i = slotOffset; i < Math.min(slotOffset+ cargoVolume, stock.cargoItems.getSlotCount()); i++) {
for (int i = slotOffset; i < Math.min(slotOffset+ cargoSlots, stock.cargoItems.getSlotCount()); i++) {
ItemStack stack = stock.cargoItems.get(i);
if (stack.isEmpty()) {
continue;
Expand Down Expand Up @@ -133,21 +168,18 @@ public <T extends Freight> void postRender(T stock, RenderState state) {
continue;
}
}
int x = renderSlot % (int) itemsX;
int z = (renderSlot / (int) itemsX) % (int) itemsZ;
int y = (renderSlot / (int) itemsX / (int) itemsZ) % (int) itemsY;

double scaleX = comp.length() / itemsX;
double scaleY = comp.height() / itemsY;
double scaleZ = comp.width() / itemsZ;
if (!comp.key.contains("STRETCHED")) {
scaleX = scaleY = scaleZ = Math.min(comp.length() / itemsX, Math.min(comp.height() / itemsY, comp.width() / itemsZ));
}
int z = renderSlot % zItems;
int x = (renderSlot / zItems) % xItems;
int y = (renderSlot / zItems / xItems) % yItems;

// Fill from center Z and X
z = zItems/2 + ((z % 2 == 0) ? z/2 : -(z+1)/2);
x = xItems/2 + ((x % 2 == 0) ? x/2 : -(x+1)/2);

Matrix4 matrix = new Matrix4()
//.scale(stock.gauge.scale(), stock.gauge.scale(), stock.gauge.scale())
.translate(comp.min.x, comp.min.y, comp.min.z)
.scale(scaleX, scaleY, scaleZ)
.translate(offset.x, offset.y, offset.z)
.scale(xScale, yScale, zScale)
.translate(0.5, 0.5, 0.5)
.translate(x, y, z);

Expand All @@ -160,7 +192,7 @@ public <T extends Freight> void postRender(T stock, RenderState state) {
model.addItem(stack, matrix);
renderSlot++;
}
slotOffset += cargoVolume;
slotOffset += cargoSlots;
}
cache.put(stock.getUUID(), model);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@

public class TrackFollower {
private final EntityMoveableRollingStock stock;
private final float min;
private final float max;
private final float min;



Expand All @@ -34,16 +34,16 @@ public TrackFollower(EntityMoveableRollingStock stock, ModelComponent frame, Whe
this.matrix = new Matrix4();

if (wheels != null && wheels.wheels.size() > 1) {
this.min = -(float) (wheels.wheels.stream().mapToDouble(w -> w.wheel.center.x).min().getAsDouble() * stock.gauge.scale());
this.max = -(float) (wheels.wheels.stream().mapToDouble(w -> w.wheel.center.x).max().getAsDouble() * stock.gauge.scale());
this.max = -(float) (wheels.wheels.stream().mapToDouble(w -> w.wheel.center.x).min().getAsDouble() * stock.gauge.scale());
this.min = -(float) (wheels.wheels.stream().mapToDouble(w -> w.wheel.center.x).max().getAsDouble() * stock.gauge.scale());
} else if (wheels != null && wheels.wheels.size() == 1) {
this.min = -(float) (wheels.wheels.get(0).wheel.min.x * stock.gauge.scale());
this.max = -(float) (wheels.wheels.get(0).wheel.max.x * stock.gauge.scale());
this.max = -(float) (wheels.wheels.get(0).wheel.min.x * stock.gauge.scale());
this.min = -(float) (wheels.wheels.get(0).wheel.max.x * stock.gauge.scale());
} else if (frame != null) {
this.min = -(float) (frame.min.x * stock.gauge.scale());
this.max = -(float) (frame.max.x * stock.gauge.scale());
this.max = -(float) (frame.min.x * stock.gauge.scale());
this.min = -(float) (frame.max.x * stock.gauge.scale());
} else {
this.min = this.max = offset;
this.max = this.min = offset;
}
}

Expand All @@ -61,8 +61,8 @@ public Matrix4 getMatrix() {
} else {
// Don't need to path to a point that's already on the track. TODO This can also be used to improve accuracy of the offset rendering
Vec3d offsetPos = pos.add(VecUtil.fromWrongYawPitch(offset, stock.getRotationYaw(), stock.getRotationPitch()));
double toMinPoint = max - offset;
double betweenPoints = min - max;
double toMinPoint = min - offset;
double betweenPoints = max - min;

float toPointYaw = 0;
float atPointYaw = 0;
Expand All @@ -71,7 +71,7 @@ public Matrix4 getMatrix() {

Vec3d pointPos = nextPosition(stock.getWorld(), stock.gauge, offsetPos, stock.getRotationYaw(), offsetYaw, toMinPoint);
Vec3d pointPosNext = nextPosition(stock.getWorld(), stock.gauge, pointPos, stock.getRotationYaw(), offsetYaw, betweenPoints);
Vec3d delta = stock.getPosition().subtract(pointPos).scale(min); // Scale copies sign
Vec3d delta = stock.getPosition().subtract(pointPos).scale(max); // Scale copies sign
if (pointPos.distanceTo(pointPosNext) > 0.1 * stock.gauge.scale()) {
toPointYaw = VecUtil.toYaw(delta) + stock.getRotationYaw() + 180;
atPointYaw = VecUtil.toYaw(pointPos.subtract(pointPosNext)) + stock.getRotationYaw() + 180 - toPointYaw ;
Expand All @@ -87,10 +87,10 @@ public Matrix4 getMatrix() {
matrix.setIdentity();
matrix.rotate(Math.toRadians(toPointYaw), 0, 1, 0);
matrix.rotate(Math.toRadians(toPointPitch), 0, 0, 1);
matrix.translate(-max / stock.gauge.scale(), 0, 0);
matrix.translate(-min / stock.gauge.scale(), 0, 0);
matrix.rotate(Math.toRadians(atPointYaw), 0, 1, 0);
matrix.rotate(Math.toRadians(atPointPitch), 0, 0, 1);
matrix.translate(max / stock.gauge.scale(), 0, 0);
matrix.translate(min / stock.gauge.scale(), 0, 0);
}
}
return matrix;
Expand Down

0 comments on commit 38c4b9f

Please sign in to comment.