optimize prediction more

This commit is contained in:
RandomityGuy 2024-02-02 12:42:09 +05:30
parent aa85fc2faa
commit 625cbc104e
6 changed files with 196 additions and 59 deletions

View file

@ -76,8 +76,8 @@ class Debug {
} }
} }
public static function drawSphere(centre:Vector, radius:Float) { public static function drawSphere(centre:Vector, radius:Float, lifetime = 0.032) {
if (drawBounds) if (drawBounds)
_spheres.push({position: centre.clone(), radius: radius, lifetime: 0.032}); _spheres.push({position: centre.clone(), radius: radius, lifetime: lifetime});
} }
} }

View file

@ -360,7 +360,7 @@ class Marble extends GameObject {
if (Settings.optionsSettings.reflectionDetail > 0) { if (Settings.optionsSettings.reflectionDetail > 0) {
var csky = level != null ? level.sky : (@:privateAccess MarbleGame.instance.previewWorld.sky); var csky = level != null ? level.sky : (@:privateAccess MarbleGame.instance.previewWorld.sky);
this.cubemapRenderer = new CubemapRenderer(MarbleGame.instance.scene, csky); this.cubemapRenderer = new CubemapRenderer(MarbleGame.instance.scene, csky, !this.controllable);
if (Settings.optionsSettings.marbleShader == null if (Settings.optionsSettings.marbleShader == null
|| Settings.optionsSettings.marbleShader == "Default" || Settings.optionsSettings.marbleShader == "Default"

View file

@ -1055,32 +1055,43 @@ class MarbleWorld extends Scheduler {
} }
} }
if (lastMove != null) { if (lastMove != null) {
// if (ourMove.serverTicks == lastMove.serverTicks) { // clientMarbles[Net.clientIdMap[client]].unpackUpdate(lastMove);
if (ourMoveStruct != null) { // needsPrediction |= 1 << client;
var otherPred = predictions.retrieveState(clientMarbles[Net.clientIdMap[client]], ourMoveStruct.timeState.ticks); // arr.insert(0, lastMove);
if (otherPred != null) { if (ourMove.serverTicks == lastMove.serverTicks) {
if (otherPred.getError(lastMove) > 0.001) { if (ourMoveStruct != null) {
// trace('Prediction error: ${otherPred.getError(lastMove)}'); var otherPred = predictions.retrieveState(clientMarbles[Net.clientIdMap[client]], ourMoveStruct.timeState.ticks);
if (otherPred != null) {
if (otherPred.getError(lastMove) > 0.001) {
Debug.drawSphere(@:privateAccess clientMarbles[Net.clientIdMap[client]].newPos, 0.2, 0.5);
// trace('Prediction error: ${otherPred.getError(lastMove)}');
trace('Desync for tick ${ourMoveStruct.timeState.ticks}');
clientMarbles[Net.clientIdMap[client]].unpackUpdate(lastMove);
needsPrediction |= 1 << client;
arr.insert(0, lastMove);
predictions.clearStatesAfterTick(clientMarbles[Net.clientIdMap[client]], ourMoveStruct.timeState.ticks);
}
} else {
Debug.drawSphere(@:privateAccess clientMarbles[Net.clientIdMap[client]].newPos, 0.2, 0.5);
trace('Desync for tick ${ourMoveStruct.timeState.ticks}'); trace('Desync for tick ${ourMoveStruct.timeState.ticks}');
clientMarbles[Net.clientIdMap[client]].unpackUpdate(lastMove); clientMarbles[Net.clientIdMap[client]].unpackUpdate(lastMove);
needsPrediction |= 1 << client; needsPrediction |= 1 << client;
arr.insert(0, lastMove); arr.insert(0, lastMove);
predictions.clearStatesAfterTick(clientMarbles[Net.clientIdMap[client]], ourMoveStruct.timeState.ticks);
} }
} else { } else {
trace('Desync for tick ${ourMoveStruct.timeState.ticks}'); Debug.drawSphere(@:privateAccess clientMarbles[Net.clientIdMap[client]].newPos, 0.2, 0.5);
trace('Desync in General');
clientMarbles[Net.clientIdMap[client]].unpackUpdate(lastMove); clientMarbles[Net.clientIdMap[client]].unpackUpdate(lastMove);
needsPrediction |= 1 << client; needsPrediction |= 1 << client;
arr.insert(0, lastMove); arr.insert(0, lastMove);
// predictions.clearStatesAfterTick(clientMarbles[Net.clientIdMap[client]], ourMoveStruct.timeState.ticks);
} }
} else {
trace('Desync in General');
clientMarbles[Net.clientIdMap[client]].unpackUpdate(lastMove);
needsPrediction |= 1 << client;
arr.insert(0, lastMove);
} }
// }
} }
} }
// marble.unpackUpdate(ourMove);
// needsPrediction |= 1 << Net.clientId;
if (ourMoveStruct != null) { if (ourMoveStruct != null) {
var ourPred = predictions.retrieveState(marble, ourMoveStruct.timeState.ticks); var ourPred = predictions.retrieveState(marble, ourMoveStruct.timeState.ticks);
if (ourPred != null) { if (ourPred != null) {
@ -1088,16 +1099,19 @@ class MarbleWorld extends Scheduler {
trace('Desync for tick ${ourMoveStruct.timeState.ticks}'); trace('Desync for tick ${ourMoveStruct.timeState.ticks}');
marble.unpackUpdate(ourMove); marble.unpackUpdate(ourMove);
needsPrediction |= 1 << Net.clientId; needsPrediction |= 1 << Net.clientId;
predictions.clearStatesAfterTick(marble, ourMoveStruct.timeState.ticks);
} }
} else { } else {
trace('Desync for tick ${ourMoveStruct.timeState.ticks}'); trace('Desync for tick ${ourMoveStruct.timeState.ticks}');
marble.unpackUpdate(ourMove); marble.unpackUpdate(ourMove);
needsPrediction |= 1 << Net.clientId; needsPrediction |= 1 << Net.clientId;
predictions.clearStatesAfterTick(marble, ourMoveStruct.timeState.ticks);
} }
} else { } else {
trace('Desync in General'); trace('Desync in General');
marble.unpackUpdate(ourMove); marble.unpackUpdate(ourMove);
needsPrediction |= 1 << Net.clientId; needsPrediction |= 1 << Net.clientId;
// predictions.clearStatesAfterTick(marble, ourMoveStruct.timeState.ticks);
} }
} }
} }

