Initial orbiting craft

This commit is contained in:
Yuki Kitagawa 2024-11-06 22:16:43 +08:00
parent a6e116c77f
commit 518ee9d429
6 changed files with 194 additions and 2 deletions

View File

@ -52,6 +52,12 @@ enabled=PackedStringArray("res://addons/imgui-godot/plugin.cfg", "res://addons/i
3d_physics/layer_7="reserved-7" 3d_physics/layer_7="reserved-7"
3d_physics/layer_8="reserved-8" 3d_physics/layer_8="reserved-8"
[physics]
3d/default_gravity=0.0
3d/default_linear_damp=0.0
3d/default_angular_damp=0.0
[rendering] [rendering]
lights_and_shadows/use_physical_light_units=true lights_and_shadows/use_physical_light_units=true

View File

@ -1,7 +1,8 @@
[gd_scene load_steps=12 format=3 uid="uid://tht1tf5iq6lw"] [gd_scene load_steps=15 format=3 uid="uid://tht1tf5iq6lw"]
[ext_resource type="Script" path="res://src/Craft/Krakensbane.cs" id="1_ju4qj"] [ext_resource type="Script" path="res://src/Craft/Krakensbane.cs" id="1_ju4qj"]
[ext_resource type="Script" path="res://src/Testing/TestThruster.cs" id="2_1t1tx"] [ext_resource type="Script" path="res://src/Testing/TestThruster.cs" id="2_1t1tx"]
[ext_resource type="Script" path="res://src/Testing/DebugUI.cs" id="3_gx3yn"]
[sub_resource type="PhysicalSkyMaterial" id="PhysicalSkyMaterial_uxbcq"] [sub_resource type="PhysicalSkyMaterial" id="PhysicalSkyMaterial_uxbcq"]
@ -16,6 +17,8 @@ sky = SubResource("Sky_iakm3")
[sub_resource type="Compositor" id="Compositor_tt8nt"] [sub_resource type="Compositor" id="Compositor_tt8nt"]
[sub_resource type="PhysicsMaterial" id="PhysicsMaterial_sjyiu"]
[sub_resource type="BoxShape3D" id="BoxShape3D_8al46"] [sub_resource type="BoxShape3D" id="BoxShape3D_8al46"]
[sub_resource type="BoxMesh" id="BoxMesh_jgj3c"] [sub_resource type="BoxMesh" id="BoxMesh_jgj3c"]
@ -26,6 +29,8 @@ size = Vector3(16.9697, 0.0310059, 15.6934)
[sub_resource type="PlaneMesh" id="PlaneMesh_xcndr"] [sub_resource type="PlaneMesh" id="PlaneMesh_xcndr"]
size = Vector2(20, 20) size = Vector2(20, 20)
[sub_resource type="LabelSettings" id="LabelSettings_v1h1b"]
[node name="root" type="Node3D"] [node name="root" type="Node3D"]
[node name="DirectionalLight3D" type="DirectionalLight3D" parent="."] [node name="DirectionalLight3D" type="DirectionalLight3D" parent="."]
@ -42,6 +47,7 @@ FocusedVessel = NodePath("test-rocket")
[node name="test-rocket" type="RigidBody3D" parent="FloatingOriginRoot"] [node name="test-rocket" type="RigidBody3D" parent="FloatingOriginRoot"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.815224, 0) transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.815224, 0)
physics_material_override = SubResource("PhysicsMaterial_sjyiu")
script = ExtResource("2_1t1tx") script = ExtResource("2_1t1tx")
[node name="CollisionShape3D" type="CollisionShape3D" parent="FloatingOriginRoot/test-rocket"] [node name="CollisionShape3D" type="CollisionShape3D" parent="FloatingOriginRoot/test-rocket"]
@ -63,3 +69,52 @@ shape = SubResource("BoxShape3D_xxi7g")
[node name="MeshInstance3D" type="MeshInstance3D" parent="FloatingOriginRoot/ground"] [node name="MeshInstance3D" type="MeshInstance3D" parent="FloatingOriginRoot/ground"]
mesh = SubResource("PlaneMesh_xcndr") mesh = SubResource("PlaneMesh_xcndr")
[node name="DebugUI" type="Panel" parent="." node_paths=PackedStringArray("minimapContainer", "planetOutline", "vesselIndicator", "krakensbane", "displayLabel")]
offset_left = 1508.0
offset_top = 62.0
offset_right = 1868.0
offset_bottom = 542.0
script = ExtResource("3_gx3yn")
minimapContainer = NodePath("VBoxContainer/MinimapContainer")
planetOutline = NodePath("VBoxContainer/MinimapContainer/Polygon2D")
vesselIndicator = NodePath("VBoxContainer/MinimapContainer/ColorRect")
krakensbane = NodePath("../FloatingOriginRoot")
displayLabel = NodePath("VBoxContainer/Label")
[node name="VBoxContainer" type="VBoxContainer" parent="DebugUI"]
layout_mode = 1
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
[node name="MinimapContainer" type="Control" parent="DebugUI/VBoxContainer"]
custom_minimum_size = Vector2(0, 360)
layout_mode = 2
[node name="Polygon2D" type="Polygon2D" parent="DebugUI/VBoxContainer/MinimapContainer"]
color = Color(0.287295, 0.287295, 0.287295, 1)
polygon = PackedVector2Array(116, 83, 96, 201, 274, 248, 289, 140, 119, 85)
[node name="y-axis" type="Line2D" parent="DebugUI/VBoxContainer/MinimapContainer"]
points = PackedVector2Array(180, 180, 180, 0)
width = 2.0
default_color = Color(0.286275, 0.290196, 1, 1)
[node name="x-axis" type="Line2D" parent="DebugUI/VBoxContainer/MinimapContainer"]
points = PackedVector2Array(180, 180, 360, 180)
width = 2.0
default_color = Color(0.671919, 0.312344, 0.0459558, 1)
[node name="ColorRect" type="ColorRect" parent="DebugUI/VBoxContainer/MinimapContainer"]
layout_mode = 0
offset_right = 10.0
offset_bottom = 10.0
pivot_offset = Vector2(5, 5)
[node name="Label" type="Label" parent="DebugUI/VBoxContainer"]
layout_mode = 2
text = "Position"
label_settings = SubResource("LabelSettings_v1h1b")

