diff --git a/src/Debug.hx b/src/Debug.hx index ab36beac..ef21d474 100644 --- a/src/Debug.hx +++ b/src/Debug.hx @@ -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) - _spheres.push({position: centre.clone(), radius: radius, lifetime: 0.032}); + _spheres.push({position: centre.clone(), radius: radius, lifetime: lifetime}); } } diff --git a/src/Marble.hx b/src/Marble.hx index ee8d19b3..e57cc06e 100644 --- a/src/Marble.hx +++ b/src/Marble.hx @@ -360,7 +360,7 @@ class Marble extends GameObject { if (Settings.optionsSettings.reflectionDetail > 0) { 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 || Settings.optionsSettings.marbleShader == "Default" diff --git a/src/MarbleWorld.hx b/src/MarbleWorld.hx index ee48ccaf..57f2c5bc 100644 --- a/src/MarbleWorld.hx +++ b/src/MarbleWorld.hx @@ -1055,32 +1055,43 @@ class MarbleWorld extends Scheduler { } } if (lastMove != null) { - // if (ourMove.serverTicks == lastMove.serverTicks) { - if (ourMoveStruct != null) { - var otherPred = predictions.retrieveState(clientMarbles[Net.clientIdMap[client]], ourMoveStruct.timeState.ticks); - if (otherPred != null) { - if (otherPred.getError(lastMove) > 0.001) { - // trace('Prediction error: ${otherPred.getError(lastMove)}'); + // clientMarbles[Net.clientIdMap[client]].unpackUpdate(lastMove); + // needsPrediction |= 1 << client; + // arr.insert(0, lastMove); + if (ourMove.serverTicks == lastMove.serverTicks) { + if (ourMoveStruct != null) { + 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}'); clientMarbles[Net.clientIdMap[client]].unpackUpdate(lastMove); needsPrediction |= 1 << client; arr.insert(0, lastMove); + predictions.clearStatesAfterTick(clientMarbles[Net.clientIdMap[client]], ourMoveStruct.timeState.ticks); } } 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); needsPrediction |= 1 << client; 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) { var ourPred = predictions.retrieveState(marble, ourMoveStruct.timeState.ticks); if (ourPred != null) { @@ -1088,16 +1099,19 @@ class MarbleWorld extends Scheduler { trace('Desync for tick ${ourMoveStruct.timeState.ticks}'); marble.unpackUpdate(ourMove); needsPrediction |= 1 << Net.clientId; + predictions.clearStatesAfterTick(marble, ourMoveStruct.timeState.ticks); } } else { trace('Desync for tick ${ourMoveStruct.timeState.ticks}'); marble.unpackUpdate(ourMove); needsPrediction |= 1 << Net.clientId; + predictions.clearStatesAfterTick(marble, ourMoveStruct.timeState.ticks); } } else { trace('Desync in General'); marble.unpackUpdate(ourMove); needsPrediction |= 1 << Net.clientId; + // predictions.clearStatesAfterTick(marble, ourMoveStruct.timeState.ticks); } } } diff --git a/src/collision/BVHTree.hx b/src/collision/BVHTree.hx index 694f9afa..39f7574b 100644 --- a/src/collision/BVHTree.hx +++ b/src/collision/BVHTree.hx @@ -15,10 +15,124 @@ class BVHNode { var child1:Int = -1; var child2:Int = -1; var isLeaf:Bool; - var bounds:Bounds; 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 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) { + 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) { + 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) { + 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 { @@ -40,9 +154,8 @@ class BVHTree { this.traverse(node -> { if (node.isLeaf) { var entity = node.object; - var tightAABB = entity.boundingBox; - if (node.bounds.containsBounds(tightAABB)) { + if (node.containsBounds(entity.boundingBox)) { return; } @@ -60,7 +173,7 @@ class BVHTree { var aabb = entity.boundingBox; var newNode = allocateNode(); - newNode.bounds = aabb; + newNode.setBounds(aabb); newNode.object = entity; newNode.isLeaf = true; @@ -71,7 +184,7 @@ class BVHTree { // Find the best sibling for the new leaf var bestSibling = this.root; - var bestCostBox = this.root.bounds.clone(); + var bestCostBox = this.root.getBounds(); bestCostBox.add(aabb); var bestCost = bestCostBox.xSize * bestCostBox.ySize + bestCostBox.xSize * bestCostBox.zSize + bestCostBox.ySize * bestCostBox.zSize; var q = [{p1: this.root.index, p2: 0.0}]; @@ -81,7 +194,7 @@ class BVHTree { var current = nodes[front.p1]; var inheritedCost = front.p2; - var combined = current.bounds.clone(); + var combined = current.getBounds(); combined.add(aabb); var directCost = combined.xSize * combined.ySize + combined.xSize * combined.zSize + combined.ySize * combined.zSize; @@ -90,9 +203,11 @@ class BVHTree { bestCost = costForCurrent; bestSibling = current; } + var xs = (current.xMax - current.xMin); + var ys = (current.yMax - current.yMin); + var zs = (current.zMax - current.zMin); - inheritedCost += directCost - - (current.bounds.xSize * current.bounds.ySize + current.bounds.xSize * current.bounds.zSize + current.bounds.ySize * current.bounds.zSize); + inheritedCost += directCost - (xs * ys + xs * zs + ys * zs); var aabbCost = aabb.xSize * aabb.ySize + aabb.xSize * aabb.zSize + aabb.ySize * aabb.zSize; var lowerBoundCost = aabbCost + inheritedCost; @@ -110,8 +225,8 @@ class BVHTree { var oldParent = bestSibling.parent != -1 ? nodes[bestSibling.parent] : null; var newParent = allocateNode(); newParent.parent = oldParent != null ? oldParent.index : -1; - newParent.bounds = bestSibling.bounds.clone(); - newParent.bounds.add(aabb); + newParent.setBoundsFromNode(bestSibling); + newParent.add(aabb); newParent.isLeaf = false; if (oldParent != null) { @@ -140,11 +255,10 @@ class BVHTree { var child1 = ancestor.child1; var child2 = ancestor.child2; - ancestor.bounds = new Bounds(); if (child1 != -1) - ancestor.bounds.add(nodes[child1].bounds); + ancestor.addNodeBounds(nodes[child1]); if (child2 != -1) - ancestor.bounds.add(nodes[child2].bounds); + ancestor.addNodeBounds(nodes[child2]); this.rotate(ancestor); @@ -205,8 +319,8 @@ class BVHTree { var child1 = nodes[ancestornode.child1]; var child2 = nodes[ancestornode.child2]; - ancestornode.bounds = child1.bounds.clone(); - ancestornode.bounds.add(child2.bounds); + ancestornode.setBoundsFromNode(child1); + ancestornode.addNodeBounds(child2); ancestor = ancestornode.parent; } } else { @@ -223,27 +337,24 @@ class BVHTree { var parent = nodes[node.parent]; var sibling = nodes[parent.child1 == node.index ? parent.child2 : parent.child1]; 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(); - ch1.add(nodes[node.child1].bounds); - 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); + costDiffs.push(sibling.getExpansionCost(nodes[node.child1]) - nodeArea); + costDiffs.push(sibling.getExpansionCost(nodes[node.child2]) - nodeArea); if (!sibling.isLeaf) { - var siblingArea = sibling.bounds.xSize * sibling.bounds.ySize + sibling.bounds.zSize * sibling.bounds.ySize - + sibling.bounds.xSize * sibling.bounds.zSize; + var sxs = sibling.xMax - sibling.xMin; + var sys = sibling.yMax - sibling.yMin; + var szs = sibling.zMax - sibling.zMin; + var siblingArea = sxs * sys + sys * szs + sxs * szs; if (sibling.child1 != -1) { - var ch3 = node.bounds.clone(); - ch3.add(nodes[sibling.child1].bounds); - costDiffs.push(ch3.xSize * ch3.ySize + ch3.zSize * ch3.ySize + ch3.xSize * ch3.zSize - siblingArea); + costDiffs.push(node.getExpansionCost(nodes[sibling.child1]) - siblingArea); } if (sibling.child2 != -1) { - var ch4 = node.bounds.clone(); - ch4.add(nodes[sibling.child2].bounds); - costDiffs.push(ch4.xSize * ch4.ySize + ch4.zSize * ch4.ySize + ch4.xSize * ch4.zSize - siblingArea); + costDiffs.push(node.getExpansionCost(nodes[sibling.child2]) - siblingArea); } } @@ -269,9 +380,9 @@ class BVHTree { node.child2 = sibling.index; sibling.parent = node.index; - node.bounds = sibling.bounds.clone(); + node.setBoundsFromNode(sibling); if (node.child1 != -1) { - node.bounds.add(nodes[node.child1].bounds); + node.addNodeBounds(nodes[node.child1]); } case 1: if (parent.child1 == sibling.index) { @@ -284,9 +395,9 @@ class BVHTree { } node.child1 = sibling.index; sibling.parent = node.index; - node.bounds = sibling.bounds.clone(); + node.setBoundsFromNode(sibling); if (node.child2 != -1) { - node.bounds.add(nodes[node.child2].bounds); + node.addNodeBounds(nodes[node.child2]); } case 2: if (parent.child1 == node.index) { @@ -299,9 +410,9 @@ class BVHTree { } sibling.child2 = node.index; node.parent = sibling.index; - sibling.bounds = node.bounds.clone(); + sibling.setBoundsFromNode(node); if (sibling.child2 != -1) { - sibling.bounds.add(nodes[sibling.child2].bounds); + sibling.addNodeBounds(nodes[sibling.child2]); } case 3: @@ -315,9 +426,9 @@ class BVHTree { } sibling.child1 = node.index; node.parent = sibling.index; - sibling.bounds = node.bounds.clone(); + sibling.setBoundsFromNode(node); if (sibling.child1 != -1) { - sibling.bounds.add(nodes[sibling.child1].bounds); + sibling.addNodeBounds(nodes[sibling.child1]); } } } @@ -335,7 +446,7 @@ class BVHTree { var current = q[qptr++]; var currentnode = this.nodes[current]; - if (currentnode.bounds.containsBounds(searchbox) || currentnode.bounds.collide(searchbox)) { + if (currentnode.containsBounds(searchbox) || currentnode.collide(searchbox)) { if (currentnode.isLeaf) { res.push(currentnode.object); } else { @@ -361,7 +472,7 @@ class BVHTree { while (qptr != q.length) { var current = q[qptr++]; var currentnode = this.nodes[current]; - if (ray.collide(currentnode.bounds)) { + if (currentnode.collideRay(ray)) { if (currentnode.isLeaf) { res = res.concat(currentnode.object.rayCast(origin, direction)); } else { diff --git a/src/net/MarblePredictionStore.hx b/src/net/MarblePredictionStore.hx index dedc2e2d..bc7c2049 100644 --- a/src/net/MarblePredictionStore.hx +++ b/src/net/MarblePredictionStore.hx @@ -59,4 +59,12 @@ class MarblePredictionStore { } 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(); + } + } } diff --git a/src/shaders/CubemapRenderer.hx b/src/shaders/CubemapRenderer.hx index 504c9d85..848cba96 100644 --- a/src/shaders/CubemapRenderer.hx +++ b/src/shaders/CubemapRenderer.hx @@ -20,11 +20,15 @@ class CubemapRenderer { var nextFaceToRender:Int; var facesPerRender:Int = 2; - public function new(scene:Scene, sky:Sky) { + public function new(scene:Scene, sky:Sky, useSky = false) { this.scene = scene; this.sky = sky; - 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); + if (useSky) + 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.position = new Vector(); this.nextFaceToRender = 0;