From 333f7b4fb4e09b1831efa01cf493207e8495a60a Mon Sep 17 00:00:00 2001 From: vladislavbelov Date: Wed, 3 Feb 2021 17:03:44 +0000 Subject: [PATCH] Fixes building snapping for non-square foundations. Fixes #5976 Tested By: Freagarach, Langbart, Stan Differential Revision: https://code.wildfiregames.com/D3510 This was SVN commit r24827. --- .../simulation/helpers/ObstructionSnap.js | 25 +++++++++++++------ .../scripting/JSInterface_Simulation.cpp | 6 ++--- 2 files changed, 21 insertions(+), 10 deletions(-) diff --git a/binaries/data/mods/public/simulation/helpers/ObstructionSnap.js b/binaries/data/mods/public/simulation/helpers/ObstructionSnap.js index 0e4a2ea40a..ace8f31218 100644 --- a/binaries/data/mods/public/simulation/helpers/ObstructionSnap.js +++ b/binaries/data/mods/public/simulation/helpers/ObstructionSnap.js @@ -68,13 +68,25 @@ class ObstructionSnap return scoreA - scoreB; } + getNearestSizeAlongNormal(width, depth, angle, normal) + { + // Front face direction. + let direction = new Vector2D(0.0, 1.0); + direction.rotate(angle); + let dot = direction.dot(normal); + const threshold = Math.cos(Math.PI / 4.0); + if (Math.abs(dot) > threshold) + return [depth, width]; + return [width, depth]; + } + getPosition(data, template) { if (!data.snapToEdges || !template.Obstruction || !template.Obstruction.Static) return undefined; - let width = template.Obstruction.Static["@depth"] / 2; - let depth = template.Obstruction.Static["@width"] / 2; + const width = template.Obstruction.Static["@width"] / 2; + const depth = template.Obstruction.Static["@depth"] / 2; const maxSide = Math.max(width, depth); let templatePos = Vector2D.from3D(data); let templateAngle = data.angle || 0; @@ -97,16 +109,15 @@ class ObstructionSnap difference = Math.min(difference, Math.PI * 2 - difference); if (difference < Math.PI / 4 + this.EPS) { - // We need to swap sides for orthogonal cases. - if (dir % 2 == 0) - [width, depth] = [depth, width]; templateAngle = angleCandidate; break; } } + let [sizeToBaseEdge, sizeToPairedEdge] = + this.getNearestSizeAlongNormal(width, depth, templateAngle, baseEdge.normal); let distance = Vector2D.dot(baseEdge.normal, templatePos) - Vector2D.dot(baseEdge.normal, baseEdge.begin); - templatePos.sub(Vector2D.mult(baseEdge.normal, distance - width - this.getPadding(baseEdge))); + templatePos.sub(Vector2D.mult(baseEdge.normal, distance - sizeToBaseEdge - this.getPadding(baseEdge))); edges = this.getValidEdges(data.snapToEdges, templatePos, maxSide); if (edges.length > 1) { @@ -136,7 +147,7 @@ class ObstructionSnap if (this.compareEdges(edge, secondEdge) < 0) secondEdge = edge; let distance = Vector2D.dot(secondEdge.normal, templatePos) - Vector2D.dot(secondEdge.normal, secondEdge.begin); - templatePos.sub(Vector2D.mult(secondEdge.normal, distance - depth - this.getPadding(secondEdge))); + templatePos.sub(Vector2D.mult(secondEdge.normal, distance - sizeToPairedEdge - this.getPadding(secondEdge))); } } return { diff --git a/source/simulation2/scripting/JSInterface_Simulation.cpp b/source/simulation2/scripting/JSInterface_Simulation.cpp index 6dba9bd66d..b8452e16f6 100644 --- a/source/simulation2/scripting/JSInterface_Simulation.cpp +++ b/source/simulation2/scripting/JSInterface_Simulation.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2020 Wildfire Games. +/* Copyright (C) 2021 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -156,7 +156,7 @@ JS::Value JSI_Simulation::GetEdgesOfStaticObstructionsOnScreenNearTo(ScriptInter halfSize, CFixedVector2D(halfSize.X, -halfSize.Y) }; - fixed angle = cmpPosition->GetRotation().Y; + const fixed angle = cmpPosition->GetRotation().Y; for (CFixedVector2D& corner : corners) corner = corner.Rotate(angle) + cmpPosition->GetPosition2D(); @@ -166,7 +166,7 @@ JS::Value JSI_Simulation::GetEdgesOfStaticObstructionsOnScreenNearTo(ScriptInter const CFixedVector2D& corner = corners[i]; const CFixedVector2D& nextCorner = corners[(i + 1) % corners.size()]; - fixed distanceToEdge = + const fixed distanceToEdge = Geometry::DistanceToSegment(entityPos, corner, nextCorner); if (distanceToEdge.ToFloat() > distanceThreshold) continue;