View File

@ -2,6 +2,7 @@ using System.Diagnostics;
using Godot; using Godot;
using ImGuiNET; using ImGuiNET;
using Quadratic.Carto.MathExt; using Quadratic.Carto.MathExt;
using Vim.Math3d;
namespace Quadratic.Carto.Craft; namespace Quadratic.Carto.Craft;
@ -20,8 +21,24 @@ public sealed partial class Krakensbane : Node3D
public Node3D? FocusedVessel { get; set; } public Node3D? FocusedVessel { get; set; }
const float maxDistance = 500.0f; const float maxDistance = 500.0f;
const float planetRadius = 6372.0f;
DVector3 originPosition = DVector3.Zero; DVector3 originPosition = DVector3.UnitY * planetRadius;
/// <summary>
/// Something to manage the non-inertial frame of reference.
/// </summary>
/// <para>
/// It's good to have an inertial frame of reference when you're close to
/// a lot of static stuff, like on the ground. However, a non-inertial frame
/// of reference might be more appropriate when you're in deep space.
/// </para>
/// <para>
/// This provider field is null if we're using an inertial frame of reference.
/// When it's not null, it should be responsible for managing the acceleration,
/// angular acceleration, and even positions and/or rotations of children
/// objects.
INonInertialFrameProvider? nonInertialFrameProvider;
public override void _PhysicsProcess(double delta) public override void _PhysicsProcess(double delta)
{ {
@ -52,6 +69,27 @@ public sealed partial class Krakensbane : Node3D
originPosition += vesselPosition.AsVim().AsDouble(); originPosition += vesselPosition.AsVim().AsDouble();
} }
// Apply gravity
foreach (var child in GetChildren())
{
if (child is RigidBody3D rb)
{
var localPosition = rb.Transform.Origin.AsVim().AsDouble();
var globalPosition = originPosition + localPosition;
var gravityVector = -globalPosition.Normalize();
var floatGravityVector = gravityVector.AsSingle().AsGodot();
var distance = globalPosition.Length();
var gravity = 9.81f * planetRadius * planetRadius / (distance * distance);
rb.ApplyCentralForce(floatGravityVector * (float)gravity);
}
}
}
public DVector3 GetPositionOf(Node3D node)
{
var localPosition = node.Transform.Origin.AsVim().AsDouble();
return originPosition + localPosition;
} }
public override void _Process(double delta) public override void _Process(double delta)
@ -61,3 +99,9 @@ public sealed partial class Krakensbane : Node3D
ImGui.End(); ImGui.End();
} }
} }
public interface INonInertialFrameProvider
{
public DVector3 GetCurrentAcceleration();
public DVector3 GetCurrentAngularAcceleration();
}

