Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions barmesh/draw.gd
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,8 @@ func _draw_barmesh(bm: BarMesh) -> void:
continue
if nd.contact_normal.length_squared() < 1e-12:
continue
var p0: Vector3 = _draw_pt(nd)
# Normals start at mesh contact; bars use cutter CL (fixed XY).
var p0: Vector3 = nd.contact_point
var p1: Vector3 = p0 + nd.contact_normal * tick
nim.surface_add_vertex(cad_to_godot(p0))
nim.surface_add_vertex(cad_to_godot(p1))
Expand All @@ -200,6 +201,6 @@ func _draw_barmesh(bm: BarMesh) -> void:


func _draw_pt(nd: BarMesh.BMNode) -> Vector3:
if nd.contact_kind != BarMesh.BMNode.ContactFeature.NONE:
return nd.contact_point
## Lattice = cutter locations. Drop is along Z: CL keeps input (x, y).
## Do not draw at contact_point — tilted faces shift contact XY and break overhead regularity.
return nd.p
5 changes: 5 additions & 0 deletions barmesh/tool_contact.gd
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,8 @@ static func drop_tool_contact(x: float, y: float, radius: float, tris_cad: Array
hit_pt = face["point"]
if not found:
return {
"x": x,
"y": y,
"z": fallback_z,
"kind": 0,
"tri": -1,
Expand All @@ -126,7 +128,10 @@ static func drop_tool_contact(x: float, y: float, radius: float, tris_cad: Array
hit_pt = cl - n * radius
elif n.length_squared() < 1e-12:
n = Vector3(0, 0, 1)
## CL is always (probe_x, probe_y, z). Contact point may differ in XY on tilted faces.
return {
"x": x,
"y": y,
"z": z_best,
"kind": kind,
"tri": tri_i,
Expand Down
9 changes: 7 additions & 2 deletions scripts/orbit_camera.gd
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,8 @@ func _unhandled_input(event: InputEvent) -> void:
var mm := event as InputEventMouseMotion
if _orbiting:
_yaw -= mm.relative.x * sensitivity
_pitch = clampf(_pitch - mm.relative.y * sensitivity, 0.05, 1.4)
# Allow true overhead (π/2) like Godot Editor top view; keep a tiny floor so we can orbit out.
_pitch = clampf(_pitch - mm.relative.y * sensitivity, 0.02, PI * 0.5)
_apply()
get_viewport().set_input_as_handled()
elif _panning:
Expand Down Expand Up @@ -96,4 +97,8 @@ func _apply() -> void:
_distance * cos(_pitch) * cos(_yaw)
)
global_position = _focus + offset
look_at(_focus, Vector3.UP)
# look_at(..., UP) fails / flips near straight-down; use a stable up near overhead.
var up := Vector3.UP
if _pitch > PI * 0.5 - 0.08:
up = Vector3(-sin(_yaw), 0.0, -cos(_yaw))
look_at(_focus, up)
32 changes: 30 additions & 2 deletions tools/test_contact.gd
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,12 @@ func _near(a: float, b: float, eps: float = 1e-5) -> bool:
return absf(a - b) <= eps


func _assert_cl_xy(hit: Dictionary, x: float, y: float) -> void:
## Drop along +Z tool axis: returned (x,y) must equal the probe.
if not _near(float(hit["x"]), x) or not _near(float(hit["y"]), y):
_fail("CL xy drifted probe=(%s,%s) hit=(%s,%s)" % [x, y, hit["x"], hit["y"]])


func _run() -> void:
var a := Vector3(0, 0, 0)
var b := Vector3(0.02, 0, 0)
Expand All @@ -32,13 +38,14 @@ func _run() -> void:
if int(face["kind"]) != KIND_FACE:
_fail("face kind " + str(face))
return
_assert_cl_xy(face, 0.005, 0.005)
if not _near(float(face["z"]), R):
_fail("face CL z " + str(face["z"]))
return
if absf(face["point"].z) > 1e-5:
_fail("face point not on plane")
return
var cl_f := Vector3(0.005, 0.005, float(face["z"]))
var cl_f := Vector3(float(face["x"]), float(face["y"]), float(face["z"]))
if absf(cl_f.distance_to(face["point"]) - R) > 1e-4:
_fail("face |CL-pt| != R")
return
Expand All @@ -47,6 +54,7 @@ func _run() -> void:
if int(vert["kind"]) != KIND_VERTEX:
_fail("vertex kind " + str(vert))
return
_assert_cl_xy(vert, 0.0, 0.0)
if vert["point"].distance_to(a) > 1e-6:
_fail("vertex point")
return
Expand All @@ -58,12 +66,32 @@ func _run() -> void:
if int(edge["kind"]) != KIND_EDGE:
_fail("edge kind " + str(edge))
return
_assert_cl_xy(edge, 0.01, 0.0)
if absf(edge["point"].y) > 1e-6 or absf(edge["point"].z) > 1e-5:
_fail("edge point not on ab")
return
if absf(Vector3(0.01, 0.0, float(edge["z"])).distance_to(edge["point"]) - R) > 1e-4:
_fail("edge |CL-pt| != R")
return

print("CONTACT_OK face,vertex,edge R=", R)
# Tilted face: contact XY can move; cutter CL must still keep probe (x,y).
var tilt: Array = [
[Vector3(0, 0, 0), Vector3(0.02, 0, 0), Vector3(0, 0.02, 0.01)],
]
var tilt_hit: Dictionary = Contact.drop_tool_contact(0.006, 0.006, R, tilt, -1.0)
_assert_cl_xy(tilt_hit, 0.006, 0.006)
if int(tilt_hit["kind"]) == 0:
_fail("tilt no contact")
return
var cl_t := Vector3(float(tilt_hit["x"]), float(tilt_hit["y"]), float(tilt_hit["z"]))
if absf(cl_t.distance_to(tilt_hit["point"]) - R) > 1e-4:
_fail("tilt |CL-pt| != R")
return
# On a tilt, contact point should generally differ from CL in XY (else face was flat).
var dxy: float = Vector2(cl_t.x - tilt_hit["point"].x, cl_t.y - tilt_hit["point"].y).length()
if dxy < 1e-6 and int(tilt_hit["kind"]) == KIND_FACE:
_fail("tilt face contact XY unexpected equal to CL")
return

print("CONTACT_OK face,vertex,edge,tilt_xy R=", R)
quit(0)