Snap correctly to non-world-aligned grid

- Support non-even item sizes
- Add wall test grid and items of various sizes
main
copygirl 5 months ago
parent 647318cc95
commit 4a3495faee
  1. 23
      player/PickupController.cs
  2. 183
      scenes/workshop.tscn
  3. 5
      scripts/globals/MathExtensions.cs

@ -72,20 +72,23 @@ public partial class PickupController : Node3D
EnsureCurrentItemValid();
if (HasItemsHeld) {
if ((RayToMouseCursor() is RayResult ray) && (ray.Collider is Grid)) {
if ((RayToMouseCursor() is RayResult ray) && (ray.Collider is Grid grid)) {
// Snao rotation to nearest axis.
// FIXME: This needs to snap relative to the grid rotation.
var globalRot = CurrentItem.GlobalRotation;
globalRot.X = Snapped(globalRot.X, Tau / 4);
globalRot.Y = Snapped(globalRot.Y, Tau / 4);
globalRot.Z = Snapped(globalRot.Z, Tau / 4);
_placementPreview.GlobalRotation = globalRot;
var localBasis = grid.GlobalBasis.Inverse() * CurrentItem.GlobalBasis;
localBasis = Basis.FromEuler(localBasis.GetEuler().Snapped(Tau / 4));
_placementPreview.GlobalBasis = grid.GlobalBasis * localBasis;
// Snap the position to the grid.
var halfSize = (Vector3)CurrentItem.Size * Grid.StepSize / 2;
var pos = ray.Position + halfSize * (ray.Normal * _placementPreview.GlobalTransform.Basis);
pos = pos.Snapped(Grid.StepSize * Vector3.One); // FIXME: This does global snapping only
_placementPreview.GlobalPosition = pos;
var localPos = ray.Position * grid.GlobalTransform; // Get grid-local ray position.
var localNormal = ray.Normal * grid.GlobalBasis; // Get grid-local ray normal. (Pointing away from surface hit.)
var off = localBasis * halfSize.PosMod(1.0f); // Calculate an offset for grid snapping.
off[(int)localNormal.Abs().MaxAxisIndex()] = 0; // Do not include offset in the normal direction.
localPos = off + (localPos - off).Snapped(Grid.StepSize); // Snap `localPos` to nearest grid value.
var axis = (localNormal * localBasis).Abs().MaxAxisIndex(); // Find object-local axis that the normal is pointing towards.
localPos += halfSize[(int)axis] * localNormal; // Offset (push out) object by half its size.
_placementPreview.GlobalPosition = grid.GlobalTransform * localPos;
_placementPreview.Visible = true;
} else {
_placementPreview.Visible = false;

@ -1,4 +1,4 @@
[gd_scene load_steps=13 format=3 uid="uid://bwfuet1irfi17"]
[gd_scene load_steps=17 format=3 uid="uid://bwfuet1irfi17"]
[ext_resource type="Script" path="res://objects/Grid.cs" id="2_gstd0"]
[ext_resource type="PackedScene" uid="uid://yvy5vvaqgxy8" path="res://objects/crate.tscn" id="2_j6a20"]
@ -23,6 +23,20 @@ size = Vector3(2, 0.1, 1)
[sub_resource type="BoxMesh" id="BoxMesh_efbik"]
size = Vector3(0.1, 0.9, 0.1)
[sub_resource type="BoxShape3D" id="BoxShape3D_dvxhj"]
size = Vector3(0.063, 0.063, 0.25)
[sub_resource type="BoxMesh" id="BoxMesh_hlein"]
material = SubResource("StandardMaterial3D_foa6h")
size = Vector3(0.063, 0.063, 0.25)
[sub_resource type="BoxShape3D" id="BoxShape3D_wh54f"]
size = Vector3(0.188, 0.063, 0.75)
[sub_resource type="BoxMesh" id="BoxMesh_pejsc"]
material = SubResource("StandardMaterial3D_foa6h")
size = Vector3(0.188, 0.063, 0.75)
[sub_resource type="WorldBoundaryShape3D" id="WorldBoundaryShape3D_5erfn"]
[sub_resource type="PlaneMesh" id="PlaneMesh_tg4vq"]
@ -62,45 +76,45 @@ transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, -4)
collision_layer = 2
collision_mask = 0
[node name="SmallBox" type="StaticBody3D" parent="Table"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -0.43938, 1.06737, 0)
[node name="Grid" type="Area3D" parent="Table"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0)
collision_layer = 8
collision_mask = 0
script = ExtResource("2_gstd0")
GridSize = Vector2i(30, 14)
[node name="SmallBox" type="StaticBody3D" parent="Table/Grid"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -0.43938, 0.0673701, 0)
collision_layer = 9
collision_mask = 0
script = ExtResource("3_01pgc")
Size = Vector3i(2, 2, 4)
[node name="CollisionShape3D" type="CollisionShape3D" parent="Table/SmallBox"]
[node name="CollisionShape3D" type="CollisionShape3D" parent="Table/Grid/SmallBox"]
shape = SubResource("BoxShape3D_hkc0l")
[node name="Model" type="Node3D" parent="Table/SmallBox"]
[node name="Model" type="Node3D" parent="Table/Grid/SmallBox"]
[node name="MeshInstance3D" type="MeshInstance3D" parent="Table/SmallBox/Model"]
[node name="MeshInstance3D" type="MeshInstance3D" parent="Table/Grid/SmallBox/Model"]
mesh = SubResource("BoxMesh_3qwx3")
skeleton = NodePath("../..")
[node name="SmallBox2" type="StaticBody3D" parent="Table"]
transform = Transform3D(-4.37114e-08, 0, -1, 0, 1, 0, 1, 0, -4.37114e-08, 0.251316, 1.06737, 0.127615)
[node name="SmallBox2" type="StaticBody3D" parent="Table/Grid"]
transform = Transform3D(-4.37114e-08, 0, -1, 0, 1, 0, 1, 0, -4.37114e-08, 0.251316, 0.0673701, 0.127615)
collision_layer = 9
collision_mask = 0
script = ExtResource("3_01pgc")
Size = Vector3i(2, 2, 4)
[node name="CollisionShape3D" type="CollisionShape3D" parent="Table/SmallBox2"]
[node name="CollisionShape3D" type="CollisionShape3D" parent="Table/Grid/SmallBox2"]
shape = SubResource("BoxShape3D_hkc0l")
[node name="Model" type="Node3D" parent="Table/SmallBox2"]
[node name="Model" type="Node3D" parent="Table/Grid/SmallBox2"]
[node name="MeshInstance3D" type="MeshInstance3D" parent="Table/SmallBox2/Model"]
[node name="MeshInstance3D" type="MeshInstance3D" parent="Table/Grid/SmallBox2/Model"]
mesh = SubResource("BoxMesh_3qwx3")
skeleton = NodePath("../..")
[node name="Grid" type="Area3D" parent="Table"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0)
collision_layer = 8
collision_mask = 0
script = ExtResource("2_gstd0")
GridSize = Vector2i(30, 14)
[node name="CollisionShape3D" type="CollisionShape3D" parent="Table"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.95, 0)
shape = SubResource("BoxShape3D_vkl3b")
@ -129,6 +143,139 @@ transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -0.9, 0.45, -0.4)
mesh = SubResource("BoxMesh_efbik")
skeleton = NodePath("../MeshInstance3D")
[node name="Table2" type="StaticBody3D" parent="."]
transform = Transform3D(1, 0, 0, 0, -4.37114e-08, -1, 0, 1, -4.37114e-08, 0, 1.5, -4.6)
collision_layer = 2
collision_mask = 0
[node name="Grid" type="Area3D" parent="Table2"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.0999999, 0)
collision_layer = 8
collision_mask = 0
script = ExtResource("2_gstd0")
GridSize = Vector2i(30, 14)
[node name="SmallBox3" type="StaticBody3D" parent="Table2/Grid"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -0.717982, 0.0335231, -0.120977)
collision_layer = 9
collision_mask = 0
script = ExtResource("3_01pgc")
Size = Vector3i(1, 1, 4)
[node name="CollisionShape3D" type="CollisionShape3D" parent="Table2/Grid/SmallBox3"]
shape = SubResource("BoxShape3D_dvxhj")
[node name="Model" type="Node3D" parent="Table2/Grid/SmallBox3"]
[node name="MeshInstance3D" type="MeshInstance3D" parent="Table2/Grid/SmallBox3/Model"]
mesh = SubResource("BoxMesh_hlein")
skeleton = NodePath("../..")
[node name="SmallBox4" type="StaticBody3D" parent="Table2/Grid"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -0.591133, 0.0335231, -0.120977)
collision_layer = 9
collision_mask = 0
script = ExtResource("3_01pgc")
Size = Vector3i(1, 1, 4)
[node name="CollisionShape3D" type="CollisionShape3D" parent="Table2/Grid/SmallBox4"]
shape = SubResource("BoxShape3D_dvxhj")
[node name="Model" type="Node3D" parent="Table2/Grid/SmallBox4"]
[node name="MeshInstance3D" type="MeshInstance3D" parent="Table2/Grid/SmallBox4/Model"]
mesh = SubResource("BoxMesh_hlein")
skeleton = NodePath("../..")
[node name="SmallBox5" type="StaticBody3D" parent="Table2/Grid"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -0.466087, 0.0335231, -0.120977)
collision_layer = 9
collision_mask = 0
script = ExtResource("3_01pgc")
Size = Vector3i(1, 1, 4)
[node name="CollisionShape3D" type="CollisionShape3D" parent="Table2/Grid/SmallBox5"]
shape = SubResource("BoxShape3D_dvxhj")
[node name="Model" type="Node3D" parent="Table2/Grid/SmallBox5"]
[node name="MeshInstance3D" type="MeshInstance3D" parent="Table2/Grid/SmallBox5/Model"]
mesh = SubResource("BoxMesh_hlein")
skeleton = NodePath("../..")
[node name="SmallBox6" type="StaticBody3D" parent="Table2/Grid"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -0.342431, 0.0335231, -0.120977)
collision_layer = 9
collision_mask = 0
script = ExtResource("3_01pgc")
Size = Vector3i(1, 1, 4)
[node name="CollisionShape3D" type="CollisionShape3D" parent="Table2/Grid/SmallBox6"]
shape = SubResource("BoxShape3D_dvxhj")
[node name="Model" type="Node3D" parent="Table2/Grid/SmallBox6"]
[node name="MeshInstance3D" type="MeshInstance3D" parent="Table2/Grid/SmallBox6/Model"]
mesh = SubResource("BoxMesh_hlein")
skeleton = NodePath("../..")
[node name="SmallBox7" type="StaticBody3D" parent="Table2/Grid"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -0.217693, 0.0335231, -0.120977)
collision_layer = 9
collision_mask = 0
script = ExtResource("3_01pgc")
Size = Vector3i(1, 1, 4)
[node name="CollisionShape3D" type="CollisionShape3D" parent="Table2/Grid/SmallBox7"]
shape = SubResource("BoxShape3D_dvxhj")
[node name="Model" type="Node3D" parent="Table2/Grid/SmallBox7"]
[node name="MeshInstance3D" type="MeshInstance3D" parent="Table2/Grid/SmallBox7/Model"]
mesh = SubResource("BoxMesh_hlein")
skeleton = NodePath("../..")
[node name="SmallBox8" type="StaticBody3D" parent="Table2/Grid"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -0.0920233, 0.0335231, -0.120977)
collision_layer = 9
collision_mask = 0
script = ExtResource("3_01pgc")
Size = Vector3i(1, 1, 4)
[node name="CollisionShape3D" type="CollisionShape3D" parent="Table2/Grid/SmallBox8"]
shape = SubResource("BoxShape3D_dvxhj")
[node name="Model" type="Node3D" parent="Table2/Grid/SmallBox8"]
[node name="MeshInstance3D" type="MeshInstance3D" parent="Table2/Grid/SmallBox8/Model"]
mesh = SubResource("BoxMesh_hlein")
skeleton = NodePath("../..")
[node name="SmallBox9" type="StaticBody3D" parent="Table2/Grid"]
transform = Transform3D(-4.37114e-08, 0, -1, 1, -4.37114e-08, -4.37114e-08, -4.37114e-08, -1, 1.91069e-15, 0.314445, 0.0927377, 0.155108)
collision_layer = 9
collision_mask = 0
script = ExtResource("3_01pgc")
Size = Vector3i(3, 1, 12)
[node name="CollisionShape3D" type="CollisionShape3D" parent="Table2/Grid/SmallBox9"]
shape = SubResource("BoxShape3D_wh54f")
[node name="Model" type="Node3D" parent="Table2/Grid/SmallBox9"]
[node name="MeshInstance3D" type="MeshInstance3D" parent="Table2/Grid/SmallBox9/Model"]
transform = Transform3D(1, 0, -8.35187e-23, 0, 1, 0, -8.35187e-23, 0, 1, 0, 0, 0)
mesh = SubResource("BoxMesh_pejsc")
skeleton = NodePath("../..")
[node name="CollisionShape3D" type="CollisionShape3D" parent="Table2"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.0499997, 0)
shape = SubResource("BoxShape3D_vkl3b")
[node name="MeshInstance3D" type="MeshInstance3D" parent="Table2"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.0499997, 0)
mesh = SubResource("BoxMesh_548mk")
[node name="Floor" type="StaticBody3D" parent="."]
collision_mask = 0

@ -0,0 +1,5 @@
public static class MathExtensions
{
public static Vector3 Snapped(this Vector3 self, float value)
=> self.Snapped(Vector3.One * value);
}
Loading…
Cancel
Save