14
src/Craft/Vessel.cs Normal file
View File

@ -0,0 +1,14 @@
using Godot;
namespace Quadratic.Carto.Craft;
/// <summary>
/// A Vessel is the smallest unit of object in the game that is considered a
/// whole on its own, such as a space station or an astronaut. Connections can
/// be made between vessels, but each vessel is still a separate entity.
/// </summary>
/// <remarks>
/// Vessel is an abstract class, and is meant to be extended by concrete
/// implementations.
/// </remarks>
public abstract class Vessel { }

9
src/Craft/VesselNode.cs Normal file
View File

@ -0,0 +1,9 @@
using Godot;
namespace Quadratic.Carto.Craft;
/// <summary>
/// A VesselNode is the node that represents a <see cref="Vessel"/> currently
/// loaded into the game world.
/// </summary>
public abstract partial class VesselNode : Node3D { }

64
src/Testing/DebugUI.cs Normal file
View File

@ -0,0 +1,64 @@
using System.Collections.Generic;
using Godot;
using Quadratic.Carto.Craft;
using Quadratic.Carto.MathExt;
namespace Quadratic.Carto.Testing;
public partial class DebugUI : Control
{
[Export]
Control minimapContainer = null!;
[Export]
Vector2 minimapSize = new Vector2(360, 360);
[Export]
float minimapSizeUnit = 6372;
[Export]
float minimapUnitLength = 90;
[Export]
Polygon2D planetOutline = null!;
[Export]
Control vesselIndicator = null!;
[Export]
Krakensbane krakensbane = null!;
[Export]
Label displayLabel = null!;
public override void _Ready()
{
// draw the planet outline
var polygon = new List<Vector2>();
const int maxPoints = 360;
var minimapCenter = minimapSize / 2;
for (int i = 0; i < maxPoints; i++)
{
var angle = (float)i / maxPoints * Mathf.Pi * 2;
var point = new Vector2(Mathf.Cos(angle), Mathf.Sin(angle)) * minimapUnitLength + minimapCenter;
polygon.Add(point);
}
planetOutline.Polygon = polygon.ToArray();
}
public override void _Process(double delta)
{
if (krakensbane.FocusedVessel == null)
{
return;
}
var vesselPosition = krakensbane.GetPositionOf(krakensbane.FocusedVessel);
var minimapCenter = minimapSize / 2;
var minimapPosition3D = (vesselPosition / minimapSizeUnit).AsSingle().AsGodot() * minimapUnitLength;
var minimapPosition2D = new Vector2(-minimapPosition3D.Y, minimapPosition3D.X) + minimapCenter;
vesselIndicator.Position = minimapPosition2D;
displayLabel.Text = $"Vessel position:\n{vesselPosition.X},\n{vesselPosition.Y},\n{vesselPosition.Z}";
}
}