solution1: Follow target with natural interpolation curve but without error correction

main
Fat mimir 3 years ago
commit 4a883bc582

2
.gitattributes vendored

@ -0,0 +1,2 @@
# Normalize EOL for all files that Git considers text files.
* text=auto eol=lf

15
.gitignore vendored

@ -0,0 +1,15 @@
# Godot 4+ specific ignores
.godot/
# Godot-specific ignores
.import/
export.cfg
export_presets.cfg
# Imported translations (automatically generated from CSV files)
*.translation
# Mono-specific ignores
.mono/
data_*/
mono_crash.*.json

@ -0,0 +1,127 @@
shader_type spatial;
render_mode blend_mix, depth_draw_always, cull_back, diffuse_burley, specular_schlick_ggx;
uniform vec4 albedo : source_color = vec4(0.6f, 0.6f, 0.6f, 1.0f);
uniform sampler2D detail_texture;
uniform vec2 detail_texture_size = vec2(256.0f, 256.0f);
uniform float specular;
uniform float metallic : hint_range(0, 1) = 0.0f;
uniform float roughness : hint_range(0, 1) = 0.5f;
uniform float point_size : hint_range(0, 128);
varying vec3 Position;
varying vec3 Normal;
void vertex()
{
Position = VERTEX;
Normal = NORMAL;
}
float SquareAntialiased(float coord, float dd) // antialiased square wave
{
coord += dd * 0.5f;
dd = max(dd, 0.0001f);
float invdd = 1.0f / dd;
coord = mod(coord, 1.0f);
float c = min(coord * invdd, 0.5f - (coord - 0.5f) / dd + 0.5f);
c = clamp(c, 0.0f, 1.0f);
return c;
}
float SXOR(float a, float b) // "smooth" xor, used to combine checker patterns
{
return abs(a - b);
}
vec4 SXOR4(vec4 a, vec4 b)
{
return abs(a - b);
}
float Checkers(vec3 coord, vec3 ddxyz, vec3 tripCoeff)
{
vec3 fade = clamp(1.0f / (ddxyz * 2.0f) - 1.0f, 0.0f, 1.0f);
float cx = SquareAntialiased(coord.x, ddxyz.x);
float cy = SquareAntialiased(coord.y, ddxyz.y);
float cz = SquareAntialiased(coord.z, ddxyz.z);
vec3 filter = clamp(1.0f / ddxyz * 0.5f - 0.5f, 0.0f, 1.0f); // smooth, manual filtering
float c = SXOR(cy * filter.y, cz * filter.z) * tripCoeff.x;
c += SXOR(cz * filter.z, cx * filter.x) * tripCoeff.y;
c += SXOR(cx * filter.x, cy * filter.y) * tripCoeff.z;
c += 1.0f - dot(filter, vec3(0.3333f));
return c;
}
vec4 texturePointSmooth(sampler2D smp, vec2 uv, vec2 tex_size, vec2 filter_width)
{
float fade = clamp(max(1.0f / filter_width.x, 1.0f / filter_width.y) - 1.0f, 0.0f, 1.0f);
filter_width = max(filter_width, vec2(1.0f));
vec2 uv_pixels = uv * tex_size;
vec2 uv_pixels_floor = round(uv_pixels) - vec2(0.5f);
vec2 uv_dxy_pixels = uv_pixels - uv_pixels_floor;
uv_dxy_pixels = clamp((uv_dxy_pixels - vec2(0.5f)) * filter_width + vec2(0.5f), 0.0f, 1.0f);
uv = uv_pixels_floor / tex_size;
return mix(textureLod(smp, uv + uv_dxy_pixels / tex_size, 0.0f), vec4(0.5f, 0.5f, 0.5f, 1.0f), fade);
}
vec4 TextureTriplanar(sampler2D smp, vec2 texSize, vec3 coord, vec3 ddxyz, vec3 tripCoeff)
{
vec4 cx = texturePointSmooth(smp, coord.yz, texSize, 1.0f / ddxyz.yz / texSize);
vec4 cy = texturePointSmooth(smp, coord.zx, texSize, 1.0f / ddxyz.zx / texSize);
vec4 cz = texturePointSmooth(smp, coord.xy, texSize, 1.0f / ddxyz.xy / texSize);
vec3 filter = clamp(1.0f / ddxyz * 0.5f - 0.5f, 0.0f, 1.0f); // smooth, manual filtering
vec4 c = cx * tripCoeff.x;
c += cy * tripCoeff.y;
c += cz * tripCoeff.z;
return c;
}
void fragment()
{
ALBEDO = albedo.rgb;
vec3 coord = Position.xyz * 4.0f;
vec3 ddxyz = fwidth(coord) * 1.0f;
vec3 tripCoeff = max((Normal * Normal * 2.0f - 0.5f), 0.001f);
tripCoeff /= (tripCoeff.x + tripCoeff.y + tripCoeff.z);
float checkers = Checkers(coord, ddxyz, tripCoeff);
coord = Position.xyz;
ddxyz = fwidth(coord);
float checkersL = 1.0f - Checkers(coord, ddxyz, tripCoeff);
vec3 detailCoord = Position.xyz * 0.5f; // Position.xyz * 2.0f
vec4 detail = TextureTriplanar(detail_texture, detail_texture_size, detailCoord, fwidth(detailCoord), tripCoeff);
checkers = mix(checkers, checkersL, 0.7f);
checkers = clamp(checkers * 0.8f + detail.r * 0.2f - 0.025f, 0.0f, 1.0f);
ALBEDO = mix(ALBEDO * 0.3f, ALBEDO, mix(checkers, 1.0f, metallic * roughness));
ROUGHNESS = mix(1.0f, 0.5f, checkers * (1.0f - roughness * 0.333f)) * roughness;
/* when using rgb noise as a texture, this can give some variation in roughness and normals
{
detail.rgb = detail.rgb * mat3(WORLD_MATRIX[0].xyz, WORLD_MATRIX[1].xyz, WORLD_MATRIX[2].xyz);
NORMAL = normalize(NORMAL + (detail.rgb - 0.5f) * 0.08f * roughness);
}
*/
METALLIC = metallic;
SPECULAR = specular;
}

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://b6oh1e3s28ngo"
path="res://.godot/imported/transparent_cursor.jpg-86c75b56e2c380b7e1b94c2bd2d0a993.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://assets/transparent_cursor.jpg"
dest_files=["res://.godot/imported/transparent_cursor.jpg-86c75b56e2c380b7e1b94c2bd2d0a993.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

Binary file not shown.

After

Width:  |  Height:  |  Size: 99 B

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://1gqwb316f5a7"
path="res://.godot/imported/transparent_cursor.png-ace4e0eb38b0048c2aad890e0663d1a9.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://assets/transparent_cursor.png"
dest_files=["res://.godot/imported/transparent_cursor.png-ace4e0eb38b0048c2aad890e0663d1a9.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

@ -0,0 +1,23 @@
extends Camera3D
@export var ray_length := 1000.0
@export var target_path : NodePath
@export var height := 3.5
@onready var target_node : MeshInstance3D = get_node(target_path)
var projected_point := Vector3.ZERO
func _input(event):
if event is InputEventMouseMotion:
var from = project_ray_origin(event.position)
var to = from + project_ray_normal(event.position) * ray_length
var result = get_world_3d().direct_space_state.intersect_ray(
PhysicsRayQueryParameters3D.create(from, to)
)
if result and result.get('position'):
projected_point = result.get('position')
func _physics_process(_delta):
if projected_point:
target_node.global_position = (
projected_point + projected_point.direction_to(global_position).normalized() * height
)

@ -0,0 +1,55 @@
extends MeshInstance3D
@export var f := 1.0
@export var z := 0.5
@export var r := 2.0
@export var target_path: NodePath
@export var f_label_path: NodePath
@export var z_label_path: NodePath
@export var r_label_path: NodePath
@onready var second_order_dynamics := SecondOrderDynamics.new(f, z, r, global_position)
@onready var target_node: Node3D = get_node(target_path)
@onready var f_label_node: Label = get_node(f_label_path)
@onready var z_label_node: Label = get_node(z_label_path)
@onready var r_label_node: Label = get_node(r_label_path)
func _ready():
process_mode = Node.PROCESS_MODE_ALWAYS
func _input(event):
if event.is_action_pressed("inc_f"):
f += 0.1
second_order_dynamics = SecondOrderDynamics.new(f, z, r, global_position)
if event.is_action_pressed("dec_f"):
f -= 0.1
second_order_dynamics = SecondOrderDynamics.new(f, z, r, global_position)
if event.is_action_pressed("inc_z"):
z += 0.1
second_order_dynamics = SecondOrderDynamics.new(f, z, r, global_position)
if event.is_action_pressed("dec_z"):
z -= 0.1
second_order_dynamics = SecondOrderDynamics.new(f, z, r, global_position)
if event.is_action_pressed("inc_r"):
r += 0.1
second_order_dynamics = SecondOrderDynamics.new(f, z, r, global_position)
if event.is_action_pressed("dec_r"):
r -= 0.1
second_order_dynamics = SecondOrderDynamics.new(f, z, r, global_position)
func _process(delta):
global_position = second_order_dynamics.update(delta, target_node.global_position, Vector3.ZERO)
if f_label_node:
f_label_node.text = "f = %.3f" % [f]
if z_label_node:
z_label_node.text = "z = %.3f" % [z]
if r_label_node:
r_label_node.text = "r = %.3f" % [r]

@ -0,0 +1 @@
<svg height="128" width="128" xmlns="http://www.w3.org/2000/svg"><g transform="translate(32 32)"><path d="m-16-32c-8.86 0-16 7.13-16 15.99v95.98c0 8.86 7.13 15.99 16 15.99h96c8.86 0 16-7.13 16-15.99v-95.98c0-8.85-7.14-15.99-16-15.99z" fill="#363d52"/><path d="m-16-32c-8.86 0-16 7.13-16 15.99v95.98c0 8.86 7.13 15.99 16 15.99h96c8.86 0 16-7.13 16-15.99v-95.98c0-8.85-7.14-15.99-16-15.99zm0 4h96c6.64 0 12 5.35 12 11.99v95.98c0 6.64-5.35 11.99-12 11.99h-96c-6.64 0-12-5.35-12-11.99v-95.98c0-6.64 5.36-11.99 12-11.99z" fill-opacity=".4"/></g><g stroke-width="9.92746" transform="matrix(.10073078 0 0 .10073078 12.425923 2.256365)"><path d="m0 0s-.325 1.994-.515 1.976l-36.182-3.491c-2.879-.278-5.115-2.574-5.317-5.459l-.994-14.247-27.992-1.997-1.904 12.912c-.424 2.872-2.932 5.037-5.835 5.037h-38.188c-2.902 0-5.41-2.165-5.834-5.037l-1.905-12.912-27.992 1.997-.994 14.247c-.202 2.886-2.438 5.182-5.317 5.46l-36.2 3.49c-.187.018-.324-1.978-.511-1.978l-.049-7.83 30.658-4.944 1.004-14.374c.203-2.91 2.551-5.263 5.463-5.472l38.551-2.75c.146-.01.29-.016.434-.016 2.897 0 5.401 2.166 5.825 5.038l1.959 13.286h28.005l1.959-13.286c.423-2.871 2.93-5.037 5.831-5.037.142 0 .284.005.423.015l38.556 2.75c2.911.209 5.26 2.562 5.463 5.472l1.003 14.374 30.645 4.966z" fill="#fff" transform="matrix(4.162611 0 0 -4.162611 919.24059 771.67186)"/><path d="m0 0v-47.514-6.035-5.492c.108-.001.216-.005.323-.015l36.196-3.49c1.896-.183 3.382-1.709 3.514-3.609l1.116-15.978 31.574-2.253 2.175 14.747c.282 1.912 1.922 3.329 3.856 3.329h38.188c1.933 0 3.573-1.417 3.855-3.329l2.175-14.747 31.575 2.253 1.115 15.978c.133 1.9 1.618 3.425 3.514 3.609l36.182 3.49c.107.01.214.014.322.015v4.711l.015.005v54.325c5.09692 6.4164715 9.92323 13.494208 13.621 19.449-5.651 9.62-12.575 18.217-19.976 26.182-6.864-3.455-13.531-7.369-19.828-11.534-3.151 3.132-6.7 5.694-10.186 8.372-3.425 2.751-7.285 4.768-10.946 7.118 1.09 8.117 1.629 16.108 1.846 24.448-9.446 4.754-19.519 7.906-29.708 10.17-4.068-6.837-7.788-14.241-11.028-21.479-3.842.642-7.702.88-11.567.926v.006c-.027 0-.052-.006-.075-.006-.024 0-.049.006-.073.006v-.006c-3.872-.046-7.729-.284-11.572-.926-3.238 7.238-6.956 14.642-11.03 21.479-10.184-2.264-20.258-5.416-29.703-10.17.216-8.34.755-16.331 1.848-24.448-3.668-2.35-7.523-4.367-10.949-7.118-3.481-2.678-7.036-5.24-10.188-8.372-6.297 4.165-12.962 8.079-19.828 11.534-7.401-7.965-14.321-16.562-19.974-26.182 4.4426579-6.973692 9.2079702-13.9828876 13.621-19.449z" fill="#478cbf" transform="matrix(4.162611 0 0 -4.162611 104.69892 525.90697)"/><path d="m0 0-1.121-16.063c-.135-1.936-1.675-3.477-3.611-3.616l-38.555-2.751c-.094-.007-.188-.01-.281-.01-1.916 0-3.569 1.406-3.852 3.33l-2.211 14.994h-31.459l-2.211-14.994c-.297-2.018-2.101-3.469-4.133-3.32l-38.555 2.751c-1.936.139-3.476 1.68-3.611 3.616l-1.121 16.063-32.547 3.138c.015-3.498.06-7.33.06-8.093 0-34.374 43.605-50.896 97.781-51.086h.066.067c54.176.19 97.766 16.712 97.766 51.086 0 .777.047 4.593.063 8.093z" fill="#478cbf" transform="matrix(4.162611 0 0 -4.162611 784.07144 817.24284)"/><path d="m0 0c0-12.052-9.765-21.815-21.813-21.815-12.042 0-21.81 9.763-21.81 21.815 0 12.044 9.768 21.802 21.81 21.802 12.048 0 21.813-9.758 21.813-21.802" fill="#fff" transform="matrix(4.162611 0 0 -4.162611 389.21484 625.67104)"/><path d="m0 0c0-7.994-6.479-14.473-14.479-14.473-7.996 0-14.479 6.479-14.479 14.473s6.483 14.479 14.479 14.479c8 0 14.479-6.485 14.479-14.479" fill="#414042" transform="matrix(4.162611 0 0 -4.162611 367.36686 631.05679)"/><path d="m0 0c-3.878 0-7.021 2.858-7.021 6.381v20.081c0 3.52 3.143 6.381 7.021 6.381s7.028-2.861 7.028-6.381v-20.081c0-3.523-3.15-6.381-7.028-6.381" fill="#fff" transform="matrix(4.162611 0 0 -4.162611 511.99336 724.73954)"/><path d="m0 0c0-12.052 9.765-21.815 21.815-21.815 12.041 0 21.808 9.763 21.808 21.815 0 12.044-9.767 21.802-21.808 21.802-12.05 0-21.815-9.758-21.815-21.802" fill="#fff" transform="matrix(4.162611 0 0 -4.162611 634.78706 625.67104)"/><path d="m0 0c0-7.994 6.477-14.473 14.471-14.473 8.002 0 14.479 6.479 14.479 14.473s-6.477 14.479-14.479 14.479c-7.994 0-14.471-6.485-14.471-14.479" fill="#414042" transform="matrix(4.162611 0 0 -4.162611 656.64056 631.05679)"/></g></svg>

After

Width:  |  Height:  |  Size: 4.1 KiB

@ -0,0 +1,37 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://csn6jebkkejps"
path="res://.godot/imported/icon.svg-218a8f2b3041327d8a5756f3a245f83b.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://icon.svg"
dest_files=["res://.godot/imported/icon.svg-218a8f2b3041327d8a5756f3a245f83b.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1
svg/scale=1.0
editor/scale_with_editor_scale=false
editor/convert_colors_with_editor_theme=false

@ -0,0 +1,13 @@
extends Node3D
@onready var cursor := load('res://assets/transparent_cursor.png')
func _ready():
Input.mouse_mode = Input.MOUSE_MODE_CONFINED
Input.set_custom_mouse_cursor(cursor)
func _input(event):
if event.is_action_pressed("ui_cancel"):
Input.mouse_mode = Input.MOUSE_MODE_VISIBLE
elif event is InputEventMouseButton:
Input.mouse_mode = Input.MOUSE_MODE_CONFINED

@ -0,0 +1,86 @@
[gd_scene load_steps=9 format=3 uid="uid://3b5ij42n5jko"]
[ext_resource type="Script" path="res://main.gd" id="1_1ywfr"]
[ext_resource type="Script" path="res://camera.gd" id="1_32slg"]
[ext_resource type="Shader" path="res://assets/floor.gdshader" id="2_snf6g"]
[ext_resource type="Script" path="res://follower.gd" id="3_4rocj"]
[sub_resource type="SphereMesh" id="SphereMesh_w43c3"]
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_j7rh5"]
albedo_color = Color(0.992157, 0.415686, 1, 1)
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_txxch"]
albedo_color = Color(0.407843, 0.721569, 0.980392, 1)
[sub_resource type="ShaderMaterial" id="ShaderMaterial_2gtpr"]
render_priority = 0
shader = ExtResource("2_snf6g")
shader_parameter/albedo = Color(0.721569, 0.615686, 0.917647, 1)
shader_parameter/detail_texture_size = Vector2(256, 256)
shader_parameter/specular = null
shader_parameter/metallic = 0.0
shader_parameter/roughness = 0.5
shader_parameter/point_size = null
[node name="Main" type="Node3D"]
script = ExtResource("1_1ywfr")
[node name="Help" type="HBoxContainer" parent="."]
anchors_preset = 10
anchor_right = 1.0
offset_bottom = 156.0
grow_horizontal = 2
pivot_offset = Vector2(1.89, 0.201)
[node name="Label" type="Label" parent="Help"]
layout_mode = 2
text = "1 - Increment f
2 - Decrement f
3 - Increment z
4 - Decrement z
5 - Increment r
6 - Decrement z"
[node name="FLabel" type="Label" parent="Help"]
layout_mode = 2
[node name="ZLabel" type="Label" parent="Help"]
layout_mode = 2
[node name="RLabel" type="Label" parent="Help"]
layout_mode = 2
[node name="Camera" type="Camera3D" parent="."]
transform = Transform3D(1, 0, 0, 0, 0.807671, 0.589633, 0, -0.589633, 0.807671, 0, 22, 24)
projection = 1
size = 7.0
script = ExtResource("1_32slg")
target_path = NodePath("../Target")
[node name="Target" type="MeshInstance3D" parent="."]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 3.5, 0)
mesh = SubResource("SphereMesh_w43c3")
surface_material_override/0 = SubResource("StandardMaterial3D_j7rh5")
[node name="Follower" type="MeshInstance3D" parent="."]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 3.5, 0)
mesh = SubResource("SphereMesh_w43c3")
surface_material_override/0 = SubResource("StandardMaterial3D_txxch")
script = ExtResource("3_4rocj")
target_path = NodePath("../Target")
f_label_path = NodePath("../Help/FLabel")
z_label_path = NodePath("../Help/ZLabel")
r_label_path = NodePath("../Help/RLabel")
[node name="Map" type="CSGCombiner3D" parent="."]
transform = Transform3D(0.707107, 0, 0.707107, 0, 1, 0, -0.707107, 0, 0.707107, 0, 0, 0)
use_collision = true
[node name="Floor" type="CSGBox3D" parent="Map"]
size = Vector3(30, 0.01, 30)
material = SubResource("ShaderMaterial_2gtpr")
[node name="Sun" type="DirectionalLight3D" parent="Map"]
transform = Transform3D(1, 0, 0, 0, 0.707107, 0.707107, 0, -0.707107, 0.707107, 3.72719, 11.0332, 9.55047)
shadow_enabled = true

@ -0,0 +1,49 @@
; Engine configuration file.
; It's best edited using the editor UI and not directly,
; since the parameters that go here are not all obvious.
;
; Format:
; [section] ; section goes between []
; param=value ; assign values to parameters
config_version=5
[application]
config/name="Interpolation Curves"
run/main_scene="res://main.tscn"
config/features=PackedStringArray("4.0", "Forward Plus")
config/icon="res://icon.svg"
[input]
inc_f={
"deadzone": 0.5,
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":49,"key_label":0,"unicode":49,"echo":false,"script":null)
]
}
dec_f={
"deadzone": 0.5,
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":50,"key_label":0,"unicode":50,"echo":false,"script":null)
]
}
inc_z={
"deadzone": 0.5,
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":51,"key_label":0,"unicode":51,"echo":false,"script":null)
]
}
dec_z={
"deadzone": 0.5,
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":52,"key_label":0,"unicode":52,"echo":false,"script":null)
]
}
inc_r={
"deadzone": 0.5,
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":53,"key_label":0,"unicode":53,"echo":false,"script":null)
]
}
dec_r={
"deadzone": 0.5,
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":54,"key_label":0,"unicode":54,"echo":false,"script":null)
]
}

@ -0,0 +1,26 @@
class_name SecondOrderDynamics
var k1: float
var k2: float
var k3: float
var xp: Vector3
var y: Vector3
var yd: Vector3
func _init(f: float, z: float, r: float, x0: Vector3):
k1 = z / PI * f
k2 = 1 / ((2 * PI * f) * (2 * PI * f))
k3 = r * z / (2 * PI * f)
xp = x0
y = x0
yd = Vector3.ZERO
func update(t: float, x: Vector3, xd: Vector3) -> Vector3:
if xd.is_zero_approx():
xd = (x - xp) / t
xp = x
y = y + t * yd
yd = yd + t * (x + k3*xd - y - k1*yd) / k2
return y
Loading…
Cancel
Save