View file

@ -15,10 +15,124 @@ class BVHNode<T:IBVHObject> {
var child1:Int = -1; var child1:Int = -1;
var child2:Int = -1; var child2:Int = -1;
var isLeaf:Bool; var isLeaf:Bool;
var bounds:Bounds;
var object:T; var object:T;
var xMin:Float = 0;
var yMin:Float = 0;
var zMin:Float = 0;
var xMax:Float = 0;
var yMax:Float = 0;
var zMax:Float = 0;
public function new() {} public function new() {}
public inline function containsBounds(b:Bounds) {
return xMin <= b.xMin && yMin <= b.yMin && zMin <= b.zMin && xMax >= b.xMax && yMax >= b.yMax && zMax >= b.zMax;
}
public inline function setBounds(b:Bounds) {
xMin = b.xMin;
yMin = b.yMin;
zMin = b.zMin;
xMax = b.xMax;
yMax = b.yMax;
zMax = b.zMax;
}
public inline function setBoundsFromNode(b:BVHNode<T>) {
xMin = b.xMin;
yMin = b.yMin;
zMin = b.zMin;
xMax = b.xMax;
yMax = b.yMax;
zMax = b.zMax;
}
public inline function getBounds() {
return Bounds.fromValues(xMin, yMin, zMin, xMax - xMin, yMax - yMin, zMax - zMin);
}
public inline function add(b:Bounds) {
if (b.xMin < xMin)
xMin = b.xMin;
if (b.xMax > xMax)
xMax = b.xMax;
if (b.yMin < yMin)
yMin = b.yMin;
if (b.yMax > yMax)
yMax = b.yMax;
if (b.zMin < zMin)
zMin = b.zMin;
if (b.zMax > zMax)
zMax = b.zMax;
}
public inline function addNodeBounds(b:BVHNode<T>) {
if (b.xMin < xMin)
xMin = b.xMin;
if (b.xMax > xMax)
xMax = b.xMax;
if (b.yMin < yMin)
yMin = b.yMin;
if (b.yMax > yMax)
yMax = b.yMax;
if (b.zMin < zMin)
zMin = b.zMin;
if (b.zMax > zMax)
zMax = b.zMax;
}
public inline function collide(b:Bounds) {
return !(xMin > b.xMax || yMin > b.yMax || zMin > b.zMax || xMax < b.xMin || yMax < b.yMin || zMax < b.zMin);
}
public inline function getExpansionCost(b:BVHNode<T>) {
var xm = xMin;
var ym = yMin;
var zm = zMin;
var xp = xMax;
var yp = yMax;
var zp = zMax;
if (b.xMin < xm)
xm = b.xMin;
if (b.xMax > xp)
xp = b.xMax;
if (b.yMin < ym)
ym = b.yMin;
if (b.yMax > yp)
yp = b.yMax;
if (b.zMin < zm)
zm = b.zMin;
if (b.zMax > zp)
zp = b.zMax;
var xs = xp - xm;
var ys = yp - ym;
var zs = zp - zm;
return xs * ys + ys * zs + xs * zs;
}
public inline function collideRay(r:h3d.col.Ray):Bool {
var dx = 1 / r.lx;
var dy = 1 / r.ly;
var dz = 1 / r.lz;
var t1 = (xMin - r.px) * dx;
var t2 = (xMax - r.px) * dx;
var t3 = (yMin - r.py) * dy;
var t4 = (yMax - r.py) * dy;
var t5 = (zMin - r.pz) * dz;
var t6 = (zMax - r.pz) * dz;
var tmin = Math.max(Math.max(Math.min(t1, t2), Math.min(t3, t4)), Math.min(t5, t6));
var tmax = Math.min(Math.min(Math.max(t1, t2), Math.max(t3, t4)), Math.max(t5, t6));
if (tmax < 0) {
// t = tmax;
return false;
} else if (tmin > tmax) {
// t = tmax;
return false;
} else {
// t = tmin;
return true;
}
}
} }
class BVHTree<T:IBVHObject> { class BVHTree<T:IBVHObject> {
@ -40,9 +154,8 @@ class BVHTree<T:IBVHObject> {
this.traverse(node -> { this.traverse(node -> {
if (node.isLeaf) { if (node.isLeaf) {
var entity = node.object; var entity = node.object;
var tightAABB = entity.boundingBox;
if (node.bounds.containsBounds(tightAABB)) { if (node.containsBounds(entity.boundingBox)) {
return; return;
} }
@ -60,7 +173,7 @@ class BVHTree<T:IBVHObject> {
var aabb = entity.boundingBox; var aabb = entity.boundingBox;
var newNode = allocateNode(); var newNode = allocateNode();
newNode.bounds = aabb; newNode.setBounds(aabb);
newNode.object = entity; newNode.object = entity;
newNode.isLeaf = true; newNode.isLeaf = true;
@ -71,7 +184,7 @@ class BVHTree<T:IBVHObject> {
// Find the best sibling for the new leaf // Find the best sibling for the new leaf
var bestSibling = this.root; var bestSibling = this.root;
var bestCostBox = this.root.bounds.clone(); var bestCostBox = this.root.getBounds();
bestCostBox.add(aabb); bestCostBox.add(aabb);
var bestCost = bestCostBox.xSize * bestCostBox.ySize + bestCostBox.xSize * bestCostBox.zSize + bestCostBox.ySize * bestCostBox.zSize; var bestCost = bestCostBox.xSize * bestCostBox.ySize + bestCostBox.xSize * bestCostBox.zSize + bestCostBox.ySize * bestCostBox.zSize;
var q = [{p1: this.root.index, p2: 0.0}]; var q = [{p1: this.root.index, p2: 0.0}];
@ -81,7 +194,7 @@ class BVHTree<T:IBVHObject> {
var current = nodes[front.p1]; var current = nodes[front.p1];
var inheritedCost = front.p2; var inheritedCost = front.p2;
var combined = current.bounds.clone(); var combined = current.getBounds();
combined.add(aabb); combined.add(aabb);
var directCost = combined.xSize * combined.ySize + combined.xSize * combined.zSize + combined.ySize * combined.zSize; var directCost = combined.xSize * combined.ySize + combined.xSize * combined.zSize + combined.ySize * combined.zSize;
@ -90,9 +203,11 @@ class BVHTree<T:IBVHObject> {
bestCost = costForCurrent; bestCost = costForCurrent;
bestSibling = current; bestSibling = current;
} }
var xs = (current.xMax - current.xMin);
var ys = (current.yMax - current.yMin);
var zs = (current.zMax - current.zMin);
inheritedCost += directCost inheritedCost += directCost - (xs * ys + xs * zs + ys * zs);
- (current.bounds.xSize * current.bounds.ySize + current.bounds.xSize * current.bounds.zSize + current.bounds.ySize * current.bounds.zSize);
var aabbCost = aabb.xSize * aabb.ySize + aabb.xSize * aabb.zSize + aabb.ySize * aabb.zSize; var aabbCost = aabb.xSize * aabb.ySize + aabb.xSize * aabb.zSize + aabb.ySize * aabb.zSize;
var lowerBoundCost = aabbCost + inheritedCost; var lowerBoundCost = aabbCost + inheritedCost;
@ -110,8 +225,8 @@ class BVHTree<T:IBVHObject> {
var oldParent = bestSibling.parent != -1 ? nodes[bestSibling.parent] : null; var oldParent = bestSibling.parent != -1 ? nodes[bestSibling.parent] : null;
var newParent = allocateNode(); var newParent = allocateNode();
newParent.parent = oldParent != null ? oldParent.index : -1; newParent.parent = oldParent != null ? oldParent.index : -1;
newParent.bounds = bestSibling.bounds.clone(); newParent.setBoundsFromNode(bestSibling);
newParent.bounds.add(aabb); newParent.add(aabb);
newParent.isLeaf = false; newParent.isLeaf = false;
if (oldParent != null) { if (oldParent != null) {
@ -140,11 +255,10 @@ class BVHTree<T:IBVHObject> {
var child1 = ancestor.child1; var child1 = ancestor.child1;
var child2 = ancestor.child2; var child2 = ancestor.child2;
ancestor.bounds = new Bounds();
if (child1 != -1) if (child1 != -1)
ancestor.bounds.add(nodes[child1].bounds); ancestor.addNodeBounds(nodes[child1]);
if (child2 != -1) if (child2 != -1)
ancestor.bounds.add(nodes[child2].bounds); ancestor.addNodeBounds(nodes[child2]);
this.rotate(ancestor); this.rotate(ancestor);
@ -205,8 +319,8 @@ class BVHTree<T:IBVHObject> {
var child1 = nodes[ancestornode.child1]; var child1 = nodes[ancestornode.child1];
var child2 = nodes[ancestornode.child2]; var child2 = nodes[ancestornode.child2];
ancestornode.bounds = child1.bounds.clone(); ancestornode.setBoundsFromNode(child1);
ancestornode.bounds.add(child2.bounds); ancestornode.addNodeBounds(child2);
ancestor = ancestornode.parent; ancestor = ancestornode.parent;
} }
} else { } else {
@ -223,27 +337,24 @@ class BVHTree<T:IBVHObject> {
var parent = nodes[node.parent]; var parent = nodes[node.parent];
var sibling = nodes[parent.child1 == node.index ? parent.child2 : parent.child1]; var sibling = nodes[parent.child1 == node.index ? parent.child2 : parent.child1];
var costDiffs = []; var costDiffs = [];
var nodeArea = node.bounds.xSize * node.bounds.ySize + node.bounds.zSize * node.bounds.ySize + node.bounds.xSize * node.bounds.zSize; var nxs = node.xMax - node.xMin;
var nys = node.yMax - node.yMin;
var nzs = node.zMax - node.zMin;
var nodeArea = nxs * nys + nzs * nys + nxs * nzs;
var ch1 = sibling.bounds.clone(); costDiffs.push(sibling.getExpansionCost(nodes[node.child1]) - nodeArea);
ch1.add(nodes[node.child1].bounds); costDiffs.push(sibling.getExpansionCost(nodes[node.child2]) - nodeArea);
costDiffs.push(ch1.xSize * ch1.ySize + ch1.zSize * ch1.ySize + ch1.xSize * ch1.zSize - nodeArea);
var ch2 = sibling.bounds.clone();
ch2.add(nodes[node.child2].bounds);
costDiffs.push(ch2.xSize * ch2.ySize + ch2.zSize * ch2.ySize + ch2.xSize * ch2.zSize - nodeArea);
if (!sibling.isLeaf) { if (!sibling.isLeaf) {
var siblingArea = sibling.bounds.xSize * sibling.bounds.ySize + sibling.bounds.zSize * sibling.bounds.ySize var sxs = sibling.xMax - sibling.xMin;
+ sibling.bounds.xSize * sibling.bounds.zSize; var sys = sibling.yMax - sibling.yMin;
var szs = sibling.zMax - sibling.zMin;
var siblingArea = sxs * sys + sys * szs + sxs * szs;
if (sibling.child1 != -1) { if (sibling.child1 != -1) {
var ch3 = node.bounds.clone(); costDiffs.push(node.getExpansionCost(nodes[sibling.child1]) - siblingArea);
ch3.add(nodes[sibling.child1].bounds);
costDiffs.push(ch3.xSize * ch3.ySize + ch3.zSize * ch3.ySize + ch3.xSize * ch3.zSize - siblingArea);
} }
if (sibling.child2 != -1) { if (sibling.child2 != -1) {
var ch4 = node.bounds.clone(); costDiffs.push(node.getExpansionCost(nodes[sibling.child2]) - siblingArea);
ch4.add(nodes[sibling.child2].bounds);
costDiffs.push(ch4.xSize * ch4.ySize + ch4.zSize * ch4.ySize + ch4.xSize * ch4.zSize - siblingArea);
} }
} }
@ -269,9 +380,9 @@ class BVHTree<T:IBVHObject> {
node.child2 = sibling.index; node.child2 = sibling.index;
sibling.parent = node.index; sibling.parent = node.index;
node.bounds = sibling.bounds.clone(); node.setBoundsFromNode(sibling);
if (node.child1 != -1) { if (node.child1 != -1) {
node.bounds.add(nodes[node.child1].bounds); node.addNodeBounds(nodes[node.child1]);
} }
case 1: case 1:
if (parent.child1 == sibling.index) { if (parent.child1 == sibling.index) {
@ -284,9 +395,9 @@ class BVHTree<T:IBVHObject> {
} }
node.child1 = sibling.index; node.child1 = sibling.index;
sibling.parent = node.index; sibling.parent = node.index;
node.bounds = sibling.bounds.clone(); node.setBoundsFromNode(sibling);
if (node.child2 != -1) { if (node.child2 != -1) {
node.bounds.add(nodes[node.child2].bounds); node.addNodeBounds(nodes[node.child2]);
} }
case 2: case 2:
if (parent.child1 == node.index) { if (parent.child1 == node.index) {
@ -299,9 +410,9 @@ class BVHTree<T:IBVHObject> {
} }
sibling.child2 = node.index; sibling.child2 = node.index;
node.parent = sibling.index; node.parent = sibling.index;
sibling.bounds = node.bounds.clone(); sibling.setBoundsFromNode(node);
if (sibling.child2 != -1) { if (sibling.child2 != -1) {
sibling.bounds.add(nodes[sibling.child2].bounds); sibling.addNodeBounds(nodes[sibling.child2]);
} }
case 3: case 3:
@ -315,9 +426,9 @@ class BVHTree<T:IBVHObject> {
} }
sibling.child1 = node.index; sibling.child1 = node.index;
node.parent = sibling.index; node.parent = sibling.index;
sibling.bounds = node.bounds.clone(); sibling.setBoundsFromNode(node);
if (sibling.child1 != -1) { if (sibling.child1 != -1) {
sibling.bounds.add(nodes[sibling.child1].bounds); sibling.addNodeBounds(nodes[sibling.child1]);
} }
} }
} }
@ -335,7 +446,7 @@ class BVHTree<T:IBVHObject> {
var current = q[qptr++]; var current = q[qptr++];
var currentnode = this.nodes[current]; var currentnode = this.nodes[current];
if (currentnode.bounds.containsBounds(searchbox) || currentnode.bounds.collide(searchbox)) { if (currentnode.containsBounds(searchbox) || currentnode.collide(searchbox)) {
if (currentnode.isLeaf) { if (currentnode.isLeaf) {
res.push(currentnode.object); res.push(currentnode.object);
} else { } else {
@ -361,7 +472,7 @@ class BVHTree<T:IBVHObject> {
while (qptr != q.length) { while (qptr != q.length) {
var current = q[qptr++]; var current = q[qptr++];
var currentnode = this.nodes[current]; var currentnode = this.nodes[current];
if (ray.collide(currentnode.bounds)) { if (currentnode.collideRay(ray)) {
if (currentnode.isLeaf) { if (currentnode.isLeaf) {
res = res.concat(currentnode.object.rayCast(origin, direction)); res = res.concat(currentnode.object.rayCast(origin, direction));
} else { } else {

View file

@ -59,4 +59,12 @@ class MarblePredictionStore {
} }
return null; return null;
} }
public function clearStatesAfterTick(marble:Marble, tick:Int) {
if (predictions.exists(marble)) {
var arr = predictions[marble];
while (arr.length != 0 && arr[arr.length - 1].tick >= tick)
arr.pop();
}
}
} }

View file

@ -20,11 +20,15 @@ class CubemapRenderer {
var nextFaceToRender:Int; var nextFaceToRender:Int;
var facesPerRender:Int = 2; var facesPerRender:Int = 2;
public function new(scene:Scene, sky:Sky) { public function new(scene:Scene, sky:Sky, useSky = false) {
this.scene = scene; this.scene = scene;
this.sky = sky; this.sky = sky;
this.cubemap = new Texture(128, 128, [Cube, Dynamic, Target], h3d.mat.Data.TextureFormat.RGB8); if (useSky)
this.cubemap.depthBuffer = new h3d.mat.DepthBuffer(128, 128, h3d.mat.DepthBuffer.DepthFormat.Depth16); this.cubemap = sky.cubemap;
else {
this.cubemap = new Texture(128, 128, [Cube, Dynamic, Target], h3d.mat.Data.TextureFormat.RGB8);
this.cubemap.depthBuffer = new h3d.mat.DepthBuffer(128, 128, h3d.mat.DepthBuffer.DepthFormat.Depth16);
}
this.camera = new Camera(90, 1, 1, 0.1, 1000); this.camera = new Camera(90, 1, 1, 0.1, 1000);
this.position = new Vector(); this.position = new Vector();
this.nextFaceToRender = 0; this.nextFaceToRender = 0;